Properly restore the GL scissor after a GL draw functor
Bug #5781254

Change-Id: I1dc4809563a793b6b579814951d4d73b4c34bf32
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index f2205f6..b151b20 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -325,6 +325,10 @@
     }
 }
 
+void Caches::resetScissor() {
+    mScissorX = mScissorY = mScissorWidth = mScissorHeight = 0;
+}
+
 TextureVertex* Caches::getRegionMesh() {
     // Create the mesh, 2 triangles and 4 vertices per rectangle in the region
     if (!mRegionMesh) {
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index d264971..409584f 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -193,6 +193,11 @@
     void setScissor(GLint x, GLint y, GLint width, GLint height);
 
     /**
+     * Resets the scissor state.
+     */
+    void resetScissor();
+
+    /**
      * Returns the mesh used to draw regions. Calling this method will
      * bind a VBO of type GL_ELEMENT_ARRAY_BUFFER that contains the
      * indices for the region mesh.
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 75c6d0a..d1b469f 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -206,6 +206,7 @@
     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 
     glEnable(GL_SCISSOR_TEST);
+    mCaches.resetScissor();
     dirtyClip();
 
     mCaches.activeTexture(0);
@@ -2517,32 +2518,38 @@
         ProgramDescription& description, bool swapSrcDst) {
     blend = blend || mode != SkXfermode::kSrcOver_Mode;
     if (blend) {
-        if (mode <= SkXfermode::kScreen_Mode) {
-            if (!mCaches.blend) {
-                glEnable(GL_BLEND);
-            }
-
-            GLenum sourceMode = swapSrcDst ? gBlendsSwap[mode].src : gBlends[mode].src;
-            GLenum destMode = swapSrcDst ? gBlendsSwap[mode].dst : gBlends[mode].dst;
-
-            if (sourceMode != mCaches.lastSrcMode || destMode != mCaches.lastDstMode) {
-                glBlendFunc(sourceMode, destMode);
-                mCaches.lastSrcMode = sourceMode;
-                mCaches.lastDstMode = destMode;
-            }
-        } else {
-            // These blend modes are not supported by OpenGL directly and have
-            // to be implemented using shaders. Since the shader will perform
-            // the blending, turn blending off here
+        // These blend modes are not supported by OpenGL directly and have
+        // to be implemented using shaders. Since the shader will perform
+        // the blending, turn blending off here
+        // If the blend mode cannot be implemented using shaders, fall
+        // back to the default SrcOver blend mode instead
+        if (mode > SkXfermode::kScreen_Mode) {
             if (mCaches.extensions.hasFramebufferFetch()) {
                 description.framebufferMode = mode;
                 description.swapSrcDst = swapSrcDst;
-            }
 
-            if (mCaches.blend) {
-                glDisable(GL_BLEND);
+                if (mCaches.blend) {
+                    glDisable(GL_BLEND);
+                    mCaches.blend = false;
+                }
+
+                return;
+            } else {
+                mode = SkXfermode::kSrcOver_Mode;
             }
-            blend = false;
+        }
+
+        if (!mCaches.blend) {
+            glEnable(GL_BLEND);
+        }
+
+        GLenum sourceMode = swapSrcDst ? gBlendsSwap[mode].src : gBlends[mode].src;
+        GLenum destMode = swapSrcDst ? gBlendsSwap[mode].dst : gBlends[mode].dst;
+
+        if (sourceMode != mCaches.lastSrcMode || destMode != mCaches.lastDstMode) {
+            glBlendFunc(sourceMode, destMode);
+            mCaches.lastSrcMode = sourceMode;
+            mCaches.lastDstMode = destMode;
         }
     } else if (mCaches.blend) {
         glDisable(GL_BLEND);