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