diff options
author | Chris Craik <ccraik@google.com> | 2013-03-15 22:54:15 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2013-03-15 22:54:16 +0000 |
commit | f40b8a939fef0a19b40188f007a3364311d6dabf (patch) | |
tree | 027797050b58bcb2d1bac153f980282a38ae49a0 /libs | |
parent | 30527267d12d4338820d4ec2526c6bf81c7f7785 (diff) | |
parent | ff78583d8a73ca35ce65b5d2592570ff6fb9901b (diff) | |
download | frameworks_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.cpp | 9 | ||||
-rw-r--r-- | libs/hwui/DeferredDisplayList.cpp | 280 | ||||
-rw-r--r-- | libs/hwui/DeferredDisplayList.h | 35 | ||||
-rw-r--r-- | libs/hwui/DisplayList.cpp | 151 | ||||
-rw-r--r-- | libs/hwui/DisplayList.h | 59 | ||||
-rw-r--r-- | libs/hwui/DisplayListOp.h | 417 | ||||
-rw-r--r-- | libs/hwui/DisplayListRenderer.cpp | 10 | ||||
-rw-r--r-- | libs/hwui/DisplayListRenderer.h | 4 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 80 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.h | 45 |
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. |