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