Each application palette corresponds to one hardware palette

When the application modifies the palette, any textures that use it will automatically be updated.
This commit is contained in:
Sam Lantinga
2025-09-28 22:10:06 -07:00
parent 5d311635cf
commit b65590159b
11 changed files with 832 additions and 451 deletions
+97 -26
View File
File diff suppressed because it is too large Load Diff
+18 -2
View File
@@ -70,6 +70,15 @@ typedef struct SDL_RenderViewState
SDL_FPoint current_scale; // this is just `scale * logical_scale`, precalculated, since we use it a lot.
} SDL_RenderViewState;
// Define the SDL texture palette structure
typedef struct SDL_TexturePalette
{
int refcount;
Uint32 version;
Uint32 last_command_generation; // last command queue generation this palette was in.
void *internal; // Driver specific palette representation
} SDL_TexturePalette;
// Define the SDL texture structure
struct SDL_Texture
{
@@ -90,7 +99,8 @@ struct SDL_Texture
SDL_ScaleMode scaleMode; // The texture scale mode
SDL_FColor color; // Texture modulation values
SDL_RenderViewState view; // Target texture view state
SDL_Palette *palette;
SDL_Palette *public_palette;
SDL_TexturePalette *palette;
Uint32 palette_version;
SDL_Surface *palette_surface;
@@ -235,7 +245,10 @@ struct SDL_Renderer
void (*InvalidateCachedState)(SDL_Renderer *renderer);
bool (*RunCommandQueue)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize);
bool (*UpdateTexturePalette)(SDL_Renderer *renderer, SDL_Texture *texture);
bool (*CreatePalette)(SDL_Renderer *renderer, SDL_TexturePalette *palette);
bool (*UpdatePalette)(SDL_Renderer *renderer, SDL_TexturePalette *palette, int ncolors, SDL_Color *colors);
void (*DestroyPalette)(SDL_Renderer *renderer, SDL_TexturePalette *palette);
bool (*ChangeTexturePalette)(SDL_Renderer *renderer, SDL_Texture *texture);
bool (*UpdateTexture)(SDL_Renderer *renderer, SDL_Texture *texture,
const SDL_Rect *rect, const void *pixels,
int pitch);
@@ -301,6 +314,9 @@ struct SDL_Renderer
SDL_Texture *target;
SDL_Mutex *target_mutex;
// The list of palettes
SDL_HashTable *palettes;
SDL_Colorspace output_colorspace;
float SDR_white_point;
float HDR_headroom;
File diff suppressed because it is too large Load Diff
+83 -49
View File
@@ -114,6 +114,13 @@ typedef struct
SDL_FColor color;
} D3D11_VertexPositionColor;
// Per-palette data
typedef struct
{
ID3D11Texture2D *texture;
ID3D11ShaderResourceView *resourceView;
} D3D11_PaletteData;
// Per-texture data
typedef struct
{
@@ -121,8 +128,6 @@ typedef struct
ID3D11Texture2D *mainTexture;
ID3D11ShaderResourceView *mainTextureResourceView;
ID3D11RenderTargetView *mainTextureRenderTargetView;
ID3D11Texture2D *paletteTexture;
ID3D11ShaderResourceView *paletteTextureResourceView;
ID3D11Texture2D *stagingTexture;
int lockedTexturePositionX;
int lockedTexturePositionY;
@@ -232,6 +237,8 @@ static const GUID SDL_DXGI_DEBUG_ALL = { 0xe48ae283, 0xda80, 0x490b, { 0x87, 0xe
#pragma GCC diagnostic pop
#endif
static bool D3D11_UpdateTextureInternal(D3D11_RenderData *rendererData, ID3D11Texture2D *texture, int bpp, int x, int y, int w, int h, const void *pixels, int pitch);
SDL_PixelFormat D3D11_DXGIFormatToSDLPixelFormat(DXGI_FORMAT dxgiFormat)
{
switch (dxgiFormat) {
@@ -1179,6 +1186,73 @@ static bool GetTextureProperty(SDL_PropertiesID props, const char *name, ID3D11T
return true;
}
static bool D3D11_CreatePalette(SDL_Renderer *renderer, SDL_TexturePalette *palette)
{
D3D11_RenderData *data = (D3D11_RenderData *)renderer->internal;
D3D11_PaletteData *palettedata = (D3D11_PaletteData *)SDL_calloc(1, sizeof(*palettedata));
if (!palettedata) {
return false;
}
palette->internal = palettedata;
if (!data->d3dDevice) {
return SDL_SetError("Device lost and couldn't be recovered");
}
D3D11_TEXTURE2D_DESC textureDesc;
SDL_zero(textureDesc);
textureDesc.Width = 256;
textureDesc.Height = 1;
textureDesc.MipLevels = 1;
textureDesc.ArraySize = 1;
textureDesc.Format = SDLPixelFormatToDXGITextureFormat(SDL_PIXELFORMAT_RGBA32, renderer->output_colorspace);
textureDesc.SampleDesc.Count = 1;
textureDesc.SampleDesc.Quality = 0;
textureDesc.MiscFlags = 0;
textureDesc.Usage = D3D11_USAGE_DEFAULT;
textureDesc.CPUAccessFlags = 0;
textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
HRESULT result = ID3D11Device_CreateTexture2D(data->d3dDevice, &textureDesc, NULL, &palettedata->texture);
if (FAILED(result)) {
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result);
}
D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc;
SDL_zero(resourceViewDesc);
resourceViewDesc.Format = SDLPixelFormatToDXGIMainResourceViewFormat(SDL_PIXELFORMAT_RGBA32, renderer->output_colorspace);
resourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
resourceViewDesc.Texture2D.MostDetailedMip = 0;
resourceViewDesc.Texture2D.MipLevels = textureDesc.MipLevels;
result = ID3D11Device_CreateShaderResourceView(data->d3dDevice,
(ID3D11Resource *)palettedata->texture,
&resourceViewDesc,
&palettedata->resourceView);
if (FAILED(result)) {
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateShaderResourceView"), result);
}
return true;
}
static bool D3D11_UpdatePalette(SDL_Renderer *renderer, SDL_TexturePalette *palette, int ncolors, SDL_Color *colors)
{
D3D11_RenderData *data = (D3D11_RenderData *)renderer->internal;
D3D11_PaletteData *palettedata = (D3D11_PaletteData *)palette->internal;
return D3D11_UpdateTextureInternal(data, palettedata->texture, 4, 0, 0, ncolors, 1, colors, ncolors * sizeof(*colors));
}
static void D3D11_DestroyPalette(SDL_Renderer *renderer, SDL_TexturePalette *palette)
{
D3D11_PaletteData *palettedata = (D3D11_PaletteData *)palette->internal;
if (palettedata) {
SAFE_RELEASE(palettedata->texture);
SAFE_RELEASE(palettedata->resourceView);
SDL_free(palettedata);
}
}
static bool D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props)
{
D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->internal;
@@ -1252,24 +1326,6 @@ static bool D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
}
SDL_SetPointerProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_D3D11_TEXTURE_POINTER, textureData->mainTexture);
if (texture->format == SDL_PIXELFORMAT_INDEX8) {
textureDesc.Width = 256;
textureDesc.Height = 1;
if (renderer->output_colorspace == SDL_COLORSPACE_SRGB_LINEAR) {
textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
} else {
textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
}
result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice,
&textureDesc,
NULL,
&textureData->paletteTexture);
if (FAILED(result)) {
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result);
}
}
#ifdef SDL_HAVE_YUV
if (texture->format == SDL_PIXELFORMAT_YV12 ||
texture->format == SDL_PIXELFORMAT_IYUV) {
@@ -1345,17 +1401,6 @@ static bool D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateShaderResourceView"), result);
}
if (texture->format == SDL_PIXELFORMAT_INDEX8) {
resourceViewDesc.Format = textureDesc.Format;
result = ID3D11Device_CreateShaderResourceView(rendererData->d3dDevice,
(ID3D11Resource *)textureData->paletteTexture,
&resourceViewDesc,
&textureData->paletteTextureResourceView);
if (FAILED(result)) {
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateShaderResourceView"), result);
}
}
#ifdef SDL_HAVE_YUV
if (textureData->yuv) {
result = ID3D11Device_CreateShaderResourceView(rendererData->d3dDevice,
@@ -1424,8 +1469,6 @@ static void D3D11_DestroyTexture(SDL_Renderer *renderer,
SAFE_RELEASE(data->mainTexture);
SAFE_RELEASE(data->mainTextureResourceView);
SAFE_RELEASE(data->mainTextureRenderTargetView);
SAFE_RELEASE(data->paletteTexture);
SAFE_RELEASE(data->paletteTextureResourceView);
SAFE_RELEASE(data->stagingTexture);
#ifdef SDL_HAVE_YUV
SAFE_RELEASE(data->mainTextureU);
@@ -1542,19 +1585,6 @@ static bool D3D11_UpdateTextureInternal(D3D11_RenderData *rendererData, ID3D11Te
return true;
}
static bool D3D11_UpdateTexturePalette(SDL_Renderer *renderer, SDL_Texture *texture)
{
D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->internal;
D3D11_TextureData *textureData = (D3D11_TextureData *)texture->internal;
SDL_Palette *palette = texture->palette;
if (!textureData) {
return SDL_SetError("Texture is not currently available");
}
return D3D11_UpdateTextureInternal(rendererData, textureData->paletteTexture, 4, 0, 0, palette->ncolors, 1, palette->colors, palette->ncolors * sizeof(*palette->colors));
}
#ifdef SDL_HAVE_YUV
static bool D3D11_UpdateTextureNV(SDL_Renderer *renderer, SDL_Texture *texture,
const SDL_Rect *rect,
@@ -2491,8 +2521,10 @@ static bool D3D11_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *
}
++numShaderSamplers;
if (texture->format == SDL_PIXELFORMAT_INDEX8) {
shaderResources[numShaderResources++] = textureData->paletteTextureResourceView;
if (texture->palette) {
D3D11_PaletteData *palette = (D3D11_PaletteData *)texture->palette->internal;
shaderResources[numShaderResources++] = palette->resourceView;
shaderSamplers[numShaderSamplers] = D3D11_GetSamplerState(rendererData, SDL_SCALEMODE_NEAREST, SDL_TEXTURE_ADDRESS_CLAMP, SDL_TEXTURE_ADDRESS_CLAMP);
if (!shaderSamplers[numShaderSamplers]) {
@@ -2846,8 +2878,10 @@ static bool D3D11_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL
renderer->WindowEvent = D3D11_WindowEvent;
renderer->SupportsBlendMode = D3D11_SupportsBlendMode;
renderer->CreatePalette = D3D11_CreatePalette;
renderer->UpdatePalette = D3D11_UpdatePalette;
renderer->DestroyPalette = D3D11_DestroyPalette;
renderer->CreateTexture = D3D11_CreateTexture;
renderer->UpdateTexturePalette = D3D11_UpdateTexturePalette;
renderer->UpdateTexture = D3D11_UpdateTexture;
#ifdef SDL_HAVE_YUV
renderer->UpdateTextureYUV = D3D11_UpdateTextureYUV;
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+62 -33
View File
@@ -125,6 +125,11 @@ typedef struct
GL_DrawStateCache drawstate;
} GL_RenderData;
typedef struct
{
GLuint texture;
} GL_PaletteData;
typedef struct
{
GLuint texture;
@@ -133,7 +138,6 @@ typedef struct
GLfloat texh;
GLenum format;
GLenum formattype;
GLuint palette;
GL_Shader shader;
float texel_size[4];
const float *shader_params;
@@ -481,6 +485,58 @@ static void SetTextureAddressMode(GL_RenderData *data, GLenum textype, SDL_Textu
data->glTexParameteri(textype, GL_TEXTURE_WRAP_T, TranslateAddressMode(addressModeV));
}
static bool GL_CreatePalette(SDL_Renderer *renderer, SDL_TexturePalette *palette)
{
GL_RenderData *data = (GL_RenderData *)renderer->internal;
GL_PaletteData *palettedata = (GL_PaletteData *)SDL_calloc(1, sizeof(*palettedata));
if (!palettedata) {
return false;
}
palette->internal = palettedata;
data->drawstate.texture = NULL; // we trash this state.
const GLenum textype = data->textype;
data->glGenTextures(1, &palettedata->texture);
data->glBindTexture(textype, palettedata->texture);
data->glTexImage2D(textype, 0, GL_RGBA8, 256, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
if (!GL_CheckError("glTexImage2D()", renderer)) {
return false;
}
SetTextureScaleMode(data, textype, SDL_SCALEMODE_NEAREST);
SetTextureAddressMode(data, textype, SDL_TEXTURE_ADDRESS_CLAMP, SDL_TEXTURE_ADDRESS_CLAMP);
return true;
}
static bool GL_UpdatePalette(SDL_Renderer *renderer, SDL_TexturePalette *palette, int ncolors, SDL_Color *colors)
{
GL_RenderData *data = (GL_RenderData *)renderer->internal;
GL_PaletteData *palettedata = (GL_PaletteData *)palette->internal;
GL_ActivateRenderer(renderer);
data->drawstate.texture = NULL; // we trash this state.
const GLenum textype = data->textype;
data->glBindTexture(textype, palettedata->texture);
data->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
data->glPixelStorei(GL_UNPACK_ROW_LENGTH, ncolors);
data->glTexSubImage2D(textype, 0, 0, 0, ncolors, 1, GL_RGBA, GL_UNSIGNED_BYTE, colors);
return GL_CheckError("glTexSubImage2D()", renderer);
}
static void GL_DestroyPalette(SDL_Renderer *renderer, SDL_TexturePalette *palette)
{
GL_RenderData *data = (GL_RenderData *)renderer->internal;
GL_PaletteData *palettedata = (GL_PaletteData *)palette->internal;
if (palettedata) {
data->glDeleteTextures(1, &palettedata->texture);
SDL_free(palettedata);
}
}
static bool GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props)
{
GL_RenderData *renderdata = (GL_RenderData *)renderer->internal;
@@ -621,14 +677,6 @@ static bool GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_P
SetTextureScaleMode(renderdata, textype, data->texture_scale_mode);
SetTextureAddressMode(renderdata, textype, data->texture_address_mode_u, data->texture_address_mode_v);
if (texture->format == SDL_PIXELFORMAT_INDEX8) {
renderdata->glGenTextures(1, &data->palette);
renderdata->glBindTexture(textype, data->palette);
renderdata->glTexImage2D(textype, 0, GL_RGBA8, 256, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
SetTextureScaleMode(renderdata, textype, SDL_SCALEMODE_NEAREST);
SetTextureAddressMode(renderdata, textype, SDL_TEXTURE_ADDRESS_CLAMP, SDL_TEXTURE_ADDRESS_CLAMP);
}
#ifdef SDL_HAVE_YUV
if (texture->format == SDL_PIXELFORMAT_YV12 ||
texture->format == SDL_PIXELFORMAT_IYUV) {
@@ -723,25 +771,6 @@ static bool GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_P
return GL_CheckError("", renderer);
}
static bool GL_UpdateTexturePalette(SDL_Renderer *renderer, SDL_Texture *texture)
{
GL_RenderData *renderdata = (GL_RenderData *)renderer->internal;
const GLenum textype = renderdata->textype;
GL_TextureData *data = (GL_TextureData *)texture->internal;
SDL_Palette *palette = texture->palette;
GL_ActivateRenderer(renderer);
renderdata->drawstate.texture = NULL; // we trash this state.
renderdata->glBindTexture(textype, data->palette);
renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, palette->ncolors);
renderdata->glTexSubImage2D(textype, 0, 0, 0, palette->ncolors, 1, GL_RGBA, GL_UNSIGNED_BYTE, palette->colors);
return GL_CheckError("glTexSubImage2D()", renderer);
}
static bool GL_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
const SDL_Rect *rect, const void *pixels, int pitch)
{
@@ -1205,8 +1234,9 @@ static bool SetCopyState(GL_RenderData *data, const SDL_RenderCommand *cmd)
}
#endif
if (texture->palette) {
GL_PaletteData *palette = (GL_PaletteData *)texture->palette->internal;
data->glActiveTextureARB(GL_TEXTURE1_ARB);
data->glBindTexture(textype, texturedata->palette);
data->glBindTexture(textype, palette->texture);
}
if (data->GL_ARB_multitexture_supported) {
data->glActiveTextureARB(GL_TEXTURE0_ARB);
@@ -1631,9 +1661,6 @@ static void GL_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
if (data->texture && !data->texture_external) {
renderdata->glDeleteTextures(1, &data->texture);
}
if (data->palette) {
renderdata->glDeleteTextures(1, &data->palette);
}
#ifdef SDL_HAVE_YUV
if (data->yuv) {
if (!data->utexture_external) {
@@ -1753,8 +1780,10 @@ static bool GL_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_Pr
renderer->WindowEvent = GL_WindowEvent;
renderer->SupportsBlendMode = GL_SupportsBlendMode;
renderer->CreatePalette = GL_CreatePalette;
renderer->UpdatePalette = GL_UpdatePalette;
renderer->DestroyPalette = GL_DestroyPalette;
renderer->CreateTexture = GL_CreateTexture;
renderer->UpdateTexturePalette = GL_UpdateTexturePalette;
renderer->UpdateTexture = GL_UpdateTexture;
#ifdef SDL_HAVE_YUV
renderer->UpdateTextureYUV = GL_UpdateTextureYUV;
+63 -42
View File
@@ -58,14 +58,18 @@ struct GLES2_FBOList
GLES2_FBOList *next;
};
typedef struct GLES2_TextureData
typedef struct
{
GLuint texture;
} GLES2_PaletteData;
typedef struct
{
GLuint texture;
bool texture_external;
GLenum texture_type;
GLenum pixel_format;
GLenum pixel_type;
GLuint palette;
void *pixel_data;
int pitch;
#ifdef SDL_HAVE_YUV
@@ -1277,8 +1281,9 @@ static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, v
}
#endif
if (texture->palette) {
GLES2_PaletteData *palette = (GLES2_PaletteData *)texture->palette->internal;
data->glActiveTexture(GL_TEXTURE1);
data->glBindTexture(tdata->texture_type, tdata->palette);
data->glBindTexture(tdata->texture_type, palette->texture);
data->glActiveTexture(GL_TEXTURE0);
}
@@ -1633,6 +1638,58 @@ static void GLES2_DestroyRenderer(SDL_Renderer *renderer)
}
}
static bool GLES2_CreatePalette(SDL_Renderer *renderer, SDL_TexturePalette *palette)
{
GLES2_RenderData *data = (GLES2_RenderData *)renderer->internal;
GLES2_PaletteData *palettedata = (GLES2_PaletteData *)SDL_calloc(1, sizeof(*palettedata));
if (!palettedata) {
return false;
}
palette->internal = palettedata;
data->drawstate.texture = NULL; // we trash this state.
data->glGenTextures(1, &palettedata->texture);
if (!GL_CheckError("glGenTexures()", renderer)) {
return false;
}
data->glActiveTexture(GL_TEXTURE1);
data->glBindTexture(GL_TEXTURE_2D, palettedata->texture);
data->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
if (!GL_CheckError("glTexImage2D()", renderer)) {
return false;
}
SetTextureScaleMode(data, GL_TEXTURE_2D, SDL_SCALEMODE_NEAREST);
SetTextureAddressMode(data, GL_TEXTURE_2D, SDL_TEXTURE_ADDRESS_CLAMP, SDL_TEXTURE_ADDRESS_CLAMP);
return true;
}
static bool GLES2_UpdatePalette(SDL_Renderer *renderer, SDL_TexturePalette *palette, int ncolors, SDL_Color *colors)
{
GLES2_RenderData *data = (GLES2_RenderData *)renderer->internal;
GLES2_PaletteData *palettedata = (GLES2_PaletteData *)palette->internal;
GLES2_ActivateRenderer(renderer);
data->drawstate.texture = NULL; // we trash this state.
data->glBindTexture(GL_TEXTURE_2D, palettedata->texture);
data->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, ncolors, 1, GL_RGBA, GL_UNSIGNED_BYTE, colors);
return GL_CheckError("glTexSubImage2D()", renderer);
}
static void GLES2_DestroyPalette(SDL_Renderer *renderer, SDL_TexturePalette *palette)
{
GLES2_RenderData *data = (GLES2_RenderData *)renderer->internal;
GLES2_PaletteData *palettedata = (GLES2_PaletteData *)palette->internal;
if (palettedata) {
data->glDeleteTextures(1, &palettedata->texture);
SDL_free(palettedata);
}
}
static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props)
{
GLES2_RenderData *renderdata = (GLES2_RenderData *)renderer->internal;
@@ -1731,25 +1788,6 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
data->texel_size[0] = 1.0f / data->texel_size[2];
data->texel_size[1] = 1.0f / data->texel_size[3];
if (texture->format == SDL_PIXELFORMAT_INDEX8) {
renderdata->glGenTextures(1, &data->palette);
if (!GL_CheckError("glGenTexures()", renderer)) {
SDL_free(data->pixel_data);
SDL_free(data);
return false;
}
renderdata->glActiveTexture(GL_TEXTURE1);
renderdata->glBindTexture(data->texture_type, data->palette);
renderdata->glTexImage2D(data->texture_type, 0, GL_RGBA, 256, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
if (!GL_CheckError("glTexImage2D()", renderer)) {
SDL_free(data->pixel_data);
SDL_free(data);
return false;
}
SetTextureScaleMode(renderdata, data->texture_type, SDL_SCALEMODE_NEAREST);
SetTextureAddressMode(renderdata, data->texture_type, SDL_TEXTURE_ADDRESS_CLAMP, SDL_TEXTURE_ADDRESS_CLAMP);
}
#ifdef SDL_HAVE_YUV
if (data->yuv) {
data->texture_v = (GLuint)SDL_GetNumberProperty(create_props, SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_V_NUMBER, 0);
@@ -1904,22 +1942,6 @@ static bool GLES2_TexSubImage2D(GLES2_RenderData *data, GLenum target, GLint xof
return true;
}
static bool GLES2_UpdateTexturePalette(SDL_Renderer *renderer, SDL_Texture *texture)
{
GLES2_RenderData *data = (GLES2_RenderData *)renderer->internal;
GLES2_TextureData *tdata = (GLES2_TextureData *)texture->internal;
SDL_Palette *palette = texture->palette;
GLES2_ActivateRenderer(renderer);
data->drawstate.texture = NULL; /* we trash this state. */
data->glBindTexture(tdata->texture_type, tdata->palette);
data->glTexSubImage2D(tdata->texture_type, 0, 0, 0, palette->ncolors, 1, GL_RGBA, GL_UNSIGNED_BYTE, palette->colors);
return GL_CheckError("glTexSubImage2D()", renderer);
}
static bool GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
const void *pixels, int pitch)
{
@@ -2160,9 +2182,6 @@ static void GLES2_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
if (tdata->texture && !tdata->texture_external) {
data->glDeleteTextures(1, &tdata->texture);
}
if (tdata->palette) {
data->glDeleteTextures(1, &tdata->palette);
}
#ifdef SDL_HAVE_YUV
if (tdata->texture_v && !tdata->texture_v_external) {
data->glDeleteTextures(1, &tdata->texture_v);
@@ -2290,8 +2309,10 @@ static bool GLES2_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL
// Populate the function pointers for the module
renderer->WindowEvent = GLES2_WindowEvent;
renderer->SupportsBlendMode = GLES2_SupportsBlendMode;
renderer->CreatePalette = GLES2_CreatePalette;
renderer->UpdatePalette = GLES2_UpdatePalette;
renderer->DestroyPalette = GLES2_DestroyPalette;
renderer->CreateTexture = GLES2_CreateTexture;
renderer->UpdateTexturePalette = GLES2_UpdateTexturePalette;
renderer->UpdateTexture = GLES2_UpdateTexture;
#ifdef SDL_HAVE_YUV
renderer->UpdateTextureYUV = GLES2_UpdateTextureYUV;
+36 -9
View File
@@ -99,6 +99,38 @@ static bool SW_GetOutputSize(SDL_Renderer *renderer, int *w, int *h)
return SDL_SetError("Software renderer doesn't have an output surface");
}
static bool SW_CreatePalette(SDL_Renderer *renderer, SDL_TexturePalette *palette)
{
SDL_Palette *surface_palette = SDL_CreatePalette(256);
if (!surface_palette) {
return false;
}
palette->internal = surface_palette;
return true;
}
static bool SW_UpdatePalette(SDL_Renderer *renderer, SDL_TexturePalette *palette, int ncolors, SDL_Color *colors)
{
SDL_Palette *surface_palette = (SDL_Palette *)palette->internal;
return SDL_SetPaletteColors(surface_palette, colors, 0, ncolors);
}
static void SW_DestroyPalette(SDL_Renderer *renderer, SDL_TexturePalette *palette)
{
SDL_Palette *surface_palette = (SDL_Palette *)palette->internal;
SDL_DestroyPalette(surface_palette);
}
static bool SW_ChangeTexturePalette(SDL_Renderer *renderer, SDL_Texture *texture)
{
SDL_Surface *surface = (SDL_Surface *)texture->internal;
SDL_Palette *surface_palette = NULL;
if (texture->palette) {
surface_palette = (SDL_Palette *)texture->palette->internal;
}
return SDL_SetSurfacePalette(surface, surface_palette);
}
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);
@@ -132,14 +164,6 @@ static bool SW_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_P
return true;
}
static bool SW_UpdateTexturePalette(SDL_Renderer *renderer, SDL_Texture *texture)
{
SDL_Surface *surface = (SDL_Surface *)texture->internal;
SDL_Palette *palette = texture->palette;
return SDL_SetPaletteColors(surface->palette, palette->colors, 0, palette->ncolors);
}
static bool SW_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
const SDL_Rect *rect, const void *pixels, int pitch)
{
@@ -1158,8 +1182,11 @@ bool SW_CreateRendererForSurface(SDL_Renderer *renderer, SDL_Surface *surface, S
renderer->WindowEvent = SW_WindowEvent;
renderer->GetOutputSize = SW_GetOutputSize;
renderer->CreatePalette = SW_CreatePalette;
renderer->UpdatePalette = SW_UpdatePalette;
renderer->DestroyPalette = SW_DestroyPalette;
renderer->ChangeTexturePalette = SW_ChangeTexturePalette;
renderer->CreateTexture = SW_CreateTexture;
renderer->UpdateTexturePalette = SW_UpdateTexturePalette;
renderer->UpdateTexture = SW_UpdateTexture;
renderer->LockTexture = SW_LockTexture;
renderer->UnlockTexture = SW_UnlockTexture;
+56 -40
View File
@@ -240,11 +240,16 @@ typedef struct
VkFormat format;
} VULKAN_Image;
// Per-palette data
typedef struct
{
VULKAN_Image image;
} VULKAN_PaletteData;
// Per-texture data
typedef struct
{
VULKAN_Image mainImage;
VULKAN_Image paletteImage;
VkRenderPass mainRenderpasses[VULKAN_RENDERPASS_COUNT];
VkFramebuffer mainFramebuffer;
VULKAN_Buffer stagingBuffer;
@@ -384,6 +389,8 @@ typedef struct
bool issueBatch;
} VULKAN_RenderData;
static bool VULKAN_UpdateTextureInternal(VULKAN_RenderData *rendererData, VkImage image, VkFormat format, int plane, int x, int y, int w, int h, const void *pixels, int pitch, VkImageLayout *imageLayout);
static SDL_PixelFormat VULKAN_VkFormatToSDLPixelFormat(VkFormat vkFormat)
{
switch (vkFormat) {
@@ -2533,6 +2540,45 @@ static bool VULKAN_SupportsBlendMode(SDL_Renderer *renderer, SDL_BlendMode blend
return true;
}
static bool VULKAN_CreatePalette(SDL_Renderer *renderer, SDL_TexturePalette *palette)
{
VULKAN_RenderData *data = (VULKAN_RenderData *)renderer->internal;
VULKAN_PaletteData *palettedata = (VULKAN_PaletteData *)SDL_calloc(1, sizeof(*palettedata));
if (!palettedata) {
return false;
}
palette->internal = palettedata;
VkFormat format = SDLPixelFormatToVkTextureFormat(SDL_PIXELFORMAT_RGBA32, renderer->output_colorspace);
VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
VkComponentMapping imageViewSwizzle = data->identitySwizzle;
VkResult result = VULKAN_AllocateImage(data, 0, 256, 1, format, usage, imageViewSwizzle, VK_NULL_HANDLE, &palettedata->image);
if (result != VK_SUCCESS) {
SET_ERROR_CODE("VULKAN_AllocateImage()", result);
return false;
}
return true;
}
static bool VULKAN_UpdatePalette(SDL_Renderer *renderer, SDL_TexturePalette *palette, int ncolors, SDL_Color *colors)
{
VULKAN_RenderData *data = (VULKAN_RenderData *)renderer->internal;
VULKAN_PaletteData *palettedata = (VULKAN_PaletteData *)palette->internal;
return VULKAN_UpdateTextureInternal(data, palettedata->image.image, palettedata->image.format, 0, 0, 0, ncolors, 1, colors, ncolors * sizeof(*colors), &palettedata->image.imageLayout);
}
static void VULKAN_DestroyPalette(SDL_Renderer *renderer, SDL_TexturePalette *palette)
{
VULKAN_RenderData *data = (VULKAN_RenderData *)renderer->internal;
VULKAN_PaletteData *palettedata = (VULKAN_PaletteData *)palette->internal;
if (palettedata) {
VULKAN_DestroyImage(data, &palettedata->image);
SDL_free(palettedata);
}
}
static bool VULKAN_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props)
{
VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
@@ -2694,21 +2740,6 @@ static bool VULKAN_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, S
return false;
}
if (texture->format == SDL_PIXELFORMAT_INDEX8) {
VkFormat paletteFormat;
if (renderer->output_colorspace == SDL_COLORSPACE_SRGB_LINEAR) {
paletteFormat = VK_FORMAT_R8G8B8A8_SRGB;
} else {
paletteFormat = VK_FORMAT_R8G8B8A8_UNORM;
}
result = VULKAN_AllocateImage(rendererData, 0, 256, 1, paletteFormat, usage, imageViewSwizzle, textureData->samplerYcbcrConversion, &textureData->paletteImage);
if (result != VK_SUCCESS) {
SET_ERROR_CODE("VULKAN_AllocateImage()", result);
return false;
}
}
SDL_PropertiesID props = SDL_GetTextureProperties(texture);
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_VULKAN_TEXTURE_NUMBER, (Sint64)textureData->mainImage.image);
@@ -2746,10 +2777,6 @@ static void VULKAN_DestroyTexture(SDL_Renderer *renderer,
VULKAN_DestroyImage(rendererData, &textureData->mainImage);
if (texture->format == SDL_PIXELFORMAT_INDEX8) {
VULKAN_DestroyImage(rendererData, &textureData->paletteImage);
}
#ifdef SDL_HAVE_YUV
if (textureData->samplerYcbcrConversion != VK_NULL_HANDLE) {
vkDestroySamplerYcbcrConversionKHR(rendererData->device, textureData->samplerYcbcrConversion, NULL);
@@ -2876,20 +2903,6 @@ static bool VULKAN_UpdateTextureInternal(VULKAN_RenderData *rendererData, VkImag
return true;
}
static bool VULKAN_UpdateTexturePalette(SDL_Renderer *renderer, SDL_Texture *texture)
{
VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
VULKAN_TextureData *textureData = (VULKAN_TextureData *)texture->internal;
SDL_Palette *palette = texture->palette;
if (!textureData) {
return SDL_SetError("Texture is not currently available");
}
return VULKAN_UpdateTextureInternal(rendererData, textureData->paletteImage.image, textureData->paletteImage.format, 0, 0, 0, palette->ncolors, 1, palette->colors, palette->ncolors * sizeof(*palette->colors), &textureData->paletteImage.imageLayout);
}
static bool VULKAN_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
const SDL_Rect *rect, const void *srcPixels,
int srcPitch)
@@ -3900,8 +3913,9 @@ static bool VULKAN_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand
}
++numSamplers;
if (texture->format == SDL_PIXELFORMAT_INDEX8) {
if (textureData->paletteImage.imageLayout != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
if (texture->palette) {
VULKAN_PaletteData *palette = (VULKAN_PaletteData *)texture->palette->internal;
if (palette->image.imageLayout != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
bool stoppedRenderPass = false;
if (rendererData->currentRenderPass != VK_NULL_HANDLE) {
vkCmdEndRenderPass(rendererData->currentCommandBuffer);
@@ -3915,14 +3929,14 @@ static bool VULKAN_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand
VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
textureData->paletteImage.image,
&textureData->paletteImage.imageLayout);
palette->image.image,
&palette->image.imageLayout);
if (stoppedRenderPass) {
VULKAN_BeginRenderPass(rendererData, VK_ATTACHMENT_LOAD_OP_LOAD, NULL);
}
}
imageViews[numImageViews++] = textureData->paletteImage.imageView;
imageViews[numImageViews++] = palette->image.imageView;
samplers[numSamplers] = VULKAN_GetSampler(rendererData, SDL_SCALEMODE_NEAREST, SDL_TEXTURE_ADDRESS_CLAMP, SDL_TEXTURE_ADDRESS_CLAMP);
if (samplers[numSamplers] == VK_NULL_HANDLE) {
@@ -4391,8 +4405,10 @@ static bool VULKAN_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SD
renderer->WindowEvent = VULKAN_WindowEvent;
renderer->SupportsBlendMode = VULKAN_SupportsBlendMode;
renderer->CreatePalette = VULKAN_CreatePalette;
renderer->UpdatePalette = VULKAN_UpdatePalette;
renderer->DestroyPalette = VULKAN_DestroyPalette;
renderer->CreateTexture = VULKAN_CreateTexture;
renderer->UpdateTexturePalette = VULKAN_UpdateTexturePalette;
renderer->UpdateTexture = VULKAN_UpdateTexture;
#ifdef SDL_HAVE_YUV
renderer->UpdateTextureYUV = VULKAN_UpdateTextureYUV;