diff --git a/build-scripts/SDL_migration.cocci b/build-scripts/SDL_migration.cocci index 0483a40bb2..9e3a4d6a24 100644 --- a/build-scripts/SDL_migration.cocci +++ b/build-scripts/SDL_migration.cocci @@ -1761,10 +1761,10 @@ expression e2; @@ ( - SDL_RenderSetLogicalSize(renderer, 0, 0) -+ SDL_SetRenderLogicalPresentation(renderer, 0, 0, SDL_LOGICAL_PRESENTATION_DISABLED, SDL_ScaleModeNearest) ++ SDL_SetRenderLogicalPresentation(renderer, 0, 0, SDL_LOGICAL_PRESENTATION_DISABLED) | - SDL_RenderSetLogicalSize(renderer, e1, e2) -+ SDL_SetRenderLogicalPresentation(renderer, e1, e2, SDL_LOGICAL_PRESENTATION_LETTERBOX, SDL_ScaleModeLinear) ++ SDL_SetRenderLogicalPresentation(renderer, e1, e2, SDL_LOGICAL_PRESENTATION_LETTERBOX) ) @@ @@ diff --git a/examples/renderer/02-primitives/primitives.c b/examples/renderer/02-primitives/primitives.c index 1222b86f14..28cba4396c 100644 --- a/examples/renderer/02-primitives/primitives.c +++ b/examples/renderer/02-primitives/primitives.c @@ -55,7 +55,7 @@ SDL_AppResult SDL_AppIterate(void *appstate) SDL_FRect rect; /* as you can see from this, rendering draws over whatever was drawn before it. */ - SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); /* black, full alpha */ + SDL_SetRenderDrawColor(renderer, 33, 33, 33, 255); /* dark gray, full alpha */ SDL_RenderClear(renderer); /* start with a blank canvas. */ /* draw a filled rectangle in the middle of the canvas. */ diff --git a/examples/renderer/17-read-pixels/read-pixels.c b/examples/renderer/17-read-pixels/read-pixels.c index 476588f66b..35af871e6e 100644 --- a/examples/renderer/17-read-pixels/read-pixels.c +++ b/examples/renderer/17-read-pixels/read-pixels.c @@ -19,9 +19,11 @@ static SDL_Window *window = NULL; static SDL_Renderer *renderer = NULL; static SDL_Texture *texture = NULL; -static SDL_Texture *converted_texture = NULL; static int texture_width = 0; static int texture_height = 0; +static SDL_Texture *converted_texture = NULL; +static int converted_texture_width = 0; +static int converted_texture_height = 0; #define WINDOW_WIDTH 640 #define WINDOW_HEIGHT 480 @@ -68,12 +70,6 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) SDL_DestroySurface(surface); /* done with this, the texture has a copy of the pixels now. */ - converted_texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, WINDOW_WIDTH, WINDOW_HEIGHT); - if (!texture) { - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't create conversion texture!", SDL_GetError(), NULL); - return SDL_APP_FAILURE; - } - return SDL_APP_CONTINUE; /* carry on with the program! */ } @@ -111,8 +107,13 @@ SDL_AppResult SDL_AppIterate(void *appstate) center.y = texture_height / 2.0f; SDL_RenderTextureRotated(renderer, texture, NULL, &dst_rect, rotation, ¢er, SDL_FLIP_NONE); - /* this whole thing is _super_ expensive. Seriously, don't do this in real life. */ + /* this next whole thing is _super_ expensive. Seriously, don't do this in real life. */ + + /* Download the pixels of what has just been rendered. This has to wait for the GPU to finish rendering it and everything before it, + and then make an expensive copy from the GPU to system RAM! */ surface = SDL_RenderReadPixels(renderer, NULL); + + /* This is also expensive, but easier: convert the pixels to a format we want. */ if (surface && (surface->format != SDL_PIXELFORMAT_RGBA8888) && (surface->format != SDL_PIXELFORMAT_BGRA8888)) { SDL_Surface *converted = SDL_ConvertSurface(surface, SDL_PIXELFORMAT_RGBA8888); SDL_DestroySurface(surface); @@ -120,6 +121,18 @@ SDL_AppResult SDL_AppIterate(void *appstate) } if (surface) { + /* Rebuild converted_texture if the dimensions have changed (window resized, etc). */ + if ((surface->w != converted_texture_width) || (surface->h != converted_texture_height)) { + SDL_DestroyTexture(converted_texture); + converted_texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, surface->w, surface->h); + if (!converted_texture) { + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't (re)create conversion texture!", SDL_GetError(), NULL); + return SDL_APP_FAILURE; + } + converted_texture_width = surface->w; + converted_texture_height = surface->h; + } + /* Turn each pixel into either black or white. This is a lousy technique but it works here. In real life, something like Floyd-Steinberg dithering might work better: https://en.wikipedia.org/wiki/Floyd%E2%80%93Steinberg_dithering*/ @@ -130,9 +143,10 @@ SDL_AppResult SDL_AppIterate(void *appstate) Uint8 *p = (Uint8 *) (&pixels[x]); const Uint32 average = (((Uint32) p[1]) + ((Uint32) p[2]) + ((Uint32) p[3])) / 3; if (average == 0) { - p[0] = 0; // turn off alpha for pure black pixels. + p[0] = p[3] = 0xFF; p[1] = p[2] = 0; /* make pure black pixels red. */ + } else { + p[1] = p[2] = p[3] = (average > 50) ? 0xFF : 0x00; /* make everything else either black or white. */ } - p[1] = p[2] = p[3] = (average > 50) ? 0xFF : 0x00; } } @@ -142,8 +156,8 @@ SDL_AppResult SDL_AppIterate(void *appstate) /* draw the texture to the top-left of the screen. */ dst_rect.x = dst_rect.y = 0.0f; - dst_rect.w = ((float) WINDOW_WIDTH) / 2.0f; - dst_rect.h = ((float) WINDOW_WIDTH) / 2.0f; + dst_rect.w = ((float) WINDOW_WIDTH) / 4.0f; + dst_rect.h = ((float) WINDOW_HEIGHT) / 4.0f; SDL_RenderTexture(renderer, converted_texture, NULL, &dst_rect); } diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index f0fd89733f..3d7167ea22 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -1266,13 +1266,23 @@ extern SDL_DECLSPEC SDL_Texture * SDLCALL SDL_GetRenderTarget(SDL_Renderer *rend /** * Set a device independent resolution and presentation mode for rendering. * - * This function sets the width and height of the logical rendering output. A - * render target is created at the specified size and used for rendering and - * then copied to the output during presentation. + * This function sets the width and height of the logical rendering output. + * The renderer will act as if the window is always the requested dimensions, + * scaling to the actual window resolution as necessary. + * + * This can be useful for games that expect a fixed size, but would like to + * scale the output to whatever is available, regardless of how a user resizes + * a window, or if the display is high DPI. * * You can disable logical coordinates by setting the mode to * SDL_LOGICAL_PRESENTATION_DISABLED, and in that case you get the full pixel - * resolution of the output window. + * resolution of the output window; it is safe to toggle logical presentation + * during the rendering of a frame: perhaps most of the rendering is done to + * specific dimensions but to make fonts look sharp, the app turns off logical + * presentation while drawing text. + * + * Letterboxing will only happen if logical presentation is enabled during + * SDL_RenderPresent; be sure to reenable it first if you were using it. * * You can convert coordinates in an event into rendering coordinates using * SDL_ConvertEventToRenderCoordinates(). @@ -1281,7 +1291,6 @@ extern SDL_DECLSPEC SDL_Texture * SDLCALL SDL_GetRenderTarget(SDL_Renderer *rend * \param w the width of the logical resolution. * \param h the height of the logical resolution. * \param mode the presentation mode used. - * \param scale_mode the scale mode used. * \returns true on success or false on failure; call SDL_GetError() for more * information. * @@ -1291,7 +1300,7 @@ extern SDL_DECLSPEC SDL_Texture * SDLCALL SDL_GetRenderTarget(SDL_Renderer *rend * \sa SDL_GetRenderLogicalPresentation * \sa SDL_GetRenderLogicalPresentationRect */ -extern SDL_DECLSPEC bool SDLCALL SDL_SetRenderLogicalPresentation(SDL_Renderer *renderer, int w, int h, SDL_RendererLogicalPresentation mode, SDL_ScaleMode scale_mode); +extern SDL_DECLSPEC bool SDLCALL SDL_SetRenderLogicalPresentation(SDL_Renderer *renderer, int w, int h, SDL_RendererLogicalPresentation mode); /** * Get device independent resolution and presentation mode for rendering. @@ -1302,8 +1311,6 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetRenderLogicalPresentation(SDL_Renderer * * \param renderer the rendering context. * \param w an int to be filled with the width. * \param h an int to be filled with the height. - * \param mode a pointer filled in with the presentation mode. - * \param scale_mode a pointer filled in with the scale mode. * \returns true on success or false on failure; call SDL_GetError() for more * information. * @@ -1311,7 +1318,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetRenderLogicalPresentation(SDL_Renderer * * * \sa SDL_SetRenderLogicalPresentation */ -extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderLogicalPresentation(SDL_Renderer *renderer, int *w, int *h, SDL_RendererLogicalPresentation *mode, SDL_ScaleMode *scale_mode); +extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderLogicalPresentation(SDL_Renderer *renderer, int *w, int *h, SDL_RendererLogicalPresentation *mode); /** * Get the final presentation rectangle for rendering. diff --git a/include/SDL3/SDL_test_common.h b/include/SDL3/SDL_test_common.h index 69f63765f4..0e7e1accdb 100644 --- a/include/SDL3/SDL_test_common.h +++ b/include/SDL3/SDL_test_common.h @@ -103,7 +103,6 @@ typedef struct int logical_h; bool auto_scale_content; SDL_RendererLogicalPresentation logical_presentation; - SDL_ScaleMode logical_scale_mode; float scale; int depth; float refresh_rate; diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 051f0b9ce4..ae93bf3e0e 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -499,7 +499,7 @@ SDL_DYNAPI_PROC(bool,SDL_GetRenderDrawBlendMode,(SDL_Renderer *a, SDL_BlendMode SDL_DYNAPI_PROC(bool,SDL_GetRenderDrawColor,(SDL_Renderer *a, Uint8 *b, Uint8 *c, Uint8 *d, Uint8 *e),(a,b,c,d,e),return) SDL_DYNAPI_PROC(bool,SDL_GetRenderDrawColorFloat,(SDL_Renderer *a, float *b, float *c, float *d, float *e),(a,b,c,d,e),return) SDL_DYNAPI_PROC(const char*,SDL_GetRenderDriver,(int a),(a),return) -SDL_DYNAPI_PROC(bool,SDL_GetRenderLogicalPresentation,(SDL_Renderer *a, int *b, int *c, SDL_RendererLogicalPresentation *d, SDL_ScaleMode *e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(bool,SDL_GetRenderLogicalPresentation,(SDL_Renderer *a, int *b, int *c, SDL_RendererLogicalPresentation *d),(a,b,c,d),return) SDL_DYNAPI_PROC(bool,SDL_GetRenderLogicalPresentationRect,(SDL_Renderer *a, SDL_FRect *b),(a,b),return) SDL_DYNAPI_PROC(void*,SDL_GetRenderMetalCommandEncoder,(SDL_Renderer *a),(a),return) SDL_DYNAPI_PROC(void*,SDL_GetRenderMetalLayer,(SDL_Renderer *a),(a),return) @@ -879,7 +879,7 @@ SDL_DYNAPI_PROC(bool,SDL_SetRenderColorScale,(SDL_Renderer *a, float b),(a,b),re SDL_DYNAPI_PROC(bool,SDL_SetRenderDrawBlendMode,(SDL_Renderer *a, SDL_BlendMode b),(a,b),return) SDL_DYNAPI_PROC(bool,SDL_SetRenderDrawColor,(SDL_Renderer *a, Uint8 b, Uint8 c, Uint8 d, Uint8 e),(a,b,c,d,e),return) SDL_DYNAPI_PROC(bool,SDL_SetRenderDrawColorFloat,(SDL_Renderer *a, float b, float c, float d, float e),(a,b,c,d,e),return) -SDL_DYNAPI_PROC(bool,SDL_SetRenderLogicalPresentation,(SDL_Renderer *a, int b, int c, SDL_RendererLogicalPresentation d, SDL_ScaleMode e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(bool,SDL_SetRenderLogicalPresentation,(SDL_Renderer *a, int b, int c, SDL_RendererLogicalPresentation d),(a,b,c,d),return) SDL_DYNAPI_PROC(bool,SDL_SetRenderScale,(SDL_Renderer *a, float b, float c),(a,b,c),return) SDL_DYNAPI_PROC(bool,SDL_SetRenderTarget,(SDL_Renderer *a, SDL_Texture *b),(a,b),return) SDL_DYNAPI_PROC(bool,SDL_SetRenderVSync,(SDL_Renderer *a, int b),(a,b),return) diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index a17365aa28..a7c534fdea 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -415,15 +415,15 @@ static SDL_RenderCommand *AllocateRenderCommand(SDL_Renderer *renderer) static void UpdatePixelViewport(SDL_Renderer *renderer, SDL_RenderViewState *view) { - view->pixel_viewport.x = (int)SDL_floorf(view->viewport.x * view->scale.x); - view->pixel_viewport.y = (int)SDL_floorf(view->viewport.y * view->scale.y); + view->pixel_viewport.x = (int)SDL_floorf((view->viewport.x * view->current_scale.x) + view->logical_offset.x); + view->pixel_viewport.y = (int)SDL_floorf((view->viewport.y * view->current_scale.y) + view->logical_offset.y); if (view->viewport.w >= 0) { - view->pixel_viewport.w = (int)SDL_ceilf(view->viewport.w * view->scale.x); + view->pixel_viewport.w = (int)SDL_ceilf(view->viewport.w * view->current_scale.x); } else { view->pixel_viewport.w = view->pixel_w; } if (view->viewport.h >= 0) { - view->pixel_viewport.h = (int)SDL_ceilf(view->viewport.h * view->scale.y); + view->pixel_viewport.h = (int)SDL_ceilf(view->viewport.h * view->current_scale.y); } else { view->pixel_viewport.h = view->pixel_h; } @@ -431,10 +431,9 @@ static void UpdatePixelViewport(SDL_Renderer *renderer, SDL_RenderViewState *vie static bool QueueCmdSetViewport(SDL_Renderer *renderer) { - SDL_Rect viewport; bool result = true; - viewport = renderer->view->pixel_viewport; + SDL_Rect viewport = renderer->view->pixel_viewport; if (!renderer->viewport_queued || SDL_memcmp(&viewport, &renderer->last_queued_viewport, sizeof(viewport)) != 0) { @@ -459,19 +458,19 @@ static bool QueueCmdSetViewport(SDL_Renderer *renderer) static void UpdatePixelClipRect(SDL_Renderer *renderer, SDL_RenderViewState *view) { - view->pixel_clip_rect.x = (int)SDL_floorf(view->clip_rect.x * view->scale.x); - view->pixel_clip_rect.y = (int)SDL_floorf(view->clip_rect.y * view->scale.y); - view->pixel_clip_rect.w = (int)SDL_ceilf(view->clip_rect.w * view->scale.x); - view->pixel_clip_rect.h = (int)SDL_ceilf(view->clip_rect.h * view->scale.y); + const float scale_x = view->current_scale.x; + const float scale_y = view->current_scale.y; + view->pixel_clip_rect.x = (int)SDL_floorf((view->clip_rect.x * scale_x) + view->logical_offset.x); + view->pixel_clip_rect.y = (int)SDL_floorf((view->clip_rect.y * scale_y) + view->logical_offset.y); + view->pixel_clip_rect.w = (int)SDL_ceilf(view->clip_rect.w * scale_x); + view->pixel_clip_rect.h = (int)SDL_ceilf(view->clip_rect.h * scale_y); } static bool QueueCmdSetClipRect(SDL_Renderer *renderer) { - SDL_Rect clip_rect; bool result = true; - clip_rect = renderer->view->pixel_clip_rect; - + SDL_Rect clip_rect = renderer->view->pixel_clip_rect; if (!renderer->cliprect_queued || renderer->view->clipping_enabled != renderer->last_queued_cliprect_enabled || SDL_memcmp(&clip_rect, &renderer->last_queued_cliprect, sizeof(clip_rect)) != 0) { @@ -718,7 +717,6 @@ static bool QueueCmdGeometry(SDL_Renderer *renderer, SDL_Texture *texture, cmd = PrepQueueCmdDraw(renderer, SDL_RENDERCMD_GEOMETRY, texture); if (cmd) { cmd->data.draw.texture_address_mode = texture_address_mode; - result = renderer->QueueGeometry(renderer, cmd, texture, xy, xy_stride, color, color_stride, uv, uv_stride, @@ -794,7 +792,7 @@ static void UpdateHDRProperties(SDL_Renderer *renderer) UpdateColorScale(renderer); } -static bool UpdateLogicalPresentation(SDL_Renderer *renderer); +static void UpdateLogicalPresentation(SDL_Renderer *renderer); int SDL_GetNumRenderDrivers(void) @@ -835,7 +833,6 @@ static bool SDLCALL SDL_RendererEventWatch(void *userdata, SDL_Event *event) if (event->type == SDL_EVENT_WINDOW_RESIZED || event->type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED || event->type == SDL_EVENT_WINDOW_METAL_VIEW_RESIZED) { - UpdateMainViewDimensions(renderer); UpdateLogicalPresentation(renderer); } else if (event->type == SDL_EVENT_WINDOW_HIDDEN) { renderer->hidden = true; @@ -1057,6 +1054,10 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props) renderer->main_view.viewport.h = -1; renderer->main_view.scale.x = 1.0f; renderer->main_view.scale.y = 1.0f; + renderer->main_view.logical_scale.x = 1.0f; + renderer->main_view.logical_scale.y = 1.0f; + renderer->main_view.current_scale.x = 1.0f; + renderer->main_view.current_scale.y = 1.0f; renderer->view = &renderer->main_view; renderer->dpi_scale.x = 1.0f; renderer->dpi_scale.y = 1.0f; @@ -1387,6 +1388,10 @@ SDL_Texture *SDL_CreateTextureWithProperties(SDL_Renderer *renderer, SDL_Propert texture->view.viewport.h = -1; texture->view.scale.x = 1.0f; texture->view.scale.y = 1.0f; + texture->view.logical_scale.x = 1.0f; + texture->view.logical_scale.y = 1.0f; + texture->view.current_scale.x = 1.0f; + texture->view.current_scale.y = 1.0f; texture->renderer = renderer; texture->next = renderer->textures; if (renderer->textures) { @@ -2485,7 +2490,7 @@ void SDL_UnlockTexture(SDL_Texture *texture) texture->locked_surface = NULL; } -static bool SDL_SetRenderTargetInternal(SDL_Renderer *renderer, SDL_Texture *texture) +bool SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) { // texture == NULL is valid and means reset the target to the window if (texture) { @@ -2537,46 +2542,35 @@ static bool SDL_SetRenderTargetInternal(SDL_Renderer *renderer, SDL_Texture *tex return true; } -bool SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) -{ - if (!texture && renderer->logical_target) { - return SDL_SetRenderTargetInternal(renderer, renderer->logical_target); - } else { - return SDL_SetRenderTargetInternal(renderer, texture); - } -} - SDL_Texture *SDL_GetRenderTarget(SDL_Renderer *renderer) { CHECK_RENDERER_MAGIC(renderer, NULL); - - if (renderer->target == renderer->logical_target) { + if (!renderer->target) { return NULL; - } else { - return (SDL_Texture *)SDL_GetPointerProperty(SDL_GetTextureProperties(renderer->target), SDL_PROP_TEXTURE_PARENT_POINTER, renderer->target); } + return (SDL_Texture *) SDL_GetPointerProperty(SDL_GetTextureProperties(renderer->target), SDL_PROP_TEXTURE_PARENT_POINTER, renderer->target); } -static bool UpdateLogicalPresentation(SDL_Renderer *renderer) +static void UpdateLogicalPresentation(SDL_Renderer *renderer) { - float logical_w = 1.0f, logical_h = 1.0f; - float output_w = (float)renderer->main_view.pixel_w; - float output_h = (float)renderer->main_view.pixel_h; - float want_aspect = 1.0f; - float real_aspect = 1.0f; - float scale; - if (renderer->logical_presentation_mode == SDL_LOGICAL_PRESENTATION_DISABLED) { - // All done! - return true; + renderer->main_view.logical_offset.x = renderer->main_view.logical_offset.y = 0.0f; + renderer->main_view.logical_scale.x = renderer->main_view.logical_scale.y = 1.0f; + renderer->main_view.current_scale.x = renderer->main_view.scale.x; // skip the multiplications against 1.0f. + renderer->main_view.current_scale.y = renderer->main_view.scale.y; + UpdateMainViewDimensions(renderer); + UpdatePixelClipRect(renderer, &renderer->main_view); + return; // All done! } - if (!SDL_GetTextureSize(renderer->logical_target, &logical_w, &logical_h)) { - goto error; - } - - want_aspect = logical_w / logical_h; - real_aspect = output_w / output_h; + int iwidth, iheight; + SDL_GetRenderOutputSize(renderer, &iwidth, &iheight); + const float output_w = (float)iwidth; + const float output_h = (float)iheight; + const float logical_w = renderer->logical_w; + const float logical_h = renderer->logical_h; + const float want_aspect = logical_w / logical_h; + const float real_aspect = output_w / output_h; renderer->logical_src_rect.x = 0.0f; renderer->logical_src_rect.y = 0.0f; @@ -2584,6 +2578,7 @@ static bool UpdateLogicalPresentation(SDL_Renderer *renderer) renderer->logical_src_rect.h = logical_h; if (renderer->logical_presentation_mode == SDL_LOGICAL_PRESENTATION_INTEGER_SCALE) { + float scale; if (want_aspect > real_aspect) { scale = (float)((int)output_w / (int)logical_w); // This an integer division! } else { @@ -2609,7 +2604,7 @@ static bool UpdateLogicalPresentation(SDL_Renderer *renderer) } else if (want_aspect > real_aspect) { if (renderer->logical_presentation_mode == SDL_LOGICAL_PRESENTATION_LETTERBOX) { // We want a wider aspect ratio than is available - letterbox it - scale = output_w / logical_w; + const float scale = output_w / logical_w; renderer->logical_dst_rect.x = 0.0f; renderer->logical_dst_rect.w = output_w; renderer->logical_dst_rect.h = SDL_floorf(logical_h * scale); @@ -2619,7 +2614,7 @@ static bool UpdateLogicalPresentation(SDL_Renderer *renderer) zoom so logical height matches the real height and the width will grow off the screen */ - scale = output_h / logical_h; + const float scale = output_h / logical_h; renderer->logical_dst_rect.y = 0.0f; renderer->logical_dst_rect.h = output_h; renderer->logical_dst_rect.w = SDL_floorf(logical_w * scale); @@ -2628,7 +2623,7 @@ static bool UpdateLogicalPresentation(SDL_Renderer *renderer) } else { if (renderer->logical_presentation_mode == SDL_LOGICAL_PRESENTATION_LETTERBOX) { // We want a narrower aspect ratio than is available - use side-bars - scale = output_h / logical_h; + const float scale = output_h / logical_h; renderer->logical_dst_rect.y = 0.0f; renderer->logical_dst_rect.h = output_h; renderer->logical_dst_rect.w = SDL_floorf(logical_w * scale); @@ -2638,7 +2633,7 @@ static bool UpdateLogicalPresentation(SDL_Renderer *renderer) zoom so logical width matches the real width and the height will grow off the screen */ - scale = output_w / logical_w; + const float scale = output_w / logical_w; renderer->logical_dst_rect.x = 0.0f; renderer->logical_dst_rect.w = output_w; renderer->logical_dst_rect.h = SDL_floorf(logical_h * scale); @@ -2646,97 +2641,48 @@ static bool UpdateLogicalPresentation(SDL_Renderer *renderer) } } - SDL_SetTextureScaleMode(renderer->logical_target, renderer->logical_scale_mode); + renderer->main_view.logical_scale.x = (logical_w != 0.0f) ? renderer->logical_dst_rect.w / logical_w : 0.0f; + renderer->main_view.logical_scale.y = (logical_h != 0.0f) ? renderer->logical_dst_rect.h / logical_h : 0.0f; + renderer->main_view.current_scale.x = renderer->main_view.scale.x * renderer->main_view.logical_scale.x; + renderer->main_view.current_scale.y = renderer->main_view.scale.y * renderer->main_view.logical_scale.y; + renderer->main_view.logical_offset.x = renderer->logical_dst_rect.x; + renderer->main_view.logical_offset.y = renderer->logical_dst_rect.y; - if (!renderer->target) { - SDL_SetRenderTarget(renderer, renderer->logical_target); - } - - return true; - -error: - SDL_SetRenderLogicalPresentation(renderer, 0, 0, SDL_LOGICAL_PRESENTATION_DISABLED, SDL_SCALEMODE_NEAREST); - return false; + UpdateMainViewDimensions(renderer); // this will replace pixel_w and pixel_h while making sure the dpi_scale is right. + renderer->main_view.pixel_w = (int) renderer->logical_dst_rect.w; + renderer->main_view.pixel_h = (int) renderer->logical_dst_rect.h; + UpdatePixelViewport(renderer, &renderer->main_view); + UpdatePixelClipRect(renderer, &renderer->main_view); } -bool SDL_SetRenderLogicalPresentation(SDL_Renderer *renderer, int w, int h, SDL_RendererLogicalPresentation mode, SDL_ScaleMode scale_mode) +bool SDL_SetRenderLogicalPresentation(SDL_Renderer *renderer, int w, int h, SDL_RendererLogicalPresentation mode) { CHECK_RENDERER_MAGIC(renderer, false); - if (mode == SDL_LOGICAL_PRESENTATION_DISABLED) { - if (renderer->logical_target) { - SDL_DestroyTexture(renderer->logical_target); - } - } else { - if (renderer->logical_target) { - SDL_PropertiesID props = SDL_GetTextureProperties(renderer->logical_target); - if (!props) { - goto error; - } - - int existing_w = (int)SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_WIDTH_NUMBER, 0); - int existing_h = (int)SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_HEIGHT_NUMBER, 0); - - if (w != existing_w || h != existing_h) { - SDL_DestroyTexture(renderer->logical_target); - } - } - if (!renderer->logical_target) { - renderer->logical_target = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_UNKNOWN, SDL_TEXTUREACCESS_TARGET, w, h); - if (!renderer->logical_target) { - goto error; - } - SDL_SetTextureBlendMode(renderer->logical_target, SDL_BLENDMODE_NONE); - } - } - renderer->logical_presentation_mode = mode; - renderer->logical_scale_mode = scale_mode; + renderer->logical_w = w; + renderer->logical_h = h; - return UpdateLogicalPresentation(renderer); + UpdateLogicalPresentation(renderer); -error: - SDL_SetRenderLogicalPresentation(renderer, 0, 0, SDL_LOGICAL_PRESENTATION_DISABLED, SDL_SCALEMODE_NEAREST); - return false; + return true; } -bool SDL_GetRenderLogicalPresentation(SDL_Renderer *renderer, int *w, int *h, SDL_RendererLogicalPresentation *mode, SDL_ScaleMode *scale_mode) +bool SDL_GetRenderLogicalPresentation(SDL_Renderer *renderer, int *w, int *h, SDL_RendererLogicalPresentation *mode) { - if (w) { - *w = 0; - } - if (h) { - *h = 0; - } - if (mode) { - *mode = SDL_LOGICAL_PRESENTATION_DISABLED; - } - if (scale_mode) { - *scale_mode = SDL_SCALEMODE_NEAREST; - } + #define SETVAL(ptr, val) if (ptr) { *ptr = val; } + + SETVAL(w, 0); + SETVAL(h, 0); + SETVAL(mode, SDL_LOGICAL_PRESENTATION_DISABLED); CHECK_RENDERER_MAGIC(renderer, false); - if (renderer->logical_target) { - SDL_PropertiesID props = SDL_GetTextureProperties(renderer->logical_target); - if (!props) { - return false; - } + SETVAL(w, renderer->logical_w); + SETVAL(h, renderer->logical_h); + SETVAL(mode, renderer->logical_presentation_mode); - if (w) { - *w = (int)SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_WIDTH_NUMBER, 0); - } - if (h) { - *h = (int)SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_HEIGHT_NUMBER, 0); - } - } - - if (mode) { - *mode = renderer->logical_presentation_mode; - } - if (scale_mode) { - *scale_mode = renderer->logical_scale_mode; - } + #undef SETVAL return true; } @@ -2814,17 +2760,48 @@ static void SDL_RenderLogicalBorders(SDL_Renderer *renderer) static void SDL_RenderLogicalPresentation(SDL_Renderer *renderer) { - SDL_assert(renderer->target == NULL); - SDL_SetRenderViewport(renderer, NULL); - SDL_SetRenderClipRect(renderer, NULL); - SDL_SetRenderScale(renderer, 1.0f, 1.0f); - SDL_RenderLogicalBorders(renderer); - SDL_RenderTexture(renderer, renderer->logical_target, &renderer->logical_src_rect, &renderer->logical_dst_rect); + const SDL_RendererLogicalPresentation mode = renderer->logical_presentation_mode; + if (mode == SDL_LOGICAL_PRESENTATION_LETTERBOX) { + // save off some state we're going to trample. + SDL_assert(renderer->view == &renderer->main_view); + SDL_RenderViewState *view = &renderer->main_view; + const int logical_w = renderer->logical_w; + const int logical_h = renderer->logical_h; + const float scale_x = view->scale.x; + const float scale_y = view->scale.y; + const bool clipping_enabled = view->clipping_enabled; + SDL_Rect orig_viewport, orig_cliprect; + + SDL_copyp(&orig_viewport, &view->viewport); + if (clipping_enabled) { + SDL_copyp(&orig_cliprect, &view->clip_rect); + } + + // trample some state. + SDL_SetRenderLogicalPresentation(renderer, logical_w, logical_h, SDL_LOGICAL_PRESENTATION_DISABLED); + SDL_SetRenderViewport(renderer, NULL); + if (clipping_enabled) { + SDL_SetRenderClipRect(renderer, NULL); + } + SDL_SetRenderScale(renderer, 1.0f, 1.0f); + + // draw the borders. + SDL_RenderLogicalBorders(renderer); + + // now set everything back. + renderer->logical_presentation_mode = mode; + SDL_SetRenderViewport(renderer, &orig_viewport); + if (clipping_enabled) { + SDL_SetRenderClipRect(renderer, &orig_cliprect); + } + SDL_SetRenderScale(renderer, scale_x, scale_y); + + SDL_SetRenderLogicalPresentation(renderer, logical_w, logical_h, mode); + } } bool SDL_RenderCoordinatesFromWindow(SDL_Renderer *renderer, float window_x, float window_y, float *x, float *y) { - SDL_RenderViewState *view; float render_x, render_y; CHECK_RENDERER_MAGIC(renderer, false); @@ -2834,22 +2811,13 @@ bool SDL_RenderCoordinatesFromWindow(SDL_Renderer *renderer, float window_x, flo render_y = window_y * renderer->dpi_scale.y; // Convert from pixels within the window to pixels within the view - if (renderer->logical_target) { + if (renderer->logical_presentation_mode != SDL_LOGICAL_PRESENTATION_DISABLED) { const SDL_FRect *src = &renderer->logical_src_rect; const SDL_FRect *dst = &renderer->logical_dst_rect; render_x = ((render_x - dst->x) * src->w) / dst->w; render_y = ((render_y - dst->y) * src->h) / dst->h; } - // Convert from pixels within the view to render coordinates - if (renderer->logical_target) { - view = &renderer->logical_target->view; - } else { - view = &renderer->main_view; - } - render_x = (render_x / view->scale.x) - view->viewport.x; - render_y = (render_y / view->scale.y) - view->viewport.y; - if (x) { *x = render_x; } @@ -2861,21 +2829,10 @@ bool SDL_RenderCoordinatesFromWindow(SDL_Renderer *renderer, float window_x, flo bool SDL_RenderCoordinatesToWindow(SDL_Renderer *renderer, float x, float y, float *window_x, float *window_y) { - SDL_RenderViewState *view; - CHECK_RENDERER_MAGIC(renderer, false); - // Convert from render coordinates to pixels within the view - if (renderer->logical_target) { - view = &renderer->logical_target->view; - } else { - view = &renderer->main_view; - } - x = (view->viewport.x + x) * view->scale.x; - y = (view->viewport.y + y) * view->scale.y; - - // Convert from pixels within the view to pixels within the window - if (renderer->logical_target) { + // Convert from render coordinates to pixels within the window + if (renderer->logical_presentation_mode != SDL_LOGICAL_PRESENTATION_DISABLED) { const SDL_FRect *src = &renderer->logical_src_rect; const SDL_FRect *dst = &renderer->logical_dst_rect; x = dst->x + ((x * dst->w) / src->w); @@ -2905,49 +2862,31 @@ bool SDL_ConvertEventToRenderCoordinates(SDL_Renderer *renderer, SDL_Event *even SDL_RenderCoordinatesFromWindow(renderer, event->motion.x, event->motion.y, &event->motion.x, &event->motion.y); if (event->motion.xrel != 0.0f) { - SDL_RenderViewState *view; - // Convert from window coordinates to pixels within the window float scale = renderer->dpi_scale.x; // Convert from pixels within the window to pixels within the view - if (renderer->logical_target) { + if (renderer->logical_presentation_mode != SDL_LOGICAL_PRESENTATION_DISABLED) { const SDL_FRect *src = &renderer->logical_src_rect; const SDL_FRect *dst = &renderer->logical_dst_rect; scale = (scale * src->w) / dst->w; } // Convert from pixels within the view to render coordinates - if (renderer->logical_target) { - view = &renderer->logical_target->view; - } else { - view = &renderer->main_view; - } - scale = (scale / view->scale.x); - event->motion.xrel *= scale; } if (event->motion.yrel != 0.0f) { - SDL_RenderViewState *view; - // Convert from window coordinates to pixels within the window float scale = renderer->dpi_scale.y; // Convert from pixels within the window to pixels within the view - if (renderer->logical_target) { + if (renderer->logical_presentation_mode != SDL_LOGICAL_PRESENTATION_DISABLED) { const SDL_FRect *src = &renderer->logical_src_rect; const SDL_FRect *dst = &renderer->logical_dst_rect; scale = (scale * src->h) / dst->h; } // Convert from pixels within the view to render coordinates - if (renderer->logical_target) { - view = &renderer->logical_target->view; - } else { - view = &renderer->main_view; - } - scale = (scale / view->scale.y); - event->motion.yrel *= scale; } } @@ -2993,6 +2932,7 @@ bool SDL_SetRenderViewport(SDL_Renderer *renderer, const SDL_Rect *rect) CHECK_RENDERER_MAGIC(renderer, false); if (rect) { + // !!! FIXME: fail if rect->w or rect->h are negative (we use this to mean "the whole viewport"). SDL_copyp(&renderer->view->viewport, rect); } else { renderer->view->viewport.x = 0; @@ -3014,17 +2954,18 @@ bool SDL_GetRenderViewport(SDL_Renderer *renderer, SDL_Rect *rect) CHECK_RENDERER_MAGIC(renderer, false); if (rect) { - rect->x = renderer->view->viewport.x; - rect->y = renderer->view->viewport.y; - if (renderer->view->viewport.w >= 0) { - rect->w = renderer->view->viewport.w; + const SDL_RenderViewState *view = renderer->view; + rect->x = view->viewport.x; + rect->y = view->viewport.y; + if (view->viewport.w >= 0) { + rect->w = view->viewport.w; } else { - rect->w = (int)SDL_ceilf(renderer->view->pixel_w / renderer->view->scale.x); + rect->w = (int)SDL_ceilf(view->pixel_w / view->current_scale.x); } if (renderer->view->viewport.h >= 0) { - rect->h = renderer->view->viewport.h; + rect->h = view->viewport.h; } else { - rect->h = (int)SDL_ceilf(renderer->view->pixel_h / renderer->view->scale.y); + rect->h = (int)SDL_ceilf(view->pixel_h / view->current_scale.y); } } return true; @@ -3043,17 +2984,23 @@ bool SDL_RenderViewportSet(SDL_Renderer *renderer) static void GetRenderViewportSize(SDL_Renderer *renderer, SDL_FRect *rect) { + const SDL_RenderViewState *view = renderer->view; + const float scale_x = view->current_scale.x; + const float scale_y = view->current_scale.y; + rect->x = 0.0f; rect->y = 0.0f; - if (renderer->view->viewport.w >= 0) { - rect->w = (float)renderer->view->viewport.w; + + if (view->viewport.w >= 0) { + rect->w = (float)view->viewport.w / scale_x; } else { - rect->w = renderer->view->pixel_w / renderer->view->scale.x; + rect->w = view->pixel_w / scale_x; } - if (renderer->view->viewport.h >= 0) { - rect->h = (float)renderer->view->viewport.h; + + if (view->viewport.h >= 0) { + rect->h = (float)view->viewport.h / scale_y; } else { - rect->h = renderer->view->pixel_h / renderer->view->scale.y; + rect->h = view->pixel_h / scale_y; } } @@ -3153,6 +3100,8 @@ bool SDL_SetRenderScale(SDL_Renderer *renderer, float scaleX, float scaleY) renderer->view->scale.x = scaleX; renderer->view->scale.y = scaleY; + renderer->view->current_scale.x = scaleX * renderer->view->logical_scale.x; + renderer->view->current_scale.y = scaleY * renderer->view->logical_scale.y; UpdatePixelViewport(renderer, renderer->view); UpdatePixelClipRect(renderer, renderer->view); @@ -3362,11 +3311,13 @@ static bool RenderPointsWithRects(SDL_Renderer *renderer, const SDL_FPoint *fpoi return false; } + const float scale_x = renderer->view->current_scale.x; + const float scale_y = renderer->view->current_scale.y; for (i = 0; i < count; ++i) { - frects[i].x = fpoints[i].x * renderer->view->scale.x; - frects[i].y = fpoints[i].y * renderer->view->scale.y; - frects[i].w = renderer->view->scale.x; - frects[i].h = renderer->view->scale.y; + frects[i].x = fpoints[i].x * scale_x; + frects[i].y = fpoints[i].y * scale_y; + frects[i].w = scale_x; + frects[i].h = scale_y; } result = QueueCmdFillRects(renderer, frects, count); @@ -3396,7 +3347,7 @@ bool SDL_RenderPoints(SDL_Renderer *renderer, const SDL_FPoint *points, int coun } #endif - if (renderer->view->scale.x != 1.0f || renderer->view->scale.y != 1.0f) { + if ((renderer->view->current_scale.x != 1.0f) || (renderer->view->current_scale.y != 1.0f)) { result = RenderPointsWithRects(renderer, points, count); } else { result = QueueCmdDrawPoints(renderer, points, count); @@ -3498,7 +3449,7 @@ static bool RenderLineBresenham(SDL_Renderer *renderer, int x1, int y1, int x2, } } - if (renderer->view->scale.x != 1.0f || renderer->view->scale.y != 1.0f) { + if ((renderer->view->current_scale.x != 1.0f) || (renderer->view->current_scale.y != 1.0f)) { result = RenderPointsWithRects(renderer, points, numpixels); } else { result = QueueCmdDrawPoints(renderer, points, numpixels); @@ -3509,11 +3460,10 @@ static bool RenderLineBresenham(SDL_Renderer *renderer, int x1, int y1, int x2, return result; } -static bool RenderLinesWithRectsF(SDL_Renderer *renderer, - const SDL_FPoint *points, const int count) +static bool RenderLinesWithRectsF(SDL_Renderer *renderer, const SDL_FPoint *points, const int count) { - const float scale_x = renderer->view->scale.x; - const float scale_y = renderer->view->scale.y; + const float scale_x = renderer->view->current_scale.x; + const float scale_y = renderer->view->current_scale.y; SDL_FRect *frect; SDL_FRect *frects; int i, nrects = 0; @@ -3600,13 +3550,13 @@ bool SDL_RenderLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count } #endif - if (renderer->line_method == SDL_RENDERLINEMETHOD_POINTS) { - result = RenderLinesWithRectsF(renderer, points, count); - } else if (renderer->line_method == SDL_RENDERLINEMETHOD_GEOMETRY) { + const bool islogical = ((renderer->logical_presentation_mode != SDL_LOGICAL_PRESENTATION_DISABLED) && (renderer->view == &renderer->main_view)); + + if (islogical || (renderer->line_method == SDL_RENDERLINEMETHOD_GEOMETRY)) { + const float scale_x = renderer->view->current_scale.x; + const float scale_y = renderer->view->current_scale.y; bool isstack1; bool isstack2; - const float scale_x = renderer->view->scale.x; - const float scale_y = renderer->view->scale.y; float *xy = SDL_small_alloc(float, 4 * 2 * count, &isstack1); int *indices = SDL_small_alloc(int, (4) * 3 * (count - 1) + (2) * 3 * (count), &isstack2); @@ -3722,7 +3672,9 @@ bool SDL_RenderLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count SDL_small_free(xy, isstack1); SDL_small_free(indices, isstack2); - } else if (renderer->view->scale.x != 1.0f || renderer->view->scale.y != 1.0f) { + } else if (renderer->line_method == SDL_RENDERLINEMETHOD_POINTS) { + result = RenderLinesWithRectsF(renderer, points, count); + } else if (renderer->view->scale.x != 1.0f || renderer->view->scale.y != 1.0f) { /* we checked for logical scale elsewhere. */ result = RenderLinesWithRectsF(renderer, points, count); } else { result = QueueCmdDrawLines(renderer, points, count); @@ -3826,11 +3778,14 @@ bool SDL_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int cou if (!frects) { return false; } + + const float scale_x = renderer->view->current_scale.x; + const float scale_y = renderer->view->current_scale.y; for (i = 0; i < count; ++i) { - frects[i].x = rects[i].x * renderer->view->scale.x; - frects[i].y = rects[i].y * renderer->view->scale.y; - frects[i].w = rects[i].w * renderer->view->scale.x; - frects[i].h = rects[i].h * renderer->view->scale.y; + frects[i].x = rects[i].x * scale_x; + frects[i].y = rects[i].y * scale_y; + frects[i].w = rects[i].w * scale_x; + frects[i].h = rects[i].h * scale_y; } result = QueueCmdFillRects(renderer, frects, count); @@ -3842,8 +3797,10 @@ bool SDL_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int cou static bool SDL_RenderTextureInternal(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_FRect *srcrect, const SDL_FRect *dstrect) { + const float scale_x = renderer->view->current_scale.x; + const float scale_y = renderer->view->current_scale.y; + const bool use_rendergeometry = (!renderer->QueueCopy); bool result; - bool use_rendergeometry = (!renderer->QueueCopy); if (use_rendergeometry) { float xy[8]; @@ -3887,18 +3844,10 @@ static bool SDL_RenderTextureInternal(SDL_Renderer *renderer, SDL_Texture *textu result = QueueCmdGeometry(renderer, texture, xy, xy_stride, &texture->color, 0 /* color_stride */, uv, uv_stride, - num_vertices, - indices, num_indices, size_indices, - renderer->view->scale.x, - renderer->view->scale.y, SDL_TEXTURE_ADDRESS_CLAMP); + num_vertices, indices, num_indices, size_indices, + scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP); } else { - SDL_FRect rect; - - rect.x = dstrect->x * renderer->view->scale.x; - rect.y = dstrect->y * renderer->view->scale.y; - rect.w = dstrect->w * renderer->view->scale.x; - rect.h = dstrect->h * renderer->view->scale.y; - + const SDL_FRect rect = { dstrect->x * scale_x, dstrect->y * scale_y, dstrect->w * scale_x, dstrect->h * scale_y }; result = QueueCmdCopy(renderer, texture, srcrect, &rect); } return result; @@ -3958,7 +3907,6 @@ bool SDL_RenderTextureRotated(SDL_Renderer *renderer, SDL_Texture *texture, SDL_FRect real_dstrect; SDL_FPoint real_center; bool result; - int use_rendergeometry; if (flip == SDL_FLIP_NONE && (int)(angle / 360) == angle / 360) { // fast path when we don't need rotation or flipping return SDL_RenderTexture(renderer, texture, srcrect, dstrect); @@ -3981,8 +3929,6 @@ bool SDL_RenderTextureRotated(SDL_Renderer *renderer, SDL_Texture *texture, } #endif - use_rendergeometry = (!renderer->QueueCopyEx); - real_srcrect.x = 0.0f; real_srcrect.y = 0.0f; real_srcrect.w = (float)texture->w; @@ -4013,6 +3959,10 @@ bool SDL_RenderTextureRotated(SDL_Renderer *renderer, SDL_Texture *texture, texture->last_command_generation = renderer->render_command_generation; + const float scale_x = renderer->view->current_scale.x; + const float scale_y = renderer->view->current_scale.y; + + const bool use_rendergeometry = (!renderer->QueueCopyEx); if (use_rendergeometry) { float xy[8]; const int xy_stride = 2 * sizeof(float); @@ -4092,15 +4042,10 @@ bool SDL_RenderTextureRotated(SDL_Renderer *renderer, SDL_Texture *texture, result = QueueCmdGeometry(renderer, texture, xy, xy_stride, &texture->color, 0 /* color_stride */, uv, uv_stride, - num_vertices, - indices, num_indices, size_indices, - renderer->view->scale.x, - renderer->view->scale.y, SDL_TEXTURE_ADDRESS_CLAMP); + num_vertices, indices, num_indices, size_indices, + scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP); } else { - - result = QueueCmdCopyEx(renderer, texture, &real_srcrect, &real_dstrect, angle, &real_center, flip, - renderer->view->scale.x, - renderer->view->scale.y); + result = QueueCmdCopyEx(renderer, texture, &real_srcrect, &real_dstrect, angle, &real_center, flip, scale_x, scale_y); } return result; } @@ -4148,10 +4093,8 @@ static bool SDL_RenderTextureTiled_Wrap(SDL_Renderer *renderer, SDL_Texture *tex return QueueCmdGeometry(renderer, texture, xy, xy_stride, &texture->color, 0 /* color_stride */, uv, uv_stride, - num_vertices, - indices, num_indices, size_indices, - renderer->view->scale.x, - renderer->view->scale.y, SDL_TEXTURE_ADDRESS_WRAP); + num_vertices, indices, num_indices, size_indices, + renderer->view->current_scale.x, renderer->view->current_scale.y, SDL_TEXTURE_ADDRESS_WRAP); } static bool SDL_RenderTextureTiled_Iterate(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_FRect *srcrect, float scale, const SDL_FRect *dstrect) @@ -4503,6 +4446,8 @@ static bool SDLCALL SDL_SW_RenderGeometryRaw(SDL_Renderer *renderer, float texw = 0.0f, texh = 0.0f; SDL_BlendMode blendMode = SDL_BLENDMODE_NONE; float r = 0, g = 0, b = 0, a = 0; + const float scale_x = renderer->view->current_scale.x; + const float scale_y = renderer->view->current_scale.y; // Save SDL_GetRenderDrawBlendMode(renderer, &blendMode); @@ -4759,8 +4704,7 @@ static bool SDLCALL SDL_SW_RenderGeometryRaw(SDL_Renderer *renderer, result = QueueCmdGeometry(renderer, texture, xy, xy_stride, color, color_stride, uv, uv_stride, num_vertices, prev, 3, 4, - renderer->view->scale.x, - renderer->view->scale.y, SDL_TEXTURE_ADDRESS_CLAMP); + scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP); if (!result) { goto end; } @@ -4780,8 +4724,7 @@ static bool SDLCALL SDL_SW_RenderGeometryRaw(SDL_Renderer *renderer, result = QueueCmdGeometry(renderer, texture, xy, xy_stride, color, color_stride, uv, uv_stride, num_vertices, prev, 3, 4, - renderer->view->scale.x, - renderer->view->scale.y, SDL_TEXTURE_ADDRESS_CLAMP); + scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP); if (!result) { goto end; } @@ -4905,18 +4848,14 @@ bool SDL_RenderGeometryRaw(SDL_Renderer *renderer, #endif return QueueCmdGeometry(renderer, texture, - xy, xy_stride, color, color_stride, uv, uv_stride, - num_vertices, - indices, num_indices, size_indices, - renderer->view->scale.x, - renderer->view->scale.y, texture_address_mode); + xy, xy_stride, color, color_stride, uv, uv_stride, + num_vertices, indices, num_indices, size_indices, + renderer->view->current_scale.x, renderer->view->current_scale.y, + texture_address_mode); } SDL_Surface *SDL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect) { - SDL_Rect real_rect; - SDL_Surface *surface; - CHECK_RENDERER_MAGIC(renderer, NULL); if (!renderer->RenderReadPixels) { @@ -4926,7 +4865,7 @@ SDL_Surface *SDL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect) FlushRenderCommands(renderer); // we need to render before we read the results. - real_rect = renderer->view->pixel_viewport; + SDL_Rect real_rect = renderer->view->pixel_viewport; if (rect) { if (!SDL_GetRectIntersection(rect, &real_rect, &real_rect)) { @@ -4934,7 +4873,7 @@ SDL_Surface *SDL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect) } } - surface = renderer->RenderReadPixels(renderer, &real_rect); + SDL_Surface *surface = renderer->RenderReadPixels(renderer, &real_rect); if (surface) { SDL_PropertiesID props = SDL_GetSurfaceProperties(surface); @@ -5008,11 +4947,13 @@ bool SDL_RenderPresent(SDL_Renderer *renderer) CHECK_RENDERER_MAGIC(renderer, false); - if (renderer->logical_target) { - SDL_SetRenderTargetInternal(renderer, NULL); - SDL_RenderLogicalPresentation(renderer); + // !!! FIXME: fail if using a render target? Or just implicitly set the render target to NULL now? + if (renderer->view != &renderer->main_view) { + return SDL_SetError("Cannot present a render target"); } + SDL_RenderLogicalPresentation(renderer); + if (renderer->transparent_window) { SDL_RenderApplyWindowShape(renderer); } @@ -5029,10 +4970,6 @@ bool SDL_RenderPresent(SDL_Renderer *renderer) presented = false; } - if (renderer->logical_target) { - SDL_SetRenderTargetInternal(renderer, renderer->logical_target); - } - if (renderer->simulate_vsync || (!presented && renderer->wanted_vsync)) { SDL_SimulateRenderVSync(renderer); @@ -5053,22 +4990,12 @@ static bool SDL_DestroyTextureInternal(SDL_Texture *texture, bool is_destroying) // Renderer get destroyed, avoid to queue more commands } else { if (texture == renderer->target) { - SDL_SetRenderTargetInternal(renderer, NULL); // implies command queue flush - - if (texture == renderer->logical_target) { - // Complete any logical presentation - SDL_RenderLogicalPresentation(renderer); - FlushRenderCommands(renderer); - } + SDL_SetRenderTarget(renderer, NULL); // implies command queue flush } else { FlushRenderCommandsIfTextureNeeded(texture); } } - if (texture == renderer->logical_target) { - renderer->logical_target = NULL; - } - SDL_SetObjectValid(texture, SDL_OBJECT_TYPE_TEXTURE, false); if (texture->next) { diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h index dcd0604bd8..c15cd9b11d 100644 --- a/src/render/SDL_sysrender.h +++ b/src/render/SDL_sysrender.h @@ -63,7 +63,9 @@ typedef struct SDL_RenderViewState SDL_Rect pixel_clip_rect; bool clipping_enabled; SDL_FPoint scale; - + SDL_FPoint logical_scale; + SDL_FPoint logical_offset; + SDL_FPoint current_scale; // this is just `scale * logical_scale`, precalculated, since we use it a lot. } SDL_RenderViewState; // Define the SDL texture structure @@ -240,9 +242,8 @@ struct SDL_Renderer Uint64 last_present; // Support for logical output coordinates - SDL_Texture *logical_target; SDL_RendererLogicalPresentation logical_presentation_mode; - SDL_ScaleMode logical_scale_mode; + int logical_w, logical_h; SDL_FRect logical_src_rect; SDL_FRect logical_dst_rect; diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c index f8b56c990b..cece6ae61c 100644 --- a/src/render/opengl/SDL_render_gl.c +++ b/src/render/opengl/SDL_render_gl.c @@ -1465,7 +1465,6 @@ static SDL_Surface *GL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect * SDL_PixelFormat format = renderer->target ? renderer->target->format : SDL_PIXELFORMAT_ARGB8888; GLint internalFormat; GLenum targetFormat, type; - int w, h; SDL_Surface *surface; GL_ActivateRenderer(renderer); @@ -1480,13 +1479,16 @@ static SDL_Surface *GL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect * return NULL; } - SDL_GetCurrentRenderOutputSize(renderer, &w, &h); + int y = rect->y; + if (!renderer->target) { + int w, h; + SDL_GetRenderOutputSize(renderer, &w, &h); + y = (h - y) - rect->h; + } data->glPixelStorei(GL_PACK_ALIGNMENT, 1); data->glPixelStorei(GL_PACK_ROW_LENGTH, (surface->pitch / SDL_BYTESPERPIXEL(format))); - - data->glReadPixels(rect->x, renderer->target ? rect->y : (h - rect->y) - rect->h, - rect->w, rect->h, targetFormat, type, surface->pixels); + data->glReadPixels(rect->x, y, rect->w, rect->h, targetFormat, type, surface->pixels); if (!GL_CheckError("glReadPixels()", renderer)) { SDL_DestroySurface(surface); diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index f782524475..ec75dc73f9 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/src/render/opengles2/SDL_render_gles2.c @@ -1993,7 +1993,6 @@ static SDL_Surface *GLES2_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rec { GLES2_RenderData *data = (GLES2_RenderData *)renderer->internal; SDL_PixelFormat format = renderer->target ? renderer->target->format : SDL_PIXELFORMAT_RGBA32; - int w, h; SDL_Surface *surface; surface = SDL_CreateSurface(rect->w, rect->h, format); @@ -2001,10 +2000,14 @@ static SDL_Surface *GLES2_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rec return NULL; } - SDL_GetCurrentRenderOutputSize(renderer, &w, &h); + int y = rect->y; + if (!renderer->target) { + int w, h; + SDL_GetRenderOutputSize(renderer, &w, &h); + y = (h - y) - rect->h; + } - data->glReadPixels(rect->x, renderer->target ? rect->y : (h - rect->y) - rect->h, - rect->w, rect->h, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels); + data->glReadPixels(rect->x, y, rect->w, rect->h, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels); if (!GL_CheckError("glReadPixels()", renderer)) { SDL_DestroySurface(surface); return NULL; diff --git a/src/render/vitagxm/SDL_render_vita_gxm.c b/src/render/vitagxm/SDL_render_vita_gxm.c index 9083ed0e2c..559a15266c 100644 --- a/src/render/vitagxm/SDL_render_vita_gxm.c +++ b/src/render/vitagxm/SDL_render_vita_gxm.c @@ -1080,7 +1080,6 @@ void read_pixels(int x, int y, size_t width, size_t height, void *data) static SDL_Surface *VITA_GXM_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect) { Uint32 format = renderer->target ? renderer->target->format : SDL_PIXELFORMAT_ABGR8888; - int w, h; SDL_Surface *surface; // TODO: read from texture rendertarget. @@ -1094,10 +1093,14 @@ static SDL_Surface *VITA_GXM_RenderReadPixels(SDL_Renderer *renderer, const SDL_ return NULL; } - SDL_GetCurrentRenderOutputSize(renderer, &w, &h); + int y = rect->y; + if (!renderer->target) { + int w, h; + SDL_GetRenderOutputSize(renderer, &w, &h); + y = (h - y) - rect->h; + } - read_pixels(rect->x, renderer->target ? rect->y : (h - rect->y) - rect->h, - rect->w, rect->h, surface->pixels); + read_pixels(rect->x, y, rect->w, rect->h, surface->pixels); // Flip the rows to be top-down if necessary diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c index 6f83cef14d..e3efb17334 100644 --- a/src/test/SDL_test_common.c +++ b/src/test/SDL_test_common.c @@ -482,21 +482,6 @@ static int SDLCALL SDLTest_CommonStateParseVideoArguments(void *data, char **arg } return -1; } - if (SDL_strcasecmp(argv[index], "--logical-scale-quality") == 0) { - ++index; - if (!argv[index]) { - return -1; - } - if (SDL_strcasecmp(argv[index], "nearest") == 0) { - state->logical_scale_mode = SDL_SCALEMODE_NEAREST; - return 2; - } - if (SDL_strcasecmp(argv[index], "linear") == 0) { - state->logical_scale_mode = SDL_SCALEMODE_LINEAR; - return 2; - } - return -1; - } if (SDL_strcasecmp(argv[index], "--scale") == 0) { ++index; if (!argv[index]) { @@ -708,7 +693,6 @@ SDLTest_CommonState *SDLTest_CommonCreateState(char **argv, SDL_InitFlags flags) state->window_w = DEFAULT_WINDOW_WIDTH; state->window_h = DEFAULT_WINDOW_HEIGHT; state->logical_presentation = SDL_LOGICAL_PRESENTATION_DISABLED; - state->logical_scale_mode = SDL_SCALEMODE_LINEAR; state->num_windows = 1; state->audio_freq = 22050; state->audio_format = SDL_AUDIO_S16; @@ -1082,21 +1066,6 @@ static void SDLTest_PrintLogicalPresentation(char *text, size_t maxlen, SDL_Rend } } -static void SDLTest_PrintScaleMode(char *text, size_t maxlen, SDL_ScaleMode scale_mode) -{ - switch (scale_mode) { - case SDL_SCALEMODE_NEAREST: - SDL_snprintfcat(text, maxlen, "NEAREST"); - break; - case SDL_SCALEMODE_LINEAR: - SDL_snprintfcat(text, maxlen, "LINEAR"); - break; - default: - SDL_snprintfcat(text, maxlen, "0x%8.8x", scale_mode); - break; - } -} - static void SDLTest_PrintRenderer(SDL_Renderer *renderer) { const char *name; @@ -1480,7 +1449,7 @@ bool SDLTest_CommonInit(SDLTest_CommonState *state) if (state->render_vsync) { SDL_SetRenderVSync(state->renderers[i], state->render_vsync); } - if (!SDL_SetRenderLogicalPresentation(state->renderers[i], state->logical_w, state->logical_h, state->logical_presentation, state->logical_scale_mode)) { + if (!SDL_SetRenderLogicalPresentation(state->renderers[i], state->logical_w, state->logical_h, state->logical_presentation)) { SDL_Log("Couldn't set logical presentation: %s\n", SDL_GetError()); return false; } @@ -2587,7 +2556,6 @@ void SDLTest_CommonDrawWindowInfo(SDL_Renderer *renderer, SDL_Window *window, fl SDL_DisplayID windowDisplayID = SDL_GetDisplayForWindow(window); const char *name; SDL_RendererLogicalPresentation logical_presentation; - SDL_ScaleMode logical_scale_mode; /* Video */ @@ -2638,12 +2606,9 @@ void SDLTest_CommonDrawWindowInfo(SDL_Renderer *renderer, SDL_Window *window, fl SDLTest_DrawString(renderer, 0.0f, textY, text); textY += lineHeight; - SDL_GetRenderLogicalPresentation(renderer, &w, &h, &logical_presentation, &logical_scale_mode); + SDL_GetRenderLogicalPresentation(renderer, &w, &h, &logical_presentation); (void)SDL_snprintf(text, sizeof(text), "SDL_GetRenderLogicalPresentation: %dx%d ", w, h); SDLTest_PrintLogicalPresentation(text, sizeof(text), logical_presentation); - SDL_snprintfcat(text, sizeof(text), ", "); - SDLTest_PrintScaleMode(text, sizeof(text), logical_scale_mode); - SDLTest_DrawString(renderer, 0.0f, textY, text); textY += lineHeight; /* Window */ diff --git a/test/testautomation_render.c b/test/testautomation_render.c index e39004117b..5e75ad0ec5 100644 --- a/test/testautomation_render.c +++ b/test/testautomation_render.c @@ -1089,7 +1089,6 @@ static int SDLCALL render_testLogicalSize(void *arg) int w, h; int set_w, set_h; SDL_RendererLogicalPresentation set_presentation_mode; - SDL_ScaleMode set_scale_mode; SDL_FRect set_rect; const int factor = 2; @@ -1108,16 +1107,13 @@ static int SDLCALL render_testLogicalSize(void *arg) /* Set the logical size and do a fill operation */ CHECK_FUNC(SDL_GetCurrentRenderOutputSize, (renderer, &w, &h)) - CHECK_FUNC(SDL_SetRenderLogicalPresentation, (renderer, w / factor, h / factor, - SDL_LOGICAL_PRESENTATION_LETTERBOX, - SDL_SCALEMODE_NEAREST)) - CHECK_FUNC(SDL_GetRenderLogicalPresentation, (renderer, &set_w, &set_h, &set_presentation_mode, &set_scale_mode)) + CHECK_FUNC(SDL_SetRenderLogicalPresentation, (renderer, w / factor, h / factor, SDL_LOGICAL_PRESENTATION_LETTERBOX)) + CHECK_FUNC(SDL_GetRenderLogicalPresentation, (renderer, &set_w, &set_h, &set_presentation_mode)) SDLTest_AssertCheck( set_w == (w / factor) && set_h == (h / factor) && - set_presentation_mode == SDL_LOGICAL_PRESENTATION_LETTERBOX && - set_scale_mode == SDL_SCALEMODE_NEAREST, - "Validate result from SDL_GetRenderLogicalPresentation, got %d, %d, %d, %d", set_w, set_h, set_presentation_mode, set_scale_mode); + set_presentation_mode == SDL_LOGICAL_PRESENTATION_LETTERBOX, + "Validate result from SDL_GetRenderLogicalPresentation, got %d, %d, %d", set_w, set_h, set_presentation_mode); CHECK_FUNC(SDL_GetRenderLogicalPresentationRect, (renderer, &set_rect)) SDLTest_AssertCheck( set_rect.x == 0.0f && @@ -1131,16 +1127,13 @@ static int SDLCALL render_testLogicalSize(void *arg) rect.w = (float)viewport.w / factor; rect.h = (float)viewport.h / factor; CHECK_FUNC(SDL_RenderFillRect, (renderer, &rect)) - CHECK_FUNC(SDL_SetRenderLogicalPresentation, (renderer, 0, 0, - SDL_LOGICAL_PRESENTATION_DISABLED, - SDL_SCALEMODE_NEAREST)) - CHECK_FUNC(SDL_GetRenderLogicalPresentation, (renderer, &set_w, &set_h, &set_presentation_mode, &set_scale_mode)) + CHECK_FUNC(SDL_SetRenderLogicalPresentation, (renderer, 0, 0, SDL_LOGICAL_PRESENTATION_DISABLED)) + CHECK_FUNC(SDL_GetRenderLogicalPresentation, (renderer, &set_w, &set_h, &set_presentation_mode)) SDLTest_AssertCheck( set_w == 0 && set_h == 0 && - set_presentation_mode == SDL_LOGICAL_PRESENTATION_DISABLED && - set_scale_mode == SDL_SCALEMODE_NEAREST, - "Validate result from SDL_GetRenderLogicalPresentation, got %d, %d, %d, %d", set_w, set_h, set_presentation_mode, set_scale_mode); + set_presentation_mode == SDL_LOGICAL_PRESENTATION_DISABLED, + "Validate result from SDL_GetRenderLogicalPresentation, got %d, %d, %d", set_w, set_h, set_presentation_mode); CHECK_FUNC(SDL_GetRenderLogicalPresentationRect, (renderer, &set_rect)) SDLTest_AssertCheck( set_rect.x == 0.0f && @@ -1157,20 +1150,16 @@ static int SDLCALL render_testLogicalSize(void *arg) /* Set the logical size and viewport and do a fill operation */ CHECK_FUNC(SDL_GetCurrentRenderOutputSize, (renderer, &w, &h)) - CHECK_FUNC(SDL_SetRenderLogicalPresentation, (renderer, w / factor, h / factor, - SDL_LOGICAL_PRESENTATION_LETTERBOX, - SDL_SCALEMODE_NEAREST)) + CHECK_FUNC(SDL_SetRenderLogicalPresentation, (renderer, w / factor, h / factor, SDL_LOGICAL_PRESENTATION_LETTERBOX)) viewport.x = (TESTRENDER_SCREEN_W / 4) / factor; viewport.y = (TESTRENDER_SCREEN_H / 4) / factor; - viewport.w = (TESTRENDER_SCREEN_W / 2) / factor; - viewport.h = (TESTRENDER_SCREEN_H / 2) / factor; + viewport.w = TESTRENDER_SCREEN_W / factor; + viewport.h = TESTRENDER_SCREEN_H / factor; CHECK_FUNC(SDL_SetRenderViewport, (renderer, &viewport)) CHECK_FUNC(SDL_SetRenderDrawColor, (renderer, 0, 255, 0, SDL_ALPHA_OPAQUE)) CHECK_FUNC(SDL_RenderFillRect, (renderer, NULL)) CHECK_FUNC(SDL_SetRenderViewport, (renderer, NULL)) - CHECK_FUNC(SDL_SetRenderLogicalPresentation, (renderer, 0, 0, - SDL_LOGICAL_PRESENTATION_DISABLED, - SDL_SCALEMODE_NEAREST)) + CHECK_FUNC(SDL_SetRenderLogicalPresentation, (renderer, 0, 0, SDL_LOGICAL_PRESENTATION_DISABLED)) /* Check to see if final image matches. */ compare(referenceSurface, ALLOWABLE_ERROR_OPAQUE); @@ -1196,15 +1185,13 @@ static int SDLCALL render_testLogicalSize(void *arg) CHECK_FUNC(SDL_SetRenderLogicalPresentation, (renderer, w - 2 * (TESTRENDER_SCREEN_W / 4), h, - SDL_LOGICAL_PRESENTATION_LETTERBOX, - SDL_SCALEMODE_LINEAR)) - CHECK_FUNC(SDL_GetRenderLogicalPresentation, (renderer, &set_w, &set_h, &set_presentation_mode, &set_scale_mode)) + SDL_LOGICAL_PRESENTATION_LETTERBOX)) + CHECK_FUNC(SDL_GetRenderLogicalPresentation, (renderer, &set_w, &set_h, &set_presentation_mode)) SDLTest_AssertCheck( set_w == w - 2 * (TESTRENDER_SCREEN_W / 4) && set_h == h && - set_presentation_mode == SDL_LOGICAL_PRESENTATION_LETTERBOX && - set_scale_mode == SDL_SCALEMODE_LINEAR, - "Validate result from SDL_GetRenderLogicalPresentation, got %d, %d, %d, %d", set_w, set_h, set_presentation_mode, set_scale_mode); + set_presentation_mode == SDL_LOGICAL_PRESENTATION_LETTERBOX, + "Validate result from SDL_GetRenderLogicalPresentation, got %d, %d, %d", set_w, set_h, set_presentation_mode); CHECK_FUNC(SDL_GetRenderLogicalPresentationRect, (renderer, &set_rect)) SDLTest_AssertCheck( set_rect.x == 20.0f && @@ -1214,16 +1201,13 @@ static int SDLCALL render_testLogicalSize(void *arg) "Validate result from SDL_GetRenderLogicalPresentationRect, got {%g, %g, %gx%g}", set_rect.x, set_rect.y, set_rect.w, set_rect.h); CHECK_FUNC(SDL_SetRenderDrawColor, (renderer, 0, 255, 0, SDL_ALPHA_OPAQUE)) CHECK_FUNC(SDL_RenderFillRect, (renderer, NULL)) - CHECK_FUNC(SDL_SetRenderLogicalPresentation, (renderer, 0, 0, - SDL_LOGICAL_PRESENTATION_DISABLED, - SDL_SCALEMODE_NEAREST)) - CHECK_FUNC(SDL_GetRenderLogicalPresentation, (renderer, &set_w, &set_h, &set_presentation_mode, &set_scale_mode)) + CHECK_FUNC(SDL_SetRenderLogicalPresentation, (renderer, 0, 0, SDL_LOGICAL_PRESENTATION_DISABLED)) + CHECK_FUNC(SDL_GetRenderLogicalPresentation, (renderer, &set_w, &set_h, &set_presentation_mode)) SDLTest_AssertCheck( set_w == 0 && set_h == 0 && - set_presentation_mode == SDL_LOGICAL_PRESENTATION_DISABLED && - set_scale_mode == SDL_SCALEMODE_NEAREST, - "Validate result from SDL_GetRenderLogicalPresentation, got %d, %d, %d, %d", set_w, set_h, set_presentation_mode, set_scale_mode); + set_presentation_mode == SDL_LOGICAL_PRESENTATION_DISABLED, + "Validate result from SDL_GetRenderLogicalPresentation, got %d, %d, %d", set_w, set_h, set_presentation_mode); CHECK_FUNC(SDL_GetRenderLogicalPresentationRect, (renderer, &set_rect)) SDLTest_AssertCheck( set_rect.x == 0.0f && diff --git a/test/testcontroller.c b/test/testcontroller.c index 6b7f9680c7..dc032ff147 100644 --- a/test/testcontroller.c +++ b/test/testcontroller.c @@ -2086,8 +2086,7 @@ int main(int argc, char *argv[]) /* scale for platforms that don't give you the window size you asked for. */ SDL_SetRenderLogicalPresentation(screen, (int)SCREEN_WIDTH, (int)SCREEN_HEIGHT, - SDL_LOGICAL_PRESENTATION_LETTERBOX, - SDL_SCALEMODE_LINEAR); + SDL_LOGICAL_PRESENTATION_LETTERBOX); title_area.w = GAMEPAD_WIDTH; diff --git a/test/testime.c b/test/testime.c index 00cce6f6af..b16a908685 100644 --- a/test/testime.c +++ b/test/testime.c @@ -1109,7 +1109,7 @@ int main(int argc, char *argv[]) SDL_Renderer *renderer = state->renderers[i]; int icon_w = 0, icon_h = 0; - SDL_SetRenderLogicalPresentation(renderer, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_LOGICAL_PRESENTATION_LETTERBOX, SDL_SCALEMODE_LINEAR); + SDL_SetRenderLogicalPresentation(renderer, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_LOGICAL_PRESENTATION_LETTERBOX); ctx->window = window; ctx->renderer = renderer; diff --git a/test/testspriteminimal.c b/test/testspriteminimal.c index a89d3a3967..e88c99cea7 100644 --- a/test/testspriteminimal.c +++ b/test/testspriteminimal.c @@ -117,11 +117,13 @@ int main(int argc, char *argv[]) goto quit; } - if (!SDL_CreateWindowAndRenderer("testspriteminimal", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) { + if (!SDL_CreateWindowAndRenderer("testspriteminimal", WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_RESIZABLE, &window, &renderer)) { return_code = 2; goto quit; } + SDL_SetRenderLogicalPresentation(renderer, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_LOGICAL_PRESENTATION_LETTERBOX); + sprite = CreateTexture(renderer, icon_bmp, icon_bmp_len, &sprite_w, &sprite_h); if (!sprite) {