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