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