From 2478dfd35176d6bc70a6dba7fd4be6c7f9307525 Mon Sep 17 00:00:00 2001 From: Jesse Hall Date: Tue, 6 Mar 2012 13:43:50 -0800 Subject: [PATCH] Work around a y-invert bug on Macs w/ Intel GPU On Macs running OS X 10.6 and 10.7 with Intel HD Graphics 3000, some screens or parts of the screen are displayed upside down. The exact conditions/sequence that triggers this aren't known yet; I haven't been able to reproduce it in a standalone test. This also means I don't know whether it is a driver bug, or a bug in the OpenglRender or Translator code that just happens to work elsewhere. Thanks to zhiyuan.li@intel.com for a patch this change is based on. Change-Id: I04823773818d3b587a6951be48e70b03804b33d0 --- .../libs/Translator/GLES_CM/GLEScmContext.cpp | 7 +++++ .../libs/Translator/GLES_CM/GLEScmImp.cpp | 7 ++--- .../libs/Translator/GLES_V2/GLESv2Context.cpp | 8 ++++++ .../libs/Translator/GLES_V2/GLESv2Imp.cpp | 9 +++--- .../libs/Translator/GLcommon/GLEScontext.cpp | 5 ++++ .../Translator/include/GLcommon/GLEScontext.h | 2 ++ .../host/libs/libOpenglRender/ColorBuffer.cpp | 28 ++++++++++++++++--- .../host/libs/libOpenglRender/ColorBuffer.h | 3 +- 8 files changed, 55 insertions(+), 14 deletions(-) diff --git a/tools/emulator/opengl/host/libs/Translator/GLES_CM/GLEScmContext.cpp b/tools/emulator/opengl/host/libs/Translator/GLES_CM/GLEScmContext.cpp index ef60cdc97..abf461c9e 100644 --- a/tools/emulator/opengl/host/libs/Translator/GLES_CM/GLEScmContext.cpp +++ b/tools/emulator/opengl/host/libs/Translator/GLES_CM/GLEScmContext.cpp @@ -31,6 +31,13 @@ void GLEScmContext::init() { m_texCoords = new GLESpointer[s_glSupport.maxTexUnits]; m_map[GL_TEXTURE_COORD_ARRAY] = &m_texCoords[m_clientActiveTexture]; + const char* baseRenderer = (const char*)dispatcher().glGetString(GL_RENDERER); + size_t baseRendererLen = strlen(baseRenderer); + s_glRenderer.clear(); + s_glRenderer.reserve(19 + baseRendererLen); + s_glRenderer.append("OpenGL ES-CM 1.1 (", 18); + s_glRenderer.append(baseRenderer, baseRendererLen); + s_glRenderer.append(")", 1); } m_initialized = true; } diff --git a/tools/emulator/opengl/host/libs/Translator/GLES_CM/GLEScmImp.cpp b/tools/emulator/opengl/host/libs/Translator/GLES_CM/GLEScmImp.cpp index f1d380165..ae903776b 100644 --- a/tools/emulator/opengl/host/libs/Translator/GLES_CM/GLEScmImp.cpp +++ b/tools/emulator/opengl/host/libs/Translator/GLES_CM/GLEScmImp.cpp @@ -249,15 +249,14 @@ GL_API GLenum GL_APIENTRY glGetError(void) { GL_API const GLubyte * GL_APIENTRY glGetString( GLenum name) { GET_CTX_RET(NULL) - static GLubyte VENDOR[] = "Google"; - static GLubyte RENDERER[] = "OpenGL ES-CM 1.1"; - static GLubyte VERSION[] = "OpenGL ES-CM 1.1"; + static const GLubyte VENDOR[] = "Google"; + static const GLubyte VERSION[] = "OpenGL ES-CM 1.1"; switch(name) { case GL_VENDOR: return VENDOR; case GL_RENDERER: - return RENDERER; + return (const GLubyte*)ctx->getRendererString(); case GL_VERSION: return VERSION; case GL_EXTENSIONS: diff --git a/tools/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Context.cpp b/tools/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Context.cpp index 92f931902..73acb6173 100644 --- a/tools/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Context.cpp +++ b/tools/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Context.cpp @@ -27,6 +27,14 @@ void GLESv2Context::init() { m_map[i] = new GLESpointer(); } setAttribute0value(0.0, 0.0, 0.0, 1.0); + + const char* baseRenderer = (const char*)dispatcher().glGetString(GL_RENDERER); + size_t baseRendererLen = strlen(baseRenderer); + s_glRenderer.clear(); + s_glRenderer.reserve(16 + baseRendererLen); + s_glRenderer.append("OpenGL ES 2.0 (", 15); + s_glRenderer.append(baseRenderer, baseRendererLen); + s_glRenderer.append(")", 1); } m_initialized = true; } diff --git a/tools/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp b/tools/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp index 319930e92..2e746cf13 100644 --- a/tools/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp +++ b/tools/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp @@ -1317,15 +1317,14 @@ GL_APICALL void GL_APIENTRY glGetShaderSource(GLuint shader, GLsizei bufsize, G GL_APICALL const GLubyte* GL_APIENTRY glGetString(GLenum name){ GET_CTX_RET(NULL) - static GLubyte VENDOR[] = "Google"; - static GLubyte RENDERER[] = "OpenGL ES 2.0"; - static GLubyte VERSION[] = "OpenGL ES 2.0"; - static GLubyte SHADING[] = "OpenGL ES GLSL ES 1.0.17"; + static const GLubyte VENDOR[] = "Google"; + static const GLubyte VERSION[] = "OpenGL ES 2.0"; + static const GLubyte SHADING[] = "OpenGL ES GLSL ES 1.0.17"; switch(name) { case GL_VENDOR: return VENDOR; case GL_RENDERER: - return RENDERER; + return (const GLubyte*)ctx->getRendererString(); case GL_VERSION: return VERSION; case GL_SHADING_LANGUAGE_VERSION: diff --git a/tools/emulator/opengl/host/libs/Translator/GLcommon/GLEScontext.cpp b/tools/emulator/opengl/host/libs/Translator/GLcommon/GLEScontext.cpp index 90088f3f1..c21390355 100644 --- a/tools/emulator/opengl/host/libs/Translator/GLcommon/GLEScontext.cpp +++ b/tools/emulator/opengl/host/libs/Translator/GLcommon/GLEScontext.cpp @@ -71,6 +71,7 @@ void GLESConversionArrays::operator++(){ GLDispatch GLEScontext::s_glDispatch; android::Mutex GLEScontext::s_lock; std::string* GLEScontext::s_glExtensions= NULL; +std::string GLEScontext::s_glRenderer; GLSupport GLEScontext::s_glSupport; Version::Version():m_major(0), @@ -469,6 +470,10 @@ const char * GLEScontext::getExtensionString() { return ret; } +const char * GLEScontext::getRendererString() const { + return s_glRenderer.c_str(); +} + void GLEScontext::getGlobalLock() { s_lock.lock(); } diff --git a/tools/emulator/opengl/host/libs/Translator/include/GLcommon/GLEScontext.h b/tools/emulator/opengl/host/libs/Translator/include/GLcommon/GLEScontext.h index d266e3df6..59e367f44 100644 --- a/tools/emulator/opengl/host/libs/Translator/include/GLcommon/GLEScontext.h +++ b/tools/emulator/opengl/host/libs/Translator/include/GLcommon/GLEScontext.h @@ -131,6 +131,7 @@ public: bool setBufferData(GLenum target,GLsizeiptr size,const GLvoid* data,GLenum usage); bool setBufferSubData(GLenum target,GLintptr offset,GLsizeiptr size,const GLvoid* data); const char * getExtensionString(); + const char * getRendererString() const; void getGlobalLock(); void releaseGlobalLock(); virtual GLSupport* getCaps(){return &s_glSupport;}; @@ -173,6 +174,7 @@ protected: GLint m_unpackAlignment; ArraysMap m_map; static std::string* s_glExtensions; + static std::string s_glRenderer; static GLSupport s_glSupport; private: diff --git a/tools/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.cpp b/tools/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.cpp index 87e7a24a4..218f32b70 100644 --- a/tools/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.cpp +++ b/tools/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.cpp @@ -113,8 +113,21 @@ ColorBuffer::ColorBuffer() : m_tex(0), m_eglImage(NULL), m_fbo(0), - m_internalFormat(0) + m_internalFormat(0), + m_warYInvertBug(false) { +#if __APPLE__ + // On Macs running OS X 10.6 and 10.7 with Intel HD Graphics 3000, some + // screens or parts of the screen are displayed upside down. The exact + // conditions/sequence that triggers this aren't known yet; I haven't + // been able to reproduce it in a standalone test. This way of enabling the + // workaround will break if it is a driver bug (rather than a bug in this + // code which works by accident elsewhere) and Apple/Intel release a fix for + // it. Running a standalone test to detect the problem at runtime would be + // more robust. + if (strstr((const char*)s_gl.glGetString(GL_RENDERER), "Intel HD Graphics 3000")) + m_warYInvertBug = true; +#endif } ColorBuffer::~ColorBuffer() @@ -199,7 +212,7 @@ bool ColorBuffer::blitFromCurrentReadBuffer() s_gl.glBindTexture(GL_TEXTURE_2D, m_blitTex); s_gl.glEnable(GL_TEXTURE_2D); s_gl.glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - drawTexQuad(); // this will render the texture flipped + drawTexQuad(!m_warYInvertBug); // unbind the fbo s_gl.glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); @@ -299,12 +312,12 @@ bool ColorBuffer::post() s_gl.glBindTexture(GL_TEXTURE_2D, m_tex); s_gl.glEnable(GL_TEXTURE_2D); s_gl.glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - drawTexQuad(); + drawTexQuad(true); return true; } -void ColorBuffer::drawTexQuad() +void ColorBuffer::drawTexQuad(bool flipy) { GLfloat verts[] = { -1.0f, -1.0f, 0.0f, -1.0f, +1.0f, 0.0f, @@ -316,6 +329,13 @@ void ColorBuffer::drawTexQuad() 1.0f, 1.0f, 1.0f, 0.0f }; + if (!flipy) { + for (int i = 0; i < 4; i++) { + // swap 0.0/1.0 in second element of each tcoord vector + tcoords[2*i + 1] = tcoords[2*i + 1] == 0.0f ? 1.0f : 0.0f; + } + } + s_gl.glClientActiveTexture(GL_TEXTURE0); s_gl.glEnableClientState(GL_TEXTURE_COORD_ARRAY); s_gl.glTexCoordPointer(2, GL_FLOAT, 0, tcoords); diff --git a/tools/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.h b/tools/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.h index 16d1ee989..4a2c6b446 100644 --- a/tools/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.h +++ b/tools/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.h @@ -40,7 +40,7 @@ public: private: ColorBuffer(); - void drawTexQuad(); + void drawTexQuad(bool flipy); bool bind_fbo(); // binds a fbo which have this texture as render target private: @@ -52,6 +52,7 @@ private: GLuint m_height; GLuint m_fbo; GLenum m_internalFormat; + bool m_warYInvertBug; }; typedef SmartPtr ColorBufferPtr;