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