Merge "Add stagingProperties"

This commit is contained in:
John Reck
2014-03-24 22:34:46 +00:00
committed by Android (Google) Code Review
8 changed files with 492 additions and 391 deletions

View File

@@ -75,123 +75,123 @@ static void android_view_RenderNode_destroyDisplayList(JNIEnv* env,
static void android_view_RenderNode_setCaching(JNIEnv* env,
jobject clazz, jlong displayListPtr, jboolean caching) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
displayList->properties().setCaching(caching);
displayList->mutateStagingProperties().setCaching(caching);
}
static void android_view_RenderNode_setStaticMatrix(JNIEnv* env,
jobject clazz, jlong displayListPtr, jlong matrixPtr) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
displayList->properties().setStaticMatrix(matrix);
displayList->mutateStagingProperties().setStaticMatrix(matrix);
}
static void android_view_RenderNode_setAnimationMatrix(JNIEnv* env,
jobject clazz, jlong displayListPtr, jlong matrixPtr) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
displayList->properties().setAnimationMatrix(matrix);
displayList->mutateStagingProperties().setAnimationMatrix(matrix);
}
static void android_view_RenderNode_setClipToBounds(JNIEnv* env,
jobject clazz, jlong displayListPtr, jboolean clipToBounds) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
displayList->properties().setClipToBounds(clipToBounds);
displayList->mutateStagingProperties().setClipToBounds(clipToBounds);
}
static void android_view_RenderNode_setProjectBackwards(JNIEnv* env,
jobject clazz, jlong displayListPtr, jboolean shouldProject) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
displayList->properties().setProjectBackwards(shouldProject);
displayList->mutateStagingProperties().setProjectBackwards(shouldProject);
}
static void android_view_RenderNode_setProjectionReceiver(JNIEnv* env,
jobject clazz, jlong displayListPtr, jboolean shouldRecieve) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
displayList->properties().setProjectionReceiver(shouldRecieve);
displayList->mutateStagingProperties().setProjectionReceiver(shouldRecieve);
}
static void android_view_RenderNode_setOutlineRoundRect(JNIEnv* env,
jobject clazz, jlong displayListPtr, jint left, jint top,
jint right, jint bottom, jfloat radius) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
displayList->properties().outline().setRoundRect(left, top, right, bottom, radius);
displayList->mutateStagingProperties().mutableOutline().setRoundRect(left, top, right, bottom, radius);
}
static void android_view_RenderNode_setOutlineConvexPath(JNIEnv* env,
jobject clazz, jlong displayListPtr, jlong outlinePathPtr) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
SkPath* outlinePath = reinterpret_cast<SkPath*>(outlinePathPtr);
displayList->properties().outline().setConvexPath(outlinePath);
displayList->mutateStagingProperties().mutableOutline().setConvexPath(outlinePath);
}
static void android_view_RenderNode_setOutlineEmpty(JNIEnv* env,
jobject clazz, jlong displayListPtr) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
displayList->properties().outline().setEmpty();
displayList->mutateStagingProperties().mutableOutline().setEmpty();
}
static void android_view_RenderNode_setClipToOutline(JNIEnv* env,
jobject clazz, jlong displayListPtr, jboolean clipToOutline) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
displayList->properties().outline().setShouldClip(clipToOutline);
displayList->mutateStagingProperties().mutableOutline().setShouldClip(clipToOutline);
}
static void android_view_RenderNode_setAlpha(JNIEnv* env,
jobject clazz, jlong displayListPtr, float alpha) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
displayList->properties().setAlpha(alpha);
displayList->mutateStagingProperties().setAlpha(alpha);
}
static void android_view_RenderNode_setHasOverlappingRendering(JNIEnv* env,
jobject clazz, jlong displayListPtr, bool hasOverlappingRendering) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
displayList->properties().setHasOverlappingRendering(hasOverlappingRendering);
displayList->mutateStagingProperties().setHasOverlappingRendering(hasOverlappingRendering);
}
static void android_view_RenderNode_setTranslationX(JNIEnv* env,
jobject clazz, jlong displayListPtr, float tx) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
displayList->properties().setTranslationX(tx);
displayList->mutateStagingProperties().setTranslationX(tx);
}
static void android_view_RenderNode_setTranslationY(JNIEnv* env,
jobject clazz, jlong displayListPtr, float ty) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
displayList->properties().setTranslationY(ty);
displayList->mutateStagingProperties().setTranslationY(ty);
}
static void android_view_RenderNode_setTranslationZ(JNIEnv* env,
jobject clazz, jlong displayListPtr, float tz) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
displayList->properties().setTranslationZ(tz);
displayList->mutateStagingProperties().setTranslationZ(tz);
}
static void android_view_RenderNode_setRotation(JNIEnv* env,
jobject clazz, jlong displayListPtr, float rotation) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
displayList->properties().setRotation(rotation);
displayList->mutateStagingProperties().setRotation(rotation);
}
static void android_view_RenderNode_setRotationX(JNIEnv* env,
jobject clazz, jlong displayListPtr, float rx) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
displayList->properties().setRotationX(rx);
displayList->mutateStagingProperties().setRotationX(rx);
}
static void android_view_RenderNode_setRotationY(JNIEnv* env,
jobject clazz, jlong displayListPtr, float ry) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
displayList->properties().setRotationY(ry);
displayList->mutateStagingProperties().setRotationY(ry);
}
static void android_view_RenderNode_setScaleX(JNIEnv* env,
jobject clazz, jlong displayListPtr, float sx) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
displayList->properties().setScaleX(sx);
displayList->mutateStagingProperties().setScaleX(sx);
}
static void android_view_RenderNode_setScaleY(JNIEnv* env,
jobject clazz, jlong displayListPtr, float sy) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
displayList->properties().setScaleY(sy);
displayList->mutateStagingProperties().setScaleY(sy);
}
static void android_view_RenderNode_setTransformationInfo(JNIEnv* env,
@@ -199,172 +199,174 @@ static void android_view_RenderNode_setTransformationInfo(JNIEnv* env,
float translationX, float translationY, float translationZ,
float rotation, float rotationX, float rotationY, float scaleX, float scaleY) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
displayList->properties().setAlpha(alpha);
displayList->properties().setTranslationX(translationX);
displayList->properties().setTranslationY(translationY);
displayList->properties().setTranslationZ(translationZ);
displayList->properties().setRotation(rotation);
displayList->properties().setRotationX(rotationX);
displayList->properties().setRotationY(rotationY);
displayList->properties().setScaleX(scaleX);
displayList->properties().setScaleY(scaleY);
displayList->mutateStagingProperties().setAlpha(alpha);
displayList->mutateStagingProperties().setTranslationX(translationX);
displayList->mutateStagingProperties().setTranslationY(translationY);
displayList->mutateStagingProperties().setTranslationZ(translationZ);
displayList->mutateStagingProperties().setRotation(rotation);
displayList->mutateStagingProperties().setRotationX(rotationX);
displayList->mutateStagingProperties().setRotationY(rotationY);
displayList->mutateStagingProperties().setScaleX(scaleX);
displayList->mutateStagingProperties().setScaleY(scaleY);
}
static void android_view_RenderNode_setPivotX(JNIEnv* env,
jobject clazz, jlong displayListPtr, float px) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
displayList->properties().setPivotX(px);
displayList->mutateStagingProperties().setPivotX(px);
}
static void android_view_RenderNode_setPivotY(JNIEnv* env,
jobject clazz, jlong displayListPtr, float py) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
displayList->properties().setPivotY(py);
displayList->mutateStagingProperties().setPivotY(py);
}
static void android_view_RenderNode_setCameraDistance(JNIEnv* env,
jobject clazz, jlong displayListPtr, float distance) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
displayList->properties().setCameraDistance(distance);
displayList->mutateStagingProperties().setCameraDistance(distance);
}
static void android_view_RenderNode_setLeft(JNIEnv* env,
jobject clazz, jlong displayListPtr, int left) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
displayList->properties().setLeft(left);
displayList->mutateStagingProperties().setLeft(left);
}
static void android_view_RenderNode_setTop(JNIEnv* env,
jobject clazz, jlong displayListPtr, int top) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
displayList->properties().setTop(top);
displayList->mutateStagingProperties().setTop(top);
}
static void android_view_RenderNode_setRight(JNIEnv* env,
jobject clazz, jlong displayListPtr, int right) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
displayList->properties().setRight(right);
displayList->mutateStagingProperties().setRight(right);
}
static void android_view_RenderNode_setBottom(JNIEnv* env,
jobject clazz, jlong displayListPtr, int bottom) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
displayList->properties().setBottom(bottom);
displayList->mutateStagingProperties().setBottom(bottom);
}
static void android_view_RenderNode_setLeftTopRightBottom(JNIEnv* env,
jobject clazz, jlong displayListPtr, int left, int top,
int right, int bottom) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
displayList->properties().setLeftTopRightBottom(left, top, right, bottom);
displayList->mutateStagingProperties().setLeftTopRightBottom(left, top, right, bottom);
}
static void android_view_RenderNode_offsetLeftAndRight(JNIEnv* env,
jobject clazz, jlong displayListPtr, float offset) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
displayList->properties().offsetLeftRight(offset);
displayList->mutateStagingProperties().offsetLeftRight(offset);
}
static void android_view_RenderNode_offsetTopAndBottom(JNIEnv* env,
jobject clazz, jlong displayListPtr, float offset) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
displayList->properties().offsetTopBottom(offset);
displayList->mutateStagingProperties().offsetTopBottom(offset);
}
static jboolean android_view_RenderNode_hasOverlappingRendering(JNIEnv* env,
jobject clazz, jlong displayListPtr) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
return displayList->properties().hasOverlappingRendering();
return displayList->stagingProperties().hasOverlappingRendering();
}
static jfloat android_view_RenderNode_getAlpha(JNIEnv* env,
jobject clazz, jlong displayListPtr) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
return displayList->properties().getAlpha();
return displayList->stagingProperties().getAlpha();
}
static jfloat android_view_RenderNode_getLeft(JNIEnv* env,
jobject clazz, jlong displayListPtr) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
return displayList->properties().getLeft();
return displayList->stagingProperties().getLeft();
}
static jfloat android_view_RenderNode_getTop(JNIEnv* env,
jobject clazz, jlong displayListPtr) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
return displayList->properties().getTop();
return displayList->stagingProperties().getTop();
}
static jfloat android_view_RenderNode_getRight(JNIEnv* env,
jobject clazz, jlong displayListPtr) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
return displayList->properties().getRight();
return displayList->stagingProperties().getRight();
}
static jfloat android_view_RenderNode_getBottom(JNIEnv* env,
jobject clazz, jlong displayListPtr) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
return displayList->properties().getBottom();
return displayList->stagingProperties().getBottom();
}
static jfloat android_view_RenderNode_getCameraDistance(JNIEnv* env,
jobject clazz, jlong displayListPtr) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
return displayList->properties().getCameraDistance();
return displayList->stagingProperties().getCameraDistance();
}
static jfloat android_view_RenderNode_getScaleX(JNIEnv* env,
jobject clazz, jlong displayListPtr) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
return displayList->properties().getScaleX();
return displayList->stagingProperties().getScaleX();
}
static jfloat android_view_RenderNode_getScaleY(JNIEnv* env,
jobject clazz, jlong displayListPtr) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
return displayList->properties().getScaleY();
return displayList->stagingProperties().getScaleY();
}
static jfloat android_view_RenderNode_getTranslationX(JNIEnv* env,
jobject clazz, jlong displayListPtr) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
return displayList->properties().getTranslationX();
return displayList->stagingProperties().getTranslationX();
}
static jfloat android_view_RenderNode_getTranslationY(JNIEnv* env,
jobject clazz, jlong displayListPtr) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
return displayList->properties().getTranslationY();
return displayList->stagingProperties().getTranslationY();
}
static jfloat android_view_RenderNode_getRotation(JNIEnv* env,
jobject clazz, jlong displayListPtr) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
return displayList->properties().getRotation();
return displayList->stagingProperties().getRotation();
}
static jfloat android_view_RenderNode_getRotationX(JNIEnv* env,
jobject clazz, jlong displayListPtr) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
return displayList->properties().getRotationX();
return displayList->stagingProperties().getRotationX();
}
static jfloat android_view_RenderNode_getRotationY(JNIEnv* env,
jobject clazz, jlong displayListPtr) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
return displayList->properties().getRotationY();
return displayList->stagingProperties().getRotationY();
}
static jfloat android_view_RenderNode_getPivotX(JNIEnv* env,
jobject clazz, jlong displayListPtr) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
return displayList->properties().getPivotX();
displayList->mutateStagingProperties().updateMatrix();
return displayList->stagingProperties().getPivotX();
}
static jfloat android_view_RenderNode_getPivotY(JNIEnv* env,
jobject clazz, jlong displayListPtr) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
return displayList->properties().getPivotY();
displayList->mutateStagingProperties().updateMatrix();
return displayList->stagingProperties().getPivotY();
}
#endif // USE_OPENGL_RENDERER

View File

@@ -200,6 +200,7 @@ void Layer::defer() {
renderer->setupFrameState(dirtyRect.left, dirtyRect.top,
dirtyRect.right, dirtyRect.bottom, !isBlend());
displayList->updateProperties();
displayList->computeOrdering();
displayList->defer(deferredState, 0);

View File

@@ -1919,6 +1919,7 @@ status_t OpenGLRenderer::drawDisplayList(RenderNode* displayList, Rect& dirty,
// will be performed by the display list itself
if (displayList && displayList->isRenderable()) {
// compute 3d ordering
displayList->updateProperties();
displayList->computeOrdering();
if (CC_UNLIKELY(mCaches.drawDeferDisabled)) {
status = startFrame();

View File

@@ -64,7 +64,7 @@ public:
return mShouldClip && (mType == kOutlineType_RoundRect);
}
const SkPath* getPath() {
const SkPath* getPath() const {
if (mType == kOutlineType_None) return NULL;
return &mPath;

View File

@@ -49,7 +49,7 @@ void RenderNode::outputLogBuffer(int fd) {
fflush(file);
}
RenderNode::RenderNode() : mDestroyed(false), mDisplayListData(0) {
RenderNode::RenderNode() : mDestroyed(false), mNeedsPropertiesSync(false), mDisplayListData(0) {
}
RenderNode::~RenderNode() {
@@ -84,7 +84,7 @@ void RenderNode::output(uint32_t level) {
ALOGD("%*s%s %d", level * 2, "", "Save",
SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
outputViewProperties(level);
properties().debugOutputProperties(level);
int flags = DisplayListOp::kOpLogFlag_Recurse;
for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) {
mDisplayListData->displayListOps[i]->output(level, flags);
@@ -93,56 +93,22 @@ void RenderNode::output(uint32_t level) {
ALOGD("%*sDone (%p, %s)", (level - 1) * 2, "", this, mName.string());
}
void RenderNode::outputViewProperties(const int level) {
properties().updateMatrix();
if (properties().mLeft != 0 || properties().mTop != 0) {
ALOGD("%*sTranslate (left, top) %d, %d", level * 2, "", properties().mLeft, properties().mTop);
}
if (properties().mStaticMatrix) {
ALOGD("%*sConcatMatrix (static) %p: " SK_MATRIX_STRING,
level * 2, "", properties().mStaticMatrix, SK_MATRIX_ARGS(properties().mStaticMatrix));
}
if (properties().mAnimationMatrix) {
ALOGD("%*sConcatMatrix (animation) %p: " SK_MATRIX_STRING,
level * 2, "", properties().mAnimationMatrix, SK_MATRIX_ARGS(properties().mAnimationMatrix));
}
if (properties().mMatrixFlags != 0) {
if (properties().mMatrixFlags == TRANSLATION) {
ALOGD("%*sTranslate %.2f, %.2f, %.2f",
level * 2, "", properties().mTranslationX, properties().mTranslationY, properties().mTranslationZ);
} else {
ALOGD("%*sConcatMatrix %p: " MATRIX_4_STRING,
level * 2, "", properties().mTransformMatrix, MATRIX_4_ARGS(properties().mTransformMatrix));
}
void RenderNode::updateProperties() {
if (mNeedsPropertiesSync) {
mNeedsPropertiesSync = false;
mProperties = mStagingProperties;
}
bool clipToBoundsNeeded = properties().mCaching ? false : properties().mClipToBounds;
if (properties().mAlpha < 1) {
if (properties().mCaching) {
ALOGD("%*sSetOverrideLayerAlpha %.2f", level * 2, "", properties().mAlpha);
} else if (!properties().mHasOverlappingRendering) {
ALOGD("%*sScaleAlpha %.2f", level * 2, "", properties().mAlpha);
} else {
int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
if (clipToBoundsNeeded) {
flags |= SkCanvas::kClipToLayer_SaveFlag;
clipToBoundsNeeded = false; // clipping done by save layer
}
ALOGD("%*sSaveLayerAlpha %d, %d, %d, %d, %d, 0x%x", level * 2, "",
0, 0, properties().mWidth, properties().mHeight,
(int)(properties().mAlpha * 255), flags);
}
}
if (clipToBoundsNeeded) {
ALOGD("%*sClipRect %d, %d, %d, %d", level * 2, "",
0, 0, properties().mWidth, properties().mHeight);
for (size_t i = 0; i < mDisplayListData->children.size(); i++) {
RenderNode* childNode = mDisplayListData->children[i]->mDisplayList;
childNode->updateProperties();
}
}
/*
* For property operations, we pass a savecount of 0, since the operations aren't part of the
* displaylist, and thus don't have to compensate for the record-time/playback-time discrepancy in
* base saveCount (i.e., how RestoreToCount uses saveCount + properties().mCount)
* base saveCount (i.e., how RestoreToCount uses saveCount + properties().getCount())
*/
#define PROPERTY_SAVECOUNT 0
@@ -150,30 +116,29 @@ template <class T>
void RenderNode::setViewProperties(OpenGLRenderer& renderer, T& handler,
const int level) {
#if DEBUG_DISPLAY_LIST
outputViewProperties(level);
properties().debugOutputProperties(level);
#endif
properties().updateMatrix();
if (properties().mLeft != 0 || properties().mTop != 0) {
renderer.translate(properties().mLeft, properties().mTop);
if (properties().getLeft() != 0 || properties().getTop() != 0) {
renderer.translate(properties().getLeft(), properties().getTop());
}
if (properties().mStaticMatrix) {
renderer.concatMatrix(properties().mStaticMatrix);
} else if (properties().mAnimationMatrix) {
renderer.concatMatrix(properties().mAnimationMatrix);
if (properties().getStaticMatrix()) {
renderer.concatMatrix(properties().getStaticMatrix());
} else if (properties().getAnimationMatrix()) {
renderer.concatMatrix(properties().getAnimationMatrix());
}
if (properties().mMatrixFlags != 0) {
if (properties().mMatrixFlags == TRANSLATION) {
renderer.translate(properties().mTranslationX, properties().mTranslationY);
if (properties().getMatrixFlags() != 0) {
if (properties().getMatrixFlags() == TRANSLATION) {
renderer.translate(properties().getTranslationX(), properties().getTranslationY());
} else {
renderer.concatMatrix(*properties().mTransformMatrix);
renderer.concatMatrix(*properties().getTransformMatrix());
}
}
bool clipToBoundsNeeded = properties().mCaching ? false : properties().mClipToBounds;
if (properties().mAlpha < 1) {
if (properties().mCaching) {
renderer.setOverrideLayerAlpha(properties().mAlpha);
} else if (!properties().mHasOverlappingRendering) {
renderer.scaleAlpha(properties().mAlpha);
bool clipToBoundsNeeded = properties().getCaching() ? false : properties().getClipToBounds();
if (properties().getAlpha() < 1) {
if (properties().getCaching()) {
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
@@ -185,21 +150,19 @@ void RenderNode::setViewProperties(OpenGLRenderer& renderer, T& handler,
}
SaveLayerOp* op = new (handler.allocator()) SaveLayerOp(
0, 0, properties().mWidth, properties().mHeight,
properties().mAlpha * 255, saveFlags);
handler(op, PROPERTY_SAVECOUNT, properties().mClipToBounds);
0, 0, properties().getWidth(), properties().getHeight(), properties().getAlpha() * 255, saveFlags);
handler(op, PROPERTY_SAVECOUNT, properties().getClipToBounds());
}
}
if (clipToBoundsNeeded) {
ClipRectOp* op = new (handler.allocator()) ClipRectOp(
0, 0, properties().mWidth, properties().mHeight, SkRegion::kIntersect_Op);
handler(op, PROPERTY_SAVECOUNT, properties().mClipToBounds);
ClipRectOp* op = new (handler.allocator()) ClipRectOp(0, 0,
properties().getWidth(), properties().getHeight(), SkRegion::kIntersect_Op);
handler(op, PROPERTY_SAVECOUNT, properties().getClipToBounds());
}
if (CC_UNLIKELY(properties().mOutline.willClip())) {
// TODO: optimize RR case
ClipPathOp* op = new (handler.allocator()) ClipPathOp(properties().mOutline.getPath(),
if (CC_UNLIKELY(properties().getOutline().willClip())) {
ClipPathOp* op = new (handler.allocator()) ClipPathOp(properties().getOutline().getPath(),
SkRegion::kIntersect_Op);
handler(op, PROPERTY_SAVECOUNT, properties().mClipToBounds);
handler(op, PROPERTY_SAVECOUNT, properties().getClipToBounds());
}
}
@@ -210,35 +173,34 @@ void RenderNode::setViewProperties(OpenGLRenderer& renderer, T& handler,
* matrix computation instead of the Skia 3x3 matrix + camera hackery.
*/
void RenderNode::applyViewPropertyTransforms(mat4& matrix, bool true3dTransform) {
if (properties().mLeft != 0 || properties().mTop != 0) {
matrix.translate(properties().mLeft, properties().mTop);
if (properties().getLeft() != 0 || properties().getTop() != 0) {
matrix.translate(properties().getLeft(), properties().getTop());
}
if (properties().mStaticMatrix) {
mat4 stat(*properties().mStaticMatrix);
if (properties().getStaticMatrix()) {
mat4 stat(*properties().getStaticMatrix());
matrix.multiply(stat);
} else if (properties().mAnimationMatrix) {
mat4 anim(*properties().mAnimationMatrix);
} else if (properties().getAnimationMatrix()) {
mat4 anim(*properties().getAnimationMatrix());
matrix.multiply(anim);
}
if (properties().mMatrixFlags != 0) {
properties().updateMatrix();
if (properties().mMatrixFlags == TRANSLATION) {
matrix.translate(properties().mTranslationX, properties().mTranslationY,
true3dTransform ? properties().mTranslationZ : 0.0f);
if (properties().getMatrixFlags() != 0) {
if (properties().getMatrixFlags() == TRANSLATION) {
matrix.translate(properties().getTranslationX(), properties().getTranslationY(),
true3dTransform ? properties().getTranslationZ() : 0.0f);
} else {
if (!true3dTransform) {
matrix.multiply(*properties().mTransformMatrix);
matrix.multiply(*properties().getTransformMatrix());
} else {
mat4 true3dMat;
true3dMat.loadTranslate(
properties().mPivotX + properties().mTranslationX,
properties().mPivotY + properties().mTranslationY,
properties().mTranslationZ);
true3dMat.rotate(properties().mRotationX, 1, 0, 0);
true3dMat.rotate(properties().mRotationY, 0, 1, 0);
true3dMat.rotate(properties().mRotation, 0, 0, 1);
true3dMat.scale(properties().mScaleX, properties().mScaleY, 1);
true3dMat.translate(-properties().mPivotX, -properties().mPivotY);
properties().getPivotX() + properties().getTranslationX(),
properties().getPivotY() + properties().getTranslationY(),
properties().getTranslationZ());
true3dMat.rotate(properties().getRotationX(), 1, 0, 0);
true3dMat.rotate(properties().getRotationY(), 0, 1, 0);
true3dMat.rotate(properties().getRotation(), 0, 0, 1);
true3dMat.scale(properties().getScaleX(), properties().getScaleY(), 1);
true3dMat.translate(-properties().getPivotX(), -properties().getPivotY());
matrix.multiply(true3dMat);
}
@@ -280,7 +242,7 @@ void RenderNode::computeOrderingImpl(
Matrix4 localTransformFromProjectionSurface(*transformFromProjectionSurface);
localTransformFromProjectionSurface.multiply(opState->mTransformFromParent);
if (properties().mProjectBackwards) {
if (properties().getProjectBackwards()) {
// composited projectee, flag for out of order draw, save matrix, and store in proj surface
opState->mSkipInOrderDraw = true;
opState->mTransformFromCompositingAncestor.load(localTransformFromProjectionSurface);
@@ -299,7 +261,7 @@ void RenderNode::computeOrderingImpl(
Vector<DrawDisplayListOp*>* projectionChildren = NULL;
const mat4* projectionTransform = NULL;
if (isProjectionReceiver && !child->properties().mProjectBackwards) {
if (isProjectionReceiver && !child->properties().getProjectBackwards()) {
// if receiving projections, collect projecting descendent
// Note that if a direct descendent is projecting backwards, we pass it's
@@ -346,7 +308,7 @@ public:
: mReplayStruct(replayStruct), mLevel(level) {}
inline void operator()(DisplayListOp* operation, int saveCount, bool clipToBounds) {
#if DEBUG_DISPLAY_LIST_OPS_AS_EVENTS
properties().mReplayStruct.mRenderer.eventMark(operation->name());
properties().getReplayStruct().mRenderer.eventMark(operation->name());
#endif
operation->replay(mReplayStruct, saveCount, mLevel, clipToBounds);
}
@@ -374,12 +336,12 @@ void RenderNode::buildZSortedChildList(Vector<ZDrawDisplayListOpPair>& zTranslat
for (unsigned int i = 0; i < mDisplayListData->children.size(); i++) {
DrawDisplayListOp* childOp = mDisplayListData->children[i];
RenderNode* child = childOp->mDisplayList;
float childZ = child->properties().mTranslationZ;
float childZ = child->properties().getTranslationZ();
if (childZ != 0.0f) {
zTranslatedNodes.add(ZDrawDisplayListOpPair(childZ, childOp));
childOp->mSkipInOrderDraw = true;
} else if (!child->properties().mProjectBackwards) {
} else if (!child->properties().getProjectBackwards()) {
// regular, in order drawing DisplayList
childOp->mSkipInOrderDraw = false;
}
@@ -404,9 +366,9 @@ void RenderNode::iterate3dChildren(const Vector<ZDrawDisplayListOpPair>& zTransl
int rootRestoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
LinearAllocator& alloc = handler.allocator();
ClipRectOp* clipOp = new (alloc) ClipRectOp(0, 0, properties().mWidth, properties().mHeight,
ClipRectOp* clipOp = new (alloc) ClipRectOp(0, 0, properties().getWidth(), properties().getHeight(),
SkRegion::kIntersect_Op); // clip to 3d root bounds
handler(clipOp, PROPERTY_SAVECOUNT, properties().mClipToBounds);
handler(clipOp, PROPERTY_SAVECOUNT, properties().getClipToBounds());
/**
* Draw shadows and (potential) casters mostly in order, but allow the shadows of casters
@@ -436,7 +398,7 @@ void RenderNode::iterate3dChildren(const Vector<ZDrawDisplayListOpPair>& zTransl
// OR if its caster's Z value is similar to the previous potential caster
if (shadowIndex == drawIndex || casterZ - lastCasterZ < SHADOW_DELTA) {
if (caster->properties().mAlpha > 0.0f) {
if (caster->properties().getAlpha() > 0.0f) {
mat4 shadowMatrixXY(casterOp->mTransformFromParent);
caster->applyViewPropertyTransforms(shadowMatrixXY);
@@ -446,9 +408,9 @@ void RenderNode::iterate3dChildren(const Vector<ZDrawDisplayListOpPair>& zTransl
DisplayListOp* shadowOp = new (alloc) DrawShadowOp(
shadowMatrixXY, shadowMatrixZ,
caster->properties().mAlpha, caster->properties().mOutline.getPath(),
caster->properties().mWidth, caster->properties().mHeight);
handler(shadowOp, PROPERTY_SAVECOUNT, properties().mClipToBounds);
caster->properties().getAlpha(), caster->properties().getOutline().getPath(),
caster->properties().getWidth(), caster->properties().getHeight());
handler(shadowOp, PROPERTY_SAVECOUNT, properties().getClipToBounds());
}
lastCasterZ = casterZ; // must do this even if current caster not casting a shadow
@@ -466,22 +428,22 @@ void RenderNode::iterate3dChildren(const Vector<ZDrawDisplayListOpPair>& zTransl
renderer.concatMatrix(childOp->mTransformFromParent);
childOp->mSkipInOrderDraw = false; // this is horrible, I'm so sorry everyone
handler(childOp, renderer.getSaveCount() - 1, properties().mClipToBounds);
handler(childOp, renderer.getSaveCount() - 1, properties().getClipToBounds());
childOp->mSkipInOrderDraw = true;
renderer.restoreToCount(restoreTo);
drawIndex++;
}
handler(new (alloc) RestoreToCountOp(rootRestoreTo), PROPERTY_SAVECOUNT, properties().mClipToBounds);
handler(new (alloc) RestoreToCountOp(rootRestoreTo), PROPERTY_SAVECOUNT, properties().getClipToBounds());
}
template <class T>
void RenderNode::iterateProjectedChildren(OpenGLRenderer& renderer, T& handler, const int level) {
int rootRestoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
LinearAllocator& alloc = handler.allocator();
ClipRectOp* clipOp = new (alloc) ClipRectOp(0, 0, properties().mWidth, properties().mHeight,
ClipRectOp* clipOp = new (alloc) ClipRectOp(0, 0, properties().getWidth(), properties().getHeight(),
SkRegion::kReplace_Op); // clip to projection surface root bounds
handler(clipOp, PROPERTY_SAVECOUNT, properties().mClipToBounds);
handler(clipOp, PROPERTY_SAVECOUNT, properties().getClipToBounds());
for (size_t i = 0; i < mProjectedNodes.size(); i++) {
DrawDisplayListOp* childOp = mProjectedNodes[i];
@@ -490,11 +452,11 @@ void RenderNode::iterateProjectedChildren(OpenGLRenderer& renderer, T& handler,
int restoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag);
renderer.concatMatrix(childOp->mTransformFromCompositingAncestor);
childOp->mSkipInOrderDraw = false; // this is horrible, I'm so sorry everyone
handler(childOp, renderer.getSaveCount() - 1, properties().mClipToBounds);
handler(childOp, renderer.getSaveCount() - 1, properties().getClipToBounds());
childOp->mSkipInOrderDraw = true;
renderer.restoreToCount(restoreTo);
}
handler(new (alloc) RestoreToCountOp(rootRestoreTo), PROPERTY_SAVECOUNT, properties().mClipToBounds);
handler(new (alloc) RestoreToCountOp(rootRestoreTo), PROPERTY_SAVECOUNT, properties().getClipToBounds());
}
/**
@@ -512,7 +474,7 @@ void RenderNode::iterate(OpenGLRenderer& renderer, T& handler, const int level)
ALOGW("Error: %s is drawing after destruction", mName.string());
CRASH();
}
if (mDisplayListData->isEmpty() || properties().mAlpha <= 0) {
if (mDisplayListData->isEmpty() || properties().getAlpha() <= 0) {
DISPLAY_LIST_LOGD("%*sEmpty display list (%p, %s)", level * 2, "", this, mName.string());
return;
}
@@ -527,14 +489,14 @@ void RenderNode::iterate(OpenGLRenderer& renderer, T& handler, const int level)
LinearAllocator& alloc = handler.allocator();
int restoreTo = renderer.getSaveCount();
handler(new (alloc) SaveOp(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag),
PROPERTY_SAVECOUNT, properties().mClipToBounds);
PROPERTY_SAVECOUNT, properties().getClipToBounds());
DISPLAY_LIST_LOGD("%*sSave %d %d", (level + 1) * 2, "",
SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag, restoreTo);
setViewProperties<T>(renderer, handler, level + 1);
bool quickRejected = properties().mClipToBounds && renderer.quickRejectConservative(0, 0, properties().mWidth, properties().mHeight);
bool quickRejected = properties().getClipToBounds() && renderer.quickRejectConservative(0, 0, properties().getWidth(), properties().getHeight());
if (!quickRejected) {
Vector<ZDrawDisplayListOpPair> zTranslatedNodes;
buildZSortedChildList(zTranslatedNodes);
@@ -553,7 +515,7 @@ void RenderNode::iterate(OpenGLRenderer& renderer, T& handler, const int level)
#endif
logBuffer.writeCommand(level, op->name());
handler(op, saveCountOffset, properties().mClipToBounds);
handler(op, saveCountOffset, properties().getClipToBounds());
if (CC_UNLIKELY(i == projectionReceiveIndex && mProjectedNodes.size() > 0)) {
iterateProjectedChildren(renderer, handler, level);
@@ -566,7 +528,7 @@ void RenderNode::iterate(OpenGLRenderer& renderer, T& handler, const int level)
DISPLAY_LIST_LOGD("%*sRestoreToCount %d", (level + 1) * 2, "", restoreTo);
handler(new (alloc) RestoreToCountOp(restoreTo),
PROPERTY_SAVECOUNT, properties().mClipToBounds);
PROPERTY_SAVECOUNT, properties().getClipToBounds());
renderer.setOverrideLayerAlpha(1.0f);
}

View File

@@ -112,10 +112,19 @@ public:
}
}
RenderProperties& properties() {
const RenderProperties& properties() {
return mProperties;
}
const RenderProperties& stagingProperties() {
return mStagingProperties;
}
RenderProperties& mutateStagingProperties() {
mNeedsPropertiesSync = true;
return mStagingProperties;
}
bool isProjectionReceiver() {
return properties().isProjectionReceiver();
}
@@ -128,6 +137,8 @@ public:
return properties().getHeight();
}
void updateProperties();
private:
typedef key_value_pair_t<float, DrawDisplayListOp*> ZDrawDisplayListOpPair;
@@ -143,8 +154,6 @@ private:
kPositiveZChildren
};
void outputViewProperties(const int level);
void applyViewPropertyTransforms(mat4& matrix, bool true3dTransform = false);
void computeOrderingImpl(DrawDisplayListOp* opState,
@@ -183,7 +192,10 @@ private:
String8 mName;
bool mDestroyed; // used for debugging crash, TODO: remove once invalid state crash fixed
bool mNeedsPropertiesSync;
RenderProperties mProperties;
RenderProperties mStagingProperties;
DisplayListData* mDisplayListData;
/**

View File

@@ -2,8 +2,8 @@
* Copyright (C) 2014 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
* you mPrimitiveFields.may not use this file except in compliance with the License.
* You mPrimitiveFields.may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
@@ -13,8 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "OpenGLRenderer"
#include "RenderProperties.h"
#include <utils/Trace.h>
#include <SkCanvas.h>
#include <SkMatrix.h>
#include "Matrix.h"
@@ -22,7 +28,7 @@
namespace android {
namespace uirenderer {
RenderProperties::RenderProperties()
RenderProperties::PrimitiveFields::PrimitiveFields()
: mClipToBounds(true)
, mProjectBackwards(false)
, mProjectionReceiver(false)
@@ -32,89 +38,146 @@ RenderProperties::RenderProperties()
, mRotation(0), mRotationX(0), mRotationY(0)
, mScaleX(1), mScaleY(1)
, mPivotX(0), mPivotY(0)
, mCameraDistance(0)
, mLeft(0), mTop(0), mRight(0), mBottom(0)
, mWidth(0), mHeight(0)
, mPrevWidth(-1), mPrevHeight(-1)
, mPivotExplicitlySet(false)
, mMatrixDirty(false)
, mMatrixIsIdentity(true)
, mTransformMatrix(NULL)
, mMatrixFlags(0)
, mTransformCamera(NULL)
, mTransformMatrix3D(NULL)
, mStaticMatrix(NULL)
, mAnimationMatrix(NULL)
, mCaching(false) {
}
RenderProperties::~RenderProperties() {
RenderProperties::ComputedFields::ComputedFields()
: mTransformMatrix(NULL)
, mTransformCamera(NULL)
, mTransformMatrix3D(NULL) {
}
RenderProperties::ComputedFields::~ComputedFields() {
delete mTransformMatrix;
delete mTransformCamera;
delete mTransformMatrix3D;
}
RenderProperties::RenderProperties()
: mCameraDistance(0)
, mStaticMatrix(NULL)
, mAnimationMatrix(NULL) {
}
RenderProperties::~RenderProperties() {
delete mStaticMatrix;
delete mAnimationMatrix;
}
float RenderProperties::getPivotX() {
updateMatrix();
return mPivotX;
RenderProperties& RenderProperties::operator=(const RenderProperties& other) {
if (this != &other) {
mPrimitiveFields = other.mPrimitiveFields;
setStaticMatrix(other.getStaticMatrix());
setAnimationMatrix(other.getAnimationMatrix());
setCameraDistance(other.getCameraDistance());
// Update the computed fields
updateMatrix();
}
return *this;
}
float RenderProperties::getPivotY() {
updateMatrix();
return mPivotY;
void RenderProperties::debugOutputProperties(const int level) const {
if (mPrimitiveFields.mLeft != 0 || mPrimitiveFields.mTop != 0) {
ALOGD("%*sTranslate (left, top) %d, %d", level * 2, "", mPrimitiveFields.mLeft, mPrimitiveFields.mTop);
}
if (mStaticMatrix) {
ALOGD("%*sConcatMatrix (static) %p: " SK_MATRIX_STRING,
level * 2, "", mStaticMatrix, SK_MATRIX_ARGS(mStaticMatrix));
}
if (mAnimationMatrix) {
ALOGD("%*sConcatMatrix (animation) %p: " SK_MATRIX_STRING,
level * 2, "", mAnimationMatrix, SK_MATRIX_ARGS(mAnimationMatrix));
}
if (mPrimitiveFields.mMatrixFlags != 0) {
if (mPrimitiveFields.mMatrixFlags == TRANSLATION) {
ALOGD("%*sTranslate %.2f, %.2f, %.2f",
level * 2, "", mPrimitiveFields.mTranslationX, mPrimitiveFields.mTranslationY, mPrimitiveFields.mTranslationZ);
} else {
ALOGD("%*sConcatMatrix %p: " MATRIX_4_STRING,
level * 2, "", mComputedFields.mTransformMatrix, MATRIX_4_ARGS(mComputedFields.mTransformMatrix));
}
}
bool clipToBoundsNeeded = mPrimitiveFields.mCaching ? false : mPrimitiveFields.mClipToBounds;
if (mPrimitiveFields.mAlpha < 1) {
if (mPrimitiveFields.mCaching) {
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
}
ALOGD("%*sSaveLayerAlpha %.2f, %.2f, %.2f, %.2f, %d, 0x%x", level * 2, "",
(float) 0, (float) 0, (float) mPrimitiveFields.mRight - mPrimitiveFields.mLeft, (float) mPrimitiveFields.mBottom - mPrimitiveFields.mTop,
(int)(mPrimitiveFields.mAlpha * 255), flags);
}
}
if (clipToBoundsNeeded) {
ALOGD("%*sClipRect %.2f, %.2f, %.2f, %.2f", level * 2, "", 0.0f, 0.0f,
(float) mPrimitiveFields.mRight - mPrimitiveFields.mLeft, (float) mPrimitiveFields.mBottom - mPrimitiveFields.mTop);
}
}
void RenderProperties::updateMatrix() {
if (mMatrixDirty) {
// NOTE: mTransformMatrix won't be up to date if a DisplayList goes from a complex transform
// to a pure translate. This is safe because the matrix isn't read in pure translate cases.
if (mMatrixFlags && mMatrixFlags != TRANSLATION) {
if (!mTransformMatrix) {
// only allocate a matrix if we have a complex transform
mTransformMatrix = new Matrix4();
if (mPrimitiveFields.mMatrixDirty) {
// NOTE: mComputedFields.mTransformMatrix won't be up to date if a DisplayList goes from a complex transform
// to a pure translate. This is safe because the mPrimitiveFields.matrix isn't read in pure translate cases.
if (mPrimitiveFields.mMatrixFlags && mPrimitiveFields.mMatrixFlags != TRANSLATION) {
if (!mComputedFields.mTransformMatrix) {
// only allocate a mPrimitiveFields.matrix if we have a complex transform
mComputedFields.mTransformMatrix = new Matrix4();
}
if (!mPivotExplicitlySet) {
if (mWidth != mPrevWidth || mHeight != mPrevHeight) {
mPrevWidth = mWidth;
mPrevHeight = mHeight;
mPivotX = mPrevWidth / 2.0f;
mPivotY = mPrevHeight / 2.0f;
if (!mPrimitiveFields.mPivotExplicitlySet) {
if (mPrimitiveFields.mWidth != mPrimitiveFields.mPrevWidth || mPrimitiveFields.mHeight != mPrimitiveFields.mPrevHeight) {
mPrimitiveFields.mPrevWidth = mPrimitiveFields.mWidth;
mPrimitiveFields.mPrevHeight = mPrimitiveFields.mHeight;
mPrimitiveFields.mPivotX = mPrimitiveFields.mPrevWidth / 2.0f;
mPrimitiveFields.mPivotY = mPrimitiveFields.mPrevHeight / 2.0f;
}
}
if ((mMatrixFlags & ROTATION_3D) == 0) {
mTransformMatrix->loadTranslate(
mPivotX + mTranslationX,
mPivotY + mTranslationY,
if ((mPrimitiveFields.mMatrixFlags & ROTATION_3D) == 0) {
mComputedFields.mTransformMatrix->loadTranslate(
mPrimitiveFields.mPivotX + mPrimitiveFields.mTranslationX,
mPrimitiveFields.mPivotY + mPrimitiveFields.mTranslationY,
0);
mTransformMatrix->rotate(mRotation, 0, 0, 1);
mTransformMatrix->scale(mScaleX, mScaleY, 1);
mTransformMatrix->translate(-mPivotX, -mPivotY);
mComputedFields.mTransformMatrix->rotate(mPrimitiveFields.mRotation, 0, 0, 1);
mComputedFields.mTransformMatrix->scale(mPrimitiveFields.mScaleX, mPrimitiveFields.mScaleY, 1);
mComputedFields.mTransformMatrix->translate(-mPrimitiveFields.mPivotX, -mPrimitiveFields.mPivotY);
} else {
if (!mTransformCamera) {
mTransformCamera = new Sk3DView();
mTransformMatrix3D = new SkMatrix();
if (!mComputedFields.mTransformCamera) {
mComputedFields.mTransformCamera = new Sk3DView();
mComputedFields.mTransformMatrix3D = new SkMatrix();
}
SkMatrix transformMatrix;
transformMatrix.reset();
mTransformCamera->save();
transformMatrix.preScale(mScaleX, mScaleY, mPivotX, mPivotY);
mTransformCamera->rotateX(mRotationX);
mTransformCamera->rotateY(mRotationY);
mTransformCamera->rotateZ(-mRotation);
mTransformCamera->getMatrix(mTransformMatrix3D);
mTransformMatrix3D->preTranslate(-mPivotX, -mPivotY);
mTransformMatrix3D->postTranslate(mPivotX + mTranslationX,
mPivotY + mTranslationY);
transformMatrix.postConcat(*mTransformMatrix3D);
mTransformCamera->restore();
mComputedFields.mTransformCamera->save();
transformMatrix.preScale(mPrimitiveFields.mScaleX, mPrimitiveFields.mScaleY, mPrimitiveFields.mPivotX, mPrimitiveFields.mPivotY);
mComputedFields.mTransformCamera->rotateX(mPrimitiveFields.mRotationX);
mComputedFields.mTransformCamera->rotateY(mPrimitiveFields.mRotationY);
mComputedFields.mTransformCamera->rotateZ(-mPrimitiveFields.mRotation);
mComputedFields.mTransformCamera->getMatrix(mComputedFields.mTransformMatrix3D);
mComputedFields.mTransformMatrix3D->preTranslate(-mPrimitiveFields.mPivotX, -mPrimitiveFields.mPivotY);
mComputedFields.mTransformMatrix3D->postTranslate(mPrimitiveFields.mPivotX + mPrimitiveFields.mTranslationX,
mPrimitiveFields.mPivotY + mPrimitiveFields.mTranslationY);
transformMatrix.postConcat(*mComputedFields.mTransformMatrix3D);
mComputedFields.mTransformCamera->restore();
mTransformMatrix->load(transformMatrix);
mComputedFields.mTransformMatrix->load(transformMatrix);
}
}
mMatrixDirty = false;
mPrimitiveFields.mMatrixDirty = false;
}
}

View File

@@ -50,33 +50,39 @@ public:
RenderProperties();
virtual ~RenderProperties();
RenderProperties& operator=(const RenderProperties& other);
void setClipToBounds(bool clipToBounds) {
mClipToBounds = clipToBounds;
mPrimitiveFields.mClipToBounds = clipToBounds;
}
void setProjectBackwards(bool shouldProject) {
mProjectBackwards = shouldProject;
mPrimitiveFields.mProjectBackwards = shouldProject;
}
void setProjectionReceiver(bool shouldRecieve) {
mProjectionReceiver = shouldRecieve;
mPrimitiveFields.mProjectionReceiver = shouldRecieve;
}
bool isProjectionReceiver() {
return mProjectionReceiver;
bool isProjectionReceiver() const {
return mPrimitiveFields.mProjectionReceiver;
}
void setStaticMatrix(SkMatrix* matrix) {
void setStaticMatrix(const SkMatrix* matrix) {
delete mStaticMatrix;
mStaticMatrix = new SkMatrix(*matrix);
if (matrix) {
mStaticMatrix = new SkMatrix(*matrix);
} else {
mStaticMatrix = NULL;
}
}
// Can return NULL
SkMatrix* getStaticMatrix() {
const SkMatrix* getStaticMatrix() const {
return mStaticMatrix;
}
void setAnimationMatrix(SkMatrix* matrix) {
void setAnimationMatrix(const SkMatrix* matrix) {
delete mAnimationMatrix;
if (matrix) {
mAnimationMatrix = new SkMatrix(*matrix);
@@ -87,171 +93,179 @@ public:
void setAlpha(float alpha) {
alpha = fminf(1.0f, fmaxf(0.0f, alpha));
if (alpha != mAlpha) {
mAlpha = alpha;
if (alpha != mPrimitiveFields.mAlpha) {
mPrimitiveFields.mAlpha = alpha;
}
}
float getAlpha() const {
return mAlpha;
return mPrimitiveFields.mAlpha;
}
void setHasOverlappingRendering(bool hasOverlappingRendering) {
mHasOverlappingRendering = hasOverlappingRendering;
mPrimitiveFields.mHasOverlappingRendering = hasOverlappingRendering;
}
bool hasOverlappingRendering() const {
return mHasOverlappingRendering;
return mPrimitiveFields.mHasOverlappingRendering;
}
void setTranslationX(float translationX) {
if (translationX != mTranslationX) {
mTranslationX = translationX;
if (translationX != mPrimitiveFields.mTranslationX) {
mPrimitiveFields.mTranslationX = translationX;
onTranslationUpdate();
}
}
float getTranslationX() const {
return mTranslationX;
return mPrimitiveFields.mTranslationX;
}
void setTranslationY(float translationY) {
if (translationY != mTranslationY) {
mTranslationY = translationY;
if (translationY != mPrimitiveFields.mTranslationY) {
mPrimitiveFields.mTranslationY = translationY;
onTranslationUpdate();
}
}
float getTranslationY() const {
return mTranslationY;
return mPrimitiveFields.mTranslationY;
}
void setTranslationZ(float translationZ) {
if (translationZ != mTranslationZ) {
mTranslationZ = translationZ;
if (translationZ != mPrimitiveFields.mTranslationZ) {
mPrimitiveFields.mTranslationZ = translationZ;
onTranslationUpdate();
}
}
float getTranslationZ() const {
return mTranslationZ;
return mPrimitiveFields.mTranslationZ;
}
void setRotation(float rotation) {
if (rotation != mRotation) {
mRotation = rotation;
mMatrixDirty = true;
if (mRotation == 0.0f) {
mMatrixFlags &= ~ROTATION;
if (rotation != mPrimitiveFields.mRotation) {
mPrimitiveFields.mRotation = rotation;
mPrimitiveFields.mMatrixDirty = true;
if (mPrimitiveFields.mRotation == 0.0f) {
mPrimitiveFields.mMatrixFlags &= ~ROTATION;
} else {
mMatrixFlags |= ROTATION;
mPrimitiveFields.mMatrixFlags |= ROTATION;
}
}
}
float getRotation() const {
return mRotation;
return mPrimitiveFields.mRotation;
}
void setRotationX(float rotationX) {
if (rotationX != mRotationX) {
mRotationX = rotationX;
mMatrixDirty = true;
if (mRotationX == 0.0f && mRotationY == 0.0f) {
mMatrixFlags &= ~ROTATION_3D;
if (rotationX != mPrimitiveFields.mRotationX) {
mPrimitiveFields.mRotationX = rotationX;
mPrimitiveFields.mMatrixDirty = true;
if (mPrimitiveFields.mRotationX == 0.0f && mPrimitiveFields.mRotationY == 0.0f) {
mPrimitiveFields.mMatrixFlags &= ~ROTATION_3D;
} else {
mMatrixFlags |= ROTATION_3D;
mPrimitiveFields.mMatrixFlags |= ROTATION_3D;
}
}
}
float getRotationX() const {
return mRotationX;
return mPrimitiveFields.mRotationX;
}
void setRotationY(float rotationY) {
if (rotationY != mRotationY) {
mRotationY = rotationY;
mMatrixDirty = true;
if (mRotationX == 0.0f && mRotationY == 0.0f) {
mMatrixFlags &= ~ROTATION_3D;
if (rotationY != mPrimitiveFields.mRotationY) {
mPrimitiveFields.mRotationY = rotationY;
mPrimitiveFields.mMatrixDirty = true;
if (mPrimitiveFields.mRotationX == 0.0f && mPrimitiveFields.mRotationY == 0.0f) {
mPrimitiveFields.mMatrixFlags &= ~ROTATION_3D;
} else {
mMatrixFlags |= ROTATION_3D;
mPrimitiveFields.mMatrixFlags |= ROTATION_3D;
}
}
}
float getRotationY() const {
return mRotationY;
return mPrimitiveFields.mRotationY;
}
void setScaleX(float scaleX) {
if (scaleX != mScaleX) {
mScaleX = scaleX;
mMatrixDirty = true;
if (mScaleX == 1.0f && mScaleY == 1.0f) {
mMatrixFlags &= ~SCALE;
if (scaleX != mPrimitiveFields.mScaleX) {
mPrimitiveFields.mScaleX = scaleX;
mPrimitiveFields.mMatrixDirty = true;
if (mPrimitiveFields.mScaleX == 1.0f && mPrimitiveFields.mScaleY == 1.0f) {
mPrimitiveFields.mMatrixFlags &= ~SCALE;
} else {
mMatrixFlags |= SCALE;
mPrimitiveFields.mMatrixFlags |= SCALE;
}
}
}
float getScaleX() const {
return mScaleX;
return mPrimitiveFields.mScaleX;
}
void setScaleY(float scaleY) {
if (scaleY != mScaleY) {
mScaleY = scaleY;
mMatrixDirty = true;
if (mScaleX == 1.0f && mScaleY == 1.0f) {
mMatrixFlags &= ~SCALE;
if (scaleY != mPrimitiveFields.mScaleY) {
mPrimitiveFields.mScaleY = scaleY;
mPrimitiveFields.mMatrixDirty = true;
if (mPrimitiveFields.mScaleX == 1.0f && mPrimitiveFields.mScaleY == 1.0f) {
mPrimitiveFields.mMatrixFlags &= ~SCALE;
} else {
mMatrixFlags |= SCALE;
mPrimitiveFields.mMatrixFlags |= SCALE;
}
}
}
float getScaleY() const {
return mScaleY;
return mPrimitiveFields.mScaleY;
}
void setPivotX(float pivotX) {
mPivotX = pivotX;
mMatrixDirty = true;
if (mPivotX == 0.0f && mPivotY == 0.0f) {
mMatrixFlags &= ~PIVOT;
mPrimitiveFields.mPivotX = pivotX;
mPrimitiveFields.mMatrixDirty = true;
if (mPrimitiveFields.mPivotX == 0.0f && mPrimitiveFields.mPivotY == 0.0f) {
mPrimitiveFields.mMatrixFlags &= ~PIVOT;
} else {
mMatrixFlags |= PIVOT;
mPrimitiveFields.mMatrixFlags |= PIVOT;
}
mPivotExplicitlySet = true;
mPrimitiveFields.mPivotExplicitlySet = true;
}
ANDROID_API float getPivotX();
/* Note that getPivotX and getPivotY are adjusted by updateMatrix(),
* so the value returned mPrimitiveFields.may be stale if the RenderProperties has been
* mPrimitiveFields.modified since the last call to updateMatrix()
*/
float getPivotX() const {
return mPrimitiveFields.mPivotX;
}
void setPivotY(float pivotY) {
mPivotY = pivotY;
mMatrixDirty = true;
if (mPivotX == 0.0f && mPivotY == 0.0f) {
mMatrixFlags &= ~PIVOT;
mPrimitiveFields.mPivotY = pivotY;
mPrimitiveFields.mMatrixDirty = true;
if (mPrimitiveFields.mPivotX == 0.0f && mPrimitiveFields.mPivotY == 0.0f) {
mPrimitiveFields.mMatrixFlags &= ~PIVOT;
} else {
mMatrixFlags |= PIVOT;
mPrimitiveFields.mMatrixFlags |= PIVOT;
}
mPivotExplicitlySet = true;
mPrimitiveFields.mPivotExplicitlySet = true;
}
ANDROID_API float getPivotY();
float getPivotY() const {
return mPrimitiveFields.mPivotY;
}
void setCameraDistance(float distance) {
if (distance != mCameraDistance) {
mCameraDistance = distance;
mMatrixDirty = true;
if (!mTransformCamera) {
mTransformCamera = new Sk3DView();
mTransformMatrix3D = new SkMatrix();
mPrimitiveFields.mMatrixDirty = true;
if (!mComputedFields.mTransformCamera) {
mComputedFields.mTransformCamera = new Sk3DView();
mComputedFields.mTransformMatrix3D = new SkMatrix();
}
mTransformCamera->setCameraLocation(0, 0, distance);
mComputedFields.mTransformCamera->setCameraLocation(0, 0, distance);
}
}
@@ -260,170 +274,216 @@ public:
}
void setLeft(int left) {
if (left != mLeft) {
mLeft = left;
mWidth = mRight - mLeft;
if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
mMatrixDirty = true;
if (left != mPrimitiveFields.mLeft) {
mPrimitiveFields.mLeft = left;
mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
if (mPrimitiveFields.mMatrixFlags > TRANSLATION && !mPrimitiveFields.mPivotExplicitlySet) {
mPrimitiveFields.mMatrixDirty = true;
}
}
}
float getLeft() const {
return mLeft;
return mPrimitiveFields.mLeft;
}
void setTop(int top) {
if (top != mTop) {
mTop = top;
mHeight = mBottom - mTop;
if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
mMatrixDirty = true;
if (top != mPrimitiveFields.mTop) {
mPrimitiveFields.mTop = top;
mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
if (mPrimitiveFields.mMatrixFlags > TRANSLATION && !mPrimitiveFields.mPivotExplicitlySet) {
mPrimitiveFields.mMatrixDirty = true;
}
}
}
float getTop() const {
return mTop;
return mPrimitiveFields.mTop;
}
void setRight(int right) {
if (right != mRight) {
mRight = right;
mWidth = mRight - mLeft;
if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
mMatrixDirty = true;
if (right != mPrimitiveFields.mRight) {
mPrimitiveFields.mRight = right;
mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
if (mPrimitiveFields.mMatrixFlags > TRANSLATION && !mPrimitiveFields.mPivotExplicitlySet) {
mPrimitiveFields.mMatrixDirty = true;
}
}
}
float getRight() const {
return mRight;
return mPrimitiveFields.mRight;
}
void setBottom(int bottom) {
if (bottom != mBottom) {
mBottom = bottom;
mHeight = mBottom - mTop;
if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
mMatrixDirty = true;
if (bottom != mPrimitiveFields.mBottom) {
mPrimitiveFields.mBottom = bottom;
mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
if (mPrimitiveFields.mMatrixFlags > TRANSLATION && !mPrimitiveFields.mPivotExplicitlySet) {
mPrimitiveFields.mMatrixDirty = true;
}
}
}
float getBottom() const {
return mBottom;
return mPrimitiveFields.mBottom;
}
void setLeftTop(int left, int top) {
if (left != mLeft || top != mTop) {
mLeft = left;
mTop = top;
mWidth = mRight - mLeft;
mHeight = mBottom - mTop;
if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
mMatrixDirty = true;
if (left != mPrimitiveFields.mLeft || top != mPrimitiveFields.mTop) {
mPrimitiveFields.mLeft = left;
mPrimitiveFields.mTop = top;
mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
if (mPrimitiveFields.mMatrixFlags > TRANSLATION && !mPrimitiveFields.mPivotExplicitlySet) {
mPrimitiveFields.mMatrixDirty = true;
}
}
}
void setLeftTopRightBottom(int left, int top, int right, int bottom) {
if (left != mLeft || top != mTop || right != mRight || bottom != mBottom) {
mLeft = left;
mTop = top;
mRight = right;
mBottom = bottom;
mWidth = mRight - mLeft;
mHeight = mBottom - mTop;
if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
mMatrixDirty = true;
if (left != mPrimitiveFields.mLeft || top != mPrimitiveFields.mTop || right != mPrimitiveFields.mRight || bottom != mPrimitiveFields.mBottom) {
mPrimitiveFields.mLeft = left;
mPrimitiveFields.mTop = top;
mPrimitiveFields.mRight = right;
mPrimitiveFields.mBottom = bottom;
mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
if (mPrimitiveFields.mMatrixFlags > TRANSLATION && !mPrimitiveFields.mPivotExplicitlySet) {
mPrimitiveFields.mMatrixDirty = true;
}
}
}
void offsetLeftRight(float offset) {
if (offset != 0) {
mLeft += offset;
mRight += offset;
if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
mMatrixDirty = true;
mPrimitiveFields.mLeft += offset;
mPrimitiveFields.mRight += offset;
if (mPrimitiveFields.mMatrixFlags > TRANSLATION && !mPrimitiveFields.mPivotExplicitlySet) {
mPrimitiveFields.mMatrixDirty = true;
}
}
}
void offsetTopBottom(float offset) {
if (offset != 0) {
mTop += offset;
mBottom += offset;
if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
mMatrixDirty = true;
mPrimitiveFields.mTop += offset;
mPrimitiveFields.mBottom += offset;
if (mPrimitiveFields.mMatrixFlags > TRANSLATION && !mPrimitiveFields.mPivotExplicitlySet) {
mPrimitiveFields.mMatrixDirty = true;
}
}
}
void setCaching(bool caching) {
mCaching = caching;
mPrimitiveFields.mCaching = caching;
}
int getWidth() const {
return mWidth;
return mPrimitiveFields.mWidth;
}
int getHeight() const {
return mHeight;
return mPrimitiveFields.mHeight;
}
Outline& outline() {
return mOutline;
const SkMatrix* getAnimationMatrix() const {
return mAnimationMatrix;
}
uint32_t getMatrixFlags() const {
return mPrimitiveFields.mMatrixFlags;
}
const Matrix4* getTransformMatrix() const {
return mComputedFields.mTransformMatrix;
}
bool getCaching() const {
return mPrimitiveFields.mCaching;
}
bool getClipToBounds() const {
return mPrimitiveFields.mClipToBounds;
}
bool getHasOverlappingRendering() const {
return mPrimitiveFields.mHasOverlappingRendering;
}
const Outline& getOutline() const {
return mPrimitiveFields.mOutline;
}
bool getProjectBackwards() const {
return mPrimitiveFields.mProjectBackwards;
}
void debugOutputProperties(const int level) const;
ANDROID_API void updateMatrix();
Outline& mutableOutline() {
return mPrimitiveFields.mOutline;
}
private:
void onTranslationUpdate() {
mMatrixDirty = true;
if (mTranslationX == 0.0f && mTranslationY == 0.0f && mTranslationZ == 0.0f) {
mMatrixFlags &= ~TRANSLATION;
mPrimitiveFields.mMatrixDirty = true;
if (mPrimitiveFields.mTranslationX == 0.0f && mPrimitiveFields.mTranslationY == 0.0f && mPrimitiveFields.mTranslationZ == 0.0f) {
mPrimitiveFields.mMatrixFlags &= ~TRANSLATION;
} else {
mMatrixFlags |= TRANSLATION;
mPrimitiveFields.mMatrixFlags |= TRANSLATION;
}
}
void updateMatrix();
// Rendering properties
Outline mOutline;
bool mClipToBounds;
bool mProjectBackwards;
bool mProjectionReceiver;
float mAlpha;
bool mHasOverlappingRendering;
float mTranslationX, mTranslationY, mTranslationZ;
float mRotation, mRotationX, mRotationY;
float mScaleX, mScaleY;
float mPivotX, mPivotY;
float mCameraDistance;
int mLeft, mTop, mRight, mBottom;
int mWidth, mHeight;
int mPrevWidth, mPrevHeight;
bool mPivotExplicitlySet;
bool mMatrixDirty;
bool mMatrixIsIdentity;
struct PrimitiveFields {
PrimitiveFields();
/**
* Stores the total transformation of the DisplayList based upon its scalar
* translate/rotate/scale properties.
*
* In the common translation-only case, the matrix isn't allocated and the mTranslation
* properties are used directly.
*/
Matrix4* mTransformMatrix;
uint32_t mMatrixFlags;
Sk3DView* mTransformCamera;
SkMatrix* mTransformMatrix3D;
Outline mOutline;
bool mClipToBounds;
bool mProjectBackwards;
bool mProjectionReceiver;
float mAlpha;
bool mHasOverlappingRendering;
float mTranslationX, mTranslationY, mTranslationZ;
float mRotation, mRotationX, mRotationY;
float mScaleX, mScaleY;
float mPivotX, mPivotY;
int mLeft, mTop, mRight, mBottom;
int mWidth, mHeight;
int mPrevWidth, mPrevHeight;
bool mPivotExplicitlySet;
bool mMatrixDirty;
bool mMatrixIsIdentity;
uint32_t mMatrixFlags;
bool mCaching;
} mPrimitiveFields;
// mCameraDistance isn't in mPrimitiveFields as it has a complex setter
float mCameraDistance;
SkMatrix* mStaticMatrix;
SkMatrix* mAnimationMatrix;
bool mCaching;
friend class RenderNode;
/**
* These fields are all generated from other properties and are not set directly.
*/
struct ComputedFields {
ComputedFields();
~ComputedFields();
/**
* Stores the total transformation of the DisplayList based upon its scalar
* translate/rotate/scale properties.
*
* In the common translation-only case, the matrix isn't allocated and the mTranslation
* properties are used directly.
*/
Matrix4* mTransformMatrix;
Sk3DView* mTransformCamera;
SkMatrix* mTransformMatrix3D;
} mComputedFields;
};
} /* namespace uirenderer */