blob: a52ea980edd6311c6f2d7cd64df89b418b3f2223 [file] [log] [blame]
Chris Craik0776a602013-02-14 15:36:01 -08001/*
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