DisplayListRenderer.cpp revision a4adcf0239039eb8f005be252409901c41b28839
1/*
2 * Copyright (C) 2010 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#define LOG_TAG "OpenGLRenderer"
18
19#include <SkCamera.h>
20
21#include <private/hwui/DrawGlInfo.h>
22
23#include "DisplayList.h"
24#include "DeferredDisplayList.h"
25#include "DisplayListLogBuffer.h"
26#include "DisplayListOp.h"
27#include "DisplayListRenderer.h"
28#include "Caches.h"
29
30namespace android {
31namespace uirenderer {
32
33DisplayListRenderer::DisplayListRenderer():
34        mCaches(Caches::getInstance()), mDisplayListData(new DisplayListData),
35        mTranslateX(0.0f), mTranslateY(0.0f), mHasTranslate(false),
36        mHasDrawOps(false), mFunctorCount(0) {
37}
38
39DisplayListRenderer::~DisplayListRenderer() {
40    reset();
41}
42
43void DisplayListRenderer::reset() {
44    mDisplayListData = new DisplayListData();
45    mCaches.resourceCache.lock();
46
47    for (size_t i = 0; i < mBitmapResources.size(); i++) {
48        mCaches.resourceCache.decrementRefcountLocked(mBitmapResources.itemAt(i));
49    }
50
51    for (size_t i = 0; i < mOwnedBitmapResources.size(); i++) {
52        mCaches.resourceCache.decrementRefcountLocked(mOwnedBitmapResources.itemAt(i));
53    }
54
55    for (size_t i = 0; i < mFilterResources.size(); i++) {
56        mCaches.resourceCache.decrementRefcountLocked(mFilterResources.itemAt(i));
57    }
58
59    for (size_t i = 0; i < mShaders.size(); i++) {
60        mCaches.resourceCache.decrementRefcountLocked(mShaders.itemAt(i));
61    }
62
63    for (size_t i = 0; i < mSourcePaths.size(); i++) {
64        mCaches.resourceCache.decrementRefcountLocked(mSourcePaths.itemAt(i));
65    }
66
67    for (size_t i = 0; i < mLayers.size(); i++) {
68        mCaches.resourceCache.decrementRefcountLocked(mLayers.itemAt(i));
69    }
70
71    mCaches.resourceCache.unlock();
72
73    mBitmapResources.clear();
74    mOwnedBitmapResources.clear();
75    mFilterResources.clear();
76    mSourcePaths.clear();
77
78    mShaders.clear();
79    mShaderMap.clear();
80
81    mPaints.clear();
82    mPaintMap.clear();
83
84    mRegions.clear();
85    mRegionMap.clear();
86
87    mPaths.clear();
88    mPathMap.clear();
89
90    mMatrices.clear();
91
92    mLayers.clear();
93
94    mHasDrawOps = false;
95    mFunctorCount = 0;
96}
97
98///////////////////////////////////////////////////////////////////////////////
99// Operations
100///////////////////////////////////////////////////////////////////////////////
101
102DisplayList* DisplayListRenderer::getDisplayList(DisplayList* displayList) {
103    if (!displayList) {
104        displayList = new DisplayList(*this);
105    } else {
106        displayList->initFromDisplayListRenderer(*this, true);
107    }
108    displayList->setRenderable(mHasDrawOps);
109    return displayList;
110}
111
112bool DisplayListRenderer::isDeferred() {
113    return true;
114}
115
116void DisplayListRenderer::setViewport(int width, int height) {
117    mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1);
118
119    mWidth = width;
120    mHeight = height;
121}
122
123status_t DisplayListRenderer::prepareDirty(float left, float top,
124        float right, float bottom, bool opaque) {
125    mSnapshot = new Snapshot(mFirstSnapshot,
126            SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
127    mSaveCount = 1;
128
129    mSnapshot->setClip(0.0f, 0.0f, mWidth, mHeight);
130    mDirtyClip = opaque;
131
132    mRestoreSaveCount = -1;
133
134    return DrawGlInfo::kStatusDone; // No invalidate needed at record-time
135}
136
137void DisplayListRenderer::finish() {
138    insertRestoreToCount();
139    insertTranslate();
140}
141
142void DisplayListRenderer::interrupt() {
143}
144
145void DisplayListRenderer::resume() {
146}
147
148status_t DisplayListRenderer::callDrawGLFunction(Functor *functor, Rect& dirty) {
149    // Ignore dirty during recording, it matters only when we replay
150    addDrawOp(new (alloc()) DrawFunctorOp(functor));
151    mFunctorCount++;
152    return DrawGlInfo::kStatusDone; // No invalidate needed at record-time
153}
154
155int DisplayListRenderer::save(int flags) {
156    addStateOp(new (alloc()) SaveOp(flags));
157    return OpenGLRenderer::save(flags);
158}
159
160void DisplayListRenderer::restore() {
161    if (mRestoreSaveCount < 0) {
162        restoreToCount(getSaveCount() - 1);
163        return;
164    }
165
166    mRestoreSaveCount--;
167    insertTranslate();
168    OpenGLRenderer::restore();
169}
170
171void DisplayListRenderer::restoreToCount(int saveCount) {
172    mRestoreSaveCount = saveCount;
173    insertTranslate();
174    OpenGLRenderer::restoreToCount(saveCount);
175}
176
177int DisplayListRenderer::saveLayer(float left, float top, float right, float bottom,
178        SkPaint* p, int flags) {
179    addStateOp(new (alloc()) SaveLayerOp(left, top, right, bottom, p, flags));
180    return OpenGLRenderer::save(flags);
181}
182
183int DisplayListRenderer::saveLayerAlpha(float left, float top, float right, float bottom,
184        int alpha, int flags) {
185    addStateOp(new (alloc()) SaveLayerAlphaOp(left, top, right, bottom, alpha, flags));
186    return OpenGLRenderer::save(flags);
187}
188
189void DisplayListRenderer::translate(float dx, float dy) {
190    mHasTranslate = true;
191    mTranslateX += dx;
192    mTranslateY += dy;
193    insertRestoreToCount();
194    OpenGLRenderer::translate(dx, dy);
195}
196
197void DisplayListRenderer::rotate(float degrees) {
198    addStateOp(new (alloc()) RotateOp(degrees));
199    OpenGLRenderer::rotate(degrees);
200}
201
202void DisplayListRenderer::scale(float sx, float sy) {
203    addStateOp(new (alloc()) ScaleOp(sx, sy));
204    OpenGLRenderer::scale(sx, sy);
205}
206
207void DisplayListRenderer::skew(float sx, float sy) {
208    addStateOp(new (alloc()) SkewOp(sx, sy));
209    OpenGLRenderer::skew(sx, sy);
210}
211
212void DisplayListRenderer::setMatrix(SkMatrix* matrix) {
213    matrix = refMatrix(matrix);
214    addStateOp(new (alloc()) SetMatrixOp(matrix));
215    OpenGLRenderer::setMatrix(matrix);
216}
217
218void DisplayListRenderer::concatMatrix(SkMatrix* matrix) {
219    matrix = refMatrix(matrix);
220    addStateOp(new (alloc()) ConcatMatrixOp(matrix));
221    OpenGLRenderer::concatMatrix(matrix);
222}
223
224bool DisplayListRenderer::clipRect(float left, float top, float right, float bottom,
225        SkRegion::Op op) {
226    addStateOp(new (alloc()) ClipRectOp(left, top, right, bottom, op));
227    return OpenGLRenderer::clipRect(left, top, right, bottom, op);
228}
229
230bool DisplayListRenderer::clipPath(SkPath* path, SkRegion::Op op) {
231    path = refPath(path);
232    addStateOp(new (alloc()) ClipPathOp(path, op));
233    return OpenGLRenderer::clipPath(path, op);
234}
235
236bool DisplayListRenderer::clipRegion(SkRegion* region, SkRegion::Op op) {
237    region = refRegion(region);
238    addStateOp(new (alloc()) ClipRegionOp(region, op));
239    return OpenGLRenderer::clipRegion(region, op);
240}
241
242status_t DisplayListRenderer::drawDisplayList(DisplayList* displayList,
243        Rect& dirty, int32_t flags) {
244    // dirty is an out parameter and should not be recorded,
245    // it matters only when replaying the display list
246
247    // TODO: To be safe, the display list should be ref-counted in the
248    //       resources cache, but we rely on the caller (UI toolkit) to
249    //       do the right thing for now
250
251    addDrawOp(new (alloc()) DrawDisplayListOp(displayList, flags));
252    return DrawGlInfo::kStatusDone;
253}
254
255status_t DisplayListRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) {
256    mLayers.add(layer);
257    mCaches.resourceCache.incrementRefcount(layer);
258    paint = refPaint(paint);
259
260    addDrawOp(new (alloc()) DrawLayerOp(layer, x, y, paint));
261    return DrawGlInfo::kStatusDone;
262}
263
264status_t DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint) {
265    bitmap = refBitmap(bitmap);
266    paint = refPaint(paint);
267
268    addDrawOp(new (alloc()) DrawBitmapOp(bitmap, left, top, paint));
269    return DrawGlInfo::kStatusDone;
270}
271
272status_t DisplayListRenderer::drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint) {
273    bitmap = refBitmap(bitmap);
274    matrix = refMatrix(matrix);
275    paint = refPaint(paint);
276
277    addDrawOp(new (alloc()) DrawBitmapMatrixOp(bitmap, matrix, paint));
278    return DrawGlInfo::kStatusDone;
279}
280
281status_t DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
282        float srcRight, float srcBottom, float dstLeft, float dstTop,
283        float dstRight, float dstBottom, SkPaint* paint) {
284    bitmap = refBitmap(bitmap);
285    paint = refPaint(paint);
286
287    addDrawOp(new (alloc()) DrawBitmapRectOp(bitmap,
288                    srcLeft, srcTop, srcRight, srcBottom,
289                    dstLeft, dstTop, dstRight, dstBottom, paint));
290    return DrawGlInfo::kStatusDone;
291}
292
293status_t DisplayListRenderer::drawBitmapData(SkBitmap* bitmap, float left, float top,
294        SkPaint* paint) {
295    bitmap = refBitmapData(bitmap);
296    paint = refPaint(paint);
297
298    addDrawOp(new (alloc()) DrawBitmapDataOp(bitmap, left, top, paint));
299    return DrawGlInfo::kStatusDone;
300}
301
302status_t DisplayListRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHeight,
303        float* vertices, int* colors, SkPaint* paint) {
304    int count = (meshWidth + 1) * (meshHeight + 1) * 2;
305    bitmap = refBitmap(bitmap);
306    vertices = refBuffer<float>(vertices, count);
307    paint = refPaint(paint);
308    colors = refBuffer<int>(colors, count);
309
310    addDrawOp(new (alloc()) DrawBitmapMeshOp(bitmap, meshWidth, meshHeight,
311                    vertices, colors, paint));
312    return DrawGlInfo::kStatusDone;
313}
314
315status_t DisplayListRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs,
316        const int32_t* yDivs, const uint32_t* colors, uint32_t width, uint32_t height,
317        int8_t numColors, float left, float top, float right, float bottom, SkPaint* paint) {
318    int alpha;
319    SkXfermode::Mode mode;
320    OpenGLRenderer::getAlphaAndModeDirect(paint, &alpha, &mode);
321
322    bitmap = refBitmap(bitmap);
323    xDivs = refBuffer<int>(xDivs, width);
324    yDivs = refBuffer<int>(yDivs, height);
325    colors = refBuffer<uint32_t>(colors, numColors);
326
327    addDrawOp(new (alloc()) DrawPatchOp(bitmap, xDivs, yDivs, colors, width, height, numColors,
328                    left, top, right, bottom, alpha, mode));
329    return DrawGlInfo::kStatusDone;
330}
331
332status_t DisplayListRenderer::drawColor(int color, SkXfermode::Mode mode) {
333    addDrawOp(new (alloc()) DrawColorOp(color, mode));
334    return DrawGlInfo::kStatusDone;
335}
336
337status_t DisplayListRenderer::drawRect(float left, float top, float right, float bottom,
338        SkPaint* paint) {
339    paint = refPaint(paint);
340    addDrawOp(new (alloc()) DrawRectOp(left, top, right, bottom, paint));
341    return DrawGlInfo::kStatusDone;
342}
343
344status_t DisplayListRenderer::drawRoundRect(float left, float top, float right, float bottom,
345        float rx, float ry, SkPaint* paint) {
346    paint = refPaint(paint);
347    addDrawOp(new (alloc()) DrawRoundRectOp(left, top, right, bottom, rx, ry, paint));
348    return DrawGlInfo::kStatusDone;
349}
350
351status_t DisplayListRenderer::drawCircle(float x, float y, float radius, SkPaint* paint) {
352    paint = refPaint(paint);
353    addDrawOp(new (alloc()) DrawCircleOp(x, y, radius, paint));
354    return DrawGlInfo::kStatusDone;
355}
356
357status_t DisplayListRenderer::drawOval(float left, float top, float right, float bottom,
358        SkPaint* paint) {
359    paint = refPaint(paint);
360    addDrawOp(new (alloc()) DrawOvalOp(left, top, right, bottom, paint));
361    return DrawGlInfo::kStatusDone;
362}
363
364status_t DisplayListRenderer::drawArc(float left, float top, float right, float bottom,
365        float startAngle, float sweepAngle, bool useCenter, SkPaint* paint) {
366    paint = refPaint(paint);
367    addDrawOp(new (alloc()) DrawArcOp(left, top, right, bottom,
368                    startAngle, sweepAngle, useCenter, paint));
369    return DrawGlInfo::kStatusDone;
370}
371
372status_t DisplayListRenderer::drawPath(SkPath* path, SkPaint* paint) {
373    path = refPath(path);
374    paint = refPaint(paint);
375
376    addDrawOp(new (alloc()) DrawPathOp(path, paint));
377    return DrawGlInfo::kStatusDone;
378}
379
380status_t DisplayListRenderer::drawLines(float* points, int count, SkPaint* paint) {
381    points = refBuffer<float>(points, count);
382    paint = refPaint(paint);
383
384    addDrawOp(new (alloc()) DrawLinesOp(points, count, paint));
385    return DrawGlInfo::kStatusDone;
386}
387
388status_t DisplayListRenderer::drawPoints(float* points, int count, SkPaint* paint) {
389    points = refBuffer<float>(points, count);
390    paint = refPaint(paint);
391
392    addDrawOp(new (alloc()) DrawPointsOp(points, count, paint));
393    return DrawGlInfo::kStatusDone;
394}
395
396status_t DisplayListRenderer::drawTextOnPath(const char* text, int bytesCount, int count,
397        SkPath* path, float hOffset, float vOffset, SkPaint* paint) {
398    if (!text || count <= 0) return DrawGlInfo::kStatusDone;
399
400    text = refText(text, bytesCount);
401    path = refPath(path);
402    paint = refPaint(paint);
403
404    DrawOp* op = new (alloc()) DrawTextOnPathOp(text, bytesCount, count, path,
405            hOffset, vOffset, paint);
406    if (addDrawOp(op)) {
407        // precache if draw operation is visible
408        FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
409        fontRenderer.precache(paint, text, count, mat4::identity());
410    }
411    return DrawGlInfo::kStatusDone;
412}
413
414status_t DisplayListRenderer::drawPosText(const char* text, int bytesCount, int count,
415        const float* positions, SkPaint* paint) {
416    if (!text || count <= 0) return DrawGlInfo::kStatusDone;
417
418    text = refText(text, bytesCount);
419    positions = refBuffer<float>(positions, count * 2);
420    paint = refPaint(paint);
421
422    DrawOp* op = new (alloc()) DrawPosTextOp(text, bytesCount, count, positions, paint);
423    if (addDrawOp(op)) {
424        // precache if draw operation is visible
425        FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
426        fontRenderer.precache(paint, text, count, mat4::identity());
427    }
428    return DrawGlInfo::kStatusDone;
429}
430
431status_t DisplayListRenderer::drawText(const char* text, int bytesCount, int count,
432        float x, float y, const float* positions, SkPaint* paint, float length) {
433    if (!text || count <= 0) return DrawGlInfo::kStatusDone;
434
435    if (length < 0.0f) length = paint->measureText(text, bytesCount);
436
437    text = refText(text, bytesCount);
438    positions = refBuffer<float>(positions, count * 2);
439    paint = refPaint(paint);
440
441    DrawOp* op = new (alloc()) DrawTextOp(text, bytesCount, count, x, y, positions, paint, length);
442    if (addDrawOp(op)) {
443        // precache if draw operation is visible
444        FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
445        const bool pureTranslate = mSnapshot->transform->isPureTranslate();
446        fontRenderer.precache(paint, text, count,
447                pureTranslate ? mat4::identity() : *mSnapshot->transform);
448    }
449    return DrawGlInfo::kStatusDone;
450}
451
452status_t DisplayListRenderer::drawRects(const float* rects, int count, SkPaint* paint) {
453    if (count <= 0) return DrawGlInfo::kStatusDone;
454
455    rects = refBuffer<float>(rects, count);
456    paint = refPaint(paint);
457    addDrawOp(new (alloc()) DrawRectsOp(rects, count, paint));
458    return DrawGlInfo::kStatusDone;
459}
460
461void DisplayListRenderer::resetShader() {
462    addStateOp(new (alloc()) ResetShaderOp());
463}
464
465void DisplayListRenderer::setupShader(SkiaShader* shader) {
466    shader = refShader(shader);
467    addStateOp(new (alloc()) SetupShaderOp(shader));
468}
469
470void DisplayListRenderer::resetColorFilter() {
471    addStateOp(new (alloc()) ResetColorFilterOp());
472}
473
474void DisplayListRenderer::setupColorFilter(SkiaColorFilter* filter) {
475    filter = refColorFilter(filter);
476    addStateOp(new (alloc()) SetupColorFilterOp(filter));
477}
478
479void DisplayListRenderer::resetShadow() {
480    addStateOp(new (alloc()) ResetShadowOp());
481}
482
483void DisplayListRenderer::setupShadow(float radius, float dx, float dy, int color) {
484    addStateOp(new (alloc()) SetupShadowOp(radius, dx, dy, color));
485}
486
487void DisplayListRenderer::resetPaintFilter() {
488    addStateOp(new (alloc()) ResetPaintFilterOp());
489}
490
491void DisplayListRenderer::setupPaintFilter(int clearBits, int setBits) {
492    addStateOp(new (alloc()) SetupPaintFilterOp(clearBits, setBits));
493}
494
495void DisplayListRenderer::insertRestoreToCount() {
496    if (mRestoreSaveCount >= 0) {
497        DisplayListOp* op = new (alloc()) RestoreToCountOp(mRestoreSaveCount);
498        mDisplayListData->displayListOps.add(op);
499        mRestoreSaveCount = -1;
500    }
501}
502
503void DisplayListRenderer::insertTranslate() {
504    if (mHasTranslate) {
505        if (mTranslateX != 0.0f || mTranslateY != 0.0f) {
506            DisplayListOp* op = new (alloc()) TranslateOp(mTranslateX, mTranslateY);
507            mDisplayListData->displayListOps.add(op);
508            mTranslateX = mTranslateY = 0.0f;
509        }
510        mHasTranslate = false;
511    }
512}
513
514void DisplayListRenderer::addStateOp(StateOp* op) {
515    addOpInternal(op);
516}
517
518bool DisplayListRenderer::addDrawOp(DrawOp* op) {
519    bool rejected = false;
520    Rect localBounds;
521    if (op->getLocalBounds(localBounds)) {
522        rejected = quickRejectNoScissor(localBounds.left, localBounds.top,
523                localBounds.right, localBounds.bottom);
524        op->setQuickRejected(rejected);
525    }
526    mHasDrawOps = true;
527    addOpInternal(op);
528    return !rejected;
529}
530
531}; // namespace uirenderer
532}; // namespace android
533