Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com --- dlls/gdi32/tests/driver.c | 2 +- dlls/winex11.drv/init.c | 2 +- dlls/winex11.drv/x11drv.h | 1 + dlls/winex11.drv/x11drv_main.c | 138 +++++++++++++++++++++++++++++++++ 4 files changed, 141 insertions(+), 2 deletions(-)
diff --git a/dlls/gdi32/tests/driver.c b/dlls/gdi32/tests/driver.c index b5f6f75a83..2ea43e3025 100644 --- a/dlls/gdi32/tests/driver.c +++ b/dlls/gdi32/tests/driver.c @@ -600,7 +600,7 @@ static void test_D3DKMTSetVidPnSourceOwner(void)
if (!pD3DKMTSetVidPnSourceOwner || pD3DKMTSetVidPnSourceOwner(&set_owner_desc) == STATUS_PROCEDURE_NOT_FOUND) { - skip("D3DKMTSetVidPnSourceOwner() is unavailable.\n"); + win_skip("D3DKMTSetVidPnSourceOwner() is unavailable.\n"); return; }
diff --git a/dlls/winex11.drv/init.c b/dlls/winex11.drv/init.c index 49d334ef62..66e6e7f09a 100644 --- a/dlls/winex11.drv/init.c +++ b/dlls/winex11.drv/init.c @@ -472,7 +472,7 @@ static const struct gdi_dc_funcs x11drv_funcs = X11DRV_UnrealizePalette, /* pUnrealizePalette */ NULL, /* pWidenPath */ NULL, /* pD3DKMTCheckVidPnExclusiveOwnership */ - NULL, /* pD3DKMTSetVidPnSourceOwner */ + X11DRV_D3DKMTSetVidPnSourceOwner, /* pD3DKMTSetVidPnSourceOwner */ X11DRV_wine_get_wgl_driver, /* wine_get_wgl_driver */ X11DRV_wine_get_vulkan_driver, /* wine_get_vulkan_driver */ GDI_PRIORITY_GRAPHICS_DRV /* priority */ diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 9ab948f724..d96a19f2e6 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -149,6 +149,7 @@ extern BOOL X11DRV_Arc( PHYSDEV dev, INT left, INT top, INT right, INT bottom, INT xstart, INT ystart, INT xend, INT yend ) DECLSPEC_HIDDEN; extern BOOL X11DRV_Chord( PHYSDEV dev, INT left, INT top, INT right, INT bottom, INT xstart, INT ystart, INT xend, INT yend ) DECLSPEC_HIDDEN; +extern NTSTATUS X11DRV_D3DKMTSetVidPnSourceOwner( const D3DKMT_SETVIDPNSOURCEOWNER *desc ) DECLSPEC_HIDDEN; extern BOOL X11DRV_Ellipse( PHYSDEV dev, INT left, INT top, INT right, INT bottom ) DECLSPEC_HIDDEN; extern INT X11DRV_EnumICMProfiles( PHYSDEV dev, ICMENUMPROCW proc, LPARAM lparam ) DECLSPEC_HIDDEN; extern BOOL X11DRV_ExtFloodFill( PHYSDEV dev, INT x, INT y, COLORREF color, UINT fillType ) DECLSPEC_HIDDEN; diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index 21807af3f1..ef973f3e48 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -42,6 +42,8 @@ #include <X11/extensions/Xrender.h> #endif
+#include "ntstatus.h" +#define WIN32_NO_STATUS #include "windef.h" #include "winbase.h" #include "winreg.h" @@ -52,6 +54,8 @@ #include "wine/unicode.h" #include "wine/debug.h" #include "wine/library.h" +#include "wine/list.h" +#include "wine/heap.h"
WINE_DEFAULT_DEBUG_CHANNEL(x11drv); WINE_DECLARE_DEBUG_CHANNEL(synchronous); @@ -96,6 +100,25 @@ static int (*old_error_handler)( Display *, XErrorEvent * ); static BOOL use_xim = TRUE; static char input_style[20];
+static CRITICAL_SECTION x11drv_section; +static CRITICAL_SECTION_DEBUG critsect_debug = +{ + 0, 0, &x11drv_section, + { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": x11drv_section") } +}; +static CRITICAL_SECTION x11drv_section = { &critsect_debug, -1, 0, 0, 0, 0 }; + +struct d3dkmt_vidpn_source +{ + D3DKMT_VIDPNSOURCEOWNER_TYPE type; /* VidPN source owner type */ + D3DDDI_VIDEO_PRESENT_SOURCE_ID id; /* VidPN present source id */ + D3DKMT_HANDLE device; /* Kernel mode device context */ + struct list entry; /* List entry */ +}; + +static struct list d3dkmt_vidpn_sources = LIST_INIT( d3dkmt_vidpn_sources ); /* VidPN source information list */ + #define IS_OPTION_TRUE(ch) \ ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1') #define IS_OPTION_FALSE(ch) \ @@ -739,3 +762,118 @@ BOOL CDECL X11DRV_SystemParametersInfo( UINT action, UINT int_param, void *ptr_p } return FALSE; /* let user32 handle it */ } + +/********************************************************************** + * X11DRV_D3DKMTSetVidPnSourceOwner + */ +NTSTATUS X11DRV_D3DKMTSetVidPnSourceOwner( const D3DKMT_SETVIDPNSOURCEOWNER *desc ) +{ + struct d3dkmt_vidpn_source *source, *source2; + NTSTATUS status = STATUS_SUCCESS; + BOOL found; + UINT i; + + TRACE("(%p)\n", desc); + + EnterCriticalSection( &x11drv_section ); + + /* Check parameters */ + for (i = 0; i < desc->VidPnSourceCount; ++i) + { + LIST_FOR_EACH_ENTRY( source, &d3dkmt_vidpn_sources, struct d3dkmt_vidpn_source, entry ) + { + if (source->id == desc->pVidPnSourceId[i]) + { + /* Same device */ + if (source->device == desc->hDevice) + { + if ((source->type == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE + && (desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_SHARED + || desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_EMULATED)) + || (source->type == D3DKMT_VIDPNSOURCEOWNER_EMULATED + && desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE)) + { + status = STATUS_INVALID_PARAMETER; + goto done; + } + } + /* Different devices */ + else + { + if ((source->type == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE + || source->type == D3DKMT_VIDPNSOURCEOWNER_EMULATED) + && (desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE + || desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_EMULATED)) + { + status = STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE; + goto done; + } + } + } + } + + /* On Windows, it seems that all video present sources are owned by DMM clients, so any attempt to set + * D3DKMT_VIDPNSOURCEOWNER_SHARED come back STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE */ + if (desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_SHARED) + { + status = STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE; + goto done; + } + + /* FIXME: D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVEGDI unsupported */ + if (desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVEGDI || desc->pType[i] > D3DKMT_VIDPNSOURCEOWNER_EMULATED) + { + status = STATUS_INVALID_PARAMETER; + goto done; + } + } + + /* Remove owner */ + if (!desc->VidPnSourceCount && !desc->pType && !desc->pVidPnSourceId) + { + LIST_FOR_EACH_ENTRY_SAFE( source, source2, &d3dkmt_vidpn_sources, struct d3dkmt_vidpn_source, entry ) + { + if (source->device == desc->hDevice) + { + list_remove( &source->entry ); + heap_free( source ); + } + } + goto done; + } + + /* Add owner */ + for (i = 0; i < desc->VidPnSourceCount; ++i) + { + found = FALSE; + LIST_FOR_EACH_ENTRY( source, &d3dkmt_vidpn_sources, struct d3dkmt_vidpn_source, entry ) + { + if (source->device == desc->hDevice && source->id == desc->pVidPnSourceId[i]) + { + found = TRUE; + break; + } + } + + if (found) + source->type = desc->pType[i]; + else + { + source = heap_alloc( sizeof( *source ) ); + if (!source) + { + status = STATUS_NO_MEMORY; + goto done; + } + + source->id = desc->pVidPnSourceId[i]; + source->type = desc->pType[i]; + source->device = desc->hDevice; + list_add_tail( &d3dkmt_vidpn_sources, &source->entry ); + } + } + +done: + LeaveCriticalSection( &x11drv_section ); + return status; +}