DisplayList.cpp revision 8afce816df7e8f668761f7ed443f54238958c49f
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 "Debug.h" 18#include "DisplayList.h" 19#include "DisplayListOp.h" 20#include "DisplayListLogBuffer.h" 21 22namespace android { 23namespace uirenderer { 24 25void DisplayList::outputLogBuffer(int fd) { 26 DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance(); 27 if (logBuffer.isEmpty()) { 28 return; 29 } 30 31 FILE *file = fdopen(fd, "a"); 32 33 fprintf(file, "\nRecent DisplayList operations\n"); 34 logBuffer.outputCommands(file); 35 36 String8 cachesLog; 37 Caches::getInstance().dumpMemoryUsage(cachesLog); 38 fprintf(file, "\nCaches:\n%s", cachesLog.string()); 39 fprintf(file, "\n"); 40 41 fflush(file); 42} 43 44DisplayList::DisplayList(const DisplayListRenderer& recorder) : 45 mTransformMatrix(NULL), mTransformCamera(NULL), mTransformMatrix3D(NULL), 46 mStaticMatrix(NULL), mAnimationMatrix(NULL) { 47 48 initFromDisplayListRenderer(recorder); 49} 50 51DisplayList::~DisplayList() { 52 clearResources(); 53} 54 55void DisplayList::destroyDisplayListDeferred(DisplayList* displayList) { 56 if (displayList) { 57 DISPLAY_LIST_LOGD("Deferring display list destruction"); 58 Caches::getInstance().deleteDisplayListDeferred(displayList); 59 } 60} 61 62void DisplayList::clearResources() { 63 mDisplayListData = NULL; 64 delete mTransformMatrix; 65 delete mTransformCamera; 66 delete mTransformMatrix3D; 67 delete mStaticMatrix; 68 delete mAnimationMatrix; 69 70 mTransformMatrix = NULL; 71 mTransformCamera = NULL; 72 mTransformMatrix3D = NULL; 73 mStaticMatrix = NULL; 74 mAnimationMatrix = NULL; 75 76 Caches& caches = Caches::getInstance(); 77 caches.unregisterFunctors(mFunctorCount); 78 caches.resourceCache.lock(); 79 80 for (size_t i = 0; i < mBitmapResources.size(); i++) { 81 caches.resourceCache.decrementRefcountLocked(mBitmapResources.itemAt(i)); 82 } 83 84 for (size_t i = 0; i < mOwnedBitmapResources.size(); i++) { 85 SkBitmap* bitmap = mOwnedBitmapResources.itemAt(i); 86 caches.resourceCache.decrementRefcountLocked(bitmap); 87 caches.resourceCache.destructorLocked(bitmap); 88 } 89 90 for (size_t i = 0; i < mFilterResources.size(); i++) { 91 caches.resourceCache.decrementRefcountLocked(mFilterResources.itemAt(i)); 92 } 93 94 for (size_t i = 0; i < mShaders.size(); i++) { 95 caches.resourceCache.decrementRefcountLocked(mShaders.itemAt(i)); 96 caches.resourceCache.destructorLocked(mShaders.itemAt(i)); 97 } 98 99 for (size_t i = 0; i < mSourcePaths.size(); i++) { 100 caches.resourceCache.decrementRefcountLocked(mSourcePaths.itemAt(i)); 101 } 102 103 for (size_t i = 0; i < mLayers.size(); i++) { 104 caches.resourceCache.decrementRefcountLocked(mLayers.itemAt(i)); 105 } 106 107 caches.resourceCache.unlock(); 108 109 for (size_t i = 0; i < mPaints.size(); i++) { 110 delete mPaints.itemAt(i); 111 } 112 113 for (size_t i = 0; i < mRegions.size(); i++) { 114 delete mRegions.itemAt(i); 115 } 116 117 for (size_t i = 0; i < mPaths.size(); i++) { 118 SkPath* path = mPaths.itemAt(i); 119 caches.pathCache.remove(path); 120 delete path; 121 } 122 123 for (size_t i = 0; i < mMatrices.size(); i++) { 124 delete mMatrices.itemAt(i); 125 } 126 127 mBitmapResources.clear(); 128 mOwnedBitmapResources.clear(); 129 mFilterResources.clear(); 130 mShaders.clear(); 131 mSourcePaths.clear(); 132 mPaints.clear(); 133 mRegions.clear(); 134 mPaths.clear(); 135 mMatrices.clear(); 136 mLayers.clear(); 137} 138 139void DisplayList::reset() { 140 clearResources(); 141 init(); 142} 143 144void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing) { 145 if (reusing) { 146 // re-using display list - clear out previous allocations 147 clearResources(); 148 } 149 150 init(); 151 152 mDisplayListData = recorder.getDisplayListData(); 153 mSize = mDisplayListData->allocator.usedSize(); 154 155 if (mSize == 0) { 156 return; 157 } 158 159 mFunctorCount = recorder.getFunctorCount(); 160 161 Caches& caches = Caches::getInstance(); 162 caches.registerFunctors(mFunctorCount); 163 caches.resourceCache.lock(); 164 165 const Vector<SkBitmap*>& bitmapResources = recorder.getBitmapResources(); 166 for (size_t i = 0; i < bitmapResources.size(); i++) { 167 SkBitmap* resource = bitmapResources.itemAt(i); 168 mBitmapResources.add(resource); 169 caches.resourceCache.incrementRefcountLocked(resource); 170 } 171 172 const Vector<SkBitmap*> &ownedBitmapResources = recorder.getOwnedBitmapResources(); 173 for (size_t i = 0; i < ownedBitmapResources.size(); i++) { 174 SkBitmap* resource = ownedBitmapResources.itemAt(i); 175 mOwnedBitmapResources.add(resource); 176 caches.resourceCache.incrementRefcountLocked(resource); 177 } 178 179 const Vector<SkiaColorFilter*>& filterResources = recorder.getFilterResources(); 180 for (size_t i = 0; i < filterResources.size(); i++) { 181 SkiaColorFilter* resource = filterResources.itemAt(i); 182 mFilterResources.add(resource); 183 caches.resourceCache.incrementRefcountLocked(resource); 184 } 185 186 const Vector<SkiaShader*>& shaders = recorder.getShaders(); 187 for (size_t i = 0; i < shaders.size(); i++) { 188 SkiaShader* resource = shaders.itemAt(i); 189 mShaders.add(resource); 190 caches.resourceCache.incrementRefcountLocked(resource); 191 } 192 193 const SortedVector<SkPath*>& sourcePaths = recorder.getSourcePaths(); 194 for (size_t i = 0; i < sourcePaths.size(); i++) { 195 mSourcePaths.add(sourcePaths.itemAt(i)); 196 caches.resourceCache.incrementRefcountLocked(sourcePaths.itemAt(i)); 197 } 198 199 const Vector<Layer*>& layers = recorder.getLayers(); 200 for (size_t i = 0; i < layers.size(); i++) { 201 mLayers.add(layers.itemAt(i)); 202 caches.resourceCache.incrementRefcountLocked(layers.itemAt(i)); 203 } 204 205 caches.resourceCache.unlock(); 206 207 mPaints.appendVector(recorder.getPaints()); 208 mRegions.appendVector(recorder.getRegions()); 209 mPaths.appendVector(recorder.getPaths()); 210 mMatrices.appendVector(recorder.getMatrices()); 211} 212 213void DisplayList::init() { 214 mSize = 0; 215 mIsRenderable = true; 216 mFunctorCount = 0; 217 mLeft = 0; 218 mTop = 0; 219 mRight = 0; 220 mBottom = 0; 221 mClipChildren = true; 222 mAlpha = 1; 223 mMultipliedAlpha = 255; 224 mHasOverlappingRendering = true; 225 mTranslationX = 0; 226 mTranslationY = 0; 227 mRotation = 0; 228 mRotationX = 0; 229 mRotationY= 0; 230 mScaleX = 1; 231 mScaleY = 1; 232 mPivotX = 0; 233 mPivotY = 0; 234 mCameraDistance = 0; 235 mMatrixDirty = false; 236 mMatrixFlags = 0; 237 mPrevWidth = -1; 238 mPrevHeight = -1; 239 mWidth = 0; 240 mHeight = 0; 241 mPivotExplicitlySet = false; 242 mCaching = false; 243} 244 245size_t DisplayList::getSize() { 246 return mSize; 247} 248 249/** 250 * This function is a simplified version of replay(), where we simply retrieve and log the 251 * display list. This function should remain in sync with the replay() function. 252 */ 253void DisplayList::output(uint32_t level) { 254 ALOGD("%*sStart display list (%p, %s, render=%d)", (level - 1) * 2, "", this, 255 mName.string(), isRenderable()); 256 ALOGD("%*s%s %d", level * 2, "", "Save", 257 SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); 258 259 outputViewProperties(level); 260 int flags = DisplayListOp::kOpLogFlag_Recurse; 261 for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) { 262 mDisplayListData->displayListOps[i]->output(level, flags); 263 } 264 265 ALOGD("%*sDone (%p, %s)", (level - 1) * 2, "", this, mName.string()); 266} 267 268float DisplayList::getPivotX() { 269 updateMatrix(); 270 return mPivotX; 271} 272 273float DisplayList::getPivotY() { 274 updateMatrix(); 275 return mPivotY; 276} 277 278void DisplayList::updateMatrix() { 279 if (mMatrixDirty) { 280 if (!mTransformMatrix) { 281 mTransformMatrix = new SkMatrix(); 282 } 283 if (mMatrixFlags == 0 || mMatrixFlags == TRANSLATION) { 284 mTransformMatrix->reset(); 285 } else { 286 if (!mPivotExplicitlySet) { 287 if (mWidth != mPrevWidth || mHeight != mPrevHeight) { 288 mPrevWidth = mWidth; 289 mPrevHeight = mHeight; 290 mPivotX = mPrevWidth / 2; 291 mPivotY = mPrevHeight / 2; 292 } 293 } 294 if ((mMatrixFlags & ROTATION_3D) == 0) { 295 mTransformMatrix->setTranslate(mTranslationX, mTranslationY); 296 mTransformMatrix->preRotate(mRotation, mPivotX, mPivotY); 297 mTransformMatrix->preScale(mScaleX, mScaleY, mPivotX, mPivotY); 298 } else { 299 if (!mTransformCamera) { 300 mTransformCamera = new Sk3DView(); 301 mTransformMatrix3D = new SkMatrix(); 302 } 303 mTransformMatrix->reset(); 304 mTransformCamera->save(); 305 mTransformMatrix->preScale(mScaleX, mScaleY, mPivotX, mPivotY); 306 mTransformCamera->rotateX(mRotationX); 307 mTransformCamera->rotateY(mRotationY); 308 mTransformCamera->rotateZ(-mRotation); 309 mTransformCamera->getMatrix(mTransformMatrix3D); 310 mTransformMatrix3D->preTranslate(-mPivotX, -mPivotY); 311 mTransformMatrix3D->postTranslate(mPivotX + mTranslationX, 312 mPivotY + mTranslationY); 313 mTransformMatrix->postConcat(*mTransformMatrix3D); 314 mTransformCamera->restore(); 315 } 316 } 317 mMatrixDirty = false; 318 } 319} 320 321void DisplayList::outputViewProperties(uint32_t level) { 322 updateMatrix(); 323 if (mLeft != 0 || mTop != 0) { 324 ALOGD("%*sTranslate (left, top) %d, %d", level * 2, "", mLeft, mTop); 325 } 326 if (mStaticMatrix) { 327 ALOGD("%*sConcatMatrix (static) %p: " MATRIX_STRING, 328 level * 2, "", mStaticMatrix, MATRIX_ARGS(mStaticMatrix)); 329 } 330 if (mAnimationMatrix) { 331 ALOGD("%*sConcatMatrix (animation) %p: " MATRIX_STRING, 332 level * 2, "", mAnimationMatrix, MATRIX_ARGS(mStaticMatrix)); 333 } 334 if (mMatrixFlags != 0) { 335 if (mMatrixFlags == TRANSLATION) { 336 ALOGD("%*sTranslate %f, %f", level * 2, "", mTranslationX, mTranslationY); 337 } else { 338 ALOGD("%*sConcatMatrix %p: " MATRIX_STRING, 339 level * 2, "", mTransformMatrix, MATRIX_ARGS(mTransformMatrix)); 340 } 341 } 342 if (mAlpha < 1 && !mCaching) { 343 if (!mHasOverlappingRendering) { 344 ALOGD("%*sSetAlpha %.2f", level * 2, "", mAlpha); 345 } else { 346 int flags = SkCanvas::kHasAlphaLayer_SaveFlag; 347 if (mClipChildren) { 348 flags |= SkCanvas::kClipToLayer_SaveFlag; 349 } 350 ALOGD("%*sSaveLayerAlpha %.2f, %.2f, %.2f, %.2f, %d, 0x%x", level * 2, "", 351 (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop, 352 mMultipliedAlpha, flags); 353 } 354 } 355 if (mClipChildren && !mCaching) { 356 ALOGD("%*sClipRect %.2f, %.2f, %.2f, %.2f", level * 2, "", 0.0f, 0.0f, 357 (float) mRight - mLeft, (float) mBottom - mTop); 358 } 359} 360 361status_t DisplayList::setViewProperties(OpenGLRenderer& renderer, Rect& dirty, 362 int32_t flags, uint32_t level, DeferredDisplayList* deferredList) { 363 status_t status = DrawGlInfo::kStatusDone; 364#if DEBUG_DISPLAYLIST 365 outputViewProperties(level); 366#endif 367 updateMatrix(); 368 if (mLeft != 0 || mTop != 0) { 369 renderer.translate(mLeft, mTop); 370 } 371 if (mStaticMatrix) { 372 renderer.concatMatrix(mStaticMatrix); 373 } else if (mAnimationMatrix) { 374 renderer.concatMatrix(mAnimationMatrix); 375 } 376 if (mMatrixFlags != 0) { 377 if (mMatrixFlags == TRANSLATION) { 378 renderer.translate(mTranslationX, mTranslationY); 379 } else { 380 renderer.concatMatrix(mTransformMatrix); 381 } 382 } 383 if (mAlpha < 1 && !mCaching) { 384 if (deferredList) { 385 // flush since we'll either enter a Layer, or set alpha, both not supported in deferral 386 status |= deferredList->flush(renderer, dirty, flags, level); 387 } 388 389 if (!mHasOverlappingRendering) { 390 renderer.setAlpha(mAlpha); 391 } else { 392 // TODO: should be able to store the size of a DL at record time and not 393 // have to pass it into this call. In fact, this information might be in the 394 // location/size info that we store with the new native transform data. 395 int flags = SkCanvas::kHasAlphaLayer_SaveFlag; 396 if (mClipChildren) { 397 flags |= SkCanvas::kClipToLayer_SaveFlag; 398 } 399 renderer.saveLayerAlpha(0, 0, mRight - mLeft, mBottom - mTop, 400 mMultipliedAlpha, flags); 401 } 402 } 403 if (mClipChildren && !mCaching) { 404 if (deferredList && CC_UNLIKELY(!renderer.hasRectToRectTransform())) { 405 // flush, since clip will likely be a region 406 status |= deferredList->flush(renderer, dirty, flags, level); 407 } 408 renderer.clipRect(0, 0, mRight - mLeft, mBottom - mTop, 409 SkRegion::kIntersect_Op); 410 } 411 return status; 412} 413 414status_t DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, uint32_t level, 415 DeferredDisplayList* deferredList) { 416 status_t drawGlStatus = DrawGlInfo::kStatusDone; 417 418#if DEBUG_DISPLAY_LIST 419 Rect* clipRect = renderer.getClipRect(); 420 DISPLAY_LIST_LOGD("%*sStart display list (%p, %s), clipRect: %.0f, %.f, %.0f, %.0f", 421 (level+1)*2, "", this, mName.string(), clipRect->left, clipRect->top, 422 clipRect->right, clipRect->bottom); 423#endif 424 425 renderer.startMark(mName.string()); 426 427 int restoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); 428 DISPLAY_LIST_LOGD("%*sSave %d %d", level * 2, "", 429 SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag, restoreTo); 430 431 drawGlStatus |= setViewProperties(renderer, dirty, flags, level, deferredList); 432 433 if (renderer.quickRejectNoScissor(0, 0, mWidth, mHeight)) { 434 DISPLAY_LIST_LOGD("%*sRestoreToCount %d", level * 2, "", restoreTo); 435 renderer.restoreToCount(restoreTo); 436 renderer.endMark(); 437 return drawGlStatus; 438 } 439 440 DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance(); 441 int saveCount = renderer.getSaveCount() - 1; 442 for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) { 443 DisplayListOp *op = mDisplayListData->displayListOps[i]; 444#if DEBUG_DISPLAY_LIST_OPS_AS_EVENTS 445 renderer.eventMark(strlen(op->name()), op->name()); 446#endif 447 drawGlStatus |= op->replay(renderer, dirty, flags, 448 saveCount, level, mCaching, mMultipliedAlpha, deferredList); 449 logBuffer.writeCommand(level, op->name()); 450 } 451 452 DISPLAY_LIST_LOGD("%*sRestoreToCount %d", level * 2, "", restoreTo); 453 renderer.restoreToCount(restoreTo); 454 renderer.endMark(); 455 456 DISPLAY_LIST_LOGD("%*sDone (%p, %s), returning %d", (level + 1) * 2, "", this, mName.string(), 457 drawGlStatus); 458 459 if (!level && CC_LIKELY(deferredList)) { 460 drawGlStatus |= deferredList->flush(renderer, dirty, flags, level); 461 } 462 463 return drawGlStatus; 464} 465 466}; // namespace uirenderer 467}; // namespace android 468