From 68a252c3dfdf1c93dfdf5d8a1b95074784fa6590 Mon Sep 17 00:00:00 2001 From: TheBrokenRail Date: Wed, 15 Sep 2021 19:12:03 -0400 Subject: [PATCH] Fix Crash When Taking Odd-Sized Screenshots --- VERSION | 2 +- docs/CHANGELOG.md | 3 ++ media-layer/core/src/screenshot.c | 25 ++++++++--- media-layer/include/GLES/gl.h | 2 + media-layer/proxy/src/GLESv1_CM.c | 71 +++++++++++++++++++++++++++---- 5 files changed, 88 insertions(+), 15 deletions(-) diff --git a/VERSION b/VERSION index b1b25a5ff..585940699 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.2.2 +2.2.3 diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 5682ed8f3..cdad6f1d7 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +**2.2.3** +* Fix Crash When Taking Odd-Sized Screenshots + **2.2.2** * Add More Missing Sound Events * Make Missing Sound Event Cause Warning Rather Than Crash diff --git a/media-layer/core/src/screenshot.c b/media-layer/core/src/screenshot.c index 22c6c3689..42f00d097 100644 --- a/media-layer/core/src/screenshot.c +++ b/media-layer/core/src/screenshot.c @@ -71,6 +71,16 @@ void media_take_screenshot(char *home) { // Get Line Size int line_size = width * 3; + { + // Handle Alignment + int alignment; + glGetIntegerv(GL_PACK_ALIGNMENT, &alignment); + // Round + int diff = line_size % alignment; + if (diff > 0) { + line_size = line_size + (alignment - diff); + } + } int size = height * line_size; // Read Pixels @@ -80,12 +90,15 @@ void media_take_screenshot(char *home) { // Handle Little Endian Systems #if __BYTE_ORDER == __LITTLE_ENDIAN // Swap Red And Blue - for (int i = 0; i < (size / 3); i++) { - int pixel = i * 3; - int red = pixels[pixel]; - int blue = pixels[pixel + 2]; - pixels[pixel] = blue; - pixels[pixel + 2] = red; + for (int j = 0; j < width; j++) { + for (int k = 0; k < height; k++) { + int pixel = (k * line_size) + (j * 3); + // Swap + int red = pixels[pixel]; + int blue = pixels[pixel + 2]; + pixels[pixel] = blue; + pixels[pixel + 2] = red; + } } #endif diff --git a/media-layer/include/GLES/gl.h b/media-layer/include/GLES/gl.h index 8918c1cf8..ba1d9fde4 100644 --- a/media-layer/include/GLES/gl.h +++ b/media-layer/include/GLES/gl.h @@ -14,6 +14,8 @@ extern "C" { #define GL_PROJECTION_MATRIX 0xba7 #define GL_VIEWPORT 0xba2 #define GL_DEPTH_TEST 0xb71 +#define GL_PACK_ALIGNMENT 0xd05 +#define GL_UNPACK_ALIGNMENT 0xcf5 #include #include diff --git a/media-layer/proxy/src/GLESv1_CM.c b/media-layer/proxy/src/GLESv1_CM.c index 988ff08a3..2eb0c6caa 100644 --- a/media-layer/proxy/src/GLESv1_CM.c +++ b/media-layer/proxy/src/GLESv1_CM.c @@ -334,7 +334,6 @@ static int get_texture_size(GLsizei width, GLsizei height, GLenum format, GLenum if (type == GL_UNSIGNED_BYTE) { switch (format) { case GL_RGB: { - PROXY_ERR("%s", "WIP"); multiplier = 3; break; } @@ -349,11 +348,29 @@ static int get_texture_size(GLsizei width, GLsizei height, GLenum format, GLenum } else { multiplier = sizeof (unsigned short); } - return width * height * multiplier; // This Should Have The Same Behavior On 32-Bit And 64-Bit Systems + int line_size = width * multiplier; + { + // Handle Alignment + int alignment; + glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment); + // Round + int diff = line_size % alignment; + if (diff > 0) { + line_size = line_size + (alignment - diff); + } + } + return line_size * height; // This Should Have The Same Behavior On 32-Bit And 64-Bit Systems } CALL(25, glTexImage2D, void, (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels)) { #if defined(MEDIA_LAYER_PROXY_SERVER) + // Get Texture Size + unsigned char is_null = pixels == NULL; + int size; + if (!is_null) { + size = get_texture_size(width, height, format, type); + } + // Lock Proxy start_proxy_call(); @@ -366,10 +383,8 @@ CALL(25, glTexImage2D, void, (GLenum target, GLint level, GLint internalformat, write_int((uint32_t) border); write_int((uint32_t) format); write_int((uint32_t) type); - unsigned char is_null = pixels == NULL; write_byte(is_null); if (!is_null) { - int size = get_texture_size(width, height, format, type); safe_write((void *) pixels, (size_t) size); } @@ -714,6 +729,13 @@ CALL(43, glColorMask, void, (GLboolean red, GLboolean green, GLboolean blue, GLb CALL(44, glTexSubImage2D, void, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels)) { #if defined(MEDIA_LAYER_PROXY_SERVER) + // Get Texture Size + unsigned char is_null = pixels == NULL; + int size; + if (!is_null) { + size = get_texture_size(width, height, format, type); + } + // Lock Proxy start_proxy_call(); @@ -726,10 +748,8 @@ CALL(44, glTexSubImage2D, void, (GLenum target, GLint level, GLint xoffset, GLin write_int((uint32_t) height); write_int((uint32_t) format); write_int((uint32_t) type); - unsigned char is_null = pixels == NULL; write_byte(is_null); if (!is_null) { - int size = get_texture_size(width, height, format, type); safe_write((void *) pixels, (size_t) size); } @@ -852,7 +872,7 @@ CALL(48, glGetFloatv, void, (GLenum pname, GLfloat *params)) { // Get Return Value int size = get_glGetFloatv_params_size(pname); - safe_read((void *) params, sizeof (float) * size); + safe_read((void *) params, sizeof (GLfloat) * size); // Release Proxy end_proxy_call(); @@ -863,7 +883,7 @@ CALL(48, glGetFloatv, void, (GLenum pname, GLfloat *params)) { // Run glGetFloatv(pname, params); // Return Value - safe_write((void *) params, sizeof (float) * size); + safe_write((void *) params, sizeof (GLfloat) * size); #endif } @@ -1076,3 +1096,38 @@ CALL(58, glIsEnabled, GLboolean, (GLenum cap)) { write_int((uint32_t) ret); #endif } + +static int get_glGetIntegerv_params_size(GLenum pname) { + switch (pname) { + case GL_UNPACK_ALIGNMENT: { + return 1; + } + default: { + PROXY_ERR("Inavlid glGetIntegerv Property: %u", pname); + } + } +} +CALL(61, glGetIntegerv, void, (GLenum pname, GLint *params)) { +#if defined(MEDIA_LAYER_PROXY_SERVER) + // Lock Proxy + start_proxy_call(); + + // Arguments + write_int((uint32_t) pname); + + // Get Return Value + int size = get_glGetIntegerv_params_size(pname); + safe_read((void *) params, sizeof (GLint) * size); + + // Release Proxy + end_proxy_call(); +#else + GLenum pname = (GLenum) read_int(); + int size = get_glGetIntegerv_params_size(pname); + GLint params[size]; + // Run + glGetIntegerv(pname, params); + // Return Value + safe_write((void *) params, sizeof (GLint) * size); +#endif +}