grimfang4/SDL_FontCache

Drawing text disapear after window resize

Opened this issue · 16 comments

Hi all,
When the renderer is created with SDL_RENDERER_ACCELERATED flag, the drawing text disapear after resizing the window.
Using the SDL_RENDERER_SOFTWARE flag, it works well.

Hi, I just found this library and came across the same issue.

If you edit this line 1185. It seems to work with the following flag which is 1.

fc_has_render_target_support = (info.flags & SDL_RENDERER_SOFTWARE);

It will also work with flag of 8192.


Also tested with SDL_RenderSetLogicalSize which is nice. @grimfang4 Thanks!

Thansk. It works.
I simply disabled this flag :
fc_has_render_target_support = 0;

Changing breaks UTF-8.

image

You are right. UTF8 is broken :/

Line 978: if(!fc_has_render_target_support)

if(fc_has_render_target_support > 0)

No. UTF-8 is still broken.

Can you post a program that demonstrates this for further investigation? Resizing a window shouldn't cause the context to be lost, as far as I understand, though fullscreening might. If the context is lost, then textures would be dropped. SDL can restore some textures, which might be what is happening here when comparing textures created with SDL_CreateTextureFromSurface() and textures created as render targets. With a definite repro case, I can look further into this.

When disabling render targets like what was suggested above, you are losing the ability to render new glyphs onto the cache level textures at drawtime. That's why UTF-8 would not work. If you know which glyphs you will need, you can work around this by preloading them with FC_SetLoadingString(). It does seem like sometimes this might be desirable, so maybe we can add a function and manual setting for disabling render target support.

Ok, Here a minimal test case :

int main(int argc, char** argv)
{
  if (SDL_Init(SDL_INIT_VIDEO) != 0)
    return -1;

  if (TTF_Init())
    return -1;

  // This change nothing
  /*
  SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1");

  if (SDL_GL_SetSwapInterval(-1))
    SDL_GL_SetSwapInterval(1);
  */

  SDL_Window *_pWindow = SDL_CreateWindow("test window",
    SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720,
    SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_MAXIMIZED);
  if (!_pWindow)
    return -1;


  // Using this line makes the text disappear as soon as I resize the window
  // Removing the SDL_RENDERER_TARGETTEXTURE changes nothing
   SDL_Renderer *_pRenderer = SDL_CreateRenderer(_pWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE);

   // Using this line makes things working right :)
   // Removing the SDL_RENDERER_TARGETTEXTURE changes nothing
   //SDL_Renderer *_pRenderer = SDL_CreateRenderer(_pWindow, -1, SDL_RENDERER_SOFTWARE | SDL_RENDERER_TARGETTEXTURE);

   // This changes nothing
   //SDL_SetRenderDrawBlendMode(_pRenderer, SDL_BLENDMODE_BLEND);

   FC_Font *_pFontTextHeader = FC_CreateFont();
   FC_LoadFont(_pFontTextHeader, _pRenderer, "res/header.ttf", 14, FC_MakeColor(200, 200, 200, 255), TTF_STYLE_NORMAL);

   int counter = 0;
   while (42)
   {
     SDL_Event ev;
     while (SDL_PollEvent(&ev))
     {
       if (ev.type == SDL_QUIT)
         return -2;
     }

     int windowWidth = SDL_GetWindowSurface(_pWindow)->w;
     int windowHeight = SDL_GetWindowSurface(_pWindow)->h;

     // Draw black background
     SDL_Rect recBg = { 0, 0, windowWidth, windowHeight };
     SDL_SetRenderDrawColor(_pRenderer, 0, 0, 0, 255);
     SDL_RenderFillRect(_pRenderer, &recBg);

     // Using test text with UTF8 symbol (°)
     FC_DrawAlign(_pFontTextHeader, _pRenderer, static_cast<float>(windowWidth / 2), static_cast<float>(windowHeight / 2), FC_ALIGN_CENTER, u8"°° %d °°", counter++);

     SDL_RenderPresent(_pRenderer);

     SDL_Delay(100);
   }

  return 0;
}

Can you post a program that demonstrates this for further investigation? Resizing a window shouldn't cause the context to be lost, as far as I understand, though fullscreening might.

I used your demo for my tests.

  • Add accelerated and resize for textures to disappear on resize with UTF-8 intact.
    main.c 326 window = SDL_CreateWindow("", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, w, h, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
    main.c 333 renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED);

  • A hack to fix resize but break UTF-8

SDL_FontCache.c 1185 fc_has_render_target_support = (info.flags & 0);

For information, I have this issue on Windows (10) with SDL2-2.0.12.x64 and SDL2_ttf-2.0.15.x64

Any news ?

I'm also getting the same error.

Got the same problem. Work around was to free the font FC_FreeFont, then recreate FC_CreateFont and load again FC_LoadFont on the window resise event SDL_WINDOWEVENT_SIZE_CHANGED.
Not ideal but can live with that.

By the way, the problem is on windows 10, it works fine on Linux.

I have also had a report that on Windows resizing my game's window results in text disappearing.

I found this thread https://discourse.libsdl.org/t/sdl2-0-10-textures-disappearing-renderer-causing-error-when-resizing-window-with-a-render-target-texture/26598

which suggests using an SDL hint to use opengl instead of directX.

From the error message I assume it’s not using OpenGL but Direct3D, which is the default on Windows. It might be interesting to see if OpenGL behaves differently, which you can do by setting this hint before creating the renderer:

SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl");

I add this line right before I created the renderer, and it seems to have resolved the issue for me (tested using Wine on my Ubuntu 20.04 system).

So in terms of solving the issue, maybe the directX vs OpenGL thing is a clue?

To fix this issue under direct3d, you have to handle the SDL_RENDER_TARGETS_RESET SDL event type then call FC_ResetFontFromRendererReset() on your fonts objects.
Sometime d3d context asks for SDL_RENDER_TARGETS_RESET that require we recreate SDL_TEXTUREACCESS_TARGET textures.

The simplest solution is to keep all your font objects references to a global std::vector<FC_Font *> then :

  while (SDL_PollEvent(&ev))
  {
    if (ev.type == SDL_RENDER_TARGETS_RESET) {
        for (FC_Font* font : _FC_FontList)
            FC_ResetFontFromRendererReset(font, _pRenderer, SDL_RENDER_TARGETS_RESET);
    }
  }