mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-09-28 16:15:55 +08:00
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:
+97
-26
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user