1 /*
2  * Copyright (C) 2014 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_CANVAS_STATE_H
18 #define ANDROID_HWUI_CANVAS_STATE_H
19 
20 #include <SkMatrix.h>
21 #include <SkPath.h>
22 #include <SkRegion.h>
23 
24 #include "Snapshot.h"
25 
26 namespace android {
27 namespace uirenderer {
28 
29 /**
30  * Abstract base class for any class containing CanvasState.
31  * Defines three mandatory callbacks.
32  */
33 class CanvasStateClient {
34 public:
CanvasStateClient()35     CanvasStateClient() { }
~CanvasStateClient()36     virtual ~CanvasStateClient() { }
37 
38     /**
39      * Callback allowing embedder to take actions in the middle of a
40      * setViewport() call.
41      */
42     virtual void onViewportInitialized() = 0;
43 
44     /**
45      * Callback allowing embedder to take actions in the middle of a
46      * restore() call.  May be called several times sequentially.
47      */
48     virtual void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) = 0;
49 
50     /**
51      * Allows subclasses to control what value is stored in snapshot's
52      * fbo field in * initializeSaveStack.
53      */
54     virtual GLuint getTargetFbo() const = 0;
55 
56 }; // class CanvasStateClient
57 
58 /**
59  * Implements Canvas state methods on behalf of Renderers.
60  *
61  * Manages the Snapshot stack, implementing matrix, save/restore, and clipping methods in the
62  * Renderer interface. Drawing and recording classes that include a CanvasState will have
63  * different use cases:
64  *
65  * Drawing code maintaining canvas state (i.e. OpenGLRenderer) can query attributes (such as
66  * transform) or hook into changes (e.g. save/restore) with minimal surface area for manipulating
67  * the stack itself.
68  *
69  * Recording code maintaining canvas state (i.e. DisplayListCanvas) can both record and pass
70  * through state operations to CanvasState, so that not only will querying operations work
71  * (getClip/Matrix), but so that quickRejection can also be used.
72  */
73 
74 class ANDROID_API CanvasState {
75 public:
76     CanvasState(CanvasStateClient& renderer);
77     ~CanvasState();
78 
79     /**
80      * Initializes the first snapshot, computing the projection matrix,
81      * and stores the dimensions of the render target.
82      */
83     void initializeSaveStack(float clipLeft, float clipTop, float clipRight, float clipBottom,
84             const Vector3& lightCenter);
85 
86     void setViewport(int width, int height);
87 
hasRectToRectTransform()88     bool hasRectToRectTransform() const {
89         return CC_LIKELY(currentTransform()->rectToRect());
90     }
91 
92     // Save (layer)
getSaveCount()93     int getSaveCount() const { return mSaveCount; }
94     int save(int flags);
95     void restore();
96     void restoreToCount(int saveCount);
97 
98     // Save/Restore without side-effects
99     int saveSnapshot(int flags);
100     void restoreSnapshot();
101 
102     // Matrix
103     void getMatrix(SkMatrix* outMatrix) const;
104     void translate(float dx, float dy, float dz = 0.0f);
105     void rotate(float degrees);
106     void scale(float sx, float sy);
107     void skew(float sx, float sy);
108 
109     void setMatrix(const SkMatrix& matrix);
110     void setMatrix(const Matrix4& matrix); // internal only convenience method
111     void concatMatrix(const SkMatrix& matrix);
112     void concatMatrix(const Matrix4& matrix); // internal only convenience method
113 
114     // Clip
getLocalClipBounds()115     const Rect& getLocalClipBounds() const { return mSnapshot->getLocalClip(); }
getRenderTargetClipBounds()116     const Rect& getRenderTargetClipBounds() const { return mSnapshot->getRenderTargetClip(); }
117 
118     bool quickRejectConservative(float left, float top, float right, float bottom) const;
119 
120     bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
121     bool clipPath(const SkPath* path, SkRegion::Op op);
122     bool clipRegion(const SkRegion* region, SkRegion::Op op);
123 
124     /**
125      * Sets a "clipping outline", which is independent from the regular clip.
126      * Currently only supports rectangles or rounded rectangles; passing in a
127      * more complicated outline fails silently. Replaces any previous clipping
128      * outline.
129      */
130     void setClippingOutline(LinearAllocator& allocator, const Outline* outline);
131     void setClippingRoundRect(LinearAllocator& allocator,
132             const Rect& rect, float radius, bool highPriority = true);
133     void setProjectionPathMask(LinearAllocator& allocator, const SkPath* path);
134 
135     /**
136      * Returns true if drawing in the rectangle (left, top, right, bottom)
137      * will be clipped out. Is conservative: might return false when subpixel-
138      * perfect tests would return true.
139      */
140     bool calculateQuickRejectForScissor(float left, float top, float right, float bottom,
141             bool* clipRequired, bool* roundRectClipRequired, bool snapOut) const;
142 
setDirtyClip(bool opaque)143     void setDirtyClip(bool opaque) { mDirtyClip = opaque; }
getDirtyClip()144     bool getDirtyClip() const { return mDirtyClip; }
145 
scaleAlpha(float alpha)146     void scaleAlpha(float alpha) { mSnapshot->alpha *= alpha; }
setEmpty(bool value)147     void setEmpty(bool value) { mSnapshot->empty = value; }
setInvisible(bool value)148     void setInvisible(bool value) { mSnapshot->invisible = value; }
149 
currentTransform()150     inline const mat4* currentTransform() const { return currentSnapshot()->transform; }
currentClipRect()151     inline const Rect& currentClipRect() const { return currentSnapshot()->getClipRect(); }
currentRegion()152     inline Region* currentRegion() const { return currentSnapshot()->region; }
currentFlags()153     inline int currentFlags() const { return currentSnapshot()->flags; }
currentLightCenter()154     const Vector3& currentLightCenter() const { return currentSnapshot()->getRelativeLightCenter(); }
currentlyIgnored()155     inline bool currentlyIgnored() const { return currentSnapshot()->isIgnored(); }
getViewportWidth()156     int getViewportWidth() const { return currentSnapshot()->getViewportWidth(); }
getViewportHeight()157     int getViewportHeight() const { return currentSnapshot()->getViewportHeight(); }
getWidth()158     int getWidth() const { return mWidth; }
getHeight()159     int getHeight() const { return mHeight; }
clipIsSimple()160     bool clipIsSimple() const { return currentSnapshot()->clipIsSimple(); }
161 
currentSnapshot()162     inline const Snapshot* currentSnapshot() const {
163         return mSnapshot != nullptr ? mSnapshot.get() : mFirstSnapshot.get();
164     }
writableSnapshot()165     inline Snapshot* writableSnapshot() { return mSnapshot.get(); }
firstSnapshot()166     inline const Snapshot* firstSnapshot() const { return mFirstSnapshot.get(); }
167 
168 private:
169     /// No default constructor - must supply a CanvasStateClient (mCanvas).
170     CanvasState();
171 
172     /// indicates that the clip has been changed since the last time it was consumed
173     bool mDirtyClip;
174 
175     /// Dimensions of the drawing surface
176     int mWidth, mHeight;
177 
178     /// Number of saved states
179     int mSaveCount;
180 
181     /// Base state
182     sp<Snapshot> mFirstSnapshot;
183 
184     /// Host providing callbacks
185     CanvasStateClient& mCanvas;
186 
187     /// Current state
188     sp<Snapshot> mSnapshot;
189 
190 }; // class CanvasState
191 
192 }; // namespace uirenderer
193 }; // namespace android
194 
195 #endif // ANDROID_HWUI_CANVAS_STATE_H
196