[PATCH v3 4/6] quartz/vmr9: Cache surfaces on connection.

Zebediah Figura z.figura12 at gmail.com
Thu Mar 19 11:29:21 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 68fc496c9f2..8f6e91ed623 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