DisplayList.h revision a2fe7affd3d077ac163da90996cb2e5e0ca3b8d1
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 setIsolatedZVolume(bool shouldIsolate) {
194        mIsolatedZVolume = shouldIsolate;
195    }
196
197    void setProjectBackwards(bool shouldProject) {
198        mProjectBackwards = shouldProject;
199    }
200
201    void setOutline(const SkPath* outline) {
202        if (!outline) {
203            mOutline.reset();
204        } else {
205            mOutline = *outline;
206        }
207    }
208
209    void setStaticMatrix(SkMatrix* matrix) {
210        delete mStaticMatrix;
211        mStaticMatrix = new SkMatrix(*matrix);
212    }
213
214    // Can return NULL
215    SkMatrix* getStaticMatrix() {
216        return mStaticMatrix;
217    }
218
219    void setAnimationMatrix(SkMatrix* matrix) {
220        delete mAnimationMatrix;
221        if (matrix) {
222            mAnimationMatrix = new SkMatrix(*matrix);
223        } else {
224            mAnimationMatrix = NULL;
225        }
226    }
227
228    void setAlpha(float alpha) {
229        alpha = fminf(1.0f, fmaxf(0.0f, alpha));
230        if (alpha != mAlpha) {
231            mAlpha = alpha;
232        }
233    }
234
235    float getAlpha() const {
236        return mAlpha;
237    }
238
239    void setHasOverlappingRendering(bool hasOverlappingRendering) {
240        mHasOverlappingRendering = hasOverlappingRendering;
241    }
242
243    bool hasOverlappingRendering() const {
244        return mHasOverlappingRendering;
245    }
246
247    void setTranslationX(float translationX) {
248        if (translationX != mTranslationX) {
249            mTranslationX = translationX;
250            onTranslationUpdate();
251        }
252    }
253
254    float getTranslationX() const {
255        return mTranslationX;
256    }
257
258    void setTranslationY(float translationY) {
259        if (translationY != mTranslationY) {
260            mTranslationY = translationY;
261            onTranslationUpdate();
262        }
263    }
264
265    float getTranslationY() const {
266        return mTranslationY;
267    }
268
269    void setTranslationZ(float translationZ) {
270        if (translationZ != mTranslationZ) {
271            mTranslationZ = translationZ;
272            onTranslationUpdate();
273        }
274    }
275
276    float getTranslationZ() const {
277        return mTranslationZ;
278    }
279
280    void setRotation(float rotation) {
281        if (rotation != mRotation) {
282            mRotation = rotation;
283            mMatrixDirty = true;
284            if (mRotation == 0.0f) {
285                mMatrixFlags &= ~ROTATION;
286            } else {
287                mMatrixFlags |= ROTATION;
288            }
289        }
290    }
291
292    float getRotation() const {
293        return mRotation;
294    }
295
296    void setRotationX(float rotationX) {
297        if (rotationX != mRotationX) {
298            mRotationX = rotationX;
299            mMatrixDirty = true;
300            if (mRotationX == 0.0f && mRotationY == 0.0f) {
301                mMatrixFlags &= ~ROTATION_3D;
302            } else {
303                mMatrixFlags |= ROTATION_3D;
304            }
305        }
306    }
307
308    float getRotationX() const {
309        return mRotationX;
310    }
311
312    void setRotationY(float rotationY) {
313        if (rotationY != mRotationY) {
314            mRotationY = rotationY;
315            mMatrixDirty = true;
316            if (mRotationX == 0.0f && mRotationY == 0.0f) {
317                mMatrixFlags &= ~ROTATION_3D;
318            } else {
319                mMatrixFlags |= ROTATION_3D;
320            }
321        }
322    }
323
324    float getRotationY() const {
325        return mRotationY;
326    }
327
328    void setScaleX(float scaleX) {
329        if (scaleX != mScaleX) {
330            mScaleX = scaleX;
331            mMatrixDirty = true;
332            if (mScaleX == 1.0f && mScaleY == 1.0f) {
333                mMatrixFlags &= ~SCALE;
334            } else {
335                mMatrixFlags |= SCALE;
336            }
337        }
338    }
339
340    float getScaleX() const {
341        return mScaleX;
342    }
343
344    void setScaleY(float scaleY) {
345        if (scaleY != mScaleY) {
346            mScaleY = scaleY;
347            mMatrixDirty = true;
348            if (mScaleX == 1.0f && mScaleY == 1.0f) {
349                mMatrixFlags &= ~SCALE;
350            } else {
351                mMatrixFlags |= SCALE;
352            }
353        }
354    }
355
356    float getScaleY() const {
357        return mScaleY;
358    }
359
360    void setPivotX(float pivotX) {
361        mPivotX = pivotX;
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 getPivotX();
372
373    void setPivotY(float pivotY) {
374        mPivotY = pivotY;
375        mMatrixDirty = true;
376        if (mPivotX == 0.0f && mPivotY == 0.0f) {
377            mMatrixFlags &= ~PIVOT;
378        } else {
379            mMatrixFlags |= PIVOT;
380        }
381        mPivotExplicitlySet = true;
382    }
383
384    ANDROID_API float getPivotY();
385
386    void setCameraDistance(float distance) {
387        if (distance != mCameraDistance) {
388            mCameraDistance = distance;
389            mMatrixDirty = true;
390            if (!mTransformCamera) {
391                mTransformCamera = new Sk3DView();
392                mTransformMatrix3D = new SkMatrix();
393            }
394            mTransformCamera->setCameraLocation(0, 0, distance);
395        }
396    }
397
398    float getCameraDistance() const {
399        return mCameraDistance;
400    }
401
402    void setLeft(int left) {
403        if (left != mLeft) {
404            mLeft = left;
405            mWidth = mRight - mLeft;
406            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
407                mMatrixDirty = true;
408            }
409        }
410    }
411
412    float getLeft() const {
413        return mLeft;
414    }
415
416    void setTop(int top) {
417        if (top != mTop) {
418            mTop = top;
419            mHeight = mBottom - mTop;
420            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
421                mMatrixDirty = true;
422            }
423        }
424    }
425
426    float getTop() const {
427        return mTop;
428    }
429
430    void setRight(int right) {
431        if (right != mRight) {
432            mRight = right;
433            mWidth = mRight - mLeft;
434            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
435                mMatrixDirty = true;
436            }
437        }
438    }
439
440    float getRight() const {
441        return mRight;
442    }
443
444    void setBottom(int bottom) {
445        if (bottom != mBottom) {
446            mBottom = bottom;
447            mHeight = mBottom - mTop;
448            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
449                mMatrixDirty = true;
450            }
451        }
452    }
453
454    float getBottom() const {
455        return mBottom;
456    }
457
458    void setLeftTop(int left, int top) {
459        if (left != mLeft || top != mTop) {
460            mLeft = left;
461            mTop = top;
462            mWidth = mRight - mLeft;
463            mHeight = mBottom - mTop;
464            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
465                mMatrixDirty = true;
466            }
467        }
468    }
469
470    void setLeftTopRightBottom(int left, int top, int right, int bottom) {
471        if (left != mLeft || top != mTop || right != mRight || bottom != mBottom) {
472            mLeft = left;
473            mTop = top;
474            mRight = right;
475            mBottom = bottom;
476            mWidth = mRight - mLeft;
477            mHeight = mBottom - mTop;
478            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
479                mMatrixDirty = true;
480            }
481        }
482    }
483
484    void offsetLeftRight(float offset) {
485        if (offset != 0) {
486            mLeft += offset;
487            mRight += offset;
488            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
489                mMatrixDirty = true;
490            }
491        }
492    }
493
494    void offsetTopBottom(float offset) {
495        if (offset != 0) {
496            mTop += offset;
497            mBottom += offset;
498            if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
499                mMatrixDirty = true;
500            }
501        }
502    }
503
504    void setCaching(bool caching) {
505        mCaching = caching;
506    }
507
508    int getWidth() {
509        return mWidth;
510    }
511
512    int getHeight() {
513        return mHeight;
514    }
515
516private:
517    typedef key_value_pair_t<float, DrawDisplayListOp*> ZDrawDisplayListOpPair;
518
519    enum ChildrenSelectMode {
520        kNegativeZChildren,
521        kPositiveZChildren
522    };
523
524    void onTranslationUpdate() {
525        mMatrixDirty = true;
526        if (mTranslationX == 0.0f && mTranslationY == 0.0f && mTranslationZ == 0.0f) {
527            mMatrixFlags &= ~TRANSLATION;
528        } else {
529            mMatrixFlags |= TRANSLATION;
530        }
531    }
532
533    void outputViewProperties(const int level);
534
535    void applyViewPropertyTransforms(mat4& matrix);
536
537    void computeOrderingImpl(DrawDisplayListOp* opState,
538            Vector<ZDrawDisplayListOpPair>* compositedChildrenOf3dRoot,
539            const mat4* transformFrom3dRoot,
540            Vector<DrawDisplayListOp*>* compositedChildrenOfProjectionSurface,
541            const mat4* transformFromProjectionSurface);
542
543    template <class T>
544    inline void setViewProperties(OpenGLRenderer& renderer, T& handler, const int level);
545
546    template <class T>
547    inline void iterate3dChildren(ChildrenSelectMode mode, OpenGLRenderer& renderer,
548        T& handler, const int level);
549
550    template <class T>
551    inline void iterateProjectedChildren(OpenGLRenderer& renderer, T& handler, const int level);
552
553    template <class T>
554    inline void iterate(OpenGLRenderer& renderer, T& handler, const int level);
555
556    void init();
557
558    void clearResources();
559
560    void updateMatrix();
561
562    class TextContainer {
563    public:
564        size_t length() const {
565            return mByteLength;
566        }
567
568        const char* text() const {
569            return (const char*) mText;
570        }
571
572        size_t mByteLength;
573        const char* mText;
574    };
575
576    Vector<const SkBitmap*> mBitmapResources;
577    Vector<const SkBitmap*> mOwnedBitmapResources;
578    Vector<SkiaColorFilter*> mFilterResources;
579    Vector<const Res_png_9patch*> mPatchResources;
580
581    Vector<const SkPaint*> mPaints;
582    Vector<const SkPath*> mPaths;
583    SortedVector<const SkPath*> mSourcePaths;
584    Vector<const SkRegion*> mRegions;
585    Vector<const SkMatrix*> mMatrices;
586    Vector<SkiaShader*> mShaders;
587    Vector<Layer*> mLayers;
588
589    sp<DisplayListData> mDisplayListData;
590
591    size_t mSize;
592
593    bool mIsRenderable;
594    uint32_t mFunctorCount;
595
596    String8 mName;
597    bool mDestroyed; // used for debugging crash, TODO: remove once invalid state crash fixed
598
599    // Rendering properties
600    bool mClipToBounds;
601    bool mIsolatedZVolume;
602    bool mProjectBackwards;
603    SkPath mOutline;
604    float mAlpha;
605    bool mHasOverlappingRendering;
606    float mTranslationX, mTranslationY, mTranslationZ;
607    float mRotation, mRotationX, mRotationY;
608    float mScaleX, mScaleY;
609    float mPivotX, mPivotY;
610    float mCameraDistance;
611    int mLeft, mTop, mRight, mBottom;
612    int mWidth, mHeight;
613    int mPrevWidth, mPrevHeight;
614    bool mPivotExplicitlySet;
615    bool mMatrixDirty;
616    bool mMatrixIsIdentity;
617    uint32_t mMatrixFlags;
618    SkMatrix* mTransformMatrix;
619    Sk3DView* mTransformCamera;
620    SkMatrix* mTransformMatrix3D;
621    SkMatrix* mStaticMatrix;
622    SkMatrix* mAnimationMatrix;
623    Matrix4 mTransform;
624    bool mCaching;
625
626    /**
627     * Draw time state - these properties are only set and used during rendering
628     */
629
630    // for 3d roots, contains a z sorted list of all children items
631    Vector<ZDrawDisplayListOpPair> m3dNodes;
632
633    // for projection surfaces, contains a list of all children items
634    Vector<DrawDisplayListOp*> mProjectedNodes;
635}; // class DisplayList
636
637}; // namespace uirenderer
638}; // namespace android
639
640#endif // ANDROID_HWUI_OPENGL_RENDERER_H
641