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
This commit is contained in:
Manolo Gouy 2016-05-08 06:42:57 +00:00
parent 048bb2b0f6
commit 300747225c
10 changed files with 971 additions and 713 deletions

View File

@ -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$".

167
FL/Fl_Gl_Window_Driver.H Normal file
View File

@ -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 $".
//

View File

@ -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;
#endif // FL_CFG_GFX_QUARTZ
#ifdef WIN32
#ifdef FL_CFG_GFX_GDI
GLContext fl_create_gl_context(Fl_Window*, const Fl_Gl_Choice*, int layer=0);
# include <FL/gl.h>
# define GLContext HGLRC
#elif defined(__APPLE_QUARTZ__) // PORTME: platform OpenGL management
// 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
};
GLContext fl_create_gl_context(Fl_Window*, const Fl_Gl_Choice*, int layer=0);
#endif // FL_CFG_GFX_GDI
#elif defined(FL_PORTING)
#ifdef FL_CFG_GFX_XLIB
# pragma message "FL_PORTING: define fl_create_gl_context function"
# include <GL/glx.h>
# define GLContext GLXContext
#else
// 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
};
GLContext fl_create_gl_context(XVisualInfo* vis);
#endif // FL_CFG_GFX_XLIB
static inline
GLContext fl_create_gl_context(Fl_Window*, const Fl_Gl_Choice* g) {
return fl_create_gl_context(g->vis);
}
#endif
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$".

View File

@ -16,110 +16,123 @@
// 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;
}
#if defined(USE_X11)
const int *blist;
int list[32];
if (alistp)
blist = alistp;
else {
int n = 0;
if (m & FL_INDEX) {
list[n++] = GLX_BUFFER_SIZE;
list[n++] = 8; // glut tries many sizes, but this should work...
} else {
list[n++] = GLX_RGBA;
list[n++] = GLX_GREEN_SIZE;
list[n++] = (m & FL_RGB8) ? 8 : 1;
if (m & FL_ALPHA) {
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;
}
}
}
if (m & FL_DOUBLE) {
list[n++] = GLX_DOUBLEBUFFER;
}
if (m & FL_DEPTH) {
list[n++] = GLX_DEPTH_SIZE; list[n++] = 1;
}
if (m & FL_STENCIL) {
list[n++] = GLX_STENCIL_SIZE; list[n++] = 1;
}
if (m & FL_STEREO) {
list[n++] = GLX_STEREO;
}
# if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample)
if (m & FL_MULTISAMPLE) {
list[n++] = GLX_SAMPLES_SGIS;
list[n++] = 4; // value Glut uses
}
# endif
list[n] = 0;
blist = list;
}
fl_open_display();
XVisualInfo *visp = glXChooseVisual(fl_display, fl_screen, (int *)blist);
if (!visp) {
# if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample)
if (m&FL_MULTISAMPLE) return find(m&~FL_MULTISAMPLE,0);
# endif
return 0;
}
#elif defined(__APPLE__) // PORTME: platform OpenGL management
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;
#elif defined(WIN32)
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();
@ -154,79 +167,19 @@ Fl_Gl_Choice *Fl_Gl_Choice::find(int m, const int *alistp) {
}
//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
return g;
}
static GLContext *context_list = 0;
static int nContext = 0, NContext = 0;
static void add_context(GLContext ctx) {
if (!ctx) return;
if (nContext==NContext) {
if (!NContext) NContext = 8;
NContext *= 2;
context_list = (GLContext*)realloc(
context_list, NContext*sizeof(GLContext));
}
context_list[nContext++] = ctx;
}
static void del_context(GLContext ctx) {
int i;
for (i=0; i<nContext; i++) {
if (context_list[i]==ctx) {
memmove(context_list+i, context_list+i+1,
(nContext-i-1) * sizeof(GLContext));
context_list[--nContext] = 0;
break;
}
}
if (!nContext) gl_remove_displaylist_fonts();
}
#if defined(USE_X11)
GLContext fl_create_gl_context(XVisualInfo* vis) {
GLContext shared_ctx = 0;
if (context_list && nContext) shared_ctx = context_list[0];
GLContext context = glXCreateContext(fl_display, vis, shared_ctx, 1);
if (context)
add_context(context);
return context;
}
#elif defined(WIN32)
GLContext fl_create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g, int layer) {
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) {
@ -237,82 +190,153 @@ GLContext fl_create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g, int lay
if (fl_palette) SelectPalette(hdc, fl_palette, FALSE);
# endif
}
GLContext context =
layer ? wglCreateLayerContext(hdc, layer) : wglCreateContext(hdc);
GLContext context = layer ? wglCreateLayerContext(hdc, layer) : wglCreateContext(hdc);
if (context) {
if (context_list && nContext)
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_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;
# 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)
glXDestroyContext(fl_display, context);
# elif defined(WIN32)
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);
# 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_GDI
#ifdef FL_CFG_GFX_XLIB
# include <FL/x.H>
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 {
int n = 0;
if (m & FL_INDEX) {
list[n++] = GLX_BUFFER_SIZE;
list[n++] = 8; // glut tries many sizes, but this should work...
} else {
list[n++] = GLX_RGBA;
list[n++] = GLX_GREEN_SIZE;
list[n++] = (m & FL_RGB8) ? 8 : 1;
if (m & FL_ALPHA) {
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;
}
}
}
if (m & FL_DOUBLE) {
list[n++] = GLX_DOUBLEBUFFER;
}
if (m & FL_DEPTH) {
list[n++] = GLX_DEPTH_SIZE; list[n++] = 1;
}
if (m & FL_STENCIL) {
list[n++] = GLX_STENCIL_SIZE; list[n++] = 1;
}
if (m & FL_STEREO) {
list[n++] = GLX_STEREO;
}
# if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample)
if (m & FL_MULTISAMPLE) {
list[n++] = GLX_SAMPLES_SGIS;
list[n++] = 4; // value Glut uses
}
# endif
list[n] = 0;
blist = list;
}
fl_open_display();
XVisualInfo *visp = glXChooseVisual(fl_display, fl_screen, (int *)blist);
if (!visp) {
# if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample)
if (m&FL_MULTISAMPLE) return find(m&~FL_MULTISAMPLE,0);
# endif
return 0;
}
g = new Fl_Gl_Choice(m, alistp, first);
first = g;
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);
return g;
}
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);
}
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);
if (context)
add_context(context);
return 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;
glXMakeCurrent(fl_display, fl_xid(w), context);
}
}
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);
del_context(context);
}
#endif // FL_CFG_GFX_XLIB
#endif // HAVE_GL
//
// End of "$Id$".

View File

@ -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 // FL_CFG_GFX_GDI
#endif
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$".

View File

@ -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
#ifdef FL_CFG_GFX_OPENGL
#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
#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$".
//

View File

@ -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

View File

@ -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"

View File

@ -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();
#endif
Fl_Gl_Window_Driver::global()->waitGL();
}
int Fl::gl_visual(int mode, int *alist) {
Fl_Gl_Choice *c = Fl_Gl_Choice::find(mode,alist);
if (!c) return 0;
#if defined(USE_X11)
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;
#elif defined(WIN32)
gl_choice = c;
#elif defined(__APPLE_QUARTZ__)
gl_choice = c;
#else
# error Unsupported platform
#endif
}
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_Window_Driver::global()->find(mode,alist);
if (!c) return 0;
Fl_Gl_Window_Driver::global()->gl_visual(c);
return 1;
}
#endif
#endif // HAVE_GL
//
// End of "$Id$".

View File

@ -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