From 1c64366b8097ff9e9361e878f6aff793dcde3bf1 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 13 Nov 2023 12:13:20 -0800 Subject: [PATCH] Added SDL_CreateRendererWithProperties() and SDL_CreateTextureWithProperties() --- include/SDL3/SDL_render.h | 129 +++++++++++++++++------ src/dynapi/SDL_dynapi.sym | 2 + src/dynapi/SDL_dynapi_overrides.h | 2 + src/dynapi/SDL_dynapi_procs.h | 2 + src/render/SDL_render.c | 71 ++++++++++--- src/render/SDL_sysrender.h | 4 +- src/render/direct3d/SDL_render_d3d.c | 8 +- src/render/direct3d11/SDL_render_d3d11.c | 75 ++++++++----- src/render/direct3d12/SDL_render_d3d12.c | 105 +++++++++++------- src/render/metal/SDL_render_metal.m | 6 +- src/render/opengl/SDL_render_gl.c | 65 +++++++++--- src/render/opengles2/SDL_render_gles2.c | 63 +++++++---- src/render/ps2/SDL_render_ps2.c | 12 ++- src/render/psp/SDL_render_psp.c | 10 +- src/render/software/SDL_render_sw.c | 10 +- src/render/vitagxm/SDL_render_vita_gxm.c | 11 +- 16 files changed, 406 insertions(+), 169 deletions(-) diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index 86a2abb1a..b7313d9d0 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -195,7 +195,6 @@ extern DECLSPEC int SDLCALL SDL_GetNumRenderDrivers(void); */ extern DECLSPEC const char *SDLCALL SDL_GetRenderDriver(int index); - /** * Create a window and default renderer. * @@ -215,14 +214,13 @@ extern DECLSPEC const char *SDLCALL SDL_GetRenderDriver(int index); */ extern DECLSPEC int SDLCALL SDL_CreateWindowAndRenderer(int width, int height, Uint32 window_flags, SDL_Window **window, SDL_Renderer **renderer); - /** * Create a 2D rendering context for a window. * * If you want a specific renderer, you can specify its name here. A list of * available renderers can be obtained by calling SDL_GetRenderDriver multiple * times, with indices from 0 to SDL_GetNumRenderDrivers()-1. If you don't - * need a specific renderer, specify NULL and SDL will attempt to chooes the + * need a specific renderer, specify NULL and SDL will attempt to choose the * best option for you, based on what is available on the user's system. * * By default the rendering size matches the window size in pixels, but you @@ -238,13 +236,37 @@ extern DECLSPEC int SDLCALL SDL_CreateWindowAndRenderer(int width, int height, U * * \since This function is available since SDL 3.0.0. * + * \sa SDL_CreateRendererWithProperties * \sa SDL_CreateSoftwareRenderer * \sa SDL_DestroyRenderer * \sa SDL_GetNumRenderDrivers * \sa SDL_GetRenderDriver * \sa SDL_GetRendererInfo */ -extern DECLSPEC SDL_Renderer *SDLCALL SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 flags); +extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 flags); + +/** + * Create a 2D rendering context for a window, with the specified properties. + * + * These are the supported properties: + * + * - "window" (pointer) - the window where rendering is displayed + * - "surface" (pointer) - the surface where rendering is displayed, if you want a software renderer without a window + * - "name" (string) - the name of the rendering driver to use, if a specific one is desired + * - "present_vsync" (boolean) - true if you want present synchronized with the refresh rate + * + * \param props the properties to use + * \returns a valid rendering context or NULL if there was an error; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_CreateRenderer + * \sa SDL_CreateSoftwareRenderer + * \sa SDL_DestroyRenderer + * \sa SDL_GetRendererInfo + */ +extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRendererWithProperties(SDL_PropertiesID props); /** * Create a 2D software rendering context for a surface. @@ -309,7 +331,7 @@ extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_Rend /** * Get the properties associated with a renderer. * - * The following properties are provided by SDL: + * The following read-only properties are provided by SDL: * * ``` * "SDL.renderer.d3d9.device" (pointer) - the IDirect3DDevice9 associated with the renderer @@ -386,6 +408,7 @@ extern DECLSPEC int SDLCALL SDL_GetCurrentRenderOutputSize(SDL_Renderer *rendere * \since This function is available since SDL 3.0.0. * * \sa SDL_CreateTextureFromSurface + * \sa SDL_CreateTextureWithProperties * \sa SDL_DestroyTexture * \sa SDL_QueryTexture * \sa SDL_UpdateTexture @@ -413,50 +436,96 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTexture(SDL_Renderer *renderer, U * \since This function is available since SDL 3.0.0. * * \sa SDL_CreateTexture + * \sa SDL_CreateTextureWithProperties * \sa SDL_DestroyTexture * \sa SDL_QueryTexture */ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *surface); /** - * Get the properties associated with a texture. + * Create a texture for a rendering context with the specified properties. * - * The following properties are provided by SDL: + * These are the supported properties: + * + * - "format" (number) - one of the enumerated values in SDL_PixelFormatEnum, defaults to the best RGBA format for the renderer + * - "access" (number) - one of the enumerated values in SDL_TextureAccess, defaults to SDL_TEXTUREACCESS_STATIC + * - "width" (number) - the width of the texture in pixels, required + * - "height" (number) - the height of the texture in pixels, required * * With the direct3d11 renderer: * - * ``` - * "SDL.texture.d3d11.texture" (pointer) - the ID3D11Texture2D associated with the texture - * "SDL.texture.d3d11.texture_u" (pointer) - the ID3D11Texture2D associated with the U plane of a YUV texture - * "SDL.texture.d3d11.texture_v" (pointer) - the ID3D11Texture2D associated with the V plane of a YUV texture - * ``` + * - "d3d11.texture" (pointer) - the ID3D11Texture2D associated with the texture, if you want to wrap an existing texture. + * - "d3d11.texture_u" (pointer) - the ID3D11Texture2D associated with the U plane of a YUV texture, if you want to wrap an existing texture. + * - "d3d11.texture_v" (pointer) - the ID3D11Texture2D associated with the V plane of a YUV texture, if you want to wrap an existing texture. * * With the direct3d12 renderer: * - * ``` - * "SDL.texture.d3d12.texture" (pointer) - the ID3D12Resource associated with the texture - * "SDL.texture.d3d12.texture_u" (pointer) - the ID3D12Resource associated with the U plane of a YUV texture - * "SDL.texture.d3d12.texture_v" (pointer) - the ID3D12Resource associated with the V plane of a YUV texture - * ``` + * - "d3d12.texture" (pointer) - the ID3D12Resource associated with the texture, if you want to wrap an existing texture. + * - "d3d12.texture_u" (pointer) - the ID3D12Resource associated with the U plane of a YUV texture, if you want to wrap an existing texture. + * - "d3d12.texture_v" (pointer) - the ID3D12Resource associated with the V plane of a YUV texture, if you want to wrap an existing texture. * * With the opengl renderer: * - * ``` - * "SDL.texture.opengl.texture" (number) - the GLuint texture associated with the texture - * "SDL.texture.opengl.texture_u" (number) - the GLuint texture associated with the U plane of a YUV texture - * "SDL.texture.opengl.texture_v" (number) - the GLuint texture associated with the V plane of a YUV texture - * "SDL.texture.opengl.tex_w" (float) - the texture coordinate width of the texture (0.0 - 1.0) - * "SDL.texture.opengl.tex_h" (float) - the texture coordinate height of the texture (0.0 - 1.0) - * ``` + * - "opengl.texture" (number) - the GLuint texture associated with the texture, if you want to wrap an existing texture. + * - "opengl.texture_uv" (number) - the GLuint texture associated with the UV plane of an NV12 texture, if you want to wrap an existing texture. + * - "opengl.texture_u" (number) - the GLuint texture associated with the U plane of a YUV texture, if you want to wrap an existing texture. + * - "opengl.texture_v" (number) - the GLuint texture associated with the V plane of a YUV texture, if you want to wrap an existing texture. * * With the opengles2 renderer: * - * ``` - * "SDL.texture.opengles2.texture" (number) - the GLuint texture associated with the texture - * "SDL.texture.opengles2.texture_uv" (number) - the GLuint texture associated with the UV plane of an NV12 texture - * "SDL.texture.opengles2.texture_u" (number) - the GLuint texture associated with the U plane of a YUV texture - * "SDL.texture.opengles2.texture_v" (number) - the GLuint texture associated with the V plane of a YUV texture - * ``` + * - "opengles2.texture" (number) - the GLuint texture associated with the texture, if you want to wrap an existing texture. + * - "opengles2.texture_uv" (number) - the GLuint texture associated with the UV plane of an NV12 texture, if you want to wrap an existing texture. + * - "opengles2.texture_u" (number) - the GLuint texture associated with the U plane of a YUV texture, if you want to wrap an existing texture. + * - "opengles2.texture_v" (number) - the GLuint texture associated with the V plane of a YUV texture, if you want to wrap an existing texture. + * + * \param renderer the rendering context + * \param props the properties to use + * \returns a pointer to the created texture or NULL if no rendering context + * was active, the format was unsupported, or the width or height + * were out of range; call SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_CreateTextureFromSurface + * \sa SDL_CreateTexture + * \sa SDL_DestroyTexture + * \sa SDL_QueryTexture + * \sa SDL_UpdateTexture + */ +extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureWithProperties(SDL_Renderer *renderer, SDL_PropertiesID props); + +/** + * Get the properties associated with a texture. + * + * The following read-only properties are provided by SDL: + * + * With the direct3d11 renderer: + * + * - "SDL.texture.d3d11.texture" (pointer) - the ID3D11Texture2D associated with the texture + * - "SDL.texture.d3d11.texture_u" (pointer) - the ID3D11Texture2D associated with the U plane of a YUV texture + * - "SDL.texture.d3d11.texture_v" (pointer) - the ID3D11Texture2D associated with the V plane of a YUV texture + * + * With the direct3d12 renderer: + * + * - "SDL.texture.d3d12.texture" (pointer) - the ID3D12Resource associated with the texture + * - "SDL.texture.d3d12.texture_u" (pointer) - the ID3D12Resource associated with the U plane of a YUV texture + * - "SDL.texture.d3d12.texture_v" (pointer) - the ID3D12Resource associated with the V plane of a YUV texture + * + * With the opengl renderer: + * + * - "SDL.texture.opengl.texture" (number) - the GLuint texture associated with the texture + * - "SDL.texture.opengl.texture_uv" (number) - the GLuint texture associated with the UV plane of an NV12 texture + * - "SDL.texture.opengl.texture_u" (number) - the GLuint texture associated with the U plane of a YUV texture + * - "SDL.texture.opengl.texture_v" (number) - the GLuint texture associated with the V plane of a YUV texture + * - "SDL.texture.opengl.tex_w" (float) - the texture coordinate width of the texture (0.0 - 1.0) + * - "SDL.texture.opengl.tex_h" (float) - the texture coordinate height of the texture (0.0 - 1.0) + * + * With the opengles2 renderer: + * + * - "SDL.texture.opengles2.texture" (number) - the GLuint texture associated with the texture + * - "SDL.texture.opengles2.texture_uv" (number) - the GLuint texture associated with the UV plane of an NV12 texture + * - "SDL.texture.opengles2.texture_u" (number) - the GLuint texture associated with the U plane of a YUV texture + * - "SDL.texture.opengles2.texture_v" (number) - the GLuint texture associated with the V plane of a YUV texture * * \param texture the texture to query * \returns a valid property ID on success or 0 on failure; call diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index bb55f404c..14bc32ae9 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -965,6 +965,8 @@ SDL3_0.0.0 { SDL_EnumerateProperties; SDL_SetBooleanProperty; SDL_GetBooleanProperty; + SDL_CreateTextureWithProperties; + SDL_CreateRendererWithProperties; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 57e1affe2..83ec2ca33 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -990,3 +990,5 @@ #define SDL_EnumerateProperties SDL_EnumerateProperties_REAL #define SDL_SetBooleanProperty SDL_SetBooleanProperty_REAL #define SDL_GetBooleanProperty SDL_GetBooleanProperty_REAL +#define SDL_CreateTextureWithProperties SDL_CreateTextureWithProperties_REAL +#define SDL_CreateRendererWithProperties SDL_CreateRendererWithProperties_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 3d8049d02..7ddba0e8c 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -1015,3 +1015,5 @@ SDL_DYNAPI_PROC(float,SDL_GetFloatProperty,(SDL_PropertiesID a, const char *b, f SDL_DYNAPI_PROC(int,SDL_EnumerateProperties,(SDL_PropertiesID a, SDL_EnumeratePropertiesCallback b, void *c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_SetBooleanProperty,(SDL_PropertiesID a, const char *b, SDL_bool c),(a,b,c),return) SDL_DYNAPI_PROC(SDL_bool,SDL_GetBooleanProperty,(SDL_PropertiesID a, const char *b, SDL_bool c),(a,b,c),return) +SDL_DYNAPI_PROC(SDL_Texture*,SDL_CreateTextureWithProperties,(SDL_Renderer *a, SDL_PropertiesID b),(a,b),return) +SDL_DYNAPI_PROC(SDL_Renderer*,SDL_CreateRendererWithProperties,(SDL_PropertiesID a),(a),return) diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index 8f987e84d..aedde6af3 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -804,15 +804,23 @@ static void SDL_CalculateSimulatedVSyncInterval(SDL_Renderer *renderer, SDL_Wind #endif /* !SDL_RENDER_DISABLED */ -SDL_Renderer *SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 flags) + +SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props) { #ifndef SDL_RENDER_DISABLED + SDL_Window *window = SDL_GetProperty(props, "window", NULL); + SDL_Surface *surface = SDL_GetProperty(props, "surface", NULL); + const char *name = SDL_GetStringProperty(props, "name", NULL); SDL_Renderer *renderer = NULL; const int n = SDL_GetNumRenderDrivers(); SDL_bool batching = SDL_TRUE; const char *hint; int i; + if (!window && surface) { + return SDL_CreateSoftwareRenderer(surface); + } + #ifdef __ANDROID__ Android_ActivityMutex_Lock_Running(); #endif @@ -834,11 +842,7 @@ SDL_Renderer *SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 fl hint = SDL_GetHint(SDL_HINT_RENDER_VSYNC); if (hint && *hint) { - if (SDL_GetHintBoolean(SDL_HINT_RENDER_VSYNC, SDL_TRUE)) { - flags |= SDL_RENDERER_PRESENTVSYNC; - } else { - flags &= ~SDL_RENDERER_PRESENTVSYNC; - } + SDL_SetBooleanProperty(props, "present_vsync", SDL_GetHintBoolean(SDL_HINT_RENDER_VSYNC, SDL_TRUE)); } if (!name) { @@ -850,7 +854,7 @@ SDL_Renderer *SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 fl const SDL_RenderDriver *driver = render_drivers[i]; if (SDL_strcasecmp(name, driver->info.name) == 0) { /* Create a new renderer instance */ - renderer = driver->CreateRenderer(window, flags); + renderer = driver->CreateRenderer(window, props); if (renderer) { batching = SDL_FALSE; } @@ -860,13 +864,11 @@ SDL_Renderer *SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 fl } else { for (i = 0; i < n; i++) { const SDL_RenderDriver *driver = render_drivers[i]; - if ((driver->info.flags & flags) == flags) { - /* Create a new renderer instance */ - renderer = driver->CreateRenderer(window, flags); - if (renderer) { - /* Yay, we got one! */ - break; - } + /* Create a new renderer instance */ + renderer = driver->CreateRenderer(window, props); + if (renderer) { + /* Yay, we got one! */ + break; } } } @@ -876,7 +878,7 @@ SDL_Renderer *SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 fl goto error; } - if (flags & SDL_RENDERER_PRESENTVSYNC) { + if (SDL_GetBooleanProperty(props, "present_vsync", SDL_FALSE)) { renderer->wanted_vsync = SDL_TRUE; if (!(renderer->info.flags & SDL_RENDERER_PRESENTVSYNC)) { @@ -956,6 +958,24 @@ error: #endif } +SDL_Renderer *SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 flags) +{ + SDL_Renderer *renderer; + SDL_PropertiesID props = SDL_CreateProperties(); + SDL_SetProperty(props, "window", window); + if (flags & SDL_RENDERER_SOFTWARE) { + SDL_SetStringProperty(props, "name", "software"); + } else { + SDL_SetStringProperty(props, "name", name); + } + if (flags & SDL_RENDERER_PRESENTVSYNC) { + SDL_SetBooleanProperty(props, "present_vsync", SDL_TRUE); + } + renderer = SDL_CreateRendererWithProperties(props); + SDL_DestroyProperties(props); + return renderer; +} + SDL_Renderer *SDL_CreateSoftwareRenderer(SDL_Surface *surface) { #if !defined(SDL_RENDER_DISABLED) && SDL_VIDEO_RENDER_SW @@ -1116,9 +1136,13 @@ static SDL_ScaleMode SDL_GetScaleMode(void) } } -SDL_Texture *SDL_CreateTexture(SDL_Renderer *renderer, Uint32 format, int access, int w, int h) +SDL_Texture *SDL_CreateTextureWithProperties(SDL_Renderer *renderer, SDL_PropertiesID props) { SDL_Texture *texture; + Uint32 format = (Uint32)SDL_GetNumberProperty(props, "format", SDL_PIXELFORMAT_UNKNOWN); + int access = (int)SDL_GetNumberProperty(props, "access", SDL_TEXTUREACCESS_STATIC); + int w = (int)SDL_GetNumberProperty(props, "width", 0); + int h = (int)SDL_GetNumberProperty(props, "height", 0); SDL_bool texture_is_fourcc_and_target; CHECK_RENDERER_MAGIC(renderer, NULL); @@ -1177,7 +1201,7 @@ SDL_Texture *SDL_CreateTexture(SDL_Renderer *renderer, Uint32 format, int access texture_is_fourcc_and_target = (access == SDL_TEXTUREACCESS_TARGET && SDL_ISPIXELFORMAT_FOURCC(texture->format)); if (texture_is_fourcc_and_target == SDL_FALSE && IsSupportedFormat(renderer, format)) { - if (renderer->CreateTexture(renderer, texture) < 0) { + if (renderer->CreateTexture(renderer, texture, props) < 0) { SDL_DestroyTexture(texture); return NULL; } @@ -1232,6 +1256,19 @@ SDL_Texture *SDL_CreateTexture(SDL_Renderer *renderer, Uint32 format, int access return texture; } +SDL_Texture *SDL_CreateTexture(SDL_Renderer *renderer, Uint32 format, int access, int w, int h) +{ + SDL_Texture *texture; + SDL_PropertiesID props = SDL_CreateProperties(); + SDL_SetNumberProperty(props, "format", format); + SDL_SetNumberProperty(props, "access", access); + SDL_SetNumberProperty(props, "width", w); + SDL_SetNumberProperty(props, "height", h); + texture = SDL_CreateTextureWithProperties(renderer, props); + SDL_DestroyProperties(props); + return texture; +} + SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *surface) { const SDL_PixelFormat *fmt; diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h index edba7e18e..187073de1 100644 --- a/src/render/SDL_sysrender.h +++ b/src/render/SDL_sysrender.h @@ -160,7 +160,7 @@ struct SDL_Renderer void (*WindowEvent)(SDL_Renderer *renderer, const SDL_WindowEvent *event); int (*GetOutputSize)(SDL_Renderer *renderer, int *w, int *h); SDL_bool (*SupportsBlendMode)(SDL_Renderer *renderer, SDL_BlendMode blendMode); - int (*CreateTexture)(SDL_Renderer *renderer, SDL_Texture *texture); + int (*CreateTexture)(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props); int (*QueueSetViewport)(SDL_Renderer *renderer, SDL_RenderCommand *cmd); int (*QueueSetDrawColor)(SDL_Renderer *renderer, SDL_RenderCommand *cmd); int (*QueueDrawPoints)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, @@ -280,7 +280,7 @@ struct SDL_Renderer /* Define the SDL render driver structure */ struct SDL_RenderDriver { - SDL_Renderer *(*CreateRenderer)(SDL_Window *window, Uint32 flags); + SDL_Renderer *(*CreateRenderer)(SDL_Window *window, SDL_PropertiesID props); /* Info about the renderer capabilities */ SDL_RendererInfo info; diff --git a/src/render/direct3d/SDL_render_d3d.c b/src/render/direct3d/SDL_render_d3d.c index 7d6428932..6a882ce0f 100644 --- a/src/render/direct3d/SDL_render_d3d.c +++ b/src/render/direct3d/SDL_render_d3d.c @@ -517,7 +517,7 @@ static void D3D_DestroyTextureRep(D3D_TextureRep *texture) } } -static int D3D_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) +static int D3D_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props) { D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata; D3D_TextureData *texturedata; @@ -1493,7 +1493,7 @@ static int D3D_Reset(SDL_Renderer *renderer) /* Allocate application render targets */ for (texture = renderer->textures; texture; texture = texture->next) { if (texture->access == SDL_TEXTUREACCESS_TARGET) { - D3D_CreateTexture(renderer, texture); + D3D_CreateTexture(renderer, texture, 0); } } @@ -1536,7 +1536,7 @@ static int D3D_SetVSync(SDL_Renderer *renderer, const int vsync) return 0; } -SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, Uint32 flags) +SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props) { SDL_Renderer *renderer; D3D_RenderData *data; @@ -1617,7 +1617,7 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, Uint32 flags) pparams.BackBufferFormat = D3DFMT_UNKNOWN; pparams.FullScreen_RefreshRateInHz = 0; } - if (flags & SDL_RENDERER_PRESENTVSYNC) { + if (SDL_GetBooleanProperty(create_props, "present_vsync", SDL_FALSE)) { pparams.PresentationInterval = D3DPRESENT_INTERVAL_ONE; } else { pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; diff --git a/src/render/direct3d11/SDL_render_d3d11.c b/src/render/direct3d11/SDL_render_d3d11.c index 4561dfe30..5e4eba0f4 100644 --- a/src/render/direct3d11/SDL_render_d3d11.c +++ b/src/render/direct3d11/SDL_render_d3d11.c @@ -1062,7 +1062,19 @@ static SDL_bool D3D11_SupportsBlendMode(SDL_Renderer *renderer, SDL_BlendMode bl return SDL_TRUE; } -static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) +static int GetTextureProperty(SDL_PropertiesID props, const char *name, ID3D11Texture2D **texture) +{ + IUnknown *unknown = SDL_GetProperty(props, name, NULL); + if (unknown) { + HRESULT result = IUnknown_QueryInterface(unknown, &SDL_IID_ID3D11Texture2D, (void **)texture); + if (FAILED(result)) { + return WIN_SetErrorFromHRESULT(name, result); + } + } + return 0; +} + +static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props) { D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata; D3D11_TextureData *textureData; @@ -1109,13 +1121,18 @@ static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; } - result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice, - &textureDesc, - NULL, - &textureData->mainTexture); - if (FAILED(result)) { - D3D11_DestroyTexture(renderer, texture); - return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result); + if (GetTextureProperty(create_props, "d3d11.texture", &textureData->mainTexture) < 0) { + return -1; + } + if (!textureData->mainTexture) { + result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice, + &textureDesc, + NULL, + &textureData->mainTexture); + if (FAILED(result)) { + D3D11_DestroyTexture(renderer, texture); + return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result); + } } SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.d3d11.texture", textureData->mainTexture); #if SDL_HAVE_YUV @@ -1126,23 +1143,33 @@ static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) textureDesc.Width = (textureDesc.Width + 1) / 2; textureDesc.Height = (textureDesc.Height + 1) / 2; - result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice, - &textureDesc, - NULL, - &textureData->mainTextureU); - if (FAILED(result)) { - D3D11_DestroyTexture(renderer, texture); - return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result); + if (GetTextureProperty(create_props, "d3d11.texture_u", &textureData->mainTextureU) < 0) { + return -1; + } + if (!textureData->mainTextureU) { + result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice, + &textureDesc, + NULL, + &textureData->mainTextureU); + if (FAILED(result)) { + D3D11_DestroyTexture(renderer, texture); + return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result); + } } SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.d3d11.texture_u", textureData->mainTextureU); - result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice, - &textureDesc, - NULL, - &textureData->mainTextureV); - if (FAILED(result)) { - D3D11_DestroyTexture(renderer, texture); - return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result); + if (GetTextureProperty(create_props, "d3d11.texture_v", &textureData->mainTextureV) < 0) { + return -1; + } + if (!textureData->mainTextureV) { + result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice, + &textureDesc, + NULL, + &textureData->mainTextureV); + if (FAILED(result)) { + D3D11_DestroyTexture(renderer, texture); + return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result); + } } SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.d3d11.texture_v", textureData->mainTextureV); } @@ -2384,7 +2411,7 @@ static int D3D11_SetVSync(SDL_Renderer *renderer, const int vsync) } #endif -SDL_Renderer *D3D11_CreateRenderer(SDL_Window *window, Uint32 flags) +SDL_Renderer *D3D11_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props) { SDL_Renderer *renderer; D3D11_RenderData *data; @@ -2445,7 +2472,7 @@ SDL_Renderer *D3D11_CreateRenderer(SDL_Window *window, Uint32 flags) */ renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; #else - if (flags & SDL_RENDERER_PRESENTVSYNC) { + if (SDL_GetBooleanProperty(create_props, "present_vsync", SDL_FALSE)) { renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; } renderer->SetVSync = D3D11_SetVSync; diff --git a/src/render/direct3d12/SDL_render_d3d12.c b/src/render/direct3d12/SDL_render_d3d12.c index 1442be58e..c241c3bc9 100644 --- a/src/render/direct3d12/SDL_render_d3d12.c +++ b/src/render/direct3d12/SDL_render_d3d12.c @@ -1432,7 +1432,19 @@ static void D3D12_FreeSRVIndex(SDL_Renderer *renderer, SIZE_T index) rendererData->srvPoolHead = &rendererData->srvPoolNodes[index]; } -static int D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) +static int GetTextureProperty(SDL_PropertiesID props, const char *name, ID3D12Resource **texture) +{ + IUnknown *unknown = SDL_GetProperty(props, name, NULL); + if (unknown) { + HRESULT result = D3D_CALL(unknown, QueryInterface, D3D_GUID(SDL_IID_ID3D12Resource), (void **)texture); + if (FAILED(result)) { + return WIN_SetErrorFromHRESULT(name, result); + } + } + return 0; +} + +static int D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props) { D3D12_RenderData *rendererData = (D3D12_RenderData *)renderer->driverdata; D3D12_TextureData *textureData; @@ -1476,19 +1488,24 @@ static int D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) heapProps.CreationNodeMask = 1; heapProps.VisibleNodeMask = 1; - result = D3D_CALL(rendererData->d3dDevice, CreateCommittedResource, - &heapProps, - D3D12_HEAP_FLAG_NONE, - &textureDesc, - D3D12_RESOURCE_STATE_COPY_DEST, - NULL, - D3D_GUID(SDL_IID_ID3D12Resource), - (void **)&textureData->mainTexture); - textureData->mainResourceState = D3D12_RESOURCE_STATE_COPY_DEST; - if (FAILED(result)) { - D3D12_DestroyTexture(renderer, texture); - return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D12Device::CreateCommittedResource [texture]"), result); + if (GetTextureProperty(create_props, "d3d12.texture", &textureData->mainTexture) < 0) { + return -1; } + if (!textureData->mainTexture) { + result = D3D_CALL(rendererData->d3dDevice, CreateCommittedResource, + &heapProps, + D3D12_HEAP_FLAG_NONE, + &textureDesc, + D3D12_RESOURCE_STATE_COPY_DEST, + NULL, + D3D_GUID(SDL_IID_ID3D12Resource), + (void **)&textureData->mainTexture); + if (FAILED(result)) { + D3D12_DestroyTexture(renderer, texture); + return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D12Device::CreateCommittedResource [texture]"), result); + } + } + textureData->mainResourceState = D3D12_RESOURCE_STATE_COPY_DEST; SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.d3d12.texture", textureData->mainTexture); #if SDL_HAVE_YUV if (texture->format == SDL_PIXELFORMAT_YV12 || @@ -1498,34 +1515,44 @@ static int D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) textureDesc.Width = (textureDesc.Width + 1) / 2; textureDesc.Height = (textureDesc.Height + 1) / 2; - result = D3D_CALL(rendererData->d3dDevice, CreateCommittedResource, - &heapProps, - D3D12_HEAP_FLAG_NONE, - &textureDesc, - D3D12_RESOURCE_STATE_COPY_DEST, - NULL, - D3D_GUID(SDL_IID_ID3D12Resource), - (void **)&textureData->mainTextureU); - textureData->mainResourceStateU = D3D12_RESOURCE_STATE_COPY_DEST; - if (FAILED(result)) { - D3D12_DestroyTexture(renderer, texture); - return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D12Device::CreateCommittedResource [texture]"), result); + if (GetTextureProperty(create_props, "d3d12.texture_u", &textureData->mainTextureU) < 0) { + return -1; } + if (!textureData->mainTextureU) { + result = D3D_CALL(rendererData->d3dDevice, CreateCommittedResource, + &heapProps, + D3D12_HEAP_FLAG_NONE, + &textureDesc, + D3D12_RESOURCE_STATE_COPY_DEST, + NULL, + D3D_GUID(SDL_IID_ID3D12Resource), + (void **)&textureData->mainTextureU); + if (FAILED(result)) { + D3D12_DestroyTexture(renderer, texture); + return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D12Device::CreateCommittedResource [texture]"), result); + } + } + textureData->mainResourceStateU = D3D12_RESOURCE_STATE_COPY_DEST; SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.d3d12.texture_u", textureData->mainTextureU); - result = D3D_CALL(rendererData->d3dDevice, CreateCommittedResource, - &heapProps, - D3D12_HEAP_FLAG_NONE, - &textureDesc, - D3D12_RESOURCE_STATE_COPY_DEST, - NULL, - D3D_GUID(SDL_IID_ID3D12Resource), - (void **)&textureData->mainTextureV); - textureData->mainResourceStateV = D3D12_RESOURCE_STATE_COPY_DEST; - if (FAILED(result)) { - D3D12_DestroyTexture(renderer, texture); - return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D12Device::CreateCommittedResource [texture]"), result); + if (GetTextureProperty(create_props, "d3d12.texture_v", &textureData->mainTextureV) < 0) { + return -1; } + if (!textureData->mainTextureV) { + result = D3D_CALL(rendererData->d3dDevice, CreateCommittedResource, + &heapProps, + D3D12_HEAP_FLAG_NONE, + &textureDesc, + D3D12_RESOURCE_STATE_COPY_DEST, + NULL, + D3D_GUID(SDL_IID_ID3D12Resource), + (void **)&textureData->mainTextureV); + if (FAILED(result)) { + D3D12_DestroyTexture(renderer, texture); + return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D12Device::CreateCommittedResource [texture]"), result); + } + } + textureData->mainResourceStateV = D3D12_RESOURCE_STATE_COPY_DEST; SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.d3d12.texture_v", textureData->mainTextureV); } @@ -2943,7 +2970,7 @@ static int D3D12_SetVSync(SDL_Renderer *renderer, const int vsync) return 0; } -SDL_Renderer *D3D12_CreateRenderer(SDL_Window *window, Uint32 flags) +SDL_Renderer *D3D12_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props) { SDL_Renderer *renderer; D3D12_RenderData *data; @@ -2990,7 +3017,7 @@ SDL_Renderer *D3D12_CreateRenderer(SDL_Window *window, Uint32 flags) renderer->info.flags = SDL_RENDERER_ACCELERATED; renderer->driverdata = data; - if (flags & SDL_RENDERER_PRESENTVSYNC) { + if (SDL_GetBooleanProperty(create_props, "present_vsync", SDL_FALSE)) { renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; } renderer->SetVSync = D3D12_SetVSync; diff --git a/src/render/metal/SDL_render_metal.m b/src/render/metal/SDL_render_metal.m index a215ff5c6..285d42018 100644 --- a/src/render/metal/SDL_render_metal.m +++ b/src/render/metal/SDL_render_metal.m @@ -544,7 +544,7 @@ static SDL_bool METAL_SupportsBlendMode(SDL_Renderer *renderer, SDL_BlendMode bl return SDL_TRUE; } -static int METAL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) +static int METAL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props) { @autoreleasepool { METAL_RenderData *data = (__bridge METAL_RenderData *)renderer->driverdata; @@ -1653,7 +1653,7 @@ static SDL_MetalView GetWindowView(SDL_Window *window) return nil; } -static SDL_Renderer *METAL_CreateRenderer(SDL_Window *window, Uint32 flags) +static SDL_Renderer *METAL_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props) { @autoreleasepool { SDL_Renderer *renderer = NULL; @@ -1921,7 +1921,7 @@ static SDL_Renderer *METAL_CreateRenderer(SDL_Window *window, Uint32 flags) #if (defined(__MACOS__) && defined(MAC_OS_X_VERSION_10_13)) || TARGET_OS_MACCATALYST if (@available(macOS 10.13, *)) { - data.mtllayer.displaySyncEnabled = (flags & SDL_RENDERER_PRESENTVSYNC) != 0; + data.mtllayer.displaySyncEnabled = SDL_GetBooleanProperty(create_props, "present_vsync", SDL_FALSE); if (data.mtllayer.displaySyncEnabled) { renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; } diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c index 523e8ac7e..d63eef782 100644 --- a/src/render/opengl/SDL_render_gl.c +++ b/src/render/opengl/SDL_render_gl.c @@ -125,6 +125,7 @@ typedef struct typedef struct { GLuint texture; + SDL_bool texture_external; GLfloat texw; GLfloat texh; GLenum format; @@ -139,7 +140,9 @@ typedef struct SDL_bool yuv; SDL_bool nv12; GLuint utexture; + SDL_bool utexture_external; GLuint vtexture; + SDL_bool vtexture_external; #endif GL_FBOList *fbo; @@ -434,7 +437,7 @@ static SDL_bool convert_format(GL_RenderData *renderdata, Uint32 pixel_format, return SDL_TRUE; } -static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) +static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props) { GL_RenderData *renderdata = (GL_RenderData *)renderer->driverdata; const GLenum textype = renderdata->textype; @@ -491,14 +494,19 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) data->fbo = NULL; } - GL_CheckError("", renderer); - renderdata->glGenTextures(1, &data->texture); - if (GL_CheckError("glGenTextures()", renderer) < 0) { - if (data->pixels) { - SDL_free(data->pixels); + data->texture = (GLuint)SDL_GetNumberProperty(create_props, "opengl.texture", 0); + if (data->texture) { + data->texture_external = SDL_TRUE; + } else { + GL_CheckError("", renderer); + renderdata->glGenTextures(1, &data->texture); + if (GL_CheckError("glGenTextures()", renderer) < 0) { + if (data->pixels) { + SDL_free(data->pixels); + } + SDL_free(data); + return -1; } - SDL_free(data); - return -1; } texture->driverdata = data; @@ -580,8 +588,18 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) texture->format == SDL_PIXELFORMAT_IYUV) { data->yuv = SDL_TRUE; - renderdata->glGenTextures(1, &data->utexture); - renderdata->glGenTextures(1, &data->vtexture); + data->utexture = (GLuint)SDL_GetNumberProperty(create_props, "opengl.texture_u", 0); + if (data->utexture) { + data->utexture_external = SDL_TRUE; + } else { + renderdata->glGenTextures(1, &data->utexture); + } + data->vtexture = (GLuint)SDL_GetNumberProperty(create_props, "opengl.texture_v", 0); + if (data->vtexture) { + data->vtexture_external = SDL_TRUE; + } else { + renderdata->glGenTextures(1, &data->vtexture); + } renderdata->glBindTexture(textype, data->utexture); renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, @@ -614,7 +632,12 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) texture->format == SDL_PIXELFORMAT_NV21) { data->nv12 = SDL_TRUE; - renderdata->glGenTextures(1, &data->utexture); + data->utexture = (GLuint)SDL_GetNumberProperty(create_props, "opengl.texture_uv", 0); + if (data->utexture) { + data->utexture_external = SDL_TRUE; + } else { + renderdata->glGenTextures(1, &data->utexture); + } renderdata->glBindTexture(textype, data->utexture); renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, scaleMode); @@ -626,6 +649,7 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) GL_CLAMP_TO_EDGE); renderdata->glTexImage2D(textype, 0, GL_LUMINANCE_ALPHA, (texture_w + 1) / 2, (texture_h + 1) / 2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL); + SDL_SetNumberProperty(props, "SDL.texture.opengl.texture_uv", data->utexture); } #endif @@ -1500,13 +1524,22 @@ static void GL_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture) if (!data) { return; } - if (data->texture) { + if (data->texture && !data->texture_external) { renderdata->glDeleteTextures(1, &data->texture); } #if SDL_HAVE_YUV if (data->yuv) { - renderdata->glDeleteTextures(1, &data->utexture); - renderdata->glDeleteTextures(1, &data->vtexture); + if (!data->utexture_external) { + renderdata->glDeleteTextures(1, &data->utexture); + } + if (!data->vtexture_external) { + renderdata->glDeleteTextures(1, &data->vtexture); + } + } + if (data->nv12) { + if (!data->utexture_external) { + renderdata->glDeleteTextures(1, &data->utexture); + } } #endif SDL_free(data->pixels); @@ -1702,7 +1735,7 @@ static SDL_bool GL_IsProbablyAccelerated(const GL_RenderData *data) return SDL_TRUE; } -static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, Uint32 flags) +static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props) { SDL_Renderer *renderer; GL_RenderData *data; @@ -1807,7 +1840,7 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, Uint32 flags) */ #endif - if (flags & SDL_RENDERER_PRESENTVSYNC) { + if (SDL_GetBooleanProperty(create_props, "present_vsync", SDL_FALSE)) { SDL_GL_SetSwapInterval(1); } else { SDL_GL_SetSwapInterval(0); diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index cb03179ef..d56568877 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/src/render/opengles2/SDL_render_gles2.c @@ -61,6 +61,7 @@ struct GLES2_FBOList typedef struct GLES2_TextureData { GLuint texture; + SDL_bool texture_external; GLenum texture_type; GLenum pixel_format; GLenum pixel_type; @@ -71,7 +72,9 @@ typedef struct GLES2_TextureData SDL_bool yuv; SDL_bool nv12; GLuint texture_v; + GLuint texture_v_external; GLuint texture_u; + GLuint texture_u_external; #endif GLES2_FBOList *fbo; } GLES2_TextureData; @@ -1396,7 +1399,7 @@ static void GLES2_DestroyRenderer(SDL_Renderer *renderer) SDL_free(renderer); } -static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) +static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props) { GLES2_RenderData *renderdata = (GLES2_RenderData *)renderer->driverdata; GLES2_TextureData *data; @@ -1488,9 +1491,14 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) #if SDL_HAVE_YUV if (data->yuv) { - renderdata->glGenTextures(1, &data->texture_v); - if (GL_CheckError("glGenTexures()", renderer) < 0) { - return -1; + data->texture_v = (GLuint)SDL_GetNumberProperty(create_props, "opengles2.texture_v", 0); + if (data->texture_v) { + data->texture_v_external = SDL_TRUE; + } else { + renderdata->glGenTextures(1, &data->texture_v); + if (GL_CheckError("glGenTexures()", renderer) < 0) { + return -1; + } } renderdata->glActiveTexture(GL_TEXTURE2); renderdata->glBindTexture(data->texture_type, data->texture_v); @@ -1501,9 +1509,14 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL); SDL_SetNumberProperty(SDL_GetTextureProperties(texture), "SDL.texture.opengles2.texture_v", data->texture_v); - renderdata->glGenTextures(1, &data->texture_u); - if (GL_CheckError("glGenTexures()", renderer) < 0) { - return -1; + data->texture_u = (GLuint)SDL_GetNumberProperty(create_props, "opengles2.texture_u", 0); + if (data->texture_u) { + data->texture_u_external = SDL_TRUE; + } else { + renderdata->glGenTextures(1, &data->texture_u); + if (GL_CheckError("glGenTexures()", renderer) < 0) { + return -1; + } } renderdata->glActiveTexture(GL_TEXTURE1); renderdata->glBindTexture(data->texture_type, data->texture_u); @@ -1518,9 +1531,14 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) SDL_SetNumberProperty(SDL_GetTextureProperties(texture), "SDL.texture.opengles2.texture_u", data->texture_u); } else if (data->nv12) { - renderdata->glGenTextures(1, &data->texture_u); - if (GL_CheckError("glGenTexures()", renderer) < 0) { - return -1; + data->texture_u = (GLuint)SDL_GetNumberProperty(create_props, "opengles2.texture_uv", 0); + if (data->texture_u) { + data->texture_u_external = SDL_TRUE; + } else { + renderdata->glGenTextures(1, &data->texture_u); + if (GL_CheckError("glGenTexures()", renderer) < 0) { + return -1; + } } renderdata->glActiveTexture(GL_TEXTURE1); renderdata->glBindTexture(data->texture_type, data->texture_u); @@ -1536,9 +1554,14 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) } #endif - renderdata->glGenTextures(1, &data->texture); - if (GL_CheckError("glGenTexures()", renderer) < 0) { - return -1; + data->texture = (GLuint)SDL_GetNumberProperty(create_props, "opengles2.texture", 0); + if (data->texture) { + data->texture_external = SDL_TRUE; + } else { + renderdata->glGenTextures(1, &data->texture); + if (GL_CheckError("glGenTexures()", renderer) < 0) { + return -1; + } } texture->driverdata = data; renderdata->glActiveTexture(GL_TEXTURE0); @@ -1893,12 +1916,14 @@ static void GLES2_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture) /* Destroy the texture */ if (tdata) { - data->glDeleteTextures(1, &tdata->texture); + if (tdata->texture && !tdata->texture_external) { + data->glDeleteTextures(1, &tdata->texture); + } #if SDL_HAVE_YUV - if (tdata->texture_v) { + if (tdata->texture_v && !tdata->texture_v_external) { data->glDeleteTextures(1, &tdata->texture_v); } - if (tdata->texture_u) { + if (tdata->texture_u && !tdata->texture_u_external) { data->glDeleteTextures(1, &tdata->texture_u); } #endif @@ -2052,7 +2077,7 @@ static int GLES2_UnbindTexture(SDL_Renderer *renderer, SDL_Texture *texture) * Renderer instantiation * *************************************************************************************************/ -static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, Uint32 flags) +static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props) { SDL_Renderer *renderer; GLES2_RenderData *data; @@ -2139,10 +2164,10 @@ static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, Uint32 flags) * is turned on. Not doing so will freeze the screen's contents to that * of the first drawn frame. */ - flags |= SDL_RENDERER_PRESENTVSYNC; + SDL_SetBooleanProperty(create_props, "present_vsync", SDL_TRUE); #endif - if (flags & SDL_RENDERER_PRESENTVSYNC) { + if (SDL_GetBooleanProperty(create_props, "present_vsync", SDL_FALSE)) { SDL_GL_SetSwapInterval(1); } else { SDL_GL_SetSwapInterval(0); diff --git a/src/render/ps2/SDL_render_ps2.c b/src/render/ps2/SDL_render_ps2.c index febf7031a..467d2745c 100644 --- a/src/render/ps2/SDL_render_ps2.c +++ b/src/render/ps2/SDL_render_ps2.c @@ -100,7 +100,7 @@ static void PS2_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event { } -static int PS2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) +static int PS2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props) { GSTEXTURE *ps2_tex = (GSTEXTURE *)SDL_calloc(1, sizeof(GSTEXTURE)); @@ -574,7 +574,7 @@ static int PS2_SetVSync(SDL_Renderer *renderer, const int vsync) return 0; } -static SDL_Renderer *PS2_CreateRenderer(SDL_Window *window, Uint32 flags) +static SDL_Renderer *PS2_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props) { SDL_Renderer *renderer; PS2_RenderData *data; @@ -634,7 +634,9 @@ static SDL_Renderer *PS2_CreateRenderer(SDL_Window *window, Uint32 flags) data->gsGlobal = gsGlobal; dynamicVsync = SDL_GetHintBoolean(SDL_HINT_PS2_DYNAMIC_VSYNC, SDL_FALSE); - data->vsync = flags & SDL_RENDERER_PRESENTVSYNC ? (dynamicVsync ? 2 : 1) : 0; + if (SDL_GetBooleanProperty(create_props, "present_vsync", SDL_FALSE)) { + data->vsync = (dynamicVsync ? 2 : 1); + } renderer->WindowEvent = PS2_WindowEvent; renderer->CreateTexture = PS2_CreateTexture; @@ -655,9 +657,13 @@ static SDL_Renderer *PS2_CreateRenderer(SDL_Window *window, Uint32 flags) renderer->DestroyRenderer = PS2_DestroyRenderer; renderer->SetVSync = PS2_SetVSync; renderer->info = PS2_RenderDriver.info; + renderer->info.flags = SDL_RENDERER_ACCELERATED; renderer->driverdata = data; renderer->window = window; + if (data->vsync) { + renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; + } return renderer; } diff --git a/src/render/psp/SDL_render_psp.c b/src/render/psp/SDL_render_psp.c index 1f5a28385..3fe45e2af 100644 --- a/src/render/psp/SDL_render_psp.c +++ b/src/render/psp/SDL_render_psp.c @@ -478,7 +478,7 @@ static void PSP_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event { } -static int PSP_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) +static int PSP_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props) { PSP_RenderData *data = renderer->driverdata; PSP_TextureData *psp_texture = (PSP_TextureData *)SDL_calloc(1, sizeof(*psp_texture)); @@ -1290,9 +1290,8 @@ static int PSP_SetVSync(SDL_Renderer *renderer, const int vsync) return 0; } -SDL_Renderer *PSP_CreateRenderer(SDL_Window *window, Uint32 flags) +SDL_Renderer *PSP_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props) { - SDL_Renderer *renderer; PSP_RenderData *data; int pixelformat; @@ -1341,7 +1340,7 @@ SDL_Renderer *PSP_CreateRenderer(SDL_Window *window, Uint32 flags) data->most_recent_target = NULL; data->least_recent_target = NULL; - if (flags & SDL_RENDERER_PRESENTVSYNC) { + if (SDL_GetBooleanProperty(create_props, "present_vsync", SDL_FALSE)) { data->vsync = SDL_TRUE; } else { data->vsync = SDL_FALSE; @@ -1400,6 +1399,9 @@ SDL_Renderer *PSP_CreateRenderer(SDL_Window *window, Uint32 flags) sceKernelRegisterSubIntrHandler(PSP_VBLANK_INT, 0, psp_on_vblank, data); sceKernelEnableSubIntr(PSP_VBLANK_INT, 0); + if (data->vsync) { + renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; + } return renderer; } diff --git a/src/render/software/SDL_render_sw.c b/src/render/software/SDL_render_sw.c index ed428d3fc..8f10ef7f0 100644 --- a/src/render/software/SDL_render_sw.c +++ b/src/render/software/SDL_render_sw.c @@ -97,7 +97,7 @@ static int SW_GetOutputSize(SDL_Renderer *renderer, int *w, int *h) return SDL_SetError("Software renderer doesn't have an output surface"); } -static int SW_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) +static int SW_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props) { SDL_Surface *surface = SDL_CreateSurface(texture->w, texture->h, texture->format); @@ -1147,7 +1147,7 @@ SDL_Renderer *SW_CreateRendererForSurface(SDL_Surface *surface) return renderer; } -static SDL_Renderer *SW_CreateRenderer(SDL_Window *window, Uint32 flags) +static SDL_Renderer *SW_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props) { const char *hint; SDL_Surface *surface; @@ -1162,7 +1162,11 @@ static SDL_Renderer *SW_CreateRenderer(SDL_Window *window, Uint32 flags) } if (no_hint_set) { - SDL_SetHint(SDL_HINT_RENDER_VSYNC, (flags & SDL_RENDERER_PRESENTVSYNC) ? "1" : "0"); + if (SDL_GetBooleanProperty(create_props, "present_vsync", SDL_FALSE)) { + SDL_SetHint(SDL_HINT_RENDER_VSYNC, "1"); + } else { + SDL_SetHint(SDL_HINT_RENDER_VSYNC, "0"); + } } surface = SDL_GetWindowSurface(window); diff --git a/src/render/vitagxm/SDL_render_vita_gxm.c b/src/render/vitagxm/SDL_render_vita_gxm.c index 289ab06f8..ec0fe146a 100644 --- a/src/render/vitagxm/SDL_render_vita_gxm.c +++ b/src/render/vitagxm/SDL_render_vita_gxm.c @@ -42,13 +42,13 @@ #include #endif -static SDL_Renderer *VITA_GXM_CreateRenderer(SDL_Window *window, Uint32 flags); +static SDL_Renderer *VITA_GXM_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props); static void VITA_GXM_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event); static SDL_bool VITA_GXM_SupportsBlendMode(SDL_Renderer *renderer, SDL_BlendMode blendMode); -static int VITA_GXM_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture); +static int VITA_GXM_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props); static int VITA_GXM_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch); @@ -209,7 +209,7 @@ static int VITA_GXM_SetVSync(SDL_Renderer *renderer, const int vsync) return 0; } -SDL_Renderer *VITA_GXM_CreateRenderer(SDL_Window *window, Uint32 flags) +SDL_Renderer *VITA_GXM_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props) { SDL_Renderer *renderer; VITA_GXM_RenderData *data; @@ -258,8 +258,9 @@ SDL_Renderer *VITA_GXM_CreateRenderer(SDL_Window *window, Uint32 flags) data->initialized = SDL_TRUE; - if (flags & SDL_RENDERER_PRESENTVSYNC) { + if (SDL_GetBooleanProperty(create_props, "present_vsync", SDL_FALSE)) { data->displayData.wait_vblank = SDL_TRUE; + renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; } else { data->displayData.wait_vblank = SDL_FALSE; } @@ -288,7 +289,7 @@ static SDL_bool VITA_GXM_SupportsBlendMode(SDL_Renderer *renderer, SDL_BlendMode return SDL_FALSE; } -static int VITA_GXM_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) +static int VITA_GXM_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props) { VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->driverdata; VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)SDL_calloc(1, sizeof(VITA_GXM_TextureData));