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