Line data Source code
1 : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #ifndef mozilla_gfx_layers_mlgpu_MLGDevice_h
7 : #define mozilla_gfx_layers_mlgpu_MLGDevice_h
8 :
9 : #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
10 : #include "mozilla/EnumeratedArray.h"
11 : #include "mozilla/RefPtr.h" // for already_AddRefed, RefCounted
12 : #include "mozilla/TypedEnumBits.h"
13 : #include "mozilla/WidgetUtils.h"
14 : #include "mozilla/gfx/Types.h"
15 : #include "mozilla/layers/CompositorTypes.h"
16 : #include "mozilla/layers/LayersTypes.h"
17 : #include "ImageTypes.h"
18 : #include "MLGDeviceTypes.h"
19 : #include "nsISupportsImpl.h"
20 : #include "nsString.h"
21 : #include "nsPrintfCString.h"
22 :
23 : namespace mozilla {
24 :
25 : namespace widget {
26 : class CompositorWidget;
27 : } // namespace widget
28 : namespace gfx {
29 : class DrawTarget;
30 : } // namespace gfx
31 :
32 : namespace layers {
33 :
34 : struct GPUStats;
35 : class BufferCache;
36 : class ConstantBufferSection;
37 : class DataTextureSource;
38 : class MLGBufferD3D11;
39 : class MLGDeviceD3D11;
40 : class MLGRenderTargetD3D11;
41 : class MLGResourceD3D11;
42 : class MLGTexture;
43 : class MLGTextureD3D11;
44 : class SharedVertexBuffer;
45 : class SharedConstantBuffer;
46 : class TextureSource;
47 : class VertexBufferSection;
48 : struct ClearRegionHelper;
49 :
50 : class MLGRenderTarget
51 : {
52 : public:
53 0 : NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MLGRenderTarget)
54 :
55 : virtual gfx::IntSize GetSize() const = 0;
56 0 : virtual MLGRenderTargetD3D11* AsD3D11() { return nullptr; }
57 :
58 : // Returns the underlying texture of the render target.
59 : virtual MLGTexture* GetTexture() = 0;
60 :
61 : bool HasDepthBuffer() const {
62 : return (mFlags & MLGRenderTargetFlags::ZBuffer) == MLGRenderTargetFlags::ZBuffer;
63 : }
64 :
65 0 : int32_t GetLastDepthStart() const {
66 0 : return mLastDepthStart;
67 : }
68 0 : void SetLastDepthStart(int32_t aDepthStart) {
69 0 : mLastDepthStart = aDepthStart;
70 0 : }
71 :
72 : protected:
73 : explicit MLGRenderTarget(MLGRenderTargetFlags aFlags);
74 : virtual ~MLGRenderTarget() {}
75 :
76 : protected:
77 : MLGRenderTargetFlags mFlags;
78 :
79 : // When using a depth buffer, callers can track the range of depth values
80 : // that were last used.
81 : int32_t mLastDepthStart;
82 : };
83 :
84 : class MLGSwapChain
85 : {
86 : protected:
87 : virtual ~MLGSwapChain() {}
88 :
89 : public:
90 0 : NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MLGSwapChain)
91 :
92 : virtual RefPtr<MLGRenderTarget> AcquireBackBuffer() = 0;
93 : virtual bool ResizeBuffers(const gfx::IntSize& aSize) = 0;
94 : virtual gfx::IntSize GetSize() const = 0;
95 :
96 : // Present to the screen.
97 : virtual void Present() = 0;
98 :
99 : // Force a present without waiting for the previous frame's present to complete.
100 : virtual void ForcePresent() = 0;
101 :
102 : // Copy an area of the backbuffer to a draw target.
103 : virtual void CopyBackbuffer(gfx::DrawTarget* aTarget, const gfx::IntRect& aBounds) = 0;
104 :
105 : // Free any internal resources.
106 : virtual void Destroy() = 0;
107 :
108 : // Give the new invalid region to the swap chain in preparation for
109 : // acquiring the backbuffer. If the new invalid region is empty,
110 : // this returns false and no composite is required.
111 : //
112 : // The extra rect is used for the debug overlay, which is factored in
113 : // separately to avoid causing unnecessary composites.
114 : bool ApplyNewInvalidRegion(nsIntRegion&& aRegion, const Maybe<gfx::IntRect>& aExtraRect);
115 :
116 0 : const nsIntRegion& GetBackBufferInvalidRegion() const {
117 0 : return mBackBufferInvalid;
118 : }
119 :
120 : protected:
121 : MLGSwapChain();
122 :
123 : protected:
124 : gfx::IntSize mLastPresentSize;
125 : // The swap chain tracks the invalid region of its buffers. After presenting,
126 : // the invalid region for the backbuffer is cleared. If using double
127 : // buffering, it is set to the area of the non-presented buffer that was not
128 : // painted this frame. The initial invalid region each frame comes from
129 : // LayerManagerMLGPU, and is combined with the back buffer's invalid region
130 : // before frame building begins.
131 : nsIntRegion mBackBufferInvalid;
132 : nsIntRegion mFrontBufferInvalid;
133 : bool mIsDoubleBuffered;
134 : };
135 :
136 : class MLGResource
137 : {
138 0 : NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MLGResource)
139 :
140 : public:
141 : enum class Type {
142 : Buffer,
143 : Texture
144 : };
145 :
146 : virtual Type GetType() const = 0;
147 : virtual MLGResourceD3D11* AsResourceD3D11() {
148 : return nullptr;
149 : }
150 :
151 : protected:
152 : virtual ~MLGResource() {}
153 : };
154 :
155 : // A buffer for use as a shader input.
156 : class MLGBuffer : public MLGResource
157 : {
158 : public:
159 : Type GetType() const override {
160 : return Type::Buffer;
161 : }
162 : virtual MLGBufferD3D11* AsD3D11() {
163 : return nullptr;
164 : }
165 : virtual size_t GetSize() const = 0;
166 :
167 : protected:
168 : ~MLGBuffer() override {}
169 : };
170 :
171 : // This is a lower-level resource than a TextureSource. It wraps
172 : // a 2D texture.
173 : class MLGTexture : public MLGResource
174 : {
175 : public:
176 : Type GetType() const override {
177 : return Type::Texture;
178 : }
179 : virtual MLGTextureD3D11* AsD3D11() {
180 : return nullptr;
181 : }
182 0 : const gfx::IntSize& GetSize() const {
183 0 : return mSize;
184 : }
185 :
186 : protected:
187 : gfx::IntSize mSize;
188 : };
189 :
190 : enum class VertexShaderID
191 : {
192 : TexturedQuad,
193 : TexturedVertex,
194 : ColoredQuad,
195 : ColoredVertex,
196 : BlendVertex,
197 : Clear,
198 : MaskCombiner,
199 : DiagnosticText,
200 : MaxShaders
201 : };
202 :
203 : enum class PixelShaderID
204 : {
205 : ColoredQuad,
206 : ColoredVertex,
207 : TexturedQuadRGB,
208 : TexturedQuadRGBA,
209 : TexturedVertexRGB,
210 : TexturedVertexRGBA,
211 : TexturedQuadIMC4,
212 : TexturedQuadNV12,
213 : TexturedVertexIMC4,
214 : TexturedVertexNV12,
215 : ComponentAlphaQuad,
216 : ComponentAlphaVertex,
217 : BlendMultiply,
218 : BlendScreen,
219 : BlendOverlay,
220 : BlendDarken,
221 : BlendLighten,
222 : BlendColorDodge,
223 : BlendColorBurn,
224 : BlendHardLight,
225 : BlendSoftLight,
226 : BlendDifference,
227 : BlendExclusion,
228 : BlendHue,
229 : BlendSaturation,
230 : BlendColor,
231 : BlendLuminosity,
232 : Clear,
233 : MaskCombiner,
234 : DiagnosticText,
235 : MaxShaders
236 : };
237 :
238 : class MLGDevice
239 : {
240 : public:
241 0 : NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MLGDevice)
242 :
243 : MLGDevice();
244 :
245 : virtual bool Initialize();
246 :
247 : virtual TextureFactoryIdentifier GetTextureFactoryIdentifier() const = 0;
248 : virtual int32_t GetMaxTextureSize() const = 0;
249 : virtual LayersBackend GetLayersBackend() const = 0;
250 :
251 : virtual RefPtr<MLGSwapChain> CreateSwapChainForWidget(widget::CompositorWidget* aWidget) = 0;
252 :
253 : // Markers for when we start and finish issuing "normal" (i.e., non-
254 : // diagnostic) draw commands for the frame.
255 : virtual void StartDiagnostics(uint32_t aInvalidPixels) = 0;
256 : virtual void EndDiagnostics() = 0;
257 : virtual void GetDiagnostics(GPUStats* aStats) = 0;
258 :
259 : // Layers interaction.
260 : virtual RefPtr<DataTextureSource> CreateDataTextureSource(TextureFlags aFlags) = 0;
261 :
262 : // Resource access
263 : virtual bool Map(MLGResource* aResource, MLGMapType aType, MLGMappedResource* aMap) = 0;
264 : virtual void Unmap(MLGResource* aResource) = 0;
265 : virtual void UpdatePartialResource(
266 : MLGResource* aResource,
267 : const gfx::IntRect* aRect,
268 : void* aData,
269 : uint32_t aStride) = 0;
270 : virtual void CopyTexture(
271 : MLGTexture* aDest,
272 : const gfx::IntPoint& aTarget,
273 : MLGTexture* aSource,
274 : const gfx::IntRect& aRect) = 0;
275 :
276 : // Begin a frame. This clears and resets all shared buffers.
277 : virtual void BeginFrame();
278 : virtual void EndFrame();
279 :
280 : // State setup commands.
281 : virtual void SetRenderTarget(MLGRenderTarget* aRT) = 0;
282 : virtual MLGRenderTarget* GetRenderTarget() = 0;
283 : virtual void SetViewport(const gfx::IntRect& aRT) = 0;
284 : virtual void SetScissorRect(const Maybe<gfx::IntRect>& aScissorRect) = 0;
285 : virtual void SetVertexShader(VertexShaderID aVertexShader) = 0;
286 : virtual void SetPixelShader(PixelShaderID aPixelShader) = 0;
287 : virtual void SetSamplerMode(uint32_t aIndex, SamplerMode aSamplerMode) = 0;
288 : virtual void SetBlendState(MLGBlendState aBlendState) = 0;
289 : virtual void SetVertexBuffer(uint32_t aSlot, MLGBuffer* aBuffer, uint32_t aStride, uint32_t aOffset = 0) = 0;
290 : virtual void SetVSConstantBuffer(uint32_t aSlot, MLGBuffer* aBuffer) = 0;
291 : virtual void SetPSConstantBuffer(uint32_t aSlot, MLGBuffer* aBuffer) = 0;
292 : virtual void SetPSTextures(uint32_t aSlot, uint32_t aNumTextures, TextureSource* const* aTextures) = 0;
293 : virtual void SetPSTexture(uint32_t aSlot, MLGTexture* aTexture) = 0;
294 : virtual void SetDepthTestMode(MLGDepthTestMode aMode) = 0;
295 :
296 : // If supported, bind constant buffers at a particular offset. These can only
297 : // be used if CanUseConstantBufferOffsetBinding returns true.
298 : virtual void SetVSConstantBuffer(uint32_t aSlot, MLGBuffer* aBuffer, uint32_t aFirstConstant, uint32_t aNumConstants) = 0;
299 : virtual void SetPSConstantBuffer(uint32_t aSlot, MLGBuffer* aBuffer, uint32_t aFirstConstant, uint32_t aNumConstants) = 0;
300 :
301 : // Set the topology. No API call is made if the topology has not changed.
302 : // The UnitQuad topology implicity binds a unit quad triangle strip as
303 : // vertex buffer #0.
304 : void SetTopology(MLGPrimitiveTopology aTopology);
305 :
306 : // Set textures that have special binding logic, and bind to multiple slots.
307 : virtual void SetPSTexturesNV12(uint32_t aSlot, TextureSource* aTexture) = 0;
308 : void SetPSTexturesYUV(uint32_t aSlot, TextureSource* aTexture);
309 :
310 : virtual RefPtr<MLGBuffer> CreateBuffer(
311 : MLGBufferType aType,
312 : uint32_t aSize,
313 : MLGUsage aUsage,
314 : const void* aInitialData = nullptr) = 0;
315 :
316 : virtual RefPtr<MLGTexture> CreateTexture(
317 : const gfx::IntSize& aSize,
318 : gfx::SurfaceFormat aFormat,
319 : MLGUsage aUsage,
320 : MLGTextureFlags aFlags) = 0;
321 :
322 : // Unwrap the underlying GPU texture in the given TextureSource, and re-wrap
323 : // it in an MLGTexture structure.
324 : virtual RefPtr<MLGTexture> CreateTexture(TextureSource* aSource) = 0;
325 :
326 : virtual RefPtr<MLGRenderTarget> CreateRenderTarget(
327 : const gfx::IntSize& aSize,
328 : MLGRenderTargetFlags aFlags = MLGRenderTargetFlags::Default) = 0;
329 :
330 : // Clear a render target to the given color, or clear a depth buffer.
331 : virtual void Clear(MLGRenderTarget* aRT, const gfx::Color& aColor) = 0;
332 : virtual void ClearDepthBuffer(MLGRenderTarget* aRT) = 0;
333 :
334 : // This is only available if CanUseClearView() returns true.
335 : virtual void ClearView(
336 : MLGRenderTarget* aRT,
337 : const gfx::Color& aColor,
338 : const gfx::IntRect* aRects,
339 : size_t aNumRects) = 0;
340 :
341 : // Drawing Commands
342 : virtual void Draw(uint32_t aVertexCount, uint32_t aOffset) = 0;
343 : virtual void DrawInstanced(uint32_t aVertexCountPerInstance, uint32_t aInstanceCount,
344 : uint32_t aVertexOffset, uint32_t aInstanceOffset) = 0;
345 : virtual void Flush() = 0;
346 :
347 : // This unlocks any textures that were implicitly locked during drawing.
348 : virtual void UnlockAllTextures() = 0;
349 :
350 0 : virtual MLGDeviceD3D11* AsD3D11() { return nullptr; }
351 :
352 : // Helpers.
353 : void SetVertexBuffer(uint32_t aSlot, const VertexBufferSection* aSection);
354 : void SetPSConstantBuffer(uint32_t aSlot, const ConstantBufferSection* aSection);
355 : void SetVSConstantBuffer(uint32_t aSlot, const ConstantBufferSection* aSection);
356 : void SetPSTexture(uint32_t aSlot, TextureSource* aSource);
357 : void SetSamplerMode(uint32_t aIndex, gfx::SamplingFilter aFilter);
358 :
359 : // This creates or returns a previously created constant buffer, containing
360 : // a YCbCrShaderConstants instance.
361 : RefPtr<MLGBuffer> GetBufferForColorSpace(YUVColorSpace aColorSpace);
362 :
363 : // A shared buffer that can be used to build VertexBufferSections.
364 0 : SharedVertexBuffer* GetSharedVertexBuffer() {
365 0 : return mSharedVertexBuffer.get();
366 : }
367 : // A shared buffer that can be used to build ConstantBufferSections. Intended
368 : // to be used with vertex shaders.
369 0 : SharedConstantBuffer* GetSharedVSBuffer() {
370 0 : return mSharedVSBuffer.get();
371 : }
372 : // A shared buffer that can be used to build ConstantBufferSections. Intended
373 : // to be used with pixel shaders.
374 0 : SharedConstantBuffer* GetSharedPSBuffer() {
375 0 : return mSharedPSBuffer.get();
376 : }
377 : // A cache for constant buffers, used when offset-based binding is not supported.
378 0 : BufferCache* GetConstantBufferCache() {
379 0 : return mConstantBufferCache.get();
380 : }
381 :
382 : // Unmap and upload all shared buffers to the GPU.
383 : void FinishSharedBufferUse();
384 :
385 : // These are used to detect and report initialization failure.
386 0 : virtual bool IsValid() const {
387 0 : return mInitialized && mIsValid;
388 : }
389 : const nsCString& GetFailureId() const {
390 : return mFailureId;
391 : }
392 : const nsCString& GetFailureMessage() const {
393 : return mFailureMessage;
394 : }
395 :
396 : // Prepare a clear-region operation to be run at a later time.
397 : void PrepareClearRegion(ClearRegionHelper* aOut,
398 : nsTArray<gfx::IntRect>&& aRects,
399 : const Maybe<int32_t>& aSortIndex);
400 :
401 : // Execute a clear-region operation. This may change shader state.
402 : void DrawClearRegion(const ClearRegionHelper& aHelper);
403 :
404 : // If supported, synchronize with the SyncObject given to clients.
405 : virtual bool Synchronize();
406 :
407 : // If this returns true, ClearView() can be called.
408 0 : bool CanUseClearView() const {
409 0 : return mCanUseClearView;
410 : }
411 :
412 : // If this returns true, constant buffers can be bound at specific offsets for
413 : // a given run of bytes. This is only supported on Windows 8+ for Direct3D 11.
414 0 : bool CanUseConstantBufferOffsetBinding() const {
415 0 : return mCanUseConstantBufferOffsetBinding;
416 : }
417 :
418 : // Return the maximum number of elements that can be bound to a constant
419 : // buffer. This is different than the maximum size of a buffer (there is
420 : // no such limit on Direct3D 11.1).
421 : //
422 : // The return value must be a power of two.
423 0 : size_t GetMaxConstantBufferBindSize() const {
424 0 : return mMaxConstantBufferBindSize;
425 : }
426 :
427 : protected:
428 : virtual ~MLGDevice();
429 :
430 : virtual void SetPrimitiveTopology(MLGPrimitiveTopology aTopology) = 0;
431 :
432 : // Optionally run a runtime test to determine if constant buffer offset
433 : // binding works.
434 0 : virtual bool VerifyConstantBufferOffsetting() {
435 0 : return true;
436 : }
437 :
438 : // Used during initialization to record failure reasons.
439 : bool Fail(const nsCString& aFailureId, const nsCString* aMessage);
440 :
441 : // Used during initialization to record failure reasons. Note: our
442 : // MOZ_FORMAT_PRINTF macro does not work on this function, so we
443 : // disable the warning.
444 : #if defined(__GNUC__)
445 : # pragma GCC diagnostic push
446 : # pragma GCC diagnostic ignored "-Wformat-security"
447 : #endif
448 : template <typename... T>
449 : bool Fail(const char* aFailureId) {
450 : nsCString failureId(aFailureId);
451 : return Fail(failureId, nullptr);
452 : }
453 : template <typename... T>
454 0 : bool Fail(const char* aFailureId,
455 : const char* aMessage,
456 : const T&... args)
457 : {
458 0 : nsCString failureId(aFailureId);
459 0 : nsPrintfCString message(aMessage, args...);
460 0 : return Fail(failureId, &message);
461 : }
462 : #if defined(__GNUC__)
463 : # pragma GCC diagnostic pop
464 : #endif
465 :
466 : void UnmapSharedBuffers();
467 :
468 : private:
469 : MLGPrimitiveTopology mTopology;
470 : UniquePtr<SharedVertexBuffer> mSharedVertexBuffer;
471 : UniquePtr<SharedConstantBuffer> mSharedVSBuffer;
472 : UniquePtr<SharedConstantBuffer> mSharedPSBuffer;
473 : UniquePtr<BufferCache> mConstantBufferCache;
474 :
475 : nsCString mFailureId;
476 : nsCString mFailureMessage;
477 : bool mInitialized;
478 :
479 : typedef EnumeratedArray<YUVColorSpace, YUVColorSpace::UNKNOWN, RefPtr<MLGBuffer>> ColorSpaceArray;
480 : ColorSpaceArray mColorSpaceBuffers;
481 :
482 : protected:
483 : bool mIsValid;
484 : bool mCanUseClearView;
485 : bool mCanUseConstantBufferOffsetBinding;
486 : size_t mMaxConstantBufferBindSize;
487 :
488 : RefPtr<MLGRenderTarget> mCurrentRT;
489 : };
490 :
491 : } // namespace layers
492 : } // namespace mozilla
493 :
494 : #endif // mozilla_gfx_layers_mlgpu_MLGDevice_h
|