d3drm: Implement AddDestroyCallback/DeleteDestroyCallback for a viewport.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2016-03-03 11:10:21 +03:00 committed by Alexandre Julliard
parent b54afbc3a1
commit 45743b4d9f
4 changed files with 190 additions and 12 deletions

View File

@ -18,13 +18,14 @@
*/
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "d3d.h"
#include "dxfile.h"
#include "initguid.h"
#include "d3drm.h"
#include "d3drm_private.h"
#include "wine/list.h"
/***********************************************************************
* DllMain (D3DRM.@)
@ -41,3 +42,66 @@ BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, void *reserved)
}
return TRUE;
}
void d3drm_object_init(struct d3drm_object *object)
{
object->ref = 1;
object->appdata = 0;
list_init(&object->destroy_callbacks);
}
struct destroy_callback
{
struct list entry;
D3DRMOBJECTCALLBACK cb;
void *ctx;
};
HRESULT d3drm_object_add_destroy_callback(struct d3drm_object *object, D3DRMOBJECTCALLBACK cb, void *ctx)
{
struct destroy_callback *callback;
if (!cb)
return D3DRMERR_BADVALUE;
callback = HeapAlloc(GetProcessHeap(), 0, sizeof(*callback));
if (!callback)
return E_OUTOFMEMORY;
callback->cb = cb;
callback->ctx = ctx;
list_add_head(&object->destroy_callbacks, &callback->entry);
return D3DRM_OK;
}
HRESULT d3drm_object_delete_destroy_callback(struct d3drm_object *object, D3DRMOBJECTCALLBACK cb, void *ctx)
{
struct destroy_callback *callback, *callback2;
if (!cb)
return D3DRMERR_BADVALUE;
LIST_FOR_EACH_ENTRY_SAFE(callback, callback2, &object->destroy_callbacks, struct destroy_callback, entry)
{
if (callback->cb == cb && callback->ctx == ctx)
{
list_remove(&callback->entry);
HeapFree(GetProcessHeap(), 0, callback);
}
}
return D3DRM_OK;
}
void d3drm_object_cleanup(IDirect3DRMObject *iface, struct d3drm_object *object)
{
struct destroy_callback *callback, *callback2;
LIST_FOR_EACH_ENTRY_SAFE(callback, callback2, &object->destroy_callbacks, struct destroy_callback, entry)
{
callback->cb(iface, callback->ctx);
list_remove(&callback->entry);
HeapFree(GetProcessHeap(), 0, callback);
}
}

View File

@ -24,13 +24,21 @@
#include "d3drm.h"
#include "dxfile.h"
#include "wine/list.h"
struct d3drm_device;
struct d3drm_object
{
LONG ref;
DWORD appdata;
struct list destroy_callbacks;
};
void d3drm_object_init(struct d3drm_object *object) DECLSPEC_HIDDEN;
HRESULT d3drm_object_add_destroy_callback(struct d3drm_object *object, D3DRMOBJECTCALLBACK cb, void *ctx) DECLSPEC_HIDDEN;
HRESULT d3drm_object_delete_destroy_callback(struct d3drm_object *object, D3DRMOBJECTCALLBACK cb, void *ctx) DECLSPEC_HIDDEN;
void d3drm_object_cleanup(IDirect3DRMObject *iface, struct d3drm_object *object) DECLSPEC_HIDDEN;
HRESULT d3drm_device_create(struct d3drm_device **out) DECLSPEC_HIDDEN;
IDirect3DRMDevice *IDirect3DRMDevice_from_impl(struct d3drm_device *device) DECLSPEC_HIDDEN;
IDirect3DRMDevice2 *IDirect3DRMDevice2_from_impl(struct d3drm_device *device) DECLSPEC_HIDDEN;

View File

@ -1212,8 +1212,31 @@ static void test_Frame(void)
IDirect3DRM_Release(d3drm);
}
struct destroy_context
{
IDirect3DRMObject *obj;
int called;
};
static void CDECL destroy_callback(IDirect3DRMObject *obj, void *arg)
{
struct destroy_context *ctxt = arg;
ok(ctxt->called == 1 || ctxt->called == 2, "got called counter %d\n", ctxt->called);
ok(obj == ctxt->obj, "called with %p, expected %p\n", obj, ctxt->obj);
ctxt->called++;
}
static void CDECL destroy_callback1(IDirect3DRMObject *obj, void *arg)
{
struct destroy_context *ctxt = (struct destroy_context*)arg;
ok(ctxt->called == 0, "got called counter %d\n", ctxt->called);
ok(obj == ctxt->obj, "called with %p, expected %p\n", obj, ctxt->obj);
ctxt->called++;
}
static void test_Viewport(void)
{
struct destroy_context context;
IDirectDrawClipper *pClipper;
HRESULT hr;
IDirect3DRM *d3drm;
@ -1299,7 +1322,79 @@ static void test_Viewport(void)
ok(data == 1, "got %x\n", data);
IDirect3DRMViewport2_Release(viewport2);
/* destroy callback */
context.called = 0;
hr = IDirect3DRMViewport_QueryInterface(viewport, &IID_IDirect3DRMObject, (void**)&context.obj);
ok(hr == D3DRM_OK, "expected D3DRM_OK (hr = %x)\n", hr);
IDirect3DRMObject_Release(context.obj);
hr = IDirect3DRMViewport_AddDestroyCallback(viewport, NULL, &context);
ok(hr == D3DRMERR_BADVALUE, "expected D3DRMERR_BADVALUE (hr = %x)\n", hr);
hr = IDirect3DRMViewport_AddDestroyCallback(viewport, destroy_callback, &context);
ok(hr == D3DRM_OK, "expected D3DRM_OK (hr = %x)\n", hr);
/* same callback added twice */
hr = IDirect3DRMViewport_AddDestroyCallback(viewport, destroy_callback, &context);
ok(hr == D3DRM_OK, "expected D3DRM_OK (hr = %x)\n", hr);
hr = IDirect3DRMViewport_DeleteDestroyCallback(viewport, destroy_callback1, NULL);
ok(hr == D3DRM_OK, "expected D3DRM_OK (hr = %x)\n", hr);
hr = IDirect3DRMViewport_DeleteDestroyCallback(viewport, destroy_callback1, &context);
ok(hr == D3DRM_OK, "expected D3DRM_OK (hr = %x)\n", hr);
/* add one more */
hr = IDirect3DRMViewport_AddDestroyCallback(viewport, destroy_callback1, &context);
ok(hr == D3DRM_OK, "expected D3DRM_OK (hr = %x)\n", hr);
hr = IDirect3DRMViewport_DeleteDestroyCallback(viewport, NULL, NULL);
ok(hr == D3DRMERR_BADVALUE, "expected D3DRM_BADVALUE (hr = %x)\n", hr);
context.called = 0;
IDirect3DRMViewport_Release(viewport);
ok(context.called == 3, "got %d, expected 3\n", context.called);
/* destroy from Viewport2 */
hr = IDirect3DRM_CreateViewport(d3drm, device, frame, rc.left, rc.top, rc.right, rc.bottom, &viewport);
ok(hr == D3DRM_OK, "Cannot get IDirect3DRMViewport interface (hr = %x)\n", hr);
hr = IDirect3DRMViewport_QueryInterface(viewport, &IID_IDirect3DRMViewport2, (void**)&viewport2);
ok(hr == D3DRM_OK, "expected D3DRM_OK (hr = %x)\n", hr);
IDirect3DRMViewport_Release(viewport);
context.called = 0;
hr = IDirect3DRMViewport2_QueryInterface(viewport2, &IID_IDirect3DRMObject, (void**)&context.obj);
ok(hr == D3DRM_OK, "expected D3DRM_OK (hr = %x)\n", hr);
IDirect3DRMObject_Release(context.obj);
hr = IDirect3DRMViewport2_AddDestroyCallback(viewport2, NULL, &context);
ok(hr == D3DRMERR_BADVALUE, "expected D3DRMERR_BADVALUE (hr = %x)\n", hr);
hr = IDirect3DRMViewport2_AddDestroyCallback(viewport2, destroy_callback, &context);
ok(hr == D3DRM_OK, "expected D3DRM_OK (hr = %x)\n", hr);
/* same callback added twice */
hr = IDirect3DRMViewport2_AddDestroyCallback(viewport2, destroy_callback, &context);
ok(hr == D3DRM_OK, "expected D3DRM_OK (hr = %x)\n", hr);
hr = IDirect3DRMViewport2_DeleteDestroyCallback(viewport2, destroy_callback1, NULL);
ok(hr == D3DRM_OK, "expected D3DRM_OK (hr = %x)\n", hr);
hr = IDirect3DRMViewport2_DeleteDestroyCallback(viewport2, destroy_callback1, &context);
ok(hr == D3DRM_OK, "expected D3DRM_OK (hr = %x)\n", hr);
/* add one more */
hr = IDirect3DRMViewport2_AddDestroyCallback(viewport2, destroy_callback1, &context);
ok(hr == D3DRM_OK, "expected D3DRM_OK (hr = %x)\n", hr);
hr = IDirect3DRMViewport2_DeleteDestroyCallback(viewport2, NULL, NULL);
ok(hr == D3DRMERR_BADVALUE, "expected D3DRM_BADVALUE (hr = %x)\n", hr);
context.called = 0;
IDirect3DRMViewport2_Release(viewport2);
ok(context.called == 3, "got %d, expected 3\n", context.called);
IDirect3DRMFrame_Release(frame);
IDirect3DRMDevice_Release(device);
IDirectDrawClipper_Release(pClipper);

View File

@ -95,7 +95,10 @@ static ULONG WINAPI d3drm_viewport1_Release(IDirect3DRMViewport *iface)
TRACE("%p decreasing refcount to %u.\n", iface, refcount);
if (!refcount)
{
d3drm_object_cleanup((IDirect3DRMObject*)iface, &viewport->obj);
HeapFree(GetProcessHeap(), 0, viewport);
}
return refcount;
}
@ -111,17 +114,21 @@ static HRESULT WINAPI d3drm_viewport1_Clone(IDirect3DRMViewport *iface,
static HRESULT WINAPI d3drm_viewport1_AddDestroyCallback(IDirect3DRMViewport *iface,
D3DRMOBJECTCALLBACK cb, void *ctx)
{
FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport(iface);
return E_NOTIMPL;
TRACE("iface %p, cb %p, ctx %p\n", iface, cb, ctx);
return IDirect3DRMViewport2_AddDestroyCallback(&viewport->IDirect3DRMViewport2_iface, cb, ctx);
}
static HRESULT WINAPI d3drm_viewport1_DeleteDestroyCallback(IDirect3DRMViewport *iface,
D3DRMOBJECTCALLBACK cb, void *ctx)
{
FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport(iface);
return E_NOTIMPL;
TRACE("iface %p, cb %p, ctx %p\n", iface, cb, ctx);
return IDirect3DRMViewport2_DeleteDestroyCallback(&viewport->IDirect3DRMViewport2_iface, cb, ctx);
}
static HRESULT WINAPI d3drm_viewport1_SetAppData(IDirect3DRMViewport *iface, DWORD data)
@ -468,17 +475,21 @@ static HRESULT WINAPI d3drm_viewport2_Clone(IDirect3DRMViewport2 *iface,
static HRESULT WINAPI d3drm_viewport2_AddDestroyCallback(IDirect3DRMViewport2 *iface,
D3DRMOBJECTCALLBACK cb, void *ctx)
{
FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport2(iface);
return E_NOTIMPL;
TRACE("iface %p, cb %p, ctx %p\n", iface, cb, ctx);
return d3drm_object_add_destroy_callback(&viewport->obj, cb, ctx);
}
static HRESULT WINAPI d3drm_viewport2_DeleteDestroyCallback(IDirect3DRMViewport2 *iface,
D3DRMOBJECTCALLBACK cb, void *ctx)
{
FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport2(iface);
return E_NOTIMPL;
TRACE("iface %p, cb %p, ctx %p\n", iface, cb, ctx);
return d3drm_object_delete_destroy_callback(&viewport->obj, cb, ctx);
}
static HRESULT WINAPI d3drm_viewport2_SetAppData(IDirect3DRMViewport2 *iface, DWORD data)
@ -829,7 +840,7 @@ HRESULT Direct3DRMViewport_create(REFIID riid, IUnknown **out)
object->IDirect3DRMViewport_iface.lpVtbl = &d3drm_viewport1_vtbl;
object->IDirect3DRMViewport2_iface.lpVtbl = &d3drm_viewport2_vtbl;
object->obj.ref = 1;
d3drm_object_init(&object->obj);
if (IsEqualGUID(riid, &IID_IDirect3DRMViewport2))
*out = (IUnknown *)&object->IDirect3DRMViewport2_iface;