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