resizing offscreen drawable from 2nd thread
<frustrated>
OK I've hit my quota of reboots for the evening, so if anyone has ideas on this, help me out.
(init)
Thread 1:
* create NSWindow
* create NSOpenGLView subclass with context "ctx" and set it as the content view of the window
* setup "ctx", textures etc
* create offscreen NSWindow
* create regular NSView and set it as the content view
* create NSOpenGLContext "offctx" shared with "ctx" and set the view to the NSView
* setup "offctx", more textures
* make "ctx" current and create texture from "offctx" via createTexture: fromView internalFormat:
* init finished, spawn rendering loop on thread 2
(loop)
Thread 1:
* sit and wait for user input
Thread 2:
* render pretty things to "offctx"
* draw "offctx" texture to "ctx" to display result in the onscreen window
* repeat
-- up to this point, everything works. If you're familiar with multithreaded GL you know that getting to this point isn't easy, because resizing the window in Thread 1 while Thread 2 is rendering to "ctx" causes a kernel panic if you don't lock. But, the NSOpenGLView subclass has locks everywhere. I can resize, drag, minimize, toggle fullscreen, everything is OK.
(then... at some later time...)
Thread 1:
* keep waiting for user input
Thread 2:
* due to certain program events, decide to reshape the offscreen drawable to better fit content into the max texture size (i.e. from 512x1024 to 1280x512 or somesuch)
* [offwin setContentSize:thenewsize], this also resizes the content view
* make offctx current --still OK so far
* [offctx update]
KA BOOM, the window server freezes!!
OK, what gives? Except during init, Thread 1 *never* makes "offctx" current, it is only issued commands by Thread 2. The window is offscreen and should never receive any events from Thread 1.
Guh?!
</frustrated>
OK I've hit my quota of reboots for the evening, so if anyone has ideas on this, help me out.
(init)
Thread 1:
* create NSWindow
* create NSOpenGLView subclass with context "ctx" and set it as the content view of the window
* setup "ctx", textures etc
* create offscreen NSWindow
* create regular NSView and set it as the content view
* create NSOpenGLContext "offctx" shared with "ctx" and set the view to the NSView
* setup "offctx", more textures
* make "ctx" current and create texture from "offctx" via createTexture: fromView internalFormat:
* init finished, spawn rendering loop on thread 2
(loop)
Thread 1:
* sit and wait for user input
Thread 2:
* render pretty things to "offctx"
* draw "offctx" texture to "ctx" to display result in the onscreen window
* repeat
-- up to this point, everything works. If you're familiar with multithreaded GL you know that getting to this point isn't easy, because resizing the window in Thread 1 while Thread 2 is rendering to "ctx" causes a kernel panic if you don't lock. But, the NSOpenGLView subclass has locks everywhere. I can resize, drag, minimize, toggle fullscreen, everything is OK.
(then... at some later time...)
Thread 1:
* keep waiting for user input
Thread 2:
* due to certain program events, decide to reshape the offscreen drawable to better fit content into the max texture size (i.e. from 512x1024 to 1280x512 or somesuch)
* [offwin setContentSize:thenewsize], this also resizes the content view
* make offctx current --still OK so far
* [offctx update]
KA BOOM, the window server freezes!!
OK, what gives? Except during init, Thread 1 *never* makes "offctx" current, it is only issued commands by Thread 2. The window is offscreen and should never receive any events from Thread 1.
Guh?!
</frustrated>
Argh!
"The NSView class is generally thread-safe, with a few exceptions. You should create, destroy, resize, move, and perform other operations on NSView objects only from the main thread of an application."
"The NSView class is generally thread-safe, with a few exceptions. You should create, destroy, resize, move, and perform other operations on NSView objects only from the main thread of an application."
Wow, that's a lot more lenient than I was expecting.
My rule of thumb is, don't make calls that touch the UI from a secondary thread.
There's an easy way to get your invocation called from the main thread's event loop, from another thread, if that helps. Otherwise, I suggest PBuffers.
My rule of thumb is, don't make calls that touch the UI from a secondary thread.
There's an easy way to get your invocation called from the main thread's event loop, from another thread, if that helps. Otherwise, I suggest PBuffers.
"UI" is a misnomer here, everything is offscreen. It just happens to be an NSView. I'm using an offscreen window instead of a pbuffer because:
1) it's compatible with Jaguar
2) I don't require mipmaps
3) there's no API to resize a pbuffer after it is created
I tried invoking the drawable resizing bit via performSelectorOnMainThread: but it still hangs the window server.
1) it's compatible with Jaguar
2) I don't require mipmaps
3) there's no API to resize a pbuffer after it is created
I tried invoking the drawable resizing bit via performSelectorOnMainThread: but it still hangs the window server.
I'm not doing anything as hairy as you're doing, but my game is multithreaded with physics in a separate thread, and with graphics running off a timer ( VBL syncd ) on the main thread.
I've had a lot of situations where something happens in the physics thread that requires changes to be made to the OpenGL state, but obviously I can't just make calls directly. Well, apparently in some cases one can, but I don't feel like KP'ing my machine. So I worked out a queue system where the physics thread can enqueue a request to the drawing thread to perform some sort of action. The drawing thread just processes & flushes the request queue at every loop.
Could something like this help you?
My code is too specific to be generically applicable, but I think the *idea* is valid.
I've had a lot of situations where something happens in the physics thread that requires changes to be made to the OpenGL state, but obviously I can't just make calls directly. Well, apparently in some cases one can, but I don't feel like KP'ing my machine. So I worked out a queue system where the physics thread can enqueue a request to the drawing thread to perform some sort of action. The drawing thread just processes & flushes the request queue at every loop.
Could something like this help you?
My code is too specific to be generically applicable, but I think the *idea* is valid.
Did you remember to lock the second thread until the context had been resized?
@Tomorrow: I can't control the thread that the rendering is done on, because this is a plugin for PCSX and the emulation happens on the second thread as dictated by the app core.
Obviously certain events (window resizing) require synchronization of the two threads; but that is what locks are for.
@OSC: performSelectorOnMainThread:...waitUntilDone:YES should effectively block the second thread until the resize is complete, but the window server still hangs.
I don't get it, why is it acceptable for the window server to freeze? EVER?!
I will look at redoing this with pbuffers.
Obviously certain events (window resizing) require synchronization of the two threads; but that is what locks are for.
@OSC: performSelectorOnMainThread:...waitUntilDone:YES should effectively block the second thread until the resize is complete, but the window server still hangs.
I don't get it, why is it acceptable for the window server to freeze? EVER?!

I will look at redoing this with pbuffers.
Well, pbuffers don't work with multisampling in 10.3.7, so forget that.
Ah, welcome to the wonderful world of Apple OpenGL.
I'd just like to point out, for the record, that Apple's support for threading in OpenGL seems to be better than many other vendors' on other OSes...
I'd just like to point out, for the record, that Apple's support for threading in OpenGL seems to be better than many other vendors' on other OSes...
Sure, there are some nice things in Apple's GL-- like having a (mostly) up to date glext.h, some ATI<->nvidia extension cross breeding (APPLE_client_storage, APPLE_texture_range, APPLE_vertex_array_range, ARB_texture_env_crossbar, ATI_texture_env_combine3...), the multi-head/multi-vendor support, and a decent profiler for free.
But the threading drives me crazy. It's the one thing that sends me back ten years, rebooting every few minutes. I feel like I'm programming GS/OS.
But the threading drives me crazy. It's the one thing that sends me back ten years, rebooting every few minutes. I feel like I'm programming GS/OS.
Another two dozen reboots later: it looks like adding glFinish() before resizing the offscreen drawable avoids the window server freeze.
arekkusu Wrote:Another two dozen reboots later: it looks like adding glFinish() before resizing the offscreen drawable avoids the window server freeze.
I don't envy you
Possibly Related Threads...
| Thread: | Author | Replies: | Views: | Last Post | |
| Using an offscreen context as a texture | Bachus | 6 | 4,466 |
Aug 10, 2004 09:53 AM Last Post: Bachus |
|
| OS X glut window resizing bug | johnMG | 10 | 3,853 |
Nov 25, 2003 01:56 PM Last Post: AnotherJake |
|
| Help with NSOpenGL: Window resizing | Tycho | 2 | 2,860 |
Aug 13, 2003 09:46 PM Last Post: Tycho |
|

