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
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 ef60cdc..abf461c 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 @@
         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 f1d3801..ae90377 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 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 92f9319..73acb61 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 @@
             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 319930e..2e746cf 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 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 90088f3..c213903 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 @@
 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 @@
     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 d266e3d..59e367f 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 @@
     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 @@
     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 87e7a24..218f32b 100644
--- a/tools/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.cpp
+++ b/tools/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.cpp
@@ -113,8 +113,21 @@
     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 @@
             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 @@
     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 @@
                            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 16d1ee9..4a2c6b4 100644
--- a/tools/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.h
+++ b/tools/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.h
@@ -40,7 +40,7 @@
 
 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 @@
     GLuint m_height;
     GLuint m_fbo;
     GLenum m_internalFormat;
+    bool m_warYInvertBug;
 };
 
 typedef SmartPtr<ColorBuffer> ColorBufferPtr;