summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManolo Gouy <Manolo>2016-05-08 06:42:57 +0000
committerManolo Gouy <Manolo>2016-05-08 06:42:57 +0000
commit300747225ca2de6db483287fa44ed24d18765b99 (patch)
tree6fb63553203032bc98f4dd84b3162c8e306ffc32
parent048bb2b0f6ea49d0a88eee879017949bbd1ac83d (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
-rw-r--r--FL/Fl_Gl_Window.H59
-rw-r--r--FL/Fl_Gl_Window_Driver.H167
-rw-r--r--src/Fl_Gl_Choice.H100
-rw-r--r--src/Fl_Gl_Choice.cxx414
-rw-r--r--src/Fl_Gl_Overlay.cxx223
-rw-r--r--src/Fl_Gl_Window.cxx571
-rw-r--r--src/config_lib.h8
-rw-r--r--src/gl_draw.cxx1
-rw-r--r--src/gl_start.cxx86
-rw-r--r--src/glut_compatability.cxx41
10 files changed, 964 insertions, 706 deletions
diff --git a/FL/Fl_Gl_Window.H b/FL/Fl_Gl_Window.H
index 8c5b9b723..11e0cef98 100644
--- a/FL/Fl_Gl_Window.H
+++ b/FL/Fl_Gl_Window.H
@@ -3,7 +3,7 @@
//
// OpenGL header file for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2015 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
@@ -33,7 +33,7 @@ typedef void* GLContext; // actually a GLXContext or HGLDC
#endif
class Fl_Gl_Choice; // structure to hold result of glXChooseVisual
-
+class Fl_Gl_Window_Driver;
/**
The Fl_Gl_Window widget sets things up so OpenGL works.
@@ -55,6 +55,8 @@ class Fl_Gl_Choice; // structure to hold result of glXChooseVisual
unless those widgets are modified to draw using OpenGL calls.
*/
class FL_EXPORT Fl_Gl_Window : public Fl_Window {
+ friend class Fl_Gl_Window_Driver;
+ Fl_Gl_Window_Driver *pGlWindowDriver;
int mode_;
const int *alist;
@@ -66,21 +68,23 @@ class FL_EXPORT Fl_Gl_Window : public Fl_Window {
void init();
void *overlay;
- void make_overlay();
- friend class _Fl_Gl_Overlay;
static int can_do(int, const int *);
int mode(int, const int *);
static int gl_plugin_linkage();
+protected:
+ virtual void draw();
public:
-
void show();
+ /** Same as Fl_Window::show(int a, char **b) */
void show(int a, char **b) {Fl_Window::show(a,b);}
void flush();
void hide();
void resize(int,int,int,int);
int handle(int);
+ /** Returns a pointer to the window's Fl_Gl_Window_Driver object */
+ Fl_Gl_Window_Driver *gl_driver() {return pGlWindowDriver;}
/**
Is turned off when FLTK creates a new context for this window or
@@ -204,50 +208,15 @@ public:
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 Fl_Widget.H to avoid redundancy.
virtual Fl_Gl_Window* as_gl_window() {return this;}
- /** 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
- */
-#ifdef __APPLE__ // PORTME: Fl_Surface_Driver - additional functionality
int pixels_per_unit();
-#elif defined(WIN32)
- int pixels_per_unit() { return 1; }
-#elif defined(FL_PORTING)
-# pragma message "FL_PORTING: define multiple resolution OpenGL rendering if your platform supports it"
-#else
- int pixels_per_unit() { return 1; }
-#endif
/** Gives the window width in OpenGL pixels.
Generally identical with the result of the w() function, but for a window mapped to
an Apple 'retina' display, and if Fl::use_high_res_GL(bool) is set to true,
@@ -279,17 +248,9 @@ public:
Fl_Gl_Window(int X, int Y, int W, int H, const char *l=0)
: Fl_Window(X,Y,W,H,l) {init();}
-
-protected:
- /**
- Draws the Fl_Gl_Window.
-
- You \e \b must override the draw() method.
- */
- virtual void draw();
};
-#endif
+#endif // Fl_Gl_Window_H
//
// End of "$Id$".
diff --git a/FL/Fl_Gl_Window_Driver.H b/FL/Fl_Gl_Window_Driver.H
new file mode 100644
index 000000000..b9b5c0a9b
--- /dev/null
+++ b/FL/Fl_Gl_Window_Driver.H
@@ -0,0 +1,167 @@
+//
+// "$Id: Fl_Gl_Window_Driver.H 11696 2016-04-25 06:29:36Z manolo $"
+//
+// Definition of classes Fl_Graphics_Driver, Fl_Surface_Device, Fl_Display_Device
+// for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 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
+// file is missing or damaged, see the license at:
+//
+// http://www.fltk.org/COPYING.php
+//
+// Please report all bugs and problems on the following page:
+//
+// http://www.fltk.org/str.php
+//
+
+#ifndef Fl_Gl_Window_Driver_H
+#define Fl_Gl_Window_Driver_H
+
+#if defined(FL_PORTING)
+# pragma message "FL_PORTING: please, derive and implement the Fl_Gl_Window_Driver class for your platform"
+#endif
+
+#include <FL/Fl_Gl_Window.H>
+
+class Fl_Gl_Choice;
+
+/* The constructor of each Fl_Gl_Window object creates also an object from a
+ platform-specific derived class from this class.
+ */
+class Fl_Gl_Window_Driver {
+protected:
+ Fl_Gl_Window *pWindow;
+public:
+ Fl_Gl_Choice* g() {return pWindow->g;}
+ void g(Fl_Gl_Choice *c) {pWindow->g = c;}
+ int mode() {return pWindow->mode_;}
+ void mode(int m) { pWindow->mode_ = m;}
+ const int *alist() {return pWindow->alist;}
+ void alist(const int *l) { pWindow->alist = l;}
+ void* overlay() {return pWindow->overlay;}
+ void draw_overlay() {pWindow->draw_overlay();}
+
+ Fl_Gl_Window_Driver(Fl_Gl_Window *win) : pWindow(win) {}
+ virtual ~Fl_Gl_Window_Driver() {}
+ static Fl_Gl_Window_Driver *newGlWindowDriver(Fl_Gl_Window *w);
+ static Fl_Gl_Window_Driver *global();
+ virtual int pixels_per_unit() {return 1;}
+ virtual void before_show(int& need_redraw) {}
+ virtual void after_show(int need_redraw) {}
+ virtual void invalidate();
+ virtual int mode_(int m, const int *a) {return 0;}
+ virtual void make_current_before() {}
+ virtual void make_current_after() {}
+ virtual void swap_buffers() {}
+ virtual void resize(int is_a_resize, int w, int h) {}
+ virtual char swap_type();
+ virtual void flush_context() {}
+ virtual int flush_begin(char& valid_f) {return 0;}
+ virtual void hide_overlay(void *& overlay) {}
+ static Fl_Gl_Choice *find_begin(int m, const int *alistp);
+ // 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:
+ virtual Fl_Gl_Choice *find(int mode, const int *alistp) {return NULL;}
+ virtual GLContext create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g, int layer = 0) {return 0;}
+ virtual void set_gl_context(Fl_Window* w, GLContext context) {}
+ virtual void delete_gl_context(GLContext) {}
+ virtual void make_overlay(void* &o);
+ virtual void hide_overlay() {}
+ virtual void make_overlay_current() {}
+ virtual void redraw_overlay() {}
+ virtual int can_do_overlay() {return 0;}
+ virtual void waitGL() {} // support for gl_finish() function
+ virtual void gl_visual(Fl_Gl_Choice*); // support for Fl::gl_visual() function
+ virtual void gl_start() {} // support for gl_start() function
+ virtual void* GetProcAddress(const char *procName); // support for glutGetProcAddress()
+};
+
+#ifdef FL_CFG_GFX_QUARTZ
+class Fl_Cocoa_Gl_Window_Driver : public Fl_Gl_Window_Driver {
+ friend class Fl_Gl_Window_Driver;
+ Fl_Cocoa_Gl_Window_Driver(Fl_Gl_Window *win) : Fl_Gl_Window_Driver(win) {}
+ virtual int pixels_per_unit();
+ virtual void before_show(int& need_redraw);
+ virtual void after_show(int need_redraw);
+ virtual int mode_(int m, const int *a);
+ virtual void make_current_before();
+ virtual void swap_buffers();
+ virtual void resize(int is_a_resize, int w, int h);
+ virtual char swap_type();
+ virtual void flush_context();
+ virtual Fl_Gl_Choice *find(int m, const int *alistp);
+ virtual GLContext create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g, int layer = 0);
+ virtual void set_gl_context(Fl_Window* w, GLContext context);
+ virtual void delete_gl_context(GLContext);
+ virtual void make_overlay_current();
+ virtual void redraw_overlay();
+ virtual void gl_start();
+};
+#endif // FL_CFG_GFX_QUARTZ
+
+
+#ifdef FL_CFG_GFX_GDI
+
+class Fl_WinAPI_Gl_Window_Driver : public Fl_Gl_Window_Driver {
+ friend class Fl_Gl_Window_Driver;
+ Fl_WinAPI_Gl_Window_Driver(Fl_Gl_Window *win) : Fl_Gl_Window_Driver(win) {}
+ virtual int mode_(int m, const int *a);
+ virtual void make_current_after();
+ virtual void swap_buffers();
+ virtual void invalidate() {}
+ virtual int flush_begin(char& valid_f);
+ virtual void hide_overlay(void *& overlay);
+ virtual Fl_Gl_Choice *find(int m, const int *alistp);
+ virtual GLContext create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g, int layer = 0);
+ virtual void set_gl_context(Fl_Window* w, GLContext context);
+ virtual void delete_gl_context(GLContext);
+ virtual void make_overlay_current();
+ virtual void redraw_overlay();
+ virtual void* GetProcAddress(const char *procName);
+#if HAVE_GL_OVERLAY
+ virtual int can_do_overlay();
+#endif
+};
+
+#endif // FL_CFG_GFX_GDI
+
+
+#ifdef FL_CFG_GFX_XLIB
+#include <X11/Xutil.h>
+class Fl_X11_Gl_Window_Driver : public Fl_Gl_Window_Driver {
+ friend class Fl_Gl_Window_Driver;
+ Fl_X11_Gl_Window_Driver(Fl_Gl_Window *win) : Fl_Gl_Window_Driver(win) {}
+ virtual void before_show(int& need_redraw);
+ virtual int mode_(int m, const int *a);
+ virtual void swap_buffers();
+ virtual void resize(int is_a_resize, int w, int h);
+ virtual char swap_type();
+ virtual Fl_Gl_Choice *find(int m, const int *alistp);
+ virtual GLContext create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g, int layer = 0);
+ virtual void set_gl_context(Fl_Window* w, GLContext context);
+ virtual void delete_gl_context(GLContext);
+#if HAVE_GL_OVERLAY
+ virtual void make_overlay(void *&o);
+ virtual int can_do_overlay();
+ virtual void hide_overlay();
+#endif
+ virtual void make_overlay_current();
+ virtual void redraw_overlay();
+ virtual void waitGL();
+ virtual void gl_visual(Fl_Gl_Choice*); // support for Fl::gl_visual()
+ virtual void gl_start();
+public:
+ static GLContext create_gl_context(XVisualInfo* vis);
+};
+
+#endif // FL_CFG_GFX_XLIB
+
+#endif /* Fl_Gl_Window_Driver_H */
+
+//
+// End of "$Id: Fl_Gl_Window_Driver.H 11662 2016-04-19 16:58:17Z manolo $".
+//
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 *&current) {
+ 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