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/RefBase.h>
     24 #include <ui/Region.h>
     25 
     26 #include <SkCanvas.h>
     27 
     28 #include "Layer.h"
     29 #include "Matrix.h"
     30 #include "Rect.h"
     31 
     32 namespace android {
     33 namespace uirenderer {
     34 
     35 /**
     36  * A snapshot holds information about the current state of the rendering
     37  * surface. A snapshot is usually created whenever the user calls save()
     38  * and discarded when the user calls restore(). Once a snapshot is created,
     39  * it can hold information for deferred rendering.
     40  *
     41  * Each snapshot has a link to a previous snapshot, indicating the previous
     42  * state of the renderer.
     43  */
     44 class Snapshot: public LightRefBase<Snapshot> {
     45 public:
     46     Snapshot(): flags(0), previous(NULL), layer(NULL), fbo(0), invisible(false), empty(false) {
     47         transform = &mTransformRoot;
     48         clipRect = &mClipRectRoot;
     49         region = NULL;
     50     }
     51 
     52     /**
     53      * Copies the specified snapshot/ The specified snapshot is stored as
     54      * the previous snapshot.
     55      */
     56     Snapshot(const sp<Snapshot>& s, int saveFlags):
     57             flags(0), previous(s), layer(NULL), fbo(s->fbo),
     58             invisible(s->invisible), empty(false), viewport(s->viewport), height(s->height) {
     59         if (saveFlags & SkCanvas::kMatrix_SaveFlag) {
     60             mTransformRoot.load(*s->transform);
     61             transform = &mTransformRoot;
     62         } else {
     63             transform = s->transform;
     64         }
     65 
     66         if (saveFlags & SkCanvas::kClip_SaveFlag) {
     67             mClipRectRoot.set(*s->clipRect);
     68             clipRect = &mClipRectRoot;
     69         } else {
     70             clipRect = s->clipRect;
     71         }
     72 
     73         if (s->flags & Snapshot::kFlagFboTarget) {
     74             flags |= Snapshot::kFlagFboTarget;
     75             region = s->region;
     76         } else {
     77             region = NULL;
     78         }
     79     }
     80 
     81     /**
     82      * Various flags set on #flags.
     83      */
     84     enum Flags {
     85         /**
     86          * Indicates that the clip region was modified. When this
     87          * snapshot is restored so must the clip.
     88          */
     89         kFlagClipSet = 0x1,
     90         /**
     91          * Indicates that this snapshot was created when saving
     92          * a new layer.
     93          */
     94         kFlagIsLayer = 0x2,
     95         /**
     96          * Indicates that this snapshot is a special type of layer
     97          * backed by an FBO. This flag only makes sense when the
     98          * flag kFlagIsLayer is also set.
     99          */
    100         kFlagIsFboLayer = 0x4,
    101         /**
    102          * Indicates that this snapshot has changed the ortho matrix.
    103          */
    104         kFlagDirtyOrtho = 0x8,
    105         /**
    106          * Indicates that this snapshot or an ancestor snapshot is
    107          * an FBO layer.
    108          */
    109         kFlagFboTarget = 0x10
    110     };
    111 
    112     /**
    113      * Modifies the current clip with the new clip rectangle and
    114      * the specified operation. The specified rectangle is transformed
    115      * by this snapshot's trasnformation.
    116      */
    117     bool clip(float left, float top, float right, float bottom,
    118             SkRegion::Op op = SkRegion::kIntersect_Op) {
    119         Rect r(left, top, right, bottom);
    120         transform->mapRect(r);
    121         return clipTransformed(r, op);
    122     }
    123 
    124     /**
    125      * Modifies the current clip with the new clip rectangle and
    126      * the specified operation. The specified rectangle is considered
    127      * already transformed.
    128      */
    129     bool clipTransformed(const Rect& r, SkRegion::Op op = SkRegion::kIntersect_Op) {
    130         bool clipped = false;
    131 
    132         // NOTE: The unimplemented operations require support for regions
    133         // Supporting regions would require using a stencil buffer instead
    134         // of the scissor. The stencil buffer itself is not too expensive
    135         // (memory cost excluded) but on fillrate limited devices, managing
    136         // the stencil might have a negative impact on the framerate.
    137         switch (op) {
    138             case SkRegion::kDifference_Op:
    139                 break;
    140             case SkRegion::kIntersect_Op:
    141                 clipped = clipRect->intersect(r);
    142                 if (!clipped) {
    143                     clipRect->setEmpty();
    144                     clipped = true;
    145                 }
    146                 break;
    147             case SkRegion::kUnion_Op:
    148                 clipped = clipRect->unionWith(r);
    149                 break;
    150             case SkRegion::kXOR_Op:
    151                 break;
    152             case SkRegion::kReverseDifference_Op:
    153                 break;
    154             case SkRegion::kReplace_Op:
    155                 clipRect->set(r);
    156                 clipped = true;
    157                 break;
    158         }
    159 
    160         if (clipped) {
    161             flags |= Snapshot::kFlagClipSet;
    162         }
    163 
    164         return clipped;
    165     }
    166 
    167     /**
    168      * Sets the current clip.
    169      */
    170     void setClip(float left, float top, float right, float bottom) {
    171         clipRect->set(left, top, right, bottom);
    172         flags |= Snapshot::kFlagClipSet;
    173     }
    174 
    175     const Rect& getLocalClip() {
    176         mat4 inverse;
    177         inverse.loadInverse(*transform);
    178 
    179         mLocalClip.set(*clipRect);
    180         inverse.mapRect(mLocalClip);
    181 
    182         return mLocalClip;
    183     }
    184 
    185     void resetTransform(float x, float y, float z) {
    186         transform = &mTransformRoot;
    187         transform->loadTranslate(x, y, z);
    188     }
    189 
    190     void resetClip(float left, float top, float right, float bottom) {
    191         clipRect = &mClipRectRoot;
    192         clipRect->set(left, top, right, bottom);
    193         flags |= Snapshot::kFlagClipSet;
    194     }
    195 
    196     bool isIgnored() const {
    197         return invisible || empty;
    198     }
    199 
    200     /**
    201      * Dirty flags.
    202      */
    203     int flags;
    204 
    205     /**
    206      * Previous snapshot.
    207      */
    208     sp<Snapshot> previous;
    209 
    210     /**
    211      * Only set when the flag kFlagIsLayer is set.
    212      */
    213     Layer* layer;
    214 
    215     /**
    216      * Only set when the flag kFlagIsFboLayer is set.
    217      */
    218     GLuint fbo;
    219 
    220     /**
    221      * Indicates that this snapshot is invisible and nothing should be drawn
    222      * inside it. This flag is set only when the layer clips drawing to its
    223      * bounds and is passed to subsequent snapshots.
    224      */
    225     bool invisible;
    226 
    227     /**
    228      * If set to true, the layer will not be composited. This is similar to
    229      * invisible but this flag is not passed to subsequent snapshots.
    230      */
    231     bool empty;
    232 
    233     /**
    234      * Current viewport.
    235      */
    236     Rect viewport;
    237 
    238     /**
    239      * Height of the framebuffer the snapshot is rendering into.
    240      */
    241     int height;
    242 
    243     /**
    244      * Contains the previous ortho matrix.
    245      */
    246     mat4 orthoMatrix;
    247 
    248     /**
    249      * Local transformation. Holds the current translation, scale and
    250      * rotation values.
    251      */
    252     mat4* transform;
    253 
    254     /**
    255      * Current clip region. The clip is stored in canvas-space coordinates,
    256      * (screen-space coordinates in the regular case.)
    257      */
    258     Rect* clipRect;
    259 
    260     /**
    261      * The ancestor layer's dirty region.
    262      */
    263     Region* region;
    264 
    265 private:
    266     mat4 mTransformRoot;
    267     Rect mClipRectRoot;
    268     Rect mLocalClip;
    269 
    270 }; // class Snapshot
    271 
    272 }; // namespace uirenderer
    273 }; // namespace android
    274 
    275 #endif // ANDROID_HWUI_SNAPSHOT_H
    276