DisplayList.cpp revision 259b696b00f07938569fc9a0ea43858cdaab909b
1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <SkCanvas.h> 18 19#include "Debug.h" 20#include "DisplayList.h" 21#include "DisplayListOp.h" 22#include "DisplayListLogBuffer.h" 23 24namespace android { 25namespace uirenderer { 26 27void DisplayList::outputLogBuffer(int fd) { 28 DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance(); 29 if (logBuffer.isEmpty()) { 30 return; 31 } 32 33 FILE *file = fdopen(fd, "a"); 34 35 fprintf(file, "\nRecent DisplayList operations\n"); 36 logBuffer.outputCommands(file); 37 38 String8 cachesLog; 39 Caches::getInstance().dumpMemoryUsage(cachesLog); 40 fprintf(file, "\nCaches:\n%s", cachesLog.string()); 41 fprintf(file, "\n"); 42 43 fflush(file); 44} 45 46DisplayList::DisplayList(const DisplayListRenderer& recorder) : 47 mTransformMatrix(NULL), mTransformCamera(NULL), mTransformMatrix3D(NULL), 48 mStaticMatrix(NULL), mAnimationMatrix(NULL) { 49 50 initFromDisplayListRenderer(recorder); 51} 52 53DisplayList::~DisplayList() { 54 clearResources(); 55} 56 57void DisplayList::destroyDisplayListDeferred(DisplayList* displayList) { 58 if (displayList) { 59 DISPLAY_LIST_LOGD("Deferring display list destruction"); 60 Caches::getInstance().deleteDisplayListDeferred(displayList); 61 } 62} 63 64void DisplayList::clearResources() { 65 mDisplayListData = NULL; 66 67 mClipRectOp = NULL; 68 mSaveLayerOp = NULL; 69 mSaveOp = NULL; 70 mRestoreToCountOp = NULL; 71 72 delete mTransformMatrix; 73 delete mTransformCamera; 74 delete mTransformMatrix3D; 75 delete mStaticMatrix; 76 delete mAnimationMatrix; 77 78 mTransformMatrix = NULL; 79 mTransformCamera = NULL; 80 mTransformMatrix3D = NULL; 81 mStaticMatrix = NULL; 82 mAnimationMatrix = NULL; 83 84 Caches& caches = Caches::getInstance(); 85 caches.unregisterFunctors(mFunctorCount); 86 caches.resourceCache.lock(); 87 88 for (size_t i = 0; i < mBitmapResources.size(); i++) { 89 caches.resourceCache.decrementRefcountLocked(mBitmapResources.itemAt(i)); 90 } 91 92 for (size_t i = 0; i < mOwnedBitmapResources.size(); i++) { 93 SkBitmap* bitmap = mOwnedBitmapResources.itemAt(i); 94 caches.resourceCache.decrementRefcountLocked(bitmap); 95 caches.resourceCache.destructorLocked(bitmap); 96 } 97 98 for (size_t i = 0; i < mFilterResources.size(); i++) { 99 caches.resourceCache.decrementRefcountLocked(mFilterResources.itemAt(i)); 100 } 101 102 for (size_t i = 0; i < mShaders.size(); i++) { 103 caches.resourceCache.decrementRefcountLocked(mShaders.itemAt(i)); 104 caches.resourceCache.destructorLocked(mShaders.itemAt(i)); 105 } 106 107 for (size_t i = 0; i < mSourcePaths.size(); i++) { 108 caches.resourceCache.decrementRefcountLocked(mSourcePaths.itemAt(i)); 109 } 110 111 for (size_t i = 0; i < mLayers.size(); i++) { 112 caches.resourceCache.decrementRefcountLocked(mLayers.itemAt(i)); 113 } 114 115 caches.resourceCache.unlock(); 116 117 for (size_t i = 0; i < mPaints.size(); i++) { 118 delete mPaints.itemAt(i); 119 } 120 121 for (size_t i = 0; i < mRegions.size(); i++) { 122 delete mRegions.itemAt(i); 123 } 124 125 for (size_t i = 0; i < mPaths.size(); i++) { 126 delete mPaths.itemAt(i); 127 } 128 129 for (size_t i = 0; i < mMatrices.size(); i++) { 130 delete mMatrices.itemAt(i); 131 } 132 133 mBitmapResources.clear(); 134 mOwnedBitmapResources.clear(); 135 mFilterResources.clear(); 136 mShaders.clear(); 137 mSourcePaths.clear(); 138 mPaints.clear(); 139 mRegions.clear(); 140 mPaths.clear(); 141 mMatrices.clear(); 142 mLayers.clear(); 143} 144 145void DisplayList::reset() { 146 clearResources(); 147 init(); 148} 149 150void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing) { 151 if (reusing) { 152 // re-using display list - clear out previous allocations 153 clearResources(); 154 } 155 156 init(); 157 158 mDisplayListData = recorder.getDisplayListData(); 159 mSize = mDisplayListData->allocator.usedSize(); 160 161 if (mSize == 0) { 162 return; 163 } 164 165 // allocate reusable ops for state-deferral 166 LinearAllocator& alloc = mDisplayListData->allocator; 167 mClipRectOp = new (alloc) ClipRectOp(); 168 mSaveLayerOp = new (alloc) SaveLayerOp(); 169 mSaveOp = new (alloc) SaveOp(); 170 mRestoreToCountOp = new (alloc) RestoreToCountOp(); 171 172 mFunctorCount = recorder.getFunctorCount(); 173 174 Caches& caches = Caches::getInstance(); 175 caches.registerFunctors(mFunctorCount); 176 caches.resourceCache.lock(); 177 178 const Vector<SkBitmap*>& bitmapResources = recorder.getBitmapResources(); 179 for (size_t i = 0; i < bitmapResources.size(); i++) { 180 SkBitmap* resource = bitmapResources.itemAt(i); 181 mBitmapResources.add(resource); 182 caches.resourceCache.incrementRefcountLocked(resource); 183 } 184 185 const Vector<SkBitmap*> &ownedBitmapResources = recorder.getOwnedBitmapResources(); 186 for (size_t i = 0; i < ownedBitmapResources.size(); i++) { 187 SkBitmap* resource = ownedBitmapResources.itemAt(i); 188 mOwnedBitmapResources.add(resource); 189 caches.resourceCache.incrementRefcountLocked(resource); 190 } 191 192 const Vector<SkiaColorFilter*>& filterResources = recorder.getFilterResources(); 193 for (size_t i = 0; i < filterResources.size(); i++) { 194 SkiaColorFilter* resource = filterResources.itemAt(i); 195 mFilterResources.add(resource); 196 caches.resourceCache.incrementRefcountLocked(resource); 197 } 198 199 const Vector<SkiaShader*>& shaders = recorder.getShaders(); 200 for (size_t i = 0; i < shaders.size(); i++) { 201 SkiaShader* resource = shaders.itemAt(i); 202 mShaders.add(resource); 203 caches.resourceCache.incrementRefcountLocked(resource); 204 } 205 206 const SortedVector<SkPath*>& sourcePaths = recorder.getSourcePaths(); 207 for (size_t i = 0; i < sourcePaths.size(); i++) { 208 mSourcePaths.add(sourcePaths.itemAt(i)); 209 caches.resourceCache.incrementRefcountLocked(sourcePaths.itemAt(i)); 210 } 211 212 const Vector<Layer*>& layers = recorder.getLayers(); 213 for (size_t i = 0; i < layers.size(); i++) { 214 mLayers.add(layers.itemAt(i)); 215 caches.resourceCache.incrementRefcountLocked(layers.itemAt(i)); 216 } 217 218 caches.resourceCache.unlock(); 219 220 mPaints.appendVector(recorder.getPaints()); 221 mRegions.appendVector(recorder.getRegions()); 222 mPaths.appendVector(recorder.getPaths()); 223 mMatrices.appendVector(recorder.getMatrices()); 224} 225 226void DisplayList::init() { 227 mSize = 0; 228 mIsRenderable = true; 229 mFunctorCount = 0; 230 mLeft = 0; 231 mTop = 0; 232 mRight = 0; 233 mBottom = 0; 234 mClipToBounds = true; 235 mAlpha = 1; 236 mHasOverlappingRendering = true; 237 mTranslationX = 0; 238 mTranslationY = 0; 239 mRotation = 0; 240 mRotationX = 0; 241 mRotationY= 0; 242 mScaleX = 1; 243 mScaleY = 1; 244 mPivotX = 0; 245 mPivotY = 0; 246 mCameraDistance = 0; 247 mMatrixDirty = false; 248 mMatrixFlags = 0; 249 mPrevWidth = -1; 250 mPrevHeight = -1; 251 mWidth = 0; 252 mHeight = 0; 253 mPivotExplicitlySet = false; 254 mCaching = false; 255} 256 257size_t DisplayList::getSize() { 258 return mSize; 259} 260 261/** 262 * This function is a simplified version of replay(), where we simply retrieve and log the 263 * display list. This function should remain in sync with the replay() function. 264 */ 265void DisplayList::output(uint32_t level) { 266 ALOGD("%*sStart display list (%p, %s, render=%d)", (level - 1) * 2, "", this, 267 mName.string(), isRenderable()); 268 ALOGD("%*s%s %d", level * 2, "", "Save", 269 SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); 270 271 outputViewProperties(level); 272 int flags = DisplayListOp::kOpLogFlag_Recurse; 273 for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) { 274 mDisplayListData->displayListOps[i]->output(level, flags); 275 } 276 277 ALOGD("%*sDone (%p, %s)", (level - 1) * 2, "", this, mName.string()); 278} 279 280float DisplayList::getPivotX() { 281 updateMatrix(); 282 return mPivotX; 283} 284 285float DisplayList::getPivotY() { 286 updateMatrix(); 287 return mPivotY; 288} 289 290void DisplayList::updateMatrix() { 291 if (mMatrixDirty) { 292 if (!mTransformMatrix) { 293 mTransformMatrix = new SkMatrix(); 294 } 295 if (mMatrixFlags == 0 || mMatrixFlags == TRANSLATION) { 296 mTransformMatrix->reset(); 297 } else { 298 if (!mPivotExplicitlySet) { 299 if (mWidth != mPrevWidth || mHeight != mPrevHeight) { 300 mPrevWidth = mWidth; 301 mPrevHeight = mHeight; 302 mPivotX = mPrevWidth / 2.0f; 303 mPivotY = mPrevHeight / 2.0f; 304 } 305 } 306 if ((mMatrixFlags & ROTATION_3D) == 0) { 307 mTransformMatrix->setTranslate(mTranslationX, mTranslationY); 308 mTransformMatrix->preRotate(mRotation, mPivotX, mPivotY); 309 mTransformMatrix->preScale(mScaleX, mScaleY, mPivotX, mPivotY); 310 } else { 311 if (!mTransformCamera) { 312 mTransformCamera = new Sk3DView(); 313 mTransformMatrix3D = new SkMatrix(); 314 } 315 mTransformMatrix->reset(); 316 mTransformCamera->save(); 317 mTransformMatrix->preScale(mScaleX, mScaleY, mPivotX, mPivotY); 318 mTransformCamera->rotateX(mRotationX); 319 mTransformCamera->rotateY(mRotationY); 320 mTransformCamera->rotateZ(-mRotation); 321 mTransformCamera->getMatrix(mTransformMatrix3D); 322 mTransformMatrix3D->preTranslate(-mPivotX, -mPivotY); 323 mTransformMatrix3D->postTranslate(mPivotX + mTranslationX, 324 mPivotY + mTranslationY); 325 mTransformMatrix->postConcat(*mTransformMatrix3D); 326 mTransformCamera->restore(); 327 } 328 } 329 mMatrixDirty = false; 330 } 331} 332 333void DisplayList::outputViewProperties(const int level) { 334 updateMatrix(); 335 if (mLeft != 0 || mTop != 0) { 336 ALOGD("%*sTranslate (left, top) %d, %d", level * 2, "", mLeft, mTop); 337 } 338 if (mStaticMatrix) { 339 ALOGD("%*sConcatMatrix (static) %p: " MATRIX_STRING, 340 level * 2, "", mStaticMatrix, MATRIX_ARGS(mStaticMatrix)); 341 } 342 if (mAnimationMatrix) { 343 ALOGD("%*sConcatMatrix (animation) %p: " MATRIX_STRING, 344 level * 2, "", mAnimationMatrix, MATRIX_ARGS(mStaticMatrix)); 345 } 346 if (mMatrixFlags != 0) { 347 if (mMatrixFlags == TRANSLATION) { 348 ALOGD("%*sTranslate %f, %f", level * 2, "", mTranslationX, mTranslationY); 349 } else { 350 ALOGD("%*sConcatMatrix %p: " MATRIX_STRING, 351 level * 2, "", mTransformMatrix, MATRIX_ARGS(mTransformMatrix)); 352 } 353 } 354 if (mAlpha < 1) { 355 if (mCaching) { 356 ALOGD("%*sSetOverrideLayerAlpha %.2f", level * 2, "", mAlpha); 357 } else if (!mHasOverlappingRendering) { 358 ALOGD("%*sScaleAlpha %.2f", level * 2, "", mAlpha); 359 } else { 360 int flags = SkCanvas::kHasAlphaLayer_SaveFlag; 361 if (mClipToBounds) { 362 flags |= SkCanvas::kClipToLayer_SaveFlag; 363 } 364 ALOGD("%*sSaveLayerAlpha %.2f, %.2f, %.2f, %.2f, %d, 0x%x", level * 2, "", 365 (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop, 366 (int)(mAlpha * 255), flags); 367 } 368 } 369 if (mClipToBounds && !mCaching) { 370 ALOGD("%*sClipRect %.2f, %.2f, %.2f, %.2f", level * 2, "", 0.0f, 0.0f, 371 (float) mRight - mLeft, (float) mBottom - mTop); 372 } 373} 374 375/* 376 * For property operations, we pass a savecount of 0, since the operations aren't part of the 377 * displaylist, and thus don't have to compensate for the record-time/playback-time discrepancy in 378 * base saveCount (i.e., how RestoreToCount uses saveCount + mCount) 379 */ 380#define PROPERTY_SAVECOUNT 0 381 382template <class T> 383void DisplayList::setViewProperties(OpenGLRenderer& renderer, T& handler, 384 const int level) { 385#if DEBUG_DISPLAY_LIST 386 outputViewProperties(level); 387#endif 388 updateMatrix(); 389 if (mLeft != 0 || mTop != 0) { 390 renderer.translate(mLeft, mTop); 391 } 392 if (mStaticMatrix) { 393 renderer.concatMatrix(mStaticMatrix); 394 } else if (mAnimationMatrix) { 395 renderer.concatMatrix(mAnimationMatrix); 396 } 397 if (mMatrixFlags != 0) { 398 if (mMatrixFlags == TRANSLATION) { 399 renderer.translate(mTranslationX, mTranslationY); 400 } else { 401 renderer.concatMatrix(mTransformMatrix); 402 } 403 } 404 if (mAlpha < 1) { 405 if (mCaching) { 406 renderer.setOverrideLayerAlpha(mAlpha); 407 } else if (!mHasOverlappingRendering) { 408 renderer.scaleAlpha(mAlpha); 409 } else { 410 // TODO: should be able to store the size of a DL at record time and not 411 // have to pass it into this call. In fact, this information might be in the 412 // location/size info that we store with the new native transform data. 413 int saveFlags = SkCanvas::kHasAlphaLayer_SaveFlag; 414 if (mClipToBounds) { 415 saveFlags |= SkCanvas::kClipToLayer_SaveFlag; 416 } 417 handler(mSaveLayerOp->reinit(0, 0, mRight - mLeft, mBottom - mTop, 418 mAlpha * 255, SkXfermode::kSrcOver_Mode, saveFlags), PROPERTY_SAVECOUNT, 419 mClipToBounds); 420 } 421 } 422 if (mClipToBounds && !mCaching) { 423 handler(mClipRectOp->reinit(0, 0, mRight - mLeft, mBottom - mTop, SkRegion::kIntersect_Op), 424 PROPERTY_SAVECOUNT, mClipToBounds); 425 } 426} 427 428class DeferOperationHandler { 429public: 430 DeferOperationHandler(DeferStateStruct& deferStruct, int level) 431 : mDeferStruct(deferStruct), mLevel(level) {} 432 inline void operator()(DisplayListOp* operation, int saveCount, bool clipToBounds) { 433 operation->defer(mDeferStruct, saveCount, mLevel, clipToBounds); 434 } 435private: 436 DeferStateStruct& mDeferStruct; 437 const int mLevel; 438}; 439 440void DisplayList::defer(DeferStateStruct& deferStruct, const int level) { 441 DeferOperationHandler handler(deferStruct, level); 442 iterate<DeferOperationHandler>(deferStruct.mRenderer, handler, level); 443} 444 445class ReplayOperationHandler { 446public: 447 ReplayOperationHandler(ReplayStateStruct& replayStruct, int level) 448 : mReplayStruct(replayStruct), mLevel(level) {} 449 inline void operator()(DisplayListOp* operation, int saveCount, bool clipToBounds) { 450#if DEBUG_DISPLAY_LIST_OPS_AS_EVENTS 451 mReplayStruct.mRenderer.eventMark(operation->name()); 452#endif 453 operation->replay(mReplayStruct, saveCount, mLevel, clipToBounds); 454 } 455private: 456 ReplayStateStruct& mReplayStruct; 457 const int mLevel; 458}; 459 460void DisplayList::replay(ReplayStateStruct& replayStruct, const int level) { 461 ReplayOperationHandler handler(replayStruct, level); 462 463 replayStruct.mRenderer.startMark(mName.string()); 464 iterate<ReplayOperationHandler>(replayStruct.mRenderer, handler, level); 465 replayStruct.mRenderer.endMark(); 466 467 DISPLAY_LIST_LOGD("%*sDone (%p, %s), returning %d", level * 2, "", this, mName.string(), 468 replayStruct.mDrawGlStatus); 469} 470 471/** 472 * This function serves both defer and replay modes, and will organize the displayList's component 473 * operations for a single frame: 474 * 475 * Every 'simple' operation that affects just the matrix and alpha (or other factors of 476 * DeferredDisplayState) may be issued directly to the renderer, but complex operations (with custom 477 * defer logic) and operations in displayListOps are issued through the 'handler' which handles the 478 * defer vs replay logic, per operation 479 */ 480template <class T> 481void DisplayList::iterate(OpenGLRenderer& renderer, T& handler, const int level) { 482 if (mSize == 0 || mAlpha <= 0) { 483 DISPLAY_LIST_LOGD("%*sEmpty display list (%p, %s)", level * 2, "", this, mName.string()); 484 return; 485 } 486 487#if DEBUG_DISPLAY_LIST 488 Rect* clipRect = renderer.getClipRect(); 489 DISPLAY_LIST_LOGD("%*sStart display list (%p, %s), clipRect: %.0f, %.0f, %.0f, %.0f", 490 level * 2, "", this, mName.string(), clipRect->left, clipRect->top, 491 clipRect->right, clipRect->bottom); 492#endif 493 494 int restoreTo = renderer.getSaveCount(); 495 handler(mSaveOp->reinit(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag), 496 PROPERTY_SAVECOUNT, mClipToBounds); 497 498 DISPLAY_LIST_LOGD("%*sSave %d %d", (level + 1) * 2, "", 499 SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag, restoreTo); 500 501 setViewProperties<T>(renderer, handler, level + 1); 502 503 if (mClipToBounds && renderer.quickRejectNoScissor(0, 0, mWidth, mHeight)) { 504 DISPLAY_LIST_LOGD("%*sRestoreToCount %d", level * 2, "", restoreTo); 505 handler(mRestoreToCountOp->reinit(restoreTo), PROPERTY_SAVECOUNT, mClipToBounds); 506 return; 507 } 508 509 DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance(); 510 int saveCount = renderer.getSaveCount() - 1; 511 for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) { 512 DisplayListOp *op = mDisplayListData->displayListOps[i]; 513 514 handler(op, saveCount, mClipToBounds); 515 logBuffer.writeCommand(level, op->name()); 516 } 517 518 DISPLAY_LIST_LOGD("%*sRestoreToCount %d", (level + 1) * 2, "", restoreTo); 519 handler(mRestoreToCountOp->reinit(restoreTo), PROPERTY_SAVECOUNT, mClipToBounds); 520 renderer.restoreToCount(restoreTo); 521 renderer.setOverrideLayerAlpha(1.0f); 522} 523 524}; // namespace uirenderer 525}; // namespace android 526