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