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