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