Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Messed up font texture (SFML2)  (Read 6074 times)

0 Members and 1 Guest are viewing this topic.

Tank

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1486
    • View Profile
    • Blog
    • Email
Messed up font texture (SFML2)
« on: February 11, 2010, 03:01:27 pm »
Hi guys,

I've recently discovered that the font texture gets somehow messed up. Look at this screenshot:



The lines are created after each other. When I don't add the last two lines (abcdef...), only the "v" in "Server disconnected" is missing.

5th line is lower-case, 6th line is upper-case. This happened to me at first with the default font, so I switched it -- just to say that it's not font-related. ;)

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Messed up font texture (SFML2)
« Reply #1 on: February 11, 2010, 03:18:53 pm »
Hi

Any message on the standard error output? Which revision are you using?
Laurent Gomila - SFML developer

Tank

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1486
    • View Profile
    • Blog
    • Email
Messed up font texture (SFML2)
« Reply #2 on: February 11, 2010, 04:23:46 pm »
Nope, no errors on stdout/err. I'm using the latest revision (updated just now).

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Messed up font texture (SFML2)
« Reply #3 on: February 11, 2010, 04:39:00 pm »
Can you show a minimal example that reproduces this problem?

What graphics card do you have?
Laurent Gomila - SFML developer

Tank

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1486
    • View Profile
    • Blog
    • Email
Messed up font texture (SFML2)
« Reply #4 on: February 11, 2010, 04:59:47 pm »
Okay this is weird. I've done the same steps in a minimal example and everything works. I'll recheck my application and post when I've got news on that.

Tank

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1486
    • View Profile
    • Blog
    • Email
Messed up font texture (SFML2)
« Reply #5 on: February 11, 2010, 05:15:00 pm »
Okay, got it. Was not so easy to get this bug working, again. ;)

The problem only shows up in a multi-threaded application. And I had to do some "tricks" to make it appear. The following code is a bit longer, but I couldn't come up with something shorter, sorry.

Code: [Select]
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
#include <list>

void ThreadFunc( void* arg );

typedef std::list<sf::Text>  TextList;

TextList   List;
bool       Running( true );
sf::Mutex  Lock;

int main() {
sf::RenderWindow  wnd( sf::VideoMode( 800, 600, 32 ), "Font" );
sf::Thread        thread( ThreadFunc, 0 );

thread.Launch();

while( Running ) {
wnd.Clear();

// Critical section begins.
Lock.Lock();

TextList::iterator  iter( List.begin() );
TextList::iterator  iterend( List.end() );

for( ; iter != iterend; ++iter ) {
wnd.Draw( *iter );
}

Lock.Unlock();
// Ends.

wnd.Display();
}

sf::Sleep( 2.f );
return 0;
}

void UpdatePositions() {
TextList::iterator  iter( List.begin() );
TextList::iterator  iterend( List.end() );
float               yoffset( 0.f );

for( ; iter != iterend; ++iter ) {
iter->SetPosition( 0.f, yoffset );
yoffset += iter->GetRect().GetSize().y + 3.f;
}
}

void ThreadFunc( void* arg ) {
sf::Context  ctx;

Lock.Lock();
List.push_back( sf::Text( L"Trying to connect..." ) );
UpdatePositions();
Lock.Unlock();
sf::Sleep( .2f );

Lock.Lock();
List.push_back( sf::Text( L"Connection established. Sending username and password..." ) );
UpdatePositions();
Lock.Unlock();
sf::Sleep( .2f );

Lock.Lock();
List.push_back( sf::Text( L"Login failed. Wrong username and/or password." ) );
UpdatePositions();
Lock.Unlock();
sf::Sleep( .2f );

Lock.Lock();
List.push_back( sf::Text( L"Server disconnected." ) );
UpdatePositions();
Lock.Unlock();
sf::Sleep( .2f );

Running = false;
}


When you move the "Lock.Unlock()" lines in "ThreadFunc()" behind the "sf::Sleep()" calls, everything's working like a charm. I don't have a clue what's happening here.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Messed up font texture (SFML2)
« Reply #6 on: February 11, 2010, 06:13:19 pm »
This is fun.

Look at this:
Code: [Select]
#include <SFML/Graphics.hpp>
#include <list>

void ThreadFunc( void* );

typedef std::list<sf::Text>  TextList;

TextList   List;
bool       Running( true );
sf::Mutex  Lock;

int main() {
   sf::RenderWindow  wnd( sf::VideoMode( 800, 600, 32 ), "Font" );
   sf::Thread        thread( ThreadFunc, 0 );

   thread.Launch();

   while( Running ) {
      wnd.Clear();

      // Critical section begins.
      Lock.Lock();

      TextList::iterator  iter( List.begin() );
      TextList::iterator  iterend( List.end() );

      for( ; iter != iterend; ++iter ) {
         wnd.Draw( *iter );
      }

      Lock.Unlock();
      // Ends.

      wnd.Display();
   }

   sf::Sleep( 2.f );
   return 0;
}

void AddText(const std::string& Text)
{
   Lock.Lock();

   List.push_back( sf::Text( Text ) );

   TextList::iterator  iter( List.begin() );
   TextList::iterator  iterend( List.end() );
   float               yoffset( 0.f );

   for( ; iter != iterend; ++iter ) {
      iter->SetPosition( 0.f, yoffset );
      yoffset += iter->GetRect().GetSize().y + 3.f;
   }

   Lock.Unlock();
   sf::Sleep( 0.5f );
}

void ThreadFunc( void* ) {
   sf::Context  ctx;

   AddText( "aej" );
   AddText( "aba" );
   AddText( "abca" );
   AddText( "abcda" );
   AddText( "abcdea" );
   AddText( "abcdefa" );
   AddText( "abcdefga" );
   AddText( "abcdefgha" );
   AddText( "abcdefghia" );
   AddText( "abcdefghija" );
   AddText( "abcdefghijka" );
   AddText( "abcdefghijkla" );
   AddText( "abcdefghijklma" );
   AddText( "abcdefghijklmna" );
   AddText( "abcdefghijklmnoa" );

   Running = false;
}


Only the glyphs contained in the first text are rendered in the other lines, all the other glyphs appear magically at the end of the program.

Note that swapping Lock and Sleep calls didn't change anything for me.

More fun: if I write AddText like this
Code: [Select]
void AddText(const std::string& Str)
{
   static float yoffset( 0.f );

   Lock.Lock();

   sf::Text Text(Str);
   Text.SetY(yoffset);
   yoffset += 30;
   List.push_back( Text );

   sf::Sleep( 0.5f );
   Lock.Unlock();
}


Everything's fine.

I have to go buy some food for my ferret, but I'll do more funny tests after that :D
Laurent Gomila - SFML developer

Tank

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1486
    • View Profile
    • Blog
    • Email
Messed up font texture (SFML2)
« Reply #7 on: February 12, 2010, 12:02:27 am »
Must have been much food. ;)

But yeah, it's truly weird. So getting rid of the iterators fixed it, mh. That's just strange in my eyes. Do you have any idea what may cause this? New font rendering? OpenGL? Some multi-threading issue?

Edit: Ha, you're right. When I push back texts with all glyphs I use later, everything's fine (like preloading them ;)).

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Messed up font texture (SFML2)
« Reply #8 on: February 12, 2010, 08:14:06 am »
Quote
Must have been much food

I had an accident on my way to the pet store :P

Quote
But yeah, it's truly weird. So getting rid of the iterators fixed it, mh. That's just strange in my eyes.

I didn't have time to check yet, but I think it is related to the GetRect() call rather than iterators.

Quote
Do you have any idea what may cause this? New font rendering? OpenGL? Some multi-threading issue?

I think it is a combination of multi-threading, internal sf::Image optimizations (lazy updates) and sf::Font texture generation on-the-fly.
Laurent Gomila - SFML developer

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Messed up font texture (SFML2)
« Reply #9 on: February 12, 2010, 11:49:01 am »
After some more tests, I found that it is indeed GetRect() that messes things up - more specifically, it is the line which generates a new glyph.

My conclusion is that an OpenGL texture cannot be active on two different contexts at the same time, even if it is not used concurrently. I kind of confirmed it by activating another texture after drawing the texts in the main thread: it worked with a little lag (probably due to the locks and sleep calls).

It also explains why the first text is always rendered properly: the texture is not active yet in the main thread.

I couldn't find more information about this, and don't know if it can be solved :(
Laurent Gomila - SFML developer

Tank

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1486
    • View Profile
    • Blog
    • Email
Messed up font texture (SFML2)
« Reply #10 on: February 12, 2010, 03:14:36 pm »
Okay, too bad OpenGL bitches so much around with multi-threading. :roll:

So the only solution is to limit the creation of textures to the main thread. Thanks for the info.

And hopefully nothing happened at your accident.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Messed up font texture (SFML2)
« Reply #11 on: February 12, 2010, 04:21:26 pm »
Quote
So the only solution is to limit the creation of textures to the main thread

No, this is a different problem. Creating a texture in a thread is of course possible, what you can't do is activating (glBindTexture) the same texture in two different threads.
The problem in SFML is that a texture remains active until another one is activated, so for example in your code the texture is always active in both threads, because this is the only one that is used.
Laurent Gomila - SFML developer

Tank

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1486
    • View Profile
    • Blog
    • Email
Messed up font texture (SFML2)
« Reply #12 on: February 12, 2010, 11:39:47 pm »
Okay I see. So a thread would have to call glBindTexture() again to ensure a proper display? If so, can this be implemented or would it not fit into the library design?

I'm currently creating and activating the texts/fonts in the main thread as a workaround. But if there'd be another and maybe simplier method, I'd prefere that, of course.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Messed up font texture (SFML2)
« Reply #13 on: February 13, 2010, 10:55:11 am »
Quote
So a thread would have to call glBindTexture() again to ensure a proper display? If so, can this be implemented or would it not fit into the library design?

It wouldn't fit at all :?

I think that you should just preload all the glyphs that you need before starting your thread, that should be enough.
Laurent Gomila - SFML developer

Tank

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1486
    • View Profile
    • Blog
    • Email
Messed up font texture (SFML2)
« Reply #14 on: February 13, 2010, 06:42:48 pm »
Good point, thanks.