Results 1 to 7 of 7

Thread: CL_GUIFontCache and shutdown problems

  1. #1
    Squire
    Join Date
    Jun 2007
    Posts
    27

    Default CL_GUIFontCache and shutdown problems

    Was debugging why some textures remain behind after the last graphic context is destroyed, and noticed the following:

    Code:
    {
      CL_GUIManager gui;
      CL_Window window(...);
      ...
      gui.exec();
    }
    When 'window' goes out of scope it destroys the gc. CL_GUIManager is still around though, and when it goes out of scope it destroys CL_GUIFontCache. That's when it tries to access the destroyed gc.

    Rombust, you've done most of the work with fonts so I suppose you know best how to handle this? Magnus added that CL_SharedGCData class recently - maybe the font caching could be moved there? I'm not even sure if CL_GUIFontCache is needed at all any more with all the changes done lately?

  2. #2
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    Heh, the old "CL_GraphicContext destroyed, before CL_Texture destruction appears yet again

    I'm not sure of the best way to solve this problem with fonts.

    In general, shared (and cached) CL_Textures should go into the CL_SharedGCData, but in this situation, things are not that simple.

    We need to keep in mind that the user may not be using CL_Font_Texture. They could be using CL_Font_Native (the OS GDI pixel buffer based font), CL_Font_FreeType (another pixel based font) and CL_Font_Vector (trangle based font)

    So, it would not make sense for the other font types to be located in CL_SharedGCData

    As all the fonts inherit CL_Font, the gui does not know (or care) of the internals of the font.

    CL_Texture_Font - Does not do any internal caching, and in my opinion, it does not need to.

    The CL_GUIFontCache is very useful, in collecting fonts, to avoid duplication. And the user can get access to this font via CL_Manager::get_named_font(), or
    set a new font via set_named_font(). So it is possible for the GUI to use vector based fonts by the user calling set_named_font(CL_Font_Vector(...))

    I do not see any advantage for moving CL_GUIFontCache elsewhere, as nowhere else uses it (within ClanLib). And as mentioned earlier, it does not fit into CL_SharedGCData

    A method of solving the CL_Texture destruction problem, is via a callback called by the CL_GraphicContextProvider when the OpenGL (of whatever) context is destroyed.

    The CL_Font_Texture would recieve the callback. Then it would also need to send a message to the CL_GUIFontCache to destroy itself.

    In my opinion, this is messy, we should not be in this situation in the first place. However, the nature of Cache's may mean that this is unavoidable.

    Another method of solving the CL_Font_Texture's destruction in the font cache, again, via a callback called by the CL_GraphicContextProvider when the OpenGL (of whatever) context is destroyed.

    The CL_GUIFontCache would receive the callback. The CL_SharedGCData would contain a list of CL_Font_Texture fonts, that we destroy.

    That's a hacky method, and would cause problems if the user provided there own CL_Texture'd based fonts.

    The 3rd method - And "MAYBE" the best - Is again, a CL_GraphicContextProvider destruction callback.

    This time the entire CL_GUIFontCache is removed.

    Consequently, any user fonts to the gui provided via CL_GUIManager::set_named_font() would be lost. As long as this is documented, it should not matter.

  3. #3
    Squire
    Join Date
    Jun 2007
    Posts
    27

    Default

    I have added the "last gc about to be destroyed" signal to CL_SharedGCData. However there are more problems:

    CL_OpenGLTextureProvider has a weak_ptr to the graphics context that created the texture. When the texture is destroyed it only has a reference to the gc used to create it, even though textures are shared by all gc's. When using i.e. CL_PopupMenuWindow, textures get created in a different gc and then cached, thus outliving the gc. When CL_PopupMenu's cached textures are destroyed at shutdown, they don't have a pointer to a valid context any more. This makes CL_OpenGLTextureProvider unable to delete the texture, and it issues the warning dialog.

    Somehow we'd need to get a valid opengl context to CL_OpenGLTextureProvider when it's destructed.

  4. #4
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    Quote Originally Posted by Harry View Post
    CL_OpenGLTextureProvider has a weak_ptr to the graphics context that created the texture.
    I added that weak_ptr over a year ago. It was only added to report the "graphic context was destroyed before texture" error message.

    It is possible that I used the weak_ptr from an incorrect source.

    In theory, that weak_ptr can be removed - However all the "graphic context was destroyed before texture" bugs will not be detected.

    This is fine on Win32, as microsoft opengl api (WGL) ignores the errors. But on Linux GLX, it crashes. (Hence, i added the warning in the first place)

    Maybe a better approach would be for the OpenGL context to count how many textures are used. On destruction, if the texture count is not 0, then display a warning.

  5. #5
    Squire
    Join Date
    Jun 2007
    Posts
    27

    Default

    I have fixed this issue in windows now. The solution become quite tricky in the end. To tell opengl contexts to share textures on windows wglShareLists is used. There used to be a list in CL_OpenGLWindowProvider_WGL:

    Code:
    class CL_OpenGLWindowProvider_WGL
    {
        ...
        static std::list<HGLRC> opengl_contexts;
    }
    The list allowed calling wglShareLists with the right parameters. Now this list has been moved to CL_SharedGCData, where pointers to the gc provider are stored:

    Code:
    CL_SharedGCData
    {
       ...
       std::vector<CL_GraphicContextProvider*> gc_providers;
    }
    A pointer is added to the list when the WGL provider creates a GC, and the pointer is removed when the display windows and the gc are destroyed, in the WGL providers destructor.

    The HGLRC used for wglShareLists is accessible through a few casts:
    Code:
    CL_OpenGLGraphicContextProvider *gl_provider = dynamic_cast<CL_OpenGLGraphicContextProvider*>(gc_providers.back());
    if (gl_provider)
    {
      const CL_RenderWindowProvider *rwp = &gl_provider->get_render_window();
      const RenderWindowProvider_WGL *render_window_wgl = dynamic_cast<const RenderWindowProvider_WGL*>(rwp);
      if (render_window_wgl)
        wglShareLists(render_window_wgl->wgl_context, opengl_context);
    }
    When CL_OpenGLTextureProvider's destructor now tries to delete a opengl texture, it gets the list of gc providers from CL_SharedGCData, casts it to the opengl gc provider and activates the context through CL_OpenGL::set_active. If there are no gc's any more in the shared list, the old warning message is displayed.

    The GLX target currently only keeps one context around, instead of a list like the WGL target used to:

    Code:
    static GLXContext share_context;
    This should prolly be changed so it also uses the shared list of contexts in CL_SharedGCData, so the texture deletion will work smoothly.

    I hope this helps with fixing things on linux also

  6. #6
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    I have modified the GLX target so it compiles and runs.

    However, it crashes on exit, and some of the GUI example fonts are missing

    I'll take a look at it some time this week.

  7. #7
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    Linux ClanLib is working again

Bookmarks

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •