Add support for GL_CHROMIUM_flipy

Review URL: http://codereview.appspot.com/5413051/


git-svn-id: http://skia.googlecode.com/svn/trunk@2723 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/gpu/GrGLDefines.h b/include/gpu/GrGLDefines.h
index 94e7cb5..650646d 100644
--- a/include/gpu/GrGLDefines.h
+++ b/include/gpu/GrGLDefines.h
@@ -174,6 +174,7 @@
 #define GR_GL_COLOR_CLEAR_VALUE              0x0C22
 #define GR_GL_COLOR_WRITEMASK                0x0C23
 #define GR_GL_UNPACK_ALIGNMENT               0x0CF5
+#define GR_GL_UNPACK_FLIP_Y                  0x9240
 #define GR_GL_PACK_ALIGNMENT                 0x0D05
 #define GR_GL_MAX_TEXTURE_SIZE               0x0D33
 #define GR_GL_MAX_VIEWPORT_DIMS              0x0D3A
diff --git a/src/gpu/GrGpuGL.cpp b/src/gpu/GrGpuGL.cpp
index cd37a54..093a53b 100644
--- a/src/gpu/GrGpuGL.cpp
+++ b/src/gpu/GrGpuGL.cpp
@@ -305,9 +305,11 @@
 
     if (kDesktop_GrGLBinding == this->glBinding()) {
         fGLCaps.fUnpackRowLengthSupport = true;
+        fGLCaps.fUnpackFlipYSupport = false;
         fGLCaps.fPackRowLengthSupport = true;
     } else {
         fGLCaps.fUnpackRowLengthSupport = this->hasExtension("GL_EXT_unpack_subimage");
+        fGLCaps.fUnpackFlipYSupport = this->hasExtension("GL_CHROMIUM_flipy");
         // no extension for pack row length
         fGLCaps.fPackRowLengthSupport = false;
     }
@@ -528,6 +530,17 @@
 
     GL_CALL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
     fHWDrawState.fRenderTarget = NULL;
+
+    // we assume these values
+    if (this->glCaps().fUnpackRowLengthSupport) {
+        GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
+    }
+    if (this->glCaps().fPackRowLengthSupport) {
+        GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH, 0));
+    }
+    if (this->glCaps().fUnpackFlipYSupport) {
+        GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE));
+    }
 }
 
 GrTexture* GrGpuGL::onCreatePlatformTexture(const GrPlatformTextureDesc& desc) {
@@ -760,8 +773,17 @@
      *  GL_UNPACK_ROW_LENGTH.
      */
     bool restoreGLRowLength = false;
-    bool flipY = GrGLTexture::kBottomUp_Orientation == desc.fOrientation;
-    if (this->glCaps().fUnpackRowLengthSupport && !flipY) {
+    bool swFlipY = false;
+    bool glFlipY = false;
+
+    if (GrGLTexture::kBottomUp_Orientation == desc.fOrientation) {
+        if (this->glCaps().fUnpackFlipYSupport) {
+            glFlipY = true;
+        } else {
+            swFlipY = true;
+        }
+    }
+    if (this->glCaps().fUnpackRowLengthSupport && !swFlipY) {
         // can't use this for flipping, only non-neg values allowed. :(
         if (rowBytes != trimRowBytes) {
             GrGLint rowLength = static_cast<GrGLint>(rowBytes / bpp);
@@ -769,17 +791,17 @@
             restoreGLRowLength = true;
         }
     } else {
-        if (trimRowBytes != rowBytes || flipY) {
+        if (trimRowBytes != rowBytes || swFlipY) {
             // copy the data into our new storage, skipping the trailing bytes
             size_t trimSize = height * trimRowBytes;
             const char* src = (const char*)data;
-            if (flipY) {
+            if (swFlipY) {
                 src += (height - 1) * rowBytes;
             }
             char* dst = (char*)tempStorage.reset(trimSize);
             for (int y = 0; y < height; y++) {
                 memcpy(dst, src, trimRowBytes);
-                if (flipY) {
+                if (swFlipY) {
                     src -= rowBytes;
                 } else {
                     src += rowBytes;
@@ -790,7 +812,9 @@
             data = tempStorage.get();
         }
     }
-
+    if (glFlipY) {
+        GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_TRUE));
+    }
     GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, static_cast<GrGLint>(bpp)));
     if (0 == left && 0 == top &&
         desc.fWidth == width && desc.fHeight == height) {
@@ -798,7 +822,7 @@
                            desc.fWidth, desc.fHeight, 0,
                            externalFormat, externalType, data));
     } else {
-        if (flipY) {
+        if (swFlipY || glFlipY) {
             top = desc.fHeight - (top + height);
         }
         GL_CALL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, left, top, width, height,
@@ -809,6 +833,9 @@
         GrAssert(this->glCaps().fUnpackRowLengthSupport);
         GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
     }
+    if (glFlipY) {
+        GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE));
+    }
 }
 
 bool GrGpuGL::createRenderTargetObjects(int width, int height,
@@ -2377,6 +2404,8 @@
              (fTextureSwizzleSupport ? "YES": "NO"));
     GrPrintf("Unpack Row length support: %s\n",
              (fUnpackRowLengthSupport ? "YES": "NO"));
+    GrPrintf("Unpack Flip Y support: %s\n",
+             (fUnpackFlipYSupport ? "YES": "NO"));
     GrPrintf("Pack Row length support: %s\n",
              (fPackRowLengthSupport ? "YES": "NO"));
 }
diff --git a/src/gpu/GrGpuGL.h b/src/gpu/GrGpuGL.h
index 3b8e6d7..eba162e 100644
--- a/src/gpu/GrGpuGL.h
+++ b/src/gpu/GrGpuGL.h
@@ -55,6 +55,7 @@
             , fBGRAIsInternalFormat(false)
             , fTextureSwizzleSupport(false)
             , fUnpackRowLengthSupport(false)
+            , fUnpackFlipYSupport(false)
             , fPackRowLengthSupport(false) {
             memset(fAASamples, 0, sizeof(fAASamples));
         }
@@ -102,6 +103,9 @@
         // Is there support for GL_UNPACK_ROW_LENGTH
         bool fUnpackRowLengthSupport;
 
+        // Is there support for GL_UNPACK_FLIP_Y
+        bool fUnpackFlipYSupport;
+
         // Is there support for GL_PACK_ROW_LENGTH
         bool fPackRowLengthSupport;