Closed Bug 875247 Opened 12 years ago Closed 10 years ago

Add DXVA2 support via D3D11 for OMTC

Categories

(Core :: Graphics: Layers, defect)

x86
Windows 8
defect
Not set
normal

Tracking

()

VERIFIED FIXED
mozilla40
Tracking Status
firefox38 --- ?
firefox39 + wontfix
firefox40 + verified

People

(Reporter: cpearce, Assigned: mattwoodrow)

References

Details

Attachments

(2 files, 2 obsolete files)

We'll need to use DXVA2 via D3D11 if we want to not do readback when we turn on OMTC on Windows.
Attached patch WIP patch (obsolete) (deleted) — Splinter Review
Bas: how does this approach look?
Attachment #753194 - Flags: feedback?(bas)
Component: Video/Audio → Graphics: Layers
Here's some background on this from Chris & ajones: -------------------- In order to get OMTC on Windows 7 or Vista we will need D3D9 implementation of ImageClient otherwise we will get a performance regression for video decoding. The performance regression is in the form of GPU read-back and re-upload on each video frame, since now that we have DXVA hardware accelerated H.264 video decoding via D3D9, decoded video frames are stored in D3D9 surfaces in GPU memory. Windows Vista/7 may support D3D11 but they don't support DXVA via D3D11. Support for DXVA via D3D11 is rumoured for Windows 7 but not currently available. On Windows 8 we can use DXVA via D3D11 but that still leaves is without a solution for Windows 7 and Vista. This solution by itself isn't satisfactory because it still leaves us with poor performance on Vista and for some period of time on Windows 7. --------------------
(In reply to Milan Sreckovic [:milan] from comment #2) > Here's some background on this from Chris & ajones: > -------------------- > In order to get OMTC on Windows 7 or Vista we will need D3D9 > implementation of ImageClient otherwise we will get a performance > regression for video decoding. The performance regression is in the form > of GPU read-back and re-upload on each video frame, since now that we > have DXVA hardware accelerated H.264 video decoding via D3D9, decoded > video frames are stored in D3D9 surfaces in GPU memory. Windows Vista/7 > may support D3D11 but they don't support DXVA via D3D11. Support for > DXVA via D3D11 is rumoured for Windows 7 but not currently available. More precisely, we want TextureClient/TextureHost implementations of shared D3D textures (but we already have this, don't we?). With Bug 858914, if the Image that is passed to the ImageClient uses a TextureClient under the hood and exposes AsTextureClient(), everything is synchronized with the compositor side without extra readback automatically. I am still working on this patch I am referring to, though.
Attachment #753194 - Flags: feedback?(bas) → review?(bas)
Comment on attachment 753194 [details] [diff] [review] WIP patch Review of attachment 753194 [details] [diff] [review]: ----------------------------------------------------------------- Not the most thorough review I've ever done, but we don't use this code at that many places and we seem to be in a hurry with it. And it looks like it should get the job done for now. ::: content/media/wmf/DXVA2Manager.cpp @@ +234,5 @@ > + UINT *pResetToken, > + IMFDXGIDeviceManager **ppDXVAManager > +); > + > +typedef HRESULT (WINAPI*D3D11CreateDeviceAndSwapChainFunc)( I don't think we need a swap chain here? @@ +253,5 @@ > +D3D11DXVA2Manager::Init() > +{ > + HRESULT hr; > + > + mDevice = gfxWindowsPlatform::GetPlatform()->GetD3D11Device(); If we're using the platform device (which is good!), why are we typedeffing CreateDevice here? @@ +259,5 @@ > + > + mDevice->GetImmediateContext(byRef(mContext)); > + NS_ENSURE_TRUE(mContext, E_FAIL); > + > + HMODULE mfplatlib = LoadLibraryW(L"mfplat.dll"); I don't really like leaking more than one reference to this library, although it's not a big problem I suppose. ::: content/media/wmf/WMFUtils.cpp @@ +358,5 @@ > > #define ENSURE_FUNCTION_PTR(FunctionName, DLL) \ > static FunctionName##Ptr_t FunctionName##Ptr = nullptr; \ > if (!FunctionName##Ptr) { \ > + FunctionName##Ptr = (FunctionName##Ptr_t)GetProcAddress(GetModuleHandle( L#DLL ), #FunctionName ); \ Should be explicitly use GetModuleHandleW if we make this change? As not to break when UNICODE might be !defined. ::: gfx/layers/D3D11ShareHandleImage.cpp @@ +39,5 @@ > + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; > + desc.CPUAccessFlags = 0; > + desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX; > + > + nsRefPtr<ID3D11Texture2D> sharableTexture; Please use RefPtr here as well for consistency. @@ +97,5 @@ > +already_AddRefed<gfxASurface> > +D3D11ShareHandleImage::GetAsSurface() > +{ > + HRESULT hr; > + nsRefPtr<ID3D11Device> device = GetD3D11Device returns TemporaryRef I believe so here we should really use RefPtr. ::: gfx/layers/client/ImageClient.cpp @@ +197,5 @@ > + SurfaceDescriptor desc = static_cast<D3D11ShareHandleImage*>(image)->GetSurfaceDescriptor(); > + if (!IsSurfaceDescriptorValid(desc)) { > + return false; > + } > + mTextureClient->SetDescriptor(desc); This is not really how we want D3D11 texture clients to work. But it'll have to do for now. ::: gfx/thebes/gfxWindowsPlatform.h @@ +47,1 @@ > class IDXGIAdapter1; While you're at it do IDXGIAdapter1 as well then ;-).
Attachment #753194 - Flags: review?(bas) → review+
Updated to reflect Bas' review comments. Nick: Can you check my changes to WMFReader::InitilizeDXVA() to ensure that my logic to only use DXVA2/D3D11 on Windows 8 when OMTC is enabled is correct?
Attachment #787797 - Flags: review+
Attachment #787797 - Flags: feedback?(ncameron)
Comment on attachment 787797 [details] [diff] [review] Patch: Use DXVA via D3D11 on Windows 8 gps: Can you look over the moz.build/Makefile.in changes in this patch please?
Attachment #787797 - Flags: review?(gps)
Attachment #753194 - Attachment is obsolete: true
Comment on attachment 787797 [details] [diff] [review] Patch: Use DXVA via D3D11 on Windows 8 Paul: Can you look over the changes in this patch to content/media*? Thanks!
Attachment #787797 - Flags: review?(paul)
Comment on attachment 787797 [details] [diff] [review] Patch: Use DXVA via D3D11 on Windows 8 Review of attachment 787797 [details] [diff] [review]: ----------------------------------------------------------------- ::: content/media/wmf/WMFReader.cpp @@ +137,5 @@ > + } else if (layerManager->GetBackendType() == LayersBackend::LAYERS_D3D9 || > + layerManager->GetBackendType() == LayersBackend::LAYERS_D3D10) { > + mDXVA2Manager = DXVA2Manager::CreateD3D9DXVA(); > + NS_ENSURE_TRUE_VOID(mDXVA2Manager); > + mVideoDecodingMode = VideoDecodingMode::DXVA_D3D9; What if we have OMTC d3d9? Or OMTC d3d11 on Win 7?
Attachment #787797 - Flags: feedback?(ncameron)
I'd assume for OMTC D3D9 we'd need a new image client (which we should do in a new bug). We can't use DXVA2 via D3D11 on Win7, as the critical function to initialize it (MFCreateDXGIDeviceManager) only exists on Win8. We'd need to use a D3D9 image client for Win7+D3D11 I guess.
Attachment #787797 - Flags: review?(paul) → review+
Comment on attachment 787797 [details] [diff] [review] Patch: Use DXVA via D3D11 on Windows 8 Review of attachment 787797 [details] [diff] [review]: ----------------------------------------------------------------- Covers just the build bits. I apologize if I held this up from landing. Feel free to ping me in IRC for small reviews like this if I don't get to them immediately.
Attachment #787797 - Flags: review?(gps) → review+
How do I run this test on my Win8 machine?
Ah, I can reproduce this when I load the file directly in -metrodesktop, when I replay tide.mp4.
(In reply to Chris Pearce (:cpearce) from comment #16) > How do I run this test on my Win8 machine? It's a simple mochitest test - TEST_PATH=browser/metro/base/tests/mochiperf/browser_gfx_01.js pymake mochitest-metro-chrome Not sure about the right mach command.
(In reply to Chris Pearce (:cpearce) from comment #17) > Ah, I can reproduce this when I load the file directly in -metrodesktop, > when I replay tide.mp4. I'm not sure if omtc works with the win32 widget backend. Might not be the same crash!
Hmm, OMTC is preffed on in Metrofox, whether it "works" or not. I can repro the crash easily, just need to seek the video.
OK, change of plan. I talked to Nick Cameron, and we can instead just have a D3D9 texture client, and use that on Win Vista through Windows 8. We can't use my above patch on Win7, so we'll need a D3D9 client here when we enable D3D11 compositing on Win7 anyway, so we may as well use the same path on Win8 as we do on Win7. See bug 904890 for the D3D9 texture client.
Status: NEW → RESOLVED
Closed: 11 years ago
Resolution: --- → WONTFIX
Comment on attachment 753194 [details] [diff] [review] WIP patch ># HG changeset patch ># Parent 4e44cd8c394d9161cd47b2048e078e03153040a3 ># User Chris Pearce <cpearce@mozilla.com> >Bug 875247 - Use DXVA2 via D3D11 on Windows 8 to avoid readback of video frames when we turn on OMTC on Windows. r=? > >diff --git a/content/media/wmf/DXVA2Manager.cpp b/content/media/wmf/DXVA2Manager.cpp >--- a/content/media/wmf/DXVA2Manager.cpp >+++ b/content/media/wmf/DXVA2Manager.cpp >@@ -1,25 +1,29 @@ > /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ > /* vim:set ts=2 sw=2 sts=2 et cindent: */ > /* This Source Code Form is subject to the terms of the Mozilla Public > * License, v. 2.0. If a copy of the MPL was not distributed with this > * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ > > #include "DXVA2Manager.h" >+#include <d3d11.h> > #include "nsThreadUtils.h" > #include "ImageContainer.h" >+#include "gfxWindowsPlatform.h" > #include "D3D9SurfaceImage.h" >+#include "D3D11ShareHandleImage.h" > #include "mozilla/Preferences.h" > > namespace mozilla { > > using layers::Image; > using layers::ImageContainer; > using layers::D3D9SurfaceImage; >+using layers::D3D11ShareHandleImage; > > class D3D9DXVA2Manager : public DXVA2Manager > { > public: > D3D9DXVA2Manager(); > virtual ~D3D9DXVA2Manager(); > > HRESULT Init(); >@@ -165,31 +169,173 @@ D3D9DXVA2Manager::CopyToImage(IMFSample* > > image.forget(aOutImage); > > return S_OK; > } > > /* static */ > DXVA2Manager* >-DXVA2Manager::Create() >+DXVA2Manager::CreateD3D9DXVA() > { > MOZ_ASSERT(NS_IsMainThread()); > HRESULT hr; > > nsAutoPtr<D3D9DXVA2Manager> d3d9Manager(new D3D9DXVA2Manager()); > hr = d3d9Manager->Init(); > if (SUCCEEDED(hr)) { > return d3d9Manager.forget(); > } > > // No hardware accelerated video decoding. :( > return nullptr; > } > >+ >+class D3D11DXVA2Manager : public DXVA2Manager >+{ >+public: >+ D3D11DXVA2Manager(); >+ virtual ~D3D11DXVA2Manager(); >+ >+ HRESULT Init(); >+ >+ IUnknown* GetDXVADeviceManager() MOZ_OVERRIDE; >+ >+ // Copies a region (aRegion) of the video frame stored in aVideoSample >+ // into an image which is returned by aOutImage. >+ HRESULT CopyToImage(IMFSample* aVideoSample, >+ const nsIntRect& aRegion, >+ ImageContainer* aContainer, >+ Image** aOutImage) MOZ_OVERRIDE; >+ >+private: >+ RefPtr<ID3D11Device> mDevice; >+ RefPtr<ID3D11DeviceContext> mContext; >+ RefPtr<IMFDXGIDeviceManager> mDXGIDeviceManager; >+ UINT mDeviceManagerToken; >+}; >+ >+D3D11DXVA2Manager::D3D11DXVA2Manager() >+ : mDeviceManagerToken(0) >+{ >+} >+ >+D3D11DXVA2Manager::~D3D11DXVA2Manager() >+{ >+} >+ >+IUnknown* >+D3D11DXVA2Manager::GetDXVADeviceManager() >+{ >+ MutexAutoLock lock(mLock); >+ return mDXGIDeviceManager; >+} >+ >+typedef HRESULT (WINAPI*MFCreateDXGIDeviceManagerFunc)( >+ UINT *pResetToken, >+ IMFDXGIDeviceManager **ppDXVAManager >+); >+ >+typedef HRESULT (WINAPI*D3D11CreateDeviceAndSwapChainFunc)( >+ IDXGIAdapter *pAdapter, >+ D3D_DRIVER_TYPE DriverType, >+ HMODULE Software, >+ UINT Flags, >+ const D3D_FEATURE_LEVEL *pFeatureLevels, >+ UINT FeatureLevels, >+ UINT SDKVersion, >+ const DXGI_SWAP_CHAIN_DESC *pSwapChainDesc, >+ IDXGISwapChain **ppSwapChain, >+ ID3D11Device **ppDevice, >+ D3D_FEATURE_LEVEL *pFeatureLevel, >+ ID3D11DeviceContext **ppImmediateContext); >+ >+HRESULT >+D3D11DXVA2Manager::Init() >+{ >+ HRESULT hr; >+ >+ mDevice = gfxWindowsPlatform::GetPlatform()->GetD3D11Device(); >+ NS_ENSURE_TRUE(mDevice, E_FAIL); >+ >+ mDevice->GetImmediateContext(byRef(mContext)); >+ NS_ENSURE_TRUE(mContext, E_FAIL); >+ >+ HMODULE mfplatlib = LoadLibraryW(L"mfplat.dll"); >+ NS_ENSURE_TRUE(mfplatlib, E_FAIL); >+ MFCreateDXGIDeviceManagerFunc devManCreate = >+ (MFCreateDXGIDeviceManagerFunc)GetProcAddress(mfplatlib, "MFCreateDXGIDeviceManager"); >+ NS_ENSURE_TRUE(devManCreate, E_FAIL); >+ >+ hr = (devManCreate)(&mDeviceManagerToken, byRef(mDXGIDeviceManager)); >+ NS_ENSURE_TRUE(SUCCEEDED(hr),hr); >+ >+ hr = mDXGIDeviceManager->ResetDevice(mDevice, mDeviceManagerToken); >+ NS_ENSURE_TRUE(SUCCEEDED(hr),hr); >+ >+ return S_OK; >+} >+ >+HRESULT >+D3D11DXVA2Manager::CopyToImage(IMFSample* aVideoSample, >+ const nsIntRect& aRegion, >+ ImageContainer* aContainer, >+ Image** aOutImage) >+{ >+ NS_ENSURE_TRUE(aVideoSample, E_POINTER); >+ NS_ENSURE_TRUE(aContainer, E_POINTER); >+ NS_ENSURE_TRUE(aOutImage, E_POINTER); >+ >+ // Our video frame is stored in a non-sharable ID3D11Texture2D. We need >+ // to create a copy of that frame as a sharable resource, save its share >+ // handle, and put that handle into the rendering pipeline. >+ >+ // First, get the frame as an ID3D11Texture2D. >+ RefPtr<IMFMediaBuffer> mediaBuffer; >+ >+ HRESULT hr = aVideoSample->GetBufferByIndex(0, byRef(mediaBuffer)); >+ NS_ENSURE_TRUE(SUCCEEDED(hr),hr); >+ >+ RefPtr<IMFDXGIBuffer> dxgiBuffer; >+ hr = mediaBuffer->QueryInterface(static_cast<IMFDXGIBuffer**>(byRef(dxgiBuffer))); >+ NS_ENSURE_TRUE(SUCCEEDED(hr), hr); >+ >+ RefPtr<ID3D11Texture2D> frameTexture; >+ hr = dxgiBuffer->GetResource(IID_ID3D11Texture2D, >+ reinterpret_cast<void**>(static_cast<ID3D11Texture2D**>(byRef(frameTexture)))); >+ NS_ENSURE_TRUE(SUCCEEDED(hr), hr); >+ >+ ImageFormat format = D3D11_SHARE_HANDLE_TEXTURE; >+ nsRefPtr<Image> image(aContainer->CreateImage(&format, 1)); >+ NS_ENSURE_TRUE(image, E_FAIL); >+ NS_ASSERTION(image->GetFormat() == D3D11_SHARE_HANDLE_TEXTURE, >+ "Wrong format?"); >+ >+ D3D11ShareHandleImage* videoImage = static_cast<D3D11ShareHandleImage*>(image.get()); >+ hr = videoImage->SetData(D3D11ShareHandleImage::Data(frameTexture, mDevice, mContext, aRegion)); >+ NS_ENSURE_TRUE(SUCCEEDED(hr), hr); >+ >+ image.forget(aOutImage); >+ >+ return S_OK; >+} >+ >+/* static */ >+DXVA2Manager* >+DXVA2Manager::CreateD3D11DXVA() >+{ >+ nsAutoPtr<D3D11DXVA2Manager> manager(new D3D11DXVA2Manager()); >+ >+ HRESULT hr = manager->Init(); >+ NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr); >+ >+ return manager.forget(); >+} >+ > DXVA2Manager::DXVA2Manager() > : mLock("DXVA2Manager") > { > MOZ_ASSERT(NS_IsMainThread()); > } > > DXVA2Manager::~DXVA2Manager() > { >diff --git a/content/media/wmf/DXVA2Manager.h b/content/media/wmf/DXVA2Manager.h >--- a/content/media/wmf/DXVA2Manager.h >+++ b/content/media/wmf/DXVA2Manager.h >@@ -21,17 +21,18 @@ class ImageContainer; > } > > class DXVA2Manager { > public: > > // Creates and initializes a DXVA2Manager. Currently we always use D3D9Ex > // to access DXVA, but via this interface we can seamlessly support D3D11 > // DXVA integration if need be. >- static DXVA2Manager* Create(); >+ static DXVA2Manager* CreateD3D9DXVA(); >+ static DXVA2Manager* CreateD3D11DXVA(); > > // Returns a pointer to the D3D device manager responsible for managing the > // device we're using for hardware accelerated video decoding. If we're using > // D3D9, this is an IDirect3DDeviceManager9. It is safe to call this on any > // thread. > virtual IUnknown* GetDXVADeviceManager() = 0; > > // Creates an Image for the video frame stored in aVideoSample. >diff --git a/content/media/wmf/Makefile.in b/content/media/wmf/Makefile.in >--- a/content/media/wmf/Makefile.in >+++ b/content/media/wmf/Makefile.in >@@ -24,8 +24,12 @@ CPPSRCS = \ > > ifeq ($(OS_ARCH),WINNT) > OS_CXXFLAGS += -DNOMINMAX > endif > > FORCE_STATIC_LIB = 1 > > include $(topsrcdir)/config/rules.mk >+include $(topsrcdir)/ipc/chromium/chromium-config.mk >+ >+ >+CXXFLAGS += $(MOZ_CAIRO_CFLAGS) >diff --git a/content/media/wmf/WMFReader.cpp b/content/media/wmf/WMFReader.cpp >--- a/content/media/wmf/WMFReader.cpp >+++ b/content/media/wmf/WMFReader.cpp >@@ -10,16 +10,17 @@ > #include "WMFByteStream.h" > #include "WMFSourceReaderCallback.h" > #include "mozilla/dom/TimeRanges.h" > #include "mozilla/Preferences.h" > #include "DXVA2Manager.h" > #include "ImageContainer.h" > #include "Layers.h" > #include "mozilla/layers/LayersTypes.h" >+#include "gfxWindowsPlatform.h" > > #ifndef MOZ_SAMPLE_TYPE_FLOAT32 > #error We expect 32bit float audio samples on desktop for the Windows Media Foundation media backend. > #endif > > #include "MediaDecoder.h" > #include "VideoUtils.h" > >@@ -48,17 +49,18 @@ WMFReader::WMFReader(AbstractMediaDecode > mVideoWidth(0), > mVideoHeight(0), > mVideoStride(0), > mAudioFrameSum(0), > mAudioFrameOffset(0), > mHasAudio(false), > mHasVideo(false), > mCanSeek(false), >- mUseHwAccel(false), >+ mMode(Software), >+ mIsOMTCEnabled(Preferences::GetBool("layers.offmainthreadcomposition.enabled", false)), > mIsMP3Enabled(WMFDecoder::IsMP3Supported()) > { > NS_ASSERTION(NS_IsMainThread(), "Must be on main thread."); > MOZ_COUNT_CTOR(WMFReader); > } > > WMFReader::~WMFReader() > { >@@ -88,16 +90,17 @@ WMFReader::OnDecodeThreadFinish() > { > NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread."); > CoUninitialize(); > } > > bool > WMFReader::InitializeDXVA() > { >+ mMode = Mode::Software; > if (!Preferences::GetBool("media.windows-media-foundation.use-dxva", false)) { > return false; > } > > // Extract the layer manager backend type so that we can determine > // whether it's worthwhile using DXVA. If we're not running with a D3D > // layer manager then the readback of decoded video frames from GPU to > // CPU memory grinds painting to a halt, and makes playback performance >@@ -106,27 +109,34 @@ WMFReader::InitializeDXVA() > NS_ENSURE_TRUE(owner, false); > > HTMLMediaElement* element = owner->GetMediaElement(); > NS_ENSURE_TRUE(element, false); > > nsIDocument* doc = element->GetOwnerDocument(); > NS_ENSURE_TRUE(doc, false); > >- nsRefPtr<LayerManager> layerManager = nsContentUtils::LayerManagerForDocument(doc); >- NS_ENSURE_TRUE(layerManager, false); >+ if (gfxWindowsPlatform::WindowsOSVersion() == gfxWindowsPlatform::kWindows8 && >+ gfxWindowsPlatform::GetPlatform()->GetD3D11Device()) { >+ mDXVA2Manager = DXVA2Manager::CreateD3D11DXVA(); >+ NS_ENSURE_TRUE(mDXVA2Manager, false); >+ mMode = Mode::DXVA_D3D11; >+ } else { >+ nsRefPtr<LayerManager> layerManager = nsContentUtils::LayerManagerForDocument(doc); >+ NS_ENSURE_TRUE(layerManager, false); > >- if (layerManager->GetBackendType() != LayersBackend::LAYERS_D3D9 && >- layerManager->GetBackendType() != LayersBackend::LAYERS_D3D10) { >- return false; >+ if (layerManager->GetBackendType() != LayersBackend::LAYERS_D3D9 && >+ layerManager->GetBackendType() != LayersBackend::LAYERS_D3D10) { >+ return false; >+ } >+ >+ mDXVA2Manager = DXVA2Manager::CreateD3D9DXVA(); >+ NS_ENSURE_TRUE(mDXVA2Manager, false); >+ mMode = Mode::DXVA_D3D9; > } >- >- mDXVA2Manager = DXVA2Manager::Create(); >- NS_ENSURE_TRUE(mDXVA2Manager, false); >- > return true; > } > > nsresult > WMFReader::Init(MediaDecoderReader* aCloneDonor) > { > NS_ASSERTION(NS_IsMainThread(), "Must be on main thread."); > >@@ -140,17 +150,17 @@ WMFReader::Init(MediaDecoderReader* aClo > > mSourceReaderCallback = new WMFSourceReaderCallback(); > > // Must be created on main thread. > mByteStream = new WMFByteStream(mDecoder->GetResource(), mSourceReaderCallback); > rv = mByteStream->Init(); > NS_ENSURE_SUCCESS(rv, rv); > >- mUseHwAccel = InitializeDXVA(); >+ InitializeDXVA(); > > return NS_OK; > } > > bool > WMFReader::HasAudio() > { > NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread."); >@@ -360,33 +370,35 @@ WMFReader::ConfigureVideoFrameGeometry(I > // Verify that the video subtype is what we expect it to be. > // When using hardware acceleration/DXVA2 the video format should > // be NV12, which is DXVA2's preferred format. For software decoding > // we use YV12, as that's easier for us to stick into our rendering > // pipeline than NV12. NV12 has interleaved UV samples, whereas YV12 > // is a planar format. > GUID videoFormat; > hr = aMediaType->GetGUID(MF_MT_SUBTYPE, &videoFormat); >- NS_ENSURE_TRUE(videoFormat == MFVideoFormat_NV12 || !mUseHwAccel, E_FAIL); >- NS_ENSURE_TRUE(videoFormat == MFVideoFormat_YV12 || mUseHwAccel, E_FAIL); >+ NS_ENSURE_TRUE(videoFormat == MFVideoFormat_NV12 || mMode != Mode::DXVA_D3D9, E_FAIL); >+ NS_ENSURE_TRUE(videoFormat == MFVideoFormat_YV12 || mMode != Mode::Software, E_FAIL); >+ NS_ENSURE_TRUE(videoFormat == MFVideoFormat_ARGB32 || mMode != Mode::DXVA_D3D11, E_FAIL); > > nsIntRect pictureRegion; > hr = GetPictureRegion(aMediaType, pictureRegion); > NS_ENSURE_TRUE(SUCCEEDED(hr), hr); > > UINT32 width = 0, height = 0; > hr = MFGetAttributeSize(aMediaType, MF_MT_FRAME_SIZE, &width, &height); > NS_ENSURE_TRUE(SUCCEEDED(hr), hr); > >- uint32_t aspectNum = 0, aspectDenom = 0; >- hr = MFGetAttributeRatio(aMediaType, >- MF_MT_PIXEL_ASPECT_RATIO, >- &aspectNum, >- &aspectDenom); >- NS_ENSURE_TRUE(SUCCEEDED(hr), hr); >+ // Note: some formats' media types don't have an aspect ratio, so just >+ // assume those are 1:1. >+ uint32_t aspectNum = 1, aspectDenom = 1; >+ MFGetAttributeRatio(aMediaType, >+ MF_MT_PIXEL_ASPECT_RATIO, >+ &aspectNum, >+ &aspectDenom); > > // Calculate and validate the picture region and frame dimensions after > // scaling by the pixel aspect ratio. > nsIntSize frameSize = nsIntSize(width, height); > nsIntSize displaySize = nsIntSize(pictureRegion.width, pictureRegion.height); > ScaleDisplayByAspectRatio(displaySize, float(aspectNum) / float(aspectDenom)); > if (!VideoInfo::ValidateVideoRegion(frameSize, pictureRegion, displaySize)) { > // Video track's frame sizes will overflow. Ignore the video track. >@@ -405,16 +417,27 @@ WMFReader::ConfigureVideoFrameGeometry(I > mVideoStride, > mPictureRegion.x, mPictureRegion.y, mPictureRegion.width, mPictureRegion.height, > displaySize.width, displaySize.height, > aspectNum, aspectDenom); > > return S_OK; > } > >+const GUID& >+WMFReader::GetVideoFormat() const >+{ >+ switch (mMode) { >+ case Software: return MFVideoFormat_YV12; >+ case DXVA_D3D9: return MFVideoFormat_NV12; >+ case DXVA_D3D11: return MFVideoFormat_ARGB32; >+ } >+ return GUID_NULL; >+} >+ > HRESULT > WMFReader::ConfigureVideoDecoder() > { > NS_ASSERTION(mSourceReader, "Must have a SourceReader before configuring decoders!"); > > // Determine if we have video. > if (!mSourceReader || > !SourceReaderHasStream(mSourceReader, MF_SOURCE_READER_FIRST_VIDEO_STREAM)) { >@@ -422,17 +445,17 @@ WMFReader::ConfigureVideoDecoder() > return S_OK; > } > > static const GUID MP4VideoTypes[] = { > MFVideoFormat_H264 > }; > HRESULT hr = ConfigureSourceReaderStream(mSourceReader, > MF_SOURCE_READER_FIRST_VIDEO_STREAM, >- mUseHwAccel ? MFVideoFormat_NV12 : MFVideoFormat_YV12, >+ GetVideoFormat(), > MP4VideoTypes, > NS_ARRAY_LENGTH(MP4VideoTypes)); > if (FAILED(hr)) { > LOG("Failed to configured video output"); > return hr; > } > > RefPtr<IMFMediaType> mediaType; >@@ -519,69 +542,95 @@ WMFReader::ConfigureAudioDecoder() > mHasAudio = mInfo.mHasAudio = true; > > LOG("Successfully configured audio stream. rate=%u channels=%u bitsPerSample=%u", > mAudioRate, mAudioChannels, mAudioBytesPerSample); > > return S_OK; > } > >+static const char* >+ModeStr(WMFReader::Mode aMode) >+{ >+ switch (aMode) { >+ case WMFReader::Software: return "Software"; >+ case WMFReader::DXVA_D3D9: return "DXVA_D3D9"; >+ case WMFReader::DXVA_D3D11: return "DXVA_D3D11"; >+ default: return "Invalid Mode"; >+ } >+} >+ >+// MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING is only defined if we're >+// building with the Win8 SDK. >+#ifndef MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING >+static const GUID MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING = >+ { 0xf81da2c, 0xb537, 0x4672, 0xa8, 0xb2, 0xa6, 0x81, 0xb1, 0x73, 0x7, 0xa3 }; >+#endif >+ > nsresult > WMFReader::ReadMetadata(VideoInfo* aInfo, > MetadataTags** aTags) > { > NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread."); > > LOG("WMFReader::ReadMetadata()"); > HRESULT hr; > > RefPtr<IMFAttributes> attr; > hr = wmf::MFCreateAttributes(byRef(attr), 1); > NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); > > hr = attr->SetUnknown(MF_SOURCE_READER_ASYNC_CALLBACK, mSourceReaderCallback); > NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); > >- if (mUseHwAccel) { >+ if (mMode == Mode::DXVA_D3D11) { >+ hr = attr->SetUINT32(MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING, TRUE); >+ if (FAILED(hr)) { >+ LOG("Failed to set MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING in attributes"); >+ mMode = Mode::Software; >+ } >+ } >+ >+ if (mMode != Mode::Software) { > hr = attr->SetUnknown(MF_SOURCE_READER_D3D_MANAGER, > mDXVA2Manager->GetDXVADeviceManager()); > if (FAILED(hr)) { > LOG("Failed to set DXVA2 D3D Device manager on source reader attributes"); >- mUseHwAccel = false; >+ mMode = Mode::Software; > } > } > > hr = wmf::MFCreateSourceReaderFromByteStream(mByteStream, attr, byRef(mSourceReader)); > NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); > > hr = ConfigureVideoDecoder(); > NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); > > hr = ConfigureAudioDecoder(); > NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); > >- if (mUseHwAccel && mInfo.mHasVideo) { >+ if (mMode != Mode::Software && mInfo.mHasVideo) { > RefPtr<IMFTransform> videoDecoder; > hr = mSourceReader->GetServiceForStream(MF_SOURCE_READER_FIRST_VIDEO_STREAM, > GUID_NULL, > IID_IMFTransform, > (void**)(IMFTransform**)(byRef(videoDecoder))); > > if (SUCCEEDED(hr)) { > ULONG_PTR manager = ULONG_PTR(mDXVA2Manager->GetDXVADeviceManager()); > hr = videoDecoder->ProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER, > manager); > } > if (FAILED(hr)) { > LOG("Failed to set DXVA2 D3D Device manager on decoder"); >- mUseHwAccel = false; >+ mMode = Mode::Software; > } > } > if (mInfo.mHasVideo) { >- LOG("Using DXVA: %s", (mUseHwAccel ? "Yes" : "No")); >+ LOG("Video Decoding mode: %s", ModeStr(mMode)); > } > > // Abort if both video and audio failed to initialize. > NS_ENSURE_TRUE(mInfo.mHasAudio || mInfo.mHasVideo, NS_ERROR_FAILURE); > > int64_t duration = 0; > if (SUCCEEDED(GetSourceReaderDuration(mSourceReader, duration))) { > ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); >@@ -827,17 +876,17 @@ WMFReader::CreateD3DVideoFrame(IMFSample > int64_t aTimestampUsecs, > int64_t aDurationUsecs, > int64_t aOffsetBytes, > VideoData** aOutVideoData) > { > NS_ENSURE_TRUE(aSample, E_POINTER); > NS_ENSURE_TRUE(aOutVideoData, E_POINTER); > NS_ENSURE_TRUE(mDXVA2Manager, E_ABORT); >- NS_ENSURE_TRUE(mUseHwAccel, E_ABORT); >+ NS_ENSURE_TRUE(mMode != Software, E_ABORT); > > *aOutVideoData = nullptr; > HRESULT hr; > > nsRefPtr<Image> image; > hr = mDXVA2Manager->CopyToImage(aSample, > mPictureRegion, > mDecoder->GetImageContainer(), >@@ -931,17 +980,17 @@ WMFReader::DecodeVideoFrame(bool &aKeyfr > int64_t timestamp = HNsToUsecs(timestampHns); > if (timestamp < aTimeThreshold) { > return true; > } > int64_t offset = mDecoder->GetResource()->Tell(); > int64_t duration = GetSampleDuration(sample); > > VideoData* v = nullptr; >- if (mUseHwAccel) { >+ if (mMode != Software) { > hr = CreateD3DVideoFrame(sample, timestamp, duration, offset, &v); > } else { > hr = CreateBasicVideoFrame(sample, timestamp, duration, offset, &v); > } > NS_ENSURE_TRUE(SUCCEEDED(hr) && v, false); > > parsed++; > decoded++; >diff --git a/content/media/wmf/WMFReader.h b/content/media/wmf/WMFReader.h >--- a/content/media/wmf/WMFReader.h >+++ b/content/media/wmf/WMFReader.h >@@ -47,16 +47,23 @@ public: > int64_t aCurrentTime) MOZ_OVERRIDE; > > nsresult GetBuffered(mozilla::dom::TimeRanges* aBuffered, > int64_t aStartTime) MOZ_OVERRIDE; > > void OnDecodeThreadStart() MOZ_OVERRIDE; > void OnDecodeThreadFinish() MOZ_OVERRIDE; > >+ // Mode that the video decoder is running in. >+ enum Mode { >+ Software, >+ DXVA_D3D9, >+ DXVA_D3D11 >+ }; >+ > private: > > HRESULT ConfigureAudioDecoder(); > HRESULT ConfigureVideoDecoder(); > HRESULT ConfigureVideoFrameGeometry(IMFMediaType* aMediaType); > void GetSupportedAudioCodecs(const GUID** aCodecs, uint32_t* aNumCodecs); > > HRESULT CreateBasicVideoFrame(IMFSample* aSample, >@@ -96,19 +103,25 @@ private: > int64_t mAudioFrameOffset; > // The number of audio frames that we've played since the last > // discontinuity. > int64_t mAudioFrameSum; > > bool mHasAudio; > bool mHasVideo; > bool mCanSeek; >- bool mUseHwAccel; >+ >+ Mode mMode; >+ >+ const GUID& GetVideoFormat() const; > > // We can't call WMFDecoder::IsMP3Supported() on non-main threads, since it > // checks a pref, so we cache its value in mIsMP3Enabled and use that on > // the decode thread. > const bool mIsMP3Enabled; >+ >+ // "layers.offmainthreadcomposition.enabled" >+ const bool mIsOMTCEnabled; > }; > > } // namespace mozilla > > #endif >diff --git a/content/media/wmf/WMFUtils.cpp b/content/media/wmf/WMFUtils.cpp >--- a/content/media/wmf/WMFUtils.cpp >+++ b/content/media/wmf/WMFUtils.cpp >@@ -354,17 +354,17 @@ UnloadDLLs() > sDLLsLoaded = false; > } > return S_OK; > } > > #define ENSURE_FUNCTION_PTR(FunctionName, DLL) \ > static FunctionName##Ptr_t FunctionName##Ptr = nullptr; \ > if (!FunctionName##Ptr) { \ >- FunctionName##Ptr = (FunctionName##Ptr_t)GetProcAddress(GetModuleHandle( #DLL ), #FunctionName ); \ >+ FunctionName##Ptr = (FunctionName##Ptr_t)GetProcAddress(GetModuleHandle( L#DLL ), #FunctionName ); \ > if (!FunctionName##Ptr) { \ > NS_WARNING("Failed to get GetProcAddress of " #FunctionName " from " #DLL ); \ > return E_FAIL; \ > } \ > } > > #define DECL_FUNCTION_PTR(FunctionName, ...) \ > typedef HRESULT (STDMETHODCALLTYPE * FunctionName##Ptr_t)(__VA_ARGS__) >diff --git a/gfx/layers/CompositorTypes.h b/gfx/layers/CompositorTypes.h >--- a/gfx/layers/CompositorTypes.h >+++ b/gfx/layers/CompositorTypes.h >@@ -46,17 +46,18 @@ enum TextureClientType > { > TEXTURE_CONTENT, // dynamically drawn content > TEXTURE_SHMEM, // shared memory > TEXTURE_YCBCR, // ShmemYCbCrImage > TEXTURE_SHARED_GL, // GLContext::SharedTextureHandle > TEXTURE_SHARED_GL_EXTERNAL, // GLContext::SharedTextureHandle, the ownership of > // the SurfaceDescriptor passed to the texture > // remains with whoever passed it. >- TEXTURE_STREAM_GL // WebGL streaming buffer >+ TEXTURE_STREAM_GL, // WebGL streaming buffer >+ TEXTURE_D3D11_HANDLE // D3D11Texture share handle. > }; > > /** > * How the Compositable should manage textures. > */ > enum CompositableType > { > BUFFER_UNKNOWN, >diff --git a/gfx/layers/D3D11ShareHandleImage.cpp b/gfx/layers/D3D11ShareHandleImage.cpp >new file mode 100644 >--- /dev/null >+++ b/gfx/layers/D3D11ShareHandleImage.cpp >@@ -0,0 +1,173 @@ >+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- >+ * This Source Code Form is subject to the terms of the Mozilla Public >+ * License, v. 2.0. If a copy of the MPL was not distributed with this >+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ >+ >+#include "D3D11ShareHandleImage.h" >+#include "gfxImageSurface.h" >+#include "gfxWindowsPlatform.h" >+#include "mozilla/layers/TextureClient.h" >+#include "d3d11.h" >+ >+ >+namespace mozilla { >+namespace layers { >+ >+HRESULT >+D3D11ShareHandleImage::SetData(const Data& aData) >+{ >+ NS_ENSURE_TRUE(aData.mTexture, E_POINTER); >+ HRESULT hr; >+ >+ RefPtr<ID3D11Texture2D> texture = aData.mTexture; >+ RefPtr<ID3D11Device> device = aData.mDevice; >+ RefPtr<ID3D11DeviceContext> context = aData.mContext; >+ >+ // Create a sharable ID3D11Texture2D of the same format. >+ D3D11_TEXTURE2D_DESC frameDesc; >+ texture->GetDesc(&frameDesc); >+ >+ D3D11_TEXTURE2D_DESC desc; >+ desc.Width = aData.mRegion.width; >+ desc.Height = aData.mRegion.height; >+ desc.Format = frameDesc.Format; >+ desc.MipLevels = 1; >+ desc.ArraySize = 1; >+ desc.SampleDesc.Count = 1; >+ desc.SampleDesc.Quality = 0; >+ desc.Usage = D3D11_USAGE_DEFAULT; >+ desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; >+ desc.CPUAccessFlags = 0; >+ desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX; >+ >+ nsRefPtr<ID3D11Texture2D> sharableTexture; >+ hr = device->CreateTexture2D(&desc, nullptr, getter_AddRefs(sharableTexture)); >+ NS_ENSURE_TRUE(SUCCEEDED(hr), hr); >+ >+ nsRefPtr<IDXGIResource> sharableDXGIRes; >+ hr = sharableTexture->QueryInterface(IID_IDXGIResource, (LPVOID*)&sharableDXGIRes); >+ NS_ENSURE_TRUE(SUCCEEDED(hr), hr); >+ >+ // Obtain handle to IDXGIResource object. >+ HANDLE sharedHandle = 0; >+ hr = sharableDXGIRes->GetSharedHandle(&sharedHandle); >+ NS_ENSURE_TRUE(SUCCEEDED(hr) && sharedHandle, hr); >+ >+ // Lock the shared texture. >+ nsRefPtr<IDXGIKeyedMutex> keyedMutex; >+ hr = sharableTexture->QueryInterface(IID_IDXGIKeyedMutex, >+ (LPVOID*)getter_AddRefs(keyedMutex)); >+ NS_ENSURE_TRUE(SUCCEEDED(hr) && keyedMutex, hr); >+ >+ hr = keyedMutex->AcquireSync(0, INFINITE); >+ NS_ENSURE_TRUE(SUCCEEDED(hr), hr); >+ // TODO: Check other return codes. >+ >+ const nsIntRect& r = aData.mRegion; >+ D3D11_BOX srcRect = { r.x, r.y, 0, r.x+r.width, r.y+r.height, 0 }; >+ context->CopySubresourceRegion(sharableTexture, 0, 0, 0, 0, texture, 0, &srcRect); >+ >+ hr = keyedMutex->ReleaseSync(0); >+ NS_ENSURE_TRUE(SUCCEEDED(hr), hr); >+ >+ const nsIntRect& region = aData.mRegion; >+ mSize = gfxIntSize(region.width, region.height); >+ mTexture = sharableTexture; >+ mShareHandle = sharedHandle; >+ >+ mSurfaceDescriptor = SurfaceDescriptorD3D10((WindowsHandle)sharedHandle, true); >+ return S_OK; >+} >+ >+HANDLE >+D3D11ShareHandleImage::GetShareHandle() >+{ >+ // Ensure the image has completed its synchronization, >+ // and safe to used by the caller on another device. >+ //EnsureSynchronized(); >+ return mShareHandle; >+} >+ >+gfxIntSize >+D3D11ShareHandleImage::GetSize() >+{ >+ return mSize; >+} >+ >+already_AddRefed<gfxASurface> >+D3D11ShareHandleImage::GetAsSurface() >+{ >+ HRESULT hr; >+ nsRefPtr<ID3D11Device> device = >+ gfxWindowsPlatform::GetPlatform()->GetD3D11Device(); >+ if (!device || !mTexture) { >+ NS_WARNING("Cannot readback from shared texture because no D3D11 device is available."); >+ return nullptr; >+ } >+ >+ nsRefPtr<IDXGIKeyedMutex> keyedMutex; >+ if (FAILED(mTexture->QueryInterface(IID_IDXGIKeyedMutex, getter_AddRefs(keyedMutex)))) { >+ NS_WARNING("Failed to QueryInterface for IDXGIKeyedMutex, strange."); >+ return nullptr; >+ } >+ >+ if (FAILED(keyedMutex->AcquireSync(0, 0))) { >+ NS_WARNING("Failed to acquire sync for keyedMutex, plugin failed to release?"); >+ return nullptr; >+ } >+ >+ D3D11_TEXTURE2D_DESC desc; >+ mTexture->GetDesc(&desc); >+ >+ CD3D11_TEXTURE2D_DESC softDesc(desc.Format, desc.Width, desc.Height); >+ softDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; >+ softDesc.BindFlags = 0; >+ softDesc.MiscFlags = 0; >+ softDesc.MipLevels = 1; >+ softDesc.Usage = D3D11_USAGE_STAGING; >+ >+ nsRefPtr<ID3D11Texture2D> softTexture; >+ hr = device->CreateTexture2D(&softDesc, NULL, getter_AddRefs(softTexture)); >+ >+ if (FAILED(hr)) { >+ NS_WARNING("Failed to create 2D staging texture."); >+ return nullptr; >+ } >+ >+ RefPtr<ID3D11DeviceContext> context; >+ device->GetImmediateContext(byRef(context)); >+ NS_ENSURE_TRUE(context, nullptr); >+ >+ context->CopyResource(softTexture, mTexture); >+ keyedMutex->ReleaseSync(0); >+ >+ >+ nsRefPtr<gfxImageSurface> surface = >+ new gfxImageSurface(mSize, gfxASurface::ImageFormatRGB24); >+ >+ if (!surface->CairoSurface() || surface->CairoStatus()) { >+ NS_WARNING("Failed to created image surface for DXGI texture."); >+ return nullptr; >+ } >+ >+ D3D11_MAPPED_SUBRESOURCE map; >+ context->Map(softTexture, 0, D3D11_MAP_READ, 0, &map); >+ >+ for (int y = 0; y < mSize.height; y++) { >+ memcpy(surface->Data() + surface->Stride() * y, >+ (unsigned char*)(map.pData) + map.RowPitch * y, >+ mSize.width * 4); >+ } >+ >+ context->Unmap(softTexture, 0); >+ >+ return surface.forget(); >+} >+ >+ID3D11Texture2D* >+D3D11ShareHandleImage::GetTexture() const { >+ return mTexture; >+} >+ >+} /* layers */ >+} /* mozilla */ >diff --git a/gfx/layers/D3D11ShareHandleImage.h b/gfx/layers/D3D11ShareHandleImage.h >new file mode 100644 >--- /dev/null >+++ b/gfx/layers/D3D11ShareHandleImage.h >@@ -0,0 +1,72 @@ >+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- >+ * This Source Code Form is subject to the terms of the Mozilla Public >+ * License, v. 2.0. If a copy of the MPL was not distributed with this >+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ >+ >+#ifndef GFX_D311_SHARE_HANDLE_IMAGE_H >+#define GFX_D311_SHARE_HANDLE_IMAGE_H >+ >+#include "mozilla/RefPtr.h" >+#include "ImageContainer.h" >+#include "nsAutoPtr.h" >+#include "d3d11.h" >+#include "mozilla/layers/LayersSurfaces.h" >+ >+namespace mozilla { >+namespace layers { >+ >+// Image class that wraps a ID3D11Texture2D. This class copies the image >+// passed into SetData(), so that it can be accessed from other D3D devices. >+// This class also manages the synchronization of the copy, to ensure the >+// resource is ready to use. >+class D3D11ShareHandleImage : public Image { >+public: >+ >+ struct Data { >+ Data(ID3D11Texture2D* aTexture, >+ ID3D11Device* aDevice, >+ ID3D11DeviceContext* aContext, >+ const nsIntRect& aRegion) >+ : mTexture(aTexture), >+ mDevice(aDevice), >+ mContext(aContext), >+ mRegion(aRegion) {} >+ RefPtr<ID3D11Texture2D> mTexture; >+ RefPtr<ID3D11Device> mDevice; >+ RefPtr<ID3D11DeviceContext> mContext; >+ nsIntRect mRegion; >+ }; >+ >+ D3D11ShareHandleImage() : Image(NULL, D3D11_SHARE_HANDLE_TEXTURE), mSize(0, 0) {} >+ virtual ~D3D11ShareHandleImage() {} >+ >+ // Copies the surface into a sharable texture's surface, and initializes >+ // the image. >+ HRESULT SetData(const Data& aData); >+ >+ // Returns the HANDLE that can be used to open the image as a shared resource. >+ HANDLE GetShareHandle(); >+ >+ gfxIntSize GetSize() MOZ_OVERRIDE; >+ >+ already_AddRefed<gfxASurface> GetAsSurface() MOZ_OVERRIDE; >+ >+ ID3D11Texture2D* GetTexture() const; >+ >+ SurfaceDescriptor GetSurfaceDescriptor() { >+ return mSurfaceDescriptor; >+ } >+ >+private: >+ >+ gfxIntSize mSize; >+ RefPtr<ID3D11Texture2D> mTexture; >+ HANDLE mShareHandle; >+ SurfaceDescriptor mSurfaceDescriptor; >+ >+}; >+ >+} // namepace layers >+} // namespace mozilla >+ >+#endif // GFX_D3DSURFACEIMAGE_H >diff --git a/gfx/layers/ImageContainer.cpp b/gfx/layers/ImageContainer.cpp >--- a/gfx/layers/ImageContainer.cpp >+++ b/gfx/layers/ImageContainer.cpp >@@ -23,16 +23,17 @@ > #include "mozilla/gfx/QuartzSupport.h" > #endif > > #ifdef XP_WIN > #include "gfxD2DSurface.h" > #include "gfxWindowsPlatform.h" > #include <d3d10_1.h> > #include "d3d10/ImageLayerD3D10.h" >+#include "D3D11ShareHandleImage.h" > #include "D3D9SurfaceImage.h" > #endif > > using namespace mozilla::ipc; > using namespace android; > using mozilla::gfx::DataSourceSurface; > using mozilla::gfx::SourceSurface; > >@@ -72,16 +73,20 @@ ImageFactory::CreateImage(const ImageFor > } > #ifdef MOZ_WIDGET_GONK > if (FormatInList(aFormats, aNumFormats, GONK_IO_SURFACE)) { > img = new GonkIOSurfaceImage(); > return img.forget(); > } > #endif > #ifdef XP_WIN >+ if (FormatInList(aFormats, aNumFormats, D3D11_SHARE_HANDLE_TEXTURE)) { >+ img = new D3D11ShareHandleImage(); >+ return img.forget(); >+ } > if (FormatInList(aFormats, aNumFormats, D3D9_RGB32_TEXTURE)) { > img = new D3D9SurfaceImage(); > return img.forget(); > } > #endif > return nullptr; > } > >diff --git a/gfx/layers/ImageTypes.h b/gfx/layers/ImageTypes.h >--- a/gfx/layers/ImageTypes.h >+++ b/gfx/layers/ImageTypes.h >@@ -66,17 +66,19 @@ enum ImageFormat { > * An DXGI shared surface handle that can be shared with a remote process. > */ > REMOTE_IMAGE_DXGI_TEXTURE, > > /** > * The D3D9_RGB32_TEXTURE format creates a D3D9SurfaceImage, and wraps a > * IDirect3DTexture9 in RGB32 layout. > */ >- D3D9_RGB32_TEXTURE >+ D3D9_RGB32_TEXTURE, >+ >+ D3D11_SHARE_HANDLE_TEXTURE > > }; > > > enum StereoMode { > STEREO_MODE_MONO, > STEREO_MODE_LEFT_RIGHT, > STEREO_MODE_RIGHT_LEFT, >diff --git a/gfx/layers/Makefile.in b/gfx/layers/Makefile.in >--- a/gfx/layers/Makefile.in >+++ b/gfx/layers/Makefile.in >@@ -76,16 +76,17 @@ CPPSRCS = \ > $(NULL) > > GTEST_CPPSRCS = \ > TestTiledLayerBuffer.cpp \ > $(NULL) > > ifeq ($(MOZ_WIDGET_TOOLKIT),windows) > CPPSRCS += \ >+ D3D11ShareHandleImage.cpp \ > D3D9SurfaceImage.cpp \ > $(NULL) > ifdef MOZ_ENABLE_D3D9_LAYER > CPPSRCS += \ > LayerManagerD3D9.cpp \ > ThebesLayerD3D9.cpp \ > ContainerLayerD3D9.cpp \ > ImageLayerD3D9.cpp \ >diff --git a/gfx/layers/client/CompositableClient.cpp b/gfx/layers/client/CompositableClient.cpp >--- a/gfx/layers/client/CompositableClient.cpp >+++ b/gfx/layers/client/CompositableClient.cpp >@@ -99,16 +99,24 @@ CompositableClient::CreateTextureClient( > result = new TextureClientStreamOGL(GetForwarder(), GetTextureInfo()); > } > break; > case TEXTURE_YCBCR: > if (parentBackend == LAYERS_OPENGL || parentBackend == LAYERS_D3D11) { > result = new TextureClientShmemYCbCr(GetForwarder(), GetTextureInfo()); > } > break; >+ case TEXTURE_D3D11_HANDLE: >+#ifdef XP_WIN >+ if (parentBackend == LAYERS_D3D11 && gfxWindowsPlatform::GetPlatform()->GetD2DDevice()) { >+ result = new TextureClientD3D11(GetForwarder(), GetTextureInfo()); >+ } >+ break; >+#endif >+ // fall through to TEXTURE_SHMEM > case TEXTURE_CONTENT: > #ifdef XP_WIN > if (parentBackend == LAYERS_D3D11 && gfxWindowsPlatform::GetPlatform()->GetD2DDevice()) { > result = new TextureClientD3D11(GetForwarder(), GetTextureInfo()); > break; > } > #endif > // fall through to TEXTURE_SHMEM >diff --git a/gfx/layers/client/ImageClient.cpp b/gfx/layers/client/ImageClient.cpp >--- a/gfx/layers/client/ImageClient.cpp >+++ b/gfx/layers/client/ImageClient.cpp >@@ -6,16 +6,17 @@ > #include "mozilla/layers/TextureClient.h" > #include "mozilla/layers/ImageClient.h" > #include "BasicLayers.h" > #include "mozilla/layers/ShadowLayers.h" > #include "SharedTextureImage.h" > #include "ImageContainer.h" // For PlanarYCbCrImage > #include "mozilla/layers/SharedRGBImage.h" > #include "mozilla/layers/SharedPlanarYCbCrImage.h" >+#include "D3D11ShareHandleImage.h" > > #ifdef MOZ_WIDGET_GONK > #include "GonkIOSurfaceImage.h" > #include "GrallocImages.h" > #endif > > namespace mozilla { > namespace layers { >@@ -178,16 +179,32 @@ ImageClientSingle::UpdateImage(ImageCont > AutoLockTextureClient lock(mTextureClient); > > SurfaceDescriptor desc = static_cast<GrallocPlanarYCbCrImage*>(image)->GetSurfaceDescriptor(); > if (!IsSurfaceDescriptorValid(desc)) { > return false; > } > mTextureClient->SetDescriptor(desc); > #endif >+#ifdef XP_WIN >+ } else if (image->GetFormat() == D3D11_SHARE_HANDLE_TEXTURE && >+ EnsureTextureClient(TEXTURE_D3D11_HANDLE)) { >+ nsIntRect rect(0, 0, >+ image->GetSize().width, >+ image->GetSize().height); >+ UpdatePictureRect(rect); >+ >+ AutoLockTextureClient lock(mTextureClient); >+ >+ SurfaceDescriptor desc = static_cast<D3D11ShareHandleImage*>(image)->GetSurfaceDescriptor(); >+ if (!IsSurfaceDescriptorValid(desc)) { >+ return false; >+ } >+ mTextureClient->SetDescriptor(desc); >+#endif > } else { > nsRefPtr<gfxASurface> surface = image->GetAsSurface(); > MOZ_ASSERT(surface); > > EnsureTextureClient(TEXTURE_SHMEM); > MOZ_ASSERT(mTextureClient, "Failed to create texture client"); > > nsRefPtr<gfxPattern> pattern = new gfxPattern(surface); >diff --git a/gfx/layers/d3d10/ImageLayerD3D10.cpp b/gfx/layers/d3d10/ImageLayerD3D10.cpp >--- a/gfx/layers/d3d10/ImageLayerD3D10.cpp >+++ b/gfx/layers/d3d10/ImageLayerD3D10.cpp >@@ -5,16 +5,17 @@ > > #include "ImageLayerD3D10.h" > #include "gfxImageSurface.h" > #include "gfxD2DSurface.h" > #include "gfxWindowsSurface.h" > #include "yuv_convert.h" > #include "../d3d9/Nv3DVUtils.h" > #include "D3D9SurfaceImage.h" >+#include "D3D11ShareHandleImage.h" > > #include "gfxWindowsPlatform.h" > > namespace mozilla { > namespace layers { > > static already_AddRefed<ID3D10Texture2D> > DataToTexture(ID3D10Device *aDevice, >@@ -153,16 +154,36 @@ ImageLayerD3D10::GetImageSRView(Image* a > dat->mTexture = texture; > > hr = device()->CreateShaderResourceView(dat->mTexture, NULL, getter_AddRefs(dat->mSRView)); > NS_ENSURE_TRUE(SUCCEEDED(hr) && dat->mSRView, nullptr); > > aImage->SetBackendData(mozilla::layers::LAYERS_D3D10, dat.forget()); > } > aHasAlpha = false; >+ } else if (aImage->GetFormat() == D3D11_SHARE_HANDLE_TEXTURE) { >+ if (!aImage->GetBackendData(mozilla::layers::LAYERS_D3D10)) { >+ // Use resource sharing to open the D3D9 texture as a D3D10 texture, >+ HRESULT hr; >+ D3D11ShareHandleImage* d3dImage = reinterpret_cast<D3D11ShareHandleImage*>(aImage); >+ nsRefPtr<ID3D10Texture2D> texture; >+ hr = device()->OpenSharedResource(d3dImage->GetShareHandle(), >+ IID_ID3D10Texture2D, >+ (void**)getter_AddRefs(texture)); >+ NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr); >+ >+ nsAutoPtr<TextureD3D10BackendData> dat(new TextureD3D10BackendData()); >+ dat->mTexture = texture; >+ >+ hr = device()->CreateShaderResourceView(dat->mTexture, NULL, getter_AddRefs(dat->mSRView)); >+ NS_ENSURE_TRUE(SUCCEEDED(hr) && dat->mSRView, nullptr); >+ >+ aImage->SetBackendData(mozilla::layers::LAYERS_D3D10, dat.forget()); >+ } >+ aHasAlpha = false; > } else { > NS_WARNING("Incorrect image type."); > return nullptr; > } > > TextureD3D10BackendData *data = > static_cast<TextureD3D10BackendData*>(aImage->GetBackendData(mozilla::layers::LAYERS_D3D10)); > >@@ -207,17 +228,18 @@ ImageLayerD3D10::RenderLayer() > SetEffectTransformAndOpacity(); > > ID3D10EffectTechnique *technique; > nsRefPtr<IDXGIKeyedMutex> keyedMutex; > > if (image->GetFormat() == ImageFormat::CAIRO_SURFACE || > image->GetFormat() == ImageFormat::REMOTE_IMAGE_BITMAP || > image->GetFormat() == ImageFormat::REMOTE_IMAGE_DXGI_TEXTURE || >- image->GetFormat() == ImageFormat::D3D9_RGB32_TEXTURE) { >+ image->GetFormat() == ImageFormat::D3D9_RGB32_TEXTURE || >+ image->GetFormat() == ImageFormat::D3D11_SHARE_HANDLE_TEXTURE) { > NS_ASSERTION(image->GetFormat() != ImageFormat::CAIRO_SURFACE || > !static_cast<CairoImage*>(image)->mSurface || > static_cast<CairoImage*>(image)->mSurface->GetContentType() != gfxASurface::CONTENT_ALPHA, > "Image layer has alpha image"); > bool hasAlpha = false; > > nsRefPtr<ID3D10ShaderResourceView> srView = GetImageSRView(image, hasAlpha, getter_AddRefs(keyedMutex)); > if (!srView) { >@@ -515,11 +537,11 @@ RemoteDXGITextureImage::GetD3D10TextureB > data->mTexture = texture; > > aDevice->CreateShaderResourceView(texture, NULL, getter_AddRefs(data->mSRView)); > > SetBackendData(mozilla::layers::LAYERS_D3D10, data); > > return data.forget(); > } >- >+ > } /* layers */ > } /* mozilla */ >diff --git a/gfx/layers/d3d11/TextureD3D11.h b/gfx/layers/d3d11/TextureD3D11.h >--- a/gfx/layers/d3d11/TextureD3D11.h >+++ b/gfx/layers/d3d11/TextureD3D11.h >@@ -63,17 +63,20 @@ private: > }; > > class TextureClientD3D11 : public TextureClient > { > public: > TextureClientD3D11(CompositableForwarder* aCompositableForwarder, const TextureInfo& aTextureInfo); > ~TextureClientD3D11(); > >- virtual bool SupportsType(TextureClientType aType) MOZ_OVERRIDE { return aType == TEXTURE_CONTENT; } >+ virtual bool SupportsType(TextureClientType aType) MOZ_OVERRIDE { >+ return aType == TEXTURE_CONTENT || >+ aType == TEXTURE_D3D11_HANDLE; >+ } > > virtual void EnsureAllocated(gfx::IntSize aSize, gfxASurface::gfxContentType aType) MOZ_OVERRIDE; > > virtual gfxASurface* LockSurface() MOZ_OVERRIDE; > virtual gfx::DrawTarget* LockDrawTarget() MOZ_OVERRIDE; > virtual void Unlock() MOZ_OVERRIDE; > > virtual void SetDescriptor(const SurfaceDescriptor& aDescriptor) MOZ_OVERRIDE; >diff --git a/gfx/layers/moz.build b/gfx/layers/moz.build >--- a/gfx/layers/moz.build >+++ b/gfx/layers/moz.build >@@ -17,16 +17,17 @@ EXPORTS += [ > 'ClientLayerManager.h', > 'ClientThebesLayer.h', > 'ClientTiledThebesLayer.h', > 'Composer2D.h', > 'CompositableHost.h', > 'CompositorChild.h', > 'CompositorParent.h', > 'CopyableCanvasLayer.h', >+ 'D3D11ShareHandleImage.h', > 'D3D9SurfaceImage.h', > 'FrameMetrics.h', > 'GonkIOSurfaceImage.h', > 'ImageContainer.h', > 'ImageHost.h', > 'ImageLayerOGL.h', > 'ImageLayers.h', > 'ImageTypes.h', >diff --git a/gfx/thebes/gfxWindowsPlatform.h b/gfx/thebes/gfxWindowsPlatform.h >--- a/gfx/thebes/gfxWindowsPlatform.h >+++ b/gfx/thebes/gfxWindowsPlatform.h >@@ -38,17 +38,17 @@ > #include <d3dcommon.h> > // Win 8.0 SDK types we'll need when building using older sdks. > #if !defined(D3D_FEATURE_LEVEL_11_1) // defined in the 8.0 SDK only > #define D3D_FEATURE_LEVEL_11_1 static_cast<D3D_FEATURE_LEVEL>(0xb100) > #define D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION 2048 > #define D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION 4096 > #endif > >-class ID3D11Device; >+struct ID3D11Device; > class IDXGIAdapter1; > > class nsIMemoryMultiReporter; > > // Utility to get a Windows HDC from a thebes context, > // used by both GDI and Uniscribe font shapers > struct DCFromContext { > DCFromContext(gfxContext *aContext) {
Comment on attachment 753194 [details] [diff] [review] WIP patch ># HG changeset patch ># Parent 4e44cd8c394d9161cd47b2048e078e03153040a3 ># User Chris Pearce <cpearce@mozilla.com> >Bug 875247 - Use DXVA2 via D3D11 on Windows 8 to avoid readback of video frames when we turn on OMTC on Windows. r=? > >diff --git a/content/media/wmf/DXVA2Manager.cpp b/content/media/wmf/DXVA2Manager.cpp >--- a/content/media/wmf/DXVA2Manager.cpp >+++ b/content/media/wmf/DXVA2Manager.cpp >@@ -1,25 +1,29 @@ > /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ > /* vim:set ts=2 sw=2 sts=2 et cindent: */ > /* This Source Code Form is subject to the terms of the Mozilla Public > * License, v. 2.0. If a copy of the MPL was not distributed with this > * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ > > #include "DXVA2Manager.h" >+#include <d3d11.h> > #include "nsThreadUtils.h" > #include "ImageContainer.h" >+#include "gfxWindowsPlatform.h" > #include "D3D9SurfaceImage.h" >+#include "D3D11ShareHandleImage.h" > #include "mozilla/Preferences.h" > > namespace mozilla { > > using layers::Image; > using layers::ImageContainer; > using layers::D3D9SurfaceImage; >+using layers::D3D11ShareHandleImage; > > class D3D9DXVA2Manager : public DXVA2Manager > { > public: > D3D9DXVA2Manager(); > virtual ~D3D9DXVA2Manager(); > > HRESULT Init(); >@@ -165,31 +169,173 @@ D3D9DXVA2Manager::CopyToImage(IMFSample* > > image.forget(aOutImage); > > return S_OK; > } > > /* static */ > DXVA2Manager* >-DXVA2Manager::Create() >+DXVA2Manager::CreateD3D9DXVA() > { > MOZ_ASSERT(NS_IsMainThread()); > HRESULT hr; > > nsAutoPtr<D3D9DXVA2Manager> d3d9Manager(new D3D9DXVA2Manager()); > hr = d3d9Manager->Init(); > if (SUCCEEDED(hr)) { > return d3d9Manager.forget(); > } > > // No hardware accelerated video decoding. :( > return nullptr; > } > >+ >+class D3D11DXVA2Manager : public DXVA2Manager >+{ >+public: >+ D3D11DXVA2Manager(); >+ virtual ~D3D11DXVA2Manager(); >+ >+ HRESULT Init(); >+ >+ IUnknown* GetDXVADeviceManager() MOZ_OVERRIDE; >+ >+ // Copies a region (aRegion) of the video frame stored in aVideoSample >+ // into an image which is returned by aOutImage. >+ HRESULT CopyToImage(IMFSample* aVideoSample, >+ const nsIntRect& aRegion, >+ ImageContainer* aContainer, >+ Image** aOutImage) MOZ_OVERRIDE; >+ >+private: >+ RefPtr<ID3D11Device> mDevice; >+ RefPtr<ID3D11DeviceContext> mContext; >+ RefPtr<IMFDXGIDeviceManager> mDXGIDeviceManager; >+ UINT mDeviceManagerToken; >+}; >+ >+D3D11DXVA2Manager::D3D11DXVA2Manager() >+ : mDeviceManagerToken(0) >+{ >+} >+ >+D3D11DXVA2Manager::~D3D11DXVA2Manager() >+{ >+} >+ >+IUnknown* >+D3D11DXVA2Manager::GetDXVADeviceManager() >+{ >+ MutexAutoLock lock(mLock); >+ return mDXGIDeviceManager; >+} >+ >+typedef HRESULT (WINAPI*MFCreateDXGIDeviceManagerFunc)( >+ UINT *pResetToken, >+ IMFDXGIDeviceManager **ppDXVAManager >+); >+ >+typedef HRESULT (WINAPI*D3D11CreateDeviceAndSwapChainFunc)( >+ IDXGIAdapter *pAdapter, >+ D3D_DRIVER_TYPE DriverType, >+ HMODULE Software, >+ UINT Flags, >+ const D3D_FEATURE_LEVEL *pFeatureLevels, >+ UINT FeatureLevels, >+ UINT SDKVersion, >+ const DXGI_SWAP_CHAIN_DESC *pSwapChainDesc, >+ IDXGISwapChain **ppSwapChain, >+ ID3D11Device **ppDevice, >+ D3D_FEATURE_LEVEL *pFeatureLevel, >+ ID3D11DeviceContext **ppImmediateContext); >+ >+HRESULT >+D3D11DXVA2Manager::Init() >+{ >+ HRESULT hr; >+ >+ mDevice = gfxWindowsPlatform::GetPlatform()->GetD3D11Device(); >+ NS_ENSURE_TRUE(mDevice, E_FAIL); >+ >+ mDevice->GetImmediateContext(byRef(mContext)); >+ NS_ENSURE_TRUE(mContext, E_FAIL); >+ >+ HMODULE mfplatlib = LoadLibraryW(L"mfplat.dll"); >+ NS_ENSURE_TRUE(mfplatlib, E_FAIL); >+ MFCreateDXGIDeviceManagerFunc devManCreate = >+ (MFCreateDXGIDeviceManagerFunc)GetProcAddress(mfplatlib, "MFCreateDXGIDeviceManager"); >+ NS_ENSURE_TRUE(devManCreate, E_FAIL); >+ >+ hr = (devManCreate)(&mDeviceManagerToken, byRef(mDXGIDeviceManager)); >+ NS_ENSURE_TRUE(SUCCEEDED(hr),hr); >+ >+ hr = mDXGIDeviceManager->ResetDevice(mDevice, mDeviceManagerToken); >+ NS_ENSURE_TRUE(SUCCEEDED(hr),hr); >+ >+ return S_OK; >+} >+ >+HRESULT >+D3D11DXVA2Manager::CopyToImage(IMFSample* aVideoSample, >+ const nsIntRect& aRegion, >+ ImageContainer* aContainer, >+ Image** aOutImage) >+{ >+ NS_ENSURE_TRUE(aVideoSample, E_POINTER); >+ NS_ENSURE_TRUE(aContainer, E_POINTER); >+ NS_ENSURE_TRUE(aOutImage, E_POINTER); >+ >+ // Our video frame is stored in a non-sharable ID3D11Texture2D. We need >+ // to create a copy of that frame as a sharable resource, save its share >+ // handle, and put that handle into the rendering pipeline. >+ >+ // First, get the frame as an ID3D11Texture2D. >+ RefPtr<IMFMediaBuffer> mediaBuffer; >+ >+ HRESULT hr = aVideoSample->GetBufferByIndex(0, byRef(mediaBuffer)); >+ NS_ENSURE_TRUE(SUCCEEDED(hr),hr); >+ >+ RefPtr<IMFDXGIBuffer> dxgiBuffer; >+ hr = mediaBuffer->QueryInterface(static_cast<IMFDXGIBuffer**>(byRef(dxgiBuffer))); >+ NS_ENSURE_TRUE(SUCCEEDED(hr), hr); >+ >+ RefPtr<ID3D11Texture2D> frameTexture; >+ hr = dxgiBuffer->GetResource(IID_ID3D11Texture2D, >+ reinterpret_cast<void**>(static_cast<ID3D11Texture2D**>(byRef(frameTexture)))); >+ NS_ENSURE_TRUE(SUCCEEDED(hr), hr); >+ >+ ImageFormat format = D3D11_SHARE_HANDLE_TEXTURE; >+ nsRefPtr<Image> image(aContainer->CreateImage(&format, 1)); >+ NS_ENSURE_TRUE(image, E_FAIL); >+ NS_ASSERTION(image->GetFormat() == D3D11_SHARE_HANDLE_TEXTURE, >+ "Wrong format?"); >+ >+ D3D11ShareHandleImage* videoImage = static_cast<D3D11ShareHandleImage*>(image.get()); >+ hr = videoImage->SetData(D3D11ShareHandleImage::Data(frameTexture, mDevice, mContext, aRegion)); >+ NS_ENSURE_TRUE(SUCCEEDED(hr), hr); >+ >+ image.forget(aOutImage); >+ >+ return S_OK; >+} >+ >+/* static */ >+DXVA2Manager* >+DXVA2Manager::CreateD3D11DXVA() >+{ >+ nsAutoPtr<D3D11DXVA2Manager> manager(new D3D11DXVA2Manager()); >+ >+ HRESULT hr = manager->Init(); >+ NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr); >+ >+ return manager.forget(); >+} >+ > DXVA2Manager::DXVA2Manager() > : mLock("DXVA2Manager") > { > MOZ_ASSERT(NS_IsMainThread()); > } > > DXVA2Manager::~DXVA2Manager() > { >diff --git a/content/media/wmf/DXVA2Manager.h b/content/media/wmf/DXVA2Manager.h >--- a/content/media/wmf/DXVA2Manager.h >+++ b/content/media/wmf/DXVA2Manager.h >@@ -21,17 +21,18 @@ class ImageContainer; > } > > class DXVA2Manager { > public: > > // Creates and initializes a DXVA2Manager. Currently we always use D3D9Ex > // to access DXVA, but via this interface we can seamlessly support D3D11 > // DXVA integration if need be. >- static DXVA2Manager* Create(); >+ static DXVA2Manager* CreateD3D9DXVA(); >+ static DXVA2Manager* CreateD3D11DXVA(); > > // Returns a pointer to the D3D device manager responsible for managing the > // device we're using for hardware accelerated video decoding. If we're using > // D3D9, this is an IDirect3DDeviceManager9. It is safe to call this on any > // thread. > virtual IUnknown* GetDXVADeviceManager() = 0; > > // Creates an Image for the video frame stored in aVideoSample. >diff --git a/content/media/wmf/Makefile.in b/content/media/wmf/Makefile.in >--- a/content/media/wmf/Makefile.in >+++ b/content/media/wmf/Makefile.in >@@ -24,8 +24,12 @@ CPPSRCS = \ > > ifeq ($(OS_ARCH),WINNT) > OS_CXXFLAGS += -DNOMINMAX > endif > > FORCE_STATIC_LIB = 1 > > include $(topsrcdir)/config/rules.mk >+include $(topsrcdir)/ipc/chromium/chromium-config.mk >+ >+ >+CXXFLAGS += $(MOZ_CAIRO_CFLAGS) >diff --git a/content/media/wmf/WMFReader.cpp b/content/media/wmf/WMFReader.cpp >--- a/content/media/wmf/WMFReader.cpp >+++ b/content/media/wmf/WMFReader.cpp >@@ -10,16 +10,17 @@ > #include "WMFByteStream.h" > #include "WMFSourceReaderCallback.h" > #include "mozilla/dom/TimeRanges.h" > #include "mozilla/Preferences.h" > #include "DXVA2Manager.h" > #include "ImageContainer.h" > #include "Layers.h" > #include "mozilla/layers/LayersTypes.h" >+#include "gfxWindowsPlatform.h" > > #ifndef MOZ_SAMPLE_TYPE_FLOAT32 > #error We expect 32bit float audio samples on desktop for the Windows Media Foundation media backend. > #endif > > #include "MediaDecoder.h" > #include "VideoUtils.h" > >@@ -48,17 +49,18 @@ WMFReader::WMFReader(AbstractMediaDecode > mVideoWidth(0), > mVideoHeight(0), > mVideoStride(0), > mAudioFrameSum(0), > mAudioFrameOffset(0), > mHasAudio(false), > mHasVideo(false), > mCanSeek(false), >- mUseHwAccel(false), >+ mMode(Software), >+ mIsOMTCEnabled(Preferences::GetBool("layers.offmainthreadcomposition.enabled", false)), > mIsMP3Enabled(WMFDecoder::IsMP3Supported()) > { > NS_ASSERTION(NS_IsMainThread(), "Must be on main thread."); > MOZ_COUNT_CTOR(WMFReader); > } > > WMFReader::~WMFReader() > { >@@ -88,16 +90,17 @@ WMFReader::OnDecodeThreadFinish() > { > NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread."); > CoUninitialize(); > } > > bool > WMFReader::InitializeDXVA() > { >+ mMode = Mode::Software; > if (!Preferences::GetBool("media.windows-media-foundation.use-dxva", false)) { > return false; > } > > // Extract the layer manager backend type so that we can determine > // whether it's worthwhile using DXVA. If we're not running with a D3D > // layer manager then the readback of decoded video frames from GPU to > // CPU memory grinds painting to a halt, and makes playback performance >@@ -106,27 +109,34 @@ WMFReader::InitializeDXVA() > NS_ENSURE_TRUE(owner, false); > > HTMLMediaElement* element = owner->GetMediaElement(); > NS_ENSURE_TRUE(element, false); > > nsIDocument* doc = element->GetOwnerDocument(); > NS_ENSURE_TRUE(doc, false); > >- nsRefPtr<LayerManager> layerManager = nsContentUtils::LayerManagerForDocument(doc); >- NS_ENSURE_TRUE(layerManager, false); >+ if (gfxWindowsPlatform::WindowsOSVersion() == gfxWindowsPlatform::kWindows8 && >+ gfxWindowsPlatform::GetPlatform()->GetD3D11Device()) { >+ mDXVA2Manager = DXVA2Manager::CreateD3D11DXVA(); >+ NS_ENSURE_TRUE(mDXVA2Manager, false); >+ mMode = Mode::DXVA_D3D11; >+ } else { >+ nsRefPtr<LayerManager> layerManager = nsContentUtils::LayerManagerForDocument(doc); >+ NS_ENSURE_TRUE(layerManager, false); > >- if (layerManager->GetBackendType() != LayersBackend::LAYERS_D3D9 && >- layerManager->GetBackendType() != LayersBackend::LAYERS_D3D10) { >- return false; >+ if (layerManager->GetBackendType() != LayersBackend::LAYERS_D3D9 && >+ layerManager->GetBackendType() != LayersBackend::LAYERS_D3D10) { >+ return false; >+ } >+ >+ mDXVA2Manager = DXVA2Manager::CreateD3D9DXVA(); >+ NS_ENSURE_TRUE(mDXVA2Manager, false); >+ mMode = Mode::DXVA_D3D9; > } >- >- mDXVA2Manager = DXVA2Manager::Create(); >- NS_ENSURE_TRUE(mDXVA2Manager, false); >- > return true; > } > > nsresult > WMFReader::Init(MediaDecoderReader* aCloneDonor) > { > NS_ASSERTION(NS_IsMainThread(), "Must be on main thread."); > >@@ -140,17 +150,17 @@ WMFReader::Init(MediaDecoderReader* aClo > > mSourceReaderCallback = new WMFSourceReaderCallback(); > > // Must be created on main thread. > mByteStream = new WMFByteStream(mDecoder->GetResource(), mSourceReaderCallback); > rv = mByteStream->Init(); > NS_ENSURE_SUCCESS(rv, rv); > >- mUseHwAccel = InitializeDXVA(); >+ InitializeDXVA(); > > return NS_OK; > } > > bool > WMFReader::HasAudio() > { > NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread."); >@@ -360,33 +370,35 @@ WMFReader::ConfigureVideoFrameGeometry(I > // Verify that the video subtype is what we expect it to be. > // When using hardware acceleration/DXVA2 the video format should > // be NV12, which is DXVA2's preferred format. For software decoding > // we use YV12, as that's easier for us to stick into our rendering > // pipeline than NV12. NV12 has interleaved UV samples, whereas YV12 > // is a planar format. > GUID videoFormat; > hr = aMediaType->GetGUID(MF_MT_SUBTYPE, &videoFormat); >- NS_ENSURE_TRUE(videoFormat == MFVideoFormat_NV12 || !mUseHwAccel, E_FAIL); >- NS_ENSURE_TRUE(videoFormat == MFVideoFormat_YV12 || mUseHwAccel, E_FAIL); >+ NS_ENSURE_TRUE(videoFormat == MFVideoFormat_NV12 || mMode != Mode::DXVA_D3D9, E_FAIL); >+ NS_ENSURE_TRUE(videoFormat == MFVideoFormat_YV12 || mMode != Mode::Software, E_FAIL); >+ NS_ENSURE_TRUE(videoFormat == MFVideoFormat_ARGB32 || mMode != Mode::DXVA_D3D11, E_FAIL); > > nsIntRect pictureRegion; > hr = GetPictureRegion(aMediaType, pictureRegion); > NS_ENSURE_TRUE(SUCCEEDED(hr), hr); > > UINT32 width = 0, height = 0; > hr = MFGetAttributeSize(aMediaType, MF_MT_FRAME_SIZE, &width, &height); > NS_ENSURE_TRUE(SUCCEEDED(hr), hr); > >- uint32_t aspectNum = 0, aspectDenom = 0; >- hr = MFGetAttributeRatio(aMediaType, >- MF_MT_PIXEL_ASPECT_RATIO, >- &aspectNum, >- &aspectDenom); >- NS_ENSURE_TRUE(SUCCEEDED(hr), hr); >+ // Note: some formats' media types don't have an aspect ratio, so just >+ // assume those are 1:1. >+ uint32_t aspectNum = 1, aspectDenom = 1; >+ MFGetAttributeRatio(aMediaType, >+ MF_MT_PIXEL_ASPECT_RATIO, >+ &aspectNum, >+ &aspectDenom); > > // Calculate and validate the picture region and frame dimensions after > // scaling by the pixel aspect ratio. > nsIntSize frameSize = nsIntSize(width, height); > nsIntSize displaySize = nsIntSize(pictureRegion.width, pictureRegion.height); > ScaleDisplayByAspectRatio(displaySize, float(aspectNum) / float(aspectDenom)); > if (!VideoInfo::ValidateVideoRegion(frameSize, pictureRegion, displaySize)) { > // Video track's frame sizes will overflow. Ignore the video track. >@@ -405,16 +417,27 @@ WMFReader::ConfigureVideoFrameGeometry(I > mVideoStride, > mPictureRegion.x, mPictureRegion.y, mPictureRegion.width, mPictureRegion.height, > displaySize.width, displaySize.height, > aspectNum, aspectDenom); > > return S_OK; > } > >+const GUID& >+WMFReader::GetVideoFormat() const >+{ >+ switch (mMode) { >+ case Software: return MFVideoFormat_YV12; >+ case DXVA_D3D9: return MFVideoFormat_NV12; >+ case DXVA_D3D11: return MFVideoFormat_ARGB32; >+ } >+ return GUID_NULL; >+} >+ > HRESULT > WMFReader::ConfigureVideoDecoder() > { > NS_ASSERTION(mSourceReader, "Must have a SourceReader before configuring decoders!"); > > // Determine if we have video. > if (!mSourceReader || > !SourceReaderHasStream(mSourceReader, MF_SOURCE_READER_FIRST_VIDEO_STREAM)) { >@@ -422,17 +445,17 @@ WMFReader::ConfigureVideoDecoder() > return S_OK; > } > > static const GUID MP4VideoTypes[] = { > MFVideoFormat_H264 > }; > HRESULT hr = ConfigureSourceReaderStream(mSourceReader, > MF_SOURCE_READER_FIRST_VIDEO_STREAM, >- mUseHwAccel ? MFVideoFormat_NV12 : MFVideoFormat_YV12, >+ GetVideoFormat(), > MP4VideoTypes, > NS_ARRAY_LENGTH(MP4VideoTypes)); > if (FAILED(hr)) { > LOG("Failed to configured video output"); > return hr; > } > > RefPtr<IMFMediaType> mediaType; >@@ -519,69 +542,95 @@ WMFReader::ConfigureAudioDecoder() > mHasAudio = mInfo.mHasAudio = true; > > LOG("Successfully configured audio stream. rate=%u channels=%u bitsPerSample=%u", > mAudioRate, mAudioChannels, mAudioBytesPerSample); > > return S_OK; > } > >+static const char* >+ModeStr(WMFReader::Mode aMode) >+{ >+ switch (aMode) { >+ case WMFReader::Software: return "Software"; >+ case WMFReader::DXVA_D3D9: return "DXVA_D3D9"; >+ case WMFReader::DXVA_D3D11: return "DXVA_D3D11"; >+ default: return "Invalid Mode"; >+ } >+} >+ >+// MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING is only defined if we're >+// building with the Win8 SDK. >+#ifndef MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING >+static const GUID MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING = >+ { 0xf81da2c, 0xb537, 0x4672, 0xa8, 0xb2, 0xa6, 0x81, 0xb1, 0x73, 0x7, 0xa3 }; >+#endif >+ > nsresult > WMFReader::ReadMetadata(VideoInfo* aInfo, > MetadataTags** aTags) > { > NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread."); > > LOG("WMFReader::ReadMetadata()"); > HRESULT hr; > > RefPtr<IMFAttributes> attr; > hr = wmf::MFCreateAttributes(byRef(attr), 1); > NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); > > hr = attr->SetUnknown(MF_SOURCE_READER_ASYNC_CALLBACK, mSourceReaderCallback); > NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); > >- if (mUseHwAccel) { >+ if (mMode == Mode::DXVA_D3D11) { >+ hr = attr->SetUINT32(MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING, TRUE); >+ if (FAILED(hr)) { >+ LOG("Failed to set MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING in attributes"); >+ mMode = Mode::Software; >+ } >+ } >+ >+ if (mMode != Mode::Software) { > hr = attr->SetUnknown(MF_SOURCE_READER_D3D_MANAGER, > mDXVA2Manager->GetDXVADeviceManager()); > if (FAILED(hr)) { > LOG("Failed to set DXVA2 D3D Device manager on source reader attributes"); >- mUseHwAccel = false; >+ mMode = Mode::Software; > } > } > > hr = wmf::MFCreateSourceReaderFromByteStream(mByteStream, attr, byRef(mSourceReader)); > NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); > > hr = ConfigureVideoDecoder(); > NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); > > hr = ConfigureAudioDecoder(); > NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); > >- if (mUseHwAccel && mInfo.mHasVideo) { >+ if (mMode != Mode::Software && mInfo.mHasVideo) { > RefPtr<IMFTransform> videoDecoder; > hr = mSourceReader->GetServiceForStream(MF_SOURCE_READER_FIRST_VIDEO_STREAM, > GUID_NULL, > IID_IMFTransform, > (void**)(IMFTransform**)(byRef(videoDecoder))); > > if (SUCCEEDED(hr)) { > ULONG_PTR manager = ULONG_PTR(mDXVA2Manager->GetDXVADeviceManager()); > hr = videoDecoder->ProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER, > manager); > } > if (FAILED(hr)) { > LOG("Failed to set DXVA2 D3D Device manager on decoder"); >- mUseHwAccel = false; >+ mMode = Mode::Software; > } > } > if (mInfo.mHasVideo) { >- LOG("Using DXVA: %s", (mUseHwAccel ? "Yes" : "No")); >+ LOG("Video Decoding mode: %s", ModeStr(mMode)); > } > > // Abort if both video and audio failed to initialize. > NS_ENSURE_TRUE(mInfo.mHasAudio || mInfo.mHasVideo, NS_ERROR_FAILURE); > > int64_t duration = 0; > if (SUCCEEDED(GetSourceReaderDuration(mSourceReader, duration))) { > ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); >@@ -827,17 +876,17 @@ WMFReader::CreateD3DVideoFrame(IMFSample > int64_t aTimestampUsecs, > int64_t aDurationUsecs, > int64_t aOffsetBytes, > VideoData** aOutVideoData) > { > NS_ENSURE_TRUE(aSample, E_POINTER); > NS_ENSURE_TRUE(aOutVideoData, E_POINTER); > NS_ENSURE_TRUE(mDXVA2Manager, E_ABORT); >- NS_ENSURE_TRUE(mUseHwAccel, E_ABORT); >+ NS_ENSURE_TRUE(mMode != Software, E_ABORT); > > *aOutVideoData = nullptr; > HRESULT hr; > > nsRefPtr<Image> image; > hr = mDXVA2Manager->CopyToImage(aSample, > mPictureRegion, > mDecoder->GetImageContainer(), >@@ -931,17 +980,17 @@ WMFReader::DecodeVideoFrame(bool &aKeyfr > int64_t timestamp = HNsToUsecs(timestampHns); > if (timestamp < aTimeThreshold) { > return true; > } > int64_t offset = mDecoder->GetResource()->Tell(); > int64_t duration = GetSampleDuration(sample); > > VideoData* v = nullptr; >- if (mUseHwAccel) { >+ if (mMode != Software) { > hr = CreateD3DVideoFrame(sample, timestamp, duration, offset, &v); > } else { > hr = CreateBasicVideoFrame(sample, timestamp, duration, offset, &v); > } > NS_ENSURE_TRUE(SUCCEEDED(hr) && v, false); > > parsed++; > decoded++; >diff --git a/content/media/wmf/WMFReader.h b/content/media/wmf/WMFReader.h >--- a/content/media/wmf/WMFReader.h >+++ b/content/media/wmf/WMFReader.h >@@ -47,16 +47,23 @@ public: > int64_t aCurrentTime) MOZ_OVERRIDE; > > nsresult GetBuffered(mozilla::dom::TimeRanges* aBuffered, > int64_t aStartTime) MOZ_OVERRIDE; > > void OnDecodeThreadStart() MOZ_OVERRIDE; > void OnDecodeThreadFinish() MOZ_OVERRIDE; > >+ // Mode that the video decoder is running in. >+ enum Mode { >+ Software, >+ DXVA_D3D9, >+ DXVA_D3D11 >+ }; >+ > private: > > HRESULT ConfigureAudioDecoder(); > HRESULT ConfigureVideoDecoder(); > HRESULT ConfigureVideoFrameGeometry(IMFMediaType* aMediaType); > void GetSupportedAudioCodecs(const GUID** aCodecs, uint32_t* aNumCodecs); > > HRESULT CreateBasicVideoFrame(IMFSample* aSample, >@@ -96,19 +103,25 @@ private: > int64_t mAudioFrameOffset; > // The number of audio frames that we've played since the last > // discontinuity. > int64_t mAudioFrameSum; > > bool mHasAudio; > bool mHasVideo; > bool mCanSeek; >- bool mUseHwAccel; >+ >+ Mode mMode; >+ >+ const GUID& GetVideoFormat() const; > > // We can't call WMFDecoder::IsMP3Supported() on non-main threads, since it > // checks a pref, so we cache its value in mIsMP3Enabled and use that on > // the decode thread. > const bool mIsMP3Enabled; >+ >+ // "layers.offmainthreadcomposition.enabled" >+ const bool mIsOMTCEnabled; > }; > > } // namespace mozilla > > #endif >diff --git a/content/media/wmf/WMFUtils.cpp b/content/media/wmf/WMFUtils.cpp >--- a/content/media/wmf/WMFUtils.cpp >+++ b/content/media/wmf/WMFUtils.cpp >@@ -354,17 +354,17 @@ UnloadDLLs() > sDLLsLoaded = false; > } > return S_OK; > } > > #define ENSURE_FUNCTION_PTR(FunctionName, DLL) \ > static FunctionName##Ptr_t FunctionName##Ptr = nullptr; \ > if (!FunctionName##Ptr) { \ >- FunctionName##Ptr = (FunctionName##Ptr_t)GetProcAddress(GetModuleHandle( #DLL ), #FunctionName ); \ >+ FunctionName##Ptr = (FunctionName##Ptr_t)GetProcAddress(GetModuleHandle( L#DLL ), #FunctionName ); \ > if (!FunctionName##Ptr) { \ > NS_WARNING("Failed to get GetProcAddress of " #FunctionName " from " #DLL ); \ > return E_FAIL; \ > } \ > } > > #define DECL_FUNCTION_PTR(FunctionName, ...) \ > typedef HRESULT (STDMETHODCALLTYPE * FunctionName##Ptr_t)(__VA_ARGS__) >diff --git a/gfx/layers/CompositorTypes.h b/gfx/layers/CompositorTypes.h >--- a/gfx/layers/CompositorTypes.h >+++ b/gfx/layers/CompositorTypes.h >@@ -46,17 +46,18 @@ enum TextureClientType > { > TEXTURE_CONTENT, // dynamically drawn content > TEXTURE_SHMEM, // shared memory > TEXTURE_YCBCR, // ShmemYCbCrImage > TEXTURE_SHARED_GL, // GLContext::SharedTextureHandle > TEXTURE_SHARED_GL_EXTERNAL, // GLContext::SharedTextureHandle, the ownership of > // the SurfaceDescriptor passed to the texture > // remains with whoever passed it. >- TEXTURE_STREAM_GL // WebGL streaming buffer >+ TEXTURE_STREAM_GL, // WebGL streaming buffer >+ TEXTURE_D3D11_HANDLE // D3D11Texture share handle. > }; > > /** > * How the Compositable should manage textures. > */ > enum CompositableType > { > BUFFER_UNKNOWN, >diff --git a/gfx/layers/D3D11ShareHandleImage.cpp b/gfx/layers/D3D11ShareHandleImage.cpp >new file mode 100644 >--- /dev/null >+++ b/gfx/layers/D3D11ShareHandleImage.cpp >@@ -0,0 +1,173 @@ >+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- >+ * This Source Code Form is subject to the terms of the Mozilla Public >+ * License, v. 2.0. If a copy of the MPL was not distributed with this >+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ >+ >+#include "D3D11ShareHandleImage.h" >+#include "gfxImageSurface.h" >+#include "gfxWindowsPlatform.h" >+#include "mozilla/layers/TextureClient.h" >+#include "d3d11.h" >+ >+ >+namespace mozilla { >+namespace layers { >+ >+HRESULT >+D3D11ShareHandleImage::SetData(const Data& aData) >+{ >+ NS_ENSURE_TRUE(aData.mTexture, E_POINTER); >+ HRESULT hr; >+ >+ RefPtr<ID3D11Texture2D> texture = aData.mTexture; >+ RefPtr<ID3D11Device> device = aData.mDevice; >+ RefPtr<ID3D11DeviceContext> context = aData.mContext; >+ >+ // Create a sharable ID3D11Texture2D of the same format. >+ D3D11_TEXTURE2D_DESC frameDesc; >+ texture->GetDesc(&frameDesc); >+ >+ D3D11_TEXTURE2D_DESC desc; >+ desc.Width = aData.mRegion.width; >+ desc.Height = aData.mRegion.height; >+ desc.Format = frameDesc.Format; >+ desc.MipLevels = 1; >+ desc.ArraySize = 1; >+ desc.SampleDesc.Count = 1; >+ desc.SampleDesc.Quality = 0; >+ desc.Usage = D3D11_USAGE_DEFAULT; >+ desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; >+ desc.CPUAccessFlags = 0; >+ desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX; >+ >+ nsRefPtr<ID3D11Texture2D> sharableTexture; >+ hr = device->CreateTexture2D(&desc, nullptr, getter_AddRefs(sharableTexture)); >+ NS_ENSURE_TRUE(SUCCEEDED(hr), hr); >+ >+ nsRefPtr<IDXGIResource> sharableDXGIRes; >+ hr = sharableTexture->QueryInterface(IID_IDXGIResource, (LPVOID*)&sharableDXGIRes); >+ NS_ENSURE_TRUE(SUCCEEDED(hr), hr); >+ >+ // Obtain handle to IDXGIResource object. >+ HANDLE sharedHandle = 0; >+ hr = sharableDXGIRes->GetSharedHandle(&sharedHandle); >+ NS_ENSURE_TRUE(SUCCEEDED(hr) && sharedHandle, hr); >+ >+ // Lock the shared texture. >+ nsRefPtr<IDXGIKeyedMutex> keyedMutex; >+ hr = sharableTexture->QueryInterface(IID_IDXGIKeyedMutex, >+ (LPVOID*)getter_AddRefs(keyedMutex)); >+ NS_ENSURE_TRUE(SUCCEEDED(hr) && keyedMutex, hr); >+ >+ hr = keyedMutex->AcquireSync(0, INFINITE); >+ NS_ENSURE_TRUE(SUCCEEDED(hr), hr); >+ // TODO: Check other return codes. >+ >+ const nsIntRect& r = aData.mRegion; >+ D3D11_BOX srcRect = { r.x, r.y, 0, r.x+r.width, r.y+r.height, 0 }; >+ context->CopySubresourceRegion(sharableTexture, 0, 0, 0, 0, texture, 0, &srcRect); >+ >+ hr = keyedMutex->ReleaseSync(0); >+ NS_ENSURE_TRUE(SUCCEEDED(hr), hr); >+ >+ const nsIntRect& region = aData.mRegion; >+ mSize = gfxIntSize(region.width, region.height); >+ mTexture = sharableTexture; >+ mShareHandle = sharedHandle; >+ >+ mSurfaceDescriptor = SurfaceDescriptorD3D10((WindowsHandle)sharedHandle, true); >+ return S_OK; >+} >+ >+HANDLE >+D3D11ShareHandleImage::GetShareHandle() >+{ >+ // Ensure the image has completed its synchronization, >+ // and safe to used by the caller on another device. >+ //EnsureSynchronized(); >+ return mShareHandle; >+} >+ >+gfxIntSize >+D3D11ShareHandleImage::GetSize() >+{ >+ return mSize; >+} >+ >+already_AddRefed<gfxASurface> >+D3D11ShareHandleImage::GetAsSurface() >+{ >+ HRESULT hr; >+ nsRefPtr<ID3D11Device> device = >+ gfxWindowsPlatform::GetPlatform()->GetD3D11Device(); >+ if (!device || !mTexture) { >+ NS_WARNING("Cannot readback from shared texture because no D3D11 device is available."); >+ return nullptr; >+ } >+ >+ nsRefPtr<IDXGIKeyedMutex> keyedMutex; >+ if (FAILED(mTexture->QueryInterface(IID_IDXGIKeyedMutex, getter_AddRefs(keyedMutex)))) { >+ NS_WARNING("Failed to QueryInterface for IDXGIKeyedMutex, strange."); >+ return nullptr; >+ } >+ >+ if (FAILED(keyedMutex->AcquireSync(0, 0))) { >+ NS_WARNING("Failed to acquire sync for keyedMutex, plugin failed to release?"); >+ return nullptr; >+ } >+ >+ D3D11_TEXTURE2D_DESC desc; >+ mTexture->GetDesc(&desc); >+ >+ CD3D11_TEXTURE2D_DESC softDesc(desc.Format, desc.Width, desc.Height); >+ softDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; >+ softDesc.BindFlags = 0; >+ softDesc.MiscFlags = 0; >+ softDesc.MipLevels = 1; >+ softDesc.Usage = D3D11_USAGE_STAGING; >+ >+ nsRefPtr<ID3D11Texture2D> softTexture; >+ hr = device->CreateTexture2D(&softDesc, NULL, getter_AddRefs(softTexture)); >+ >+ if (FAILED(hr)) { >+ NS_WARNING("Failed to create 2D staging texture."); >+ return nullptr; >+ } >+ >+ RefPtr<ID3D11DeviceContext> context; >+ device->GetImmediateContext(byRef(context)); >+ NS_ENSURE_TRUE(context, nullptr); >+ >+ context->CopyResource(softTexture, mTexture); >+ keyedMutex->ReleaseSync(0); >+ >+ >+ nsRefPtr<gfxImageSurface> surface = >+ new gfxImageSurface(mSize, gfxASurface::ImageFormatRGB24); >+ >+ if (!surface->CairoSurface() || surface->CairoStatus()) { >+ NS_WARNING("Failed to created image surface for DXGI texture."); >+ return nullptr; >+ } >+ >+ D3D11_MAPPED_SUBRESOURCE map; >+ context->Map(softTexture, 0, D3D11_MAP_READ, 0, &map); >+ >+ for (int y = 0; y < mSize.height; y++) { >+ memcpy(surface->Data() + surface->Stride() * y, >+ (unsigned char*)(map.pData) + map.RowPitch * y, >+ mSize.width * 4); >+ } >+ >+ context->Unmap(softTexture, 0); >+ >+ return surface.forget(); >+} >+ >+ID3D11Texture2D* >+D3D11ShareHandleImage::GetTexture() const { >+ return mTexture; >+} >+ >+} /* layers */ >+} /* mozilla */ >diff --git a/gfx/layers/D3D11ShareHandleImage.h b/gfx/layers/D3D11ShareHandleImage.h >new file mode 100644 >--- /dev/null >+++ b/gfx/layers/D3D11ShareHandleImage.h >@@ -0,0 +1,72 @@ >+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- >+ * This Source Code Form is subject to the terms of the Mozilla Public >+ * License, v. 2.0. If a copy of the MPL was not distributed with this >+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ >+ >+#ifndef GFX_D311_SHARE_HANDLE_IMAGE_H >+#define GFX_D311_SHARE_HANDLE_IMAGE_H >+ >+#include "mozilla/RefPtr.h" >+#include "ImageContainer.h" >+#include "nsAutoPtr.h" >+#include "d3d11.h" >+#include "mozilla/layers/LayersSurfaces.h" >+ >+namespace mozilla { >+namespace layers { >+ >+// Image class that wraps a ID3D11Texture2D. This class copies the image >+// passed into SetData(), so that it can be accessed from other D3D devices. >+// This class also manages the synchronization of the copy, to ensure the >+// resource is ready to use. >+class D3D11ShareHandleImage : public Image { >+public: >+ >+ struct Data { >+ Data(ID3D11Texture2D* aTexture, >+ ID3D11Device* aDevice, >+ ID3D11DeviceContext* aContext, >+ const nsIntRect& aRegion) >+ : mTexture(aTexture), >+ mDevice(aDevice), >+ mContext(aContext), >+ mRegion(aRegion) {} >+ RefPtr<ID3D11Texture2D> mTexture; >+ RefPtr<ID3D11Device> mDevice; >+ RefPtr<ID3D11DeviceContext> mContext; >+ nsIntRect mRegion; >+ }; >+ >+ D3D11ShareHandleImage() : Image(NULL, D3D11_SHARE_HANDLE_TEXTURE), mSize(0, 0) {} >+ virtual ~D3D11ShareHandleImage() {} >+ >+ // Copies the surface into a sharable texture's surface, and initializes >+ // the image. >+ HRESULT SetData(const Data& aData); >+ >+ // Returns the HANDLE that can be used to open the image as a shared resource. >+ HANDLE GetShareHandle(); >+ >+ gfxIntSize GetSize() MOZ_OVERRIDE; >+ >+ already_AddRefed<gfxASurface> GetAsSurface() MOZ_OVERRIDE; >+ >+ ID3D11Texture2D* GetTexture() const; >+ >+ SurfaceDescriptor GetSurfaceDescriptor() { >+ return mSurfaceDescriptor; >+ } >+ >+private: >+ >+ gfxIntSize mSize; >+ RefPtr<ID3D11Texture2D> mTexture; >+ HANDLE mShareHandle; >+ SurfaceDescriptor mSurfaceDescriptor; >+ >+}; >+ >+} // namepace layers >+} // namespace mozilla >+ >+#endif // GFX_D3DSURFACEIMAGE_H >diff --git a/gfx/layers/ImageContainer.cpp b/gfx/layers/ImageContainer.cpp >--- a/gfx/layers/ImageContainer.cpp >+++ b/gfx/layers/ImageContainer.cpp >@@ -23,16 +23,17 @@ > #include "mozilla/gfx/QuartzSupport.h" > #endif > > #ifdef XP_WIN > #include "gfxD2DSurface.h" > #include "gfxWindowsPlatform.h" > #include <d3d10_1.h> > #include "d3d10/ImageLayerD3D10.h" >+#include "D3D11ShareHandleImage.h" > #include "D3D9SurfaceImage.h" > #endif > > using namespace mozilla::ipc; > using namespace android; > using mozilla::gfx::DataSourceSurface; > using mozilla::gfx::SourceSurface; > >@@ -72,16 +73,20 @@ ImageFactory::CreateImage(const ImageFor > } > #ifdef MOZ_WIDGET_GONK > if (FormatInList(aFormats, aNumFormats, GONK_IO_SURFACE)) { > img = new GonkIOSurfaceImage(); > return img.forget(); > } > #endif > #ifdef XP_WIN >+ if (FormatInList(aFormats, aNumFormats, D3D11_SHARE_HANDLE_TEXTURE)) { >+ img = new D3D11ShareHandleImage(); >+ return img.forget(); >+ } > if (FormatInList(aFormats, aNumFormats, D3D9_RGB32_TEXTURE)) { > img = new D3D9SurfaceImage(); > return img.forget(); > } > #endif > return nullptr; > } > >diff --git a/gfx/layers/ImageTypes.h b/gfx/layers/ImageTypes.h >--- a/gfx/layers/ImageTypes.h >+++ b/gfx/layers/ImageTypes.h >@@ -66,17 +66,19 @@ enum ImageFormat { > * An DXGI shared surface handle that can be shared with a remote process. > */ > REMOTE_IMAGE_DXGI_TEXTURE, > > /** > * The D3D9_RGB32_TEXTURE format creates a D3D9SurfaceImage, and wraps a > * IDirect3DTexture9 in RGB32 layout. > */ >- D3D9_RGB32_TEXTURE >+ D3D9_RGB32_TEXTURE, >+ >+ D3D11_SHARE_HANDLE_TEXTURE > > }; > > > enum StereoMode { > STEREO_MODE_MONO, > STEREO_MODE_LEFT_RIGHT, > STEREO_MODE_RIGHT_LEFT, >diff --git a/gfx/layers/Makefile.in b/gfx/layers/Makefile.in >--- a/gfx/layers/Makefile.in >+++ b/gfx/layers/Makefile.in >@@ -76,16 +76,17 @@ CPPSRCS = \ > $(NULL) > > GTEST_CPPSRCS = \ > TestTiledLayerBuffer.cpp \ > $(NULL) > > ifeq ($(MOZ_WIDGET_TOOLKIT),windows) > CPPSRCS += \ >+ D3D11ShareHandleImage.cpp \ > D3D9SurfaceImage.cpp \ > $(NULL) > ifdef MOZ_ENABLE_D3D9_LAYER > CPPSRCS += \ > LayerManagerD3D9.cpp \ > ThebesLayerD3D9.cpp \ > ContainerLayerD3D9.cpp \ > ImageLayerD3D9.cpp \ >diff --git a/gfx/layers/client/CompositableClient.cpp b/gfx/layers/client/CompositableClient.cpp >--- a/gfx/layers/client/CompositableClient.cpp >+++ b/gfx/layers/client/CompositableClient.cpp >@@ -99,16 +99,24 @@ CompositableClient::CreateTextureClient( > result = new TextureClientStreamOGL(GetForwarder(), GetTextureInfo()); > } > break; > case TEXTURE_YCBCR: > if (parentBackend == LAYERS_OPENGL || parentBackend == LAYERS_D3D11) { > result = new TextureClientShmemYCbCr(GetForwarder(), GetTextureInfo()); > } > break; >+ case TEXTURE_D3D11_HANDLE: >+#ifdef XP_WIN >+ if (parentBackend == LAYERS_D3D11 && gfxWindowsPlatform::GetPlatform()->GetD2DDevice()) { >+ result = new TextureClientD3D11(GetForwarder(), GetTextureInfo()); >+ } >+ break; >+#endif >+ // fall through to TEXTURE_SHMEM > case TEXTURE_CONTENT: > #ifdef XP_WIN > if (parentBackend == LAYERS_D3D11 && gfxWindowsPlatform::GetPlatform()->GetD2DDevice()) { > result = new TextureClientD3D11(GetForwarder(), GetTextureInfo()); > break; > } > #endif > // fall through to TEXTURE_SHMEM >diff --git a/gfx/layers/client/ImageClient.cpp b/gfx/layers/client/ImageClient.cpp >--- a/gfx/layers/client/ImageClient.cpp >+++ b/gfx/layers/client/ImageClient.cpp >@@ -6,16 +6,17 @@ > #include "mozilla/layers/TextureClient.h" > #include "mozilla/layers/ImageClient.h" > #include "BasicLayers.h" > #include "mozilla/layers/ShadowLayers.h" > #include "SharedTextureImage.h" > #include "ImageContainer.h" // For PlanarYCbCrImage > #include "mozilla/layers/SharedRGBImage.h" > #include "mozilla/layers/SharedPlanarYCbCrImage.h" >+#include "D3D11ShareHandleImage.h" > > #ifdef MOZ_WIDGET_GONK > #include "GonkIOSurfaceImage.h" > #include "GrallocImages.h" > #endif > > namespace mozilla { > namespace layers { >@@ -178,16 +179,32 @@ ImageClientSingle::UpdateImage(ImageCont > AutoLockTextureClient lock(mTextureClient); > > SurfaceDescriptor desc = static_cast<GrallocPlanarYCbCrImage*>(image)->GetSurfaceDescriptor(); > if (!IsSurfaceDescriptorValid(desc)) { > return false; > } > mTextureClient->SetDescriptor(desc); > #endif >+#ifdef XP_WIN >+ } else if (image->GetFormat() == D3D11_SHARE_HANDLE_TEXTURE && >+ EnsureTextureClient(TEXTURE_D3D11_HANDLE)) { >+ nsIntRect rect(0, 0, >+ image->GetSize().width, >+ image->GetSize().height); >+ UpdatePictureRect(rect); >+ >+ AutoLockTextureClient lock(mTextureClient); >+ >+ SurfaceDescriptor desc = static_cast<D3D11ShareHandleImage*>(image)->GetSurfaceDescriptor(); >+ if (!IsSurfaceDescriptorValid(desc)) { >+ return false; >+ } >+ mTextureClient->SetDescriptor(desc); >+#endif > } else { > nsRefPtr<gfxASurface> surface = image->GetAsSurface(); > MOZ_ASSERT(surface); > > EnsureTextureClient(TEXTURE_SHMEM); > MOZ_ASSERT(mTextureClient, "Failed to create texture client"); > > nsRefPtr<gfxPattern> pattern = new gfxPattern(surface); >diff --git a/gfx/layers/d3d10/ImageLayerD3D10.cpp b/gfx/layers/d3d10/ImageLayerD3D10.cpp >--- a/gfx/layers/d3d10/ImageLayerD3D10.cpp >+++ b/gfx/layers/d3d10/ImageLayerD3D10.cpp >@@ -5,16 +5,17 @@ > > #include "ImageLayerD3D10.h" > #include "gfxImageSurface.h" > #include "gfxD2DSurface.h" > #include "gfxWindowsSurface.h" > #include "yuv_convert.h" > #include "../d3d9/Nv3DVUtils.h" > #include "D3D9SurfaceImage.h" >+#include "D3D11ShareHandleImage.h" > > #include "gfxWindowsPlatform.h" > > namespace mozilla { > namespace layers { > > static already_AddRefed<ID3D10Texture2D> > DataToTexture(ID3D10Device *aDevice, >@@ -153,16 +154,36 @@ ImageLayerD3D10::GetImageSRView(Image* a > dat->mTexture = texture; > > hr = device()->CreateShaderResourceView(dat->mTexture, NULL, getter_AddRefs(dat->mSRView)); > NS_ENSURE_TRUE(SUCCEEDED(hr) && dat->mSRView, nullptr); > > aImage->SetBackendData(mozilla::layers::LAYERS_D3D10, dat.forget()); > } > aHasAlpha = false; >+ } else if (aImage->GetFormat() == D3D11_SHARE_HANDLE_TEXTURE) { >+ if (!aImage->GetBackendData(mozilla::layers::LAYERS_D3D10)) { >+ // Use resource sharing to open the D3D9 texture as a D3D10 texture, >+ HRESULT hr; >+ D3D11ShareHandleImage* d3dImage = reinterpret_cast<D3D11ShareHandleImage*>(aImage); >+ nsRefPtr<ID3D10Texture2D> texture; >+ hr = device()->OpenSharedResource(d3dImage->GetShareHandle(), >+ IID_ID3D10Texture2D, >+ (void**)getter_AddRefs(texture)); >+ NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr); >+ >+ nsAutoPtr<TextureD3D10BackendData> dat(new TextureD3D10BackendData()); >+ dat->mTexture = texture; >+ >+ hr = device()->CreateShaderResourceView(dat->mTexture, NULL, getter_AddRefs(dat->mSRView)); >+ NS_ENSURE_TRUE(SUCCEEDED(hr) && dat->mSRView, nullptr); >+ >+ aImage->SetBackendData(mozilla::layers::LAYERS_D3D10, dat.forget()); >+ } >+ aHasAlpha = false; > } else { > NS_WARNING("Incorrect image type."); > return nullptr; > } > > TextureD3D10BackendData *data = > static_cast<TextureD3D10BackendData*>(aImage->GetBackendData(mozilla::layers::LAYERS_D3D10)); > >@@ -207,17 +228,18 @@ ImageLayerD3D10::RenderLayer() > SetEffectTransformAndOpacity(); > > ID3D10EffectTechnique *technique; > nsRefPtr<IDXGIKeyedMutex> keyedMutex; > > if (image->GetFormat() == ImageFormat::CAIRO_SURFACE || > image->GetFormat() == ImageFormat::REMOTE_IMAGE_BITMAP || > image->GetFormat() == ImageFormat::REMOTE_IMAGE_DXGI_TEXTURE || >- image->GetFormat() == ImageFormat::D3D9_RGB32_TEXTURE) { >+ image->GetFormat() == ImageFormat::D3D9_RGB32_TEXTURE || >+ image->GetFormat() == ImageFormat::D3D11_SHARE_HANDLE_TEXTURE) { > NS_ASSERTION(image->GetFormat() != ImageFormat::CAIRO_SURFACE || > !static_cast<CairoImage*>(image)->mSurface || > static_cast<CairoImage*>(image)->mSurface->GetContentType() != gfxASurface::CONTENT_ALPHA, > "Image layer has alpha image"); > bool hasAlpha = false; > > nsRefPtr<ID3D10ShaderResourceView> srView = GetImageSRView(image, hasAlpha, getter_AddRefs(keyedMutex)); > if (!srView) { >@@ -515,11 +537,11 @@ RemoteDXGITextureImage::GetD3D10TextureB > data->mTexture = texture; > > aDevice->CreateShaderResourceView(texture, NULL, getter_AddRefs(data->mSRView)); > > SetBackendData(mozilla::layers::LAYERS_D3D10, data); > > return data.forget(); > } >- >+ > } /* layers */ > } /* mozilla */ >diff --git a/gfx/layers/d3d11/TextureD3D11.h b/gfx/layers/d3d11/TextureD3D11.h >--- a/gfx/layers/d3d11/TextureD3D11.h >+++ b/gfx/layers/d3d11/TextureD3D11.h >@@ -63,17 +63,20 @@ private: > }; > > class TextureClientD3D11 : public TextureClient > { > public: > TextureClientD3D11(CompositableForwarder* aCompositableForwarder, const TextureInfo& aTextureInfo); > ~TextureClientD3D11(); > >- virtual bool SupportsType(TextureClientType aType) MOZ_OVERRIDE { return aType == TEXTURE_CONTENT; } >+ virtual bool SupportsType(TextureClientType aType) MOZ_OVERRIDE { >+ return aType == TEXTURE_CONTENT || >+ aType == TEXTURE_D3D11_HANDLE; >+ } > > virtual void EnsureAllocated(gfx::IntSize aSize, gfxASurface::gfxContentType aType) MOZ_OVERRIDE; > > virtual gfxASurface* LockSurface() MOZ_OVERRIDE; > virtual gfx::DrawTarget* LockDrawTarget() MOZ_OVERRIDE; > virtual void Unlock() MOZ_OVERRIDE; > > virtual void SetDescriptor(const SurfaceDescriptor& aDescriptor) MOZ_OVERRIDE; >diff --git a/gfx/layers/moz.build b/gfx/layers/moz.build >--- a/gfx/layers/moz.build >+++ b/gfx/layers/moz.build >@@ -17,16 +17,17 @@ EXPORTS += [ > 'ClientLayerManager.h', > 'ClientThebesLayer.h', > 'ClientTiledThebesLayer.h', > 'Composer2D.h', > 'CompositableHost.h', > 'CompositorChild.h', > 'CompositorParent.h', > 'CopyableCanvasLayer.h', >+ 'D3D11ShareHandleImage.h', > 'D3D9SurfaceImage.h', > 'FrameMetrics.h', > 'GonkIOSurfaceImage.h', > 'ImageContainer.h', > 'ImageHost.h', > 'ImageLayerOGL.h', > 'ImageLayers.h', > 'ImageTypes.h', >diff --git a/gfx/thebes/gfxWindowsPlatform.h b/gfx/thebes/gfxWindowsPlatform.h >--- a/gfx/thebes/gfxWindowsPlatform.h >+++ b/gfx/thebes/gfxWindowsPlatform.h >@@ -38,17 +38,17 @@ > #include <d3dcommon.h> > // Win 8.0 SDK types we'll need when building using older sdks. > #if !defined(D3D_FEATURE_LEVEL_11_1) // defined in the 8.0 SDK only > #define D3D_FEATURE_LEVEL_11_1 static_cast<D3D_FEATURE_LEVEL>(0xb100) > #define D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION 2048 > #define D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION 4096 > #endif > >-class ID3D11Device; >+struct ID3D11Device; > class IDXGIAdapter1; > > class nsIMemoryMultiReporter; > > // Utility to get a Windows HDC from a thebes context, > // used by both GDI and Uniscribe font shapers > struct DCFromContext { > DCFromContext(gfxContext *aContext) {
Attached patch Rebased patch (obsolete) (deleted) — Splinter Review
Rebased the patch so that it builds on tip. Unfortunately it requires windows 8 to work, so I can't actually test it.
Attached patch Use DXVA via D3D11 on Windows 8 (deleted) — Splinter Review
Assignee: cpearce → matt.woodrow
Attachment #8565274 - Attachment is obsolete: true
Status: RESOLVED → REOPENED
Attachment #8586547 - Flags: review?(cpearce)
Resolution: WONTFIX → ---
With media.windows-media-foundation.use-dxva=false I get a crash, here's the callstack: > xul.dll!mozilla::WMFVideoMFTManager::ConfigureVideoFrameGeometry() Line 319 C++ xul.dll!mozilla::WMFVideoMFTManager::Output(__int64 aStreamOffset, nsRefPtr<mozilla::MediaData> & aOutData) Line 500 C++ xul.dll!mozilla::WMFMediaDataDecoder::ProcessOutput() Line 109 C++ xul.dll!mozilla::WMFMediaDataDecoder::ProcessDecode(mp4_demuxer::MP4Sample * aSample) Line 101 C++ xul.dll!nsRunnableMethodArguments<nsAutoPtr<mp4_demuxer::MP4Sample> >::apply<mozilla::WMFMediaDataDecoder,void (__thiscall mozilla::WMFMediaDataDecoder::*)(mp4_demuxer::MP4Sample *)>(mozilla::WMFMediaDataDecoder * o, void (mp4_demuxer::MP4Sample *) * m) Line 587 C++ xul.dll!nsRunnableMethodImpl<void (__thiscall mozilla::WMFMediaDataDecoder::*)(mp4_demuxer::MP4Sample *),1,nsAutoPtr<mp4_demuxer::MP4Sample> >::Run() Line 668 C++ xul.dll!mozilla::MediaTaskQueue::Runner::Run() Line 233 C++ mDXVA2Manager is null, and is being derefed. Adding a nullcheck around that fixes it. I also see in the console: [4196] WARNING: Failed to allocate a TextureClient, falling back to BufferTextureClient.: file c:\Users\Bob\src\mozilla\purple\gfx\layers\client/TextureClient.cpp, line 416 [GFX3-]: Invalid draw target type specified. [4196] WARNING: Failed to allocate a TextureClient, falling back to BufferTextureClient.: file c:\Users\Bob\src\mozilla\purple\gfx\layers\client/TextureClient.cpp, line 416 [GFX3-]: Invalid draw target type specified. Not sure if that's related. With media.windows-media-foundation.use-dxva=true, it works, DXVA initializes. Will try an opt build though, perf isn't good in a debug build. I thought you were removing the media.windows-media-foundation.use-dxva pref, did it not land yet?
(In reply to Chris Pearce (:cpearce) from comment #26) > With media.windows-media-foundation.use-dxva=false I get a crash, here's the > callstack: > > > xul.dll!mozilla::WMFVideoMFTManager::ConfigureVideoFrameGeometry() Line 319 C++ > xul.dll!mozilla::WMFVideoMFTManager::Output(__int64 aStreamOffset, > nsRefPtr<mozilla::MediaData> & aOutData) Line 500 C++ > xul.dll!mozilla::WMFMediaDataDecoder::ProcessOutput() Line 109 C++ > xul.dll!mozilla::WMFMediaDataDecoder::ProcessDecode(mp4_demuxer::MP4Sample > * aSample) Line 101 C++ > xul.dll!nsRunnableMethodArguments<nsAutoPtr<mp4_demuxer::MP4Sample> > >::apply<mozilla::WMFMediaDataDecoder,void (__thiscall > mozilla::WMFMediaDataDecoder::*)(mp4_demuxer::MP4Sample > *)>(mozilla::WMFMediaDataDecoder * o, void (mp4_demuxer::MP4Sample *) * m) > Line 587 C++ > xul.dll!nsRunnableMethodImpl<void (__thiscall > mozilla::WMFMediaDataDecoder::*)(mp4_demuxer::MP4Sample > *),1,nsAutoPtr<mp4_demuxer::MP4Sample> >::Run() Line 668 C++ > xul.dll!mozilla::MediaTaskQueue::Runner::Run() Line 233 C++ > > > mDXVA2Manager is null, and is being derefed. Adding a nullcheck around that > fixes it. Good catch, I forgot to test this configuration. > > I also see in the console: > > [4196] WARNING: Failed to allocate a TextureClient, falling back to > BufferTextureClient.: file > c:\Users\Bob\src\mozilla\purple\gfx\layers\client/TextureClient.cpp, line 416 > [GFX3-]: Invalid draw target type specified. > [4196] WARNING: Failed to allocate a TextureClient, falling back to > BufferTextureClient.: file > c:\Users\Bob\src\mozilla\purple\gfx\layers\client/TextureClient.cpp, line 416 > [GFX3-]: Invalid draw target type specified. > > Not sure if that's related. I don't see that locally, works fine with/without dxva enabled. > > With media.windows-media-foundation.use-dxva=true, it works, DXVA > initializes. Will try an opt build though, perf isn't good in a debug build. > > I thought you were removing the media.windows-media-foundation.use-dxva > pref, did it not land yet? It's been deprecated (hidden from about:config), but it still works. The preferred way to disable dxva is using media.hardware-video-decoding.enabled=false now.
Comment on attachment 8586547 [details] [diff] [review] Use DXVA via D3D11 on Windows 8 Review of attachment 8586547 [details] [diff] [review]: ----------------------------------------------------------------- ::: gfx/thebes/gfxWindowsPlatform.cpp @@ +2019,5 @@ > > +TemporaryRef<ID3D11Device> > +gfxWindowsPlatform::CreateD3D11DecoderDevice() > +{ > + nsModuleHandle d3d11Module(LoadLibrarySystem32(L"d3d11.dll")); Indentation is wrong for this whole function, fixed locally.
Comment on attachment 8586547 [details] [diff] [review] Use DXVA via D3D11 on Windows 8 Review of attachment 8586547 [details] [diff] [review]: ----------------------------------------------------------------- r+ with nits. ::: dom/media/fmp4/wmf/WMFVideoMFTManager.cpp @@ +222,5 @@ > > + hr = inputType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive); > + NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr); > + > + hr = inputType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE); Do you need MF_MT_ALL_SAMPLES_INDEPENDENT here? I'd have thought that if your input is H.264, you'd not be able to set this, since some samples are P or B frames, which are not independent. I tested, and on my machine it's not needed. ::: dom/media/wmf/DXVA2Manager.cpp @@ +362,5 @@ > + hr = keyedMutex->AcquireSync(0, INFINITE); > + NS_ENSURE_TRUE(SUCCEEDED(hr), hr); > + > + hr = mTransform->Output(&sample); > + NS_ENSURE_TRUE(SUCCEEDED(hr), hr); if IMFTransform::Output() fails, you'll bail out here without calling ReleaseSync(). I think you need to. @@ +403,5 @@ > +{ > + mWidth = aWidth; > + mHeight = aHeight; > + > + HRESULT hr = mTransform->SendMFTMessage(MFT_MESSAGE_NOTIFY_END_STREAMING, 0); Do you need the NOTIFY_END_STREAMING message? The MSDN docs make it sound like it's optional to process this message. YouTube stream switching works on my machine without this call. @@ +446,5 @@ > + > + gfx::IntSize size(mWidth, mHeight); > + hr = mTransform->SetMediaTypes(inputType, outputType, ConfigureOutput, &size); > + NS_ENSURE_TRUE(SUCCEEDED(hr), hr); > + Bit of a shame we need to be called back to get the frame size set at the right time correctly. ::: gfx/layers/D3D11ShareHandleImage.cpp @@ +72,5 @@ > + > + if (FAILED(keyedMutex->AcquireSync(0, 0))) { > + NS_WARNING("Failed to acquire sync for keyedMutex, plugin failed to release?"); > + return nullptr; > + } Won't you leak the keyedMutex's lock count it you don't release it on the return-on-failure paths that happen between here and the ReleaseSync call on line 103?
Attachment #8586547 - Flags: review?(cpearce) → review+
Status: REOPENED → RESOLVED
Closed: 11 years ago10 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla40
[Tracking Requested - why for this release]: Fixes bug 1161349 for windows 8 users.
Comment on attachment 8586547 [details] [diff] [review] Use DXVA via D3D11 on Windows 8 Approval Request Comment [Feature/regressing bug #]: HTML5 Video [User impact if declined]: Incorrect colours for HD H264 videos on youtube, this fixes it for windows 8 users. [Describe test coverage new/current, TreeHerder]: Tested manually, all windows 8 youtube users on nightly have been using it. [Risks and why]: Medium risk, changes the API we use for decoding h264 on windows 8, no issues so far though. [String/UUID change made/needed]: None
Attachment #8586547 - Flags: approval-mozilla-aurora?
This looks great and I'd like to uplift this to 39 if we think it's safe enough to do so. Jeff and Milan can you have a look and let me know your opinion of the risk here and what it might break?
Flags: needinfo?(milan)
Flags: needinfo?(jmuizelaar)
(In reply to Liz Henry (:lizzard) from comment #34) > This looks great and I'd like to uplift this to 39 if we think it's safe > enough to do so. > > Jeff and Milan can you have a look and let me know your opinion of the risk > here and what it might break? I don't have a great answer. Seems like something where the more testing the better.
Flags: needinfo?(jmuizelaar)
So, we've had it on nightly for about a month, but this uplift would effectively mean we're skipping the dev edition audience and going to beta. A bit on the scary side. As to what might break - we still don't know if there is a connection between DXVA and driver resets triggering crashes, and this could either make things better, or worse.
Flags: needinfo?(milan)
Flags: needinfo?(bas)
Comment on attachment 8586547 [details] [diff] [review] Use DXVA via D3D11 on Windows 8 Review of attachment 8586547 [details] [diff] [review]: ----------------------------------------------------------------- I don't see code in here that will deal with removal of D3D11 devices. It would probably be good to merge the D3D11 device creation with the device creation of our other devices and also deal with device losses there. Other than that we should add a pref to switch off DXVA2 so we can switch back quickly if it breaks beta.
Attachment #8586547 - Flags: review-
Milan, how about if we see how it does on 40 for the next couple of weeks. That will give us a somewhat wider, or different, group of users to help us uncover problems. We aren't releasing 39 beta 1 until another week or so, so there's no rush. But also, I'm not sure if this is worth the risk of uplifting to beta given that this has been an issue since the 33 release and it looks like a complex change. Do you feel strongly about the need to have this in 39 rather than let it ride with 40? Having the pref you suggest in comment 37 sounds good. Can you file a new bug for that?
Flags: needinfo?(milan)
I'm good with riding 40.
Flags: needinfo?(milan)
Comment on attachment 8586547 [details] [diff] [review] Use DXVA via D3D11 on Windows 8 This patch is already on 40 so we don't need to uplift it.
Attachment #8586547 - Flags: approval-mozilla-aurora?
OK. Thanks Milan. I'll wontfix it for 39 for now. If you want to revisit that let me know.
Depends on: 1167045
No longer depends on: 1167045
Reproduced with STR from bug 1138024 comment 1 using Firefox 38.0.5 build 4 (Build ID: 20150525141253) under Windows 8 32-bit. Verified fixed with latest 40.0a2 (Build ID: 20150608004126) under Windows 8 32-bit, 2 different machines with: nVIDIA GeForce 210 and nVIDIA GeForce 620. Also encountered bug 1163454. Is this enough to be called verified? If not, could you please give me some guidance? Thanks in advance!
Flags: needinfo?(matt.woodrow)
(In reply to Alexandra Lucinet, QA Mentor [:adalucinet] from comment #42) > Reproduced with STR from bug 1138024 comment 1 using Firefox 38.0.5 build 4 > (Build ID: 20150525141253) under Windows 8 32-bit. > Verified fixed with latest 40.0a2 (Build ID: 20150608004126) under Windows 8 > 32-bit, 2 different machines with: nVIDIA GeForce 210 and nVIDIA GeForce > 620. Also encountered bug 1163454. > Is this enough to be called verified? If not, could you please give me some > guidance? Thanks in advance! That's great, thanks. Can you please post in bug 1163454 with the details of how you reproduced and what hardware that was on etc?
Flags: needinfo?(matt.woodrow)
(In reply to Matt Woodrow (:mattwoodrow) from comment #43) > (In reply to Alexandra Lucinet, QA Mentor [:adalucinet] from comment #42) > > Reproduced with STR from bug 1138024 comment 1 using Firefox 38.0.5 build 4 > > (Build ID: 20150525141253) under Windows 8 32-bit. > > Verified fixed with latest 40.0a2 (Build ID: 20150608004126) under Windows 8 > > 32-bit, 2 different machines with: nVIDIA GeForce 210 and nVIDIA GeForce > > 620. Also encountered bug 1163454. > > Is this enough to be called verified? If not, could you please give me some > > guidance? Thanks in advance! > > That's great, thanks. > > Can you please post in bug 1163454 with the details of how you reproduced > and what hardware that was on etc? Sure thing, added the requested details in bug 1163454. Since you did not add anything else that needs testing, marking here accordingly.
Status: RESOLVED → VERIFIED
I also tried skipping the YUV -> RGB conversion using MediaFoundation, and instead tried to do the conversion in our shaders. Will upload the patch when I get to the machine that has it.
Flags: needinfo?(bas)
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: