summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/GLES20RecordingCanvas.java7
-rw-r--r--core/java/android/view/RenderNode.java72
-rw-r--r--core/java/android/view/View.java46
-rw-r--r--core/java/android/view/ViewGroup.java5
-rw-r--r--core/jni/android_view_RenderNode.cpp49
-rw-r--r--graphics/java/android/graphics/Canvas.java3
-rw-r--r--libs/hwui/RenderNode.cpp22
-rw-r--r--libs/hwui/RenderProperties.cpp30
-rw-r--r--libs/hwui/RenderProperties.h57
9 files changed, 149 insertions, 142 deletions
diff --git a/core/java/android/view/GLES20RecordingCanvas.java b/core/java/android/view/GLES20RecordingCanvas.java
index b2961e5..5e49d8e 100644
--- a/core/java/android/view/GLES20RecordingCanvas.java
+++ b/core/java/android/view/GLES20RecordingCanvas.java
@@ -17,6 +17,7 @@
package android.view;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.util.Pools.SynchronizedPool;
/**
@@ -41,7 +42,6 @@ class GLES20RecordingCanvas extends GLES20Canvas {
static GLES20RecordingCanvas obtain(@NonNull RenderNode node) {
if (node == null) throw new IllegalArgumentException("node cannot be null");
-
GLES20RecordingCanvas canvas = sPool.acquire();
if (canvas == null) {
canvas = new GLES20RecordingCanvas();
@@ -58,4 +58,9 @@ class GLES20RecordingCanvas extends GLES20Canvas {
long finishRecording() {
return nFinishRecording(mRenderer);
}
+
+ @Override
+ public boolean isRecordingFor(Object o) {
+ return o == mNode;
+ }
}
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index 73c7321..8aba8af 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -17,9 +17,11 @@
package android.view;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.graphics.Matrix;
import android.graphics.Outline;
import android.graphics.Paint;
+import android.graphics.Rect;
/**
* <p>A display list records a series of graphics related operations and can replay
@@ -294,13 +296,6 @@ public class RenderNode {
// RenderProperty Setters
///////////////////////////////////////////////////////////////////////////
- /**
- * Set the caching property on the display list, which indicates whether the display list
- * holds a layer. Layer display lists should avoid creating an alpha layer, since alpha is
- * handled in the drawLayer operation directly (and more efficiently).
- *
- * @param caching true if the display list represents a hardware layer, false otherwise.
- */
public boolean setLayerType(int layerType) {
return nSetLayerType(mNativeRenderNode, layerType);
}
@@ -309,6 +304,14 @@ public class RenderNode {
return nSetLayerPaint(mNativeRenderNode, paint != null ? paint.mNativePaint : 0);
}
+ public boolean setClipBounds(@Nullable Rect rect) {
+ if (rect == null) {
+ return nSetClipBoundsEmpty(mNativeRenderNode);
+ } else {
+ return nSetClipBounds(mNativeRenderNode, rect.left, rect.top, rect.right, rect.bottom);
+ }
+ }
+
/**
* Set whether the Render node should clip itself to its bounds. This property is controlled by
* the view's parent.
@@ -702,85 +705,45 @@ public class RenderNode {
* @param left The left position, in pixels, of the display list
*
* @see View#setLeft(int)
- * @see #getLeft()
*/
public boolean setLeft(int left) {
return nSetLeft(mNativeRenderNode, left);
}
/**
- * Returns the left position for the display list in pixels.
- *
- * @see #setLeft(int)
- */
- public float getLeft() {
- return nGetLeft(mNativeRenderNode);
- }
-
- /**
* Sets the top position for the display list.
*
* @param top The top position, in pixels, of the display list
*
* @see View#setTop(int)
- * @see #getTop()
*/
public boolean setTop(int top) {
return nSetTop(mNativeRenderNode, top);
}
/**
- * Returns the top position for the display list in pixels.
- *
- * @see #setTop(int)
- */
- public float getTop() {
- return nGetTop(mNativeRenderNode);
- }
-
- /**
* Sets the right position for the display list.
*
* @param right The right position, in pixels, of the display list
*
* @see View#setRight(int)
- * @see #getRight()
*/
public boolean setRight(int right) {
return nSetRight(mNativeRenderNode, right);
}
/**
- * Returns the right position for the display list in pixels.
- *
- * @see #setRight(int)
- */
- public float getRight() {
- return nGetRight(mNativeRenderNode);
- }
-
- /**
* Sets the bottom position for the display list.
*
* @param bottom The bottom position, in pixels, of the display list
*
* @see View#setBottom(int)
- * @see #getBottom()
*/
public boolean setBottom(int bottom) {
return nSetBottom(mNativeRenderNode, bottom);
}
/**
- * Returns the bottom position for the display list in pixels.
- *
- * @see #setBottom(int)
- */
- public float getBottom() {
- return nGetBottom(mNativeRenderNode);
- }
-
- /**
* Sets the left and top positions for the display list
*
* @param left The left position of the display list, in pixels
@@ -805,7 +768,7 @@ public class RenderNode {
*
* @see View#offsetLeftAndRight(int)
*/
- public boolean offsetLeftAndRight(float offset) {
+ public boolean offsetLeftAndRight(int offset) {
return nOffsetLeftAndRight(mNativeRenderNode, offset);
}
@@ -817,7 +780,7 @@ public class RenderNode {
*
* @see View#offsetTopAndBottom(int)
*/
- public boolean offsetTopAndBottom(float offset) {
+ public boolean offsetTopAndBottom(int offset) {
return nOffsetTopAndBottom(mNativeRenderNode, offset);
}
@@ -860,8 +823,8 @@ public class RenderNode {
// Properties
- private static native boolean nOffsetTopAndBottom(long renderNode, float offset);
- private static native boolean nOffsetLeftAndRight(long renderNode, float offset);
+ private static native boolean nOffsetTopAndBottom(long renderNode, int offset);
+ private static native boolean nOffsetLeftAndRight(long renderNode, int offset);
private static native boolean nSetLeftTopRightBottom(long renderNode, int left, int top,
int right, int bottom);
private static native boolean nSetBottom(long renderNode, int bottom);
@@ -874,6 +837,9 @@ public class RenderNode {
private static native boolean nSetLayerType(long renderNode, int layerType);
private static native boolean nSetLayerPaint(long renderNode, long paint);
private static native boolean nSetClipToBounds(long renderNode, boolean clipToBounds);
+ private static native boolean nSetClipBounds(long renderNode, int left, int top,
+ int right, int bottom);
+ private static native boolean nSetClipBoundsEmpty(long renderNode);
private static native boolean nSetProjectBackwards(long renderNode, boolean shouldProject);
private static native boolean nSetProjectionReceiver(long renderNode, boolean shouldRecieve);
private static native boolean nSetOutlineRoundRect(long renderNode, int left, int top,
@@ -902,10 +868,6 @@ public class RenderNode {
private static native boolean nHasOverlappingRendering(long renderNode);
private static native boolean nGetClipToOutline(long renderNode);
private static native float nGetAlpha(long renderNode);
- private static native float nGetLeft(long renderNode);
- private static native float nGetTop(long renderNode);
- private static native float nGetRight(long renderNode);
- private static native float nGetBottom(long renderNode);
private static native float nGetCameraDistance(long renderNode);
private static native float nGetScaleX(long renderNode);
private static native float nGetScaleY(long renderNode);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 0079cc9..4c1c2f9 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -724,11 +724,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
private static boolean sIgnoreMeasureCache = false;
/**
- * Ignore the clipBounds of this view for the children.
- */
- static boolean sIgnoreClipBoundsForChildren = false;
-
- /**
* This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
* calling setFlags.
*/
@@ -3558,9 +3553,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
// of whether a layout was requested on that View.
sIgnoreMeasureCache = targetSdkVersion < KITKAT;
- // Older apps may need this to ignore the clip bounds
- sIgnoreClipBoundsForChildren = targetSdkVersion < L;
-
sCompatibilityDone = true;
}
}
@@ -14309,6 +14301,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
mClipBounds = null;
}
}
+ mRenderNode.setClipBounds(mClipBounds);
}
/**
@@ -14430,7 +14423,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* to be called from anywhere else other than ViewGroup.drawChild().
*/
boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
- boolean useDisplayListProperties = mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
+ boolean usingRenderNodeProperties = mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
boolean more = false;
final boolean childHasIdentityMatrix = hasIdentityMatrix();
final int flags = parent.mGroupFlags;
@@ -14471,7 +14464,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
mRenderNode.setAnimationMatrix(null);
mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
}
- if (!useDisplayListProperties &&
+ if (!usingRenderNodeProperties &&
(flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
final Transformation t = parent.getChildTransformation();
final boolean hasTransform = parent.getChildStaticTransformation(this, t);
@@ -14519,7 +14512,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
} else {
switch (layerType) {
case LAYER_TYPE_SOFTWARE:
- if (useDisplayListProperties) {
+ if (usingRenderNodeProperties) {
hasDisplayList = canHaveDisplayList();
} else {
buildDrawingCache(true);
@@ -14527,7 +14520,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
break;
case LAYER_TYPE_HARDWARE:
- if (useDisplayListProperties) {
+ if (usingRenderNodeProperties) {
hasDisplayList = canHaveDisplayList();
}
break;
@@ -14539,8 +14532,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
}
}
- useDisplayListProperties &= hasDisplayList;
- if (useDisplayListProperties) {
+ usingRenderNodeProperties &= hasDisplayList;
+ if (usingRenderNodeProperties) {
renderNode = getDisplayList();
if (!renderNode.isValid()) {
// Uncommon, but possible. If a view is removed from the hierarchy during the call
@@ -14548,7 +14541,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
// try to use it again.
renderNode = null;
hasDisplayList = false;
- useDisplayListProperties = false;
+ usingRenderNodeProperties = false;
}
}
@@ -14565,17 +14558,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
layerType != LAYER_TYPE_HARDWARE;
int restoreTo = -1;
- if (!useDisplayListProperties || transformToApply != null) {
+ if (!usingRenderNodeProperties || transformToApply != null) {
restoreTo = canvas.save();
}
if (offsetForScroll) {
canvas.translate(mLeft - sx, mTop - sy);
} else {
- if (!useDisplayListProperties) {
+ if (!usingRenderNodeProperties) {
canvas.translate(mLeft, mTop);
}
if (scalingRequired) {
- if (useDisplayListProperties) {
+ if (usingRenderNodeProperties) {
// TODO: Might not need this if we put everything inside the DL
restoreTo = canvas.save();
}
@@ -14585,7 +14578,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
}
- float alpha = useDisplayListProperties ? 1 : (getAlpha() * getTransitionAlpha());
+ float alpha = usingRenderNodeProperties ? 1 : (getAlpha() * getTransitionAlpha());
if (transformToApply != null || alpha < 1 || !hasIdentityMatrix() ||
(mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
if (transformToApply != null || !childHasIdentityMatrix) {
@@ -14599,7 +14592,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (transformToApply != null) {
if (concatMatrix) {
- if (useDisplayListProperties) {
+ if (usingRenderNodeProperties) {
renderNode.setAnimationMatrix(transformToApply.getMatrix());
} else {
// Undo the scroll translation, apply the transformation matrix,
@@ -14618,7 +14611,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
}
- if (!childHasIdentityMatrix && !useDisplayListProperties) {
+ if (!childHasIdentityMatrix && !usingRenderNodeProperties) {
canvas.translate(-transX, -transY);
canvas.concat(getMatrix());
canvas.translate(transX, transY);
@@ -14642,7 +14635,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
layerType != LAYER_TYPE_NONE) {
layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG;
}
- if (useDisplayListProperties) {
+ if (usingRenderNodeProperties) {
renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
} else if (layerType == LAYER_TYPE_NONE) {
final int scrollX = hasDisplayList ? 0 : sx;
@@ -14662,7 +14655,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) == ViewGroup.FLAG_CLIP_CHILDREN &&
- !useDisplayListProperties && cache == null) {
+ !usingRenderNodeProperties && cache == null) {
if (offsetForScroll) {
canvas.clipRect(sx, sy, sx + (mRight - mLeft), sy + (mBottom - mTop));
} else {
@@ -14674,7 +14667,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
}
- if (!useDisplayListProperties && hasDisplayList) {
+ if (!usingRenderNodeProperties && hasDisplayList) {
renderNode = getDisplayList();
if (!renderNode.isValid()) {
// Uncommon, but possible. If a view is removed from the hierarchy during the call
@@ -14687,7 +14680,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (hasNoCache) {
boolean layerRendered = false;
- if (layerType == LAYER_TYPE_HARDWARE && !useDisplayListProperties) {
+ if (layerType == LAYER_TYPE_HARDWARE && !usingRenderNodeProperties) {
final HardwareLayer layer = getHardwareLayer();
if (layer != null && layer.isValid()) {
mLayerPaint.setAlpha((int) (alpha * 255));
@@ -14774,7 +14767,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @param canvas The Canvas to which the View is rendered.
*/
public void draw(Canvas canvas) {
- if (mClipBounds != null) {
+ boolean usingRenderNodeProperties = canvas.isRecordingFor(mRenderNode);
+ if (mClipBounds != null && !usingRenderNodeProperties) {
canvas.clipRect(mClipBounds);
}
final int privateFlags = mPrivateFlags;
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 1028a0c..c4c3242 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3015,6 +3015,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
*/
@Override
protected void dispatchDraw(Canvas canvas) {
+ boolean usingRenderNodeProperties = canvas.isRecordingFor(mRenderNode);
final int childrenCount = mChildrenCount;
final View[] children = mChildren;
int flags = mGroupFlags;
@@ -3059,7 +3060,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
int clipSaveCount = 0;
final boolean clipToPadding = (flags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK;
- boolean hasClipBounds = mClipBounds != null && !sIgnoreClipBoundsForChildren;
+ boolean hasClipBounds = mClipBounds != null && !usingRenderNodeProperties;
boolean clippingNeeded = clipToPadding || hasClipBounds;
if (clippingNeeded) {
@@ -3087,7 +3088,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
// Only use the preordered list if not HW accelerated, since the HW pipeline will do the
// draw reordering internally
- final ArrayList<View> preorderedList = canvas.isHardwareAccelerated()
+ final ArrayList<View> preorderedList = usingRenderNodeProperties
? null : buildOrderedChildList();
final boolean customOrder = preorderedList == null
&& isChildrenDrawingOrderEnabled();
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index 1f3909a..3b6f0eb 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -117,6 +117,17 @@ static jboolean android_view_RenderNode_setClipToBounds(JNIEnv* env,
return SET_AND_DIRTY(setClipToBounds, clipToBounds, RenderNode::GENERIC);
}
+static jboolean android_view_RenderNode_setClipBounds(JNIEnv* env,
+ jobject clazz, jlong renderNodePtr, jint left, jint top, jint right, jint bottom) {
+ android::uirenderer::Rect clipBounds(left, top, right, bottom);
+ return SET_AND_DIRTY(setClipBounds, clipBounds, RenderNode::GENERIC);
+}
+
+static jboolean android_view_RenderNode_setClipBoundsEmpty(JNIEnv* env,
+ jobject clazz, jlong renderNodePtr) {
+ return SET_AND_DIRTY(setClipBoundsEmpty,, RenderNode::GENERIC);
+}
+
static jboolean android_view_RenderNode_setProjectBackwards(JNIEnv* env,
jobject clazz, jlong renderNodePtr, jboolean shouldProject) {
return SET_AND_DIRTY(setProjectBackwards, shouldProject, RenderNode::GENERIC);
@@ -282,12 +293,12 @@ static jboolean android_view_RenderNode_setLeftTopRightBottom(JNIEnv* env,
}
static jboolean android_view_RenderNode_offsetLeftAndRight(JNIEnv* env,
- jobject clazz, jlong renderNodePtr, float offset) {
+ jobject clazz, jlong renderNodePtr, jint offset) {
return SET_AND_DIRTY(offsetLeftRight, offset, RenderNode::X);
}
static jboolean android_view_RenderNode_offsetTopAndBottom(JNIEnv* env,
- jobject clazz, jlong renderNodePtr, float offset) {
+ jobject clazz, jlong renderNodePtr, jint offset) {
return SET_AND_DIRTY(offsetTopBottom, offset, RenderNode::Y);
}
@@ -313,30 +324,6 @@ static jfloat android_view_RenderNode_getAlpha(JNIEnv* env,
return renderNode->stagingProperties().getAlpha();
}
-static jfloat android_view_RenderNode_getLeft(JNIEnv* env,
- jobject clazz, jlong renderNodePtr) {
- RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- return renderNode->stagingProperties().getLeft();
-}
-
-static jfloat android_view_RenderNode_getTop(JNIEnv* env,
- jobject clazz, jlong renderNodePtr) {
- RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- return renderNode->stagingProperties().getTop();
-}
-
-static jfloat android_view_RenderNode_getRight(JNIEnv* env,
- jobject clazz, jlong renderNodePtr) {
- RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- return renderNode->stagingProperties().getRight();
-}
-
-static jfloat android_view_RenderNode_getBottom(JNIEnv* env,
- jobject clazz, jlong renderNodePtr) {
- RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- return renderNode->stagingProperties().getBottom();
-}
-
static jfloat android_view_RenderNode_getCameraDistance(JNIEnv* env,
jobject clazz, jlong renderNodePtr) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
@@ -488,6 +475,8 @@ static JNINativeMethod gMethods[] = {
{ "nSetStaticMatrix", "(JJ)Z", (void*) android_view_RenderNode_setStaticMatrix },
{ "nSetAnimationMatrix", "(JJ)Z", (void*) android_view_RenderNode_setAnimationMatrix },
{ "nSetClipToBounds", "(JZ)Z", (void*) android_view_RenderNode_setClipToBounds },
+ { "nSetClipBounds", "(JIIII)Z", (void*) android_view_RenderNode_setClipBounds },
+ { "nSetClipBoundsEmpty", "(J)Z", (void*) android_view_RenderNode_setClipBoundsEmpty },
{ "nSetProjectBackwards", "(JZ)Z", (void*) android_view_RenderNode_setProjectBackwards },
{ "nSetProjectionReceiver","(JZ)Z", (void*) android_view_RenderNode_setProjectionReceiver },
@@ -518,16 +507,12 @@ static JNINativeMethod gMethods[] = {
{ "nSetRight", "(JI)Z", (void*) android_view_RenderNode_setRight },
{ "nSetBottom", "(JI)Z", (void*) android_view_RenderNode_setBottom },
{ "nSetLeftTopRightBottom","(JIIII)Z", (void*) android_view_RenderNode_setLeftTopRightBottom },
- { "nOffsetLeftAndRight", "(JF)Z", (void*) android_view_RenderNode_offsetLeftAndRight },
- { "nOffsetTopAndBottom", "(JF)Z", (void*) android_view_RenderNode_offsetTopAndBottom },
+ { "nOffsetLeftAndRight", "(JI)Z", (void*) android_view_RenderNode_offsetLeftAndRight },
+ { "nOffsetTopAndBottom", "(JI)Z", (void*) android_view_RenderNode_offsetTopAndBottom },
{ "nHasOverlappingRendering", "(J)Z", (void*) android_view_RenderNode_hasOverlappingRendering },
{ "nGetClipToOutline", "(J)Z", (void*) android_view_RenderNode_getClipToOutline },
{ "nGetAlpha", "(J)F", (void*) android_view_RenderNode_getAlpha },
- { "nGetLeft", "(J)F", (void*) android_view_RenderNode_getLeft },
- { "nGetTop", "(J)F", (void*) android_view_RenderNode_getTop },
- { "nGetRight", "(J)F", (void*) android_view_RenderNode_getRight },
- { "nGetBottom", "(J)F", (void*) android_view_RenderNode_getBottom },
{ "nGetCameraDistance", "(J)F", (void*) android_view_RenderNode_getCameraDistance },
{ "nGetScaleX", "(J)F", (void*) android_view_RenderNode_getScaleX },
{ "nGetScaleY", "(J)F", (void*) android_view_RenderNode_getScaleY },
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index ef4b260..f3af8f6 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -52,6 +52,9 @@ public class Canvas {
return mNativeCanvasWrapper;
}
+ /** @hide */
+ public boolean isRecordingFor(Object o) { return false; }
+
// may be null
private Bitmap mBitmap;
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index b77b36f..01c7761 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -347,31 +347,35 @@ void RenderNode::setViewProperties(OpenGLRenderer& renderer, T& handler) {
}
}
const bool isLayer = properties().layerProperties().type() != kLayerTypeNone;
- bool clipToBoundsNeeded = isLayer ? false : properties().getClipToBounds();
+ int clipFlags = properties().getClippingFlags();
if (properties().getAlpha() < 1) {
if (isLayer) {
+ clipFlags &= ~CLIP_TO_BOUNDS; // bounds clipping done by layer
+
renderer.setOverrideLayerAlpha(properties().getAlpha());
} else if (!properties().getHasOverlappingRendering()) {
renderer.scaleAlpha(properties().getAlpha());
} else {
- // TODO: should be able to store the size of a DL at record time and not
- // have to pass it into this call. In fact, this information might be in the
- // location/size info that we store with the new native transform data.
+ Rect layerBounds(0, 0, getWidth(), getHeight());
int saveFlags = SkCanvas::kHasAlphaLayer_SaveFlag;
- if (clipToBoundsNeeded) {
+ if (clipFlags) {
saveFlags |= SkCanvas::kClipToLayer_SaveFlag;
- clipToBoundsNeeded = false; // clipping done by saveLayer
+ properties().getClippingRectForFlags(clipFlags, &layerBounds);
+ clipFlags = 0; // all clipping done by saveLayer
}
SaveLayerOp* op = new (handler.allocator()) SaveLayerOp(
- 0, 0, properties().getWidth(), properties().getHeight(),
+ layerBounds.left, layerBounds.top, layerBounds.right, layerBounds.bottom,
properties().getAlpha() * 255, saveFlags);
handler(op, PROPERTY_SAVECOUNT, properties().getClipToBounds());
}
}
- if (clipToBoundsNeeded) {
+ if (clipFlags) {
+ Rect clipRect;
+ properties().getClippingRectForFlags(clipFlags, &clipRect);
ClipRectOp* op = new (handler.allocator()) ClipRectOp(
- 0, 0, properties().getWidth(), properties().getHeight(), SkRegion::kIntersect_Op);
+ clipRect.left, clipRect.top, clipRect.right, clipRect.bottom,
+ SkRegion::kIntersect_Op);
handler(op, PROPERTY_SAVECOUNT, properties().getClipToBounds());
}
diff --git a/libs/hwui/RenderProperties.cpp b/libs/hwui/RenderProperties.cpp
index 8848b2f..250cadc 100644
--- a/libs/hwui/RenderProperties.cpp
+++ b/libs/hwui/RenderProperties.cpp
@@ -75,7 +75,7 @@ LayerProperties& LayerProperties::operator=(const LayerProperties& other) {
}
RenderProperties::PrimitiveFields::PrimitiveFields()
- : mClipToBounds(true)
+ : mClippingFlags(CLIP_TO_BOUNDS)
, mProjectBackwards(false)
, mProjectionReceiver(false)
, mAlpha(1)
@@ -146,26 +146,34 @@ void RenderProperties::debugOutputProperties(const int level) const {
}
}
- bool clipToBoundsNeeded = layerProperties().type() != kLayerTypeNone ? false : mPrimitiveFields.mClipToBounds;
+ const bool isLayer = layerProperties().type() != kLayerTypeNone;
+ int clipFlags = getClippingFlags();
if (mPrimitiveFields.mAlpha < 1) {
- if (layerProperties().type() != kLayerTypeNone) {
+ if (isLayer) {
+ clipFlags &= ~CLIP_TO_BOUNDS; // bounds clipping done by layer
+
ALOGD("%*sSetOverrideLayerAlpha %.2f", level * 2, "", mPrimitiveFields.mAlpha);
} else if (!mPrimitiveFields.mHasOverlappingRendering) {
ALOGD("%*sScaleAlpha %.2f", level * 2, "", mPrimitiveFields.mAlpha);
} else {
- int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
- if (clipToBoundsNeeded) {
- flags |= SkCanvas::kClipToLayer_SaveFlag;
- clipToBoundsNeeded = false; // clipping done by save layer
+ Rect layerBounds(0, 0, getWidth(), getHeight());
+ int saveFlags = SkCanvas::kHasAlphaLayer_SaveFlag;
+ if (clipFlags) {
+ saveFlags |= SkCanvas::kClipToLayer_SaveFlag;
+ getClippingRectForFlags(clipFlags, &layerBounds);
+ clipFlags = 0; // all clipping done by saveLayer
}
+
ALOGD("%*sSaveLayerAlpha %d, %d, %d, %d, %d, 0x%x", level * 2, "",
- 0, 0, getWidth(), getHeight(),
- (int)(mPrimitiveFields.mAlpha * 255), flags);
+ (int)layerBounds.left, (int)layerBounds.top, (int)layerBounds.right, (int)layerBounds.bottom,
+ (int)(mPrimitiveFields.mAlpha * 255), saveFlags);
}
}
- if (clipToBoundsNeeded) {
+ if (clipFlags) {
+ Rect clipRect;
+ getClippingRectForFlags(clipFlags, &clipRect);
ALOGD("%*sClipRect %d, %d, %d, %d", level * 2, "",
- 0, 0, getWidth(), getHeight());
+ (int)clipRect.left, (int)clipRect.top, (int)clipRect.right, (int)clipRect.bottom);
}
}
diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h
index 227d56e..f50e514 100644
--- a/libs/hwui/RenderProperties.h
+++ b/libs/hwui/RenderProperties.h
@@ -58,6 +58,11 @@ enum LayerType {
// TODO: LayerTypeSurfaceTexture? Maybe?
};
+enum ClippingFlags {
+ CLIP_TO_BOUNDS = 0x1 << 0,
+ CLIP_TO_CLIP_BOUNDS = 0x1 << 1,
+};
+
class ANDROID_API LayerProperties {
public:
bool setType(LayerType type) {
@@ -135,10 +140,35 @@ public:
RenderProperties();
virtual ~RenderProperties();
+ static bool setFlag(int flag, bool newValue, int* outFlags) {
+ if (newValue) {
+ if (!(flag & *outFlags)) {
+ *outFlags |= flag;
+ return true;
+ }
+ return false;
+ } else {
+ if (flag & *outFlags) {
+ *outFlags &= ~flag;
+ return true;
+ }
+ return false;
+ }
+ }
+
RenderProperties& operator=(const RenderProperties& other);
bool setClipToBounds(bool clipToBounds) {
- return RP_SET(mPrimitiveFields.mClipToBounds, clipToBounds);
+ return setFlag(CLIP_TO_BOUNDS, clipToBounds, &mPrimitiveFields.mClippingFlags);
+ }
+
+ bool setClipBounds(const Rect& clipBounds) {
+ bool ret = setFlag(CLIP_TO_CLIP_BOUNDS, true, &mPrimitiveFields.mClippingFlags);
+ return RP_SET(mPrimitiveFields.mClipBounds, clipBounds) || ret;
+ }
+
+ bool setClipBoundsEmpty() {
+ return setFlag(CLIP_TO_CLIP_BOUNDS, false, &mPrimitiveFields.mClippingFlags);
}
bool setProjectBackwards(bool shouldProject) {
@@ -433,7 +463,7 @@ public:
return false;
}
- bool offsetLeftRight(float offset) {
+ bool offsetLeftRight(int offset) {
if (offset != 0) {
mPrimitiveFields.mLeft += offset;
mPrimitiveFields.mRight += offset;
@@ -442,7 +472,7 @@ public:
return false;
}
- bool offsetTopBottom(float offset) {
+ bool offsetTopBottom(int offset) {
if (offset != 0) {
mPrimitiveFields.mTop += offset;
mPrimitiveFields.mBottom += offset;
@@ -477,8 +507,23 @@ public:
return mComputedFields.mTransformMatrix;
}
+ int getClippingFlags() const {
+ return mPrimitiveFields.mClippingFlags;
+ }
+
bool getClipToBounds() const {
- return mPrimitiveFields.mClipToBounds;
+ return mPrimitiveFields.mClippingFlags & CLIP_TO_BOUNDS;
+ }
+
+ void getClippingRectForFlags(uint32_t flags, Rect* outRect) const {
+ if (flags & CLIP_TO_BOUNDS) {
+ outRect->set(0, 0, getWidth(), getHeight());
+ if (flags & CLIP_TO_CLIP_BOUNDS) {
+ outRect->intersect(mPrimitiveFields.mClipBounds);
+ }
+ } else {
+ outRect->set(mPrimitiveFields.mClipBounds);
+ }
}
bool getHasOverlappingRendering() const {
@@ -540,14 +585,13 @@ public:
}
private:
-
// Rendering properties
struct PrimitiveFields {
PrimitiveFields();
Outline mOutline;
RevealClip mRevealClip;
- bool mClipToBounds;
+ int mClippingFlags;
bool mProjectBackwards;
bool mProjectionReceiver;
float mAlpha;
@@ -561,6 +605,7 @@ private:
int mWidth, mHeight;
bool mPivotExplicitlySet;
bool mMatrixOrPivotDirty;
+ Rect mClipBounds;
} mPrimitiveFields;
SkMatrix* mStaticMatrix;