sdl ttf_rendertext_blended fails randomly
Asked Answered
I

2

7

EDIT: Even that the problem still exists, I haven't been able to reproduce this frequently enough to examine it closer. See more info at the end of the question.


I started to develop a game, and I am currently writing basic library for it. I'm using D programming language with SDL-2 and OpenGL 3 (using Derelict3 bindings), on Linux Mint 13 (Maya). Compiler is DMD64 D Compiler v2.067.1, and I rebuild binary each time with 'rdmd'.

To render (changing) text, I create glyphs on-demand. The piece of code I use for this is:

class Font {
...

Texture render(char c) {
    if(!(c in rendered)) rendered[c] = texture(to!string(c));
    return rendered[c];
}

Texture texture(string text) {
    SDL_Color color={255, 255, 255, 255};

    auto bitmap = TTF_RenderText_Blended(
        font,
        std.string.toStringz(text),
        color
    );
    if(!bitmap) {
        throw new TTFError(
            "TTF_RenderText_Blended: " ~
            to!string(TTF_GetError()) ~ ": '" ~ text ~ "'"
        );
    }
    auto texture = new Texture(bitmap);
    SDL_FreeSurface(bitmap);
    return texture;
}

The problem is that this fails purely randomly. Sometimes it works without any problems. When it fails to render a glyph, it is interesting that it will fail to render the same glyph over and over again. Here is an example when catching the exception I throw:

...
TTF_RenderText_Blended: Text has zero width: '9'
TTF_RenderText_Blended: Text has zero width: '6'
TTF_RenderText_Blended: Text has zero width: '9'
TTF_RenderText_Blended: Text has zero width: '6'
TTF_RenderText_Blended: Text has zero width: '9'
TTF_RenderText_Blended: Text has zero width: '6'
...

(I'm printing score to screen, other numbers showing fine except those few ones). The numbers TTF_RenderText_Blended fails to render vary from run to run, and as mentioned, time to time it renders all the numbers.

One detail is that static strings I render before entering game loop have not yet failed to render, just single letters I use for changing texts.

I'm pretty much out of any ideas, and haven't found anything related to this problem by searching web. Any ideas to look for solutions are very well appreciated.


CURRENT SITUATION: I updated compiler to DMD 2.067.1 and the problem remains (compilers used so far: 2.066.1, 2.067.1). The whole - lets say project family is in the github at the moment:

https://github.com/mkoskim/games

The text glyph rendering function is located in this file:

https://github.com/mkoskim/games/blob/master/engine/ext/font.d

...and it is used from here:

https://github.com/mkoskim/games/blob/master/engine/ext/gui/label.d

The problem occurs mainly/most frequently in the pacman game (although very seldomly just right now):

https://github.com/mkoskim/games/tree/master/testbench/pacman

If you want to try it out, first, read the (hopefully complete enough) installation instructions:

https://github.com/mkoskim/games/blob/master/INSTALL

The project is made for 64-bit Linux Mint Maya, and it is currently not that user friendly and portable from building perspective. Pacman is the only demo that (hopefully) works without game controller. After successful installation of required libraries and tools, you can build it with command:

games/testbench/pacman$ make default
Improbity answered 16/11, 2014 at 11:58 Comment(16)
Just for experimentation, try putting a few spaces around the character, like " " ~ c instead of just to!string(c) in the render function and see what happens. Maybe SDL doesn't like rendering a single char..Warm
@AdamD.Ruppe, I have already tried things like that. Anyways, I changed the code like this: if(!(c in rendered)) rendered[c] = texture(std.string.format(" %c ", c));, and first test run gave me endless list of: ...TTF_RenderText_Blended: Text has zero width: ' 7 '...Improbity
"Sometimes it works without any problems. When it fails to render a glyph, it is interesting that it will fail to render the same glyph over and over again." Will it succeed at rendering new glyphs after the first one failed? I.e. is it possible that it stops being able to render glyphs completely, except for those cached in rendered?Carlcarla
@CyberShadow, I haven't done explicit tests for that, but points go up like 10, 20, 30, ..., so the code creates numbers in the same order. Thus, in the example case, it has created numbers in order 0, 1, 2, ..., 9, and failed to render numbers 6 and 9. It is purely random which glyphs fail, but when they fail, they keep failing all the time. I try to make a test case explicitely testing that case, thought.Improbity
I can't understand this... I slightly modified the code to see what glyphs get rendered and what not, and couldn't reproduce the case. Now, even when changing code back does not reproduce the failure :o My slight hunch is that this has nothing to do with SDL & TTF, but with compiler (I'm using Linux DMD64 D Compiler v2.066.1, compiling with rdmd)... I continue investigating the case.Improbity
Rendering still fails some times, but strangely now the frequency is very low for some reason (like once per 50 runs). All I did was first modify code to catch the error in Font.render(char) method, and then change the implementation back. I make full recompile between all runs. I think I should head to D / DMD forums to look for glues...Improbity
Are you using threads?Carlcarla
No (not explicitly at least). I use plain callbacks and Fibers. The point rendering code is called as callback from game main loop. But true, such random behavior sounds like thread/interrupt problem. Also, I don't use optimizations (-O), the args for compiler are "-w -debug -gc"Improbity
This thing is absolutely driving me grazy. For no apparent reason, it works or works not, and when not working, when I add traces and catches to get it, it stops failing D: I am now adding GUI things (text/font intensive code) to my base library, and random crashes from my own Exception (and no crashes when trying to catch it, or something), makes my life very miserable. It feels like at some situations, D and SDL-TTF-C-library do not agree with parameters, meaning that D thinks it is OK, and underlying (in this case) libft disagrees.Improbity
As an experiment, see if turning off garbage collection helps (import core.memory and call GC.disable()).Carlcarla
Can you try compiling for 32bit or using GDC or LDC? I fear it can be this bug: issues.dlang.org/show_bug.cgi?id=5570Obeded
Currently, the problem appears far too infrequently to be examined. If I ever get it coming more often, I try out the suggestions.Improbity
I have noticed TTF_RenderText_Blended() crashes when you pass a string with strange characters (like national characters). Haven't tested it enough to be sure how/why exactly (maybe if glyphs of that kind are not supported by the font)?Phycomycete
I haven't worked with this project for a while (had been busy with new job), but in my case I'm not feeding any strange characters, just plain numbers (0 - 9). I didn't find any pattern for failure in the past, and I haven't tested it with newer compiler & libraries.Improbity
I have the exact same problem and I just discovered something very strange: if I move the mouse within the window before it finishes initializing I get "Text has zero width" all over the place every time. If I do not move the mouse within the SDL window and wait for it to start the main game loop it works fine every time. No idea what to make of this.Disinfect
maybe it is lazy-loading something? parts of the kerning table or something. and crashes when the source SDL_RWops that was used to load the font, is then no longer available? Might explain a seemingly random behavior because it would depend on the individual combination of glyphs accessed.Serriform
M
3

I ran into the exact same issue, and for me it was fixed by keeping the SDL_RWops structure used to create the font (with TTF_OpenFontRW) alive for the whole lifetime of the TTF_Font created by it. I saw you're creating the font with TTF_OpenFontRW as well so I assume this will fix it for you as well. It looks like SDL_ttf relies on this being kept alive, it reads freed memory otherwise.

Morganstein answered 15/7, 2020 at 18:13 Comment(2)
Interesting! I need to try this out as soon as I continue the project!Improbity
I was able to reproduce the problem in SDL_ttf version 2.20.0 today. Although we're calling TTF_OpenFontRW with a nonzero value for the freesrc param, it relies on the source SDL_RWops after the call. I now leave them around along with the fonts as long as I use them, just as you describe, and it works perfectly. This is either a bug or a misrepresentation of the function of the freesrc argument in the SDL_ttf documentation.Serriform
A
1

I know this question is a little bit outdated but I maybe had a similar problem. I fixed it with simply call SDL_DestroyTexture() every time befor I used TTF_Render_Text_Blended() :)

Alys answered 1/2, 2017 at 19:7 Comment(1)
Heheh, old question, but not outdated :) Thanks for tip, I will try it when coming back to text rendering! I try to remember to update this item here, but sadly many things have already changed (SDL version, compiler version, etc etc).Improbity

© 2022 - 2024 — McMap. All rights reserved.