Use -(NSGraphicsContext*)[NSWindow graphicsContext] to obtain the adequate

graphics context to draw to a window. This requires Mac OS 10.4.
The advantage is that it is possible for a secondary thread to call 
Fl_Window::make_current() without needing to create an autorelease pool.

We save the native graphics state, and also the state with origin at top. 
Fl_X::q_release_context() restores the graphics state twice to return to
the native state. This allows to use a single graphics context for a single
window and a single thread.

Under 10.3, we have to create a new NSGraphicsContext when Fl_Window::make_current()
is called directly, so that secondary threads cannot call Fl_Window::make_current() without
having created an autorelease pool.

git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@10816 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Manolo Gouy
2015-07-24 22:17:36 +00:00
parent 80402f622c
commit a3e48a4afd
2 changed files with 17 additions and 9 deletions
+2 -1
View File
@@ -361,8 +361,9 @@ void fl_begin_offscreen(Fl_Offscreen ctx) {
/** Quit sending drawing commands to the current offscreen buffer. /** Quit sending drawing commands to the current offscreen buffer.
*/ */
void fl_end_offscreen() { void fl_end_offscreen() {
Fl_X::q_release_context();
fl_pop_clip(); fl_pop_clip();
CGContextRestoreGState(fl_gc); // matches CGContextSaveGState in fl_begin_offscreen()
CGContextFlush(fl_gc);
if (stack_ix>0) if (stack_ix>0)
stack_ix--; stack_ix--;
else else
+15 -8
View File
@@ -3243,19 +3243,20 @@ void Fl_Window::resize(int X,int Y,int W,int H) {
The system sends the drawRect: message to the window's view after having prepared the current The system sends the drawRect: message to the window's view after having prepared the current
graphics context to draw to this view. Processing of drawRect: sets variable through_drawRect graphics context to draw to this view. Processing of drawRect: sets variable through_drawRect
to YES and calls handleUpdateEvent() that calls Fl_X::flush(). Fl_X::flush() sets through_Fl_X_flush to YES and calls handleUpdateEvent() that calls Fl_X::flush(). Fl_X::flush() sets through_Fl_X_flush
to YES and calls Fl_Window::flush() that calls Fl_Window::make_current() that only needs to to YES and calls Fl_Window::flush() that calls Fl_Window::make_current() that
identify the graphics port of the current graphics context. The window's draw() function is then executed. uses the window's graphics context. The window's draw() function is then executed.
2) At each round of the FLTK event loop. 2) At each round of the FLTK event loop.
Fl::flush() is called, that calls Fl_X::flush() on each window that needs drawing. Variable Fl::flush() is called, that calls Fl_X::flush() on each window that needs drawing. Variable
through_Fl_X_flush is set to YES. Fl_X::flush() locks the focus to the view and calls Fl_Window::flush() through_Fl_X_flush is set to YES. Fl_X::flush() locks the focus to the view and calls Fl_Window::flush()
that calls Fl_Window::make_current() which uses the current graphics context. that calls Fl_Window::make_current() which uses the window's graphics context.
Fl_Window::flush() then runs the window's draw() function. Fl_Window::flush() then runs the window's draw() function.
3) An FLTK application can call Fl_Window::make_current() at any time before it draws to a window. 3) An FLTK application can call Fl_Window::make_current() at any time before it draws to a window.
This occurs for instance in the idle callback function of the mandelbrot test program. Variable This occurs for instance in the idle callback function of the mandelbrot test program. Variable
through_Fl_X_flush is NO, so Fl_Window::make_current() creates a new graphics context adequate for through_Fl_X_flush is NO. Under Mac OS 10.4 and higher, the window's graphics context is obtained.
the window. Subsequent drawing requests go to this window. CAUTION: it's not possible to call Fl::wait(), Under Mac OS 10.3 a new graphics context adequate for the window is created.
Subsequent drawing requests go to this window. CAUTION: it's not possible to call Fl::wait(),
Fl::check() nor Fl::ready() while in the draw() function of a widget. Use an idle callback instead. Fl::check() nor Fl::ready() while in the draw() function of a widget. Use an idle callback instead.
*/ */
void Fl_Window::make_current() void Fl_Window::make_current()
@@ -3269,11 +3270,16 @@ void Fl_Window::make_current()
#endif #endif
current_ = this; current_ = this;
NSGraphicsContext *nsgc = through_Fl_X_flush ? [NSGraphicsContext currentContext] : NSGraphicsContext *nsgc;
[NSGraphicsContext graphicsContextWithWindow:fl_window]; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
if (fl_mac_os_version >= 100400)
nsgc = [fl_window graphicsContext]; // 10.4
else
#endif
nsgc = through_Fl_X_flush ? [NSGraphicsContext currentContext] : [NSGraphicsContext graphicsContextWithWindow:fl_window];
i->gc = (CGContextRef)[nsgc graphicsPort]; i->gc = (CGContextRef)[nsgc graphicsPort];
fl_gc = i->gc; fl_gc = i->gc;
CGContextSaveGState(fl_gc); // native context
// antialiasing must be deactivated because it applies to rectangles too // antialiasing must be deactivated because it applies to rectangles too
// and escapes even clipping!!! // and escapes even clipping!!!
// it gets activated when needed (e.g., draw text) // it gets activated when needed (e.g., draw text)
@@ -3327,6 +3333,7 @@ void Fl_X::q_release_context(Fl_X *x) {
if (x && x->gc!=fl_gc) return; if (x && x->gc!=fl_gc) return;
if (!fl_gc) return; if (!fl_gc) return;
CGContextRestoreGState(fl_gc); // KEEP IT: matches the CGContextSaveGState of make_current CGContextRestoreGState(fl_gc); // KEEP IT: matches the CGContextSaveGState of make_current
CGContextRestoreGState(fl_gc);
#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::set_high_resolution(false); Fl_X::set_high_resolution(false);
#endif #endif