DisplayList.h revision 9f68c096263b36f59c383435e587bd8bd279af34
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/KeyedVector.h>
30#include <utils/LinearAllocator.h>
31#include <utils/RefBase.h>
32#include <utils/SortedVector.h>
33#include <utils/String8.h>
34#include <utils/Vector.h>
35
36#include <cutils/compiler.h>
37
38#include <androidfw/ResourceTypes.h>
39
40#include "Debug.h"
41#include "Matrix.h"
42#include "DeferredDisplayList.h"
43
44#define TRANSLATION 0x0001
45#define ROTATION    0x0002
46#define ROTATION_3D 0x0004
47#define SCALE       0x0008
48#define PIVOT       0x0010
49
50class SkBitmap;
51class SkPaint;
52class SkPath;
53class SkRegion;
54
55namespace android {
56namespace uirenderer {
57
58class DeferredDisplayList;
59class DisplayListOp;
60class DisplayListRenderer;
61class OpenGLRenderer;
62class Rect;
63class Layer;
64class SkiaColorFilter;
65class SkiaShader;
66
67class ClipRectOp;
68class SaveLayerOp;
69class SaveOp;
70class RestoreToCountOp;
71class DrawDisplayListOp;
72
73/**
74 * Holds data used in the playback a tree of DisplayLists.
75 */
76class PlaybackStateStruct {
77protected:
78    PlaybackStateStruct(OpenGLRenderer& renderer, int replayFlags, LinearAllocator* allocator)
79            : mRenderer(renderer), mReplayFlags(replayFlags), mAllocator(allocator){}
80
81public:
82    OpenGLRenderer& mRenderer;
83    const int mReplayFlags;
84
85    // Allocator with the lifetime of a single frame.
86    // replay uses an Allocator owned by the struct, while defer shares the DeferredDisplayList's Allocator
87    LinearAllocator * const mAllocator;
88};
89
90class DeferStateStruct : public PlaybackStateStruct {
91public:
92    DeferStateStruct(DeferredDisplayList& deferredList, OpenGLRenderer& renderer, int replayFlags)
93            : PlaybackStateStruct(renderer, replayFlags, &(deferredList.mAllocator)),
94            mDeferredList(deferredList) {}
95
96    DeferredDisplayList& mDeferredList;
97};
98
99class ReplayStateStruct : public PlaybackStateStruct {
100public:
101    ReplayStateStruct(OpenGLRenderer& renderer, Rect& dirty, int replayFlags)
102            : PlaybackStateStruct(renderer, replayFlags, &mReplayAllocator),
103            mDirty(dirty), mDrawGlStatus(DrawGlInfo::kStatusDone) {}
104
105    Rect& mDirty;
106    status_t mDrawGlStatus;
107    LinearAllocator mReplayAllocator;
108};
109
110/**
111 * Refcounted structure that holds the list of commands used in display list stream.
112 */
113class DisplayListData : public LightRefBase<DisplayListData> {
114public:
115    // allocator into which all ops were allocated
116    LinearAllocator allocator;
117
118    // pointers to all ops within display list, pointing into allocator data
119    Vector<DisplayListOp*> displayListOps;
120
121    // list of children display lists for quick, non-drawing traversal
122    Vector<DrawDisplayListOp*> children;
123};
124
125/**
126 * Primary class for storing recorded canvas commands, as well as per-View/ViewGroup display properties.
127 *
128 * Recording of canvas commands is somewhat similar to SkPicture, except the canvas-recording
129 * functionality is split between DisplayListRenderer (which manages the recording), DisplayListData
130 * (which holds the actual data), and DisplayList (which holds properties and performs playback onto
131 * a renderer).
132 *
133 * Note that DisplayListData is swapped out from beneath an individual DisplayList when a view's
134 * recorded stream of canvas operations is refreshed. The DisplayList (and its properties) stay
135 * attached.
136 */
137class DisplayList {
138public:
139    DisplayList(const DisplayListRenderer& recorder);
140    ANDROID_API ~DisplayList();
141
142    // See flags defined in DisplayList.java
143    enum ReplayFlag {
144        kReplayFlag_ClipChildren = 0x1
145    };
146
147    ANDROID_API size_t getSize();
148    ANDROID_API static void destroyDisplayListDeferred(DisplayList* displayList);
149    ANDROID_API static void outputLogBuffer(int fd);
150
151    void initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing = false);
152
153    void computeOrdering();
154    void defer(DeferStateStruct& deferStruct, const int level);
155    void replay(ReplayStateStruct& replayStruct, const int level);
156
157    ANDROID_API void output(uint32_t level = 1);
158
159    ANDROID_API void reset();
160
161    void setRenderable(bool renderable) {
162        mIsRenderable = renderable;
163    }
164
165    bool isRenderable() const {
166        return mIsRenderable;
167    }
168
169    void setName(const char* name) {
170        if (name) {
171            char* lastPeriod = strrchr(name, '.');
172            if (lastPeriod) {
173                mName.setTo(lastPeriod + 1);
174            } else {
175                mName.setTo(name);
176            }
177        }
178    }
179
180    const char* getName() const {
181        return mName.string();
182    }
183
184    void setClipToBounds(bool clipToBounds) {
185        mClipToBounds = clipToBounds;
186    }
187
188    void setIsContainedVolume(bool isContainedVolume) {
189        mIsContainedVolume = isContainedVolume;
190    }
191
192    void setProjectToContainedVolume(bool shouldProject) {
193        mProjectToContainedVolume = shouldProject;
194    }
195
196    void setStaticMatrix(SkMatrix* matrix) {
197        delete mStaticMatrix;
198        mStaticMatrix = new SkMatrix(*matrix);
199    }
200
201    // Can return NULL
202    SkMatrix* getStaticMatrix() {
203        return mStaticMatrix;
204    }
205
206    void setAnimationMatrix(SkMatrix* matrix) {
207        delete mAnimationMatrix;
208        if (matrix) {
209            mAnimationMatrix = new SkMatrix(*matrix);
210        } else {
211            mAnimationMatrix = NULL;
212        }
213    }
214
215    void setAlpha(float alpha) {
216        alpha = fminf(1.0f, fmaxf(0.0f, alpha));
217        if (alpha != mAlpha) {
218            mAlpha = alpha;
219        }
220    }
221
222    float getAlpha() const {
223        return mAlpha;
224    }
225
226    void setHasOverlappingRendering(bool hasOverlappingRendering) {
227        mHasOverlappingRendering = hasOverlappingRendering;
228    }
229
230    bool hasOverlappingRendering() const {
231        return mHasOverlappingRendering;
232    }
233
234    void setTranslationX(float translationX) {
235        if (translationX != mTranslationX) {
236            mTranslationX = translationX;
237            onTranslationUpdate();
238        }
239    }
240
241    float getTranslationX() const {
242        return mTranslationX;
243    }
244
245    void setTranslationY(float translationY) {
246        if (translationY != mTranslationY) {
247            mTranslationY = translationY;
248            onTranslationUpdate();
249        }
250    }
251
252    float getTranslationY() const {
253        return mTranslationY;
254    }
255
256    void setTranslationZ(float translationZ) {
257        if (translationZ != mTranslationZ) {
258            mTranslationZ = translationZ;
259            onTranslationUpdate();
260        }
261    }
262
263    float getTranslationZ() const {
264        return mTranslationZ;
265    }
266
267    void setRotation(float rotation) {
268        if (rotation != mRotation) {
269            mRotation = rotation;
270            mMatrixDirty = true;
271            if (mRotation == 0.0f) {
272                mMatrixFlags &= ~ROTATION;
273            } else {
274                mMatrixFlags |= ROTATION;
275            }
276        }
277    }
278
279    float getRotation() const {
280        return mRotation;
281    }
282
283    void setRotationX(float rotationX) {
284        if (rotationX != mRotationX) {
285            mRotationX = rotationX;
286            mMatrixDirty = true;
287            if (mRotationX == 0.0f && mRotationY == 0.0f) {
288                mMatrixFlags &= ~ROTATION_3D;
289            } else {
290                mMatrixFlags |= ROTATION_3D;
291            }
292        }
293    }
294
295    float getRotationX() const {
296        return mRotationX;
297    }
298
299    void setRotationY(float rotationY) {
300        if (rotationY != mRotationY) {
301            mRotationY = rotationY;
302            mMatrixDirty = true;
303            if (mRotationX == 0.0f && mRotationY == 0.0f) {
304                mMatrixFlags &= ~ROTATION_3D;
305            } else {
306                mMatrixFlags |= ROTATION_3D;
307            }
308        }
309    }
310
311    float getRotationY() const {
312        return mRotationY;
313    }
314
315    void setScaleX(float scaleX) {
316        if (scaleX != mScaleX) {
317            mScaleX = scaleX;
318            mMatrixDirty = true;
319            if (mScaleX == 1.0f && mScaleY == 1.0f) {
320                mMatrixFlags &= ~SCALE;
321            } else {
322                mMatrixFlags |= SCALE;
323            }
324        }
325    }
326
327    float getScaleX() const {
328        return mScaleX;
329    }
330
331    void setScaleY(float scaleY) {
332        if (scaleY != mScaleY) {
333            mScaleY = scaleY;
334            mMatrixDirty = true;
335            if (mScaleX == 1.0f && mScaleY == 1.0f) {
336                mMatrixFlags &= ~SCALE;
337            } else {
338                mMatrixFlags |= SCALE;
339            }
340        }
341    }
342
343    float getScaleY() const {
344        return mScaleY;
345    }
346
347    void setPivotX(float pivotX) {
348        mPivotX = pivotX;
349        mMatrixDirty = true;
350        if (mPivotX == 0.0f && mPivotY == 0.0f) {
351            mMatrixFlags &= ~PIVOT;
352        } else {
353            mMatrixFlags |= PIVOT;
354        }
355        mPivotExplicitlySet = true;
356    }
357
358    ANDROID_API float getPivotX();
359
360    void setPivotY(float pivotY) {
361        mPivotY = pivotY;
362        mMatrixDirty = true;
363        if (mPivotX == 0.0f && mPivotY == 0.0f) {
364            mMatrixFlags &= ~PIVOT;
365        } else {
366            mMatrixFlags |= PIVOT;
367        }
368        mPivotExplicitlySet = true;
369    }
370
371    ANDROID_API float getPivotY();
372
373    void setCameraDistance(float distance) {
374        if (distance != mCameraDistance) {
375            mCameraDistance = distance;
376            mMatrixDirty = true;
377            if (!mTransformCamera) {
378                mTransformCamera = new Sk3DView();
379                mTransformMatrix3D = new SkMatrix();
380            }
381            mTransformCamera->setCameraLocation(0, 0, distance);
382        }
383    }
384
385    float getCameraDistance() const {
386        return mCameraDistance;
387    }
388
389    void setLeft(int left) {
390        if (left != mLeft) {
391            mLeft = left;
392            mWidth = mRight - mLeft;
393            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
394                mMatrixDirty = true;
395            }
396        }
397    }
398
399    float getLeft() const {
400        return mLeft;
401    }
402
403    void setTop(int top) {
404        if (top != mTop) {
405            mTop = top;
406            mHeight = mBottom - mTop;
407            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
408                mMatrixDirty = true;
409            }
410        }
411    }
412
413    float getTop() const {
414        return mTop;
415    }
416
417    void setRight(int right) {
418        if (right != mRight) {
419            mRight = right;
420            mWidth = mRight - mLeft;
421            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
422                mMatrixDirty = true;
423            }
424        }
425    }
426
427    float getRight() const {
428        return mRight;
429    }
430
431    void setBottom(int bottom) {
432        if (bottom != mBottom) {
433            mBottom = bottom;
434            mHeight = mBottom - mTop;
435            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
436                mMatrixDirty = true;
437            }
438        }
439    }
440
441    float getBottom() const {
442        return mBottom;
443    }
444
445    void setLeftTop(int left, int top) {
446        if (left != mLeft || top != mTop) {
447            mLeft = left;
448            mTop = top;
449            mWidth = mRight - mLeft;
450            mHeight = mBottom - mTop;
451            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
452                mMatrixDirty = true;
453            }
454        }
455    }
456
457    void setLeftTopRightBottom(int left, int top, int right, int bottom) {
458        if (left != mLeft || top != mTop || right != mRight || bottom != mBottom) {
459            mLeft = left;
460            mTop = top;
461            mRight = right;
462            mBottom = bottom;
463            mWidth = mRight - mLeft;
464            mHeight = mBottom - mTop;
465            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
466                mMatrixDirty = true;
467            }
468        }
469    }
470
471    void offsetLeftRight(float offset) {
472        if (offset != 0) {
473            mLeft += offset;
474            mRight += offset;
475            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
476                mMatrixDirty = true;
477            }
478        }
479    }
480
481    void offsetTopBottom(float offset) {
482        if (offset != 0) {
483            mTop += offset;
484            mBottom += offset;
485            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
486                mMatrixDirty = true;
487            }
488        }
489    }
490
491    void setCaching(bool caching) {
492        mCaching = caching;
493    }
494
495    int getWidth() {
496        return mWidth;
497    }
498
499    int getHeight() {
500        return mHeight;
501    }
502
503private:
504    typedef key_value_pair_t<float, DrawDisplayListOp*> ZDrawDisplayListOpPair;
505
506    enum ChildrenSelectMode {
507        kNegativeZChildren,
508        kPositiveZChildren
509    };
510
511    void onTranslationUpdate() {
512        mMatrixDirty = true;
513        if (mTranslationX == 0.0f && mTranslationY == 0.0f && mTranslationZ == 0.0f) {
514            mMatrixFlags &= ~TRANSLATION;
515        } else {
516            mMatrixFlags |= TRANSLATION;
517        }
518    }
519
520    void outputViewProperties(const int level);
521
522    void applyViewPropertyTransforms(mat4& matrix);
523
524    void computeOrderingImpl(DrawDisplayListOp* opState,
525            Vector<ZDrawDisplayListOpPair>* compositedChildrenOf3dRoot,
526            const mat4* transformFromRoot);
527
528    template <class T>
529    inline void setViewProperties(OpenGLRenderer& renderer, T& handler, const int level);
530
531    template <class T>
532    inline void iterate3dChildren(ChildrenSelectMode mode, OpenGLRenderer& renderer,
533        T& handler, const int level);
534
535    template <class T>
536    inline void iterate(OpenGLRenderer& renderer, T& handler, const int level);
537
538    void init();
539
540    void clearResources();
541
542    void updateMatrix();
543
544    class TextContainer {
545    public:
546        size_t length() const {
547            return mByteLength;
548        }
549
550        const char* text() const {
551            return (const char*) mText;
552        }
553
554        size_t mByteLength;
555        const char* mText;
556    };
557
558    Vector<const SkBitmap*> mBitmapResources;
559    Vector<const SkBitmap*> mOwnedBitmapResources;
560    Vector<SkiaColorFilter*> mFilterResources;
561    Vector<const Res_png_9patch*> mPatchResources;
562
563    Vector<const SkPaint*> mPaints;
564    Vector<const SkPath*> mPaths;
565    SortedVector<const SkPath*> mSourcePaths;
566    Vector<const SkRegion*> mRegions;
567    Vector<const SkMatrix*> mMatrices;
568    Vector<SkiaShader*> mShaders;
569    Vector<Layer*> mLayers;
570
571    sp<DisplayListData> mDisplayListData;
572
573    size_t mSize;
574
575    bool mIsRenderable;
576    uint32_t mFunctorCount;
577
578    String8 mName;
579    bool mDestroyed; // used for debugging crash, TODO: remove once invalid state crash fixed
580
581    // Rendering properties
582    bool mClipToBounds;
583    bool mIsContainedVolume;
584    bool mProjectToContainedVolume;
585    float mAlpha;
586    bool mHasOverlappingRendering;
587    float mTranslationX, mTranslationY, mTranslationZ;
588    float mRotation, mRotationX, mRotationY;
589    float mScaleX, mScaleY;
590    float mPivotX, mPivotY;
591    float mCameraDistance;
592    int mLeft, mTop, mRight, mBottom;
593    int mWidth, mHeight;
594    int mPrevWidth, mPrevHeight;
595    bool mPivotExplicitlySet;
596    bool mMatrixDirty;
597    bool mMatrixIsIdentity;
598    uint32_t mMatrixFlags;
599    SkMatrix* mTransformMatrix;
600    Sk3DView* mTransformCamera;
601    SkMatrix* mTransformMatrix3D;
602    SkMatrix* mStaticMatrix;
603    SkMatrix* mAnimationMatrix;
604    Matrix4 mTransform;
605    bool mCaching;
606
607    /**
608     * Draw time state - these properties are only set and used during rendering
609     */
610
611    // for 3d roots, contains a z sorted list of all children items
612    Vector<ZDrawDisplayListOpPair> m3dNodes;
613}; // class DisplayList
614
615}; // namespace uirenderer
616}; // namespace android
617
618#endif // ANDROID_HWUI_OPENGL_RENDERER_H
619