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