SDL icon indicating copy to clipboard operation
SDL copied to clipboard

SDL 2: Scaled blitting of 8-bit indexed surface shows a black screen

Open legacythewolf opened this issue 1 year ago • 2 comments

I have an 8-bit indexed surface, in this example, 320x240. I would like to scale it to multiples of that resolution, for example, 640x480, but scaled blitting of the indexed surface shows an empty screen

int main(int argc, char * argv [])
{
	SDL_Window *window;
	SDL_Surface *screen, *display;
	SDL_Event event;
	SDL_Palette *palette;
	Uint8 *pixels;
	
	/* initialize system */
	if (SDL_Init(SDL_INIT_VIDEO) == -1)
	{
		puts("Cannot initialize SDL video");
		return 1;
	}
	atexit(SDL_Quit);
	
	/* initialize screen */
	window = SDL_CreateWindow("", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WIDTH * 2, HEIGHT * 2, 0);
	if (!window)
	{
		puts("Cannot set video mode");
		return 1;
	}
	display = SDL_GetWindowSurface(window);
	SDL_ShowCursor(SDL_DISABLE);
	
	screen = SDL_CreateRGBSurface(0, WIDTH, HEIGHT, 8, 0, 0, 0, 0);
	if (!screen)
	{
		puts("Cannot allocate screen");
		return 1;
	}
	
	/* initialize palette */
	palette = create_palette();
	if (!palette) return 1;
	if (SDL_SetSurfacePalette(screen, palette))
	{
		puts("Unable to set palette");
		return 1;
	}
	SDL_SetSurfaceBlendMode(display, SDL_BLENDMODE_NONE); 
	SDL_SetSurfaceBlendMode(screen, SDL_BLENDMODE_NONE); 
	
	/* draw screen */
	pixels = (Uint8 *) screen->pixels;
	draw_screen(pixels, screen->pitch);
	
/*
      ===============================
           HERE IS THE PROBLEM
      ===============================
*/

/*	SDL_BlitSurface(screen, NULL, display, NULL); note that this would work just fine */
	SDL_BlitScaled(screen, NULL, display, NULL);
	SDL_UpdateWindowSurface(window);
	
	/* event loop */
	while (1)
	{
		while (SDL_PollEvent(&event))
		{
			if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_q) return 0;
		}
		
		SDL_Delay(10);
	}
	return 0;
}

legacythewolf avatar May 24 '24 14:05 legacythewolf

That's correct, scaled conversion blitting from an 8-bit surface to a non-8-bit surface is not currently supported. You can scale an 8-bit surface and convert to 32-bit or convert to 32-bit and then scale, but currently you can't do both in the same operation.

slouken avatar May 24 '24 16:05 slouken

FYI, here's the SDL 3.0 version of your example program:

#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>

#define WIDTH  320
#define HEIGHT 240

SDL_Palette *create_palette()
{
    SDL_Palette *p = SDL_CreatePalette(2);
    p->colors[1].r = 0;
    p->colors[1].g = 0xff;
    p->colors[1].b = 0;
    return p;
}

static void draw_screen(Uint8 *pixels, int pitch)
{
    SDL_memset(pixels, 1, pitch * HEIGHT);
}

int main(int argc, char *argv[])
{
    SDL_Window *window;
    SDL_Surface *screen, *display;
    SDL_Event event;
    SDL_Palette *palette;
    Uint8 *pixels;

    /* initialize system */
    if (SDL_Init(SDL_INIT_VIDEO) == -1) {
        SDL_Log("Cannot initialize SDL video");
        return 1;
    }

    /* initialize screen */
    window = SDL_CreateWindow("", WIDTH * 2, HEIGHT * 2, 0);
    if (!window) {
        SDL_Log("Cannot set video mode");
        return 1;
    }
    display = SDL_GetWindowSurface(window);
    SDL_HideCursor();

    screen = SDL_CreateSurface(WIDTH, HEIGHT, SDL_PIXELFORMAT_INDEX8);
    if (!screen) {
        SDL_Log("Cannot allocate screen");
        return 1;
    }

    /* initialize palette */
    palette = create_palette();
    if (!palette)
        return 1;
    if (!SDL_SetSurfacePalette(screen, palette)) {
        SDL_Log("Unable to set palette");
        return 1;
    }
    SDL_SetSurfaceBlendMode(display, SDL_BLENDMODE_NONE);
    SDL_SetSurfaceBlendMode(screen, SDL_BLENDMODE_NONE);

    /* draw screen */
    pixels = (Uint8 *)screen->pixels;
    draw_screen(pixels, screen->pitch);

    /*
          ===============================
               HERE IS THE PROBLEM
          ===============================
    */

    // SDL_BlitSurface(screen, NULL, display, NULL);
    if (!SDL_BlitSurfaceScaled(screen, NULL, display, NULL, SDL_SCALEMODE_NEAREST)) {
        SDL_Log("SDL_BlitSurfaceScaled failed: %s\n", SDL_GetError());
    }
    SDL_UpdateWindowSurface(window);

    /* event loop */
    while (1) {
        while (SDL_PollEvent(&event)) {
            if (event.type == SDL_EVENT_KEY_DOWN && event.key.key == SDLK_Q)
                return 0;
        }

        SDL_Delay(10);
    }
    return 0;
}

slouken avatar May 24 '24 16:05 slouken

This now implemented in SDL3.

slouken avatar Oct 06 '24 18:10 slouken