Coverage Report

Created: 2018-09-25 14:53

/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