Home | History | Annotate | Download | only in hwui
      1 /*
      2  * Copyright (C) 2015 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 #ifndef CLIPAREA_H
     17 #define CLIPAREA_H
     18 
     19 #include "Matrix.h"
     20 #include "Rect.h"
     21 #include "utils/Pair.h"
     22 
     23 #include <SkRegion.h>
     24 
     25 namespace android {
     26 namespace uirenderer {
     27 
     28 class LinearAllocator;
     29 
     30 Rect transformAndCalculateBounds(const Rect& r, const Matrix4& transform);
     31 
     32 class TransformedRectangle {
     33 public:
     34     TransformedRectangle();
     35     TransformedRectangle(const Rect& bounds, const Matrix4& transform);
     36 
     37     bool canSimplyIntersectWith(const TransformedRectangle& other) const;
     38     void intersectWith(const TransformedRectangle& other);
     39 
     40     bool isEmpty() const;
     41 
     42     const Rect& getBounds() const { return mBounds; }
     43 
     44     Rect transformedBounds() const {
     45         Rect transformedBounds(transformAndCalculateBounds(mBounds, mTransform));
     46         return transformedBounds;
     47     }
     48 
     49     const Matrix4& getTransform() const { return mTransform; }
     50 
     51     void transform(const Matrix4& transform) {
     52         Matrix4 t;
     53         t.loadMultiply(transform, mTransform);
     54         mTransform = t;
     55     }
     56 
     57 private:
     58     Rect mBounds;
     59     Matrix4 mTransform;
     60 };
     61 
     62 class RectangleList {
     63 public:
     64     RectangleList();
     65 
     66     bool isEmpty() const;
     67     int getTransformedRectanglesCount() const;
     68     const TransformedRectangle& getTransformedRectangle(int i) const;
     69 
     70     void setEmpty();
     71     void set(const Rect& bounds, const Matrix4& transform);
     72     bool intersectWith(const Rect& bounds, const Matrix4& transform);
     73     void transform(const Matrix4& transform);
     74 
     75     SkRegion convertToRegion(const SkRegion& clip) const;
     76     Rect calculateBounds() const;
     77 
     78     enum { kMaxTransformedRectangles = 5 };
     79 
     80 private:
     81     int mTransformedRectanglesCount;
     82     TransformedRectangle mTransformedRectangles[kMaxTransformedRectangles];
     83 };
     84 
     85 enum class ClipMode {
     86     Rectangle,
     87     RectangleList,
     88 
     89     // region and path - intersected. if either is empty, don't use
     90     Region
     91 };
     92 
     93 struct ClipBase {
     94     explicit ClipBase(ClipMode mode) : mode(mode) {}
     95     explicit ClipBase(const Rect& rect) : mode(ClipMode::Rectangle), rect(rect) {}
     96     const ClipMode mode;
     97     bool intersectWithRoot = false;
     98     // Bounds of the clipping area, used to define the scissor, and define which
     99     // portion of the stencil is updated/used
    100     Rect rect;
    101 
    102     void dump() const;
    103 };
    104 
    105 struct ClipRect : ClipBase {
    106     explicit ClipRect(const Rect& rect) : ClipBase(rect) {}
    107 };
    108 
    109 struct ClipRectList : ClipBase {
    110     explicit ClipRectList(const RectangleList& rectList)
    111             : ClipBase(ClipMode::RectangleList), rectList(rectList) {}
    112     RectangleList rectList;
    113 };
    114 
    115 struct ClipRegion : ClipBase {
    116     explicit ClipRegion(const SkRegion& region) : ClipBase(ClipMode::Region), region(region) {}
    117     ClipRegion() : ClipBase(ClipMode::Region) {}
    118     SkRegion region;
    119 };
    120 
    121 class ClipArea {
    122 public:
    123     ClipArea();
    124 
    125     void setViewportDimensions(int width, int height);
    126 
    127     bool isEmpty() const { return mClipRect.isEmpty(); }
    128 
    129     void setEmpty();
    130     void setClip(float left, float top, float right, float bottom);
    131     void clipRectWithTransform(const Rect& r, const mat4* transform, SkRegion::Op op);
    132     void clipPathWithTransform(const SkPath& path, const mat4* transform, SkRegion::Op op);
    133 
    134     const Rect& getClipRect() const { return mClipRect; }
    135 
    136     const SkRegion& getClipRegion() const { return mClipRegion; }
    137 
    138     const RectangleList& getRectangleList() const { return mRectangleList; }
    139 
    140     bool isRegion() const { return ClipMode::Region == mMode; }
    141 
    142     bool isSimple() const { return mMode == ClipMode::Rectangle; }
    143 
    144     bool isRectangleList() const { return mMode == ClipMode::RectangleList; }
    145 
    146     WARN_UNUSED_RESULT const ClipBase* serializeClip(LinearAllocator& allocator);
    147     WARN_UNUSED_RESULT const ClipBase* serializeIntersectedClip(
    148             LinearAllocator& allocator, const ClipBase* recordedClip,
    149             const Matrix4& recordedClipTransform);
    150     void applyClip(const ClipBase* recordedClip, const Matrix4& recordedClipTransform);
    151 
    152     static void applyTransformToRegion(const Matrix4& transform, SkRegion* region);
    153 
    154 private:
    155     void enterRectangleMode();
    156     void rectangleModeClipRectWithTransform(const Rect& r, const mat4* transform, SkRegion::Op op);
    157 
    158     void enterRectangleListMode();
    159     void rectangleListModeClipRectWithTransform(const Rect& r, const mat4* transform,
    160                                                 SkRegion::Op op);
    161 
    162     void enterRegionModeFromRectangleMode();
    163     void enterRegionModeFromRectangleListMode();
    164     void enterRegionMode();
    165     void regionModeClipRectWithTransform(const Rect& r, const mat4* transform, SkRegion::Op op);
    166 
    167     void clipRegion(const SkRegion& region, SkRegion::Op op);
    168     void ensureClipRegion();
    169     void onClipRegionUpdated();
    170 
    171     // Called by every state modifying public method.
    172     void onClipUpdated() {
    173         mPostViewportClipObserved = true;
    174         mLastSerialization = nullptr;
    175         mLastResolutionResult = nullptr;
    176     }
    177 
    178     SkRegion createViewportRegion() { return SkRegion(mViewportBounds.toSkIRect()); }
    179 
    180     void regionFromPath(const SkPath& path, SkRegion& pathAsRegion) {
    181         // TODO: this should not mask every path to the viewport - this makes it impossible to use
    182         // paths to clip to larger areas (which is valid e.g. with SkRegion::kReplace_Op)
    183         pathAsRegion.setPath(path, createViewportRegion());
    184     }
    185 
    186     ClipMode mMode;
    187     bool mPostViewportClipObserved = false;
    188     bool mReplaceOpObserved = false;
    189 
    190     /**
    191      * If mLastSerialization is non-null, it represents an already serialized copy
    192      * of the current clip state. If null, it has not been computed.
    193      */
    194     const ClipBase* mLastSerialization = nullptr;
    195 
    196     /**
    197      * This pair of pointers is a single entry cache of most recently seen
    198      */
    199     const ClipBase* mLastResolutionResult = nullptr;
    200     const ClipBase* mLastResolutionClip = nullptr;
    201     Matrix4 mLastResolutionTransform;
    202 
    203     Rect mViewportBounds;
    204     Rect mClipRect;
    205     SkRegion mClipRegion;
    206     RectangleList mRectangleList;
    207 };
    208 
    209 } /* namespace uirenderer */
    210 } /* namespace android */
    211 
    212 #endif /* CLIPAREA_H_ */
    213