mirror of
https://github.com/fltk/fltk.git
synced 2026-05-26 10:07:06 +08:00
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:
@@ -125,6 +125,9 @@ typedef void (*Fl_Clipboard_Notify_Handler)(int source, void *data);
|
||||
class FL_EXPORT Fl {
|
||||
Fl() {}; // no constructor!
|
||||
|
||||
private:
|
||||
static int use_high_res_GL_;
|
||||
|
||||
public: // should be private!
|
||||
#ifndef FL_DOXYGEN
|
||||
static int e_number;
|
||||
@@ -1206,6 +1209,16 @@ public:
|
||||
static void release_widget_pointer(Fl_Widget *&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
|
||||
/** \defgroup group_cairo Cairo support functions and classes
|
||||
|
||||
+21
-2
@@ -89,7 +89,7 @@ public:
|
||||
\code
|
||||
void mywindow::draw() {
|
||||
if (!valid()) {
|
||||
glViewport(0,0,w(),h());
|
||||
glViewport(0,0,pixel_w(),pixel_h());
|
||||
glFrustum(...);
|
||||
...other initialization...
|
||||
}
|
||||
@@ -168,7 +168,8 @@ public:
|
||||
int mode(int a) {return mode(a,0);}
|
||||
/** See Fl_Mode mode() const */
|
||||
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(void*, int destroy_flag = 0);
|
||||
void make_current();
|
||||
@@ -201,6 +202,24 @@ public:
|
||||
// Note: Doxygen docs in Fl_Widget.H to avoid redundancy.
|
||||
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();
|
||||
/**
|
||||
Creates a new Fl_Gl_Window widget using the given size, and label string.
|
||||
|
||||
@@ -74,8 +74,10 @@ typedef CGContextRef Fl_Offscreen;
|
||||
|
||||
#ifdef __OBJC__
|
||||
@class NSCursor;
|
||||
@class NSOpenGLPixelFormat;
|
||||
#else
|
||||
class NSCursor;
|
||||
class NSOpenGLPixelFormat;
|
||||
#endif // __OBJC__
|
||||
|
||||
typedef CGContextRef Fl_Offscreen;
|
||||
@@ -151,6 +153,8 @@ public:
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
|
||||
bool mapped_to_retina(); // is window 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
|
||||
// Quartz additions:
|
||||
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_end_image();
|
||||
// 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 map(void);
|
||||
void unmap(void);
|
||||
@@ -183,7 +189,8 @@ public:
|
||||
private:
|
||||
#if FLTK_ABI_VERSION >= 10304
|
||||
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
|
||||
bool subwindow; // for ABI compatibility, useless with true subwindows
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -2190,7 +2190,7 @@ Fl_Widget_Tracker::~Fl_Widget_Tracker()
|
||||
Fl::release_widget_pointer(wp_); // remove pointer from watch list
|
||||
}
|
||||
|
||||
|
||||
int Fl::use_high_res_GL_ = 0;
|
||||
//
|
||||
// End of "$Id$".
|
||||
//
|
||||
|
||||
+10
-6
@@ -51,10 +51,16 @@
|
||||
# include <FL/gl.h>
|
||||
# define GLContext HGLRC
|
||||
#elif defined(__APPLE_QUARTZ__)
|
||||
// warning: the Quartz version should probably use Core GL (CGL) instead of AGL
|
||||
# include <OpenGL/gl.h>
|
||||
# include <AGL/agl.h>
|
||||
# define GLContext AGLContext
|
||||
#ifdef __OBJC__
|
||||
@class NSOpenGLPixelFormat;
|
||||
@class NSOpenGLContext;
|
||||
#else
|
||||
class NSOpenGLPixelFormat;
|
||||
class NSOpenGLContext;
|
||||
#endif // __OBJC__
|
||||
typedef NSOpenGLContext* FLOpenGLContextPtr;
|
||||
# define GLContext FLOpenGLContextPtr
|
||||
#else
|
||||
# include <GL/glx.h>
|
||||
# define GLContext GLXContext
|
||||
@@ -70,8 +76,7 @@ public:
|
||||
int pixelformat; // the visual to use
|
||||
PIXELFORMATDESCRIPTOR pfd; // some wgl calls need this thing
|
||||
#elif defined(__APPLE_QUARTZ__)
|
||||
// warning: the Quartz version should probably use Core GL (CGL) instead of AGL
|
||||
AGLPixelFormat pixelformat;
|
||||
NSOpenGLPixelFormat* pixelformat;
|
||||
#else
|
||||
XVisualInfo *vis; // the visual to use
|
||||
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);
|
||||
|
||||
#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);
|
||||
|
||||
|
||||
+10
-104
@@ -28,8 +28,11 @@
|
||||
# include <FL/fl_utf8.h>
|
||||
|
||||
# ifdef __APPLE__
|
||||
# include <ApplicationServices/ApplicationServices.h>
|
||||
# include <FL/Fl_Window.H>
|
||||
extern NSOpenGLContext* gl_create_context_for_window(NSOpenGLPixelFormat *pixelformat,
|
||||
NSOpenGLContext *shared_ctx, Fl_Window *window);
|
||||
extern void gl_context_release(NSOpenGLContext*);
|
||||
extern void gl_context_makecurrent(NSOpenGLContext*);
|
||||
extern void gl_cleardrawable(void);
|
||||
# endif
|
||||
|
||||
# ifdef WIN32
|
||||
@@ -108,53 +111,7 @@ Fl_Gl_Choice *Fl_Gl_Choice::find(int m, const int *alistp) {
|
||||
}
|
||||
|
||||
#elif defined(__APPLE_QUARTZ__)
|
||||
// warning: the Quartz version should probably use Core GL (CGL) instead of AGL
|
||||
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);
|
||||
NSOpenGLPixelFormat* fmt = Fl_X::mode_to_NSOpenGLPixelFormat(m, alistp);
|
||||
if (!fmt) return 0;
|
||||
|
||||
#elif defined(WIN32)
|
||||
@@ -216,7 +173,6 @@ Fl_Gl_Choice *Fl_Gl_Choice::find(int m, const int *alistp) {
|
||||
g->pixelformat = pixelformat;
|
||||
g->pfd = chosen_pfd;
|
||||
# elif defined(__APPLE_QUARTZ__)
|
||||
// warning: the Quartz version should probably use Core GL (CGL) instead of AGL
|
||||
g->pixelformat = fmt;
|
||||
# else
|
||||
# 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__)
|
||||
#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 context, shared_ctx = 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;
|
||||
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);
|
||||
}
|
||||
# else
|
||||
@@ -337,23 +268,7 @@ void fl_set_gl_context(Fl_Window* w, GLContext context) {
|
||||
# elif defined(WIN32)
|
||||
wglMakeCurrent(Fl_X::i(w)->private_dc, context);
|
||||
# elif defined(__APPLE_QUARTZ__)
|
||||
// warning: the Quartz version should probably use Core GL (CGL) instead of AGL
|
||||
#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);
|
||||
gl_context_makecurrent(context);
|
||||
# else
|
||||
# error unsupported platform
|
||||
# endif
|
||||
@@ -368,15 +283,7 @@ void fl_no_gl_context() {
|
||||
# elif defined(WIN32)
|
||||
wglMakeCurrent(0, 0);
|
||||
# elif defined(__APPLE_QUARTZ__)
|
||||
// warning: the Quartz version should probably use Core GL (CGL) instead of AGL
|
||||
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);
|
||||
gl_cleardrawable();
|
||||
# else
|
||||
# error unsupported platform
|
||||
# endif
|
||||
@@ -389,8 +296,7 @@ void fl_delete_gl_context(GLContext context) {
|
||||
# elif defined(WIN32)
|
||||
wglDeleteContext(context);
|
||||
# elif defined(__APPLE_QUARTZ__)
|
||||
// warning: the Quartz version should probably use Core GL (CGL) instead of AGL
|
||||
aglDestroyContext( context );
|
||||
gl_context_release(context);
|
||||
# else
|
||||
# error unsupported platform
|
||||
# endif
|
||||
|
||||
@@ -53,10 +53,13 @@ static Fl_RGB_Image* capture_gl_rectangle(Fl_Gl_Window *glw, int x, int y, int w
|
||||
{
|
||||
#if defined(__APPLE__)
|
||||
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
|
||||
const int bytesperpixel = 3;
|
||||
#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.
|
||||
// For extra safety, save & restore OpenGL states that are changed
|
||||
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;
|
||||
mByteWidth = (mByteWidth + 3) & ~3; // Align to 4 bytes
|
||||
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__)
|
||||
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
#else
|
||||
@@ -85,6 +88,11 @@ static Fl_RGB_Image* capture_gl_rectangle(Fl_Gl_Window *glw, int x, int y, int w
|
||||
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
|
||||
was linked to the program
|
||||
@@ -97,7 +105,27 @@ public:
|
||||
Fl_Gl_Window *glw = w->as_gl_window();
|
||||
if (!glw) return 0;
|
||||
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;
|
||||
return 1;
|
||||
}
|
||||
|
||||
+53
-59
@@ -26,10 +26,12 @@ extern void gl_texture_reset();
|
||||
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/x.H>
|
||||
#include "Fl_Gl_Choice.H"
|
||||
#ifdef __APPLE__
|
||||
#include <FL/gl.h>
|
||||
extern void gl_context_update(NSOpenGLContext*);
|
||||
extern void gl_context_flushbuffer(NSOpenGLContext*);
|
||||
#endif
|
||||
#include "Fl_Gl_Choice.H"
|
||||
#include <FL/Fl_Gl_Window.H>
|
||||
#include <stdlib.h>
|
||||
#include <FL/fl_utf8.h>
|
||||
@@ -97,6 +99,20 @@ void Fl_Gl_Window::show() {
|
||||
#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
|
||||
equivalent to calling value(0).
|
||||
@@ -140,7 +156,6 @@ int Fl_Gl_Window::mode(int m, const int *a) {
|
||||
show();
|
||||
}
|
||||
#elif defined(__APPLE_QUARTZ__)
|
||||
// warning: the Quartz version should probably use Core GL (CGL) instead of AGL
|
||||
redraw();
|
||||
#else
|
||||
# error unsupported platform
|
||||
@@ -163,6 +178,14 @@ int Fl_Gl_Window::mode(int m, const int *a) {
|
||||
void Fl_Gl_Window::make_current() {
|
||||
// puts("Fl_Gl_Window::make_current()");
|
||||
// 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_) {
|
||||
mode_ &= ~NON_LOCAL_CONTEXT;
|
||||
context_ = fl_create_gl_context(this, g);
|
||||
@@ -170,26 +193,12 @@ void Fl_Gl_Window::make_current() {
|
||||
context_valid(0);
|
||||
#ifdef __APPLE__
|
||||
// resets the pile of string textures used to draw strings
|
||||
// necessary when the context is renewed
|
||||
gl_texture_reset();
|
||||
#endif
|
||||
}
|
||||
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 (fl_palette) {
|
||||
fl_GetDC(fl_xid(this));
|
||||
@@ -219,8 +228,8 @@ void Fl_Gl_Window::ortho() {
|
||||
GLint v[2];
|
||||
glGetIntegerv(GL_MAX_VIEWPORT_DIMS, v);
|
||||
glLoadIdentity();
|
||||
glViewport(w()-v[0], h()-v[1], v[0], v[1]);
|
||||
glOrtho(w()-v[0], w(), h()-v[1], h(), -1, 1);
|
||||
glViewport(pixel_w()-v[0], pixel_h()-v[1], v[0], v[1]);
|
||||
glOrtho(pixel_w()-v[0], pixel_w(), pixel_h()-v[1], pixel_h(), -1, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -244,7 +253,7 @@ void Fl_Gl_Window::swap_buffers() {
|
||||
// STR# 2944 [1]
|
||||
// Save matrixmode/proj/modelview/rasterpos before doing overlay.
|
||||
//
|
||||
int wo=w(), ho=h();
|
||||
int wo=pixel_w(), ho=pixel_h();
|
||||
GLint matrixmode;
|
||||
GLfloat pos[4];
|
||||
glGetIntegerv(GL_MATRIX_MODE, &matrixmode);
|
||||
@@ -270,8 +279,10 @@ void Fl_Gl_Window::swap_buffers() {
|
||||
glMatrixMode(matrixmode);
|
||||
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_);
|
||||
*/
|
||||
#else
|
||||
# error unsupported platform
|
||||
#endif
|
||||
@@ -290,19 +301,6 @@ void Fl_Gl_Window::flush() {
|
||||
uchar save_valid_f = valid_f_;
|
||||
#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)
|
||||
|
||||
// Draw into hardware overlay planes if they are damaged:
|
||||
@@ -383,22 +381,25 @@ void Fl_Gl_Window::flush() {
|
||||
glReadBuffer(GL_BACK);
|
||||
glDrawBuffer(GL_FRONT);
|
||||
glLoadIdentity();
|
||||
glViewport(0, 0, w(), h());
|
||||
glOrtho(0, w(), 0, h(), -1, 1);
|
||||
glViewport(0, 0, pixel_w(), pixel_h());
|
||||
glOrtho(0, pixel_w(), 0, pixel_h(), -1, 1);
|
||||
glRasterPos2i(0,0);
|
||||
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
|
||||
damage1_ = 0;
|
||||
|
||||
} else {
|
||||
damage1_ = damage();
|
||||
clear_damage(0xff); draw();
|
||||
swap_buffers();
|
||||
damage1_ = damage();
|
||||
clear_damage(0xff); draw();
|
||||
swap_buffers();
|
||||
}
|
||||
|
||||
}
|
||||
#ifdef __APPLE__
|
||||
gl_context_flushbuffer(context_);
|
||||
#endif
|
||||
|
||||
if (overlay==this && SWAP_TYPE != SWAP) { // fake overlay in front buffer
|
||||
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("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 (X != x() || Y != y() || W != w() || H != h()) aglUpdateContext(context_);
|
||||
#elif !defined(WIN32)
|
||||
if ((W != w() || H != h()) && !resizable() && overlay && overlay != this) {
|
||||
#if ! ( defined(__APPLE__) || defined(WIN32) )
|
||||
if (is_a_resize && !resizable() && overlay && overlay != this) {
|
||||
((Fl_Gl_Window*)overlay)->resize(0,0,W,H);
|
||||
}
|
||||
#endif
|
||||
|
||||
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
|
||||
using. This is a system-dependent structure, but it is portable to copy
|
||||
Sets a pointer to the GLContext that this window is using.
|
||||
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,
|
||||
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.
|
||||
@@ -540,18 +546,6 @@ void Fl_Gl_Window::draw() {
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
+189
-17
@@ -1107,7 +1107,10 @@ static void position_subwindows(Fl_Window *parent, BOOL is_a_move)
|
||||
NSRect rchild;
|
||||
Fl_Window *sub = [child getFl_Window];
|
||||
#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
|
||||
rchild.origin = NSMakePoint(pframe.origin.x + sub->x(), pframe.origin.y + parent->h() - (sub->h() + sub->y()));
|
||||
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
|
||||
Fl_X *flx = Fl_X::i(window);
|
||||
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 );
|
||||
if (previous != flx->mapped_to_retina()) flx->changed_resolution(true);
|
||||
// window needs redrawn when moving from low res to retina
|
||||
if ((!previous) && flx->mapped_to_retina()) {
|
||||
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() {
|
||||
#if FLTK_ABI_VERSION >= 10304
|
||||
return (bool)mapped_to_retina_;
|
||||
return mapped_to_retina_ & mapped_mask;
|
||||
#else
|
||||
return xidChildren != NULL;
|
||||
return (unsigned long)xidChildren & mapped_mask;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Fl_X::mapped_to_retina(bool b) {
|
||||
#if FLTK_ABI_VERSION >= 10304
|
||||
mapped_to_retina_ = b;
|
||||
if (b) mapped_to_retina_ |= mapped;
|
||||
else mapped_to_retina_ &= ~mapped;
|
||||
#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
|
||||
}
|
||||
|
||||
@@ -2162,20 +2194,21 @@ static FLTextInputContext* fltextinputcontext_instance = nil;
|
||||
cocoaKeyboardHandler(theEvent);
|
||||
BOOL handled;
|
||||
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];
|
||||
if ( (mods & NSShiftKeyMask) && (mods & NSCommandKeyMask) ) {
|
||||
s = [s uppercaseString]; // US keyboards return lowercase letter in s if cmd-shift-key is hit
|
||||
}
|
||||
[FLView prepareEtext:s];
|
||||
Fl::compose_state = 0;
|
||||
handled = Fl::handle(FL_KEYBOARD, [(FLWindow*)[theEvent window] getFl_Window]);
|
||||
handled = Fl::handle(FL_KEYBOARD, w);
|
||||
}
|
||||
else {
|
||||
in_key_event = YES;
|
||||
need_handle = NO;
|
||||
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;
|
||||
}
|
||||
fl_unlock_function();
|
||||
@@ -2238,8 +2271,13 @@ static FLTextInputContext* fltextinputcontext_instance = nil;
|
||||
Fl::first_window(window);
|
||||
cocoaKeyboardHandler(theEvent);
|
||||
in_key_event = YES;
|
||||
need_handle = NO;
|
||||
[self fl_handle_keydown_event:theEvent];
|
||||
if (window->as_gl_window() && Fl::focus() == window ) { // ignore text input methods for GL windows
|
||||
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);
|
||||
in_key_event = NO;
|
||||
fl_unlock_function();
|
||||
@@ -2588,6 +2626,125 @@ static FLTextInputContext* fltextinputcontext_instance = nil;
|
||||
}
|
||||
@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() {
|
||||
_set_fullscreen();
|
||||
/* 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()
|
||||
{
|
||||
if (through_drawRect || w->as_gl_window()) {
|
||||
make_current_counts = 1;
|
||||
w->flush();
|
||||
make_current_counts = 0;
|
||||
Fl_X::q_release_context();
|
||||
if (through_drawRect) {
|
||||
if (w->as_gl_window()) {
|
||||
w->flush();
|
||||
} else {
|
||||
make_current_counts = 1;
|
||||
w->flush();
|
||||
make_current_counts = 0;
|
||||
Fl_X::q_release_context();
|
||||
}
|
||||
return;
|
||||
}
|
||||
// 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;
|
||||
[view setNeedsDisplay:YES];
|
||||
// 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 (w->parent()) x->mapped_to_retina( w->top_window()->i->mapped_to_retina() );
|
||||
else x->mapped_to_retina(false);
|
||||
x->changed_resolution(false);
|
||||
#endif
|
||||
|
||||
NSRect crect;
|
||||
@@ -2781,6 +2943,11 @@ void Fl_X::make(Fl_Window* w)
|
||||
Fl_X::first = x;
|
||||
}
|
||||
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];
|
||||
[myview release];
|
||||
[cw setLevel:winlevel];
|
||||
@@ -2835,6 +3002,10 @@ void Fl_X::make(Fl_Window* w)
|
||||
FLWindow *pxid = fl_xid(w->top_window());
|
||||
[pxid makeFirstResponder:[pxid contentView]];
|
||||
} 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];
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
// 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_Device_Plugin *pi = (Fl_Device_Plugin*)pm.plugin("opengl.device.fltk.org");
|
||||
|
||||
+26
-51
@@ -36,9 +36,9 @@
|
||||
#include "Xutf8.h"
|
||||
#endif
|
||||
|
||||
#if USE_XFT
|
||||
//extern XFontStruct* fl_xxfont();
|
||||
#endif // USE_XFT
|
||||
#ifdef __APPLE__
|
||||
static int gl_scale = 1; // set to 2 for high resolution Fl_Gl_Window
|
||||
#endif
|
||||
|
||||
/** Returns the current font's 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;
|
||||
|
||||
#define GL_DRAW_USES_TEXTURES (defined(__APPLE__) && !__ppc__) // 1 only for non-PPC OSX
|
||||
#ifndef __APPLE__
|
||||
# define USE_OksiD_style_GL_font_selection 1 // Most hosts except OSX
|
||||
#else
|
||||
# undef USE_OksiD_style_GL_font_selection // OSX
|
||||
#endif
|
||||
|
||||
#if USE_XFT
|
||||
@@ -70,7 +67,7 @@ static Fl_Font_Descriptor *gl_fontsize;
|
||||
void gl_font(int fontid, int size) {
|
||||
fl_font(fontid, size);
|
||||
Fl_Font_Descriptor *fl_fontsize = fl_graphics_driver->font_descriptor();
|
||||
#if !GL_DRAW_USES_TEXTURES
|
||||
#ifndef __APPLE__
|
||||
if (!fl_fontsize->listbase) {
|
||||
|
||||
#ifdef USE_OksiD_style_GL_font_selection
|
||||
@@ -97,28 +94,12 @@ void gl_font(int fontid, int size) {
|
||||
fl_fontsize->listbase = glGenLists(256);
|
||||
wglUseFontBitmaps(fl_gc, base, count, fl_fontsize->listbase+base);
|
||||
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 // USE_OksiD_style_GL_font_selection
|
||||
}
|
||||
glListBase(fl_fontsize->listbase);
|
||||
#endif // !GL_DRAW_USES_TEXTURES
|
||||
#endif // !__APPLE__
|
||||
gl_fontsize = fl_fontsize;
|
||||
}
|
||||
|
||||
@@ -143,8 +124,6 @@ static void get_list(int r) {
|
||||
HFONT oldFid = (HFONT)SelectObject(fl_gc, gl_fontsize->fid);
|
||||
wglUseFontBitmapsW(fl_gc, ii, ii + 0x03ff, gl_fontsize->listbase+ii);
|
||||
SelectObject(fl_gc, oldFid);
|
||||
#elif defined(__APPLE_QUARTZ__)
|
||||
// handled by textures
|
||||
#else
|
||||
# error unsupported platform
|
||||
#endif
|
||||
@@ -189,7 +168,7 @@ void gl_remove_displaylist_fonts()
|
||||
#endif
|
||||
}
|
||||
|
||||
#if GL_DRAW_USES_TEXTURES
|
||||
#if __APPLE__
|
||||
static void gl_draw_textures(const char* str, int n);
|
||||
#endif
|
||||
|
||||
@@ -200,13 +179,7 @@ static void gl_draw_textures(const char* str, int n);
|
||||
*/
|
||||
void gl_draw(const char* str, int n) {
|
||||
#ifdef __APPLE__
|
||||
|
||||
#if GL_DRAW_USES_TEXTURES
|
||||
gl_draw_textures(str, n);
|
||||
#else
|
||||
glCallLists(n, GL_UNSIGNED_BYTE, str);
|
||||
#endif
|
||||
|
||||
#else
|
||||
static xchar *buf = NULL;
|
||||
static int l = 0;
|
||||
@@ -284,11 +257,13 @@ void gl_draw(
|
||||
const char* str, // the (multi-line) string
|
||||
int x, int y, int w, int h, // bounding box
|
||||
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 */
|
||||
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.
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
#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
|
||||
class gl_texture_fifo {
|
||||
@@ -364,6 +339,7 @@ private:
|
||||
Fl_Font_Descriptor *fdesc; // its font
|
||||
int width; // its width
|
||||
int height; // its height
|
||||
int scale; // 1 or 2 for low/high resolution
|
||||
} data;
|
||||
data *fifo; // array of pile elements
|
||||
int size_; // pile height
|
||||
@@ -408,14 +384,14 @@ void gl_texture_fifo::display_texture(int rank)
|
||||
glMatrixMode (GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity ();
|
||||
float winw = Fl_Window::current()->w();
|
||||
float winh = Fl_Window::current()->h();
|
||||
float winw = gl_scale * Fl_Window::current()->w();
|
||||
float winh = gl_scale * Fl_Window::current()->h();
|
||||
glScalef (2.0f / winw, 2.0f / winh, 1.0f);
|
||||
glTranslatef (-winw / 2.0f, -winh / 2.0f, 0.0f);
|
||||
//write the texture on screen
|
||||
GLfloat pos[4];
|
||||
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
|
||||
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].width = 0, 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();
|
||||
void *base = calloc(4*fifo[current].width, fifo[current].height);
|
||||
if (base == NULL) return -1;
|
||||
@@ -481,8 +460,10 @@ int gl_texture_fifo::compute_texture(const char* str, int n)
|
||||
GLfloat colors[4];
|
||||
glGetFloatv(GL_CURRENT_COLOR, colors);
|
||||
fl_color((uchar)(colors[0]*255), (uchar)(colors[1]*255), (uchar)(colors[2]*255));
|
||||
fl_draw(str, n, 0, fifo[current].height - fl_descent());
|
||||
//put this bitmap in a texture
|
||||
CGContextTranslateCTM(fl_gc, 0, fifo[current].height - gl_scale*fl_descent());
|
||||
CGContextScaleCTM(fl_gc, gl_scale, gl_scale);
|
||||
fl_draw(str, n, 0, 0);
|
||||
//put this bitmap in a texture
|
||||
glPushAttrib(GL_TEXTURE_BIT);
|
||||
glBindTexture (GL_TEXTURE_RECTANGLE_EXT, fifo[current].texName);
|
||||
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;
|
||||
for ( rank = 0; rank <= last; rank++) {
|
||||
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;
|
||||
}
|
||||
@@ -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
|
||||
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->textures_generated) {
|
||||
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()
|
||||
{
|
||||
#if GL_DRAW_USES_TEXTURES
|
||||
if (gl_fifo) gl_texture_pile_height(gl_texture_pile_height());
|
||||
#endif // GL_DRAW_USES_TEXTURES
|
||||
}
|
||||
#endif // __APPLE__
|
||||
|
||||
|
||||
+4
-3
@@ -48,6 +48,7 @@ static Fl_Gl_Choice* gl_choice;
|
||||
|
||||
#ifdef __APPLE__
|
||||
static Fl_Gl_Choice* gl_choice;
|
||||
extern void gl_context_update(NSOpenGLContext*);
|
||||
#endif
|
||||
|
||||
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);
|
||||
context = fl_create_gl_context(Fl_Window::current(), gl_choice);
|
||||
#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);
|
||||
#else
|
||||
# error Unsupported platform
|
||||
#endif
|
||||
}
|
||||
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();
|
||||
#endif
|
||||
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)
|
||||
gl_choice = c;
|
||||
#elif defined(__APPLE_QUARTZ__)
|
||||
// warning: the Quartz version should probably use Core GL (CGL) instead of AGL
|
||||
gl_choice = c;
|
||||
#else
|
||||
# error Unsupported platform
|
||||
|
||||
@@ -38,6 +38,9 @@
|
||||
# include <dlfcn.h>
|
||||
# endif // HAVE_DLFCN_H
|
||||
# define MAXWINDOWS 32
|
||||
# ifdef __APPLE__
|
||||
# include <FL/x.H>
|
||||
# endif
|
||||
static Fl_Glut_Window *windows[MAXWINDOWS+1];
|
||||
|
||||
static void (*glut_idle_func)() = 0; // global glut idle function
|
||||
@@ -59,7 +62,7 @@ static int indraw;
|
||||
void Fl_Glut_Window::draw() {
|
||||
glut_window = this;
|
||||
indraw = 1;
|
||||
if (!valid()) {reshape(w(),h()); valid(1);}
|
||||
if (!valid()) {reshape(pixel_w(),pixel_h()); valid(1);}
|
||||
display();
|
||||
indraw = 0;
|
||||
}
|
||||
@@ -70,7 +73,7 @@ void glutSwapBuffers() {
|
||||
|
||||
void Fl_Glut_Window::draw_overlay() {
|
||||
glut_window = this;
|
||||
if (!valid()) {reshape(w(),h()); valid(1);}
|
||||
if (!valid()) {reshape(pixel_w(),pixel_h()); valid(1);}
|
||||
overlaydisplay();
|
||||
}
|
||||
|
||||
@@ -80,6 +83,13 @@ int Fl_Glut_Window::handle(int event) {
|
||||
make_current();
|
||||
int ex = Fl::event_x();
|
||||
int ey = Fl::event_y();
|
||||
#ifdef __APPLE__
|
||||
if (shown()) {
|
||||
int factor = Fl_X::resolution_scaling_factor(this);
|
||||
ex *= factor;
|
||||
ey *= factor;
|
||||
}
|
||||
#endif
|
||||
int button;
|
||||
switch (event) {
|
||||
|
||||
@@ -377,8 +387,8 @@ int glutGet(GLenum type) {
|
||||
case GLUT_RETURN_ZERO: return 0;
|
||||
case GLUT_WINDOW_X: return glut_window->x();
|
||||
case GLUT_WINDOW_Y: return glut_window->y();
|
||||
case GLUT_WINDOW_WIDTH: return glut_window->w();
|
||||
case GLUT_WINDOW_HEIGHT: return glut_window->h();
|
||||
case GLUT_WINDOW_WIDTH: return glut_window->pixel_w();
|
||||
case GLUT_WINDOW_HEIGHT: return glut_window->pixel_h();
|
||||
case GLUT_WINDOW_PARENT:
|
||||
if (glut_window->parent())
|
||||
return ((Fl_Glut_Window *)(glut_window->parent()))->number;
|
||||
|
||||
+2
-1
@@ -94,7 +94,7 @@ void cube_box::draw() {
|
||||
lasttime = lasttime+speed;
|
||||
if (!valid()) {
|
||||
glLoadIdentity();
|
||||
glViewport(0,0,w(),h());
|
||||
glViewport(0,0,pixel_w(),pixel_h());
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glFrustum(-1,1,-1,1,2,10000);
|
||||
glTranslatef(0,0,-10);
|
||||
@@ -167,6 +167,7 @@ void print_cb(Fl_Widget *w, void *data)
|
||||
// end of printing demo
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
Fl::use_high_res_GL(1);
|
||||
makeform(argv[0]);
|
||||
// added to demo printing
|
||||
form->begin();
|
||||
|
||||
@@ -768,6 +768,7 @@ void handlemenu(Fl_Widget*, void *value) {handlemenu(fl_intptr_t(value));}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
Fl::use_high_res_GL(1);
|
||||
// glutInit(&argc, argv); // this line removed for FLTK
|
||||
|
||||
// create FLTK window:
|
||||
|
||||
+2
-1
@@ -84,7 +84,7 @@ void shape_window::draw() {
|
||||
valid(1);
|
||||
// printf("init\n");
|
||||
glLoadIdentity();
|
||||
glViewport(0,0,w(),h());
|
||||
glViewport(0,0,pixel_w(),pixel_h());
|
||||
}
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glColor3f(.5,.6,.7);
|
||||
@@ -267,6 +267,7 @@ int arg(int, char **argv, int &i) {
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
Fl::use_high_res_GL(1);
|
||||
int i=0;
|
||||
if (Fl::args(argc,argv,i,arg) < argc)
|
||||
Fl::fatal("Options are:\n -2 = 2 windows\n -f = startup fullscreen\n%s",Fl::help);
|
||||
|
||||
+3
-2
@@ -57,7 +57,7 @@ void shape_window::draw() {
|
||||
if (!valid()) {
|
||||
valid(1);
|
||||
glLoadIdentity();
|
||||
glViewport(0,0,w(),h());
|
||||
glViewport(0,0,pixel_w(),pixel_h());
|
||||
}
|
||||
// draw an amazing but slow graphic:
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
@@ -78,7 +78,7 @@ void shape_window::draw_overlay() {
|
||||
if (!valid()) {
|
||||
valid(1);
|
||||
glLoadIdentity();
|
||||
glViewport(0,0,w(),h());
|
||||
glViewport(0,0,pixel_w(),pixel_h());
|
||||
}
|
||||
// draw an amazing graphic:
|
||||
gl_color(FL_RED);
|
||||
@@ -108,6 +108,7 @@ void overlay_sides_cb(Fl_Widget *o, void *p) {
|
||||
#include <stdio.h>
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
Fl::use_high_res_GL(1);
|
||||
Fl_Window window(300, 370);
|
||||
|
||||
shape_window sw(10, 75, window.w()-20, window.h()-90);
|
||||
|
||||
@@ -1416,6 +1416,7 @@ main(int argc, char **argv)
|
||||
{
|
||||
long i;
|
||||
|
||||
Fl::use_high_res_GL(1);
|
||||
glutInit(&argc, argv);
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (argv[i][0] == '-') {
|
||||
|
||||
+2
-1
@@ -45,7 +45,7 @@ void shape_window::draw() {
|
||||
if (!valid()) {
|
||||
valid(1);
|
||||
glLoadIdentity();
|
||||
glViewport(0, 0, w(), h());
|
||||
glViewport(0, 0, pixel_w(), pixel_h());
|
||||
}
|
||||
// draw an amazing graphic:
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
@@ -81,6 +81,7 @@ void sides_cb(Fl_Widget *o, void *p) {
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
Fl::use_high_res_GL(1);
|
||||
Fl_Window window(300, 330);
|
||||
|
||||
// the shape window could be it's own window, but here we make it
|
||||
|
||||
Reference in New Issue
Block a user