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