diff options
| author | Manolo Gouy <Manolo> | 2016-05-08 06:42:57 +0000 |
|---|---|---|
| committer | Manolo Gouy <Manolo> | 2016-05-08 06:42:57 +0000 |
| commit | 300747225ca2de6db483287fa44ed24d18765b99 (patch) | |
| tree | 6fb63553203032bc98f4dd84b3162c8e306ffc32 /src | |
| parent | 048bb2b0f6ea49d0a88eee879017949bbd1ac83d (diff) | |
Rewrite OpenGL-related code under the driver model.
Class Fl_Gl_Window_Driver, with its platform-specific derived classes, is created
to hold platform-specific, OpenGL code.
File gl_draw.cxx still needs to be converted to the driver model.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3-porting@11716 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src')
| -rw-r--r-- | src/Fl_Gl_Choice.H | 100 | ||||
| -rw-r--r-- | src/Fl_Gl_Choice.cxx | 414 | ||||
| -rw-r--r-- | src/Fl_Gl_Overlay.cxx | 223 | ||||
| -rw-r--r-- | src/Fl_Gl_Window.cxx | 571 | ||||
| -rw-r--r-- | src/config_lib.h | 8 | ||||
| -rw-r--r-- | src/gl_draw.cxx | 1 | ||||
| -rw-r--r-- | src/gl_start.cxx | 86 | ||||
| -rw-r--r-- | src/glut_compatability.cxx | 41 |
8 files changed, 787 insertions, 657 deletions
diff --git a/src/Fl_Gl_Choice.H b/src/Fl_Gl_Choice.H index a9de81b1f..8e1a6bc93 100644 --- a/src/Fl_Gl_Choice.H +++ b/src/Fl_Gl_Choice.H @@ -3,7 +3,7 @@ // // OpenGL definitions for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2010 by Bill Spitzak and others. +// Copyright 1998-2016 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -22,41 +22,29 @@ // 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 +// create_gl_context takes a window (necessary only on Win32) and an // Fl_Gl_Choice 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 +// On X another create_gl_context is provided to create it for any // X visual. // -// fl_set_gl_context makes the given OpenGL context current and makes +// 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. +// delete_gl_context destroys the context. // // This code is used by Fl_Gl_Window, gl_start(), and gl_visual() #ifndef Fl_Gl_Choice_H #define Fl_Gl_Choice_H -#if defined(WIN32) || defined(__APPLE__) // PORTME: platform OpenGL management -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: add code to list and select OpenGL drawing contexts" -#else -#endif -// Warning: whatever GLContext is defined to must take exactly the same -// space in a structure as a void*!!! -#ifdef WIN32 -# include <FL/gl.h> -# define GLContext HGLRC -#elif defined(__APPLE_QUARTZ__) // PORTME: platform OpenGL management +#ifdef FL_CFG_GFX_QUARTZ + # include <OpenGL/gl.h> #ifdef __OBJC__ @class NSOpenGLPixelFormat; @@ -67,64 +55,60 @@ class NSOpenGLContext; #endif // __OBJC__ typedef NSOpenGLContext* FLOpenGLContextPtr; # define GLContext FLOpenGLContextPtr -#else -# include <GL/glx.h> -# define GLContext GLXContext -#endif -// Describes crap needed to create a GLContext. +// Describes crap needed to create a GLContext under Mac OS X. class Fl_Gl_Choice { + friend class Fl_Gl_Window_Driver; int mode; const int *alist; Fl_Gl_Choice *next; public: -#ifdef WIN32 - int pixelformat; // the visual to use - PIXELFORMATDESCRIPTOR pfd; // some wgl calls need this thing -#elif defined(__APPLE_QUARTZ__) // PORTME: platform OpenGL management + Fl_Gl_Choice(int m, const int *alistp, Fl_Gl_Choice *n) : mode(m), alist(alistp), next(n) {} NSOpenGLPixelFormat* pixelformat; -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: define OpenGL pixel format containers" -#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 Fl_Gl_Choice *find(int mode, const int *); }; -class Fl_Window; - -#ifdef WIN32 +#endif // FL_CFG_GFX_QUARTZ -GLContext fl_create_gl_context(Fl_Window*, const Fl_Gl_Choice*, int layer=0); +#ifdef FL_CFG_GFX_GDI -#elif defined(__APPLE_QUARTZ__) // PORTME: platform OpenGL management - -GLContext fl_create_gl_context(Fl_Window*, const Fl_Gl_Choice*, int layer=0); +# include <FL/gl.h> +# define GLContext HGLRC -#elif defined(FL_PORTING) +// Describes crap needed to create a GLContext under MSWindows. +class Fl_Gl_Choice { + friend class Fl_Gl_Window_Driver; + int mode; + const int *alist; + Fl_Gl_Choice *next; +public: + Fl_Gl_Choice(int m, const int *alistp, Fl_Gl_Choice *n) : mode(m), alist(alistp), next(n) {} + int pixelformat; // the visual to use + PIXELFORMATDESCRIPTOR pfd; // some wgl calls need this thing +}; -# pragma message "FL_PORTING: define fl_create_gl_context function" +#endif // FL_CFG_GFX_GDI -#else +#ifdef FL_CFG_GFX_XLIB -GLContext fl_create_gl_context(XVisualInfo* vis); +# include <GL/glx.h> +# define GLContext GLXContext -static inline -GLContext fl_create_gl_context(Fl_Window*, const Fl_Gl_Choice* g) { - return fl_create_gl_context(g->vis); -} +// Describes crap needed to create a GLContext under X11. +class Fl_Gl_Choice { + friend class Fl_Gl_Window_Driver; + int mode; + const int *alist; + Fl_Gl_Choice *next; +public: + Fl_Gl_Choice(int m, const int *alistp, Fl_Gl_Choice *n) : mode(m), alist(alistp), next(n) {} + XVisualInfo *vis; // the visual to use + Colormap colormap; // a colormap for that visual +}; -#endif +#endif // FL_CFG_GFX_XLIB -void fl_set_gl_context(Fl_Window*, GLContext); -void fl_no_gl_context(); -void fl_delete_gl_context(GLContext); -#endif +#endif // Fl_Gl_Choice_H // // End of "$Id$". diff --git a/src/Fl_Gl_Choice.cxx b/src/Fl_Gl_Choice.cxx index 6d5e8f6e4..5eb55cac5 100644 --- a/src/Fl_Gl_Choice.cxx +++ b/src/Fl_Gl_Choice.cxx @@ -16,49 +16,221 @@ // http://www.fltk.org/str.php // -#include <config.h> +#include "config_lib.h" #if HAVE_GL # include <FL/Fl.H> -# include <FL/x.H> # include <FL/Fl_Graphics_Driver.H> # include <stdlib.h> # include "Fl_Gl_Choice.H" +# include <FL/Fl_Gl_Window.H> +# include <FL/Fl_Gl_Window_Driver.H> # include <FL/gl_draw.H> # include "flstring.h" # include <FL/fl_utf8.h> -#if defined(WIN32) -#include "drivers/WinAPI/Fl_WinAPI_Window_Driver.H" -#elif defined(__APPLE__) // PORTME: platform OpenGL management -#include "drivers/Cocoa/Fl_Cocoa_Screen_Driver.H" -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: add code to list and select OpenGL drawing contexts" -#else -#endif - -# ifdef WIN32 -void fl_save_dc(HWND, HDC); -#elif defined(__APPLE__) // PORTME: platform OpenGL management -extern void gl_texture_reset(); -#endif + +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(); +} static Fl_Gl_Choice *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... -Fl_Gl_Choice *Fl_Gl_Choice::find(int m, const int *alistp) { +Fl_Gl_Choice *Fl_Gl_Window_Driver::find_begin(int m, const int *alistp) { Fl_Gl_Choice *g; - for (g = first; g; g = g->next) - if (g->mode == m && g->alist == alistp) + if (g->mode == m && g->alist == alistp) return g; + return NULL; +} + + +static GLContext cached_context; +static Fl_Window* cached_window; + + +#ifdef FL_CFG_GFX_QUARTZ +#include "drivers/Cocoa/Fl_Cocoa_Screen_Driver.H" +extern void gl_texture_reset(); + +Fl_Gl_Choice *Fl_Cocoa_Gl_Window_Driver::find(int m, const int *alistp) +{ + Fl_Gl_Choice *g = Fl_Gl_Window_Driver::find_begin(m, alistp); + if (g) return g; + NSOpenGLPixelFormat* fmt = Fl_Cocoa_Screen_Driver::mode_to_NSOpenGLPixelFormat(m, alistp); + if (!fmt) return 0; + g = new Fl_Gl_Choice(m, alistp, first); + first = g; + g->pixelformat = fmt; + return g; +} + +GLContext Fl_Cocoa_Gl_Window_Driver::create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g, int layer) { + GLContext context, shared_ctx = 0; + if (context_list && nContext) shared_ctx = context_list[0]; + // resets the pile of string textures used to draw strings + // necessary before the first context is created + if (!shared_ctx) gl_texture_reset(); + context = Fl_Cocoa_Screen_Driver::create_GLcontext_for_window(g->pixelformat, shared_ctx, window); + if (!context) return 0; + add_context((GLContext)context); + return (context); +} + +void Fl_Cocoa_Gl_Window_Driver::set_gl_context(Fl_Window* w, GLContext context) { + if (context != cached_context || w != cached_window) { + cached_context = context; + cached_window = w; + Fl_Cocoa_Screen_Driver::GLcontext_makecurrent(context); + } +} + +void Fl_Cocoa_Gl_Window_Driver::delete_gl_context(GLContext context) { + if (cached_context == context) { + cached_context = 0; + cached_window = 0; + Fl_Cocoa_Screen_Driver::GL_cleardrawable(); + } + Fl_Cocoa_Screen_Driver::GLcontext_release(context); + del_context(context); +} + +#endif // FL_CFG_GFX_QUARTZ + +#ifdef FL_CFG_GFX_GDI +# include <FL/x.H> +#include "drivers/WinAPI/Fl_WinAPI_Window_Driver.H" +extern void fl_save_dc(HWND, HDC); + +Fl_Gl_Choice *Fl_WinAPI_Gl_Window_Driver::find(int m, const int *alistp) +{ + Fl_Gl_Choice *g = Fl_Gl_Window_Driver::find_begin(m, alistp); + if (g) return g; + + // Replacement for ChoosePixelFormat() that finds one with an overlay + // if possible: + HDC gc = (HDC)fl_graphics_driver->gc(); + if (!gc) gc = fl_GetDC(0); + int pixelformat = 0; + PIXELFORMATDESCRIPTOR chosen_pfd; + for (int i = 1; ; i++) { + PIXELFORMATDESCRIPTOR pfd; + if (!DescribePixelFormat(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&FL_INDEX)?PFD_TYPE_COLORINDEX:PFD_TYPE_RGBA)) continue; + if ((m & FL_ALPHA) && !pfd.cAlphaBits) continue; + if ((m & FL_ACCUM) && !pfd.cAccumBits) continue; + if ((!(m & FL_DOUBLE)) != (!(pfd.dwFlags & PFD_DOUBLEBUFFER))) continue; + if ((!(m & FL_STEREO)) != (!(pfd.dwFlags & PFD_STEREO))) continue; + if ((m & FL_DEPTH) && !pfd.cDepthBits) continue; + if ((m & FL_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; + + g = new Fl_Gl_Choice(m, alistp, first); + first = g; + + g->pixelformat = pixelformat; + g->pfd = chosen_pfd; + + return g; +} + + +GLContext Fl_WinAPI_Gl_Window_Driver::create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g, int layer) +{ + Fl_X* i = Fl_X::i(window); + HDC hdc = Fl_WinAPI_Window_Driver::driver(window)->private_dc; + if (!hdc) { + hdc = Fl_WinAPI_Window_Driver::driver(window)->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; +} + + +void Fl_WinAPI_Gl_Window_Driver::set_gl_context(Fl_Window* w, GLContext context) { + if (context != cached_context || w != cached_window) { + cached_context = context; + cached_window = w; + wglMakeCurrent(Fl_WinAPI_Window_Driver::driver(w)->private_dc, context); + } +} + +void Fl_WinAPI_Gl_Window_Driver::delete_gl_context(GLContext context) { + if (cached_context == context) { + cached_context = 0; + cached_window = 0; + wglMakeCurrent(0, 0); + } + wglDeleteContext(context); + del_context(context); +} + +#endif // FL_CFG_GFX_GDI + +#ifdef FL_CFG_GFX_XLIB +# include <FL/x.H> -#if defined(USE_X11) +Fl_Gl_Choice *Fl_X11_Gl_Window_Driver::find(int m, const int *alistp) +{ + Fl_Gl_Choice *g = Fl_Gl_Window_Driver::find_begin(m, alistp); + if (g) return g; + const int *blist; int list[32]; - + if (alistp) blist = alistp; else { @@ -71,16 +243,16 @@ Fl_Gl_Choice *Fl_Gl_Choice::find(int m, const int *alistp) { list[n++] = GLX_GREEN_SIZE; list[n++] = (m & FL_RGB8) ? 8 : 1; if (m & FL_ALPHA) { - list[n++] = GLX_ALPHA_SIZE; - list[n++] = (m & FL_RGB8) ? 8 : 1; + list[n++] = GLX_ALPHA_SIZE; + list[n++] = (m & FL_RGB8) ? 8 : 1; } if (m & FL_ACCUM) { - list[n++] = GLX_ACCUM_GREEN_SIZE; - list[n++] = 1; - if (m & FL_ALPHA) { - list[n++] = GLX_ACCUM_ALPHA_SIZE; - list[n++] = 1; - } + list[n++] = GLX_ACCUM_GREEN_SIZE; + list[n++] = 1; + if (m & FL_ALPHA) { + list[n++] = GLX_ACCUM_ALPHA_SIZE; + list[n++] = 1; + } } } if (m & FL_DOUBLE) { @@ -104,7 +276,7 @@ Fl_Gl_Choice *Fl_Gl_Choice::find(int m, const int *alistp) { list[n] = 0; blist = list; } - + fl_open_display(); XVisualInfo *visp = glXChooseVisual(fl_display, fl_screen, (int *)blist); if (!visp) { @@ -113,109 +285,29 @@ Fl_Gl_Choice *Fl_Gl_Choice::find(int m, const int *alistp) { # endif return 0; } - -#elif defined(__APPLE__) // PORTME: platform OpenGL management - NSOpenGLPixelFormat* fmt = Fl_Cocoa_Screen_Driver::mode_to_NSOpenGLPixelFormat(m, alistp); - if (!fmt) return 0; -#elif defined(WIN32) - - // Replacement for ChoosePixelFormat() that finds one with an overlay - // if possible: - HDC gc = (HDC)fl_graphics_driver->gc(); - if (!gc) gc = fl_GetDC(0); - int pixelformat = 0; - PIXELFORMATDESCRIPTOR chosen_pfd; - for (int i = 1; ; i++) { - PIXELFORMATDESCRIPTOR pfd; - if (!DescribePixelFormat(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&FL_INDEX)?PFD_TYPE_COLORINDEX:PFD_TYPE_RGBA)) continue; - if ((m & FL_ALPHA) && !pfd.cAlphaBits) continue; - if ((m & FL_ACCUM) && !pfd.cAccumBits) continue; - if ((!(m & FL_DOUBLE)) != (!(pfd.dwFlags & PFD_DOUBLEBUFFER))) continue; - if ((!(m & FL_STEREO)) != (!(pfd.dwFlags & PFD_STEREO))) continue; - if ((m & FL_DEPTH) && !pfd.cDepthBits) continue; - if ((m & FL_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 Fl_Gl_Choice; - g->mode = m; - g->alist = alistp; - g->next = first; + g = new Fl_Gl_Choice(m, alistp, first); first = g; - -#if defined(USE_X11) + g->vis = visp; - + if (/*MaxCmapsOfScreen(ScreenOfDisplay(fl_display,fl_screen))==1 && */ visp->visualid == fl_visual->visualid && !fl_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__) // PORTME: platform OpenGL management - g->pixelformat = fmt; -# else -# error unsupported platform -# endif - + visp->visual, AllocNone); + 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(); +GLContext Fl_X11_Gl_Window_Driver::create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g, int layer) { + return create_gl_context(g->vis); } -#if defined(USE_X11) - -GLContext fl_create_gl_context(XVisualInfo* vis) { +GLContext Fl_X11_Gl_Window_Driver::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); @@ -224,95 +316,27 @@ GLContext fl_create_gl_context(XVisualInfo* vis) { return context; } -#elif defined(WIN32) - -GLContext fl_create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g, int layer) { - Fl_X* i = Fl_X::i(window); - HDC hdc = Fl_WinAPI_Window_Driver::driver(window)->private_dc; - if (!hdc) { - hdc = Fl_WinAPI_Window_Driver::driver(window)->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__) // PORTME: platform OpenGL management - -GLContext fl_create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g, int layer) { - GLContext context, shared_ctx = 0; - if (context_list && nContext) shared_ctx = context_list[0]; - // resets the pile of string textures used to draw strings - // necessary before the first context is created - if (!shared_ctx) gl_texture_reset(); - context = Fl_Cocoa_Screen_Driver::create_GLcontext_for_window(g->pixelformat, shared_ctx, window); - if (!context) return 0; - add_context((GLContext)context); - return (context); -} -# else -# error unsupported platform -# endif - -static GLContext cached_context; -static Fl_Window* cached_window; - -void fl_set_gl_context(Fl_Window* w, GLContext context) { +void Fl_X11_Gl_Window_Driver::set_gl_context(Fl_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_WinAPI_Window_Driver::driver(w)->private_dc, context); -# elif defined(__APPLE__) // PORTME: platform OpenGL management - Fl_Cocoa_Screen_Driver::GLcontext_makecurrent(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__) // PORTME: platform OpenGL management - Fl_Cocoa_Screen_Driver::GL_cleardrawable(); -# else -# error unsupported platform -# endif -} - -void fl_delete_gl_context(GLContext context) { - if (cached_context == context) fl_no_gl_context(); -# if defined(USE_X11) +void Fl_X11_Gl_Window_Driver::delete_gl_context(GLContext context) { + if (cached_context == context) { + cached_context = 0; + cached_window = 0; + glXMakeCurrent(fl_display, 0, 0); + } glXDestroyContext(fl_display, context); -# elif defined(WIN32) - wglDeleteContext(context); -# elif defined(__APPLE__) // PORTME: platform OpenGL management - Fl_Cocoa_Screen_Driver::GLcontext_release(context); -# else -# error unsupported platform -# endif del_context(context); } -#endif // HAVE_GL +#endif // FL_CFG_GFX_XLIB +#endif // HAVE_GL // // End of "$Id$". diff --git a/src/Fl_Gl_Overlay.cxx b/src/Fl_Gl_Overlay.cxx index e82fa22a1..afb2c3038 100644 --- a/src/Fl_Gl_Overlay.cxx +++ b/src/Fl_Gl_Overlay.cxx @@ -3,7 +3,7 @@ // // OpenGL overlay code for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2010 by Bill Spitzak and others. +// Copyright 1998-2016 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -16,30 +16,58 @@ // http://www.fltk.org/str.php // -#include <config.h> +#include "config_lib.h" #if HAVE_GL #include <FL/Fl.H> -#include <FL/x.H> +#include <FL/gl.h> #include "Fl_Gl_Choice.H" #include <FL/Fl_Gl_Window.H> +#include <FL/Fl_Gl_Window_Driver.H> #include <stdlib.h> -#if defined(WIN32) // PORTME: platform OpenGL management -#include "drivers/WinAPI/Fl_WinAPI_Window_Driver.H" -#elif defined(__APPLE__) -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: implement OpenGL hardware overlays if they are availbale in a compatible way. This is rarely needed." -#else -#endif +/** + 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 Fl_Gl_Window::can_do_overlay() { + return pGlWindowDriver->can_do_overlay(); +} -#if !HAVE_GL_OVERLAY +void Fl_Gl_Window_Driver::make_overlay(void *&o) { + o = pWindow; +} -int Fl_Gl_Window::can_do_overlay() {return 0;} +/** + 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 Fl_Gl_Window::redraw_overlay() { + if (!shown()) return; + pGlWindowDriver->make_overlay(overlay); + pGlWindowDriver->redraw_overlay(); +} -void Fl_Gl_Window::make_overlay() {overlay = this;} +/** + Selects the OpenGL context for the widget's overlay. + This method 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 Fl_Gl_Window::make_overlay_current() { + pGlWindowDriver->make_overlay(overlay); + pGlWindowDriver->make_overlay_current(); +} + +/** Hides the window if it is not this window, does nothing in WIN32. */ +void Fl_Gl_Window::hide_overlay() { + pGlWindowDriver->hide_overlay(); +} -#else // Methods on Fl_Gl_Window that create an overlay window. Because // many programs don't need the overlay, this is separated into this @@ -56,10 +84,44 @@ void Fl_Gl_Window::make_overlay() {overlay = this;} // "faked" by drawing into the main layers. This is indicated by // setting overlay == this. -#ifndef WIN32 +#ifdef FL_CFG_GFX_QUARTZ + +void Fl_Cocoa_Gl_Window_Driver::make_overlay_current() { + // 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. + pWindow->make_current(); +} + +void Fl_Cocoa_Gl_Window_Driver::redraw_overlay() { + pWindow->redraw(); +} + +#endif // FL_CFG_GFX_QUARTZ + + +#ifdef FL_CFG_GFX_XLIB +#include <FL/x.H> //////////////////////////////////////////////////////////////// // X version +void Fl_X11_Gl_Window_Driver::make_overlay_current() { +#if HAVE_GL_OVERLAY + if (overlay() != pWindow) { + ((Fl_Gl_Window*)overlay())->make_current(); + } else +#endif + glDrawBuffer(GL_FRONT); +} + +void Fl_X11_Gl_Window_Driver::redraw_overlay() { + if (overlay() != pWindow) + ((Fl_Gl_Window*)overlay())->redraw(); + else + pWindow->damage(FL_DAMAGE_OVERLAY); +} + +#if HAVE_GL_OVERLAY + extern XVisualInfo *fl_find_overlay_visual(); extern XVisualInfo *fl_overlay_visual; extern Colormap fl_overlay_colormap; @@ -100,7 +162,7 @@ void _Fl_Gl_Overlay::draw() { uchar save_valid = w->valid(); w->valid(valid()); fl_overlay = 1; - w->draw_overlay(); + w->gl_driver()->draw_overlay(); fl_overlay = 0; valid(w->valid()); w->valid(save_valid); @@ -115,42 +177,79 @@ void _Fl_Gl_Overlay::show() { Fl_Window *w = window(); for (;;) {Fl_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); + context(Fl_X11_Gl_Window_Driver::create_gl_context(fl_overlay_visual), 1); valid(0); } Fl_Gl_Window::show(); } -int Fl_Gl_Window::can_do_overlay() { +void Fl_X11_Gl_Window_Driver::hide_overlay() { + if (overlay() && overlay() != pWindow) ((Fl_Gl_Window*)overlay())->hide(); +} + +int Fl_X11_Gl_Window_Driver::can_do_overlay() { return fl_find_overlay_visual() != 0; } -void Fl_Gl_Window::make_overlay() { - if (overlay) return; + +void Fl_X11_Gl_Window_Driver::make_overlay(void *¤t) { + if (current) return; if (can_do_overlay()) { - _Fl_Gl_Overlay* o = new _Fl_Gl_Overlay(0,0,w(),h()); - overlay = o; - add(*o); + _Fl_Gl_Overlay* o = new _Fl_Gl_Overlay(0, 0, pWindow->w(), pWindow->h()); + current = o; + pWindow->add(*o); o->show(); } else { - overlay = this; // fake the overlay + current = pWindow; // fake the overlay } } +#endif // HAVE_GL_OVERLAY + +#endif // FL_CFG_GFX_XLIB + + +#ifdef FL_CFG_GFX_GDI +#include "drivers/WinAPI/Fl_WinAPI_Window_Driver.H" -#else //////////////////////////////////////////////////////////////// // WIN32 version: +void Fl_WinAPI_Gl_Window_Driver::hide_overlay(void *& overlay) { +#if HAVE_GL_OVERLAY + if (overlay && overlay != pWindow) { + delete_gl_context((GLContext)overlay); + overlay = 0; + } +#endif +} + +void Fl_WinAPI_Gl_Window_Driver::make_overlay_current() { +#if HAVE_GL_OVERLAY + if (overlay != this) { + pGlWindowDriver->set_gl_context(this, (GLContext)overlay); + // if (fl_overlay_depth) + // wglRealizeLayerPalette(Fl_X::i(this)->private_dc, 1, TRUE); + } else +#endif + glDrawBuffer(GL_FRONT); +} + +void Fl_WinAPI_Gl_Window_Driver::redraw_overlay() { + pWindow->damage(FL_DAMAGE_OVERLAY); +} + +#if HAVE_GL_OVERLAY + //static COLORREF *palette; extern int fl_overlay_depth; -void Fl_Gl_Window::make_overlay() { +void Fl_WinAPI_Gl_Window_Driver::make_overlay(void*&overlay) { if (overlay) return; - GLContext context = fl_create_gl_context(this, g, 1); - if (!context) {overlay = this; return;} // fake the overlay + GLContext context = create_gl_context(pWindow, g, 1); + if (!context) {overlay = pWindow; return;} // fake the overlay - HDC hdc = Fl_WinAPI_Window_Driver::driver(this)->private_dc; + HDC hdc = Fl_WinAPI_Window_Driver::driver(pWindow)->private_dc; overlay = context; LAYERPLANEDESCRIPTOR pfd; wglDescribeLayerPlane(hdc, g->pixelformat, 1, sizeof(pfd), &pfd); @@ -179,68 +278,18 @@ void Fl_Gl_Window::make_overlay() { return; } -int Fl_Gl_Window::can_do_overlay() { - if (!g) { - g = Fl_Gl_Choice::find(mode_,alist); - if (!g) return 0; +int Fl_WinAPI_Gl_Window_Driver::can_do_overlay() { + if (!g()) { + g( find(mode(), alist()) ); + if (!g()) return 0; } - return (g->pfd.bReserved & 15) != 0; + return (g()->pfd.bReserved & 15) != 0; } +#endif // HAVE_GL_OVERLAY -//////////////////////////////////////////////////////////////// -#endif - -#endif +#endif // FL_CFG_GFX_GDI -void Fl_Gl_Window::redraw_overlay() { - if (!shown()) return; - make_overlay(); -#ifdef __APPLE__ // PORTME: platform OpenGL management - redraw(); -#else -#ifndef WIN32 - if (overlay != this) - ((Fl_Gl_Window*)overlay)->redraw(); - else -#endif - damage(FL_DAMAGE_OVERLAY); -#endif -} - -void Fl_Gl_Window::make_overlay_current() { - make_overlay(); -#ifdef __APPLE__ // PORTME: platform OpenGL management - // 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 - ((Fl_Gl_Window*)overlay)->make_current(); -#endif - } else -#endif - glDrawBuffer(GL_FRONT); -#endif -} -/** Hides the window if it is not this window, does nothing in WIN32. */ -void Fl_Gl_Window::hide_overlay() { -#if HAVE_GL_OVERLAY -#ifdef WIN32 - // nothing needs to be done? Or should it be erased? -#else - if (overlay && overlay!=this) ((Fl_Gl_Window*)overlay)->hide(); -#endif -#endif -} - -#endif +#endif // HAVE_GL // // End of "$Id$". diff --git a/src/Fl_Gl_Window.cxx b/src/Fl_Gl_Window.cxx index fc8c47c51..0cfdcb7c9 100644 --- a/src/Fl_Gl_Window.cxx +++ b/src/Fl_Gl_Window.cxx @@ -16,39 +16,29 @@ // http://www.fltk.org/str.php // -#include "flstring.h" #include "config_lib.h" #if HAVE_GL extern int fl_gl_load_plugin; -#include <FL/Fl.H> -#include <FL/Fl_Graphics_Driver.H> -#include <FL/Fl_Window_Driver.H> -#include <FL/x.H> #include "Fl_Gl_Choice.H" -#ifdef __APPLE__ // PORTME: platform OpenGL management -#include <FL/gl.h> -#include <OpenGL/OpenGL.h> -#include "drivers/Cocoa/Fl_Cocoa_Window_Driver.H" -#include "drivers/Cocoa/Fl_Cocoa_Screen_Driver.H" -#elif defined(WIN32) -#include "drivers/WinAPI/Fl_WinAPI_Window_Driver.H" -#endif #include <FL/Fl_Gl_Window.H> -#include <FL/Fl_Device.H> +#include <FL/Fl_Gl_Window_Driver.H> #include <stdlib.h> #include <FL/fl_utf8.h> +# if HAVE_DLFCN_H +# include <dlfcn.h> +# endif // HAVE_DLFCN_H +# ifdef HAVE_GLXGETPROCADDRESSARB +# define GLX_GLXEXT_LEGACY +# include <GL/glx.h> +# endif // HAVE_GLXGETPROCADDRESSARB -#include "drivers/OpenGL/Fl_OpenGL_Display_Device.H" -#if defined(WIN32) || defined(__APPLE__) // PORTME: platform OpenGL management -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: implement the creation and destruction of OpenGL surfaces" -#else +#ifdef FL_CFG_GFX_OPENGL +#include "drivers/OpenGL/Fl_OpenGL_Display_Device.H" #endif - //////////////////////////////////////////////////////////////// // The symbol SWAP_TYPE defines what is in the back buffer after doing @@ -76,18 +66,16 @@ 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 Fl_Gl_Window::can_do(int a, const int *b) { - return Fl_Gl_Choice::find(a,b) != 0; + return Fl_Gl_Window_Driver::global()->find(a,b) != 0; } void Fl_Gl_Window::show() { -#if defined(__APPLE__) // PORTME: platform OpenGL management int need_redraw = 0; -#endif if (!shown()) { if (!g) { - g = Fl_Gl_Choice::find(mode_,alist); + g = pGlWindowDriver->find(mode_,alist); if (!g && (mode_ & FL_DOUBLE) == FL_SINGLE) { - g = Fl_Gl_Choice::find(mode_ | FL_DOUBLE,alist); + g = pGlWindowDriver->find(mode_ | FL_DOUBLE,alist); if (g) mode_ |= FL_FAKE_SINGLE; } @@ -96,30 +84,12 @@ void Fl_Gl_Window::show() { return; } } -#if !defined(WIN32) && !defined(__APPLE__) // PORTME: platform OpenGL management - Fl_X::make_xid(this, g->vis, g->colormap); - if (overlay && overlay != this) ((Fl_Gl_Window*)overlay)->show(); -#elif defined(__APPLE__) // PORTME: platform OpenGL management - if( ! parent() ) need_redraw=1; -#endif + pGlWindowDriver->before_show(need_redraw); } Fl_Window::show(); - -#ifdef __APPLE__ // PORTME: platform OpenGL management - set_visible(); - if(need_redraw) redraw();//necessary only after creation of a top-level GL window -#endif /* __APPLE__ */ // PORTME: platform OpenGL management + pGlWindowDriver->after_show(need_redraw); } -#if defined(__APPLE__) // PORTME: platform OpenGL management - -int Fl_Gl_Window::pixels_per_unit() -{ - return (fl_mac_os_version >= 100700 && Fl::use_high_res_GL() && Fl_X::i(this) && - Fl_Cocoa_Window_Driver::driver(this)->mapped_to_retina()) ? 2 : 1; -} - -#endif // __APPLE__ // PORTME: platform OpenGL management /** The invalidate() method turns off valid() and is @@ -128,62 +98,12 @@ int Fl_Gl_Window::pixels_per_unit() void Fl_Gl_Window::invalidate() { valid(0); context_valid(0); -#ifndef WIN32 - if (overlay) { - ((Fl_Gl_Window*)overlay)->valid(0); - ((Fl_Gl_Window*)overlay)->context_valid(0); - } -#endif + pGlWindowDriver->invalidate(); } int Fl_Gl_Window::mode(int m, const int *a) { if (m == mode_ && a == alist) return 0; -#ifndef __APPLE__ // PORTME: platform OpenGL management - int oldmode = mode_; -#endif -#if defined(__APPLE__) || defined(USE_X11) // PORTME: platform OpenGL management - if (a) { // when the mode is set using the a array of system-dependent values, and if asking for double buffer, - // the FL_DOUBLE flag must be set in the mode_ member variable - const int *aa = a; - while (*aa) { - if (*(aa++) == -# if defined(__APPLE__) // PORTME: platform OpenGL management - kCGLPFADoubleBuffer -# else - GLX_DOUBLEBUFFER -# endif - ) { m |= FL_DOUBLE; break; } - } - } -#endif // !__APPLE__ // PORTME: platform OpenGL management -#if !defined(WIN32) && !defined(__APPLE__) // PORTME: platform OpenGL management - Fl_Gl_Choice* oldg = g; -#endif // !WIN32 && !__APPLE__ // PORTME: platform OpenGL management - context(0); - mode_ = m; alist = a; - if (shown()) { - g = Fl_Gl_Choice::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)&FL_DOUBLE) { - hide(); - show(); - } -#elif defined(WIN32) - if (!g || (oldmode^m)&(FL_DOUBLE|FL_STEREO)) { - hide(); - show(); - } -#elif defined(__APPLE_QUARTZ__) // PORTME: platform OpenGL management - redraw(); -#else -# error unsupported platform -#endif - } else { - g = 0; - } - return 1; + return pGlWindowDriver->mode_(m, a); } #define NON_LOCAL_CONTEXT 0x80000000 @@ -198,30 +118,15 @@ int Fl_Gl_Window::mode(int m, const int *a) { void Fl_Gl_Window::make_current() { // puts("Fl_Gl_Window::make_current()"); // printf("make_current: context_=%p\n", context_); -#if defined(__APPLE__) // PORTME: platform OpenGL management - // detect if the window was moved between low and high resolution displays - Fl_Cocoa_Window_Driver *d = Fl_Cocoa_Window_Driver::driver(this); - if (d->changed_resolution()){ - d->changed_resolution(false); - invalidate(); - Fl_Cocoa_Screen_Driver::GLcontext_update(context_); - } -#endif + pGlWindowDriver->make_current_before(); if (!context_) { mode_ &= ~NON_LOCAL_CONTEXT; - context_ = fl_create_gl_context(this, g); + context_ = pGlWindowDriver->create_gl_context(this, g); valid(0); context_valid(0); } - fl_set_gl_context(this, context_); - -#if defined(WIN32) && USE_COLORMAP - if (fl_palette) { - fl_GetDC(fl_xid(this)); - SelectPalette((HDC)fl_graphics_driver->gc(), fl_palette, FALSE); - RealizePalette((HDC)fl_graphics_driver->gc()); - } -#endif // USE_COLORMAP + pGlWindowDriver->set_gl_context(this, context_); + pGlWindowDriver->make_current_after(); if (mode_ & FL_FAKE_SINGLE) { glDrawBuffer(GL_FRONT); glReadBuffer(GL_FRONT); @@ -254,91 +159,13 @@ void Fl_Gl_Window::ortho() { It is called automatically after the draw() method is called. */ void Fl_Gl_Window::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_WinAPI_Window_Driver::driver(this)->private_dc, WGL_SWAP_MAIN_PLANE); - DWORD err = GetLastError();; -# else - SwapBuffers(Fl_WinAPI_Window_Driver::driver(this)->private_dc); -# endif -#elif defined(__APPLE_QUARTZ__) // PORTME: platform OpenGL management - if(overlay != NULL) { - // STR# 2944 [1] - // Save matrixmode/proj/modelview/rasterpos before doing overlay. - // - int wo=pixel_w(), ho=pixel_h(); - GLint matrixmode; - GLfloat pos[4]; - glGetIntegerv(GL_MATRIX_MODE, &matrixmode); - glGetFloatv(GL_CURRENT_RASTER_POSITION, pos); // save original glRasterPos - glMatrixMode(GL_PROJECTION); // save proj/model matrices - glPushMatrix(); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - glScalef(2.0f/wo, 2.0f/ho, 1.0f); - glTranslatef(-wo/2.0f, -ho/2.0f, 0.0f); // set transform so 0,0 is bottom/left of Gl_Window - glRasterPos2i(0,0); // set glRasterPos to bottom left corner - { - // Emulate overlay by doing copypixels - glReadBuffer(GL_BACK); - glDrawBuffer(GL_FRONT); - glCopyPixels(0, 0, wo, ho, GL_COLOR); // copy GL_BACK to GL_FRONT - } - glPopMatrix(); // GL_MODELVIEW // restore model/proj matrices - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(matrixmode); - glRasterPos3f(pos[0], pos[1], pos[2]); // restore original glRasterPos - } - /* // nothing to do here under Cocoa because [NSOpenGLContext -flushBuffer] done later replaces it - else - aglSwapBuffers((AGLContext)context_); - */ -#else -# error unsupported platform -#endif + pGlWindowDriver->swap_buffers(); } -#if HAVE_GL_OVERLAY && defined(WIN32) -uchar fl_overlay; // changes how fl_color() works -int fl_overlay_depth = 0; -#endif - - void Fl_Gl_Window::flush() { if (!shown()) return; uchar save_valid = valid_f_ & 1; -#if HAVE_GL_OVERLAY && defined(WIN32) - uchar save_valid_f = valid_f_; -#endif - -#if HAVE_GL_OVERLAY && defined(WIN32) - - // Draw into hardware overlay planes if they are damaged: - if (overlay && overlay != this - && (damage()&(FL_DAMAGE_OVERLAY|FL_DAMAGE_EXPOSE) || !save_valid)) { - fl_set_gl_context(this, (GLContext)overlay); - if (fl_overlay_depth) - wglRealizeLayerPalette(Fl_WinAPI_Window_Driver::driver(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_WinAPI_Window_Driver::driver(this)->private_dc, WGL_SWAP_OVERLAY1); - // if only the overlay was damaged we are done, leave main layer alone: - if (damage() == FL_DAMAGE_OVERLAY) { - return; - } - } -#endif - + if (pGlWindowDriver->flush_begin(valid_f_) ) return; make_current(); if (mode_ & FL_DOUBLE) { @@ -346,11 +173,7 @@ void Fl_Gl_Window::flush() { glDrawBuffer(GL_BACK); if (!SWAP_TYPE) { -#if defined (__APPLE_QUARTZ__) || defined (USE_X11) // PORTME: platform OpenGL management - SWAP_TYPE = COPY; -#else - SWAP_TYPE = UNDEFINED; -#endif + SWAP_TYPE = pGlWindowDriver->swap_type(); const char* c = fl_getenv("GL_SWAP_TYPE"); if (c) { if (!strcmp(c,"COPY")) SWAP_TYPE = COPY; @@ -390,8 +213,8 @@ void Fl_Gl_Window::flush() { static GLContext ortho_context = 0; static Fl_Gl_Window* 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) ortho_context = pGlWindowDriver->create_gl_context(this, g); + pGlWindowDriver->set_gl_context(this, ortho_context); if (orthoinit || !save_valid || ortho_window != this) { glDisable(GL_DEPTH_TEST); glReadBuffer(GL_BACK); @@ -413,10 +236,7 @@ void Fl_Gl_Window::flush() { } } -#ifdef __APPLE__ // PORTME: platform OpenGL management - Fl_Cocoa_Screen_Driver::GLcontext_flushbuffer(context_); -#endif - + pGlWindowDriver->flush_context(); if (overlay==this && SWAP_TYPE != SWAP) { // fake overlay in front buffer glDrawBuffer(GL_FRONT); draw_overlay(); @@ -442,19 +262,7 @@ void Fl_Gl_Window::resize(int X,int Y,int W,int H) { int is_a_resize = (W != Fl_Widget::w() || H != Fl_Widget::h()); if (is_a_resize) valid(0); - -#ifdef __APPLE__ // PORTME: platform OpenGL management - Fl_X *flx = Fl_X::i(this); - Fl_Cocoa_Window_Driver *d = Fl_Cocoa_Window_Driver::driver(this); - if (flx && d->in_windowDidResize()) Fl_Cocoa_Screen_Driver::GLcontext_update(context_); -#endif - -#if ! ( defined(__APPLE__) || defined(WIN32) ) // PORTME: platform OpenGL management - if (is_a_resize && !resizable() && overlay && overlay != this) { - ((Fl_Gl_Window*)overlay)->resize(0,0,W,H); - } -#endif - + pGlWindowDriver->resize(is_a_resize, W, H); Fl_Window::resize(X,Y,W,H); } @@ -470,7 +278,7 @@ void Fl_Gl_Window::resize(int X,int Y,int W,int H) { or the next time context(x) is called. */ void Fl_Gl_Window::context(void* v, int destroy_flag) { - if (context_ && !(mode_&NON_LOCAL_CONTEXT)) fl_delete_gl_context(context_); + if (context_ && !(mode_&NON_LOCAL_CONTEXT)) pGlWindowDriver->delete_gl_context(context_); context_ = (GLContext)v; if (destroy_flag) mode_ &= ~NON_LOCAL_CONTEXT; else mode_ |= NON_LOCAL_CONTEXT; @@ -481,12 +289,7 @@ void Fl_Gl_Window::context(void* v, int destroy_flag) { */ void Fl_Gl_Window::hide() { context(0); -#if HAVE_GL_OVERLAY && defined(WIN32) - if (overlay && overlay != this) { - fl_delete_gl_context((GLContext)overlay); - overlay = 0; - } -#endif + pGlWindowDriver->hide_overlay(overlay); Fl_Window::hide(); } @@ -497,9 +300,11 @@ void Fl_Gl_Window::hide() { Fl_Gl_Window::~Fl_Gl_Window() { hide(); // delete overlay; this is done by ~Fl_Group + delete pGlWindowDriver; } void Fl_Gl_Window::init() { + pGlWindowDriver = Fl_Gl_Window_Driver::newGlWindowDriver(this); end(); // we probably don't want any children box(FL_NO_BOX); @@ -535,9 +340,9 @@ void Fl_Gl_Window::init() { */ void Fl_Gl_Window::draw_overlay() {} -#endif +#endif // HAVE_GL - /** + /** Draws the Fl_Gl_Window. You \e \b must subclass Fl_Gl_Window 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 @@ -590,6 +395,314 @@ int Fl_Gl_Window::gl_plugin_linkage() { return fl_gl_load_plugin; } +/** The number of pixels per FLTK unit of length for the window. + Returns 1, except for a window mapped to + an Apple 'retina' display, and if Fl::use_high_res_GL(bool) is set to true, + when it returns 2. This method dynamically adjusts its value when the window + is moved to/from a retina display. This method is useful, e.g., to convert, + in a window's handle() method, the FLTK units returned by Fl::event_x() and + Fl::event_y() to the pixel units used by the OpenGL source code. + \version 1.3.4 + */ +int Fl_Gl_Window::pixels_per_unit() { + return pGlWindowDriver->pixels_per_unit(); +} + +// creates a unique, dummy Fl_Gl_Window_Driver object used when no Fl_Gl_Window is around +Fl_Gl_Window_Driver *Fl_Gl_Window_Driver::global() { + static Fl_Gl_Window_Driver *gwd = newGlWindowDriver(NULL); + return gwd; +} + +void Fl_Gl_Window_Driver::invalidate() { + if (pWindow->overlay) { + ((Fl_Gl_Window*)pWindow->overlay)->valid(0); + ((Fl_Gl_Window*)pWindow->overlay)->context_valid(0); + } +} + + +char Fl_Gl_Window_Driver::swap_type() {return UNDEFINED;} + + +void* Fl_Gl_Window_Driver::GetProcAddress(const char *procName) { +#if (HAVE_DLSYM && HAVE_DLFCN_H) + char symbol[1024]; + + snprintf(symbol, sizeof(symbol), "_%s", procName); + +# ifdef RTLD_DEFAULT + return dlsym(RTLD_DEFAULT, symbol); + +# else // No RTLD_DEFAULT support, so open the current a.out symbols... + static void *rtld_default = dlopen(0, RTLD_LAZY); + + if (rtld_default) return dlsym(rtld_default, symbol); + else return 0; + +# endif // RTLD_DEFAULT + +#elif defined(HAVE_GLXGETPROCADDRESSARB) + return glXGetProcAddressARB((const GLubyte *)procName); + +#else + return 0; +#endif // HAVE_DLSYM +} + + +#ifdef FL_CFG_GFX_QUARTZ +//#include <FL/gl.h> +#include <FL/x.H> +#include <OpenGL/OpenGL.h> +#include "drivers/Cocoa/Fl_Cocoa_Window_Driver.H" +#include "drivers/Cocoa/Fl_Cocoa_Screen_Driver.H" + +Fl_Gl_Window_Driver *Fl_Gl_Window_Driver::newGlWindowDriver(Fl_Gl_Window *w) +{ + return new Fl_Cocoa_Gl_Window_Driver(w); +} + +void Fl_Cocoa_Gl_Window_Driver::before_show(int& need_redraw) { + if( ! pWindow->parent() ) need_redraw=1; +} + +void Fl_Cocoa_Gl_Window_Driver::after_show(int need_redraw) { + pWindow->set_visible(); + if(need_redraw) pWindow->redraw();//necessary only after creation of a top-level GL window +} + +int Fl_Cocoa_Gl_Window_Driver::pixels_per_unit() +{ + return (fl_mac_os_version >= 100700 && Fl::use_high_res_GL() && Fl_X::i(pWindow) && + Fl_Cocoa_Window_Driver::driver(pWindow)->mapped_to_retina()) ? 2 : 1; +} + +int Fl_Cocoa_Gl_Window_Driver::mode_(int m, const int *a) { + if (a) { // when the mode is set using the a array of system-dependent values, and if asking for double buffer, + // the FL_DOUBLE flag must be set in the mode_ member variable + const int *aa = a; + while (*aa) { + if (*(aa++) == + kCGLPFADoubleBuffer + ) { m |= FL_DOUBLE; break; } + } + } + pWindow->context(0); + mode( m); alist(a); + if (pWindow->shown()) { + g( find(m, a) ); + pWindow->redraw(); + } else { + g(0); + } + return 1; +} + +void Fl_Cocoa_Gl_Window_Driver::make_current_before() { + // detect if the window was moved between low and high resolution displays + Fl_Cocoa_Window_Driver *d = Fl_Cocoa_Window_Driver::driver(pWindow); + if (d->changed_resolution()){ + d->changed_resolution(false); + invalidate(); + Fl_Cocoa_Screen_Driver::GLcontext_update((GLContext)pWindow->context()); + } +} + +void Fl_Cocoa_Gl_Window_Driver::swap_buffers() { + if (overlay() != NULL) { + // STR# 2944 [1] + // Save matrixmode/proj/modelview/rasterpos before doing overlay. + // + int wo = pWindow->pixel_w(), ho = pWindow->pixel_h(); + GLint matrixmode; + GLfloat pos[4]; + glGetIntegerv(GL_MATRIX_MODE, &matrixmode); + glGetFloatv(GL_CURRENT_RASTER_POSITION, pos); // save original glRasterPos + glMatrixMode(GL_PROJECTION); // save proj/model matrices + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glScalef(2.0f/wo, 2.0f/ho, 1.0f); + glTranslatef(-wo/2.0f, -ho/2.0f, 0.0f); // set transform so 0,0 is bottom/left of Gl_Window + glRasterPos2i(0,0); // set glRasterPos to bottom left corner + { + // Emulate overlay by doing copypixels + glReadBuffer(GL_BACK); + glDrawBuffer(GL_FRONT); + glCopyPixels(0, 0, wo, ho, GL_COLOR); // copy GL_BACK to GL_FRONT + } + glPopMatrix(); // GL_MODELVIEW // restore model/proj matrices + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(matrixmode); + glRasterPos3f(pos[0], pos[1], pos[2]); // restore original glRasterPos + } + /* // nothing to do here under Cocoa because [NSOpenGLContext -flushBuffer] done later replaces it + else + aglSwapBuffers((AGLContext)context_); + */ +} + +void Fl_Cocoa_Gl_Window_Driver::resize(int is_a_resize, int unused, int also) { + Fl_X *flx = Fl_X::i(pWindow); + Fl_Cocoa_Window_Driver *d = Fl_Cocoa_Window_Driver::driver(pWindow); + if (flx && d->in_windowDidResize()) Fl_Cocoa_Screen_Driver::GLcontext_update((GLContext)pWindow->context()); +} + +char Fl_Cocoa_Gl_Window_Driver::swap_type() {return COPY;} + +void Fl_Cocoa_Gl_Window_Driver::flush_context() { + Fl_Cocoa_Screen_Driver::GLcontext_flushbuffer((GLContext)pWindow->context()); +} + +#endif // FL_CFG_GFX_QUARTZ + +#if defined(FL_CFG_GFX_GDI) +#include "drivers/WinAPI/Fl_WinAPI_Window_Driver.H" +#include <FL/x.H> +#include <FL/Fl_Graphics_Driver.H> + +Fl_Gl_Window_Driver *Fl_Gl_Window_Driver::newGlWindowDriver(Fl_Gl_Window *w) +{ + return new Fl_WinAPI_Gl_Window_Driver(w); +} + +int Fl_WinAPI_Gl_Window_Driver::mode_(int m, const int *a) { + int oldmode = mode(); + pWindow->context(0); + mode( m); alist(a); + if (pWindow->shown()) { + g( find(m, a) ); + if (!g() || (oldmode^m)&(FL_DOUBLE|FL_STEREO)) { + pWindow->hide(); + pWindow->show(); + } + } else { + g(0); + } + return 1; +} + +void Fl_WinAPI_Gl_Window_Driver::make_current_after() { +#if USE_COLORMAP + if (fl_palette) { + fl_GetDC(fl_xid(pWindow)); + SelectPalette((HDC)fl_graphics_driver->gc(), fl_palette, FALSE); + RealizePalette((HDC)fl_graphics_driver->gc()); + } +#endif // USE_COLORMAP +} + +//#define HAVE_GL_OVERLAY 1 //test only + +void Fl_WinAPI_Gl_Window_Driver::swap_buffers() { +# if HAVE_GL_OVERLAY + // Do not swap the overlay, to match GLX: + BOOL ret = wglSwapLayerBuffers(Fl_WinAPI_Window_Driver::driver(pWindow)->private_dc, WGL_SWAP_MAIN_PLANE); + DWORD err = GetLastError(); +# else + SwapBuffers(Fl_WinAPI_Window_Driver::driver(pWindow)->private_dc); +# endif +} + +#if HAVE_GL_OVERLAY +uchar fl_overlay; // changes how fl_color() works +int fl_overlay_depth = 0; +#endif + +int Fl_WinAPI_Gl_Window_Driver::flush_begin(char& valid_f_) { +#if HAVE_GL_OVERLAY + char save_valid_f = valid_f_; + // Draw into hardware overlay planes if they are damaged: + if (overlay() && overlay() != pWindow + && (pWindow->damage()&(FL_DAMAGE_OVERLAY|FL_DAMAGE_EXPOSE) || !save_valid_f & 1)) { + set_gl_context(pWindow, (GLContext)overlay()); + if (fl_overlay_depth) + wglRealizeLayerPalette(Fl_WinAPI_Window_Driver::driver(pWindow)->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_WinAPI_Window_Driver::driver(pWindow)->private_dc, WGL_SWAP_OVERLAY1); + // if only the overlay was damaged we are done, leave main layer alone: + if (pWindow->damage() == FL_DAMAGE_OVERLAY) { + return 1; + } + } +#endif + return 0; +} + +void* Fl_WinAPI_Gl_Window_Driver::GetProcAddress(const char *procName) { + return (void*)wglGetProcAddress((LPCSTR)procName); +} + +#endif // FL_CFG_GFX_GDI + + +#if defined(FL_CFG_GFX_XLIB) +#include <FL/x.H> + +Fl_Gl_Window_Driver *Fl_Gl_Window_Driver::newGlWindowDriver(Fl_Gl_Window *w) +{ + return new Fl_X11_Gl_Window_Driver(w); +} + +void Fl_X11_Gl_Window_Driver::before_show(int& need_redraw) { + Fl_X::make_xid(pWindow, g()->vis, g()->colormap); + if (overlay() && overlay() != pWindow) ((Fl_Gl_Window*)overlay())->show(); +} + +int Fl_X11_Gl_Window_Driver::mode_(int m, const int *a) { + int oldmode = mode(); + if (a) { // when the mode is set using the a array of system-dependent values, and if asking for double buffer, + // the FL_DOUBLE flag must be set in the mode_ member variable + const int *aa = a; + while (*aa) { + if (*(aa++) == + GLX_DOUBLEBUFFER + ) { m |= FL_DOUBLE; break; } + } + } + Fl_Gl_Choice* oldg = g(); + pWindow->context(0); + mode(m); alist(a); + if (pWindow->shown()) { + g( find(m, a) ); + // under X, if the visual changes we must make a new X window (yuck!): + if (!g() || g()->vis->visualid != oldg->vis->visualid || (oldmode^m)&FL_DOUBLE) { + pWindow->hide(); + pWindow->show(); + } + } else { + g(0); + } + return 1; +} + +void Fl_X11_Gl_Window_Driver::swap_buffers() { + glXSwapBuffers(fl_display, fl_xid(pWindow)); +} + +void Fl_X11_Gl_Window_Driver::resize(int is_a_resize, int W, int H) { + if (is_a_resize && !pWindow->resizable() && overlay() && overlay() != pWindow) { + ((Fl_Gl_Window*)overlay())->resize(0,0,W,H); + } +} + +char Fl_X11_Gl_Window_Driver::swap_type() {return COPY;} + +void Fl_X11_Gl_Window_Driver::waitGL() { + glXWaitGL(); +} + +#endif // FL_CFG_GFX_XLIB + // // End of "$Id$". // diff --git a/src/config_lib.h b/src/config_lib.h index 929fa7c39..0fd18a322 100644 --- a/src/config_lib.h +++ b/src/config_lib.h @@ -27,7 +27,7 @@ # endif #elif defined(FL_PORTING) # pragma message "FL_PORTING: please choose a core graphics library" -#else /* X11 */ +#elif defined(USE_X11) /* X11 */ # define FL_CFG_GFX_XLIB # ifdef HAVE_GL # define FL_CFG_GFX_OPENGL @@ -46,7 +46,7 @@ # define FL_CFG_PRN_WIN32 #elif defined(FL_PORTING) # pragma message "FL_PORTING: please choose a printer driver" -#else /* X11 */ +#elif defined(USE_X11) /* X11 */ # define FL_CFG_PRN_PS #endif @@ -62,7 +62,7 @@ # define FL_CFG_WIN_WIN32 #elif defined(FL_PORTING) # pragma message "FL_PORTING: please choose a window management library" -#else /* X11 */ +#elif defined(USE_X11) /* X11 */ # define FL_CFG_WIN_X11 #endif @@ -78,7 +78,7 @@ # define FL_CFG_SYS_WIN32 #elif defined(FL_PORTING) # pragma message "FL_PORTING: please choose a system library" -#else /* X11 */ +#elif defined(USE_X11) /* X11 */ # define FL_CFG_SYS_POSIX #endif diff --git a/src/gl_draw.cxx b/src/gl_draw.cxx index 050e9ea6f..9c7961d87 100644 --- a/src/gl_draw.cxx +++ b/src/gl_draw.cxx @@ -19,6 +19,7 @@ // Functions from <FL/gl.h> // See also Fl_Gl_Window and gl_start.cxx +#include "config_lib.h" #if defined(WIN32) || defined(__APPLE__) // PORTME: Fl_Graphics_Driver - platform opengl #elif defined(FL_PORTING) # pragma message "FL_PORTING: implement OpenGL text rendering here" diff --git a/src/gl_start.cxx b/src/gl_start.cxx index a9da93f73..9ca2717ef 100644 --- a/src/gl_start.cxx +++ b/src/gl_start.cxx @@ -3,7 +3,7 @@ // // OpenGL context routines for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2010 by Bill Spitzak and others. +// Copyright 1998-2016 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -28,56 +28,31 @@ // be erased when the buffers are swapped (when double buffer hardware // is being used) -#if defined(WIN32) // PORTME: platform opengl -#elif defined(__APPLE__) -#include "drivers/Cocoa/Fl_Cocoa_Screen_Driver.H" -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: if possible, add OpenGL rendering in non-OpenGL contexts" -#else -#endif - -#include <config.h> +#include "config_lib.h" #if HAVE_GL #include <FL/Fl.H> #include <FL/Fl_Window.H> -#include <FL/x.H> #include <FL/fl_draw.H> #include <FL/gl.h> #include "Fl_Gl_Choice.H" +#include <FL/Fl_Gl_Window.H> +#include <FL/Fl_Gl_Window_Driver.H> static GLContext context; static int clip_state_number=-1; static int pw, ph; -#ifdef WIN32 -static Fl_Gl_Choice* gl_choice; -#endif - -#ifdef __APPLE__ static Fl_Gl_Choice* gl_choice; -#endif /** Creates an OpenGL context */ void gl_start() { if (!context) { -#if defined(USE_X11) - context = fl_create_gl_context(fl_visual); -#elif defined(WIN32) if (!gl_choice) Fl::gl_visual(0); - context = fl_create_gl_context(Fl_Window::current(), gl_choice); -#elif defined(__APPLE_QUARTZ__) - context = fl_create_gl_context(Fl_Window::current(), gl_choice); -#else -# error Unsupported platform -#endif + context = Fl_Gl_Window_Driver::global()->create_gl_context(Fl_Window::current(), gl_choice); } - fl_set_gl_context(Fl_Window::current(), context); -#ifdef __APPLE__ - Fl_Cocoa_Screen_Driver::GLcontext_update(context); // supports window resizing -#elif !defined(WIN32) - glXWaitX(); -#endif + Fl_Gl_Window_Driver::global()->set_gl_context(Fl_Window::current(), context); + Fl_Gl_Window_Driver::global()->gl_start(); if (pw != Fl_Window::current()->w() || ph != Fl_Window::current()->h()) { pw = Fl_Window::current()->w(); ph = Fl_Window::current()->h(); @@ -103,27 +78,46 @@ void gl_start() { /** Releases an OpenGL context */ void gl_finish() { glFlush(); -#if !defined(WIN32) && !defined(__APPLE__) - glXWaitGL(); + Fl_Gl_Window_Driver::global()->waitGL(); +} + +void Fl_Gl_Window_Driver::gl_visual(Fl_Gl_Choice *c) { + gl_choice = c; +} + +#ifdef FL_CFG_GFX_QUARTZ +#include "drivers/Cocoa/Fl_Cocoa_Screen_Driver.H" + +void Fl_Cocoa_Gl_Window_Driver::gl_start() { + Fl_Cocoa_Screen_Driver::GLcontext_update(context); // supports window resizing +} + #endif + + +#ifdef FL_CFG_GFX_XLIB +#include <FL/x.H> + +void Fl_X11_Gl_Window_Driver::gl_visual(Fl_Gl_Choice *c) { + Fl_Gl_Window_Driver::gl_visual(c); + fl_visual = c->vis; + fl_colormap = c->colormap; } +void Fl_X11_Gl_Window_Driver::gl_start() { + glXWaitX(); +} + +#endif // FL_CFG_GFX_XLIB + int Fl::gl_visual(int mode, int *alist) { - Fl_Gl_Choice *c = Fl_Gl_Choice::find(mode,alist); + Fl_Gl_Choice *c = Fl_Gl_Window_Driver::global()->find(mode,alist); if (!c) return 0; -#if defined(USE_X11) - fl_visual = c->vis; - fl_colormap = c->colormap; -#elif defined(WIN32) - gl_choice = c; -#elif defined(__APPLE_QUARTZ__) - gl_choice = c; -#else -# error Unsupported platform -#endif + Fl_Gl_Window_Driver::global()->gl_visual(c); return 1; } -#endif + +#endif // HAVE_GL // // End of "$Id$". diff --git a/src/glut_compatability.cxx b/src/glut_compatability.cxx index 1031b94ae..6a024d321 100644 --- a/src/glut_compatability.cxx +++ b/src/glut_compatability.cxx @@ -28,19 +28,10 @@ #include "flstring.h" #if HAVE_GL - +# include <FL/Fl_Gl_Window_Driver.H> # include <FL/glut.H> -# ifdef HAVE_GLXGETPROCADDRESSARB -# define GLX_GLXEXT_LEGACY -# include <GL/glx.h> -# endif // HAVE_GLXGETPROCADDRESSARB -# if HAVE_DLFCN_H -# include <dlfcn.h> -# endif // HAVE_DLFCN_H # define MAXWINDOWS 32 -# ifdef __APPLE__ -# include <FL/x.H> -# endif + static Fl_Glut_Window *windows[MAXWINDOWS+1]; static void (*glut_idle_func)() = 0; // global glut idle function @@ -440,33 +431,7 @@ int glutDeviceGet(GLenum type) { // Get extension function address... GLUTproc glutGetProcAddress(const char *procName) { -# ifdef WIN32 - return (GLUTproc)wglGetProcAddress((LPCSTR)procName); - -# elif (HAVE_DLSYM && HAVE_DLFCN_H) - char symbol[1024]; - - snprintf(symbol, sizeof(symbol), "_%s", procName); - -# ifdef RTLD_DEFAULT - return (GLUTproc)dlsym(RTLD_DEFAULT, symbol); - -# else // No RTLD_DEFAULT support, so open the current a.out symbols... - static void *rtld_default = 0; - - if (!rtld_default) rtld_default = dlopen(0, RTLD_LAZY); - - if (rtld_default) return (GLUTproc)dlsym(rtld_default, symbol); - else return 0; - -# endif // RTLD_DEFAULT - -# elif defined(HAVE_GLXGETPROCADDRESSARB) - return (GLUTproc)glXGetProcAddressARB((const GLubyte *)procName); - -# else - return (GLUTproc)0; -# endif // WIN32 + return (GLUTproc)Fl_Gl_Window_Driver::global()->GetProcAddress(procName); } // Parse the GL_EXTENSIONS string to see if the named extension is |
