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