mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 19:04:45 +00:00
Bug 1257013 - Part 1: Use readback to synchronize d3d9 video. r=cpearce,Bas
--HG-- extra : rebase_source : 104b692bb1f732ec86113506ebac8961ac8fb5b8
This commit is contained in:
parent
c20d56eea7
commit
49c3c58a6c
@ -66,6 +66,11 @@ static const DWORD sAMDPreUVD4[] = {
|
||||
0x999c, 0x999d, 0x99a0, 0x99a2, 0x99a4
|
||||
};
|
||||
|
||||
// The size we use for our synchronization surface.
|
||||
// 16x16 is the size recommended by Microsoft (in the D3D9ExDXGISharedSurf sample) that works
|
||||
// best to avoid driver bugs.
|
||||
static const uint32_t kSyncSurfaceSize = 16;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using layers::Image;
|
||||
@ -100,6 +105,7 @@ private:
|
||||
RefPtr<IDirect3DDeviceManager9> mDeviceManager;
|
||||
RefPtr<D3D9RecycleAllocator> mTextureClientAllocator;
|
||||
RefPtr<IDirectXVideoDecoderService> mDecoderService;
|
||||
RefPtr<IDirect3DSurface9> mSyncSurface;
|
||||
GUID mDecoderGUID;
|
||||
UINT32 mResetToken;
|
||||
bool mFirstFrame;
|
||||
@ -392,12 +398,19 @@ D3D9DXVA2Manager::Init(nsACString& aFailureReason)
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<IDirect3DSurface9> syncSurf;
|
||||
hr = device->CreateRenderTarget(kSyncSurfaceSize, kSyncSurfaceSize,
|
||||
D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE,
|
||||
0, TRUE, getter_AddRefs(syncSurf), NULL);
|
||||
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
|
||||
|
||||
mDecoderService = decoderService;
|
||||
|
||||
mResetToken = resetToken;
|
||||
mD3D9 = d3d9Ex;
|
||||
mDevice = device;
|
||||
mDeviceManager = deviceManager;
|
||||
mSyncSurface = syncSurf;
|
||||
|
||||
mTextureClientAllocator = new D3D9RecycleAllocator(layers::ImageBridgeChild::GetSingleton(),
|
||||
mDevice);
|
||||
@ -427,35 +440,20 @@ D3D9DXVA2Manager::CopyToImage(IMFSample* aSample,
|
||||
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<IDirect3DQuery9> query;
|
||||
hr = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, getter_AddRefs(query));
|
||||
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
|
||||
hr = query->Issue(D3DISSUE_END);
|
||||
RefPtr<IDirect3DSurface9> sourceSurf = image->GetD3D9Surface();
|
||||
|
||||
// Copy a small rect into our sync surface, and then map it
|
||||
// to block until decoding/color conversion completes.
|
||||
RECT copyRect = { 0, 0, kSyncSurfaceSize, kSyncSurfaceSize };
|
||||
hr = mDevice->StretchRect(sourceSurf, ©Rect, mSyncSurface, ©Rect, D3DTEXF_NONE);
|
||||
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;
|
||||
}
|
||||
D3DLOCKED_RECT lockedRect;
|
||||
hr = mSyncSurface->LockRect(&lockedRect, NULL, D3DLOCK_READONLY);
|
||||
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
|
||||
|
||||
mFirstFrame = false;
|
||||
|
||||
if (!valid) {
|
||||
image->Invalidate();
|
||||
}
|
||||
hr = mSyncSurface->UnlockRect();
|
||||
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
|
||||
|
||||
image.forget(aOutImage);
|
||||
return S_OK;
|
||||
|
@ -77,6 +77,13 @@ D3D9SurfaceImage::AllocateAndCopy(D3D9RecycleAllocator* aAllocator,
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<IDirect3DSurface9>
|
||||
D3D9SurfaceImage::GetD3D9Surface()
|
||||
{
|
||||
return static_cast<DXGID3D9TextureData*>(
|
||||
mTextureClient->GetInternalData())->GetD3D9Surface();
|
||||
}
|
||||
|
||||
const D3DSURFACE_DESC&
|
||||
D3D9SurfaceImage::GetDesc() const
|
||||
{
|
||||
|
@ -63,6 +63,8 @@ public:
|
||||
|
||||
virtual TextureClient* GetTextureClient(CompositableClient* aClient) override;
|
||||
|
||||
already_AddRefed<IDirect3DSurface9> GetD3D9Surface();
|
||||
|
||||
virtual bool IsValid() override { return mValid; }
|
||||
|
||||
void Invalidate() { mValid = false; }
|
||||
|
Loading…
Reference in New Issue
Block a user