diff --git a/FL/mac.H b/FL/mac.H
index d289774f2..015b9ddda 100644
--- a/FL/mac.H
+++ b/FL/mac.H
@@ -154,9 +154,6 @@ extern FLWindow *fl_mac_xid(const Fl_Window *win);
/** Returns the Fl_Window corresponding to the given macOS-specific window reference */
extern Fl_Window *fl_mac_find(FLWindow *);
class Fl_Gl_Window;
-/** Call this to make possible the addition of FLTK widgets to a GL3-using Fl_Gl_Window.
- \see \ref opengl3 */
-extern Fl_Gl_Window *fl_mac_prepare_add_widgets_to_GL3_win(Fl_Gl_Window *);
/** The version number of the running Mac OS X (e.g., 100604 for 10.6.4, 101300 for 10.13).
FLTK initializes this global variable before main() begins running. If
diff --git a/documentation/src/opengl.dox b/documentation/src/opengl.dox
index 68f5e71aa..d1a36be11 100644
--- a/documentation/src/opengl.dox
+++ b/documentation/src/opengl.dox
@@ -605,36 +605,6 @@ to be created among your Fl_Gl_Window-derived classes:
\endcode
after the first glutCreateWindow() call.
-\li If the GL3-using window is intended to contain FLTK widgets laid over
-the GL3 scene (see \ref opengl_with_fltk_widgets), extra steps are necessary to make this possible in a
-cross-platform way.
-
- Create a function called, say, add_widgets(), charged of the creation
-of all FLTK widgets expected to be drawn above the GL3 scene, as follows
-\code
-void add_widgets(Fl_Gl_Window *g) {
-#ifdef __APPLE__
- g = fl_mac_prepare_add_widgets_to_GL3_win(g);
-#endif
- g->begin();
- // … Create here FLTK widgets expected to be drawn above the GL3 scene …
- g->end();
-}
-\endcode
-and call this function with the GL3-using window as argument to populate it
-with FLTK widgets.
-
-
-Put
-\code
-#ifndef __APPLE__
- glUseProgram(0); // Switch from GL3-style to GL1-style drawing
- Fl_Gl_Window::draw(); // Draw FLTK child widgets.
-#endif
-\endcode
-at the end of your GL3 window's draw() function. This is not necessary if
-the GL3 window is built by GLUT, because Fl_Glut_Window::draw() does it.
-
-
-
If GLEW is installed on the Mac OS development platform, it is possible
to use the same code for all platforms, with one exception: put
\code
diff --git a/examples/OpenGL3test.cxx b/examples/OpenGL3test.cxx
index 9de83b5bd..edcb56d93 100644
--- a/examples/OpenGL3test.cxx
+++ b/examples/OpenGL3test.cxx
@@ -128,23 +128,17 @@ public:
glEnableVertexAttribArray((GLuint)colourAttribute );
glVertexAttribPointer((GLuint)positionAttribute, 4, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), 0);
glVertexAttribPointer((GLuint)colourAttribute , 4, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (char*)0+4*sizeof(GLfloat));
+ glUseProgram(shaderProgram);
}
else if ((!valid())) {
glViewport(0, 0, pixel_w(), pixel_h());
}
glClearColor(0.08, 0.8, 0.8, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
- glUseProgram(shaderProgram);
GLfloat p[]={0,0};
glUniform2fv(positionUniform, 1, (const GLfloat *)&p);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-#ifndef __APPLE__
- // suggested by https://stackoverflow.com/questions/22293870/mixing-fixed-function-pipeline-and-programmable-pipeline-in-opengl
- // Switch from GL3-style to GL1-style drawing;
- // good under Windows, X11 and Wayland; impossible under macOS.
- glUseProgram(0);
Fl_Gl_Window::draw(); // Draw FLTK child widgets.
-#endif
}
virtual int handle(int event) {
static int first = 1;
@@ -233,9 +227,6 @@ void button_cb(Fl_Widget *, void *) {
}
void add_widgets(Fl_Gl_Window *g) {
-#ifdef __APPLE__
- g = fl_mac_prepare_add_widgets_to_GL3_win(g);
-#endif
Fl::set_color(FL_FREE_COLOR, 255, 0, 0, 140); // partially transparent red
g->begin();
// Create here widgets to go above the GL3 scene
diff --git a/src/Fl_Gl_Choice.cxx b/src/Fl_Gl_Choice.cxx
index f0ddda652..bafab56fd 100644
--- a/src/Fl_Gl_Choice.cxx
+++ b/src/Fl_Gl_Choice.cxx
@@ -28,7 +28,10 @@
#include "Fl_Gl_Window_Driver.H"
#include
#include
-
+#ifndef GL_CURRENT_PROGRAM
+// from glew.h in Windows, glext.h in Unix, not used by FLTK's macOS platform
+# define GL_CURRENT_PROGRAM 0x8B8D
+#endif
GLContext *Fl_Gl_Window_Driver::context_list = 0;
int Fl_Gl_Window_Driver::nContext = 0;
static int NContext = 0;
@@ -57,6 +60,23 @@ void Fl_Gl_Window_Driver::del_context(GLContext ctx) {
if (!nContext) gl_remove_displaylist_fonts();
}
+Fl_Gl_Window_Driver::glUseProgram_type Fl_Gl_Window_Driver::glUseProgram_f = NULL;
+
+void Fl_Gl_Window_Driver::switch_to_GL1() {
+ if (!glUseProgram_f) {
+ glUseProgram_f = (glUseProgram_type)GetProcAddress("glUseProgram");
+ }
+ glGetIntegerv(GL_CURRENT_PROGRAM, ¤t_prog);
+ // Switch from GL3-style to GL1-style drawing;
+ // good under Windows, X11 and Wayland; not appropriate under macOS.
+ // suggested by https://stackoverflow.com/questions/22293870/mixing-fixed-function-pipeline-and-programmable-pipeline-in-opengl
+ if (current_prog) glUseProgram_f(0);
+}
+
+void Fl_Gl_Window_Driver::switch_back() {
+ if (current_prog) glUseProgram_f((GLuint)current_prog);
+}
+
Fl_Gl_Choice *Fl_Gl_Window_Driver::first;
// this assumes one of the two arguments is zero:
diff --git a/src/Fl_Gl_Window.cxx b/src/Fl_Gl_Window.cxx
index 7784af9cb..b6c8f0135 100644
--- a/src/Fl_Gl_Window.cxx
+++ b/src/Fl_Gl_Window.cxx
@@ -262,6 +262,7 @@ void Fl_Gl_Window::resize(int X,int Y,int W,int H) {
if (is_a_resize) valid(0);
pGlWindowDriver->resize(is_a_resize, W, H);
Fl_Window::resize(X,Y,W,H);
+ //pGlWindowDriver->resize(is_a_resize, W, H);//essai
}
/**
@@ -343,6 +344,7 @@ void Fl_Gl_Window::draw_overlay() {}
\see \ref opengl_with_fltk_widgets
*/
void Fl_Gl_Window::draw_begin() {
+ if (mode() & FL_OPENGL3) pGlWindowDriver->switch_to_GL1();
Fl_Surface_Device::push_current( Fl_OpenGL_Display_Device::display_device() );
Fl_OpenGL_Graphics_Driver *drv = (Fl_OpenGL_Graphics_Driver*)Fl_Surface_Device::surface()->driver();
drv->pixels_per_unit_ = pixels_per_unit();
@@ -391,6 +393,7 @@ void Fl_Gl_Window::draw_end() {
glPopAttrib(); // GL_ENABLE_BIT
Fl_Surface_Device::pop_current();
+ if (mode() & FL_OPENGL3) pGlWindowDriver->switch_back();
}
/** Draws the Fl_Gl_Window.
diff --git a/src/Fl_Gl_Window_Driver.H b/src/Fl_Gl_Window_Driver.H
index 8f3f6cf29..383b6bf56 100644
--- a/src/Fl_Gl_Window_Driver.H
+++ b/src/Fl_Gl_Window_Driver.H
@@ -25,6 +25,7 @@
#define Fl_Gl_Window_Driver_H
#include
+#include // for GLint
class Fl_Gl_Choice;
class Fl_Font_Descriptor;
@@ -33,6 +34,10 @@ class Fl_Font_Descriptor;
platform-specific derived class from this class.
*/
class Fl_Gl_Window_Driver {
+private:
+ GLint current_prog;
+ typedef void (*glUseProgram_type)(GLint);
+ static glUseProgram_type glUseProgram_f;
protected:
Fl_Gl_Window *pWindow;
public:
@@ -53,7 +58,7 @@ public:
void* overlay() {return pWindow->overlay;}
void draw_overlay() {pWindow->draw_overlay();}
- Fl_Gl_Window_Driver(Fl_Gl_Window *win) : pWindow(win) {}
+ Fl_Gl_Window_Driver(Fl_Gl_Window *win) : pWindow(win) {current_prog=0;}
virtual ~Fl_Gl_Window_Driver() {}
static Fl_Gl_Window_Driver *newGlWindowDriver(Fl_Gl_Window *w);
static Fl_Gl_Window_Driver *global();
@@ -104,6 +109,8 @@ public:
// true means the platform uses glScissor() to make sure GL subwindows
// don't leak outside their parent window
virtual bool need_scissor() { return false; }
+ virtual void switch_to_GL1();
+ virtual void switch_back();
};
#endif /* Fl_Gl_Window_Driver_H */
diff --git a/src/Fl_cocoa.mm b/src/Fl_cocoa.mm
index 47be438fc..783273662 100644
--- a/src/Fl_cocoa.mm
+++ b/src/Fl_cocoa.mm
@@ -2940,6 +2940,28 @@ NSOpenGLContext* Fl_Cocoa_Window_Driver::create_GLcontext_for_window(NSOpenGLPix
return context;
}
+
+NSOpenGLContext *Fl_Cocoa_Window_Driver::gl1ctxt_create() {
+ FLView *view = (FLView*)[fl_xid(pWindow) contentView];
+ NSView *gl1view = [[NSView alloc] initWithFrame:[view frame]];
+ [view addSubview:gl1view];
+ [gl1view release];
+ NSOpenGLPixelFormat *gl1pixelformat =
+ Fl_Cocoa_Window_Driver::mode_to_NSOpenGLPixelFormat(
+ FL_RGB8 | FL_ALPHA | FL_SINGLE, NULL);
+ NSOpenGLContext *gl1ctxt = [[NSOpenGLContext alloc]
+ initWithFormat:gl1pixelformat shareContext:nil];
+ [gl1pixelformat release];
+ remove_gl_context_opacity(gl1ctxt);
+ [gl1ctxt setView:gl1view];
+ return gl1ctxt;
+}
+
+
+void Fl_Cocoa_Window_Driver::gl1ctxt_resize(NSOpenGLContext *ctxt) {
+ [[ctxt view] setFrame:[[[ctxt view] superview] frame]];
+}
+
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_VERSION_12_0
# define NSOpenGLContextParameterSurfaceOpacity NSOpenGLCPSurfaceOpacity
#endif
diff --git a/src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.H b/src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.H
index 1f0332103..e1a8dabb3 100644
--- a/src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.H
+++ b/src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.H
@@ -20,10 +20,17 @@
#include "../../Fl_Gl_Window_Driver.H"
class Fl_Gl_Choice;
+#ifdef __OBJC__
+ @class NSOpenGLContext;
+#else
+ class NSOpenGLContext;
+#endif
class Fl_Cocoa_Gl_Window_Driver : public Fl_Gl_Window_Driver {
+ NSOpenGLContext *gl1ctxt; // GL1 context in addition to GL3 context
friend Fl_Gl_Window_Driver* Fl_Gl_Window_Driver::newGlWindowDriver(Fl_Gl_Window *);
- Fl_Cocoa_Gl_Window_Driver(Fl_Gl_Window *win) : Fl_Gl_Window_Driver(win) {}
+ Fl_Cocoa_Gl_Window_Driver(Fl_Gl_Window *win);
+ ~Fl_Cocoa_Gl_Window_Driver();
virtual float pixels_per_unit();
virtual void before_show(int& need_after);
virtual void after_show();
@@ -44,6 +51,8 @@ class Fl_Cocoa_Gl_Window_Driver : public Fl_Gl_Window_Driver {
virtual bool need_scissor() { return true; }
virtual void* GetProcAddress(const char *procName);
void apply_scissor();
+ virtual void switch_to_GL1();
+ virtual void switch_back();
};
diff --git a/src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.cxx b/src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.cxx
index b14ac6a17..7a20a7536 100644
--- a/src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.cxx
+++ b/src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.cxx
@@ -48,6 +48,15 @@ public:
};
+Fl_Cocoa_Gl_Window_Driver::Fl_Cocoa_Gl_Window_Driver(Fl_Gl_Window *win) :
+ Fl_Gl_Window_Driver(win) {
+ gl1ctxt = NULL;
+}
+
+Fl_Cocoa_Gl_Window_Driver::~Fl_Cocoa_Gl_Window_Driver() {
+ if (gl1ctxt) Fl_Cocoa_Window_Driver::GLcontext_release(gl1ctxt);
+}
+
Fl_Gl_Choice *Fl_Cocoa_Gl_Window_Driver::find(int m, const int *alistp)
{
Fl::screen_driver()->open_display(); // useful when called through gl_start()
@@ -188,9 +197,18 @@ void Fl_Cocoa_Gl_Window_Driver::swap_buffers() {
char Fl_Cocoa_Gl_Window_Driver::swap_type() {return copy;}
+static void delayed_redraw(Fl_Gl_Window *win) {
+ win->redraw();
+}
+
void Fl_Cocoa_Gl_Window_Driver::resize(int is_a_resize, int w, int h) {
if (pWindow->shown()) apply_scissor();
Fl_Cocoa_Window_Driver::GLcontext_update((NSOpenGLContext*)pWindow->context());
+ if (gl1ctxt) {
+ Fl_Cocoa_Window_Driver::gl1ctxt_resize(gl1ctxt);
+ Fl_Cocoa_Window_Driver::GLcontext_update(gl1ctxt);
+ Fl::add_timeout(0.01, (Fl_Timeout_Handler)delayed_redraw, pWindow);
+ }
}
void Fl_Cocoa_Gl_Window_Driver::apply_scissor() {
@@ -304,44 +322,26 @@ FL_EXPORT NSOpenGLContext *fl_mac_glcontext(GLContext rc) {
}
-/* macOS offers only core contexts when using GL3. This forbids to add
- FLTK widgets to a GL3-using Fl_Gl_Window because these widgets are drawn
+/* macOS offers only core contexts when using GL3. This forbids to draw
+ FLTK widgets in a GL3-using NSOpenGLContext because these widgets are drawn
with the GL1-based Fl_OpenGL_Graphics_Driver. The solution implemented here
- is to create, with public function fl_mac_prepare_add_widgets_to_GL3_win(),
- an additional Fl_Gl_Window placed above and sized as the GL3-based window,
- to give it a non opaque, GL1-based context, and to put the FLTK widgets
- in that additional window.
+ is to create an additional NSView and an associated additional NSOpenGLContext
+ placed above and sized as the GL3-based window, to set the new NSOpenGLContext
+ non opaque and GL1-based, and to draw the FLTK widgets in the new
+ view/GL context.
*/
-class transparentGlWindow : public Fl_Gl_Window { // utility class
- bool need_remove_opacity;
-public:
- transparentGlWindow(int x, int y, int w, int h) : Fl_Gl_Window(x, y, w, h) {
- mode(FL_RGB8 | FL_ALPHA | FL_SINGLE);
- need_remove_opacity = true;
+void Fl_Cocoa_Gl_Window_Driver::switch_to_GL1() {
+ if (!gl1ctxt) {
+ gl1ctxt = Fl_Cocoa_Window_Driver::driver(pWindow)->gl1ctxt_create();
+ Fl::add_timeout(0.01, (Fl_Timeout_Handler)delayed_redraw, pWindow);
}
- void show() {
- Fl_Gl_Window::show();
- if (need_remove_opacity) {
- need_remove_opacity = false;
- Fl_Cocoa_Window_Driver *d = Fl_Cocoa_Window_Driver::driver(this);
- d->remove_gl_context_opacity((NSOpenGLContext*)context());
- }
- }
-};
+ Fl_Cocoa_Window_Driver::GLcontext_makecurrent(gl1ctxt);
+}
-
-Fl_Gl_Window *fl_mac_prepare_add_widgets_to_GL3_win(Fl_Gl_Window *gl3win) {
- gl3win->begin();
- transparentGlWindow *transp = new transparentGlWindow(0, 0,
- gl3win->w(), gl3win->h());
- gl3win->end();
- if (!gl3win->resizable()) gl3win->resizable(gl3win);
- if (gl3win->shown()) {
- transp->show();
- gl3win->make_current();
- }
- return transp;
+void Fl_Cocoa_Gl_Window_Driver::switch_back() {
+ glFlush();
+ Fl_Cocoa_Window_Driver::GLcontext_makecurrent((NSOpenGLContext*)pWindow->context());
}
diff --git a/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H b/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H
index cbd853776..d6f7534c2 100644
--- a/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H
+++ b/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H
@@ -155,6 +155,8 @@ public:
static void GL_cleardrawable(void); // uses Objective-c
static void gl_start(NSOpenGLContext*); // uses Objective-c
static void remove_gl_context_opacity(NSOpenGLContext*); // uses Objective-c
+ NSOpenGLContext *gl1ctxt_create(); // uses Objective-c
+ static void gl1ctxt_resize(NSOpenGLContext*); // uses Objective-c
//icons
virtual void icons(const Fl_RGB_Image *icons[], int count);
diff --git a/src/glut_compatibility.cxx b/src/glut_compatibility.cxx
index 011f9290b..c7484ad5f 100644
--- a/src/glut_compatibility.cxx
+++ b/src/glut_compatibility.cxx
@@ -30,9 +30,6 @@
# include "Fl_Screen_Driver.H"
# include
# define MAXWINDOWS 32
-# ifndef GL_CURRENT_PROGRAM
-# define GL_CURRENT_PROGRAM 0x8B8D // from glew.h
-# endif
static Fl_Glut_Window *windows[MAXWINDOWS+1];
@@ -58,25 +55,7 @@ void Fl_Glut_Window::draw() {
if (!valid()) {reshape(pixel_w(),pixel_h()); valid(1);}
display();
if (children()) {
- if ((mode() & FL_OPENGL3)) {
-#ifndef __APPLE__
- typedef void (*glUseProgram_type)(GLint);
- static glUseProgram_type glUseProgram_f = NULL;
- if (!glUseProgram_f) {
- Fl_Gl_Window_Driver *dr = Fl_Gl_Window_Driver::driver(this);
- glUseProgram_f = (glUseProgram_type)dr->GetProcAddress("glUseProgram");
- }
- GLint current_prog = 0;
- glGetIntegerv(GL_CURRENT_PROGRAM, ¤t_prog);
- // Switch from GL3-style to GL1-style drawing;
- // good under Windows, X11 and Wayland; impossible under macOS.
- glUseProgram_f(0);
- // Draw FLTK child widgets
- Fl_Gl_Window::draw();
- // Switch back to GL3-style drawing
- glUseProgram_f((GLuint)current_prog);
-#endif // ! __APPLE__
- } else Fl_Gl_Window::draw(); // Draw FLTK child widgets
+ Fl_Gl_Window::draw(); // Draw FLTK child widgets
}
indraw = 0;
}