|
commit c96a4f3141259d412b249144086492ec4c400355
Author: ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>
AuthorDate: Thu Sep 29 16:25:14 2022 +0200
Commit: ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>
CommitDate: Thu Sep 29 16:25:14 2022 +0200
macOS platform: rename Fl_Cocoa_Gl_Window_Driver.cxx to .mm
src/CMakeLists.txt | 2 +-
src/Fl_cocoa.mm | 181 ---------
src/Makefile | 4 +-
src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.H | 1 -
src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.cxx | 380 -----------------
src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.mm | 518 ++++++++++++++++++++++++
src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H | 15 -
7 files changed, 521 insertions(+), 580 deletions(-)
diff --git src/CMakeLists.txt src/CMakeLists.txt
index 91d4f5f..ab5188e 100644
--- src/CMakeLists.txt
+++ src/CMakeLists.txt
@@ -440,7 +440,7 @@ elseif (FLTK_USE_X11)
set (GL_DRIVER_FILES ${GL_DRIVER_FILES} drivers/X11/Fl_X11_Gl_Window_Driver.cxx drivers/X11/fl_X11_gl_platform_init.cxx)
set (GL_DRIVER_HEADER_FILES drivers/X11/Fl_X11_Gl_Window_Driver.H)
elseif (APPLE)
- set (GL_DRIVER_FILES ${GL_DRIVER_FILES} drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.cxx drivers/Cocoa/fl_macOS_gl_platform_init.cxx)
+ set (GL_DRIVER_FILES ${GL_DRIVER_FILES} drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.mm drivers/Cocoa/fl_macOS_gl_platform_init.cxx)
set (GL_DRIVER_HEADER_FILES drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.H)
elseif (WIN32)
set (GL_DRIVER_FILES ${GL_DRIVER_FILES} drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.cxx drivers/WinAPI/fl_WinAPI_gl_platform_init.cxx)
diff --git src/Fl_cocoa.mm src/Fl_cocoa.mm
index ccb4ebe..694e54a 100644
--- src/Fl_cocoa.mm
+++ src/Fl_cocoa.mm
@@ -2831,184 +2831,6 @@ static FLTextInputContext* fltextinputcontext_instance = nil;
@end
-NSOpenGLPixelFormat* Fl_Cocoa_Window_Driver::mode_to_NSOpenGLPixelFormat(int m, const int *alistp)
-{
- NSOpenGLPixelFormatAttribute attribs[32];
- int n = 0;
- // AGL-style code remains commented out for comparison
- if (!alistp) {
- if (m & FL_INDEX) {
- //list[n++] = AGL_BUFFER_SIZE; list[n++] = 8;
- } else {
- //list[n++] = AGL_RGBA;
- //list[n++] = AGL_GREEN_SIZE;
- //list[n++] = (m & FL_RGB8) ? 8 : 1;
- attribs[n++] = NSOpenGLPFAColorSize;
- attribs[n++] = (NSOpenGLPixelFormatAttribute)((m & FL_RGB8) ? 32 : 1);
- if (m & FL_ALPHA) {
- //list[n++] = AGL_ALPHA_SIZE;
- attribs[n++] = NSOpenGLPFAAlphaSize;
- attribs[n++] = (NSOpenGLPixelFormatAttribute)((m & FL_RGB8) ? 8 : 1);
- }
- if (m & FL_ACCUM) {
- //list[n++] = AGL_ACCUM_GREEN_SIZE; list[n++] = 1;
- attribs[n++] = NSOpenGLPFAAccumSize;
- attribs[n++] = (NSOpenGLPixelFormatAttribute)1;
- if (m & FL_ALPHA) {
- //list[n++] = AGL_ACCUM_ALPHA_SIZE; list[n++] = 1;
- }
- }
- }
- if (m & FL_DOUBLE) {
- //list[n++] = AGL_DOUBLEBUFFER;
- attribs[n++] = NSOpenGLPFADoubleBuffer;
- }
- if (m & FL_DEPTH) {
- //list[n++] = AGL_DEPTH_SIZE; list[n++] = 24;
- attribs[n++] = NSOpenGLPFADepthSize;
- attribs[n++] = (NSOpenGLPixelFormatAttribute)24;
- }
- if (m & FL_STENCIL) {
- //list[n++] = AGL_STENCIL_SIZE; list[n++] = 1;
- attribs[n++] = NSOpenGLPFAStencilSize;
- attribs[n++] = (NSOpenGLPixelFormatAttribute)1;
- }
- if (m & FL_STEREO) {
- //list[n++] = AGL_STEREO;
- attribs[n++] = NSOpenGLPFAStereo;
- }
- if ((m & FL_MULTISAMPLE) && fl_mac_os_version >= 100400) {
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
- attribs[n++] = NSOpenGLPFAMultisample, // 10.4
-#endif
- attribs[n++] = NSOpenGLPFASampleBuffers; attribs[n++] = (NSOpenGLPixelFormatAttribute)1;
- attribs[n++] = NSOpenGLPFASamples; attribs[n++] = (NSOpenGLPixelFormatAttribute)4;
- }
-#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
-#define NSOpenGLPFAOpenGLProfile (NSOpenGLPixelFormatAttribute)99
-#define kCGLPFAOpenGLProfile NSOpenGLPFAOpenGLProfile
-#define NSOpenGLProfileVersionLegacy (NSOpenGLPixelFormatAttribute)0x1000
-#define NSOpenGLProfileVersion3_2Core (NSOpenGLPixelFormatAttribute)0x3200
-#define kCGLOGLPVersion_Legacy NSOpenGLProfileVersionLegacy
-#endif
- if (fl_mac_os_version >= 100700) {
- attribs[n++] = NSOpenGLPFAOpenGLProfile;
- attribs[n++] = (m & FL_OPENGL3) ? NSOpenGLProfileVersion3_2Core : NSOpenGLProfileVersionLegacy;
- }
- } else {
- while (alistp[n] && n < 30) {
- if (alistp[n] == kCGLPFAOpenGLProfile) {
- if (fl_mac_os_version < 100700) {
- if (alistp[n+1] != kCGLOGLPVersion_Legacy) return nil;
- n += 2;
- continue;
- }
- }
- attribs[n] = (NSOpenGLPixelFormatAttribute)alistp[n];
- n++;
- }
- }
- attribs[n] = (NSOpenGLPixelFormatAttribute)0;
- NSOpenGLPixelFormat *pixform = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
- /*GLint color,alpha,accum,depth;
- [pixform getValues:&color forAttribute:NSOpenGLPFAColorSize forVirtualScreen:0];
- [pixform getValues:&alpha forAttribute:NSOpenGLPFAAlphaSize forVirtualScreen:0];
- [pixform getValues:&accum forAttribute:NSOpenGLPFAAccumSize forVirtualScreen:0];
- [pixform getValues:&depth forAttribute:NSOpenGLPFADepthSize forVirtualScreen:0];
- NSLog(@"color=%d alpha=%d accum=%d depth=%d",color,alpha,accum,depth);*/
- return pixform;
-}
-
-NSOpenGLContext* Fl_Cocoa_Window_Driver::create_GLcontext_for_window(NSOpenGLPixelFormat *pixelformat,
- NSOpenGLContext *shared_ctx, Fl_Window *window)
-{
- NSOpenGLContext *context = [[NSOpenGLContext alloc] initWithFormat:pixelformat shareContext:shared_ctx];
- if (shared_ctx && !context) context = [[NSOpenGLContext alloc] initWithFormat:pixelformat shareContext:nil];
- if (context) {
- FLView *view = (FLView*)[fl_xid(window) contentView];
- if (fl_mac_os_version >= 100700) {
- //replaces [view setWantsBestResolutionOpenGLSurface:YES] without compiler warning
- typedef void (*bestResolutionIMP)(id, SEL, BOOL);
- static bestResolutionIMP addr = (bestResolutionIMP)[NSView instanceMethodForSelector:@selector(setWantsBestResolutionOpenGLSurface:)];
- addr(view, @selector(setWantsBestResolutionOpenGLSurface:), Fl::use_high_res_GL() != 0);
- }
- [context setView:view];
- if (Fl_Cocoa_Window_Driver::driver(window)->subRect()) {
- remove_gl_context_opacity(context);
- }
- }
- return context;
-}
-
-
-NSOpenGLContext *Fl_Cocoa_Window_Driver::gl1ctxt_create(NSView **gl1view) {
- FLView *view = (FLView*)[fl_xid(pWindow) contentView];
- *gl1view = [[NSView alloc] initWithFrame:[view frame]];
- 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];
- return gl1ctxt;
-}
-
-void Fl_Cocoa_Window_Driver::gl1ctxt_add(NSOpenGLContext *gl1ctxt, NSView *gl1view) {
- FLView *flview = (FLView*)[fl_xid(pWindow) contentView];
- [flview addSubview:gl1view];
- [gl1view release];
-#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_7
- if (fl_mac_os_version >= 100700 && Fl::use_high_res_GL()) {
- [gl1view setWantsBestResolutionOpenGLSurface:YES];
- }
-#endif
- [gl1ctxt setView:gl1view];
- remove_gl_context_opacity(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
-
-void Fl_Cocoa_Window_Driver::remove_gl_context_opacity(NSOpenGLContext *ctx) {
- GLint gl_opacity;
- [ctx getValues:&gl_opacity forParameter:NSOpenGLContextParameterSurfaceOpacity];
- if (gl_opacity != 0) {
- gl_opacity = 0;
- [ctx setValues:&gl_opacity forParameter:NSOpenGLContextParameterSurfaceOpacity];
- }
-}
-
-void Fl_Cocoa_Window_Driver::GLcontext_update(NSOpenGLContext* ctxt)
-{
- [ctxt update];
-}
-
-void Fl_Cocoa_Window_Driver::flush_context(NSOpenGLContext* ctxt)
-{
- [ctxt flushBuffer];
-}
-
-void Fl_Cocoa_Window_Driver::GLcontext_release(NSOpenGLContext* ctxt)
-{
- [ctxt release];
-}
-
-void Fl_Cocoa_Window_Driver::GL_cleardrawable(void)
-{
- [[NSOpenGLContext currentContext] clearDrawable];
-}
-
-void Fl_Cocoa_Window_Driver::GLcontext_makecurrent(NSOpenGLContext* ctxt)
-{
- [ctxt makeCurrentContext];
-}
-
/*
* Initialize the given port for redraw and call the window's flush() to actually draw the content
*/
@@ -4561,9 +4383,6 @@ void Fl_Cocoa_Window_Driver::draw_titlebar_to_context(CGContextRef gc, int w, in
}
}
-void Fl_Cocoa_Window_Driver::gl_start(NSOpenGLContext *ctxt) {
- [ctxt update]; // supports window resizing
-}
/* Returns the version of the running Mac OS as an int such as 100802 for 10.8.2,
and also assigns that value to global fl_mac_os_version.
diff --git src/Makefile src/Makefile
index 0510cbb..1271f7c 100644
--- src/Makefile
+++ src/Makefile
@@ -202,7 +202,7 @@ GLCPPFILES = \
drivers/OpenGL/Fl_OpenGL_Graphics_Driver_rect.cxx \
drivers/OpenGL/Fl_OpenGL_Graphics_Driver_vertex.cxx
-GLCPPFILES_OSX = drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.cxx \
+GLCPPFILES_OSX = drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.mm \
drivers/Cocoa/fl_macOS_gl_platform_init.cxx
GLCPPFILES_X11 = drivers/X11/Fl_X11_Gl_Window_Driver.cxx \
drivers/X11/fl_X11_gl_platform_init.cxx
@@ -427,7 +427,7 @@ CXXFLAGS += $(EXTRA_CXXFLAGS_$(BUILD))
OBJECTS = $(MMFILES:.mm=.o) $(CPPFILES:.cxx=.o) $(CFILES:.c=.o) $(UTF8CFILES:.c=.o)
OBJECTS += $(EXTRA_OBJECTS_$(BUILD))
-GLOBJECTS = $(GLCPPFILES:.cxx=.o)
+GLOBJECTS = $(GLCPPFILES:.cxx=.o) $(GLCPPFILES:.mm=.o)
FLOBJECTS = $(FLCPPFILES:.cxx=.o)
IMGOBJECTS = $(IMGCPPFILES:.cxx=.o)
diff --git src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.H src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.H
index f0456ee..01ab231 100644
--- src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.H
+++ src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.H
@@ -28,7 +28,6 @@ class Fl_Gl_Choice;
class Fl_Cocoa_Gl_Window_Driver : public Fl_Gl_Window_Driver {
NSOpenGLContext *gl1ctxt; // GL1 context in addition to GL3 context
- static void delayed_addgl1ctxt(void *data);
friend Fl_Gl_Window_Driver* Fl_Gl_Window_Driver::newGlWindowDriver(Fl_Gl_Window *);
Fl_Cocoa_Gl_Window_Driver(Fl_Gl_Window *win);
virtual float pixels_per_unit();
diff --git src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.cxx src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.cxx
deleted file mode 100644
index 3ee281b..0000000
--- src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.cxx
+++ /dev/null
@@ -1,380 +0,0 @@
-//
-// Class Fl_Cocoa_Gl_Window_Driver for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2021-2022 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_Cocoa_Gl_Window_Driver.H"
-#include <FL/Fl_Graphics_Driver.H>
-#include <OpenGL/OpenGL.h>
-#include <FL/Fl_Image_Surface.H>
-#include <dlfcn.h>
-
-
-#ifdef __OBJC__
-@class NSOpenGLPixelFormat;
-#else
-class NSOpenGLPixelFormat;
-#endif // __OBJC__
-
-
-// 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_Cocoa_Gl_Window_Driver::Fl_Cocoa_Gl_Window_Driver(Fl_Gl_Window *win) :
- Fl_Gl_Window_Driver(win) {
- gl1ctxt = 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, (NSOpenGLContext*)shared_ctx, window);
- if (!context) return 0;
- add_context(context);
- Fl_Cocoa_Window_Driver::GLcontext_makecurrent((NSOpenGLContext*)context);
- glClearColor(0., 0., 0., 1.);
- apply_scissor();
- 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((NSOpenGLContext*)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((NSOpenGLContext*)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();
-}
-
-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((NSOpenGLContext*)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((NSOpenGLContext*)pWindow->context());//aglSwapBuffers((AGLContext)context_);
-}
-
-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() {
- CGRect *extents = Fl_Cocoa_Window_Driver::driver(pWindow)->subRect();
- if (extents) {
- Fl_Cocoa_Window_Driver::remove_gl_context_opacity((NSOpenGLContext*)pWindow->context());
- glDisable(GL_SCISSOR_TEST);
- GLdouble vals[4];
- glGetDoublev(GL_COLOR_CLEAR_VALUE, vals);
- glClearColor(0., 0., 0., 0.);
- glClear(GL_COLOR_BUFFER_BIT);
- glClearColor(vals[0], vals[1], vals[2], vals[3]);
- float s = pWindow->pixels_per_unit();
- glScissor(s*extents->origin.x, s*extents->origin.y, s*extents->size.width, s*extents->size.height);
-//printf("apply_scissor %dx%d %dx%d\n",extents->x, extents->y, extents->width, extents->height);
- glEnable(GL_SCISSOR_TEST);
- }
-}
-
-
-/* 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, Fl_Fontsize fs)
-{
- // write str to a bitmap just big enough
- Fl_Image_Surface *surf = new Fl_Image_Surface(w, h);
- Fl_Font f=fl_font();
- Fl_Surface_Device::push_current(surf);
- fl_color(FL_WHITE);
- fl_font(f, fs);
- 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((CGContextRef)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((NSOpenGLContext*)gl_start_context);
-}
-
-// convert BGRA to RGB and also exchange top and bottom
-static uchar *convert_BGRA_to_RGB(uchar *baseAddress, int w, int h, int mByteWidth)
-{
- uchar *newimg = new uchar[3*w*h];
- uchar *to = newimg;
- for (int i = h-1; i >= 0; i--) {
- uchar *from = baseAddress + i * mByteWidth;
- for (int j = 0; j < w; j++, from += 4) {
-#if defined(__ppc__) && __ppc__
- memcpy(to, from + 1, 3);
- to += 3;
-#else
- *(to++) = *(from+2);
- *(to++) = *(from+1);
- *(to++) = *from;
-#endif
- }
- }
- delete[] baseAddress;
- return newimg;
-}
-
-Fl_RGB_Image* Fl_Cocoa_Gl_Window_Driver::capture_gl_rectangle(int x, int y, int w, int h)
-{
- Fl_Gl_Window* glw = pWindow;
- float factor = glw->pixels_per_unit();
- if (factor != 1) {
- w *= factor; h *= factor; x *= factor; y *= factor;
- }
- Fl_Cocoa_Window_Driver::GLcontext_makecurrent((NSOpenGLContext*)glw->context());
- Fl_Cocoa_Window_Driver::flush_context((NSOpenGLContext*)glw->context()); // to capture also the overlay and for directGL demo
- // Read OpenGL context pixels directly.
- // For extra safety, save & restore OpenGL states that are changed
- glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
- glPixelStorei(GL_PACK_ALIGNMENT, 4); /* Force 4-byte alignment */
- glPixelStorei(GL_PACK_ROW_LENGTH, 0);
- glPixelStorei(GL_PACK_SKIP_ROWS, 0);
- glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
- // Read a block of pixels from the frame buffer
- int mByteWidth = w * 4;
- mByteWidth = (mByteWidth + 3) & ~3; // Align to 4 bytes
- uchar *baseAddress = new uchar[mByteWidth * h];
- glReadPixels(x, glw->pixel_h() - (y+h), w, h,
- GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, baseAddress);
- glPopClientAttrib();
- baseAddress = convert_BGRA_to_RGB(baseAddress, w, h, mByteWidth);
- Fl_RGB_Image *img = new Fl_RGB_Image(baseAddress, w, h, 3, 3 * w);
- img->alloc_array = 1;
- Fl_Cocoa_Window_Driver::flush_context((NSOpenGLContext*)glw->context());
- return img;
-}
-
-
-void* Fl_Cocoa_Gl_Window_Driver::GetProcAddress(const char *procName) {
- return dlsym(RTLD_DEFAULT, procName);
-}
-
-
-FL_EXPORT NSOpenGLContext *fl_mac_glcontext(GLContext rc) {
- return (NSOpenGLContext*)rc;
-}
-
-
-/* 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 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.
- */
-
-static struct win_view {
- Fl_Gl_Window *win;
- NSView *gl1view;
- NSOpenGLContext *gl1ctxt;
-} win_view_struct;
-
-void Fl_Cocoa_Gl_Window_Driver::delayed_addgl1ctxt(void *d) {
- struct win_view *data = (struct win_view *)d;
- Fl_Cocoa_Window_Driver::driver(data->win)->gl1ctxt_add(data->gl1ctxt, data->gl1view);
- data->win->redraw();
-}
-
-void Fl_Cocoa_Gl_Window_Driver::switch_to_GL1() {
- if (!gl1ctxt) {
- gl1ctxt = Fl_Cocoa_Window_Driver::driver(pWindow)->gl1ctxt_create(
- &win_view_struct.gl1view);
- win_view_struct.win = pWindow;
- win_view_struct.gl1ctxt = gl1ctxt;
- Fl::add_timeout(0.01,
- Fl_Cocoa_Gl_Window_Driver::delayed_addgl1ctxt,
- &win_view_struct);
- }
- Fl_Cocoa_Window_Driver::GLcontext_makecurrent(gl1ctxt);
- glClearColor(0., 0., 0., 0.);
- glClear(GL_COLOR_BUFFER_BIT);
-}
-
-void Fl_Cocoa_Gl_Window_Driver::switch_back() {
- glFlush();
- Fl_Cocoa_Window_Driver::GLcontext_makecurrent((NSOpenGLContext*)pWindow->context());
-}
-
-void Fl_Cocoa_Gl_Window_Driver::gl_hide_before(void *&) {
- if (gl1ctxt) {
- Fl_Cocoa_Window_Driver::GLcontext_release(gl1ctxt);
- gl1ctxt = 0;
- }
-}
-
-
-class Fl_Gl_Cocoa_Plugin : public Fl_Cocoa_Plugin {
-public:
- Fl_Gl_Cocoa_Plugin() : Fl_Cocoa_Plugin(name()) { }
- virtual const char *name() { return "gl.cocoa.fltk.org"; }
- virtual void resize(Fl_Gl_Window *glw, int x, int y, int w, int h) {
- glw->Fl_Gl_Window::resize(x, y, w, h);
- }
-};
-
-static Fl_Gl_Cocoa_Plugin Gl_Cocoa_Plugin;
-
-#endif // HAVE_GL
diff --git src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.mm src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.mm
new file mode 100644
index 0000000..741ab33
--- /dev/null
+++ src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.mm
@@ -0,0 +1,518 @@
+//
+// Class Fl_Cocoa_Gl_Window_Driver for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 2021-2022 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_Cocoa_Gl_Window_Driver.H"
+#include <FL/Fl_Graphics_Driver.H>
+#include <OpenGL/OpenGL.h>
+#include <FL/Fl_Image_Surface.H>
+#include <dlfcn.h>
+
+#import <Cocoa/Cocoa.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_Cocoa_Gl_Window_Driver::Fl_Cocoa_Gl_Window_Driver(Fl_Gl_Window *win) :
+ Fl_Gl_Window_Driver(win) {
+ gl1ctxt = NULL;
+}
+
+
+static NSOpenGLPixelFormat* mode_to_NSOpenGLPixelFormat(int m, const int *alistp)
+{
+ NSOpenGLPixelFormatAttribute attribs[32];
+ int n = 0;
+ // AGL-style code remains commented out for comparison
+ if (!alistp) {
+ if (m & FL_INDEX) {
+ //list[n++] = AGL_BUFFER_SIZE; list[n++] = 8;
+ } else {
+ //list[n++] = AGL_RGBA;
+ //list[n++] = AGL_GREEN_SIZE;
+ //list[n++] = (m & FL_RGB8) ? 8 : 1;
+ attribs[n++] = NSOpenGLPFAColorSize;
+ attribs[n++] = (NSOpenGLPixelFormatAttribute)((m & FL_RGB8) ? 32 : 1);
+ if (m & FL_ALPHA) {
+ //list[n++] = AGL_ALPHA_SIZE;
+ attribs[n++] = NSOpenGLPFAAlphaSize;
+ attribs[n++] = (NSOpenGLPixelFormatAttribute)((m & FL_RGB8) ? 8 : 1);
+ }
+ if (m & FL_ACCUM) {
+ //list[n++] = AGL_ACCUM_GREEN_SIZE; list[n++] = 1;
+ attribs[n++] = NSOpenGLPFAAccumSize;
+ attribs[n++] = (NSOpenGLPixelFormatAttribute)1;
+ if (m & FL_ALPHA) {
+ //list[n++] = AGL_ACCUM_ALPHA_SIZE; list[n++] = 1;
+ }
+ }
+ }
+ if (m & FL_DOUBLE) {
+ //list[n++] = AGL_DOUBLEBUFFER;
+ attribs[n++] = NSOpenGLPFADoubleBuffer;
+ }
+ if (m & FL_DEPTH) {
+ //list[n++] = AGL_DEPTH_SIZE; list[n++] = 24;
+ attribs[n++] = NSOpenGLPFADepthSize;
+ attribs[n++] = (NSOpenGLPixelFormatAttribute)24;
+ }
+ if (m & FL_STENCIL) {
+ //list[n++] = AGL_STENCIL_SIZE; list[n++] = 1;
+ attribs[n++] = NSOpenGLPFAStencilSize;
+ attribs[n++] = (NSOpenGLPixelFormatAttribute)1;
+ }
+ if (m & FL_STEREO) {
+ //list[n++] = AGL_STEREO;
+ attribs[n++] = NSOpenGLPFAStereo;
+ }
+ if ((m & FL_MULTISAMPLE) && fl_mac_os_version >= 100400) {
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+ attribs[n++] = NSOpenGLPFAMultisample, // 10.4
+#endif
+ attribs[n++] = NSOpenGLPFASampleBuffers; attribs[n++] = (NSOpenGLPixelFormatAttribute)1;
+ attribs[n++] = NSOpenGLPFASamples; attribs[n++] = (NSOpenGLPixelFormatAttribute)4;
+ }
+#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
+#define NSOpenGLPFAOpenGLProfile (NSOpenGLPixelFormatAttribute)99
+#define kCGLPFAOpenGLProfile NSOpenGLPFAOpenGLProfile
+#define NSOpenGLProfileVersionLegacy (NSOpenGLPixelFormatAttribute)0x1000
+#define NSOpenGLProfileVersion3_2Core (NSOpenGLPixelFormatAttribute)0x3200
+#define kCGLOGLPVersion_Legacy NSOpenGLProfileVersionLegacy
+#endif
+ if (fl_mac_os_version >= 100700) {
+ attribs[n++] = NSOpenGLPFAOpenGLProfile;
+ attribs[n++] = (m & FL_OPENGL3) ? NSOpenGLProfileVersion3_2Core : NSOpenGLProfileVersionLegacy;
+ }
+ } else {
+ while (alistp[n] && n < 30) {
+ if (alistp[n] == kCGLPFAOpenGLProfile) {
+ if (fl_mac_os_version < 100700) {
+ if (alistp[n+1] != kCGLOGLPVersion_Legacy) return nil;
+ n += 2;
+ continue;
+ }
+ }
+ attribs[n] = (NSOpenGLPixelFormatAttribute)alistp[n];
+ n++;
+ }
+ }
+ attribs[n] = (NSOpenGLPixelFormatAttribute)0;
+ NSOpenGLPixelFormat *pixform = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
+ /*GLint color,alpha,accum,depth;
+ [pixform getValues:&color forAttribute:NSOpenGLPFAColorSize forVirtualScreen:0];
+ [pixform getValues:&alpha forAttribute:NSOpenGLPFAAlphaSize forVirtualScreen:0];
+ [pixform getValues:&accum forAttribute:NSOpenGLPFAAccumSize forVirtualScreen:0];
+ [pixform getValues:&depth forAttribute:NSOpenGLPFADepthSize forVirtualScreen:0];
+ NSLog(@"color=%d alpha=%d accum=%d depth=%d",color,alpha,accum,depth);*/
+ return pixform;
+}
+
+
+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 = 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;
+}
+
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_VERSION_12_0
+# define NSOpenGLContextParameterSurfaceOpacity NSOpenGLCPSurfaceOpacity
+#endif
+
+static void remove_gl_context_opacity(NSOpenGLContext *ctx) {
+ GLint gl_opacity;
+ [ctx getValues:&gl_opacity forParameter:NSOpenGLContextParameterSurfaceOpacity];
+ if (gl_opacity != 0) {
+ gl_opacity = 0;
+ [ctx setValues:&gl_opacity forParameter:NSOpenGLContextParameterSurfaceOpacity];
+ }
+}
+
+
+static NSOpenGLContext *create_GLcontext_for_window(
+ NSOpenGLPixelFormat *pixelformat,
+ NSOpenGLContext *shared_ctx, Fl_Window *window)
+{
+ NSOpenGLContext *context = [[NSOpenGLContext alloc] initWithFormat:pixelformat shareContext:shared_ctx];
+ if (shared_ctx && !context) context = [[NSOpenGLContext alloc] initWithFormat:pixelformat shareContext:nil];
+ if (context) {
+ NSView *view = [fl_xid(window) contentView];
+ if (fl_mac_os_version >= 100700) {
+ //replaces [view setWantsBestResolutionOpenGLSurface:YES] without compiler warning
+ typedef void (*bestResolutionIMP)(id, SEL, BOOL);
+ static bestResolutionIMP addr = (bestResolutionIMP)[NSView instanceMethodForSelector:@selector(setWantsBestResolutionOpenGLSurface:)];
+ addr(view, @selector(setWantsBestResolutionOpenGLSurface:), Fl::use_high_res_GL() != 0);
+ }
+ [context setView:view];
+ if (Fl_Cocoa_Window_Driver::driver(window)->subRect()) {
+ remove_gl_context_opacity(context);
+ }
+ }
+ return context;
+}
+
+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 = create_GLcontext_for_window(((Fl_Cocoa_Gl_Choice*)g)->pixelformat, (NSOpenGLContext*)shared_ctx, window);
+ if (!context) return 0;
+ add_context(context);
+ [(NSOpenGLContext*)context makeCurrentContext];
+ glClearColor(0., 0., 0., 1.);
+ apply_scissor();
+ 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;
+ [(NSOpenGLContext*)context makeCurrentContext];
+ }
+}
+
+void Fl_Cocoa_Gl_Window_Driver::delete_gl_context(GLContext context) {
+ if (cached_context == context) {
+ cached_context = 0;
+ cached_window = 0;
+ [[NSOpenGLContext currentContext] clearDrawable];
+ }
+ [(NSOpenGLContext*)context release];
+ 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();
+}
+
+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();
+ [(NSOpenGLContext*)pWindow->context() update];
+ }
+}
+
+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 {
+ [(NSOpenGLContext*)pWindow->context() flushBuffer];
+ }
+}
+
+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();
+ [(NSOpenGLContext*)pWindow->context() update];
+ if (gl1ctxt) {
+ [[gl1ctxt view] setFrame:[[[gl1ctxt view] superview] frame]];
+ [gl1ctxt update];
+ Fl::add_timeout(0.01, (Fl_Timeout_Handler)delayed_redraw, pWindow);
+ }
+}
+
+void Fl_Cocoa_Gl_Window_Driver::apply_scissor() {
+ CGRect *extents = Fl_Cocoa_Window_Driver::driver(pWindow)->subRect();
+ if (extents) {
+ remove_gl_context_opacity((NSOpenGLContext*)pWindow->context());
+ glDisable(GL_SCISSOR_TEST);
+ GLdouble vals[4];
+ glGetDoublev(GL_COLOR_CLEAR_VALUE, vals);
+ glClearColor(0., 0., 0., 0.);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glClearColor(vals[0], vals[1], vals[2], vals[3]);
+ float s = pWindow->pixels_per_unit();
+ glScissor(s*extents->origin.x, s*extents->origin.y, s*extents->size.width, s*extents->size.height);
+//printf("apply_scissor %dx%d %dx%d\n",extents->x, extents->y, extents->width, extents->height);
+ glEnable(GL_SCISSOR_TEST);
+ }
+}
+
+
+/* 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, Fl_Fontsize fs)
+{
+ // write str to a bitmap just big enough
+ Fl_Image_Surface *surf = new Fl_Image_Surface(w, h);
+ Fl_Font f=fl_font();
+ Fl_Surface_Device::push_current(surf);
+ fl_color(FL_WHITE);
+ fl_font(f, fs);
+ 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((CGContextRef)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() {
+ [(NSOpenGLContext*)gl_start_context update];
+}
+
+// convert BGRA to RGB and also exchange top and bottom
+static uchar *convert_BGRA_to_RGB(uchar *baseAddress, int w, int h, int mByteWidth)
+{
+ uchar *newimg = new uchar[3*w*h];
+ uchar *to = newimg;
+ for (int i = h-1; i >= 0; i--) {
+ uchar *from = baseAddress + i * mByteWidth;
+ for (int j = 0; j < w; j++, from += 4) {
+#if defined(__ppc__) && __ppc__
+ memcpy(to, from + 1, 3);
+ to += 3;
+#else
+ *(to++) = *(from+2);
+ *(to++) = *(from+1);
+ *(to++) = *from;
+#endif
+ }
+ }
+ delete[] baseAddress;
+ return newimg;
+}
+
+Fl_RGB_Image* Fl_Cocoa_Gl_Window_Driver::capture_gl_rectangle(int x, int y, int w, int h)
+{
+ Fl_Gl_Window* glw = pWindow;
+ float factor = glw->pixels_per_unit();
+ if (factor != 1) {
+ w *= factor; h *= factor; x *= factor; y *= factor;
+ }
+ [(NSOpenGLContext*)glw->context() makeCurrentContext];
+// to capture also the overlay and for directGL demo
+ [(NSOpenGLContext*)glw->context() flushBuffer];
+ // Read OpenGL context pixels directly.
+ // For extra safety, save & restore OpenGL states that are changed
+ glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
+ glPixelStorei(GL_PACK_ALIGNMENT, 4); /* Force 4-byte alignment */
+ glPixelStorei(GL_PACK_ROW_LENGTH, 0);
+ glPixelStorei(GL_PACK_SKIP_ROWS, 0);
+ glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
+ // Read a block of pixels from the frame buffer
+ int mByteWidth = w * 4;
+ mByteWidth = (mByteWidth + 3) & ~3; // Align to 4 bytes
+ uchar *baseAddress = new uchar[mByteWidth * h];
+ glReadPixels(x, glw->pixel_h() - (y+h), w, h,
+ GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, baseAddress);
+ glPopClientAttrib();
+ baseAddress = convert_BGRA_to_RGB(baseAddress, w, h, mByteWidth);
+ Fl_RGB_Image *img = new Fl_RGB_Image(baseAddress, w, h, 3, 3 * w);
+ img->alloc_array = 1;
+ [(NSOpenGLContext*)glw->context() flushBuffer];
+ return img;
+}
+
+
+void* Fl_Cocoa_Gl_Window_Driver::GetProcAddress(const char *procName) {
+ return dlsym(RTLD_DEFAULT, procName);
+}
+
+
+FL_EXPORT NSOpenGLContext *fl_mac_glcontext(GLContext rc) {
+ return (NSOpenGLContext*)rc;
+}
+
+
+/* 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 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.
+ */
+
+static struct win_view {
+ Fl_Gl_Window *win;
+ NSView *gl1view;
+ NSOpenGLContext *gl1ctxt;
+} win_view_struct;
+
+
+static void delayed_addgl1ctxt(struct win_view *data) {
+ NSView *flview = [fl_mac_xid(data->win) contentView];
+ [flview addSubview:data->gl1view];
+ [data->gl1view release];
+#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_7
+ if (fl_mac_os_version >= 100700 && Fl::use_high_res_GL()) {
+ [data->gl1view setWantsBestResolutionOpenGLSurface:YES];
+ }
+#endif
+ [data->gl1ctxt setView:data->gl1view];
+ remove_gl_context_opacity(data->gl1ctxt);
+ data->win->redraw();
+}
+
+
+void Fl_Cocoa_Gl_Window_Driver::switch_to_GL1() {
+ if (!gl1ctxt) {
+ NSView *view = [fl_xid(pWindow) contentView];
+ win_view_struct.gl1view = [[NSView alloc] initWithFrame:[view frame]];
+ NSOpenGLPixelFormat *gl1pixelformat = mode_to_NSOpenGLPixelFormat(
+ FL_RGB8 | FL_ALPHA | FL_SINGLE, NULL);
+ gl1ctxt = [[NSOpenGLContext alloc]
+ initWithFormat:gl1pixelformat shareContext:nil];
+ [gl1pixelformat release];
+ win_view_struct.win = pWindow;
+ win_view_struct.gl1ctxt = gl1ctxt;
+ Fl::add_timeout(0.01, (Fl_Timeout_Handler)delayed_addgl1ctxt,
+ &win_view_struct);
+ }
+ [gl1ctxt makeCurrentContext];
+ glClearColor(0., 0., 0., 0.);
+ glClear(GL_COLOR_BUFFER_BIT);
+}
+
+
+void Fl_Cocoa_Gl_Window_Driver::switch_back() {
+ glFlush();
+ [(NSOpenGLContext*)pWindow->context() makeCurrentContext];
+}
+
+
+void Fl_Cocoa_Gl_Window_Driver::gl_hide_before(void *&) {
+ if (gl1ctxt) {
+ [gl1ctxt release];
+ gl1ctxt = 0;
+ }
+}
+
+
+class Fl_Gl_Cocoa_Plugin : public Fl_Cocoa_Plugin {
+public:
+ Fl_Gl_Cocoa_Plugin() : Fl_Cocoa_Plugin(name()) { }
+ virtual const char *name() { return "gl.cocoa.fltk.org"; }
+ virtual void resize(Fl_Gl_Window *glw, int x, int y, int w, int h) {
+ glw->Fl_Gl_Window::resize(x, y, w, h);
+ }
+};
+
+static Fl_Gl_Cocoa_Plugin Gl_Cocoa_Plugin;
+
+#endif // HAVE_GL
diff --git src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H
index 16cea4e..520c4c2 100644
--- src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H
+++ src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H
@@ -146,21 +146,6 @@ public:
void draw_titlebar_to_context(CGContextRef gc, int w, int h);
virtual int scroll(int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, void (*draw_area)(void*, int,int,int,int), void* data);
- // these functions are OpenGL-related and use objective-c
- // they are put here to avoid libfltk_gl dependency in Fl_cocoa.mm
- static NSOpenGLContext* create_GLcontext_for_window(NSOpenGLPixelFormat *pixelformat, NSOpenGLContext *shared_ctx, Fl_Window *window);
- static NSOpenGLPixelFormat *mode_to_NSOpenGLPixelFormat(int mode, const int*); // uses Objective-c
- static void GLcontext_update(NSOpenGLContext*); // uses Objective-c
- static void GLcontext_release(NSOpenGLContext*); // uses Objective-c
- static void flush_context(NSOpenGLContext*); // uses Objective-c
- static void GLcontext_makecurrent(NSOpenGLContext*); // uses Objective-c
- 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(NSView **); // uses Objective-c
- void gl1ctxt_add(NSOpenGLContext*, NSView*); // uses Objective-c
- static void gl1ctxt_resize(NSOpenGLContext*); // uses Objective-c
-
//icons
virtual void icons(const Fl_RGB_Image *icons[], int count);
NSImage *icon_image;
[ Direct Link to Message ] | |