DisplayListRenderer.h revision 8d56b0e1d24f7392314df4be6503af395a843696
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#ifndef ANDROID_HWUI_DISPLAY_LIST_RENDERER_H
18#define ANDROID_HWUI_DISPLAY_LIST_RENDERER_H
19
20#include <SkChunkAlloc.h>
21#include <SkFlattenable.h>
22#include <SkMatrix.h>
23#include <SkCamera.h>
24#include <SkPaint.h>
25#include <SkPath.h>
26#include <SkRefCnt.h>
27#include <SkTDArray.h>
28#include <SkTSearch.h>
29
30#include <cutils/compiler.h>
31
32#include "DisplayListLogBuffer.h"
33#include "OpenGLRenderer.h"
34
35namespace android {
36namespace uirenderer {
37
38///////////////////////////////////////////////////////////////////////////////
39// Defines
40///////////////////////////////////////////////////////////////////////////////
41
42#define MIN_WRITER_SIZE 4096
43#define OP_MAY_BE_SKIPPED_MASK 0xff000000
44
45// Debug
46#if DEBUG_DISPLAY_LIST
47    #define DISPLAY_LIST_LOGD(...) ALOGD(__VA_ARGS__)
48#else
49    #define DISPLAY_LIST_LOGD(...)
50#endif
51
52// Set to 1 to enable native processing of View properties. 0 by default. Eventually this
53// will go away and we will always use this approach for accelerated apps.
54#define USE_DISPLAY_LIST_PROPERTIES 1
55
56#define TRANSLATION 0x0001
57#define ROTATION    0x0002
58#define ROTATION_3D 0x0004
59#define SCALE       0x0008
60#define PIVOT       0x0010
61
62///////////////////////////////////////////////////////////////////////////////
63// Display list
64///////////////////////////////////////////////////////////////////////////////
65
66class DisplayListRenderer;
67
68/**
69 * Replays recorded drawing commands.
70 */
71class DisplayList {
72public:
73    DisplayList(const DisplayListRenderer& recorder);
74    ANDROID_API ~DisplayList();
75
76    // IMPORTANT: Update the intialization of OP_NAMES in the .cpp file
77    //            when modifying this file
78    enum Op {
79        // Non-drawing operations
80        Save = 0,
81        Restore,
82        RestoreToCount,
83        SaveLayer,
84        SaveLayerAlpha,
85        Translate,
86        Rotate,
87        Scale,
88        Skew,
89        SetMatrix,
90        ConcatMatrix,
91        ClipRect,
92        // Drawing operations
93        DrawDisplayList,
94        DrawLayer,
95        DrawBitmap,
96        DrawBitmapMatrix,
97        DrawBitmapRect,
98        DrawBitmapMesh,
99        DrawPatch,
100        DrawColor,
101        DrawRect,
102        DrawRoundRect,
103        DrawCircle,
104        DrawOval,
105        DrawArc,
106        DrawPath,
107        DrawLines,
108        DrawPoints,
109        DrawText,
110        DrawTextOnPath,
111        DrawPosText,
112        ResetShader,
113        SetupShader,
114        ResetColorFilter,
115        SetupColorFilter,
116        ResetShadow,
117        SetupShadow,
118        ResetPaintFilter,
119        SetupPaintFilter,
120        DrawGLFunction,
121    };
122
123    // See flags defined in DisplayList.java
124    enum ReplayFlag {
125        kReplayFlag_ClipChildren = 0x1
126    };
127
128    static const char* OP_NAMES[];
129
130    void setViewProperties(OpenGLRenderer& renderer, uint32_t width, uint32_t height,
131            uint32_t level);
132    void outputViewProperties(OpenGLRenderer& renderer, char* indent);
133
134    ANDROID_API size_t getSize();
135    ANDROID_API static void destroyDisplayListDeferred(DisplayList* displayList);
136    ANDROID_API static void outputLogBuffer(int fd);
137
138    void initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing = false);
139
140    status_t replay(OpenGLRenderer& renderer, uint32_t width, uint32_t height,
141            Rect& dirty, int32_t flags, uint32_t level = 0);
142
143    void output(OpenGLRenderer& renderer, uint32_t level = 0);
144
145    void setRenderable(bool renderable) {
146        mIsRenderable = renderable;
147    }
148
149    bool isRenderable() const {
150        return mIsRenderable;
151    }
152
153    void setName(const char* name) {
154        if (name) {
155            mName.setTo(name);
156        }
157    }
158
159    void setClipChildren(bool clipChildren) {
160        mClipChildren = clipChildren;
161    }
162
163    void setStaticMatrix(SkMatrix* matrix) {
164        delete mStaticMatrix;
165        mStaticMatrix = new SkMatrix(*matrix);
166    }
167
168    void setAnimationMatrix(SkMatrix* matrix) {
169        delete mAnimationMatrix;
170        if (matrix) {
171            mAnimationMatrix = new SkMatrix(*matrix);
172        } else {
173            mAnimationMatrix = NULL;
174        }
175    }
176
177    void setAlpha(float alpha) {
178        if (alpha != mAlpha) {
179            mAlpha = alpha;
180            mMultipliedAlpha = (int)(255 * alpha);
181        }
182    }
183
184    void setTranslationX(float translationX) {
185        if (translationX != mTranslationX) {
186            mTranslationX = translationX;
187            mMatrixDirty = true;
188            if (ALMOST_EQUAL(mTranslationX, 0) && ALMOST_EQUAL(mTranslationY, 0)) {
189                mMatrixFlags &= ~TRANSLATION;
190            } else {
191                mMatrixFlags |= TRANSLATION;
192            }
193        }
194    }
195
196    void setTranslationY(float translationY) {
197        if (translationY != mTranslationY) {
198            mTranslationY = translationY;
199            mMatrixDirty = true;
200            if (ALMOST_EQUAL(mTranslationX, 0) && ALMOST_EQUAL(mTranslationY, 0)) {
201                mMatrixFlags &= ~TRANSLATION;
202            } else {
203                mMatrixFlags |= TRANSLATION;
204            }
205        }
206    }
207
208    void setRotation(float rotation) {
209        if (rotation != mRotation) {
210            mRotation = rotation;
211            mMatrixDirty = true;
212            if (ALMOST_EQUAL(mRotation, 0)) {
213                mMatrixFlags &= ~ROTATION;
214            } else {
215                mMatrixFlags |= ROTATION;
216            }
217        }
218    }
219
220    void setRotationX(float rotationX) {
221        if (rotationX != mRotationX) {
222            mRotationX = rotationX;
223            mMatrixDirty = true;
224            if (ALMOST_EQUAL(mRotationX, 0) && ALMOST_EQUAL(mRotationY, 0)) {
225                mMatrixFlags &= ~ROTATION_3D;
226            } else {
227                mMatrixFlags |= ROTATION_3D;
228            }
229        }
230    }
231
232    void setRotationY(float rotationY) {
233        if (rotationY != mRotationY) {
234            mRotationY = rotationY;
235            mMatrixDirty = true;
236            if (ALMOST_EQUAL(mRotationX, 0) && ALMOST_EQUAL(mRotationY, 0)) {
237                mMatrixFlags &= ~ROTATION_3D;
238            } else {
239                mMatrixFlags |= ROTATION_3D;
240            }
241        }
242    }
243
244    void setScaleX(float scaleX) {
245        if (scaleX != mScaleX) {
246            mScaleX = scaleX;
247            mMatrixDirty = true;
248            if (ALMOST_EQUAL(mScaleX, 1) && ALMOST_EQUAL(mScaleY, 1)) {
249                mMatrixFlags &= ~SCALE;
250            } else {
251                mMatrixFlags |= SCALE;
252            }
253        }
254    }
255
256    void setScaleY(float scaleY) {
257        if (scaleY != mScaleY) {
258            mScaleY = scaleY;
259            mMatrixDirty = true;
260            if (ALMOST_EQUAL(mScaleX, 1) && ALMOST_EQUAL(mScaleY, 1)) {
261                mMatrixFlags &= ~SCALE;
262            } else {
263                mMatrixFlags |= SCALE;
264            }
265        }
266    }
267
268    void setPivotX(float pivotX) {
269        mPivotX = pivotX;
270        mMatrixDirty = true;
271        if (ALMOST_EQUAL(mPivotX, 0) && ALMOST_EQUAL(mPivotY, 0)) {
272            mMatrixFlags &= ~PIVOT;
273        } else {
274            mMatrixFlags |= PIVOT;
275        }
276        mPivotExplicitlySet = true;
277    }
278
279    void setPivotY(float pivotY) {
280        mPivotY = pivotY;
281        mMatrixDirty = true;
282        if (ALMOST_EQUAL(mPivotX, 0) && ALMOST_EQUAL(mPivotY, 0)) {
283            mMatrixFlags &= ~PIVOT;
284        } else {
285            mMatrixFlags |= PIVOT;
286        }
287        mPivotExplicitlySet = true;
288    }
289
290    void setCameraDistance(float distance) {
291        if (distance != mCameraDistance) {
292            mCameraDistance = distance;
293            mMatrixDirty = true;
294            if (!mTransformCamera) {
295                mTransformCamera = new Sk3DView();
296                mTransformMatrix3D = new SkMatrix();
297            }
298            mTransformCamera->setCameraLocation(0, 0, distance);
299        }
300    }
301
302    void setLeft(int left) {
303        if (left != mLeft) {
304            mLeft = left;
305            mWidth = mRight - mLeft;
306            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
307                mMatrixDirty = true;
308            }
309        }
310    }
311
312    void setTop(int top) {
313        if (top != mTop) {
314            mTop = top;
315            mHeight = mBottom - mTop;
316            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
317                mMatrixDirty = true;
318            }
319        }
320    }
321
322    void setRight(int right) {
323        if (right != mRight) {
324            mRight = right;
325            mWidth = mRight - mLeft;
326            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
327                mMatrixDirty = true;
328            }
329        }
330    }
331
332    void setBottom(int bottom) {
333        if (bottom != mBottom) {
334            mBottom = bottom;
335            mHeight = mBottom - mTop;
336            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
337                mMatrixDirty = true;
338            }
339        }
340    }
341
342    void setLeftTop(int left, int top) {
343        if (left != mLeft || top != mTop) {
344            mLeft = left;
345            mTop = top;
346            mWidth = mRight - mLeft;
347            mHeight = mBottom - mTop;
348            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
349                mMatrixDirty = true;
350            }
351        }
352    }
353
354    void setLeftTopRightBottom(int left, int top, int right, int bottom) {
355        if (left != mLeft || top != mTop || right != mRight || bottom != mBottom) {
356            mLeft = left;
357            mTop = top;
358            mRight = right;
359            mBottom = bottom;
360            mWidth = mRight - mLeft;
361            mHeight = mBottom - mTop;
362            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
363                mMatrixDirty = true;
364            }
365        }
366    }
367
368    void offsetLeftRight(int offset) {
369        if (offset != 0) {
370            mLeft += offset;
371            mRight += offset;
372            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
373                mMatrixDirty = true;
374            }
375        }
376    }
377
378    void offsetTopBottom(int offset) {
379        if (offset != 0) {
380            mTop += offset;
381            mBottom += offset;
382            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
383                mMatrixDirty = true;
384            }
385        }
386    }
387
388    void setCaching(bool caching) {
389        mCaching = caching;
390    }
391
392private:
393    void init();
394
395    void initProperties();
396
397    void clearResources();
398
399    void updateMatrix();
400
401    class TextContainer {
402    public:
403        size_t length() const {
404            return mByteLength;
405        }
406
407        const char* text() const {
408            return (const char*) mText;
409        }
410
411        size_t mByteLength;
412        const char* mText;
413    };
414
415    SkBitmap* getBitmap() {
416        return (SkBitmap*) getInt();
417    }
418
419    SkiaShader* getShader() {
420        return (SkiaShader*) getInt();
421    }
422
423    SkiaColorFilter* getColorFilter() {
424        return (SkiaColorFilter*) getInt();
425    }
426
427    inline int32_t getIndex() {
428        return mReader.readInt();
429    }
430
431    inline int32_t getInt() {
432        return mReader.readInt();
433    }
434
435    inline uint32_t getUInt() {
436        return mReader.readU32();
437    }
438
439    SkMatrix* getMatrix() {
440        return (SkMatrix*) getInt();
441    }
442
443    SkPath* getPath() {
444        return (SkPath*) getInt();
445    }
446
447    SkPaint* getPaint(OpenGLRenderer& renderer) {
448        return renderer.filterPaint((SkPaint*) getInt());
449    }
450
451    DisplayList* getDisplayList() {
452        return (DisplayList*) getInt();
453    }
454
455    inline float getFloat() {
456        return mReader.readScalar();
457    }
458
459    int32_t* getInts(uint32_t& count) {
460        count = getInt();
461        return (int32_t*) mReader.skip(count * sizeof(int32_t));
462    }
463
464    uint32_t* getUInts(int8_t& count) {
465        count = getInt();
466        return (uint32_t*) mReader.skip(count * sizeof(uint32_t));
467    }
468
469    float* getFloats(int32_t& count) {
470        count = getInt();
471        return (float*) mReader.skip(count * sizeof(float));
472    }
473
474    void getText(TextContainer* text) {
475        size_t length = text->mByteLength = getInt();
476        text->mText = (const char*) mReader.skip(length);
477    }
478
479    Vector<SkBitmap*> mBitmapResources;
480    Vector<SkiaColorFilter*> mFilterResources;
481
482    Vector<SkPaint*> mPaints;
483    Vector<SkPath*> mPaths;
484    Vector<SkMatrix*> mMatrices;
485    Vector<SkiaShader*> mShaders;
486
487    mutable SkFlattenableReadBuffer mReader;
488
489    size_t mSize;
490
491    bool mIsRenderable;
492
493    String8 mName;
494
495    // View properties
496    bool mClipChildren;
497    float mAlpha;
498    int mMultipliedAlpha;
499    float mTranslationX, mTranslationY;
500    float mRotation, mRotationX, mRotationY;
501    float mScaleX, mScaleY;
502    float mPivotX, mPivotY;
503    float mCameraDistance;
504    int mLeft, mTop, mRight, mBottom;
505    int mWidth, mHeight;
506    int mPrevWidth, mPrevHeight;
507    bool mPivotExplicitlySet;
508    bool mMatrixDirty;
509    bool mMatrixIsIdentity;
510    uint32_t mMatrixFlags;
511    SkMatrix* mTransformMatrix;
512    Sk3DView* mTransformCamera;
513    SkMatrix* mTransformMatrix3D;
514    SkMatrix* mStaticMatrix;
515    SkMatrix* mAnimationMatrix;
516    bool mCaching;
517};
518
519///////////////////////////////////////////////////////////////////////////////
520// Renderer
521///////////////////////////////////////////////////////////////////////////////
522
523/**
524 * Records drawing commands in a display list for latter playback.
525 */
526class DisplayListRenderer: public OpenGLRenderer {
527public:
528    ANDROID_API DisplayListRenderer();
529    virtual ~DisplayListRenderer();
530
531    ANDROID_API DisplayList* getDisplayList(DisplayList* displayList);
532
533    virtual void setViewport(int width, int height);
534    virtual void prepareDirty(float left, float top, float right, float bottom, bool opaque);
535    virtual void finish();
536
537    virtual status_t callDrawGLFunction(Functor *functor, Rect& dirty);
538
539    virtual void interrupt();
540    virtual void resume();
541
542    virtual int save(int flags);
543    virtual void restore();
544    virtual void restoreToCount(int saveCount);
545
546    virtual int saveLayer(float left, float top, float right, float bottom,
547            SkPaint* p, int flags);
548    virtual int saveLayerAlpha(float left, float top, float right, float bottom,
549                int alpha, int flags);
550
551    virtual void translate(float dx, float dy);
552    virtual void rotate(float degrees);
553    virtual void scale(float sx, float sy);
554    virtual void skew(float sx, float sy);
555
556    virtual void setMatrix(SkMatrix* matrix);
557    virtual void concatMatrix(SkMatrix* matrix);
558
559    virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
560
561    virtual status_t drawDisplayList(DisplayList* displayList, uint32_t width, uint32_t height,
562            Rect& dirty, int32_t flags, uint32_t level = 0);
563    virtual void drawLayer(Layer* layer, float x, float y, SkPaint* paint);
564    virtual void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
565    virtual void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
566    virtual void drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
567            float srcRight, float srcBottom, float dstLeft, float dstTop,
568            float dstRight, float dstBottom, SkPaint* paint);
569    virtual void drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHeight,
570            float* vertices, int* colors, SkPaint* paint);
571    virtual void drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
572            const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors,
573            float left, float top, float right, float bottom, SkPaint* paint);
574    virtual void drawColor(int color, SkXfermode::Mode mode);
575    virtual void drawRect(float left, float top, float right, float bottom, SkPaint* paint);
576    virtual void drawRoundRect(float left, float top, float right, float bottom,
577            float rx, float ry, SkPaint* paint);
578    virtual void drawCircle(float x, float y, float radius, SkPaint* paint);
579    virtual void drawOval(float left, float top, float right, float bottom, SkPaint* paint);
580    virtual void drawArc(float left, float top, float right, float bottom,
581            float startAngle, float sweepAngle, bool useCenter, SkPaint* paint);
582    virtual void drawPath(SkPath* path, SkPaint* paint);
583    virtual void drawLines(float* points, int count, SkPaint* paint);
584    virtual void drawPoints(float* points, int count, SkPaint* paint);
585    virtual void drawText(const char* text, int bytesCount, int count, float x, float y,
586            SkPaint* paint, float length = -1.0f);
587    virtual void drawTextOnPath(const char* text, int bytesCount, int count, SkPath* path,
588            float hOffset, float vOffset, SkPaint* paint);
589    virtual void drawPosText(const char* text, int bytesCount, int count, const float* positions,
590            SkPaint* paint);
591
592    virtual void resetShader();
593    virtual void setupShader(SkiaShader* shader);
594
595    virtual void resetColorFilter();
596    virtual void setupColorFilter(SkiaColorFilter* filter);
597
598    virtual void resetShadow();
599    virtual void setupShadow(float radius, float dx, float dy, int color);
600
601    virtual void resetPaintFilter();
602    virtual void setupPaintFilter(int clearBits, int setBits);
603
604    ANDROID_API void reset();
605
606    const SkWriter32& writeStream() const {
607        return mWriter;
608    }
609
610    const Vector<SkBitmap*>& getBitmapResources() const {
611        return mBitmapResources;
612    }
613
614    const Vector<SkiaColorFilter*>& getFilterResources() const {
615        return mFilterResources;
616    }
617
618    const Vector<SkiaShader*>& getShaders() const {
619        return mShaders;
620    }
621
622    const Vector<SkPaint*>& getPaints() const {
623        return mPaints;
624    }
625
626    const Vector<SkPath*>& getPaths() const {
627        return mPaths;
628    }
629
630    const Vector<SkMatrix*>& getMatrices() const {
631        return mMatrices;
632    }
633
634private:
635    void insertRestoreToCount() {
636        if (mRestoreSaveCount >= 0) {
637            mWriter.writeInt(DisplayList::RestoreToCount);
638            addInt(mRestoreSaveCount);
639            mRestoreSaveCount = -1;
640        }
641    }
642
643    void insertTranlate() {
644        if (mHasTranslate) {
645            if (mTranslateX != 0.0f || mTranslateY != 0.0f) {
646                mWriter.writeInt(DisplayList::Translate);
647                addPoint(mTranslateX, mTranslateY);
648                mTranslateX = mTranslateY = 0.0f;
649            }
650            mHasTranslate = false;
651        }
652    }
653
654    inline void addOp(const DisplayList::Op drawOp) {
655        insertRestoreToCount();
656        insertTranlate();
657        mWriter.writeInt(drawOp);
658        mHasDrawOps = mHasDrawOps || drawOp >= DisplayList::DrawDisplayList;
659    }
660
661    uint32_t* addOp(const DisplayList::Op drawOp, const bool reject) {
662        insertRestoreToCount();
663        insertTranlate();
664        mHasDrawOps = mHasDrawOps || drawOp >= DisplayList::DrawDisplayList;
665        if (reject) {
666            mWriter.writeInt(OP_MAY_BE_SKIPPED_MASK | drawOp);
667            mWriter.writeInt(0xdeaddead);
668            mBufferSize = mWriter.size();
669            return mWriter.peek32(mBufferSize - sizeof(int32_t));
670        }
671        mWriter.writeInt(drawOp);
672        return NULL;
673    }
674
675    inline void addSkip(uint32_t* location) {
676        if (location) {
677            *location = (int32_t) (mWriter.size() - mBufferSize);
678        }
679    }
680
681    inline void addInt(int32_t value) {
682        mWriter.writeInt(value);
683    }
684
685    inline void addSize(uint32_t w, uint32_t h) {
686        mWriter.writeInt(w);
687        mWriter.writeInt(h);
688    }
689
690    void addInts(const int32_t* values, uint32_t count) {
691        mWriter.writeInt(count);
692        for (uint32_t i = 0; i < count; i++) {
693            mWriter.writeInt(values[i]);
694        }
695    }
696
697    void addUInts(const uint32_t* values, int8_t count) {
698        mWriter.writeInt(count);
699        for (int8_t i = 0; i < count; i++) {
700            mWriter.writeInt(values[i]);
701        }
702    }
703
704    inline void addFloat(float value) {
705        mWriter.writeScalar(value);
706    }
707
708    void addFloats(const float* values, int32_t count) {
709        mWriter.writeInt(count);
710        for (int32_t i = 0; i < count; i++) {
711            mWriter.writeScalar(values[i]);
712        }
713    }
714
715    inline void addPoint(float x, float y) {
716        mWriter.writeScalar(x);
717        mWriter.writeScalar(y);
718    }
719
720    inline void addBounds(float left, float top, float right, float bottom) {
721        mWriter.writeScalar(left);
722        mWriter.writeScalar(top);
723        mWriter.writeScalar(right);
724        mWriter.writeScalar(bottom);
725    }
726
727    inline void addText(const void* text, size_t byteLength) {
728        mWriter.writeInt(byteLength);
729        mWriter.writePad(text, byteLength);
730    }
731
732    inline void addPath(SkPath* path) {
733        if (!path) {
734            addInt((int) NULL);
735            return;
736        }
737
738        SkPath* pathCopy = mPathMap.valueFor(path);
739        if (pathCopy == NULL || pathCopy->getGenerationID() != path->getGenerationID()) {
740            pathCopy = new SkPath(*path);
741            pathCopy->setSourcePath(path);
742            // replaceValueFor() performs an add if the entry doesn't exist
743            mPathMap.replaceValueFor(path, pathCopy);
744            mPaths.add(pathCopy);
745        }
746
747        addInt((int) pathCopy);
748    }
749
750    inline void addPaint(SkPaint* paint) {
751        if (!paint) {
752            addInt((int) NULL);
753            return;
754        }
755
756        SkPaint* paintCopy = mPaintMap.valueFor(paint);
757        if (paintCopy == NULL || paintCopy->getGenerationID() != paint->getGenerationID()) {
758            paintCopy = new SkPaint(*paint);
759            // replaceValueFor() performs an add if the entry doesn't exist
760            mPaintMap.replaceValueFor(paint, paintCopy);
761            mPaints.add(paintCopy);
762        }
763
764        addInt((int) paintCopy);
765    }
766
767    inline void addDisplayList(DisplayList* displayList) {
768        // TODO: To be safe, the display list should be ref-counted in the
769        //       resources cache, but we rely on the caller (UI toolkit) to
770        //       do the right thing for now
771        addInt((int) displayList);
772    }
773
774    inline void addMatrix(SkMatrix* matrix) {
775        // Copying the matrix is cheap and prevents against the user changing the original
776        // matrix before the operation that uses it
777        SkMatrix* copy = new SkMatrix(*matrix);
778        addInt((int) copy);
779        mMatrices.add(copy);
780    }
781
782    inline void addBitmap(SkBitmap* bitmap) {
783        // Note that this assumes the bitmap is immutable. There are cases this won't handle
784        // correctly, such as creating the bitmap from scratch, drawing with it, changing its
785        // contents, and drawing again. The only fix would be to always copy it the first time,
786        // which doesn't seem worth the extra cycles for this unlikely case.
787        addInt((int) bitmap);
788        mBitmapResources.add(bitmap);
789        Caches::getInstance().resourceCache.incrementRefcount(bitmap);
790    }
791
792    inline void addShader(SkiaShader* shader) {
793        if (!shader) {
794            addInt((int) NULL);
795            return;
796        }
797
798        SkiaShader* shaderCopy = mShaderMap.valueFor(shader);
799        // TODO: We also need to handle generation ID changes in compose shaders
800        if (shaderCopy == NULL || shaderCopy->getGenerationId() != shader->getGenerationId()) {
801            shaderCopy = shader->copy();
802            // replaceValueFor() performs an add if the entry doesn't exist
803            mShaderMap.replaceValueFor(shader, shaderCopy);
804            mShaders.add(shaderCopy);
805            Caches::getInstance().resourceCache.incrementRefcount(shaderCopy);
806        }
807
808        addInt((int) shaderCopy);
809    }
810
811    inline void addColorFilter(SkiaColorFilter* colorFilter) {
812        addInt((int) colorFilter);
813        mFilterResources.add(colorFilter);
814        Caches::getInstance().resourceCache.incrementRefcount(colorFilter);
815    }
816
817    Vector<SkBitmap*> mBitmapResources;
818    Vector<SkiaColorFilter*> mFilterResources;
819
820    Vector<SkPaint*> mPaints;
821    DefaultKeyedVector<SkPaint*, SkPaint*> mPaintMap;
822
823    Vector<SkPath*> mPaths;
824    DefaultKeyedVector<SkPath*, SkPath*> mPathMap;
825
826    Vector<SkiaShader*> mShaders;
827    DefaultKeyedVector<SkiaShader*, SkiaShader*> mShaderMap;
828
829    Vector<SkMatrix*> mMatrices;
830
831    SkWriter32 mWriter;
832    uint32_t mBufferSize;
833
834    int mRestoreSaveCount;
835
836    float mTranslateX;
837    float mTranslateY;
838    bool mHasTranslate;
839
840    bool mHasDrawOps;
841
842    friend class DisplayList;
843
844}; // class DisplayListRenderer
845
846}; // namespace uirenderer
847}; // namespace android
848
849#endif // ANDROID_HWUI_DISPLAY_LIST_RENDERER_H
850