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