DisplayList.h revision a08f95cfeca7217f9c533b03663bf0dceedd259a
1/*
2 * Copyright (C) 2013 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_H
18#define ANDROID_HWUI_DISPLAY_LIST_H
19
20#ifndef LOG_TAG
21    #define LOG_TAG "OpenGLRenderer"
22#endif
23
24#include <SkCamera.h>
25#include <SkMatrix.h>
26
27#include <private/hwui/DrawGlInfo.h>
28
29#include <utils/RefBase.h>
30#include <utils/SortedVector.h>
31#include <utils/String8.h>
32#include <utils/Vector.h>
33#include <cutils/compiler.h>
34
35#include "utils/LinearAllocator.h"
36
37#include "Debug.h"
38
39#define TRANSLATION 0x0001
40#define ROTATION    0x0002
41#define ROTATION_3D 0x0004
42#define SCALE       0x0008
43#define PIVOT       0x0010
44
45class SkBitmap;
46class SkPaint;
47class SkPath;
48class SkRegion;
49
50namespace android {
51namespace uirenderer {
52
53class DeferredDisplayList;
54class DisplayListOp;
55class DisplayListRenderer;
56class OpenGLRenderer;
57class Rect;
58class Layer;
59class SkiaColorFilter;
60class SkiaShader;
61
62class ClipRectOp;
63class SaveLayerOp;
64class SaveOp;
65class RestoreToCountOp;
66
67struct DeferStateStruct {
68    DeferStateStruct(DeferredDisplayList& deferredList, OpenGLRenderer& renderer, int replayFlags)
69            : mDeferredList(deferredList), mRenderer(renderer), mReplayFlags(replayFlags) {}
70    DeferredDisplayList& mDeferredList;
71    OpenGLRenderer& mRenderer;
72    const int mReplayFlags;
73};
74
75struct ReplayStateStruct {
76    ReplayStateStruct(OpenGLRenderer& renderer, Rect& dirty, int replayFlags)
77            : mRenderer(renderer), mDirty(dirty), mReplayFlags(replayFlags),
78            mDrawGlStatus(DrawGlInfo::kStatusDone) {}
79    OpenGLRenderer& mRenderer;
80    Rect& mDirty;
81    const int mReplayFlags;
82    status_t mDrawGlStatus;
83};
84
85/**
86 * Refcounted structure that holds data used in display list stream
87 */
88class DisplayListData : public LightRefBase<DisplayListData> {
89public:
90    LinearAllocator allocator;
91    Vector<DisplayListOp*> displayListOps;
92};
93
94/**
95 * Replays recorded drawing commands.
96 */
97class DisplayList {
98public:
99    DisplayList(const DisplayListRenderer& recorder);
100    ANDROID_API ~DisplayList();
101
102    // See flags defined in DisplayList.java
103    enum ReplayFlag {
104        kReplayFlag_ClipChildren = 0x1
105    };
106
107
108    ANDROID_API size_t getSize();
109    ANDROID_API static void destroyDisplayListDeferred(DisplayList* displayList);
110    ANDROID_API static void outputLogBuffer(int fd);
111
112    void initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing = false);
113
114
115    void defer(DeferStateStruct& deferStruct, const int level);
116    void replay(ReplayStateStruct& replayStruct, const int level);
117
118    void output(uint32_t level = 0);
119
120    ANDROID_API void reset();
121
122    void setRenderable(bool renderable) {
123        mIsRenderable = renderable;
124    }
125
126    bool isRenderable() const {
127        return mIsRenderable;
128    }
129
130    void setName(const char* name) {
131        if (name) {
132            mName.setTo(name);
133        }
134    }
135
136    const char* getName() const {
137        return mName.string();
138    }
139
140    void setClipChildren(bool clipChildren) {
141        mClipChildren = clipChildren;
142    }
143
144    void setStaticMatrix(SkMatrix* matrix) {
145        delete mStaticMatrix;
146        mStaticMatrix = new SkMatrix(*matrix);
147    }
148
149    // Can return NULL
150    SkMatrix* getStaticMatrix() {
151        return mStaticMatrix;
152    }
153
154    void setAnimationMatrix(SkMatrix* matrix) {
155        delete mAnimationMatrix;
156        if (matrix) {
157            mAnimationMatrix = new SkMatrix(*matrix);
158        } else {
159            mAnimationMatrix = NULL;
160        }
161    }
162
163    void setAlpha(float alpha) {
164        alpha = fminf(1.0f, fmaxf(0.0f, alpha));
165        if (alpha != mAlpha) {
166            mAlpha = alpha;
167        }
168    }
169
170    float getAlpha() const {
171        return mAlpha;
172    }
173
174    void setHasOverlappingRendering(bool hasOverlappingRendering) {
175        mHasOverlappingRendering = hasOverlappingRendering;
176    }
177
178    bool hasOverlappingRendering() const {
179        return mHasOverlappingRendering;
180    }
181
182    void setTranslationX(float translationX) {
183        if (translationX != mTranslationX) {
184            mTranslationX = translationX;
185            mMatrixDirty = true;
186            if (mTranslationX == 0.0f && mTranslationY == 0.0f) {
187                mMatrixFlags &= ~TRANSLATION;
188            } else {
189                mMatrixFlags |= TRANSLATION;
190            }
191        }
192    }
193
194    float getTranslationX() const {
195        return mTranslationX;
196    }
197
198    void setTranslationY(float translationY) {
199        if (translationY != mTranslationY) {
200            mTranslationY = translationY;
201            mMatrixDirty = true;
202            if (mTranslationX == 0.0f && mTranslationY == 0.0f) {
203                mMatrixFlags &= ~TRANSLATION;
204            } else {
205                mMatrixFlags |= TRANSLATION;
206            }
207        }
208    }
209
210    float getTranslationY() const {
211        return mTranslationY;
212    }
213
214    void setRotation(float rotation) {
215        if (rotation != mRotation) {
216            mRotation = rotation;
217            mMatrixDirty = true;
218            if (mRotation == 0.0f) {
219                mMatrixFlags &= ~ROTATION;
220            } else {
221                mMatrixFlags |= ROTATION;
222            }
223        }
224    }
225
226    float getRotation() const {
227        return mRotation;
228    }
229
230    void setRotationX(float rotationX) {
231        if (rotationX != mRotationX) {
232            mRotationX = rotationX;
233            mMatrixDirty = true;
234            if (mRotationX == 0.0f && mRotationY == 0.0f) {
235                mMatrixFlags &= ~ROTATION_3D;
236            } else {
237                mMatrixFlags |= ROTATION_3D;
238            }
239        }
240    }
241
242    float getRotationX() const {
243        return mRotationX;
244    }
245
246    void setRotationY(float rotationY) {
247        if (rotationY != mRotationY) {
248            mRotationY = rotationY;
249            mMatrixDirty = true;
250            if (mRotationX == 0.0f && mRotationY == 0.0f) {
251                mMatrixFlags &= ~ROTATION_3D;
252            } else {
253                mMatrixFlags |= ROTATION_3D;
254            }
255        }
256    }
257
258    float getRotationY() const {
259        return mRotationY;
260    }
261
262    void setScaleX(float scaleX) {
263        if (scaleX != mScaleX) {
264            mScaleX = scaleX;
265            mMatrixDirty = true;
266            if (mScaleX == 1.0f && mScaleY == 1.0f) {
267                mMatrixFlags &= ~SCALE;
268            } else {
269                mMatrixFlags |= SCALE;
270            }
271        }
272    }
273
274    float getScaleX() const {
275        return mScaleX;
276    }
277
278    void setScaleY(float scaleY) {
279        if (scaleY != mScaleY) {
280            mScaleY = scaleY;
281            mMatrixDirty = true;
282            if (mScaleX == 1.0f && mScaleY == 1.0f) {
283                mMatrixFlags &= ~SCALE;
284            } else {
285                mMatrixFlags |= SCALE;
286            }
287        }
288    }
289
290    float getScaleY() const {
291        return mScaleY;
292    }
293
294    void setPivotX(float pivotX) {
295        mPivotX = pivotX;
296        mMatrixDirty = true;
297        if (mPivotX == 0.0f && mPivotY == 0.0f) {
298            mMatrixFlags &= ~PIVOT;
299        } else {
300            mMatrixFlags |= PIVOT;
301        }
302        mPivotExplicitlySet = true;
303    }
304
305    ANDROID_API float getPivotX();
306
307    void setPivotY(float pivotY) {
308        mPivotY = pivotY;
309        mMatrixDirty = true;
310        if (mPivotX == 0.0f && mPivotY == 0.0f) {
311            mMatrixFlags &= ~PIVOT;
312        } else {
313            mMatrixFlags |= PIVOT;
314        }
315        mPivotExplicitlySet = true;
316    }
317
318    ANDROID_API float getPivotY();
319
320    void setCameraDistance(float distance) {
321        if (distance != mCameraDistance) {
322            mCameraDistance = distance;
323            mMatrixDirty = true;
324            if (!mTransformCamera) {
325                mTransformCamera = new Sk3DView();
326                mTransformMatrix3D = new SkMatrix();
327            }
328            mTransformCamera->setCameraLocation(0, 0, distance);
329        }
330    }
331
332    float getCameraDistance() const {
333        return mCameraDistance;
334    }
335
336    void setLeft(int left) {
337        if (left != mLeft) {
338            mLeft = left;
339            mWidth = mRight - mLeft;
340            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
341                mMatrixDirty = true;
342            }
343        }
344    }
345
346    float getLeft() const {
347        return mLeft;
348    }
349
350    void setTop(int top) {
351        if (top != mTop) {
352            mTop = top;
353            mHeight = mBottom - mTop;
354            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
355                mMatrixDirty = true;
356            }
357        }
358    }
359
360    float getTop() const {
361        return mTop;
362    }
363
364    void setRight(int right) {
365        if (right != mRight) {
366            mRight = right;
367            mWidth = mRight - mLeft;
368            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
369                mMatrixDirty = true;
370            }
371        }
372    }
373
374    float getRight() const {
375        return mRight;
376    }
377
378    void setBottom(int bottom) {
379        if (bottom != mBottom) {
380            mBottom = bottom;
381            mHeight = mBottom - mTop;
382            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
383                mMatrixDirty = true;
384            }
385        }
386    }
387
388    float getBottom() const {
389        return mBottom;
390    }
391
392    void setLeftTop(int left, int top) {
393        if (left != mLeft || top != mTop) {
394            mLeft = left;
395            mTop = top;
396            mWidth = mRight - mLeft;
397            mHeight = mBottom - mTop;
398            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
399                mMatrixDirty = true;
400            }
401        }
402    }
403
404    void setLeftTopRightBottom(int left, int top, int right, int bottom) {
405        if (left != mLeft || top != mTop || right != mRight || bottom != mBottom) {
406            mLeft = left;
407            mTop = top;
408            mRight = right;
409            mBottom = bottom;
410            mWidth = mRight - mLeft;
411            mHeight = mBottom - mTop;
412            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
413                mMatrixDirty = true;
414            }
415        }
416    }
417
418    void offsetLeftRight(float offset) {
419        if (offset != 0) {
420            mLeft += offset;
421            mRight += offset;
422            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
423                mMatrixDirty = true;
424            }
425        }
426    }
427
428    void offsetTopBottom(float offset) {
429        if (offset != 0) {
430            mTop += offset;
431            mBottom += offset;
432            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
433                mMatrixDirty = true;
434            }
435        }
436    }
437
438    void setCaching(bool caching) {
439        mCaching = caching;
440    }
441
442    int getWidth() {
443        return mWidth;
444    }
445
446    int getHeight() {
447        return mHeight;
448    }
449
450private:
451    void outputViewProperties(const int level);
452
453    template <class T>
454    inline void setViewProperties(OpenGLRenderer& renderer, T& handler, const int level);
455
456    template <class T>
457    inline void iterate(OpenGLRenderer& renderer, T& handler, const int level);
458
459    void init();
460
461    void clearResources();
462
463    void updateMatrix();
464
465    class TextContainer {
466    public:
467        size_t length() const {
468            return mByteLength;
469        }
470
471        const char* text() const {
472            return (const char*) mText;
473        }
474
475        size_t mByteLength;
476        const char* mText;
477    };
478
479    Vector<SkBitmap*> mBitmapResources;
480    Vector<SkBitmap*> mOwnedBitmapResources;
481    Vector<SkiaColorFilter*> mFilterResources;
482
483    Vector<SkPaint*> mPaints;
484    Vector<SkPath*> mPaths;
485    SortedVector<SkPath*> mSourcePaths;
486    Vector<SkRegion*> mRegions;
487    Vector<SkMatrix*> mMatrices;
488    Vector<SkiaShader*> mShaders;
489    Vector<Layer*> mLayers;
490
491    sp<DisplayListData> mDisplayListData;
492
493    size_t mSize;
494
495    bool mIsRenderable;
496    uint32_t mFunctorCount;
497
498    String8 mName;
499
500    // View properties
501    bool mClipChildren;
502    float mAlpha;
503    bool mHasOverlappingRendering;
504    float mTranslationX, mTranslationY;
505    float mRotation, mRotationX, mRotationY;
506    float mScaleX, mScaleY;
507    float mPivotX, mPivotY;
508    float mCameraDistance;
509    int mLeft, mTop, mRight, mBottom;
510    int mWidth, mHeight;
511    int mPrevWidth, mPrevHeight;
512    bool mPivotExplicitlySet;
513    bool mMatrixDirty;
514    bool mMatrixIsIdentity;
515    uint32_t mMatrixFlags;
516    SkMatrix* mTransformMatrix;
517    Sk3DView* mTransformCamera;
518    SkMatrix* mTransformMatrix3D;
519    SkMatrix* mStaticMatrix;
520    SkMatrix* mAnimationMatrix;
521    bool mCaching;
522
523    /**
524     * State operations - needed to defer displayList property operations (for example, when setting
525     * an alpha causes a SaveLayerAlpha to occur). These operations point into mDisplayListData's
526     * allocation, or null if uninitialized.
527     *
528     * These are initialized (via friend constructors) when a displayList is issued in either replay
529     * or deferred mode. If replaying, the ops are not used until the next frame. If deferring, the
530     * ops may be stored in the DeferredDisplayList to be played back a second time.
531     *
532     * They should be used at most once per frame (one call to iterate)
533     */
534    ClipRectOp* mClipRectOp;
535    SaveLayerOp* mSaveLayerOp;
536    SaveOp* mSaveOp;
537    RestoreToCountOp* mRestoreToCountOp;
538}; // class DisplayList
539
540}; // namespace uirenderer
541}; // namespace android
542
543#endif // ANDROID_HWUI_OPENGL_RENDERER_H
544