Implement clipRect with a transform, clipRegion & clipPath
Bug #7146141
When non-rectangular clipping occurs in a layer the render buffer
used as the stencil buffer is not cached. If this happens on a
View's hardware layer the render buffer will live for as long
as the layer is bound to the view. When a stencil buffer is
required because of a call to Canvas.saveLayer() it will be allocated
on every frame. A future change will address this problem.
If "show GPU overdraw" is enabled, non-rectangular clips are not
supported anymore and we fall back to rectangular clips instead.
This is a limitation imposed by OpenGL ES that cannot be worked
around at this time.
This change also improves the Matrix4 implementation to easily
detect when a rect remains a rect after transform.
Change-Id: I0e69fb901792d38bc0c4ca1bf9fdb02d7db415b9
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index f07325f..d4e1eb5 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -287,6 +287,19 @@
void resumeAfterLayer();
/**
+ * This method is called whenever a stencil buffer is required. Subclasses
+ * should override this method and call attachStencilBufferToLayer() on the
+ * appropriate layer(s).
+ */
+ virtual void ensureStencilBuffer();
+
+ /**
+ * Obtains a stencil render buffer (allocating it if necessary) and
+ * attaches it to the specified layer.
+ */
+ void attachStencilBufferToLayer(Layer* layer);
+
+ /**
* Compose the layer defined in the current snapshot with the layer
* defined by the previous snapshot.
*
@@ -423,6 +436,12 @@
void setScissorFromClip();
/**
+ * Sets the clipping region using the stencil buffer. The clip region
+ * is defined by the current snapshot's clipRegion member.
+ */
+ void setStencilFromClip();
+
+ /**
* Performs a quick reject but does not affect the scissor. Returns
* the transformed rect to test and the current clip.
*/
@@ -524,9 +543,10 @@
* @param color The rectangles' ARGB color, defined as a packed 32 bits word
* @param mode The Skia xfermode to use
* @param ignoreTransform True if the current transform should be ignored
+ * @param dirty True if calling this method should dirty the current layer
*/
status_t drawColorRects(const float* rects, int count, int color,
- SkXfermode::Mode mode, bool ignoreTransform = false);
+ SkXfermode::Mode mode, bool ignoreTransform = false, bool dirty = true);
/**
* Draws the shape represented by the specified path texture.
@@ -774,6 +794,19 @@
*/
void drawRegionRects(const Region& region);
+ /**
+ * Renders the specified region as a series of rectangles. The region
+ * must be in screen-space coordinates.
+ */
+ void drawRegionRects(const SkRegion& region, int color, SkXfermode::Mode mode,
+ bool dirty = false);
+
+ /**
+ * Draws the current clip region if any. Only when DEBUG_CLIP_REGIONS
+ * is turned on.
+ */
+ void debugClip();
+
void debugOverdraw(bool enable, bool clear);
void renderOverdraw();