DisplayList.h revision 450dc7554de90026a6dd2a1ec7108c1423fce18e
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            char* lastPeriod = strrchr(name, '.');
133            if (lastPeriod) {
134                mName.setTo(lastPeriod + 1);
135            } else {
136                mName.setTo(name);
137            }
138        }
139    }
140
141    const char* getName() const {
142        return mName.string();
143    }
144
145    void setClipToBounds(bool clipToBounds) {
146        mClipToBounds = clipToBounds;
147    }
148
149    void setStaticMatrix(SkMatrix* matrix) {
150        delete mStaticMatrix;
151        mStaticMatrix = new SkMatrix(*matrix);
152    }
153
154    // Can return NULL
155    SkMatrix* getStaticMatrix() {
156        return mStaticMatrix;
157    }
158
159    void setAnimationMatrix(SkMatrix* matrix) {
160        delete mAnimationMatrix;
161        if (matrix) {
162            mAnimationMatrix = new SkMatrix(*matrix);
163        } else {
164            mAnimationMatrix = NULL;
165        }
166    }
167
168    void setAlpha(float alpha) {
169        alpha = fminf(1.0f, fmaxf(0.0f, alpha));
170        if (alpha != mAlpha) {
171            mAlpha = alpha;
172        }
173    }
174
175    float getAlpha() const {
176        return mAlpha;
177    }
178
179    void setHasOverlappingRendering(bool hasOverlappingRendering) {
180        mHasOverlappingRendering = hasOverlappingRendering;
181    }
182
183    bool hasOverlappingRendering() const {
184        return mHasOverlappingRendering;
185    }
186
187    void setTranslationX(float translationX) {
188        if (translationX != mTranslationX) {
189            mTranslationX = translationX;
190            mMatrixDirty = true;
191            if (mTranslationX == 0.0f && mTranslationY == 0.0f) {
192                mMatrixFlags &= ~TRANSLATION;
193            } else {
194                mMatrixFlags |= TRANSLATION;
195            }
196        }
197    }
198
199    float getTranslationX() const {
200        return mTranslationX;
201    }
202
203    void setTranslationY(float translationY) {
204        if (translationY != mTranslationY) {
205            mTranslationY = translationY;
206            mMatrixDirty = true;
207            if (mTranslationX == 0.0f && mTranslationY == 0.0f) {
208                mMatrixFlags &= ~TRANSLATION;
209            } else {
210                mMatrixFlags |= TRANSLATION;
211            }
212        }
213    }
214
215    float getTranslationY() const {
216        return mTranslationY;
217    }
218
219    void setRotation(float rotation) {
220        if (rotation != mRotation) {
221            mRotation = rotation;
222            mMatrixDirty = true;
223            if (mRotation == 0.0f) {
224                mMatrixFlags &= ~ROTATION;
225            } else {
226                mMatrixFlags |= ROTATION;
227            }
228        }
229    }
230
231    float getRotation() const {
232        return mRotation;
233    }
234
235    void setRotationX(float rotationX) {
236        if (rotationX != mRotationX) {
237            mRotationX = rotationX;
238            mMatrixDirty = true;
239            if (mRotationX == 0.0f && mRotationY == 0.0f) {
240                mMatrixFlags &= ~ROTATION_3D;
241            } else {
242                mMatrixFlags |= ROTATION_3D;
243            }
244        }
245    }
246
247    float getRotationX() const {
248        return mRotationX;
249    }
250
251    void setRotationY(float rotationY) {
252        if (rotationY != mRotationY) {
253            mRotationY = rotationY;
254            mMatrixDirty = true;
255            if (mRotationX == 0.0f && mRotationY == 0.0f) {
256                mMatrixFlags &= ~ROTATION_3D;
257            } else {
258                mMatrixFlags |= ROTATION_3D;
259            }
260        }
261    }
262
263    float getRotationY() const {
264        return mRotationY;
265    }
266
267    void setScaleX(float scaleX) {
268        if (scaleX != mScaleX) {
269            mScaleX = scaleX;
270            mMatrixDirty = true;
271            if (mScaleX == 1.0f && mScaleY == 1.0f) {
272                mMatrixFlags &= ~SCALE;
273            } else {
274                mMatrixFlags |= SCALE;
275            }
276        }
277    }
278
279    float getScaleX() const {
280        return mScaleX;
281    }
282
283    void setScaleY(float scaleY) {
284        if (scaleY != mScaleY) {
285            mScaleY = scaleY;
286            mMatrixDirty = true;
287            if (mScaleX == 1.0f && mScaleY == 1.0f) {
288                mMatrixFlags &= ~SCALE;
289            } else {
290                mMatrixFlags |= SCALE;
291            }
292        }
293    }
294
295    float getScaleY() const {
296        return mScaleY;
297    }
298
299    void setPivotX(float pivotX) {
300        mPivotX = pivotX;
301        mMatrixDirty = true;
302        if (mPivotX == 0.0f && mPivotY == 0.0f) {
303            mMatrixFlags &= ~PIVOT;
304        } else {
305            mMatrixFlags |= PIVOT;
306        }
307        mPivotExplicitlySet = true;
308    }
309
310    ANDROID_API float getPivotX();
311
312    void setPivotY(float pivotY) {
313        mPivotY = pivotY;
314        mMatrixDirty = true;
315        if (mPivotX == 0.0f && mPivotY == 0.0f) {
316            mMatrixFlags &= ~PIVOT;
317        } else {
318            mMatrixFlags |= PIVOT;
319        }
320        mPivotExplicitlySet = true;
321    }
322
323    ANDROID_API float getPivotY();
324
325    void setCameraDistance(float distance) {
326        if (distance != mCameraDistance) {
327            mCameraDistance = distance;
328            mMatrixDirty = true;
329            if (!mTransformCamera) {
330                mTransformCamera = new Sk3DView();
331                mTransformMatrix3D = new SkMatrix();
332            }
333            mTransformCamera->setCameraLocation(0, 0, distance);
334        }
335    }
336
337    float getCameraDistance() const {
338        return mCameraDistance;
339    }
340
341    void setLeft(int left) {
342        if (left != mLeft) {
343            mLeft = left;
344            mWidth = mRight - mLeft;
345            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
346                mMatrixDirty = true;
347            }
348        }
349    }
350
351    float getLeft() const {
352        return mLeft;
353    }
354
355    void setTop(int top) {
356        if (top != mTop) {
357            mTop = top;
358            mHeight = mBottom - mTop;
359            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
360                mMatrixDirty = true;
361            }
362        }
363    }
364
365    float getTop() const {
366        return mTop;
367    }
368
369    void setRight(int right) {
370        if (right != mRight) {
371            mRight = right;
372            mWidth = mRight - mLeft;
373            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
374                mMatrixDirty = true;
375            }
376        }
377    }
378
379    float getRight() const {
380        return mRight;
381    }
382
383    void setBottom(int bottom) {
384        if (bottom != mBottom) {
385            mBottom = bottom;
386            mHeight = mBottom - mTop;
387            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
388                mMatrixDirty = true;
389            }
390        }
391    }
392
393    float getBottom() const {
394        return mBottom;
395    }
396
397    void setLeftTop(int left, int top) {
398        if (left != mLeft || top != mTop) {
399            mLeft = left;
400            mTop = top;
401            mWidth = mRight - mLeft;
402            mHeight = mBottom - mTop;
403            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
404                mMatrixDirty = true;
405            }
406        }
407    }
408
409    void setLeftTopRightBottom(int left, int top, int right, int bottom) {
410        if (left != mLeft || top != mTop || right != mRight || bottom != mBottom) {
411            mLeft = left;
412            mTop = top;
413            mRight = right;
414            mBottom = bottom;
415            mWidth = mRight - mLeft;
416            mHeight = mBottom - mTop;
417            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
418                mMatrixDirty = true;
419            }
420        }
421    }
422
423    void offsetLeftRight(float offset) {
424        if (offset != 0) {
425            mLeft += offset;
426            mRight += offset;
427            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
428                mMatrixDirty = true;
429            }
430        }
431    }
432
433    void offsetTopBottom(float offset) {
434        if (offset != 0) {
435            mTop += offset;
436            mBottom += offset;
437            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
438                mMatrixDirty = true;
439            }
440        }
441    }
442
443    void setCaching(bool caching) {
444        mCaching = caching;
445    }
446
447    int getWidth() {
448        return mWidth;
449    }
450
451    int getHeight() {
452        return mHeight;
453    }
454
455private:
456    void outputViewProperties(const int level);
457
458    template <class T>
459    inline void setViewProperties(OpenGLRenderer& renderer, T& handler, const int level);
460
461    template <class T>
462    inline void iterate(OpenGLRenderer& renderer, T& handler, const int level);
463
464    void init();
465
466    void clearResources();
467
468    void updateMatrix();
469
470    class TextContainer {
471    public:
472        size_t length() const {
473            return mByteLength;
474        }
475
476        const char* text() const {
477            return (const char*) mText;
478        }
479
480        size_t mByteLength;
481        const char* mText;
482    };
483
484    Vector<SkBitmap*> mBitmapResources;
485    Vector<SkBitmap*> mOwnedBitmapResources;
486    Vector<SkiaColorFilter*> mFilterResources;
487
488    Vector<SkPaint*> mPaints;
489    Vector<SkPath*> mPaths;
490    SortedVector<SkPath*> mSourcePaths;
491    Vector<SkRegion*> mRegions;
492    Vector<SkMatrix*> mMatrices;
493    Vector<SkiaShader*> mShaders;
494    Vector<Layer*> mLayers;
495
496    sp<DisplayListData> mDisplayListData;
497
498    size_t mSize;
499
500    bool mIsRenderable;
501    uint32_t mFunctorCount;
502
503    String8 mName;
504
505    // View properties
506    bool mClipToBounds;
507    float mAlpha;
508    bool mHasOverlappingRendering;
509    float mTranslationX, mTranslationY;
510    float mRotation, mRotationX, mRotationY;
511    float mScaleX, mScaleY;
512    float mPivotX, mPivotY;
513    float mCameraDistance;
514    int mLeft, mTop, mRight, mBottom;
515    int mWidth, mHeight;
516    int mPrevWidth, mPrevHeight;
517    bool mPivotExplicitlySet;
518    bool mMatrixDirty;
519    bool mMatrixIsIdentity;
520    uint32_t mMatrixFlags;
521    SkMatrix* mTransformMatrix;
522    Sk3DView* mTransformCamera;
523    SkMatrix* mTransformMatrix3D;
524    SkMatrix* mStaticMatrix;
525    SkMatrix* mAnimationMatrix;
526    bool mCaching;
527
528    /**
529     * State operations - needed to defer displayList property operations (for example, when setting
530     * an alpha causes a SaveLayerAlpha to occur). These operations point into mDisplayListData's
531     * allocation, or null if uninitialized.
532     *
533     * These are initialized (via friend constructors) when a displayList is issued in either replay
534     * or deferred mode. If replaying, the ops are not used until the next frame. If deferring, the
535     * ops may be stored in the DeferredDisplayList to be played back a second time.
536     *
537     * They should be used at most once per frame (one call to iterate)
538     */
539    ClipRectOp* mClipRectOp;
540    SaveLayerOp* mSaveLayerOp;
541    SaveOp* mSaveOp;
542    RestoreToCountOp* mRestoreToCountOp;
543}; // class DisplayList
544
545}; // namespace uirenderer
546}; // namespace android
547
548#endif // ANDROID_HWUI_OPENGL_RENDERER_H
549