Even FASTER damage calculations!
* Now with more native!
* Less matrix math thanks to bulk-property-update support!
* Zero JNI on the View.damageInParent() path!
* Fully aware of RT-driven animators!
* Likely full of new and exciting bugs!
* But it also fixes at least 1 existing invalidate bug!
Change-Id: Ie0773f85a60850ff2668370c58defef2e8aa079f
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index e5c8898..cc62170 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -14,6 +14,7 @@
AmbientShadow.cpp \
Animator.cpp \
AssetAtlas.cpp \
+ DamageAccumulator.cpp \
FontRenderer.cpp \
GammaFontRenderer.cpp \
Caches.cpp \
diff --git a/libs/hwui/DamageAccumulator.cpp b/libs/hwui/DamageAccumulator.cpp
new file mode 100644
index 0000000..8aa8c92
--- /dev/null
+++ b/libs/hwui/DamageAccumulator.cpp
@@ -0,0 +1,105 @@
+/*
+ * 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "DamageAccumulator"
+
+#include "DamageAccumulator.h"
+
+#include <cutils/log.h>
+
+#include "RenderNode.h"
+#include "utils/MathUtils.h"
+
+namespace android {
+namespace uirenderer {
+
+struct DirtyStack {
+ const RenderNode* node;
+ // When this frame is pop'd, this rect is mapped through the above transform
+ // and applied to the previous (aka parent) frame
+ SkRect pendingDirty;
+ DirtyStack* prev;
+ DirtyStack* next;
+};
+
+DamageAccumulator::DamageAccumulator() {
+ mHead = (DirtyStack*) mAllocator.alloc(sizeof(DirtyStack));
+ memset(mHead, 0, sizeof(DirtyStack));
+ // Create a root that we will not pop off
+ mHead->prev = mHead;
+}
+
+void DamageAccumulator::pushNode(const RenderNode* node) {
+ if (!mHead->next) {
+ DirtyStack* nextFrame = (DirtyStack*) mAllocator.alloc(sizeof(DirtyStack));
+ nextFrame->next = 0;
+ nextFrame->prev = mHead;
+ mHead->next = nextFrame;
+ }
+ mHead = mHead->next;
+ mHead->node = node;
+ mHead->pendingDirty.setEmpty();
+}
+
+void DamageAccumulator::popNode() {
+ 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();
+ const SkMatrix* transform = props.getTransformMatrix();
+ if (transform && !transform->isIdentity()) {
+ transform->mapRect(&mappedDirty, dirtyFrame->pendingDirty);
+ } else {
+ mappedDirty = dirtyFrame->pendingDirty;
+ }
+ 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();
+ }
+ }
+ 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());
+ }
+ } else {
+ mappedDirty.offset(props.getLeft(), props.getTop());
+ }
+ dirty(mappedDirty.fLeft, mappedDirty.fTop, mappedDirty.fRight, mappedDirty.fBottom);
+ }
+}
+
+void DamageAccumulator::dirty(float left, float top, float right, float bottom) {
+ mHead->pendingDirty.join(left, top, right, bottom);
+}
+
+void DamageAccumulator::finish(SkRect* totalDirty) {
+ LOG_ALWAYS_FATAL_IF(mHead->prev != mHead, "Cannot finish, mismatched push/pop calls! %p vs. %p", mHead->prev, mHead);
+ // Root node never has a transform, so this is the fully mapped dirty rect
+ *totalDirty = mHead->pendingDirty;
+ totalDirty->roundOut();
+ mHead->pendingDirty.setEmpty();
+}
+
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/DamageAccumulator.h b/libs/hwui/DamageAccumulator.h
new file mode 100644
index 0000000..c62a351
--- /dev/null
+++ b/libs/hwui/DamageAccumulator.h
@@ -0,0 +1,57 @@
+/*
+ * 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef DAMAGEACCUMULATOR_H
+#define DAMAGEACCUMULATOR_H
+
+#include <utils/LinearAllocator.h>
+
+#include <SkMatrix.h>
+#include <SkRect.h>
+
+#include "utils/Macros.h"
+
+namespace android {
+namespace uirenderer {
+
+struct DirtyStack;
+class RenderNode;
+
+class DamageAccumulator {
+ PREVENT_COPY_AND_ASSIGN(DamageAccumulator);
+public:
+ DamageAccumulator();
+ // mAllocator will clean everything up for us, no need for a dtor
+
+ // 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);
+ // 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);
+
+ void finish(SkRect* totalDirty);
+
+private:
+ LinearAllocator mAllocator;
+ DirtyStack* mHead;
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* DAMAGEACCUMULATOR_H */
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index 97e9bf6..d494c4c 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -81,6 +81,10 @@
success = LayerRenderer::resizeLayer(mLayer, mWidth, mHeight);
}
mLayer->setBlend(mBlend);
+ // TODO: Use DamageAccumulator to get the damage area for the layer's
+ // subtree to only update that part of the layer. Do this as part of
+ // reworking layers to be a RenderProperty instead of a View-managed object
+ mDirtyRect.set(0, 0, mWidth, mHeight);
mDisplayList->prepareTree(info);
mLayer->updateDeferred(mDisplayList.get(),
mDirtyRect.left, mDirtyRect.top, mDirtyRect.right, mDirtyRect.bottom);
diff --git a/libs/hwui/DrawProfiler.cpp b/libs/hwui/DrawProfiler.cpp
index 971a66e..2409554 100644
--- a/libs/hwui/DrawProfiler.cpp
+++ b/libs/hwui/DrawProfiler.cpp
@@ -109,7 +109,7 @@
mCurrentFrame = (mCurrentFrame + 1) % mDataSize;
}
-void DrawProfiler::unionDirty(Rect* dirty) {
+void DrawProfiler::unionDirty(SkRect* dirty) {
RETURN_IF_DISABLED();
// Not worth worrying about minimizing the dirty region for debugging, so just
// dirty the entire viewport.
diff --git a/libs/hwui/DrawProfiler.h b/libs/hwui/DrawProfiler.h
index c1aa1c6..7c06e5d 100644
--- a/libs/hwui/DrawProfiler.h
+++ b/libs/hwui/DrawProfiler.h
@@ -37,7 +37,7 @@
void markPlaybackEnd();
void finishFrame();
- void unionDirty(Rect* dirty);
+ void unionDirty(SkRect* dirty);
void draw(OpenGLRenderer* canvas);
void dumpData(int fd);
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index baf372a..c2f6df8 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -25,6 +25,7 @@
#include <utils/Trace.h>
+#include "DamageAccumulator.h"
#include "Debug.h"
#include "DisplayListOp.h"
#include "DisplayListLogBuffer.h"
@@ -110,14 +111,36 @@
prepareTreeImpl(info);
}
-void RenderNode::prepareTreeImpl(TreeInfo& info) {
- if (info.performStagingPush) {
- pushStagingChanges(info);
+static inline void pushNode(RenderNode* self, TreeInfo& info) {
+ if (info.damageAccumulator) {
+ info.damageAccumulator->pushNode(self);
}
- if (info.evaluateAnimations) {
+}
+
+static inline void popNode(TreeInfo& info) {
+ if (info.damageAccumulator) {
+ info.damageAccumulator->popNode();
+ }
+}
+
+void RenderNode::damageSelf(TreeInfo& info) {
+ if (info.damageAccumulator && isRenderable() && properties().getAlpha() > 0) {
+ info.damageAccumulator->dirty(0, 0, properties().getWidth(), properties().getHeight());
+ }
+}
+
+void RenderNode::prepareTreeImpl(TreeInfo& info) {
+ pushNode(this, info);
+ if (info.mode == TreeInfo::MODE_FULL) {
+ pushStagingChanges(info);
+ evaluateAnimations(info);
+ } else if (info.mode == TreeInfo::MODE_MAYBE_DETACHING) {
+ pushStagingChanges(info);
+ } else if (info.mode == TreeInfo::MODE_RT_ONLY) {
evaluateAnimations(info);
}
prepareSubTree(info, mDisplayListData);
+ popNode(info);
}
class PushAnimatorsFunctor {
@@ -149,18 +172,28 @@
}
if (mDirtyPropertyFields) {
mDirtyPropertyFields = 0;
+ damageSelf(info);
+ popNode(info);
mProperties = mStagingProperties;
+ pushNode(this, info);
+ // We could try to be clever and only re-damage if the matrix changed.
+ // However, we don't need to worry about that. The cost of over-damaging
+ // here is only going to be a single additional map rect of this node
+ // plus a rect join(). The parent's transform (and up) will only be
+ // performed once.
+ damageSelf(info);
}
if (mNeedsDisplayListDataSync) {
mNeedsDisplayListDataSync = false;
// Do a push pass on the old tree to handle freeing DisplayListData
// that are no longer used
- TreeInfo oldTreeInfo;
+ TreeInfo oldTreeInfo(TreeInfo::MODE_MAYBE_DETACHING);
+ oldTreeInfo.damageAccumulator = info.damageAccumulator;
prepareSubTree(oldTreeInfo, mDisplayListData);
- // TODO: The damage for the old tree should be accounted for
delete mDisplayListData;
mDisplayListData = mStagingDisplayListData;
mStagingDisplayListData = 0;
+ damageSelf(info);
}
}
@@ -180,12 +213,21 @@
void RenderNode::evaluateAnimations(TreeInfo& info) {
if (!mAnimators.size()) return;
+ // TODO: Can we target this better? For now treat it like any other staging
+ // property push and just damage self before and after animators are run
+
+ damageSelf(info);
+ popNode(info);
+
AnimateFunctor functor(this, info);
std::vector< sp<BaseRenderNodeAnimator> >::iterator newEnd;
newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
mAnimators.erase(newEnd, mAnimators.end());
mProperties.updateMatrix();
info.out.hasAnimations |= mAnimators.size();
+
+ pushNode(this, info);
+ damageSelf(info);
}
void RenderNode::prepareSubTree(TreeInfo& info, DisplayListData* subtree) {
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index 1a5377b..393d4ea 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -148,7 +148,7 @@
mDirtyPropertyFields |= fields;
}
- const RenderProperties& properties() {
+ const RenderProperties& properties() const {
return mProperties;
}
@@ -187,6 +187,9 @@
mNeedsAnimatorsSync = true;
}
+protected:
+ virtual void damageSelf(TreeInfo& info);
+
private:
typedef key_value_pair_t<float, DrawDisplayListOp*> ZDrawDisplayListOpPair;
diff --git a/libs/hwui/RenderProperties.cpp b/libs/hwui/RenderProperties.cpp
index 5f7d4e3..6163df5 100644
--- a/libs/hwui/RenderProperties.cpp
+++ b/libs/hwui/RenderProperties.cpp
@@ -44,6 +44,7 @@
, mPivotX(0), mPivotY(0)
, mLeft(0), mTop(0), mRight(0), mBottom(0)
, mWidth(0), mHeight(0)
+ , mScrollX(0), mScrollY(0)
, mPivotExplicitlySet(false)
, mMatrixOrPivotDirty(false)
, mCaching(false) {
diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h
index b012fc5..c294f38 100644
--- a/libs/hwui/RenderProperties.h
+++ b/libs/hwui/RenderProperties.h
@@ -366,6 +366,22 @@
return false;
}
+ bool setScrollX(int scrollX) {
+ return RP_SET(mPrimitiveFields.mScrollX, scrollX);
+ }
+
+ bool setScrollY(int scrollY) {
+ return RP_SET(mPrimitiveFields.mScrollY, scrollY);
+ }
+
+ int getScrollX() const {
+ return mPrimitiveFields.mScrollX;
+ }
+
+ int getScrollY() const {
+ return mPrimitiveFields.mScrollY;
+ }
+
bool setCaching(bool caching) {
return RP_SET(mPrimitiveFields.mCaching, caching);
}
@@ -465,6 +481,7 @@
float mPivotX, mPivotY;
int mLeft, mTop, mRight, mBottom;
int mWidth, mHeight;
+ int mScrollX, mScrollY;
bool mPivotExplicitlySet;
bool mMatrixOrPivotDirty;
bool mCaching;
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index 8355f83..2096f98 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -18,11 +18,14 @@
#include <utils/Timers.h>
+#include "utils/Macros.h"
+
namespace android {
namespace uirenderer {
class BaseRenderNodeAnimator;
class AnimationListener;
+class DamageAccumulator;
class AnimationHook {
public:
@@ -31,21 +34,44 @@
~AnimationHook() {}
};
-struct TreeInfo {
- // The defaults here should be safe for everyone but DrawFrameTask to use as-is.
- TreeInfo()
- : frameTimeMs(0)
+// This would be a struct, but we want to PREVENT_COPY_AND_ASSIGN
+class TreeInfo {
+ PREVENT_COPY_AND_ASSIGN(TreeInfo);
+public:
+ enum TraversalMode {
+ // The full monty - sync, push, run animators, etc... Used by DrawFrameTask
+ // May only be used if both the UI thread and RT thread are blocked on the
+ // prepare
+ MODE_FULL,
+ // Run only what can be done safely on RT thread. Currently this only means
+ // animators, but potentially things like SurfaceTexture updates
+ // could be handled by this as well if there are no listeners
+ MODE_RT_ONLY,
+ // The subtree is being detached. Maybe. If the RenderNode is present
+ // in both the old and new display list's children then it will get a
+ // MODE_MAYBE_DETACHING followed shortly by a MODE_FULL.
+ // Push any pending display list changes in case it is detached,
+ // but don't evaluate animators and such as if it isn't detached as a
+ // MODE_FULL will follow shortly.
+ MODE_MAYBE_DETACHING,
+ // TODO: TRIM_MEMORY?
+ };
+
+ explicit TreeInfo(TraversalMode mode)
+ : mode(mode)
+ , frameTimeMs(0)
, animationHook(NULL)
- , prepareTextures(false)
- , performStagingPush(true)
- , evaluateAnimations(false)
+ , prepareTextures(mode == MODE_FULL)
+ , damageAccumulator(0)
{}
+ const TraversalMode mode;
nsecs_t frameTimeMs;
AnimationHook* animationHook;
+ // TODO: Remove this? Currently this is used to signal to stop preparing
+ // textures if we run out of cache space.
bool prepareTextures;
- bool performStagingPush;
- bool evaluateAnimations;
+ DamageAccumulator* damageAccumulator;
struct Out {
Out()
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 9ebee1d..8a5c857 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -439,6 +439,7 @@
mRenderThread.removeFrameCallback(this);
info.frameTimeMs = mRenderThread.timeLord().frameTimeMs();
+ info.damageAccumulator = &mDamageAccumulator;
mRootRenderNode->prepareTree(info);
int runningBehind = 0;
@@ -465,27 +466,30 @@
mRenderThread.pushBackFrameCallback(this);
}
-void CanvasContext::draw(Rect* dirty) {
+void CanvasContext::draw() {
LOG_ALWAYS_FATAL_IF(!mCanvas || mEglSurface == EGL_NO_SURFACE,
"drawDisplayList called on a context with no canvas or surface!");
profiler().markPlaybackStart();
+ SkRect dirty;
+ mDamageAccumulator.finish(&dirty);
+
EGLint width, height;
mGlobalContext->beginFrame(mEglSurface, &width, &height);
if (width != mCanvas->getViewportWidth() || height != mCanvas->getViewportHeight()) {
mCanvas->setViewport(width, height);
- dirty = NULL;
+ dirty.setEmpty();
} else if (!mDirtyRegionsEnabled || mHaveNewSurface) {
- dirty = NULL;
+ dirty.setEmpty();
} else {
- profiler().unionDirty(dirty);
+ profiler().unionDirty(&dirty);
}
status_t status;
- if (dirty && !dirty->isEmpty()) {
- status = mCanvas->prepareDirty(dirty->left, dirty->top,
- dirty->right, dirty->bottom, mOpaque);
+ if (!dirty.isEmpty()) {
+ status = mCanvas->prepareDirty(dirty.fLeft, dirty.fTop,
+ dirty.fRight, dirty.fBottom, mOpaque);
} else {
status = mCanvas->prepare(mOpaque);
}
@@ -516,14 +520,12 @@
profiler().startFrame();
- TreeInfo info;
- info.evaluateAnimations = true;
- info.performStagingPush = false;
+ TreeInfo info(TreeInfo::MODE_RT_ONLY);
info.prepareTextures = false;
prepareTree(info);
if (info.out.canDrawThisFrame) {
- draw(NULL);
+ draw();
}
}
@@ -543,7 +545,7 @@
bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
requireGlContext();
- TreeInfo info;
+ TreeInfo info(TreeInfo::MODE_FULL);
layer->apply(info);
return LayerRenderer::copyLayer(layer->backingLayer(), bitmap);
}
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 00c5bf0..d926b38 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -23,6 +23,7 @@
#include <utils/Functor.h>
#include <utils/Vector.h>
+#include "../DamageAccumulator.h"
#include "../DrawProfiler.h"
#include "../RenderNode.h"
#include "RenderTask.h"
@@ -57,7 +58,7 @@
void makeCurrent();
void processLayerUpdate(DeferredLayerUpdater* layerUpdater, TreeInfo& info);
void prepareTree(TreeInfo& info);
- void draw(Rect* dirty);
+ void draw();
void destroyCanvasAndSurface();
// IFrameCallback, Chroreographer-driven frame callback entry point
@@ -99,6 +100,7 @@
bool mOpaque;
OpenGLRenderer* mCanvas;
bool mHaveNewSurface;
+ DamageAccumulator mDamageAccumulator;
const sp<RenderNode> mRootRenderNode;
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 61d67ca..bdfdd21 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -68,10 +68,6 @@
}
}
-void DrawFrameTask::setDirty(int left, int top, int right, int bottom) {
- mDirty.set(left, top, right, bottom);
-}
-
int DrawFrameTask::drawFrame(nsecs_t frameTimeNanos, nsecs_t recordDurationNanos) {
LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!");
@@ -83,7 +79,6 @@
// Reset the single-frame data
mFrameTimeNanos = 0;
mRecordDurationNanos = 0;
- mDirty.setEmpty();
return mSyncResult;
}
@@ -103,13 +98,12 @@
bool canUnblockUiThread;
bool canDrawThisFrame;
{
- TreeInfo info;
+ TreeInfo info(TreeInfo::MODE_FULL);
canUnblockUiThread = syncFrameState(info);
canDrawThisFrame = info.out.canDrawThisFrame;
}
// Grab a copy of everything we need
- Rect dirty(mDirty);
CanvasContext* context = mContext;
// From this point on anything in "this" is *UNSAFE TO ACCESS*
@@ -118,7 +112,7 @@
}
if (CC_LIKELY(canDrawThisFrame)) {
- context->draw(&dirty);
+ context->draw();
}
if (!canUnblockUiThread) {
@@ -126,18 +120,11 @@
}
}
-static void initTreeInfo(TreeInfo& info) {
- info.prepareTextures = true;
- info.performStagingPush = true;
- info.evaluateAnimations = true;
-}
-
bool DrawFrameTask::syncFrameState(TreeInfo& info) {
ATRACE_CALL();
mRenderThread->timeLord().vsyncReceived(mFrameTimeNanos);
mContext->makeCurrent();
Caches::getInstance().textureCache.resetMarkInUse();
- initTreeInfo(info);
for (size_t i = 0; i < mLayers.size(); i++) {
mContext->processLayerUpdate(mLayers[i].get(), info);
@@ -149,8 +136,6 @@
mContext->prepareTree(info);
if (info.out.hasAnimations) {
- // TODO: dirty calculations, for now just do a full-screen inval
- mDirty.setEmpty();
if (info.out.requiresUiRedraw) {
mSyncResult |= kSync_UIRedrawRequired;
}
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index d4129b6..96f0add 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -60,7 +60,6 @@
void pushLayerUpdate(DeferredLayerUpdater* layer);
void removeLayerUpdate(DeferredLayerUpdater* layer);
- void setDirty(int left, int top, int right, int bottom);
void setDensity(float density) { mDensity = density; }
int drawFrame(nsecs_t frameTimeNanos, nsecs_t recordDurationNanos);
@@ -80,7 +79,6 @@
/*********************************************
* Single frame data
*********************************************/
- Rect mDirty;
nsecs_t mFrameTimeNanos;
nsecs_t mRecordDurationNanos;
float mDensity;
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 0901963..ded10a1 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -180,8 +180,7 @@
}
int RenderProxy::syncAndDrawFrame(nsecs_t frameTimeNanos, nsecs_t recordDurationNanos,
- float density, int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom) {
- mDrawFrameTask.setDirty(dirtyLeft, dirtyTop, dirtyRight, dirtyBottom);
+ float density) {
mDrawFrameTask.setDensity(density);
return mDrawFrameTask.drawFrame(frameTimeNanos, recordDurationNanos);
}
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 944ff9c..a95f8f0 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -70,7 +70,7 @@
ANDROID_API void setup(int width, int height, const Vector3& lightCenter, float lightRadius);
ANDROID_API void setOpaque(bool opaque);
ANDROID_API int syncAndDrawFrame(nsecs_t frameTimeNanos, nsecs_t recordDurationNanos,
- float density, int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom);
+ float density);
ANDROID_API void destroyCanvasAndSurface();
ANDROID_API void invokeFunctor(Functor* functor, bool waitForCompletion);