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