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