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