Maelstrom: SDL can now take care of mapping from a logical resolution to the display resolution. We still use high res assets if they...

https://github.com/libsdl-org/Maelstrom/commit/d14c7602542cd7a563998d349fa999340990a7d6

From d14c7602542cd7a563998d349fa999340990a7d6 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Mon, 1 Oct 2012 23:15:40 -0700
Subject: [PATCH] SDL can now take care of mapping from a logical resolution to
 the display resolution.  We still use high res assets if they are available.

---
 game/init.cpp              | 17 +++++++++
 screenlib/SDL_FrameBuf.cpp | 78 +++++++++++++-------------------------
 screenlib/SDL_FrameBuf.h   | 21 +++-------
 screenlib/UIManager.cpp    | 15 +++-----
 4 files changed, 56 insertions(+), 75 deletions(-)

diff --git a/game/init.cpp b/game/init.cpp
index d25130c9..efd06636 100644
--- a/game/init.cpp
+++ b/game/init.cpp
@@ -158,6 +158,7 @@ static bool InitResolutions(int &w, int &h)
 		}
 	}
 
+#if 0 // We don't need this now that we're guaranteed our logical resolution
 	// Look for the best mode in two passes, first check to see if any of
 	// our supported modes are available, and if not just grab the first mode
 	// that's bigger than any of our supported modes and stretch to that.
@@ -184,6 +185,11 @@ static bool InitResolutions(int &w, int &h)
 
 	error("Couldn't find any supported resolutions\n");
 	return false;
+#else
+	w = GAME_WIDTH;
+	h = GAME_HEIGHT;
+	return true;
+#endif
 }
 
 /* ----------------------------------------------------------------- */
@@ -868,6 +874,7 @@ int DoInitializations(Uint32 window_flags, Uint32 render_flags)
 	ui = new MaelstromUI(screen, prefs);
 
 	/* Set up for the resolution we actually got */
+#if 0 // We don't need this now that we're guaranteed our logical resolution
 	gResolutionIndex = FindResolution(screen->Width(), screen->Height());
 
 	const Resolution &resolution = gResolutions[gResolutionIndex];
@@ -875,6 +882,16 @@ int DoInitializations(Uint32 window_flags, Uint32 render_flags)
 	gScrnRect.y = (screen->Height() - resolution.h) / 2;
 	gScrnRect.w = resolution.w;
 	gScrnRect.h = resolution.h;
+#else
+	int display_w, display_h;
+	screen->GetDisplaySize(display_w, display_h);
+	gResolutionIndex = FindResolution(display_w, display_h);
+
+	gScrnRect.x = 0;
+	gScrnRect.y = 0;
+	gScrnRect.w = screen->Width();
+	gScrnRect.h = screen->Height();
+#endif
 
 	SDL_Rect clipRect;
 	clipRect.x = (SPRITES_WIDTH << SPRITE_PRECISION);
diff --git a/screenlib/SDL_FrameBuf.cpp b/screenlib/SDL_FrameBuf.cpp
index 71939580..9e6b61a5 100644
--- a/screenlib/SDL_FrameBuf.cpp
+++ b/screenlib/SDL_FrameBuf.cpp
@@ -37,14 +37,20 @@ FrameBuf:: FrameBuf() : ErrorBase()
 	/* Initialize various variables to null state */
 	window = NULL;
 	renderer = NULL;
-	texture = NULL;
 	faded = 0;
+	resizable = false;
 }
 
 int
 FrameBuf:: Init(int width, int height, Uint32 window_flags, Uint32 render_flags,
 		SDL_Surface *icon)
 {
+	if (window_flags & SDL_WINDOW_RESIZABLE) {
+		resizable = true;
+	} else {
+		resizable = false;
+	}
+
 	window = SDL_CreateWindow(NULL, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, window_flags);
 	if (!window) {
 		SetError("Couldn't create %dx%d window: %s", 
@@ -66,38 +72,20 @@ FrameBuf:: Init(int width, int height, Uint32 window_flags, Uint32 render_flags,
 	}
 
 	/* Set the output area */
-	int w, h;
-	SDL_GetWindowSize(window, &w, &h);
-
-	if ( (window_flags & SDL_WINDOW_RESIZABLE) || (w == width && h == height) ) {
-		UpdateWindowSize(w, h);
+	int w = width;
+	int h = height;
+	if (Resizable()) {
+		SDL_GetWindowSize(window, &w, &h);
 	} else {
-		// The application isn't resizable but the window isn't what we
-		// expected, so we'll render to a texture of the expected size
-		// and scale input coordinates accordingly
-
-		texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_TARGET, width, height);
-		if (!texture) {
-			SetError("Couldn't create target texture: %s", SDL_GetError());
-			return(-1);
-		}
-
-		if (SDL_SetRenderTarget(renderer, texture) < 0) {
-			SetError("Couldn't set render target: %s", SDL_GetError());
-			return(-1);
-		}
-
-		UpdateWindowSize(width, height);
+		SDL_RenderSetLogicalSize(renderer, width, height);
 	}
+	UpdateWindowSize(w, h);
 
 	return(0);
 }
 
 FrameBuf:: ~FrameBuf()
 {
-	if (texture) {
-		SDL_DestroyTexture(texture);
-	}
 	if (renderer) {
 		SDL_DestroyRenderer(renderer);
 	}
@@ -112,26 +100,19 @@ FrameBuf::ProcessEvent(SDL_Event *event)
 	switch (event->type) {
 	case SDL_WINDOWEVENT:
 		if (event->window.event == SDL_WINDOWEVENT_RESIZED) {
-			SDL_Window *window = SDL_GetWindowFromID(event->window.windowID);
 			int w, h;
+			SDL_Window *window = SDL_GetWindowFromID(event->window.windowID);
 
-			SDL_GetWindowSize(window, &w, &h);
+			w = Width();
+			h = Height();
+			if (Resizable()) {
+				// We'll accept this window size change
+				SDL_GetWindowSize(window, &w, &h);
+				SDL_RenderSetViewport(renderer, NULL);
+			}
 			UpdateWindowSize(w, h);
 		}
 		break;
-	case SDL_MOUSEMOTION:
-		event->motion.x -= output.x;
-		event->motion.y -= output.y;
-		event->motion.x = (event->motion.x * rect.w) / output.w;
-		event->motion.y = (event->motion.y * rect.h) / output.h;
-		break;
-	case SDL_MOUSEBUTTONDOWN:
-	case SDL_MOUSEBUTTONUP:
-		event->button.x -= output.x;
-		event->button.y -= output.y;
-		event->button.x = (event->button.x * rect.w) / output.w;
-		event->button.y = (event->button.y * rect.h) / output.h;
-		break;
 	}
 }
 
@@ -178,6 +159,12 @@ FrameBuf::DisableTextInput()
 	SDL_StopTextInput();
 }
 
+void
+FrameBuf:: GetDisplaySize(int &w, int &h)
+{
+	SDL_GetWindowSize(window, &w, &h);
+}
+
 void
 FrameBuf:: QueueBlit(int dstx, int dsty, SDL_Texture *src,
 			int srcx, int srcy, int w, int h, clipval do_clip)
@@ -216,18 +203,7 @@ FrameBuf:: StretchBlit(const SDL_Rect *dstrect, SDL_Texture *src, const SDL_Rect
 void
 FrameBuf:: Update(void)
 {
-	/* Copy from our render texture to the screen and show it! */
-	if (texture) {
-		SDL_SetRenderTarget(renderer, NULL);
-		SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
-		SDL_RenderClear(renderer);
-		SDL_RenderCopy(renderer, texture, NULL, &output);
-	}
 	SDL_RenderPresent(renderer);
-
-	if (texture) {
-		SDL_SetRenderTarget(renderer, texture);
-	}
 }
 
 void
diff --git a/screenlib/SDL_FrameBuf.h b/screenlib/SDL_FrameBuf.h
index 7fccd5db..e8617fb0 100644
--- a/screenlib/SDL_FrameBuf.h
+++ b/screenlib/SDL_FrameBuf.h
@@ -104,6 +104,10 @@ class FrameBuf : public ErrorBase {
 	int Height() const {
 		return rect.h;
 	}
+	bool Resizable() const {
+		return resizable;
+	}
+	void GetDisplaySize(int &w, int &h);
 
 	/* Blit and update routines */
 	void QueueBlit(int dstx, int dsty, SDL_Texture *src,
@@ -208,32 +212,19 @@ class FrameBuf : public ErrorBase {
 	/* The current display */
 	SDL_Window *window;
 	SDL_Renderer *renderer;
-	SDL_Texture *texture;
 	int faded;
 	SDL_Rect rect;
 	SDL_Rect clip;
 	SDL_Rect output;
+	bool resizable;
 
 	void UpdateWindowSize(int width, int height) {
-		int w, h;
-		SDL_Rect viewport;
-
-		SDL_GetWindowSize(window, &w, &h);
-		output.w = w;
-		output.h = (height * w)/width;
-		output.x = (w - output.w) / 2;
-		output.y = (h - output.h) / 2;
-
 		clip.x = rect.x = 0;
 		clip.y = rect.y = 0;
 		clip.w = rect.w = width;
 		clip.h = rect.h = height;
 
-		viewport.x = 0;
-		viewport.y = 0;
-		viewport.w = w;
-		viewport.h = h;
-		SDL_RenderSetViewport(renderer, &viewport);
+		SDL_RenderGetViewport(renderer, &output);
 	}
 	void UpdateDrawColor(Uint32 color) {
 		Uint8 r, g, b;
diff --git a/screenlib/UIManager.cpp b/screenlib/UIManager.cpp
index bf9ec5cb..32702953 100644
--- a/screenlib/UIManager.cpp
+++ b/screenlib/UIManager.cpp
@@ -247,22 +247,19 @@ bool
 UIManager::HandleEvent(const SDL_Event &event)
 {
 	if (event.type == SDL_WINDOWEVENT &&
-	    event.window.event == SDL_WINDOWEVENT_RESIZED) {
-		SDL_Window *window = SDL_GetWindowFromID(event.window.windowID);
-		int w, h;
+	    event.window.event == SDL_WINDOWEVENT_RESIZED &&
+	    m_screen->Resizable()) {
 		SDL_Rect clip;
 
-		SDL_GetWindowSize(window, &w, &h);
-
 		// Reset the clip rectangle
 		clip.x = 0;
 		clip.y = 0;
-		clip.w = w;
-		clip.h = h;
+		clip.w = m_screen->Width();
+		clip.h = m_screen->Height();
 		m_screen->ClipBlit(&clip);
-		
+
 		// Resize to match window size
-		SetSize(w, h);
+		SetSize(m_screen->Width(), m_screen->Height());
 	}
 
 	for (unsigned i = m_visible.length(); i--; ) {