mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-10-03 08:28:29 +00: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:
@@ -347,6 +347,15 @@ static bool FlushRenderCommandsIfTextureNeeded(SDL_Texture *texture)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool FlushRenderCommandsIfPaletteNeeded(SDL_Renderer *renderer, SDL_TexturePalette *palette)
|
||||
{
|
||||
if (palette->last_command_generation == renderer->render_command_generation) {
|
||||
// the current command queue depends on this palette, flush the queue now before it changes
|
||||
return FlushRenderCommands(renderer);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool FlushRenderCommandsIfGPURenderStateNeeded(SDL_GPURenderState *state)
|
||||
{
|
||||
SDL_Renderer *renderer = state->renderer;
|
||||
@@ -700,20 +709,22 @@ static bool QueueCmdFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, co
|
||||
static bool UpdateTexturePalette(SDL_Texture *texture)
|
||||
{
|
||||
SDL_Renderer *renderer = texture->renderer;
|
||||
SDL_Palette *public = texture->public_palette;
|
||||
|
||||
if (!SDL_ISPIXELFORMAT_INDEXED(texture->format)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!texture->palette) {
|
||||
if (!public) {
|
||||
return SDL_SetError("Texture doesn't have a palette");
|
||||
}
|
||||
|
||||
if (texture->palette_version == texture->palette->version) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (texture->native) {
|
||||
// Keep the native texture in sync with palette updates
|
||||
if (texture->palette_version == public->version) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!FlushRenderCommandsIfTextureNeeded(texture->native)) {
|
||||
return false;
|
||||
}
|
||||
@@ -727,17 +738,25 @@ static bool UpdateTexturePalette(SDL_Texture *texture)
|
||||
if (!result) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!FlushRenderCommandsIfTextureNeeded(texture)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!renderer->UpdateTexturePalette(renderer, texture)) {
|
||||
return false;
|
||||
}
|
||||
texture->palette_version = public->version;
|
||||
return true;
|
||||
}
|
||||
|
||||
texture->palette_version = texture->palette->version;
|
||||
SDL_TexturePalette *palette = texture->palette;
|
||||
if (palette->version != public->version) {
|
||||
// Keep the native palette in sync with palette updates
|
||||
if (!FlushRenderCommandsIfPaletteNeeded(renderer, palette)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!renderer->UpdatePalette(renderer, palette, public->ncolors, public->colors)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
palette->version = public->version;
|
||||
}
|
||||
|
||||
palette->last_command_generation = renderer->render_command_generation;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1143,6 +1162,11 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
|
||||
UpdatePixelClipRect(renderer, &renderer->main_view);
|
||||
UpdateMainViewDimensions(renderer);
|
||||
|
||||
renderer->palettes = SDL_CreateHashTable(0, false, SDL_HashPointer, SDL_KeyMatchPointer, SDL_DestroyHashValue, NULL);
|
||||
if (!renderer->palettes) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
// new textures start at zero, so we start at 1 so first render doesn't flush by accident.
|
||||
renderer->render_command_generation = 1;
|
||||
|
||||
@@ -1656,7 +1680,7 @@ static bool SDL_UpdateTextureFromSurface(SDL_Texture *texture, SDL_Rect *rect, S
|
||||
bool direct_update;
|
||||
|
||||
if (surface->format == texture->format &&
|
||||
surface->palette == texture->palette &&
|
||||
surface->palette == texture->public_palette &&
|
||||
SDL_GetSurfaceColorspace(surface) == texture->colorspace) {
|
||||
if (SDL_ISPIXELFORMAT_ALPHA(surface->format) && SDL_SurfaceHasColorKey(surface)) {
|
||||
/* Surface and Renderer formats are identical.
|
||||
@@ -1682,7 +1706,7 @@ static bool SDL_UpdateTextureFromSurface(SDL_Texture *texture, SDL_Rect *rect, S
|
||||
}
|
||||
} else {
|
||||
// Set up a destination surface for the texture update
|
||||
SDL_Surface *temp = SDL_ConvertSurfaceAndColorspace(surface, texture->format, texture->palette, texture->colorspace, SDL_GetSurfaceProperties(surface));
|
||||
SDL_Surface *temp = SDL_ConvertSurfaceAndColorspace(surface, texture->format, texture->public_palette, texture->colorspace, SDL_GetSurfaceProperties(surface));
|
||||
if (temp) {
|
||||
SDL_UpdateTexture(texture, NULL, temp->pixels, temp->pitch);
|
||||
SDL_DestroySurface(temp);
|
||||
@@ -1901,16 +1925,56 @@ bool SDL_SetTexturePalette(SDL_Texture *texture, SDL_Palette *palette)
|
||||
return SDL_SetError("SDL_SetSurfacePalette() passed a palette that doesn't match the surface format");
|
||||
}
|
||||
|
||||
if (palette != texture->palette) {
|
||||
if (texture->palette) {
|
||||
SDL_DestroyPalette(texture->palette);
|
||||
if (palette != texture->public_palette) {
|
||||
SDL_Renderer *renderer = texture->renderer;
|
||||
|
||||
if (texture->public_palette) {
|
||||
SDL_DestroyPalette(texture->public_palette);
|
||||
|
||||
if (!texture->native) {
|
||||
// Clean up the texture palette
|
||||
--texture->palette->refcount;
|
||||
if (texture->palette->refcount == 0) {
|
||||
renderer->DestroyPalette(renderer, texture->palette);
|
||||
SDL_RemoveFromHashTable(renderer->palettes, texture->public_palette);
|
||||
}
|
||||
texture->palette = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
texture->palette = palette;
|
||||
texture->public_palette = palette;
|
||||
texture->palette_version = 0;
|
||||
|
||||
if (texture->palette) {
|
||||
++texture->palette->refcount;
|
||||
if (texture->public_palette) {
|
||||
++texture->public_palette->refcount;
|
||||
|
||||
if (!texture->native) {
|
||||
if (SDL_FindInHashTable(renderer->palettes, palette, (const void **)&texture->palette)) {
|
||||
++texture->palette->refcount;
|
||||
} else {
|
||||
SDL_TexturePalette *texture_palette = (SDL_TexturePalette *)SDL_calloc(1, sizeof(*texture_palette));
|
||||
if (!texture_palette) {
|
||||
SDL_SetTexturePalette(texture, NULL);
|
||||
return false;
|
||||
}
|
||||
if (!renderer->CreatePalette(renderer, texture_palette)) {
|
||||
renderer->DestroyPalette(renderer, texture_palette);
|
||||
SDL_SetTexturePalette(texture, NULL);
|
||||
return false;
|
||||
}
|
||||
texture->palette = texture_palette;
|
||||
texture->palette->refcount = 1;
|
||||
|
||||
if (!SDL_InsertIntoHashTable(renderer->palettes, palette, texture->palette, false)) {
|
||||
SDL_SetTexturePalette(texture, NULL);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!texture->native && renderer->ChangeTexturePalette) {
|
||||
renderer->ChangeTexturePalette(renderer, texture);
|
||||
}
|
||||
}
|
||||
|
||||
if (texture->palette_surface) {
|
||||
@@ -1924,7 +1988,7 @@ SDL_Palette *SDL_GetTexturePalette(SDL_Texture *texture)
|
||||
{
|
||||
CHECK_TEXTURE_MAGIC(texture, NULL);
|
||||
|
||||
return texture->palette;
|
||||
return texture->public_palette;
|
||||
}
|
||||
|
||||
bool 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
|
||||
SDL_UnlockTexture(texture);
|
||||
return false;
|
||||
}
|
||||
if (texture->palette) {
|
||||
SDL_SetSurfacePalette(texture->locked_surface, texture->palette);
|
||||
if (texture->public_palette) {
|
||||
SDL_SetSurfacePalette(texture->locked_surface, texture->public_palette);
|
||||
}
|
||||
|
||||
*surface = texture->locked_surface;
|
||||
@@ -5513,7 +5577,7 @@ static void SDL_DestroyTextureInternal(SDL_Texture *texture, bool is_destroying)
|
||||
{
|
||||
SDL_Renderer *renderer;
|
||||
|
||||
if (texture->palette) {
|
||||
if (texture->public_palette) {
|
||||
SDL_SetTexturePalette(texture, NULL);
|
||||
}
|
||||
|
||||
@@ -5634,6 +5698,13 @@ void SDL_DestroyRendererWithoutFreeing(SDL_Renderer *renderer)
|
||||
SDL_assert(tex != renderer->textures); // satisfy static analysis.
|
||||
}
|
||||
|
||||
// Free palette cache, which should be empty now
|
||||
if (renderer->palettes) {
|
||||
SDL_assert(SDL_HashTableEmpty(renderer->palettes));
|
||||
SDL_DestroyHashTable(renderer->palettes);
|
||||
renderer->palettes = NULL;
|
||||
}
|
||||
|
||||
// Clean up renderer-specific resources
|
||||
if (renderer->DestroyRenderer) {
|
||||
renderer->DestroyRenderer(renderer);
|
||||
|
@@ -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;
|
||||
|
@@ -48,6 +48,26 @@ typedef struct
|
||||
const float *shader_params;
|
||||
} D3D_DrawStateCache;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool dirty;
|
||||
int w, h;
|
||||
DWORD usage;
|
||||
Uint32 format;
|
||||
D3DFORMAT d3dfmt;
|
||||
IDirect3DTexture9 *texture;
|
||||
IDirect3DTexture9 *staging;
|
||||
} D3D_TextureRep;
|
||||
|
||||
struct D3D_PaletteData
|
||||
{
|
||||
D3D_TextureRep texture;
|
||||
|
||||
struct D3D_PaletteData *prev;
|
||||
struct D3D_PaletteData *next;
|
||||
};
|
||||
typedef struct D3D_PaletteData D3D_PaletteData;
|
||||
|
||||
// Direct3D renderer implementation
|
||||
|
||||
typedef struct
|
||||
@@ -74,23 +94,12 @@ typedef struct
|
||||
int currentVertexBuffer;
|
||||
bool reportedVboProblem;
|
||||
D3D_DrawStateCache drawstate;
|
||||
D3D_PaletteData *palettes;
|
||||
} D3D_RenderData;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool dirty;
|
||||
int w, h;
|
||||
DWORD usage;
|
||||
Uint32 format;
|
||||
D3DFORMAT d3dfmt;
|
||||
IDirect3DTexture9 *texture;
|
||||
IDirect3DTexture9 *staging;
|
||||
} D3D_TextureRep;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
D3D_TextureRep texture;
|
||||
D3D_TextureRep palette;
|
||||
D3D9_Shader shader;
|
||||
const float *shader_params;
|
||||
|
||||
@@ -532,6 +541,99 @@ static void D3D_DestroyTextureRep(D3D_TextureRep *texture)
|
||||
}
|
||||
}
|
||||
|
||||
static bool D3D_CreatePalette(SDL_Renderer *renderer, SDL_TexturePalette *palette)
|
||||
{
|
||||
D3D_RenderData *data = (D3D_RenderData *)renderer->internal;
|
||||
D3D_PaletteData *palettedata = (D3D_PaletteData *)SDL_calloc(1, sizeof(*palettedata));
|
||||
if (!palettedata) {
|
||||
return false;
|
||||
}
|
||||
palette->internal = palettedata;
|
||||
|
||||
if (!D3D_CreateTextureRep(data->device, &palettedata->texture, 0, SDL_PIXELFORMAT_ARGB8888, D3DFMT_A8R8G8B8, 256, 1)) {
|
||||
SDL_free(palettedata);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Keep a reference to the palette so we can restore the texture if we lose the D3D device
|
||||
if (data->palettes) {
|
||||
palettedata->next = data->palettes;
|
||||
data->palettes->prev = palettedata;
|
||||
}
|
||||
data->palettes = palettedata;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool D3D_UpdatePalette(SDL_Renderer *renderer, SDL_TexturePalette *palette, int ncolors, SDL_Color *colors)
|
||||
{
|
||||
D3D_RenderData *data = (D3D_RenderData *)renderer->internal;
|
||||
D3D_PaletteData *palettedata = (D3D_PaletteData *)palette->internal;
|
||||
bool retval;
|
||||
|
||||
Uint32 *entries = SDL_stack_alloc(Uint32, ncolors);
|
||||
if (!entries) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < ncolors; ++i) {
|
||||
entries[i] = (colors[i].a << 24) | (colors[i].r << 16) | (colors[i].g << 8) | colors[i].b;
|
||||
}
|
||||
retval = D3D_UpdateTextureRep(data->device, &palettedata->texture, 0, 0, ncolors, 1, entries, ncolors * sizeof(*entries));
|
||||
SDL_stack_free(entries);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void D3D_DestroyPalette(SDL_Renderer *renderer, SDL_TexturePalette *palette)
|
||||
{
|
||||
D3D_RenderData *data = (D3D_RenderData *)renderer->internal;
|
||||
D3D_PaletteData *palettedata = (D3D_PaletteData *)palette->internal;
|
||||
|
||||
if (palettedata) {
|
||||
D3D_DestroyTextureRep(&palettedata->texture);
|
||||
|
||||
if (data->palettes == palettedata) {
|
||||
data->palettes = palettedata->next;
|
||||
} else if (palettedata->prev) {
|
||||
palettedata->prev->next = palettedata->next;
|
||||
}
|
||||
if (palettedata->next) {
|
||||
palettedata->next->prev = palettedata->prev;
|
||||
}
|
||||
SDL_free(palettedata);
|
||||
}
|
||||
}
|
||||
|
||||
static bool D3D_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
|
||||
const SDL_Rect *rect, const void *pixels, int pitch)
|
||||
{
|
||||
D3D_RenderData *data = (D3D_RenderData *)renderer->internal;
|
||||
D3D_TextureData *texturedata = (D3D_TextureData *)texture->internal;
|
||||
|
||||
if (!texturedata) {
|
||||
return SDL_SetError("Texture is not currently available");
|
||||
}
|
||||
|
||||
if (!D3D_UpdateTextureRep(data->device, &texturedata->texture, rect->x, rect->y, rect->w, rect->h, pixels, pitch)) {
|
||||
return false;
|
||||
}
|
||||
#ifdef SDL_HAVE_YUV
|
||||
if (texturedata->yuv) {
|
||||
// Skip to the correct offset into the next texture
|
||||
pixels = (const void *)((const Uint8 *)pixels + rect->h * pitch);
|
||||
|
||||
if (!D3D_UpdateTextureRep(data->device, texture->format == SDL_PIXELFORMAT_YV12 ? &texturedata->vtexture : &texturedata->utexture, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, pixels, (pitch + 1) / 2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Skip to the correct offset into the next texture
|
||||
pixels = (const void *)((const Uint8 *)pixels + ((rect->h + 1) / 2) * ((pitch + 1) / 2));
|
||||
if (!D3D_UpdateTextureRep(data->device, texture->format == SDL_PIXELFORMAT_YV12 ? &texturedata->utexture : &texturedata->vtexture, rect->x / 2, (rect->y + 1) / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, pixels, (pitch + 1) / 2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool D3D_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props)
|
||||
{
|
||||
D3D_RenderData *data = (D3D_RenderData *)renderer->internal;
|
||||
@@ -555,10 +657,6 @@ static bool D3D_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_
|
||||
return false;
|
||||
}
|
||||
if (texture->format == SDL_PIXELFORMAT_INDEX8) {
|
||||
if (!D3D_CreateTextureRep(data->device, &texturedata->palette, usage, SDL_PIXELFORMAT_ARGB8888, D3DFMT_A8R8G8B8, 256, 1)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
texturedata->shader = SHADER_PALETTE;
|
||||
}
|
||||
#ifdef SDL_HAVE_YUV
|
||||
@@ -596,12 +694,6 @@ static bool D3D_RecreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||
if (!D3D_RecreateTextureRep(data->device, &texturedata->texture)) {
|
||||
return false;
|
||||
}
|
||||
if (texture->format == SDL_PIXELFORMAT_INDEX8) {
|
||||
if (!D3D_RecreateTextureRep(data->device, &texturedata->palette)) {
|
||||
return false;
|
||||
}
|
||||
texture->palette_version = 0;
|
||||
}
|
||||
#ifdef SDL_HAVE_YUV
|
||||
if (texturedata->yuv) {
|
||||
if (!D3D_RecreateTextureRep(data->device, &texturedata->utexture)) {
|
||||
@@ -616,56 +708,6 @@ static bool D3D_RecreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool D3D_UpdateTexturePalette(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||
{
|
||||
D3D_RenderData *data = (D3D_RenderData *)renderer->internal;
|
||||
D3D_TextureData *texturedata = (D3D_TextureData *)texture->internal;
|
||||
const int ncolors = texture->palette->ncolors;
|
||||
const SDL_Color *colors = texture->palette->colors;
|
||||
Uint32 palette[256];
|
||||
|
||||
if (!texturedata) {
|
||||
return SDL_SetError("Texture is not currently available");
|
||||
}
|
||||
|
||||
for (int i = 0; i < ncolors; ++i) {
|
||||
palette[i] = (colors[i].a << 24) | (colors[i].r << 16) | (colors[i].g << 8) | colors[i].b;
|
||||
}
|
||||
return D3D_UpdateTextureRep(data->device, &texturedata->palette, 0, 0, 256, 1, palette, sizeof(palette));
|
||||
}
|
||||
|
||||
static bool D3D_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
|
||||
const SDL_Rect *rect, const void *pixels, int pitch)
|
||||
{
|
||||
D3D_RenderData *data = (D3D_RenderData *)renderer->internal;
|
||||
D3D_TextureData *texturedata = (D3D_TextureData *)texture->internal;
|
||||
|
||||
if (!texturedata) {
|
||||
return SDL_SetError("Texture is not currently available");
|
||||
}
|
||||
|
||||
if (!D3D_UpdateTextureRep(data->device, &texturedata->texture, rect->x, rect->y, rect->w, rect->h, pixels, pitch)) {
|
||||
return false;
|
||||
}
|
||||
#ifdef SDL_HAVE_YUV
|
||||
if (texturedata->yuv) {
|
||||
// Skip to the correct offset into the next texture
|
||||
pixels = (const void *)((const Uint8 *)pixels + rect->h * pitch);
|
||||
|
||||
if (!D3D_UpdateTextureRep(data->device, texture->format == SDL_PIXELFORMAT_YV12 ? &texturedata->vtexture : &texturedata->utexture, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, pixels, (pitch + 1) / 2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Skip to the correct offset into the next texture
|
||||
pixels = (const void *)((const Uint8 *)pixels + ((rect->h + 1) / 2) * ((pitch + 1) / 2));
|
||||
if (!D3D_UpdateTextureRep(data->device, texture->format == SDL_PIXELFORMAT_YV12 ? &texturedata->utexture : &texturedata->vtexture, rect->x / 2, (rect->y + 1) / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, pixels, (pitch + 1) / 2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef SDL_HAVE_YUV
|
||||
static bool D3D_UpdateTextureYUV(SDL_Renderer *renderer, SDL_Texture *texture,
|
||||
const SDL_Rect *rect,
|
||||
@@ -1013,8 +1055,9 @@ static bool SetupTextureState(D3D_RenderData *data, SDL_Texture *texture, D3D9_S
|
||||
if (!BindTextureRep(data->device, &texturedata->texture, 0)) {
|
||||
return false;
|
||||
}
|
||||
if (texture->format == SDL_PIXELFORMAT_INDEX8) {
|
||||
if (!BindTextureRep(data->device, &texturedata->palette, 1)) {
|
||||
if (texture->palette) {
|
||||
D3D_PaletteData *palette = (D3D_PaletteData *)texture->palette->internal;
|
||||
if (!BindTextureRep(data->device, &palette->texture, 1)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1046,8 +1089,8 @@ static bool SetDrawState(D3D_RenderData *data, const SDL_RenderCommand *cmd)
|
||||
if (!texture) {
|
||||
IDirect3DDevice9_SetTexture(data->device, 0, NULL);
|
||||
}
|
||||
if ((!newtexturedata || (texture->format != SDL_PIXELFORMAT_INDEX8)) &&
|
||||
(oldtexturedata && (data->drawstate.texture->format == SDL_PIXELFORMAT_INDEX8))) {
|
||||
if ((!newtexturedata || !texture->palette) &&
|
||||
(oldtexturedata && (data->drawstate.texture->palette))) {
|
||||
IDirect3DDevice9_SetTexture(data->device, 1, NULL);
|
||||
}
|
||||
#ifdef SDL_HAVE_YUV
|
||||
@@ -1086,8 +1129,9 @@ static bool SetDrawState(D3D_RenderData *data, const SDL_RenderCommand *cmd)
|
||||
D3D_TextureData *texturedata = (D3D_TextureData *)texture->internal;
|
||||
if (texturedata) {
|
||||
UpdateDirtyTexture(data->device, &texturedata->texture);
|
||||
if (texture->format == SDL_PIXELFORMAT_INDEX8) {
|
||||
UpdateDirtyTexture(data->device, &texturedata->palette);
|
||||
if (texture->palette) {
|
||||
D3D_PaletteData *palettedata = (D3D_PaletteData *)texture->palette->internal;
|
||||
UpdateDirtyTexture(data->device, &palettedata->texture);
|
||||
}
|
||||
#ifdef SDL_HAVE_YUV
|
||||
if (texturedata->yuv) {
|
||||
@@ -1488,7 +1532,7 @@ static void D3D_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||
renderdata->drawstate.shader_params = NULL;
|
||||
IDirect3DDevice9_SetPixelShader(renderdata->device, NULL);
|
||||
IDirect3DDevice9_SetTexture(renderdata->device, 0, NULL);
|
||||
if (texture->format == SDL_PIXELFORMAT_INDEX8) {
|
||||
if (texture->palette) {
|
||||
IDirect3DDevice9_SetTexture(renderdata->device, 1, NULL);
|
||||
}
|
||||
#ifdef SDL_HAVE_YUV
|
||||
@@ -1520,6 +1564,9 @@ static void D3D_DestroyRenderer(SDL_Renderer *renderer)
|
||||
if (data) {
|
||||
int i;
|
||||
|
||||
// Make sure the palettes have been freed
|
||||
SDL_assert(!data->palettes);
|
||||
|
||||
// Release the render target
|
||||
if (data->defaultRenderTarget) {
|
||||
IDirect3DSurface9_Release(data->defaultRenderTarget);
|
||||
@@ -1560,6 +1607,7 @@ static bool D3D_Reset(SDL_Renderer *renderer)
|
||||
const Float4X4 d3dmatrix = MatrixIdentity();
|
||||
HRESULT result;
|
||||
SDL_Texture *texture;
|
||||
D3D_PaletteData *palette;
|
||||
int i;
|
||||
|
||||
// Cancel any scene that we've started
|
||||
@@ -1587,6 +1635,11 @@ static bool D3D_Reset(SDL_Renderer *renderer)
|
||||
}
|
||||
}
|
||||
|
||||
// Release all palettes
|
||||
for (palette = data->palettes; palette; palette = palette->next) {
|
||||
D3D_RecreateTextureRep(data->device, &palette->texture);
|
||||
}
|
||||
|
||||
// Release all vertex buffers
|
||||
for (i = 0; i < SDL_arraysize(data->vertexBuffers); ++i) {
|
||||
if (data->vertexBuffers[i]) {
|
||||
@@ -1711,8 +1764,10 @@ static bool D3D_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_P
|
||||
|
||||
renderer->WindowEvent = D3D_WindowEvent;
|
||||
renderer->SupportsBlendMode = D3D_SupportsBlendMode;
|
||||
renderer->CreatePalette = D3D_CreatePalette;
|
||||
renderer->UpdatePalette = D3D_UpdatePalette;
|
||||
renderer->DestroyPalette = D3D_DestroyPalette;
|
||||
renderer->CreateTexture = D3D_CreateTexture;
|
||||
renderer->UpdateTexturePalette = D3D_UpdateTexturePalette;
|
||||
renderer->UpdateTexture = D3D_UpdateTexture;
|
||||
#ifdef SDL_HAVE_YUV
|
||||
renderer->UpdateTextureYUV = D3D_UpdateTextureYUV;
|
||||
|
@@ -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;
|
||||
|
@@ -109,6 +109,15 @@ typedef struct
|
||||
SDL_FColor color;
|
||||
} D3D12_VertexPositionColor;
|
||||
|
||||
// Per-palette data
|
||||
typedef struct
|
||||
{
|
||||
ID3D12Resource *texture;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE resourceView;
|
||||
D3D12_RESOURCE_STATES resourceState;
|
||||
SIZE_T SRVIndex;
|
||||
} D3D12_PaletteData;
|
||||
|
||||
// Per-texture data
|
||||
typedef struct
|
||||
{
|
||||
@@ -119,10 +128,6 @@ typedef struct
|
||||
SIZE_T mainSRVIndex;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE mainTextureRenderTargetView;
|
||||
DXGI_FORMAT mainTextureFormat;
|
||||
ID3D12Resource *paletteTexture;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE paletteTextureResourceView;
|
||||
D3D12_RESOURCE_STATES paletteResourceState;
|
||||
SIZE_T paletteSRVIndex;
|
||||
ID3D12Resource *stagingBuffer;
|
||||
D3D12_RESOURCE_STATES stagingResourceState;
|
||||
const float *YCbCr_matrix;
|
||||
@@ -289,6 +294,8 @@ static const GUID SDL_IID_ID3D12InfoQueue = { 0x0742a90b, 0xc387, 0x483f, { 0xb9
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
static bool D3D12_UpdateTextureInternal(D3D12_RenderData *rendererData, ID3D12Resource *texture, int plane, int x, int y, int w, int h, const void *pixels, int pitch, D3D12_RESOURCE_STATES *resourceState);
|
||||
|
||||
static UINT D3D12_Align(UINT location, UINT alignment)
|
||||
{
|
||||
return (location + (alignment - 1)) & ~(alignment - 1);
|
||||
@@ -1537,6 +1544,88 @@ static bool GetTextureProperty(SDL_PropertiesID props, const char *name, ID3D12R
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool D3D12_CreatePalette(SDL_Renderer *renderer, SDL_TexturePalette *palette)
|
||||
{
|
||||
D3D12_RenderData *data = (D3D12_RenderData *)renderer->internal;
|
||||
D3D12_PaletteData *palettedata = (D3D12_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");
|
||||
}
|
||||
|
||||
D3D12_RESOURCE_DESC textureDesc;
|
||||
SDL_zero(textureDesc);
|
||||
textureDesc.Width = 256;
|
||||
textureDesc.Height = 1;
|
||||
textureDesc.MipLevels = 1;
|
||||
textureDesc.DepthOrArraySize = 1;
|
||||
textureDesc.Format = SDLPixelFormatToDXGITextureFormat(SDL_PIXELFORMAT_RGBA32, renderer->output_colorspace);
|
||||
textureDesc.SampleDesc.Count = 1;
|
||||
textureDesc.SampleDesc.Quality = 0;
|
||||
textureDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
||||
textureDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
|
||||
D3D12_HEAP_PROPERTIES heapProps;
|
||||
SDL_zero(heapProps);
|
||||
heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||
heapProps.CreationNodeMask = 1;
|
||||
heapProps.VisibleNodeMask = 1;
|
||||
|
||||
HRESULT result = ID3D12Device1_CreateCommittedResource(data->d3dDevice,
|
||||
&heapProps,
|
||||
D3D12_HEAP_FLAG_NONE,
|
||||
&textureDesc,
|
||||
D3D12_RESOURCE_STATE_COPY_DEST,
|
||||
NULL,
|
||||
D3D_GUID(SDL_IID_ID3D12Resource),
|
||||
(void **)&palettedata->texture);
|
||||
if (FAILED(result)) {
|
||||
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D12Device::CreateCommittedResource [texture]"), result);
|
||||
}
|
||||
palettedata->resourceState = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC resourceViewDesc;
|
||||
SDL_zero(resourceViewDesc);
|
||||
resourceViewDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||
resourceViewDesc.Format = SDLPixelFormatToDXGIMainResourceViewFormat(SDL_PIXELFORMAT_RGBA32, renderer->output_colorspace);
|
||||
resourceViewDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||
resourceViewDesc.Texture2D.MipLevels = textureDesc.MipLevels;
|
||||
|
||||
D3D_CALL_RET(data->srvDescriptorHeap, GetCPUDescriptorHandleForHeapStart, &palettedata->resourceView);
|
||||
palettedata->SRVIndex = D3D12_GetAvailableSRVIndex(renderer);
|
||||
palettedata->resourceView.ptr += palettedata->SRVIndex * data->srvDescriptorSize;
|
||||
|
||||
ID3D12Device1_CreateShaderResourceView(data->d3dDevice,
|
||||
palettedata->texture,
|
||||
&resourceViewDesc,
|
||||
palettedata->resourceView);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool D3D12_UpdatePalette(SDL_Renderer *renderer, SDL_TexturePalette *palette, int ncolors, SDL_Color *colors)
|
||||
{
|
||||
D3D12_RenderData *data = (D3D12_RenderData *)renderer->internal;
|
||||
D3D12_PaletteData *palettedata = (D3D12_PaletteData *)palette->internal;
|
||||
|
||||
return D3D12_UpdateTextureInternal(data, palettedata->texture, 0, 0, 0, ncolors, 1, colors, ncolors * sizeof(*colors), &palettedata->resourceState);
|
||||
}
|
||||
|
||||
static void D3D12_DestroyPalette(SDL_Renderer *renderer, SDL_TexturePalette *palette)
|
||||
{
|
||||
D3D12_PaletteData *palettedata = (D3D12_PaletteData *)palette->internal;
|
||||
|
||||
if (palettedata) {
|
||||
D3D_SAFE_RELEASE(palettedata->texture);
|
||||
D3D12_FreeSRVIndex(renderer, palettedata->SRVIndex);
|
||||
SDL_free(palettedata);
|
||||
}
|
||||
}
|
||||
|
||||
static bool D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props)
|
||||
{
|
||||
D3D12_RenderData *rendererData = (D3D12_RenderData *)renderer->internal;
|
||||
@@ -1612,29 +1701,6 @@ static bool D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
|
||||
textureData->mainResourceState = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
SDL_SetPointerProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_D3D12_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 = ID3D12Device1_CreateCommittedResource(rendererData->d3dDevice,
|
||||
&heapProps,
|
||||
D3D12_HEAP_FLAG_NONE,
|
||||
&textureDesc,
|
||||
D3D12_RESOURCE_STATE_COPY_DEST,
|
||||
NULL,
|
||||
D3D_GUID(SDL_IID_ID3D12Resource),
|
||||
(void **)&textureData->paletteTexture);
|
||||
if (FAILED(result)) {
|
||||
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D12Device::CreateCommittedResource [texture]"), result);
|
||||
}
|
||||
textureData->paletteResourceState = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
}
|
||||
|
||||
#ifdef SDL_HAVE_YUV
|
||||
if (texture->format == SDL_PIXELFORMAT_YV12 ||
|
||||
texture->format == SDL_PIXELFORMAT_IYUV) {
|
||||
@@ -1723,19 +1789,6 @@ static bool D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
|
||||
&resourceViewDesc,
|
||||
textureData->mainTextureResourceView);
|
||||
|
||||
if (texture->format == SDL_PIXELFORMAT_INDEX8) {
|
||||
resourceViewDesc.Format = textureDesc.Format;
|
||||
|
||||
D3D_CALL_RET(rendererData->srvDescriptorHeap, GetCPUDescriptorHandleForHeapStart, &textureData->paletteTextureResourceView);
|
||||
textureData->paletteSRVIndex = D3D12_GetAvailableSRVIndex(renderer);
|
||||
textureData->paletteTextureResourceView.ptr += textureData->paletteSRVIndex * rendererData->srvDescriptorSize;
|
||||
|
||||
ID3D12Device1_CreateShaderResourceView(rendererData->d3dDevice,
|
||||
textureData->paletteTexture,
|
||||
&resourceViewDesc,
|
||||
textureData->paletteTextureResourceView);
|
||||
}
|
||||
|
||||
#ifdef SDL_HAVE_YUV
|
||||
if (textureData->yuv) {
|
||||
D3D_CALL_RET(rendererData->srvDescriptorHeap, GetCPUDescriptorHandleForHeapStart, &textureData->mainTextureResourceViewU);
|
||||
@@ -1811,10 +1864,6 @@ static void D3D12_DestroyTexture(SDL_Renderer *renderer,
|
||||
D3D_SAFE_RELEASE(textureData->mainTexture);
|
||||
D3D_SAFE_RELEASE(textureData->stagingBuffer);
|
||||
D3D12_FreeSRVIndex(renderer, textureData->mainSRVIndex);
|
||||
if (texture->format == SDL_PIXELFORMAT_INDEX8) {
|
||||
D3D_SAFE_RELEASE(textureData->paletteTexture);
|
||||
D3D12_FreeSRVIndex(renderer, textureData->paletteSRVIndex);
|
||||
}
|
||||
#ifdef SDL_HAVE_YUV
|
||||
D3D_SAFE_RELEASE(textureData->mainTextureU);
|
||||
D3D_SAFE_RELEASE(textureData->mainTextureV);
|
||||
@@ -1969,19 +2018,6 @@ static bool D3D12_UpdateTextureInternal(D3D12_RenderData *rendererData, ID3D12Re
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool D3D12_UpdateTexturePalette(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||
{
|
||||
D3D12_RenderData *rendererData = (D3D12_RenderData *)renderer->internal;
|
||||
D3D12_TextureData *textureData = (D3D12_TextureData *)texture->internal;
|
||||
SDL_Palette *palette = texture->palette;
|
||||
|
||||
if (!textureData) {
|
||||
return SDL_SetError("Texture is not currently available");
|
||||
}
|
||||
|
||||
return D3D12_UpdateTextureInternal(rendererData, textureData->paletteTexture, 0, 0, 0, palette->ncolors, 1, palette->colors, palette->ncolors * sizeof(*palette->colors), &textureData->paletteResourceState);
|
||||
}
|
||||
|
||||
static bool D3D12_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
|
||||
const SDL_Rect *rect, const void *srcPixels,
|
||||
int srcPitch)
|
||||
@@ -2902,10 +2938,12 @@ static bool D3D12_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *
|
||||
}
|
||||
shaderSamplers[numShaderSamplers++] = *textureSampler;
|
||||
|
||||
if (texture->format == SDL_PIXELFORMAT_INDEX8) {
|
||||
D3D12_TransitionResource(rendererData, textureData->paletteTexture, textureData->paletteResourceState, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
|
||||
textureData->paletteResourceState = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
|
||||
shaderResources[numShaderResources++] = textureData->paletteTextureResourceView;
|
||||
if (texture->palette) {
|
||||
D3D12_PaletteData *palette = (D3D12_PaletteData *)texture->palette->internal;
|
||||
|
||||
D3D12_TransitionResource(rendererData, palette->texture, palette->resourceState, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
|
||||
palette->resourceState = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
|
||||
shaderResources[numShaderResources++] = palette->resourceView;
|
||||
|
||||
textureSampler = D3D12_GetSamplerState(rendererData, SDL_SCALEMODE_NEAREST, SDL_TEXTURE_ADDRESS_CLAMP, SDL_TEXTURE_ADDRESS_CLAMP);
|
||||
if (!textureSampler) {
|
||||
@@ -3366,8 +3404,10 @@ bool D3D12_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_Proper
|
||||
|
||||
renderer->WindowEvent = D3D12_WindowEvent;
|
||||
renderer->SupportsBlendMode = D3D12_SupportsBlendMode;
|
||||
renderer->CreatePalette = D3D12_CreatePalette;
|
||||
renderer->UpdatePalette = D3D12_UpdatePalette;
|
||||
renderer->DestroyPalette = D3D12_DestroyPalette;
|
||||
renderer->CreateTexture = D3D12_CreateTexture;
|
||||
renderer->UpdateTexturePalette = D3D12_UpdateTexturePalette;
|
||||
renderer->UpdateTexture = D3D12_UpdateTexture;
|
||||
#ifdef SDL_HAVE_YUV
|
||||
renderer->UpdateTextureYUV = D3D12_UpdateTextureYUV;
|
||||
|
@@ -86,10 +86,14 @@ typedef struct GPU_RenderData
|
||||
SDL_GPUSampler *samplers[RENDER_SAMPLER_COUNT];
|
||||
} GPU_RenderData;
|
||||
|
||||
typedef struct GPU_PaletteData
|
||||
{
|
||||
SDL_GPUTexture *texture;
|
||||
} GPU_PaletteData;
|
||||
|
||||
typedef struct GPU_TextureData
|
||||
{
|
||||
SDL_GPUTexture *texture;
|
||||
SDL_GPUTexture *palette;
|
||||
SDL_GPUTextureFormat format;
|
||||
GPU_FragmentShaderID shader;
|
||||
void *pixels;
|
||||
@@ -118,6 +122,88 @@ static bool GPU_SupportsBlendMode(SDL_Renderer *renderer, SDL_BlendMode blendMod
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool GPU_CreatePalette(SDL_Renderer *renderer, SDL_TexturePalette *palette)
|
||||
{
|
||||
GPU_RenderData *data = (GPU_RenderData *)renderer->internal;
|
||||
GPU_PaletteData *palettedata = (GPU_PaletteData *)SDL_calloc(1, sizeof(*palettedata));
|
||||
if (!palettedata) {
|
||||
return false;
|
||||
}
|
||||
palette->internal = palettedata;
|
||||
|
||||
SDL_GPUTextureCreateInfo tci;
|
||||
SDL_zero(tci);
|
||||
tci.format = SDL_GetGPUTextureFormatFromPixelFormat(SDL_PIXELFORMAT_RGBA32);
|
||||
tci.layer_count_or_depth = 1;
|
||||
tci.num_levels = 1;
|
||||
tci.usage = SDL_GPU_TEXTUREUSAGE_SAMPLER;
|
||||
tci.width = 256;
|
||||
tci.height = 1;
|
||||
tci.sample_count = SDL_GPU_SAMPLECOUNT_1;
|
||||
|
||||
palettedata->texture = SDL_CreateGPUTexture(data->device, &tci);
|
||||
if (!palettedata->texture) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool GPU_UpdatePalette(SDL_Renderer *renderer, SDL_TexturePalette *palette, int ncolors, SDL_Color *colors)
|
||||
{
|
||||
GPU_RenderData *data = (GPU_RenderData *)renderer->internal;
|
||||
GPU_PaletteData *palettedata = (GPU_PaletteData *)palette->internal;
|
||||
const Uint32 data_size = ncolors * sizeof(*colors);
|
||||
|
||||
SDL_GPUTransferBufferCreateInfo tbci;
|
||||
SDL_zero(tbci);
|
||||
tbci.size = data_size;
|
||||
tbci.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD;
|
||||
|
||||
SDL_GPUTransferBuffer *tbuf = SDL_CreateGPUTransferBuffer(data->device, &tbci);
|
||||
if (tbuf == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Uint8 *output = SDL_MapGPUTransferBuffer(data->device, tbuf, false);
|
||||
SDL_memcpy(output, colors, data_size);
|
||||
SDL_UnmapGPUTransferBuffer(data->device, tbuf);
|
||||
|
||||
SDL_GPUCommandBuffer *cbuf = data->state.command_buffer;
|
||||
SDL_GPUCopyPass *cpass = SDL_BeginGPUCopyPass(cbuf);
|
||||
|
||||
SDL_GPUTextureTransferInfo tex_src;
|
||||
SDL_zero(tex_src);
|
||||
tex_src.transfer_buffer = tbuf;
|
||||
tex_src.rows_per_layer = 1;
|
||||
tex_src.pixels_per_row = ncolors;
|
||||
|
||||
SDL_GPUTextureRegion tex_dst;
|
||||
SDL_zero(tex_dst);
|
||||
tex_dst.texture = palettedata->texture;
|
||||
tex_dst.x = 0;
|
||||
tex_dst.y = 0;
|
||||
tex_dst.w = ncolors;
|
||||
tex_dst.h = 1;
|
||||
tex_dst.d = 1;
|
||||
|
||||
SDL_UploadToGPUTexture(cpass, &tex_src, &tex_dst, false);
|
||||
SDL_EndGPUCopyPass(cpass);
|
||||
SDL_ReleaseGPUTransferBuffer(data->device, tbuf);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void GPU_DestroyPalette(SDL_Renderer *renderer, SDL_TexturePalette *palette)
|
||||
{
|
||||
GPU_RenderData *data = (GPU_RenderData *)renderer->internal;
|
||||
GPU_PaletteData *palettedata = (GPU_PaletteData *)palette->internal;
|
||||
|
||||
if (palettedata) {
|
||||
SDL_ReleaseGPUTexture(data->device, palettedata->texture);
|
||||
SDL_free(palettedata);
|
||||
}
|
||||
}
|
||||
|
||||
static bool GPU_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props)
|
||||
{
|
||||
GPU_RenderData *renderdata = (GPU_RenderData *)renderer->internal;
|
||||
@@ -184,16 +270,6 @@ static bool GPU_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_
|
||||
return false;
|
||||
}
|
||||
|
||||
if (texture->format == SDL_PIXELFORMAT_INDEX8) {
|
||||
tci.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM;
|
||||
tci.width = 256;
|
||||
tci.height = 1;
|
||||
data->palette = SDL_CreateGPUTexture(renderdata->device, &tci);
|
||||
if (!data->palette) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_PropertiesID props = SDL_GetTextureProperties(texture);
|
||||
SDL_SetPointerProperty(props, SDL_PROP_TEXTURE_GPU_TEXTURE_POINTER, data->texture);
|
||||
|
||||
@@ -206,52 +282,6 @@ static bool GPU_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool GPU_UpdateTexturePalette(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||
{
|
||||
GPU_RenderData *renderdata = (GPU_RenderData *)renderer->internal;
|
||||
GPU_TextureData *data = (GPU_TextureData *)texture->internal;
|
||||
SDL_Palette *palette = texture->palette;
|
||||
const Uint32 data_size = palette->ncolors * sizeof(*palette->colors);
|
||||
|
||||
SDL_GPUTransferBufferCreateInfo tbci;
|
||||
SDL_zero(tbci);
|
||||
tbci.size = data_size;
|
||||
tbci.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD;
|
||||
|
||||
SDL_GPUTransferBuffer *tbuf = SDL_CreateGPUTransferBuffer(renderdata->device, &tbci);
|
||||
if (tbuf == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Uint8 *output = SDL_MapGPUTransferBuffer(renderdata->device, tbuf, false);
|
||||
SDL_memcpy(output, palette->colors, data_size);
|
||||
SDL_UnmapGPUTransferBuffer(renderdata->device, tbuf);
|
||||
|
||||
SDL_GPUCommandBuffer *cbuf = renderdata->state.command_buffer;
|
||||
SDL_GPUCopyPass *cpass = SDL_BeginGPUCopyPass(cbuf);
|
||||
|
||||
SDL_GPUTextureTransferInfo tex_src;
|
||||
SDL_zero(tex_src);
|
||||
tex_src.transfer_buffer = tbuf;
|
||||
tex_src.rows_per_layer = 1;
|
||||
tex_src.pixels_per_row = palette->ncolors;
|
||||
|
||||
SDL_GPUTextureRegion tex_dst;
|
||||
SDL_zero(tex_dst);
|
||||
tex_dst.texture = data->palette;
|
||||
tex_dst.x = 0;
|
||||
tex_dst.y = 0;
|
||||
tex_dst.w = palette->ncolors;
|
||||
tex_dst.h = 1;
|
||||
tex_dst.d = 1;
|
||||
|
||||
SDL_UploadToGPUTexture(cpass, &tex_src, &tex_dst, false);
|
||||
SDL_EndGPUCopyPass(cpass);
|
||||
SDL_ReleaseGPUTransferBuffer(renderdata->device, tbuf);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool GPU_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
|
||||
const SDL_Rect *rect, const void *pixels, int pitch)
|
||||
{
|
||||
@@ -663,9 +693,11 @@ static void Draw(
|
||||
sampler_bind.texture = tdata->texture;
|
||||
SDL_BindGPUFragmentSamplers(pass, sampler_slot++, &sampler_bind, 1);
|
||||
|
||||
if (texture->format == SDL_PIXELFORMAT_INDEX8) {
|
||||
if (texture->palette) {
|
||||
GPU_PaletteData *palette = (GPU_PaletteData *)texture->palette->internal;
|
||||
|
||||
sampler_bind.sampler = GetSampler(data, SDL_SCALEMODE_NEAREST, SDL_TEXTURE_ADDRESS_CLAMP, SDL_TEXTURE_ADDRESS_CLAMP);
|
||||
sampler_bind.texture = tdata->palette;
|
||||
sampler_bind.texture = palette->texture;
|
||||
SDL_BindGPUFragmentSamplers(pass, sampler_slot++, &sampler_bind, 1);
|
||||
}
|
||||
}
|
||||
@@ -1128,7 +1160,6 @@ static void GPU_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||
}
|
||||
|
||||
SDL_ReleaseGPUTexture(renderdata->device, data->texture);
|
||||
SDL_ReleaseGPUTexture(renderdata->device, data->palette);
|
||||
SDL_free(data->pixels);
|
||||
SDL_free(data);
|
||||
texture->internal = NULL;
|
||||
@@ -1242,8 +1273,10 @@ static bool GPU_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_P
|
||||
}
|
||||
|
||||
renderer->SupportsBlendMode = GPU_SupportsBlendMode;
|
||||
renderer->CreatePalette = GPU_CreatePalette;
|
||||
renderer->UpdatePalette = GPU_UpdatePalette;
|
||||
renderer->DestroyPalette = GPU_DestroyPalette;
|
||||
renderer->CreateTexture = GPU_CreateTexture;
|
||||
renderer->UpdateTexturePalette = GPU_UpdateTexturePalette;
|
||||
renderer->UpdateTexture = GPU_UpdateTexture;
|
||||
renderer->LockTexture = GPU_LockTexture;
|
||||
renderer->UnlockTexture = GPU_UnlockTexture;
|
||||
|
@@ -144,6 +144,14 @@ typedef struct METAL_ShaderPipelines
|
||||
@implementation SDL3METAL_RenderData
|
||||
@end
|
||||
|
||||
@interface SDL3METAL_PaletteData : NSObject
|
||||
@property(nonatomic, retain) id<MTLTexture> mtltexture;
|
||||
@property(nonatomic, assign) BOOL hasdata;
|
||||
@end
|
||||
|
||||
@implementation SDL3METAL_PaletteData
|
||||
@end
|
||||
|
||||
@interface SDL3METAL_TextureData : NSObject
|
||||
@property(nonatomic, retain) id<MTLTexture> mtltexture;
|
||||
@property(nonatomic, retain) id<MTLTexture> mtlpalette;
|
||||
@@ -162,6 +170,10 @@ typedef struct METAL_ShaderPipelines
|
||||
@implementation SDL3METAL_TextureData
|
||||
@end
|
||||
|
||||
static bool METAL_UpdateTextureInternal(SDL_Renderer *renderer, BOOL hasdata,
|
||||
id<MTLTexture> texture, SDL_Rect rect, int slice,
|
||||
const void *pixels, int pitch);
|
||||
|
||||
static const MTLBlendOperation invalidBlendOperation = (MTLBlendOperation)0xFFFFFFFF;
|
||||
static const MTLBlendFactor invalidBlendFactor = (MTLBlendFactor)0xFFFFFFFF;
|
||||
|
||||
@@ -611,13 +623,68 @@ size_t GetYCbCRtoRGBConversionMatrix(SDL_Colorspace colorspace, int w, int h, in
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool METAL_CreatePalette(SDL_Renderer *renderer, SDL_TexturePalette *palette)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL3METAL_RenderData *data = (__bridge SDL3METAL_RenderData *)renderer->internal;
|
||||
MTLPixelFormat pixfmt;
|
||||
MTLTextureDescriptor *mtltexdesc;
|
||||
id<MTLTexture> mtltexture = nil;
|
||||
SDL3METAL_PaletteData *palettedata;
|
||||
|
||||
if (renderer->output_colorspace == SDL_COLORSPACE_SRGB_LINEAR) {
|
||||
pixfmt = MTLPixelFormatRGBA8Unorm_sRGB;
|
||||
} else {
|
||||
pixfmt = MTLPixelFormatRGBA8Unorm;
|
||||
}
|
||||
mtltexdesc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:pixfmt
|
||||
width:256
|
||||
height:1
|
||||
mipmapped:NO];
|
||||
mtltexdesc.usage = MTLTextureUsageShaderRead;
|
||||
|
||||
mtltexture = [data.mtldevice newTextureWithDescriptor:mtltexdesc];
|
||||
if (mtltexture == nil) {
|
||||
return SDL_SetError("Palette allocation failed");
|
||||
}
|
||||
|
||||
palettedata = [[SDL3METAL_PaletteData alloc] init];
|
||||
palettedata.mtltexture = mtltexture;
|
||||
palette->internal = (void *)CFBridgingRetain(palettedata);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static bool METAL_UpdatePalette(SDL_Renderer *renderer, SDL_TexturePalette *palette, int ncolors, SDL_Color *colors)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL3METAL_PaletteData *palettedata = (__bridge SDL3METAL_PaletteData *)palette->internal;
|
||||
SDL_Rect rect = { 0, 0, ncolors, 1 };
|
||||
|
||||
if (!METAL_UpdateTextureInternal(renderer, palettedata.hasdata, palettedata.mtltexture, rect, 0, colors, ncolors * sizeof(*colors))) {
|
||||
return false;
|
||||
}
|
||||
palettedata.hasdata = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static void METAL_DestroyPalette(SDL_Renderer *renderer, SDL_TexturePalette *palette)
|
||||
{
|
||||
@autoreleasepool {
|
||||
CFBridgingRelease(palette->internal);
|
||||
palette->internal = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static bool METAL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL3METAL_RenderData *data = (__bridge SDL3METAL_RenderData *)renderer->internal;
|
||||
MTLPixelFormat pixfmt;
|
||||
MTLTextureDescriptor *mtltexdesc;
|
||||
id<MTLTexture> mtltexture = nil, mtltextureUv = nil, mtlpalette = nil;
|
||||
id<MTLTexture> mtltexture = nil, mtltextureUv = nil;
|
||||
SDL3METAL_TextureData *texturedata;
|
||||
CVPixelBufferRef pixelbuffer = nil;
|
||||
IOSurfaceRef surface = nil;
|
||||
@@ -688,25 +755,6 @@ static bool METAL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
|
||||
return SDL_SetError("Texture allocation failed");
|
||||
}
|
||||
|
||||
if (texture->format == SDL_PIXELFORMAT_INDEX8) {
|
||||
if (renderer->output_colorspace == SDL_COLORSPACE_SRGB_LINEAR) {
|
||||
pixfmt = MTLPixelFormatBGRA8Unorm_sRGB;
|
||||
} else {
|
||||
pixfmt = MTLPixelFormatBGRA8Unorm;
|
||||
}
|
||||
mtltexdesc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:pixfmt
|
||||
width:256
|
||||
height:1
|
||||
mipmapped:NO];
|
||||
|
||||
mtltexdesc.usage = MTLTextureUsageShaderRead;
|
||||
|
||||
mtlpalette = [data.mtldevice newTextureWithDescriptor:mtltexdesc];
|
||||
if (mtlpalette == nil) {
|
||||
return SDL_SetError("Palette allocation failed");
|
||||
}
|
||||
}
|
||||
|
||||
mtltextureUv = nil;
|
||||
#ifdef SDL_HAVE_YUV
|
||||
BOOL yuv = (texture->format == SDL_PIXELFORMAT_IYUV || texture->format == SDL_PIXELFORMAT_YV12);
|
||||
@@ -753,7 +801,6 @@ static bool METAL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
|
||||
texturedata.fragmentFunction = SDL_METAL_FRAGMENT_COPY;
|
||||
}
|
||||
texturedata.mtltexture = mtltexture;
|
||||
texturedata.mtlpalette = mtlpalette;
|
||||
texturedata.mtltextureUv = mtltextureUv;
|
||||
#ifdef SDL_HAVE_YUV
|
||||
texturedata.yuv = yuv;
|
||||
@@ -788,7 +835,7 @@ static MTLStorageMode METAL_GetStorageMode(id<MTLResource> resource)
|
||||
return resource.storageMode;
|
||||
}
|
||||
|
||||
static bool METAL_UpdateTextureInternal(SDL_Renderer *renderer, SDL3METAL_TextureData *texturedata,
|
||||
static bool METAL_UpdateTextureInternal(SDL_Renderer *renderer, BOOL hasdata,
|
||||
id<MTLTexture> texture, SDL_Rect rect, int slice,
|
||||
const void *pixels, int pitch)
|
||||
{
|
||||
@@ -801,7 +848,7 @@ static bool METAL_UpdateTextureInternal(SDL_Renderer *renderer, SDL3METAL_Textur
|
||||
/* If the texture is managed or shared and this is the first upload, we can
|
||||
* use replaceRegion to upload to it directly. Otherwise we upload the data
|
||||
* to a staging texture and copy that over. */
|
||||
if (!texturedata.hasdata && METAL_GetStorageMode(texture) != MTLStorageModePrivate) {
|
||||
if (!hasdata && METAL_GetStorageMode(texture) != MTLStorageModePrivate) {
|
||||
METAL_UploadTextureData(texture, rect, slice, pixels, pitch);
|
||||
return true;
|
||||
}
|
||||
@@ -856,24 +903,13 @@ static bool METAL_UpdateTextureInternal(SDL_Renderer *renderer, SDL3METAL_Textur
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool METAL_UpdateTexturePalette(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL3METAL_TextureData *texturedata = (__bridge SDL3METAL_TextureData *)texture->internal;
|
||||
SDL_Palette *palette = texture->palette;
|
||||
SDL_Rect rect = { 0, 0, palette->ncolors, 1 };
|
||||
|
||||
return METAL_UpdateTextureInternal(renderer, texturedata, texturedata.mtlpalette, rect, 0, palette->colors, palette->ncolors * sizeof(*palette->colors));
|
||||
}
|
||||
}
|
||||
|
||||
static bool METAL_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
|
||||
const SDL_Rect *rect, const void *pixels, int pitch)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL3METAL_TextureData *texturedata = (__bridge SDL3METAL_TextureData *)texture->internal;
|
||||
|
||||
if (!METAL_UpdateTextureInternal(renderer, texturedata, texturedata.mtltexture, *rect, 0, pixels, pitch)) {
|
||||
if (!METAL_UpdateTextureInternal(renderer, texturedata.hasdata, texturedata.mtltexture, *rect, 0, pixels, pitch)) {
|
||||
return false;
|
||||
}
|
||||
#ifdef SDL_HAVE_YUV
|
||||
@@ -885,13 +921,13 @@ static bool METAL_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
|
||||
|
||||
// Skip to the correct offset into the next texture
|
||||
pixels = (const void *)((const Uint8 *)pixels + rect->h * pitch);
|
||||
if (!METAL_UpdateTextureInternal(renderer, texturedata, texturedata.mtltextureUv, UVrect, Uslice, pixels, UVpitch)) {
|
||||
if (!METAL_UpdateTextureInternal(renderer, texturedata.hasdata, texturedata.mtltextureUv, UVrect, Uslice, pixels, UVpitch)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Skip to the correct offset into the next texture
|
||||
pixels = (const void *)((const Uint8 *)pixels + UVrect.h * UVpitch);
|
||||
if (!METAL_UpdateTextureInternal(renderer, texturedata, texturedata.mtltextureUv, UVrect, Vslice, pixels, UVpitch)) {
|
||||
if (!METAL_UpdateTextureInternal(renderer, texturedata.hasdata, texturedata.mtltextureUv, UVrect, Vslice, pixels, UVpitch)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -902,7 +938,7 @@ static bool METAL_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
|
||||
|
||||
// Skip to the correct offset into the next texture
|
||||
pixels = (const void *)((const Uint8 *)pixels + rect->h * pitch);
|
||||
if (!METAL_UpdateTextureInternal(renderer, texturedata, texturedata.mtltextureUv, UVrect, 0, pixels, UVpitch)) {
|
||||
if (!METAL_UpdateTextureInternal(renderer, texturedata.hasdata, texturedata.mtltextureUv, UVrect, 0, pixels, UVpitch)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -931,13 +967,13 @@ static bool METAL_UpdateTextureYUV(SDL_Renderer *renderer, SDL_Texture *texture,
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!METAL_UpdateTextureInternal(renderer, texturedata, texturedata.mtltexture, *rect, 0, Yplane, Ypitch)) {
|
||||
if (!METAL_UpdateTextureInternal(renderer, texturedata.hasdata, texturedata.mtltexture, *rect, 0, Yplane, Ypitch)) {
|
||||
return false;
|
||||
}
|
||||
if (!METAL_UpdateTextureInternal(renderer, texturedata, texturedata.mtltextureUv, UVrect, Uslice, Uplane, Upitch)) {
|
||||
if (!METAL_UpdateTextureInternal(renderer, texturedata.hasdata, texturedata.mtltextureUv, UVrect, Uslice, Uplane, Upitch)) {
|
||||
return false;
|
||||
}
|
||||
if (!METAL_UpdateTextureInternal(renderer, texturedata, texturedata.mtltextureUv, UVrect, Vslice, Vplane, Vpitch)) {
|
||||
if (!METAL_UpdateTextureInternal(renderer, texturedata.hasdata, texturedata.mtltextureUv, UVrect, Vslice, Vplane, Vpitch)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -961,11 +997,11 @@ static bool METAL_UpdateTextureNV(SDL_Renderer *renderer, SDL_Texture *texture,
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!METAL_UpdateTextureInternal(renderer, texturedata, texturedata.mtltexture, *rect, 0, Yplane, Ypitch)) {
|
||||
if (!METAL_UpdateTextureInternal(renderer, texturedata.hasdata, texturedata.mtltexture, *rect, 0, Yplane, Ypitch)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!METAL_UpdateTextureInternal(renderer, texturedata, texturedata.mtltextureUv, UVrect, 0, UVplane, UVpitch)) {
|
||||
if (!METAL_UpdateTextureInternal(renderer, texturedata.hasdata, texturedata.mtltextureUv, UVrect, 0, UVplane, UVpitch)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1568,8 +1604,9 @@ static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, c
|
||||
|
||||
if (texture != statecache->texture) {
|
||||
[data.mtlcmdencoder setFragmentTexture:texturedata.mtltexture atIndex:0];
|
||||
if (texture->format == SDL_PIXELFORMAT_INDEX8) {
|
||||
[data.mtlcmdencoder setFragmentTexture:texturedata.mtlpalette atIndex:1];
|
||||
if (texture->palette) {
|
||||
SDL3METAL_PaletteData *palette = (__bridge SDL3METAL_PaletteData *)texture->palette->internal;
|
||||
[data.mtlcmdencoder setFragmentTexture:palette.mtltexture atIndex:1];
|
||||
}
|
||||
#ifdef SDL_HAVE_YUV
|
||||
if (texturedata.yuv || texturedata.nv12) {
|
||||
@@ -1593,7 +1630,7 @@ static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, c
|
||||
statecache->texture_address_mode_u = cmd->data.draw.texture_address_mode_u;
|
||||
statecache->texture_address_mode_v = cmd->data.draw.texture_address_mode_v;
|
||||
}
|
||||
if (texture->format == SDL_PIXELFORMAT_INDEX8) {
|
||||
if (texture->palette) {
|
||||
if (!statecache->texture_palette) {
|
||||
id<MTLSamplerState> mtlsampler = GetSampler(data, SDL_SCALEMODE_NEAREST, SDL_TEXTURE_ADDRESS_CLAMP, SDL_TEXTURE_ADDRESS_CLAMP);
|
||||
if (mtlsampler == nil) {
|
||||
@@ -2201,8 +2238,10 @@ static bool METAL_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL
|
||||
renderer->WindowEvent = METAL_WindowEvent;
|
||||
renderer->GetOutputSize = METAL_GetOutputSize;
|
||||
renderer->SupportsBlendMode = METAL_SupportsBlendMode;
|
||||
renderer->CreatePalette = METAL_CreatePalette;
|
||||
renderer->UpdatePalette = METAL_UpdatePalette;
|
||||
renderer->DestroyPalette = METAL_DestroyPalette;
|
||||
renderer->CreateTexture = METAL_CreateTexture;
|
||||
renderer->UpdateTexturePalette = METAL_UpdateTexturePalette;
|
||||
renderer->UpdateTexture = METAL_UpdateTexture;
|
||||
#ifdef SDL_HAVE_YUV
|
||||
renderer->UpdateTextureYUV = METAL_UpdateTextureYUV;
|
||||
|
@@ -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