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