Renderer logical size is now implemented as a render target

This fixes rounding errors with coordinate scaling and gives more flexibility in the presentation, as well as making it easy to maintain device independent resolution as windows move between different pixel density displays.

By default when a renderer is created, it will match the window size so window coordinates and render coordinates are 1-1.

Mouse and touch events are no longer filtered to change their coordinates, instead you can call SDL_ConvertEventToRenderCoordinates() to explicitly map event coordinates into the rendering viewport.

SDL_RenderWindowToLogical() and SDL_RenderLogicalToWindow() have been renamed SDL_RenderCoordinatesFromWindow() and SDL_RenderCoordinatesToWindow() and take floating point coordinates in both directions.

The viewport, clipping state, and scale for render targets are now persistent and will remain set whenever they are active.
This commit is contained in:
Sam Lantinga
2023-02-03 12:25:46 -08:00
parent 93fc72a405
commit dcd17f5473
28 changed files with 1113 additions and 910 deletions

1162
src/render/SDL_render.c Normal file → Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -45,18 +45,31 @@ typedef struct SDL_DRect
typedef struct SDL_RenderDriver SDL_RenderDriver;
/* Rendering view state */
typedef struct SDL_RenderViewState
{
int pixel_w;
int pixel_h;
SDL_Rect viewport;
SDL_Rect clip_rect;
SDL_bool clipping_enabled;
SDL_FPoint scale;
} SDL_RenderViewState;
/* Define the SDL texture structure */
struct SDL_Texture
{
const void *magic;
Uint32 format; /**< The pixel format of the texture */
int access; /**< SDL_TextureAccess */
int w; /**< The width of the texture */
int h; /**< The height of the texture */
int modMode; /**< The texture modulation mode */
SDL_BlendMode blendMode; /**< The texture blend mode */
SDL_ScaleMode scaleMode; /**< The texture scale mode */
SDL_Color color; /**< Texture modulation values */
Uint32 format; /**< The pixel format of the texture */
int access; /**< SDL_TextureAccess */
int w; /**< The width of the texture */
int h; /**< The height of the texture */
int modMode; /**< The texture modulation mode */
SDL_BlendMode blendMode; /**< The texture blend mode */
SDL_ScaleMode scaleMode; /**< The texture scale mode */
SDL_Color color; /**< Texture modulation values */
SDL_RenderViewState view; /**< Target texture view state */
SDL_Renderer *renderer;
@@ -212,37 +225,19 @@ struct SDL_Renderer
Uint64 simulate_vsync_interval_ns;
Uint64 last_present;
/* The logical resolution for rendering */
int logical_w;
int logical_h;
int logical_w_backup;
int logical_h_backup;
/* Support for logical output coordinates */
SDL_Texture *logical_target;
SDL_RendererLogicalPresentation logical_presentation_mode;
SDL_ScaleMode logical_scale_mode;
SDL_Rect logical_src_rect;
SDL_FRect logical_dst_rect;
/* Whether or not to force the viewport to even integer intervals */
SDL_bool integer_scale;
SDL_RenderViewState *view;
SDL_RenderViewState main_view;
/* The drawable area within the window */
SDL_DRect viewport;
SDL_DRect viewport_backup;
/* The clip rectangle within the window */
SDL_DRect clip_rect;
SDL_DRect clip_rect_backup;
/* Whether or not the clipping rectangle is used. */
SDL_bool clipping_enabled;
SDL_bool clipping_enabled_backup;
/* The render output coordinate scale */
SDL_FPoint scale;
SDL_FPoint scale_backup;
/* The pixel to point coordinate scale */
/* The window pixel to point coordinate scale */
SDL_FPoint dpi_scale;
/* Whether or not to scale relative mouse motion */
SDL_bool relative_scaling;
/* The method of drawing lines */
SDL_RenderLineMethod line_method;
@@ -264,8 +259,8 @@ struct SDL_Renderer
SDL_RenderCommand *render_commands_pool;
Uint32 render_command_generation;
Uint32 last_queued_color;
SDL_DRect last_queued_viewport;
SDL_DRect last_queued_cliprect;
SDL_Rect last_queued_viewport;
SDL_Rect last_queued_cliprect;
SDL_bool last_queued_cliprect_enabled;
SDL_bool color_queued;
SDL_bool viewport_queued;

View File

@@ -337,12 +337,6 @@ static void D3D_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event
}
}
static int D3D_GetOutputSize(SDL_Renderer *renderer, int *w, int *h)
{
SDL_GetWindowSizeInPixels(renderer->window, w, h);
return 0;
}
static D3DBLEND GetBlendFunc(SDL_BlendFactor factor)
{
switch (factor) {
@@ -1586,7 +1580,6 @@ D3D_CreateRenderer(SDL_Window *window, Uint32 flags)
}
renderer->WindowEvent = D3D_WindowEvent;
renderer->GetOutputSize = D3D_GetOutputSize;
renderer->SupportsBlendMode = D3D_SupportsBlendMode;
renderer->CreateTexture = D3D_CreateTexture;
renderer->UpdateTexture = D3D_UpdateTexture;
@@ -1609,7 +1602,7 @@ D3D_CreateRenderer(SDL_Window *window, Uint32 flags)
renderer->DestroyRenderer = D3D_DestroyRenderer;
renderer->SetVSync = D3D_SetVSync;
renderer->info = D3D_RenderDriver.info;
renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
renderer->info.flags = SDL_RENDERER_ACCELERATED;
renderer->driverdata = data;
SDL_GetWindowSizeInPixels(window, &w, &h);
@@ -1727,7 +1720,7 @@ D3D_CreateRenderer(SDL_Window *window, Uint32 flags)
SDL_RenderDriver D3D_RenderDriver = {
D3D_CreateRenderer,
{ "direct3d",
(SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE),
(SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC),
1,
{ SDL_PIXELFORMAT_ARGB8888 },
0,

View File

@@ -1033,14 +1033,6 @@ static void D3D11_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *eve
}
}
#if !defined(__WINRT__)
static int D3D11_GetOutputSize(SDL_Renderer *renderer, int *w, int *h)
{
SDL_GetWindowSizeInPixels(renderer->window, w, h);
return 0;
}
#endif
static SDL_bool D3D11_SupportsBlendMode(SDL_Renderer *renderer, SDL_BlendMode blendMode)
{
SDL_BlendFactor srcColorFactor = SDL_GetBlendModeSrcColorFactor(blendMode);
@@ -2324,9 +2316,6 @@ D3D11_CreateRenderer(SDL_Window *window, Uint32 flags)
data->identity = MatrixIdentity();
renderer->WindowEvent = D3D11_WindowEvent;
#if !defined(__WINRT__)
renderer->GetOutputSize = D3D11_GetOutputSize;
#endif
renderer->SupportsBlendMode = D3D11_SupportsBlendMode;
renderer->CreateTexture = D3D11_CreateTexture;
renderer->UpdateTexture = D3D11_UpdateTexture;
@@ -2349,7 +2338,7 @@ D3D11_CreateRenderer(SDL_Window *window, Uint32 flags)
renderer->DestroyTexture = D3D11_DestroyTexture;
renderer->DestroyRenderer = D3D11_DestroyRenderer;
renderer->info = D3D11_RenderDriver.info;
renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
renderer->info.flags = SDL_RENDERER_ACCELERATED;
renderer->driverdata = data;
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
@@ -2394,12 +2383,10 @@ SDL_RenderDriver D3D11_RenderDriver = {
D3D11_CreateRenderer,
{
"direct3d11",
(
SDL_RENDERER_ACCELERATED |
SDL_RENDERER_PRESENTVSYNC |
SDL_RENDERER_TARGETTEXTURE), /* flags. see SDL_RendererFlags */
6, /* num_texture_formats */
{ /* texture_formats */
(SDL_RENDERER_ACCELERATED |
SDL_RENDERER_PRESENTVSYNC), /* flags. see SDL_RendererFlags */
6, /* num_texture_formats */
{ /* texture_formats */
SDL_PIXELFORMAT_ARGB8888,
SDL_PIXELFORMAT_RGB888,
SDL_PIXELFORMAT_YV12,

View File

@@ -502,12 +502,6 @@ static void D3D12_DestroyRenderer(SDL_Renderer *renderer)
SDL_free(renderer);
}
static int D3D12_GetOutputSize(SDL_Renderer *renderer, int *w, int *h)
{
SDL_GetWindowSizeInPixels(renderer->window, w, h);
return 0;
}
static D3D12_BLEND GetBlendFunc(SDL_BlendFactor factor)
{
switch (factor) {
@@ -2972,7 +2966,6 @@ D3D12_CreateRenderer(SDL_Window *window, Uint32 flags)
data->identity = MatrixIdentity();
renderer->WindowEvent = D3D12_WindowEvent;
renderer->GetOutputSize = D3D12_GetOutputSize;
renderer->SupportsBlendMode = D3D12_SupportsBlendMode;
renderer->CreateTexture = D3D12_CreateTexture;
renderer->UpdateTexture = D3D12_UpdateTexture;
@@ -2995,7 +2988,7 @@ D3D12_CreateRenderer(SDL_Window *window, Uint32 flags)
renderer->DestroyTexture = D3D12_DestroyTexture;
renderer->DestroyRenderer = D3D12_DestroyRenderer;
renderer->info = D3D12_RenderDriver.info;
renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
renderer->info.flags = SDL_RENDERER_ACCELERATED;
renderer->driverdata = data;
if ((flags & SDL_RENDERER_PRESENTVSYNC)) {
@@ -3025,12 +3018,10 @@ SDL_RenderDriver D3D12_RenderDriver = {
D3D12_CreateRenderer,
{
"direct3d12",
(
SDL_RENDERER_ACCELERATED |
SDL_RENDERER_PRESENTVSYNC |
SDL_RENDERER_TARGETTEXTURE), /* flags. see SDL_RendererFlags */
6, /* num_texture_formats */
{ /* texture_formats */
(SDL_RENDERER_ACCELERATED |
SDL_RENDERER_PRESENTVSYNC), /* flags. see SDL_RendererFlags */
6, /* num_texture_formats */
{ /* texture_formats */
SDL_PIXELFORMAT_ARGB8888,
SDL_PIXELFORMAT_RGB888,
SDL_PIXELFORMAT_YV12,

View File

@@ -1911,7 +1911,7 @@ static SDL_Renderer *METAL_CreateRenderer(SDL_Window *window, Uint32 flags)
renderer->GetMetalCommandEncoder = METAL_GetMetalCommandEncoder;
renderer->info = METAL_RenderDriver.info;
renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
renderer->info.flags = SDL_RENDERER_ACCELERATED;
renderer->always_batch = SDL_TRUE;
@@ -1972,7 +1972,7 @@ SDL_RenderDriver METAL_RenderDriver = {
METAL_CreateRenderer,
{
"metal",
(SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE),
(SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC),
6,
{ SDL_PIXELFORMAT_ARGB8888,
SDL_PIXELFORMAT_ABGR8888,

View File

@@ -331,12 +331,6 @@ static void GL_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event)
}
}
static int GL_GetOutputSize(SDL_Renderer *renderer, int *w, int *h)
{
SDL_GetWindowSizeInPixels(renderer->window, w, h);
return 0;
}
static GLenum GetBlendFunc(SDL_BlendFactor factor)
{
switch (factor) {
@@ -1440,7 +1434,7 @@ static int GL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect,
return SDL_OutOfMemory();
}
SDL_GetRendererOutputSize(renderer, &w, &h);
SDL_GetCurrentRenderOutputSize(renderer, &w, &h);
data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
data->glPixelStorei(GL_PACK_ROW_LENGTH,
@@ -1749,7 +1743,6 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, Uint32 flags)
}
renderer->WindowEvent = GL_WindowEvent;
renderer->GetOutputSize = GL_GetOutputSize;
renderer->SupportsBlendMode = GL_SupportsBlendMode;
renderer->CreateTexture = GL_CreateTexture;
renderer->UpdateTexture = GL_UpdateTexture;
@@ -1935,9 +1928,13 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, Uint32 flags)
SDL_GL_GetProcAddress("glBindFramebufferEXT");
data->glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)
SDL_GL_GetProcAddress("glCheckFramebufferStatusEXT");
renderer->info.flags |= SDL_RENDERER_TARGETTEXTURE;
} else {
SDL_SetError("Can't create render targets, GL_EXT_framebuffer_object not available");
SDL_GL_DeleteContext(data->context);
SDL_free(renderer);
SDL_free(data);
goto error;
}
data->framebuffers = NULL;
/* Set up parameters for rendering */
data->glMatrixMode(GL_MODELVIEW);
@@ -1972,7 +1969,7 @@ error:
SDL_RenderDriver GL_RenderDriver = {
GL_CreateRenderer,
{ "opengl",
(SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE),
(SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC),
4,
{ SDL_PIXELFORMAT_ARGB8888,
SDL_PIXELFORMAT_ABGR8888,

View File

@@ -311,12 +311,6 @@ static void GLES2_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *eve
}
}
static int GLES2_GetOutputSize(SDL_Renderer *renderer, int *w, int *h)
{
SDL_GetWindowSizeInPixels(renderer->window, w, h);
return 0;
}
static GLenum GetBlendFunc(SDL_BlendFactor factor)
{
switch (factor) {
@@ -1935,7 +1929,7 @@ static int GLES2_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect,
return SDL_OutOfMemory();
}
SDL_GetRendererOutputSize(renderer, &w, &h);
SDL_GetCurrentRenderOutputSize(renderer, &w, &h);
data->glReadPixels(rect->x, renderer->target ? rect->y : (h - rect->y) - rect->h,
rect->w, rect->h, GL_RGBA, GL_UNSIGNED_BYTE, temp_pixels);
@@ -2109,7 +2103,7 @@ static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
goto error;
}
renderer->info = GLES2_RenderDriver.info;
renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
renderer->info.flags = SDL_RENDERER_ACCELERATED;
renderer->driverdata = data;
renderer->window = window;
@@ -2190,7 +2184,6 @@ static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
/* Populate the function pointers for the module */
renderer->WindowEvent = GLES2_WindowEvent;
renderer->GetOutputSize = GLES2_GetOutputSize;
renderer->SupportsBlendMode = GLES2_SupportsBlendMode;
renderer->CreateTexture = GLES2_CreateTexture;
renderer->UpdateTexture = GLES2_UpdateTexture;
@@ -2272,7 +2265,7 @@ error:
SDL_RenderDriver GLES2_RenderDriver = {
GLES2_CreateRenderer,
{ "opengles2",
(SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE),
(SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC),
4,
{ SDL_PIXELFORMAT_ARGB8888,
SDL_PIXELFORMAT_ABGR8888,

View File

@@ -665,7 +665,7 @@ SDL_RenderDriver PS2_RenderDriver = {
.CreateRenderer = PS2_CreateRenderer,
.info = {
.name = "PS2 gsKit",
.flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE,
.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC),
.num_texture_formats = 2,
.texture_formats = {
[0] = SDL_PIXELFORMAT_ABGR1555,

View File

@@ -1333,7 +1333,7 @@ PSP_CreateRenderer(SDL_Window *window, Uint32 flags)
renderer->DestroyRenderer = PSP_DestroyRenderer;
renderer->SetVSync = PSP_SetVSync;
renderer->info = PSP_RenderDriver.info;
renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
renderer->info.flags = SDL_RENDERER_ACCELERATED;
renderer->driverdata = data;
renderer->window = window;
@@ -1407,7 +1407,7 @@ SDL_RenderDriver PSP_RenderDriver = {
.CreateRenderer = PSP_CreateRenderer,
.info = {
.name = "PSP",
.flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE,
.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC),
.num_texture_formats = 4,
.texture_formats = {
[0] = SDL_PIXELFORMAT_BGR565,

View File

@@ -1175,7 +1175,7 @@ static SDL_Renderer *SW_CreateRenderer(SDL_Window *window, Uint32 flags)
SDL_RenderDriver SW_RenderDriver = {
SW_CreateRenderer,
{ "software",
SDL_RENDERER_SOFTWARE | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE,
(SDL_RENDERER_SOFTWARE | SDL_RENDERER_PRESENTVSYNC),
0,
{ /* formats filled in later */
SDL_PIXELFORMAT_UNKNOWN },

View File

@@ -102,7 +102,7 @@ SDL_RenderDriver VITA_GXM_RenderDriver = {
.CreateRenderer = VITA_GXM_CreateRenderer,
.info = {
.name = "VITA gxm",
.flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE,
.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC),
.num_texture_formats = 8,
.texture_formats = {
[0] = SDL_PIXELFORMAT_ABGR8888,
@@ -253,7 +253,7 @@ VITA_GXM_CreateRenderer(SDL_Window *window, Uint32 flags)
renderer->SetVSync = VITA_GXM_SetVSync;
renderer->info = VITA_GXM_RenderDriver.info;
renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
renderer->info.flags = SDL_RENDERER_ACCELERATED;
renderer->driverdata = data;
renderer->window = window;
@@ -1106,7 +1106,7 @@ static int VITA_GXM_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rec
return SDL_OutOfMemory();
}
SDL_GetRendererOutputSize(renderer, &w, &h);
SDL_GetCurrentRenderOutputSize(renderer, &w, &h);
read_pixels(rect->x, renderer->target ? rect->y : (h - rect->y) - rect->h,
rect->w, rect->h, temp_pixels);