From f7acde244cbe5100faab749b1465b001d2c4ea11 Mon Sep 17 00:00:00 2001 From: Aaron Culliney Date: Wed, 30 Sep 2015 21:55:07 -0700 Subject: [PATCH] Work around broken Adreno 200 GPU - Rework checks to compare with POSIX Regexs ... which themselves appear broken with android-10 NDK ... sigh --- src/video/glalert.c | 1 + src/video/glhudmodel.c | 2 +- src/video/gltouchjoy.c | 2 + src/video/gltouchkbd.c | 1 + src/video/gltouchmenu.c | 1 + src/video/glvideo.c | 92 ++++++++++++++++++++++++++++++++++++----- src/video/glvideo.h | 21 +++++++++- 7 files changed, 107 insertions(+), 13 deletions(-) diff --git a/src/video/glalert.c b/src/video/glalert.c index 07df9dd8..2b06c18f 100644 --- a/src/video/glalert.c +++ b/src/video/glalert.c @@ -182,6 +182,7 @@ static void alert_render(void) { glBindTexture(GL_TEXTURE_2D, messageModel->textureName); if (messageModel->texDirty) { messageModel->texDirty = false; + _HACKAROUND_GLTEXIMAGE2D_PRE(TEXTURE_ACTIVE_MESSAGE, messageModel->textureName); glTexImage2D(GL_TEXTURE_2D, /*level*/0, TEX_FORMAT_INTERNAL, messageModel->texWidth, messageModel->texHeight, /*border*/0, TEX_FORMAT, TEX_TYPE, messageModel->texPixels); } glUniform1i(texSamplerLoc, TEXTURE_ID_MESSAGE); diff --git a/src/video/glhudmodel.c b/src/video/glhudmodel.c index 80f0e761..9b0faab6 100644 --- a/src/video/glhudmodel.c +++ b/src/video/glhudmodel.c @@ -140,7 +140,7 @@ void glhud_renderDefault(GLModel *parent) { #endif // Draw the object - GL_DRAW_CALL_PRE(); + _HACKAROUND_GLDRAW_PRE(); glDrawElements(parent->primType, parent->numElements, parent->elementType, 0); GL_ERRLOG("glhudparent render"); } diff --git a/src/video/gltouchjoy.c b/src/video/gltouchjoy.c index 54271d5d..c5cc24d8 100644 --- a/src/video/gltouchjoy.c +++ b/src/video/gltouchjoy.c @@ -294,6 +294,7 @@ static void gltouchjoy_render(void) { glBindTexture(GL_TEXTURE_2D, axes.model->textureName); if (axes.model->texDirty) { axes.model->texDirty = false; + _HACKAROUND_GLTEXIMAGE2D_PRE(TEXTURE_ACTIVE_TOUCHJOY_AXIS, axes.model->textureName); glTexImage2D(GL_TEXTURE_2D, /*level*/0, TEX_FORMAT_INTERNAL, axes.model->texWidth, axes.model->texHeight, /*border*/0, TEX_FORMAT, TEX_TYPE, axes.model->texPixels); } if (axes.modelDirty) { @@ -315,6 +316,7 @@ static void gltouchjoy_render(void) { glBindTexture(GL_TEXTURE_2D, buttons.model->textureName); if (buttons.model->texDirty) { buttons.model->texDirty = false; + _HACKAROUND_GLTEXIMAGE2D_PRE(TEXTURE_ACTIVE_TOUCHJOY_BUTTON, buttons.model->textureName); glTexImage2D(GL_TEXTURE_2D, /*level*/0, TEX_FORMAT_INTERNAL, buttons.model->texWidth, buttons.model->texHeight, /*border*/0, TEX_FORMAT, TEX_TYPE, buttons.model->texPixels); } if (buttons.modelDirty) { diff --git a/src/video/gltouchkbd.c b/src/video/gltouchkbd.c index 992381fc..41b8d474 100644 --- a/src/video/gltouchkbd.c +++ b/src/video/gltouchkbd.c @@ -524,6 +524,7 @@ static void gltouchkbd_render(void) { glBindTexture(GL_TEXTURE_2D, kbd.model->textureName); if (kbd.model->texDirty) { kbd.model->texDirty = false; + _HACKAROUND_GLTEXIMAGE2D_PRE(TEXTURE_ACTIVE_TOUCHKBD, kbd.model->textureName); glTexImage2D(GL_TEXTURE_2D, /*level*/0, TEX_FORMAT_INTERNAL, kbd.model->texWidth, kbd.model->texHeight, /*border*/0, TEX_FORMAT, TEX_TYPE, kbd.model->texPixels); } if (kbd.modelDirty) { diff --git a/src/video/gltouchmenu.c b/src/video/gltouchmenu.c index 7adba21d..717fcb60 100644 --- a/src/video/gltouchmenu.c +++ b/src/video/gltouchmenu.c @@ -430,6 +430,7 @@ static void gltouchmenu_render(void) { glBindTexture(GL_TEXTURE_2D, menu.model->textureName); if (menu.model->texDirty) { menu.model->texDirty = false; + _HACKAROUND_GLTEXIMAGE2D_PRE(TEXTURE_ACTIVE_TOUCHMENU, menu.model->textureName); glTexImage2D(GL_TEXTURE_2D, /*level*/0, TEX_FORMAT_INTERNAL, menu.model->texWidth, menu.model->texHeight, /*border*/0, TEX_FORMAT, TEX_TYPE, menu.model->texPixels); } glUniform1i(texSamplerLoc, TEXTURE_ID_TOUCHMENU); diff --git a/src/video/glvideo.c b/src/video/glvideo.c index 1730d529..f10e6c80 100644 --- a/src/video/glvideo.c +++ b/src/video/glvideo.c @@ -16,6 +16,8 @@ #include "video/glinput.h" #include "video/glnode.h" +#include + bool safe_to_do_opengl_logging = false; bool renderer_shutting_down = false; @@ -35,7 +37,9 @@ static int adjustedHeight = 0; GLint texSamplerLoc = UNINITIALIZED_GL; GLint alphaValue = UNINITIALIZED_GL; GLuint mainShaderProgram = UNINITIALIZED_GL; + bool hackAroundBrokenAdreno200 = false; +bool hackAroundBrokenAdreno205 = false; static GLint uniformMVPIdx = UNINITIALIZED_GL; static GLenum crtElementType = UNINITIALIZED_GL; @@ -496,24 +500,89 @@ static demoSource *_create_shader_source(const char *fileName) { static void gldriver_render(void); -static void gldriver_init_common(void) { +static void _gldriver_setup_hackarounds(void) { + const char *vendor = (const char *)glGetString(GL_VENDOR); const char *renderer = (const char *)glGetString(GL_RENDERER); const char *version = (const char *)glGetString(GL_VERSION); if (vendor && renderer && version) { - LOG("GL_VENDOR:%s GL_RENDERER:%s GL_VERSION:%s", vendor, renderer, version); + LOG("GL_VENDOR:[%s] GL_RENDERER:[%s] GL_VERSION:[%s]", vendor, renderer, version); } else { - RELEASE_LOG("One or more of GL_VENDOR, GL_RENDERER, and GL_VERSION is NULL ... possibly about to crash ..."); + RELEASE_LOG("One or more of GL_VENDOR, GL_RENDERER, and GL_VERSION is NULL ... this is bad ..."); + return; } - if (vendor && strcasestr(vendor, "qualcomm")) { - if (renderer && strcasestr(renderer, "adreno")) { - if (strcasestr(renderer, "200")) { - LOG("HACKING AROUND BROKEN ADRENO 200"); - hackAroundBrokenAdreno200 = true; - } + regex_t qualcommRegex = { 0 }; + regex_t adrenoRegex = { 0 }; + regex_t twoHundredRegex = { 0 }; + regex_t twoHundredFiveRegex = { 0 }; + + do { + // As if we didn't have enough problems with Android ... Bionic's POSIX Regex support for android-10 appears + // very basic ... we can't match the word-boundary atomics \> \< \b ... sigh ... hopefully by the time there is + // an Adreno 2000 we can remove these hackarounds ;-) + + int err = regcomp(&qualcommRegex, "qualcomm", REG_ICASE|REG_NOSUB|REG_EXTENDED); + if (err) { + LOG("Cannot compile regex : %d", err); + break; } - } + int nomatch = regexec(&qualcommRegex, vendor, /*nmatch:*/0, /*pmatch:*/NULL, /*eflags:*/0); + if (nomatch) { + LOG("NO MATCH QUALCOMM >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); + break; + } + + err = regcomp(&adrenoRegex, "adreno", REG_ICASE|REG_NOSUB|REG_EXTENDED); + if (err) { + LOG("Cannot compile regex : %d", err); + break; + } + nomatch = regexec(&adrenoRegex, renderer, /*nmatch:*/0, /*pmatch:*/NULL, /*eflags:*/0); + if (nomatch) { + LOG("NO MATCH ADRENO >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); + break; + } + + err = regcomp(&twoHundredRegex, "200", REG_ICASE|REG_NOSUB|REG_EXTENDED); + if (err) { + LOG("Cannot compile regex : %d", err); + break; + } + err = regcomp(&twoHundredFiveRegex, "205", REG_ICASE|REG_NOSUB|REG_EXTENDED); + if (err) { + LOG("Cannot compile regex : %d", err); + break; + } + + int found200 = !regexec(&twoHundredRegex, renderer, /*nmatch:*/0, /*pmatch:*/NULL, /*eflags:*/0); + int found205 = !regexec(&twoHundredFiveRegex, renderer, /*nmatch:*/0, /*pmatch:*/NULL, /*eflags:*/0); + if (found200) { + LOG("HACKING AROUND BROKEN ADRENO 200"); + hackAroundBrokenAdreno200 = true; + break; + } + if (found205) { + LOG("HACKING AROUND BROKEN ADRENO 205"); + hackAroundBrokenAdreno200 = true; + hackAroundBrokenAdreno205 = true; + break; + } + } while (0); + + regfree(&qualcommRegex); + regfree(&adrenoRegex); + regfree(&twoHundredRegex); + regfree(&twoHundredFiveRegex); +} + +static void gldriver_init_common(void) { + + _gldriver_setup_hackarounds(); + + GLint value = UNINITIALIZED_GL; + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value); + LOG("GL_MAX_TEXTURE_SIZE:%d", value); renderer_shutting_down = false; @@ -721,6 +790,7 @@ static void gldriver_render(void) { glBindTexture(GL_TEXTURE_2D, a2TextureName); glUniform1i(texSamplerLoc, TEXTURE_ID_FRAMEBUFFER); if (wasDirty) { + _HACKAROUND_GLTEXIMAGE2D_PRE(TEXTURE_ACTIVE_FRAMEBUFFER, a2TextureName); glTexImage2D(GL_TEXTURE_2D, /*level*/0, TEX_FORMAT_INTERNAL, SCANWIDTH, SCANHEIGHT, /*border*/0, TEX_FORMAT, TEX_TYPE, (GLvoid *)&pixels[0]); } @@ -764,7 +834,7 @@ static void gldriver_render(void) { //glCullFace(GL_BACK); // Draw the CRT object and others - GL_DRAW_CALL_PRE(); + _HACKAROUND_GLDRAW_PRE(); glDrawElements(GL_TRIANGLES, crtNumElements, crtElementType, 0); // Render HUD nodes diff --git a/src/video/glvideo.h b/src/video/glvideo.h index 0e7d8f65..58d909cb 100644 --- a/src/video/glvideo.h +++ b/src/video/glvideo.h @@ -50,7 +50,8 @@ extern GLuint mainShaderProgram; // http://stackoverflow.com/questions/13676070/how-to-properly-mix-drawing-calls-and-changes-of-a-sampler-value-with-a-single-s // https://developer.qualcomm.com/forum/qdevnet-forums/mobile-gaming-graphics-optimization-adreno/8896 extern bool hackAroundBrokenAdreno200; -#define GL_DRAW_CALL_PRE() \ +extern bool hackAroundBrokenAdreno205; +#define _HACKAROUND_GLDRAW_PRE() \ ({ \ if (hackAroundBrokenAdreno200) { \ glUseProgram(0); \ @@ -58,5 +59,23 @@ extern bool hackAroundBrokenAdreno200; } \ }) +#define _HACKAROUND_GLTEXIMAGE2D_PRE(ACTIVE, NAME) \ + ({ \ + if (hackAroundBrokenAdreno205) { \ + /* Adreno 205 driver (HTC Desire) is even more broken than the 200! It appears that we must delete and recreate textures every time we upload new pixels! */ \ + glBindTexture(GL_TEXTURE_2D, 0); \ + glDeleteTextures(1, &(NAME)); \ + glGenTextures(1, &(NAME)); \ + glActiveTexture((ACTIVE)); \ + glBindTexture(GL_TEXTURE_2D, (NAME)); \ + /* HACK NOTE : these should match what is (currently hardcoded) in modelUtil.c */ \ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); \ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); \ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); \ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); \ + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); \ + } \ + }) + #endif