[PATCH 4/6] quartz/vmr9: Cache surfaces on connection.
Zebediah Figura
z.figura12 at gmail.com
Wed Mar 18 19:55:33 CDT 2020
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 at codeweavers.com>
---
dlls/quartz/vmr9.c | 34 +++++++++++++++++++++++++++-------
1 file changed, 27 insertions(+), 7 deletions(-)
diff --git a/dlls/quartz/vmr9.c b/dlls/quartz/vmr9.c
index c2cd8fbf260..84d8f66705d 100644
--- a/dlls/quartz/vmr9.c
+++ b/dlls/quartz/vmr9.c
@@ -75,6 +75,7 @@ struct quartz_vmr
/* Presentation related members */
IDirect3DDevice9 *allocator_d3d9_dev;
HMONITOR allocator_mon;
+ IDirect3DSurface9 **surfaces;
DWORD num_surfaces;
DWORD cur_surface;
DWORD_PTR cookie;
@@ -312,14 +313,9 @@ static HRESULT WINAPI VMR9_DoRenderSample(struct strmbase_renderer *iface, IMedi
info.rtEnd = tStop;
info.szAspectRatio.cx = This->bmiheader.biWidth;
info.szAspectRatio.cy = This->bmiheader.biHeight;
-
- hr = IVMRSurfaceAllocatorEx9_GetSurface(This->allocator, This->cookie, (++This->cur_surface)%This->num_surfaces, 0, &info.lpSurf);
-
- if (FAILED(hr))
- return hr;
+ info.lpSurf = This->surfaces[(++This->cur_surface) % This->num_surfaces];
VMR9_SendSampleData(This, &info, pbSrcStream, cbSrcStream);
- IDirect3DSurface9_Release(info.lpSurf);
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)
{
- DWORD buffer_count = 1;
+ DWORD buffer_count = 1, i;
HRESULT hr;
if (FAILED(hr = IVMRSurfaceAllocatorEx9_InitializeDevice(filter->allocator,
@@ -361,6 +357,25 @@ static HRESULT initialize_device(struct quartz_vmr *filter, VMR9AllocationInfo *
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);
filter->num_surfaces = buffer_count;
@@ -519,6 +534,7 @@ static HRESULT WINAPI VMR9_BreakConnect(struct strmbase_renderer *This)
{
struct quartz_vmr *pVMR9 = impl_from_IBaseFilter(&This->filter.IBaseFilter_iface);
HRESULT hr = S_OK;
+ DWORD i;
if (!pVMR9->mode)
return S_FALSE;
@@ -530,6 +546,10 @@ static HRESULT WINAPI VMR9_BreakConnect(struct strmbase_renderer *This)
}
if (pVMR9->renderer.filter.state == State_Running)
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);
pVMR9->num_surfaces = 0;
}
--
2.25.1
More information about the wine-devel
mailing list