quartz/vmr9: Cache surfaces on connection.

How to Survive does not reference the IDirect3DSurface9 in
IVMRSurfaceAllocator9::GetSurface(), nor does it dereference it in
IVMRSurfaceAllocator9::TerminateDevice(). Native quartz only asks for each
surface once, when connecting, and releases those surfaces when disconnecting,
which lets these two application bugs cancel each other out.

Signed-off-by: Zebediah Figura <zfigura@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zebediah Figura 2020-03-19 18:50:53 -05:00 committed by Alexandre Julliard
parent 01f83593ed
commit d6a70366e1
1 changed files with 27 additions and 7 deletions

View File

@ -75,6 +75,7 @@ struct quartz_vmr
/* Presentation related members */ /* Presentation related members */
IDirect3DDevice9 *allocator_d3d9_dev; IDirect3DDevice9 *allocator_d3d9_dev;
HMONITOR allocator_mon; HMONITOR allocator_mon;
IDirect3DSurface9 **surfaces;
DWORD num_surfaces; DWORD num_surfaces;
DWORD cur_surface; DWORD cur_surface;
DWORD_PTR cookie; DWORD_PTR cookie;
@ -312,14 +313,9 @@ static HRESULT WINAPI VMR9_DoRenderSample(struct strmbase_renderer *iface, IMedi
info.rtEnd = tStop; info.rtEnd = tStop;
info.szAspectRatio.cx = This->bmiheader.biWidth; info.szAspectRatio.cx = This->bmiheader.biWidth;
info.szAspectRatio.cy = This->bmiheader.biHeight; info.szAspectRatio.cy = This->bmiheader.biHeight;
info.lpSurf = This->surfaces[(++This->cur_surface) % This->num_surfaces];
hr = IVMRSurfaceAllocatorEx9_GetSurface(This->allocator, This->cookie, (++This->cur_surface)%This->num_surfaces, 0, &info.lpSurf);
if (FAILED(hr))
return hr;
VMR9_SendSampleData(This, &info, pbSrcStream, cbSrcStream); VMR9_SendSampleData(This, &info, pbSrcStream, cbSrcStream);
IDirect3DSurface9_Release(info.lpSurf);
if (This->renderer.filter.state == State_Paused) if (This->renderer.filter.state == State_Paused)
{ {
@ -351,7 +347,7 @@ static HRESULT WINAPI VMR9_CheckMediaType(struct strmbase_renderer *iface, const
static HRESULT initialize_device(struct quartz_vmr *filter, VMR9AllocationInfo *info) static HRESULT initialize_device(struct quartz_vmr *filter, VMR9AllocationInfo *info)
{ {
DWORD buffer_count = 1; DWORD buffer_count = 1, i;
HRESULT hr; HRESULT hr;
if (FAILED(hr = IVMRSurfaceAllocatorEx9_InitializeDevice(filter->allocator, if (FAILED(hr = IVMRSurfaceAllocatorEx9_InitializeDevice(filter->allocator,
@ -361,6 +357,25 @@ static HRESULT initialize_device(struct quartz_vmr *filter, VMR9AllocationInfo *
return hr; return hr;
} }
if (!(filter->surfaces = calloc(buffer_count, sizeof(IDirect3DSurface9 *))))
{
IVMRSurfaceAllocatorEx9_TerminateDevice(filter->allocator, filter->cookie);
return E_OUTOFMEMORY;
}
for (i = 0; i < buffer_count; ++i)
{
if (FAILED(hr = IVMRSurfaceAllocatorEx9_GetSurface(filter->allocator,
filter->cookie, i, 0, &filter->surfaces[i])))
{
ERR("Failed to get surface %u, hr %#x.\n", i, hr);
while (i--)
IDirect3DSurface9_Release(filter->surfaces[i]);
IVMRSurfaceAllocatorEx9_TerminateDevice(filter->allocator, filter->cookie);
return hr;
}
}
SetRect(&filter->source_rect, 0, 0, filter->bmiheader.biWidth, filter->bmiheader.biHeight); SetRect(&filter->source_rect, 0, 0, filter->bmiheader.biWidth, filter->bmiheader.biHeight);
filter->num_surfaces = buffer_count; filter->num_surfaces = buffer_count;
@ -538,6 +553,7 @@ static HRESULT WINAPI VMR9_BreakConnect(struct strmbase_renderer *This)
{ {
struct quartz_vmr *pVMR9 = impl_from_IBaseFilter(&This->filter.IBaseFilter_iface); struct quartz_vmr *pVMR9 = impl_from_IBaseFilter(&This->filter.IBaseFilter_iface);
HRESULT hr = S_OK; HRESULT hr = S_OK;
DWORD i;
if (!pVMR9->mode) if (!pVMR9->mode)
return S_FALSE; return S_FALSE;
@ -549,6 +565,10 @@ static HRESULT WINAPI VMR9_BreakConnect(struct strmbase_renderer *This)
} }
if (pVMR9->renderer.filter.state == State_Running) if (pVMR9->renderer.filter.state == State_Running)
hr = IVMRImagePresenter9_StopPresenting(pVMR9->presenter, pVMR9->cookie); hr = IVMRImagePresenter9_StopPresenting(pVMR9->presenter, pVMR9->cookie);
for (i = 0; i < pVMR9->num_surfaces; ++i)
IDirect3DSurface9_Release(pVMR9->surfaces[i]);
free(pVMR9->surfaces);
IVMRSurfaceAllocatorEx9_TerminateDevice(pVMR9->allocator, pVMR9->cookie); IVMRSurfaceAllocatorEx9_TerminateDevice(pVMR9->allocator, pVMR9->cookie);
pVMR9->num_surfaces = 0; pVMR9->num_surfaces = 0;
} }