DisplayListRenderer.h revision 27454a42de8b3c54cdd3b2b2a12446c2c10c8cb9
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    void finish();
242
243    void acquireContext();
244    void releaseContext();
245
246    int save(int flags);
247    void restore();
248    void restoreToCount(int saveCount);
249
250    int saveLayer(float left, float top, float right, float bottom,
251            SkPaint* p, int flags);
252    int saveLayerAlpha(float left, float top, float right, float bottom,
253                int alpha, int flags);
254
255    void translate(float dx, float dy);
256    void rotate(float degrees);
257    void scale(float sx, float sy);
258    void skew(float sx, float sy);
259
260    void setMatrix(SkMatrix* matrix);
261    void concatMatrix(SkMatrix* matrix);
262
263    bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
264
265    void drawDisplayList(DisplayList* displayList, uint32_t level = 0);
266    void drawLayer(Layer* layer, float x, float y, SkPaint* paint);
267    void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
268    void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
269    void drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
270            float srcRight, float srcBottom, float dstLeft, float dstTop,
271            float dstRight, float dstBottom, SkPaint* paint);
272    void drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHeight,
273            float* vertices, int* colors, SkPaint* paint);
274    void drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
275            const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors,
276            float left, float top, float right, float bottom, SkPaint* paint);
277    void drawColor(int color, SkXfermode::Mode mode);
278    void drawRect(float left, float top, float right, float bottom, SkPaint* paint);
279    void drawRoundRect(float left, float top, float right, float bottom,
280            float rx, float ry, SkPaint* paint);
281    void drawCircle(float x, float y, float radius, SkPaint* paint);
282    void drawPath(SkPath* path, SkPaint* paint);
283    void drawLines(float* points, int count, SkPaint* paint);
284    void drawText(const char* text, int bytesCount, int count, float x, float y, SkPaint* paint);
285
286    void resetShader();
287    void setupShader(SkiaShader* shader);
288
289    void resetColorFilter();
290    void setupColorFilter(SkiaColorFilter* filter);
291
292    void resetShadow();
293    void setupShadow(float radius, float dx, float dy, int color);
294
295    void reset();
296
297    const SkWriter32& writeStream() const {
298        return mWriter;
299    }
300
301    const Vector<SkBitmap*>& getBitmapResources() const {
302        return mBitmapResources;
303    }
304
305    const Vector<SkiaShader*>& getShaders() const {
306        return mShaders;
307    }
308
309    const Vector<SkPaint*>& getPaints() const {
310        return mPaints;
311    }
312
313    const Vector<SkMatrix*>& getMatrices() const {
314        return mMatrices;
315    }
316
317    const Vector<SkiaColorFilter*>& getFilterResources() const {
318        return mFilterResources;
319    }
320
321private:
322    void insertRestoreToCount() {
323        if (mRestoreSaveCount >= 0) {
324            mWriter.writeInt(DisplayList::RestoreToCount);
325            addInt(mRestoreSaveCount);
326            mRestoreSaveCount = -1;
327        }
328    }
329
330    inline void addOp(DisplayList::Op drawOp) {
331        insertRestoreToCount();
332        mWriter.writeInt(drawOp);
333    }
334
335    inline void addInt(int value) {
336        mWriter.writeInt(value);
337    }
338
339    void addInts(const int32_t* values, uint32_t count) {
340        mWriter.writeInt(count);
341        for (uint32_t i = 0; i < count; i++) {
342            mWriter.writeInt(values[i]);
343        }
344    }
345
346    void addUInts(const uint32_t* values, int8_t count) {
347        mWriter.writeInt(count);
348        for (int8_t i = 0; i < count; i++) {
349            mWriter.writeInt(values[i]);
350        }
351    }
352
353    inline void addFloat(float value) {
354        mWriter.writeScalar(value);
355    }
356
357    void addFloats(const float* values, int count) {
358        mWriter.writeInt(count);
359        for (int i = 0; i < count; i++) {
360            mWriter.writeScalar(values[i]);
361        }
362    }
363
364    inline void addPoint(float x, float y) {
365        mWriter.writeScalar(x);
366        mWriter.writeScalar(y);
367    }
368
369    inline void addBounds(float left, float top, float right, float bottom) {
370        mWriter.writeScalar(left);
371        mWriter.writeScalar(top);
372        mWriter.writeScalar(right);
373        mWriter.writeScalar(bottom);
374    }
375
376    inline void addText(const void* text, size_t byteLength) {
377        mWriter.writeInt(byteLength);
378        mWriter.writePad(text, byteLength);
379    }
380
381    inline void addPath(const SkPath* path) {
382        if (mPathHeap == NULL) {
383            mPathHeap = new PathHeap();
384        }
385        addInt(mPathHeap->append(*path));
386    }
387
388    inline void addPaint(SkPaint* paint) {
389        if (!paint) {
390            addInt((int) NULL);
391            return;
392        }
393
394        SkPaint* paintCopy =  mPaintMap.valueFor(paint);
395        if (paintCopy == NULL || paintCopy->getGenerationID() != paint->getGenerationID()) {
396            paintCopy = new SkPaint(*paint);
397            mPaintMap.add(paint, paintCopy);
398            mPaints.add(paintCopy);
399        }
400
401        addInt((int) paintCopy);
402    }
403
404    inline void addDisplayList(DisplayList* displayList) {
405        // TODO: To be safe, the display list should be ref-counted in the
406        //       resources cache, but we rely on the caller (UI toolkit) to
407        //       do the right thing for now
408        addInt((int) displayList);
409    }
410
411    inline void addMatrix(SkMatrix* matrix) {
412        // Copying the matrix is cheap and prevents against the user changing the original
413        // matrix before the operation that uses it
414        addInt((int) new SkMatrix(*matrix));
415    }
416
417    inline void addBitmap(SkBitmap* bitmap) {
418        // Note that this assumes the bitmap is immutable. There are cases this won't handle
419        // correctly, such as creating the bitmap from scratch, drawing with it, changing its
420        // contents, and drawing again. The only fix would be to always copy it the first time,
421        // which doesn't seem worth the extra cycles for this unlikely case.
422        addInt((int) bitmap);
423        mBitmapResources.add(bitmap);
424        Caches& caches = Caches::getInstance();
425        caches.resourceCache.incrementRefcount(bitmap);
426    }
427
428    inline void addShader(SkiaShader* shader) {
429        if (!shader) {
430            addInt((int) NULL);
431            return;
432        }
433
434        SkiaShader* shaderCopy = mShaderMap.valueFor(shader);
435        // TODO: We also need to handle generation ID changes in compose shaders
436        if (shaderCopy == NULL || shaderCopy->getGenerationId() != shader->getGenerationId()) {
437            shaderCopy = shader->copy();
438            mShaderMap.add(shader, shaderCopy);
439            mShaders.add(shaderCopy);
440            Caches::getInstance().resourceCache.incrementRefcount(shaderCopy);
441        }
442
443        addInt((int) shaderCopy);
444    }
445
446    inline void addColorFilter(SkiaColorFilter* colorFilter) {
447        addInt((int) colorFilter);
448        mFilterResources.add(colorFilter);
449        Caches& caches = Caches::getInstance();
450        caches.resourceCache.incrementRefcount(colorFilter);
451    }
452
453    SkChunkAlloc mHeap;
454
455    Vector<SkBitmap*> mBitmapResources;
456    Vector<SkiaColorFilter*> mFilterResources;
457
458    Vector<SkPaint*> mPaints;
459    DefaultKeyedVector<SkPaint*, SkPaint*> mPaintMap;
460
461    Vector<SkiaShader*> mShaders;
462    DefaultKeyedVector<SkiaShader*, SkiaShader*> mShaderMap;
463
464    Vector<SkMatrix*> mMatrices;
465
466    PathHeap* mPathHeap;
467    SkWriter32 mWriter;
468
469    SkRefCntRecorder mRCRecorder;
470    SkRefCntRecorder mTFRecorder;
471
472    DisplayList *mDisplayList;
473
474    int mRestoreSaveCount;
475
476    friend class DisplayList;
477
478}; // class DisplayListRenderer
479
480}; // namespace uirenderer
481}; // namespace android
482
483#endif // ANDROID_HWUI_DISPLAY_LIST_RENDERER_H
484