Home | History | Annotate | Download | only in hwui
      1 /*
      2  * Copyright (C) 2012 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 #include "Snapshot.h"
     18 
     19 #include <SkCanvas.h>
     20 
     21 namespace android {
     22 namespace uirenderer {
     23 
     24 ///////////////////////////////////////////////////////////////////////////////
     25 // Constructors
     26 ///////////////////////////////////////////////////////////////////////////////
     27 
     28 Snapshot::Snapshot(): flags(0), previous(NULL), layer(NULL), fbo(0),
     29         invisible(false), empty(false), alpha(1.0f) {
     30 
     31     transform = &mTransformRoot;
     32     clipRect = &mClipRectRoot;
     33     region = NULL;
     34     clipRegion = NULL;
     35 }
     36 
     37 /**
     38  * Copies the specified snapshot/ The specified snapshot is stored as
     39  * the previous snapshot.
     40  */
     41 Snapshot::Snapshot(const sp<Snapshot>& s, int saveFlags):
     42         flags(0), previous(s), layer(NULL), fbo(s->fbo),
     43         invisible(s->invisible), empty(false),
     44         viewport(s->viewport), height(s->height), alpha(s->alpha) {
     45 
     46     clipRegion = NULL;
     47 
     48     if (saveFlags & SkCanvas::kMatrix_SaveFlag) {
     49         mTransformRoot.load(*s->transform);
     50         transform = &mTransformRoot;
     51     } else {
     52         transform = s->transform;
     53     }
     54 
     55     if (saveFlags & SkCanvas::kClip_SaveFlag) {
     56         mClipRectRoot.set(*s->clipRect);
     57         clipRect = &mClipRectRoot;
     58 #if STENCIL_BUFFER_SIZE
     59         if (s->clipRegion) {
     60             mClipRegionRoot.op(*s->clipRegion, SkRegion::kUnion_Op);
     61             clipRegion = &mClipRegionRoot;
     62         }
     63 #endif
     64     } else {
     65         clipRect = s->clipRect;
     66 #if STENCIL_BUFFER_SIZE
     67         clipRegion = s->clipRegion;
     68 #endif
     69     }
     70 
     71     if (s->flags & Snapshot::kFlagFboTarget) {
     72         flags |= Snapshot::kFlagFboTarget;
     73         region = s->region;
     74     } else {
     75         region = NULL;
     76     }
     77 }
     78 
     79 ///////////////////////////////////////////////////////////////////////////////
     80 // Clipping
     81 ///////////////////////////////////////////////////////////////////////////////
     82 
     83 void Snapshot::ensureClipRegion() {
     84 #if STENCIL_BUFFER_SIZE
     85     if (!clipRegion) {
     86         clipRegion = &mClipRegionRoot;
     87         clipRegion->setRect(clipRect->left, clipRect->top, clipRect->right, clipRect->bottom);
     88     }
     89 #endif
     90 }
     91 
     92 void Snapshot::copyClipRectFromRegion() {
     93 #if STENCIL_BUFFER_SIZE
     94     if (!clipRegion->isEmpty()) {
     95         const SkIRect& bounds = clipRegion->getBounds();
     96         clipRect->set(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
     97 
     98         if (clipRegion->isRect()) {
     99             clipRegion->setEmpty();
    100             clipRegion = NULL;
    101         }
    102     } else {
    103         clipRect->setEmpty();
    104         clipRegion = NULL;
    105     }
    106 #endif
    107 }
    108 
    109 bool Snapshot::clipRegionOp(float left, float top, float right, float bottom, SkRegion::Op op) {
    110 #if STENCIL_BUFFER_SIZE
    111     SkIRect tmp;
    112     tmp.set(left, top, right, bottom);
    113     clipRegion->op(tmp, op);
    114     copyClipRectFromRegion();
    115     return true;
    116 #else
    117     return false;
    118 #endif
    119 }
    120 
    121 bool Snapshot::clip(float left, float top, float right, float bottom, SkRegion::Op op) {
    122     Rect r(left, top, right, bottom);
    123     transform->mapRect(r);
    124     return clipTransformed(r, op);
    125 }
    126 
    127 bool Snapshot::clipTransformed(const Rect& r, SkRegion::Op op) {
    128     bool clipped = false;
    129 
    130     switch (op) {
    131         case SkRegion::kIntersect_Op: {
    132             if (CC_UNLIKELY(clipRegion)) {
    133                 clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, SkRegion::kIntersect_Op);
    134             } else {
    135                 clipped = clipRect->intersect(r);
    136                 if (!clipped) {
    137                     clipRect->setEmpty();
    138                     clipped = true;
    139                 }
    140             }
    141             break;
    142         }
    143         case SkRegion::kUnion_Op: {
    144             if (CC_UNLIKELY(clipRegion)) {
    145                 clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, SkRegion::kUnion_Op);
    146             } else {
    147                 clipped = clipRect->unionWith(r);
    148             }
    149             break;
    150         }
    151         case SkRegion::kReplace_Op: {
    152             setClip(r.left, r.top, r.right, r.bottom);
    153             clipped = true;
    154             break;
    155         }
    156         default: {
    157             ensureClipRegion();
    158             clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, op);
    159             break;
    160         }
    161     }
    162 
    163     if (clipped) {
    164         flags |= Snapshot::kFlagClipSet;
    165     }
    166 
    167     return clipped;
    168 }
    169 
    170 void Snapshot::setClip(float left, float top, float right, float bottom) {
    171     clipRect->set(left, top, right, bottom);
    172 #if STENCIL_BUFFER_SIZE
    173     if (clipRegion) {
    174         clipRegion->setEmpty();
    175         clipRegion = NULL;
    176     }
    177 #endif
    178     flags |= Snapshot::kFlagClipSet;
    179 }
    180 
    181 bool Snapshot::hasPerspectiveTransform() const {
    182     return transform->isPerspective();
    183 }
    184 
    185 const Rect& Snapshot::getLocalClip() {
    186     mat4 inverse;
    187     inverse.loadInverse(*transform);
    188 
    189     mLocalClip.set(*clipRect);
    190     inverse.mapRect(mLocalClip);
    191 
    192     return mLocalClip;
    193 }
    194 
    195 void Snapshot::resetClip(float left, float top, float right, float bottom) {
    196     clipRect = &mClipRectRoot;
    197     setClip(left, top, right, bottom);
    198 }
    199 
    200 ///////////////////////////////////////////////////////////////////////////////
    201 // Transforms
    202 ///////////////////////////////////////////////////////////////////////////////
    203 
    204 void Snapshot::resetTransform(float x, float y, float z) {
    205     transform = &mTransformRoot;
    206     transform->loadTranslate(x, y, z);
    207 }
    208 
    209 ///////////////////////////////////////////////////////////////////////////////
    210 // Queries
    211 ///////////////////////////////////////////////////////////////////////////////
    212 
    213 bool Snapshot::isIgnored() const {
    214     return invisible || empty;
    215 }
    216 
    217 }; // namespace uirenderer
    218 }; // namespace android
    219