Compositor.h (15143B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef MOZILLA_GFX_COMPOSITOR_H 8 #define MOZILLA_GFX_COMPOSITOR_H 9 10 #include "Units.h" // for ScreenPoint 11 #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc 12 #include "mozilla/gfx/2D.h" // for DrawTarget 13 #include "mozilla/gfx/MatrixFwd.h" // for Matrix, Matrix4x4 14 #include "mozilla/gfx/Point.h" // for IntSize, Point 15 #include "mozilla/gfx/Polygon.h" // for Polygon 16 #include "mozilla/gfx/Rect.h" // for Rect, IntRect 17 #include "mozilla/gfx/Types.h" // for Float 18 #include "mozilla/gfx/Triangle.h" // for Triangle, TexturedTriangle 19 #include "mozilla/layers/CompositorTypes.h" // for DiagnosticTypes, etc 20 #include "mozilla/layers/LayersTypes.h" // for LayersBackend 21 #include "mozilla/layers/SurfacePool.h" // for SurfacePoolHandle 22 #include "mozilla/layers/TextureSourceProvider.h" 23 #include "mozilla/widget/CompositorWidget.h" 24 #include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc 25 #include "nsRegion.h" 26 #include "mozilla/WidgetUtils.h" 27 28 /** 29 * Different elements of a web pages are rendered into separate "layers" before 30 * they are flattened into the final image that is brought to the screen. 31 * See Layers.h for more informations about layers and why we use retained 32 * structures. 33 * Most of the documentation for layers is directly in the source code in the 34 * form of doc comments. An overview can also be found in the the wiki: 35 * https://wiki.mozilla.org/Gecko:Overview#Graphics 36 * 37 * 38 * # Main interfaces and abstractions 39 * 40 * - CompositableClient and CompositableHost 41 * (client/CompositableClient.h composite/CompositableHost.h) 42 * - TextureClient and TextureHost 43 * (client/TextureClient.h composite/TextureHost.h) 44 * - TextureSource 45 * (composite/TextureHost.h) 46 * - Forwarders 47 * (ipc/CompositableForwarder.h ipc/ShadowLayers.h) 48 * - Compositor 49 * (this file) 50 * - IPDL protocols 51 * (.ipdl files under the gfx/layers/ipc directory) 52 * 53 * The *Client and Shadowable* classes are always used on the content thread. 54 * Forwarders are always used on the content thread. 55 * The *Host and Shadow* classes are always used on the compositor thread. 56 * Compositors, TextureSource, and Effects are always used on the compositor 57 * thread. 58 * Most enums and constants are declared in LayersTypes.h and CompositorTypes.h. 59 * 60 * 61 * # Texture transfer 62 * 63 * Most layer classes own a Compositable plus some extra information like 64 * transforms and clip rects. They are platform independent. 65 * Compositable classes manipulate Texture objects and are reponsible for 66 * things like tiling, buffer rotation or double buffering. Compositables 67 * are also platform-independent. Examples of compositable classes are: 68 * - ImageClient 69 * - CanvasClient 70 * - etc. 71 * Texture classes (TextureClient and TextureHost) are thin abstractions over 72 * platform-dependent texture memory. They are maniplulated by compositables 73 * and don't know about buffer rotations and such. The purposes of TextureClient 74 * and TextureHost are to synchronize, serialize and deserialize texture data. 75 * TextureHosts provide access to TextureSources that are views on the 76 * Texture data providing the necessary api for Compositor backend to composite 77 * them. 78 * 79 * Compositable and Texture clients and hosts are created using factory methods. 80 * They should only be created by using their constructor in exceptional 81 * circumstances. The factory methods are located: 82 * TextureClient - CompositableClient::CreateTextureClient 83 * TextureHost - TextureHost::CreateTextureHost, which calls a 84 * platform-specific function, e.g., 85 * CreateTextureHostOGL CompositableClient - in the appropriate subclass, e.g., 86 * CanvasClient::CreateCanvasClient 87 * CompositableHost - CompositableHost::Create 88 * 89 * 90 * # IPDL 91 * 92 * If off-main-thread compositing (OMTC) is enabled, compositing is performed 93 * in a dedicated thread. In some setups compositing happens in a dedicated 94 * process. Documentation may refer to either the compositor thread or the 95 * compositor process. 96 * See explanations in ShadowLayers.h. 97 * 98 * 99 * # Backend implementations 100 * 101 * Compositor backends like OpenGL or flavours of D3D live in their own 102 * directory under gfx/layers/. To add a new backend, implement at least the 103 * following interfaces: 104 * - Compositor (ex. CompositorOGL) 105 * - TextureHost (ex. SurfaceTextureHost) 106 * Depending on the type of data that needs to be serialized, you may need to 107 * add specific TextureClient implementations. 108 */ 109 110 class nsIWidget; 111 112 namespace mozilla { 113 namespace gfx { 114 class DrawTarget; 115 class DataSourceSurface; 116 } // namespace gfx 117 118 namespace layers { 119 120 struct Effect; 121 struct EffectChain; 122 class Image; 123 class Layer; 124 class TextureSource; 125 class DataTextureSource; 126 class CompositingRenderTarget; 127 class CompositorBridgeParent; 128 class NativeLayer; 129 class CompositorOGL; 130 class CompositorD3D11; 131 class TextureReadLock; 132 struct GPUStats; 133 class AsyncReadbackBuffer; 134 class RecordedFrame; 135 136 enum SurfaceInitMode { INIT_MODE_NONE, INIT_MODE_CLEAR }; 137 138 /** 139 * Common interface for compositor backends. 140 * 141 * Compositor provides a cross-platform interface to a set of operations for 142 * compositing quads. Compositor knows nothing about the layer tree. It must be 143 * told everything about each composited quad - contents, location, transform, 144 * opacity, etc. 145 * 146 * In theory it should be possible for different widgets to use the same 147 * compositor. In practice, we use one compositor per window. 148 * 149 * # Usage 150 * 151 * For an example of a user of Compositor, see LayerManagerComposite. 152 * 153 * Initialization: create a Compositor object, call Initialize(). 154 * 155 * Destruction: destroy any resources associated with the compositor, call 156 * Destroy(), delete the Compositor object. 157 * 158 * Composition: 159 * call BeginFrame, 160 * for each quad to be composited: 161 * call MakeCurrent if necessary (not necessary if no other context has been 162 * made current), 163 * take care of any texture upload required to composite the quad, this step 164 * is backend-dependent, 165 * construct an EffectChain for the quad, 166 * call DrawQuad, 167 * call EndFrame. 168 * 169 * By default, the compositor will render to the screen if BeginFrameForWindow 170 * is called. To render to a target, call BeginFrameForTarget or 171 * or SetRenderTarget, the latter with a target created 172 * by CreateRenderTarget or CreateRenderTargetFromSource. 173 * 174 * The target and viewport methods can be called before any DrawQuad call and 175 * affect any subsequent DrawQuad calls. 176 */ 177 class Compositor : public TextureSourceProvider { 178 protected: 179 virtual ~Compositor(); 180 181 public: 182 explicit Compositor(widget::CompositorWidget* aWidget); 183 184 bool IsValid() const override { return true; } 185 186 virtual bool Initialize(nsCString* const out_failureReason) = 0; 187 void Destroy() override; 188 bool IsDestroyed() const { return mIsDestroyed; } 189 190 /** 191 * Creates a Surface that can be used as a rendering target by this 192 * compositor. 193 */ 194 virtual already_AddRefed<CompositingRenderTarget> CreateRenderTarget( 195 const gfx::IntRect& aRect, SurfaceInitMode aInit) = 0; 196 197 /** 198 * Grab a snapshot of aSource and store it in aDest, so that the pixels can 199 * be read on the CPU by mapping aDest at some point in the future. 200 * aSource and aDest must have the same size. 201 * If this is a GPU compositor, this call must not block on the GPU. 202 * Returns whether the operation was successful. 203 */ 204 virtual bool ReadbackRenderTarget(CompositingRenderTarget* aSource, 205 AsyncReadbackBuffer* aDest) = 0; 206 207 /** 208 * Create an AsyncReadbackBuffer of the specified size. Can return null. 209 */ 210 virtual already_AddRefed<AsyncReadbackBuffer> CreateAsyncReadbackBuffer( 211 const gfx::IntSize& aSize) = 0; 212 213 /** 214 * Draw a part of aSource into the current render target. 215 * Scaling is done with linear filtering. 216 * Returns whether the operation was successful. 217 */ 218 virtual bool BlitRenderTarget(CompositingRenderTarget* aSource, 219 const gfx::IntSize& aSourceSize, 220 const gfx::IntSize& aDestSize) = 0; 221 222 /** 223 * Sets the given surface as the target for subsequent calls to DrawQuad. 224 * Passing null as aSurface sets the screen as the target. 225 */ 226 virtual void SetRenderTarget(CompositingRenderTarget* aSurface) = 0; 227 228 /** 229 * Returns the current target for rendering. Will return null if we are 230 * rendering to the screen. 231 */ 232 virtual already_AddRefed<CompositingRenderTarget> GetCurrentRenderTarget() 233 const = 0; 234 235 /** 236 * Returns a render target which contains the entire window's drawing. 237 * On platforms where no such render target is used during compositing (e.g. 238 * with buffered BasicCompositor, where only the invalid area is drawn to a 239 * render target), this will return null. 240 */ 241 virtual already_AddRefed<CompositingRenderTarget> GetWindowRenderTarget() 242 const = 0; 243 244 /** 245 * Mostly the compositor will pull the size from a widget and this method will 246 * be ignored, but compositor implementations are free to use it if they like. 247 */ 248 virtual void SetDestinationSurfaceSize(const gfx::IntSize& aSize) = 0; 249 250 /** 251 * Tell the compositor to draw a quad. What to do draw and how it is 252 * drawn is specified by aEffectChain. aRect is the quad to draw, in user 253 * space. aTransform transforms from user space to screen space. If texture 254 * coords are required, these will be in the primary effect in the effect 255 * chain. aVisibleRect is used to determine which edges should be antialiased, 256 * without applying the effect to the inner edges of a tiled layer. 257 */ 258 virtual void DrawQuad(const gfx::Rect& aRect, const gfx::IntRect& aClipRect, 259 const EffectChain& aEffectChain, gfx::Float aOpacity, 260 const gfx::Matrix4x4& aTransform, 261 const gfx::Rect& aVisibleRect) = 0; 262 263 void SetClearColor(const gfx::DeviceColor& aColor) { mClearColor = aColor; } 264 265 /** 266 * Start a new frame for rendering to the window. 267 * Needs to be paired with a call to EndFrame() if the return value is not 268 * Nothing(). 269 * 270 * aInvalidRegion is the invalid region of the window. 271 * aClipRect is the clip rect for all drawing (optional). 272 * aRenderBounds is the bounding rect for rendering. 273 * aOpaqueRegion is the area that contains opaque content. 274 * All coordinates are in window space. 275 * 276 * Returns the non-empty render bounds actually used by the compositor in 277 * window space, or Nothing() if composition should be aborted. 278 */ 279 virtual Maybe<gfx::IntRect> BeginFrameForWindow( 280 const nsIntRegion& aInvalidRegion, const Maybe<gfx::IntRect>& aClipRect, 281 const gfx::IntRect& aRenderBounds, const nsIntRegion& aOpaqueRegion) = 0; 282 283 /** 284 * Flush the current frame to the screen and tidy up. 285 * 286 * Derived class overriding this should call Compositor::EndFrame. 287 */ 288 virtual void EndFrame(); 289 290 virtual void CancelFrame(bool aNeedFlush = true) {} 291 292 #ifdef MOZ_DUMP_PAINTING 293 virtual const char* Name() const = 0; 294 #endif // MOZ_DUMP_PAINTING 295 296 virtual CompositorD3D11* AsCompositorD3D11() { return nullptr; } 297 298 Compositor* AsCompositor() override { return this; } 299 300 TimeStamp GetLastCompositionEndTime() const override { 301 return mLastCompositionEndTime; 302 } 303 304 /** 305 * Notify the compositor that composition is being paused. This allows the 306 * compositor to temporarily release any resources. 307 * Between calling Pause and Resume, compositing may fail. 308 */ 309 virtual void Pause() {} 310 /** 311 * Notify the compositor that composition is being resumed. The compositor 312 * regain any resources it requires for compositing. 313 * Returns true if succeeded. 314 */ 315 virtual bool Resume() { return true; } 316 317 widget::CompositorWidget* GetWidget() const { return mWidget; } 318 319 /** 320 * Request the compositor to allow recording its frames. 321 * 322 * This is a noop on |CompositorOGL|. 323 */ 324 virtual void RequestAllowFrameRecording(bool aWillRecord) { 325 mRecordFrames = aWillRecord; 326 } 327 328 protected: 329 /** 330 * Whether or not the compositor should be prepared to record frames. While 331 * this returns true, compositors are expected to maintain a full window 332 * render target that they return from GetWindowRenderTarget() between 333 * NormalDrawingDone() and EndFrame(). 334 * 335 * This will be true when either we are recording a profile with screenshots 336 * enabled or the |LayerManagerComposite| has requested us to record frames 337 * for the |CompositionRecorder|. 338 */ 339 bool ShouldRecordFrames() const; 340 341 /** 342 * Last Composition end time. 343 */ 344 TimeStamp mLastCompositionEndTime; 345 346 widget::CompositorWidget* mWidget; 347 348 bool mIsDestroyed; 349 350 gfx::DeviceColor mClearColor; 351 352 bool mRecordFrames = false; 353 354 private: 355 static LayersBackend sBackend; 356 }; 357 358 // Returns the number of rects. (Up to 4) 359 typedef gfx::Rect decomposedRectArrayT[4]; 360 size_t DecomposeIntoNoRepeatRects(const gfx::Rect& aRect, 361 const gfx::Rect& aTexCoordRect, 362 decomposedRectArrayT* aLayerRects, 363 decomposedRectArrayT* aTextureRects); 364 365 static inline bool BlendOpIsMixBlendMode(gfx::CompositionOp aOp) { 366 switch (aOp) { 367 case gfx::CompositionOp::OP_MULTIPLY: 368 case gfx::CompositionOp::OP_SCREEN: 369 case gfx::CompositionOp::OP_OVERLAY: 370 case gfx::CompositionOp::OP_DARKEN: 371 case gfx::CompositionOp::OP_LIGHTEN: 372 case gfx::CompositionOp::OP_COLOR_DODGE: 373 case gfx::CompositionOp::OP_COLOR_BURN: 374 case gfx::CompositionOp::OP_HARD_LIGHT: 375 case gfx::CompositionOp::OP_SOFT_LIGHT: 376 case gfx::CompositionOp::OP_DIFFERENCE: 377 case gfx::CompositionOp::OP_EXCLUSION: 378 case gfx::CompositionOp::OP_HUE: 379 case gfx::CompositionOp::OP_SATURATION: 380 case gfx::CompositionOp::OP_COLOR: 381 case gfx::CompositionOp::OP_LUMINOSITY: 382 return true; 383 default: 384 return false; 385 } 386 } 387 388 class AsyncReadbackBuffer { 389 public: 390 NS_INLINE_DECL_REFCOUNTING(AsyncReadbackBuffer) 391 392 gfx::IntSize GetSize() const { return mSize; } 393 virtual bool MapAndCopyInto(gfx::DataSourceSurface* aSurface, 394 const gfx::IntSize& aReadSize) const = 0; 395 396 protected: 397 explicit AsyncReadbackBuffer(const gfx::IntSize& aSize) : mSize(aSize) {} 398 virtual ~AsyncReadbackBuffer() = default; 399 400 gfx::IntSize mSize; 401 }; 402 403 struct TexturedVertex { 404 float position[2]; 405 float texCoords[2]; 406 }; 407 408 nsTArray<TexturedVertex> TexturedTrianglesToVertexArray( 409 const nsTArray<gfx::TexturedTriangle>& aTriangles); 410 411 } // namespace layers 412 } // namespace mozilla 413 414 #endif /* MOZILLA_GFX_COMPOSITOR_H */