Add support for partial invalidates in WebView
Bug #3461349

This change also fixes two bugs that prevented partial invalidates
from working with other views. Both bugs were in our EGL implementation:
they were preventing the caller from comparing the current context/surface
with another context/surface. This was causing HardwareRenderer to always
redraw the entire screen.

Change-Id: I33e096b304d4a0b7e6c8f92930f71d2ece9bebf5
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 38e0848..f4a0161 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -15,7 +15,6 @@
 		LayerCache.cpp \
 		LayerRenderer.cpp \
 		Matrix.cpp \
-		OpenGLDebugRenderer.cpp \
 		OpenGLRenderer.cpp \
 		Patch.cpp \
 		PatchCache.cpp \
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index d5d2ba0..737fa02 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -166,7 +166,7 @@
 void DisplayList::init() {
 }
 
-bool DisplayList::replay(OpenGLRenderer& renderer, uint32_t level) {
+bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) {
     bool needsInvalidate = false;
     TextContainer text;
     mReader.rewind();
@@ -189,7 +189,7 @@
             case DrawGLFunction: {
                 Functor *functor = (Functor *) getInt();
                 DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], functor);
-                needsInvalidate |= renderer.callDrawGLFunction(functor);
+                needsInvalidate |= renderer.callDrawGLFunction(functor, dirty);
             }
             break;
             case Save: {
@@ -287,7 +287,7 @@
                 DisplayList* displayList = getDisplayList();
                 DISPLAY_LIST_LOGD("%s%s %p, %d", (char*) indent, OP_NAMES[op],
                     displayList, level + 1);
-                needsInvalidate |= renderer.drawDisplayList(displayList, level + 1);
+                needsInvalidate |= renderer.drawDisplayList(displayList, dirty, level + 1);
             }
             break;
             case DrawLayer: {
@@ -589,7 +589,8 @@
 void DisplayListRenderer::resume() {
 }
 
-bool DisplayListRenderer::callDrawGLFunction(Functor *functor) {
+bool DisplayListRenderer::callDrawGLFunction(Functor *functor, Rect& dirty) {
+    // Ignore dirty during recording, it matters only when we replay
     addOp(DisplayList::DrawGLFunction);
     addInt((int) functor);
     return false; // No invalidate needed at record-time
@@ -673,7 +674,9 @@
     return OpenGLRenderer::clipRect(left, top, right, bottom, op);
 }
 
-bool DisplayListRenderer::drawDisplayList(DisplayList* displayList, uint32_t level) {
+bool DisplayListRenderer::drawDisplayList(DisplayList* displayList, Rect& dirty, uint32_t level) {
+    // dirty is an out parameter and should not be recorded,
+    // it matters only when replaying the display list
     addOp(DisplayList::DrawDisplayList);
     addDisplayList(displayList);
     return false;
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index e8f189d..f24545d 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -103,7 +103,7 @@
 
     void initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing = false);
 
-    bool replay(OpenGLRenderer& renderer, uint32_t level = 0);
+    bool replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level = 0);
 
 private:
     void init();
@@ -214,7 +214,7 @@
     void prepareDirty(float left, float top, float right, float bottom, bool opaque);
     void finish();
 
-    bool callDrawGLFunction(Functor *functor);
+    bool callDrawGLFunction(Functor *functor, Rect& dirty);
 
     void interrupt();
     void resume();
@@ -238,7 +238,7 @@
 
     bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
 
-    bool drawDisplayList(DisplayList* displayList, uint32_t level = 0);
+    bool drawDisplayList(DisplayList* displayList, Rect& dirty, uint32_t level = 0);
     void drawLayer(Layer* layer, float x, float y, SkPaint* paint);
     void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
     void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
diff --git a/libs/hwui/OpenGLDebugRenderer.cpp b/libs/hwui/OpenGLDebugRenderer.cpp
deleted file mode 100644
index 05870bb..0000000
--- a/libs/hwui/OpenGLDebugRenderer.cpp
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "OpenGLRenderer"
-
-#include <utils/StopWatch.h>
-
-#include "OpenGLDebugRenderer.h"
-
-namespace android {
-namespace uirenderer {
-
-void OpenGLDebugRenderer::prepareDirty(float left, float top,
-        float right, float bottom, bool opaque) {
-    mPrimitivesCount = 0;
-    LOGD("========= Frame start =========");
-    OpenGLRenderer::prepareDirty(left, top, right, bottom, opaque);
-}
-
-void OpenGLDebugRenderer::finish() {
-    LOGD("========= Frame end =========");
-    LOGD("Primitives draw count = %d", mPrimitivesCount);
-    OpenGLRenderer::finish();
-}
-
-void OpenGLDebugRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) {
-    mPrimitivesCount++;
-    StopWatch w("composeLayer");
-    return OpenGLRenderer::composeLayer(current, previous);
-}
-
-int OpenGLDebugRenderer::saveLayer(float left, float top, float right, float bottom,
-        SkPaint* p, int flags) {
-    mPrimitivesCount++;
-    StopWatch w("saveLayer");
-    return OpenGLRenderer::saveLayer(left, top, right, bottom, p, flags);
-}
-
-bool OpenGLDebugRenderer::drawDisplayList(DisplayList* displayList, uint32_t level) {
-    mPrimitivesCount++;
-    StopWatch w("drawDisplayList");
-    return OpenGLRenderer::drawDisplayList(displayList);
-}
-
-void OpenGLDebugRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) {
-    mPrimitivesCount++;
-    StopWatch w("drawLayer");
-    OpenGLRenderer::drawLayer(layer, x, y, paint);
-}
-
-void OpenGLDebugRenderer::drawBitmap(SkBitmap* bitmap, float left, float top,
-        SkPaint* paint) {
-    mPrimitivesCount++;
-    StopWatch w("drawBitmap");
-    OpenGLRenderer::drawBitmap(bitmap, left, top, paint);
-}
-
-void OpenGLDebugRenderer::drawBitmap(SkBitmap* bitmap, SkMatrix* matrix,
-        SkPaint* paint) {
-    mPrimitivesCount++;
-    StopWatch w("drawBitmapMatrix");
-    OpenGLRenderer::drawBitmap(bitmap, matrix, paint);
-}
-
-void OpenGLDebugRenderer::drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
-        float srcRight, float srcBottom, float dstLeft, float dstTop,
-        float dstRight, float dstBottom, SkPaint* paint) {
-    mPrimitivesCount++;
-    StopWatch w("drawBitmapRect");
-    OpenGLRenderer::drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
-            dstLeft, dstTop, dstRight, dstBottom, paint);
-}
-
-void OpenGLDebugRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
-        const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors,
-        float left, float top, float right, float bottom, SkPaint* paint) {
-    mPrimitivesCount++;
-    StopWatch w("drawPatch");
-    OpenGLRenderer::drawPatch(bitmap, xDivs, yDivs, colors, width, height, numColors,
-            left, top, right, bottom, paint);
-}
-
-void OpenGLDebugRenderer::drawColor(int color, SkXfermode::Mode mode) {
-    mPrimitivesCount++;
-    StopWatch w("drawColor");
-    OpenGLRenderer::drawColor(color, mode);
-}
-
-void OpenGLDebugRenderer::drawRect(float left, float top, float right, float bottom,
-        SkPaint* paint) {
-    mPrimitivesCount++;
-    StopWatch w("drawRect");
-    OpenGLRenderer::drawRect(left, top, right, bottom, paint);
-}
-
-void OpenGLDebugRenderer::drawRoundRect(float left, float top, float right, float bottom,
-        float rx, float ry, SkPaint* paint) {
-    mPrimitivesCount++;
-    StopWatch w("drawRoundRect");
-    OpenGLRenderer::drawRoundRect(left, top, right, bottom, rx, ry, paint);
-}
-
-void OpenGLDebugRenderer::drawCircle(float x, float y, float radius, SkPaint* paint) {
-    mPrimitivesCount++;
-    StopWatch w("drawCircle");
-    OpenGLRenderer::drawCircle(x, y, radius, paint);
-}
-
-void OpenGLDebugRenderer::drawOval(float left, float top, float right, float bottom,
-        SkPaint* paint) {
-    mPrimitivesCount++;
-    StopWatch w("drawOval");
-    OpenGLRenderer::drawOval(left, top, right, bottom, paint);
-}
-
-void OpenGLDebugRenderer::drawArc(float left, float top, float right, float bottom,
-        float startAngle, float sweepAngle, bool useCenter, SkPaint* paint) {
-    mPrimitivesCount++;
-    StopWatch w("drawArc");
-    OpenGLRenderer::drawArc(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint);
-}
-
-void OpenGLDebugRenderer::drawPath(SkPath* path, SkPaint* paint) {
-    mPrimitivesCount++;
-    StopWatch w("drawPath");
-    OpenGLRenderer::drawPath(path, paint);
-}
-
-void OpenGLDebugRenderer::drawLines(float* points, int count, SkPaint* paint) {
-    mPrimitivesCount++;
-    StopWatch w("drawLines");
-    OpenGLRenderer::drawLines(points, count, paint);
-}
-
-void OpenGLDebugRenderer::drawText(const char* text, int bytesCount, int count, float x, float y,
-        SkPaint* paint) {
-    mPrimitivesCount++;
-    StopWatch w("drawText");
-    OpenGLRenderer::drawText(text, bytesCount, count, x, y, paint);
-}
-
-}; // namespace uirenderer
-}; // namespace android
diff --git a/libs/hwui/OpenGLDebugRenderer.h b/libs/hwui/OpenGLDebugRenderer.h
deleted file mode 100644
index 1a18a67..0000000
--- a/libs/hwui/OpenGLDebugRenderer.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HWUI_OPENGL_DEBUG_RENDERER_H
-#define ANDROID_HWUI_OPENGL_DEBUG_RENDERER_H
-
-#include "OpenGLRenderer.h"
-
-namespace android {
-namespace uirenderer {
-
-///////////////////////////////////////////////////////////////////////////////
-// Renderer
-///////////////////////////////////////////////////////////////////////////////
-
-class OpenGLDebugRenderer: public OpenGLRenderer {
-public:
-    OpenGLDebugRenderer(): mPrimitivesCount(0) {
-    }
-
-    ~OpenGLDebugRenderer() {
-    }
-
-    void prepareDirty(float left, float top, float right, float bottom, bool opaque);
-    void finish();
-
-    int saveLayer(float left, float top, float right, float bottom,
-            SkPaint* p, int flags);
-
-    bool drawDisplayList(DisplayList* displayList, uint32_t level = 0);
-    void drawLayer(Layer* layer, float x, float y, SkPaint* paint);
-    void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
-    void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
-    void drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
-            float srcRight, float srcBottom, float dstLeft, float dstTop,
-            float dstRight, float dstBottom, SkPaint* paint);
-    void drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
-            const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors,
-            float left, float top, float right, float bottom, SkPaint* paint);
-    void drawColor(int color, SkXfermode::Mode mode);
-    void drawRect(float left, float top, float right, float bottom, SkPaint* paint);
-    void drawRoundRect(float left, float top, float right, float bottom,
-            float rx, float ry, SkPaint* paint);
-    void drawCircle(float x, float y, float radius, SkPaint* paint);
-    void drawOval(float left, float top, float right, float bottom, SkPaint* paint);
-    void drawArc(float left, float top, float right, float bottom,
-            float startAngle, float sweepAngle, bool useCenter, SkPaint* paint);
-    void drawPath(SkPath* path, SkPaint* paint);
-    void drawLines(float* points, int count, SkPaint* paint);
-    void drawText(const char* text, int bytesCount, int count, float x, float y,
-            SkPaint* paint);
-
-protected:
-    void composeLayer(sp<Snapshot> current, sp<Snapshot> previous);
-
-private:
-    uint32_t mPrimitivesCount;
-
-}; // class OpenGLDebugRenderer
-
-}; // namespace uirenderer
-}; // namespace android
-
-#endif // ANDROID_HWUI_OPENGL_DEBUG_RENDERER_H
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index dfca7eb..1f65201 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -210,7 +210,7 @@
     glBlendEquation(GL_FUNC_ADD);
 }
 
-bool OpenGLRenderer::callDrawGLFunction(Functor *functor) {
+bool OpenGLRenderer::callDrawGLFunction(Functor *functor, Rect& dirty) {
     interrupt();
     if (mDirtyClip) {
         setScissorFromClip();
@@ -226,9 +226,16 @@
     }
 #endif
 
-    status_t result = (*functor)();
+    float bounds[4];
+    status_t result = (*functor)(&bounds[0], 4);
+
+    if (result != 0) {
+        Rect localDirty(bounds[0], bounds[1], bounds[2], bounds[3]);
+        dirty.unionWith(localDirty);
+    }
+
     resume();
-    return (result == 0) ? false : true;
+    return result != 0;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1057,11 +1064,11 @@
 // Drawing
 ///////////////////////////////////////////////////////////////////////////////
 
-bool OpenGLRenderer::drawDisplayList(DisplayList* displayList, uint32_t level) {
+bool OpenGLRenderer::drawDisplayList(DisplayList* displayList, Rect& dirty, uint32_t level) {
     // All the usual checks and setup operations (quickReject, setupDraw, etc.)
     // will be performed by the display list itself
     if (displayList) {
-        return displayList->replay(*this, level);
+        return displayList->replay(*this, dirty, level);
     }
     return false;
 }
@@ -1522,7 +1529,6 @@
             break;
     }
 
-    // TODO: Handle paint->getTextScaleX()
     const float oldX = x;
     const float oldY = y;
     const bool pureTranslate = mSnapshot->transform->isPureTranslate();
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 7bbf034..9d86388 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -70,7 +70,7 @@
     virtual void interrupt();
     virtual void resume();
 
-    virtual bool callDrawGLFunction(Functor *functor);
+    virtual bool callDrawGLFunction(Functor *functor, Rect& dirty);
 
     int getSaveCount() const;
     virtual int save(int flags);
@@ -96,7 +96,7 @@
     bool quickReject(float left, float top, float right, float bottom);
     virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
 
-    virtual bool drawDisplayList(DisplayList* displayList, uint32_t level = 0);
+    virtual bool drawDisplayList(DisplayList* displayList, Rect& dirty, uint32_t level = 0);
     virtual void drawLayer(Layer* layer, float x, float y, SkPaint* paint);
     virtual void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
     virtual void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
diff --git a/libs/hwui/TextDropShadowCache.h b/libs/hwui/TextDropShadowCache.h
index 62c4250..d46686d 100644
--- a/libs/hwui/TextDropShadowCache.h
+++ b/libs/hwui/TextDropShadowCache.h
@@ -42,6 +42,17 @@
 
         textSize = paint->getTextSize();
         typeface = paint->getTypeface();
+
+        flags = 0;
+        if (paint->isFakeBoldText()) {
+            flags |= Font::kFakeBold;
+        }
+
+        const float skewX = paint->getTextSkewX();
+        italicStyle = *(uint32_t*) &skewX;
+
+        const float scaleXFloat = paint->getTextScaleX();
+        scaleX = *(uint32_t*) &scaleXFloat;
     }
 
     ~ShadowText() {
@@ -51,6 +62,9 @@
     uint32_t len;
     float textSize;
     SkTypeface* typeface;
+    uint32_t flags;
+    uint32_t italicStyle;
+    uint32_t scaleX;
     const char16_t* text;
     String16 str;
 
@@ -65,7 +79,13 @@
             LTE_INT(radius) {
                 LTE_FLOAT(textSize) {
                     LTE_INT(typeface) {
-                        return strncmp16(text, rhs.text, len >> 1) < 0;
+                        LTE_INT(flags) {
+                            LTE_INT(italicStyle) {
+                                LTE_INT(scaleX) {
+                                    return strncmp16(text, rhs.text, len >> 1) < 0;
+                                }
+                            }
+                        }
                     }
                 }
             }