summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--FL/mac.H4
-rw-r--r--documentation/src/opengl.dox30
-rw-r--r--examples/OpenGL3test.cxx32
-rw-r--r--src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.cxx41
-rw-r--r--src/glut_compatibility.cxx24
5 files changed, 130 insertions, 1 deletions
diff --git a/FL/mac.H b/FL/mac.H
index 9af98a2e4..d289774f2 100644
--- a/FL/mac.H
+++ b/FL/mac.H
@@ -153,6 +153,10 @@ extern CGContextRef fl_mac_gc();
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 d1a36be11..68f5e71aa 100644
--- a/documentation/src/opengl.dox
+++ b/documentation/src/opengl.dox
@@ -605,6 +605,36 @@ 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.
+<ol><li>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.
+<li>
+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.
+
+</ol>
+
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 9acbaf38b..26ee1b816 100644
--- a/examples/OpenGL3test.cxx
+++ b/examples/OpenGL3test.cxx
@@ -138,6 +138,13 @@ public:
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;
@@ -161,6 +168,9 @@ public:
redraw();
}
+ int retval = Fl_Gl_Window::handle(event);
+ if (retval) return retval;
+
if (event == FL_PUSH && gl_version_major >= 3) {
static float factor = 1.1;
GLfloat data[4];
@@ -175,7 +185,7 @@ public:
add_output("push Fl_Gl_Window::pixels_per_unit()=%.1f\n", pixels_per_unit());
return 1;
}
- return Fl_Gl_Window::handle(event);
+ return retval;
}
void reset(void) { shaderProgram = 0; }
};
@@ -218,6 +228,25 @@ void add_output(const char *format, ...)
}
+void button_cb(Fl_Widget *, void *) {
+ add_output("run button callback\n");
+}
+
+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
+ Fl_Button* b = new Fl_Button( 0, 170, 60, 30, "button");
+ b->color(FL_FREE_COLOR);
+ b->box(FL_BORDER_BOX );
+ b->callback(button_cb, NULL);
+ g->end();
+}
+
+
int main(int argc, char **argv)
{
Fl::use_high_res_GL(1);
@@ -225,6 +254,7 @@ int main(int argc, char **argv)
SimpleGL3Window *win = new SimpleGL3Window(0, 0, 300, 300);
win->end();
output_win(win);
+ add_widgets(win);
topwin->end();
topwin->resizable(win);
topwin->label("Click GL panel to reshape");
diff --git a/src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.cxx b/src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.cxx
index 4d47c3015..b14ac6a17 100644
--- a/src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.cxx
+++ b/src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.cxx
@@ -304,6 +304,47 @@ 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
+ 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.
+ */
+
+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 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_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;
+}
+
+
class Fl_Gl_Cocoa_Plugin : public Fl_Cocoa_Plugin {
public:
Fl_Gl_Cocoa_Plugin() : Fl_Cocoa_Plugin(name()) { }
diff --git a/src/glut_compatibility.cxx b/src/glut_compatibility.cxx
index 0a5a6b30e..011f9290b 100644
--- a/src/glut_compatibility.cxx
+++ b/src/glut_compatibility.cxx
@@ -30,6 +30,9 @@
# include "Fl_Screen_Driver.H"
# include <FL/glut.H>
# define MAXWINDOWS 32
+# ifndef GL_CURRENT_PROGRAM
+# define GL_CURRENT_PROGRAM 0x8B8D // from glew.h
+# endif
static Fl_Glut_Window *windows[MAXWINDOWS+1];
@@ -54,6 +57,27 @@ void Fl_Glut_Window::draw() {
indraw = 1;
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, &current_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
+ }
indraw = 0;
}