Loading core/java/android/view/RenderNode.java +0 −8 Original line number Diff line number Diff line Loading @@ -841,13 +841,6 @@ public class RenderNode { return nOffsetTopAndBottom(mNativeRenderNode, offset); } /** * Sets the scroll position, this is used for damage calculations */ public void setScrollPosition(int x, int y) { nSetScrollPosition(mNativeRenderNode, x, y); } /** * Outputs the display list to the log. This method exists for use by * tools to output display lists for selected nodes to the log. Loading Loading @@ -906,7 +899,6 @@ public class RenderNode { private static native boolean nSetRight(long renderNode, int right); private static native boolean nSetTop(long renderNode, int top); private static native boolean nSetLeft(long renderNode, int left); private static native void nSetScrollPosition(long renderNode, int scrollX, int scrollY); private static native boolean nSetCameraDistance(long renderNode, float distance); private static native boolean nSetPivotY(long renderNode, float pivotY); private static native boolean nSetPivotX(long renderNode, float pivotX); Loading core/java/android/view/View.java +0 −1 Original line number Diff line number Diff line Loading @@ -13738,7 +13738,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return; } renderNode.setScrollPosition(mScrollX, mScrollY); if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || !renderNode.isValid() || (!isLayer && mRecreateDisplayList)) { core/jni/android_view_RenderNode.cpp +0 −8 Original line number Diff line number Diff line Loading @@ -275,13 +275,6 @@ static jboolean android_view_RenderNode_offsetTopAndBottom(JNIEnv* env, return SET_AND_DIRTY(offsetTopBottom, offset, RenderNode::Y); } static void android_view_RenderNode_setScrollPosition(JNIEnv* env, jobject clazz, jlong renderNodePtr, jint scrollX, jint scrollY) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); SET_AND_DIRTY(setScrollX, scrollX, RenderNode::GENERIC); SET_AND_DIRTY(setScrollY, scrollY, RenderNode::GENERIC); } // ---------------------------------------------------------------------------- // RenderProperties - getters // ---------------------------------------------------------------------------- Loading Loading @@ -517,7 +510,6 @@ static JNINativeMethod gMethods[] = { { "nSetLeftTopRightBottom","(JIIII)Z", (void*) android_view_RenderNode_setLeftTopRightBottom }, { "nOffsetLeftAndRight", "(JF)Z", (void*) android_view_RenderNode_offsetLeftAndRight }, { "nOffsetTopAndBottom", "(JF)Z", (void*) android_view_RenderNode_offsetTopAndBottom }, { "nSetScrollPosition", "(JII)V", (void*) android_view_RenderNode_setScrollPosition }, { "nHasOverlappingRendering", "(J)Z", (void*) android_view_RenderNode_hasOverlappingRendering }, { "nGetClipToOutline", "(J)Z", (void*) android_view_RenderNode_getClipToOutline }, Loading libs/hwui/DamageAccumulator.cpp +121 −28 Original line number Diff line number Diff line Loading @@ -26,8 +26,23 @@ namespace android { namespace uirenderer { NullDamageAccumulator NullDamageAccumulator::sInstance; NullDamageAccumulator* NullDamageAccumulator::instance() { return &sInstance; } enum TransformType { TransformRenderNode, TransformMatrix4, }; struct DirtyStack { const RenderNode* node; TransformType type; union { const RenderNode* renderNode; const Matrix4* matrix4; }; // When this frame is pop'd, this rect is mapped through the above transform // and applied to the previous (aka parent) frame SkRect pendingDirty; Loading @@ -42,7 +57,7 @@ DamageAccumulator::DamageAccumulator() { mHead->prev = mHead; } void DamageAccumulator::pushNode(const RenderNode* node) { void DamageAccumulator::pushCommon() { if (!mHead->next) { DirtyStack* nextFrame = (DirtyStack*) mAllocator.alloc(sizeof(DirtyStack)); nextFrame->next = 0; Loading @@ -50,42 +65,120 @@ void DamageAccumulator::pushNode(const RenderNode* node) { mHead->next = nextFrame; } mHead = mHead->next; mHead->node = node; mHead->pendingDirty.setEmpty(); } void DamageAccumulator::popNode() { void DamageAccumulator::pushTransform(const RenderNode* transform) { pushCommon(); mHead->type = TransformRenderNode; mHead->renderNode = transform; } void DamageAccumulator::pushTransform(const Matrix4* transform) { pushCommon(); mHead->type = TransformMatrix4; mHead->matrix4 = transform; } void DamageAccumulator::popTransform() { LOG_ALWAYS_FATAL_IF(mHead->prev == mHead, "Cannot pop the root frame!"); DirtyStack* dirtyFrame = mHead; mHead = mHead->prev; if (!dirtyFrame->pendingDirty.isEmpty()) { SkRect mappedDirty; const RenderProperties& props = dirtyFrame->node->properties(); if (dirtyFrame->type == TransformRenderNode) { applyRenderNodeTransform(dirtyFrame); } else { applyMatrix4Transform(dirtyFrame); } } static inline void mapRect(const Matrix4* matrix, const SkRect& in, SkRect* out) { if (in.isEmpty()) return; Rect temp(in); matrix->mapRect(temp); out->join(RECT_ARGS(temp)); } void DamageAccumulator::applyMatrix4Transform(DirtyStack* frame) { mapRect(frame->matrix4, frame->pendingDirty, &mHead->pendingDirty); } static inline void mapRect(const RenderProperties& props, const SkRect& in, SkRect* out) { if (in.isEmpty()) return; const SkMatrix* transform = props.getTransformMatrix(); SkRect temp(in); if (transform && !transform->isIdentity()) { transform->mapRect(&mappedDirty, dirtyFrame->pendingDirty); transform->mapRect(&temp); } temp.offset(props.getLeft(), props.getTop()); out->join(temp); } static DirtyStack* findParentRenderNode(DirtyStack* frame) { while (frame->prev != frame) { frame = frame->prev; if (frame->type == TransformRenderNode) { return frame; } } return NULL; } static DirtyStack* findProjectionReceiver(DirtyStack* frame) { if (frame) { while (frame->prev != frame) { frame = frame->prev; if (frame->type == TransformRenderNode && frame->renderNode->hasProjectionReceiver()) { return frame; } } } return NULL; } static void applyTransforms(DirtyStack* frame, DirtyStack* end) { SkRect* rect = &frame->pendingDirty; while (frame != end) { if (frame->type == TransformRenderNode) { mapRect(frame->renderNode->properties(), *rect, rect); } else { mappedDirty = dirtyFrame->pendingDirty; mapRect(frame->matrix4, *rect, rect); } frame = frame->prev; } if (CC_LIKELY(mHead->node)) { const RenderProperties& parentProps = mHead->node->properties(); mappedDirty.offset(props.getLeft() - parentProps.getScrollX(), props.getTop() - parentProps.getScrollY()); if (props.getClipToBounds()) { if (!mappedDirty.intersect(0, 0, parentProps.getWidth(), parentProps.getHeight())) { mappedDirty.setEmpty(); } void DamageAccumulator::applyRenderNodeTransform(DirtyStack* frame) { if (frame->pendingDirty.isEmpty()) { return; } if (CC_UNLIKELY(!MathUtils::isZero(props.getTranslationZ()))) { // TODO: Can we better bound the shadow damage area? For now // match the old damageShadowReceiver() path and just dirty // the entire parent bounds mappedDirty.join(0, 0, parentProps.getWidth(), parentProps.getHeight()); const RenderProperties& props = frame->renderNode->properties(); // Perform clipping if (props.getClipToBounds() && !frame->pendingDirty.isEmpty()) { if (!frame->pendingDirty.intersect(0, 0, props.getWidth(), props.getHeight())) { frame->pendingDirty.setEmpty(); } } // apply all transforms mapRect(props, frame->pendingDirty, &mHead->pendingDirty); // project backwards if necessary if (props.getProjectBackwards() && !frame->pendingDirty.isEmpty()) { // First, find our parent RenderNode: DirtyStack* parentNode = findParentRenderNode(frame); // Find our parent's projection receiver, which is what we project onto DirtyStack* projectionReceiver = findProjectionReceiver(parentNode); if (projectionReceiver) { applyTransforms(frame, projectionReceiver); projectionReceiver->pendingDirty.join(frame->pendingDirty); } else { mappedDirty.offset(props.getLeft(), props.getTop()); ALOGW("Failed to find projection receiver? Dropping on the floor..."); } dirty(mappedDirty.fLeft, mappedDirty.fTop, mappedDirty.fRight, mappedDirty.fBottom); frame->pendingDirty.setEmpty(); } } Loading libs/hwui/DamageAccumulator.h +42 −6 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #ifndef DAMAGEACCUMULATOR_H #define DAMAGEACCUMULATOR_H #include <cutils/compiler.h> #include <utils/LinearAllocator.h> #include <SkMatrix.h> Loading @@ -28,8 +29,19 @@ namespace uirenderer { struct DirtyStack; class RenderNode; class Matrix4; class DamageAccumulator { class IDamageAccumulator { public: virtual void pushTransform(const RenderNode* transform) = 0; virtual void pushTransform(const Matrix4* transform) = 0; virtual void popTransform() = 0; virtual void dirty(float left, float top, float right, float bottom) = 0; protected: virtual ~IDamageAccumulator() {} }; class DamageAccumulator : public IDamageAccumulator { PREVENT_COPY_AND_ASSIGN(DamageAccumulator); public: DamageAccumulator(); Loading @@ -37,20 +49,44 @@ public: // Push a transform node onto the stack. This should be called prior // to any dirty() calls. Subsequent calls to dirty() // will be affected by the node's transform when popNode() is called. void pushNode(const RenderNode* node); // will be affected by the transform when popTransform() is called. virtual void pushTransform(const RenderNode* transform); virtual void pushTransform(const Matrix4* transform); // Pops a transform node from the stack, propagating the dirty rect // up to the parent node. void popNode(); void dirty(float left, float top, float right, float bottom); // up to the parent node. Returns the IDamageTransform that was just applied virtual void popTransform(); virtual void dirty(float left, float top, float right, float bottom); void finish(SkRect* totalDirty); private: void pushCommon(); void applyMatrix4Transform(DirtyStack* frame); void applyRenderNodeTransform(DirtyStack* frame); LinearAllocator mAllocator; DirtyStack* mHead; }; class NullDamageAccumulator : public IDamageAccumulator { PREVENT_COPY_AND_ASSIGN(NullDamageAccumulator); public: virtual void pushTransform(const RenderNode* transform) { } virtual void pushTransform(const Matrix4* transform) { } virtual void popTransform() { } virtual void dirty(float left, float top, float right, float bottom) { } ANDROID_API static NullDamageAccumulator* instance(); private: NullDamageAccumulator() {} ~NullDamageAccumulator() {} static NullDamageAccumulator sInstance; }; } /* namespace uirenderer */ } /* namespace android */ Loading Loading
core/java/android/view/RenderNode.java +0 −8 Original line number Diff line number Diff line Loading @@ -841,13 +841,6 @@ public class RenderNode { return nOffsetTopAndBottom(mNativeRenderNode, offset); } /** * Sets the scroll position, this is used for damage calculations */ public void setScrollPosition(int x, int y) { nSetScrollPosition(mNativeRenderNode, x, y); } /** * Outputs the display list to the log. This method exists for use by * tools to output display lists for selected nodes to the log. Loading Loading @@ -906,7 +899,6 @@ public class RenderNode { private static native boolean nSetRight(long renderNode, int right); private static native boolean nSetTop(long renderNode, int top); private static native boolean nSetLeft(long renderNode, int left); private static native void nSetScrollPosition(long renderNode, int scrollX, int scrollY); private static native boolean nSetCameraDistance(long renderNode, float distance); private static native boolean nSetPivotY(long renderNode, float pivotY); private static native boolean nSetPivotX(long renderNode, float pivotX); Loading
core/java/android/view/View.java +0 −1 Original line number Diff line number Diff line Loading @@ -13738,7 +13738,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return; } renderNode.setScrollPosition(mScrollX, mScrollY); if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || !renderNode.isValid() || (!isLayer && mRecreateDisplayList)) {
core/jni/android_view_RenderNode.cpp +0 −8 Original line number Diff line number Diff line Loading @@ -275,13 +275,6 @@ static jboolean android_view_RenderNode_offsetTopAndBottom(JNIEnv* env, return SET_AND_DIRTY(offsetTopBottom, offset, RenderNode::Y); } static void android_view_RenderNode_setScrollPosition(JNIEnv* env, jobject clazz, jlong renderNodePtr, jint scrollX, jint scrollY) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); SET_AND_DIRTY(setScrollX, scrollX, RenderNode::GENERIC); SET_AND_DIRTY(setScrollY, scrollY, RenderNode::GENERIC); } // ---------------------------------------------------------------------------- // RenderProperties - getters // ---------------------------------------------------------------------------- Loading Loading @@ -517,7 +510,6 @@ static JNINativeMethod gMethods[] = { { "nSetLeftTopRightBottom","(JIIII)Z", (void*) android_view_RenderNode_setLeftTopRightBottom }, { "nOffsetLeftAndRight", "(JF)Z", (void*) android_view_RenderNode_offsetLeftAndRight }, { "nOffsetTopAndBottom", "(JF)Z", (void*) android_view_RenderNode_offsetTopAndBottom }, { "nSetScrollPosition", "(JII)V", (void*) android_view_RenderNode_setScrollPosition }, { "nHasOverlappingRendering", "(J)Z", (void*) android_view_RenderNode_hasOverlappingRendering }, { "nGetClipToOutline", "(J)Z", (void*) android_view_RenderNode_getClipToOutline }, Loading
libs/hwui/DamageAccumulator.cpp +121 −28 Original line number Diff line number Diff line Loading @@ -26,8 +26,23 @@ namespace android { namespace uirenderer { NullDamageAccumulator NullDamageAccumulator::sInstance; NullDamageAccumulator* NullDamageAccumulator::instance() { return &sInstance; } enum TransformType { TransformRenderNode, TransformMatrix4, }; struct DirtyStack { const RenderNode* node; TransformType type; union { const RenderNode* renderNode; const Matrix4* matrix4; }; // When this frame is pop'd, this rect is mapped through the above transform // and applied to the previous (aka parent) frame SkRect pendingDirty; Loading @@ -42,7 +57,7 @@ DamageAccumulator::DamageAccumulator() { mHead->prev = mHead; } void DamageAccumulator::pushNode(const RenderNode* node) { void DamageAccumulator::pushCommon() { if (!mHead->next) { DirtyStack* nextFrame = (DirtyStack*) mAllocator.alloc(sizeof(DirtyStack)); nextFrame->next = 0; Loading @@ -50,42 +65,120 @@ void DamageAccumulator::pushNode(const RenderNode* node) { mHead->next = nextFrame; } mHead = mHead->next; mHead->node = node; mHead->pendingDirty.setEmpty(); } void DamageAccumulator::popNode() { void DamageAccumulator::pushTransform(const RenderNode* transform) { pushCommon(); mHead->type = TransformRenderNode; mHead->renderNode = transform; } void DamageAccumulator::pushTransform(const Matrix4* transform) { pushCommon(); mHead->type = TransformMatrix4; mHead->matrix4 = transform; } void DamageAccumulator::popTransform() { LOG_ALWAYS_FATAL_IF(mHead->prev == mHead, "Cannot pop the root frame!"); DirtyStack* dirtyFrame = mHead; mHead = mHead->prev; if (!dirtyFrame->pendingDirty.isEmpty()) { SkRect mappedDirty; const RenderProperties& props = dirtyFrame->node->properties(); if (dirtyFrame->type == TransformRenderNode) { applyRenderNodeTransform(dirtyFrame); } else { applyMatrix4Transform(dirtyFrame); } } static inline void mapRect(const Matrix4* matrix, const SkRect& in, SkRect* out) { if (in.isEmpty()) return; Rect temp(in); matrix->mapRect(temp); out->join(RECT_ARGS(temp)); } void DamageAccumulator::applyMatrix4Transform(DirtyStack* frame) { mapRect(frame->matrix4, frame->pendingDirty, &mHead->pendingDirty); } static inline void mapRect(const RenderProperties& props, const SkRect& in, SkRect* out) { if (in.isEmpty()) return; const SkMatrix* transform = props.getTransformMatrix(); SkRect temp(in); if (transform && !transform->isIdentity()) { transform->mapRect(&mappedDirty, dirtyFrame->pendingDirty); transform->mapRect(&temp); } temp.offset(props.getLeft(), props.getTop()); out->join(temp); } static DirtyStack* findParentRenderNode(DirtyStack* frame) { while (frame->prev != frame) { frame = frame->prev; if (frame->type == TransformRenderNode) { return frame; } } return NULL; } static DirtyStack* findProjectionReceiver(DirtyStack* frame) { if (frame) { while (frame->prev != frame) { frame = frame->prev; if (frame->type == TransformRenderNode && frame->renderNode->hasProjectionReceiver()) { return frame; } } } return NULL; } static void applyTransforms(DirtyStack* frame, DirtyStack* end) { SkRect* rect = &frame->pendingDirty; while (frame != end) { if (frame->type == TransformRenderNode) { mapRect(frame->renderNode->properties(), *rect, rect); } else { mappedDirty = dirtyFrame->pendingDirty; mapRect(frame->matrix4, *rect, rect); } frame = frame->prev; } if (CC_LIKELY(mHead->node)) { const RenderProperties& parentProps = mHead->node->properties(); mappedDirty.offset(props.getLeft() - parentProps.getScrollX(), props.getTop() - parentProps.getScrollY()); if (props.getClipToBounds()) { if (!mappedDirty.intersect(0, 0, parentProps.getWidth(), parentProps.getHeight())) { mappedDirty.setEmpty(); } void DamageAccumulator::applyRenderNodeTransform(DirtyStack* frame) { if (frame->pendingDirty.isEmpty()) { return; } if (CC_UNLIKELY(!MathUtils::isZero(props.getTranslationZ()))) { // TODO: Can we better bound the shadow damage area? For now // match the old damageShadowReceiver() path and just dirty // the entire parent bounds mappedDirty.join(0, 0, parentProps.getWidth(), parentProps.getHeight()); const RenderProperties& props = frame->renderNode->properties(); // Perform clipping if (props.getClipToBounds() && !frame->pendingDirty.isEmpty()) { if (!frame->pendingDirty.intersect(0, 0, props.getWidth(), props.getHeight())) { frame->pendingDirty.setEmpty(); } } // apply all transforms mapRect(props, frame->pendingDirty, &mHead->pendingDirty); // project backwards if necessary if (props.getProjectBackwards() && !frame->pendingDirty.isEmpty()) { // First, find our parent RenderNode: DirtyStack* parentNode = findParentRenderNode(frame); // Find our parent's projection receiver, which is what we project onto DirtyStack* projectionReceiver = findProjectionReceiver(parentNode); if (projectionReceiver) { applyTransforms(frame, projectionReceiver); projectionReceiver->pendingDirty.join(frame->pendingDirty); } else { mappedDirty.offset(props.getLeft(), props.getTop()); ALOGW("Failed to find projection receiver? Dropping on the floor..."); } dirty(mappedDirty.fLeft, mappedDirty.fTop, mappedDirty.fRight, mappedDirty.fBottom); frame->pendingDirty.setEmpty(); } } Loading
libs/hwui/DamageAccumulator.h +42 −6 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #ifndef DAMAGEACCUMULATOR_H #define DAMAGEACCUMULATOR_H #include <cutils/compiler.h> #include <utils/LinearAllocator.h> #include <SkMatrix.h> Loading @@ -28,8 +29,19 @@ namespace uirenderer { struct DirtyStack; class RenderNode; class Matrix4; class DamageAccumulator { class IDamageAccumulator { public: virtual void pushTransform(const RenderNode* transform) = 0; virtual void pushTransform(const Matrix4* transform) = 0; virtual void popTransform() = 0; virtual void dirty(float left, float top, float right, float bottom) = 0; protected: virtual ~IDamageAccumulator() {} }; class DamageAccumulator : public IDamageAccumulator { PREVENT_COPY_AND_ASSIGN(DamageAccumulator); public: DamageAccumulator(); Loading @@ -37,20 +49,44 @@ public: // Push a transform node onto the stack. This should be called prior // to any dirty() calls. Subsequent calls to dirty() // will be affected by the node's transform when popNode() is called. void pushNode(const RenderNode* node); // will be affected by the transform when popTransform() is called. virtual void pushTransform(const RenderNode* transform); virtual void pushTransform(const Matrix4* transform); // Pops a transform node from the stack, propagating the dirty rect // up to the parent node. void popNode(); void dirty(float left, float top, float right, float bottom); // up to the parent node. Returns the IDamageTransform that was just applied virtual void popTransform(); virtual void dirty(float left, float top, float right, float bottom); void finish(SkRect* totalDirty); private: void pushCommon(); void applyMatrix4Transform(DirtyStack* frame); void applyRenderNodeTransform(DirtyStack* frame); LinearAllocator mAllocator; DirtyStack* mHead; }; class NullDamageAccumulator : public IDamageAccumulator { PREVENT_COPY_AND_ASSIGN(NullDamageAccumulator); public: virtual void pushTransform(const RenderNode* transform) { } virtual void pushTransform(const Matrix4* transform) { } virtual void popTransform() { } virtual void dirty(float left, float top, float right, float bottom) { } ANDROID_API static NullDamageAccumulator* instance(); private: NullDamageAccumulator() {} ~NullDamageAccumulator() {} static NullDamageAccumulator sInstance; }; } /* namespace uirenderer */ } /* namespace android */ Loading