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