From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/d3dkmt.c | 23 ++++++-- dlls/win32u/tests/d3dkmt.c | 12 ++--- server/d3dkmt.c | 108 ++++++++++++++++++++++++++++++++++--- server/protocol.def | 2 + 4 files changed, 129 insertions(+), 16 deletions(-)
diff --git a/dlls/win32u/d3dkmt.c b/dlls/win32u/d3dkmt.c index e47a95d9c85..2deefd7aada 100644 --- a/dlls/win32u/d3dkmt.c +++ b/dlls/win32u/d3dkmt.c @@ -908,7 +908,7 @@ void free_vulkan_gpu( struct vulkan_gpu *gpu ) NTSTATUS WINAPI NtGdiDdDDIShareObjects( UINT count, const D3DKMT_HANDLE *handles, OBJECT_ATTRIBUTES *attr, UINT access, HANDLE *handle ) { - struct d3dkmt_object *object, *sync; + struct d3dkmt_object *object, *resource = NULL, *sync = NULL, *mutex = NULL; struct object_attributes *objattr; data_size_t len; NTSTATUS status; @@ -918,9 +918,24 @@ NTSTATUS WINAPI NtGdiDdDDIShareObjects( UINT count, const D3DKMT_HANDLE *handles if (count == 1) { if (!(object = get_d3dkmt_object( handles[0], -1 )) || !object->shared) goto failed; - if (object->type == D3DKMT_SYNC) sync = object; + if (object->type == D3DKMT_RESOURCE) resource = object; + else if (object->type == D3DKMT_SYNC) sync = object; else goto failed; } + else if (count == 3) + { + if (!(object = get_d3dkmt_object( handles[0], -1 )) || !object->shared) goto failed; + if (object->type != D3DKMT_RESOURCE) goto failed; + resource = object; + + if (!(object = get_d3dkmt_object( handles[1], -1 )) || !object->shared) goto failed; + if (object->type != D3DKMT_MUTEX) goto failed; + mutex = object; + + if (!(object = get_d3dkmt_object( handles[2], -1 )) || !object->shared) goto failed; + if (object->type != D3DKMT_SYNC) goto failed; + sync = object; + } else goto failed;
if ((status = alloc_object_attributes( attr, &objattr, &len ))) return status; @@ -928,7 +943,9 @@ NTSTATUS WINAPI NtGdiDdDDIShareObjects( UINT count, const D3DKMT_HANDLE *handles SERVER_START_REQ( d3dkmt_share_objects ) { req->access = access | STANDARD_RIGHTS_ALL; - req->sync = sync->global; + if (resource) req->resource = resource->global; + if (mutex) req->mutex = mutex->global; + if (sync) req->sync = sync->global; wine_server_add_data( req, objattr, len ); status = wine_server_call( req ); *handle = wine_server_ptr_handle( reply->handle ); diff --git a/dlls/win32u/tests/d3dkmt.c b/dlls/win32u/tests/d3dkmt.c index 56ac8f81b1e..baa4b95355f 100644 --- a/dlls/win32u/tests/d3dkmt.c +++ b/dlls/win32u/tests/d3dkmt.c @@ -2396,10 +2396,10 @@ static void test_D3DKMTShareObjects( void ) status = D3DKMTShareObjects( 1, &alloc.hAllocation, &attr, STANDARD_RIGHTS_READ, &handle ); ok_nt( STATUS_INVALID_PARAMETER, status ); status = D3DKMTShareObjects( 1, &create_alloc.hResource, &attr, STANDARD_RIGHTS_READ, &handle ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status );
- todo_wine check_object_type( handle, L"DxgkSharedResource" ); - todo_wine check_object_name( handle, name.Buffer ); + check_object_type( handle, L"DxgkSharedResource" ); + check_object_name( handle, name.Buffer );
status = D3DKMTOpenNtHandleFromName( &open_resource_name ); @@ -2562,10 +2562,10 @@ static void test_D3DKMTShareObjects( void ) objects[2] = create_sync2.hSyncObject; handle = (HANDLE)0xdeadbeef; status = D3DKMTShareObjects( 3, objects, &attr, STANDARD_RIGHTS_ALL, &handle ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status );
- todo_wine check_object_type( handle, L"DxgkSharedResource" ); - todo_wine check_object_name( handle, name.Buffer ); + check_object_type( handle, L"DxgkSharedResource" ); + check_object_name( handle, name.Buffer );
destroy_mutex.hKeyedMutex = create_mutex2.hKeyedMutex; status = D3DKMTDestroyKeyedMutex( &destroy_mutex ); diff --git a/server/d3dkmt.c b/server/d3dkmt.c index 95032ede3d1..0939cdecbb3 100644 --- a/server/d3dkmt.c +++ b/server/d3dkmt.c @@ -138,6 +138,76 @@ static void dxgk_shared_sync_destroy( struct object *obj ) release_object( shared->sync ); }
+#define DXGK_SHARED_RESOURCE_MODIFY_STATE 0x0001 +#define DXGK_SHARED_RESOURCE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x1) + +static const WCHAR dxgk_shared_resource_name[] = {'D','x','g','k','S','h','a','r','e','d','R','e','s','o','u','r','c','e'}; + +struct type_descr dxgk_shared_resource_type = +{ + { dxgk_shared_resource_name, sizeof(dxgk_shared_resource_name) }, /* name */ + DXGK_SHARED_RESOURCE_ALL_ACCESS, /* valid_access */ + { /* mapping */ + STANDARD_RIGHTS_READ, + STANDARD_RIGHTS_WRITE | DXGK_SHARED_RESOURCE_MODIFY_STATE, + STANDARD_RIGHTS_EXECUTE, + STANDARD_RIGHTS_REQUIRED | DXGK_SHARED_RESOURCE_MODIFY_STATE, + }, +}; + +struct dxgk_shared_resource +{ + struct object obj; /* object header */ + struct object *resource; /* shared resource object */ + struct object *mutex; /* shared keyed mutex object */ + struct object *sync; /* shared sync object */ +}; + +static void dxgk_shared_resource_dump( struct object *obj, int verbose ); +static void dxgk_shared_resource_destroy( struct object *obj ); + +static const struct object_ops dxgk_shared_resource_ops = +{ + sizeof(struct dxgk_shared_resource), /* size */ + &dxgk_shared_resource_type, /* type */ + dxgk_shared_resource_dump, /* dump */ + no_add_queue, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ + NULL, /* satisfied */ + no_signal, /* signal */ + no_get_fd, /* get_fd */ + default_get_sync, /* get_sync */ + default_map_access, /* map_access */ + default_get_sd, /* get_sd */ + default_set_sd, /* set_sd */ + default_get_full_name, /* get_full_name */ + no_lookup_name, /* lookup_name */ + directory_link_name, /* link_name */ + default_unlink_name, /* unlink_name */ + no_open_file, /* open_file */ + no_kernel_obj_list, /* get_kernel_obj_list */ + no_close_handle, /* close_handle */ + dxgk_shared_resource_destroy, /* destroy */ +}; + +static void dxgk_shared_resource_dump( struct object *obj, int verbose ) +{ + struct dxgk_shared_resource *shared = (struct dxgk_shared_resource *)obj; + assert( obj->ops == &dxgk_shared_resource_ops ); + fprintf( stderr, "resource=%p mutex=%p sync=%p\n", shared->resource, + shared->mutex, shared->sync ); +} + +static void dxgk_shared_resource_destroy( struct object *obj ) +{ + struct dxgk_shared_resource *shared = (struct dxgk_shared_resource *)obj; + assert( obj->ops == &dxgk_shared_resource_ops ); + release_object( shared->resource ); + if (shared->mutex) release_object( shared->mutex ); + if (shared->sync) release_object( shared->sync ); +} + static struct d3dkmt_object **objects, **objects_end, **objects_next;
#define D3DKMT_HANDLE_BIT 0x40000000 @@ -330,19 +400,43 @@ DECL_HANDLER(d3dkmt_object_open) /* share global d3dkmt objects together */ DECL_HANDLER(d3dkmt_share_objects) { - struct object *sync = NULL; + struct object *resource = NULL, *mutex = NULL, *sync = NULL; const struct object_attributes *objattr; const struct security_descriptor *sd; - struct dxgk_shared_sync *shared; struct unicode_str name; struct object *root;
objattr = get_req_object_attributes( &sd, &name, &root );
- if (!(sync = get_d3dkmt_object( req->sync, D3DKMT_SYNC ))) return; + if (req->resource) + { + struct dxgk_shared_resource *shared; + + if (!(resource = d3dkmt_object_open( req->resource, D3DKMT_RESOURCE ))) return; + if (req->mutex && !(mutex = d3dkmt_object_open( req->mutex, D3DKMT_MUTEX ))) goto done; + if (req->sync && !(sync = d3dkmt_object_open( req->sync, D3DKMT_SYNC ))) goto done; + + if (!(shared = create_named_object( root, &dxgk_shared_resource_ops, &name, objattr->attributes | OBJ_CASE_INSENSITIVE, NULL ))) goto done; + shared->resource = grab_object( resource ); + if ((shared->mutex = mutex)) grab_object( mutex ); + if ((shared->sync = sync)) grab_object( sync ); + reply->handle = alloc_handle( current->process, shared, req->access, OBJ_INHERIT ); + release_object( shared ); + } + else + { + struct dxgk_shared_sync *shared; + + if (!(sync = d3dkmt_object_open( req->sync, D3DKMT_SYNC ))) return;
- if (!(shared = create_named_object( root, &dxgk_shared_sync_ops, &name, objattr->attributes | OBJ_CASE_INSENSITIVE, NULL ))) return; - shared->sync = grab_object( sync ); - reply->handle = alloc_handle( current->process, shared, req->access, OBJ_INHERIT ); - release_object( shared ); + if (!(shared = create_named_object( root, &dxgk_shared_sync_ops, &name, objattr->attributes | OBJ_CASE_INSENSITIVE, NULL ))) goto done; + shared->sync = grab_object( sync ); + reply->handle = alloc_handle( current->process, shared, req->access, OBJ_INHERIT ); + release_object( shared ); + } + +done: + if (resource) release_object( resource ); + if (mutex) release_object( mutex ); + if (sync) release_object( sync ); } diff --git a/server/protocol.def b/server/protocol.def index 819ea6e8311..2e9c4d6ea27 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -4186,6 +4186,8 @@ enum inproc_sync_type
/* Share d3dkmt objects together */ @REQ(d3dkmt_share_objects) + d3dkmt_handle_t resource; /* resource global handle */ + d3dkmt_handle_t mutex; /* mutex global handle */ d3dkmt_handle_t sync; /* sync global handle */ unsigned int access; /* wanted access rights */ VARARG(objattr,object_attributes); /* object attributes */