DisplayListRenderer.h revision 01d58e43ede5ca98cbebdd166f9b0c545032c01b
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 <SkPaint.h>
24#include <SkPath.h>
25#include <SkPictureFlat.h>
26#include <SkRefCnt.h>
27#include <SkTDArray.h>
28#include <SkTSearch.h>
29
30#include "OpenGLRenderer.h"
31
32namespace android {
33namespace uirenderer {
34
35///////////////////////////////////////////////////////////////////////////////
36// Defines
37///////////////////////////////////////////////////////////////////////////////
38
39#define MIN_WRITER_SIZE 16384
40#define HEAP_BLOCK_SIZE 4096
41
42// Debug
43#if DEBUG_DISPLAY_LIST
44    #define DISPLAY_LIST_LOGD(...) LOGD(__VA_ARGS__)
45#else
46    #define DISPLAY_LIST_LOGD(...)
47#endif
48
49///////////////////////////////////////////////////////////////////////////////
50// Helpers
51///////////////////////////////////////////////////////////////////////////////
52
53class PathHeap: public SkRefCnt {
54public:
55    PathHeap();
56    PathHeap(SkFlattenableReadBuffer& buffer);
57    ~PathHeap();
58
59    int append(const SkPath& path);
60
61    int count() const { return mPaths.count(); }
62
63    SkPath& operator[](int index) const {
64        return *mPaths[index];
65    }
66
67    void flatten(SkFlattenableWriteBuffer& buffer) const;
68
69private:
70    SkChunkAlloc mHeap;
71    SkTDArray<SkPath*> mPaths;
72};
73
74///////////////////////////////////////////////////////////////////////////////
75// Display list
76///////////////////////////////////////////////////////////////////////////////
77
78class DisplayListRenderer;
79
80/**
81 * Replays recorded drawing commands.
82 */
83class DisplayList {
84public:
85    DisplayList(const DisplayListRenderer& recorder);
86    ~DisplayList();
87
88    // IMPORTANT: Update the intialization of OP_NAMES in the .cpp file
89    //            when modifying this file
90    enum Op {
91        AcquireContext = 0,
92        ReleaseContext,
93        Save,
94        Restore,
95        RestoreToCount,
96        SaveLayer,
97        SaveLayerAlpha,
98        Translate,
99        Rotate,
100        Scale,
101        Skew,
102        SetMatrix,
103        ConcatMatrix,
104        ClipRect,
105        DrawDisplayList,
106        DrawLayer,
107        DrawBitmap,
108        DrawBitmapMatrix,
109        DrawBitmapRect,
110        DrawPatch,
111        DrawColor,
112        DrawRect,
113        DrawRoundRect,
114        DrawCircle,
115        DrawPath,
116        DrawLines,
117        DrawText,
118        ResetShader,
119        SetupShader,
120        ResetColorFilter,
121        SetupColorFilter,
122        ResetShadow,
123        SetupShadow,
124    };
125
126    static const char* OP_NAMES[];
127
128    void initFromDisplayListRenderer(const DisplayListRenderer& recorder);
129
130    void replay(OpenGLRenderer& renderer, uint32_t level = 0);
131
132private:
133    void init();
134
135    class TextContainer {
136    public:
137        size_t length() const {
138            return mByteLength;
139        }
140
141        const char* text() const {
142            return (const char*) mText;
143        }
144
145        size_t mByteLength;
146        const char* mText;
147    };
148
149    SkBitmap* getBitmap() {
150        return (SkBitmap*) getInt();
151    }
152
153    SkiaShader* getShader() {
154        return (SkiaShader*) getInt();
155    }
156
157    SkiaColorFilter* getColorFilter() {
158        return (SkiaColorFilter*) getInt();
159    }
160
161    inline int getIndex() {
162        return mReader.readInt();
163    }
164
165    inline int getInt() {
166        return mReader.readInt();
167    }
168
169    SkMatrix* getMatrix() {
170        return (SkMatrix*) getInt();
171    }
172
173    SkPath* getPath() {
174        return &(*mPathHeap)[getInt() - 1];
175    }
176
177    SkPaint* getPaint() {
178        return (SkPaint*) getInt();
179    }
180
181    DisplayList* getDisplayList() {
182        return (DisplayList*) getInt();
183    }
184
185    inline float getFloat() {
186        return mReader.readScalar();
187    }
188
189    int32_t* getInts(uint32_t& count) {
190        count = getInt();
191        return (int32_t*) mReader.skip(count * sizeof(int32_t));
192    }
193
194    uint32_t* getUInts(int8_t& count) {
195        count = getInt();
196        return (uint32_t*) mReader.skip(count * sizeof(uint32_t));
197    }
198
199    float* getFloats(int& count) {
200        count = getInt();
201        return (float*) mReader.skip(count * sizeof(float));
202    }
203
204    void getText(TextContainer* text) {
205        size_t length = text->mByteLength = getInt();
206        text->mText = (const char*) mReader.skip(length);
207    }
208
209    PathHeap* mPathHeap;
210
211    Vector<SkBitmap*> mBitmapResources;
212    Vector<SkiaColorFilter*> mFilterResources;
213
214    Vector<SkPaint*> mPaints;
215    Vector<SkMatrix*> mMatrices;
216    Vector<SkiaShader*> mShaders;
217
218    mutable SkFlattenableReadBuffer mReader;
219
220    SkRefCntPlayback mRCPlayback;
221    SkTypefacePlayback mTFPlayback;
222};
223
224///////////////////////////////////////////////////////////////////////////////
225// Renderer
226///////////////////////////////////////////////////////////////////////////////
227
228/**
229 * Records drawing commands in a display list for latter playback.
230 */
231class DisplayListRenderer: public OpenGLRenderer {
232public:
233    DisplayListRenderer();
234    ~DisplayListRenderer();
235
236    DisplayList* getDisplayList();
237
238    void setViewport(int width, int height);
239    void prepare(bool opaque);
240
241    void acquireContext();
242    void releaseContext();
243
244    int save(int flags);
245    void restore();
246    void restoreToCount(int saveCount);
247
248    int saveLayer(float left, float top, float right, float bottom,
249            SkPaint* p, int flags);
250    int saveLayerAlpha(float left, float top, float right, float bottom,
251                int alpha, int flags);
252
253    void translate(float dx, float dy);
254    void rotate(float degrees);
255    void scale(float sx, float sy);
256    void skew(float sx, float sy);
257
258    void setMatrix(SkMatrix* matrix);
259    void concatMatrix(SkMatrix* matrix);
260
261    bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
262
263    void drawDisplayList(DisplayList* displayList, uint32_t level = 0);
264    void drawLayer(Layer* layer, float x, float y, SkPaint* paint);
265    void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
266    void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
267    void drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
268            float srcRight, float srcBottom, float dstLeft, float dstTop,
269            float dstRight, float dstBottom, SkPaint* paint);
270    void drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
271            const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors,
272            float left, float top, float right, float bottom, SkPaint* paint);
273    void drawColor(int color, SkXfermode::Mode mode);
274    void drawRect(float left, float top, float right, float bottom, SkPaint* paint);
275    void drawRoundRect(float left, float top, float right, float bottom,
276            float rx, float ry, SkPaint* paint);
277    void drawCircle(float x, float y, float radius, SkPaint* paint);
278    void drawPath(SkPath* path, SkPaint* paint);
279    void drawLines(float* points, int count, SkPaint* paint);
280    void drawText(const char* text, int bytesCount, int count, float x, float y, SkPaint* paint);
281
282    void resetShader();
283    void setupShader(SkiaShader* shader);
284
285    void resetColorFilter();
286    void setupColorFilter(SkiaColorFilter* filter);
287
288    void resetShadow();
289    void setupShadow(float radius, float dx, float dy, int color);
290
291    void reset();
292
293    const SkWriter32& writeStream() const {
294        return mWriter;
295    }
296
297    const Vector<SkBitmap*>& getBitmapResources() const {
298        return mBitmapResources;
299    }
300
301    const Vector<SkiaShader*>& getShaders() const {
302        return mShaders;
303    }
304
305    const Vector<SkPaint*>& getPaints() const {
306        return mPaints;
307    }
308
309    const Vector<SkMatrix*>& getMatrices() const {
310        return mMatrices;
311    }
312
313    const Vector<SkiaColorFilter*>& getFilterResources() const {
314        return mFilterResources;
315    }
316
317private:
318    inline void addOp(DisplayList::Op drawOp) {
319        mWriter.writeInt(drawOp);
320    }
321
322    inline void addInt(int value) {
323        mWriter.writeInt(value);
324    }
325
326    void addInts(const int32_t* values, uint32_t count) {
327        mWriter.writeInt(count);
328        for (uint32_t i = 0; i < count; i++) {
329            mWriter.writeInt(values[i]);
330        }
331    }
332
333    void addUInts(const uint32_t* values, int8_t count) {
334        mWriter.writeInt(count);
335        for (int8_t i = 0; i < count; i++) {
336            mWriter.writeInt(values[i]);
337        }
338    }
339
340    inline void addFloat(float value) {
341        mWriter.writeScalar(value);
342    }
343
344    void addFloats(const float* values, int count) {
345        mWriter.writeInt(count);
346        for (int i = 0; i < count; i++) {
347            mWriter.writeScalar(values[i]);
348        }
349    }
350
351    inline void addPoint(float x, float y) {
352        mWriter.writeScalar(x);
353        mWriter.writeScalar(y);
354    }
355
356    inline void addBounds(float left, float top, float right, float bottom) {
357        mWriter.writeScalar(left);
358        mWriter.writeScalar(top);
359        mWriter.writeScalar(right);
360        mWriter.writeScalar(bottom);
361    }
362
363    inline void addText(const void* text, size_t byteLength) {
364        mWriter.writeInt(byteLength);
365        mWriter.writePad(text, byteLength);
366    }
367
368    inline void addPath(const SkPath* path) {
369        if (mPathHeap == NULL) {
370            mPathHeap = new PathHeap();
371        }
372        addInt(mPathHeap->append(*path));
373    }
374
375    inline void addPaint(SkPaint* paint) {
376        if (!paint) {
377            addInt((int) NULL);
378            return;
379        }
380
381        SkPaint* paintCopy =  mPaintMap.valueFor(paint);
382        if (paintCopy == NULL || paintCopy->getGenerationID() != paint->getGenerationID()) {
383            paintCopy = new SkPaint(*paint);
384            mPaintMap.add(paint, paintCopy);
385            mPaints.add(paintCopy);
386        }
387
388        addInt((int) paintCopy);
389    }
390
391    inline void addDisplayList(DisplayList* displayList) {
392        // TODO: To be safe, the display list should be ref-counted in the
393        //       resources cache, but we rely on the caller (UI toolkit) to
394        //       do the right thing for now
395        addInt((int) displayList);
396    }
397
398    inline void addMatrix(SkMatrix* matrix) {
399        // Copying the matrix is cheap and prevents against the user changing the original
400        // matrix before the operation that uses it
401        addInt((int) new SkMatrix(*matrix));
402    }
403
404    inline void addBitmap(SkBitmap* bitmap) {
405        // Note that this assumes the bitmap is immutable. There are cases this won't handle
406        // correctly, such as creating the bitmap from scratch, drawing with it, changing its
407        // contents, and drawing again. The only fix would be to always copy it the first time,
408        // which doesn't seem worth the extra cycles for this unlikely case.
409        addInt((int) bitmap);
410        mBitmapResources.add(bitmap);
411        Caches& caches = Caches::getInstance();
412        caches.resourceCache.incrementRefcount(bitmap);
413    }
414
415    inline void addShader(SkiaShader* shader) {
416        if (!shader) {
417            addInt((int) NULL);
418            return;
419        }
420
421        SkiaShader* shaderCopy = mShaderMap.valueFor(shader);
422        // TODO: We also need to handle generation ID changes in compose shaders
423        if (shaderCopy == NULL || shaderCopy->getGenerationId() != shader->getGenerationId()) {
424            shaderCopy = shader->copy();
425            mShaderMap.add(shader, shaderCopy);
426            mShaders.add(shaderCopy);
427            Caches::getInstance().resourceCache.incrementRefcount(shaderCopy);
428        }
429
430        addInt((int) shaderCopy);
431    }
432
433    inline void addColorFilter(SkiaColorFilter* colorFilter) {
434        addInt((int) colorFilter);
435        mFilterResources.add(colorFilter);
436        Caches& caches = Caches::getInstance();
437        caches.resourceCache.incrementRefcount(colorFilter);
438    }
439
440    SkChunkAlloc mHeap;
441
442    Vector<SkBitmap*> mBitmapResources;
443    Vector<SkiaColorFilter*> mFilterResources;
444
445    Vector<SkPaint*> mPaints;
446    DefaultKeyedVector<SkPaint*, SkPaint*> mPaintMap;
447
448    Vector<SkiaShader*> mShaders;
449    DefaultKeyedVector<SkiaShader*, SkiaShader*> mShaderMap;
450
451    Vector<SkMatrix*> mMatrices;
452
453    PathHeap* mPathHeap;
454    SkWriter32 mWriter;
455
456    SkRefCntRecorder mRCRecorder;
457    SkRefCntRecorder mTFRecorder;
458
459    DisplayList *mDisplayList;
460
461    friend class DisplayList;
462
463}; // class DisplayListRenderer
464
465}; // namespace uirenderer
466}; // namespace android
467
468#endif // ANDROID_HWUI_DISPLAY_LIST_RENDERER_H
469