[patch] OS X carbon SDL_WINDOWID support

I’ve been working with embedding SDL in a cross-platform application for
video playback using the SDL_WINDOWID hack. On OS X my application is
Carbon-based so I made a few changes to support this. Sorry that this
is based on 1.2.11, but I was unaware of the 1.3 work when I began this
a while ago. Apple’s documentation is lacking so I’ve had to use a
lot of trial and error to get this to work. Also I must excuse myself
for not being a real mac developer.

To use this feature, set these environment variables like this example
before calling SDL_SetVideoMode() :
SDL_WINDOWID=12345234 (your carbon WindowRef cast to a long)
SDL_VIDEO_WINDOW_POS=100,200 (x and y position of the origin,
specified relative to the top-left of the carbon window)
IMHO it would be better if SDL environment variable “hacks” were
promoted to full-fledged API features (but i wanted to remain consistent
with what’s there now). Is that in the plans for 1.3?

My app is able to successfully do this once, show some video, then reset
SDL_VIDEO_WINDOW_POS to a different origin and call SDL_SetVideoMode()
again to reposition the origin on the same SDL_WINDOWID. I have not
tested changing SDL_WINDOWID between calls to SDL_SetVideoMode().

Note that with this patch, if an external window is being specified, SDL
will no longer close it since it doesn’t own it. I’ve attempted to make
this the case also for the alternative SDL_NSWindowPointer hack (for
embedding SDL video in a cocoa window) since this seems to be the right
thing to do in either case, but maybe it would be better not to change
the behavior in that case in case some apps might expect the existing
behavior (seems like a bug to me though). That would be a simple matter
of omitting the first instance of
qz_window_should_be_closed = FALSE;

Also note that this has so far only been tested on OS 10.4. The
underlying carbon/cocoa integration support may be missing in older OS X
versions.

On a related topic, I’ve found what I think is a bug in the thread code
for OS X. My application creates threads, and I see scary run-time
warnings in stderr about leaking of various cocoa objects that were
allocated in those threads. According to Apple, "If you are making
Cocoa calls outside of the Application Kit’s main thread, however, you
need to create your own autorelease pool. This is the case if you are a
Foundation-only application or if you detach a thread."
http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/Concepts/AutoreleasePools.html
I find that calling the following code from my newly created thread
fixes the leaking warnings:
NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];
Then when the thread is being destroyed we should release the pool:
[pool release];
I believe that SDL should be doing these things in its thread creation
and destruction code, but I’m not sure where the right place is to put this.

I hope this is useful to others.

thanks
earl

-------------- next part --------------
A non-text attachment was scrubbed…
Name: SDL.diff
Type: text/x-patch
Size: 7133 bytes
Desc: not available
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20060922/911e13ca/attachment.bin

On a related topic, I’ve found what I think is a bug in the thread code
for OS X. My application creates threads, and I see scary run-time
warnings in stderr about leaking of various cocoa objects that were
allocated in those threads. According to Apple, "If you are making
Cocoa calls outside of the Application Kit’s main thread, however, you
need to create your own autorelease pool. This is the case if you are a
Foundation-only application or if you detach a thread."
http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/Concepts/AutoreleasePools.html
I find that calling the following code from my newly created thread
fixes the leaking warnings:
NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];
Then when the thread is being destroyed we should release the pool:
[pool release];
I believe that SDL should be doing these things in its thread creation
and destruction code, but I’m not sure where the right place is to put this.

That’s really not how you want to do it, unless the threads are short
lived. The idiom for maintaining NSAutoreleasePool is that you should
release them periodically, the main thread does this after each
iteration of the event loop for example. Otherwise you’re effectively
leaking memory for the lifetime of the thread.

What you’re seeing means one of two things: you’re either doing
something that you shouldn’t, or SDL isn’t guaranteeing an
NSAutoreleasePool in the safe-for-alternate-thread functions where it
happens to use Objective-C. Only the latter should be patched, but
someone would have to track down exactly where this is happening (the
stderr spew should say which function to set a breakpoint on).

-bobOn 9/22/06, earl wrote:

IMHO it would be better if SDL environment variable “hacks” were
promoted to full-fledged API features (but i wanted to remain consistent
with what’s there now). Is that in the plans for 1.3?

Yes, I haven’t tested it yet, just getting everything working in SDL’s
window creation code first, but the framework is theoretically there in 1.3.

See ya,
-Sam Lantinga, Senior Software Engineer, Blizzard Entertainment

Hi Bob,

That’s really not how you want to do it, unless the threads are short
lived. The idiom for maintaining NSAutoreleasePool is that you should
release them periodically, the main thread does this after each
iteration of the event loop for example. Otherwise you’re effectively
leaking memory for the lifetime of the thread.

Thanks for setting me straight on this. I am not a cocoa developer.

What you’re seeing means one of two things: you’re either doing
something that you shouldn’t, or SDL isn’t guaranteeing an
NSAutoreleasePool in the safe-for-alternate-thread functions where it
happens to use Objective-C.

The SDL FAQ reminds us that “most graphics back-ends are not
thread-safe”. However it should be OK to call SDL video functions
strictly from a single thread even if that thread is not the main thread
of an application, right?

Other than leaking these cocoa objects, calling SDL video functions from
a single thread is working flawlessly for me on Windows, Linux/X11, and
OS X. This lack of an autorelease pool for the Quartz video code is the
only SDL bug I’m having to work around. Perhaps this could be fixed in
SDL, even though it doesn’t change the fact that you shouldn’t call SDL
video functions from multiple threads.

Only the latter should be patched, but
someone would have to track down exactly where this is happening (the
stderr spew should say which function to set a breakpoint on).

For the record, here’s a trivial test program followed by the errors
(without the timestamps printed on each line). Unfortunately the errors
don’t reveal source code line numbers.

#include <SDL.h>
int test_thread(void*data)
{
SDL_SetVideoMode(100, 200, 0,

SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL|SDL_NOFRAME|SDL_RESIZABLE);
return 0;
}
int main(int argc, char* argv[]) {
SDL_Init (SDL_INIT_VIDEO);
SDL_CreateThread(test_thread, NULL);
SDL_Delay(1000); /* crudely wait for the thread to finish */
}

*** _NSAutoreleaseNoPool(): Object 0x11137a0 of class NSCFNumber
autoreleased with no pool in place - just leaking
*** _NSAutoreleaseNoPool(): Object 0x112c360 of class NSView
autoreleased with no pool in place - just leaking
*** _NSAutoreleaseNoPool(): Object 0x112cd60 of class
SDL_QuartzWindowDelegate autoreleased with no pool in place - just leaking
*** _NSAutoreleaseNoPool(): Object 0x112e310 of class NSIdEnumerator
autoreleased with no pool in place - just leaking
*** _NSAutoreleaseNoPool(): Object 0xa3712254 of class NSCFString
autoreleased with no pool in place - just leaking
*** _NSAutoreleaseNoPool(): Object 0x1111440 of class NSCFArray
autoreleased with no pool in place - just leaking
*** _NSAutoreleaseNoPool(): Object 0x1133670 of class NSView
autoreleased with no pool in place - just leaking
*** _NSAutoreleaseNoPool(): Object 0x1133670 of class NSView
autoreleased with no pool in place - just leaking

A non-trivial application using other SDL video functions in the thread
will produce errors about other leaked objects as well.

thanks
earlOn 9/22/06,Bob Ippolito wrote:

earl wrote:

The SDL FAQ reminds us that “most graphics back-ends are not
thread-safe”. However it should be OK to call SDL video functions
strictly from a single thread even if that thread is not the main thread
of an application, right?

No. Many windowing systems explicitly require to be called only from the
main thread. At least that used to be the case with Cocoa, as far as I
remember, though it seems that the restriction has been somewhat
weakened in recent versions. See
http://developer.apple.com/documentation/Cocoa/Conceptual/Multithreading/articles/CocoaSafety.html
for details about what you can and can’t do from non-main threads.

-Christian

Christian wrote:

earl wrote:

The SDL FAQ reminds us that “most graphics back-ends are not
thread-safe”. However it should be OK to call SDL video functions
strictly from a single thread even if that thread is not the main thread
of an application, right?

No. Many windowing systems explicitly require to be called only from the
main thread. At least that used to be the case with Cocoa, as far as I
remember, though it seems that the restriction has been somewhat
weakened in recent versions. See

http://developer.apple.com/documentation/Cocoa/Conceptual/Multithreading/articles/CocoaSafety.html

for details about what you can and can’t do from non-main threads.

Thanks very much for pointing out this documentation and saving me from
making a big mistake. My application is being reworked now to keep all
the SDL video function calls in the main thread.

I took the liberty of adding a note about this to the FAQ:
http://www.libsdl.org/cgi/docwiki.cgi/FAQ_20Function_20calls_20from_20multiple_20threads
Just out of curiosity, does anyone know any good references for why
calling SDL video functions from a non-main thread is forbidden on other
platforms? If so I’d like to add those references to the FAQ too.

Regardless of this discussion about threads, I’m still very interested
in feedback from anyone who tries out the carbon SDL_WINDOWID patch.
Can I do anything to help get it accepted into SVN?

thanks
Earl Levine