2020-01-01 21:29:24 +01:00
|
|
|
#include "Screen.h"
|
|
|
|
|
2020-07-19 21:43:29 +02:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
#include "FileSystemUtils.h"
|
|
|
|
#include "GraphicsUtil.h"
|
|
|
|
|
|
|
|
// Used to create the window icon
|
|
|
|
extern "C"
|
|
|
|
{
|
|
|
|
extern unsigned lodepng_decode24(
|
|
|
|
unsigned char** out,
|
|
|
|
unsigned* w,
|
|
|
|
unsigned* h,
|
|
|
|
const unsigned char* in,
|
|
|
|
size_t insize
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-11-13 01:29:11 +01:00
|
|
|
ScreenSettings::ScreenSettings()
|
|
|
|
{
|
|
|
|
windowWidth = 320;
|
|
|
|
windowHeight = 240;
|
|
|
|
fullscreen = false;
|
|
|
|
useVsync = false;
|
|
|
|
stretch = 0;
|
|
|
|
linearFilter = false;
|
|
|
|
badSignal = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Screen::init(const ScreenSettings& settings)
|
|
|
|
{
|
2020-04-02 22:28:12 +02:00
|
|
|
m_window = NULL;
|
|
|
|
m_renderer = NULL;
|
|
|
|
m_screenTexture = NULL;
|
|
|
|
m_screen = NULL;
|
2020-11-13 01:29:11 +01:00
|
|
|
isWindowed = !settings.fullscreen;
|
|
|
|
stretchMode = settings.stretch;
|
|
|
|
isFiltered = settings.linearFilter;
|
|
|
|
vsync = settings.useVsync;
|
2020-04-02 22:28:12 +02:00
|
|
|
filterSubrect.x = 1;
|
|
|
|
filterSubrect.y = 1;
|
|
|
|
filterSubrect.w = 318;
|
|
|
|
filterSubrect.h = 238;
|
2020-07-09 03:42:57 +02:00
|
|
|
|
|
|
|
SDL_SetHintWithPriority(
|
|
|
|
SDL_HINT_RENDER_SCALE_QUALITY,
|
|
|
|
isFiltered ? "linear" : "nearest",
|
|
|
|
SDL_HINT_OVERRIDE
|
|
|
|
);
|
|
|
|
SDL_SetHintWithPriority(
|
|
|
|
SDL_HINT_RENDER_VSYNC,
|
|
|
|
vsync ? "1" : "0",
|
|
|
|
SDL_HINT_OVERRIDE
|
|
|
|
);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
// Uncomment this next line when you need to debug -flibit
|
|
|
|
// SDL_SetHintWithPriority(SDL_HINT_RENDER_DRIVER, "software", SDL_HINT_OVERRIDE);
|
Work around SDL2 bug where VSync hint only applies on renderer creation
Ugh, this is terrible and stupid and I hate myself for it.
Anyway, since the SDL2 VSync hint only applies when the renderer is
created, we have to re-create the renderer whenever VSync is toggled.
However, this also means we need to re-create m_screenTexture as well,
AND call ResizeScreen() after that or else the letterbox/integer modes
won't be applied.
Unfortunately, this means that in main(), gameScreen.init() will create
a renderer only to be destroyed later by graphics.processVsync().
There's not much we can do about this. Fixing this would require putting
graphics.processVsync() before gameScreen.init(). However, in order to
know whether the user has VSync set, we would have to call
game.loadstats() first, but wait, we can't, because game.loadstats()
mutates gameScreen! Gahhhhhh!!!!
@leo60228 suggested to fix that problem (
https://github.com/TerryCavanagh/VVVVVV/pull/220#issuecomment-624217939
) by adding NULL checks to game.loadstats() and then calling it twice,
but then you're trading wastefully creating a renderer only to be
destroyed, for wastefully opening and parsing unlock.vvv twice instead
of once. In either case, you're doing something twice and wasting work.
2020-06-19 23:12:56 +02:00
|
|
|
// FIXME: m_renderer is also created in Graphics::processVsync()!
|
2020-01-01 21:29:24 +01:00
|
|
|
SDL_CreateWindowAndRenderer(
|
|
|
|
640,
|
|
|
|
480,
|
2021-01-01 02:55:57 +01:00
|
|
|
SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI,
|
2020-01-01 21:29:24 +01:00
|
|
|
&m_window,
|
|
|
|
&m_renderer
|
|
|
|
);
|
|
|
|
SDL_SetWindowTitle(m_window, "VVVVVV");
|
|
|
|
|
2020-11-01 04:25:27 +01:00
|
|
|
LoadIcon();
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
// FIXME: This surface should be the actual backbuffer! -flibit
|
|
|
|
m_screen = SDL_CreateRGBSurface(
|
|
|
|
0,
|
|
|
|
320,
|
|
|
|
240,
|
|
|
|
32,
|
|
|
|
0x00FF0000,
|
|
|
|
0x0000FF00,
|
|
|
|
0x000000FF,
|
|
|
|
0xFF000000
|
|
|
|
);
|
Work around SDL2 bug where VSync hint only applies on renderer creation
Ugh, this is terrible and stupid and I hate myself for it.
Anyway, since the SDL2 VSync hint only applies when the renderer is
created, we have to re-create the renderer whenever VSync is toggled.
However, this also means we need to re-create m_screenTexture as well,
AND call ResizeScreen() after that or else the letterbox/integer modes
won't be applied.
Unfortunately, this means that in main(), gameScreen.init() will create
a renderer only to be destroyed later by graphics.processVsync().
There's not much we can do about this. Fixing this would require putting
graphics.processVsync() before gameScreen.init(). However, in order to
know whether the user has VSync set, we would have to call
game.loadstats() first, but wait, we can't, because game.loadstats()
mutates gameScreen! Gahhhhhh!!!!
@leo60228 suggested to fix that problem (
https://github.com/TerryCavanagh/VVVVVV/pull/220#issuecomment-624217939
) by adding NULL checks to game.loadstats() and then calling it twice,
but then you're trading wastefully creating a renderer only to be
destroyed, for wastefully opening and parsing unlock.vvv twice instead
of once. In either case, you're doing something twice and wasting work.
2020-06-19 23:12:56 +02:00
|
|
|
// ALSO FIXME: This SDL_CreateTexture() is duplicated in Graphics::processVsync()!
|
2020-01-01 21:29:24 +01:00
|
|
|
m_screenTexture = SDL_CreateTexture(
|
|
|
|
m_renderer,
|
|
|
|
SDL_PIXELFORMAT_ARGB8888,
|
|
|
|
SDL_TEXTUREACCESS_STREAMING,
|
|
|
|
320,
|
|
|
|
240
|
|
|
|
);
|
|
|
|
|
2020-11-13 01:29:11 +01:00
|
|
|
badSignalEffect = settings.badSignal;
|
2020-07-08 20:30:57 +02:00
|
|
|
|
2020-11-13 01:29:11 +01:00
|
|
|
ResizeScreen(settings.windowWidth, settings.windowHeight);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
2020-12-22 01:34:16 +01:00
|
|
|
void Screen::GetSettings(ScreenSettings* settings)
|
|
|
|
{
|
|
|
|
int width, height;
|
|
|
|
GetWindowSize(&width, &height);
|
|
|
|
|
|
|
|
settings->windowWidth = width;
|
|
|
|
settings->windowHeight = height;
|
|
|
|
|
|
|
|
settings->fullscreen = !isWindowed;
|
|
|
|
settings->useVsync = vsync;
|
|
|
|
settings->stretch = stretchMode;
|
|
|
|
settings->linearFilter = isFiltered;
|
|
|
|
settings->badSignal = badSignalEffect;
|
|
|
|
}
|
|
|
|
|
2020-11-01 04:25:27 +01:00
|
|
|
void Screen::LoadIcon()
|
|
|
|
{
|
|
|
|
unsigned char *fileIn = NULL;
|
|
|
|
size_t length = 0;
|
|
|
|
unsigned char *data;
|
|
|
|
unsigned int width, height;
|
|
|
|
FILESYSTEM_loadFileToMemory("VVVVVV.png", &fileIn, &length);
|
|
|
|
lodepng_decode24(&data, &width, &height, fileIn, length);
|
|
|
|
FILESYSTEM_freeMemory(&fileIn);
|
|
|
|
SDL_Surface *icon = SDL_CreateRGBSurfaceFrom(
|
|
|
|
data,
|
|
|
|
width,
|
|
|
|
height,
|
|
|
|
24,
|
|
|
|
width * 3,
|
|
|
|
0x000000FF,
|
|
|
|
0x0000FF00,
|
|
|
|
0x00FF0000,
|
|
|
|
0x00000000
|
|
|
|
);
|
|
|
|
SDL_SetWindowIcon(m_window, icon);
|
|
|
|
SDL_FreeSurface(icon);
|
Reduce dependency on libc functions
During 2.3 development, there's been a gradual shift to using SDL stdlib
functions instead of libc functions, but there are still some libc
functions (or the same libc function but from the STL) in the code.
Well, this patch replaces all the rest of them in one fell swoop.
SDL's stdlib can replace most of these, but its SDL_min() and SDL_max()
are inadequate - they aren't really functions, they're more like macros
with a nasty penchant for double-evaluation. So I just made my own
VVV_min() and VVV_max() functions and placed them in Maths.h instead,
then replaced all the previous usages of min(), max(), std::min(),
std::max(), SDL_min(), and SDL_max() with VVV_min() and VVV_max().
Additionally, there's no SDL_isxdigit(), so I just implemented my own
VVV_isxdigit().
SDL has SDL_malloc() and SDL_free(), but they have some refcounting
built in to them, so in order to use them with LodePNG, I have to
replace the malloc() and free() that LodePNG uses. Which isn't too hard,
I did it in a new file called ThirdPartyDeps.c, and LodePNG is now
compiled with the LODEPNG_NO_COMPILE_ALLOCATORS definition.
Lastly, I also refactored the awful strcpy() and strcat() usages in
PLATFORM_migrateSaveData() to use SDL_snprintf() instead. I know save
migration is getting axed in 2.4, but it still bothers me to have
something like that in the codebase otherwise.
Without further ado, here is the full list of functions that the
codebase now uses:
- SDL_strlcpy() instead of strcpy()
- SDL_strlcat() instead of strcat()
- SDL_snprintf() instead of sprintf(), strcpy(), or strcat() (see above)
- VVV_min() instead of min(), std::min(), or SDL_min()
- VVV_max() instead of max(), std::max(), or SDL_max()
- VVV_isxdigit() instead of isxdigit()
- SDL_strcmp() instead of strcmp()
- SDL_strcasecmp() instead of strcasecmp() or Win32 strcmpi()
- SDL_strstr() instead of strstr()
- SDL_strlen() instead of strlen()
- SDL_sscanf() instead of sscanf()
- SDL_getenv() instead of getenv()
- SDL_malloc() instead of malloc() (replacing in LodePNG as well)
- SDL_free() instead of free() (replacing in LodePNG as well)
2021-01-12 01:17:45 +01:00
|
|
|
SDL_free(data);
|
2020-11-01 04:25:27 +01:00
|
|
|
}
|
|
|
|
|
2020-03-13 23:22:37 +01:00
|
|
|
void Screen::ResizeScreen(int x, int y)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
static int resX = 320;
|
|
|
|
static int resY = 240;
|
|
|
|
if (x != -1 && y != -1)
|
|
|
|
{
|
|
|
|
// This is a user resize!
|
|
|
|
resX = x;
|
|
|
|
resY = y;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!isWindowed)
|
|
|
|
{
|
2020-03-13 23:22:37 +01:00
|
|
|
int result = SDL_SetWindowFullscreen(m_window, SDL_WINDOW_FULLSCREEN_DESKTOP);
|
|
|
|
if (result != 0)
|
|
|
|
{
|
|
|
|
printf("Error: could not set the game to fullscreen mode: %s\n", SDL_GetError());
|
|
|
|
return;
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-03-13 23:22:37 +01:00
|
|
|
int result = SDL_SetWindowFullscreen(m_window, 0);
|
|
|
|
if (result != 0)
|
|
|
|
{
|
|
|
|
printf("Error: could not set the game to windowed mode: %s\n", SDL_GetError());
|
|
|
|
return;
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
if (x != -1 && y != -1)
|
|
|
|
{
|
|
|
|
SDL_SetWindowSize(m_window, resX, resY);
|
|
|
|
SDL_SetWindowPosition(m_window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (stretchMode == 1)
|
|
|
|
{
|
|
|
|
int winX, winY;
|
2021-01-01 03:12:30 +01:00
|
|
|
GetWindowSize(&winX, &winY);
|
2020-03-13 23:22:37 +01:00
|
|
|
int result = SDL_RenderSetLogicalSize(m_renderer, winX, winY);
|
|
|
|
if (result != 0)
|
|
|
|
{
|
|
|
|
printf("Error: could not set logical size: %s\n", SDL_GetError());
|
|
|
|
return;
|
|
|
|
}
|
Don't print useless false error message when toggling fullscreen
Whenever you would press Alt+Enter, or Alt+F, or on macOS Command+Enter,
or on macOS Command+F, or F11, the game would print this useless error
message to console, every single time: "Error: failed: " and it would
concatenate SDL_GetError() after it, but most of the time SDL_GetError()
is blank, so it would print just that.
Instead, what the fullscreen shortcut will now do is check the result of
the relevant SDL functions, BEFORE it decides to print an error message.
And when it DOES print an error message, it will be less vague and will
say instead "Error: toggling fullscreen failed: <output of
SDL_GetError()>".
This means Screen::ResizeScreen() and Screen::toggleFullScreen() are now
int-returning functions. Ideally, every function interfacing with SDL
would return an error code, but that's too much for this simple patch.
Additionally, I took the opportunity to clean up the surrounding
formatting of the code a bit, most notably dedenting the
keypress-clearing stuff by one tab level, converting the
shortcut-handling code to spaces, and removing commented-out code.
2020-03-13 08:23:48 +01:00
|
|
|
result = SDL_RenderSetIntegerScale(m_renderer, SDL_FALSE);
|
2020-03-13 23:22:37 +01:00
|
|
|
if (result != 0)
|
|
|
|
{
|
|
|
|
printf("Error: could not set scale: %s\n", SDL_GetError());
|
|
|
|
return;
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SDL_RenderSetLogicalSize(m_renderer, 320, 240);
|
2020-03-13 23:22:37 +01:00
|
|
|
int result = SDL_RenderSetIntegerScale(m_renderer, (SDL_bool) (stretchMode == 2));
|
|
|
|
if (result != 0)
|
|
|
|
{
|
|
|
|
printf("Error: could not set scale: %s\n", SDL_GetError());
|
|
|
|
return;
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
SDL_ShowWindow(m_window);
|
|
|
|
}
|
|
|
|
|
Add "resize to nearest" graphics option
If you want your game window to simply be exactly 320x240, or 640x480,
or 960x720 etc. then it's really annoying that there's no easy way to do
this (to clarify, this is different from integer mode, which controls
the size of the game INSIDE the window). The easiest way would be having
to close the game, go into unlock.vvv, and edit the window size
manually. VCE has a 1x/2x/3x/4x graphics option to solve this, although
it does not account for actual monitor size (those 1x/2x/3x/4x modes are
all you get, whether or not you have a monitor too small for some of
them or too big for any of them to be what you want).
I discussed this with flibit, and he said that VCE's approach (if it
accounted for monitor size) wouldn't work on high-retina displays or
high DPIs, because getting the actual multiplier to account for those
monitors is kind of a pain. So the next best thing would be to add an
option that resizes to the nearest perfect multiple of 320x240. That way
you could simply resize the window and let the game correct any
imperfect dimensions automatically.
2020-06-30 07:02:21 +02:00
|
|
|
void Screen::ResizeToNearestMultiple()
|
|
|
|
{
|
|
|
|
int w, h;
|
|
|
|
GetWindowSize(&w, &h);
|
|
|
|
|
|
|
|
// Check aspect ratio first
|
|
|
|
bool using_width;
|
|
|
|
int usethisdimension, usethisratio;
|
|
|
|
|
|
|
|
if ((float) w / (float) h > 4.0 / 3.0)
|
|
|
|
{
|
|
|
|
// Width is bigger, so it's limited by height
|
|
|
|
usethisdimension = h;
|
|
|
|
usethisratio = 240;
|
|
|
|
using_width = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Height is bigger, so it's limited by width. Or we're exactly 4:3 already
|
|
|
|
usethisdimension = w;
|
|
|
|
usethisratio = 320;
|
|
|
|
using_width = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
int floor = (usethisdimension / usethisratio) * usethisratio;
|
|
|
|
int ceiling = floor + usethisratio;
|
|
|
|
|
|
|
|
int final_dimension;
|
|
|
|
|
|
|
|
if (usethisdimension - floor < ceiling - usethisdimension)
|
|
|
|
{
|
|
|
|
// Floor is nearest
|
|
|
|
final_dimension = floor;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Ceiling is nearest. Or we're exactly on a multiple already
|
|
|
|
final_dimension = ceiling;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (final_dimension == 0)
|
|
|
|
{
|
|
|
|
// We're way too small!
|
|
|
|
ResizeScreen(320, 240);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (using_width)
|
|
|
|
{
|
|
|
|
ResizeScreen(final_dimension, final_dimension / 4 * 3);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ResizeScreen(final_dimension * 4 / 3, final_dimension);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
void Screen::GetWindowSize(int* x, int* y)
|
|
|
|
{
|
2021-01-01 03:00:20 +01:00
|
|
|
SDL_GetRendererOutputSize(m_renderer, x, y);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Screen::UpdateScreen(SDL_Surface* buffer, SDL_Rect* rect )
|
|
|
|
{
|
2020-04-02 22:28:12 +02:00
|
|
|
if((buffer == NULL) && (m_screen == NULL) )
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-04-02 22:28:12 +02:00
|
|
|
if(badSignalEffect)
|
|
|
|
{
|
|
|
|
buffer = ApplyFilter(buffer);
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
|
2020-04-02 22:28:12 +02:00
|
|
|
FillRect(m_screen, 0x000);
|
|
|
|
BlitSurfaceStandard(buffer,NULL,m_screen,rect);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-04-02 22:28:12 +02:00
|
|
|
if(badSignalEffect)
|
|
|
|
{
|
|
|
|
SDL_FreeSurface(buffer);
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const SDL_PixelFormat* Screen::GetFormat()
|
|
|
|
{
|
2020-04-02 22:28:12 +02:00
|
|
|
return m_screen->format;
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Screen::FlipScreen()
|
|
|
|
{
|
|
|
|
SDL_UpdateTexture(
|
|
|
|
m_screenTexture,
|
|
|
|
NULL,
|
|
|
|
m_screen->pixels,
|
|
|
|
m_screen->pitch
|
|
|
|
);
|
|
|
|
SDL_RenderCopy(
|
|
|
|
m_renderer,
|
|
|
|
m_screenTexture,
|
|
|
|
isFiltered ? &filterSubrect : NULL,
|
|
|
|
NULL
|
|
|
|
);
|
|
|
|
SDL_RenderPresent(m_renderer);
|
|
|
|
SDL_RenderClear(m_renderer);
|
|
|
|
SDL_FillRect(m_screen, NULL, 0x00000000);
|
|
|
|
}
|
|
|
|
|
2020-03-13 23:22:37 +01:00
|
|
|
void Screen::toggleFullScreen()
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
isWindowed = !isWindowed;
|
2020-03-13 23:22:37 +01:00
|
|
|
ResizeScreen(-1, -1);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Screen::toggleStretchMode()
|
|
|
|
{
|
|
|
|
stretchMode = (stretchMode + 1) % 3;
|
|
|
|
ResizeScreen(-1, -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Screen::toggleLinearFilter()
|
|
|
|
{
|
|
|
|
isFiltered = !isFiltered;
|
2020-07-09 03:42:57 +02:00
|
|
|
SDL_SetHintWithPriority(
|
|
|
|
SDL_HINT_RENDER_SCALE_QUALITY,
|
|
|
|
isFiltered ? "linear" : "nearest",
|
|
|
|
SDL_HINT_OVERRIDE
|
|
|
|
);
|
2020-01-01 21:29:24 +01:00
|
|
|
SDL_DestroyTexture(m_screenTexture);
|
|
|
|
m_screenTexture = SDL_CreateTexture(
|
|
|
|
m_renderer,
|
|
|
|
SDL_PIXELFORMAT_ARGB8888,
|
|
|
|
SDL_TEXTUREACCESS_STREAMING,
|
|
|
|
320,
|
|
|
|
240
|
|
|
|
);
|
|
|
|
}
|
2020-07-02 06:19:40 +02:00
|
|
|
|
|
|
|
void Screen::resetRendererWorkaround()
|
|
|
|
{
|
|
|
|
SDL_SetHintWithPriority(
|
|
|
|
SDL_HINT_RENDER_VSYNC,
|
|
|
|
vsync ? "1" : "0",
|
|
|
|
SDL_HINT_OVERRIDE
|
|
|
|
);
|
|
|
|
|
|
|
|
/* FIXME: This exists because SDL_HINT_RENDER_VSYNC is not dynamic!
|
|
|
|
* As a result, our only workaround is to tear down the renderer
|
|
|
|
* and recreate everything so that it can process the variable.
|
|
|
|
* -flibit
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (m_renderer == NULL)
|
|
|
|
{
|
|
|
|
/* We haven't made it to init yet, don't worry about it */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_RendererInfo renderInfo;
|
|
|
|
SDL_GetRendererInfo(m_renderer, &renderInfo);
|
|
|
|
bool curVsync = (renderInfo.flags & SDL_RENDERER_PRESENTVSYNC) != 0;
|
|
|
|
if (vsync == curVsync)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_DestroyTexture(m_screenTexture);
|
|
|
|
SDL_DestroyRenderer(m_renderer);
|
|
|
|
|
|
|
|
m_renderer = SDL_CreateRenderer(m_window, -1, 0);
|
|
|
|
m_screenTexture = SDL_CreateTexture(
|
|
|
|
m_renderer,
|
|
|
|
SDL_PIXELFORMAT_ARGB8888,
|
|
|
|
SDL_TEXTUREACCESS_STREAMING,
|
|
|
|
320,
|
|
|
|
240
|
|
|
|
);
|
|
|
|
|
|
|
|
/* Ugh, have to make sure to re-apply graphics options after doing the
|
|
|
|
* above, otherwise letterbox/integer won't be applied...
|
|
|
|
*/
|
|
|
|
ResizeScreen(-1, -1);
|
|
|
|
}
|