diff options
| author | ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> | 2021-02-16 09:29:13 +0100 |
|---|---|---|
| committer | ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> | 2021-02-16 09:29:13 +0100 |
| commit | 1adaa3def2138fafd40b9d9df212a068c57cdbf4 (patch) | |
| tree | 0898ea907c763d197d5137dc299eef8005c16de1 /src/drivers/Cocoa | |
| parent | 1f55bfe65cc8ca6e7b79efad66a7c304a69b12fe (diff) | |
Create classes Fl_XXX_Gl_Window_Driver according to driver model.
Diffstat (limited to 'src/drivers/Cocoa')
| -rw-r--r-- | src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.cxx | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.cxx b/src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.cxx new file mode 100644 index 000000000..188f4febf --- /dev/null +++ b/src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.cxx @@ -0,0 +1,248 @@ +// +// Class Fl_Cocoa_Gl_Window_Driver for the Fast Light Tool Kit (FLTK). +// +// Copyright 2021 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: +// +// https://www.fltk.org/COPYING.php +// +// Please see the following page on how to report bugs and issues: +// +// https://www.fltk.org/bugs.php +// + +#include <config.h> +#if HAVE_GL +#include <FL/platform.H> +#include <FL/gl.h> +#include "../../Fl_Gl_Choice.H" +#include "../../Fl_Screen_Driver.H" +#include "Fl_Cocoa_Window_Driver.H" +#include "../../Fl_Gl_Window_Driver.H" +#include <FL/Fl_Graphics_Driver.H> +#include <OpenGL/OpenGL.h> +#include <FL/Fl_Image_Surface.H> + +extern void gl_texture_reset(); + +#ifdef __OBJC__ +@class NSOpenGLPixelFormat; +#else +class NSOpenGLPixelFormat; +#endif // __OBJC__ + +class Fl_Cocoa_Gl_Window_Driver : public Fl_Gl_Window_Driver { + friend class Fl_Gl_Window_Driver; + friend class Fl_OpenGL_Display_Device; + Fl_Cocoa_Gl_Window_Driver(Fl_Gl_Window *win) : Fl_Gl_Window_Driver(win) {} + virtual float pixels_per_unit(); + virtual void before_show(int& need_after); + virtual void after_show(); + 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 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(); + virtual char *alpha_mask_for_string(const char *str, int n, int w, int h); +}; + +// Describes crap needed to create a GLContext. +class Fl_Cocoa_Gl_Choice : public Fl_Gl_Choice { + friend class Fl_Cocoa_Gl_Window_Driver; +private: + NSOpenGLPixelFormat* pixelformat; +public: + Fl_Cocoa_Gl_Choice(int m, const int *alistp, Fl_Gl_Choice *n) : Fl_Gl_Choice(m, alistp, n) { + pixelformat = NULL; + } +}; + + +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() + Fl_Cocoa_Gl_Choice *g = (Fl_Cocoa_Gl_Choice*)Fl_Gl_Window_Driver::find_begin(m, alistp); + if (g) return g; + NSOpenGLPixelFormat* fmt = Fl_Cocoa_Window_Driver::mode_to_NSOpenGLPixelFormat(m, alistp); + if (!fmt) return 0; + g = new Fl_Cocoa_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_Window_Driver::create_GLcontext_for_window(((Fl_Cocoa_Gl_Choice*)g)->pixelformat, shared_ctx, window); + if (!context) return 0; + add_context(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_Window_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_Window_Driver::GL_cleardrawable(); + } + Fl_Cocoa_Window_Driver::GLcontext_release(context); + del_context(context); +} + +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(); +} + + +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_after) { + need_after = 1; +} + +void Fl_Cocoa_Gl_Window_Driver::after_show() { + // Makes sure the GL context is created to avoid drawing twice the window when first shown + pWindow->make_current(); +} + +float Fl_Cocoa_Gl_Window_Driver::pixels_per_unit() +{ + int retina = (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; + return retina * Fl_Graphics_Driver::default_driver().scale(); +} + +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); + pWindow->invalidate(); + Fl_Cocoa_Window_Driver::GLcontext_update(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 + } + else + Fl_Cocoa_Window_Driver::flush_context(pWindow->context());//aglSwapBuffers((AGLContext)context_); +} + +char Fl_Cocoa_Gl_Window_Driver::swap_type() {return copy;} + +void Fl_Cocoa_Gl_Window_Driver::resize(int is_a_resize, int w, int h) { + Fl_Cocoa_Window_Driver::GLcontext_update(pWindow->context()); +} + +/* Some old Apple hardware doesn't implement the GL_EXT_texture_rectangle extension. + For it, draw_string_legacy_glut() is used to draw text. */ + +char *Fl_Cocoa_Gl_Window_Driver::alpha_mask_for_string(const char *str, int n, int w, int h) +{ + // write str to a bitmap just big enough + Fl_Image_Surface *surf = new Fl_Image_Surface(w, h); + Fl_Font f=fl_font(); Fl_Fontsize s=fl_size(); + Fl_Surface_Device::push_current(surf); + fl_color(FL_WHITE); + fl_font(f, s * gl_scale); + fl_draw(str, n, 0, fl_height() - fl_descent()); + // get the alpha channel only of the bitmap + char *alpha_buf = new char[w*h], *r = alpha_buf, *q; + q = (char*)CGBitmapContextGetData(surf->offscreen()); + for (int i = 0; i < h; i++) { + for (int j = 0; j < w; j++) { + *r++ = *(q+3); + q += 4; + } + } + Fl_Surface_Device::pop_current(); + delete surf; + return alpha_buf; +} + +void Fl_Cocoa_Gl_Window_Driver::gl_start() { + Fl_Cocoa_Window_Driver::gl_start(gl_start_context); +} + +#endif // HAVE_GL |
