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 ):
SDL_Surface* surf = TTF_RenderUTF8_Blended(font->GetFont(), label->GetText().c_str(), fontColor );
-
creating SDL_Texture* with :
SDL_Texture* sdlTexture = SDL_CreateTexture( renderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STREAMING, surf->w, surf->h );
-
setting pixels from surface to texture:
if ( 0 != SDL_UpdateTexture( sdlTexture, 0, surf->pixels, surf->pitch ) )
std::cerr << "E: Failed to set texture pixels: " << SDL_GetError() << “\n”; -
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 ?
P.S.
The complete method code with commented-out manual creation
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;
}