DisplayListRenderer.h revision db8c9a6a4d9bf8c39f834b25611926caf21380f6
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 setHasOverlappingRendering(bool hasOverlappingRendering) {
185        mHasOverlappingRendering = hasOverlappingRendering;
186    }
187
188    void setTranslationX(float translationX) {
189        if (translationX != mTranslationX) {
190            mTranslationX = translationX;
191            mMatrixDirty = true;
192            if (ALMOST_EQUAL(mTranslationX, 0) && ALMOST_EQUAL(mTranslationY, 0)) {
193                mMatrixFlags &= ~TRANSLATION;
194            } else {
195                mMatrixFlags |= TRANSLATION;
196            }
197        }
198    }
199
200    void setTranslationY(float translationY) {
201        if (translationY != mTranslationY) {
202            mTranslationY = translationY;
203            mMatrixDirty = true;
204            if (ALMOST_EQUAL(mTranslationX, 0) && ALMOST_EQUAL(mTranslationY, 0)) {
205                mMatrixFlags &= ~TRANSLATION;
206            } else {
207                mMatrixFlags |= TRANSLATION;
208            }
209        }
210    }
211
212    void setRotation(float rotation) {
213        if (rotation != mRotation) {
214            mRotation = rotation;
215            mMatrixDirty = true;
216            if (ALMOST_EQUAL(mRotation, 0)) {
217                mMatrixFlags &= ~ROTATION;
218            } else {
219                mMatrixFlags |= ROTATION;
220            }
221        }
222    }
223
224    void setRotationX(float rotationX) {
225        if (rotationX != mRotationX) {
226            mRotationX = rotationX;
227            mMatrixDirty = true;
228            if (ALMOST_EQUAL(mRotationX, 0) && ALMOST_EQUAL(mRotationY, 0)) {
229                mMatrixFlags &= ~ROTATION_3D;
230            } else {
231                mMatrixFlags |= ROTATION_3D;
232            }
233        }
234    }
235
236    void setRotationY(float rotationY) {
237        if (rotationY != mRotationY) {
238            mRotationY = rotationY;
239            mMatrixDirty = true;
240            if (ALMOST_EQUAL(mRotationX, 0) && ALMOST_EQUAL(mRotationY, 0)) {
241                mMatrixFlags &= ~ROTATION_3D;
242            } else {
243                mMatrixFlags |= ROTATION_3D;
244            }
245        }
246    }
247
248    void setScaleX(float scaleX) {
249        if (scaleX != mScaleX) {
250            mScaleX = scaleX;
251            mMatrixDirty = true;
252            if (ALMOST_EQUAL(mScaleX, 1) && ALMOST_EQUAL(mScaleY, 1)) {
253                mMatrixFlags &= ~SCALE;
254            } else {
255                mMatrixFlags |= SCALE;
256            }
257        }
258    }
259
260    void setScaleY(float scaleY) {
261        if (scaleY != mScaleY) {
262            mScaleY = scaleY;
263            mMatrixDirty = true;
264            if (ALMOST_EQUAL(mScaleX, 1) && ALMOST_EQUAL(mScaleY, 1)) {
265                mMatrixFlags &= ~SCALE;
266            } else {
267                mMatrixFlags |= SCALE;
268            }
269        }
270    }
271
272    void setPivotX(float pivotX) {
273        mPivotX = pivotX;
274        mMatrixDirty = true;
275        if (ALMOST_EQUAL(mPivotX, 0) && ALMOST_EQUAL(mPivotY, 0)) {
276            mMatrixFlags &= ~PIVOT;
277        } else {
278            mMatrixFlags |= PIVOT;
279        }
280        mPivotExplicitlySet = true;
281    }
282
283    void setPivotY(float pivotY) {
284        mPivotY = pivotY;
285        mMatrixDirty = true;
286        if (ALMOST_EQUAL(mPivotX, 0) && ALMOST_EQUAL(mPivotY, 0)) {
287            mMatrixFlags &= ~PIVOT;
288        } else {
289            mMatrixFlags |= PIVOT;
290        }
291        mPivotExplicitlySet = true;
292    }
293
294    void setCameraDistance(float distance) {
295        if (distance != mCameraDistance) {
296            mCameraDistance = distance;
297            mMatrixDirty = true;
298            if (!mTransformCamera) {
299                mTransformCamera = new Sk3DView();
300                mTransformMatrix3D = new SkMatrix();
301            }
302            mTransformCamera->setCameraLocation(0, 0, distance);
303        }
304    }
305
306    void setLeft(int left) {
307        if (left != mLeft) {
308            mLeft = left;
309            mWidth = mRight - mLeft;
310            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
311                mMatrixDirty = true;
312            }
313        }
314    }
315
316    void setTop(int top) {
317        if (top != mTop) {
318            mTop = top;
319            mHeight = mBottom - mTop;
320            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
321                mMatrixDirty = true;
322            }
323        }
324    }
325
326    void setRight(int right) {
327        if (right != mRight) {
328            mRight = right;
329            mWidth = mRight - mLeft;
330            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
331                mMatrixDirty = true;
332            }
333        }
334    }
335
336    void setBottom(int bottom) {
337        if (bottom != mBottom) {
338            mBottom = bottom;
339            mHeight = mBottom - mTop;
340            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
341                mMatrixDirty = true;
342            }
343        }
344    }
345
346    void setLeftTop(int left, int top) {
347        if (left != mLeft || top != mTop) {
348            mLeft = left;
349            mTop = top;
350            mWidth = mRight - mLeft;
351            mHeight = mBottom - mTop;
352            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
353                mMatrixDirty = true;
354            }
355        }
356    }
357
358    void setLeftTopRightBottom(int left, int top, int right, int bottom) {
359        if (left != mLeft || top != mTop || right != mRight || bottom != mBottom) {
360            mLeft = left;
361            mTop = top;
362            mRight = right;
363            mBottom = bottom;
364            mWidth = mRight - mLeft;
365            mHeight = mBottom - mTop;
366            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
367                mMatrixDirty = true;
368            }
369        }
370    }
371
372    void offsetLeftRight(int offset) {
373        if (offset != 0) {
374            mLeft += offset;
375            mRight += offset;
376            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
377                mMatrixDirty = true;
378            }
379        }
380    }
381
382    void offsetTopBottom(int offset) {
383        if (offset != 0) {
384            mTop += offset;
385            mBottom += offset;
386            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
387                mMatrixDirty = true;
388            }
389        }
390    }
391
392    void setCaching(bool caching) {
393        mCaching = caching;
394    }
395
396private:
397    void init();
398
399    void initProperties();
400
401    void clearResources();
402
403    void updateMatrix();
404
405    class TextContainer {
406    public:
407        size_t length() const {
408            return mByteLength;
409        }
410
411        const char* text() const {
412            return (const char*) mText;
413        }
414
415        size_t mByteLength;
416        const char* mText;
417    };
418
419    SkBitmap* getBitmap() {
420        return (SkBitmap*) getInt();
421    }
422
423    SkiaShader* getShader() {
424        return (SkiaShader*) getInt();
425    }
426
427    SkiaColorFilter* getColorFilter() {
428        return (SkiaColorFilter*) getInt();
429    }
430
431    inline int32_t getIndex() {
432        return mReader.readInt();
433    }
434
435    inline int32_t getInt() {
436        return mReader.readInt();
437    }
438
439    inline uint32_t getUInt() {
440        return mReader.readU32();
441    }
442
443    SkMatrix* getMatrix() {
444        return (SkMatrix*) getInt();
445    }
446
447    SkPath* getPath() {
448        return (SkPath*) getInt();
449    }
450
451    SkPaint* getPaint(OpenGLRenderer& renderer) {
452        return renderer.filterPaint((SkPaint*) getInt());
453    }
454
455    DisplayList* getDisplayList() {
456        return (DisplayList*) getInt();
457    }
458
459    inline float getFloat() {
460        return mReader.readScalar();
461    }
462
463    int32_t* getInts(uint32_t& count) {
464        count = getInt();
465        return (int32_t*) mReader.skip(count * sizeof(int32_t));
466    }
467
468    uint32_t* getUInts(int8_t& count) {
469        count = getInt();
470        return (uint32_t*) mReader.skip(count * sizeof(uint32_t));
471    }
472
473    float* getFloats(int32_t& count) {
474        count = getInt();
475        return (float*) mReader.skip(count * sizeof(float));
476    }
477
478    void getText(TextContainer* text) {
479        size_t length = text->mByteLength = getInt();
480        text->mText = (const char*) mReader.skip(length);
481    }
482
483    Vector<SkBitmap*> mBitmapResources;
484    Vector<SkiaColorFilter*> mFilterResources;
485
486    Vector<SkPaint*> mPaints;
487    Vector<SkPath*> mPaths;
488    Vector<SkMatrix*> mMatrices;
489    Vector<SkiaShader*> mShaders;
490
491    mutable SkFlattenableReadBuffer mReader;
492
493    size_t mSize;
494
495    bool mIsRenderable;
496
497    String8 mName;
498
499    // View properties
500    bool mClipChildren;
501    float mAlpha;
502    int mMultipliedAlpha;
503    bool mHasOverlappingRendering;
504    float mTranslationX, mTranslationY;
505    float mRotation, mRotationX, mRotationY;
506    float mScaleX, mScaleY;
507    float mPivotX, mPivotY;
508    float mCameraDistance;
509    int mLeft, mTop, mRight, mBottom;
510    int mWidth, mHeight;
511    int mPrevWidth, mPrevHeight;
512    bool mPivotExplicitlySet;
513    bool mMatrixDirty;
514    bool mMatrixIsIdentity;
515    uint32_t mMatrixFlags;
516    SkMatrix* mTransformMatrix;
517    Sk3DView* mTransformCamera;
518    SkMatrix* mTransformMatrix3D;
519    SkMatrix* mStaticMatrix;
520    SkMatrix* mAnimationMatrix;
521    bool mCaching;
522};
523
524///////////////////////////////////////////////////////////////////////////////
525// Renderer
526///////////////////////////////////////////////////////////////////////////////
527
528/**
529 * Records drawing commands in a display list for latter playback.
530 */
531class DisplayListRenderer: public OpenGLRenderer {
532public:
533    ANDROID_API DisplayListRenderer();
534    virtual ~DisplayListRenderer();
535
536    ANDROID_API DisplayList* getDisplayList(DisplayList* displayList);
537
538    virtual void setViewport(int width, int height);
539    virtual void prepareDirty(float left, float top, float right, float bottom, bool opaque);
540    virtual void finish();
541
542    virtual status_t callDrawGLFunction(Functor *functor, Rect& dirty);
543
544    virtual void interrupt();
545    virtual void resume();
546
547    virtual int save(int flags);
548    virtual void restore();
549    virtual void restoreToCount(int saveCount);
550
551    virtual int saveLayer(float left, float top, float right, float bottom,
552            SkPaint* p, int flags);
553    virtual int saveLayerAlpha(float left, float top, float right, float bottom,
554                int alpha, int flags);
555
556    virtual void translate(float dx, float dy);
557    virtual void rotate(float degrees);
558    virtual void scale(float sx, float sy);
559    virtual void skew(float sx, float sy);
560
561    virtual void setMatrix(SkMatrix* matrix);
562    virtual void concatMatrix(SkMatrix* matrix);
563
564    virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
565
566    virtual status_t drawDisplayList(DisplayList* displayList, uint32_t width, uint32_t height,
567            Rect& dirty, int32_t flags, uint32_t level = 0);
568    virtual void drawLayer(Layer* layer, float x, float y, SkPaint* paint);
569    virtual void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
570    virtual void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
571    virtual void drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
572            float srcRight, float srcBottom, float dstLeft, float dstTop,
573            float dstRight, float dstBottom, SkPaint* paint);
574    virtual void drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHeight,
575            float* vertices, int* colors, SkPaint* paint);
576    virtual void drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
577            const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors,
578            float left, float top, float right, float bottom, SkPaint* paint);
579    virtual void drawColor(int color, SkXfermode::Mode mode);
580    virtual void drawRect(float left, float top, float right, float bottom, SkPaint* paint);
581    virtual void drawRoundRect(float left, float top, float right, float bottom,
582            float rx, float ry, SkPaint* paint);
583    virtual void drawCircle(float x, float y, float radius, SkPaint* paint);
584    virtual void drawOval(float left, float top, float right, float bottom, SkPaint* paint);
585    virtual void drawArc(float left, float top, float right, float bottom,
586            float startAngle, float sweepAngle, bool useCenter, SkPaint* paint);
587    virtual void drawPath(SkPath* path, SkPaint* paint);
588    virtual void drawLines(float* points, int count, SkPaint* paint);
589    virtual void drawPoints(float* points, int count, SkPaint* paint);
590    virtual void drawText(const char* text, int bytesCount, int count, float x, float y,
591            SkPaint* paint, float length = -1.0f);
592    virtual void drawTextOnPath(const char* text, int bytesCount, int count, SkPath* path,
593            float hOffset, float vOffset, SkPaint* paint);
594    virtual void drawPosText(const char* text, int bytesCount, int count, const float* positions,
595            SkPaint* paint);
596
597    virtual void resetShader();
598    virtual void setupShader(SkiaShader* shader);
599
600    virtual void resetColorFilter();
601    virtual void setupColorFilter(SkiaColorFilter* filter);
602
603    virtual void resetShadow();
604    virtual void setupShadow(float radius, float dx, float dy, int color);
605
606    virtual void resetPaintFilter();
607    virtual void setupPaintFilter(int clearBits, int setBits);
608
609    ANDROID_API void reset();
610
611    const SkWriter32& writeStream() const {
612        return mWriter;
613    }
614
615    const Vector<SkBitmap*>& getBitmapResources() const {
616        return mBitmapResources;
617    }
618
619    const Vector<SkiaColorFilter*>& getFilterResources() const {
620        return mFilterResources;
621    }
622
623    const Vector<SkiaShader*>& getShaders() const {
624        return mShaders;
625    }
626
627    const Vector<SkPaint*>& getPaints() const {
628        return mPaints;
629    }
630
631    const Vector<SkPath*>& getPaths() const {
632        return mPaths;
633    }
634
635    const Vector<SkMatrix*>& getMatrices() const {
636        return mMatrices;
637    }
638
639private:
640    void insertRestoreToCount() {
641        if (mRestoreSaveCount >= 0) {
642            mWriter.writeInt(DisplayList::RestoreToCount);
643            addInt(mRestoreSaveCount);
644            mRestoreSaveCount = -1;
645        }
646    }
647
648    void insertTranlate() {
649        if (mHasTranslate) {
650            if (mTranslateX != 0.0f || mTranslateY != 0.0f) {
651                mWriter.writeInt(DisplayList::Translate);
652                addPoint(mTranslateX, mTranslateY);
653                mTranslateX = mTranslateY = 0.0f;
654            }
655            mHasTranslate = false;
656        }
657    }
658
659    inline void addOp(const DisplayList::Op drawOp) {
660        insertRestoreToCount();
661        insertTranlate();
662        mWriter.writeInt(drawOp);
663        mHasDrawOps = mHasDrawOps || drawOp >= DisplayList::DrawDisplayList;
664    }
665
666    uint32_t* addOp(const DisplayList::Op drawOp, const bool reject) {
667        insertRestoreToCount();
668        insertTranlate();
669        mHasDrawOps = mHasDrawOps || drawOp >= DisplayList::DrawDisplayList;
670        if (reject) {
671            mWriter.writeInt(OP_MAY_BE_SKIPPED_MASK | drawOp);
672            mWriter.writeInt(0xdeaddead);
673            mBufferSize = mWriter.size();
674            return mWriter.peek32(mBufferSize - sizeof(int32_t));
675        }
676        mWriter.writeInt(drawOp);
677        return NULL;
678    }
679
680    inline void addSkip(uint32_t* location) {
681        if (location) {
682            *location = (int32_t) (mWriter.size() - mBufferSize);
683        }
684    }
685
686    inline void addInt(int32_t value) {
687        mWriter.writeInt(value);
688    }
689
690    inline void addSize(uint32_t w, uint32_t h) {
691        mWriter.writeInt(w);
692        mWriter.writeInt(h);
693    }
694
695    void addInts(const int32_t* values, uint32_t count) {
696        mWriter.writeInt(count);
697        for (uint32_t i = 0; i < count; i++) {
698            mWriter.writeInt(values[i]);
699        }
700    }
701
702    void addUInts(const uint32_t* values, int8_t count) {
703        mWriter.writeInt(count);
704        for (int8_t i = 0; i < count; i++) {
705            mWriter.writeInt(values[i]);
706        }
707    }
708
709    inline void addFloat(float value) {
710        mWriter.writeScalar(value);
711    }
712
713    void addFloats(const float* values, int32_t count) {
714        mWriter.writeInt(count);
715        for (int32_t i = 0; i < count; i++) {
716            mWriter.writeScalar(values[i]);
717        }
718    }
719
720    inline void addPoint(float x, float y) {
721        mWriter.writeScalar(x);
722        mWriter.writeScalar(y);
723    }
724
725    inline void addBounds(float left, float top, float right, float bottom) {
726        mWriter.writeScalar(left);
727        mWriter.writeScalar(top);
728        mWriter.writeScalar(right);
729        mWriter.writeScalar(bottom);
730    }
731
732    inline void addText(const void* text, size_t byteLength) {
733        mWriter.writeInt(byteLength);
734        mWriter.writePad(text, byteLength);
735    }
736
737    inline void addPath(SkPath* path) {
738        if (!path) {
739            addInt((int) NULL);
740            return;
741        }
742
743        SkPath* pathCopy = mPathMap.valueFor(path);
744        if (pathCopy == NULL || pathCopy->getGenerationID() != path->getGenerationID()) {
745            pathCopy = new SkPath(*path);
746            pathCopy->setSourcePath(path);
747            // replaceValueFor() performs an add if the entry doesn't exist
748            mPathMap.replaceValueFor(path, pathCopy);
749            mPaths.add(pathCopy);
750        }
751
752        addInt((int) pathCopy);
753    }
754
755    inline void addPaint(SkPaint* paint) {
756        if (!paint) {
757            addInt((int) NULL);
758            return;
759        }
760
761        SkPaint* paintCopy = mPaintMap.valueFor(paint);
762        if (paintCopy == NULL || paintCopy->getGenerationID() != paint->getGenerationID()) {
763            paintCopy = new SkPaint(*paint);
764            // replaceValueFor() performs an add if the entry doesn't exist
765            mPaintMap.replaceValueFor(paint, paintCopy);
766            mPaints.add(paintCopy);
767        }
768
769        addInt((int) paintCopy);
770    }
771
772    inline void addDisplayList(DisplayList* displayList) {
773        // TODO: To be safe, the display list should be ref-counted in the
774        //       resources cache, but we rely on the caller (UI toolkit) to
775        //       do the right thing for now
776        addInt((int) displayList);
777    }
778
779    inline void addMatrix(SkMatrix* matrix) {
780        // Copying the matrix is cheap and prevents against the user changing the original
781        // matrix before the operation that uses it
782        SkMatrix* copy = new SkMatrix(*matrix);
783        addInt((int) copy);
784        mMatrices.add(copy);
785    }
786
787    inline void addBitmap(SkBitmap* bitmap) {
788        // Note that this assumes the bitmap is immutable. There are cases this won't handle
789        // correctly, such as creating the bitmap from scratch, drawing with it, changing its
790        // contents, and drawing again. The only fix would be to always copy it the first time,
791        // which doesn't seem worth the extra cycles for this unlikely case.
792        addInt((int) bitmap);
793        mBitmapResources.add(bitmap);
794        Caches::getInstance().resourceCache.incrementRefcount(bitmap);
795    }
796
797    inline void addShader(SkiaShader* shader) {
798        if (!shader) {
799            addInt((int) NULL);
800            return;
801        }
802
803        SkiaShader* shaderCopy = mShaderMap.valueFor(shader);
804        // TODO: We also need to handle generation ID changes in compose shaders
805        if (shaderCopy == NULL || shaderCopy->getGenerationId() != shader->getGenerationId()) {
806            shaderCopy = shader->copy();
807            // replaceValueFor() performs an add if the entry doesn't exist
808            mShaderMap.replaceValueFor(shader, shaderCopy);
809            mShaders.add(shaderCopy);
810            Caches::getInstance().resourceCache.incrementRefcount(shaderCopy);
811        }
812
813        addInt((int) shaderCopy);
814    }
815
816    inline void addColorFilter(SkiaColorFilter* colorFilter) {
817        addInt((int) colorFilter);
818        mFilterResources.add(colorFilter);
819        Caches::getInstance().resourceCache.incrementRefcount(colorFilter);
820    }
821
822    Vector<SkBitmap*> mBitmapResources;
823    Vector<SkiaColorFilter*> mFilterResources;
824
825    Vector<SkPaint*> mPaints;
826    DefaultKeyedVector<SkPaint*, SkPaint*> mPaintMap;
827
828    Vector<SkPath*> mPaths;
829    DefaultKeyedVector<SkPath*, SkPath*> mPathMap;
830
831    Vector<SkiaShader*> mShaders;
832    DefaultKeyedVector<SkiaShader*, SkiaShader*> mShaderMap;
833
834    Vector<SkMatrix*> mMatrices;
835
836    SkWriter32 mWriter;
837    uint32_t mBufferSize;
838
839    int mRestoreSaveCount;
840
841    float mTranslateX;
842    float mTranslateY;
843    bool mHasTranslate;
844
845    bool mHasDrawOps;
846
847    friend class DisplayList;
848
849}; // class DisplayListRenderer
850
851}; // namespace uirenderer
852}; // namespace android
853
854#endif // ANDROID_HWUI_DISPLAY_LIST_RENDERER_H
855