Author: matt Date: 2011-08-25 03:53:58 -0700 (Thu, 25 Aug 2011) New Revision: 9009 Log: More OpenGL renaming
Added: branches/branch-3.0/include/fltk3gl/GL_Window.h branches/branch-3.0/src/fltk3gl/GL_Choice.cxx branches/branch-3.0/src/fltk3gl/GL_Choice.h branches/branch-3.0/src/fltk3gl/GL_DevicePlugin.cxx branches/branch-3.0/src/fltk3gl/GL_Overlay.cxx branches/branch-3.0/src/fltk3gl/GL_Window.cxx Removed: branches/branch-3.0/include/fltk3gl/GlWindow.h branches/branch-3.0/src/fltk3gl/GlChoice.cxx branches/branch-3.0/src/fltk3gl/GlChoice.h branches/branch-3.0/src/fltk3gl/GlDevicePlugin.cxx branches/branch-3.0/src/fltk3gl/GlOverlay.cxx branches/branch-3.0/src/fltk3gl/GlWindow.cxx Copied: branches/branch-3.0/include/fltk3gl/GL_Window.h (from rev 9008, branches/branch-3.0/include/fltk3gl/GlWindow.h) =================================================================== --- branches/branch-3.0/include/fltk3gl/GL_Window.h (rev 0) +++ branches/branch-3.0/include/fltk3gl/GL_Window.h 2011-08-25 10:53:58 UTC (rev 9009) @@ -0,0 +1,248 @@ +// +// "$Id: GlWindow.h 8157 2011-01-01 14:01:53Z AlbrechtS $" +// +// OpenGL header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2010 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +/* \file + fltk3::GlWindow widget . */ + +#ifndef Fltk3_Gl_Window_H +#define Fltk3_Gl_Window_H + +#include "Window.h" + +#ifndef GLContext +/** + Opaque pointer type to hide system specific implementation. + */ +typedef void* GLContext; // actually a GLXContext or HGLDC +#endif + +class Fl_Gl_Window; + +namespace fltk3 { + + class GlChoice; // structure to hold result of glXChooseVisual + + /** + The fltk3::GlWindow widget sets things up so OpenGL works. + + It also keeps an OpenGL "context" for that window, so that changes to the + lighting and projection may be reused between redraws. fltk3::GlWindow + also flushes the OpenGL streams and swaps buffers after draw() returns. + + OpenGL hardware typically provides some overlay bit planes, which + are very useful for drawing UI controls atop your 3D graphics. If the + overlay hardware is not provided, FLTK tries to simulate the overlay. + This works pretty well if your graphics are double buffered, but not + very well for single-buffered. + + Please note that the FLTK drawing and clipping functions + will not work inside an fltk3::GlWindow. All drawing + should be done using OpenGL calls exclusively. + Even though fltk3::GlWindow is derived from fltk3::Group, + it is not useful to add other FLTK Widgets as children, + unless those widgets are modified to draw using OpenGL calls. + */ + class FLTK3_EXPORT GlWindow : public fltk3::Window { + + friend class ::Fl_Gl_Window; + + int mode_; + const int *alist; + GlChoice *g; + GLContext context_; + char valid_f_; + char damage1_; // damage() of back buffer + virtual void draw_overlay(); + void init(); + + void *overlay; + void make_overlay(); + friend class _Fl_Gl_Overlay; + + static int can_do(int, const int *); + int mode(int, const int *); + + public: + + void show(); + void show(int a, char **b) {Window::show(a,b);} + void flush(); + void hide(); + void resize(int,int,int,int); + int handle(int); + + /** + Is turned off when FLTK creates a new context for this window or + when the window resizes, and is turned on \e after draw() is called. + You can use this inside your draw() method to avoid unnecessarily + initializing the OpenGL context. Just do this: + \code + void mywindow::draw() { + if (!valid()) { + glViewport(0,0,w(),h()); + glFrustum(...); + ...other initialization... + } + if (!context_valid()) { + ...load textures, etc. ... + } + ... draw your geometry here ... + } + \endcode + + You can turn valid() on by calling valid(1). You + should only do this after fixing the transformation inside a draw() + or after make_current(). This is done automatically after + draw() returns. + */ + char valid() const {return valid_f_ & 1;} + /** + See char fltk3::GlWindow::valid() const + */ + void valid(char v) {if (v) valid_f_ |= 1; else valid_f_ &= 0xfe;} + void invalidate(); + + /** + Will only be set if the + OpenGL context is created or recreated. It differs from + fltk3::GlWindow::valid() which is also set whenever the context + changes size. + */ + char context_valid() const {return valid_f_ & 2;} + /** + See char fltk3::GlWindow::context_valid() const + */ + void context_valid(char v) {if (v) valid_f_ |= 2; else valid_f_ &= 0xfd;} + + /** Returns non-zero if the hardware supports the given or current OpenGL mode. */ + static int can_do(int m) {return can_do(m,0);} + /** Returns non-zero if the hardware supports the given or current OpenGL mode. */ + static int can_do(const int *m) {return can_do(0, m);} + /** Returns non-zero if the hardware supports the given or current OpenGL mode. */ + int can_do() {return can_do(mode_,alist);} + /** + Set or change the OpenGL capabilites of the window. The value can be + any of the following OR'd together: + + - \c fltk3::RGB - RGB color (not indexed) + - \c fltk3::RGB8 - RGB color with at least 8 bits of each color + - \c fltk3::INDEX - Indexed mode + - \c fltk3::SINGLE - not double buffered + - \c fltk3::DOUBLE - double buffered + - \c fltk3::ACCUM - accumulation buffer + - \c fltk3::ALPHA - alpha channel in color + - \c fltk3::DEPTH - depth buffer + - \c fltk3::STENCIL - stencil buffer + - \c fltk3::MULTISAMPLE - multisample antialiasing + + fltk3::RGB and fltk3::SINGLE have a value of zero, so they + are "on" unless you give fltk3::INDEX or fltk3::DOUBLE. + + If the desired combination cannot be done, FLTK will try turning off + fltk3::MULTISAMPLE. If this also fails the show() will call + fltk3::error() and not show the window. + + You can change the mode while the window is displayed. This is most + useful for turning double-buffering on and off. Under X this will + cause the old X window to be destroyed and a new one to be created. If + this is a top-level window this will unfortunately also cause the + window to blink, raise to the top, and be de-iconized, and the xid() + will change, possibly breaking other code. It is best to make the GL + window a child of another window if you wish to do this! + + mode() must not be called within draw() since it + changes the current context. + */ + fltk3::Mode mode() const {return (fltk3::Mode)mode_;} + /** See fltk3::Mode mode() const */ + int mode(int a) {return mode(a,0);} + /** See fltk3::Mode mode() const */ + int mode(const int *a) {return mode(0, a);} + /** void See void context(void* v, int destroy_flag) */ + void* context() const {return context_;} + void context(void*, int destroy_flag = 0); + void make_current(); + void swap_buffers(); + void ortho(); + + /** + Returns true if the hardware overlay is possible. If this is false, + FLTK will try to simulate the overlay, with significant loss of update + speed. Calling this will cause FLTK to open the display. + */ + int can_do_overlay(); + /** + This method causes draw_overlay() to be called at a later time. + Initially the overlay is clear. If you want the window to display + something in the overlay when it first appears, you must call this + immediately after you show() your window. + */ + void redraw_overlay(); + void hide_overlay(); + /** + The make_overlay_current() method selects the OpenGL context + for the widget's overlay. It is called automatically prior to the + draw_overlay() method being called and can also be used to + implement feedback and/or selection within the handle() + method. + */ + void make_overlay_current(); + + // Note: Doxygen docs in Widget.h to avoid redundancy. + virtual fltk3::GlWindow* as_gl_window() {return this;} + + ~GlWindow(); + /** + Creates a new fltk3::GlWindow widget using the given size, and label string. + The default boxtype is fltk3::NO_BOX. The default mode is fltk3::RGB|fltk3::DOUBLE|fltk3::DEPTH. + */ + GlWindow(int W, int H, const char *l=0) : fltk3::Window(W,H,l) {init();} + /** + Creates a new fltk3::GlWindow widget using the given position, + size, and label string. The default boxtype is fltk3::NO_BOX. The + default mode is fltk3::RGB|fltk3::DOUBLE|fltk3::DEPTH. + */ + + GlWindow(int X, int Y, int W, int H, const char *l=0) + : fltk3::Window(X,Y,W,H,l) {init();} + + protected: + /** + Draws the fltk3::GlWindow. + + You \e \b must override the draw() method. + */ + virtual void draw(); + }; + +} + +#endif + +// +// End of "$Id: GlWindow.h 8157 2011-01-01 14:01:53Z AlbrechtS $". +// Deleted: branches/branch-3.0/include/fltk3gl/GlWindow.h Copied: branches/branch-3.0/src/fltk3gl/GL_Choice.cxx (from rev 9008, branches/branch-3.0/src/fltk3gl/GlChoice.cxx) =================================================================== --- branches/branch-3.0/src/fltk3gl/GL_Choice.cxx (rev 0) +++ branches/branch-3.0/src/fltk3gl/GL_Choice.cxx 2011-08-25 10:53:58 UTC (rev 9009) @@ -0,0 +1,426 @@ +// +// "$Id$" +// +// OpenGL visual selection code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2010 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <config.h> +#if HAVE_GL + +# include <fltk3/run.h> +# include <fltk3/x.h> +# include <stdlib.h> +# include "Fl_Gl_Choice.H" +# include <fltk3/glDraw.h> +# include "flstring.h" +# include <fltk3/utf8.h> + +# ifdef __APPLE__ +# include <ApplicationServices/ApplicationServices.h> +# include <fltk3/Window.h> +# endif + +# ifdef WIN32 +void fl_save_dc(HWND, HDC); +# endif + +static fltk3::GlChoice *first; + +// this assumes one of the two arguments is zero: +// We keep the list system in Win32 to stay compatible and interpret +// the list later... +fltk3::GlChoice *fltk3::GlChoice::find(int m, const int *alistp) { + fltk3::GlChoice *g; + + for (g = first; g; g = g->next) + if (g->mode == m && g->alist == alistp) + return g; + +#if defined(USE_X11) + const int *blist; + int list[32]; + + if (alistp) + blist = alistp; + else { + int n = 0; + if (m & fltk3::INDEX) { + list[n++] = GLX_BUFFER_SIZE; + list[n++] = 8; // glut tries many sizes, but this should work... + } else { + list[n++] = GLX_RGBA; + list[n++] = GLX_GREEN_SIZE; + list[n++] = (m & fltk3::RGB8) ? 8 : 1; + if (m & fltk3::ALPHA) { + list[n++] = GLX_ALPHA_SIZE; + list[n++] = (m & fltk3::RGB8) ? 8 : 1; + } + if (m & fltk3::ACCUM) { + list[n++] = GLX_ACCUM_GREEN_SIZE; + list[n++] = 1; + if (m & fltk3::ALPHA) { + list[n++] = GLX_ACCUM_ALPHA_SIZE; + list[n++] = 1; + } + } + } + if (m & fltk3::DOUBLE) { + list[n++] = GLX_DOUBLEBUFFER; + } + if (m & fltk3::DEPTH) { + list[n++] = GLX_DEPTH_SIZE; list[n++] = 1; + } + if (m & fltk3::STENCIL) { + list[n++] = GLX_STENCIL_SIZE; list[n++] = 1; + } + if (m & fltk3::STEREO) { + list[n++] = GLX_STEREO; + } +# if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample) + if (m & fltk3::MULTISAMPLE) { + list[n++] = GLX_SAMPLES_SGIS; + list[n++] = 4; // value Glut uses + } +# endif + list[n] = 0; + blist = list; + } + + fl_open_display(); + XVisualInfo *visp = glXChooseVisual(fl_display, fl_screen, (int *)blist); + if (!visp) { +# if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample) + if (m&fltk3::MULTISAMPLE) return find(m&~fltk3::MULTISAMPLE,0); +# endif + return 0; + } + +#elif defined(__APPLE_QUARTZ__) + // warning: the Quartz version should probably use Core GL (CGL) instead of AGL + const int *blist; + int list[32]; + + if (alistp) + blist = alistp; + else { + int n = 0; + if (m & fltk3::INDEX) { + list[n++] = AGL_BUFFER_SIZE; + list[n++] = 8; // glut tries many sizes, but this should work... + } else { + list[n++] = AGL_RGBA; + list[n++] = AGL_GREEN_SIZE; + list[n++] = (m & fltk3::RGB8) ? 8 : 1; + if (m & fltk3::ALPHA) { + list[n++] = AGL_ALPHA_SIZE; + list[n++] = (m & fltk3::RGB8) ? 8 : 1; + } + if (m & fltk3::ACCUM) { + list[n++] = AGL_ACCUM_GREEN_SIZE; + list[n++] = 1; + if (m & fltk3::ALPHA) { + list[n++] = AGL_ACCUM_ALPHA_SIZE; + list[n++] = 1; + } + } + } + if (m & fltk3::DOUBLE) { + list[n++] = AGL_DOUBLEBUFFER; + } + if (m & fltk3::DEPTH) { + list[n++] = AGL_DEPTH_SIZE; list[n++] = 24; + } + if (m & fltk3::STENCIL) { + list[n++] = AGL_STENCIL_SIZE; list[n++] = 1; + } +# ifdef AGL_STEREO + if (m & fltk3::STEREO) { + list[n++] = AGL_STEREO; + } +# endif + list[n] = AGL_NONE; + blist = list; + } + fl_open_display(); + AGLPixelFormat fmt = aglChoosePixelFormat(NULL, 0, (GLint*)blist); + if (!fmt) return 0; + +#elif defined(WIN32) + + // Replacement for ChoosePixelFormat() that finds one with an overlay + // if possible: + if (!fl_gc) fl_GetDC(0); + int pixelformat = 0; + PIXELFORMATDESCRIPTOR chosen_pfd; + for (int i = 1; ; i++) { + PIXELFORMATDESCRIPTOR pfd; + if (!DescribePixelFormat(fl_gc, i, sizeof(pfd), &pfd)) break; + // continue if it does not satisfy our requirements: + if (~pfd.dwFlags & (PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL)) continue; + if (pfd.iPixelType != ((m&fltk3::INDEX)?PFD_TYPE_COLORINDEX:PFD_TYPE_RGBA)) continue; + if ((m & fltk3::ALPHA) && !pfd.cAlphaBits) continue; + if ((m & fltk3::ACCUM) && !pfd.cAccumBits) continue; + if ((!(m & fltk3::DOUBLE)) != (!(pfd.dwFlags & PFD_DOUBLEBUFFER))) continue; + if ((!(m & fltk3::STEREO)) != (!(pfd.dwFlags & PFD_STEREO))) continue; + if ((m & fltk3::DEPTH) && !pfd.cDepthBits) continue; + if ((m & fltk3::STENCIL) && !pfd.cStencilBits) continue; + // see if better than the one we have already: + if (pixelformat) { + // offering non-generic rendering is better (read: hardware accelleration) + if (!(chosen_pfd.dwFlags & PFD_GENERIC_FORMAT) && + (pfd.dwFlags & PFD_GENERIC_FORMAT)) continue; + // offering overlay is better: + else if (!(chosen_pfd.bReserved & 15) && (pfd.bReserved & 15)) {} + // otherwise more bit planes is better: + else if (chosen_pfd.cColorBits > pfd.cColorBits) continue; + else if (chosen_pfd.cDepthBits > pfd.cDepthBits) continue; + } + pixelformat = i; + chosen_pfd = pfd; + } + //printf("Chosen pixel format is %d\n", pixelformat); + if (!pixelformat) return 0; +#else +# error platform unsupported +#endif + + g = new fltk3::GlChoice; + g->mode = m; + g->alist = alistp; + g->next = first; + first = g; + +#if defined(USE_X11) + g->vis = visp; + + if (/*MaxCmapsOfScreen(ScreenOfDisplay(fl_display,fl_screen))==1 && */ + visp->visualid == fl_visual->visualid && + !fltk3::getenv("MESA_PRIVATE_CMAP")) + g->colormap = fl_colormap; + else + g->colormap = XCreateColormap(fl_display, RootWindow(fl_display,fl_screen), + visp->visual, AllocNone); +# elif defined(WIN32) + g->pixelformat = pixelformat; + g->pfd = chosen_pfd; +# elif defined(__APPLE_QUARTZ__) + // warning: the Quartz version should probably use Core GL (CGL) instead of AGL + g->pixelformat = fmt; +# else +# error unsupported platform +# endif + + return g; +} + +static GLContext *context_list = 0; +static int nContext = 0, NContext = 0; + +static void add_context(GLContext ctx) { + if (!ctx) return; + if (nContext==NContext) { + if (!NContext) NContext = 8; + NContext *= 2; + context_list = (GLContext*)realloc( + context_list, NContext*sizeof(GLContext)); + } + context_list[nContext++] = ctx; +} + +static void del_context(GLContext ctx) { + int i; + for (i=0; i<nContext; i++) { + if (context_list[i]==ctx) { + memmove(context_list+i, context_list+i+1, + (nContext-i-1) * sizeof(GLContext)); + context_list[--nContext] = 0; + break; + } + } + if (!nContext) gl_remove_displaylist_fonts(); +} + +#if defined(USE_X11) + +GLContext fl_create_gl_context(XVisualInfo* vis) { + GLContext shared_ctx = 0; + if (context_list && nContext) shared_ctx = context_list[0]; + GLContext context = glXCreateContext(fl_display, vis, shared_ctx, 1); + if (context) + add_context(context); + return context; +} + +#elif defined(WIN32) + +GLContext fl_create_gl_context(fltk3::Window* window, const fltk3::GlChoice* g, int layer) { + Fl_X* i = Fl_X::i(window); + HDC hdc = i->private_dc; + if (!hdc) { + hdc = i->private_dc = GetDCEx(i->xid, 0, DCX_CACHE); + fl_save_dc(i->xid, hdc); + SetPixelFormat(hdc, g->pixelformat, (PIXELFORMATDESCRIPTOR*)(&g->pfd)); +# if USE_COLORMAP + if (fl_palette) SelectPalette(hdc, fl_palette, FALSE); +# endif + } + GLContext context = + layer ? wglCreateLayerContext(hdc, layer) : wglCreateContext(hdc); + if (context) { + if (context_list && nContext) + wglShareLists(context_list[0], context); + add_context(context); + } + return context; +} + +# elif defined(__APPLE_QUARTZ__) +#if !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && __LP64__) +static CGrafPtr fl_GetWindowPort(WindowRef window) +{ + typedef CGrafPtr (*wf)(WindowRef); + static wf f = NULL; + if ( ! f) f = (wf)Fl_X::get_carbon_function("GetWindowPort"); + return (*f)(window); +} +#endif + +// warning: the Quartz version should probably use Core GL (CGL) instead of AGL +GLContext fl_create_gl_context(fltk3::Window* window, const fltk3::GlChoice* g, int layer) { + GLContext context, shared_ctx = 0; + if (context_list && nContext) shared_ctx = context_list[0]; + context = aglCreateContext( g->pixelformat, shared_ctx); + if (!context) return 0; + add_context((GLContext)context); + if ( window->parent() ) { + int H = window->window()->h(); + GLint rect[] = { window->x(), H-window->h()-window->y(), window->w(), window->h() }; + aglSetInteger( (GLContext)context, AGL_BUFFER_RECT, rect ); + aglEnable( (GLContext)context, AGL_BUFFER_RECT ); + } +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +#if __LP64__ + // 64 bit version + aglSetWindowRef(context, Fl_X::i(window)->window_ref() ); +#else + // 32 bit version >= 10.5 + if (aglSetWindowRef != NULL) + aglSetWindowRef(context, Fl_X::i(window)->window_ref() ); + else + aglSetDrawable( context, fl_GetWindowPort( Fl_X::i(window)->window_ref() ) ); +#endif +#else + // 32 bit version < 10.5 + aglSetDrawable( context, fl_GetWindowPort( Fl_X::i(window)->window_ref() ) ); +#endif + return (context); +} +# else +# error unsupported platform +# endif + +static GLContext cached_context; +static fltk3::Window* cached_window; + +void fl_set_gl_context(fltk3::Window* w, GLContext context) { + if (context != cached_context || w != cached_window) { + cached_context = context; + cached_window = w; +# if defined(USE_X11) + glXMakeCurrent(fl_display, fl_xid(w), context); +# elif defined(WIN32) + wglMakeCurrent(Fl_X::i(w)->private_dc, context); +# elif defined(__APPLE_QUARTZ__) + // warning: the Quartz version should probably use Core GL (CGL) instead of AGL + if ( w->parent() ) { //: resize our GL buffer rectangle + int H = w->window()->h(); + GLint rect[] = { w->x(), H-w->h()-w->y(), w->w(), w->h() }; + aglSetInteger( context, AGL_BUFFER_RECT, rect ); + aglEnable( context, AGL_BUFFER_RECT ); + } +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +#if __LP64__ + // 64 bit version + aglSetWindowRef(context, Fl_X::i(w)->window_ref() ); +#else + // 32 bit version >= 10.5 + if (aglSetWindowRef != NULL) + aglSetWindowRef(context, Fl_X::i(w)->window_ref() ); + else + aglSetDrawable( context, fl_GetWindowPort( Fl_X::i(w)->window_ref() ) ); +#endif +#else + // 32 bit version < 10.5 + aglSetDrawable( context, fl_GetWindowPort( Fl_X::i(w)->window_ref() ) ); +#endif + aglSetCurrentContext(context); +# else +# error unsupported platform +# endif + } +} + +void fl_no_gl_context() { + cached_context = 0; + cached_window = 0; +# if defined(USE_X11) + glXMakeCurrent(fl_display, 0, 0); +# elif defined(WIN32) + wglMakeCurrent(0, 0); +# elif defined(__APPLE_QUARTZ__) + // warning: the Quartz version should probably use Core GL (CGL) instead of AGL + AGLContext ctx = aglGetCurrentContext(); +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + if (aglSetWindowRef != NULL) + { if(ctx) aglSetWindowRef(ctx, NULL ); } + else +#endif + if(ctx) aglSetDrawable( ctx, NULL ); + aglSetCurrentContext(0); +# else +# error unsupported platform +# endif +} + +void fl_delete_gl_context(GLContext context) { + if (cached_context == context) fl_no_gl_context(); +# if defined(USE_X11) + glXDestroyContext(fl_display, context); +# elif defined(WIN32) + wglDeleteContext(context); +# elif defined(__APPLE_QUARTZ__) + // warning: the Quartz version should probably use Core GL (CGL) instead of AGL + aglDestroyContext( context ); +# else +# error unsupported platform +# endif + del_context(context); +} + +#endif // HAVE_GL + + +// +// End of "$Id$". +// Copied: branches/branch-3.0/src/fltk3gl/GL_Choice.h (from rev 9008, branches/branch-3.0/src/fltk3gl/GlChoice.h) =================================================================== --- branches/branch-3.0/src/fltk3gl/GL_Choice.h (rev 0) +++ branches/branch-3.0/src/fltk3gl/GL_Choice.h 2011-08-25 10:53:58 UTC (rev 9009) @@ -0,0 +1,129 @@ +// +// "$Id$" +// +// OpenGL definitions for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2010 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Internal interface to set up OpenGL. +// +// A "fltk3::GlChoice" is created from an OpenGL mode and holds information +// necessary to create a window (on X) and to create an OpenGL "context" +// (on both X and Win32). +// +// fl_create_gl_context takes a window (necessary only on Win32) and an +// fltk3::GlChoice and returns a new OpenGL context. All contexts share +// display lists with each other. +// +// On X another fl_create_gl_context is provided to create it for any +// X visual. +// +// fl_set_gl_context makes the given OpenGL context current and makes +// it draw into the passed window. It tracks the current one context +// to avoid calling the context switching code when the same context +// is used, though it is a mystery to me why the GLX/WGL libraries +// don't do this themselves... +// +// fl_no_gl_context clears that cache so the next fl_set_gl_context is +// guaranteed to work. +// +// fl_delete_gl_context destroys the context. +// +// This code is used by fltk3::GlWindow, gl_start(), and gl_visual() + +#ifndef Fl_Gl_Choice_H +#define Fl_Gl_Choice_H + +// Warning: whatever GLContext is defined to must take exactly the same +// space in a structure as a void*!!! +#ifdef WIN32 +# include <fltk3/gl.h> +# define GLContext HGLRC +#elif defined(__APPLE_QUARTZ__) +// warning: the Quartz version should probably use Core GL (CGL) instead of AGL +# include <OpenGL/gl.h> +# include <AGL/agl.h> +# define GLContext AGLContext +#else +# include <GL/glx.h> +# define GLContext GLXContext +#endif + +namespace fltk3 { + + // Describes crap needed to create a GLContext. + class GlChoice { + int mode; + const int *alist; + fltk3::GlChoice *next; + public: +#ifdef WIN32 + int pixelformat; // the visual to use + PIXELFORMATDESCRIPTOR pfd; // some wgl calls need this thing +#elif defined(__APPLE_QUARTZ__) + // warning: the Quartz version should probably use Core GL (CGL) instead of AGL + AGLPixelFormat pixelformat; +#else + XVisualInfo *vis; // the visual to use + Colormap colormap; // a colormap for that visual +#endif + // Return one of these structures for a given gl mode. + // The second argument is a glX attribute list, and is used if mode is + // zero. This is not supported on Win32: + static fltk3::GlChoice *find(int mode, const int *); + }; + + class Window; + +} // namespace + + +#ifdef WIN32 + + GLContext fl_create_gl_context(fltk3::Window*, const fltk3::GlChoice*, int layer=0); + +#elif defined(__APPLE_QUARTZ__) + // warning: the Quartz version should probably use Core GL (CGL) instead of AGL + + GLContext fl_create_gl_context(fltk3::Window*, const fltk3::GlChoice*, int layer=0); + +#else + + GLContext fl_create_gl_context(XVisualInfo* vis); + + static inline + GLContext fl_create_gl_context(fltk3::Window*, const fltk3::GlChoice* g) { + return fl_create_gl_context(g->vis); + } + +#endif + + void fl_set_gl_context(fltk3::Window*, GLContext); + void fl_no_gl_context(); + void fl_delete_gl_context(GLContext); + +#endif + +// +// End of "$Id$". +// Copied: branches/branch-3.0/src/fltk3gl/GL_DevicePlugin.cxx (from rev 9008, branches/branch-3.0/src/fltk3gl/GlDevicePlugin.cxx) =================================================================== --- branches/branch-3.0/src/fltk3gl/GL_DevicePlugin.cxx (rev 0) +++ branches/branch-3.0/src/fltk3gl/GL_DevicePlugin.cxx 2011-08-25 10:53:58 UTC (rev 9009) @@ -0,0 +1,156 @@ +// +// "$Id$" +// +// implementation of class Fl_Gl_Device_Plugin for the Fast Light Tool Kit (FLTK). +// +// Copyright 2010 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems to: +// +// http://www.fltk.org/str.php +// + +#include <config.h> +#include <fltk3/Printer.h> +#include <fltk3/GlWindow.h> +#include "Fl_Gl_Choice.H" +#include <fltk3/run.h> +#ifndef __APPLE__ +#include <fltk3/draw.h> +#endif + +#if defined(__APPLE__) +static void imgProviderReleaseData (void *info, const void *data, size_t size) +{ + free((void *)data); +} +#endif + +static void print_gl_window(fltk3::GlWindow *glw, int x, int y, int height) +{ +#ifdef WIN32 + HDC save_gc = fl_gc; + const int bytesperpixel = 3; +#elif defined(__APPLE__) + CGContextRef save_gc = fl_gc; + const int bytesperpixel = 4; +#else + _XGC *save_gc = fl_gc; + const int bytesperpixel = 3; +#endif + fltk3::SurfaceDevice *save_surface = fltk3::SurfaceDevice::surface(); + fl_gc = NULL; + fltk3::DisplayDevice::display_device()->set_current(); +#ifdef WIN32 + fltk3::check(); + fltk3::Window *win = (fltk3::Window*)glw; + while( win->window() ) win = win->window(); + win->redraw(); + fltk3::check(); + glw->make_current(); +#else + glw->make_current(); + glw->redraw(); + glFlush(); + fltk3::check(); + glFinish(); +#endif + // Read OpenGL context pixels directly. + // For extra safety, save & restore OpenGL states that are changed + glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); + glPixelStorei(GL_PACK_ALIGNMENT, 4); /* Force 4-byte alignment */ + glPixelStorei(GL_PACK_ROW_LENGTH, 0); + glPixelStorei(GL_PACK_SKIP_ROWS, 0); + glPixelStorei(GL_PACK_SKIP_PIXELS, 0); + // Read a block of pixels from the frame buffer + int mByteWidth = glw->w() * bytesperpixel; + mByteWidth = (mByteWidth + 3) & ~3; // Align to 4 bytes + uchar *baseAddress = (uchar*)malloc(mByteWidth * glw->h()); + glReadPixels(0, 0, glw->w(), glw->h(), +#ifdef WIN32 + GL_RGB, GL_UNSIGNED_BYTE, +#elif defined(__APPLE__) + GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, +#else // FIXME Linux/Unix + GL_RGB, GL_UNSIGNED_BYTE, +#endif + baseAddress); + glPopClientAttrib(); + save_surface->set_current(); + fl_gc = save_gc; +#if defined(__APPLE__) +// kCGBitmapByteOrder32Host and CGBitmapInfo are supposed to arrive with 10.4 +// but some 10.4 don't have kCGBitmapByteOrder32Host, so we play a little #define game +#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_4 +#define kCGBitmapByteOrder32Host 0 +#define CGBitmapInfo CGImageAlphaInfo +#elif ! defined(kCGBitmapByteOrder32Host) +#ifdef __BIG_ENDIAN__ +#define kCGBitmapByteOrder32Host (4 << 12) +#else /* Little endian. */ +#define kCGBitmapByteOrder32Host (2 << 12) +#endif +#endif + CGColorSpaceRef cSpace = CGColorSpaceCreateDeviceRGB(); + CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, baseAddress, mByteWidth * glw->h(), imgProviderReleaseData); + CGImageRef image = CGImageCreate(glw->w(), glw->h(), 8, 8*bytesperpixel, mByteWidth, cSpace, + (CGBitmapInfo)(kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host), + provider, NULL, false, kCGRenderingIntentDefault); + if(image == NULL) return; + CGContextSaveGState(fl_gc); + CGContextTranslateCTM(fl_gc, 0, height); + CGContextScaleCTM(fl_gc, 1.0f, -1.0f); + CGRect rect = { { x, height - y - glw->h() }, { glw->w(), glw->h() } }; + Fl_X::q_begin_image(rect, 0, 0, glw->w(), glw->h()); + CGContextDrawImage(fl_gc, rect, image); + Fl_X::q_end_image(); + CGContextRestoreGState(fl_gc); + CGImageRelease(image); + CGColorSpaceRelease(cSpace); + CGDataProviderRelease(provider); +#else + fltk3::draw_image(baseAddress + (glw->h() - 1) * mByteWidth, x, y , glw->w(), glw->h(), bytesperpixel, - mByteWidth); + free(baseAddress); +#endif // __APPLE__ +} + +/** + This class will make sure that OpenGL printing is available if fltk_gl + was linked to the program. + */ +class Fl_Gl_Device_Plugin : public fltk3::DevicePlugin { +public: + Fl_Gl_Device_Plugin() : fltk3::DevicePlugin(name()) { } + virtual const char *name() { return "opengl.device.fltk.org"; } + virtual int print(fltk3::Widget *w, int x, int y, int height) { + fltk3::GlWindow *glw = w->as_gl_window(); + if (!glw) return 0; + print_gl_window(glw, x, y, height); + return 1; + } +}; + +static Fl_Gl_Device_Plugin Gl_Device_Plugin; + +// The purpose of this variable, used in fltk3::GlWindow.cxx, is only to force this file to be loaded +// whenever fltk3::GlWindow.cxx is loaded, that is, whenever fltk_gl is. +FLTK3_EXPORT int fl_gl_load_plugin = 0; + +// +// End of "$Id$". +// Copied: branches/branch-3.0/src/fltk3gl/GL_Overlay.cxx (from rev 9008, branches/branch-3.0/src/fltk3gl/GlOverlay.cxx) =================================================================== --- branches/branch-3.0/src/fltk3gl/GL_Overlay.cxx (rev 0) +++ branches/branch-3.0/src/fltk3gl/GL_Overlay.cxx 2011-08-25 10:53:58 UTC (rev 9009) @@ -0,0 +1,248 @@ +// +// "$Id$" +// +// OpenGL overlay code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2010 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <config.h> +#if HAVE_GL + +#include <fltk3/run.h> +#include <fltk3/x.h> +#include "Fl_Gl_Choice.H" +#include <fltk3/GlWindow.h> +#include <stdlib.h> + +#if !HAVE_GL_OVERLAY + +int fltk3::GlWindow::can_do_overlay() {return 0;} + +void fltk3::GlWindow::make_overlay() {overlay = this;} + +#else + +// Methods on fltk3::GlWindow that create an overlay window. Because +// many programs don't need the overlay, this is separated into this +// source file so it is not linked in if not used. + +// Under X this is done by creating another window, of class _Fl_Gl_Overlay +// which is a subclass of fltk3::GlWindow except it uses the overlay planes. +// A pointer to this is stored in the "overlay" pointer of the fltk3::GlWindow. + +// Under win32 another GLX context is created to draw into the overlay +// and it is stored in the "overlay" pointer. + +// In both cases if overlay hardware is unavailable, the overlay is +// "faked" by drawing into the main layers. This is indicated by +// setting overlay == this. + +#ifndef WIN32 +//////////////////////////////////////////////////////////////// +// X version + +extern XVisualInfo *fl_find_overlay_visual(); +extern XVisualInfo *fl_overlay_visual; +extern Colormap fl_overlay_colormap; +extern unsigned long fl_transparent_pixel; +extern uchar fl_overlay; + +class _Fl_Gl_Overlay : public fltk3::GlWindow { + void flush(); + void draw(); +public: + void show(); + _Fl_Gl_Overlay(int x, int y, int w, int h) : + fltk3::GlWindow(x,y,w,h) { + set_flag(INACTIVE); + } +}; + +void _Fl_Gl_Overlay::flush() { + make_current(); +#ifdef BOXX_BUGS + // The BoXX overlay is broken and you must not call swap-buffers. This + // code will make it work, but we lose because machines that do support + // double-buffered overlays will blink when they don't have to + glDrawBuffer(GL_FRONT); + draw(); +#else + draw(); + swap_buffers(); +#endif + glFlush(); + valid(1); +} + +void _Fl_Gl_Overlay::draw() { + if (!valid()) glClearIndex((GLfloat)fl_transparent_pixel); + if (damage() != fltk3::DAMAGE_EXPOSE) glClear(GL_COLOR_BUFFER_BIT); + fltk3::GlWindow *w = (fltk3::GlWindow *)parent(); + uchar save_valid = w->valid(); + w->valid(valid()); + fl_overlay = 1; + w->draw_overlay(); + fl_overlay = 0; + valid(w->valid()); + w->valid(save_valid); +} + +void _Fl_Gl_Overlay::show() { + if (!shown()) { + fl_background_pixel = int(fl_transparent_pixel); + Fl_X::make_xid(this, fl_overlay_visual, fl_overlay_colormap); + fl_background_pixel = -1; + // find the outermost window to tell wm about the colormap: + fltk3::Window *w = window(); + for (;;) {fltk3::Window *w1 = w->window(); if (!w1) break; w = w1;} + XSetWMColormapWindows(fl_display, fl_xid(w), &(Fl_X::i(this)->xid), 1); + context(fl_create_gl_context(fl_overlay_visual), 1); + valid(0); + } + fltk3::GlWindow::show(); +} + +int fltk3::GlWindow::can_do_overlay() { + return fl_find_overlay_visual() != 0; +} + +void fltk3::GlWindow::make_overlay() { + if (overlay) return; + if (can_do_overlay()) { + _Fl_Gl_Overlay* o = new _Fl_Gl_Overlay(0,0,w(),h()); + overlay = o; + add(*o); + o->show(); + } else { + overlay = this; // fake the overlay + } +} + +#else +//////////////////////////////////////////////////////////////// +// WIN32 version: + +//static COLORREF *palette; +extern int fl_overlay_depth; + +void fltk3::GlWindow::make_overlay() { + if (overlay) return; + + GLContext context = fl_create_gl_context(this, g, 1); + if (!context) {overlay = this; return;} // fake the overlay + + HDC hdc = Fl_X::i(this)->private_dc; + overlay = context; + LAYERPLANEDESCRIPTOR pfd; + wglDescribeLayerPlane(hdc, g->pixelformat, 1, sizeof(pfd), &pfd); + if (!pfd.iPixelType) { + ; // full-color overlay + } else { + fl_overlay_depth = pfd.cColorBits; // used by gl_color() + if (fl_overlay_depth > 8) fl_overlay_depth = 8; + COLORREF palette[256]; + int n = (1<<fl_overlay_depth)-1; + // copy all colors except #0 into the overlay palette: + for (int i = 0; i <= n; i++) { + uchar r,g,b; fltk3::get_color((fltk3::Color)i,r,g,b); + palette[i] = RGB(r,g,b); + } + // always provide black & white in the last 2 pixels: + if (fl_overlay_depth < 8) { + palette[n-1] = RGB(0,0,0); + palette[n] = RGB(255,255,255); + } + // and use it: + wglSetLayerPaletteEntries(hdc, 1, 1, n, palette+1); + wglRealizeLayerPalette(hdc, 1, TRUE); + } + valid(0); + return; +} + +int fltk3::GlWindow::can_do_overlay() { + if (!g) { + g = fltk3::GlChoice::find(mode_,alist); + if (!g) return 0; + } + return (g->pfd.bReserved & 15) != 0; +} + +//////////////////////////////////////////////////////////////// +#endif + +#endif + +void fltk3::GlWindow::redraw_overlay() { + if (!shown()) return; + make_overlay(); +#ifdef __APPLE__ + redraw(); +#else +#ifndef WIN32 + if (overlay != this) + ((fltk3::GlWindow*)overlay)->redraw(); + else +#endif + damage(fltk3::DAMAGE_OVERLAY); +#endif +} + +void fltk3::GlWindow::make_overlay_current() { + make_overlay(); +#ifdef __APPLE__ + // this is not very useful, but unfortunately, Apple decided + // that front buffer drawing can no longer (OS X 10.4) be + // supported on their platforms. + make_current(); +#else +#if HAVE_GL_OVERLAY + if (overlay != this) { +#ifdef WIN32 + fl_set_gl_context(this, (GLContext)overlay); +// if (fl_overlay_depth) +// wglRealizeLayerPalette(Fl_X::i(this)->private_dc, 1, TRUE); +#else + ((fltk3::GlWindow*)overlay)->make_current(); +#endif + } else +#endif + glDrawBuffer(GL_FRONT); +#endif +} +/** Hides the window if it is not this window, does nothing in WIN32. */ +void fltk3::GlWindow::hide_overlay() { +#if HAVE_GL_OVERLAY +#ifdef WIN32 + // nothing needs to be done? Or should it be erased? +#else + if (overlay && overlay!=this) ((fltk3::GlWindow*)overlay)->hide(); +#endif +#endif +} + +#endif + +// +// End of "$Id$". +// Copied: branches/branch-3.0/src/fltk3gl/GL_Window.cxx (from rev 9008, branches/branch-3.0/src/fltk3gl/GlWindow.cxx) =================================================================== --- branches/branch-3.0/src/fltk3gl/GL_Window.cxx (rev 0) +++ branches/branch-3.0/src/fltk3gl/GL_Window.cxx 2011-08-25 10:53:58 UTC (rev 9009) @@ -0,0 +1,554 @@ +// +// "$Id$" +// +// OpenGL window code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2010 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include "flstring.h" +#if HAVE_GL + +extern int fl_gl_load_plugin; + +static int temp = fl_gl_load_plugin; + +#include <fltk3/Wrapper.h> +#include <fltk3/run.h> +#include <fltk3/x.h> +#ifdef __APPLE__ +#include <fltk3/gl.h> +#endif +#include "Fl_Gl_Choice.H" +#include <fltk3/GlWindow.h> +#include <stdlib.h> +#include <fltk3/utf8.h> + +//////////////////////////////////////////////////////////////// + +// The symbol SWAP_TYPE defines what is in the back buffer after doing +// a glXSwapBuffers(). + +// The OpenGl documentation says that the contents of the backbuffer +// are "undefined" after glXSwapBuffers(). However, if we know what +// is in the backbuffers then we can save a good deal of time. For +// this reason you can define some symbols to describe what is left in +// the back buffer. + +// Having not found any way to determine this from glx (or wgl) I have +// resorted to letting the user specify it with an environment variable, +// GL_SWAP_TYPE, it should be equal to one of these symbols: + +// contents of back buffer after glXSwapBuffers(): +#define UNDEFINED 1 // anything +#define SWAP 2 // former front buffer (same as unknown) +#define COPY 3 // unchanged +#define NODAMAGE 4 // unchanged even by X expose() events + +static char SWAP_TYPE = 0 ; // 0 = determine it from environment variable + +//////////////////////////////////////////////////////////////// + +/** Returns non-zero if the hardware supports the given or current OpenGL mode. */ +int fltk3::GlWindow::can_do(int a, const int *b) { + return fltk3::GlChoice::find(a,b) != 0; +} + +void fltk3::GlWindow::show() { +#if defined(__APPLE__) + int need_redraw = 0; +#endif + if (!shown()) { + if (!g) { + g = fltk3::GlChoice::find(mode_,alist); + + if (!g && (mode_ & fltk3::DOUBLE) == fltk3::SINGLE) { + g = fltk3::GlChoice::find(mode_ | fltk3::DOUBLE,alist); + if (g) mode_ |= fltk3::FAKE_SINGLE; + } + + if (!g) { + fltk3::error("Insufficient GL support"); + return; + } + } +#if !defined(WIN32) && !defined(__APPLE__) + Fl_X::make_xid(this, g->vis, g->colormap); + if (overlay && overlay != this) ((fltk3::GlWindow*)overlay)->show(); +#elif defined(__APPLE__) + if( ! parent() ) need_redraw=1; +#endif + } + Window::show(); + +#ifdef __APPLE__ + set_visible(); + if(need_redraw) redraw();//necessary only after creation of a top-level GL window +#endif /* __APPLE__ */ +} + +/** + The invalidate() method turns off valid() and is + equivalent to calling value(0). +*/ +void fltk3::GlWindow::invalidate() { + valid(0); + context_valid(0); +#ifndef WIN32 + if (overlay) { + ((fltk3::GlWindow*)overlay)->valid(0); + ((fltk3::GlWindow*)overlay)->context_valid(0); + } +#endif +} + +/** + See const int fltk3::GlWindow::mode() const +*/ +int fltk3::GlWindow::mode(int m, const int *a) { + if (m == mode_ && a == alist) return 0; +#ifndef __APPLE__ + int oldmode = mode_; +#endif // !__APPLE__ +#if !defined(WIN32) && !defined(__APPLE__) + fltk3::GlChoice* oldg = g; +#endif // !WIN32 && !__APPLE__ + context(0); + mode_ = m; alist = a; + if (shown()) { + g = fltk3::GlChoice::find(m, a); + +#if defined(USE_X11) + // under X, if the visual changes we must make a new X window (yuck!): + if (!g || g->vis->visualid!=oldg->vis->visualid || (oldmode^m)&fltk3::DOUBLE) { + hide(); + show(); + } +#elif defined(WIN32) + if (!g || (oldmode^m)&(fltk3::DOUBLE|fltk3::STEREO)) { + hide(); + show(); + } +#elif defined(__APPLE_QUARTZ__) + // warning: the Quartz version should probably use Core GL (CGL) instead of AGL + redraw(); +#else +# error unsupported platform +#endif + } else { + g = 0; + } + return 1; +} + +#define NON_LOCAL_CONTEXT 0x80000000 + +/** + The make_current() method selects the OpenGL context for the + widget. It is called automatically prior to the draw() method + being called and can also be used to implement feedback and/or + selection within the handle() method. +*/ + +void fltk3::GlWindow::make_current() { +// puts("fltk3::GlWindow::make_current()"); +// printf("make_current: context_=%p\n", context_); + if (!context_) { + mode_ &= ~NON_LOCAL_CONTEXT; + context_ = fl_create_gl_context(this, g); + valid(0); + context_valid(0); + } + fl_set_gl_context(this, context_); + +#ifdef __APPLE__ + // Set the buffer rectangle here, since in resize() we won't have the + // correct parent window size to work with... + GLint xywh[4]; + + if (window()) { + xywh[0] = x(); + xywh[1] = window()->h() - y() - h(); + } else { + xywh[0] = 0; + xywh[1] = 0; + } + + xywh[2] = w(); + xywh[3] = h(); + + aglSetInteger(context_, AGL_BUFFER_RECT, xywh); + aglEnable(context_, AGL_BUFFER_RECT); +// printf("make_current: xywh=[%d %d %d %d]\n", xywh[0], xywh[1], xywh[2], xywh[3]); +#endif // __APPLE__ + +#if defined(WIN32) && USE_COLORMAP + if (fl_palette) { + fl_GetDC(fl_xid(this)); + SelectPalette(fl_gc, fl_palette, FALSE); + RealizePalette(fl_gc); + } +#endif // USE_COLORMAP + if (mode_ & fltk3::FAKE_SINGLE) { + glDrawBuffer(GL_FRONT); + glReadBuffer(GL_FRONT); + } + current_ = this; +} + +/** + Sets the projection so 0,0 is in the lower left of the window and each + pixel is 1 unit wide/tall. If you are drawing 2D images, your + draw() method may want to call this if valid() is false. +*/ +void fltk3::GlWindow::ortho() { +// Alpha NT seems to have a broken OpenGL that does not like negative coords: +#ifdef _M_ALPHA + glLoadIdentity(); + glViewport(0, 0, w(), h()); + glOrtho(0, w(), 0, h(), -1, 1); +#else + GLint v[2]; + glGetIntegerv(GL_MAX_VIEWPORT_DIMS, v); + glLoadIdentity(); + glViewport(w()-v[0], h()-v[1], v[0], v[1]); + glOrtho(w()-v[0], w(), h()-v[1], h(), -1, 1); +#endif +} + +/** + The swap_buffers() method swaps the back and front buffers. + It is called automatically after the draw() method is called. +*/ +void fltk3::GlWindow::swap_buffers() { +#if defined(USE_X11) + glXSwapBuffers(fl_display, fl_xid(this)); +#elif defined(WIN32) +# if HAVE_GL_OVERLAY + // Do not swap the overlay, to match GLX: + BOOL ret = wglSwapLayerBuffers(Fl_X::i(this)->private_dc, WGL_SWAP_MAIN_PLANE); + DWORD err = GetLastError();; +# else + SwapBuffers(Fl_X::i(this)->private_dc); +# endif +#elif defined(__APPLE_QUARTZ__) + if(overlay != NULL) { + //aglSwapBuffers does not work well with overlays under cocoa + glReadBuffer(GL_BACK); + glDrawBuffer(GL_FRONT); + glCopyPixels(0,0,w(),h(),GL_COLOR); + } + else + aglSwapBuffers((AGLContext)context_); +#else +# error unsupported platform +#endif +} + +#if HAVE_GL_OVERLAY && defined(WIN32) +uchar fl_overlay; // changes how fltk3::color() works +int fl_overlay_depth = 0; +#endif + + +void fltk3::GlWindow::flush() { + uchar save_valid = valid_f_ & 1; +#if HAVE_GL_OVERLAY && defined(WIN32) + uchar save_valid_f = valid_f_; +#endif + +#if defined(__APPLE_QUARTZ__) + // warning: the Quartz version should probably use Core GL (CGL) instead of AGL + //: clear previous clipping in this shared port +#if ! __LP64__ +/*GrafPtr port = GetWindowPort( Fl_X::i(this)->window_ref() ); + Rect rect; SetRect( &rect, 0, 0, 0x7fff, 0x7fff ); + GrafPtr old; GetPort( &old ); + SetPort( port ); + ClipRect( &rect ); + SetPort( old );*/ +#endif +#endif + +#if HAVE_GL_OVERLAY && defined(WIN32) + + bool fixcursor = false; // for fixing the SGI 320 bug + + // Draw into hardware overlay planes if they are damaged: + if (overlay && overlay != this + && (damage()&(fltk3::DAMAGE_OVERLAY|fltk3::DAMAGE_EXPOSE) || !save_valid)) { + // SGI 320 messes up overlay with user-defined cursors: + if (Fl_X::i(this)->cursor && Fl_X::i(this)->cursor != fl_default_cursor) { + fixcursor = true; // make it restore cursor later + SetCursor(0); + } + fl_set_gl_context(this, (GLContext)overlay); + if (fl_overlay_depth) + wglRealizeLayerPalette(Fl_X::i(this)->private_dc, 1, TRUE); + glDisable(GL_SCISSOR_TEST); + glClear(GL_COLOR_BUFFER_BIT); + fl_overlay = 1; + draw_overlay(); + fl_overlay = 0; + valid_f_ = save_valid_f; + wglSwapLayerBuffers(Fl_X::i(this)->private_dc, WGL_SWAP_OVERLAY1); + // if only the overlay was damaged we are done, leave main layer alone: + if (damage() == fltk3::DAMAGE_OVERLAY) { + if (fixcursor) SetCursor(Fl_X::i(this)->cursor); + return; + } + } +#endif + + make_current(); + + if (mode_ & fltk3::DOUBLE) { + + glDrawBuffer(GL_BACK); + + if (!SWAP_TYPE) { +#if defined (__APPLE_QUARTZ__) || defined (USE_X11) + SWAP_TYPE = COPY; +#else + SWAP_TYPE = UNDEFINED; +#endif + const char* c = fltk3::getenv("GL_SWAP_TYPE"); + if (c) { + if (!strcmp(c,"COPY")) SWAP_TYPE = COPY; + else if (!strcmp(c, "NODAMAGE")) SWAP_TYPE = NODAMAGE; + else if (!strcmp(c, "SWAP")) SWAP_TYPE = SWAP; + else SWAP_TYPE = UNDEFINED; + } + } + + if (SWAP_TYPE == NODAMAGE) { + + // don't draw if only overlay damage or expose events: + if ((damage()&~(fltk3::DAMAGE_OVERLAY|fltk3::DAMAGE_EXPOSE)) || !save_valid) + draw(); + swap_buffers(); + + } else if (SWAP_TYPE == COPY) { + + // don't draw if only the overlay is damaged: + if (damage() != fltk3::DAMAGE_OVERLAY || !save_valid) draw(); + swap_buffers(); + + } else if (SWAP_TYPE == SWAP){ + damage(fltk3::DAMAGE_ALL); + draw(); + if (overlay == this) draw_overlay(); + swap_buffers(); + } else if (SWAP_TYPE == UNDEFINED){ // SWAP_TYPE == UNDEFINED + + // If we are faking the overlay, use CopyPixels to act like + // SWAP_TYPE == COPY. Otherwise overlay redraw is way too slow. + if (overlay == this) { + // don't draw if only the overlay is damaged: + if (damage1_ || damage() != fltk3::DAMAGE_OVERLAY || !save_valid) draw(); + // we use a separate context for the copy because rasterpos must be 0 + // and depth test needs to be off: + static GLContext ortho_context = 0; + static fltk3::GlWindow* ortho_window = 0; + int orthoinit = !ortho_context; + if (orthoinit) ortho_context = fl_create_gl_context(this, g); + fl_set_gl_context(this, ortho_context); + if (orthoinit || !save_valid || ortho_window != this) { + glDisable(GL_DEPTH_TEST); + glReadBuffer(GL_BACK); + glDrawBuffer(GL_FRONT); + glLoadIdentity(); + glViewport(0, 0, w(), h()); + glOrtho(0, w(), 0, h(), -1, 1); + glRasterPos2i(0,0); + ortho_window = this; + } + glCopyPixels(0,0,w(),h(),GL_COLOR); + make_current(); // set current context back to draw overlay + damage1_ = 0; + + } else { + damage1_ = damage(); + clear_damage(0xff); draw(); + swap_buffers(); + } + + } + + if (overlay==this && SWAP_TYPE != SWAP) { // fake overlay in front buffer + glDrawBuffer(GL_FRONT); + draw_overlay(); + glDrawBuffer(GL_BACK); + glFlush(); + } + + } else { // single-buffered context is simpler: + + draw(); + if (overlay == this) draw_overlay(); + glFlush(); + + } + +#if HAVE_GL_OVERLAY && defined(WIN32) + if (fixcursor) SetCursor(Fl_X::i(this)->cursor); +#endif + valid(1); + context_valid(1); +} + +void fltk3::GlWindow::resize(int X,int Y,int W,int H) { +// printf("fltk3::GlWindow::resize(X=%d, Y=%d, W=%d, H=%d)\n", X, Y, W, H); +// printf("current: x()=%d, y()=%d, w()=%d, h()=%d\n", x(), y(), w(), h()); + + if (W != w() || H != h()) valid(0); + +#ifdef __APPLE__ + if (X != x() || Y != y() || W != w() || H != h()) aglUpdateContext(context_); +#elif !defined(WIN32) + if ((W != w() || H != h()) && !resizable() && overlay && overlay != this) { + ((fltk3::GlWindow*)overlay)->resize(0,0,W,H); + } +#endif + + Window::resize(X,Y,W,H); +} + +/** + Returns or sets a pointer to the GLContext that this window is + using. This is a system-dependent structure, but it is portable to copy + the context from one window to another. You can also set it to NULL, + which will force FLTK to recreate the context the next time make_current() + is called, this is useful for getting around bugs in OpenGL implementations. + + If <i>destroy_flag</i> is true the context will be destroyed by + fltk when the window is destroyed, or when the mode() is changed, + or the next time context(x) is called. +*/ +void fltk3::GlWindow::context(void* v, int destroy_flag) { + if (context_ && !(mode_&NON_LOCAL_CONTEXT)) fl_delete_gl_context(context_); + context_ = (GLContext)v; + if (destroy_flag) mode_ &= ~NON_LOCAL_CONTEXT; + else mode_ |= NON_LOCAL_CONTEXT; +} + +/** + Hides the window and destroys the OpenGL context. +*/ +void fltk3::GlWindow::hide() { + context(0); +#if HAVE_GL_OVERLAY && defined(WIN32) + if (overlay && overlay != this) { + fl_delete_gl_context((GLContext)overlay); + overlay = 0; + } +#endif + Window::hide(); +} + +/** + The destructor removes the widget and destroys the OpenGL context + associated with it. +*/ +fltk3::GlWindow::~GlWindow() { + hide(); +// delete overlay; this is done by ~Fl_Group +#ifdef __APPLE__ + // resets the pile of string textures used to draw strings + extern void gl_texture_reset(); + gl_texture_reset(); +#endif +} + +void fltk3::GlWindow::init() { + end(); // we probably don't want any children + box(fltk3::NO_BOX); + + mode_ = fltk3::RGB | fltk3::DEPTH | fltk3::DOUBLE; + alist = 0; + context_ = 0; + g = 0; + overlay = 0; + valid_f_ = 0; + damage1_ = 0; + +#if 0 // This breaks resizing on Linux/X11 + int H = h(); + h(1); // Make sure we actually do something in resize()... + resize(x(), y(), w(), H); +#endif // 0 +} + +/** + You must implement this virtual function if you want to draw into the + overlay. The overlay is cleared before this is called. You should + draw anything that is not clear using OpenGL. You must use + gl_color(i) to choose colors (it allocates them from the colormap + using system-specific calls), and remember that you are in an indexed + OpenGL mode and drawing anything other than flat-shaded will probably + not work. + + Both this function and fltk3::GlWindow::draw() should check + fltk3::GlWindow::valid() and set the same transformation. If you + don't your code may not work on other systems. Depending on the OS, + and on whether overlays are real or simulated, the OpenGL context may + be the same or different between the overlay and main window. +*/ +void fltk3::GlWindow::draw_overlay() { + FLTK3_OBJECT_VCALLS_WRAPPER(draw_overlay(), DrawOverlay) +} + +#endif + + /** + You \e \b must subclass fltk3::GlWindow and provide an implementation for + draw(). You may also provide an implementation of draw_overlay() + if you want to draw into the overlay planes. You can avoid + reinitializing the viewport and lights and other things by checking + valid() at the start of draw() and only doing the + initialization if it is false. + + The draw() method can <I>only</I> use OpenGL calls. Do not + attempt to call X, any of the functions in <fltk3/draw.h>, or glX + directly. Do not call gl_start() or gl_finish(). + + If double-buffering is enabled in the window, the back and front + buffers are swapped after this function is completed. +*/ +void fltk3::GlWindow::draw() { + FLTK3_OBJECT_VCALLS_WRAPPER(draw(), Draw) + fltk3::fatal("fltk3::GlWindow::draw() *must* be overriden. Please refer to the documentation."); +} + + +/** + Handle some FLTK events as needed. + */ +int fltk3::GlWindow::handle(int event) +{ + FLTK3_OBJECT_VCALLS_WRAPPER_RET(int, handle(event), Handle) + return Window::handle(event); +} + +// +// End of "$Id$". +// Deleted: branches/branch-3.0/src/fltk3gl/GlChoice.cxx Deleted: branches/branch-3.0/src/fltk3gl/GlChoice.h Deleted: branches/branch-3.0/src/fltk3gl/GlDevicePlugin.cxx Deleted: branches/branch-3.0/src/fltk3gl/GlOverlay.cxx Deleted: branches/branch-3.0/src/fltk3gl/GlWindow.cxx _______________________________________________ fltk-commit mailing list [email protected] http://lists.easysw.com/mailman/listinfo/fltk-commit
