shared context breaking FTGL texture fonts

Moderator
Posts: 1,140
Joined: 2005.07
Post: #1
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.
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #2
I seem to have resolved the problem. Apparently the mere vibes of the board revealed the answer to me. Wink 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.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #3
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.
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #4
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.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #5
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.
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #6
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.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #7
Just to check, then -- Outnumbered (http://onesadcookie.com/Software/) does work for you, right? Smile

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 Wink
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #8
It does work. Unfortunately, I don't have a PowerMac available with multiple graphics cards. Annoyed I'll have to look into it and see if I can find any other differences.

Edit: I don't suppose the order matters?
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #9
In case it matters, here's the modified function.
Code:
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.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #10
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 Smile
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #11
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.
Quote this message in a reply
Sage
Posts: 1,232
Joined: 2002.10
Post: #12
OneSadCookie Wrote: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 Smile

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.
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #13
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*
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  How do I flip upside down fonts in FTGL mr5z 4 1,004 Mar 3, 2014 03:36 PM
Last Post: JustinFic
  Xcode and FTGL hiddenspring81 7 5,984 Oct 10, 2013 03:00 PM
Last Post: ardowz
  ios/mac shader - shared glsl source OptimisticMonkey 2 5,215 Jun 17, 2011 08:59 AM
Last Post: OptimisticMonkey
  Bitmap fonts markhula 6 7,962 Feb 27, 2011 12:55 PM
Last Post: markhula
  Anyone run into this problem with FTGL? wadesworld 1 3,044 Apr 21, 2009 02:19 PM
Last Post: Oddity007