• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #pragma once
18 
19 #include "Snapshot.h"
20 
21 #include <SkClipOp.h>
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 (e.g. FrameBuilder) 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 (e.g. RecordingCanvas) 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     explicit 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, SkClipOp op);
126     bool clipPath(const SkPath* path, SkClipOp op);
127 
128     /**
129      * Sets a "clipping outline", which is independent from the regular clip.
130      * Currently only supports rectangles or rounded rectangles; passing in a
131      * more complicated outline fails silently. Replaces any previous clipping
132      * outline.
133      */
134     void setClippingOutline(LinearAllocator& allocator, const Outline* outline);
135     void setClippingRoundRect(LinearAllocator& allocator,
136             const Rect& rect, float radius, bool highPriority = true) {
137         mSnapshot->setClippingRoundRect(allocator, rect, radius, highPriority);
138     }
setProjectionPathMask(const SkPath * path)139     void setProjectionPathMask(const SkPath* path) {
140         mSnapshot->setProjectionPathMask(path);
141     }
142 
143     /**
144      * Returns true if drawing in the rectangle (left, top, right, bottom)
145      * will be clipped out. Is conservative: might return false when subpixel-
146      * perfect tests would return true.
147      */
148     bool calculateQuickRejectForScissor(float left, float top, float right, float bottom,
149             bool* clipRequired, bool* roundRectClipRequired, bool snapOut) const;
150 
scaleAlpha(float alpha)151     void scaleAlpha(float alpha) { mSnapshot->alpha *= alpha; }
152 
currentTransform()153     inline const mat4* currentTransform() const { return currentSnapshot()->transform; }
currentRenderTargetClip()154     inline const Rect& currentRenderTargetClip() const { return currentSnapshot()->getRenderTargetClip(); }
currentFlags()155     inline int currentFlags() const { return currentSnapshot()->flags; }
currentLightCenter()156     const Vector3& currentLightCenter() const { return currentSnapshot()->getRelativeLightCenter(); }
getViewportWidth()157     int getViewportWidth() const { return currentSnapshot()->getViewportWidth(); }
getViewportHeight()158     int getViewportHeight() const { return currentSnapshot()->getViewportHeight(); }
getWidth()159     int getWidth() const { return mWidth; }
getHeight()160     int getHeight() const { return mHeight; }
clipIsSimple()161     bool clipIsSimple() const { return currentSnapshot()->clipIsSimple(); }
162 
currentSnapshot()163     inline const Snapshot* currentSnapshot() const { return mSnapshot; }
writableSnapshot()164     inline Snapshot* writableSnapshot() { return mSnapshot; }
firstSnapshot()165     inline const Snapshot* firstSnapshot() const { return &mFirstSnapshot; }
166 
167 private:
168     Snapshot* allocSnapshot(Snapshot* previous, int savecount);
169     void freeSnapshot(Snapshot* snapshot);
170     void freeAllSnapshots();
171 
172     /// Dimensions of the drawing surface
173     int mWidth, mHeight;
174 
175     /// Number of saved states
176     int mSaveCount;
177 
178     /// Base state
179     Snapshot mFirstSnapshot;
180 
181     /// Host providing callbacks
182     CanvasStateClient& mCanvas;
183 
184     /// Current state
185     Snapshot* mSnapshot;
186 
187     // Pool of allocated snapshots to re-use
188     // NOTE: The dtors have already been invoked!
189     Snapshot* mSnapshotPool = nullptr;
190     int mSnapshotPoolCount = 0;
191 
192 }; // class CanvasState
193 
194 }; // namespace uirenderer
195 }; // namespace android
196