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