Preliminary Support for region clipping

Region clipping, using Canvas.clipPath or Canvas.clipRegion, requires
a stencil buffer to be always present. In addition, extra wiring is
required in JNI and display lists.

This change only adds the necessary JNI/C++ APIs and some extra
plumbing to start the real work on properly supporting region
clipping.

A new debug define called DEBUG_CLIP_REGIONS can be used to draw
the current clip region. It is off by default, as is region
clipping.

The default implementation of clipPath() and clipRegion(), now
in native, mimics the previous Dalvik implementation to prevent
regressions.

Change-Id: I7903e7cfd7412b9b9b622566d4dbfce7bdcec00c
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 8cda729..bb1edbb 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1288,10 +1288,38 @@
     bool clipped = mSnapshot->clip(left, top, right, bottom, op);
     if (clipped) {
         dirtyClip();
+#if DEBUG_CLIP_REGIONS
+        if (!isDeferred() && mSnapshot->clipRegion && !mSnapshot->clipRegion->isRect()) {
+            int count = 0;
+            Vector<float> rects;
+            SkRegion::Iterator it(*mSnapshot->clipRegion);
+            while (!it.done()) {
+                const SkIRect& r = it.rect();
+                rects.push(r.fLeft);
+                rects.push(r.fTop);
+                rects.push(r.fRight);
+                rects.push(r.fBottom);
+                count++;
+                it.next();
+            }
+
+            drawColorRects(rects.array(), count, 0x7f00ff00, SkXfermode::kSrcOver_Mode, true);
+        }
+#endif
     }
     return !mSnapshot->clipRect->isEmpty();
 }
 
+bool OpenGLRenderer::clipPath(SkPath* path, SkRegion::Op op) {
+    const SkRect& bounds = path->getBounds();
+    return clipRect(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, op);
+}
+
+bool OpenGLRenderer::clipRegion(SkRegion* region, SkRegion::Op op) {
+    const SkIRect& bounds = region->getBounds();
+    return clipRect(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, op);
+}
+
 Rect* OpenGLRenderer::getClipRect() {
     return mSnapshot->clipRect;
 }
@@ -3046,6 +3074,19 @@
         return DrawGlInfo::kStatusDone;
     }
 
+    int color = paint->getColor();
+    // If a shader is set, preserve only the alpha
+    if (mShader) {
+        color |= 0x00ffffff;
+    }
+    SkXfermode::Mode mode = getXfermode(paint->getXfermode());
+
+    return drawColorRects(rects, count, color, mode);
+}
+
+status_t OpenGLRenderer::drawColorRects(const float* rects, int count, int color,
+        SkXfermode::Mode mode, bool ignoreTransform) {
+
     float left = FLT_MAX;
     float top = FLT_MAX;
     float right = FLT_MIN;
@@ -3081,13 +3122,6 @@
 
     if (count == 0) return DrawGlInfo::kStatusDone;
 
-    int color = paint->getColor();
-    // If a shader is set, preserve only the alpha
-    if (mShader) {
-        color |= 0x00ffffff;
-    }
-    SkXfermode::Mode mode = getXfermode(paint->getXfermode());
-
     setupDraw();
     setupDrawNoTexture();
     setupDrawColor(color, ((color >> 24) & 0xFF) * mSnapshot->alpha);
@@ -3096,7 +3130,7 @@
     setupDrawBlending(mode);
     setupDrawProgram();
     setupDrawDirtyRegionsDisabled();
-    setupDrawModelView(0.0f, 0.0f, 1.0f, 1.0f);
+    setupDrawModelView(0.0f, 0.0f, 1.0f, 1.0f, ignoreTransform, true);
     setupDrawColorUniforms();
     setupDrawShaderUniforms();
     setupDrawColorFilterUniforms();