[PATCH v3 resend 3/4] winex11.drv: Implement X11DRV_D3DKMTSetVidPnSourceOwner.

Zhiyi Zhang zzhang at codeweavers.com
Tue Oct 22 03:39:06 CDT 2019


Signed-off-by: Zhiyi Zhang <zzhang at 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 0040dbb430..a833b3c208 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 135faa8989..8930690f45 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -149,6 +149,7 @@ extern BOOL CDECL X11DRV_Arc( PHYSDEV dev, INT left, INT top, INT right,
                               INT bottom, INT xstart, INT ystart, INT xend, INT yend ) DECLSPEC_HIDDEN;
 extern BOOL CDECL X11DRV_Chord( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
                                 INT xstart, INT ystart, INT xend, INT yend ) DECLSPEC_HIDDEN;
+extern NTSTATUS CDECL X11DRV_D3DKMTSetVidPnSourceOwner( const D3DKMT_SETVIDPNSOURCEOWNER *desc ) DECLSPEC_HIDDEN;
 extern BOOL CDECL X11DRV_Ellipse( PHYSDEV dev, INT left, INT top, INT right, INT bottom ) DECLSPEC_HIDDEN;
 extern INT CDECL X11DRV_EnumICMProfiles( PHYSDEV dev, ICMENUMPROCW proc, LPARAM lparam ) DECLSPEC_HIDDEN;
 extern BOOL CDECL 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..ac5ba66324 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 CDECL 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;
+}
-- 
2.23.0




More information about the wine-devel mailing list