IMFYCbCrImage.cpp (4370B)
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 #include "IMFYCbCrImage.h" 8 #include "mozilla/gfx/DeviceManagerDx.h" 9 #include "mozilla/gfx/gfxVars.h" 10 #include "mozilla/gfx/Types.h" 11 #include "mozilla/layers/TextureD3D11.h" 12 #include "mozilla/layers/CompositableClient.h" 13 #include "mozilla/layers/CompositableForwarder.h" 14 #include "mozilla/layers/D3D11YCbCrImage.h" 15 #include "mozilla/layers/FenceD3D11.h" 16 #include "mozilla/layers/CompositeProcessD3D11FencesHolderMap.h" 17 #include "mozilla/layers/TextureClient.h" 18 19 namespace mozilla { 20 namespace layers { 21 22 IMFYCbCrImage::IMFYCbCrImage(IMFMediaBuffer* aBuffer, IMF2DBuffer* a2DBuffer, 23 KnowsCompositor* aKnowsCompositor, 24 ImageContainer* aContainer) 25 : RecyclingPlanarYCbCrImage(nullptr), 26 mBuffer(aBuffer), 27 m2DBuffer(a2DBuffer) { 28 mAllocator = aContainer->GetD3D11YCbCrRecycleAllocator(aKnowsCompositor); 29 } 30 31 IMFYCbCrImage::~IMFYCbCrImage() { 32 if (m2DBuffer) { 33 m2DBuffer->Unlock2D(); 34 } else { 35 mBuffer->Unlock(); 36 } 37 } 38 39 /* static */ 40 bool IMFYCbCrImage::CopyDataToTexture(const Data& aData, ID3D11Device* aDevice, 41 DXGIYCbCrTextureData* aTextureData) { 42 MOZ_ASSERT(aTextureData); 43 44 if (!gfx::DeviceManagerDx::Get()->CanInitializeKeyedMutexTextures()) { 45 return false; 46 } 47 48 ID3D11Texture2D* textureY = aTextureData->GetD3D11Texture(0); 49 ID3D11Texture2D* textureCb = aTextureData->GetD3D11Texture(1); 50 ID3D11Texture2D* textureCr = aTextureData->GetD3D11Texture(2); 51 52 RefPtr<ID3D11DeviceContext> ctx; 53 aDevice->GetImmediateContext(getter_AddRefs(ctx)); 54 if (!ctx) { 55 gfxCriticalError() << "Failed to get immediate context."; 56 return false; 57 } 58 59 D3D11_BOX box; 60 box.front = box.top = box.left = 0; 61 box.back = 1; 62 box.right = aData.YDataSize().width; 63 box.bottom = aData.YDataSize().height; 64 ctx->UpdateSubresource(textureY, 0, &box, aData.mYChannel, aData.mYStride, 0); 65 66 box.right = aData.CbCrDataSize().width; 67 box.bottom = aData.CbCrDataSize().height; 68 ctx->UpdateSubresource(textureCb, 0, &box, aData.mCbChannel, 69 aData.mCbCrStride, 0); 70 ctx->UpdateSubresource(textureCr, 0, &box, aData.mCrChannel, 71 aData.mCbCrStride, 0); 72 73 auto* fenceHolderMap = CompositeProcessD3D11FencesHolderMap::Get(); 74 if (!fenceHolderMap) { 75 MOZ_ASSERT_UNREACHABLE("unexpected to be called"); 76 return false; 77 } 78 79 aTextureData->mWriteFence->IncrementAndSignal(); 80 fenceHolderMap->SetWriteFence(aTextureData->mFencesHolderId, 81 aTextureData->mWriteFence); 82 83 return true; 84 } 85 86 TextureClient* IMFYCbCrImage::GetD3D11TextureClient( 87 KnowsCompositor* aKnowsCompositor) { 88 if (!mAllocator) { 89 return nullptr; 90 } 91 92 auto* fenceHolderMap = CompositeProcessD3D11FencesHolderMap::Get(); 93 if (!fenceHolderMap) { 94 MOZ_ASSERT_UNREACHABLE("unexpected to be called"); 95 return nullptr; 96 } 97 98 RefPtr<ID3D11Device> device = gfx::DeviceManagerDx::Get()->GetImageDevice(); 99 if (!device) { 100 return nullptr; 101 } 102 103 { 104 DXGIYCbCrTextureAllocationHelper helper(mData, TextureFlags::DEFAULT, 105 device); 106 mTextureClient = mAllocator->CreateOrRecycle(helper).unwrapOr(nullptr); 107 } 108 109 if (!mTextureClient) { 110 return nullptr; 111 } 112 113 DXGIYCbCrTextureData* data = 114 mTextureClient->GetInternalData()->AsDXGIYCbCrTextureData(); 115 116 if (!fenceHolderMap->WaitAllFencesAndForget(data->mFencesHolderId, device)) { 117 return nullptr; 118 } 119 120 if (!CopyDataToTexture(mData, device, data)) { 121 // Failed to copy data 122 mTextureClient = nullptr; 123 return nullptr; 124 } 125 126 return mTextureClient; 127 } 128 129 TextureClient* IMFYCbCrImage::GetTextureClient( 130 KnowsCompositor* aKnowsCompositor) { 131 if (mTextureClient) { 132 return mTextureClient; 133 } 134 135 RefPtr<ID3D11Device> device = gfx::DeviceManagerDx::Get()->GetImageDevice(); 136 if (!device || !aKnowsCompositor->SupportsD3D11()) { 137 return nullptr; 138 } 139 return GetD3D11TextureClient(aKnowsCompositor); 140 } 141 142 } // namespace layers 143 } // namespace mozilla