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