View Full Version : shared context breaking FTGL texture fonts
akb825
2006.09.07, 04:54 PM
I've been trying to compile a version of SDL to have shared contexts so resizing the window/coming in and out of fullscreen won't destroy all the textures and display lists. I successfully got a version for OS X working, but unfortunately FTGL texture fonts seem to be somewhat broken. The problem is, characters that show up before the change won't ever show again. (I know the texture is still valid, since the quads it draws are white instead of the text color (black)) Other characters show up fine if brought up later. The one display list I used also shows up fine. Any help will be appreciated.
akb825
2006.09.07, 05:10 PM
I seem to have resolved the problem. Apparently the mere vibes of the board revealed the answer to me. ;) Though it's still somewhat of a mystery as to why this occurred. This seems to have arisen from not setting up the projection or modelview matrices or viewport before switching resolutions for my test. When I called my resize function for both contexts, it then worked.
Once I get the Windows build up and running, I can release the source modifications for all of you to use. Just a bit of FYI, in order to allow context sharing between fullscreen and windowed contexts, I had to specify fullscreen for the shared context. As a result, it will not be compatible with Jaguar under windowed mode if you so decided to build a Jaguar-compatible version.
OneSadCookie
2006.09.07, 06:29 PM
You do not have to specify full-screen for the windowed context to enable sharing. You do have to specify single renderer, no recovery, and display mask, however, tying it to a single screen. Plenty of examples on http://onesadcookie.com/ -- the GameShell source for example.
akb825
2006.09.07, 06:47 PM
I applied all those attributes, and the problem is it won't connect to a fullscreen context. Not supplying single render on either one seems to still work, though, for both windowed and fullscreen.
OneSadCookie
2006.09.07, 06:50 PM
To get a full-screen context, you must have all those attributes (if you don't, it may work on a machine with a single GPU, but won't on a machine with more than one). To get sharing between two contexts, they must have the same attributes in this regard. Again, see GameShell.
akb825
2006.09.07, 07:24 PM
Adding SingleRenderer to both contexts seems to break it. If I leave fullscreen in there, it breaks for both. If I just have SingleRenderer, it no longer works for fullscreen. It's quite strange, since I don't see that much difference from your example.
OneSadCookie
2006.09.07, 07:35 PM
Just to check, then -- Outnumbered (http://onesadcookie.com/Software/) does work for you, right? :)
Make sure you check your code on a PowerBook (which is where I had problems until I figured out the critical 3 attributes), and on a PowerMac or Mac Pro with two different graphics cards, before you trust it ;)
akb825
2006.09.07, 07:48 PM
It does work. Unfortunately, I don't have a PowerMac available with multiple graphics cards. :\ I'll have to look into it and see if I can find any other differences.
Edit: I don't suppose the order matters?
akb825
2006.09.07, 08:05 PM
In case it matters, here's the modified function.
int QZ_SetupOpenGL (_THIS, int bpp, Uint32 flags) {
NSOpenGLPixelFormatAttribute attr[32];
NSOpenGLPixelFormat *fmt;
int i = 0;
int colorBits = bpp;
/* if a GL library hasn't been loaded at this point, load the default. */
if (!this->gl_config.driver_loaded) {
if (QZ_GL_LoadLibrary(this, NULL) == -1)
return 0;
}
//Add a shared context on the first creation to make sure that the textures
//are preserved
if (!SDL_SharedContext || (sharedAccelerated && this->gl_config.accelerated <= 0) ||
(!sharedAccelerated && this->gl_config.accelerated > 0))
{
attr[i++] = NSOpenGLPFASingleRenderer;
attr[i++] = NSOpenGLPFAScreenMask;
attr[i++] = CGDisplayIDToOpenGLDisplayMask (display_id);
if (this->gl_config.accelerated > 0)
{
attr[i++] = NSOpenGLPFAAccelerated;
attr[i++] = NSOpenGLPFANoRecovery;
sharedAccelerated = TRUE;
}
else
sharedAccelerated = FALSE;
attr[i] = 0;
fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
SDL_SharedContext = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:NULL];
[fmt release];
}
if ( flags & SDL_FULLSCREEN ) {
attr[i++] = NSOpenGLPFAFullScreen;
}
/* In windowed mode, the OpenGL pixel depth must match device pixel depth */
else if ( colorBits != device_bpp ) {
colorBits = device_bpp;
}
attr[i++] = NSOpenGLPFAColorSize;
attr[i++] = colorBits;
attr[i++] = NSOpenGLPFADepthSize;
attr[i++] = this->gl_config.depth_size;
if ( this->gl_config.double_buffer ) {
attr[i++] = NSOpenGLPFADoubleBuffer;
}
if ( this->gl_config.stereo ) {
attr[i++] = NSOpenGLPFAStereo;
}
if ( this->gl_config.stencil_size != 0 ) {
attr[i++] = NSOpenGLPFAStencilSize;
attr[i++] = this->gl_config.stencil_size;
}
if ( (this->gl_config.accum_red_size +
this->gl_config.accum_green_size +
this->gl_config.accum_blue_size +
this->gl_config.accum_alpha_size) > 0 ) {
attr[i++] = NSOpenGLPFAAccumSize;
attr[i++] = this->gl_config.accum_red_size + this->gl_config.accum_green_size + this->gl_config.accum_blue_size + this->gl_config.accum_alpha_size;
}
if ( this->gl_config.multisamplebuffers != 0 ) {
attr[i++] = NSOpenGLPFASampleBuffers;
attr[i++] = this->gl_config.multisamplebuffers;
}
if ( this->gl_config.multisamplesamples != 0 ) {
attr[i++] = NSOpenGLPFASamples;
attr[i++] = this->gl_config.multisamplesamples;
}
if ( this->gl_config.accelerated > 0 ) {
attr[i++] = NSOpenGLPFAAccelerated;
attr[i++] = NSOpenGLPFANoRecovery;
}
attr[i++] = NSOpenGLPFASingleRenderer;
attr[i++] = NSOpenGLPFAScreenMask;
attr[i++] = CGDisplayIDToOpenGLDisplayMask (display_id);
attr[i] = 0;
fmt = [ [ NSOpenGLPixelFormat alloc ] initWithAttributes:attr ];
if (fmt == nil) {
SDL_SetError ("Failed creating OpenGL pixel format");
return 0;
}
gl_context = [ [ NSOpenGLContext alloc ] initWithFormat:fmt
shareContext:SDL_SharedContext];
// shareContext:nil];
[ fmt release ];
if (gl_context == nil) {
SDL_SetError ("Failed creating OpenGL context");
return 0;
}
/* Synchronize QZ_GL_SwapBuffers() to vertical retrace.
* (Apple's documentation is not completely clear about what this setting
* exactly does, IMHO - for a detailed explanation see
* http://lists.apple.com/archives/mac-opengl/2006/Jan/msg00080.html )
*/
if ( this->gl_config.swap_control >= 0 ) {
long value;
value = this->gl_config.swap_control;
[ gl_context setValues: &value forParameter: NSOpenGLCPSwapInterval ];
}
/*
* Wisdom from Apple engineer in reference to UT2003's OpenGL performance:
* "You are blowing a couple of the internal OpenGL function caches. This
* appears to be happening in the VAO case. You can tell OpenGL to up
* the cache size by issuing the following calls right after you create
* the OpenGL context. The default cache size is 16." --ryan.
*/
#ifndef GLI_ARRAY_FUNC_CACHE_MAX
#define GLI_ARRAY_FUNC_CACHE_MAX 284
#endif
#ifndef GLI_SUBMIT_FUNC_CACHE_MAX
#define GLI_SUBMIT_FUNC_CACHE_MAX 280
#endif
{
long cache_max = 64;
CGLContextObj ctx = [ gl_context cglContext ];
CGLSetParameter (ctx, GLI_SUBMIT_FUNC_CACHE_MAX, &cache_max);
CGLSetParameter (ctx, GLI_ARRAY_FUNC_CACHE_MAX, &cache_max);
}
/* End Wisdom from Apple Engineer section. --ryan. */
return 1;
}
BTW, SDL doesn't use SingleRenderer for their context.
OneSadCookie
2006.09.07, 08:10 PM
It's kinda hard to tell precisely what pixel formats you're going to end up with, that way... an actual dump of the attributes from the OpenGL profiler might be handy.
My recollection is that you don't need the single renderer thing unless you're sharing contexts. If you're sharing contexts, both contexts must have the same renderer, and the only way to ensure that is to tie it down to exactly one. I could be remembering wrongly there though :)
akb825
2006.09.07, 08:34 PM
In the test application I was using, the only settings change from the default were double buffered, an 8 bit stencil buffer, and hardware accelerated. BTW, Apple's NSOpenGLPixellFormat page says that SingleRenderer is generally not useful.
Edit: it also says that SingleRenderer is implied for fullscreen. I'm thinking it's only valid for fullscreen contexts that would want to span multiple screens.
arekkusu
2006.09.08, 12:23 AM
If you're sharing contexts, both contexts must have the same renderer, and the only way to ensure that is to tie it down to exactly one. I could be remembering wrongly there though :)
Yes, you can only share contexts if they have exactly the same set of virtual screens (i.e. one renderer.)
Another way to do it is to create contexts with the RendererID attribute.
If you first query all the available renderers, you can choose everything by ID. You can use the display masks to figure out which renderers can drive which displays.
Then create all shared contexts with that same RendererID.
akb825
2006.09.08, 12:56 AM
SDL just uses the main display when creating their contexts. I'm not going to change that, since all I wanted to change was the fact that it frees all the textures etc. I'll do a little more testing on the computers available to me, and once I get a project that I can distribute I'll ask people with multiple video cards to test it. Hopefully this will work for just about everyone. *crosses fingers*
vBulletin® v3.6.8, Copyright ©2000-2008, Jelsoft Enterprises Ltd.