DisplayListRenderer.h revision ada830f639591b99c3e40de22b07296c7932a33f
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(Layer* layer, float x, float y, SkPaint* paint);
250    void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
251    void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
252    void drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
253            float srcRight, float srcBottom, float dstLeft, float dstTop,
254            float dstRight, float dstBottom, SkPaint* paint);
255    void drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
256            const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors,
257            float left, float top, float right, float bottom, SkPaint* paint);
258    void drawColor(int color, SkXfermode::Mode mode);
259    void drawRect(float left, float top, float right, float bottom, SkPaint* paint);
260    void drawPath(SkPath* path, SkPaint* paint);
261    void drawLines(float* points, int count, SkPaint* paint);
262    void drawText(const char* text, int bytesCount, int count, float x, float y, SkPaint* paint);
263
264    void resetShader();
265    void setupShader(SkiaShader* shader);
266
267    void resetColorFilter();
268    void setupColorFilter(SkiaColorFilter* filter);
269
270    void resetShadow();
271    void setupShadow(float radius, float dx, float dy, int color);
272
273    void reset();
274
275    const SkWriter32& writeStream() const {
276        return mWriter;
277    }
278
279    const Vector<SkBitmap*>& getBitmapResources() const {
280        return mBitmapResources;
281    }
282
283    const Vector<SkiaShader*>& getShaderResources() const {
284        return mShaderResources;
285    }
286
287    const Vector<SkPaint*>& getPaints() const {
288        return mPaints;
289    }
290
291    const Vector<SkMatrix*>& getMatrices() const {
292        return mMatrices;
293    }
294
295    const Vector<SkiaColorFilter*>& getFilterResources() const {
296        return mFilterResources;
297    }
298
299private:
300    inline void addOp(DisplayList::Op drawOp) {
301        mWriter.writeInt(drawOp);
302    }
303
304    inline void addInt(int value) {
305        mWriter.writeInt(value);
306    }
307
308    void addInts(const int32_t* values, uint32_t count) {
309        mWriter.writeInt(count);
310        for (uint32_t i = 0; i < count; i++) {
311            mWriter.writeInt(values[i]);
312        }
313    }
314
315    void addUInts(const uint32_t* values, int8_t count) {
316        mWriter.writeInt(count);
317        for (int8_t i = 0; i < count; i++) {
318            mWriter.writeInt(values[i]);
319        }
320    }
321
322    inline void addFloat(float value) {
323        mWriter.writeScalar(value);
324    }
325
326    void addFloats(const float* values, int count) {
327        mWriter.writeInt(count);
328        for (int i = 0; i < count; i++) {
329            mWriter.writeScalar(values[i]);
330        }
331    }
332
333    inline void addPoint(float x, float y) {
334        mWriter.writeScalar(x);
335        mWriter.writeScalar(y);
336    }
337
338    inline void addBounds(float left, float top, float right, float bottom) {
339        mWriter.writeScalar(left);
340        mWriter.writeScalar(top);
341        mWriter.writeScalar(right);
342        mWriter.writeScalar(bottom);
343    }
344
345    inline void addText(const void* text, size_t byteLength) {
346        mWriter.writeInt(byteLength);
347        mWriter.writePad(text, byteLength);
348    }
349
350    inline void addPath(const SkPath* path) {
351        if (mPathHeap == NULL) {
352            mPathHeap = new PathHeap();
353        }
354        addInt(mPathHeap->append(*path));
355    }
356
357    inline void addPaint(SkPaint* paint) {
358        if (paint == NULL) {
359            addInt((int) NULL);
360            return;
361        }
362
363        SkPaint *paintCopy =  mPaintMap.valueFor(paint);
364        if (paintCopy == NULL || paintCopy->getGenerationID() != paint->getGenerationID()) {
365            paintCopy = new SkPaint(*paint);
366            mPaintMap.add(paint, paintCopy);
367            mPaints.add(paintCopy);
368        }
369
370        addInt((int) paintCopy);
371    }
372
373    inline void addDisplayList(DisplayList* displayList) {
374        // TODO: To be safe, the display list should be ref-counted in the
375        //       resources cache, but we rely on the caller (UI toolkit) to
376        //       do the right thing for now
377        addInt((int) displayList);
378    }
379
380    inline void addMatrix(SkMatrix* matrix) {
381        // Copying the matrix is cheap and prevents against the user changing the original
382        // matrix before the operation that uses it
383        addInt((int) new SkMatrix(*matrix));
384    }
385
386    inline void addBitmap(SkBitmap* bitmap) {
387        // Note that this assumes the bitmap is immutable. There are cases this won't handle
388        // correctly, such as creating the bitmap from scratch, drawing with it, changing its
389        // contents, and drawing again. The only fix would be to always copy it the first time,
390        // which doesn't seem worth the extra cycles for this unlikely case.
391        addInt((int) bitmap);
392        mBitmapResources.add(bitmap);
393        Caches& caches = Caches::getInstance();
394        caches.resourceCache.incrementRefcount(bitmap);
395    }
396
397    inline void addShader(SkiaShader* shader) {
398        addInt((int) shader);
399        mShaderResources.add(shader);
400        Caches& caches = Caches::getInstance();
401        caches.resourceCache.incrementRefcount(shader);
402    }
403
404    inline void addColorFilter(SkiaColorFilter* colorFilter) {
405        addInt((int) colorFilter);
406        mFilterResources.add(colorFilter);
407        Caches& caches = Caches::getInstance();
408        caches.resourceCache.incrementRefcount(colorFilter);
409    }
410
411    SkChunkAlloc mHeap;
412
413    Vector<SkBitmap*> mBitmapResources;
414    Vector<SkiaShader*> mShaderResources;
415    Vector<SkiaColorFilter*> mFilterResources;
416
417    Vector<SkPaint*> mPaints;
418    DefaultKeyedVector<SkPaint*, SkPaint*> mPaintMap;
419    Vector<SkMatrix*> mMatrices;
420
421    PathHeap* mPathHeap;
422    SkWriter32 mWriter;
423
424    SkRefCntRecorder mRCRecorder;
425    SkRefCntRecorder mTFRecorder;
426
427    DisplayList *mDisplayList;
428
429    friend class DisplayList;
430
431}; // class DisplayListRenderer
432
433}; // namespace uirenderer
434}; // namespace android
435
436#endif // ANDROID_HWUI_DISPLAY_LIST_RENDERER_H
437