1
\$\begingroup\$

I'm trying to convert my emulator to SDL2 (from SDL 1.2).

As I'm drawing pixel per pixel, I follow "If your game just wants to get fully rendered frames to the screen" in the migration guide: https://wiki.libsdl.org/MigrationGuide#If_your_game_just_wants_to_get_fully-rendered_frames_to_the_screen

I basically do:

SDL_CreateWindowAndRenderer(...);
vid = SDL_CreateRGBSurface(..., bpp, ...);
texture = SDL_CreateTextureFromSurface(renderer, vid);

// ... and then later, when "blitting" ...

SDL_UpdateTexture(texture, NULL, vid->pixels, vid->pitch);
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);

It works fine if I use 32bpp but this doesn't work for other bpp: the colors are not as expected. This is because the surface has a pixel format with the BPP I want but the texture has a different pixel format. This is problematic because:

  • I have some (optional) specific scaling algorithms that require 16bpp surfaces
  • I'm not sure whether it will behave the same for all users
  • When not scaling with my own algorithms, the performance is better if I directly use the bpp of the display

The reason why the bpp doesn't match is that the SDL_UpdateTexture accesses the surface data (pixels) without even looking at the pixel format and SDL_CreateTextureFromSurface creates a texture compatible with the renderer, not caring about the surface format.

So my questions are:

  • Is there a simple way to get a surface that is compatible with the renderer? [1]
  • Is there a way to blit the surface on the texture that does the color conversion? [2]

[1] I found:

SDL_RendererInfo infos;
SDL_GetRendererInfo(renderer, &infos);
vid = SDL_CreateRGBSurfaceWithFormat(0, w, h, SDL_BITSPERPIXEL(infos.texture_formats[0]), infos.texture_formats[0]);

but it's a bit heavy, there are multiple supported so I'm not sure which one to choose and I also had some display issues that suggest the result is not really what I want.

[2] One idea I had is to have another surface with the format taken from [1] and to blit to it first for the conversion, before copying it to the texture, but I'm surprised there's no simpler way to do it.

\$\endgroup\$
0
\$\begingroup\$

In the end, what I ended up doing is indeed what I suggested in the question:

  • Use SDL_GetRendererInfo to retrieve the BPP of the renderer and pass it to SDL_CreateRGBSurface to have a surface with compatible BPP
  • Create a new intermediary 16bpp surface for the scaling algorithm that need it and blit it to the surface created with the compatible BPP before calling SDL_UpdateTexture

After a lot of searching through doc and on the web, this seems like the best way to do it.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.