DisplayListRenderer.cpp revision 63696bfc0592a0b8808aa2b1c40bcf33c656c659
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 "DisplayListLogBuffer.h"
24#include "DisplayListOp.h"
25#include "DisplayListRenderer.h"
26#include "Caches.h"
27
28namespace android {
29namespace uirenderer {
30
31///////////////////////////////////////////////////////////////////////////////
32// Display list
33///////////////////////////////////////////////////////////////////////////////
34
35void DisplayList::outputLogBuffer(int fd) {
36    DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
37    if (logBuffer.isEmpty()) {
38        return;
39    }
40
41    FILE *file = fdopen(fd, "a");
42
43    fprintf(file, "\nRecent DisplayList operations\n");
44    logBuffer.outputCommands(file);
45
46    String8 cachesLog;
47    Caches::getInstance().dumpMemoryUsage(cachesLog);
48    fprintf(file, "\nCaches:\n%s", cachesLog.string());
49    fprintf(file, "\n");
50
51    fflush(file);
52}
53
54DisplayList::DisplayList(const DisplayListRenderer& recorder) :
55    mTransformMatrix(NULL), mTransformCamera(NULL), mTransformMatrix3D(NULL),
56    mStaticMatrix(NULL), mAnimationMatrix(NULL) {
57
58    initFromDisplayListRenderer(recorder);
59}
60
61DisplayList::~DisplayList() {
62    clearResources();
63}
64
65void DisplayList::destroyDisplayListDeferred(DisplayList* displayList) {
66    if (displayList) {
67        DISPLAY_LIST_LOGD("Deferring display list destruction");
68        Caches::getInstance().deleteDisplayListDeferred(displayList);
69    }
70}
71
72void DisplayList::clearResources() {
73    mDisplayListData = NULL;
74    delete mTransformMatrix;
75    delete mTransformCamera;
76    delete mTransformMatrix3D;
77    delete mStaticMatrix;
78    delete mAnimationMatrix;
79
80    mTransformMatrix = NULL;
81    mTransformCamera = NULL;
82    mTransformMatrix3D = NULL;
83    mStaticMatrix = NULL;
84    mAnimationMatrix = NULL;
85
86    Caches& caches = Caches::getInstance();
87    caches.unregisterFunctors(mFunctorCount);
88    caches.resourceCache.lock();
89
90    for (size_t i = 0; i < mBitmapResources.size(); i++) {
91        caches.resourceCache.decrementRefcountLocked(mBitmapResources.itemAt(i));
92    }
93
94    for (size_t i = 0; i < mOwnedBitmapResources.size(); i++) {
95        SkBitmap* bitmap = mOwnedBitmapResources.itemAt(i);
96        caches.resourceCache.decrementRefcountLocked(bitmap);
97        caches.resourceCache.destructorLocked(bitmap);
98    }
99
100    for (size_t i = 0; i < mFilterResources.size(); i++) {
101        caches.resourceCache.decrementRefcountLocked(mFilterResources.itemAt(i));
102    }
103
104    for (size_t i = 0; i < mShaders.size(); i++) {
105        caches.resourceCache.decrementRefcountLocked(mShaders.itemAt(i));
106        caches.resourceCache.destructorLocked(mShaders.itemAt(i));
107    }
108
109    for (size_t i = 0; i < mSourcePaths.size(); i++) {
110        caches.resourceCache.decrementRefcountLocked(mSourcePaths.itemAt(i));
111    }
112
113    for (size_t i = 0; i < mLayers.size(); i++) {
114        caches.resourceCache.decrementRefcountLocked(mLayers.itemAt(i));
115    }
116
117    caches.resourceCache.unlock();
118
119    for (size_t i = 0; i < mPaints.size(); i++) {
120        delete mPaints.itemAt(i);
121    }
122
123    for (size_t i = 0; i < mRegions.size(); i++) {
124        delete mRegions.itemAt(i);
125    }
126
127    for (size_t i = 0; i < mPaths.size(); i++) {
128        SkPath* path = mPaths.itemAt(i);
129        caches.pathCache.remove(path);
130        delete path;
131    }
132
133    for (size_t i = 0; i < mMatrices.size(); i++) {
134        delete mMatrices.itemAt(i);
135    }
136
137    mBitmapResources.clear();
138    mOwnedBitmapResources.clear();
139    mFilterResources.clear();
140    mShaders.clear();
141    mSourcePaths.clear();
142    mPaints.clear();
143    mRegions.clear();
144    mPaths.clear();
145    mMatrices.clear();
146    mLayers.clear();
147}
148
149void DisplayList::reset() {
150    clearResources();
151    init();
152}
153
154void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing) {
155    if (reusing) {
156        // re-using display list - clear out previous allocations
157        clearResources();
158    }
159
160    init();
161
162    mDisplayListData = recorder.getDisplayListData();
163    mSize = mDisplayListData->allocator.usedSize();
164
165    if (mSize == 0) {
166        return;
167    }
168
169    mFunctorCount = recorder.getFunctorCount();
170
171    Caches& caches = Caches::getInstance();
172    caches.registerFunctors(mFunctorCount);
173    caches.resourceCache.lock();
174
175    const Vector<SkBitmap*>& bitmapResources = recorder.getBitmapResources();
176    for (size_t i = 0; i < bitmapResources.size(); i++) {
177        SkBitmap* resource = bitmapResources.itemAt(i);
178        mBitmapResources.add(resource);
179        caches.resourceCache.incrementRefcountLocked(resource);
180    }
181
182    const Vector<SkBitmap*> &ownedBitmapResources = recorder.getOwnedBitmapResources();
183    for (size_t i = 0; i < ownedBitmapResources.size(); i++) {
184        SkBitmap* resource = ownedBitmapResources.itemAt(i);
185        mOwnedBitmapResources.add(resource);
186        caches.resourceCache.incrementRefcountLocked(resource);
187    }
188
189    const Vector<SkiaColorFilter*>& filterResources = recorder.getFilterResources();
190    for (size_t i = 0; i < filterResources.size(); i++) {
191        SkiaColorFilter* resource = filterResources.itemAt(i);
192        mFilterResources.add(resource);
193        caches.resourceCache.incrementRefcountLocked(resource);
194    }
195
196    const Vector<SkiaShader*>& shaders = recorder.getShaders();
197    for (size_t i = 0; i < shaders.size(); i++) {
198        SkiaShader* resource = shaders.itemAt(i);
199        mShaders.add(resource);
200        caches.resourceCache.incrementRefcountLocked(resource);
201    }
202
203    const SortedVector<SkPath*>& sourcePaths = recorder.getSourcePaths();
204    for (size_t i = 0; i < sourcePaths.size(); i++) {
205        mSourcePaths.add(sourcePaths.itemAt(i));
206        caches.resourceCache.incrementRefcountLocked(sourcePaths.itemAt(i));
207    }
208
209    const Vector<Layer*>& layers = recorder.getLayers();
210    for (size_t i = 0; i < layers.size(); i++) {
211        mLayers.add(layers.itemAt(i));
212        caches.resourceCache.incrementRefcountLocked(layers.itemAt(i));
213    }
214
215    caches.resourceCache.unlock();
216
217    mPaints.appendVector(recorder.getPaints());
218    mRegions.appendVector(recorder.getRegions());
219    mPaths.appendVector(recorder.getPaths());
220    mMatrices.appendVector(recorder.getMatrices());
221}
222
223void DisplayList::init() {
224    mSize = 0;
225    mIsRenderable = true;
226    mFunctorCount = 0;
227    mLeft = 0;
228    mTop = 0;
229    mRight = 0;
230    mBottom = 0;
231    mClipChildren = true;
232    mAlpha = 1;
233    mMultipliedAlpha = 255;
234    mHasOverlappingRendering = true;
235    mTranslationX = 0;
236    mTranslationY = 0;
237    mRotation = 0;
238    mRotationX = 0;
239    mRotationY= 0;
240    mScaleX = 1;
241    mScaleY = 1;
242    mPivotX = 0;
243    mPivotY = 0;
244    mCameraDistance = 0;
245    mMatrixDirty = false;
246    mMatrixFlags = 0;
247    mPrevWidth = -1;
248    mPrevHeight = -1;
249    mWidth = 0;
250    mHeight = 0;
251    mPivotExplicitlySet = false;
252    mCaching = false;
253}
254
255size_t DisplayList::getSize() {
256    return mSize;
257}
258
259/**
260 * This function is a simplified version of replay(), where we simply retrieve and log the
261 * display list. This function should remain in sync with the replay() function.
262 */
263void DisplayList::output(uint32_t level) {
264    ALOGD("%*sStart display list (%p, %s, render=%d)", level * 2, "", this,
265            mName.string(), isRenderable());
266
267    ALOGD("%*s%s %d", level * 2, "", "Save", SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
268    outputViewProperties(level);
269    int flags = DisplayListOp::kOpLogFlag_Recurse;
270    for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) {
271        mDisplayListData->displayListOps[i]->output(level, flags);
272    }
273    ALOGD("%*sDone (%p, %s)", level * 2, "", this, mName.string());
274}
275
276void DisplayList::updateMatrix() {
277    if (mMatrixDirty) {
278        if (!mTransformMatrix) {
279            mTransformMatrix = new SkMatrix();
280        }
281        if (mMatrixFlags == 0 || mMatrixFlags == TRANSLATION) {
282            mTransformMatrix->reset();
283        } else {
284            if (!mPivotExplicitlySet) {
285                if (mWidth != mPrevWidth || mHeight != mPrevHeight) {
286                    mPrevWidth = mWidth;
287                    mPrevHeight = mHeight;
288                    mPivotX = mPrevWidth / 2;
289                    mPivotY = mPrevHeight / 2;
290                }
291            }
292            if ((mMatrixFlags & ROTATION_3D) == 0) {
293                mTransformMatrix->setTranslate(mTranslationX, mTranslationY);
294                mTransformMatrix->preRotate(mRotation, mPivotX, mPivotY);
295                mTransformMatrix->preScale(mScaleX, mScaleY, mPivotX, mPivotY);
296            } else {
297                if (!mTransformCamera) {
298                    mTransformCamera = new Sk3DView();
299                    mTransformMatrix3D = new SkMatrix();
300                }
301                mTransformMatrix->reset();
302                mTransformCamera->save();
303                mTransformMatrix->preScale(mScaleX, mScaleY, mPivotX, mPivotY);
304                mTransformCamera->rotateX(mRotationX);
305                mTransformCamera->rotateY(mRotationY);
306                mTransformCamera->rotateZ(-mRotation);
307                mTransformCamera->getMatrix(mTransformMatrix3D);
308                mTransformMatrix3D->preTranslate(-mPivotX, -mPivotY);
309                mTransformMatrix3D->postTranslate(mPivotX + mTranslationX,
310                        mPivotY + mTranslationY);
311                mTransformMatrix->postConcat(*mTransformMatrix3D);
312                mTransformCamera->restore();
313            }
314        }
315        mMatrixDirty = false;
316    }
317}
318
319void DisplayList::outputViewProperties(uint32_t level) {
320    updateMatrix();
321    if (mLeft != 0 || mTop != 0) {
322        ALOGD("%*sTranslate (left, top) %d, %d", level * 2, "", mLeft, mTop);
323    }
324    if (mStaticMatrix) {
325        ALOGD("%*sConcatMatrix (static) %p: " MATRIX_STRING,
326                level * 2, "", mStaticMatrix, MATRIX_ARGS(mStaticMatrix));
327    }
328    if (mAnimationMatrix) {
329        ALOGD("%*sConcatMatrix (animation) %p: " MATRIX_STRING,
330                level * 2, "", mAnimationMatrix, MATRIX_ARGS(mStaticMatrix));
331    }
332    if (mMatrixFlags != 0) {
333        if (mMatrixFlags == TRANSLATION) {
334            ALOGD("%*sTranslate %f, %f", level * 2, "", mTranslationX, mTranslationY);
335        } else {
336            ALOGD("%*sConcatMatrix %p: " MATRIX_STRING,
337                    level * 2, "", mTransformMatrix, MATRIX_ARGS(mTransformMatrix));
338        }
339    }
340    if (mAlpha < 1 && !mCaching) {
341        if (!mHasOverlappingRendering) {
342            ALOGD("%*sSetAlpha %.2f", level * 2, "", mAlpha);
343        } else {
344            int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
345            if (mClipChildren) {
346                flags |= SkCanvas::kClipToLayer_SaveFlag;
347            }
348            ALOGD("%*sSaveLayerAlpha %.2f, %.2f, %.2f, %.2f, %d, 0x%x", level * 2, "",
349                    (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop,
350                    mMultipliedAlpha, flags);
351        }
352    }
353    if (mClipChildren && !mCaching) {
354        ALOGD("%*sClipRect %.2f, %.2f, %.2f, %.2f", level * 2, "", 0.0f, 0.0f,
355                (float) mRight - mLeft, (float) mBottom - mTop);
356    }
357}
358
359void DisplayList::setViewProperties(OpenGLRenderer& renderer, uint32_t level) {
360#if DEBUG_DISPLAYLIST
361    outputViewProperties(level);
362#endif
363    updateMatrix();
364    if (mLeft != 0 || mTop != 0) {
365        renderer.translate(mLeft, mTop);
366    }
367    if (mStaticMatrix) {
368        renderer.concatMatrix(mStaticMatrix);
369    } else if (mAnimationMatrix) {
370        renderer.concatMatrix(mAnimationMatrix);
371    }
372    if (mMatrixFlags != 0) {
373        if (mMatrixFlags == TRANSLATION) {
374            renderer.translate(mTranslationX, mTranslationY);
375        } else {
376            renderer.concatMatrix(mTransformMatrix);
377        }
378    }
379    if (mAlpha < 1 && !mCaching) {
380        if (!mHasOverlappingRendering) {
381            renderer.setAlpha(mAlpha);
382        } else {
383            // TODO: should be able to store the size of a DL at record time and not
384            // have to pass it into this call. In fact, this information might be in the
385            // location/size info that we store with the new native transform data.
386            int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
387            if (mClipChildren) {
388                flags |= SkCanvas::kClipToLayer_SaveFlag;
389            }
390            renderer.saveLayerAlpha(0, 0, mRight - mLeft, mBottom - mTop,
391                    mMultipliedAlpha, flags);
392        }
393    }
394    if (mClipChildren && !mCaching) {
395        renderer.clipRect(0, 0, mRight - mLeft, mBottom - mTop,
396                SkRegion::kIntersect_Op);
397    }
398}
399
400status_t DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, uint32_t level) {
401    status_t drawGlStatus = DrawGlInfo::kStatusDone;
402
403#if DEBUG_DISPLAY_LIST
404    Rect* clipRect = renderer.getClipRect();
405    DISPLAY_LIST_LOGD("%*sStart display list (%p, %s), clipRect: %.0f, %.f, %.0f, %.0f",
406            (level+1)*2, "", this, mName.string(), clipRect->left, clipRect->top,
407            clipRect->right, clipRect->bottom);
408#endif
409
410    renderer.startMark(mName.string());
411
412    int restoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
413    DISPLAY_LIST_LOGD("%*sSave %d %d", level * 2, "",
414            SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag, restoreTo);
415    setViewProperties(renderer, level);
416
417    if (renderer.quickRejectNoScissor(0, 0, mWidth, mHeight)) {
418        DISPLAY_LIST_LOGD("%*sRestoreToCount %d", level * 2, "", restoreTo);
419        renderer.restoreToCount(restoreTo);
420        renderer.endMark();
421        return drawGlStatus;
422    }
423
424    DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
425    int saveCount = renderer.getSaveCount() - 1;
426    for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) {
427        DisplayListOp *op = mDisplayListData->displayListOps[i];
428#if DEBUG_DISPLAY_LIST_OPS_AS_EVENTS
429        Caches::getInstance().eventMark(strlen(op->name()), op->name());
430#endif
431
432        drawGlStatus |= op->replay(renderer, dirty, flags,
433                saveCount, level, mCaching, mMultipliedAlpha);
434        logBuffer.writeCommand(level, op->name());
435    }
436
437    DISPLAY_LIST_LOGD("%*sRestoreToCount %d", level * 2, "", restoreTo);
438    renderer.restoreToCount(restoreTo);
439    renderer.endMark();
440
441    DISPLAY_LIST_LOGD("%*sDone (%p, %s), returning %d", (level + 1) * 2, "", this, mName.string(),
442            drawGlStatus);
443    return drawGlStatus;
444}
445
446///////////////////////////////////////////////////////////////////////////////
447// Base structure
448///////////////////////////////////////////////////////////////////////////////
449
450DisplayListRenderer::DisplayListRenderer():
451        mCaches(Caches::getInstance()), mDisplayListData(new DisplayListData),
452        mTranslateX(0.0f), mTranslateY(0.0f), mHasTranslate(false),
453        mHasDrawOps(false), mFunctorCount(0) {
454}
455
456DisplayListRenderer::~DisplayListRenderer() {
457    reset();
458}
459
460void DisplayListRenderer::reset() {
461    mDisplayListData = new DisplayListData();
462    mCaches.resourceCache.lock();
463
464    for (size_t i = 0; i < mBitmapResources.size(); i++) {
465        mCaches.resourceCache.decrementRefcountLocked(mBitmapResources.itemAt(i));
466    }
467
468    for (size_t i = 0; i < mOwnedBitmapResources.size(); i++) {
469        mCaches.resourceCache.decrementRefcountLocked(mOwnedBitmapResources.itemAt(i));
470    }
471
472    for (size_t i = 0; i < mFilterResources.size(); i++) {
473        mCaches.resourceCache.decrementRefcountLocked(mFilterResources.itemAt(i));
474    }
475
476    for (size_t i = 0; i < mShaders.size(); i++) {
477        mCaches.resourceCache.decrementRefcountLocked(mShaders.itemAt(i));
478    }
479
480    for (size_t i = 0; i < mSourcePaths.size(); i++) {
481        mCaches.resourceCache.decrementRefcountLocked(mSourcePaths.itemAt(i));
482    }
483
484    for (size_t i = 0; i < mLayers.size(); i++) {
485        mCaches.resourceCache.decrementRefcountLocked(mLayers.itemAt(i));
486    }
487
488    mCaches.resourceCache.unlock();
489
490    mBitmapResources.clear();
491    mOwnedBitmapResources.clear();
492    mFilterResources.clear();
493    mSourcePaths.clear();
494
495    mShaders.clear();
496    mShaderMap.clear();
497
498    mPaints.clear();
499    mPaintMap.clear();
500
501    mRegions.clear();
502    mRegionMap.clear();
503
504    mPaths.clear();
505    mPathMap.clear();
506
507    mMatrices.clear();
508
509    mLayers.clear();
510
511    mHasDrawOps = false;
512    mFunctorCount = 0;
513}
514
515///////////////////////////////////////////////////////////////////////////////
516// Operations
517///////////////////////////////////////////////////////////////////////////////
518
519DisplayList* DisplayListRenderer::getDisplayList(DisplayList* displayList) {
520    if (!displayList) {
521        displayList = new DisplayList(*this);
522    } else {
523        displayList->initFromDisplayListRenderer(*this, true);
524    }
525    displayList->setRenderable(mHasDrawOps);
526    return displayList;
527}
528
529bool DisplayListRenderer::isDeferred() {
530    return true;
531}
532
533void DisplayListRenderer::setViewport(int width, int height) {
534    mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1);
535
536    mWidth = width;
537    mHeight = height;
538}
539
540status_t DisplayListRenderer::prepareDirty(float left, float top,
541        float right, float bottom, bool opaque) {
542    mSnapshot = new Snapshot(mFirstSnapshot,
543            SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
544    mSaveCount = 1;
545
546    mSnapshot->setClip(0.0f, 0.0f, mWidth, mHeight);
547    mDirtyClip = opaque;
548
549    mRestoreSaveCount = -1;
550
551    return DrawGlInfo::kStatusDone; // No invalidate needed at record-time
552}
553
554void DisplayListRenderer::finish() {
555    insertRestoreToCount();
556    insertTranslate();
557}
558
559void DisplayListRenderer::interrupt() {
560}
561
562void DisplayListRenderer::resume() {
563}
564
565status_t DisplayListRenderer::callDrawGLFunction(Functor *functor, Rect& dirty) {
566    // Ignore dirty during recording, it matters only when we replay
567    addDrawOp(new (alloc()) DrawFunctorOp(functor));
568    mFunctorCount++;
569    return DrawGlInfo::kStatusDone; // No invalidate needed at record-time
570}
571
572int DisplayListRenderer::save(int flags) {
573    addStateOp(new (alloc()) SaveOp(flags));
574    return OpenGLRenderer::save(flags);
575}
576
577void DisplayListRenderer::restore() {
578    if (mRestoreSaveCount < 0) {
579        restoreToCount(getSaveCount() - 1);
580        return;
581    }
582
583    mRestoreSaveCount--;
584    insertTranslate();
585    OpenGLRenderer::restore();
586}
587
588void DisplayListRenderer::restoreToCount(int saveCount) {
589    mRestoreSaveCount = saveCount;
590    insertTranslate();
591    OpenGLRenderer::restoreToCount(saveCount);
592}
593
594int DisplayListRenderer::saveLayer(float left, float top, float right, float bottom,
595        SkPaint* p, int flags) {
596    addStateOp(new (alloc()) SaveLayerOp(left, top, right, bottom, p, flags));
597    return OpenGLRenderer::save(flags);
598}
599
600int DisplayListRenderer::saveLayerAlpha(float left, float top, float right, float bottom,
601        int alpha, int flags) {
602    addStateOp(new (alloc()) SaveLayerAlphaOp(left, top, right, bottom, alpha, flags));
603    return OpenGLRenderer::save(flags);
604}
605
606void DisplayListRenderer::translate(float dx, float dy) {
607    mHasTranslate = true;
608    mTranslateX += dx;
609    mTranslateY += dy;
610    insertRestoreToCount();
611    OpenGLRenderer::translate(dx, dy);
612}
613
614void DisplayListRenderer::rotate(float degrees) {
615    addStateOp(new (alloc()) RotateOp(degrees));
616    OpenGLRenderer::rotate(degrees);
617}
618
619void DisplayListRenderer::scale(float sx, float sy) {
620    addStateOp(new (alloc()) ScaleOp(sx, sy));
621    OpenGLRenderer::scale(sx, sy);
622}
623
624void DisplayListRenderer::skew(float sx, float sy) {
625    addStateOp(new (alloc()) SkewOp(sx, sy));
626    OpenGLRenderer::skew(sx, sy);
627}
628
629void DisplayListRenderer::setMatrix(SkMatrix* matrix) {
630    matrix = refMatrix(matrix);
631    addStateOp(new (alloc()) SetMatrixOp(matrix));
632    OpenGLRenderer::setMatrix(matrix);
633}
634
635void DisplayListRenderer::concatMatrix(SkMatrix* matrix) {
636    matrix = refMatrix(matrix);
637    addStateOp(new (alloc()) ConcatMatrixOp(matrix));
638    OpenGLRenderer::concatMatrix(matrix);
639}
640
641bool DisplayListRenderer::clipRect(float left, float top, float right, float bottom,
642        SkRegion::Op op) {
643    addStateOp(new (alloc()) ClipRectOp(left, top, right, bottom, op));
644    return OpenGLRenderer::clipRect(left, top, right, bottom, op);
645}
646
647bool DisplayListRenderer::clipPath(SkPath* path, SkRegion::Op op) {
648    path = refPath(path);
649    addStateOp(new (alloc()) ClipPathOp(path, op));
650    return OpenGLRenderer::clipPath(path, op);
651}
652
653bool DisplayListRenderer::clipRegion(SkRegion* region, SkRegion::Op op) {
654    region = refRegion(region);
655    addStateOp(new (alloc()) ClipRegionOp(region, op));
656    return OpenGLRenderer::clipRegion(region, op);
657}
658
659status_t DisplayListRenderer::drawDisplayList(DisplayList* displayList,
660        Rect& dirty, int32_t flags, uint32_t level) {
661    // dirty is an out parameter and should not be recorded,
662    // it matters only when replaying the display list
663
664    // TODO: To be safe, the display list should be ref-counted in the
665    //       resources cache, but we rely on the caller (UI toolkit) to
666    //       do the right thing for now
667
668    addDrawOp(new (alloc()) DrawDisplayListOp(displayList, flags));
669    return DrawGlInfo::kStatusDone;
670}
671
672status_t DisplayListRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) {
673    mLayers.add(layer);
674    mCaches.resourceCache.incrementRefcount(layer);
675    paint = refPaint(paint);
676
677    addDrawOp(new (alloc()) DrawLayerOp(layer, x, y, paint));
678    return DrawGlInfo::kStatusDone;
679}
680
681status_t DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint) {
682    bitmap = refBitmap(bitmap);
683    paint = refPaint(paint);
684
685    addDrawOp(new (alloc()) DrawBitmapOp(bitmap, left, top, paint));
686    return DrawGlInfo::kStatusDone;
687}
688
689status_t DisplayListRenderer::drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint) {
690    bitmap = refBitmap(bitmap);
691    matrix = refMatrix(matrix);
692    paint = refPaint(paint);
693
694    addDrawOp(new (alloc()) DrawBitmapMatrixOp(bitmap, matrix, paint));
695    return DrawGlInfo::kStatusDone;
696}
697
698status_t DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
699        float srcRight, float srcBottom, float dstLeft, float dstTop,
700        float dstRight, float dstBottom, SkPaint* paint) {
701    bitmap = refBitmap(bitmap);
702    paint = refPaint(paint);
703
704    addDrawOp(new (alloc()) DrawBitmapRectOp(bitmap,
705                    srcLeft, srcTop, srcRight, srcBottom,
706                    dstLeft, dstTop, dstRight, dstBottom, paint));
707    return DrawGlInfo::kStatusDone;
708}
709
710status_t DisplayListRenderer::drawBitmapData(SkBitmap* bitmap, float left, float top,
711        SkPaint* paint) {
712    bitmap = refBitmapData(bitmap);
713    paint = refPaint(paint);
714
715    addDrawOp(new (alloc()) DrawBitmapDataOp(bitmap, left, top, paint));
716    return DrawGlInfo::kStatusDone;
717}
718
719status_t DisplayListRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHeight,
720        float* vertices, int* colors, SkPaint* paint) {
721    int count = (meshWidth + 1) * (meshHeight + 1) * 2;
722    bitmap = refBitmap(bitmap);
723    vertices = refBuffer<float>(vertices, count);
724    paint = refPaint(paint);
725    colors = refBuffer<int>(colors, count);
726
727    addDrawOp(new (alloc()) DrawBitmapMeshOp(bitmap, meshWidth, meshHeight,
728                    vertices, colors, paint));
729    return DrawGlInfo::kStatusDone;
730}
731
732status_t DisplayListRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs,
733        const int32_t* yDivs, const uint32_t* colors, uint32_t width, uint32_t height,
734        int8_t numColors, float left, float top, float right, float bottom, SkPaint* paint) {
735    int alpha;
736    SkXfermode::Mode mode;
737    OpenGLRenderer::getAlphaAndModeDirect(paint, &alpha, &mode);
738
739    bitmap = refBitmap(bitmap);
740    xDivs = refBuffer<int>(xDivs, width);
741    yDivs = refBuffer<int>(yDivs, height);
742    colors = refBuffer<uint32_t>(colors, numColors);
743
744    addDrawOp(new (alloc()) DrawPatchOp(bitmap, xDivs, yDivs, colors, width, height, numColors,
745                    left, top, right, bottom, alpha, mode));
746    return DrawGlInfo::kStatusDone;
747}
748
749status_t DisplayListRenderer::drawColor(int color, SkXfermode::Mode mode) {
750    addDrawOp(new (alloc()) DrawColorOp(color, mode));
751    return DrawGlInfo::kStatusDone;
752}
753
754status_t DisplayListRenderer::drawRect(float left, float top, float right, float bottom,
755        SkPaint* paint) {
756    paint = refPaint(paint);
757    addDrawOp(new (alloc()) DrawRectOp(left, top, right, bottom, paint));
758    return DrawGlInfo::kStatusDone;
759}
760
761status_t DisplayListRenderer::drawRoundRect(float left, float top, float right, float bottom,
762        float rx, float ry, SkPaint* paint) {
763    paint = refPaint(paint);
764    addDrawOp(new (alloc()) DrawRoundRectOp(left, top, right, bottom, rx, ry, paint));
765    return DrawGlInfo::kStatusDone;
766}
767
768status_t DisplayListRenderer::drawCircle(float x, float y, float radius, SkPaint* paint) {
769    paint = refPaint(paint);
770    addDrawOp(new (alloc()) DrawCircleOp(x, y, radius, paint));
771    return DrawGlInfo::kStatusDone;
772}
773
774status_t DisplayListRenderer::drawOval(float left, float top, float right, float bottom,
775        SkPaint* paint) {
776    paint = refPaint(paint);
777    addDrawOp(new (alloc()) DrawOvalOp(left, top, right, bottom, paint));
778    return DrawGlInfo::kStatusDone;
779}
780
781status_t DisplayListRenderer::drawArc(float left, float top, float right, float bottom,
782        float startAngle, float sweepAngle, bool useCenter, SkPaint* paint) {
783    paint = refPaint(paint);
784    addDrawOp(new (alloc()) DrawArcOp(left, top, right, bottom,
785                    startAngle, sweepAngle, useCenter, paint));
786    return DrawGlInfo::kStatusDone;
787}
788
789status_t DisplayListRenderer::drawPath(SkPath* path, SkPaint* paint) {
790    path = refPath(path);
791    paint = refPaint(paint);
792
793    addDrawOp(new (alloc()) DrawPathOp(path, paint));
794    return DrawGlInfo::kStatusDone;
795}
796
797status_t DisplayListRenderer::drawLines(float* points, int count, SkPaint* paint) {
798    points = refBuffer<float>(points, count);
799    paint = refPaint(paint);
800
801    addDrawOp(new (alloc()) DrawLinesOp(points, count, paint));
802    return DrawGlInfo::kStatusDone;
803}
804
805status_t DisplayListRenderer::drawPoints(float* points, int count, SkPaint* paint) {
806    points = refBuffer<float>(points, count);
807    paint = refPaint(paint);
808
809    addDrawOp(new (alloc()) DrawPointsOp(points, count, paint));
810    return DrawGlInfo::kStatusDone;
811}
812
813status_t DisplayListRenderer::drawTextOnPath(const char* text, int bytesCount, int count,
814        SkPath* path, float hOffset, float vOffset, SkPaint* paint) {
815    if (!text || count <= 0) return DrawGlInfo::kStatusDone;
816
817    text = refText(text, bytesCount);
818    path = refPath(path);
819    paint = refPaint(paint);
820
821    DrawOp* op = new (alloc()) DrawTextOnPathOp(text, bytesCount, count, path,
822            hOffset, vOffset, paint);
823    if (addDrawOp(op)) {
824        // precache if draw operation is visible
825        FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
826        fontRenderer.precache(paint, text, count, *mSnapshot->transform);
827    }
828    return DrawGlInfo::kStatusDone;
829}
830
831status_t DisplayListRenderer::drawPosText(const char* text, int bytesCount, int count,
832        const float* positions, SkPaint* paint) {
833    if (!text || count <= 0) return DrawGlInfo::kStatusDone;
834
835    text = refText(text, bytesCount);
836    positions = refBuffer<float>(positions, count * 2);
837    paint = refPaint(paint);
838
839    DrawOp* op = new (alloc()) DrawPosTextOp(text, bytesCount, count, positions, paint);
840    if (addDrawOp(op)) {
841        // precache if draw operation is visible
842        FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
843        fontRenderer.precache(paint, text, count, *mSnapshot->transform);
844    }
845    return DrawGlInfo::kStatusDone;
846}
847
848status_t DisplayListRenderer::drawText(const char* text, int bytesCount, int count,
849        float x, float y, const float* positions, SkPaint* paint, float length) {
850    if (!text || count <= 0) return DrawGlInfo::kStatusDone;
851
852    if (length < 0.0f) length = paint->measureText(text, bytesCount);
853
854    text = refText(text, bytesCount);
855    positions = refBuffer<float>(positions, count * 2);
856    paint = refPaint(paint);
857
858    DrawOp* op = new (alloc()) DrawTextOp(text, bytesCount, count, x, y, positions, paint, length);
859    if (addDrawOp(op)) {
860        // precache if draw operation is visible
861        FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
862        fontRenderer.precache(paint, text, count, *mSnapshot->transform);
863    }
864    return DrawGlInfo::kStatusDone;
865}
866
867status_t DisplayListRenderer::drawRects(const float* rects, int count, SkPaint* paint) {
868    if (count <= 0) return DrawGlInfo::kStatusDone;
869
870    rects = refBuffer<float>(rects, count);
871    paint = refPaint(paint);
872    addDrawOp(new (alloc()) DrawRectsOp(rects, count, paint));
873    return DrawGlInfo::kStatusDone;
874}
875
876void DisplayListRenderer::resetShader() {
877    addStateOp(new (alloc()) ResetShaderOp());
878}
879
880void DisplayListRenderer::setupShader(SkiaShader* shader) {
881    shader = refShader(shader);
882    addStateOp(new (alloc()) SetupShaderOp(shader));
883}
884
885void DisplayListRenderer::resetColorFilter() {
886    addStateOp(new (alloc()) ResetColorFilterOp());
887}
888
889void DisplayListRenderer::setupColorFilter(SkiaColorFilter* filter) {
890    filter = refColorFilter(filter);
891    addStateOp(new (alloc()) SetupColorFilterOp(filter));
892}
893
894void DisplayListRenderer::resetShadow() {
895    addStateOp(new (alloc()) ResetShadowOp());
896}
897
898void DisplayListRenderer::setupShadow(float radius, float dx, float dy, int color) {
899    addStateOp(new (alloc()) SetupShadowOp(radius, dx, dy, color));
900}
901
902void DisplayListRenderer::resetPaintFilter() {
903    addStateOp(new (alloc()) ResetPaintFilterOp());
904}
905
906void DisplayListRenderer::setupPaintFilter(int clearBits, int setBits) {
907    addStateOp(new (alloc()) SetupPaintFilterOp(clearBits, setBits));
908}
909
910void DisplayListRenderer::insertRestoreToCount() {
911    if (mRestoreSaveCount >= 0) {
912        DisplayListOp* op = new (alloc()) RestoreToCountOp(mRestoreSaveCount);
913        mDisplayListData->displayListOps.add(op);
914        mRestoreSaveCount = -1;
915    }
916}
917
918void DisplayListRenderer::insertTranslate() {
919    if (mHasTranslate) {
920        if (mTranslateX != 0.0f || mTranslateY != 0.0f) {
921            DisplayListOp* op = new (alloc()) TranslateOp(mTranslateX, mTranslateY);
922            mDisplayListData->displayListOps.add(op);
923            mTranslateX = mTranslateY = 0.0f;
924        }
925        mHasTranslate = false;
926    }
927}
928
929void DisplayListRenderer::addStateOp(StateOp* op) {
930    addOpInternal(op);
931}
932
933bool DisplayListRenderer::addDrawOp(DrawOp* op) {
934    bool rejected = false;
935    Rect localBounds;
936    if (op->getLocalBounds(localBounds)) {
937        rejected = quickRejectNoScissor(localBounds.left, localBounds.top,
938                localBounds.right, localBounds.bottom);
939        op->setQuickRejected(rejected);
940    }
941    mHasDrawOps = true;
942    addOpInternal(op);
943    return !rejected;
944}
945
946}; // namespace uirenderer
947}; // namespace android
948