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