Added SDL_RenderSetLogicalSize() and SDL_RenderGetLogicalSize()
This commit is contained in:
parent
b88f38c169
commit
3c4b366a81
3 changed files with 166 additions and 11 deletions
|
@ -417,6 +417,40 @@ extern DECLSPEC SDL_bool SDLCALL SDL_RenderTargetSupported(SDL_Renderer *rendere
|
||||||
extern DECLSPEC int SDLCALL SDL_SetRenderTarget(SDL_Renderer *renderer,
|
extern DECLSPEC int SDLCALL SDL_SetRenderTarget(SDL_Renderer *renderer,
|
||||||
SDL_Texture *texture);
|
SDL_Texture *texture);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Set device independent resolution for rendering
|
||||||
|
*
|
||||||
|
* \param w The width of the logical resolution
|
||||||
|
* \param h The height of the logical resolution
|
||||||
|
*
|
||||||
|
* This function uses the viewport and scaling functionality to allow a fixed logical
|
||||||
|
* resolution for rendering, regardless of the actual output resolution. If the actual
|
||||||
|
* output resolution doesn't have the same aspect ratio the output rendering will be
|
||||||
|
* centered within the output display.
|
||||||
|
*
|
||||||
|
* If the output display is a window, mouse events in the window will be filtered
|
||||||
|
* and scaled so they seem to arrive within the logical resolution.
|
||||||
|
*
|
||||||
|
* \note If this function results in scaling or subpixel drawing by the
|
||||||
|
* rendering backend, it will be handled using the appropriate
|
||||||
|
* quality hints.
|
||||||
|
*
|
||||||
|
* \sa SDL_RenderGetLogicalSize()
|
||||||
|
* \sa SDL_RenderSetScale()
|
||||||
|
* \sa SDL_RenderSetViewport()
|
||||||
|
*/
|
||||||
|
extern DECLSPEC int SDLCALL SDL_RenderSetLogicalSize(SDL_Renderer * renderer, int w, int h);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Get device independent resolution for rendering
|
||||||
|
*
|
||||||
|
* \param w A pointer filled with the width of the logical resolution
|
||||||
|
* \param h A pointer filled with the height of the logical resolution
|
||||||
|
*
|
||||||
|
* \sa SDL_RenderSetLogicalSize()
|
||||||
|
*/
|
||||||
|
extern DECLSPEC void SDLCALL SDL_RenderGetLogicalSize(SDL_Renderer * renderer, int *w, int *y);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Set the drawing area for rendering on the current target.
|
* \brief Set the drawing area for rendering on the current target.
|
||||||
*
|
*
|
||||||
|
@ -426,12 +460,17 @@ extern DECLSPEC int SDLCALL SDL_SetRenderTarget(SDL_Renderer *renderer,
|
||||||
*
|
*
|
||||||
* \note When the window is resized, the current viewport is automatically
|
* \note When the window is resized, the current viewport is automatically
|
||||||
* centered within the new window size.
|
* centered within the new window size.
|
||||||
|
*
|
||||||
|
* \sa SDL_RenderGetViewport()
|
||||||
|
* \sa SDL_RenderSetLogicalSize()
|
||||||
*/
|
*/
|
||||||
extern DECLSPEC int SDLCALL SDL_RenderSetViewport(SDL_Renderer * renderer,
|
extern DECLSPEC int SDLCALL SDL_RenderSetViewport(SDL_Renderer * renderer,
|
||||||
const SDL_Rect * rect);
|
const SDL_Rect * rect);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Get the drawing area for the current target.
|
* \brief Get the drawing area for the current target.
|
||||||
|
*
|
||||||
|
* \sa SDL_RenderSetViewport()
|
||||||
*/
|
*/
|
||||||
extern DECLSPEC void SDLCALL SDL_RenderGetViewport(SDL_Renderer * renderer,
|
extern DECLSPEC void SDLCALL SDL_RenderGetViewport(SDL_Renderer * renderer,
|
||||||
SDL_Rect * rect);
|
SDL_Rect * rect);
|
||||||
|
@ -449,6 +488,9 @@ extern DECLSPEC void SDLCALL SDL_RenderGetViewport(SDL_Renderer * renderer,
|
||||||
* \note If this results in scaling or subpixel drawing by the
|
* \note If this results in scaling or subpixel drawing by the
|
||||||
* rendering backend, it will be handled using the appropriate
|
* rendering backend, it will be handled using the appropriate
|
||||||
* quality hints. For best results use integer scaling factors.
|
* quality hints. For best results use integer scaling factors.
|
||||||
|
*
|
||||||
|
* \sa SDL_RenderGetScale()
|
||||||
|
* \sa SDL_RenderSetLogicalSize()
|
||||||
*/
|
*/
|
||||||
extern DECLSPEC int SDLCALL SDL_RenderSetScale(SDL_Renderer * renderer,
|
extern DECLSPEC int SDLCALL SDL_RenderSetScale(SDL_Renderer * renderer,
|
||||||
float scaleX, float scaleY);
|
float scaleX, float scaleY);
|
||||||
|
@ -458,6 +500,8 @@ extern DECLSPEC int SDLCALL SDL_RenderSetScale(SDL_Renderer * renderer,
|
||||||
*
|
*
|
||||||
* \param scaleX A pointer filled in with the horizontal scaling factor
|
* \param scaleX A pointer filled in with the horizontal scaling factor
|
||||||
* \param scaleY A pointer filled in with the vertical scaling factor
|
* \param scaleY A pointer filled in with the vertical scaling factor
|
||||||
|
*
|
||||||
|
* \sa SDL_RenderSetScale()
|
||||||
*/
|
*/
|
||||||
extern DECLSPEC void SDLCALL SDL_RenderGetScale(SDL_Renderer * renderer,
|
extern DECLSPEC void SDLCALL SDL_RenderGetScale(SDL_Renderer * renderer,
|
||||||
float *scaleX, float *scaleY);
|
float *scaleX, float *scaleY);
|
||||||
|
|
|
@ -70,6 +70,8 @@ static const SDL_RenderDriver *render_drivers[] = {
|
||||||
static char renderer_magic;
|
static char renderer_magic;
|
||||||
static char texture_magic;
|
static char texture_magic;
|
||||||
|
|
||||||
|
static int UpdateLogicalSize(SDL_Renderer *renderer);
|
||||||
|
|
||||||
int
|
int
|
||||||
SDL_GetNumRenderDrivers(void)
|
SDL_GetNumRenderDrivers(void)
|
||||||
{
|
{
|
||||||
|
@ -101,21 +103,27 @@ SDL_RendererEventWatch(void *userdata, SDL_Event *event)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event->window.event == SDL_WINDOWEVENT_RESIZED) {
|
if (event->window.event == SDL_WINDOWEVENT_RESIZED) {
|
||||||
/* Try to keep the previous viewport centered */
|
if (renderer->logical_w) {
|
||||||
int w, h;
|
/* We'll update the renderer in the SIZE_CHANGED event */
|
||||||
|
|
||||||
SDL_GetWindowSize(window, &w, &h);
|
|
||||||
if (renderer->target) {
|
|
||||||
renderer->viewport_backup.x = (w - renderer->viewport_backup.w) / 2;
|
|
||||||
renderer->viewport_backup.y = (h - renderer->viewport_backup.h) / 2;
|
|
||||||
} else {
|
} else {
|
||||||
renderer->viewport.x = (w - renderer->viewport.w) / 2;
|
/* Try to keep the previous viewport centered */
|
||||||
renderer->viewport.y = (h - renderer->viewport.h) / 2;
|
int w, h;
|
||||||
renderer->UpdateViewport(renderer);
|
|
||||||
|
SDL_GetWindowSize(window, &w, &h);
|
||||||
|
if (renderer->target) {
|
||||||
|
renderer->viewport_backup.x = (w - renderer->viewport_backup.w) / 2;
|
||||||
|
renderer->viewport_backup.y = (h - renderer->viewport_backup.h) / 2;
|
||||||
|
} else {
|
||||||
|
renderer->viewport.x = (w - renderer->viewport.w) / 2;
|
||||||
|
renderer->viewport.y = (h - renderer->viewport.h) / 2;
|
||||||
|
renderer->UpdateViewport(renderer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
renderer->resized = SDL_TRUE;
|
renderer->resized = SDL_TRUE;
|
||||||
} else if (event->window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
|
} else if (event->window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
|
||||||
if (!renderer->resized) {
|
if (renderer->logical_w) {
|
||||||
|
UpdateLogicalSize(renderer);
|
||||||
|
} else if (!renderer->resized) {
|
||||||
/* Window was programmatically resized, reset viewport */
|
/* Window was programmatically resized, reset viewport */
|
||||||
int w, h;
|
int w, h;
|
||||||
|
|
||||||
|
@ -148,6 +156,21 @@ SDL_RendererEventWatch(void *userdata, SDL_Event *event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (event->type == SDL_MOUSEMOTION) {
|
||||||
|
if (renderer->logical_w) {
|
||||||
|
event->motion.x -= renderer->viewport.x;
|
||||||
|
event->motion.y -= renderer->viewport.y;
|
||||||
|
event->motion.x = (int)(event->motion.x / renderer->scale.x);
|
||||||
|
event->motion.y = (int)(event->motion.y / renderer->scale.y);
|
||||||
|
}
|
||||||
|
} else if (event->type == SDL_MOUSEBUTTONDOWN ||
|
||||||
|
event->type == SDL_MOUSEBUTTONUP) {
|
||||||
|
if (renderer->logical_w) {
|
||||||
|
event->button.x -= renderer->viewport.x;
|
||||||
|
event->button.y -= renderer->viewport.y;
|
||||||
|
event->button.x = (int)(event->button.x / renderer->scale.x);
|
||||||
|
event->button.y = (int)(event->button.y / renderer->scale.y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -245,6 +268,8 @@ SDL_CreateRenderer(SDL_Window * window, int index, Uint32 flags)
|
||||||
renderer->window = window;
|
renderer->window = window;
|
||||||
renderer->scale.x = 1.0f;
|
renderer->scale.x = 1.0f;
|
||||||
renderer->scale.y = 1.0f;
|
renderer->scale.y = 1.0f;
|
||||||
|
renderer->logical_w = 0;
|
||||||
|
renderer->logical_h = 0;
|
||||||
|
|
||||||
if (SDL_GetWindowFlags(window) & (SDL_WINDOW_HIDDEN|SDL_WINDOW_MINIMIZED)) {
|
if (SDL_GetWindowFlags(window) & (SDL_WINDOW_HIDDEN|SDL_WINDOW_MINIMIZED)) {
|
||||||
renderer->hidden = SDL_TRUE;
|
renderer->hidden = SDL_TRUE;
|
||||||
|
@ -921,6 +946,88 @@ SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
UpdateLogicalSize(SDL_Renderer *renderer)
|
||||||
|
{
|
||||||
|
int w, h;
|
||||||
|
float want_aspect;
|
||||||
|
float real_aspect;
|
||||||
|
float scale;
|
||||||
|
SDL_Rect viewport;
|
||||||
|
|
||||||
|
if (renderer->window) {
|
||||||
|
SDL_GetWindowSize(renderer->window, &w, &h);
|
||||||
|
} else {
|
||||||
|
/* FIXME */
|
||||||
|
SDL_SetError("Internal error: No way to get output resolution");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
want_aspect = (float)renderer->logical_w / renderer->logical_h;
|
||||||
|
real_aspect = (float)w / h;
|
||||||
|
|
||||||
|
/* Clear the scale because we're setting viewport in output coordinates */
|
||||||
|
SDL_RenderSetScale(renderer, 1.0f, 1.0f);
|
||||||
|
|
||||||
|
if (SDL_fabs(want_aspect-real_aspect) < 0.0001) {
|
||||||
|
/* The aspect ratios are the same, just scale appropriately */
|
||||||
|
scale = (float)w / renderer->logical_w;
|
||||||
|
SDL_RenderSetViewport(renderer, NULL);
|
||||||
|
} else if (want_aspect > real_aspect) {
|
||||||
|
/* We want a wider aspect ratio than is available - letterbox it */
|
||||||
|
scale = (float)w / renderer->logical_w;
|
||||||
|
viewport.x = 0;
|
||||||
|
viewport.w = w;
|
||||||
|
viewport.h = (int)SDL_ceil(renderer->logical_h * scale);
|
||||||
|
viewport.y = (h - viewport.h) / 2;
|
||||||
|
SDL_RenderSetViewport(renderer, &viewport);
|
||||||
|
} else {
|
||||||
|
/* We want a narrower aspect ratio than is available - use side-bars */
|
||||||
|
scale = (float)h / renderer->logical_h;
|
||||||
|
viewport.y = 0;
|
||||||
|
viewport.h = h;
|
||||||
|
viewport.w = (int)SDL_ceil(renderer->logical_w * scale);
|
||||||
|
viewport.x = (w - viewport.w) / 2;
|
||||||
|
SDL_RenderSetViewport(renderer, &viewport);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the new scale */
|
||||||
|
SDL_RenderSetScale(renderer, scale, scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
SDL_RenderSetLogicalSize(SDL_Renderer * renderer, int w, int h)
|
||||||
|
{
|
||||||
|
CHECK_RENDERER_MAGIC(renderer, -1);
|
||||||
|
|
||||||
|
if (!w || !h) {
|
||||||
|
/* Clear any previous logical resolution */
|
||||||
|
renderer->logical_w = 0;
|
||||||
|
renderer->logical_h = 0;
|
||||||
|
SDL_RenderSetViewport(renderer, NULL);
|
||||||
|
SDL_RenderSetScale(renderer, 1.0f, 1.0f);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer->logical_w = w;
|
||||||
|
renderer->logical_h = h;
|
||||||
|
|
||||||
|
return UpdateLogicalSize(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SDL_RenderGetLogicalSize(SDL_Renderer * renderer, int *w, int *h)
|
||||||
|
{
|
||||||
|
CHECK_RENDERER_MAGIC(renderer, );
|
||||||
|
|
||||||
|
if (w) {
|
||||||
|
*w = renderer->logical_w;
|
||||||
|
}
|
||||||
|
if (h) {
|
||||||
|
*h = renderer->logical_h;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
SDL_RenderSetViewport(SDL_Renderer * renderer, const SDL_Rect * rect)
|
SDL_RenderSetViewport(SDL_Renderer * renderer, const SDL_Rect * rect)
|
||||||
{
|
{
|
||||||
|
|
|
@ -123,6 +123,10 @@ struct SDL_Renderer
|
||||||
SDL_bool hidden;
|
SDL_bool hidden;
|
||||||
SDL_bool resized;
|
SDL_bool resized;
|
||||||
|
|
||||||
|
/* The logical resolution for rendering */
|
||||||
|
int logical_w;
|
||||||
|
int logical_h;
|
||||||
|
|
||||||
/* The drawable area within the window */
|
/* The drawable area within the window */
|
||||||
SDL_Rect viewport;
|
SDL_Rect viewport;
|
||||||
SDL_Rect viewport_backup;
|
SDL_Rect viewport_backup;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue