Fix Crash When Taking Odd-Sized Screenshots

This commit is contained in:
TheBrokenRail 2021-09-15 19:12:03 -04:00
parent 866ebfe159
commit 68a252c3df
5 changed files with 88 additions and 15 deletions

View File

@ -1 +1 @@
2.2.2 2.2.3

View File

@ -1,5 +1,8 @@
# Changelog # Changelog
**2.2.3**
* Fix Crash When Taking Odd-Sized Screenshots
**2.2.2** **2.2.2**
* Add More Missing Sound Events * Add More Missing Sound Events
* Make Missing Sound Event Cause Warning Rather Than Crash * Make Missing Sound Event Cause Warning Rather Than Crash

View File

@ -71,6 +71,16 @@ void media_take_screenshot(char *home) {
// Get Line Size // Get Line Size
int line_size = width * 3; 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; int size = height * line_size;
// Read Pixels // Read Pixels
@ -80,12 +90,15 @@ void media_take_screenshot(char *home) {
// Handle Little Endian Systems // Handle Little Endian Systems
#if __BYTE_ORDER == __LITTLE_ENDIAN #if __BYTE_ORDER == __LITTLE_ENDIAN
// Swap Red And Blue // Swap Red And Blue
for (int i = 0; i < (size / 3); i++) { for (int j = 0; j < width; j++) {
int pixel = i * 3; for (int k = 0; k < height; k++) {
int red = pixels[pixel]; int pixel = (k * line_size) + (j * 3);
int blue = pixels[pixel + 2]; // Swap
pixels[pixel] = blue; int red = pixels[pixel];
pixels[pixel + 2] = red; int blue = pixels[pixel + 2];
pixels[pixel] = blue;
pixels[pixel + 2] = red;
}
} }
#endif #endif

View File

@ -14,6 +14,8 @@ extern "C" {
#define GL_PROJECTION_MATRIX 0xba7 #define GL_PROJECTION_MATRIX 0xba7
#define GL_VIEWPORT 0xba2 #define GL_VIEWPORT 0xba2
#define GL_DEPTH_TEST 0xb71 #define GL_DEPTH_TEST 0xb71
#define GL_PACK_ALIGNMENT 0xd05
#define GL_UNPACK_ALIGNMENT 0xcf5
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>

View File

@ -334,7 +334,6 @@ static int get_texture_size(GLsizei width, GLsizei height, GLenum format, GLenum
if (type == GL_UNSIGNED_BYTE) { if (type == GL_UNSIGNED_BYTE) {
switch (format) { switch (format) {
case GL_RGB: { case GL_RGB: {
PROXY_ERR("%s", "WIP");
multiplier = 3; multiplier = 3;
break; break;
} }
@ -349,11 +348,29 @@ static int get_texture_size(GLsizei width, GLsizei height, GLenum format, GLenum
} else { } else {
multiplier = sizeof (unsigned short); 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)) { 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) #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 // Lock Proxy
start_proxy_call(); 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) border);
write_int((uint32_t) format); write_int((uint32_t) format);
write_int((uint32_t) type); write_int((uint32_t) type);
unsigned char is_null = pixels == NULL;
write_byte(is_null); write_byte(is_null);
if (!is_null) { if (!is_null) {
int size = get_texture_size(width, height, format, type);
safe_write((void *) pixels, (size_t) size); 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)) { 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) #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 // Lock Proxy
start_proxy_call(); 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) height);
write_int((uint32_t) format); write_int((uint32_t) format);
write_int((uint32_t) type); write_int((uint32_t) type);
unsigned char is_null = pixels == NULL;
write_byte(is_null); write_byte(is_null);
if (!is_null) { if (!is_null) {
int size = get_texture_size(width, height, format, type);
safe_write((void *) pixels, (size_t) size); safe_write((void *) pixels, (size_t) size);
} }
@ -852,7 +872,7 @@ CALL(48, glGetFloatv, void, (GLenum pname, GLfloat *params)) {
// Get Return Value // Get Return Value
int size = get_glGetFloatv_params_size(pname); int size = get_glGetFloatv_params_size(pname);
safe_read((void *) params, sizeof (float) * size); safe_read((void *) params, sizeof (GLfloat) * size);
// Release Proxy // Release Proxy
end_proxy_call(); end_proxy_call();
@ -863,7 +883,7 @@ CALL(48, glGetFloatv, void, (GLenum pname, GLfloat *params)) {
// Run // Run
glGetFloatv(pname, params); glGetFloatv(pname, params);
// Return Value // Return Value
safe_write((void *) params, sizeof (float) * size); safe_write((void *) params, sizeof (GLfloat) * size);
#endif #endif
} }
@ -1076,3 +1096,38 @@ CALL(58, glIsEnabled, GLboolean, (GLenum cap)) {
write_int((uint32_t) ret); write_int((uint32_t) ret);
#endif #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
}