Commit 45743b4d authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

d3drm: Implement AddDestroyCallback/DeleteDestroyCallback for a viewport.

parent b54afbc3
...@@ -18,13 +18,14 @@ ...@@ -18,13 +18,14 @@
*/ */
#include <stdarg.h> #include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "d3d.h" #include "d3d.h"
#include "dxfile.h"
#include "initguid.h" #include "initguid.h"
#include "d3drm.h" #include "d3drm.h"
#include "d3drm_private.h"
#include "wine/list.h"
/*********************************************************************** /***********************************************************************
* DllMain (D3DRM.@) * DllMain (D3DRM.@)
...@@ -41,3 +42,66 @@ BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, void *reserved) ...@@ -41,3 +42,66 @@ BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, void *reserved)
} }
return TRUE; 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);
}
}
...@@ -24,13 +24,21 @@ ...@@ -24,13 +24,21 @@
#include "d3drm.h" #include "d3drm.h"
#include "dxfile.h" #include "dxfile.h"
#include "wine/list.h"
struct d3drm_device; struct d3drm_device;
struct d3drm_object struct d3drm_object
{ {
LONG ref; LONG ref;
DWORD appdata; 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; HRESULT d3drm_device_create(struct d3drm_device **out) DECLSPEC_HIDDEN;
IDirect3DRMDevice *IDirect3DRMDevice_from_impl(struct d3drm_device *device) DECLSPEC_HIDDEN; IDirect3DRMDevice *IDirect3DRMDevice_from_impl(struct d3drm_device *device) DECLSPEC_HIDDEN;
IDirect3DRMDevice2 *IDirect3DRMDevice2_from_impl(struct d3drm_device *device) DECLSPEC_HIDDEN; IDirect3DRMDevice2 *IDirect3DRMDevice2_from_impl(struct d3drm_device *device) DECLSPEC_HIDDEN;
......
...@@ -1212,8 +1212,31 @@ static void test_Frame(void) ...@@ -1212,8 +1212,31 @@ static void test_Frame(void)
IDirect3DRM_Release(d3drm); 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) static void test_Viewport(void)
{ {
struct destroy_context context;
IDirectDrawClipper *pClipper; IDirectDrawClipper *pClipper;
HRESULT hr; HRESULT hr;
IDirect3DRM *d3drm; IDirect3DRM *d3drm;
...@@ -1299,7 +1322,79 @@ static void test_Viewport(void) ...@@ -1299,7 +1322,79 @@ static void test_Viewport(void)
ok(data == 1, "got %x\n", data); ok(data == 1, "got %x\n", data);
IDirect3DRMViewport2_Release(viewport2); 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); 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); IDirect3DRMFrame_Release(frame);
IDirect3DRMDevice_Release(device); IDirect3DRMDevice_Release(device);
IDirectDrawClipper_Release(pClipper); IDirectDrawClipper_Release(pClipper);
......
...@@ -95,7 +95,10 @@ static ULONG WINAPI d3drm_viewport1_Release(IDirect3DRMViewport *iface) ...@@ -95,7 +95,10 @@ static ULONG WINAPI d3drm_viewport1_Release(IDirect3DRMViewport *iface)
TRACE("%p decreasing refcount to %u.\n", iface, refcount); TRACE("%p decreasing refcount to %u.\n", iface, refcount);
if (!refcount) if (!refcount)
{
d3drm_object_cleanup((IDirect3DRMObject*)iface, &viewport->obj);
HeapFree(GetProcessHeap(), 0, viewport); HeapFree(GetProcessHeap(), 0, viewport);
}
return refcount; return refcount;
} }
...@@ -111,17 +114,21 @@ static HRESULT WINAPI d3drm_viewport1_Clone(IDirect3DRMViewport *iface, ...@@ -111,17 +114,21 @@ static HRESULT WINAPI d3drm_viewport1_Clone(IDirect3DRMViewport *iface,
static HRESULT WINAPI d3drm_viewport1_AddDestroyCallback(IDirect3DRMViewport *iface, static HRESULT WINAPI d3drm_viewport1_AddDestroyCallback(IDirect3DRMViewport *iface,
D3DRMOBJECTCALLBACK cb, void *ctx) 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, static HRESULT WINAPI d3drm_viewport1_DeleteDestroyCallback(IDirect3DRMViewport *iface,
D3DRMOBJECTCALLBACK cb, void *ctx) 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) static HRESULT WINAPI d3drm_viewport1_SetAppData(IDirect3DRMViewport *iface, DWORD data)
...@@ -468,17 +475,21 @@ static HRESULT WINAPI d3drm_viewport2_Clone(IDirect3DRMViewport2 *iface, ...@@ -468,17 +475,21 @@ static HRESULT WINAPI d3drm_viewport2_Clone(IDirect3DRMViewport2 *iface,
static HRESULT WINAPI d3drm_viewport2_AddDestroyCallback(IDirect3DRMViewport2 *iface, static HRESULT WINAPI d3drm_viewport2_AddDestroyCallback(IDirect3DRMViewport2 *iface,
D3DRMOBJECTCALLBACK cb, void *ctx) 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, static HRESULT WINAPI d3drm_viewport2_DeleteDestroyCallback(IDirect3DRMViewport2 *iface,
D3DRMOBJECTCALLBACK cb, void *ctx) 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) static HRESULT WINAPI d3drm_viewport2_SetAppData(IDirect3DRMViewport2 *iface, DWORD data)
...@@ -829,7 +840,7 @@ HRESULT Direct3DRMViewport_create(REFIID riid, IUnknown **out) ...@@ -829,7 +840,7 @@ HRESULT Direct3DRMViewport_create(REFIID riid, IUnknown **out)
object->IDirect3DRMViewport_iface.lpVtbl = &d3drm_viewport1_vtbl; object->IDirect3DRMViewport_iface.lpVtbl = &d3drm_viewport1_vtbl;
object->IDirect3DRMViewport2_iface.lpVtbl = &d3drm_viewport2_vtbl; object->IDirect3DRMViewport2_iface.lpVtbl = &d3drm_viewport2_vtbl;
object->obj.ref = 1; d3drm_object_init(&object->obj);
if (IsEqualGUID(riid, &IID_IDirect3DRMViewport2)) if (IsEqualGUID(riid, &IID_IDirect3DRMViewport2))
*out = (IUnknown *)&object->IDirect3DRMViewport2_iface; *out = (IUnknown *)&object->IDirect3DRMViewport2_iface;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment