@@ -347,6 +347,15 @@ static bool FlushRenderCommandsIfTextureNeeded(SDL_Texture *texture)
347347 return true;
348348}
349349
350+ static bool FlushRenderCommandsIfPaletteNeeded (SDL_Renderer * renderer , SDL_TexturePalette * palette )
351+ {
352+ if (palette -> last_command_generation == renderer -> render_command_generation ) {
353+ // the current command queue depends on this palette, flush the queue now before it changes
354+ return FlushRenderCommands (renderer );
355+ }
356+ return true;
357+ }
358+
350359static bool FlushRenderCommandsIfGPURenderStateNeeded (SDL_GPURenderState * state )
351360{
352361 SDL_Renderer * renderer = state -> renderer ;
@@ -700,20 +709,22 @@ static bool QueueCmdFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, co
700709static bool UpdateTexturePalette (SDL_Texture * texture )
701710{
702711 SDL_Renderer * renderer = texture -> renderer ;
712+ SDL_Palette * public = texture -> public_palette ;
703713
704714 if (!SDL_ISPIXELFORMAT_INDEXED (texture -> format )) {
705715 return true;
706716 }
707717
708- if (!texture -> palette ) {
718+ if (!public ) {
709719 return SDL_SetError ("Texture doesn't have a palette" );
710720 }
711721
712- if (texture -> palette_version == texture -> palette -> version ) {
713- return true;
714- }
715-
716722 if (texture -> native ) {
723+ // Keep the native texture in sync with palette updates
724+ if (texture -> palette_version == public -> version ) {
725+ return true;
726+ }
727+
717728 if (!FlushRenderCommandsIfTextureNeeded (texture -> native )) {
718729 return false;
719730 }
@@ -727,17 +738,25 @@ static bool UpdateTexturePalette(SDL_Texture *texture)
727738 if (!result ) {
728739 return false;
729740 }
730- } else {
731- if (!FlushRenderCommandsIfTextureNeeded (texture )) {
741+ texture -> palette_version = public -> version ;
742+ return true;
743+ }
744+
745+ SDL_TexturePalette * palette = texture -> palette ;
746+ if (palette -> version != public -> version ) {
747+ // Keep the native palette in sync with palette updates
748+ if (!FlushRenderCommandsIfPaletteNeeded (renderer , palette )) {
732749 return false;
733750 }
734751
735- if (!renderer -> UpdateTexturePalette (renderer , texture )) {
752+ if (!renderer -> UpdatePalette (renderer , palette , public -> ncolors , public -> colors )) {
736753 return false;
737754 }
755+
756+ palette -> version = public -> version ;
738757 }
739758
740- texture -> palette_version = texture -> palette -> version ;
759+ palette -> last_command_generation = renderer -> render_command_generation ;
741760 return true;
742761}
743762
@@ -1143,6 +1162,11 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
11431162 UpdatePixelClipRect (renderer , & renderer -> main_view );
11441163 UpdateMainViewDimensions (renderer );
11451164
1165+ renderer -> palettes = SDL_CreateHashTable (0 , false, SDL_HashPointer , SDL_KeyMatchPointer , SDL_DestroyHashValue , NULL );
1166+ if (!renderer -> palettes ) {
1167+ goto error ;
1168+ }
1169+
11461170 // new textures start at zero, so we start at 1 so first render doesn't flush by accident.
11471171 renderer -> render_command_generation = 1 ;
11481172
@@ -1656,7 +1680,7 @@ static bool SDL_UpdateTextureFromSurface(SDL_Texture *texture, SDL_Rect *rect, S
16561680 bool direct_update ;
16571681
16581682 if (surface -> format == texture -> format &&
1659- surface -> palette == texture -> palette &&
1683+ surface -> palette == texture -> public_palette &&
16601684 SDL_GetSurfaceColorspace (surface ) == texture -> colorspace ) {
16611685 if (SDL_ISPIXELFORMAT_ALPHA (surface -> format ) && SDL_SurfaceHasColorKey (surface )) {
16621686 /* Surface and Renderer formats are identical.
@@ -1682,7 +1706,7 @@ static bool SDL_UpdateTextureFromSurface(SDL_Texture *texture, SDL_Rect *rect, S
16821706 }
16831707 } else {
16841708 // Set up a destination surface for the texture update
1685- SDL_Surface * temp = SDL_ConvertSurfaceAndColorspace (surface , texture -> format , texture -> palette , texture -> colorspace , SDL_GetSurfaceProperties (surface ));
1709+ SDL_Surface * temp = SDL_ConvertSurfaceAndColorspace (surface , texture -> format , texture -> public_palette , texture -> colorspace , SDL_GetSurfaceProperties (surface ));
16861710 if (temp ) {
16871711 SDL_UpdateTexture (texture , NULL , temp -> pixels , temp -> pitch );
16881712 SDL_DestroySurface (temp );
@@ -1901,16 +1925,56 @@ bool SDL_SetTexturePalette(SDL_Texture *texture, SDL_Palette *palette)
19011925 return SDL_SetError ("SDL_SetSurfacePalette() passed a palette that doesn't match the surface format" );
19021926 }
19031927
1904- if (palette != texture -> palette ) {
1905- if (texture -> palette ) {
1906- SDL_DestroyPalette (texture -> palette );
1928+ if (palette != texture -> public_palette ) {
1929+ SDL_Renderer * renderer = texture -> renderer ;
1930+
1931+ if (texture -> public_palette ) {
1932+ SDL_DestroyPalette (texture -> public_palette );
1933+
1934+ if (!texture -> native ) {
1935+ // Clean up the texture palette
1936+ -- texture -> palette -> refcount ;
1937+ if (texture -> palette -> refcount == 0 ) {
1938+ renderer -> DestroyPalette (renderer , texture -> palette );
1939+ SDL_RemoveFromHashTable (renderer -> palettes , texture -> public_palette );
1940+ }
1941+ texture -> palette = NULL ;
1942+ }
19071943 }
19081944
1909- texture -> palette = palette ;
1945+ texture -> public_palette = palette ;
19101946 texture -> palette_version = 0 ;
19111947
1912- if (texture -> palette ) {
1913- ++ texture -> palette -> refcount ;
1948+ if (texture -> public_palette ) {
1949+ ++ texture -> public_palette -> refcount ;
1950+
1951+ if (!texture -> native ) {
1952+ if (SDL_FindInHashTable (renderer -> palettes , palette , (const void * * )& texture -> palette )) {
1953+ ++ texture -> palette -> refcount ;
1954+ } else {
1955+ SDL_TexturePalette * texture_palette = (SDL_TexturePalette * )SDL_calloc (1 , sizeof (* texture_palette ));
1956+ if (!texture_palette ) {
1957+ SDL_SetTexturePalette (texture , NULL );
1958+ return false;
1959+ }
1960+ if (!renderer -> CreatePalette (renderer , texture_palette )) {
1961+ renderer -> DestroyPalette (renderer , texture_palette );
1962+ SDL_SetTexturePalette (texture , NULL );
1963+ return false;
1964+ }
1965+ texture -> palette = texture_palette ;
1966+ texture -> palette -> refcount = 1 ;
1967+
1968+ if (!SDL_InsertIntoHashTable (renderer -> palettes , palette , texture -> palette , false)) {
1969+ SDL_SetTexturePalette (texture , NULL );
1970+ return false;
1971+ }
1972+ }
1973+ }
1974+
1975+ if (!texture -> native && renderer -> ChangeTexturePalette ) {
1976+ renderer -> ChangeTexturePalette (renderer , texture );
1977+ }
19141978 }
19151979
19161980 if (texture -> palette_surface ) {
@@ -1924,7 +1988,7 @@ SDL_Palette *SDL_GetTexturePalette(SDL_Texture *texture)
19241988{
19251989 CHECK_TEXTURE_MAGIC (texture , NULL );
19261990
1927- return texture -> palette ;
1991+ return texture -> public_palette ;
19281992}
19291993
19301994bool SDL_SetTextureColorMod (SDL_Texture * texture , Uint8 r , Uint8 g , Uint8 b )
@@ -2602,8 +2666,8 @@ bool SDL_LockTextureToSurface(SDL_Texture *texture, const SDL_Rect *rect, SDL_Su
26022666 SDL_UnlockTexture (texture );
26032667 return false;
26042668 }
2605- if (texture -> palette ) {
2606- SDL_SetSurfacePalette (texture -> locked_surface , texture -> palette );
2669+ if (texture -> public_palette ) {
2670+ SDL_SetSurfacePalette (texture -> locked_surface , texture -> public_palette );
26072671 }
26082672
26092673 * surface = texture -> locked_surface ;
@@ -5513,7 +5577,7 @@ static void SDL_DestroyTextureInternal(SDL_Texture *texture, bool is_destroying)
55135577{
55145578 SDL_Renderer * renderer ;
55155579
5516- if (texture -> palette ) {
5580+ if (texture -> public_palette ) {
55175581 SDL_SetTexturePalette (texture , NULL );
55185582 }
55195583
@@ -5634,6 +5698,13 @@ void SDL_DestroyRendererWithoutFreeing(SDL_Renderer *renderer)
56345698 SDL_assert (tex != renderer -> textures ); // satisfy static analysis.
56355699 }
56365700
5701+ // Free palette cache, which should be empty now
5702+ if (renderer -> palettes ) {
5703+ SDL_assert (SDL_HashTableEmpty (renderer -> palettes ));
5704+ SDL_DestroyHashTable (renderer -> palettes );
5705+ renderer -> palettes = NULL ;
5706+ }
5707+
56375708 // Clean up renderer-specific resources
56385709 if (renderer -> DestroyRenderer ) {
56395710 renderer -> DestroyRenderer (renderer );
0 commit comments