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 "Snapshot.h"
21 
22 #include <SkMatrix.h>
23 #include <SkPath.h>
24 #include <SkRegion.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 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 initializeRecordingSaveStack(int viewportWidth, int viewportHeight);
84 
85     /**
86      * Initializes the first snapshot, computing the projection matrix,
87      * and stores the dimensions of the render target.
88      */
89     void initializeSaveStack(int viewportWidth, int viewportHeight,
90             float clipLeft, float clipTop, float clipRight, float clipBottom,
91             const Vector3& lightCenter);
92 
hasRectToRectTransform()93     bool hasRectToRectTransform() const {
94         return CC_LIKELY(currentTransform()->rectToRect());
95     }
96 
97     // Save (layer)
getSaveCount()98     int getSaveCount() const { return mSaveCount; }
99     int save(int flags);
100     void restore();
101     void restoreToCount(int saveCount);
102 
103     // Save/Restore without side-effects
104     int saveSnapshot(int flags);
105     void restoreSnapshot();
106 
107     // Matrix
108     void getMatrix(SkMatrix* outMatrix) const;
109     void translate(float dx, float dy, float dz = 0.0f);
110     void rotate(float degrees);
111     void scale(float sx, float sy);
112     void skew(float sx, float sy);
113 
114     void setMatrix(const SkMatrix& matrix);
115     void setMatrix(const Matrix4& matrix); // internal only convenience method
116     void concatMatrix(const SkMatrix& matrix);
117     void concatMatrix(const Matrix4& matrix); // internal only convenience method
118 
119     // Clip
getLocalClipBounds()120     const Rect& getLocalClipBounds() const { return mSnapshot->getLocalClip(); }
getRenderTargetClipBounds()121     const Rect& getRenderTargetClipBounds() const { return mSnapshot->getRenderTargetClip(); }
122 
123     bool quickRejectConservative(float left, float top, float right, float bottom) const;
124 
125     bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
126     bool clipPath(const SkPath* path, SkRegion::Op op);
127     bool clipRegion(const SkRegion* region, SkRegion::Op op);
128 
129     /**
130      * Sets a "clipping outline", which is independent from the regular clip.
131      * Currently only supports rectangles or rounded rectangles; passing in a
132      * more complicated outline fails silently. Replaces any previous clipping
133      * outline.
134      */
135     void setClippingOutline(LinearAllocator& allocator, const Outline* outline);
136     void setClippingRoundRect(LinearAllocator& allocator,
137             const Rect& rect, float radius, bool highPriority = true);
138     void setProjectionPathMask(LinearAllocator& allocator, const SkPath* path);
139 
140     /**
141      * Returns true if drawing in the rectangle (left, top, right, bottom)
142      * will be clipped out. Is conservative: might return false when subpixel-
143      * perfect tests would return true.
144      */
145     bool calculateQuickRejectForScissor(float left, float top, float right, float bottom,
146             bool* clipRequired, bool* roundRectClipRequired, bool snapOut) const;
147 
setDirtyClip(bool opaque)148     void setDirtyClip(bool opaque) { mDirtyClip = opaque; }
getDirtyClip()149     bool getDirtyClip() const { return mDirtyClip; }
150 
scaleAlpha(float alpha)151     void scaleAlpha(float alpha) { mSnapshot->alpha *= alpha; }
setEmpty(bool value)152     void setEmpty(bool value) { mSnapshot->empty = value; }
setInvisible(bool value)153     void setInvisible(bool value) { mSnapshot->invisible = value; }
154 
currentTransform()155     inline const mat4* currentTransform() const { return currentSnapshot()->transform; }
currentRenderTargetClip()156     inline const Rect& currentRenderTargetClip() const { return currentSnapshot()->getRenderTargetClip(); }
currentRegion()157     inline Region* currentRegion() const { return currentSnapshot()->region; }
currentFlags()158     inline int currentFlags() const { return currentSnapshot()->flags; }
currentLightCenter()159     const Vector3& currentLightCenter() const { return currentSnapshot()->getRelativeLightCenter(); }
currentlyIgnored()160     inline bool currentlyIgnored() const { return currentSnapshot()->isIgnored(); }
getViewportWidth()161     int getViewportWidth() const { return currentSnapshot()->getViewportWidth(); }
getViewportHeight()162     int getViewportHeight() const { return currentSnapshot()->getViewportHeight(); }
getWidth()163     int getWidth() const { return mWidth; }
getHeight()164     int getHeight() const { return mHeight; }
clipIsSimple()165     bool clipIsSimple() const { return currentSnapshot()->clipIsSimple(); }
166 
currentSnapshot()167     inline const Snapshot* currentSnapshot() const { return mSnapshot; }
writableSnapshot()168     inline Snapshot* writableSnapshot() { return mSnapshot; }
firstSnapshot()169     inline const Snapshot* firstSnapshot() const { return &mFirstSnapshot; }
170 
171 private:
172     Snapshot* allocSnapshot(Snapshot* previous, int savecount);
173     void freeSnapshot(Snapshot* snapshot);
174     void freeAllSnapshots();
175 
176     /// indicates that the clip has been changed since the last time it was consumed
177     // TODO: delete when switching to HWUI_NEW_OPS
178     bool mDirtyClip;
179 
180     /// Dimensions of the drawing surface
181     int mWidth, mHeight;
182 
183     /// Number of saved states
184     int mSaveCount;
185 
186     /// Base state
187     Snapshot mFirstSnapshot;
188 
189     /// Host providing callbacks
190     CanvasStateClient& mCanvas;
191 
192     /// Current state
193     Snapshot* mSnapshot;
194 
195     // Pool of allocated snapshots to re-use
196     // NOTE: The dtors have already been invoked!
197     Snapshot* mSnapshotPool = nullptr;
198     int mSnapshotPoolCount = 0;
199 
200 }; // class CanvasState
201 
202 }; // namespace uirenderer
203 }; // namespace android
204 
205 #endif // ANDROID_HWUI_CANVAS_STATE_H
206