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