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