From 0a80acd8b3cc5c594df961f5c52f11e07834fbf0 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Sun, 22 Mar 2026 19:09:47 -0700
Subject: [PATCH] Removed rendering to a rendering target
This reduces memory usage and allows drawing to the entire screen in the future.
---
game/main.cpp | 78 ++++++++++++++++++++------------------
maclib/Mac_FontServ.cpp | 8 +++-
screenlib/SDL_FrameBuf.cpp | 73 +++++++++++++++--------------------
screenlib/SDL_FrameBuf.h | 5 +--
screenlib/UIManager.cpp | 43 ++++++++++++---------
screenlib/UIManager.h | 2 +-
6 files changed, 106 insertions(+), 103 deletions(-)
diff --git a/game/main.cpp b/game/main.cpp
index e990095b..3c4a545c 100644
--- a/game/main.cpp
+++ b/game/main.cpp
@@ -58,7 +58,7 @@ Bool gNetworkAvailable = false;
Bool gUpdateBuffer = false;
Bool gDelaySound = false;
int gDelayTicks = 0;
-Bool gRunning = false;
+Bool gRunning = true;
// Main Menu actions:
@@ -210,52 +210,56 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
SDL_AppResult SDL_AppIterate(void *appstate)
{
- if (screen->Fading()) {
- screen->FadeStep();
- return SDL_APP_CONTINUE;
- }
+ while (!screen->Fading()) {
- if (gDelaySound) {
- if (sound->Playing()) {
- screen->Update();
- Delay(2);
- return SDL_APP_CONTINUE;
+ if (gDelaySound) {
+ if (sound->Playing()) {
+ ui->Draw(false);
+ Delay(2);
+ break;
+ }
+ gDelaySound = false;
}
- gDelaySound = false;
- }
- if (gDelayTicks) {
- int ticks = SDL_min(gDelayTicks, 2);
- screen->Update();
- Delay(ticks);
- gDelayTicks -= ticks;
- return SDL_APP_CONTINUE;
- }
+ if (gDelayTicks) {
+ int ticks = SDL_min(gDelayTicks, 2);
+ ui->Draw(false);
+ Delay(ticks);
+ gDelayTicks -= ticks;
+ break;
+ }
- if (gInitializing) {
- if (ContinueInitialization()) {
- ui->Draw();
- Delay(2);
- return SDL_APP_CONTINUE;
- } else {
- return SDL_APP_FAILURE;
+ if (gInitializing) {
+ if (ContinueInitialization()) {
+ ui->Draw();
+ Delay(2);
+ break;
+ } else {
+ return SDL_APP_FAILURE;
+ }
}
- }
- ui->Draw();
+ ui->Draw();
- if (!gGameOn) {
- // If we got a replay event, start it up!
- if (gReplayFile) {
- RunReplayGame(gReplayFile);
- SDL_free(gReplayFile);
- gReplayFile = nullptr;
+ if (!gGameOn) {
+ // If we got a replay event, start it up!
+ if (gReplayFile) {
+ RunReplayGame(gReplayFile);
+ SDL_free(gReplayFile);
+ gReplayFile = nullptr;
+ }
}
- }
- UpdateSteam();
+ UpdateSteam();
+
+ DelayFrame();
- DelayFrame();
+ break;
+ }
+
+ if (screen->Fading()) {
+ screen->FadeStep();
+ }
if (gRunning) {
return SDL_APP_CONTINUE;
diff --git a/maclib/Mac_FontServ.cpp b/maclib/Mac_FontServ.cpp
index 02c7c185..308f0d40 100644
--- a/maclib/Mac_FontServ.cpp
+++ b/maclib/Mac_FontServ.cpp
@@ -378,7 +378,9 @@ FontServ::TextImage(const char *text, MFont *font, Uint8 style, SDL_Color fg)
image = screen->LoadImage(surface);
SDL_FreeSurface(surface);
- SDL_SetTextureBlendMode(image, SDL_BLENDMODE_BLEND);
+ SDL_SetTextureBlendMode(image, SDL_ComposeCustomBlendMode(
+ SDL_BLENDFACTOR_ONE, SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, SDL_BLENDOPERATION_ADD,
+ SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_ADD));
SDL_SetTextureColorMod(image, fg.r, fg.g, fg.b);
return image;
}
@@ -491,7 +493,9 @@ FontServ::TextImage(const char *text, MFont *font, Uint8 style, SDL_Color fg)
/* Create the image */
image = screen->LoadImage(width, height, bitmap);
delete[] bitmap;
- SDL_SetTextureBlendMode(image, SDL_BLENDMODE_BLEND);
+ SDL_SetTextureBlendMode(image, SDL_ComposeCustomBlendMode(
+ SDL_BLENDFACTOR_ONE, SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, SDL_BLENDOPERATION_ADD,
+ SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_ADD));
SDL_SetTextureColorMod(image, fg.r, fg.g, fg.b);
return(image);
diff --git a/screenlib/SDL_FrameBuf.cpp b/screenlib/SDL_FrameBuf.cpp
index 82b15421..767f69fb 100644
--- a/screenlib/SDL_FrameBuf.cpp
+++ b/screenlib/SDL_FrameBuf.cpp
@@ -70,6 +70,9 @@ FrameBuf::Init(int width, int height, Uint32 window_flags, const char *title, SD
SetError("Couldn't create renderer: %s", SDL_GetError());
return(-1);
}
+ //SDL_SetDefaultTextureScaleMode(m_renderer, SDL_SCALEMODE_PIXELART);
+
+ Clear();
/* Set the output area */
SDL_SetRenderLogicalPresentation(m_renderer, width, height, SDL_LOGICAL_PRESENTATION_LETTERBOX);
@@ -81,16 +84,6 @@ FrameBuf::Init(int width, int height, Uint32 window_flags, const char *title, SD
m_clip.w = (float)width;
m_clip.h = (float)height;
- /* Create the render target */
- m_target = SDL_CreateTexture(m_renderer, SDL_PIXELFORMAT_UNKNOWN, SDL_TEXTUREACCESS_TARGET, width, height);
- if (!m_target) {
- SetError("Couldn't create target: %s", SDL_GetError());
- return(-1);
- }
- //SDL_SetTextureScaleMode(m_target, SDL_SCALEMODE_PIXELART);
-
- SDL_SetRenderTarget(m_renderer, m_target);
-
return(0);
}
@@ -99,9 +92,6 @@ FrameBuf::~FrameBuf()
for (unsigned int i = 0; i < m_gamepads.length(); ++i) {
SDL_CloseGamepad(m_gamepads[i]);
}
- if (m_target) {
- SDL_DestroyTexture(m_target);
- }
if (m_renderer) {
SDL_DestroyRenderer(m_renderer);
}
@@ -435,25 +425,7 @@ FrameBuf::Update(void)
return;
}
- if (m_target) {
- Update(m_target);
- } else {
- SDL_RenderPresent(m_renderer);
- }
-}
-
-void
-FrameBuf::Update(SDL_Texture *texture)
-{
- SDL_SetRenderTarget(m_renderer, NULL);
-
- SDL_SetRenderDrawColor(m_renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
- SDL_RenderClear(m_renderer);
-
- SDL_RenderTexture(m_renderer, texture, NULL, NULL);
SDL_RenderPresent(m_renderer);
-
- SDL_SetRenderTarget(m_renderer, m_target);
}
void
@@ -461,12 +433,10 @@ FrameBuf::Fade(void)
{
m_fadeStep = 1;
- if (!m_fadeTexture) {
- m_fadeTexture = SDL_CreateTexture(m_renderer, SDL_PIXELFORMAT_UNKNOWN, SDL_TEXTUREACCESS_TARGET, m_width, m_height);
- }
- SDL_SetRenderTarget(m_renderer, m_fadeTexture);
- SDL_RenderTexture(m_renderer, m_target, nullptr, nullptr);
- SDL_SetRenderTarget(m_renderer, m_target);
+ SDL_Surface *content = SDL_RenderReadPixels(m_renderer, NULL);
+ SDL_DestroyTexture(m_fadeTexture);
+ m_fadeTexture = SDL_CreateTextureFromSurface(m_renderer, content);
+ SDL_DestroySurface(content);
}
void
@@ -475,17 +445,27 @@ FrameBuf::FadeStep(void)
const int max = 32;
int v = m_faded ? m_fadeStep : max - m_fadeStep;
Uint8 value = (Uint8)(255 * v / max);
+ SDL_SetRenderDrawColor(m_renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
+ SDL_RenderClear(m_renderer);
SDL_SetTextureColorMod(m_fadeTexture, value, value, value);
- Update(m_fadeTexture);
+ SDL_RenderTexture(m_renderer, m_fadeTexture, NULL, NULL);
+ SDL_RenderPresent(m_renderer);
SDL_Delay(10);
++m_fadeStep;
if (m_fadeStep > max) {
- SDL_DestroyTexture(m_fadeTexture);
- m_fadeTexture = nullptr;
- m_faded = !m_faded;
+ FadeComplete();
}
-}
+}
+
+void
+FrameBuf::FadeComplete(void)
+{
+ SDL_SetRenderTarget(m_renderer, nullptr);
+ SDL_DestroyTexture(m_fadeTexture);
+ m_fadeTexture = nullptr;
+ m_faded = !m_faded;
+}
int
FrameBuf::ScreenDump(const char *prefix, int x, int y, int w, int h)
@@ -560,7 +540,14 @@ FrameBuf::LoadImage(const char *file)
SDL_Texture *
FrameBuf::LoadImage(SDL_Surface *surface)
{
- return SDL_CreateTextureFromSurface(m_renderer, surface);
+ SDL_Texture *texture;
+
+ texture = SDL_CreateTextureFromSurface(m_renderer, surface);
+ if (!texture) {
+ SetError("%s", SDL_GetError());
+ return NULL;
+ }
+ return(texture);
}
SDL_Texture *
diff --git a/screenlib/SDL_FrameBuf.h b/screenlib/SDL_FrameBuf.h
index f138997b..0fd87762 100644
--- a/screenlib/SDL_FrameBuf.h
+++ b/screenlib/SDL_FrameBuf.h
@@ -109,7 +109,6 @@ class FrameBuf : public ErrorBase {
void StretchBlit(const SDL_Rect *dstrect, SDL_Texture *src, const SDL_Rect *srcrect);
void Update(void);
- void Update(SDL_Texture *texture);
void FadeOut(void) {
if (!m_faded) {
Fade();
@@ -125,6 +124,7 @@ class FrameBuf : public ErrorBase {
return m_fadeTexture ? true : false;
}
void FadeStep(void);
+ void FadeComplete(void);
/* Drawing routines */
void Clear(int x, int y, int w, int h) {
@@ -194,7 +194,6 @@ class FrameBuf : public ErrorBase {
/* The current display */
SDL_Window *m_window = nullptr;
SDL_Renderer *m_renderer = nullptr;
- SDL_Texture *m_target = nullptr;
SDL_Texture *m_fadeTexture = nullptr;
int m_fadeStep = 0;
bool m_faded = false;
@@ -212,7 +211,7 @@ class FrameBuf : public ErrorBase {
r = (color >> 16) & 0xFF;
g = (color >> 8) & 0xFF;
b = (color >> 0) & 0xFF;
- SDL_SetRenderDrawColor(m_renderer, r, g, b, 0xFF);
+ SDL_SetRenderDrawColor(m_renderer, r, g, b, SDL_ALPHA_OPAQUE);
}
void OpenGamepad(SDL_JoystickID id);
diff --git a/screenlib/UIManager.cpp b/screenlib/UIManager.cpp
index 6d33c860..cd316477 100644
--- a/screenlib/UIManager.cpp
+++ b/screenlib/UIManager.cpp
@@ -278,19 +278,30 @@ UIManager::ShowPanel(UIPanel *panel)
void
UIManager::HidePanel(UIPanel *panel)
{
- if (panel && m_visible.remove(panel)) {
- panel->Hide();
-
+ if (panel && m_visible.find(panel)) {
if (m_panelTransition == PANEL_TRANSITION_FADE &&
- panel->IsFullscreen()) {
+ panel->IsFullscreen()) {
+ // Draw one last time so we have valid contents to fade
+ m_screen->Clear();
+ for (unsigned int i = 0; i < m_visible.length(); ++i) {
+ UIPanel* panel = m_visible[i];
+
+ for (int drawLevel = 0; drawLevel < NUM_DRAWLEVELS; ++drawLevel) {
+ panel->Draw((DRAWLEVEL)drawLevel);
+ }
+ }
m_screen->FadeOut();
}
+
+ panel->Hide();
+
if (!panel->IsCursorVisible()) {
m_screen->ShowCursor();
}
if (panel->IsCursorVisible()) {
m_screen->SetGamepadMouse(false);
}
+ m_visible.remove(panel);
#ifdef FAST_ITERATION
// This is useful for iteration, panels are reloaded
@@ -387,21 +398,21 @@ UIManager::Poll()
}
void
-UIManager::Draw(bool fullUpdate)
+UIManager::Draw(bool tick)
{
unsigned int i;
// Run the tick before we draw in case it changes drawing state
- for (i = 0; i < m_visible.length(); ++i) {
- UIPanel *panel = m_visible[i];
+ if (tick) {
+ for (i = 0; i < m_visible.length(); ++i) {
+ UIPanel* panel = m_visible[i];
- panel->Poll();
- panel->Tick();
+ panel->Poll();
+ panel->Tick();
+ }
}
- if (fullUpdate) {
- m_screen->Clear();
- }
+ m_screen->Clear();
for (i = 0; i < m_visible.length(); ++i) {
UIPanel *panel = m_visible[i];
@@ -409,11 +420,9 @@ UIManager::Draw(bool fullUpdate)
panel->Draw((DRAWLEVEL)drawLevel);
}
}
- if (fullUpdate) {
- m_screen->Update();
- if (m_panelTransition == PANEL_TRANSITION_FADE) {
- m_screen->FadeIn();
- }
+ m_screen->Update();
+ if (m_panelTransition == PANEL_TRANSITION_FADE) {
+ m_screen->FadeIn();
}
}
diff --git a/screenlib/UIManager.h b/screenlib/UIManager.h
index 1f428310..17148181 100644
--- a/screenlib/UIManager.h
+++ b/screenlib/UIManager.h
@@ -121,7 +121,7 @@ class UIManager : public UIArea, public UIFontInterface, public UIImageInterface
bool CheckCondition(const char *condition);
void Poll();
- void Draw(bool fullUpdate = true);
+ void Draw(bool tick = true);
bool HandleEvent(const SDL_Event &event);
virtual void OnRectChanged() {