TextureD3D11.h (19970B)
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_TEXTURED3D11_H 8 #define MOZILLA_GFX_TEXTURED3D11_H 9 10 #include <d3d11.h> 11 #include <d3d11_1.h> 12 #include <vector> 13 14 #include "d3d9.h" 15 #include "gfxWindowsPlatform.h" 16 #include "mozilla/DataMutex.h" 17 #include "mozilla/GfxMessageUtils.h" 18 #include "mozilla/Maybe.h" 19 #include "mozilla/gfx/2D.h" 20 #include "mozilla/layers/Compositor.h" 21 #include "mozilla/layers/SyncObject.h" 22 #include "mozilla/layers/TextureClient.h" 23 #include "mozilla/layers/TextureHost.h" 24 25 namespace mozilla { 26 27 namespace gfx { 28 class FileHandleWrapper; 29 } // namespace gfx 30 31 namespace gl { 32 class GLBlitHelper; 33 } 34 35 namespace layers { 36 37 class FenceD3D11; 38 39 gfx::DeviceResetReason DXGIErrorToDeviceResetReason(HRESULT aError); 40 41 already_AddRefed<TextureHost> CreateTextureHostD3D11( 42 const SurfaceDescriptor& aDesc, ISurfaceAllocator* aDeallocator, 43 LayersBackend aBackend, TextureFlags aFlags); 44 45 class MOZ_RAII AutoTextureLock final { 46 public: 47 AutoTextureLock(IDXGIKeyedMutex* aMutex, HRESULT& aResult, 48 uint32_t aTimeout = 0); 49 ~AutoTextureLock(); 50 51 private: 52 RefPtr<IDXGIKeyedMutex> mMutex; 53 HRESULT mResult; 54 }; 55 56 class CompositorD3D11; 57 class ZeroCopyUsageInfo; 58 class VideoProcessorD3D11; 59 60 class D3D11TextureData final : public TextureData { 61 public: 62 // If aDevice is null, use one provided by gfxWindowsPlatform. 63 static D3D11TextureData* Create(gfx::IntSize aSize, 64 gfx::SurfaceFormat aFormat, 65 TextureAllocationFlags aAllocFlags, 66 ID3D11Device* aDevice = nullptr); 67 68 static already_AddRefed<TextureClient> CreateTextureClient( 69 ID3D11Texture2D* aTexture, uint32_t aIndex, gfx::IntSize aSize, 70 gfx::SurfaceFormat aFormat, gfx::ColorSpace2 aColorSpace, 71 gfx::ColorRange aColorRange, KnowsCompositor* aKnowsCompositor, 72 RefPtr<ZeroCopyUsageInfo> aUsageInfo, 73 const RefPtr<FenceD3D11> aWriteFence); 74 75 virtual ~D3D11TextureData(); 76 77 bool UpdateFromSurface(gfx::SourceSurface* aSurface) override; 78 79 bool Lock(OpenMode aMode) override; 80 81 void Unlock() override; 82 83 already_AddRefed<gfx::DrawTarget> BorrowDrawTarget() override; 84 85 TextureData* CreateSimilar(LayersIPCChannel* aAllocator, 86 LayersBackend aLayersBackend, TextureFlags aFlags, 87 TextureAllocationFlags aAllocFlags) const override; 88 89 void SyncWithObject(RefPtr<SyncObjectClient> aSyncObject) override; 90 91 ID3D11Texture2D* GetD3D11Texture() const { return mTexture; } 92 93 void Deallocate(LayersIPCChannel* aAllocator) override; 94 95 D3D11TextureData* AsD3D11TextureData() override { return this; } 96 97 TextureAllocationFlags GetTextureAllocationFlags() const { 98 return mAllocationFlags; 99 } 100 101 TextureType GetTextureType() const override { return TextureType::D3D11; } 102 103 void FillInfo(TextureData::Info& aInfo) const override; 104 105 bool Serialize(SurfaceDescriptor& aOutDescrptor) override; 106 void GetSubDescriptor(RemoteDecoderVideoSubDescriptor* aOutDesc) override; 107 108 gfx::ColorRange GetColorRange() const { return mColorRange; } 109 void SetColorRange(gfx::ColorRange aColorRange) { mColorRange = aColorRange; } 110 111 gfx::IntSize GetSize() const { return mSize; } 112 gfx::SurfaceFormat GetSurfaceFormat() const { return mFormat; } 113 114 TextureFlags GetTextureFlags() const override; 115 116 void SetGpuProcessTextureId(GpuProcessTextureId aTextureId) { 117 mGpuProcessTextureId = Some(aTextureId); 118 } 119 120 Maybe<GpuProcessTextureId> GetGpuProcessTextureId() { 121 return mGpuProcessTextureId; 122 } 123 124 void IncrementAndSignalWriteFence(); 125 126 private: 127 D3D11TextureData(ID3D11Device* aDevice, ID3D11Texture2D* aTexture, 128 uint32_t aArrayIndex, 129 RefPtr<gfx::FileHandleWrapper> aSharedHandle, 130 gfx::IntSize aSize, gfx::SurfaceFormat aFormat, 131 const Maybe<CompositeProcessFencesHolderId> aFencesHolderId, 132 const RefPtr<FenceD3D11> aWriteFence, 133 TextureAllocationFlags aFlags); 134 135 friend class gl::GLBlitHelper; 136 bool SerializeSpecific(SurfaceDescriptorD3D10* aOutDesc); 137 138 static D3D11TextureData* Create(gfx::IntSize aSize, 139 gfx::SurfaceFormat aFormat, 140 gfx::SourceSurface* aSurface, 141 TextureAllocationFlags aAllocFlags, 142 ID3D11Device* aDevice = nullptr); 143 144 public: 145 const gfx::IntSize mSize; 146 const gfx::SurfaceFormat mFormat; 147 const bool mHasKeyedMutex; 148 const Maybe<CompositeProcessFencesHolderId> mFencesHolderId; 149 const RefPtr<FenceD3D11> mWriteFence; 150 gfx::ColorSpace2 mColorSpace = gfx::ColorSpace2::SRGB; 151 152 private: 153 gfx::ColorRange mColorRange = gfx::ColorRange::LIMITED; 154 bool mNeedsClear = false; 155 156 const RefPtr<ID3D11Device> mDevice; 157 RefPtr<ID3D11Texture2D> mTexture; 158 const RefPtr<gfx::FileHandleWrapper> mSharedHandle; 159 Maybe<GpuProcessTextureId> mGpuProcessTextureId; 160 uint32_t mArrayIndex = 0; 161 const TextureAllocationFlags mAllocationFlags; 162 }; 163 164 class DXGIYCbCrTextureData : public TextureData { 165 friend class gl::GLBlitHelper; 166 167 public: 168 static DXGIYCbCrTextureData* Create(ID3D11Texture2D* aTextureCb, 169 ID3D11Texture2D* aTextureY, 170 ID3D11Texture2D* aTextureCr, 171 const gfx::IntSize& aSize, 172 const gfx::IntSize& aSizeY, 173 const gfx::IntSize& aSizeCbCr, 174 const gfx::ColorDepth aColorDepth, 175 const gfx::YUVColorSpace aYUVColorSpace, 176 const gfx::ColorRange aColorRange); 177 178 bool Lock(OpenMode) override { return true; } 179 180 void Unlock() override {} 181 182 void FillInfo(TextureData::Info& aInfo) const override; 183 184 void SerializeSpecific(SurfaceDescriptorDXGIYCbCr* aOutDesc); 185 bool Serialize(SurfaceDescriptor& aOutDescriptor) override; 186 void GetSubDescriptor(RemoteDecoderVideoSubDescriptor* aOutDesc) override; 187 188 already_AddRefed<gfx::DrawTarget> BorrowDrawTarget() override { 189 return nullptr; 190 } 191 192 void Deallocate(LayersIPCChannel* aAllocator) override; 193 194 bool UpdateFromSurface(gfx::SourceSurface*) override { return false; } 195 196 TextureFlags GetTextureFlags() const override; 197 198 DXGIYCbCrTextureData* AsDXGIYCbCrTextureData() override { return this; } 199 200 ID3D11Texture2D* GetD3D11Texture(size_t index) { 201 return mD3D11Textures[index]; 202 } 203 204 const gfx::IntSize mSize; 205 const gfx::IntSize mSizeY; 206 const gfx::IntSize mSizeCbCr; 207 const gfx::ColorDepth mColorDepth; 208 const gfx::YUVColorSpace mYUVColorSpace; 209 const gfx::ColorRange mColorRange; 210 const CompositeProcessFencesHolderId mFencesHolderId; 211 const RefPtr<FenceD3D11> mWriteFence; 212 213 protected: 214 DXGIYCbCrTextureData(RefPtr<ID3D11Texture2D> (&aD3D11Textures)[3], 215 RefPtr<gfx::FileHandleWrapper>(aHandles)[3], 216 const gfx::IntSize& aSize, const gfx::IntSize& aSizeY, 217 const gfx::IntSize& aSizeCbCr, 218 const gfx::ColorDepth aColorDepth, 219 const gfx::YUVColorSpace aYUVColorSpace, 220 const gfx::ColorRange aColorRange, 221 const CompositeProcessFencesHolderId aFencesHolderId, 222 const RefPtr<FenceD3D11> aWriteFence); 223 virtual ~DXGIYCbCrTextureData(); 224 225 RefPtr<ID3D11Texture2D> mD3D11Textures[3]; 226 RefPtr<gfx::FileHandleWrapper> mHandles[3]; 227 }; 228 229 /** 230 * TextureSource that provides with the necessary APIs to be composited by a 231 * CompositorD3D11. 232 */ 233 class TextureSourceD3D11 { 234 public: 235 TextureSourceD3D11() : mFormatOverride(DXGI_FORMAT_UNKNOWN) {} 236 virtual ~TextureSourceD3D11() = default; 237 238 virtual ID3D11Texture2D* GetD3D11Texture() const { return mTexture; } 239 virtual ID3D11ShaderResourceView* GetShaderResourceView(); 240 241 protected: 242 virtual gfx::IntSize GetSize() const { return mSize; } 243 244 gfx::IntSize mSize; 245 RefPtr<ID3D11Texture2D> mTexture; 246 RefPtr<ID3D11ShaderResourceView> mSRV; 247 DXGI_FORMAT mFormatOverride; 248 }; 249 250 /** 251 * A TextureSource that implements the DataTextureSource interface. 252 * it can be used without a TextureHost and is able to upload texture data 253 * from a gfx::DataSourceSurface. 254 */ 255 class DataTextureSourceD3D11 : public DataTextureSource, 256 public TextureSourceD3D11, 257 public BigImageIterator { 258 public: 259 /// Constructor allowing the texture to perform texture uploads. 260 /// 261 /// The texture can be used as an actual DataTextureSource. 262 DataTextureSourceD3D11(ID3D11Device* aDevice, gfx::SurfaceFormat aFormat, 263 TextureFlags aFlags); 264 265 /// Constructor for textures created around DXGI shared handles, disallowing 266 /// texture uploads. 267 /// 268 /// The texture CANNOT be used as a DataTextureSource. 269 DataTextureSourceD3D11(ID3D11Device* aDevice, gfx::SurfaceFormat aFormat, 270 ID3D11Texture2D* aTexture); 271 272 DataTextureSourceD3D11(gfx::SurfaceFormat aFormat, 273 TextureSourceProvider* aProvider, 274 ID3D11Texture2D* aTexture); 275 DataTextureSourceD3D11(gfx::SurfaceFormat aFormat, 276 TextureSourceProvider* aProvider, TextureFlags aFlags); 277 278 virtual ~DataTextureSourceD3D11(); 279 280 const char* Name() const override { return "DataTextureSourceD3D11"; } 281 282 // DataTextureSource 283 284 bool Update(gfx::DataSourceSurface* aSurface, 285 nsIntRegion* aDestRegion = nullptr, 286 gfx::IntPoint* aSrcOffset = nullptr, 287 gfx::IntPoint* aDstOffset = nullptr) override; 288 289 // TextureSource 290 291 TextureSourceD3D11* AsSourceD3D11() override { return this; } 292 293 ID3D11Texture2D* GetD3D11Texture() const override; 294 295 ID3D11ShaderResourceView* GetShaderResourceView() override; 296 297 // Returns nullptr if this texture was created by a DXGI TextureHost. 298 DataTextureSource* AsDataTextureSource() override { 299 return mAllowTextureUploads ? this : nullptr; 300 } 301 302 void DeallocateDeviceData() override { mTexture = nullptr; } 303 304 gfx::IntSize GetSize() const override { return mSize; } 305 306 gfx::SurfaceFormat GetFormat() const override { return mFormat; } 307 308 // BigImageIterator 309 310 BigImageIterator* AsBigImageIterator() override { 311 return mIsTiled ? this : nullptr; 312 } 313 314 size_t GetTileCount() override { return mTileTextures.size(); } 315 316 bool NextTile() override { return (++mCurrentTile < mTileTextures.size()); } 317 318 gfx::IntRect GetTileRect() override; 319 320 void EndBigImageIteration() override { mIterating = false; } 321 322 void BeginBigImageIteration() override { 323 mIterating = true; 324 mCurrentTile = 0; 325 } 326 327 RefPtr<TextureSource> ExtractCurrentTile() override; 328 329 void Reset(); 330 331 protected: 332 gfx::IntRect GetTileRect(uint32_t aIndex) const; 333 334 std::vector<RefPtr<ID3D11Texture2D>> mTileTextures; 335 std::vector<RefPtr<ID3D11ShaderResourceView>> mTileSRVs; 336 RefPtr<ID3D11Device> mDevice; 337 gfx::SurfaceFormat mFormat; 338 TextureFlags mFlags; 339 uint32_t mCurrentTile; 340 bool mIsTiled; 341 bool mIterating; 342 // Sadly, the code was originally organized so that this class is used both in 343 // the cases where we want to perform texture uploads through the 344 // DataTextureSource interface, and the cases where we wrap the texture around 345 // an existing DXGI handle in which case we should not use it as a 346 // DataTextureSource. This member differentiates the two scenarios. When it is 347 // false the texture "pretends" to not be a DataTextureSource. 348 bool mAllowTextureUploads; 349 }; 350 351 /** 352 * A TextureHost for shared D3D11 textures. 353 */ 354 class DXGITextureHostD3D11 : public TextureHost { 355 public: 356 DXGITextureHostD3D11(TextureFlags aFlags, 357 const SurfaceDescriptorD3D10& aDescriptor); 358 ~DXGITextureHostD3D11() override; 359 360 void DeallocateDeviceData() override {} 361 362 gfx::SurfaceFormat GetFormat() const override { return mFormat; } 363 364 gfx::IntSize GetSize() const override { return mSize; } 365 gfx::ColorRange GetColorRange() const override { return mColorRange; } 366 367 already_AddRefed<gfx::DataSourceSurface> GetAsSurface( 368 gfx::DataSourceSurface* aSurface) override; 369 370 // Return DataSourceSurface using aDevice withou readback to CPU. 371 already_AddRefed<gfx::DataSourceSurface> GetAsSurfaceWithDevice( 372 ID3D11Device* const aDevice); 373 374 void CreateRenderTexture( 375 const wr::ExternalImageId& aExternalImageId) override; 376 377 uint32_t NumSubTextures() override; 378 379 void PushResourceUpdates(wr::TransactionBuilder& aResources, 380 ResourceUpdateOp aOp, 381 const Range<wr::ImageKey>& aImageKeys, 382 const wr::ExternalImageId& aExtID) override; 383 384 void PushDisplayItems(wr::DisplayListBuilder& aBuilder, 385 const wr::LayoutRect& aBounds, 386 const wr::LayoutRect& aClip, wr::ImageRendering aFilter, 387 const Range<wr::ImageKey>& aImageKeys, 388 PushDisplayItemFlagSet aFlags) override; 389 390 bool SupportsExternalCompositing(WebRenderBackend aBackend) override; 391 392 DXGITextureHostD3D11* AsDXGITextureHostD3D11() override { return this; } 393 394 void NotifyNotUsed() override; 395 396 void SetReadFence(Fence* aReadFence) override; 397 398 const RefPtr<gfx::FileHandleWrapper> mHandle; 399 const Maybe<GpuProcessTextureId> mGpuProcessTextureId; 400 const uint32_t mArrayIndex; 401 const gfx::IntSize mSize; 402 const gfx::SurfaceFormat mFormat; 403 const bool mHasKeyedMutex; 404 const Maybe<CompositeProcessFencesHolderId> mFencesHolderId; 405 const gfx::ColorSpace2 mColorSpace; 406 const gfx::ColorRange mColorRange; 407 408 protected: 409 RefPtr<FenceD3D11> mReadFence; 410 }; 411 412 class DXGIYCbCrTextureHostD3D11 : public TextureHost { 413 public: 414 DXGIYCbCrTextureHostD3D11(TextureFlags aFlags, 415 const SurfaceDescriptorDXGIYCbCr& aDescriptor); 416 ~DXGIYCbCrTextureHostD3D11() override; 417 418 void DeallocateDeviceData() override {} 419 420 gfx::SurfaceFormat GetFormat() const override { 421 return gfx::SurfaceFormat::YUV420; 422 } 423 424 gfx::ColorDepth GetColorDepth() const override { return mColorDepth; } 425 gfx::YUVColorSpace GetYUVColorSpace() const override { 426 return mYUVColorSpace; 427 } 428 gfx::ColorRange GetColorRange() const override { return mColorRange; } 429 430 gfx::IntSize GetSize() const override { return mSize; } 431 432 already_AddRefed<gfx::DataSourceSurface> GetAsSurface( 433 gfx::DataSourceSurface* aSurface) override { 434 return nullptr; 435 } 436 437 void CreateRenderTexture( 438 const wr::ExternalImageId& aExternalImageId) override; 439 440 uint32_t NumSubTextures() override; 441 442 void PushResourceUpdates(wr::TransactionBuilder& aResources, 443 ResourceUpdateOp aOp, 444 const Range<wr::ImageKey>& aImageKeys, 445 const wr::ExternalImageId& aExtID) override; 446 447 void PushDisplayItems(wr::DisplayListBuilder& aBuilder, 448 const wr::LayoutRect& aBounds, 449 const wr::LayoutRect& aClip, wr::ImageRendering aFilter, 450 const Range<wr::ImageKey>& aImageKeys, 451 PushDisplayItemFlagSet aFlags) override; 452 453 bool SupportsExternalCompositing(WebRenderBackend aBackend) override; 454 455 void NotifyNotUsed() override; 456 457 DXGIYCbCrTextureHostD3D11* AsDXGIYCbCrTextureHostD3D11() override { 458 return this; 459 } 460 461 void SetReadFence(Fence* aReadFence) override; 462 463 // Handles will be closed automatically when `UniqueFileHandle` gets 464 // destroyed. 465 const RefPtr<gfx::FileHandleWrapper> mHandles[3]; 466 const gfx::IntSize mSize; 467 const gfx::IntSize mSizeY; 468 const gfx::IntSize mSizeCbCr; 469 const gfx::ColorDepth mColorDepth; 470 const gfx::YUVColorSpace mYUVColorSpace; 471 const gfx::ColorRange mColorRange; 472 const CompositeProcessFencesHolderId mFencesHolderId; 473 474 protected: 475 bool mIsLocked = false; 476 RefPtr<FenceD3D11> mReadFence; 477 }; 478 479 class CompositingRenderTargetD3D11 : public CompositingRenderTarget, 480 public TextureSourceD3D11 { 481 public: 482 CompositingRenderTargetD3D11( 483 ID3D11Texture2D* aTexture, const gfx::IntPoint& aOrigin, 484 DXGI_FORMAT aFormatOverride = DXGI_FORMAT_UNKNOWN); 485 486 const char* Name() const override { return "CompositingRenderTargetD3D11"; } 487 488 TextureSourceD3D11* AsSourceD3D11() override { return this; } 489 490 void BindRenderTarget(ID3D11DeviceContext* aContext); 491 492 gfx::IntSize GetSize() const override; 493 494 void SetSize(const gfx::IntSize& aSize) { mSize = aSize; } 495 496 private: 497 friend class CompositorD3D11; 498 RefPtr<ID3D11RenderTargetView> mRTView; 499 }; 500 501 class SyncObjectD3D11Host : public SyncObjectHost { 502 public: 503 explicit SyncObjectD3D11Host(ID3D11Device* aDevice); 504 505 bool Init() override; 506 507 SyncHandle GetSyncHandle() override; 508 509 bool Synchronize(bool aFallible) override; 510 511 IDXGIKeyedMutex* GetKeyedMutex() { return mKeyedMutex.get(); }; 512 513 private: 514 virtual ~SyncObjectD3D11Host() = default; 515 516 SyncHandle mSyncHandle; 517 RefPtr<ID3D11Device> mDevice; 518 RefPtr<IDXGIResource1> mSyncTexture; 519 RefPtr<IDXGIKeyedMutex> mKeyedMutex; 520 }; 521 522 class SyncObjectD3D11Client : public SyncObjectClient { 523 public: 524 SyncObjectD3D11Client(SyncHandle aSyncHandle, ID3D11Device* aDevice); 525 526 bool Synchronize(bool aFallible) override; 527 528 bool IsSyncObjectValid() override; 529 530 void EnsureInitialized() override {} 531 532 SyncType GetSyncType() override { return SyncType::D3D11; } 533 534 void RegisterTexture(ID3D11Texture2D* aTexture); 535 536 protected: 537 explicit SyncObjectD3D11Client(SyncHandle aSyncHandle); 538 bool Init(ID3D11Device* aDevice, bool aFallible); 539 bool SynchronizeInternal(ID3D11Device* aDevice, bool aFallible); 540 Mutex mSyncLock MOZ_UNANNOTATED; 541 RefPtr<ID3D11Texture2D> mSyncTexture; 542 std::vector<ID3D11Texture2D*> mSyncedTextures; 543 544 private: 545 SyncHandle mSyncHandle; 546 RefPtr<IDXGIKeyedMutex> mKeyedMutex; 547 const RefPtr<ID3D11Device> mDevice; 548 }; 549 550 class SyncObjectD3D11ClientContentDevice : public SyncObjectD3D11Client { 551 public: 552 explicit SyncObjectD3D11ClientContentDevice(SyncHandle aSyncHandle); 553 554 bool Synchronize(bool aFallible) override; 555 556 bool IsSyncObjectValid() override; 557 558 void EnsureInitialized() override; 559 560 private: 561 RefPtr<ID3D11Device> mContentDevice; 562 }; 563 564 inline uint32_t GetMaxTextureSizeForFeatureLevel( 565 D3D_FEATURE_LEVEL aFeatureLevel) { 566 int32_t maxTextureSize; 567 switch (aFeatureLevel) { 568 case D3D_FEATURE_LEVEL_11_1: 569 case D3D_FEATURE_LEVEL_11_0: 570 maxTextureSize = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; 571 break; 572 case D3D_FEATURE_LEVEL_10_1: 573 case D3D_FEATURE_LEVEL_10_0: 574 maxTextureSize = D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; 575 break; 576 case D3D_FEATURE_LEVEL_9_3: 577 maxTextureSize = D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; 578 break; 579 default: 580 maxTextureSize = D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; 581 } 582 return maxTextureSize; 583 } 584 585 uint32_t GetMaxTextureSizeFromDevice(ID3D11Device* aDevice); 586 void ReportTextureMemoryUsage(ID3D11Texture2D* aTexture, size_t aBytes); 587 588 class AutoLockD3D11Texture { 589 public: 590 explicit AutoLockD3D11Texture(ID3D11Texture2D* aTexture); 591 ~AutoLockD3D11Texture(); 592 593 private: 594 RefPtr<IDXGIKeyedMutex> mMutex; 595 }; 596 597 class D3D11MTAutoEnter { 598 public: 599 explicit D3D11MTAutoEnter(already_AddRefed<ID3D10Multithread> aMT) 600 : mMT(aMT) { 601 if (mMT) { 602 mMT->Enter(); 603 } 604 } 605 ~D3D11MTAutoEnter() { 606 if (mMT) { 607 mMT->Leave(); 608 } 609 } 610 611 private: 612 RefPtr<ID3D10Multithread> mMT; 613 }; 614 615 } // namespace layers 616 } // namespace mozilla 617 618 #endif /* MOZILLA_GFX_TEXTURED3D11_H */