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\$

1 Answer 1

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\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .