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:
parent
b54afbc3a1
commit
45743b4d9f
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue