diff options
Diffstat (limited to 'libs/hwui/DisplayList.cpp')
-rw-r--r-- | libs/hwui/DisplayList.cpp | 532 |
1 files changed, 38 insertions, 494 deletions
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp index bb6526e5b108..f418c9bf8f9a 100644 --- a/libs/hwui/DisplayList.cpp +++ b/libs/hwui/DisplayList.cpp @@ -14,7 +14,12 @@ * limitations under the License. */ +#define ATRACE_TAG ATRACE_TAG_VIEW + #include <SkCanvas.h> +#include <algorithm> + +#include <utils/Trace.h> #include "Debug.h" #include "DisplayList.h" @@ -24,533 +29,72 @@ namespace android { namespace uirenderer { -void DisplayList::outputLogBuffer(int fd) { - DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance(); - if (logBuffer.isEmpty()) { - return; - } - - FILE *file = fdopen(fd, "a"); - - fprintf(file, "\nRecent DisplayList operations\n"); - logBuffer.outputCommands(file); - - String8 cachesLog; - Caches::getInstance().dumpMemoryUsage(cachesLog); - fprintf(file, "\nCaches:\n%s", cachesLog.string()); - fprintf(file, "\n"); - - fflush(file); -} - -DisplayList::DisplayList(const DisplayListRenderer& recorder) : - mDestroyed(false), mTransformMatrix(NULL), mTransformCamera(NULL), mTransformMatrix3D(NULL), - mStaticMatrix(NULL), mAnimationMatrix(NULL) { - - initFromDisplayListRenderer(recorder); -} - -DisplayList::~DisplayList() { - mDestroyed = true; - clearResources(); -} - -void DisplayList::destroyDisplayListDeferred(DisplayList* displayList) { - if (displayList) { - DISPLAY_LIST_LOGD("Deferring display list destruction"); - Caches::getInstance().deleteDisplayListDeferred(displayList); - } -} - -void DisplayList::clearResources() { - mDisplayListData = NULL; - - mClipRectOp = NULL; - mSaveLayerOp = NULL; - mSaveOp = NULL; - mRestoreToCountOp = NULL; - - delete mTransformMatrix; - delete mTransformCamera; - delete mTransformMatrix3D; - delete mStaticMatrix; - delete mAnimationMatrix; - - mTransformMatrix = NULL; - mTransformCamera = NULL; - mTransformMatrix3D = NULL; - mStaticMatrix = NULL; - mAnimationMatrix = NULL; - - Caches& caches = Caches::getInstance(); - caches.unregisterFunctors(mFunctorCount); - caches.resourceCache.lock(); - - for (size_t i = 0; i < mBitmapResources.size(); i++) { - caches.resourceCache.decrementRefcountLocked(mBitmapResources.itemAt(i)); - } - - for (size_t i = 0; i < mOwnedBitmapResources.size(); i++) { - SkBitmap* bitmap = mOwnedBitmapResources.itemAt(i); - caches.resourceCache.decrementRefcountLocked(bitmap); - caches.resourceCache.destructorLocked(bitmap); - } - - for (size_t i = 0; i < mFilterResources.size(); i++) { - caches.resourceCache.decrementRefcountLocked(mFilterResources.itemAt(i)); - } - - for (size_t i = 0; i < mPatchResources.size(); i++) { - caches.resourceCache.decrementRefcountLocked(mPatchResources.itemAt(i)); - } - - for (size_t i = 0; i < mShaders.size(); i++) { - caches.resourceCache.decrementRefcountLocked(mShaders.itemAt(i)); - caches.resourceCache.destructorLocked(mShaders.itemAt(i)); - } - - for (size_t i = 0; i < mSourcePaths.size(); i++) { - caches.resourceCache.decrementRefcountLocked(mSourcePaths.itemAt(i)); - } - - for (size_t i = 0; i < mLayers.size(); i++) { - caches.resourceCache.decrementRefcountLocked(mLayers.itemAt(i)); - } - - caches.resourceCache.unlock(); - - for (size_t i = 0; i < mPaints.size(); i++) { - delete mPaints.itemAt(i); - } - - for (size_t i = 0; i < mRegions.size(); i++) { - delete mRegions.itemAt(i); - } - - for (size_t i = 0; i < mPaths.size(); i++) { - delete mPaths.itemAt(i); - } - - for (size_t i = 0; i < mMatrices.size(); i++) { - delete mMatrices.itemAt(i); - } - - mBitmapResources.clear(); - mOwnedBitmapResources.clear(); - mFilterResources.clear(); - mPatchResources.clear(); - mShaders.clear(); - mSourcePaths.clear(); - mPaints.clear(); - mRegions.clear(); - mPaths.clear(); - mMatrices.clear(); - mLayers.clear(); +DisplayListData::DisplayListData() + : projectionReceiveIndex(-1) + , functorCount(0) + , hasDrawOps(false) { } -void DisplayList::reset() { - clearResources(); - init(); +DisplayListData::~DisplayListData() { + cleanupResources(); } -void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing) { - if (reusing) { - // re-using display list - clear out previous allocations - clearResources(); - } - - init(); - - mDisplayListData = recorder.getDisplayListData(); - mSize = mDisplayListData->allocator.usedSize(); - - if (mSize == 0) { - 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(); - if (CC_UNLIKELY(!mSaveOp)) { // temporary debug logging - ALOGW("Error: %s's SaveOp not allocated, size %d", getName(), mSize); - CRASH(); - } - - mFunctorCount = recorder.getFunctorCount(); - +void DisplayListData::cleanupResources() { Caches& caches = Caches::getInstance(); - caches.registerFunctors(mFunctorCount); + caches.unregisterFunctors(functorCount); caches.resourceCache.lock(); - const Vector<SkBitmap*>& bitmapResources = recorder.getBitmapResources(); for (size_t i = 0; i < bitmapResources.size(); i++) { - SkBitmap* resource = bitmapResources.itemAt(i); - mBitmapResources.add(resource); - caches.resourceCache.incrementRefcountLocked(resource); + caches.resourceCache.decrementRefcountLocked(bitmapResources.itemAt(i)); } - const Vector<SkBitmap*> &ownedBitmapResources = recorder.getOwnedBitmapResources(); for (size_t i = 0; i < ownedBitmapResources.size(); i++) { - SkBitmap* resource = ownedBitmapResources.itemAt(i); - mOwnedBitmapResources.add(resource); - caches.resourceCache.incrementRefcountLocked(resource); - } - - const Vector<SkiaColorFilter*>& filterResources = recorder.getFilterResources(); - for (size_t i = 0; i < filterResources.size(); i++) { - SkiaColorFilter* resource = filterResources.itemAt(i); - mFilterResources.add(resource); - caches.resourceCache.incrementRefcountLocked(resource); + const SkBitmap* bitmap = ownedBitmapResources.itemAt(i); + caches.resourceCache.decrementRefcountLocked(bitmap); + caches.resourceCache.destructorLocked(bitmap); } - const Vector<Res_png_9patch*>& patchResources = recorder.getPatchResources(); for (size_t i = 0; i < patchResources.size(); i++) { - Res_png_9patch* resource = patchResources.itemAt(i); - mPatchResources.add(resource); - caches.resourceCache.incrementRefcountLocked(resource); - } - - const Vector<SkiaShader*>& shaders = recorder.getShaders(); - for (size_t i = 0; i < shaders.size(); i++) { - SkiaShader* resource = shaders.itemAt(i); - mShaders.add(resource); - caches.resourceCache.incrementRefcountLocked(resource); + caches.resourceCache.decrementRefcountLocked(patchResources.itemAt(i)); } - const SortedVector<SkPath*>& sourcePaths = recorder.getSourcePaths(); for (size_t i = 0; i < sourcePaths.size(); i++) { - mSourcePaths.add(sourcePaths.itemAt(i)); - caches.resourceCache.incrementRefcountLocked(sourcePaths.itemAt(i)); + caches.resourceCache.decrementRefcountLocked(sourcePaths.itemAt(i)); } - const Vector<Layer*>& layers = recorder.getLayers(); for (size_t i = 0; i < layers.size(); i++) { - mLayers.add(layers.itemAt(i)); - caches.resourceCache.incrementRefcountLocked(layers.itemAt(i)); + caches.resourceCache.decrementRefcountLocked(layers.itemAt(i)); } caches.resourceCache.unlock(); - mPaints.appendVector(recorder.getPaints()); - mRegions.appendVector(recorder.getRegions()); - mPaths.appendVector(recorder.getPaths()); - mMatrices.appendVector(recorder.getMatrices()); -} - -void DisplayList::init() { - mSize = 0; - mIsRenderable = true; - mFunctorCount = 0; - mLeft = 0; - mTop = 0; - mRight = 0; - mBottom = 0; - mClipToBounds = true; - mAlpha = 1; - mHasOverlappingRendering = true; - mTranslationX = 0; - mTranslationY = 0; - mRotation = 0; - mRotationX = 0; - mRotationY= 0; - mScaleX = 1; - mScaleY = 1; - mPivotX = 0; - mPivotY = 0; - mCameraDistance = 0; - mMatrixDirty = false; - mMatrixFlags = 0; - mPrevWidth = -1; - mPrevHeight = -1; - mWidth = 0; - mHeight = 0; - mPivotExplicitlySet = false; - mCaching = false; -} - -size_t DisplayList::getSize() { - return mSize; -} - -/** - * This function is a simplified version of replay(), where we simply retrieve and log the - * display list. This function should remain in sync with the replay() function. - */ -void DisplayList::output(uint32_t level) { - ALOGD("%*sStart display list (%p, %s, render=%d)", (level - 1) * 2, "", this, - mName.string(), isRenderable()); - ALOGD("%*s%s %d", level * 2, "", "Save", - SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); - - outputViewProperties(level); - int flags = DisplayListOp::kOpLogFlag_Recurse; - for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) { - mDisplayListData->displayListOps[i]->output(level, flags); + for (size_t i = 0; i < paints.size(); i++) { + delete paints.itemAt(i); } - ALOGD("%*sDone (%p, %s)", (level - 1) * 2, "", this, mName.string()); -} - -float DisplayList::getPivotX() { - updateMatrix(); - return mPivotX; -} - -float DisplayList::getPivotY() { - updateMatrix(); - return mPivotY; -} - -void DisplayList::updateMatrix() { - if (mMatrixDirty) { - if (!mTransformMatrix) { - mTransformMatrix = new SkMatrix(); - } - if (mMatrixFlags == 0 || mMatrixFlags == TRANSLATION) { - mTransformMatrix->reset(); - } else { - if (!mPivotExplicitlySet) { - if (mWidth != mPrevWidth || mHeight != mPrevHeight) { - mPrevWidth = mWidth; - mPrevHeight = mHeight; - mPivotX = mPrevWidth / 2.0f; - mPivotY = mPrevHeight / 2.0f; - } - } - if ((mMatrixFlags & ROTATION_3D) == 0) { - mTransformMatrix->setTranslate(mTranslationX, mTranslationY); - mTransformMatrix->preRotate(mRotation, mPivotX, mPivotY); - mTransformMatrix->preScale(mScaleX, mScaleY, mPivotX, mPivotY); - } else { - if (!mTransformCamera) { - mTransformCamera = new Sk3DView(); - mTransformMatrix3D = new SkMatrix(); - } - mTransformMatrix->reset(); - mTransformCamera->save(); - mTransformMatrix->preScale(mScaleX, mScaleY, mPivotX, mPivotY); - mTransformCamera->rotateX(mRotationX); - mTransformCamera->rotateY(mRotationY); - mTransformCamera->rotateZ(-mRotation); - mTransformCamera->getMatrix(mTransformMatrix3D); - mTransformMatrix3D->preTranslate(-mPivotX, -mPivotY); - mTransformMatrix3D->postTranslate(mPivotX + mTranslationX, - mPivotY + mTranslationY); - mTransformMatrix->postConcat(*mTransformMatrix3D); - mTransformCamera->restore(); - } - } - mMatrixDirty = false; + for (size_t i = 0; i < regions.size(); i++) { + delete regions.itemAt(i); } -} -void DisplayList::outputViewProperties(const int level) { - updateMatrix(); - if (mLeft != 0 || mTop != 0) { - ALOGD("%*sTranslate (left, top) %d, %d", level * 2, "", mLeft, mTop); - } - if (mStaticMatrix) { - ALOGD("%*sConcatMatrix (static) %p: " MATRIX_STRING, - level * 2, "", mStaticMatrix, MATRIX_ARGS(mStaticMatrix)); - } - if (mAnimationMatrix) { - ALOGD("%*sConcatMatrix (animation) %p: " MATRIX_STRING, - level * 2, "", mAnimationMatrix, MATRIX_ARGS(mAnimationMatrix)); - } - if (mMatrixFlags != 0) { - if (mMatrixFlags == TRANSLATION) { - ALOGD("%*sTranslate %f, %f", level * 2, "", mTranslationX, mTranslationY); - } else { - ALOGD("%*sConcatMatrix %p: " MATRIX_STRING, - level * 2, "", mTransformMatrix, MATRIX_ARGS(mTransformMatrix)); - } + for (size_t i = 0; i < paths.size(); i++) { + delete paths.itemAt(i); } - bool clipToBoundsNeeded = mCaching ? false : mClipToBounds; - if (mAlpha < 1) { - if (mCaching) { - ALOGD("%*sSetOverrideLayerAlpha %.2f", level * 2, "", mAlpha); - } else if (!mHasOverlappingRendering) { - ALOGD("%*sScaleAlpha %.2f", level * 2, "", mAlpha); - } else { - int flags = SkCanvas::kHasAlphaLayer_SaveFlag; - if (clipToBoundsNeeded) { - flags |= SkCanvas::kClipToLayer_SaveFlag; - clipToBoundsNeeded = false; // clipping done by save layer - } - ALOGD("%*sSaveLayerAlpha %.2f, %.2f, %.2f, %.2f, %d, 0x%x", level * 2, "", - (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop, - (int)(mAlpha * 255), flags); - } - } - if (clipToBoundsNeeded) { - ALOGD("%*sClipRect %.2f, %.2f, %.2f, %.2f", level * 2, "", 0.0f, 0.0f, - (float) mRight - mLeft, (float) mBottom - mTop); - } + bitmapResources.clear(); + ownedBitmapResources.clear(); + patchResources.clear(); + sourcePaths.clear(); + paints.clear(); + regions.clear(); + paths.clear(); + layers.clear(); } -/* - * 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(); - if (mLeft != 0 || mTop != 0) { - renderer.translate(mLeft, mTop); - } - if (mStaticMatrix) { - renderer.concatMatrix(mStaticMatrix); - } else if (mAnimationMatrix) { - renderer.concatMatrix(mAnimationMatrix); - } - if (mMatrixFlags != 0) { - if (mMatrixFlags == TRANSLATION) { - renderer.translate(mTranslationX, mTranslationY); - } else { - renderer.concatMatrix(mTransformMatrix); - } - } - bool clipToBoundsNeeded = mCaching ? false : mClipToBounds; - if (mAlpha < 1) { - if (mCaching) { - renderer.setOverrideLayerAlpha(mAlpha); - } else if (!mHasOverlappingRendering) { - renderer.scaleAlpha(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 saveFlags = SkCanvas::kHasAlphaLayer_SaveFlag; - if (clipToBoundsNeeded) { - saveFlags |= SkCanvas::kClipToLayer_SaveFlag; - clipToBoundsNeeded = false; // clipping done by saveLayer - } - handler(mSaveLayerOp->reinit(0, 0, mRight - mLeft, mBottom - mTop, - mAlpha * 255, SkXfermode::kSrcOver_Mode, saveFlags), PROPERTY_SAVECOUNT, - mClipToBounds); - } - } - if (clipToBoundsNeeded) { - handler(mClipRectOp->reinit(0, 0, mRight - mLeft, mBottom - mTop, SkRegion::kIntersect_Op), - PROPERTY_SAVECOUNT, mClipToBounds); - } -} - -class DeferOperationHandler { -public: - DeferOperationHandler(DeferStateStruct& deferStruct, int level) - : mDeferStruct(deferStruct), mLevel(level) {} - inline void operator()(DisplayListOp* operation, int saveCount, bool clipToBounds) { - operation->defer(mDeferStruct, saveCount, mLevel, clipToBounds); - } -private: - DeferStateStruct& mDeferStruct; - const int mLevel; -}; - -void DisplayList::defer(DeferStateStruct& deferStruct, const int level) { - DeferOperationHandler handler(deferStruct, level); - iterate<DeferOperationHandler>(deferStruct.mRenderer, handler, level); -} - -class ReplayOperationHandler { -public: - ReplayOperationHandler(ReplayStateStruct& replayStruct, int level) - : mReplayStruct(replayStruct), mLevel(level) {} - inline void operator()(DisplayListOp* operation, int saveCount, bool clipToBounds) { -#if DEBUG_DISPLAY_LIST_OPS_AS_EVENTS - mReplayStruct.mRenderer.eventMark(operation->name()); -#endif - operation->replay(mReplayStruct, saveCount, mLevel, clipToBounds); - } -private: - ReplayStateStruct& mReplayStruct; - const int mLevel; -}; - -void DisplayList::replay(ReplayStateStruct& replayStruct, const int level) { - ReplayOperationHandler handler(replayStruct, 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); -} - -/** - * 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 (CC_UNLIKELY(mDestroyed)) { // temporary debug logging - ALOGW("Error: %s is drawing after destruction, size %d", getName(), mSize); - CRASH(); - } - 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, %.0f, %.0f, %.0f", - level * 2, "", this, mName.string(), clipRect->left, clipRect->top, - clipRect->right, clipRect->bottom); -#endif - - int restoreTo = renderer.getSaveCount(); - handler(mSaveOp->reinit(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag), - PROPERTY_SAVECOUNT, mClipToBounds); - - DISPLAY_LIST_LOGD("%*sSave %d %d", (level + 1) * 2, "", - SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag, restoreTo); - - setViewProperties<T>(renderer, handler, level + 1); - - if (mClipToBounds && renderer.quickRejectNoScissor(0, 0, mWidth, mHeight)) { - DISPLAY_LIST_LOGD("%*sRestoreToCount %d", (level + 1) * 2, "", restoreTo); - handler(mRestoreToCountOp->reinit(restoreTo), PROPERTY_SAVECOUNT, mClipToBounds); - renderer.restoreToCount(restoreTo); - renderer.setOverrideLayerAlpha(1.0f); - 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 - op->output(level + 1); -#endif - - logBuffer.writeCommand(level, op->name()); - handler(op, saveCount, mClipToBounds); - } +void DisplayListData::addChild(DrawDisplayListOp* op) { + LOG_ALWAYS_FATAL_IF(!op->renderNode(), "DrawDisplayListOp with no render node!"); - DISPLAY_LIST_LOGD("%*sRestoreToCount %d", (level + 1) * 2, "", restoreTo); - handler(mRestoreToCountOp->reinit(restoreTo), PROPERTY_SAVECOUNT, mClipToBounds); - renderer.restoreToCount(restoreTo); - renderer.setOverrideLayerAlpha(1.0f); + mChildren.push(op); + mReferenceHolders.push(op->renderNode()); } }; // namespace uirenderer |