From 8c314be70d342935d65c6385f9864591b84adaf7 Mon Sep 17 00:00:00 2001
From: Tim Felgentreff <timfelgentreff@gmail.com>
Date: Mon, 14 Mar 2016 23:50:01 +0100
Subject: [PATCH 1/3] account for viewport sizes and shaders in screenshot
 code, don't rely on std::vector internal organization

---
 src/include/shaders.h |  6 ++++++
 src/video/png.cpp     | 32 ++++++++++++++++++++++++++------
 2 files changed, 32 insertions(+), 6 deletions(-)

diff --git a/src/include/shaders.h b/src/include/shaders.h
index b10c8c654..5c6ec27c1 100644
--- a/src/include/shaders.h
+++ b/src/include/shaders.h
@@ -2,6 +2,12 @@
 #define __SHADERS_H__
 #ifdef USE_OPENGL
 #define MAX_SHADERS 5
+#ifndef __APPLE__
+extern PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebuffer;
+#else
+#define glBindFramebuffer glBindFramebufferEXT
+#endif
+extern GLuint fullscreenFramebuffer;
 extern unsigned ShaderIndex;
 extern void LoadShaders();
 extern bool LoadShaderExtensions();
diff --git a/src/video/png.cpp b/src/video/png.cpp
index 8b84e4f18..07ee7c874 100644
--- a/src/video/png.cpp
+++ b/src/video/png.cpp
@@ -318,7 +318,19 @@ void SaveScreenshotPNG(const char *name)
 	/* set up the output control if you are using standard C streams */
 	png_init_io(png_ptr, fp);
 
-	png_set_IHDR(png_ptr, info_ptr, Video.Width, Video.Height, 8,
+	int pngw, pngh;
+#if defined(USE_OPENGL) || defined(USE_GLES)
+	if (UseOpenGL) {
+		pngw = Video.ViewportWidth;
+		pngh = Video.ViewportHeight;
+	}
+	else
+#endif
+	{
+		pngw = Video.Width;
+		pngh = Video.Height;
+	}
+	png_set_IHDR(png_ptr, info_ptr, pngw, pngh, 8,
 				 PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
 				 PNG_FILTER_TYPE_DEFAULT);
 
@@ -328,15 +340,23 @@ void SaveScreenshotPNG(const char *name)
 
 #if defined(USE_OPENGL) || defined(USE_GLES)
 	if (UseOpenGL) {
-		std::vector<unsigned char> pixels;
-		pixels.resize(Video.Width * Video.Height * 3);
+		unsigned char* pixels = new unsigned char[Video.ViewportWidth * Video.ViewportHeight * 3];
+		if (GLShaderPipelineSupported) {
+			// switch to real display
+			glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
+		}
 #ifdef USE_OPENGL
 		glReadBuffer(GL_FRONT);
 #endif
-		glReadPixels(0, 0, Video.Width, Video.Height, GL_RGB, GL_UNSIGNED_BYTE, &pixels[0]);
-		for (int i = 0; i < Video.Height; ++i) {
-			png_write_row(png_ptr, &pixels[(Video.Height - 1 - i) * Video.Width * 3]);
+		glReadPixels(0, 0, Video.ViewportWidth, Video.ViewportHeight, GL_RGB, GL_UNSIGNED_BYTE, pixels);
+		if (GLShaderPipelineSupported) {
+			// switch back to framebuffer
+			glBindFramebuffer(GL_FRAMEBUFFER_EXT, fullscreenFramebuffer);
 		}
+		for (int i = 0; i < Video.Height; ++i) {
+			png_write_row(png_ptr, &pixels[(Video.ViewportHeight - 1 - i) * Video.ViewportWidth * 3]);
+		}
+		delete []pixels;
 	} else
 #endif
 	{

From 15b6eaa48facb77f5c86bca8057c6b0de6f5165f Mon Sep 17 00:00:00 2001
From: Tim Felgentreff <timfelgentreff@gmail.com>
Date: Tue, 15 Mar 2016 00:09:42 +0100
Subject: [PATCH 2/3] do proper error checking when testing if shaders are
 supported, so when the hardware won't accept the shader or the program (even
 though the opengl lib supports it), we don't get an upside down image any
 longer

---
 src/include/shaders.h |  2 +-
 src/ui/interface.cpp  |  1 +
 src/video/shaders.cpp | 37 ++++++++++++++++++++++++++++++++++---
 3 files changed, 36 insertions(+), 4 deletions(-)

diff --git a/src/include/shaders.h b/src/include/shaders.h
index 5c6ec27c1..6cc07a479 100644
--- a/src/include/shaders.h
+++ b/src/include/shaders.h
@@ -9,7 +9,7 @@ extern PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebuffer;
 #endif
 extern GLuint fullscreenFramebuffer;
 extern unsigned ShaderIndex;
-extern void LoadShaders();
+extern bool LoadShaders();
 extern bool LoadShaderExtensions();
 extern void SetupFramebuffer();
 extern void RenderFramebufferToScreen();
diff --git a/src/ui/interface.cpp b/src/ui/interface.cpp
index 7dcb49414..9e5639967 100644
--- a/src/ui/interface.cpp
+++ b/src/ui/interface.cpp
@@ -993,6 +993,7 @@ int HandleKeyModifiersDown(unsigned key, unsigned)
 			return 1;
 		case SDLK_SYSREQ:
 		case SDLK_PRINT:
+		case SDLK_F11:
 			Screenshot();
 			if (GameRunning) {
 				SetMessage("%s", _("Screenshot made."));
diff --git a/src/video/shaders.cpp b/src/video/shaders.cpp
index 8ccd02324..08f502e79 100644
--- a/src/video/shaders.cpp
+++ b/src/video/shaders.cpp
@@ -394,27 +394,59 @@ void printProgramInfoLog(GLuint obj, const char* prefix)
 
 unsigned ShaderIndex = 0;
 
-extern void LoadShaders() {
+extern bool LoadShaders() {
 	GLuint vs, fs;
+	GLint params;
 	fs = glCreateShader(GL_FRAGMENT_SHADER);
+	if (fs == 0) {
+	    return false;
+	}
 	glShaderSource(fs, 1, (const char**)&(fragment_shaders[ShaderIndex]), NULL);
 	glCompileShader(fs);
+	glGetShaderiv(fs, GL_COMPILE_STATUS, &params);
+	if (params == GL_FALSE) {
+		glDeleteShader(fs);
+		return false;
+	}
 	//printShaderInfoLog(fs, "Fragment Shader");
 	ShaderIndex = (ShaderIndex + 1) % MAX_SHADERS;
 	vs = glCreateShader(GL_VERTEX_SHADER);
+	if (fs == 0) {
+	    glDeleteShader(fs);
+	    return false;
+	}
 	glShaderSource(vs, 1, (const char**)&vertex_shader, NULL);
 	glCompileShader(vs);
+	glGetShaderiv(fs, GL_COMPILE_STATUS, &params);
+	if (params == GL_FALSE) {
+		glDeleteShader(fs);
+		glDeleteShader(vs);
+		return false;
+	}
 	//printShaderInfoLog(vs, "Vertex Shader");
 	if (glIsProgram(fullscreenShader)) {
 		glDeleteProgram(fullscreenShader);
 	}
 	fullscreenShader = glCreateProgram();
+	if (fullscreenShader == 0) {
+		glDeleteShader(fs);
+		glDeleteShader(vs);
+		return false;
+	}
 	glAttachShader(fullscreenShader, vs);
 	glAttachShader(fullscreenShader, fs);
 	glLinkProgram(fullscreenShader);
+	glGetProgramiv(fullscreenShader, GL_LINK_STATUS, &params);
+	if (params == GL_FALSE) {
+		glDeleteShader(fs);
+		glDeleteShader(vs);
+		glDeleteProgram(fullscreenShader);
+		return false;
+	}
 	glDeleteShader(fs);
 	glDeleteShader(vs);
 	//printProgramInfoLog(fullscreenShader, "Shader Program");
+	return true;
 }
 
 extern bool LoadShaderExtensions() {
@@ -449,8 +481,7 @@ extern bool LoadShaderExtensions() {
 	glDrawBuffers = (PFNGLDRAWBUFFERSPROC)(uintptr_t)SDL_GL_GetProcAddress("glDrawBuffers");
 	glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)(uintptr_t)SDL_GL_GetProcAddress("glCheckFramebufferStatus");
 	if (glCreateShader && glGenFramebuffers && glGetUniformLocation && glActiveTextureProc) {
-		LoadShaders();
-		return true;
+		return LoadShaders();
 	} else {
 		return false;
 	}

From 542fb43c38eea872efe2d04d5b8d2b3efa4e83bc Mon Sep 17 00:00:00 2001
From: Tim Felgentreff <timfelgentreff@gmail.com>
Date: Tue, 15 Mar 2016 00:12:19 +0100
Subject: [PATCH 3/3] revert unintentional change

---
 src/ui/interface.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/ui/interface.cpp b/src/ui/interface.cpp
index 9e5639967..7dcb49414 100644
--- a/src/ui/interface.cpp
+++ b/src/ui/interface.cpp
@@ -993,7 +993,6 @@ int HandleKeyModifiersDown(unsigned key, unsigned)
 			return 1;
 		case SDLK_SYSREQ:
 		case SDLK_PRINT:
-		case SDLK_F11:
 			Screenshot();
 			if (GameRunning) {
 				SetMessage("%s", _("Screenshot made."));