mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-10-03 16:36:25 +00:00
Simplify palette code
Each texture gets its own palette, the palette is updated when it is rendered if necessary, rendering is flushed if a texture render is already queued up. Trying to share palettes and handle the different cases of queued rendering and changing palettes in the middle of the frame ends up being very complicated, so we'll keep it simple for now.
This commit is contained in:
@@ -1900,17 +1900,6 @@ bool SDL_SetTexturePalette(SDL_Texture *texture, SDL_Palette *palette)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (palette != texture->palette) {
|
if (palette != texture->palette) {
|
||||||
if (!FlushRenderCommandsIfTextureNeeded(texture)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!texture->native) {
|
|
||||||
SDL_Renderer *renderer = texture->renderer;
|
|
||||||
if (!renderer->ChangeTexturePalette(renderer, texture, palette)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (texture->palette) {
|
if (texture->palette) {
|
||||||
SDL_DestroyPalette(texture->palette);
|
SDL_DestroyPalette(texture->palette);
|
||||||
}
|
}
|
||||||
|
@@ -235,7 +235,6 @@ struct SDL_Renderer
|
|||||||
|
|
||||||
void (*InvalidateCachedState)(SDL_Renderer *renderer);
|
void (*InvalidateCachedState)(SDL_Renderer *renderer);
|
||||||
bool (*RunCommandQueue)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize);
|
bool (*RunCommandQueue)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize);
|
||||||
bool (*ChangeTexturePalette)(SDL_Renderer *renderer, SDL_Texture *texture, SDL_Palette *palette);
|
|
||||||
bool (*UpdateTexturePalette)(SDL_Renderer *renderer, SDL_Texture *texture);
|
bool (*UpdateTexturePalette)(SDL_Renderer *renderer, SDL_Texture *texture);
|
||||||
bool (*UpdateTexture)(SDL_Renderer *renderer, SDL_Texture *texture,
|
bool (*UpdateTexture)(SDL_Renderer *renderer, SDL_Texture *texture,
|
||||||
const SDL_Rect *rect, const void *pixels,
|
const SDL_Rect *rect, const void *pixels,
|
||||||
|
@@ -37,13 +37,6 @@
|
|||||||
|
|
||||||
// SDL surface based renderer implementation
|
// SDL surface based renderer implementation
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
SDL_Palette *palette;
|
|
||||||
Uint32 version;
|
|
||||||
int refcount;
|
|
||||||
} SW_Palette;
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
const SDL_Rect *viewport;
|
const SDL_Rect *viewport;
|
||||||
@@ -56,7 +49,6 @@ typedef struct
|
|||||||
{
|
{
|
||||||
SDL_Surface *surface;
|
SDL_Surface *surface;
|
||||||
SDL_Surface *window;
|
SDL_Surface *window;
|
||||||
SDL_HashTable *palettes;
|
|
||||||
} SW_RenderData;
|
} SW_RenderData;
|
||||||
|
|
||||||
static SDL_Surface *SW_ActivateRenderer(SDL_Renderer *renderer)
|
static SDL_Surface *SW_ActivateRenderer(SDL_Renderer *renderer)
|
||||||
@@ -110,20 +102,26 @@ static bool SW_GetOutputSize(SDL_Renderer *renderer, int *w, int *h)
|
|||||||
static bool SW_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props)
|
static bool SW_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props)
|
||||||
{
|
{
|
||||||
SDL_Surface *surface = SDL_CreateSurface(texture->w, texture->h, texture->format);
|
SDL_Surface *surface = SDL_CreateSurface(texture->w, texture->h, texture->format);
|
||||||
Uint8 r, g, b, a;
|
if (!surface) {
|
||||||
|
return SDL_SetError("Can't create surface");
|
||||||
if (!SDL_SurfaceValid(surface)) {
|
|
||||||
return SDL_SetError("Cannot create surface");
|
|
||||||
}
|
}
|
||||||
texture->internal = surface;
|
texture->internal = surface;
|
||||||
r = (Uint8)SDL_roundf(SDL_clamp(texture->color.r, 0.0f, 1.0f) * 255.0f);
|
|
||||||
g = (Uint8)SDL_roundf(SDL_clamp(texture->color.g, 0.0f, 1.0f) * 255.0f);
|
Uint8 r = (Uint8)SDL_roundf(SDL_clamp(texture->color.r, 0.0f, 1.0f) * 255.0f);
|
||||||
b = (Uint8)SDL_roundf(SDL_clamp(texture->color.b, 0.0f, 1.0f) * 255.0f);
|
Uint8 g = (Uint8)SDL_roundf(SDL_clamp(texture->color.g, 0.0f, 1.0f) * 255.0f);
|
||||||
a = (Uint8)SDL_roundf(SDL_clamp(texture->color.a, 0.0f, 1.0f) * 255.0f);
|
Uint8 b = (Uint8)SDL_roundf(SDL_clamp(texture->color.b, 0.0f, 1.0f) * 255.0f);
|
||||||
|
Uint8 a = (Uint8)SDL_roundf(SDL_clamp(texture->color.a, 0.0f, 1.0f) * 255.0f);
|
||||||
SDL_SetSurfaceColorMod(surface, r, g, b);
|
SDL_SetSurfaceColorMod(surface, r, g, b);
|
||||||
SDL_SetSurfaceAlphaMod(surface, a);
|
SDL_SetSurfaceAlphaMod(surface, a);
|
||||||
SDL_SetSurfaceBlendMode(surface, texture->blendMode);
|
SDL_SetSurfaceBlendMode(surface, texture->blendMode);
|
||||||
|
|
||||||
|
if (SDL_ISPIXELFORMAT_INDEXED(surface->format)) {
|
||||||
|
surface->palette = SDL_CreatePalette((1 << SDL_BITSPERPIXEL(surface->format)));
|
||||||
|
if (!surface->palette) {
|
||||||
|
return SDL_SetError("Can't create palette");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Only RLE encode textures without an alpha channel since the RLE coder
|
/* Only RLE encode textures without an alpha channel since the RLE coder
|
||||||
* discards the color values of pixels with an alpha value of zero.
|
* discards the color values of pixels with an alpha value of zero.
|
||||||
*/
|
*/
|
||||||
@@ -134,87 +132,12 @@ static bool SW_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_P
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SW_DestroyPalette(void *unused, const void *key, const void *value)
|
|
||||||
{
|
|
||||||
SW_Palette *internal = (SW_Palette *)value;
|
|
||||||
if (internal->palette) {
|
|
||||||
SDL_DestroyPalette(internal->palette);
|
|
||||||
}
|
|
||||||
SDL_free(internal);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool SW_ChangeTexturePalette(SDL_Renderer *renderer, SDL_Texture *texture, SDL_Palette *palette)
|
|
||||||
{
|
|
||||||
SW_RenderData *data = (SW_RenderData *)renderer->internal;
|
|
||||||
SDL_Surface *surface = (SDL_Surface *)texture->internal;
|
|
||||||
|
|
||||||
// We can't use the palette directly since it may change while drawing is in flight,
|
|
||||||
// so we'll keep a shadow of the palette that our texture surfaces will use instead.
|
|
||||||
if (!data->palettes) {
|
|
||||||
data->palettes = SDL_CreateHashTable(0, false, SDL_HashPointer, SDL_KeyMatchPointer, SW_DestroyPalette, NULL);
|
|
||||||
if (!data->palettes) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unreference our internal palette
|
|
||||||
SW_Palette *internal = NULL;
|
|
||||||
if (texture->palette) {
|
|
||||||
if (SDL_FindInHashTable(data->palettes, texture->palette, (const void **)&internal)) {
|
|
||||||
--internal->refcount;
|
|
||||||
if (internal->refcount == 0) {
|
|
||||||
SDL_RemoveFromHashTable(data->palettes, texture->palette);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (palette) {
|
|
||||||
if (SDL_FindInHashTable(data->palettes, palette, (const void **)&internal)) {
|
|
||||||
++internal->refcount;
|
|
||||||
} else {
|
|
||||||
internal = (SW_Palette *)SDL_calloc(1, sizeof(*internal));
|
|
||||||
if (!internal) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
internal->refcount = 1;
|
|
||||||
|
|
||||||
if (!SDL_InsertIntoHashTable(data->palettes, palette, internal, false)) {
|
|
||||||
SW_DestroyPalette(NULL, palette, internal);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return SDL_SetSurfacePalette(surface, internal->palette);
|
|
||||||
} else {
|
|
||||||
return SDL_SetSurfacePalette(surface, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool SW_UpdateTexturePalette(SDL_Renderer *renderer, SDL_Texture *texture)
|
static bool SW_UpdateTexturePalette(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||||
{
|
{
|
||||||
SW_RenderData *data = (SW_RenderData *)renderer->internal;
|
|
||||||
SDL_Surface *surface = (SDL_Surface *)texture->internal;
|
SDL_Surface *surface = (SDL_Surface *)texture->internal;
|
||||||
SDL_Palette *palette = texture->palette;
|
SDL_Palette *palette = texture->palette;
|
||||||
Uint32 version = palette->version;
|
|
||||||
|
|
||||||
SW_Palette *internal = NULL;
|
return SDL_SetPaletteColors(surface->palette, palette->colors, 0, palette->ncolors);
|
||||||
if (!SDL_FindInHashTable(data->palettes, palette, (const void **)&internal)) {
|
|
||||||
return SDL_SetError("Couldn't find internal palette");
|
|
||||||
}
|
|
||||||
if (internal->version != version) {
|
|
||||||
// Cycle the palette as some drawing might be in flight using the old colors
|
|
||||||
if (internal->palette) {
|
|
||||||
SDL_DestroyPalette(internal->palette);
|
|
||||||
}
|
|
||||||
internal->palette = SDL_CreatePalette(palette->ncolors);
|
|
||||||
if (!internal->palette) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!SDL_SetPaletteColors(internal->palette, palette->colors, 0, palette->ncolors)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
internal->version = version;
|
|
||||||
}
|
|
||||||
return SDL_SetSurfacePalette(surface, internal->palette);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool SW_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
|
static bool SW_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
|
||||||
@@ -1107,10 +1030,6 @@ static void SW_DestroyRenderer(SDL_Renderer *renderer)
|
|||||||
SDL_Window *window = renderer->window;
|
SDL_Window *window = renderer->window;
|
||||||
SW_RenderData *data = (SW_RenderData *)renderer->internal;
|
SW_RenderData *data = (SW_RenderData *)renderer->internal;
|
||||||
|
|
||||||
if (data->palettes) {
|
|
||||||
SDL_assert(SDL_HashTableEmpty(data->palettes));
|
|
||||||
SDL_DestroyHashTable(data->palettes);
|
|
||||||
}
|
|
||||||
if (window) {
|
if (window) {
|
||||||
SDL_DestroyWindowSurface(window);
|
SDL_DestroyWindowSurface(window);
|
||||||
}
|
}
|
||||||
@@ -1240,7 +1159,6 @@ bool SW_CreateRendererForSurface(SDL_Renderer *renderer, SDL_Surface *surface, S
|
|||||||
renderer->WindowEvent = SW_WindowEvent;
|
renderer->WindowEvent = SW_WindowEvent;
|
||||||
renderer->GetOutputSize = SW_GetOutputSize;
|
renderer->GetOutputSize = SW_GetOutputSize;
|
||||||
renderer->CreateTexture = SW_CreateTexture;
|
renderer->CreateTexture = SW_CreateTexture;
|
||||||
renderer->ChangeTexturePalette = SW_ChangeTexturePalette;
|
|
||||||
renderer->UpdateTexturePalette = SW_UpdateTexturePalette;
|
renderer->UpdateTexturePalette = SW_UpdateTexturePalette;
|
||||||
renderer->UpdateTexture = SW_UpdateTexture;
|
renderer->UpdateTexture = SW_UpdateTexture;
|
||||||
renderer->LockTexture = SW_LockTexture;
|
renderer->LockTexture = SW_LockTexture;
|
||||||
|
Reference in New Issue
Block a user