diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Fl_Gl_Choice.cxx | 22 | ||||
| -rw-r--r-- | src/Fl_Gl_Window.cxx | 3 | ||||
| -rw-r--r-- | src/Fl_Gl_Window_Driver.H | 9 | ||||
| -rw-r--r-- | src/Fl_cocoa.mm | 22 | ||||
| -rw-r--r-- | src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.H | 11 | ||||
| -rw-r--r-- | src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.cxx | 66 | ||||
| -rw-r--r-- | src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H | 2 | ||||
| -rw-r--r-- | src/glut_compatibility.cxx | 23 |
8 files changed, 100 insertions, 58 deletions
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 <FL/gl_draw.H> #include <stdlib.h> - +#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 <FL/Fl_Gl_Window.H> +#include <FL/gl.h> // 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 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()); - } +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); } -}; - + 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 <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]; @@ -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; } |
