Skip to content

Commit 2e40c46

Browse files
committed
Added support for external GPU textures to the GPU renderer
1 parent 2638537 commit 2e40c46

File tree

2 files changed

+103
-53
lines changed

2 files changed

+103
-53
lines changed

include/SDL3/SDL_render.h

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,19 @@ extern SDL_DECLSPEC SDL_Texture * SDLCALL SDL_CreateTextureFromSurface(SDL_Rende
765765
* VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL associated with the texture, if
766766
* you want to wrap an existing texture.
767767
*
768+
* With the GPU renderer:
769+
*
770+
* - `SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_POINTER`: the SDL_GPUTexture associated with the texture, if you want to wrap an existing texture.
771+
* - `SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_UV_NUMBER`: the SDL_GPUTexture
772+
* associated with the UV plane of an NV12 texture, if you want to wrap an
773+
* existing texture.
774+
* - `SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_U_NUMBER`: the SDL_GPUTexture
775+
* associated with the U plane of a YUV texture, if you want to wrap an
776+
* existing texture.
777+
* - `SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_V_NUMBER`: the SDL_GPUTexture
778+
* associated with the V plane of a YUV texture, if you want to wrap an
779+
* existing texture.
780+
*
768781
* \param renderer the rendering context.
769782
* \param props the properties to use.
770783
* \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
783796
*/
784797
extern SDL_DECLSPEC SDL_Texture * SDLCALL SDL_CreateTextureWithProperties(SDL_Renderer *renderer, SDL_PropertiesID props);
785798

786-
#define SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER "SDL.texture.create.colorspace"
787-
#define SDL_PROP_TEXTURE_CREATE_FORMAT_NUMBER "SDL.texture.create.format"
788-
#define SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER "SDL.texture.create.access"
789-
#define SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER "SDL.texture.create.width"
790-
#define SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER "SDL.texture.create.height"
791-
#define SDL_PROP_TEXTURE_CREATE_PALETTE_POINTER "SDL.texture.create.palette"
792-
#define SDL_PROP_TEXTURE_CREATE_SDR_WHITE_POINT_FLOAT "SDL.texture.create.SDR_white_point"
793-
#define SDL_PROP_TEXTURE_CREATE_HDR_HEADROOM_FLOAT "SDL.texture.create.HDR_headroom"
794-
#define SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_POINTER "SDL.texture.create.d3d11.texture"
795-
#define SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_U_POINTER "SDL.texture.create.d3d11.texture_u"
796-
#define SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_V_POINTER "SDL.texture.create.d3d11.texture_v"
797-
#define SDL_PROP_TEXTURE_CREATE_D3D12_TEXTURE_POINTER "SDL.texture.create.d3d12.texture"
798-
#define SDL_PROP_TEXTURE_CREATE_D3D12_TEXTURE_U_POINTER "SDL.texture.create.d3d12.texture_u"
799-
#define SDL_PROP_TEXTURE_CREATE_D3D12_TEXTURE_V_POINTER "SDL.texture.create.d3d12.texture_v"
800-
#define SDL_PROP_TEXTURE_CREATE_METAL_PIXELBUFFER_POINTER "SDL.texture.create.metal.pixelbuffer"
801-
#define SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_NUMBER "SDL.texture.create.opengl.texture"
802-
#define SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_UV_NUMBER "SDL.texture.create.opengl.texture_uv"
803-
#define SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_U_NUMBER "SDL.texture.create.opengl.texture_u"
804-
#define SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_V_NUMBER "SDL.texture.create.opengl.texture_v"
805-
#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER "SDL.texture.create.opengles2.texture"
806-
#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_UV_NUMBER "SDL.texture.create.opengles2.texture_uv"
807-
#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_U_NUMBER "SDL.texture.create.opengles2.texture_u"
808-
#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_V_NUMBER "SDL.texture.create.opengles2.texture_v"
809-
#define SDL_PROP_TEXTURE_CREATE_VULKAN_TEXTURE_NUMBER "SDL.texture.create.vulkan.texture"
799+
#define SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER "SDL.texture.create.colorspace"
800+
#define SDL_PROP_TEXTURE_CREATE_FORMAT_NUMBER "SDL.texture.create.format"
801+
#define SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER "SDL.texture.create.access"
802+
#define SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER "SDL.texture.create.width"
803+
#define SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER "SDL.texture.create.height"
804+
#define SDL_PROP_TEXTURE_CREATE_PALETTE_POINTER "SDL.texture.create.palette"
805+
#define SDL_PROP_TEXTURE_CREATE_SDR_WHITE_POINT_FLOAT "SDL.texture.create.SDR_white_point"
806+
#define SDL_PROP_TEXTURE_CREATE_HDR_HEADROOM_FLOAT "SDL.texture.create.HDR_headroom"
807+
#define SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_POINTER "SDL.texture.create.d3d11.texture"
808+
#define SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_U_POINTER "SDL.texture.create.d3d11.texture_u"
809+
#define SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_V_POINTER "SDL.texture.create.d3d11.texture_v"
810+
#define SDL_PROP_TEXTURE_CREATE_D3D12_TEXTURE_POINTER "SDL.texture.create.d3d12.texture"
811+
#define SDL_PROP_TEXTURE_CREATE_D3D12_TEXTURE_U_POINTER "SDL.texture.create.d3d12.texture_u"
812+
#define SDL_PROP_TEXTURE_CREATE_D3D12_TEXTURE_V_POINTER "SDL.texture.create.d3d12.texture_v"
813+
#define SDL_PROP_TEXTURE_CREATE_METAL_PIXELBUFFER_POINTER "SDL.texture.create.metal.pixelbuffer"
814+
#define SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_NUMBER "SDL.texture.create.opengl.texture"
815+
#define SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_UV_NUMBER "SDL.texture.create.opengl.texture_uv"
816+
#define SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_U_NUMBER "SDL.texture.create.opengl.texture_u"
817+
#define SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_V_NUMBER "SDL.texture.create.opengl.texture_v"
818+
#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER "SDL.texture.create.opengles2.texture"
819+
#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_UV_NUMBER "SDL.texture.create.opengles2.texture_uv"
820+
#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_U_NUMBER "SDL.texture.create.opengles2.texture_u"
821+
#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_V_NUMBER "SDL.texture.create.opengles2.texture_v"
822+
#define SDL_PROP_TEXTURE_CREATE_VULKAN_TEXTURE_NUMBER "SDL.texture.create.vulkan.texture"
823+
#define SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_POINTER "SDL.texture.create.gpu.texture"
824+
#define SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_UV_POINTER "SDL.texture.create.gpu.texture_uv"
825+
#define SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_U_POINTER "SDL.texture.create.gpu.texture_u"
826+
#define SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_V_POINTER "SDL.texture.create.gpu.texture_v"
810827

811828
/**
812829
* Get the properties associated with a texture.

src/render/gpu/SDL_render_gpu.c

Lines changed: 62 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ typedef struct GPU_PaletteData
133133

134134
typedef struct GPU_TextureData
135135
{
136+
bool external_texture;
136137
SDL_GPUTexture *texture;
137138
SDL_GPUTextureFormat format;
138139
void *pixels;
@@ -142,11 +143,14 @@ typedef struct GPU_TextureData
142143
#ifdef SDL_HAVE_YUV
143144
// YV12 texture support
144145
bool yuv;
146+
bool external_texture_u;
147+
bool external_texture_v;
145148
SDL_GPUTexture *textureU;
146149
SDL_GPUTexture *textureV;
147150

148151
// NV12 texture support
149152
bool nv12;
153+
bool external_texture_nv;
150154
SDL_GPUTexture *textureNV;
151155
#endif
152156
} GPU_TextureData;
@@ -261,6 +265,12 @@ static bool GPU_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_
261265
SDL_GPUTextureFormat format;
262266
SDL_GPUTextureUsageFlags usage = SDL_GPU_TEXTUREUSAGE_SAMPLER;
263267

268+
data = (GPU_TextureData *)SDL_calloc(1, sizeof(*data));
269+
if (!data) {
270+
return false;
271+
}
272+
texture->internal = data;
273+
264274
switch (texture->format) {
265275
case SDL_PIXELFORMAT_INDEX8:
266276
case SDL_PIXELFORMAT_YV12:
@@ -292,11 +302,7 @@ static bool GPU_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_
292302
return SDL_SetError("Texture format %s not supported by SDL_GPU",
293303
SDL_GetPixelFormatName(texture->format));
294304
}
295-
296-
data = (GPU_TextureData *)SDL_calloc(1, sizeof(*data));
297-
if (!data) {
298-
return false;
299-
}
305+
data->format = format;
300306

301307
if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
302308
size_t size;
@@ -326,7 +332,6 @@ static bool GPU_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_
326332
usage |= SDL_GPU_TEXTUREUSAGE_COLOR_TARGET;
327333
}
328334

329-
texture->internal = data;
330335
SDL_GPUTextureCreateInfo tci;
331336
SDL_zero(tci);
332337
tci.format = format;
@@ -336,11 +341,16 @@ static bool GPU_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_
336341
tci.width = texture->w;
337342
tci.height = texture->h;
338343
tci.sample_count = SDL_GPU_SAMPLECOUNT_1;
344+
tci.props = create_props;
339345

340-
data->format = format;
341-
data->texture = SDL_CreateGPUTexture(renderdata->device, &tci);
342-
if (!data->texture) {
343-
return false;
346+
data->texture = SDL_GetPointerProperty(create_props, SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_POINTER, NULL);
347+
if (data->texture) {
348+
data->external_texture = true;
349+
} else {
350+
data->texture = SDL_CreateGPUTexture(renderdata->device, &tci);
351+
if (!data->texture) {
352+
return false;
353+
}
344354
}
345355

346356
SDL_PropertiesID props = SDL_GetTextureProperties(texture);
@@ -354,15 +364,25 @@ static bool GPU_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_
354364
tci.width = (tci.width + 1) / 2;
355365
tci.height = (tci.height + 1) / 2;
356366

357-
data->textureU = SDL_CreateGPUTexture(renderdata->device, &tci);
358-
if (!data->textureU) {
359-
return false;
367+
data->textureU = SDL_GetPointerProperty(create_props, SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_U_POINTER, NULL);
368+
if (data->textureU) {
369+
data->external_texture_u = true;
370+
} else {
371+
data->textureU = SDL_CreateGPUTexture(renderdata->device, &tci);
372+
if (!data->textureU) {
373+
return false;
374+
}
360375
}
361376
SDL_SetPointerProperty(props, SDL_PROP_TEXTURE_GPU_TEXTURE_U_POINTER, data->textureU);
362377

363-
data->textureV = SDL_CreateGPUTexture(renderdata->device, &tci);
364-
if (!data->textureV) {
365-
return false;
378+
data->textureV = SDL_GetPointerProperty(create_props, SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_V_POINTER, NULL);
379+
if (data->textureV) {
380+
data->external_texture_v = true;
381+
} else {
382+
data->textureV = SDL_CreateGPUTexture(renderdata->device, &tci);
383+
if (!data->textureV) {
384+
return false;
385+
}
366386
}
367387
SDL_SetPointerProperty(props, SDL_PROP_TEXTURE_GPU_TEXTURE_V_POINTER, data->textureU);
368388

@@ -378,17 +398,22 @@ static bool GPU_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_
378398

379399
data->nv12 = true;
380400

381-
tci.width = ((tci.width + 1) / 2);
382-
tci.height = ((tci.height + 1) / 2);
383-
if (texture->format == SDL_PIXELFORMAT_P010) {
384-
tci.format = SDL_GPU_TEXTUREFORMAT_R16G16_UNORM;
401+
data->textureNV = SDL_GetPointerProperty(create_props, SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_UV_POINTER, NULL);
402+
if (data->textureNV) {
403+
data->external_texture_nv = true;
385404
} else {
386-
tci.format = SDL_GPU_TEXTUREFORMAT_R8G8_UNORM;
387-
}
405+
tci.width = ((tci.width + 1) / 2);
406+
tci.height = ((tci.height + 1) / 2);
407+
if (texture->format == SDL_PIXELFORMAT_P010) {
408+
tci.format = SDL_GPU_TEXTUREFORMAT_R16G16_UNORM;
409+
} else {
410+
tci.format = SDL_GPU_TEXTUREFORMAT_R8G8_UNORM;
411+
}
388412

389-
data->textureNV = SDL_CreateGPUTexture(renderdata->device, &tci);
390-
if (!data->textureNV) {
391-
return false;
413+
data->textureNV = SDL_CreateGPUTexture(renderdata->device, &tci);
414+
if (!data->textureNV) {
415+
return false;
416+
}
392417
}
393418
SDL_SetPointerProperty(props, SDL_PROP_TEXTURE_GPU_TEXTURE_UV_POINTER, data->textureNV);
394419

@@ -1484,11 +1509,19 @@ static void GPU_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
14841509
return;
14851510
}
14861511

1487-
SDL_ReleaseGPUTexture(renderdata->device, data->texture);
1512+
if (!data->external_texture) {
1513+
SDL_ReleaseGPUTexture(renderdata->device, data->texture);
1514+
}
14881515
#ifdef SDL_HAVE_YUV
1489-
SDL_ReleaseGPUTexture(renderdata->device, data->textureU);
1490-
SDL_ReleaseGPUTexture(renderdata->device, data->textureV);
1491-
SDL_ReleaseGPUTexture(renderdata->device, data->textureNV);
1516+
if (!data->external_texture_u) {
1517+
SDL_ReleaseGPUTexture(renderdata->device, data->textureU);
1518+
}
1519+
if (!data->external_texture_v) {
1520+
SDL_ReleaseGPUTexture(renderdata->device, data->textureV);
1521+
}
1522+
if (!data->external_texture_nv) {
1523+
SDL_ReleaseGPUTexture(renderdata->device, data->textureNV);
1524+
}
14921525
#endif
14931526
SDL_free(data->pixels);
14941527
SDL_free(data);

0 commit comments

Comments
 (0)