mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-11-05 10:14:31 +00:00
Added support for external GPU textures to the GPU renderer
This commit is contained in:
@@ -765,6 +765,19 @@ extern SDL_DECLSPEC SDL_Texture * SDLCALL SDL_CreateTextureFromSurface(SDL_Rende
|
|||||||
* VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL associated with the texture, if
|
* VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL associated with the texture, if
|
||||||
* you want to wrap an existing texture.
|
* you want to wrap an existing texture.
|
||||||
*
|
*
|
||||||
|
* With the GPU renderer:
|
||||||
|
*
|
||||||
|
* - `SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_POINTER`: the SDL_GPUTexture associated with the texture, if you want to wrap an existing texture.
|
||||||
|
* - `SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_UV_NUMBER`: the SDL_GPUTexture
|
||||||
|
* associated with the UV plane of an NV12 texture, if you want to wrap an
|
||||||
|
* existing texture.
|
||||||
|
* - `SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_U_NUMBER`: the SDL_GPUTexture
|
||||||
|
* associated with the U plane of a YUV texture, if you want to wrap an
|
||||||
|
* existing texture.
|
||||||
|
* - `SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_V_NUMBER`: the SDL_GPUTexture
|
||||||
|
* associated with the V plane of a YUV texture, if you want to wrap an
|
||||||
|
* existing texture.
|
||||||
|
*
|
||||||
* \param renderer the rendering context.
|
* \param renderer the rendering context.
|
||||||
* \param props the properties to use.
|
* \param props the properties to use.
|
||||||
* \returns the created texture or NULL on failure; call SDL_GetError() for
|
* \returns the created texture or NULL on failure; call SDL_GetError() for
|
||||||
@@ -783,30 +796,34 @@ extern SDL_DECLSPEC SDL_Texture * SDLCALL SDL_CreateTextureFromSurface(SDL_Rende
|
|||||||
*/
|
*/
|
||||||
extern SDL_DECLSPEC SDL_Texture * SDLCALL SDL_CreateTextureWithProperties(SDL_Renderer *renderer, SDL_PropertiesID props);
|
extern SDL_DECLSPEC SDL_Texture * SDLCALL SDL_CreateTextureWithProperties(SDL_Renderer *renderer, SDL_PropertiesID props);
|
||||||
|
|
||||||
#define SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER "SDL.texture.create.colorspace"
|
#define SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER "SDL.texture.create.colorspace"
|
||||||
#define SDL_PROP_TEXTURE_CREATE_FORMAT_NUMBER "SDL.texture.create.format"
|
#define SDL_PROP_TEXTURE_CREATE_FORMAT_NUMBER "SDL.texture.create.format"
|
||||||
#define SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER "SDL.texture.create.access"
|
#define SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER "SDL.texture.create.access"
|
||||||
#define SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER "SDL.texture.create.width"
|
#define SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER "SDL.texture.create.width"
|
||||||
#define SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER "SDL.texture.create.height"
|
#define SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER "SDL.texture.create.height"
|
||||||
#define SDL_PROP_TEXTURE_CREATE_PALETTE_POINTER "SDL.texture.create.palette"
|
#define SDL_PROP_TEXTURE_CREATE_PALETTE_POINTER "SDL.texture.create.palette"
|
||||||
#define SDL_PROP_TEXTURE_CREATE_SDR_WHITE_POINT_FLOAT "SDL.texture.create.SDR_white_point"
|
#define SDL_PROP_TEXTURE_CREATE_SDR_WHITE_POINT_FLOAT "SDL.texture.create.SDR_white_point"
|
||||||
#define SDL_PROP_TEXTURE_CREATE_HDR_HEADROOM_FLOAT "SDL.texture.create.HDR_headroom"
|
#define SDL_PROP_TEXTURE_CREATE_HDR_HEADROOM_FLOAT "SDL.texture.create.HDR_headroom"
|
||||||
#define SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_POINTER "SDL.texture.create.d3d11.texture"
|
#define SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_POINTER "SDL.texture.create.d3d11.texture"
|
||||||
#define SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_U_POINTER "SDL.texture.create.d3d11.texture_u"
|
#define SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_U_POINTER "SDL.texture.create.d3d11.texture_u"
|
||||||
#define SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_V_POINTER "SDL.texture.create.d3d11.texture_v"
|
#define SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_V_POINTER "SDL.texture.create.d3d11.texture_v"
|
||||||
#define SDL_PROP_TEXTURE_CREATE_D3D12_TEXTURE_POINTER "SDL.texture.create.d3d12.texture"
|
#define SDL_PROP_TEXTURE_CREATE_D3D12_TEXTURE_POINTER "SDL.texture.create.d3d12.texture"
|
||||||
#define SDL_PROP_TEXTURE_CREATE_D3D12_TEXTURE_U_POINTER "SDL.texture.create.d3d12.texture_u"
|
#define SDL_PROP_TEXTURE_CREATE_D3D12_TEXTURE_U_POINTER "SDL.texture.create.d3d12.texture_u"
|
||||||
#define SDL_PROP_TEXTURE_CREATE_D3D12_TEXTURE_V_POINTER "SDL.texture.create.d3d12.texture_v"
|
#define SDL_PROP_TEXTURE_CREATE_D3D12_TEXTURE_V_POINTER "SDL.texture.create.d3d12.texture_v"
|
||||||
#define SDL_PROP_TEXTURE_CREATE_METAL_PIXELBUFFER_POINTER "SDL.texture.create.metal.pixelbuffer"
|
#define SDL_PROP_TEXTURE_CREATE_METAL_PIXELBUFFER_POINTER "SDL.texture.create.metal.pixelbuffer"
|
||||||
#define SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_NUMBER "SDL.texture.create.opengl.texture"
|
#define SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_NUMBER "SDL.texture.create.opengl.texture"
|
||||||
#define SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_UV_NUMBER "SDL.texture.create.opengl.texture_uv"
|
#define SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_UV_NUMBER "SDL.texture.create.opengl.texture_uv"
|
||||||
#define SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_U_NUMBER "SDL.texture.create.opengl.texture_u"
|
#define SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_U_NUMBER "SDL.texture.create.opengl.texture_u"
|
||||||
#define SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_V_NUMBER "SDL.texture.create.opengl.texture_v"
|
#define SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_V_NUMBER "SDL.texture.create.opengl.texture_v"
|
||||||
#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER "SDL.texture.create.opengles2.texture"
|
#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER "SDL.texture.create.opengles2.texture"
|
||||||
#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_UV_NUMBER "SDL.texture.create.opengles2.texture_uv"
|
#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_UV_NUMBER "SDL.texture.create.opengles2.texture_uv"
|
||||||
#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_U_NUMBER "SDL.texture.create.opengles2.texture_u"
|
#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_U_NUMBER "SDL.texture.create.opengles2.texture_u"
|
||||||
#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_V_NUMBER "SDL.texture.create.opengles2.texture_v"
|
#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_V_NUMBER "SDL.texture.create.opengles2.texture_v"
|
||||||
#define SDL_PROP_TEXTURE_CREATE_VULKAN_TEXTURE_NUMBER "SDL.texture.create.vulkan.texture"
|
#define SDL_PROP_TEXTURE_CREATE_VULKAN_TEXTURE_NUMBER "SDL.texture.create.vulkan.texture"
|
||||||
|
#define SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_POINTER "SDL.texture.create.gpu.texture"
|
||||||
|
#define SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_UV_POINTER "SDL.texture.create.gpu.texture_uv"
|
||||||
|
#define SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_U_POINTER "SDL.texture.create.gpu.texture_u"
|
||||||
|
#define SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_V_POINTER "SDL.texture.create.gpu.texture_v"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the properties associated with a texture.
|
* Get the properties associated with a texture.
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ typedef struct GPU_PaletteData
|
|||||||
|
|
||||||
typedef struct GPU_TextureData
|
typedef struct GPU_TextureData
|
||||||
{
|
{
|
||||||
|
bool external_texture;
|
||||||
SDL_GPUTexture *texture;
|
SDL_GPUTexture *texture;
|
||||||
SDL_GPUTextureFormat format;
|
SDL_GPUTextureFormat format;
|
||||||
void *pixels;
|
void *pixels;
|
||||||
@@ -142,11 +143,14 @@ typedef struct GPU_TextureData
|
|||||||
#ifdef SDL_HAVE_YUV
|
#ifdef SDL_HAVE_YUV
|
||||||
// YV12 texture support
|
// YV12 texture support
|
||||||
bool yuv;
|
bool yuv;
|
||||||
|
bool external_texture_u;
|
||||||
|
bool external_texture_v;
|
||||||
SDL_GPUTexture *textureU;
|
SDL_GPUTexture *textureU;
|
||||||
SDL_GPUTexture *textureV;
|
SDL_GPUTexture *textureV;
|
||||||
|
|
||||||
// NV12 texture support
|
// NV12 texture support
|
||||||
bool nv12;
|
bool nv12;
|
||||||
|
bool external_texture_nv;
|
||||||
SDL_GPUTexture *textureNV;
|
SDL_GPUTexture *textureNV;
|
||||||
#endif
|
#endif
|
||||||
} GPU_TextureData;
|
} GPU_TextureData;
|
||||||
@@ -261,6 +265,12 @@ static bool GPU_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_
|
|||||||
SDL_GPUTextureFormat format;
|
SDL_GPUTextureFormat format;
|
||||||
SDL_GPUTextureUsageFlags usage = SDL_GPU_TEXTUREUSAGE_SAMPLER;
|
SDL_GPUTextureUsageFlags usage = SDL_GPU_TEXTUREUSAGE_SAMPLER;
|
||||||
|
|
||||||
|
data = (GPU_TextureData *)SDL_calloc(1, sizeof(*data));
|
||||||
|
if (!data) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
texture->internal = data;
|
||||||
|
|
||||||
switch (texture->format) {
|
switch (texture->format) {
|
||||||
case SDL_PIXELFORMAT_INDEX8:
|
case SDL_PIXELFORMAT_INDEX8:
|
||||||
case SDL_PIXELFORMAT_YV12:
|
case SDL_PIXELFORMAT_YV12:
|
||||||
@@ -292,11 +302,7 @@ static bool GPU_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_
|
|||||||
return SDL_SetError("Texture format %s not supported by SDL_GPU",
|
return SDL_SetError("Texture format %s not supported by SDL_GPU",
|
||||||
SDL_GetPixelFormatName(texture->format));
|
SDL_GetPixelFormatName(texture->format));
|
||||||
}
|
}
|
||||||
|
data->format = format;
|
||||||
data = (GPU_TextureData *)SDL_calloc(1, sizeof(*data));
|
|
||||||
if (!data) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
|
if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
|
||||||
size_t size;
|
size_t size;
|
||||||
@@ -326,7 +332,6 @@ static bool GPU_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_
|
|||||||
usage |= SDL_GPU_TEXTUREUSAGE_COLOR_TARGET;
|
usage |= SDL_GPU_TEXTUREUSAGE_COLOR_TARGET;
|
||||||
}
|
}
|
||||||
|
|
||||||
texture->internal = data;
|
|
||||||
SDL_GPUTextureCreateInfo tci;
|
SDL_GPUTextureCreateInfo tci;
|
||||||
SDL_zero(tci);
|
SDL_zero(tci);
|
||||||
tci.format = format;
|
tci.format = format;
|
||||||
@@ -336,11 +341,16 @@ static bool GPU_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_
|
|||||||
tci.width = texture->w;
|
tci.width = texture->w;
|
||||||
tci.height = texture->h;
|
tci.height = texture->h;
|
||||||
tci.sample_count = SDL_GPU_SAMPLECOUNT_1;
|
tci.sample_count = SDL_GPU_SAMPLECOUNT_1;
|
||||||
|
tci.props = create_props;
|
||||||
|
|
||||||
data->format = format;
|
data->texture = SDL_GetPointerProperty(create_props, SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_POINTER, NULL);
|
||||||
data->texture = SDL_CreateGPUTexture(renderdata->device, &tci);
|
if (data->texture) {
|
||||||
if (!data->texture) {
|
data->external_texture = true;
|
||||||
return false;
|
} else {
|
||||||
|
data->texture = SDL_CreateGPUTexture(renderdata->device, &tci);
|
||||||
|
if (!data->texture) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_PropertiesID props = SDL_GetTextureProperties(texture);
|
SDL_PropertiesID props = SDL_GetTextureProperties(texture);
|
||||||
@@ -354,15 +364,25 @@ static bool GPU_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_
|
|||||||
tci.width = (tci.width + 1) / 2;
|
tci.width = (tci.width + 1) / 2;
|
||||||
tci.height = (tci.height + 1) / 2;
|
tci.height = (tci.height + 1) / 2;
|
||||||
|
|
||||||
data->textureU = SDL_CreateGPUTexture(renderdata->device, &tci);
|
data->textureU = SDL_GetPointerProperty(create_props, SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_U_POINTER, NULL);
|
||||||
if (!data->textureU) {
|
if (data->textureU) {
|
||||||
return false;
|
data->external_texture_u = true;
|
||||||
|
} else {
|
||||||
|
data->textureU = SDL_CreateGPUTexture(renderdata->device, &tci);
|
||||||
|
if (!data->textureU) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
SDL_SetPointerProperty(props, SDL_PROP_TEXTURE_GPU_TEXTURE_U_POINTER, data->textureU);
|
SDL_SetPointerProperty(props, SDL_PROP_TEXTURE_GPU_TEXTURE_U_POINTER, data->textureU);
|
||||||
|
|
||||||
data->textureV = SDL_CreateGPUTexture(renderdata->device, &tci);
|
data->textureV = SDL_GetPointerProperty(create_props, SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_V_POINTER, NULL);
|
||||||
if (!data->textureV) {
|
if (data->textureV) {
|
||||||
return false;
|
data->external_texture_v = true;
|
||||||
|
} else {
|
||||||
|
data->textureV = SDL_CreateGPUTexture(renderdata->device, &tci);
|
||||||
|
if (!data->textureV) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
SDL_SetPointerProperty(props, SDL_PROP_TEXTURE_GPU_TEXTURE_V_POINTER, data->textureU);
|
SDL_SetPointerProperty(props, SDL_PROP_TEXTURE_GPU_TEXTURE_V_POINTER, data->textureU);
|
||||||
|
|
||||||
@@ -378,17 +398,22 @@ static bool GPU_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_
|
|||||||
|
|
||||||
data->nv12 = true;
|
data->nv12 = true;
|
||||||
|
|
||||||
tci.width = ((tci.width + 1) / 2);
|
data->textureNV = SDL_GetPointerProperty(create_props, SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_UV_POINTER, NULL);
|
||||||
tci.height = ((tci.height + 1) / 2);
|
if (data->textureNV) {
|
||||||
if (texture->format == SDL_PIXELFORMAT_P010) {
|
data->external_texture_nv = true;
|
||||||
tci.format = SDL_GPU_TEXTUREFORMAT_R16G16_UNORM;
|
|
||||||
} else {
|
} else {
|
||||||
tci.format = SDL_GPU_TEXTUREFORMAT_R8G8_UNORM;
|
tci.width = ((tci.width + 1) / 2);
|
||||||
}
|
tci.height = ((tci.height + 1) / 2);
|
||||||
|
if (texture->format == SDL_PIXELFORMAT_P010) {
|
||||||
|
tci.format = SDL_GPU_TEXTUREFORMAT_R16G16_UNORM;
|
||||||
|
} else {
|
||||||
|
tci.format = SDL_GPU_TEXTUREFORMAT_R8G8_UNORM;
|
||||||
|
}
|
||||||
|
|
||||||
data->textureNV = SDL_CreateGPUTexture(renderdata->device, &tci);
|
data->textureNV = SDL_CreateGPUTexture(renderdata->device, &tci);
|
||||||
if (!data->textureNV) {
|
if (!data->textureNV) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
SDL_SetPointerProperty(props, SDL_PROP_TEXTURE_GPU_TEXTURE_UV_POINTER, data->textureNV);
|
SDL_SetPointerProperty(props, SDL_PROP_TEXTURE_GPU_TEXTURE_UV_POINTER, data->textureNV);
|
||||||
|
|
||||||
@@ -1484,11 +1509,19 @@ static void GPU_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_ReleaseGPUTexture(renderdata->device, data->texture);
|
if (!data->external_texture) {
|
||||||
|
SDL_ReleaseGPUTexture(renderdata->device, data->texture);
|
||||||
|
}
|
||||||
#ifdef SDL_HAVE_YUV
|
#ifdef SDL_HAVE_YUV
|
||||||
SDL_ReleaseGPUTexture(renderdata->device, data->textureU);
|
if (!data->external_texture_u) {
|
||||||
SDL_ReleaseGPUTexture(renderdata->device, data->textureV);
|
SDL_ReleaseGPUTexture(renderdata->device, data->textureU);
|
||||||
SDL_ReleaseGPUTexture(renderdata->device, data->textureNV);
|
}
|
||||||
|
if (!data->external_texture_v) {
|
||||||
|
SDL_ReleaseGPUTexture(renderdata->device, data->textureV);
|
||||||
|
}
|
||||||
|
if (!data->external_texture_nv) {
|
||||||
|
SDL_ReleaseGPUTexture(renderdata->device, data->textureNV);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
SDL_free(data->pixels);
|
SDL_free(data->pixels);
|
||||||
SDL_free(data);
|
SDL_free(data);
|
||||||
|
|||||||
Reference in New Issue
Block a user