1 /* 2 * Copyright (C) 2010 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_SNAPSHOT_H 18 #define ANDROID_HWUI_SNAPSHOT_H 19 20 #include <GLES2/gl2.h> 21 #include <GLES2/gl2ext.h> 22 23 #include <utils/LinearAllocator.h> 24 #include <utils/RefBase.h> 25 #include <ui/Region.h> 26 27 #include <SkRegion.h> 28 29 #include "ClipArea.h" 30 #include "Layer.h" 31 #include "Matrix.h" 32 #include "Outline.h" 33 #include "Rect.h" 34 #include "utils/Macros.h" 35 36 namespace android { 37 namespace uirenderer { 38 39 /** 40 * Temporary structure holding information for a single outline clip. 41 * 42 * These structures are treated as immutable once created, and only exist for a single frame, which 43 * is why they may only be allocated with a LinearAllocator. 44 */ 45 class RoundRectClipState { 46 public: 47 static void* operator new(size_t size) = delete; new(size_t size,LinearAllocator & allocator)48 static void* operator new(size_t size, LinearAllocator& allocator) { 49 return allocator.alloc<RoundRectClipState>(size); 50 } 51 areaRequiresRoundRectClip(const Rect & rect)52 bool areaRequiresRoundRectClip(const Rect& rect) const { 53 return rect.intersects(dangerRects[0]) 54 || rect.intersects(dangerRects[1]) 55 || rect.intersects(dangerRects[2]) 56 || rect.intersects(dangerRects[3]); 57 } 58 59 bool highPriority; 60 Matrix4 matrix; 61 Rect dangerRects[4]; 62 Rect innerRect; 63 float radius; 64 }; 65 66 // TODO: remove for HWUI_NEW_OPS 67 class ProjectionPathMask { 68 public: 69 static void* operator new(size_t size) = delete; new(size_t size,LinearAllocator & allocator)70 static void* operator new(size_t size, LinearAllocator& allocator) { 71 return allocator.alloc<ProjectionPathMask>(size); 72 } 73 74 const SkPath* projectionMask; 75 Matrix4 projectionMaskTransform; 76 }; 77 78 /** 79 * A snapshot holds information about the current state of the rendering 80 * surface. A snapshot is usually created whenever the user calls save() 81 * and discarded when the user calls restore(). Once a snapshot is created, 82 * it can hold information for deferred rendering. 83 * 84 * Each snapshot has a link to a previous snapshot, indicating the previous 85 * state of the renderer. 86 */ 87 class Snapshot { 88 public: 89 90 Snapshot(); 91 Snapshot(Snapshot* s, int saveFlags); 92 93 /** 94 * Various flags set on ::flags. 95 */ 96 enum Flags { 97 /** 98 * Indicates that the clip region was modified. When this 99 * snapshot is restored so must the clip. 100 */ 101 kFlagClipSet = 0x1, 102 /** 103 * Indicates that this snapshot was created when saving 104 * a new layer. 105 */ 106 kFlagIsLayer = 0x2, 107 /** 108 * Indicates that this snapshot is a special type of layer 109 * backed by an FBO. This flag only makes sense when the 110 * flag kFlagIsLayer is also set. 111 * 112 * Viewport has been modified to fit the new Fbo, and must be 113 * restored when this snapshot is restored. 114 */ 115 kFlagIsFboLayer = 0x4, 116 /** 117 * Indicates that this snapshot or an ancestor snapshot is 118 * an FBO layer. 119 */ 120 kFlagFboTarget = 0x8, // TODO: remove for HWUI_NEW_OPS 121 }; 122 123 /** 124 * Modifies the current clip with the new clip rectangle and 125 * the specified operation. The specified rectangle is transformed 126 * by this snapshot's trasnformation. 127 */ 128 void clip(const Rect& localClip, SkRegion::Op op); 129 130 /** 131 * Modifies the current clip with the new clip rectangle and 132 * the specified operation. The specified rectangle is considered 133 * already transformed. 134 */ 135 void clipTransformed(const Rect& r, SkRegion::Op op = SkRegion::kIntersect_Op); 136 137 /** 138 * Modifies the current clip with the specified region and operation. 139 * The specified region is considered already transformed. 140 */ 141 void clipRegionTransformed(const SkRegion& region, SkRegion::Op op); 142 143 /** 144 * Modifies the current clip with the specified path and operation. 145 */ 146 void clipPath(const SkPath& path, SkRegion::Op op); 147 148 /** 149 * Sets the current clip. 150 */ 151 void setClip(float left, float top, float right, float bottom); 152 153 /** 154 * Returns the current clip in local coordinates. The clip rect is 155 * transformed by the inverse transform matrix. 156 */ 157 ANDROID_API const Rect& getLocalClip(); 158 159 /** 160 * Returns the current clip in render target coordinates. 161 */ getRenderTargetClip()162 const Rect& getRenderTargetClip() const { return mClipArea->getClipRect(); } 163 164 /* 165 * Accessor functions so that the clip area can stay private 166 */ clipIsEmpty()167 bool clipIsEmpty() const { return mClipArea->isEmpty(); } getClipRegion()168 const SkRegion& getClipRegion() const { return mClipArea->getClipRegion(); } clipIsSimple()169 bool clipIsSimple() const { return mClipArea->isSimple(); } getClipArea()170 const ClipArea& getClipArea() const { return *mClipArea; } mutateClipArea()171 ClipArea& mutateClipArea() { return *mClipArea; } 172 173 WARN_UNUSED_RESULT const ClipBase* serializeIntersectedClip(LinearAllocator& allocator, 174 const ClipBase* recordedClip, const Matrix4& recordedClipTransform); 175 void applyClip(const ClipBase* clip, const Matrix4& transform); 176 177 /** 178 * Resets the clip to the specified rect. 179 */ 180 void resetClip(float left, float top, float right, float bottom); 181 182 /** 183 * Resets the current transform to a pure 3D translation. 184 */ 185 void resetTransform(float x, float y, float z); 186 initializeViewport(int width,int height)187 void initializeViewport(int width, int height) { 188 mViewportData.initialize(width, height); 189 mClipAreaRoot.setViewportDimensions(width, height); 190 } 191 getViewportWidth()192 int getViewportWidth() const { return mViewportData.mWidth; } getViewportHeight()193 int getViewportHeight() const { return mViewportData.mHeight; } getOrthoMatrix()194 const Matrix4& getOrthoMatrix() const { return mViewportData.mOrthoMatrix; } 195 getRelativeLightCenter()196 const Vector3& getRelativeLightCenter() const { return mRelativeLightCenter; } setRelativeLightCenter(const Vector3 & lightCenter)197 void setRelativeLightCenter(const Vector3& lightCenter) { mRelativeLightCenter = lightCenter; } 198 199 /** 200 * Sets (and replaces) the current clipping outline 201 * 202 * If the current round rect clip is high priority, the incoming clip is ignored. 203 */ 204 void setClippingRoundRect(LinearAllocator& allocator, const Rect& bounds, 205 float radius, bool highPriority); 206 207 /** 208 * Sets (and replaces) the current projection mask 209 */ 210 void setProjectionPathMask(LinearAllocator& allocator, const SkPath* path); 211 212 /** 213 * Indicates whether this snapshot should be ignored. A snapshot 214 * is typically ignored if its layer is invisible or empty. 215 */ 216 bool isIgnored() const; 217 218 /** 219 * Indicates whether the current transform has perspective components. 220 */ 221 bool hasPerspectiveTransform() const; 222 223 /** 224 * Fills outTransform with the current, total transform to screen space, 225 * across layer boundaries. 226 */ 227 // TODO: remove for HWUI_NEW_OPS 228 void buildScreenSpaceTransform(Matrix4* outTransform) const; 229 230 /** 231 * Dirty flags. 232 */ 233 int flags; 234 235 /** 236 * Previous snapshot. 237 */ 238 Snapshot* previous; 239 240 /** 241 * A pointer to the currently active layer. 242 * 243 * This snapshot does not own the layer, this pointer must not be freed. 244 */ 245 Layer* layer; 246 247 /** 248 * Target FBO used for rendering. Set to 0 when rendering directly 249 * into the framebuffer. 250 */ 251 GLuint fbo; 252 253 /** 254 * Indicates that this snapshot is invisible and nothing should be drawn 255 * inside it. This flag is set only when the layer clips drawing to its 256 * bounds and is passed to subsequent snapshots. 257 */ 258 bool invisible; 259 260 /** 261 * If set to true, the layer will not be composited. This is similar to 262 * invisible but this flag is not passed to subsequent snapshots. 263 */ 264 bool empty; 265 266 /** 267 * Local transformation. Holds the current translation, scale and 268 * rotation values. 269 * 270 * This is a reference to a matrix owned by this snapshot or another 271 * snapshot. This pointer must not be freed. See ::mTransformRoot. 272 */ 273 mat4* transform; 274 275 /** 276 * The ancestor layer's dirty region. 277 * 278 * This is a reference to a region owned by a layer. This pointer must 279 * not be freed. 280 */ 281 Region* region; 282 283 /** 284 * Current alpha value. This value is 1 by default, but may be set by a DisplayList which 285 * has translucent rendering in a non-overlapping View. This value will be used by 286 * the renderer to set the alpha in the current color being used for ensuing drawing 287 * operations. The value is inherited by child snapshots because the same value should 288 * be applied to descendants of the current DisplayList (for example, a TextView contains 289 * the base alpha value which should be applied to the child DisplayLists used for drawing 290 * the actual text). 291 */ 292 float alpha; 293 294 /** 295 * Current clipping round rect. 296 * 297 * Points to data not owned by the snapshot, and may only be replaced by subsequent RR clips, 298 * never modified. 299 */ 300 const RoundRectClipState* roundRectClipState; 301 302 /** 303 * Current projection masking path - used exclusively to mask projected, tessellated circles. 304 */ 305 #if HWUI_NEW_OPS 306 const SkPath* projectionPathMask; 307 #else 308 const ProjectionPathMask* projectionPathMask; 309 #endif 310 311 void dump() const; 312 313 private: 314 struct ViewportData { ViewportDataViewportData315 ViewportData() : mWidth(0), mHeight(0) {} initializeViewportData316 void initialize(int width, int height) { 317 mWidth = width; 318 mHeight = height; 319 mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1); 320 } 321 322 /* 323 * Width and height of current viewport. 324 * 325 * The viewport is always defined to be (0, 0, width, height). 326 */ 327 int mWidth; 328 int mHeight; 329 /** 330 * Contains the current orthographic, projection matrix. 331 */ 332 mat4 mOrthoMatrix; 333 }; 334 335 mat4 mTransformRoot; 336 337 ClipArea mClipAreaRoot; 338 ClipArea* mClipArea; 339 Rect mLocalClip; 340 341 ViewportData mViewportData; 342 Vector3 mRelativeLightCenter; 343 344 }; // class Snapshot 345 346 }; // namespace uirenderer 347 }; // namespace android 348 349 #endif // ANDROID_HWUI_SNAPSHOT_H 350