Home | History | Annotate | Download | only in hwui
      1 /*
      2  * Copyright (C) 2010 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_SNAPSHOT_H
     18 #define ANDROID_HWUI_SNAPSHOT_H
     19 
     20 #include <GLES2/gl2.h>
     21 #include <GLES2/gl2ext.h>
     22 
     23 #include <utils/LinearAllocator.h>
     24 #include <utils/RefBase.h>
     25 #include <ui/Region.h>
     26 
     27 #include <SkRegion.h>
     28 
     29 #include "Layer.h"
     30 #include "Matrix.h"
     31 #include "Outline.h"
     32 #include "Rect.h"
     33 #include "utils/Macros.h"
     34 
     35 namespace android {
     36 namespace uirenderer {
     37 
     38 /**
     39  * Temporary structure holding information for a single outline clip.
     40  *
     41  * These structures are treated as immutable once created, and only exist for a single frame, which
     42  * is why they may only be allocated with a LinearAllocator.
     43  */
     44 class RoundRectClipState {
     45 public:
     46     /** static void* operator new(size_t size); PURPOSELY OMITTED, allocator only **/
     47     static void* operator new(size_t size, LinearAllocator& allocator) {
     48         return allocator.alloc(size);
     49     }
     50 
     51     bool areaRequiresRoundRectClip(const Rect& rect) const {
     52         return rect.intersects(dangerRects[0])
     53                 || rect.intersects(dangerRects[1])
     54                 || rect.intersects(dangerRects[2])
     55                 || rect.intersects(dangerRects[3]);
     56     }
     57 
     58     bool highPriority;
     59     Matrix4 matrix;
     60     Rect dangerRects[4];
     61     Rect innerRect;
     62     float radius;
     63 };
     64 
     65 /**
     66  * A snapshot holds information about the current state of the rendering
     67  * surface. A snapshot is usually created whenever the user calls save()
     68  * and discarded when the user calls restore(). Once a snapshot is created,
     69  * it can hold information for deferred rendering.
     70  *
     71  * Each snapshot has a link to a previous snapshot, indicating the previous
     72  * state of the renderer.
     73  */
     74 class Snapshot: public LightRefBase<Snapshot> {
     75 public:
     76 
     77     Snapshot();
     78     Snapshot(const sp<Snapshot>& s, int saveFlags);
     79 
     80     /**
     81      * Various flags set on ::flags.
     82      */
     83     enum Flags {
     84         /**
     85          * Indicates that the clip region was modified. When this
     86          * snapshot is restored so must the clip.
     87          */
     88         kFlagClipSet = 0x1,
     89         /**
     90          * Indicates that this snapshot was created when saving
     91          * a new layer.
     92          */
     93         kFlagIsLayer = 0x2,
     94         /**
     95          * Indicates that this snapshot is a special type of layer
     96          * backed by an FBO. This flag only makes sense when the
     97          * flag kFlagIsLayer is also set.
     98          *
     99          * Viewport has been modified to fit the new Fbo, and must be
    100          * restored when this snapshot is restored.
    101          */
    102         kFlagIsFboLayer = 0x4,
    103         /**
    104          * Indicates that this snapshot or an ancestor snapshot is
    105          * an FBO layer.
    106          */
    107         kFlagFboTarget = 0x8,
    108     };
    109 
    110     /**
    111      * Modifies the current clip with the new clip rectangle and
    112      * the specified operation. The specified rectangle is transformed
    113      * by this snapshot's trasnformation.
    114      */
    115     bool clip(float left, float top, float right, float bottom,
    116             SkRegion::Op op = SkRegion::kIntersect_Op);
    117 
    118     /**
    119      * Modifies the current clip with the new clip rectangle and
    120      * the specified operation. The specified rectangle is considered
    121      * already transformed.
    122      */
    123     bool clipTransformed(const Rect& r, SkRegion::Op op = SkRegion::kIntersect_Op);
    124 
    125     /**
    126      * Modifies the current clip with the specified region and operation.
    127      * The specified region is considered already transformed.
    128      */
    129     bool clipRegionTransformed(const SkRegion& region, SkRegion::Op op);
    130 
    131     /**
    132      * Sets the current clip.
    133      */
    134     void setClip(float left, float top, float right, float bottom);
    135 
    136     /**
    137      * Returns the current clip in local coordinates. The clip rect is
    138      * transformed by the inverse transform matrix.
    139      */
    140     ANDROID_API const Rect& getLocalClip();
    141 
    142     /**
    143      * Returns the current clip in render target coordinates.
    144      */
    145     const Rect& getRenderTargetClip() { return *clipRect; }
    146 
    147     /**
    148      * Resets the clip to the specified rect.
    149      */
    150     void resetClip(float left, float top, float right, float bottom);
    151 
    152     /**
    153      * Resets the current transform to a pure 3D translation.
    154      */
    155     void resetTransform(float x, float y, float z);
    156 
    157     void initializeViewport(int width, int height) {
    158         mViewportData.initialize(width, height);
    159     }
    160 
    161     int getViewportWidth() const { return mViewportData.mWidth; }
    162     int getViewportHeight() const { return mViewportData.mHeight; }
    163     const Matrix4& getOrthoMatrix() const { return mViewportData.mOrthoMatrix; }
    164 
    165     const Vector3& getRelativeLightCenter() const { return mRelativeLightCenter; }
    166     void setRelativeLightCenter(const Vector3& lightCenter) { mRelativeLightCenter = lightCenter; }
    167 
    168     /**
    169      * Sets (and replaces) the current clipping outline
    170      *
    171      * If the current round rect clip is high priority, the incoming clip is ignored.
    172      */
    173     void setClippingRoundRect(LinearAllocator& allocator, const Rect& bounds,
    174             float radius, bool highPriority);
    175 
    176     /**
    177      * Indicates whether this snapshot should be ignored. A snapshot
    178      * is typicalled ignored if its layer is invisible or empty.
    179      */
    180     bool isIgnored() const;
    181 
    182     /**
    183      * Indicates whether the current transform has perspective components.
    184      */
    185     bool hasPerspectiveTransform() const;
    186 
    187     /**
    188      * Dirty flags.
    189      */
    190     int flags;
    191 
    192     /**
    193      * Previous snapshot.
    194      */
    195     sp<Snapshot> previous;
    196 
    197     /**
    198      * A pointer to the currently active layer.
    199      *
    200      * This snapshot does not own the layer, this pointer must not be freed.
    201      */
    202     Layer* layer;
    203 
    204     /**
    205      * Target FBO used for rendering. Set to 0 when rendering directly
    206      * into the framebuffer.
    207      */
    208     GLuint fbo;
    209 
    210     /**
    211      * Indicates that this snapshot is invisible and nothing should be drawn
    212      * inside it. This flag is set only when the layer clips drawing to its
    213      * bounds and is passed to subsequent snapshots.
    214      */
    215     bool invisible;
    216 
    217     /**
    218      * If set to true, the layer will not be composited. This is similar to
    219      * invisible but this flag is not passed to subsequent snapshots.
    220      */
    221     bool empty;
    222 
    223     /**
    224      * Local transformation. Holds the current translation, scale and
    225      * rotation values.
    226      *
    227      * This is a reference to a matrix owned by this snapshot or another
    228      *  snapshot. This pointer must not be freed. See ::mTransformRoot.
    229      */
    230     mat4* transform;
    231 
    232     /**
    233      * Current clip rect. The clip is stored in canvas-space coordinates,
    234      * (screen-space coordinates in the regular case.)
    235      *
    236      * This is a reference to a rect owned by this snapshot or another
    237      * snapshot. This pointer must not be freed. See ::mClipRectRoot.
    238      */
    239     Rect* clipRect;
    240 
    241     /**
    242      * Current clip region. The clip is stored in canvas-space coordinates,
    243      * (screen-space coordinates in the regular case.)
    244      *
    245      * This is a reference to a region owned by this snapshot or another
    246      * snapshot. This pointer must not be freed. See ::mClipRegionRoot.
    247      */
    248     SkRegion* clipRegion;
    249 
    250     /**
    251      * The ancestor layer's dirty region.
    252      *
    253      * This is a reference to a region owned by a layer. This pointer must
    254      * not be freed.
    255      */
    256     Region* region;
    257 
    258     /**
    259      * Current alpha value. This value is 1 by default, but may be set by a DisplayList which
    260      * has translucent rendering in a non-overlapping View. This value will be used by
    261      * the renderer to set the alpha in the current color being used for ensuing drawing
    262      * operations. The value is inherited by child snapshots because the same value should
    263      * be applied to descendents of the current DisplayList (for example, a TextView contains
    264      * the base alpha value which should be applied to the child DisplayLists used for drawing
    265      * the actual text).
    266      */
    267     float alpha;
    268 
    269     /**
    270      * Current clipping round rect.
    271      *
    272      * Points to data not owned by the snapshot, and may only be replaced by subsequent RR clips,
    273      * never modified.
    274      */
    275     const RoundRectClipState* roundRectClipState;
    276 
    277     void dump() const;
    278 
    279 private:
    280     struct ViewportData {
    281         ViewportData() : mWidth(0), mHeight(0) {}
    282         void initialize(int width, int height) {
    283             mWidth = width;
    284             mHeight = height;
    285             mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1);
    286         }
    287 
    288         /*
    289          * Width and height of current viewport.
    290          *
    291          * The viewport is always defined to be (0, 0, width, height).
    292          */
    293         int mWidth;
    294         int mHeight;
    295         /**
    296          * Contains the current orthographic, projection matrix.
    297          */
    298         mat4 mOrthoMatrix;
    299     };
    300 
    301     void ensureClipRegion();
    302     void copyClipRectFromRegion();
    303 
    304     bool clipRegionOp(float left, float top, float right, float bottom, SkRegion::Op op);
    305 
    306     mat4 mTransformRoot;
    307     Rect mClipRectRoot;
    308     Rect mLocalClip; // don't use directly, call getLocalClip() which initializes this
    309 
    310     SkRegion mClipRegionRoot;
    311     ViewportData mViewportData;
    312     Vector3 mRelativeLightCenter;
    313 
    314 }; // class Snapshot
    315 
    316 }; // namespace uirenderer
    317 }; // namespace android
    318 
    319 #endif // ANDROID_HWUI_SNAPSHOT_H
    320