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