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