DisplayListRenderer.h revision b051e895ccb696604349c6c5efe7c4747e1d1ab6
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_UI_DISPLAY_LIST_RENDERER_H
18#define ANDROID_UI_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///////////////////////////////////////////////////////////////////////////////
43// Helpers
44///////////////////////////////////////////////////////////////////////////////
45
46class PathHeap: public SkRefCnt {
47public:
48    PathHeap(): mHeap(64 * sizeof(SkPath)) {
49    };
50
51    PathHeap(SkFlattenableReadBuffer& buffer): mHeap(64 * sizeof(SkPath)) {
52        int count = buffer.readS32();
53
54        mPaths.setCount(count);
55        SkPath** ptr = mPaths.begin();
56        SkPath* p = (SkPath*) mHeap.allocThrow(count * sizeof(SkPath));
57
58        for (int i = 0; i < count; i++) {
59            new (p) SkPath;
60            p->unflatten(buffer);
61            *ptr++ = p;
62            p++;
63        }
64    }
65
66    ~PathHeap() {
67        SkPath** iter = mPaths.begin();
68        SkPath** stop = mPaths.end();
69        while (iter < stop) {
70            (*iter)->~SkPath();
71            iter++;
72        }
73    }
74
75    int append(const SkPath& path) {
76        SkPath* p = (SkPath*) mHeap.allocThrow(sizeof(SkPath));
77        new (p) SkPath(path);
78        *mPaths.append() = p;
79        return mPaths.count();
80    }
81
82    int count() const { return mPaths.count(); }
83
84    SkPath& operator[](int index) const {
85        return *mPaths[index];
86    }
87
88    void flatten(SkFlattenableWriteBuffer& buffer) const {
89        int count = mPaths.count();
90
91        buffer.write32(count);
92        SkPath** iter = mPaths.begin();
93        SkPath** stop = mPaths.end();
94        while (iter < stop) {
95            (*iter)->flatten(buffer);
96            iter++;
97        }
98    }
99
100private:
101    SkChunkAlloc mHeap;
102    SkTDArray<SkPath*> mPaths;
103};
104
105///////////////////////////////////////////////////////////////////////////////
106// Display list
107///////////////////////////////////////////////////////////////////////////////
108
109class DisplayListRenderer;
110
111/**
112 * Replays recorded drawing commands.
113 */
114class DisplayList {
115public:
116    DisplayList(const DisplayListRenderer& recorder);
117    ~DisplayList();
118
119    enum Op {
120        AcquireContext,
121        ReleaseContext,
122        Save,
123        Restore,
124        RestoreToCount,
125        SaveLayer,
126        Translate,
127        Rotate,
128        Scale,
129        SetMatrix,
130        ConcatMatrix,
131        ClipRect,
132        DrawBitmap,
133        DrawBitmapMatrix,
134        DrawBitmapRect,
135        DrawPatch,
136        DrawColor,
137        DrawRect,
138        DrawPath,
139        DrawLines,
140        DrawText,
141        ResetShader,
142        SetupShader,
143        ResetColorFilter,
144        SetupColorFilter,
145        ResetShadow,
146        SetupShadow
147    };
148
149    void replay(OpenGLRenderer& renderer);
150
151private:
152    void init();
153
154    class TextContainer {
155    public:
156        size_t length() const {
157            return mByteLength;
158        }
159
160        const char* text() const {
161            return (const char*) mText;
162        }
163
164        size_t mByteLength;
165        const char* mText;
166    };
167
168    SkBitmap* getBitmap() {
169        int index = getInt();
170        return &mBitmaps[index - 1];
171    }
172
173    inline int getIndex() {
174        return mReader.readInt();
175    }
176
177    inline int getInt() {
178        return mReader.readInt();
179    }
180
181    SkMatrix* getMatrix() {
182        int index = getInt();
183        if (index == 0) {
184            return NULL;
185        }
186        return &mMatrices[index - 1];
187    }
188
189    SkPath* getPath() {
190        return &(*mPathHeap)[getInt() - 1];
191    }
192
193    SkPaint* getPaint() {
194        int index = getInt();
195        if (index == 0) {
196            return NULL;
197        }
198        return &mPaints[index - 1];
199    }
200
201    inline float getFloat() {
202        return mReader.readScalar();
203    }
204
205    int32_t* getInts(uint32_t& count) {
206        count = getInt();
207        return (int32_t*) mReader.skip(count * sizeof(int32_t));
208    }
209
210    float* getFloats(int& count) {
211        count = getInt();
212        return (float*) mReader.skip(count * sizeof(float));
213    }
214
215    void getText(TextContainer* text) {
216        size_t length = text->mByteLength = getInt();
217        text->mText = (const char*) mReader.skip(length);
218    }
219
220    PathHeap* mPathHeap;
221
222    SkBitmap* mBitmaps;
223    int mBitmapCount;
224
225    SkMatrix* mMatrices;
226    int mMatrixCount;
227
228    SkPaint* mPaints;
229    int mPaintCount;
230
231    mutable SkFlattenableReadBuffer mReader;
232
233    SkRefCntPlayback mRCPlayback;
234    SkTypefacePlayback mTFPlayback;
235};
236
237///////////////////////////////////////////////////////////////////////////////
238// Renderer
239///////////////////////////////////////////////////////////////////////////////
240
241/**
242 * Records drawing commands in a display list for latter playback.
243 */
244class DisplayListRenderer: public OpenGLRenderer {
245public:
246    DisplayListRenderer();
247    ~DisplayListRenderer();
248
249    void setViewport(int width, int height);
250    void prepare();
251
252    void acquireContext();
253    void releaseContext();
254
255    int save(int flags);
256    void restore();
257    void restoreToCount(int saveCount);
258
259    int saveLayer(float left, float top, float right, float bottom,
260            const SkPaint* p, int flags);
261
262    void translate(float dx, float dy);
263    void rotate(float degrees);
264    void scale(float sx, float sy);
265
266    void setMatrix(SkMatrix* matrix);
267    void concatMatrix(SkMatrix* matrix);
268
269    bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
270
271    void drawBitmap(SkBitmap* bitmap, float left, float top, const SkPaint* paint);
272    void drawBitmap(SkBitmap* bitmap, const SkMatrix* matrix, const SkPaint* paint);
273    void drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
274            float srcRight, float srcBottom, float dstLeft, float dstTop,
275            float dstRight, float dstBottom, const SkPaint* paint);
276    void drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
277            uint32_t width, uint32_t height, float left, float top, float right, float bottom,
278            const SkPaint* paint);
279    void drawColor(int color, SkXfermode::Mode mode);
280    void drawRect(float left, float top, float right, float bottom, const SkPaint* paint);
281    void drawPath(SkPath* path, SkPaint* paint);
282    void drawLines(float* points, int count, const SkPaint* paint);
283    void drawText(const char* text, int bytesCount, int count, float x, float y, SkPaint* paint);
284
285    void resetShader();
286    void setupShader(SkiaShader* shader);
287
288    void resetColorFilter();
289    void setupColorFilter(SkiaColorFilter* filter);
290
291    void resetShadow();
292    void setupShadow(float radius, float dx, float dy, int color);
293
294    void reset();
295
296    DisplayList* getDisplayList() const {
297        return new DisplayList(*this);
298    }
299
300    const SkWriter32& writeStream() const {
301        return mWriter;
302    }
303
304    const SkTDArray<const SkFlatBitmap*>& getBitmaps() const {
305        return mBitmaps;
306    }
307
308    const SkTDArray<const SkFlatMatrix*>& getMatrices() const {
309        return mMatrices;
310    }
311
312    const SkTDArray<const SkFlatPaint*>& getPaints() const {
313        return mPaints;
314    }
315
316private:
317    inline void addOp(DisplayList::Op drawOp) {
318        mWriter.writeInt(drawOp);
319    }
320
321    inline void addInt(int value) {
322        mWriter.writeInt(value);
323    }
324
325    void addInts(const int32_t* values, uint32_t count) {
326        mWriter.writeInt(count);
327        for (uint32_t i = 0; i < count; i++) {
328            mWriter.writeInt(values[i]);
329        }
330    }
331
332    inline void addFloat(float value) {
333        mWriter.writeScalar(value);
334    }
335
336    void addFloats(const float* values, int count) {
337        mWriter.writeInt(count);
338        for (int i = 0; i < count; i++) {
339            mWriter.writeScalar(values[i]);
340        }
341    }
342
343    inline void addPoint(float x, float y) {
344        mWriter.writeScalar(x);
345        mWriter.writeScalar(y);
346    }
347
348    inline void addBounds(float left, float top, float right, float bottom) {
349        mWriter.writeScalar(left);
350        mWriter.writeScalar(top);
351        mWriter.writeScalar(right);
352        mWriter.writeScalar(bottom);
353    }
354
355    inline void addText(const void* text, size_t byteLength) {
356        mWriter.writeInt(byteLength);
357        mWriter.writePad(text, byteLength);
358    }
359
360    inline void addPath(const SkPath* path) {
361        if (mPathHeap == NULL) {
362            mPathHeap = new PathHeap();
363        }
364        addInt(mPathHeap->append(*path));
365    }
366
367    int find(SkTDArray<const SkFlatPaint*>& paints, const SkPaint* paint);
368
369    inline void addPaint(const SkPaint* paint) {
370        addInt(find(mPaints, paint));
371    }
372
373    int find(SkTDArray<const SkFlatMatrix*>& matrices, const SkMatrix* matrix);
374
375    inline void addMatrix(const SkMatrix* matrix) {
376        addInt(find(mMatrices, matrix));
377    }
378
379    int find(SkTDArray<const SkFlatBitmap*>& bitmaps, const SkBitmap& bitmap);
380
381    inline void addBitmap(const SkBitmap* bitmap) {
382        addInt(find(mBitmaps, *bitmap));
383    }
384
385    SkChunkAlloc mHeap;
386
387    int mBitmapIndex;
388    SkTDArray<const SkFlatBitmap*> mBitmaps;
389
390    int mMatrixIndex;
391    SkTDArray<const SkFlatMatrix*> mMatrices;
392
393    int mPaintIndex;
394    SkTDArray<const SkFlatPaint*> mPaints;
395
396    PathHeap* mPathHeap;
397    SkWriter32 mWriter;
398
399    SkRefCntRecorder mRCRecorder;
400    SkRefCntRecorder mTFRecorder;
401
402    friend class DisplayList;
403
404}; // class DisplayListRenderer
405
406}; // namespace uirenderer
407}; // namespace android
408
409#endif // ANDROID_UI_DISPLAY_LIST_RENDERER_H
410