diff --git a/dom/media/MediaDecoderStateMachine.cpp b/dom/media/MediaDecoderStateMachine.cpp index 01f6a3387ae7..ae04a4b971bc 100644 --- a/dom/media/MediaDecoderStateMachine.cpp +++ b/dom/media/MediaDecoderStateMachine.cpp @@ -48,6 +48,7 @@ #include "TimeUnits.h" #include "VideoSegment.h" #include "VideoUtils.h" +#include "gfxPrefs.h" namespace mozilla { @@ -2420,7 +2421,7 @@ MediaDecoderStateMachine::CheckFrameValidity(VideoData* aData) MOZ_ASSERT(OnTaskQueue()); // Update corrupt-frames statistics - if (aData->mImage && !aData->mImage->IsValid()) { + if (aData->mImage && !aData->mImage->IsValid() && !gfxPrefs::HardwareVideoDecodingForceEnabled()) { FrameStatistics& frameStats = *mFrameStats; frameStats.NotifyCorruptFrame(); // If more than 10% of the last 30 frames have been corrupted, then try disabling diff --git a/dom/media/platforms/wmf/DXVA2Manager.cpp b/dom/media/platforms/wmf/DXVA2Manager.cpp index dfa71b3c6e28..fca385fcc2bf 100644 --- a/dom/media/platforms/wmf/DXVA2Manager.cpp +++ b/dom/media/platforms/wmf/DXVA2Manager.cpp @@ -423,12 +423,40 @@ D3D9DXVA2Manager::CopyToImage(IMFSample* aSample, getter_AddRefs(surface)); NS_ENSURE_TRUE(SUCCEEDED(hr), hr); - RefPtr image = new D3D9SurfaceImage(mFirstFrame); + RefPtr image = new D3D9SurfaceImage(); hr = image->AllocateAndCopy(mTextureClientAllocator, surface, aRegion); NS_ENSURE_TRUE(SUCCEEDED(hr), hr); + // Flush the draw command now, so that by the time we come to draw this + // image, we're less likely to need to wait for the draw operation to + // complete. + RefPtr query; + hr = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, getter_AddRefs(query)); + NS_ENSURE_TRUE(SUCCEEDED(hr), hr); + hr = query->Issue(D3DISSUE_END); + NS_ENSURE_TRUE(SUCCEEDED(hr), hr); + + bool valid = false; + int iterations = 0; + while (iterations < (mFirstFrame ? 100 : 10)) { + hr = query->GetData(nullptr, 0, D3DGETDATA_FLUSH); + if (hr == S_FALSE) { + Sleep(1); + iterations++; + continue; + } + if (hr == S_OK) { + valid = true; + } + break; + } + mFirstFrame = false; + if (!valid) { + image->Invalidate(); + } + image.forget(aOutImage); return S_OK; } diff --git a/gfx/layers/D3D9SurfaceImage.cpp b/gfx/layers/D3D9SurfaceImage.cpp index bc49f45261c6..745499fea578 100644 --- a/gfx/layers/D3D9SurfaceImage.cpp +++ b/gfx/layers/D3D9SurfaceImage.cpp @@ -15,11 +15,10 @@ namespace mozilla { namespace layers { -D3D9SurfaceImage::D3D9SurfaceImage(bool aIsFirstFrame) +D3D9SurfaceImage::D3D9SurfaceImage() : Image(nullptr, ImageFormat::D3D9_RGB32_TEXTURE) , mSize(0, 0) , mValid(false) - , mIsFirstFrame(aIsFirstFrame) {} D3D9SurfaceImage::~D3D9SurfaceImage() @@ -73,52 +72,11 @@ D3D9SurfaceImage::AllocateAndCopy(D3D9RecycleAllocator* aAllocator, hr = device->StretchRect(surface, &src, textureSurface, nullptr, D3DTEXF_NONE); NS_ENSURE_TRUE(SUCCEEDED(hr), hr); - // Flush the draw command now, so that by the time we come to draw this - // image, we're less likely to need to wait for the draw operation to - // complete. - RefPtr query; - hr = device->CreateQuery(D3DQUERYTYPE_EVENT, getter_AddRefs(query)); - NS_ENSURE_TRUE(SUCCEEDED(hr), hr); - hr = query->Issue(D3DISSUE_END); - NS_ENSURE_TRUE(SUCCEEDED(hr), hr); - mTextureClient = textureClient; mSize = aRegion.Size(); - mQuery = query; return S_OK; } -bool -D3D9SurfaceImage::IsValid() -{ - EnsureSynchronized(); - return mValid; -} - -void -D3D9SurfaceImage::EnsureSynchronized() -{ - RefPtr query = mQuery; - if (!query) { - // Not setup, or already synchronized. - return; - } - int iterations = 0; - while (iterations < (mIsFirstFrame ? 100 : 10)) { - HRESULT hr = query->GetData(nullptr, 0, D3DGETDATA_FLUSH); - if (hr == S_FALSE) { - Sleep(1); - iterations++; - continue; - } - if (hr == S_OK) { - mValid = true; - } - break; - } - mQuery = nullptr; -} - const D3DSURFACE_DESC& D3D9SurfaceImage::GetDesc() const { @@ -136,7 +94,6 @@ D3D9SurfaceImage::GetTextureClient(CompositableClient* aClient) { MOZ_ASSERT(mTextureClient); MOZ_ASSERT(mTextureClient->GetAllocator() == aClient->GetForwarder()); - EnsureSynchronized(); return mTextureClient; } @@ -153,9 +110,6 @@ D3D9SurfaceImage::GetAsSourceSurface() return nullptr; } - // Ensure that the texture is ready to be used. - EnsureSynchronized(); - DXGID3D9TextureData* texData = static_cast(mTextureClient->GetInternalData()); // Readback the texture from GPU memory into system memory, so that // we can copy it into the Cairo image. This is expensive. diff --git a/gfx/layers/D3D9SurfaceImage.h b/gfx/layers/D3D9SurfaceImage.h index 86c7616ad2e4..9ea39045f7f0 100644 --- a/gfx/layers/D3D9SurfaceImage.h +++ b/gfx/layers/D3D9SurfaceImage.h @@ -47,7 +47,7 @@ protected: // resource is ready to use. class D3D9SurfaceImage : public Image { public: - explicit D3D9SurfaceImage(bool aIsFirstFrame); + explicit D3D9SurfaceImage(); virtual ~D3D9SurfaceImage(); HRESULT AllocateAndCopy(D3D9RecycleAllocator* aAllocator, @@ -63,19 +63,15 @@ public: virtual TextureClient* GetTextureClient(CompositableClient* aClient) override; - virtual bool IsValid() override; + virtual bool IsValid() override { return mValid; } + + void Invalidate() { mValid = false; } private: - // Blocks the calling thread until the copy operation started in SetData() - // is complete, whereupon the texture is safe to use. - void EnsureSynchronized(); - gfx::IntSize mSize; - RefPtr mQuery; RefPtr mTextureClient; bool mValid; - bool mIsFirstFrame; }; } // namepace layers