The SDL forums have moved to discourse.libsdl.org.
This is just a read-only archive of the previous forums, to keep old links working.


SDL Forum Index
SDL
Simple Directmedia Layer Forums
SDL_UpdateTexture()/SDL_CreateTexture() bug ?
knd


Joined: 29 Jan 2014
Posts: 5
Hello to all.

I'm working on own GUI library with SDL2 rendering front-end, using SDL2-2.0.0, SDL2_ttf2.0.12 and SDL2_image-2.0.0.

The problem I am facing is about manual texture creation from existing surface.

Here's how I am doing this for rendering labels:

1 ) rendering some text with TTF_RenderUTF8_Blended, getting SDL_Surface* with pixel format SDL_PIXELFORMAT_ARGB8888 ( queried that, that's for sure ):

Code:
SDL_Surface* surf = TTF_RenderUTF8_Blended(font->GetFont(), label->GetText().c_str(), fontColor );   


2) creating SDL_Texture* with :

Code:
SDL_Texture* sdlTexture = SDL_CreateTexture( renderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STREAMING, surf->w, surf->h );


3) setting pixels from surface to texture:
Code:

if ( 0 != SDL_UpdateTexture( sdlTexture, 0, surf->pixels, surf->pitch ) )
         std::cerr << "E: Failed to set texture pixels: " << SDL_GetError() << "\n";

4) clean-up an stuff

The troubles raising when this all comes to actual rendering to the screen - if I'm using SDL_PIXELFORMAT_ABGR8888 or surf-format->format in SDL_CreateTexture() then I see white rectangles instead of labels; if I'm using SDL_PIXELFORMAT_RGBA8888 I can see white letters on cyan background. If I'm using SDL_CreateTextureFromSurface() then all is OK.

The surface's and texture's pixel formats are matching each other in each situation.

Why is the same pixel format differs it's behavior in different situations? Maybe there's some internal hack in the SDL_CreateTextureFromSurface() which SDL_UpdateTexture() is lacking ?

Or ( most possible ) I'm doing something wrong ? Smile

P.S.

The complete method code with commented-out manual creation


Code:
GuiSDLTexture* GuiSDLRenderer::RecreateLabelTexture( Label* label ) {
      if ( 0 == label ) {
         std::cerr << "E: Can not create new texture or reload old one for NULL label.\n";
         return 0;
      }
      GuiSDLTexture* texture = 0;
      texture = dynamic_cast< GuiSDLTexture* >( GetTextureByName( label->GetName() ) );
      if ( ( 0 != texture ) && !label->Resized() && !label->TextChanged() )
         return texture; // no need to do anything - label is ok
      // check if we have everything we need
      // get fontManager
      GuiSDLFontManager* sdlFontManager  = dynamic_cast< GuiSDLFontManager* >( fontManager );
      if ( 0 == sdlFontManager ) {
         std::cerr<< "E: Unable to proceed with label rendering without font manager.\n";
         return 0;
      }
      // get needed font
      GuiSDLFont* font = dynamic_cast< GuiSDLFont*>( sdlFontManager->GetFontByName( label->GetFontName() ) );
      if ( 0 == font ) {
         std::cerr << "E: Unable to proceed with label rendering: font '" << label->GetFontName() <<"' not found.\n";
         return 0;
      }
      // check if we in need of a font resize
      if ( font->GetSize() != label->GetFontSize() ) 
         sdlFontManager->ReloadFontSized( font->GetName(), label->GetFontSize() );
      // manipulate texture
      if ( ( 0 != texture ) && ( label->Resized() || label->TextChanged() ) ) {
         SDL_DestroyTexture ( texture->GetTextureData() );
         texture->SetTextureData( 0 );
      }
      if ( 0 == texture )  {
         texture = new GuiSDLTexture;
         texture->SetName( label->GetName() );
         texture->SetTextureData( 0 );
      }
      assert( texture ); // now we should have non-zero texture with null texture data
      // render
      SDL_Color fontColor;
      fontColor.r = colorScheme.GetText().GetRGBA()[ 0 ];
      fontColor.g = colorScheme.GetText().GetRGBA()[ 1 ];
      fontColor.b = colorScheme.GetText().GetRGBA()[ 2 ];
      fontColor.a = 0xff;
      //colorScheme.GetText().GetRGBA()[ 3 ];

      SDL_Surface* surf = TTF_RenderUTF8_Blended(font->GetFont(), label->GetText().c_str(), fontColor );
      if ( 0 == surf ) {
         std::cerr << "E: Failed to render TTF font '" << font->GetName() << "' for label '" << label->GetName() << "'.\n";
         std::cerr << SDL_GetError() << "\n";
         // clean all up
         RemoveTexture( texture );
         delete texture;
         texture = 0;
         return 0;
      }
      std::cerr << "I: a) Rendered UTF8 surface sized " << surf->w << "*" << surf->h << " of format " << SDL_GetPixelFormatName( surf->format->format ) << "\n";
      std::cerr << "\t used pitch: " << surf->pitch << "; pixel size: " <<  surf->pitch/surf->w << ".\n";
      // create sdl2 texture
      SDL_Texture* sdlTexture = SDL_CreateTextureFromSurface( renderer, surf );
      /*SDL_Texture* sdlTexture = SDL_CreateTexture( renderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STREAMING, surf->w, surf->h );
      if ( 0 == sdlTexture ) {
         SDL_FreeSurface( surf );
         surf = 0;
         std::cerr << "E: Failed to create texture for TTF font '" << font->GetName() << "' for label '" << label->GetName() << "'.\n";
         std::cerr << SDL_GetError() << "\n";
         // clean all up
         RemoveTexture( texture );
         delete texture;
         texture = 0;
         return 0;
      }*/
      Uint32 format;
      int w, h, access;
      SDL_QueryTexture( sdlTexture, &format, &access, &w, &h );
      std::cerr << "I: b) Created UTF8 texture sized " << w << "*" << h << " pixels of " << SDL_GetPixelFormatName( format ) << " format.\n";
//      std::cerr << "\t used pitch: " << ->pitch << "\n";
      
   /*   if ( 0 != SDL_UpdateTexture( sdlTexture, 0, surf->pixels, surf->pitch ) )
         std::cerr << "E: Failed to set texture pixels: " << SDL_GetError() << "\n";
   */
      // unload surface
      SDL_FreeSurface( surf );
      // finally - set data and add
      texture->SetTextureData( sdlTexture );
      texture->SetName( label->GetName() );
      AddTexture( texture );
      return texture;
   }
knd


Joined: 29 Jan 2014
Posts: 5
I didn't found an answer about SDL_UpdateTexture() so far, but I've managed to solve the prior task: accessing texture's pixels to check their alpha ( that's SDL_TEXTUREACCESS_STREAMING and manual texture creation where needed for ).

It's bit a hack, but...
Instead of creating streaming textures I am creating regular textures and taking a bitmask of alpha layer of initial SDL_Surface.
Then I'm accessing that bitmask instead of mocking with textures and their locks/unlocks. It takes RAM, but it works and works fast.

Thanks to everyone =_=
mattbentley


Joined: 07 Jul 2013
Posts: 72
I had this same issue, ended up using createtexturefromsurface as well...

Does anybody know how to (accurately) determine what the renderer's expected texture format is, without creating a surface and then creating a texture from it?
Kind of a huge overhead when mainly using UpdateTexture.