summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
authorChris Craik <ccraik@google.com>2013-03-15 22:54:15 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2013-03-15 22:54:16 +0000
commitf40b8a939fef0a19b40188f007a3364311d6dabf (patch)
tree027797050b58bcb2d1bac153f980282a38ae49a0 /libs
parent30527267d12d4338820d4ec2526c6bf81c7f7785 (diff)
parentff78583d8a73ca35ce65b5d2592570ff6fb9901b (diff)
downloadframeworks_base-f40b8a939fef0a19b40188f007a3364311d6dabf.zip
frameworks_base-f40b8a939fef0a19b40188f007a3364311d6dabf.tar.gz
frameworks_base-f40b8a939fef0a19b40188f007a3364311d6dabf.tar.bz2
Merge "Fully deferred displaylist replay" into jb-mr2-dev
Diffstat (limited to 'libs')
-rw-r--r--libs/hwui/Caches.cpp9
-rw-r--r--libs/hwui/DeferredDisplayList.cpp280
-rw-r--r--libs/hwui/DeferredDisplayList.h35
-rw-r--r--libs/hwui/DisplayList.cpp151
-rw-r--r--libs/hwui/DisplayList.h59
-rw-r--r--libs/hwui/DisplayListOp.h417
-rw-r--r--libs/hwui/DisplayListRenderer.cpp10
-rw-r--r--libs/hwui/DisplayListRenderer.h4
-rw-r--r--libs/hwui/OpenGLRenderer.cpp80
-rw-r--r--libs/hwui/OpenGLRenderer.h45
10 files changed, 732 insertions, 358 deletions
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index a1cc2e8..4642a4f 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -103,14 +103,9 @@ void Caches::initFont() {
void Caches::initExtensions() {
if (mExtensions.hasDebugMarker()) {
eventMark = glInsertEventMarkerEXT;
- if ((drawDeferDisabled || drawReorderDisabled)) {
- startMark = glPushGroupMarkerEXT;
- endMark = glPopGroupMarkerEXT;
- } else {
- startMark = startMarkNull;
- endMark = endMarkNull;
- }
+ startMark = glPushGroupMarkerEXT;
+ endMark = glPopGroupMarkerEXT;
} else {
eventMark = eventMarkNull;
startMark = startMarkNull;
diff --git a/libs/hwui/DeferredDisplayList.cpp b/libs/hwui/DeferredDisplayList.cpp
index a4e9950..2027fc8 100644
--- a/libs/hwui/DeferredDisplayList.cpp
+++ b/libs/hwui/DeferredDisplayList.cpp
@@ -32,15 +32,15 @@
namespace android {
namespace uirenderer {
+/////////////////////////////////////////////////////////////////////////////////
+// Operation Batches
+/////////////////////////////////////////////////////////////////////////////////
+
class DrawOpBatch {
public:
- DrawOpBatch() {
- mOps.clear();
- }
+ DrawOpBatch() { mOps.clear(); }
- ~DrawOpBatch() {
- mOps.clear();
- }
+ virtual ~DrawOpBatch() { mOps.clear(); }
void add(DrawOp* op) {
// NOTE: ignore empty bounds special case, since we don't merge across those ops
@@ -48,8 +48,9 @@ public:
mOps.add(op);
}
- bool intersects(Rect& rect) {
+ virtual bool intersects(Rect& rect) {
if (!rect.intersects(mBounds)) return false;
+
for (unsigned int i = 0; i < mOps.size(); i++) {
if (rect.intersects(mOps[i]->state.mBounds)) {
#if DEBUG_DEFER
@@ -64,27 +65,217 @@ public:
return false;
}
- Vector<DrawOp*> mOps;
+ virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty) {
+ DEFER_LOGD("replaying draw batch %p", this);
+
+ status_t status = DrawGlInfo::kStatusDone;
+ DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
+ for (unsigned int i = 0; i < mOps.size(); i++) {
+ DrawOp* op = mOps[i];
+
+ renderer.restoreDisplayState(op->state, kStateDeferFlag_Draw);
+
+#if DEBUG_DISPLAY_LIST_OPS_AS_EVENTS
+ renderer.eventMark(strlen(op->name()), op->name());
+#endif
+ status |= op->applyDraw(renderer, dirty, 0, op->state.mMultipliedAlpha);
+ logBuffer.writeCommand(0, op->name());
+ }
+ return status;
+ }
+
+ inline int count() const { return mOps.size(); }
private:
+ Vector<DrawOp*> mOps;
Rect mBounds;
};
-void DeferredDisplayList::clear() {
+class StateOpBatch : public DrawOpBatch {
+public:
+ // creates a single operation batch
+ StateOpBatch(StateOp* op) : mOp(op) {}
+
+ bool intersects(Rect& rect) {
+ // if something checks for intersection, it's trying to go backwards across a state op,
+ // something not currently supported - state ops are always barriers
+ CRASH();
+ return false;
+ }
+
+ virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty) {
+ DEFER_LOGD("replaying state op batch %p", this);
+ renderer.restoreDisplayState(mOp->state, 0);
+
+ // use invalid save count because it won't be used at flush time - RestoreToCountOp is the
+ // only one to use it, and we don't use that class at flush time, instead calling
+ // renderer.restoreToCount directly
+ int saveCount = -1;
+ mOp->applyState(renderer, saveCount);
+ return DrawGlInfo::kStatusDone;
+ }
+
+private:
+ StateOp* mOp;
+};
+
+class RestoreToCountBatch : public DrawOpBatch {
+public:
+ RestoreToCountBatch(int restoreCount) : mRestoreCount(restoreCount) {}
+
+ bool intersects(Rect& rect) {
+ // if something checks for intersection, it's trying to go backwards across a state op,
+ // something not currently supported - state ops are always barriers
+ CRASH();
+ return false;
+ }
+
+ virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty) {
+ DEFER_LOGD("batch %p restoring to count %d", this, mRestoreCount);
+ renderer.restoreToCount(mRestoreCount);
+
+ return DrawGlInfo::kStatusDone;
+ }
+
+private:
+ /*
+ * The count used here represents the flush() time saveCount. This is as opposed to the
+ * DisplayList record time, or defer() time values (which are RestoreToCountOp's mCount, and
+ * (saveCount + mCount) respectively). Since the count is different from the original
+ * RestoreToCountOp, we don't store a pointer to the op, as elsewhere.
+ */
+ const int mRestoreCount;
+};
+
+/////////////////////////////////////////////////////////////////////////////////
+// DeferredDisplayList
+/////////////////////////////////////////////////////////////////////////////////
+
+void DeferredDisplayList::resetBatchingState() {
for (int i = 0; i < kOpBatch_Count; i++) {
mBatchIndices[i] = -1;
}
+}
+
+void DeferredDisplayList::clear() {
+ resetBatchingState();
+ mComplexClipStackStart = -1;
+
for (unsigned int i = 0; i < mBatches.size(); i++) {
delete mBatches[i];
}
mBatches.clear();
+ mSaveStack.clear();
}
-void DeferredDisplayList::add(DrawOp* op, bool disallowReorder) {
- if (CC_UNLIKELY(disallowReorder)) {
- if (!mBatches.isEmpty()) {
- mBatches[0]->add(op);
- return;
+/////////////////////////////////////////////////////////////////////////////////
+// Operation adding
+/////////////////////////////////////////////////////////////////////////////////
+
+int DeferredDisplayList::getStateOpDeferFlags() const {
+ // For both clipOp and save(Layer)Op, we don't want to save drawing info, and only want to save
+ // the clip if we aren't recording a complex clip (and can thus trust it to be a rect)
+ return recordingComplexClip() ? 0 : kStateDeferFlag_Clip;
+}
+
+int DeferredDisplayList::getDrawOpDeferFlags() const {
+ return kStateDeferFlag_Draw | getStateOpDeferFlags();
+}
+
+/**
+ * When an clipping operation occurs that could cause a complex clip, record the operation and all
+ * subsequent clipOps, save/restores (if the clip flag is set). During a flush, instead of loading
+ * the clip from deferred state, we play back all of the relevant state operations that generated
+ * the complex clip.
+ *
+ * Note that we don't need to record the associated restore operation, since operations at defer
+ * time record whether they should store the renderer's current clip
+ */
+void DeferredDisplayList::addClip(OpenGLRenderer& renderer, ClipOp* op) {
+ if (recordingComplexClip() || op->canCauseComplexClip() || !renderer.hasRectToRectTransform()) {
+ DEFER_LOGD("%p Received complex clip operation %p", this, op);
+
+ // NOTE: defer clip op before setting mComplexClipStackStart so previous clip is recorded
+ storeStateOpBarrier(renderer, op);
+
+ if (!recordingComplexClip()) {
+ mComplexClipStackStart = renderer.getSaveCount() - 1;
+ DEFER_LOGD(" Starting complex clip region, start is %d", mComplexClipStackStart);
}
+ }
+}
+
+/**
+ * For now, we record save layer operations as barriers in the batch list, preventing drawing
+ * operations from reordering around the saveLayer and it's associated restore()
+ *
+ * In the future, we should send saveLayer commands (if they can be played out of order) and their
+ * contained drawing operations to a seperate list of batches, so that they may draw at the
+ * beginning of the frame. This would avoid targetting and removing an FBO in the middle of a frame.
+ *
+ * saveLayer operations should be pulled to the beginning of the frame if the canvas doesn't have a
+ * complex clip, and if the flags (kClip_SaveFlag & kClipToLayer_SaveFlag) are set.
+ */
+void DeferredDisplayList::addSaveLayer(OpenGLRenderer& renderer,
+ SaveLayerOp* op, int newSaveCount) {
+ DEFER_LOGD("%p adding saveLayerOp %p, flags %x, new count %d",
+ this, op, op->getFlags(), newSaveCount);
+
+ storeStateOpBarrier(renderer, op);
+ mSaveStack.push(newSaveCount);
+}
+
+/**
+ * Takes save op and it's return value - the new save count - and stores it into the stream as a
+ * barrier if it's needed to properly modify a complex clip
+ */
+void DeferredDisplayList::addSave(OpenGLRenderer& renderer, SaveOp* op, int newSaveCount) {
+ int saveFlags = op->getFlags();
+ DEFER_LOGD("%p adding saveOp %p, flags %x, new count %d", this, op, saveFlags, newSaveCount);
+
+ if (recordingComplexClip() && (saveFlags & SkCanvas::kClip_SaveFlag)) {
+ // store and replay the save operation, as it may be needed to correctly playback the clip
+ DEFER_LOGD(" adding save barrier with new save count %d", newSaveCount);
+ storeStateOpBarrier(renderer, op);
+ mSaveStack.push(newSaveCount);
+ }
+}
+
+/**
+ * saveLayer() commands must be associated with a restoreToCount batch that will clean up and draw
+ * the layer in the deferred list
+ *
+ * other save() commands which occur as children of a snapshot with complex clip will be deferred,
+ * and must be restored
+ *
+ * Either will act as a barrier to draw operation reordering, as we want to play back layer
+ * save/restore and complex canvas modifications (including save/restore) in order.
+ */
+void DeferredDisplayList::addRestoreToCount(OpenGLRenderer& renderer, int newSaveCount) {
+ DEFER_LOGD("%p addRestoreToCount %d", this, newSaveCount);
+
+ if (recordingComplexClip() && newSaveCount <= mComplexClipStackStart) {
+ mComplexClipStackStart = -1;
+ resetBatchingState();
+ }
+
+ if (mSaveStack.isEmpty() || newSaveCount > mSaveStack.top()) {
+ return;
+ }
+
+ while (!mSaveStack.isEmpty() && mSaveStack.top() >= newSaveCount) mSaveStack.pop();
+
+ storeRestoreToCountBarrier(mSaveStack.size() + 1);
+}
+
+void DeferredDisplayList::addDrawOp(OpenGLRenderer& renderer, DrawOp* op) {
+ if (renderer.storeDisplayState(op->state, getDrawOpDeferFlags())) {
+ return; // quick rejected
+ }
+
+ op->onDrawOpDeferred(renderer);
+
+ if (CC_UNLIKELY(renderer.getCaches().drawReorderDisabled)) {
+ // TODO: elegant way to reuse batches?
DrawOpBatch* b = new DrawOpBatch();
b->add(op);
mBatches.add(b);
@@ -138,9 +329,41 @@ void DeferredDisplayList::add(DrawOp* op, bool disallowReorder) {
targetBatch->add(op);
}
-status_t DeferredDisplayList::flush(OpenGLRenderer& renderer, Rect& dirty, int32_t flags,
- uint32_t level) {
- ATRACE_CALL();
+void DeferredDisplayList::storeStateOpBarrier(OpenGLRenderer& renderer, StateOp* op) {
+ DEFER_LOGD("%p adding state op barrier at pos %d", this, mBatches.size());
+
+ renderer.storeDisplayState(op->state, getStateOpDeferFlags());
+ mBatches.add(new StateOpBatch(op));
+ resetBatchingState();
+}
+
+void DeferredDisplayList::storeRestoreToCountBarrier(int newSaveCount) {
+ DEFER_LOGD("%p adding restore to count %d barrier, pos %d",
+ this, newSaveCount, mBatches.size());
+
+ mBatches.add(new RestoreToCountBatch(newSaveCount));
+ resetBatchingState();
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+// Replay / flush
+/////////////////////////////////////////////////////////////////////////////////
+
+static status_t replayBatchList(Vector<DrawOpBatch*>& batchList,
+ OpenGLRenderer& renderer, Rect& dirty) {
+ status_t status = DrawGlInfo::kStatusDone;
+
+ int opCount = 0;
+ for (unsigned int i = 0; i < batchList.size(); i++) {
+ status |= batchList[i]->replay(renderer, dirty);
+ opCount += batchList[i]->count();
+ }
+ DEFER_LOGD("--flushed, drew %d batches (total %d ops)", batchList.size(), opCount);
+ return status;
+}
+
+status_t DeferredDisplayList::flush(OpenGLRenderer& renderer, Rect& dirty) {
+ ATRACE_NAME("flush drawing commands");
status_t status = DrawGlInfo::kStatusDone;
if (isEmpty()) return status; // nothing to flush
@@ -148,29 +371,12 @@ status_t DeferredDisplayList::flush(OpenGLRenderer& renderer, Rect& dirty, int32
DEFER_LOGD("--flushing");
renderer.eventMark("Flush");
- DrawModifiers restoreDrawModifiers = renderer.getDrawModifiers();
- int restoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
- int opCount = 0;
- for (unsigned int i = 0; i < mBatches.size(); i++) {
- DrawOpBatch* batch = mBatches[i];
- for (unsigned int j = 0; j < batch->mOps.size(); j++) {
- DrawOp* op = batch->mOps[j];
+ renderer.restoreToCount(1);
- renderer.restoreDisplayState(op->state);
-
-#if DEBUG_DEFER
- op->output(2);
-#endif
- status |= op->applyDraw(renderer, dirty, level,
- op->state.mMultipliedAlpha >= 0, op->state.mMultipliedAlpha);
- opCount++;
- }
- }
+ status |= replayBatchList(mBatches, renderer, dirty);
- DEFER_LOGD("--flushed, drew %d batches (total %d ops)", mBatches.size(), opCount);
+ DEFER_LOGD("--flush complete, returning %x", status);
- renderer.restoreToCount(restoreTo);
- renderer.setDrawModifiers(restoreDrawModifiers);
clear();
return status;
}
diff --git a/libs/hwui/DeferredDisplayList.h b/libs/hwui/DeferredDisplayList.h
index 4fcb297..8e908fa 100644
--- a/libs/hwui/DeferredDisplayList.h
+++ b/libs/hwui/DeferredDisplayList.h
@@ -26,10 +26,13 @@
namespace android {
namespace uirenderer {
+class ClipOp;
class DrawOp;
+class SaveOp;
+class SaveLayerOp;
+class StateOp;
class DrawOpBatch;
class OpenGLRenderer;
-class SkiaShader;
class DeferredDisplayList {
public:
@@ -55,18 +58,42 @@ public:
* Plays back all of the draw ops recorded into batches to the renderer.
* Adjusts the state of the renderer as necessary, and restores it when complete
*/
- status_t flush(OpenGLRenderer& renderer, Rect& dirty, int32_t flags,
- uint32_t level);
+ status_t flush(OpenGLRenderer& renderer, Rect& dirty);
+
+ void addClip(OpenGLRenderer& renderer, ClipOp* op);
+ void addSaveLayer(OpenGLRenderer& renderer, SaveLayerOp* op, int newSaveCount);
+ void addSave(OpenGLRenderer& renderer, SaveOp* op, int newSaveCount);
+ void addRestoreToCount(OpenGLRenderer& renderer, int newSaveCount);
/**
* Add a draw op into the DeferredDisplayList, reordering as needed (for performance) if
* disallowReorder is false, respecting draw order when overlaps occur
*/
- void add(DrawOp* op, bool disallowReorder);
+ void addDrawOp(OpenGLRenderer& renderer, DrawOp* op);
private:
+ /*
+ * Resets the batching back-pointers, creating a barrier in the operation stream so that no ops
+ * added in the future will be inserted into a batch that already exist.
+ */
+ void resetBatchingState();
+
void clear();
+ void storeStateOpBarrier(OpenGLRenderer& renderer, StateOp* op);
+ void storeRestoreToCountBarrier(int newSaveCount);
+
+ bool recordingComplexClip() const { return mComplexClipStackStart >= 0; }
+
+ int getStateOpDeferFlags() const;
+ int getDrawOpDeferFlags() const;
+
+ /*
+ *
+ * at defer time, stores the savecount of save/saveLayer ops that were
+ */
+ Vector<int> mSaveStack;
+ int mComplexClipStackStart;
Vector<DrawOpBatch*> mBatches;
int mBatchIndices[kOpBatch_Count];
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index 5781f4d..4743f58 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -61,6 +61,12 @@ void DisplayList::destroyDisplayListDeferred(DisplayList* displayList) {
void DisplayList::clearResources() {
mDisplayListData = NULL;
+
+ mClipRectOp = NULL;
+ mSaveLayerOp = NULL;
+ mSaveOp = NULL;
+ mRestoreToCountOp = NULL;
+
delete mTransformMatrix;
delete mTransformCamera;
delete mTransformMatrix3D;
@@ -156,6 +162,13 @@ void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorde
return;
}
+ // allocate reusable ops for state-deferral
+ LinearAllocator& alloc = mDisplayListData->allocator;
+ mClipRectOp = new (alloc) ClipRectOp();
+ mSaveLayerOp = new (alloc) SaveLayerOp();
+ mSaveOp = new (alloc) SaveOp();
+ mRestoreToCountOp = new (alloc) RestoreToCountOp();
+
mFunctorCount = recorder.getFunctorCount();
Caches& caches = Caches::getInstance();
@@ -318,7 +331,7 @@ void DisplayList::updateMatrix() {
}
}
-void DisplayList::outputViewProperties(uint32_t level) {
+void DisplayList::outputViewProperties(const int level) {
updateMatrix();
if (mLeft != 0 || mTop != 0) {
ALOGD("%*sTranslate (left, top) %d, %d", level * 2, "", mLeft, mTop);
@@ -358,10 +371,17 @@ void DisplayList::outputViewProperties(uint32_t level) {
}
}
-status_t DisplayList::setViewProperties(OpenGLRenderer& renderer, Rect& dirty,
- int32_t flags, uint32_t level, DeferredDisplayList* deferredList) {
- status_t status = DrawGlInfo::kStatusDone;
-#if DEBUG_DISPLAYLIST
+/*
+ * 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 + mCount)
+ */
+#define PROPERTY_SAVECOUNT 0
+
+template <class T>
+void DisplayList::setViewProperties(OpenGLRenderer& renderer, T& handler,
+ const int level) {
+#if DEBUG_DISPLAY_LIST
outputViewProperties(level);
#endif
updateMatrix();
@@ -381,86 +401,121 @@ status_t DisplayList::setViewProperties(OpenGLRenderer& renderer, Rect& dirty,
}
}
if (mAlpha < 1 && !mCaching) {
- if (deferredList) {
- // flush since we'll either enter a Layer, or set alpha, both not supported in deferral
- status |= deferredList->flush(renderer, dirty, flags, level);
- }
-
if (!mHasOverlappingRendering) {
renderer.setAlpha(mAlpha);
} else {
// TODO: should be able to store the size of a DL at record time and not
// have to pass it into this call. In fact, this information might be in the
// location/size info that we store with the new native transform data.
- int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
+ int saveFlags = SkCanvas::kHasAlphaLayer_SaveFlag;
if (mClipChildren) {
- flags |= SkCanvas::kClipToLayer_SaveFlag;
+ saveFlags |= SkCanvas::kClipToLayer_SaveFlag;
}
- renderer.saveLayerAlpha(0, 0, mRight - mLeft, mBottom - mTop,
- mMultipliedAlpha, flags);
+ handler(mSaveLayerOp->reinit(0, 0, mRight - mLeft, mBottom - mTop,
+ mMultipliedAlpha, SkXfermode::kSrcOver_Mode, saveFlags), PROPERTY_SAVECOUNT);
}
}
if (mClipChildren && !mCaching) {
- if (deferredList && CC_UNLIKELY(!renderer.hasRectToRectTransform())) {
- // flush, since clip will likely be a region
- status |= deferredList->flush(renderer, dirty, flags, level);
- }
- renderer.clipRect(0, 0, mRight - mLeft, mBottom - mTop,
- SkRegion::kIntersect_Op);
+ handler(mClipRectOp->reinit(0, 0, mRight - mLeft, mBottom - mTop, SkRegion::kIntersect_Op),
+ PROPERTY_SAVECOUNT);
+ }
+}
+
+class DeferOperationHandler {
+public:
+ DeferOperationHandler(DeferStateStruct& deferStruct, int multipliedAlpha, int level)
+ : mDeferStruct(deferStruct), mMultipliedAlpha(multipliedAlpha), mLevel(level) {}
+ inline void operator()(DisplayListOp* operation, int saveCount) {
+ operation->defer(mDeferStruct, saveCount, mLevel, mMultipliedAlpha);
+ }
+private:
+ DeferStateStruct& mDeferStruct;
+ const int mMultipliedAlpha;
+ const int mLevel;
+};
+
+void DisplayList::defer(DeferStateStruct& deferStruct, const int level) {
+ DeferOperationHandler handler(deferStruct, mCaching ? mMultipliedAlpha : -1, level);
+ iterate<DeferOperationHandler>(deferStruct.mRenderer, handler, level);
+}
+
+class ReplayOperationHandler {
+public:
+ ReplayOperationHandler(ReplayStateStruct& replayStruct, int multipliedAlpha, int level)
+ : mReplayStruct(replayStruct), mMultipliedAlpha(multipliedAlpha), mLevel(level) {}
+ inline void operator()(DisplayListOp* operation, int saveCount) {
+#if DEBUG_DISPLAY_LIST_OPS_AS_EVENTS
+ replayStruct.mRenderer.eventMark(operation->name());
+#endif
+ operation->replay(mReplayStruct, saveCount, mLevel, mMultipliedAlpha);
}
- return status;
+private:
+ ReplayStateStruct& mReplayStruct;
+ const int mMultipliedAlpha;
+ const int mLevel;
+};
+
+void DisplayList::replay(ReplayStateStruct& replayStruct, const int level) {
+ ReplayOperationHandler handler(replayStruct, mCaching ? mMultipliedAlpha : -1, level);
+
+ replayStruct.mRenderer.startMark(mName.string());
+ iterate<ReplayOperationHandler>(replayStruct.mRenderer, handler, level);
+ replayStruct.mRenderer.endMark();
+
+ DISPLAY_LIST_LOGD("%*sDone (%p, %s), returning %d", level * 2, "", this, mName.string(),
+ replayStruct.mDrawGlStatus);
}
-status_t DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, uint32_t level,
- DeferredDisplayList* deferredList) {
- status_t drawGlStatus = DrawGlInfo::kStatusDone;
+/**
+ * This function serves both defer and replay modes, and will organize the displayList's component
+ * operations for a single frame:
+ *
+ * Every 'simple' operation that affects just the matrix and alpha (or other factors of
+ * DeferredDisplayState) may be issued directly to the renderer, but complex operations (with custom
+ * defer logic) and operations in displayListOps are issued through the 'handler' which handles the
+ * defer vs replay logic, per operation
+ */
+template <class T>
+void DisplayList::iterate(OpenGLRenderer& renderer, T& handler, const int level) {
+ if (mSize == 0 || mAlpha <= 0) {
+ DISPLAY_LIST_LOGD("%*sEmpty display list (%p, %s)", level * 2, "", this, mName.string());
+ return;
+ }
#if DEBUG_DISPLAY_LIST
Rect* clipRect = renderer.getClipRect();
DISPLAY_LIST_LOGD("%*sStart display list (%p, %s), clipRect: %.0f, %.f, %.0f, %.0f",
- (level+1)*2, "", this, mName.string(), clipRect->left, clipRect->top,
+ level * 2, "", this, mName.string(), clipRect->left, clipRect->top,
clipRect->right, clipRect->bottom);
#endif
- renderer.startMark(mName.string());
+ int restoreTo = renderer.getSaveCount();
+ handler(mSaveOp->reinit(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag),
+ PROPERTY_SAVECOUNT);
- int restoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
- DISPLAY_LIST_LOGD("%*sSave %d %d", level * 2, "",
+ DISPLAY_LIST_LOGD("%*sSave %d %d", (level + 1) * 2, "",
SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag, restoreTo);
- drawGlStatus |= setViewProperties(renderer, dirty, flags, level, deferredList);
+ setViewProperties<T>(renderer, handler, level + 1);
if (renderer.quickRejectNoScissor(0, 0, mWidth, mHeight)) {
DISPLAY_LIST_LOGD("%*sRestoreToCount %d", level * 2, "", restoreTo);
- renderer.restoreToCount(restoreTo);
- renderer.endMark();
- return drawGlStatus;
+ handler(mRestoreToCountOp->reinit(restoreTo), PROPERTY_SAVECOUNT);
+ return;
}
DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
int saveCount = renderer.getSaveCount() - 1;
for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) {
DisplayListOp *op = mDisplayListData->displayListOps[i];
-#if DEBUG_DISPLAY_LIST_OPS_AS_EVENTS
- renderer.eventMark(strlen(op->name()), op->name());
-#endif
- drawGlStatus |= op->replay(renderer, dirty, flags,
- saveCount, level, mCaching, mMultipliedAlpha, deferredList);
+
+ handler(op, saveCount);
logBuffer.writeCommand(level, op->name());
}
- DISPLAY_LIST_LOGD("%*sRestoreToCount %d", level * 2, "", restoreTo);
+ DISPLAY_LIST_LOGD("%*sRestoreToCount %d", (level + 1) * 2, "", restoreTo);
+ handler(mRestoreToCountOp->reinit(restoreTo), PROPERTY_SAVECOUNT);
renderer.restoreToCount(restoreTo);
- renderer.endMark();
-
- DISPLAY_LIST_LOGD("%*sDone (%p, %s), returning %d", (level + 1) * 2, "", this, mName.string(),
- drawGlStatus);
-
- if (!level && CC_LIKELY(deferredList)) {
- drawGlStatus |= deferredList->flush(renderer, dirty, flags, level);
- }
-
- return drawGlStatus;
}
}; // namespace uirenderer
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index feee69c..5392587 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -24,6 +24,8 @@
#include <SkCamera.h>
#include <SkMatrix.h>
+#include <private/hwui/DrawGlInfo.h>
+
#include <utils/RefBase.h>
#include <utils/SortedVector.h>
#include <utils/String8.h>
@@ -57,10 +59,33 @@ class Layer;
class SkiaColorFilter;
class SkiaShader;
+class ClipRectOp;
+class SaveLayerOp;
+class SaveOp;
+class RestoreToCountOp;
+
+struct DeferStateStruct {
+ DeferStateStruct(DeferredDisplayList& deferredList, OpenGLRenderer& renderer, int replayFlags)
+ : mDeferredList(deferredList), mRenderer(renderer), mReplayFlags(replayFlags) {}
+ DeferredDisplayList& mDeferredList;
+ OpenGLRenderer& mRenderer;
+ const int mReplayFlags;
+};
+
+struct ReplayStateStruct {
+ ReplayStateStruct(OpenGLRenderer& renderer, Rect& dirty, int replayFlags)
+ : mRenderer(renderer), mDirty(dirty), mReplayFlags(replayFlags),
+ mDrawGlStatus(DrawGlInfo::kStatusDone) {}
+ OpenGLRenderer& mRenderer;
+ Rect& mDirty;
+ const int mReplayFlags;
+ status_t mDrawGlStatus;
+};
+
/**
* Refcounted structure that holds data used in display list stream
*/
-class DisplayListData: public LightRefBase<DisplayListData> {
+class DisplayListData : public LightRefBase<DisplayListData> {
public:
LinearAllocator allocator;
Vector<DisplayListOp*> displayListOps;
@@ -79,9 +104,6 @@ public:
kReplayFlag_ClipChildren = 0x1
};
- status_t setViewProperties(OpenGLRenderer& renderer, Rect& dirty,
- int32_t flags, uint32_t level, DeferredDisplayList* deferredList);
- void outputViewProperties(uint32_t level);
ANDROID_API size_t getSize();
ANDROID_API static void destroyDisplayListDeferred(DisplayList* displayList);
@@ -89,8 +111,9 @@ public:
void initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing = false);
- status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, uint32_t level = 0,
- DeferredDisplayList* deferredList = NULL);
+
+ void defer(DeferStateStruct& deferStruct, const int level);
+ void replay(ReplayStateStruct& replayStruct, const int level);
void output(uint32_t level = 0);
@@ -426,6 +449,14 @@ public:
}
private:
+ void outputViewProperties(const int level);
+
+ template <class T>
+ inline void setViewProperties(OpenGLRenderer& renderer, T& handler, const int level);
+
+ template <class T>
+ inline void iterate(OpenGLRenderer& renderer, T& handler, const int level);
+
void init();
void clearResources();
@@ -490,6 +521,22 @@ private:
SkMatrix* mStaticMatrix;
SkMatrix* mAnimationMatrix;
bool mCaching;
+
+ /**
+ * State operations - needed to defer displayList property operations (for example, when setting
+ * an alpha causes a SaveLayerAlpha to occur). These operations point into mDisplayListData's
+ * allocation, or null if uninitialized.
+ *
+ * These are initialized (via friend constructors) when a displayList is issued in either replay
+ * or deferred mode. If replaying, the ops are not used until the next frame. If deferring, the
+ * ops may be stored in the DeferredDisplayList to be played back a second time.
+ *
+ * They should be used at most once per frame (one call to iterate)
+ */
+ ClipRectOp* mClipRectOp;
+ SaveLayerOp* mSaveLayerOp;
+ SaveOp* mSaveOp;
+ RestoreToCountOp* mRestoreToCountOp;
}; // class DisplayList
}; // namespace uirenderer
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 4e6b552..9988bb8 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -78,17 +78,26 @@ public:
kOpLogFlag_JSON = 0x2 // TODO: add?
};
- // If a DeferredDisplayList is supplied, DrawOps will be stored until the list is flushed
- // NOTE: complex clips and layers prevent deferral
- virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, int saveCount,
- uint32_t level, bool caching, int multipliedAlpha,
- DeferredDisplayList* deferredList) = 0;
+ virtual void defer(DeferStateStruct& deferStruct, int saveCount,
+ int level, int multipliedAlpha) = 0;
- virtual void output(int level, uint32_t flags = 0) = 0;
+ virtual void replay(ReplayStateStruct& replayStruct, int saveCount,
+ int level, int multipliedAlpha) = 0;
+
+ virtual void output(int level, uint32_t logFlags = 0) = 0;
// NOTE: it would be nice to declare constants and overriding the implementation in each op to
// point at the constants, but that seems to require a .cpp file
virtual const char* name() = 0;
+
+ /**
+ * Stores the relevant canvas state of the object between deferral and replay (if the canvas
+ * state supports being stored) See OpenGLRenderer::simpleClipAndState()
+ *
+ * TODO: don't reserve space for StateOps that won't be deferred
+ */
+ DeferredDisplayState state;
+
};
class StateOp : public DisplayListOp {
@@ -97,28 +106,22 @@ public:
virtual ~StateOp() {}
+ virtual void defer(DeferStateStruct& deferStruct, int saveCount,
+ int level, int multipliedAlpha) {
+ // default behavior only affects immediate, deferrable state, issue directly to renderer
+ applyState(deferStruct.mRenderer, saveCount);
+ }
+
/**
* State operations are applied directly to the renderer, but can cause the deferred drawing op
* list to flush
*/
- virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, int saveCount,
- uint32_t level, bool caching, int multipliedAlpha, DeferredDisplayList* deferredList) {
- status_t status = DrawGlInfo::kStatusDone;
- if (deferredList && requiresDrawOpFlush(renderer)) {
- // will be setting renderer state that affects ops in deferredList, so flush list first
- status |= deferredList->flush(renderer, dirty, flags, level);
- }
- applyState(renderer, saveCount);
- return status;
+ virtual void replay(ReplayStateStruct& replayStruct, int saveCount,
+ int level, int multipliedAlpha) {
+ applyState(replayStruct.mRenderer, saveCount);
}
virtual void applyState(OpenGLRenderer& renderer, int saveCount) = 0;
-
- /**
- * Returns true if it affects renderer drawing state in such a way to break deferral
- * see OpenGLRenderer::disallowDeferral()
- */
- virtual bool requiresDrawOpFlush(OpenGLRenderer& renderer) { return false; }
};
class DrawOp : public DisplayListOp {
@@ -126,36 +129,35 @@ public:
DrawOp(SkPaint* paint)
: mPaint(paint), mQuickRejected(false) {}
- /** Draw operations are stored in the deferredList with information necessary for playback */
- virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, int saveCount,
- uint32_t level, bool caching, int multipliedAlpha, DeferredDisplayList* deferredList) {
- if (mQuickRejected && CC_LIKELY(flags & DisplayList::kReplayFlag_ClipChildren)) {
- return DrawGlInfo::kStatusDone;
- }
-
- if (!deferredList || renderer.disallowDeferral()) {
- // dispatch draw immediately, since the renderer's state is too complex for deferral
- return applyDraw(renderer, dirty, level, caching, multipliedAlpha);
+ virtual void defer(DeferStateStruct& deferStruct, int saveCount,
+ int level, int multipliedAlpha) {
+ if (mQuickRejected &&
+ CC_LIKELY(deferStruct.mReplayFlags & DisplayList::kReplayFlag_ClipChildren)) {
+ return;
}
- if (!caching) multipliedAlpha = -1;
state.mMultipliedAlpha = multipliedAlpha;
if (!getLocalBounds(state.mBounds)) {
// empty bounds signify bounds can't be calculated
state.mBounds.setEmpty();
}
- if (!renderer.storeDisplayState(state)) {
- // op wasn't quick-rejected, so defer
- deferredList->add(this, renderer.getCaches().drawReorderDisabled);
- onDrawOpDeferred(renderer);
+ deferStruct.mDeferredList.addDrawOp(deferStruct.mRenderer, this);
+ }
+
+ virtual void replay(ReplayStateStruct& replayStruct, int saveCount,
+ int level, int multipliedAlpha) {
+ if (mQuickRejected &&
+ CC_LIKELY(replayStruct.mReplayFlags & DisplayList::kReplayFlag_ClipChildren)) {
+ return;
}
- return DrawGlInfo::kStatusDone;
+ replayStruct.mDrawGlStatus |= applyDraw(replayStruct.mRenderer, replayStruct.mDirty,
+ level, multipliedAlpha);
}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
- bool caching, int multipliedAlpha) = 0;
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
+ int multipliedAlpha) = 0;
virtual void onDrawOpDeferred(OpenGLRenderer& renderer) {
}
@@ -174,11 +176,6 @@ public:
float strokeWidthOutset() { return mPaint->getStrokeWidth() * 0.5f; }
- /**
- * Stores the relevant canvas state of the object between deferral and replay (if the canvas
- * state supports being stored) See OpenGLRenderer::simpleClipAndState()
- */
- DeferredDisplayState state;
protected:
SkPaint* getPaint(OpenGLRenderer& renderer, bool alwaysCopy = false) {
return renderer.filterPaint(mPaint, alwaysCopy);
@@ -225,88 +222,113 @@ protected:
///////////////////////////////////////////////////////////////////////////////
class SaveOp : public StateOp {
+ friend class DisplayList; // give DisplayList private constructor/reinit access
public:
SaveOp(int flags)
: mFlags(flags) {}
+ virtual void defer(DeferStateStruct& deferStruct, int saveCount,
+ int level, int multipliedAlpha) {
+ int newSaveCount = deferStruct.mRenderer.save(mFlags);
+ deferStruct.mDeferredList.addSave(deferStruct.mRenderer, this, newSaveCount);
+ }
+
virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
renderer.save(mFlags);
}
- virtual void output(int level, uint32_t flags = 0) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("Save flags %x", mFlags);
}
virtual const char* name() { return "Save"; }
+ int getFlags() const { return mFlags; }
private:
+ SaveOp() {}
+ DisplayListOp* reinit(int flags) {
+ mFlags = flags;
+ return this;
+ }
+
int mFlags;
};
class RestoreToCountOp : public StateOp {
+ friend class DisplayList; // give DisplayList private constructor/reinit access
public:
RestoreToCountOp(int count)
: mCount(count) {}
+ virtual void defer(DeferStateStruct& deferStruct, int saveCount,
+ int level, int multipliedAlpha) {
+ deferStruct.mDeferredList.addRestoreToCount(deferStruct.mRenderer, saveCount + mCount);
+ deferStruct.mRenderer.restoreToCount(saveCount + mCount);
+ }
+
virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
renderer.restoreToCount(saveCount + mCount);
-
}
- virtual void output(int level, uint32_t flags = 0) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("Restore to count %d", mCount);
}
virtual const char* name() { return "RestoreToCount"; }
- // Note: don't have to return true for requiresDrawOpFlush - even though restore can create a
- // complex clip, the clip and matrix are overridden by DeferredDisplayList::flush()
private:
+ RestoreToCountOp() {}
+ DisplayListOp* reinit(int count) {
+ mCount = count;
+ return this;
+ }
+
int mCount;
};
class SaveLayerOp : public StateOp {
+ friend class DisplayList; // give DisplayList private constructor/reinit access
public:
- SaveLayerOp(float left, float top, float right, float bottom, SkPaint* paint, int flags)
- : mArea(left, top, right, bottom), mPaint(paint), mFlags(flags) {}
-
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
- SkPaint* paint = renderer.filterPaint(mPaint);
- renderer.saveLayer(mArea.left, mArea.top, mArea.right, mArea.bottom, paint, mFlags);
- }
+ SaveLayerOp(float left, float top, float right, float bottom,
+ int alpha, SkXfermode::Mode mode, int flags)
+ : mArea(left, top, right, bottom), mAlpha(alpha), mMode(mode), mFlags(flags) {}
- virtual void output(int level, uint32_t flags = 0) {
- OP_LOG("SaveLayer of area " RECT_STRING, RECT_ARGS(mArea));
+ virtual void defer(DeferStateStruct& deferStruct, int saveCount,
+ int level, int multipliedAlpha) {
+ // NOTE: don't bother with actual saveLayer, instead issuing it at flush time
+ int newSaveCount = deferStruct.mRenderer.save(mFlags);
+ deferStruct.mDeferredList.addSaveLayer(deferStruct.mRenderer, this, newSaveCount);
}
- virtual const char* name() { return "SaveLayer"; }
- virtual bool requiresDrawOpFlush(OpenGLRenderer& renderer) { return true; }
-
-private:
- Rect mArea;
- SkPaint* mPaint;
- int mFlags;
-};
-
-class SaveLayerAlphaOp : public StateOp {
-public:
- SaveLayerAlphaOp(float left, float top, float right, float bottom, int alpha, int flags)
- : mArea(left, top, right, bottom), mAlpha(alpha), mFlags(flags) {}
-
virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
- renderer.saveLayerAlpha(mArea.left, mArea.top, mArea.right, mArea.bottom, mAlpha, mFlags);
+ renderer.saveLayer(mArea.left, mArea.top, mArea.right, mArea.bottom, mAlpha, mMode, mFlags);
}
- virtual void output(int level, uint32_t flags = 0) {
- OP_LOG("SaveLayerAlpha of area " RECT_STRING, RECT_ARGS(mArea));
+ virtual void output(int level, uint32_t logFlags) {
+ OP_LOG("SaveLayer%s of area " RECT_STRING,
+ (isSaveLayerAlpha() ? "Alpha" : ""),RECT_ARGS(mArea));
}
- virtual const char* name() { return "SaveLayerAlpha"; }
- virtual bool requiresDrawOpFlush(OpenGLRenderer& renderer) { return true; }
+ virtual const char* name() { return isSaveLayerAlpha() ? "SaveLayerAlpha" : "SaveLayer"; }
+
+ int getFlags() { return mFlags; }
private:
+ // Special case, reserved for direct DisplayList usage
+ SaveLayerOp() {}
+ DisplayListOp* reinit(float left, float top, float right, float bottom,
+ int alpha, SkXfermode::Mode mode, int flags) {
+ mArea.set(left, top, right, bottom);
+ mAlpha = alpha;
+ mMode = mode;
+ mFlags = flags;
+ return this;
+ }
+
+ bool isSaveLayerAlpha() { return mAlpha < 255 && mMode == SkXfermode::kSrcOver_Mode; }
Rect mArea;
int mAlpha;
+ SkXfermode::Mode mMode;
int mFlags;
};
@@ -319,7 +341,7 @@ public:
renderer.translate(mDx, mDy);
}
- virtual void output(int level, uint32_t flags = 0) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("Translate by %f %f", mDx, mDy);
}
@@ -339,7 +361,7 @@ public:
renderer.rotate(mDegrees);
}
- virtual void output(int level, uint32_t flags = 0) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("Rotate by %f degrees", mDegrees);
}
@@ -358,7 +380,7 @@ public:
renderer.scale(mSx, mSy);
}
- virtual void output(int level, uint32_t flags = 0) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("Scale by %f %f", mSx, mSy);
}
@@ -378,7 +400,7 @@ public:
renderer.skew(mSx, mSy);
}
- virtual void output(int level, uint32_t flags = 0) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("Skew by %f %f", mSx, mSy);
}
@@ -398,7 +420,7 @@ public:
renderer.setMatrix(mMatrix);
}
- virtual void output(int level, uint32_t flags = 0) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("SetMatrix " MATRIX_STRING, MATRIX_ARGS(mMatrix));
}
@@ -417,7 +439,7 @@ public:
renderer.concatMatrix(mMatrix);
}
- virtual void output(int level, uint32_t flags = 0) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("ConcatMatrix " MATRIX_STRING, MATRIX_ARGS(mMatrix));
}
@@ -427,75 +449,97 @@ private:
SkMatrix* mMatrix;
};
-class ClipRectOp : public StateOp {
+class ClipOp : public StateOp {
+public:
+ ClipOp(SkRegion::Op op) : mOp(op) {}
+
+ virtual void defer(DeferStateStruct& deferStruct, int saveCount,
+ int level, int multipliedAlpha) {
+ // NOTE: must defer op BEFORE applying state, since it may read clip
+ deferStruct.mDeferredList.addClip(deferStruct.mRenderer, this);
+
+ // TODO: Can we avoid applying complex clips at defer time?
+ applyState(deferStruct.mRenderer, saveCount);
+ }
+
+ bool canCauseComplexClip() {
+ return ((mOp != SkRegion::kIntersect_Op) && (mOp != SkRegion::kReplace_Op)) || !isRect();
+ }
+
+protected:
+ ClipOp() {}
+ virtual bool isRect() { return false; }
+
+ SkRegion::Op mOp;
+};
+
+class ClipRectOp : public ClipOp {
+ friend class DisplayList; // give DisplayList private constructor/reinit access
public:
ClipRectOp(float left, float top, float right, float bottom, SkRegion::Op op)
- : mArea(left, top, right, bottom), mOp(op) {}
+ : ClipOp(op), mArea(left, top, right, bottom) {}
virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
renderer.clipRect(mArea.left, mArea.top, mArea.right, mArea.bottom, mOp);
}
- virtual void output(int level, uint32_t flags = 0) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("ClipRect " RECT_STRING, RECT_ARGS(mArea));
}
virtual const char* name() { return "ClipRect"; }
- virtual bool requiresDrawOpFlush(OpenGLRenderer& renderer) {
- // TODO: currently, we flush when we *might* cause a clip region to exist. Ideally, we
- // should only flush when a non-rectangular clip would result
- return !renderer.hasRectToRectTransform() || !hasRectToRectOp();
- }
+protected:
+ virtual bool isRect() { return true; }
private:
- inline bool hasRectToRectOp() {
- return mOp == SkRegion::kIntersect_Op || mOp == SkRegion::kReplace_Op;
+ ClipRectOp() {}
+ DisplayListOp* reinit(float left, float top, float right, float bottom, SkRegion::Op op) {
+ mOp = op;
+ mArea.set(left, top, right, bottom);
+ return this;
}
+
Rect mArea;
- SkRegion::Op mOp;
};
-class ClipPathOp : public StateOp {
+class ClipPathOp : public ClipOp {
public:
ClipPathOp(SkPath* path, SkRegion::Op op)
- : mPath(path), mOp(op) {}
+ : ClipOp(op), mPath(path) {}
virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
renderer.clipPath(mPath, mOp);
}
- virtual void output(int level, uint32_t flags = 0) {
+ virtual void output(int level, uint32_t logFlags) {
SkRect bounds = mPath->getBounds();
OP_LOG("ClipPath bounds " RECT_STRING,
bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
}
virtual const char* name() { return "ClipPath"; }
- virtual bool requiresDrawOpFlush(OpenGLRenderer& renderer) { return true; }
private:
SkPath* mPath;
- SkRegion::Op mOp;
};
-class ClipRegionOp : public StateOp {
+class ClipRegionOp : public ClipOp {
public:
ClipRegionOp(SkRegion* region, SkRegion::Op op)
- : mRegion(region), mOp(op) {}
+ : ClipOp(op), mRegion(region) {}
virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
renderer.clipRegion(mRegion, mOp);
}
- virtual void output(int level, uint32_t flags = 0) {
+ virtual void output(int level, uint32_t logFlags) {
SkIRect bounds = mRegion->getBounds();
OP_LOG("ClipRegion bounds %d %d %d %d",
bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
}
virtual const char* name() { return "ClipRegion"; }
- virtual bool requiresDrawOpFlush(OpenGLRenderer& renderer) { return true; }
private:
SkRegion* mRegion;
@@ -508,7 +552,7 @@ public:
renderer.resetShader();
}
- virtual void output(int level, uint32_t flags = 0) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOGS("ResetShader");
}
@@ -523,7 +567,7 @@ public:
renderer.setupShader(mShader);
}
- virtual void output(int level, uint32_t flags = 0) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("SetupShader, shader %p", mShader);
}
@@ -539,7 +583,7 @@ public:
renderer.resetColorFilter();
}
- virtual void output(int level, uint32_t flags = 0) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOGS("ResetColorFilter");
}
@@ -555,7 +599,7 @@ public:
renderer.setupColorFilter(mColorFilter);
}
- virtual void output(int level, uint32_t flags = 0) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("SetupColorFilter, filter %p", mColorFilter);
}
@@ -571,7 +615,7 @@ public:
renderer.resetShadow();
}
- virtual void output(int level, uint32_t flags = 0) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOGS("ResetShadow");
}
@@ -587,7 +631,7 @@ public:
renderer.setupShadow(mRadius, mDx, mDy, mColor);
}
- virtual void output(int level, uint32_t flags = 0) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("SetupShadow, radius %f, %f, %f, color %#x", mRadius, mDx, mDy, mColor);
}
@@ -606,7 +650,7 @@ public:
renderer.resetPaintFilter();
}
- virtual void output(int level, uint32_t flags = 0) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOGS("ResetPaintFilter");
}
@@ -622,7 +666,7 @@ public:
renderer.setupPaintFilter(mClearBits, mSetBits);
}
- virtual void output(int level, uint32_t flags = 0) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("SetupPaintFilter, clear %#x, set %#x", mClearBits, mSetBits);
}
@@ -645,9 +689,9 @@ public:
paint),
mBitmap(bitmap) {}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
- bool caching, int multipliedAlpha) {
- bool makeCopy = caching && multipliedAlpha < 255;
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
+ int multipliedAlpha) {
+ bool makeCopy = multipliedAlpha >= 0 && multipliedAlpha < 255;
SkPaint* paint = getPaint(renderer, makeCopy);
if (makeCopy) {
// The paint is safe to modify since we're working on a copy
@@ -657,7 +701,7 @@ public:
return ret;
}
- virtual void output(int level, uint32_t flags) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("Draw bitmap %p at %f %f", mBitmap, mLocalBounds.left, mLocalBounds.top);
}
@@ -679,12 +723,12 @@ public:
transform.mapRect(mLocalBounds);
}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
- bool caching, int multipliedAlpha) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
+ int multipliedAlpha) {
return renderer.drawBitmap(mBitmap, mMatrix, getPaint(renderer));
}
- virtual void output(int level, uint32_t flags) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("Draw bitmap %p matrix " MATRIX_STRING, mBitmap, MATRIX_ARGS(mMatrix));
}
@@ -705,14 +749,14 @@ public:
: DrawBoundedOp(dstLeft, dstTop, dstRight, dstBottom, paint),
mBitmap(bitmap), mSrc(srcLeft, srcTop, srcRight, srcBottom) {}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
- bool caching, int multipliedAlpha) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
+ int multipliedAlpha) {
return renderer.drawBitmap(mBitmap, mSrc.left, mSrc.top, mSrc.right, mSrc.bottom,
mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
getPaint(renderer));
}
- virtual void output(int level, uint32_t flags) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("Draw bitmap %p src="RECT_STRING", dst="RECT_STRING,
mBitmap, RECT_ARGS(mSrc), RECT_ARGS(mLocalBounds));
}
@@ -732,13 +776,13 @@ public:
DrawBitmapDataOp(SkBitmap* bitmap, float left, float top, SkPaint* paint)
: DrawBitmapOp(bitmap, left, top, paint) {}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
- bool caching, int multipliedAlpha) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
+ int multipliedAlpha) {
return renderer.drawBitmapData(mBitmap, mLocalBounds.left,
mLocalBounds.top, getPaint(renderer));
}
- virtual void output(int level, uint32_t flags) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("Draw bitmap %p", mBitmap);
}
@@ -756,13 +800,13 @@ public:
mBitmap(bitmap), mMeshWidth(meshWidth), mMeshHeight(meshHeight),
mVertices(vertices), mColors(colors) {}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
- bool caching, int multipliedAlpha) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
+ int multipliedAlpha) {
return renderer.drawBitmapMesh(mBitmap, mMeshWidth, mMeshHeight,
mVertices, mColors, getPaint(renderer));
}
- virtual void output(int level, uint32_t flags) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("Draw bitmap %p mesh %d x %d", mBitmap, mMeshWidth, mMeshHeight);
}
@@ -790,8 +834,8 @@ public:
mColors(colors), mxDivsCount(width), myDivsCount(height),
mNumColors(numColors), mAlpha(alpha), mMode(mode) {};
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
- bool caching, int multipliedAlpha) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
+ int multipliedAlpha) {
// NOTE: not calling the virtual method, which takes a paint
return renderer.drawPatch(mBitmap, mxDivs, myDivs, mColors,
mxDivsCount, myDivsCount, mNumColors,
@@ -799,7 +843,7 @@ public:
mLocalBounds.right, mLocalBounds.bottom, mAlpha, mMode);
}
- virtual void output(int level, uint32_t flags) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("Draw patch "RECT_STRING, RECT_ARGS(mLocalBounds));
}
@@ -825,12 +869,12 @@ public:
DrawColorOp(int color, SkXfermode::Mode mode)
: DrawOp(0), mColor(color), mMode(mode) {};
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
- bool caching, int multipliedAlpha) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
+ int multipliedAlpha) {
return renderer.drawColor(mColor, mMode);
}
- virtual void output(int level, uint32_t flags) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("Draw color %#x, mode %d", mColor, mMode);
}
@@ -869,13 +913,13 @@ public:
DrawRectOp(float left, float top, float right, float bottom, SkPaint* paint)
: DrawStrokableOp(left, top, right, bottom, paint) {}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
- bool caching, int multipliedAlpha) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
+ int multipliedAlpha) {
return renderer.drawRect(mLocalBounds.left, mLocalBounds.top,
mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
}
- virtual void output(int level, uint32_t flags) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("Draw Rect "RECT_STRING, RECT_ARGS(mLocalBounds));
}
@@ -888,12 +932,12 @@ public:
: DrawBoundedOp(rects, count, paint),
mRects(rects), mCount(count) {}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
- bool caching, int multipliedAlpha) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
+ int multipliedAlpha) {
return renderer.drawRects(mRects, mCount, getPaint(renderer));
}
- virtual void output(int level, uint32_t flags) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("Draw Rects count %d", mCount);
}
@@ -914,13 +958,13 @@ public:
float rx, float ry, SkPaint* paint)
: DrawStrokableOp(left, top, right, bottom, paint), mRx(rx), mRy(ry) {}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
- bool caching, int multipliedAlpha) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
+ int multipliedAlpha) {
return renderer.drawRoundRect(mLocalBounds.left, mLocalBounds.top,
mLocalBounds.right, mLocalBounds.bottom, mRx, mRy, getPaint(renderer));
}
- virtual void output(int level, uint32_t flags) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("Draw RoundRect "RECT_STRING", rx %f, ry %f", RECT_ARGS(mLocalBounds), mRx, mRy);
}
@@ -937,12 +981,12 @@ public:
: DrawStrokableOp(x - radius, y - radius, x + radius, y + radius, paint),
mX(x), mY(y), mRadius(radius) {}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
- bool caching, int multipliedAlpha) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
+ int multipliedAlpha) {
return renderer.drawCircle(mX, mY, mRadius, getPaint(renderer));
}
- virtual void output(int level, uint32_t flags) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("Draw Circle x %f, y %f, r %f", mX, mY, mRadius);
}
@@ -959,13 +1003,13 @@ public:
DrawOvalOp(float left, float top, float right, float bottom, SkPaint* paint)
: DrawStrokableOp(left, top, right, bottom, paint) {}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
- bool caching, int multipliedAlpha) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
+ int multipliedAlpha) {
return renderer.drawOval(mLocalBounds.left, mLocalBounds.top,
mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
}
- virtual void output(int level, uint32_t flags) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("Draw Oval "RECT_STRING, RECT_ARGS(mLocalBounds));
}
@@ -979,14 +1023,14 @@ public:
: DrawStrokableOp(left, top, right, bottom, paint),
mStartAngle(startAngle), mSweepAngle(sweepAngle), mUseCenter(useCenter) {}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
- bool caching, int multipliedAlpha) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
+ int multipliedAlpha) {
return renderer.drawArc(mLocalBounds.left, mLocalBounds.top,
mLocalBounds.right, mLocalBounds.bottom,
mStartAngle, mSweepAngle, mUseCenter, getPaint(renderer));
}
- virtual void output(int level, uint32_t flags) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("Draw Arc "RECT_STRING", start %f, sweep %f, useCenter %d",
RECT_ARGS(mLocalBounds), mStartAngle, mSweepAngle, mUseCenter);
}
@@ -1011,8 +1055,8 @@ public:
mLocalBounds.set(left, top, left + width, top + height);
}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
- bool caching, int multipliedAlpha) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
+ int multipliedAlpha) {
return renderer.drawPath(mPath, getPaint(renderer));
}
@@ -1021,7 +1065,7 @@ public:
renderer.getCaches().pathCache.precache(mPath, paint);
}
- virtual void output(int level, uint32_t flags) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("Draw Path %p in "RECT_STRING, mPath, RECT_ARGS(mLocalBounds));
}
@@ -1042,12 +1086,12 @@ public:
mLocalBounds.outset(strokeWidthOutset());
}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
- bool caching, int multipliedAlpha) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
+ int multipliedAlpha) {
return renderer.drawLines(mPoints, mCount, getPaint(renderer));
}
- virtual void output(int level, uint32_t flags) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("Draw Lines count %d", mCount);
}
@@ -1069,12 +1113,12 @@ public:
DrawPointsOp(float* points, int count, SkPaint* paint)
: DrawLinesOp(points, count, paint) {}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
- bool caching, int multipliedAlpha) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
+ int multipliedAlpha) {
return renderer.drawPoints(mPoints, mCount, getPaint(renderer));
}
- virtual void output(int level, uint32_t flags) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("Draw Points count %d", mCount);
}
@@ -1086,7 +1130,7 @@ public:
DrawSomeTextOp(const char* text, int bytesCount, int count, SkPaint* paint)
: DrawOp(paint), mText(text), mBytesCount(bytesCount), mCount(count) {};
- virtual void output(int level, uint32_t flags) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("Draw some text, %d bytes", mBytesCount);
}
@@ -1116,8 +1160,8 @@ public:
/* TODO: inherit from DrawBounded and init mLocalBounds */
}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
- bool caching, int multipliedAlpha) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
+ int multipliedAlpha) {
return renderer.drawTextOnPath(mText, mBytesCount, mCount, mPath,
mHOffset, mVOffset, getPaint(renderer));
}
@@ -1138,8 +1182,8 @@ public:
/* TODO: inherit from DrawBounded and init mLocalBounds */
}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
- bool caching, int multipliedAlpha) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
+ int multipliedAlpha) {
return renderer.drawPosText(mText, mBytesCount, mCount, mPositions, getPaint(renderer));
}
@@ -1187,13 +1231,13 @@ public:
}
}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
- bool caching, int multipliedAlpha) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
+ int multipliedAlpha) {
return renderer.drawText(mText, mBytesCount, mCount, mX, mY,
mPositions, getPaint(renderer), mLength);
}
- virtual void output(int level, uint32_t flags) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("Draw Text of count %d, bytes %d", mCount, mBytesCount);
}
@@ -1225,15 +1269,15 @@ public:
DrawFunctorOp(Functor* functor)
: DrawOp(0), mFunctor(functor) {}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
- bool caching, int multipliedAlpha) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
+ int multipliedAlpha) {
renderer.startMark("GL functor");
status_t ret = renderer.callDrawGLFunction(mFunctor, dirty);
renderer.endMark();
return ret;
}
- virtual void output(int level, uint32_t flags) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("Draw Functor %p", mFunctor);
}
@@ -1249,21 +1293,26 @@ public:
: DrawBoundedOp(0, 0, displayList->getWidth(), displayList->getHeight(), 0),
mDisplayList(displayList), mFlags(flags) {}
- virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, int saveCount,
- uint32_t level, bool caching, int multipliedAlpha, DeferredDisplayList* deferredList) {
+ virtual void defer(DeferStateStruct& deferStruct, int saveCount,
+ int level, int multipliedAlpha) {
+ if (mDisplayList && mDisplayList->isRenderable()) {
+ mDisplayList->defer(deferStruct, level + 1);
+ }
+ }
+
+ virtual void replay(ReplayStateStruct& replayStruct, int saveCount,
+ int level, int multipliedAlpha) {
if (mDisplayList && mDisplayList->isRenderable()) {
- return mDisplayList->replay(renderer, dirty, mFlags, level + 1, deferredList);
+ mDisplayList->replay(replayStruct, level + 1);
}
- return DrawGlInfo::kStatusDone;
}
- // NOT USED, since replay is overridden
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
- bool caching, int multipliedAlpha) { return DrawGlInfo::kStatusDone; }
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
+ int multipliedAlpha) { return DrawGlInfo::kStatusDone; }
- virtual void output(int level, uint32_t flags) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("Draw Display List %p, flags %#x", mDisplayList, mFlags);
- if (mDisplayList && (flags & kOpLogFlag_Recurse)) {
+ if (mDisplayList && (logFlags & kOpLogFlag_Recurse)) {
mDisplayList->output(level + 1);
}
}
@@ -1280,11 +1329,11 @@ public:
DrawLayerOp(Layer* layer, float x, float y, SkPaint* paint)
: DrawOp(paint), mLayer(layer), mX(x), mY(y) {}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
- bool caching, int multipliedAlpha) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
+ int multipliedAlpha) {
int oldAlpha = -1;
- if (caching && multipliedAlpha < 255) {
+ if (multipliedAlpha >= 0 && multipliedAlpha < 255) {
oldAlpha = mLayer->getAlpha();
mLayer->setAlpha(multipliedAlpha);
}
@@ -1295,7 +1344,7 @@ public:
return ret;
}
- virtual void output(int level, uint32_t flags) {
+ virtual void output(int level, uint32_t logFlags) {
OP_LOG("Draw Layer %p at %f %f", mLayer, mX, mY);
}
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index b011443..11a655e 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -175,14 +175,8 @@ void DisplayListRenderer::restoreToCount(int saveCount) {
}
int DisplayListRenderer::saveLayer(float left, float top, float right, float bottom,
- SkPaint* p, int flags) {
- addStateOp(new (alloc()) SaveLayerOp(left, top, right, bottom, p, flags));
- return OpenGLRenderer::save(flags);
-}
-
-int DisplayListRenderer::saveLayerAlpha(float left, float top, float right, float bottom,
- int alpha, int flags) {
- addStateOp(new (alloc()) SaveLayerAlphaOp(left, top, right, bottom, alpha, flags));
+ int alpha, SkXfermode::Mode mode, int flags) {
+ addStateOp(new (alloc()) SaveLayerOp(left, top, right, bottom, alpha, mode, flags));
return OpenGLRenderer::save(flags);
}
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 38619bf..73b9b66 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -79,9 +79,7 @@ public:
virtual void restoreToCount(int saveCount);
virtual int saveLayer(float left, float top, float right, float bottom,
- SkPaint* p, int flags);
- virtual int saveLayerAlpha(float left, float top, float right, float bottom,
- int alpha, int flags);
+ int alpha, SkXfermode::Mode mode, int flags);
virtual void translate(float dx, float dy);
virtual void rotate(float degrees);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 7fe0a69..428980e 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -635,38 +635,17 @@ bool OpenGLRenderer::restoreSnapshot() {
///////////////////////////////////////////////////////////////////////////////
int OpenGLRenderer::saveLayer(float left, float top, float right, float bottom,
- SkPaint* p, int flags) {
+ int alpha, SkXfermode::Mode mode, int flags) {
const GLuint previousFbo = mSnapshot->fbo;
const int count = saveSnapshot(flags);
if (!mSnapshot->isIgnored()) {
- int alpha = 255;
- SkXfermode::Mode mode;
-
- if (p) {
- alpha = p->getAlpha();
- mode = getXfermode(p->getXfermode());
- } else {
- mode = SkXfermode::kSrcOver_Mode;
- }
-
createLayer(left, top, right, bottom, alpha, mode, flags, previousFbo);
}
return count;
}
-int OpenGLRenderer::saveLayerAlpha(float left, float top, float right, float bottom,
- int alpha, int flags) {
- if (alpha >= 255) {
- return saveLayer(left, top, right, bottom, NULL, flags);
- } else {
- SkPaint paint;
- paint.setAlpha(alpha);
- return saveLayer(left, top, right, bottom, &paint, flags);
- }
-}
-
/**
* Layers are viewed by Skia are slightly different than layers in image editing
* programs (for instance.) When a layer is created, previously created layers
@@ -1225,36 +1204,48 @@ void OpenGLRenderer::clearLayerRegions() {
// State Deferral
///////////////////////////////////////////////////////////////////////////////
-bool OpenGLRenderer::storeDisplayState(DeferredDisplayState& state) {
+bool OpenGLRenderer::storeDisplayState(DeferredDisplayState& state, int stateDeferFlags) {
const Rect& currentClip = *(mSnapshot->clipRect);
const mat4& currentMatrix = *(mSnapshot->transform);
- // state only has bounds initialized in local coordinates
- if (!state.mBounds.isEmpty()) {
- currentMatrix.mapRect(state.mBounds);
- if (!state.mBounds.intersect(currentClip)) {
- // quick rejected
- return true;
+ if (stateDeferFlags & kStateDeferFlag_Draw) {
+ // state has bounds initialized in local coordinates
+ if (!state.mBounds.isEmpty()) {
+ currentMatrix.mapRect(state.mBounds);
+ if (!state.mBounds.intersect(currentClip)) {
+ // quick rejected
+ return true;
+ }
+ } else {
+ state.mBounds.set(currentClip);
}
+ state.mDrawModifiers = mDrawModifiers;
+ state.mAlpha = mSnapshot->alpha;
+ }
+
+ if (stateDeferFlags & kStateDeferFlag_Clip) {
+ state.mClip.set(currentClip);
} else {
- state.mBounds.set(currentClip);
+ state.mClip.setEmpty();
}
- state.mClip.set(currentClip);
+ // transform always deferred
state.mMatrix.load(currentMatrix);
- state.mDrawModifiers = mDrawModifiers;
return false;
}
-void OpenGLRenderer::restoreDisplayState(const DeferredDisplayState& state) {
+void OpenGLRenderer::restoreDisplayState(const DeferredDisplayState& state, int stateDeferFlags) {
currentTransform().load(state.mMatrix);
- // NOTE: a clip RECT will be saved and restored, but DeferredDisplayState doesn't support
- // complex clips. In the future, we should add support for deferral of operations clipped by
- // these. for now, we don't defer with complex clips (see OpenGLRenderer::disallowDeferral())
- mSnapshot->setClip(state.mClip.left, state.mClip.top, state.mClip.right, state.mClip.bottom);
- dirtyClip();
- mDrawModifiers = state.mDrawModifiers;
+ if (stateDeferFlags & kStateDeferFlag_Draw) {
+ mDrawModifiers = state.mDrawModifiers;
+ mSnapshot->alpha = state.mAlpha;
+ }
+
+ if (!state.mClip.isEmpty()) { //stateDeferFlags & kStateDeferFlag_Clip) {
+ mSnapshot->setClip(state.mClip.left, state.mClip.top, state.mClip.right, state.mClip.bottom);
+ dirtyClip();
+ }
}
///////////////////////////////////////////////////////////////////////////////
@@ -1805,16 +1796,21 @@ void OpenGLRenderer::finishDrawTexture() {
// Drawing
///////////////////////////////////////////////////////////////////////////////
-status_t OpenGLRenderer::drawDisplayList(DisplayList* displayList, Rect& dirty, int32_t flags) {
+status_t OpenGLRenderer::drawDisplayList(DisplayList* displayList, Rect& dirty,
+ int32_t replayFlags) {
// All the usual checks and setup operations (quickReject, setupDraw, etc.)
// will be performed by the display list itself
if (displayList && displayList->isRenderable()) {
if (CC_UNLIKELY(mCaches.drawDeferDisabled)) {
- return displayList->replay(*this, dirty, flags, 0);
+ ReplayStateStruct replayStruct(*this, dirty, replayFlags);
+ displayList->replay(replayStruct, 0);
+ return replayStruct.mDrawGlStatus;
}
DeferredDisplayList deferredList;
- return displayList->replay(*this, dirty, flags, 0, &deferredList);
+ DeferStateStruct deferStruct(deferredList, *this, replayFlags);
+ displayList->defer(deferStruct, 0);
+ return deferredList.flush(*this, dirty);
}
return DrawGlInfo::kStatusDone;
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index e961af2..e6c636c 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -65,6 +65,11 @@ struct DrawModifiers {
int mPaintFilterSetBits;
};
+enum StateDeferFlags {
+ kStateDeferFlag_Draw = 0x1,
+ kStateDeferFlag_Clip = 0x2
+};
+
struct DeferredDisplayState {
Rect mBounds; // local bounds, mapped with matrix to be in screen space coordinates, clipped.
int mMultipliedAlpha; // -1 if invalid (because caching not set)
@@ -72,8 +77,8 @@ struct DeferredDisplayState {
// the below are set and used by the OpenGLRenderer at record and deferred playback
Rect mClip;
mat4 mMatrix;
- SkiaShader* mShader;
DrawModifiers mDrawModifiers;
+ float mAlpha;
};
///////////////////////////////////////////////////////////////////////////////
@@ -188,10 +193,18 @@ public:
virtual void restore();
virtual void restoreToCount(int saveCount);
+ ANDROID_API int saveLayer(float left, float top, float right, float bottom,
+ SkPaint* paint, int flags) {
+ SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode;
+ if (paint) mode = getXfermode(paint->getXfermode());
+ return saveLayer(left, top, right, bottom, paint ? paint->getAlpha() : 255, mode, flags);
+ }
+ ANDROID_API int saveLayerAlpha(float left, float top, float right, float bottom,
+ int alpha, int flags) {
+ return saveLayer(left, top, right, bottom, alpha, SkXfermode::kSrcOver_Mode, flags);
+ }
virtual int saveLayer(float left, float top, float right, float bottom,
- SkPaint* p, int flags);
- virtual int saveLayerAlpha(float left, float top, float right, float bottom,
- int alpha, int flags);
+ int alpha, SkXfermode::Mode mode, int flags);
virtual void translate(float dx, float dy);
virtual void rotate(float degrees);
@@ -211,7 +224,7 @@ public:
virtual bool clipRegion(SkRegion* region, SkRegion::Op op);
virtual Rect* getClipRect();
- virtual status_t drawDisplayList(DisplayList* displayList, Rect& dirty, int32_t flags);
+ virtual status_t drawDisplayList(DisplayList* displayList, Rect& dirty, int32_t replayFlags);
virtual void outputDisplayList(DisplayList* displayList);
virtual status_t drawLayer(Layer* layer, float x, float y, SkPaint* paint);
virtual status_t drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
@@ -261,21 +274,10 @@ public:
SkPaint* filterPaint(SkPaint* paint, bool alwaysCopy = false);
- bool disallowDeferral() {
- // returns true if the OpenGLRenderer's state can be completely represented by
- // a DeferredDisplayState object
- return !mSnapshot->clipRegion->isEmpty() ||
- mSnapshot->alpha < 1.0 ||
- (mSnapshot->flags & Snapshot::kFlagIsLayer) ||
- (mSnapshot->flags & Snapshot::kFlagFboTarget); // ensure we're not in a layer
- }
-
- bool storeDisplayState(DeferredDisplayState& state);
- void restoreDisplayState(const DeferredDisplayState& state);
-
- const DrawModifiers& getDrawModifiers() { return mDrawModifiers; }
- void setDrawModifiers(const DrawModifiers& drawModifiers) { mDrawModifiers = drawModifiers; }
+ bool storeDisplayState(DeferredDisplayState& state, int stateDeferFlags);
+ void restoreDisplayState(const DeferredDisplayState& state, int stateDeferFlags);
+ // TODO: what does this mean? no perspective? no rotate?
ANDROID_API bool isCurrentTransformSimple() {
return mSnapshot->transform->isSimple();
}
@@ -284,6 +286,11 @@ public:
return mCaches;
}
+ // simple rect clip
+ bool isCurrentClipSimple() {
+ return mSnapshot->clipRegion->isEmpty();
+ }
+
/**
* Sets the alpha on the current snapshot. This alpha value will be modulated
* with other alpha values when drawing primitives.