Changed OpenGL support for the Mac OS X platform: use cocoa instead of deprecated AGL.

All changes are mac-specific, except a very minor change in file src/gl_draw.cxx
where string drawing wrongly claimed to support @symbol, not possible
because symbols are drawn using non-GL primitives.

Unchanged application code can use the new FLTK code.
In addition, the new code allows mac applications to draw OpenGL scenes
at high resolution on so-called 'retina' displays, but this requires some
support from app code. They must call, before opening GL windows,
Fl::use_high_resolution(1);
and change their glViewport() calls as follows
glViewport(0, 0, pxel_w(), pixel_h());
This uses 2 new member functions of the Fl_Gl_Window class,
pixel_w() and pixel_h() returning the window dimensions in pixel
units, that is, twice the w() and h() when the window is mapped
on a retina display.


git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@10498 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Manolo Gouy
2014-12-20 07:19:23 +00:00
parent a7dc3ea9e2
commit f3a84c0ee5
18 changed files with 391 additions and 256 deletions
+13
View File
@@ -125,6 +125,9 @@ typedef void (*Fl_Clipboard_Notify_Handler)(int source, void *data);
class FL_EXPORT Fl { class FL_EXPORT Fl {
Fl() {}; // no constructor! Fl() {}; // no constructor!
private:
static int use_high_res_GL_;
public: // should be private! public: // should be private!
#ifndef FL_DOXYGEN #ifndef FL_DOXYGEN
static int e_number; static int e_number;
@@ -1206,6 +1209,16 @@ public:
static void release_widget_pointer(Fl_Widget *&w); static void release_widget_pointer(Fl_Widget *&w);
static void clear_widget_pointer(Fl_Widget const *w); static void clear_widget_pointer(Fl_Widget const *w);
/** @} */ /** @} */
/** sets whether GL windows should be drawn at high resolution on Apple
computers with retina displays
*/
static void use_high_res_GL(int val) { use_high_res_GL_ = val; }
/** returns whether GL windows should be drawn at high resolution on Apple
computers with retina displays.
Default is no.
*/
static int use_high_res_GL() { return use_high_res_GL_; }
#ifdef FLTK_HAVE_CAIRO #ifdef FLTK_HAVE_CAIRO
/** \defgroup group_cairo Cairo support functions and classes /** \defgroup group_cairo Cairo support functions and classes
+21 -2
View File
@@ -89,7 +89,7 @@ public:
\code \code
void mywindow::draw() { void mywindow::draw() {
if (!valid()) { if (!valid()) {
glViewport(0,0,w(),h()); glViewport(0,0,pixel_w(),pixel_h());
glFrustum(...); glFrustum(...);
...other initialization... ...other initialization...
} }
@@ -168,7 +168,8 @@ public:
int mode(int a) {return mode(a,0);} int mode(int a) {return mode(a,0);}
/** See Fl_Mode mode() const */ /** See Fl_Mode mode() const */
int mode(const int *a) {return mode(0, a);} int mode(const int *a) {return mode(0, a);}
/** void See void context(void* v, int destroy_flag) */ /** Returns a pointer to the GLContext that this window is using.
\see void context(void* v, int destroy_flag) */
void* context() const {return context_;} void* context() const {return context_;}
void context(void*, int destroy_flag = 0); void context(void*, int destroy_flag = 0);
void make_current(); void make_current();
@@ -201,6 +202,24 @@ public:
// Note: Doxygen docs in Fl_Widget.H to avoid redundancy. // Note: Doxygen docs in Fl_Widget.H to avoid redundancy.
virtual Fl_Gl_Window* as_gl_window() {return this;} virtual Fl_Gl_Window* as_gl_window() {return this;}
#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
int pixel_w();
int pixel_h();
#else
/** Gives the window width in OpenGL pixels.
Generally identical with the result of the w() function, but on macintosh computers
with a 'retina' display, and if Fl::use_high_res_GL(bool) is set to true,
pixel_w() returns 2 * w().
*/
int pixel_w() { return w(); }
/** Gives the window height in OpenGL pixels.
Generally identical with the result of the h() function, but on macintosh computers
with a 'retina' display, and if Fl::use_high_res_GL(bool) is set to true,
pixel_h() returns 2 * h().
*/
int pixel_h() { return h(); }
#endif
~Fl_Gl_Window(); ~Fl_Gl_Window();
/** /**
Creates a new Fl_Gl_Window widget using the given size, and label string. Creates a new Fl_Gl_Window widget using the given size, and label string.
+8 -1
View File
@@ -74,8 +74,10 @@ typedef CGContextRef Fl_Offscreen;
#ifdef __OBJC__ #ifdef __OBJC__
@class NSCursor; @class NSCursor;
@class NSOpenGLPixelFormat;
#else #else
class NSCursor; class NSCursor;
class NSOpenGLPixelFormat;
#endif // __OBJC__ #endif // __OBJC__
typedef CGContextRef Fl_Offscreen; typedef CGContextRef Fl_Offscreen;
@@ -151,6 +153,8 @@ public:
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
bool mapped_to_retina(); // is window mapped to retina display? bool mapped_to_retina(); // is window mapped to retina display?
void mapped_to_retina(bool); // sets whether window is mapped to retina display void mapped_to_retina(bool); // sets whether window is mapped to retina display
bool changed_resolution(); // did window just moved to display with another resolution?
void changed_resolution(bool);// sets whether window just moved to display with another resolution
#endif #endif
// Quartz additions: // Quartz additions:
CGContextRef gc; // graphics context (NULL when using QD) CGContextRef gc; // graphics context (NULL when using QD)
@@ -160,6 +164,8 @@ public:
static void q_begin_image(CGRect&, int x, int y, int w, int h); static void q_begin_image(CGRect&, int x, int y, int w, int h);
static void q_end_image(); static void q_end_image();
// Cocoa additions // Cocoa additions
static int resolution_scaling_factor(Fl_Window*);
static NSOpenGLPixelFormat *mode_to_NSOpenGLPixelFormat(int mode, const int*); // computes NSOpenGLPixelFormat from Gl window's mode
void destroy(void); void destroy(void);
void map(void); void map(void);
void unmap(void); void unmap(void);
@@ -183,7 +189,8 @@ public:
private: private:
#if FLTK_ABI_VERSION >= 10304 #if FLTK_ABI_VERSION >= 10304
CGRect* subRect_; // makes sure subwindow remains inside its parent window CGRect* subRect_; // makes sure subwindow remains inside its parent window
unsigned mapped_to_retina_; // stores whether window is mapped to retina display // stores 2 binary flags: whether window is mapped to retina display; whether resolution just changed
unsigned mapped_to_retina_;
#else #else
bool subwindow; // for ABI compatibility, useless with true subwindows bool subwindow; // for ABI compatibility, useless with true subwindows
#endif #endif
+1 -1
View File
@@ -2190,7 +2190,7 @@ Fl_Widget_Tracker::~Fl_Widget_Tracker()
Fl::release_widget_pointer(wp_); // remove pointer from watch list Fl::release_widget_pointer(wp_); // remove pointer from watch list
} }
int Fl::use_high_res_GL_ = 0;
// //
// End of "$Id$". // End of "$Id$".
// //
+10 -6
View File
@@ -51,10 +51,16 @@
# include <FL/gl.h> # include <FL/gl.h>
# define GLContext HGLRC # define GLContext HGLRC
#elif defined(__APPLE_QUARTZ__) #elif defined(__APPLE_QUARTZ__)
// warning: the Quartz version should probably use Core GL (CGL) instead of AGL
# include <OpenGL/gl.h> # include <OpenGL/gl.h>
# include <AGL/agl.h> #ifdef __OBJC__
# define GLContext AGLContext @class NSOpenGLPixelFormat;
@class NSOpenGLContext;
#else
class NSOpenGLPixelFormat;
class NSOpenGLContext;
#endif // __OBJC__
typedef NSOpenGLContext* FLOpenGLContextPtr;
# define GLContext FLOpenGLContextPtr
#else #else
# include <GL/glx.h> # include <GL/glx.h>
# define GLContext GLXContext # define GLContext GLXContext
@@ -70,8 +76,7 @@ public:
int pixelformat; // the visual to use int pixelformat; // the visual to use
PIXELFORMATDESCRIPTOR pfd; // some wgl calls need this thing PIXELFORMATDESCRIPTOR pfd; // some wgl calls need this thing
#elif defined(__APPLE_QUARTZ__) #elif defined(__APPLE_QUARTZ__)
// warning: the Quartz version should probably use Core GL (CGL) instead of AGL NSOpenGLPixelFormat* pixelformat;
AGLPixelFormat pixelformat;
#else #else
XVisualInfo *vis; // the visual to use XVisualInfo *vis; // the visual to use
Colormap colormap; // a colormap for that visual Colormap colormap; // a colormap for that visual
@@ -89,7 +94,6 @@ class Fl_Window;
GLContext fl_create_gl_context(Fl_Window*, const Fl_Gl_Choice*, int layer=0); GLContext fl_create_gl_context(Fl_Window*, const Fl_Gl_Choice*, int layer=0);
#elif defined(__APPLE_QUARTZ__) #elif defined(__APPLE_QUARTZ__)
// warning: the Quartz version should probably use Core GL (CGL) instead of AGL
GLContext fl_create_gl_context(Fl_Window*, const Fl_Gl_Choice*, int layer=0); GLContext fl_create_gl_context(Fl_Window*, const Fl_Gl_Choice*, int layer=0);
+10 -104
View File
@@ -28,8 +28,11 @@
# include <FL/fl_utf8.h> # include <FL/fl_utf8.h>
# ifdef __APPLE__ # ifdef __APPLE__
# include <ApplicationServices/ApplicationServices.h> extern NSOpenGLContext* gl_create_context_for_window(NSOpenGLPixelFormat *pixelformat,
# include <FL/Fl_Window.H> NSOpenGLContext *shared_ctx, Fl_Window *window);
extern void gl_context_release(NSOpenGLContext*);
extern void gl_context_makecurrent(NSOpenGLContext*);
extern void gl_cleardrawable(void);
# endif # endif
# ifdef WIN32 # ifdef WIN32
@@ -108,53 +111,7 @@ Fl_Gl_Choice *Fl_Gl_Choice::find(int m, const int *alistp) {
} }
#elif defined(__APPLE_QUARTZ__) #elif defined(__APPLE_QUARTZ__)
// warning: the Quartz version should probably use Core GL (CGL) instead of AGL NSOpenGLPixelFormat* fmt = Fl_X::mode_to_NSOpenGLPixelFormat(m, alistp);
const int *blist;
int list[32];
if (alistp)
blist = alistp;
else {
int n = 0;
if (m & FL_INDEX) {
list[n++] = AGL_BUFFER_SIZE;
list[n++] = 8; // glut tries many sizes, but this should work...
} else {
list[n++] = AGL_RGBA;
list[n++] = AGL_GREEN_SIZE;
list[n++] = (m & FL_RGB8) ? 8 : 1;
if (m & FL_ALPHA) {
list[n++] = AGL_ALPHA_SIZE;
list[n++] = (m & FL_RGB8) ? 8 : 1;
}
if (m & FL_ACCUM) {
list[n++] = AGL_ACCUM_GREEN_SIZE;
list[n++] = 1;
if (m & FL_ALPHA) {
list[n++] = AGL_ACCUM_ALPHA_SIZE;
list[n++] = 1;
}
}
}
if (m & FL_DOUBLE) {
list[n++] = AGL_DOUBLEBUFFER;
}
if (m & FL_DEPTH) {
list[n++] = AGL_DEPTH_SIZE; list[n++] = 24;
}
if (m & FL_STENCIL) {
list[n++] = AGL_STENCIL_SIZE; list[n++] = 1;
}
# ifdef AGL_STEREO
if (m & FL_STEREO) {
list[n++] = AGL_STEREO;
}
# endif
list[n] = AGL_NONE;
blist = list;
}
fl_open_display();
AGLPixelFormat fmt = aglChoosePixelFormat(NULL, 0, (GLint*)blist);
if (!fmt) return 0; if (!fmt) return 0;
#elif defined(WIN32) #elif defined(WIN32)
@@ -216,7 +173,6 @@ Fl_Gl_Choice *Fl_Gl_Choice::find(int m, const int *alistp) {
g->pixelformat = pixelformat; g->pixelformat = pixelformat;
g->pfd = chosen_pfd; g->pfd = chosen_pfd;
# elif defined(__APPLE_QUARTZ__) # elif defined(__APPLE_QUARTZ__)
// warning: the Quartz version should probably use Core GL (CGL) instead of AGL
g->pixelformat = fmt; g->pixelformat = fmt;
# else # else
# error unsupported platform # error unsupported platform
@@ -287,38 +243,13 @@ GLContext fl_create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g, int lay
} }
# elif defined(__APPLE_QUARTZ__) # elif defined(__APPLE_QUARTZ__)
#if !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && __LP64__)
static CGrafPtr fl_GetWindowPort(WindowRef window)
{
typedef CGrafPtr (*wf)(WindowRef);
static wf f = NULL;
if ( ! f) f = (wf)Fl_X::get_carbon_function("GetWindowPort");
return (*f)(window);
}
#endif
// warning: the Quartz version should probably use Core GL (CGL) instead of AGL
GLContext fl_create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g, int layer) { GLContext fl_create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g, int layer) {
GLContext context, shared_ctx = 0; GLContext context, shared_ctx = 0;
if (context_list && nContext) shared_ctx = context_list[0]; if (context_list && nContext) shared_ctx = context_list[0];
context = aglCreateContext( g->pixelformat, shared_ctx); context = gl_create_context_for_window(g->pixelformat, shared_ctx, window);
if (!context) return 0; if (!context) return 0;
add_context((GLContext)context); add_context((GLContext)context);
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
#if __LP64__
// 64 bit version
aglSetWindowRef(context, Fl_X::i(window)->window_ref() );
#else
// 32 bit version >= 10.5
if (aglSetWindowRef != NULL)
aglSetWindowRef(context, Fl_X::i(window)->window_ref() );
else
aglSetDrawable( context, fl_GetWindowPort( Fl_X::i(window)->window_ref() ) );
#endif
#else
// 32 bit version < 10.5
aglSetDrawable( context, fl_GetWindowPort( Fl_X::i(window)->window_ref() ) );
#endif
return (context); return (context);
} }
# else # else
@@ -337,23 +268,7 @@ void fl_set_gl_context(Fl_Window* w, GLContext context) {
# elif defined(WIN32) # elif defined(WIN32)
wglMakeCurrent(Fl_X::i(w)->private_dc, context); wglMakeCurrent(Fl_X::i(w)->private_dc, context);
# elif defined(__APPLE_QUARTZ__) # elif defined(__APPLE_QUARTZ__)
// warning: the Quartz version should probably use Core GL (CGL) instead of AGL gl_context_makecurrent(context);
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
#if __LP64__
// 64 bit version
aglSetWindowRef(context, Fl_X::i(w)->window_ref() );
#else
// 32 bit version >= 10.5
if (aglSetWindowRef != NULL)
aglSetWindowRef(context, Fl_X::i(w)->window_ref() );
else
aglSetDrawable( context, fl_GetWindowPort( Fl_X::i(w)->window_ref() ) );
#endif
#else
// 32 bit version < 10.5
aglSetDrawable( context, fl_GetWindowPort( Fl_X::i(w)->window_ref() ) );
#endif
aglSetCurrentContext(context);
# else # else
# error unsupported platform # error unsupported platform
# endif # endif
@@ -368,15 +283,7 @@ void fl_no_gl_context() {
# elif defined(WIN32) # elif defined(WIN32)
wglMakeCurrent(0, 0); wglMakeCurrent(0, 0);
# elif defined(__APPLE_QUARTZ__) # elif defined(__APPLE_QUARTZ__)
// warning: the Quartz version should probably use Core GL (CGL) instead of AGL gl_cleardrawable();
AGLContext ctx = aglGetCurrentContext();
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
if (aglSetWindowRef != NULL)
{ if(ctx) aglSetWindowRef(ctx, NULL ); }
else
#endif
if(ctx) aglSetDrawable( ctx, NULL );
aglSetCurrentContext(0);
# else # else
# error unsupported platform # error unsupported platform
# endif # endif
@@ -389,8 +296,7 @@ void fl_delete_gl_context(GLContext context) {
# elif defined(WIN32) # elif defined(WIN32)
wglDeleteContext(context); wglDeleteContext(context);
# elif defined(__APPLE_QUARTZ__) # elif defined(__APPLE_QUARTZ__)
// warning: the Quartz version should probably use Core GL (CGL) instead of AGL gl_context_release(context);
aglDestroyContext( context );
# else # else
# error unsupported platform # error unsupported platform
# endif # endif
+31 -3
View File
@@ -53,10 +53,13 @@ static Fl_RGB_Image* capture_gl_rectangle(Fl_Gl_Window *glw, int x, int y, int w
{ {
#if defined(__APPLE__) #if defined(__APPLE__)
const int bytesperpixel = 4; const int bytesperpixel = 4;
if (Fl_X::resolution_scaling_factor(glw) > 1) {
w = 2*w; h = 2*h; x = 2*x; y = 2*y;
}
#else #else
const int bytesperpixel = 3; const int bytesperpixel = 3;
#endif #endif
glw->flush(); // forces a GL redraw necessary for the glpuzzle demo glw->flush(); // forces a GL redraw, necessary for the glpuzzle demo
// Read OpenGL context pixels directly. // Read OpenGL context pixels directly.
// For extra safety, save & restore OpenGL states that are changed // For extra safety, save & restore OpenGL states that are changed
glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
@@ -68,7 +71,7 @@ static Fl_RGB_Image* capture_gl_rectangle(Fl_Gl_Window *glw, int x, int y, int w
int mByteWidth = w * bytesperpixel; int mByteWidth = w * bytesperpixel;
mByteWidth = (mByteWidth + 3) & ~3; // Align to 4 bytes mByteWidth = (mByteWidth + 3) & ~3; // Align to 4 bytes
uchar *baseAddress = new uchar[mByteWidth * h]; uchar *baseAddress = new uchar[mByteWidth * h];
glReadPixels(x, glw->h() - (y+h), w, h, glReadPixels(x, glw->pixel_h() - (y+h), w, h,
#if defined(__APPLE__) #if defined(__APPLE__)
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
#else #else
@@ -85,6 +88,11 @@ static Fl_RGB_Image* capture_gl_rectangle(Fl_Gl_Window *glw, int x, int y, int w
return img; return img;
} }
static void imgProviderReleaseData (void *info, const void *data, size_t size)
{
delete (Fl_RGB_Image *)info;
}
/** /**
This class will make sure that OpenGL printing/screen capture is available if fltk_gl This class will make sure that OpenGL printing/screen capture is available if fltk_gl
was linked to the program was linked to the program
@@ -97,7 +105,27 @@ public:
Fl_Gl_Window *glw = w->as_gl_window(); Fl_Gl_Window *glw = w->as_gl_window();
if (!glw) return 0; if (!glw) return 0;
Fl_RGB_Image *img = capture_gl_rectangle(glw, 0, 0, glw->w(), glw->h()); Fl_RGB_Image *img = capture_gl_rectangle(glw, 0, 0, glw->w(), glw->h());
fl_draw_image(img->array + (glw->h() - 1) * img->ld(), x, y , glw->w(), glw->h(), 3, - img->ld()); #ifdef __APPLE__
if (Fl_Surface_Device::surface()->class_name() == Fl_Printer::class_id) {
// convert the image to CGImage, and draw it at full res (useful on retina display)
CGColorSpaceRef cSpace = CGColorSpaceCreateDeviceRGB();
CGDataProviderRef provider = CGDataProviderCreateWithData(img, img->array, img->ld() * img->h(), imgProviderReleaseData);
CGImageRef cgimg = CGImageCreate(img->w(), img->h(), 8, 24, img->ld(), cSpace,
(CGBitmapInfo)(kCGImageAlphaNone),
provider, NULL, false, kCGRenderingIntentDefault);
CGColorSpaceRelease(cSpace);
CGDataProviderRelease(provider);
CGContextDrawImage(fl_gc, CGRectMake(0, 0, glw->w(), glw->h()), cgimg);
CFRelease(cgimg);
return 1;
} else if (img->w() > glw->w()) {
Fl_RGB_Image *img2 = (Fl_RGB_Image*)img->copy(glw->w(), glw->h());
delete img;
img = img2;
}
#endif
int ld = img->ld() ? img->ld() : img->w() * img->d();
fl_draw_image(img->array + (img->h() - 1) * ld, x, y , img->w(), img->h(), 3, - ld);
delete img; delete img;
return 1; return 1;
} }
+53 -59
View File
@@ -26,10 +26,12 @@ extern void gl_texture_reset();
#include <FL/Fl.H> #include <FL/Fl.H>
#include <FL/x.H> #include <FL/x.H>
#include "Fl_Gl_Choice.H"
#ifdef __APPLE__ #ifdef __APPLE__
#include <FL/gl.h> #include <FL/gl.h>
extern void gl_context_update(NSOpenGLContext*);
extern void gl_context_flushbuffer(NSOpenGLContext*);
#endif #endif
#include "Fl_Gl_Choice.H"
#include <FL/Fl_Gl_Window.H> #include <FL/Fl_Gl_Window.H>
#include <stdlib.h> #include <stdlib.h>
#include <FL/fl_utf8.h> #include <FL/fl_utf8.h>
@@ -97,6 +99,20 @@ void Fl_Gl_Window::show() {
#endif /* __APPLE__ */ #endif /* __APPLE__ */
} }
#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
int Fl_Gl_Window::pixel_w()
{
return Fl_X::resolution_scaling_factor(this) * w();
}
int Fl_Gl_Window::pixel_h()
{
return Fl_X::resolution_scaling_factor(this) * h();
}
#endif
/** /**
The invalidate() method turns off valid() and is The invalidate() method turns off valid() and is
equivalent to calling value(0). equivalent to calling value(0).
@@ -140,7 +156,6 @@ int Fl_Gl_Window::mode(int m, const int *a) {
show(); show();
} }
#elif defined(__APPLE_QUARTZ__) #elif defined(__APPLE_QUARTZ__)
// warning: the Quartz version should probably use Core GL (CGL) instead of AGL
redraw(); redraw();
#else #else
# error unsupported platform # error unsupported platform
@@ -163,6 +178,14 @@ int Fl_Gl_Window::mode(int m, const int *a) {
void Fl_Gl_Window::make_current() { void Fl_Gl_Window::make_current() {
// puts("Fl_Gl_Window::make_current()"); // puts("Fl_Gl_Window::make_current()");
// printf("make_current: context_=%p\n", context_); // printf("make_current: context_=%p\n", context_);
#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
// detect if the window was moved between low and high resolution displays
if (Fl_X::i(this)->changed_resolution()){
Fl_X::i(this)->changed_resolution(false);
invalidate();
gl_context_update(context_);
}
#endif
if (!context_) { if (!context_) {
mode_ &= ~NON_LOCAL_CONTEXT; mode_ &= ~NON_LOCAL_CONTEXT;
context_ = fl_create_gl_context(this, g); context_ = fl_create_gl_context(this, g);
@@ -170,26 +193,12 @@ void Fl_Gl_Window::make_current() {
context_valid(0); context_valid(0);
#ifdef __APPLE__ #ifdef __APPLE__
// resets the pile of string textures used to draw strings // resets the pile of string textures used to draw strings
// necessary when the context is renewed
gl_texture_reset(); gl_texture_reset();
#endif #endif
} }
fl_set_gl_context(this, context_); fl_set_gl_context(this, context_);
#ifdef __APPLE__
// Set the buffer rectangle here, since in resize() we won't have the
// correct parent window size to work with...
GLint xywh[4];
xywh[0] = 0;
xywh[1] = 0;
xywh[2] = w();
xywh[3] = h();
aglSetInteger(context_, AGL_BUFFER_RECT, xywh);
aglEnable(context_, AGL_BUFFER_RECT);
// printf("make_current: xywh=[%d %d %d %d]\n", xywh[0], xywh[1], xywh[2], xywh[3]);
#endif // __APPLE__
#if defined(WIN32) && USE_COLORMAP #if defined(WIN32) && USE_COLORMAP
if (fl_palette) { if (fl_palette) {
fl_GetDC(fl_xid(this)); fl_GetDC(fl_xid(this));
@@ -219,8 +228,8 @@ void Fl_Gl_Window::ortho() {
GLint v[2]; GLint v[2];
glGetIntegerv(GL_MAX_VIEWPORT_DIMS, v); glGetIntegerv(GL_MAX_VIEWPORT_DIMS, v);
glLoadIdentity(); glLoadIdentity();
glViewport(w()-v[0], h()-v[1], v[0], v[1]); glViewport(pixel_w()-v[0], pixel_h()-v[1], v[0], v[1]);
glOrtho(w()-v[0], w(), h()-v[1], h(), -1, 1); glOrtho(pixel_w()-v[0], pixel_w(), pixel_h()-v[1], pixel_h(), -1, 1);
#endif #endif
} }
@@ -244,7 +253,7 @@ void Fl_Gl_Window::swap_buffers() {
// STR# 2944 [1] // STR# 2944 [1]
// Save matrixmode/proj/modelview/rasterpos before doing overlay. // Save matrixmode/proj/modelview/rasterpos before doing overlay.
// //
int wo=w(), ho=h(); int wo=pixel_w(), ho=pixel_h();
GLint matrixmode; GLint matrixmode;
GLfloat pos[4]; GLfloat pos[4];
glGetIntegerv(GL_MATRIX_MODE, &matrixmode); glGetIntegerv(GL_MATRIX_MODE, &matrixmode);
@@ -270,8 +279,10 @@ void Fl_Gl_Window::swap_buffers() {
glMatrixMode(matrixmode); glMatrixMode(matrixmode);
glRasterPos3f(pos[0], pos[1], pos[2]); // restore original glRasterPos glRasterPos3f(pos[0], pos[1], pos[2]); // restore original glRasterPos
} }
else /* // nothing to do here under Cocoa because [NSOpenGLContext -flushBuffer] done later replaces it
else
aglSwapBuffers((AGLContext)context_); aglSwapBuffers((AGLContext)context_);
*/
#else #else
# error unsupported platform # error unsupported platform
#endif #endif
@@ -290,19 +301,6 @@ void Fl_Gl_Window::flush() {
uchar save_valid_f = valid_f_; uchar save_valid_f = valid_f_;
#endif #endif
#if defined(__APPLE_QUARTZ__)
// warning: the Quartz version should probably use Core GL (CGL) instead of AGL
//: clear previous clipping in this shared port
#if ! __LP64__
/*GrafPtr port = GetWindowPort( Fl_X::i(this)->window_ref() );
Rect rect; SetRect( &rect, 0, 0, 0x7fff, 0x7fff );
GrafPtr old; GetPort( &old );
SetPort( port );
ClipRect( &rect );
SetPort( old );*/
#endif
#endif
#if HAVE_GL_OVERLAY && defined(WIN32) #if HAVE_GL_OVERLAY && defined(WIN32)
// Draw into hardware overlay planes if they are damaged: // Draw into hardware overlay planes if they are damaged:
@@ -383,22 +381,25 @@ void Fl_Gl_Window::flush() {
glReadBuffer(GL_BACK); glReadBuffer(GL_BACK);
glDrawBuffer(GL_FRONT); glDrawBuffer(GL_FRONT);
glLoadIdentity(); glLoadIdentity();
glViewport(0, 0, w(), h()); glViewport(0, 0, pixel_w(), pixel_h());
glOrtho(0, w(), 0, h(), -1, 1); glOrtho(0, pixel_w(), 0, pixel_h(), -1, 1);
glRasterPos2i(0,0); glRasterPos2i(0,0);
ortho_window = this; ortho_window = this;
} }
glCopyPixels(0,0,w(),h(),GL_COLOR); glCopyPixels(0,0,pixel_w(),pixel_h(),GL_COLOR);
make_current(); // set current context back to draw overlay make_current(); // set current context back to draw overlay
damage1_ = 0; damage1_ = 0;
} else { } else {
damage1_ = damage(); damage1_ = damage();
clear_damage(0xff); draw(); clear_damage(0xff); draw();
swap_buffers(); swap_buffers();
} }
} }
#ifdef __APPLE__
gl_context_flushbuffer(context_);
#endif
if (overlay==this && SWAP_TYPE != SWAP) { // fake overlay in front buffer if (overlay==this && SWAP_TYPE != SWAP) { // fake overlay in front buffer
glDrawBuffer(GL_FRONT); glDrawBuffer(GL_FRONT);
@@ -423,22 +424,27 @@ void Fl_Gl_Window::resize(int X,int Y,int W,int H) {
// printf("Fl_Gl_Window::resize(X=%d, Y=%d, W=%d, H=%d)\n", X, Y, W, H); // printf("Fl_Gl_Window::resize(X=%d, Y=%d, W=%d, H=%d)\n", X, Y, W, H);
// printf("current: x()=%d, y()=%d, w()=%d, h()=%d\n", x(), y(), w(), h()); // printf("current: x()=%d, y()=%d, w()=%d, h()=%d\n", x(), y(), w(), h());
if (W != w() || H != h()) valid(0); int is_a_resize = (W != Fl_Widget::w() || H != Fl_Widget::h());
if (is_a_resize) valid(0);
#ifdef __APPLE__ #if ! ( defined(__APPLE__) || defined(WIN32) )
if (X != x() || Y != y() || W != w() || H != h()) aglUpdateContext(context_); if (is_a_resize && !resizable() && overlay && overlay != this) {
#elif !defined(WIN32)
if ((W != w() || H != h()) && !resizable() && overlay && overlay != this) {
((Fl_Gl_Window*)overlay)->resize(0,0,W,H); ((Fl_Gl_Window*)overlay)->resize(0,0,W,H);
} }
#endif #endif
Fl_Window::resize(X,Y,W,H); Fl_Window::resize(X,Y,W,H);
#ifdef __APPLE__
if (is_a_resize) {
gl_context_update(context_);
redraw();
}
#endif
} }
/** /**
Returns or sets a pointer to the GLContext that this window is Sets a pointer to the GLContext that this window is using.
using. This is a system-dependent structure, but it is portable to copy This is a system-dependent structure, but it is portable to copy
the context from one window to another. You can also set it to NULL, the context from one window to another. You can also set it to NULL,
which will force FLTK to recreate the context the next time make_current() which will force FLTK to recreate the context the next time make_current()
is called, this is useful for getting around bugs in OpenGL implementations. is called, this is useful for getting around bugs in OpenGL implementations.
@@ -540,18 +546,6 @@ void Fl_Gl_Window::draw() {
*/ */
int Fl_Gl_Window::handle(int event) int Fl_Gl_Window::handle(int event)
{ {
#ifdef __APPLE_QUARTZ__
if (event==FL_HIDE) {
// if we are not hidden, just the parent was hidden, so we must throw away the context
if (!visible_r())
context(0); // remove context without setting the hidden flags
}
if (event==FL_SHOW) {
// if we are not hidden, just the parent was shown, so we must create a new context
if (visible_r())
show(); //
}
#endif
return Fl_Window::handle(event); return Fl_Window::handle(event);
} }
+189 -17
View File
@@ -1107,7 +1107,10 @@ static void position_subwindows(Fl_Window *parent, BOOL is_a_move)
NSRect rchild; NSRect rchild;
Fl_Window *sub = [child getFl_Window]; Fl_Window *sub = [child getFl_Window];
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
Fl_X::i(sub)->mapped_to_retina( Fl_X::i(parent)->mapped_to_retina() ); Fl_X *subx = Fl_X::i(sub);
bool previous = subx->mapped_to_retina();
subx->mapped_to_retina( Fl_X::i(parent)->mapped_to_retina() );
if (previous != subx->mapped_to_retina()) subx->changed_resolution(true);
#endif #endif
rchild.origin = NSMakePoint(pframe.origin.x + sub->x(), pframe.origin.y + parent->h() - (sub->h() + sub->y())); rchild.origin = NSMakePoint(pframe.origin.x + sub->x(), pframe.origin.y + parent->h() - (sub->h() + sub->y()));
rchild.size = NSMakeSize(sub->w(), sub->h()); rchild.size = NSMakeSize(sub->w(), sub->h());
@@ -1143,8 +1146,9 @@ static void compute_mapped_to_retina(Fl_Window *window)
if (fl_mac_os_version >= 100700) { // determine whether window is now mapped to a retina display if (fl_mac_os_version >= 100700) { // determine whether window is now mapped to a retina display
Fl_X *flx = Fl_X::i(window); Fl_X *flx = Fl_X::i(window);
bool previous = flx->mapped_to_retina(); bool previous = flx->mapped_to_retina();
NSSize s = [[fl_xid(window) contentView] convertSizeToBacking:NSMakeSize(10, 10)]; NSSize s = [[flx->xid contentView] convertSizeToBacking:NSMakeSize(10, 10)];
flx->mapped_to_retina( int(s.width + 0.5) > 10 ); flx->mapped_to_retina( int(s.width + 0.5) > 10 );
if (previous != flx->mapped_to_retina()) flx->changed_resolution(true);
// window needs redrawn when moving from low res to retina // window needs redrawn when moving from low res to retina
if ((!previous) && flx->mapped_to_retina()) { if ((!previous) && flx->mapped_to_retina()) {
window->redraw(); window->redraw();
@@ -1152,19 +1156,47 @@ static void compute_mapped_to_retina(Fl_Window *window)
} }
} }
#if FLTK_ABI_VERSION >= 10304
static const unsigned mapped_mask = 1;
static const unsigned changed_mask = 2;
#else
static const unsigned long mapped_mask = 1; // sizeof(unsigned long) = sizeof(Fl_X*)
static const unsigned long changed_mask = 2;
#endif
bool Fl_X::mapped_to_retina() { bool Fl_X::mapped_to_retina() {
#if FLTK_ABI_VERSION >= 10304 #if FLTK_ABI_VERSION >= 10304
return (bool)mapped_to_retina_; return mapped_to_retina_ & mapped_mask;
#else #else
return xidChildren != NULL; return (unsigned long)xidChildren & mapped_mask;
#endif #endif
} }
void Fl_X::mapped_to_retina(bool b) { void Fl_X::mapped_to_retina(bool b) {
#if FLTK_ABI_VERSION >= 10304 #if FLTK_ABI_VERSION >= 10304
mapped_to_retina_ = b; if (b) mapped_to_retina_ |= mapped;
else mapped_to_retina_ &= ~mapped;
#else #else
xidChildren = (b ? (Fl_X*)1 : NULL); if (b) xidChildren = (Fl_X*)((unsigned long)xidChildren | mapped_mask);
else xidChildren = (Fl_X*)((unsigned long)xidChildren & ~mapped_mask);
#endif
}
bool Fl_X::changed_resolution() {
#if FLTK_ABI_VERSION >= 10304
return mapped_to_retina_ & changed_mask;
#else
return (unsigned long)xidChildren & changed_mask;
#endif
}
void Fl_X::changed_resolution(bool b) {
#if FLTK_ABI_VERSION >= 10304
if (b) mapped_to_retina_ |= changed_mask;
else mapped_to_retina_ &= ~changed_mask;
#else
if (b) xidChildren = (Fl_X*)((unsigned long)xidChildren | changed_mask);
else xidChildren = (Fl_X*)((unsigned long)xidChildren & ~changed_mask);
#endif #endif
} }
@@ -2162,20 +2194,21 @@ static FLTextInputContext* fltextinputcontext_instance = nil;
cocoaKeyboardHandler(theEvent); cocoaKeyboardHandler(theEvent);
BOOL handled; BOOL handled;
NSUInteger mods = [theEvent modifierFlags]; NSUInteger mods = [theEvent modifierFlags];
if ( (mods & NSControlKeyMask) || (mods & NSCommandKeyMask) ) { Fl_Window *w = [(FLWindow*)[theEvent window] getFl_Window];
if ( (mods & NSControlKeyMask) || (mods & NSCommandKeyMask) || (w->as_gl_window() && Fl::focus() == w)) {
NSString *s = [theEvent characters]; NSString *s = [theEvent characters];
if ( (mods & NSShiftKeyMask) && (mods & NSCommandKeyMask) ) { if ( (mods & NSShiftKeyMask) && (mods & NSCommandKeyMask) ) {
s = [s uppercaseString]; // US keyboards return lowercase letter in s if cmd-shift-key is hit s = [s uppercaseString]; // US keyboards return lowercase letter in s if cmd-shift-key is hit
} }
[FLView prepareEtext:s]; [FLView prepareEtext:s];
Fl::compose_state = 0; Fl::compose_state = 0;
handled = Fl::handle(FL_KEYBOARD, [(FLWindow*)[theEvent window] getFl_Window]); handled = Fl::handle(FL_KEYBOARD, w);
} }
else { else {
in_key_event = YES; in_key_event = YES;
need_handle = NO; need_handle = NO;
handled = [self fl_handle_keydown_event:theEvent]; handled = [self fl_handle_keydown_event:theEvent];
if (need_handle) handled = Fl::handle(FL_KEYBOARD, [(FLWindow*)[theEvent window] getFl_Window]); if (need_handle) handled = Fl::handle(FL_KEYBOARD, w);
in_key_event = NO; in_key_event = NO;
} }
fl_unlock_function(); fl_unlock_function();
@@ -2238,8 +2271,13 @@ static FLTextInputContext* fltextinputcontext_instance = nil;
Fl::first_window(window); Fl::first_window(window);
cocoaKeyboardHandler(theEvent); cocoaKeyboardHandler(theEvent);
in_key_event = YES; in_key_event = YES;
need_handle = NO; if (window->as_gl_window() && Fl::focus() == window ) { // ignore text input methods for GL windows
[self fl_handle_keydown_event:theEvent]; need_handle = YES;
[FLView prepareEtext:[theEvent characters]];
} else {
need_handle = NO;
[self fl_handle_keydown_event:theEvent];
}
if (need_handle) Fl::handle(FL_KEYBOARD, window); if (need_handle) Fl::handle(FL_KEYBOARD, window);
in_key_event = NO; in_key_event = NO;
fl_unlock_function(); fl_unlock_function();
@@ -2588,6 +2626,125 @@ static FLTextInputContext* fltextinputcontext_instance = nil;
} }
@end @end
// For Fl_Gl_Window on retina display, returns 2, otherwise 1
int Fl_X::resolution_scaling_factor(Fl_Window* win)
{
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
return (win->as_gl_window() && Fl::use_high_res_GL() && win->i->mapped_to_retina()) ? 2 : 1;
#else
return 1;
#endif
}
NSOpenGLPixelFormat* Fl_X::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++] = (m & FL_RGB8) ? 32 : 1;
if (m & FL_ALPHA) {
//list[n++] = AGL_ALPHA_SIZE;
attribs[n++] = NSOpenGLPFAAlphaSize;
attribs[n++] = (m & FL_RGB8) ? 8 : 1;
}
if (m & FL_ACCUM) {
//list[n++] = AGL_ACCUM_GREEN_SIZE; list[n++] = 1;
attribs[n++] = NSOpenGLPFAAccumSize;
attribs[n++] = 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++] = 24;
}
if (m & FL_STENCIL) {
//list[n++] = AGL_STENCIL_SIZE; list[n++] = 1;
attribs[n++] = NSOpenGLPFAStencilSize;
attribs[n++] = 1;
}
if (m & FL_STEREO) {
//list[n++] = AGL_STEREO;
attribs[n++] = NSOpenGLPFAStereo;
}
if (m & FL_MULTISAMPLE) {
attribs[n++] = NSOpenGLPFAMultisample,
attribs[n++] = NSOpenGLPFASampleBuffers; attribs[n++] = 1;
attribs[n++] = NSOpenGLPFASamples; attribs[n++] = 4;
}
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
if (fl_mac_os_version >= 100700) {
attribs[n++] = NSOpenGLPFAOpenGLProfile;
attribs[n++] = NSOpenGLProfileVersionLegacy;
}
#endif
} else {
while (alistp[n] && n < 30) {
attribs[n] = alistp[n];
n++;
}
}
attribs[n] = 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* gl_create_context_for_window(NSOpenGLPixelFormat *pixelformat,
NSOpenGLContext *shared_ctx, Fl_Window *window)
{
NSOpenGLContext *context = [[NSOpenGLContext alloc] initWithFormat:pixelformat shareContext:shared_ctx];
if (context) [context setView:[fl_xid(window) contentView]];
return context;
}
void gl_context_update(NSOpenGLContext* ctxt)
{
[ctxt update];
}
void gl_context_flushbuffer(NSOpenGLContext* ctxt)
{
[ctxt flushBuffer];
}
void gl_context_release(NSOpenGLContext* ctxt)
{
[ctxt release];
}
void gl_cleardrawable(void)
{
[[NSOpenGLContext currentContext] clearDrawable];
}
void gl_context_makecurrent(NSOpenGLContext* ctxt)
{
[ctxt makeCurrentContext];
}
void Fl_Window::fullscreen_x() { void Fl_Window::fullscreen_x() {
_set_fullscreen(); _set_fullscreen();
/* On OS X < 10.6, it is necessary to recreate the window. This is done /* On OS X < 10.6, it is necessary to recreate the window. This is done
@@ -2610,15 +2767,19 @@ void Fl_Window::fullscreen_off_x(int X, int Y, int W, int H) {
*/ */
void Fl_X::flush() void Fl_X::flush()
{ {
if (through_drawRect || w->as_gl_window()) { if (through_drawRect) {
make_current_counts = 1; if (w->as_gl_window()) {
w->flush(); w->flush();
make_current_counts = 0; } else {
Fl_X::q_release_context(); make_current_counts = 1;
w->flush();
make_current_counts = 0;
Fl_X::q_release_context();
}
return; return;
} }
// have Cocoa immediately redraw the window's view // have Cocoa immediately redraw the window's view
FLView *view = (FLView*)[fl_xid(w) contentView]; FLView *view = (FLView*)[xid contentView];
fl_x_to_redraw = this; fl_x_to_redraw = this;
[view setNeedsDisplay:YES]; [view setNeedsDisplay:YES];
// will send the drawRect: message to the window's view after having prepared the adequate NSGraphicsContext // will send the drawRect: message to the window's view after having prepared the adequate NSGraphicsContext
@@ -2717,6 +2878,7 @@ void Fl_X::make(Fl_Window* w)
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
if (w->parent()) x->mapped_to_retina( w->top_window()->i->mapped_to_retina() ); if (w->parent()) x->mapped_to_retina( w->top_window()->i->mapped_to_retina() );
else x->mapped_to_retina(false); else x->mapped_to_retina(false);
x->changed_resolution(false);
#endif #endif
NSRect crect; NSRect crect;
@@ -2781,6 +2943,11 @@ void Fl_X::make(Fl_Window* w)
Fl_X::first = x; Fl_X::first = x;
} }
FLView *myview = [[FLView alloc] initWithFrame:crect]; FLView *myview = [[FLView alloc] initWithFrame:crect];
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
if (w->as_gl_window() && fl_mac_os_version >= 100700 && Fl::use_high_res_GL()) {
[myview setWantsBestResolutionOpenGLSurface:YES];
}
#endif
[cw setContentView:myview]; [cw setContentView:myview];
[myview release]; [myview release];
[cw setLevel:winlevel]; [cw setLevel:winlevel];
@@ -2835,6 +3002,10 @@ void Fl_X::make(Fl_Window* w)
FLWindow *pxid = fl_xid(w->top_window()); FLWindow *pxid = fl_xid(w->top_window());
[pxid makeFirstResponder:[pxid contentView]]; [pxid makeFirstResponder:[pxid contentView]];
} else { } else {
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
compute_mapped_to_retina(w);
x->changed_resolution(false);
#endif
[cw makeKeyAndOrderFront:nil]; [cw makeKeyAndOrderFront:nil];
} }
@@ -3928,6 +4099,7 @@ static void write_bitmap_inside(NSBitmapImageRep *to, int to_width, NSBitmapImag
static NSBitmapImageRep* GL_rect_to_nsbitmap(Fl_Window *win, int x, int y, int w, int h) static NSBitmapImageRep* GL_rect_to_nsbitmap(Fl_Window *win, int x, int y, int w, int h)
// captures a rectangle from a GL window and returns it as an allocated NSBitmapImageRep // captures a rectangle from a GL window and returns it as an allocated NSBitmapImageRep
// the capture has high res on retina
{ {
Fl_Plugin_Manager pm("fltk:device"); Fl_Plugin_Manager pm("fltk:device");
Fl_Device_Plugin *pi = (Fl_Device_Plugin*)pm.plugin("opengl.device.fltk.org"); Fl_Device_Plugin *pi = (Fl_Device_Plugin*)pm.plugin("opengl.device.fltk.org");
+26 -51
View File
@@ -36,9 +36,9 @@
#include "Xutf8.h" #include "Xutf8.h"
#endif #endif
#if USE_XFT #ifdef __APPLE__
//extern XFontStruct* fl_xxfont(); static int gl_scale = 1; // set to 2 for high resolution Fl_Gl_Window
#endif // USE_XFT #endif
/** Returns the current font's height */ /** Returns the current font's height */
int gl_height() {return fl_height();} int gl_height() {return fl_height();}
@@ -53,11 +53,8 @@ double gl_width(uchar c) {return fl_width(c);}
static Fl_Font_Descriptor *gl_fontsize; static Fl_Font_Descriptor *gl_fontsize;
#define GL_DRAW_USES_TEXTURES (defined(__APPLE__) && !__ppc__) // 1 only for non-PPC OSX
#ifndef __APPLE__ #ifndef __APPLE__
# define USE_OksiD_style_GL_font_selection 1 // Most hosts except OSX # define USE_OksiD_style_GL_font_selection 1 // Most hosts except OSX
#else
# undef USE_OksiD_style_GL_font_selection // OSX
#endif #endif
#if USE_XFT #if USE_XFT
@@ -70,7 +67,7 @@ static Fl_Font_Descriptor *gl_fontsize;
void gl_font(int fontid, int size) { void gl_font(int fontid, int size) {
fl_font(fontid, size); fl_font(fontid, size);
Fl_Font_Descriptor *fl_fontsize = fl_graphics_driver->font_descriptor(); Fl_Font_Descriptor *fl_fontsize = fl_graphics_driver->font_descriptor();
#if !GL_DRAW_USES_TEXTURES #ifndef __APPLE__
if (!fl_fontsize->listbase) { if (!fl_fontsize->listbase) {
#ifdef USE_OksiD_style_GL_font_selection #ifdef USE_OksiD_style_GL_font_selection
@@ -97,28 +94,12 @@ void gl_font(int fontid, int size) {
fl_fontsize->listbase = glGenLists(256); fl_fontsize->listbase = glGenLists(256);
wglUseFontBitmaps(fl_gc, base, count, fl_fontsize->listbase+base); wglUseFontBitmaps(fl_gc, base, count, fl_fontsize->listbase+base);
SelectObject(fl_gc, oldFid); SelectObject(fl_gc, oldFid);
# elif defined(__APPLE_QUARTZ__)
//AGL is not supported for use in 64-bit applications:
//http://developer.apple.com/mac/library/documentation/Carbon/Conceptual/Carbon64BitGuide/OtherAPIChanges/OtherAPIChanges.html
short font, face, size;
uchar fn[256];
const char *pname = Fl::get_font_name(fontid, NULL);
fn[0]=strlen(pname);
strcpy((char*)(fn+1), pname);
GetFNum(fn, &font);
face = 0;
size = fl_fontsize->size;
fl_fontsize->listbase = glGenLists(256);
aglUseFont(aglGetCurrentContext(), font, face,
size, 0, 256, fl_fontsize->listbase);
# else
# error unsupported platform
# endif # endif
#endif // USE_OksiD_style_GL_font_selection #endif // USE_OksiD_style_GL_font_selection
} }
glListBase(fl_fontsize->listbase); glListBase(fl_fontsize->listbase);
#endif // !GL_DRAW_USES_TEXTURES #endif // !__APPLE__
gl_fontsize = fl_fontsize; gl_fontsize = fl_fontsize;
} }
@@ -143,8 +124,6 @@ static void get_list(int r) {
HFONT oldFid = (HFONT)SelectObject(fl_gc, gl_fontsize->fid); HFONT oldFid = (HFONT)SelectObject(fl_gc, gl_fontsize->fid);
wglUseFontBitmapsW(fl_gc, ii, ii + 0x03ff, gl_fontsize->listbase+ii); wglUseFontBitmapsW(fl_gc, ii, ii + 0x03ff, gl_fontsize->listbase+ii);
SelectObject(fl_gc, oldFid); SelectObject(fl_gc, oldFid);
#elif defined(__APPLE_QUARTZ__)
// handled by textures
#else #else
# error unsupported platform # error unsupported platform
#endif #endif
@@ -189,7 +168,7 @@ void gl_remove_displaylist_fonts()
#endif #endif
} }
#if GL_DRAW_USES_TEXTURES #if __APPLE__
static void gl_draw_textures(const char* str, int n); static void gl_draw_textures(const char* str, int n);
#endif #endif
@@ -200,13 +179,7 @@ static void gl_draw_textures(const char* str, int n);
*/ */
void gl_draw(const char* str, int n) { void gl_draw(const char* str, int n) {
#ifdef __APPLE__ #ifdef __APPLE__
#if GL_DRAW_USES_TEXTURES
gl_draw_textures(str, n); gl_draw_textures(str, n);
#else
glCallLists(n, GL_UNSIGNED_BYTE, str);
#endif
#else #else
static xchar *buf = NULL; static xchar *buf = NULL;
static int l = 0; static int l = 0;
@@ -284,11 +257,13 @@ void gl_draw(
const char* str, // the (multi-line) string const char* str, // the (multi-line) string
int x, int y, int w, int h, // bounding box int x, int y, int w, int h, // bounding box
Fl_Align align) { Fl_Align align) {
fl_draw(str, x, -y-h, w, h, align, gl_draw_invert); fl_draw(str, x, -y-h, w, h, align, gl_draw_invert, NULL, 0);
} }
/** Measure how wide and tall the string will be when drawn by the gl_draw() function */ /** Measure how wide and tall the string will be when drawn by the gl_draw() function */
void gl_measure(const char* str, int& x, int& y) {fl_measure(str,x,y);} void gl_measure(const char* str, int& x, int& y) {
fl_measure(str,x,y,0);
}
/** /**
Outlines the given rectangle with the current color. Outlines the given rectangle with the current color.
@@ -350,9 +325,9 @@ void gl_draw_image(const uchar* b, int x, int y, int w, int h, int d, int ld) {
glDrawPixels(w,h,d<4?GL_RGB:GL_RGBA,GL_UNSIGNED_BYTE,(const ulong*)b); glDrawPixels(w,h,d<4?GL_RGB:GL_RGBA,GL_UNSIGNED_BYTE,(const ulong*)b);
} }
#if GL_DRAW_USES_TEXTURES || defined(FL_DOXYGEN) #if __APPLE__ || defined(FL_DOXYGEN)
#include <FL/glu.h> #include <FL/glu.h> // for gluUnProject()
// manages a fifo pile of pre-computed string textures // manages a fifo pile of pre-computed string textures
class gl_texture_fifo { class gl_texture_fifo {
@@ -364,6 +339,7 @@ private:
Fl_Font_Descriptor *fdesc; // its font Fl_Font_Descriptor *fdesc; // its font
int width; // its width int width; // its width
int height; // its height int height; // its height
int scale; // 1 or 2 for low/high resolution
} data; } data;
data *fifo; // array of pile elements data *fifo; // array of pile elements
int size_; // pile height int size_; // pile height
@@ -408,14 +384,14 @@ void gl_texture_fifo::display_texture(int rank)
glMatrixMode (GL_MODELVIEW); glMatrixMode (GL_MODELVIEW);
glPushMatrix(); glPushMatrix();
glLoadIdentity (); glLoadIdentity ();
float winw = Fl_Window::current()->w(); float winw = gl_scale * Fl_Window::current()->w();
float winh = Fl_Window::current()->h(); float winh = gl_scale * Fl_Window::current()->h();
glScalef (2.0f / winw, 2.0f / winh, 1.0f); glScalef (2.0f / winw, 2.0f / winh, 1.0f);
glTranslatef (-winw / 2.0f, -winh / 2.0f, 0.0f); glTranslatef (-winw / 2.0f, -winh / 2.0f, 0.0f);
//write the texture on screen //write the texture on screen
GLfloat pos[4]; GLfloat pos[4];
glGetFloatv(GL_CURRENT_RASTER_POSITION, pos); glGetFloatv(GL_CURRENT_RASTER_POSITION, pos);
CGRect bounds = CGRectMake (pos[0], pos[1] - fl_descent(), fifo[rank].width, fifo[rank].height); CGRect bounds = CGRectMake (pos[0], pos[1] - gl_scale*fl_descent(), fifo[rank].width, fifo[rank].height);
// GL_COLOR_BUFFER_BIT for glBlendFunc, GL_ENABLE_BIT for glEnable / glDisable // GL_COLOR_BUFFER_BIT for glBlendFunc, GL_ENABLE_BIT for glEnable / glDisable
glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT); glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT);
@@ -471,6 +447,9 @@ int gl_texture_fifo::compute_texture(const char* str, int n)
fifo[current].utf8[n] = 0; fifo[current].utf8[n] = 0;
fifo[current].width = 0, fifo[current].height = 0; fifo[current].width = 0, fifo[current].height = 0;
fl_measure(fifo[current].utf8, fifo[current].width, fifo[current].height, 0); fl_measure(fifo[current].utf8, fifo[current].width, fifo[current].height, 0);
fifo[current].width *= gl_scale;
fifo[current].height *= gl_scale;
fifo[current].scale = gl_scale;
CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB(); CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB();
void *base = calloc(4*fifo[current].width, fifo[current].height); void *base = calloc(4*fifo[current].width, fifo[current].height);
if (base == NULL) return -1; if (base == NULL) return -1;
@@ -481,8 +460,10 @@ int gl_texture_fifo::compute_texture(const char* str, int n)
GLfloat colors[4]; GLfloat colors[4];
glGetFloatv(GL_CURRENT_COLOR, colors); glGetFloatv(GL_CURRENT_COLOR, colors);
fl_color((uchar)(colors[0]*255), (uchar)(colors[1]*255), (uchar)(colors[2]*255)); fl_color((uchar)(colors[0]*255), (uchar)(colors[1]*255), (uchar)(colors[2]*255));
fl_draw(str, n, 0, fifo[current].height - fl_descent()); CGContextTranslateCTM(fl_gc, 0, fifo[current].height - gl_scale*fl_descent());
//put this bitmap in a texture CGContextScaleCTM(fl_gc, gl_scale, gl_scale);
fl_draw(str, n, 0, 0);
//put this bitmap in a texture
glPushAttrib(GL_TEXTURE_BIT); glPushAttrib(GL_TEXTURE_BIT);
glBindTexture (GL_TEXTURE_RECTANGLE_EXT, fifo[current].texName); glBindTexture (GL_TEXTURE_RECTANGLE_EXT, fifo[current].texName);
glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -502,7 +483,7 @@ int gl_texture_fifo::already_known(const char *str, int n)
int rank; int rank;
for ( rank = 0; rank <= last; rank++) { for ( rank = 0; rank <= last; rank++) {
if ( memcmp(str, fifo[rank].utf8, n) == 0 && fifo[rank].utf8[n] == 0 && if ( memcmp(str, fifo[rank].utf8, n) == 0 && fifo[rank].utf8[n] == 0 &&
fifo[rank].fdesc == gl_fontsize) return rank; fifo[rank].fdesc == gl_fontsize && fifo[rank].scale == gl_scale) return rank;
} }
return -1; return -1;
} }
@@ -512,6 +493,8 @@ static gl_texture_fifo *gl_fifo = NULL; // points to the texture pile class inst
// draws a utf8 string using pre-computed texture if available // draws a utf8 string using pre-computed texture if available
static void gl_draw_textures(const char* str, int n) static void gl_draw_textures(const char* str, int n)
{ {
gl_scale = Fl_X::resolution_scaling_factor(Fl_Window::current());
//fprintf(stderr,"gl_scale=%d\n",gl_scale);
if (! gl_fifo) gl_fifo = new gl_texture_fifo(); if (! gl_fifo) gl_fifo = new gl_texture_fifo();
if (!gl_fifo->textures_generated) { if (!gl_fifo->textures_generated) {
for (int i = 0; i < gl_fifo->size_; i++) glGenTextures (1, &(gl_fifo->fifo[i].texName)); for (int i = 0; i < gl_fifo->size_; i++) glGenTextures (1, &(gl_fifo->fifo[i].texName));
@@ -553,17 +536,9 @@ void gl_texture_pile_height(int max)
/** @} */ /** @} */
#elif defined(__APPLE__)
// used only if __ppc__
int gl_texture_pile_height(void) {return 0;}
void gl_texture_pile_height(int max) {}
#endif // GL_DRAW_USES_TEXTURES
#if defined(__APPLE__)
void gl_texture_reset() void gl_texture_reset()
{ {
#if GL_DRAW_USES_TEXTURES
if (gl_fifo) gl_texture_pile_height(gl_texture_pile_height()); if (gl_fifo) gl_texture_pile_height(gl_texture_pile_height());
#endif // GL_DRAW_USES_TEXTURES
} }
#endif // __APPLE__ #endif // __APPLE__
+4 -3
View File
@@ -48,6 +48,7 @@ static Fl_Gl_Choice* gl_choice;
#ifdef __APPLE__ #ifdef __APPLE__
static Fl_Gl_Choice* gl_choice; static Fl_Gl_Choice* gl_choice;
extern void gl_context_update(NSOpenGLContext*);
#endif #endif
Fl_Region XRectangleRegion(int x, int y, int w, int h); // in fl_rect.cxx Fl_Region XRectangleRegion(int x, int y, int w, int h); // in fl_rect.cxx
@@ -61,14 +62,15 @@ void gl_start() {
if (!gl_choice) Fl::gl_visual(0); if (!gl_choice) Fl::gl_visual(0);
context = fl_create_gl_context(Fl_Window::current(), gl_choice); context = fl_create_gl_context(Fl_Window::current(), gl_choice);
#elif defined(__APPLE_QUARTZ__) #elif defined(__APPLE_QUARTZ__)
// warning: the Quartz version should probably use Core GL (CGL) instead of AGL
context = fl_create_gl_context(Fl_Window::current(), gl_choice); context = fl_create_gl_context(Fl_Window::current(), gl_choice);
#else #else
# error Unsupported platform # error Unsupported platform
#endif #endif
} }
fl_set_gl_context(Fl_Window::current(), context); fl_set_gl_context(Fl_Window::current(), context);
#if !defined(WIN32) && !defined(__APPLE__) #ifdef __APPLE__
gl_context_update(context); // supports window resizing
#elif !defined(WIN32)
glXWaitX(); glXWaitX();
#endif #endif
if (pw != Fl_Window::current()->w() || ph != Fl_Window::current()->h()) { if (pw != Fl_Window::current()->w() || ph != Fl_Window::current()->h()) {
@@ -110,7 +112,6 @@ int Fl::gl_visual(int mode, int *alist) {
#elif defined(WIN32) #elif defined(WIN32)
gl_choice = c; gl_choice = c;
#elif defined(__APPLE_QUARTZ__) #elif defined(__APPLE_QUARTZ__)
// warning: the Quartz version should probably use Core GL (CGL) instead of AGL
gl_choice = c; gl_choice = c;
#else #else
# error Unsupported platform # error Unsupported platform
+14 -4
View File
@@ -38,6 +38,9 @@
# include <dlfcn.h> # include <dlfcn.h>
# endif // HAVE_DLFCN_H # endif // HAVE_DLFCN_H
# define MAXWINDOWS 32 # define MAXWINDOWS 32
# ifdef __APPLE__
# include <FL/x.H>
# endif
static Fl_Glut_Window *windows[MAXWINDOWS+1]; static Fl_Glut_Window *windows[MAXWINDOWS+1];
static void (*glut_idle_func)() = 0; // global glut idle function static void (*glut_idle_func)() = 0; // global glut idle function
@@ -59,7 +62,7 @@ static int indraw;
void Fl_Glut_Window::draw() { void Fl_Glut_Window::draw() {
glut_window = this; glut_window = this;
indraw = 1; indraw = 1;
if (!valid()) {reshape(w(),h()); valid(1);} if (!valid()) {reshape(pixel_w(),pixel_h()); valid(1);}
display(); display();
indraw = 0; indraw = 0;
} }
@@ -70,7 +73,7 @@ void glutSwapBuffers() {
void Fl_Glut_Window::draw_overlay() { void Fl_Glut_Window::draw_overlay() {
glut_window = this; glut_window = this;
if (!valid()) {reshape(w(),h()); valid(1);} if (!valid()) {reshape(pixel_w(),pixel_h()); valid(1);}
overlaydisplay(); overlaydisplay();
} }
@@ -80,6 +83,13 @@ int Fl_Glut_Window::handle(int event) {
make_current(); make_current();
int ex = Fl::event_x(); int ex = Fl::event_x();
int ey = Fl::event_y(); int ey = Fl::event_y();
#ifdef __APPLE__
if (shown()) {
int factor = Fl_X::resolution_scaling_factor(this);
ex *= factor;
ey *= factor;
}
#endif
int button; int button;
switch (event) { switch (event) {
@@ -377,8 +387,8 @@ int glutGet(GLenum type) {
case GLUT_RETURN_ZERO: return 0; case GLUT_RETURN_ZERO: return 0;
case GLUT_WINDOW_X: return glut_window->x(); case GLUT_WINDOW_X: return glut_window->x();
case GLUT_WINDOW_Y: return glut_window->y(); case GLUT_WINDOW_Y: return glut_window->y();
case GLUT_WINDOW_WIDTH: return glut_window->w(); case GLUT_WINDOW_WIDTH: return glut_window->pixel_w();
case GLUT_WINDOW_HEIGHT: return glut_window->h(); case GLUT_WINDOW_HEIGHT: return glut_window->pixel_h();
case GLUT_WINDOW_PARENT: case GLUT_WINDOW_PARENT:
if (glut_window->parent()) if (glut_window->parent())
return ((Fl_Glut_Window *)(glut_window->parent()))->number; return ((Fl_Glut_Window *)(glut_window->parent()))->number;
+2 -1
View File
@@ -94,7 +94,7 @@ void cube_box::draw() {
lasttime = lasttime+speed; lasttime = lasttime+speed;
if (!valid()) { if (!valid()) {
glLoadIdentity(); glLoadIdentity();
glViewport(0,0,w(),h()); glViewport(0,0,pixel_w(),pixel_h());
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glFrustum(-1,1,-1,1,2,10000); glFrustum(-1,1,-1,1,2,10000);
glTranslatef(0,0,-10); glTranslatef(0,0,-10);
@@ -167,6 +167,7 @@ void print_cb(Fl_Widget *w, void *data)
// end of printing demo // end of printing demo
int main(int argc, char **argv) { int main(int argc, char **argv) {
Fl::use_high_res_GL(1);
makeform(argv[0]); makeform(argv[0]);
// added to demo printing // added to demo printing
form->begin(); form->begin();
+1
View File
@@ -768,6 +768,7 @@ void handlemenu(Fl_Widget*, void *value) {handlemenu(fl_intptr_t(value));}
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
Fl::use_high_res_GL(1);
// glutInit(&argc, argv); // this line removed for FLTK // glutInit(&argc, argv); // this line removed for FLTK
// create FLTK window: // create FLTK window:
+2 -1
View File
@@ -84,7 +84,7 @@ void shape_window::draw() {
valid(1); valid(1);
// printf("init\n"); // printf("init\n");
glLoadIdentity(); glLoadIdentity();
glViewport(0,0,w(),h()); glViewport(0,0,pixel_w(),pixel_h());
} }
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
glColor3f(.5,.6,.7); glColor3f(.5,.6,.7);
@@ -267,6 +267,7 @@ int arg(int, char **argv, int &i) {
int main(int argc, char **argv) { int main(int argc, char **argv) {
Fl::use_high_res_GL(1);
int i=0; int i=0;
if (Fl::args(argc,argv,i,arg) < argc) if (Fl::args(argc,argv,i,arg) < argc)
Fl::fatal("Options are:\n -2 = 2 windows\n -f = startup fullscreen\n%s",Fl::help); Fl::fatal("Options are:\n -2 = 2 windows\n -f = startup fullscreen\n%s",Fl::help);
+3 -2
View File
@@ -57,7 +57,7 @@ void shape_window::draw() {
if (!valid()) { if (!valid()) {
valid(1); valid(1);
glLoadIdentity(); glLoadIdentity();
glViewport(0,0,w(),h()); glViewport(0,0,pixel_w(),pixel_h());
} }
// draw an amazing but slow graphic: // draw an amazing but slow graphic:
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
@@ -78,7 +78,7 @@ void shape_window::draw_overlay() {
if (!valid()) { if (!valid()) {
valid(1); valid(1);
glLoadIdentity(); glLoadIdentity();
glViewport(0,0,w(),h()); glViewport(0,0,pixel_w(),pixel_h());
} }
// draw an amazing graphic: // draw an amazing graphic:
gl_color(FL_RED); gl_color(FL_RED);
@@ -108,6 +108,7 @@ void overlay_sides_cb(Fl_Widget *o, void *p) {
#include <stdio.h> #include <stdio.h>
int main(int argc, char **argv) { int main(int argc, char **argv) {
Fl::use_high_res_GL(1);
Fl_Window window(300, 370); Fl_Window window(300, 370);
shape_window sw(10, 75, window.w()-20, window.h()-90); shape_window sw(10, 75, window.w()-20, window.h()-90);
+1
View File
@@ -1416,6 +1416,7 @@ main(int argc, char **argv)
{ {
long i; long i;
Fl::use_high_res_GL(1);
glutInit(&argc, argv); glutInit(&argc, argv);
for (i = 1; i < argc; i++) { for (i = 1; i < argc; i++) {
if (argv[i][0] == '-') { if (argv[i][0] == '-') {
+2 -1
View File
@@ -45,7 +45,7 @@ void shape_window::draw() {
if (!valid()) { if (!valid()) {
valid(1); valid(1);
glLoadIdentity(); glLoadIdentity();
glViewport(0, 0, w(), h()); glViewport(0, 0, pixel_w(), pixel_h());
} }
// draw an amazing graphic: // draw an amazing graphic:
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
@@ -81,6 +81,7 @@ void sides_cb(Fl_Widget *o, void *p) {
int main(int argc, char **argv) { int main(int argc, char **argv) {
Fl::use_high_res_GL(1);
Fl_Window window(300, 330); Fl_Window window(300, 330);
// the shape window could be it's own window, but here we make it // the shape window could be it's own window, but here we make it