Aric Stewart : quartz: Allocate surfaces in VMR-9.

Alexandre Julliard julliard at winehq.org
Thu Jun 7 13:39:17 CDT 2012


Module: wine
Branch: master
Commit: 82a562a603f75b08802b8dc569225689ca7dd491
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=82a562a603f75b08802b8dc569225689ca7dd491

Author: Aric Stewart <aric at codeweavers.com>
Date:   Wed Jun  6 13:47:16 2012 -0500

quartz: Allocate surfaces in VMR-9.

---

 dlls/quartz/vmr9.c |  166 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 165 insertions(+), 1 deletions(-)

diff --git a/dlls/quartz/vmr9.c b/dlls/quartz/vmr9.c
index a470fd2..8fa1b15 100644
--- a/dlls/quartz/vmr9.c
+++ b/dlls/quartz/vmr9.c
@@ -132,8 +132,12 @@ typedef struct
 
     IDirect3DDevice9 *d3d9_dev;
     IDirect3D9 *d3d9_ptr;
+    IDirect3DSurface9 **d3d9_surfaces;
     IDirect3DVertexBuffer9 *d3d9_vertex;
+    HMONITOR hMon;
+    DWORD num_surfaces;
 
+    BOOL reset;
     VMR9AllocationInfo info;
 
     VMR9Impl* pVMR9;
@@ -1349,9 +1353,22 @@ static ULONG WINAPI VMR9_ImagePresenter_Release(IVMRImagePresenter9 *iface)
 
     if (!refCount)
     {
+        int i;
         TRACE("Destroying\n");
         IUnknown_Release(This->d3d9_ptr);
 
+        TRACE("Number of surfaces: %u\n", This->num_surfaces);
+        for (i = 0; i < This->num_surfaces; ++i)
+        {
+            IDirect3DSurface9 *surface = This->d3d9_surfaces[i];
+            TRACE("Releasing surface %p\n", surface);
+            if (surface)
+                IUnknown_Release(surface);
+        }
+
+        CoTaskMemFree(This->d3d9_surfaces);
+        This->d3d9_surfaces = NULL;
+        This->num_surfaces = 0;
         if (This->d3d9_vertex)
         {
             IUnknown_Release(This->d3d9_vertex);
@@ -1527,6 +1544,29 @@ static ULONG WINAPI VMR9_SurfaceAllocator_Release(IVMRSurfaceAllocatorEx9 *iface
     return VMR9_ImagePresenter_Release(&This->IVMRImagePresenter9_iface);
 }
 
+static UINT d3d9_adapter_from_hwnd(IDirect3D9 *d3d9, HWND hwnd, HMONITOR *mon_out)
+{
+    UINT d3d9_adapter;
+    HMONITOR mon;
+
+    mon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONULL);
+    if (!mon)
+        d3d9_adapter = 0;
+    else
+    {
+        for (d3d9_adapter = 0; d3d9_adapter < IDirect3D9_GetAdapterCount(d3d9); ++d3d9_adapter)
+        {
+            if (mon == IDirect3D9_GetAdapterMonitor(d3d9, d3d9_adapter))
+                break;
+        }
+        if (d3d9_adapter >= IDirect3D9_GetAdapterCount(d3d9))
+            d3d9_adapter = 0;
+    }
+    if (mon_out)
+        *mon_out = mon;
+    return d3d9_adapter;
+}
+
 static HRESULT WINAPI VMR9_SurfaceAllocator_InitializeDevice(IVMRSurfaceAllocatorEx9 *iface, DWORD_PTR id, VMR9AllocationInfo *allocinfo, DWORD *numbuffers)
 {
     VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface);
@@ -1558,6 +1598,116 @@ static HRESULT WINAPI VMR9_SurfaceAllocator_TerminateDevice(IVMRSurfaceAllocator
     return S_OK;
 }
 
+/* Recreate all surfaces (If allocated as D3DPOOL_DEFAULT) and survive! */
+static HRESULT VMR9_SurfaceAllocator_UpdateDeviceReset(VMR9DefaultAllocatorPresenterImpl *This)
+{
+    struct VERTEX t_vert[4];
+    UINT width, height;
+    INT i;
+    void *bits = NULL;
+    D3DPRESENT_PARAMETERS d3dpp;
+    HRESULT hr;
+
+    if (!This->pVMR9->baseControlWindow.baseWindow.hWnd)
+    {
+        ERR("No window\n");
+        return E_FAIL;
+    }
+
+    if (!This->d3d9_surfaces || !This->reset)
+        return S_OK;
+
+    This->reset = FALSE;
+    TRACE("RESETTING\n");
+    if (This->d3d9_vertex)
+    {
+        IDirect3DVertexBuffer9_Release(This->d3d9_vertex);
+        This->d3d9_vertex = NULL;
+    }
+
+    for (i = 0; i < This->num_surfaces; ++i)
+    {
+        IDirect3DSurface9 *surface = This->d3d9_surfaces[i];
+        TRACE("Releasing surface %p\n", surface);
+        if (surface)
+            IUnknown_Release(surface);
+    }
+    ZeroMemory(This->d3d9_surfaces, sizeof(IDirect3DSurface9 *) * This->num_surfaces);
+
+    /* Now try to create the d3d9 device */
+    ZeroMemory(&d3dpp, sizeof(d3dpp));
+    d3dpp.Windowed = TRUE;
+    d3dpp.hDeviceWindow = This->pVMR9->baseControlWindow.baseWindow.hWnd;
+    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+
+    if (This->d3d9_dev)
+        IDirect3DDevice9_Release(This->d3d9_dev);
+    This->d3d9_dev = NULL;
+    hr = IDirect3D9_CreateDevice(This->d3d9_ptr, d3d9_adapter_from_hwnd(This->d3d9_ptr, This->pVMR9->baseControlWindow.baseWindow.hWnd, &This->hMon), D3DDEVTYPE_HAL, NULL, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &This->d3d9_dev);
+    if (FAILED(hr))
+    {
+        hr = IDirect3D9_CreateDevice(This->d3d9_ptr, d3d9_adapter_from_hwnd(This->d3d9_ptr, This->pVMR9->baseControlWindow.baseWindow.hWnd, &This->hMon), D3DDEVTYPE_HAL, NULL, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &This->d3d9_dev);
+        if (FAILED(hr))
+        {
+            ERR("--> Creating device: %08x\n", hr);
+            return S_OK;
+        }
+    }
+    IVMRSurfaceAllocatorNotify9_ChangeD3DDevice(This->SurfaceAllocatorNotify, This->d3d9_dev, This->hMon);
+
+    IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(This->SurfaceAllocatorNotify, &This->info, &This->num_surfaces, This->d3d9_surfaces);
+
+    This->reset = FALSE;
+
+    if (!(This->info.dwFlags & VMR9AllocFlag_TextureSurface))
+        return S_OK;
+
+    hr = IDirect3DDevice9_CreateVertexBuffer(This->d3d9_dev, 4 * sizeof(struct VERTEX), D3DUSAGE_WRITEONLY, USED_FVF,
+                                             This->info.Pool, &This->d3d9_vertex, NULL);
+
+    width = This->info.dwWidth;
+    height = This->info.dwHeight;
+
+    for (i = 0; i < sizeof(t_vert) / sizeof(t_vert[0]); ++i)
+    {
+        if (i % 2)
+        {
+            t_vert[i].x = (float)This->pVMR9->target_rect.right - (float)This->pVMR9->target_rect.left - 0.5f;
+            t_vert[i].u = (float)This->pVMR9->source_rect.right / (float)width;
+        }
+        else
+        {
+            t_vert[i].x = -0.5f;
+            t_vert[i].u = (float)This->pVMR9->source_rect.left / (float)width;
+        }
+
+        if (i % 4 < 2)
+        {
+            t_vert[i].y = -0.5f;
+            t_vert[i].v = (float)This->pVMR9->source_rect.bottom / (float)height;
+        }
+        else
+        {
+            t_vert[i].y = (float)This->pVMR9->target_rect.bottom - (float)This->pVMR9->target_rect.top - 0.5f;
+            t_vert[i].v = (float)This->pVMR9->source_rect.top / (float)height;
+        }
+        t_vert[i].z = 0.0f;
+        t_vert[i].rhw = 1.0f;
+    }
+
+    FIXME("Vertex rectangle:\n");
+    FIXME("X, Y: %f, %f\n", t_vert[0].x, t_vert[0].y);
+    FIXME("X, Y: %f, %f\n", t_vert[3].x, t_vert[3].y);
+    FIXME("TOP, LEFT: %f, %f\n", t_vert[0].u, t_vert[0].v);
+    FIXME("DOWN, BOTTOM: %f, %f\n", t_vert[3].u, t_vert[3].v);
+
+    IDirect3DVertexBuffer9_Lock(This->d3d9_vertex, 0, sizeof(t_vert), &bits, 0);
+    memcpy(bits, t_vert, sizeof(t_vert));
+    IDirect3DVertexBuffer9_Unlock(This->d3d9_vertex);
+
+    return S_OK;
+}
+
 static HRESULT WINAPI VMR9_SurfaceAllocator_GetSurface(IVMRSurfaceAllocatorEx9 *iface, DWORD_PTR id, DWORD surfaceindex, DWORD flags, IDirect3DSurface9 **surface)
 {
     VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface);
@@ -1569,7 +1719,17 @@ static HRESULT WINAPI VMR9_SurfaceAllocator_GetSurface(IVMRSurfaceAllocatorEx9 *
         return E_FAIL;
     }
 
-    return E_NOTIMPL;
+    VMR9_SurfaceAllocator_UpdateDeviceReset(This);
+
+    if (surfaceindex >= This->num_surfaces)
+    {
+        ERR("surfaceindex is greater than num_surfaces\n");
+        return E_FAIL;
+    }
+    *surface = This->d3d9_surfaces[surfaceindex];
+    IUnknown_AddRef(*surface);
+
+    return S_OK;
 }
 
 static HRESULT WINAPI VMR9_SurfaceAllocator_AdviseNotify(IVMRSurfaceAllocatorEx9 *iface, IVMRSurfaceAllocatorNotify9 *allocnotify)
@@ -1635,9 +1795,13 @@ static HRESULT VMR9DefaultAllocatorPresenterImpl_create(VMR9Impl *parent, LPVOID
 
     This->refCount = 1;
     This->pVMR9 = parent;
+    This->d3d9_surfaces = NULL;
     This->d3d9_dev = NULL;
+    This->hMon = 0;
     This->d3d9_vertex = NULL;
+    This->num_surfaces = 0;
     This->SurfaceAllocatorNotify = NULL;
+    This->reset = FALSE;
 
     *ppv = This;
     return S_OK;




More information about the wine-cvs mailing list