1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/layers/Compositor.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,542 @@ 1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 +* This Source Code Form is subject to the terms of the Mozilla Public 1.6 +* License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 +* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef MOZILLA_GFX_COMPOSITOR_H 1.10 +#define MOZILLA_GFX_COMPOSITOR_H 1.11 + 1.12 +#include "Units.h" // for ScreenPoint 1.13 +#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc 1.14 +#include "mozilla/RefPtr.h" // for TemporaryRef, RefCounted 1.15 +#include "mozilla/gfx/Point.h" // for IntSize, Point 1.16 +#include "mozilla/gfx/Rect.h" // for Rect, IntRect 1.17 +#include "mozilla/gfx/Types.h" // for Float 1.18 +#include "mozilla/layers/CompositorTypes.h" // for DiagnosticTypes, etc 1.19 +#include "mozilla/layers/LayersTypes.h" // for LayersBackend 1.20 +#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc 1.21 +#include "nsRegion.h" 1.22 +#include <vector> 1.23 +#include "mozilla/WidgetUtils.h" 1.24 + 1.25 +/** 1.26 + * Different elements of a web pages are rendered into separate "layers" before 1.27 + * they are flattened into the final image that is brought to the screen. 1.28 + * See Layers.h for more informations about layers and why we use retained 1.29 + * structures. 1.30 + * Most of the documentation for layers is directly in the source code in the 1.31 + * form of doc comments. An overview can also be found in the the wiki: 1.32 + * https://wiki.mozilla.org/Gecko:Overview#Graphics 1.33 + * 1.34 + * 1.35 + * # Main interfaces and abstractions 1.36 + * 1.37 + * - Layer, ShadowableLayer and LayerComposite 1.38 + * (see Layers.h and ipc/ShadowLayers.h) 1.39 + * - CompositableClient and CompositableHost 1.40 + * (client/CompositableClient.h composite/CompositableHost.h) 1.41 + * - TextureClient and TextureHost 1.42 + * (client/TextureClient.h composite/TextureHost.h) 1.43 + * - TextureSource 1.44 + * (composite/TextureHost.h) 1.45 + * - Forwarders 1.46 + * (ipc/CompositableForwarder.h ipc/ShadowLayers.h) 1.47 + * - Compositor 1.48 + * (this file) 1.49 + * - IPDL protocols 1.50 + * (.ipdl files under the gfx/layers/ipc directory) 1.51 + * 1.52 + * The *Client and Shadowable* classes are always used on the content thread. 1.53 + * Forwarders are always used on the content thread. 1.54 + * The *Host and Shadow* classes are always used on the compositor thread. 1.55 + * Compositors, TextureSource, and Effects are always used on the compositor 1.56 + * thread. 1.57 + * Most enums and constants are declared in LayersTypes.h and CompositorTypes.h. 1.58 + * 1.59 + * 1.60 + * # Texture transfer 1.61 + * 1.62 + * Most layer classes own a Compositable plus some extra information like 1.63 + * transforms and clip rects. They are platform independent. 1.64 + * Compositable classes manipulate Texture objects and are reponsible for 1.65 + * things like tiling, buffer rotation or double buffering. Compositables 1.66 + * are also platform-independent. Examples of compositable classes are: 1.67 + * - ImageClient 1.68 + * - CanvasClient 1.69 + * - ContentHost 1.70 + * - etc. 1.71 + * Texture classes (TextureClient and TextureHost) are thin abstractions over 1.72 + * platform-dependent texture memory. They are maniplulated by compositables 1.73 + * and don't know about buffer rotations and such. The purposes of TextureClient 1.74 + * and TextureHost are to synchronize, serialize and deserialize texture data. 1.75 + * TextureHosts provide access to TextureSources that are views on the 1.76 + * Texture data providing the necessary api for Compositor backend to composite 1.77 + * them. 1.78 + * 1.79 + * Compositable and Texture clients and hosts are created using factory methods. 1.80 + * They should only be created by using their constructor in exceptional 1.81 + * circumstances. The factory methods are located: 1.82 + * TextureClient - CompositableClient::CreateTextureClient 1.83 + * TextureHost - TextureHost::CreateTextureHost, which calls a 1.84 + * platform-specific function, e.g., CreateTextureHostOGL 1.85 + * CompositableClient - in the appropriate subclass, e.g., 1.86 + * CanvasClient::CreateCanvasClient 1.87 + * CompositableHost - CompositableHost::Create 1.88 + * 1.89 + * 1.90 + * # IPDL 1.91 + * 1.92 + * If off-main-thread compositing (OMTC) is enabled, compositing is performed 1.93 + * in a dedicated thread. In some setups compositing happens in a dedicated 1.94 + * process. Documentation may refer to either the compositor thread or the 1.95 + * compositor process. 1.96 + * See explanations in ShadowLayers.h. 1.97 + * 1.98 + * 1.99 + * # Backend implementations 1.100 + * 1.101 + * Compositor backends like OpenGL or flavours of D3D live in their own directory 1.102 + * under gfx/layers/. To add a new backend, implement at least the following 1.103 + * interfaces: 1.104 + * - Compositor (ex. CompositorOGL) 1.105 + * - TextureHost (ex. SharedTextureHostOGL) 1.106 + * Depending on the type of data that needs to be serialized, you may need to 1.107 + * add specific TextureClient implementations. 1.108 + */ 1.109 + 1.110 +class nsIWidget; 1.111 +struct nsIntSize; 1.112 +class nsIntRegion; 1.113 + 1.114 +namespace mozilla { 1.115 +namespace gfx { 1.116 +class Matrix; 1.117 +class Matrix4x4; 1.118 +class DrawTarget; 1.119 +} 1.120 + 1.121 +namespace layers { 1.122 + 1.123 +struct Effect; 1.124 +struct EffectChain; 1.125 +class Image; 1.126 +class ISurfaceAllocator; 1.127 +class Layer; 1.128 +class NewTextureSource; 1.129 +class DataTextureSource; 1.130 +class CompositingRenderTarget; 1.131 +class PCompositorParent; 1.132 +class LayerManagerComposite; 1.133 + 1.134 +enum SurfaceInitMode 1.135 +{ 1.136 + INIT_MODE_NONE, 1.137 + INIT_MODE_CLEAR 1.138 +}; 1.139 + 1.140 +/** 1.141 + * A base class for a platform-dependent helper for use by TextureHost. 1.142 + */ 1.143 +class CompositorBackendSpecificData 1.144 +{ 1.145 + NS_INLINE_DECL_REFCOUNTING(CompositorBackendSpecificData) 1.146 + 1.147 +protected: 1.148 + virtual ~CompositorBackendSpecificData() {} 1.149 +}; 1.150 + 1.151 +/** 1.152 + * Common interface for compositor backends. 1.153 + * 1.154 + * Compositor provides a cross-platform interface to a set of operations for 1.155 + * compositing quads. Compositor knows nothing about the layer tree. It must be 1.156 + * told everything about each composited quad - contents, location, transform, 1.157 + * opacity, etc. 1.158 + * 1.159 + * In theory it should be possible for different widgets to use the same 1.160 + * compositor. In practice, we use one compositor per window. 1.161 + * 1.162 + * # Usage 1.163 + * 1.164 + * For an example of a user of Compositor, see LayerManagerComposite. 1.165 + * 1.166 + * Initialization: create a Compositor object, call Initialize(). 1.167 + * 1.168 + * Destruction: destroy any resources associated with the compositor, call 1.169 + * Destroy(), delete the Compositor object. 1.170 + * 1.171 + * Composition: 1.172 + * call BeginFrame, 1.173 + * for each quad to be composited: 1.174 + * call MakeCurrent if necessary (not necessary if no other context has been 1.175 + * made current), 1.176 + * take care of any texture upload required to composite the quad, this step 1.177 + * is backend-dependent, 1.178 + * construct an EffectChain for the quad, 1.179 + * call DrawQuad, 1.180 + * call EndFrame. 1.181 + * If the user has to stop compositing at any point before EndFrame, call 1.182 + * AbortFrame. 1.183 + * If the compositor is usually used for compositing but compositing is 1.184 + * temporarily done without the compositor, call EndFrameForExternalComposition 1.185 + * after compositing each frame so the compositor can remain internally 1.186 + * consistent. 1.187 + * 1.188 + * By default, the compositor will render to the screen, to render to a target, 1.189 + * call SetTargetContext or SetRenderTarget, the latter with a target created 1.190 + * by CreateRenderTarget or CreateRenderTargetFromSource. 1.191 + * 1.192 + * The target and viewport methods can be called before any DrawQuad call and 1.193 + * affect any subsequent DrawQuad calls. 1.194 + */ 1.195 +class Compositor 1.196 +{ 1.197 +protected: 1.198 + virtual ~Compositor() {} 1.199 + 1.200 +public: 1.201 + NS_INLINE_DECL_REFCOUNTING(Compositor) 1.202 + 1.203 + Compositor(PCompositorParent* aParent = nullptr) 1.204 + : mCompositorID(0) 1.205 + , mDiagnosticTypes(DIAGNOSTIC_NONE) 1.206 + , mParent(aParent) 1.207 + , mScreenRotation(ROTATION_0) 1.208 + { 1.209 + } 1.210 + 1.211 + virtual TemporaryRef<DataTextureSource> CreateDataTextureSource(TextureFlags aFlags = 0) = 0; 1.212 + virtual bool Initialize() = 0; 1.213 + virtual void Destroy() = 0; 1.214 + 1.215 + /** 1.216 + * Return true if the effect type is supported. 1.217 + * 1.218 + * By default Compositor implementations should support all effects but in 1.219 + * some rare cases it is not possible to support an effect efficiently. 1.220 + * This is the case for BasicCompositor with EffectYCbCr. 1.221 + */ 1.222 + virtual bool SupportsEffect(EffectTypes aEffect) { return true; } 1.223 + 1.224 + /** 1.225 + * Request a texture host identifier that may be used for creating textures 1.226 + * across process or thread boundaries that are compatible with this 1.227 + * compositor. 1.228 + */ 1.229 + virtual TextureFactoryIdentifier GetTextureFactoryIdentifier() = 0; 1.230 + 1.231 + /** 1.232 + * Properties of the compositor. 1.233 + */ 1.234 + virtual bool CanUseCanvasLayerForSize(const gfx::IntSize& aSize) = 0; 1.235 + virtual int32_t GetMaxTextureSize() const = 0; 1.236 + 1.237 + /** 1.238 + * Set the target for rendering. Results will have been written to aTarget by 1.239 + * the time that EndFrame returns. 1.240 + * 1.241 + * If this method is not used, or we pass in nullptr, we target the compositor's 1.242 + * usual swap chain and render to the screen. 1.243 + */ 1.244 + virtual void SetTargetContext(gfx::DrawTarget* aTarget) = 0; 1.245 + 1.246 + typedef uint32_t MakeCurrentFlags; 1.247 + static const MakeCurrentFlags ForceMakeCurrent = 0x1; 1.248 + /** 1.249 + * Make this compositor's rendering context the current context for the 1.250 + * underlying graphics API. This may be a global operation, depending on the 1.251 + * API. Our context will remain the current one until someone else changes it. 1.252 + * 1.253 + * Clients of the compositor should call this at the start of the compositing 1.254 + * process, it might be required by texture uploads etc. 1.255 + * 1.256 + * If aFlags == ForceMakeCurrent then we will (re-)set our context on the 1.257 + * underlying API even if it is already the current context. 1.258 + */ 1.259 + virtual void MakeCurrent(MakeCurrentFlags aFlags = 0) = 0; 1.260 + 1.261 + /** 1.262 + * Creates a Surface that can be used as a rendering target by this 1.263 + * compositor. 1.264 + */ 1.265 + virtual TemporaryRef<CompositingRenderTarget> 1.266 + CreateRenderTarget(const gfx::IntRect& aRect, SurfaceInitMode aInit) = 0; 1.267 + 1.268 + /** 1.269 + * Creates a Surface that can be used as a rendering target by this 1.270 + * compositor, and initializes the surface by copying from aSource. 1.271 + * If aSource is null, then the current screen buffer is used as source. 1.272 + * 1.273 + * aSourcePoint specifies the point in aSource to copy data from. 1.274 + */ 1.275 + virtual TemporaryRef<CompositingRenderTarget> 1.276 + CreateRenderTargetFromSource(const gfx::IntRect& aRect, 1.277 + const CompositingRenderTarget* aSource, 1.278 + const gfx::IntPoint& aSourcePoint) = 0; 1.279 + 1.280 + /** 1.281 + * Sets the given surface as the target for subsequent calls to DrawQuad. 1.282 + * Passing null as aSurface sets the screen as the target. 1.283 + */ 1.284 + virtual void SetRenderTarget(CompositingRenderTarget* aSurface) = 0; 1.285 + 1.286 + /** 1.287 + * Returns the current target for rendering. Will return null if we are 1.288 + * rendering to the screen. 1.289 + */ 1.290 + virtual CompositingRenderTarget* GetCurrentRenderTarget() const = 0; 1.291 + 1.292 + /** 1.293 + * Mostly the compositor will pull the size from a widget and this method will 1.294 + * be ignored, but compositor implementations are free to use it if they like. 1.295 + */ 1.296 + virtual void SetDestinationSurfaceSize(const gfx::IntSize& aSize) = 0; 1.297 + 1.298 + /** 1.299 + * Declare an offset to use when rendering layers. This will be ignored when 1.300 + * rendering to a target instead of the screen. 1.301 + */ 1.302 + virtual void SetScreenRenderOffset(const ScreenPoint& aOffset) = 0; 1.303 + 1.304 + /** 1.305 + * Tell the compositor to draw a quad. What to do draw and how it is 1.306 + * drawn is specified by aEffectChain. aRect is the quad to draw, in user space. 1.307 + * aTransform transforms from user space to screen space. If texture coords are 1.308 + * required, these will be in the primary effect in the effect chain. 1.309 + */ 1.310 + virtual void DrawQuad(const gfx::Rect& aRect, const gfx::Rect& aClipRect, 1.311 + const EffectChain& aEffectChain, 1.312 + gfx::Float aOpacity, const gfx::Matrix4x4 &aTransform) = 0; 1.313 + 1.314 + /** 1.315 + * Tell the compositor to draw lines connecting the points. Behaves like 1.316 + * DrawQuad. 1.317 + */ 1.318 + virtual void DrawLines(const std::vector<gfx::Point>& aLines, const gfx::Rect& aClipRect, 1.319 + const gfx::Color& aColor, 1.320 + gfx::Float aOpacity, const gfx::Matrix4x4 &aTransform) 1.321 + { /* Should turn into pure virtual once implemented in D3D */ } 1.322 + 1.323 + /* 1.324 + * Clear aRect on current render target. 1.325 + */ 1.326 + virtual void ClearRect(const gfx::Rect& aRect) { } 1.327 + 1.328 + /** 1.329 + * Start a new frame. 1.330 + * 1.331 + * aInvalidRect is the invalid region of the screen; it can be ignored for 1.332 + * compositors where the performance for compositing the entire window is 1.333 + * sufficient. 1.334 + * 1.335 + * aClipRectIn is the clip rect for the window in window space (optional). 1.336 + * aTransform is the transform from user space to window space. 1.337 + * aRenderBounds bounding rect for rendering, in user space. 1.338 + * 1.339 + * If aClipRectIn is null, this method sets *aClipRectOut to the clip rect 1.340 + * actually used for rendering (if aClipRectIn is non-null, we will use that 1.341 + * for the clip rect). 1.342 + * 1.343 + * If aRenderBoundsOut is non-null, it will be set to the render bounds 1.344 + * actually used by the compositor in window space. If aRenderBoundsOut 1.345 + * is returned empty, composition should be aborted. 1.346 + */ 1.347 + virtual void BeginFrame(const nsIntRegion& aInvalidRegion, 1.348 + const gfx::Rect* aClipRectIn, 1.349 + const gfx::Matrix& aTransform, 1.350 + const gfx::Rect& aRenderBounds, 1.351 + gfx::Rect* aClipRectOut = nullptr, 1.352 + gfx::Rect* aRenderBoundsOut = nullptr) = 0; 1.353 + 1.354 + /** 1.355 + * Flush the current frame to the screen and tidy up. 1.356 + */ 1.357 + virtual void EndFrame() = 0; 1.358 + 1.359 + virtual void SetFBAcquireFence(Layer* aLayer) {} 1.360 + 1.361 + /** 1.362 + * Post-rendering stuff if the rendering is done outside of this Compositor 1.363 + * e.g., by Composer2D. 1.364 + * aTransform is the transform from user space to window space. 1.365 + */ 1.366 + virtual void EndFrameForExternalComposition(const gfx::Matrix& aTransform) = 0; 1.367 + 1.368 + /** 1.369 + * Tidy up if BeginFrame has been called, but EndFrame won't be. 1.370 + */ 1.371 + virtual void AbortFrame() = 0; 1.372 + 1.373 + /** 1.374 + * Setup the viewport and projection matrix for rendering to a target of the 1.375 + * given dimensions. The size and transform here will override those set in 1.376 + * BeginFrame. BeginFrame sets a size and transform for the default render 1.377 + * target, usually the screen. Calling this method prepares the compositor to 1.378 + * render using a different viewport (that is, size and transform), usually 1.379 + * associated with a new render target. 1.380 + * aWorldTransform is the transform from user space to the new viewport's 1.381 + * coordinate space. 1.382 + */ 1.383 + virtual void PrepareViewport(const gfx::IntSize& aSize, 1.384 + const gfx::Matrix& aWorldTransform) = 0; 1.385 + 1.386 + /** 1.387 + * Whether textures created by this compositor can receive partial updates. 1.388 + */ 1.389 + virtual bool SupportsPartialTextureUpdate() = 0; 1.390 + 1.391 + void SetDiagnosticTypes(DiagnosticTypes aDiagnostics) 1.392 + { 1.393 + mDiagnosticTypes = aDiagnostics; 1.394 + } 1.395 + 1.396 + DiagnosticTypes GetDiagnosticTypes() const 1.397 + { 1.398 + return mDiagnosticTypes; 1.399 + } 1.400 + 1.401 + void DrawDiagnostics(DiagnosticFlags aFlags, 1.402 + const gfx::Rect& visibleRect, 1.403 + const gfx::Rect& aClipRect, 1.404 + const gfx::Matrix4x4& transform, 1.405 + uint32_t aFlashCounter = DIAGNOSTIC_FLASH_COUNTER_MAX); 1.406 + 1.407 + void DrawDiagnostics(DiagnosticFlags aFlags, 1.408 + const nsIntRegion& visibleRegion, 1.409 + const gfx::Rect& aClipRect, 1.410 + const gfx::Matrix4x4& transform, 1.411 + uint32_t aFlashCounter = DIAGNOSTIC_FLASH_COUNTER_MAX); 1.412 + 1.413 +#ifdef MOZ_DUMP_PAINTING 1.414 + virtual const char* Name() const = 0; 1.415 +#endif // MOZ_DUMP_PAINTING 1.416 + 1.417 + virtual LayersBackend GetBackendType() const = 0; 1.418 + 1.419 + /** 1.420 + * Each Compositor has a unique ID. 1.421 + * This ID is used to keep references to each Compositor in a map accessed 1.422 + * from the compositor thread only, so that async compositables can find 1.423 + * the right compositor parent and schedule compositing even if the compositor 1.424 + * changed. 1.425 + */ 1.426 + uint32_t GetCompositorID() const 1.427 + { 1.428 + return mCompositorID; 1.429 + } 1.430 + void SetCompositorID(uint32_t aID) 1.431 + { 1.432 + MOZ_ASSERT(mCompositorID == 0, "The compositor ID must be set only once."); 1.433 + mCompositorID = aID; 1.434 + } 1.435 + 1.436 + /** 1.437 + * Notify the compositor that composition is being paused. This allows the 1.438 + * compositor to temporarily release any resources. 1.439 + * Between calling Pause and Resume, compositing may fail. 1.440 + */ 1.441 + virtual void Pause() {} 1.442 + /** 1.443 + * Notify the compositor that composition is being resumed. The compositor 1.444 + * regain any resources it requires for compositing. 1.445 + * Returns true if succeeded. 1.446 + */ 1.447 + virtual bool Resume() { return true; } 1.448 + 1.449 + /** 1.450 + * Call before rendering begins to ensure the compositor is ready to 1.451 + * composite. Returns false if rendering should be aborted. 1.452 + */ 1.453 + virtual bool Ready() { return true; } 1.454 + 1.455 + // XXX I expect we will want to move mWidget into this class and implement 1.456 + // these methods properly. 1.457 + virtual nsIWidget* GetWidget() const { return nullptr; } 1.458 + 1.459 + /** 1.460 + * Debug-build assertion that can be called to ensure code is running on the 1.461 + * compositor thread. 1.462 + */ 1.463 + static void AssertOnCompositorThread(); 1.464 + 1.465 + /** 1.466 + * We enforce that there can only be one Compositor backend type off the main 1.467 + * thread at the same time. The backend type in use can be checked with this 1.468 + * static method. We need this for creating texture clients/hosts etc. when we 1.469 + * don't have a reference to a Compositor. 1.470 + * 1.471 + * This can only be used from the compositor thread! 1.472 + */ 1.473 + static LayersBackend GetBackend(); 1.474 + 1.475 + size_t GetFillRatio() { 1.476 + float fillRatio = 0; 1.477 + if (mPixelsFilled > 0 && mPixelsPerFrame > 0) { 1.478 + fillRatio = 100.0f * float(mPixelsFilled) / float(mPixelsPerFrame); 1.479 + if (fillRatio > 999.0f) { 1.480 + fillRatio = 999.0f; 1.481 + } 1.482 + } 1.483 + return fillRatio; 1.484 + } 1.485 + 1.486 + virtual CompositorBackendSpecificData* GetCompositorBackendSpecificData() { 1.487 + return nullptr; 1.488 + } 1.489 + 1.490 + ScreenRotation GetScreenRotation() const { 1.491 + return mScreenRotation; 1.492 + } 1.493 + 1.494 + void SetScreenRotation(ScreenRotation aRotation) { 1.495 + mScreenRotation = aRotation; 1.496 + } 1.497 + 1.498 + // On b2g the clip rect is in the coordinate space of the physical screen 1.499 + // independently of its rotation, while the coordinate space of the layers, 1.500 + // on the other hand, depends on the screen orientation. 1.501 + // This only applies to b2g as with other platforms, orientation is handled 1.502 + // at the OS level rather than in Gecko. 1.503 + // In addition, the clip rect needs to be offset by the rendering origin. 1.504 + // This becomes important if intermediate surfaces are used. 1.505 + gfx::Rect ClipRectInLayersCoordinates(gfx::Rect aClip) const; 1.506 + 1.507 +protected: 1.508 + void DrawDiagnosticsInternal(DiagnosticFlags aFlags, 1.509 + const gfx::Rect& aVisibleRect, 1.510 + const gfx::Rect& aClipRect, 1.511 + const gfx::Matrix4x4& transform, 1.512 + uint32_t aFlashCounter); 1.513 + 1.514 + bool ShouldDrawDiagnostics(DiagnosticFlags); 1.515 + 1.516 + /** 1.517 + * Set the global Compositor backend, checking that one isn't already set. 1.518 + */ 1.519 + static void SetBackend(LayersBackend backend); 1.520 + 1.521 + uint32_t mCompositorID; 1.522 + DiagnosticTypes mDiagnosticTypes; 1.523 + PCompositorParent* mParent; 1.524 + 1.525 + /** 1.526 + * We keep track of the total number of pixels filled as we composite the 1.527 + * current frame. This value is an approximation and is not accurate, 1.528 + * especially in the presence of transforms. 1.529 + */ 1.530 + size_t mPixelsPerFrame; 1.531 + size_t mPixelsFilled; 1.532 + 1.533 + ScreenRotation mScreenRotation; 1.534 + 1.535 + virtual gfx::IntSize GetWidgetSize() const = 0; 1.536 + 1.537 +private: 1.538 + static LayersBackend sBackend; 1.539 + 1.540 +}; 1.541 + 1.542 +} // namespace layers 1.543 +} // namespace mozilla 1.544 + 1.545 +#endif /* MOZILLA_GFX_COMPOSITOR_H */