Skip to content

Commit 3dec989

Browse files
committed
Render to a small texture, then scale up to the screen size
To be honest, I thought this is what SDL_RenderSetLogicalSize() did, but actually it scales up each object that you draw with SDL_RenderCopy(). This is necessary because on some GPUs, scaling up can cause a sprite to bleed into an adjacent frame in the spritesheet texture. This shouldn't happen with nearest neighbor scaling, but it nevertheless does happen on some GPUs such as my laptop's embedded Intel GPU. On this GPU I saw a one pixel wide strip on the top and left of every sprite that showed the neighboring sprite frame. The strip was one pixel wide in my screen's pixels, not the logical resolution's pixels. Rendering everything to a 320x240 texture and then scaling up the whole texture at once makes strange bugs like this impossible.
1 parent 3ca02b4 commit 3dec989

File tree

10 files changed

+63
-35
lines changed

10 files changed

+63
-35
lines changed

src/endgame/island.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ void island_draw()
8080
{
8181

8282
// draw the scene
83-
Renderer::getInstance()->fillScreen(BLACK);
83+
Renderer::getInstance()->clearScreen(BLACK);
8484

8585
Renderer::getInstance()->setClip(island.scene_x, island.scene_y, Renderer::getInstance()->sprites.sprites[SPR_ISLAND_SCENE].w, Renderer::getInstance()->sprites.sprites[SPR_ISLAND_SCENE].h);
8686

src/game.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ bool Game::pause(int pausemode, int param)
220220

221221
void Game::tick(void)
222222
{
223-
Renderer::getInstance()->clearScreen();
223+
Renderer::getInstance()->clearScreen(BLACK);
224224
debug_clear();
225225

226226
if (game.paused)
@@ -353,7 +353,7 @@ void DrawScene(void)
353353
{
354354
int scr_x, scr_y;
355355
extern int flipacceltime;
356-
Renderer::getInstance()->fillScreen(BLACK);
356+
Renderer::getInstance()->clearScreen(BLACK);
357357

358358
// draw background map tiles
359359
if (!flipacceltime)

src/graphics/Renderer.cpp

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ bool Renderer::initVideo(int scale)
6969
{
7070
uint32_t window_flags = SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI;
7171

72+
//TODO: sync this with setResolution
7273
if (widescreen) {
7374
screenWidth = 432;
7475
screenHeight = 243;
@@ -138,6 +139,9 @@ bool Renderer::initVideo(int scale)
138139
return false;
139140
}
140141

142+
if (!createRenderTarget(screenWidth, screenHeight))
143+
return false;
144+
141145
std::string spotpath = ResourceManager::getInstance()->getPath("spot.png");
142146

143147
SDL_Surface *image;
@@ -148,6 +152,24 @@ bool Renderer::initVideo(int scale)
148152
return true;
149153
}
150154

155+
bool Renderer::createRenderTarget(int width, int height)
156+
{
157+
SDL_RendererInfo info;
158+
SDL_GetRendererInfo(_renderer, &info);
159+
160+
_texture = SDL_CreateTexture(_renderer,
161+
info.texture_formats[0],
162+
SDL_TEXTUREACCESS_TARGET,
163+
width, height);
164+
if (SDL_SetRenderTarget(_renderer, _texture)) {
165+
LOG_ERROR("Renderer::createRenderTarget: SDL_SetRenderTarget failed: {}", SDL_GetError());
166+
return false;
167+
}
168+
SDL_RenderClear(_renderer);
169+
170+
return true;
171+
}
172+
151173
bool Renderer::flushAll()
152174
{
153175
LOG_DEBUG("Renderer::flushAll()");
@@ -200,18 +222,24 @@ bool Renderer::setResolution(int scale, bool newWidescreen)
200222
LOG_INFO("Renderer logical resolution: {}x{}", newWidth, newHeight);
201223

202224
SDL_SetWindowSize(_window, newWidth * scale, newHeight * scale);
225+
226+
SDL_SetRenderTarget(_renderer, NULL);
227+
SDL_DestroyTexture(_texture);
203228
if (SDL_RenderSetLogicalSize(_renderer, newWidth, newHeight)) {
204229
LOG_ERROR("Renderer::setResolution: SDL_RenderSetLogicalSize failed: {}", SDL_GetError());
205230
return false;
206231
}
207232

233+
if (!flushAll())
234+
return false;
235+
236+
if (!createRenderTarget(newWidth, newHeight))
237+
return false;
238+
208239
screenWidth = newWidth;
209240
screenHeight = newHeight;
210241
widescreen = newWidescreen;
211242

212-
if (!flushAll())
213-
return false;
214-
215243
recalc_map_offsets();
216244
textbox.RecalculateOffsets();
217245

@@ -237,7 +265,7 @@ void Renderer::showLoadingScreen()
237265
int x = (screenWidth / 2) - (loading.width() / 2);
238266
int y = (screenHeight / 2) - loading.height();
239267

240-
fillScreen(BLACK);
268+
clearScreen(BLACK);
241269
drawSurface(&loading, x, y);
242270
flip();
243271
}
@@ -252,16 +280,15 @@ SDL_Window* Renderer::window()
252280
return _window;
253281
}
254282

255-
void Renderer::clearScreen()
256-
{
257-
SDL_SetRenderDrawColor(_renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
258-
SDL_RenderClear(_renderer);
259-
}
260-
261283
void Renderer::flip()
262284
{
263285
// LOG_INFO("===FLIPPING===\n");
286+
SDL_SetRenderTarget(_renderer, NULL);
287+
SDL_SetRenderDrawColor(_renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
288+
SDL_RenderClear(_renderer);
289+
SDL_RenderCopy(_renderer, _texture, NULL, NULL);
264290
SDL_RenderPresent(_renderer);
291+
SDL_SetRenderTarget(_renderer, _texture);
265292
// LOG_INFO("===FLIPPED===\n");
266293
}
267294

@@ -390,7 +417,7 @@ void Renderer::drawPixel(int x, int y, uint8_t r, uint8_t g, uint8_t b)
390417
fillRect(x, y, x, y, r, g, b);
391418
}
392419

393-
void Renderer::fillScreen(uint8_t r, uint8_t g, uint8_t b)
420+
void Renderer::clearScreen(uint8_t r, uint8_t g, uint8_t b)
394421
{
395422
SDL_SetRenderDrawColor(_renderer, r, g, b, SDL_ALPHA_OPAQUE);
396423
SDL_RenderFillRect(_renderer, NULL);

src/graphics/Renderer.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,14 @@ class Renderer
4848

4949
void showLoadingScreen();
5050

51-
void clearScreen();
52-
5351
void drawSurface(Surface *src, int x, int y);
5452
void drawSurface(Surface *src, int dstx, int dsty, int srcx, int srcy, int wd, int ht);
5553
void drawSurfaceMirrored(Surface *src, int dstx, int dsty, int srcx, int srcy, int wd, int ht);
5654

5755
void blitPatternAcross(Surface *sfc, int x_dst, int y_dst, int y_src, int height);
5856

59-
void fillScreen(NXColor color);
60-
void fillScreen(uint8_t r, uint8_t g, uint8_t b);
57+
void clearScreen(NXColor color);
58+
void clearScreen(uint8_t r, uint8_t g, uint8_t b);
6159

6260
void drawLine(int x1, int y1, int x2, int y2, NXColor color);
6361

@@ -96,12 +94,15 @@ class Renderer
9694
private:
9795
SDL_Window *_window = nullptr;
9896
SDL_Renderer *_renderer = nullptr;
97+
SDL_Texture *_texture = nullptr;
9998
int _current_res = -1;
10099
bool _need_clip = false;
101100
SDL_Rect _clip_rect;
102101
SDL_Texture* _spot_light;
103102
bool _fullscreen = false;
104103

104+
bool createRenderTarget(int width, int height);
105+
105106
protected:
106107
friend class Singleton<Renderer>;
107108

@@ -151,9 +152,9 @@ void inline Renderer::drawPixel(int x, int y, NXColor color)
151152
drawPixel(x, y, color.r, color.g, color.b);
152153
}
153154

154-
void inline Renderer::fillScreen(NXColor color)
155+
void inline Renderer::clearScreen(NXColor color)
155156
{
156-
fillScreen(color.r, color.g, color.b);
157+
clearScreen(color.r, color.g, color.b);
157158
}
158159

159160
void inline Renderer::setClip(NXRect *rect)

src/intro/intro.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ void intro_tick()
4343
}
4444
if (blanktimer > 0)
4545
{
46-
Renderer::getInstance()->fillScreen(BLACK);
46+
Renderer::getInstance()->clearScreen(BLACK);
4747

4848
if (--blanktimer == 0)
4949
game.setmode(GM_TITLE);

src/intro/title.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ std::vector<menuitem> _menuitems;
6262
static void draw_title()
6363
{
6464
// background is dk grey, not pure black
65-
Renderer::getInstance()->fillScreen(0x20, 0x20, 0x20);
65+
Renderer::getInstance()->clearScreen(0x20, 0x20, 0x20);
6666
map_draw_backdrop();
6767
// DrawFastLeftLayered();
6868

@@ -343,7 +343,7 @@ void title_tick()
343343
{
344344
if (title.seldelay > 0)
345345
{
346-
Renderer::getInstance()->fillScreen(BLACK);
346+
Renderer::getInstance()->clearScreen(BLACK);
347347

348348
title.seldelay--;
349349
if (!title.seldelay)
@@ -357,7 +357,7 @@ void title_tick()
357357
}
358358
else
359359
{
360-
Renderer::getInstance()->fillScreen(BLACK);
360+
Renderer::getInstance()->clearScreen(BLACK);
361361

362362
if (!textbox.SaveSelect.IsVisible())
363363
{ // selection was made, and settings.last_save_slot is now set appropriately

src/map.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -588,9 +588,9 @@ void map_draw_backdrop(void)
588588
case BK_HIDE3:
589589
{
590590
if (game.curmap == STAGE_KINGS) // intro cutscene
591-
Renderer::getInstance()->fillScreen(BLACK);
591+
Renderer::getInstance()->clearScreen(BLACK);
592592
else
593-
Renderer::getInstance()->fillScreen(DK_BLUE);
593+
Renderer::getInstance()->clearScreen(DK_BLUE);
594594
}
595595
return;
596596

@@ -644,15 +644,15 @@ void DrawFastLeftLayered(void)
644644
y1 = x = 0;
645645
// fix for extra height
646646
if (map.backdrop == 9)
647-
Renderer::getInstance()->fillScreen(111, 156, 214);
647+
Renderer::getInstance()->clearScreen(111, 156, 214);
648648
else if (map.backdrop == 10 && game.curmap != 64)
649-
Renderer::getInstance()->fillScreen(107, 105, 82);
649+
Renderer::getInstance()->clearScreen(107, 105, 82);
650650
else if (map.backdrop == 12)
651-
Renderer::getInstance()->fillScreen(179, 190, 210);
651+
Renderer::getInstance()->clearScreen(179, 190, 210);
652652
else if (map.backdrop == 13)
653-
Renderer::getInstance()->fillScreen(170, 101, 0);
653+
Renderer::getInstance()->clearScreen(170, 101, 0);
654654
else if (map.backdrop == 14)
655-
Renderer::getInstance()->fillScreen(202, 97, 97);
655+
Renderer::getInstance()->clearScreen(202, 97, 97);
656656

657657
for (i = 0; i < nlayers; i++)
658658
{

src/pause/mods.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ bool mods_init(int param)
7272
void mods_tick()
7373
{
7474
if (moddlg != NULL) {
75-
Renderer::getInstance()->fillScreen(BLACK);
75+
Renderer::getInstance()->clearScreen(BLACK);
7676
moddlg->Draw();
7777
moddlg->RunInput();
7878
}

src/pause/options.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ void options_tick()
113113
unsigned int i;
114114
FocusHolder *fh;
115115

116-
Renderer::getInstance()->fillScreen(BLACK);
116+
Renderer::getInstance()->clearScreen(BLACK);
117117
Options::run_and_draw_objects();
118118

119119
fh = (FocusHolder *)optionstack.at(optionstack.size() - 1);

src/screeneffect.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ void SE_FlashScreen::Draw(void)
4141
}
4242

4343
if (flashstate)
44-
Renderer::getInstance()->fillScreen(0xff, 0xff, 0xff);
44+
Renderer::getInstance()->clearScreen(0xff, 0xff, 0xff);
4545
}
4646

4747
/*
@@ -170,7 +170,7 @@ void SE_Fade::Draw(void)
170170
}
171171
else if (state == FS_FADED_OUT)
172172
{
173-
Renderer::getInstance()->fillScreen(DK_BLUE);
173+
Renderer::getInstance()->clearScreen(DK_BLUE);
174174
return;
175175
}
176176

0 commit comments

Comments
 (0)