Skip to content

Instantly share code, notes, and snippets.

@Thermionix
Created August 11, 2014 23:56
Show Gist options
  • Save Thermionix/329dddf2bf84d86e6383 to your computer and use it in GitHub Desktop.
Save Thermionix/329dddf2bf84d86e6383 to your computer and use it in GitHub Desktop.
wine-1.7.24 d3dadapter patch
diff --git a/configure b/configure
index 40cadd2..6f563de 100755
--- a/configure
+++ b/configure
@@ -821,6 +821,7 @@ with_netapi
with_openal
with_opencl
with_opengl
+with_d3dadapter
with_osmesa
with_oss
with_pcap
@@ -831,6 +832,7 @@ with_tiff
with_v4l
with_xcomposite
with_xcursor
+with_xfixes
with_xinerama
with_xinput
with_xinput2
@@ -2091,6 +2093,7 @@ Optional Packages:
--without-openal do not use OpenAL
--without-opencl do not use OpenCL
--without-opengl do not use OpenGL
+ --without-d3dadapter do not use native Direct3D
--without-osmesa do not use the OSMesa library
--without-oss do not use the OSS sound support
--without-pcap do not use the Packet Capture library
@@ -2101,6 +2104,7 @@ Optional Packages:
--without-v4l do not use v4l1 (v4l support)
--without-xcomposite do not use the Xcomposite extension
--without-xcursor do not use the Xcursor extension
+ --without-xfixes do not use the Xfixes extension
--without-xinerama do not use Xinerama (multi-monitor support)
--without-xinput do not use the Xinput extension
--without-xinput2 do not use the Xinput 2 extension
@@ -3313,6 +3317,12 @@ if test "${with_opengl+set}" = set; then :
fi
+# Check whether --with-d3dadapter was given.
+if test "${with_d3dadapter+set}" = set; then :
+ withval=$with_d3dadapter;
+fi
+
+
# Check whether --with-osmesa was given.
if test "${with_osmesa+set}" = set; then :
withval=$with_osmesa;
@@ -3373,6 +3383,12 @@ if test "${with_xcursor+set}" = set; then :
fi
+# Check whether --with-xfixes was given.
+if test "${with_xfixes+set}" = set; then :
+ withval=$with_xfixes; if test "x$withval" = "xno"; then ac_cv_header_X11_extensions_Xfixes_h=no; fi
+fi
+
+
# Check whether --with-xinerama was given.
if test "${with_xinerama+set}" = set; then :
withval=$with_xinerama; if test "x$withval" = "xno"; then ac_cv_header_X11_extensions_Xinerama_h=no; fi
@@ -9403,6 +9419,7 @@ fi
X11/extensions/XInput2.h \
X11/extensions/XShm.h \
X11/extensions/Xcomposite.h \
+ X11/extensions/Xfixes.h \
X11/extensions/Xinerama.h \
X11/extensions/Xrandr.h \
X11/extensions/Xrender.h \
@@ -10179,6 +10196,71 @@ This is an error since --with-xcomposite was requested." "$LINENO" 5 ;;
esac
fi
+ if test "$ac_cv_header_X11_extensions_Xfixes_h" = "yes"
+ then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -lXfixes" >&5
+$as_echo_n "checking for -lXfixes... " >&6; }
+if ${ac_cv_lib_soname_Xfixes+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_soname_save_LIBS=$LIBS
+LIBS="-lXfixes $X_LIBS $XLIB $X_EXTRA_LIBS $LIBS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char XFixesCreateRegion ();
+int
+main ()
+{
+return XFixesCreateRegion ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ case "$LIBEXT" in
+ dll) ac_cv_lib_soname_Xfixes=`$ac_cv_path_LDD conftest.exe | grep "Xfixes" | sed -e "s/dll.*/dll/"';2,$d'` ;;
+ dylib) ac_cv_lib_soname_Xfixes=`otool -L conftest$ac_exeext | grep "libXfixes\\.[0-9A-Za-z.]*dylib" | sed -e "s/^.*\/\(libXfixes\.[0-9A-Za-z.]*dylib\).*$/\1/"';2,$d'` ;;
+ *) ac_cv_lib_soname_Xfixes=`$READELF -d conftest$ac_exeext | grep "NEEDED.*libXfixes\\.$LIBEXT" | sed -e "s/^.*\\[\\(libXfixes\\.$LIBEXT[^ ]*\\)\\].*$/\1/"';2,$d'`
+ if test "x$ac_cv_lib_soname_Xfixes" = x; then :
+ ac_cv_lib_soname_Xfixes=`$LDD conftest$ac_exeext | grep "libXfixes\\.$LIBEXT" | sed -e "s/^.*\(libXfixes\.$LIBEXT[^ ]*\).*$/\1/"';2,$d'`
+fi ;;
+ esac
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LIBS=$ac_check_soname_save_LIBS
+fi
+if test "x$ac_cv_lib_soname_Xfixes" = "x"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_soname_Xfixes" >&5
+$as_echo "$ac_cv_lib_soname_Xfixes" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define SONAME_LIBXFIXES "$ac_cv_lib_soname_Xfixes"
+_ACEOF
+
+
+fi
+ fi
+ if test "x$ac_cv_lib_soname_Xfixes" = "x"; then :
+ case "x$with_xfixes" in
+ x) as_fn_append wine_notices "|libxfixes ${notice_platform}development files not found, Xfixes won't be supported." ;;
+ xno) ;;
+ *) as_fn_error $? "libxfixes ${notice_platform}development files not found, Xfixes won't be supported.
+This is an error since --with-xfixes was requested." "$LINENO" 5 ;;
+esac
+fi
+
ac_fn_c_check_member "$LINENO" "XICCallback" "callback" "ac_cv_member_XICCallback_callback" "#ifdef HAVE_X11_XLIB_H
#include <X11/Xlib.h>
#endif
@@ -10448,6 +10530,71 @@ This is an error since --with-opengl was requested." "$LINENO" 5 ;;
esac
fi
+ if test "x$with_d3dadapter" != "xno"
+ then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -ld3dadapter9" >&5
+$as_echo_n "checking for -ld3dadapter9... " >&6; }
+if ${ac_cv_lib_soname_d3dadapter9+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_soname_save_LIBS=$LIBS
+LIBS="-ld3dadapter9 $LIBS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char D3DAdapter9GetProc ();
+int
+main ()
+{
+return D3DAdapter9GetProc ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ case "$LIBEXT" in
+ dll) ac_cv_lib_soname_d3dadapter9=`$ac_cv_path_LDD conftest.exe | grep "d3dadapter9" | sed -e "s/dll.*/dll/"';2,$d'` ;;
+ dylib) ac_cv_lib_soname_d3dadapter9=`otool -L conftest$ac_exeext | grep "libd3dadapter9\\.[0-9A-Za-z.]*dylib" | sed -e "s/^.*\/\(libd3dadapter9\.[0-9A-Za-z.]*dylib\).*$/\1/"';2,$d'` ;;
+ *) ac_cv_lib_soname_d3dadapter9=`$READELF -d conftest$ac_exeext | grep "NEEDED.*libd3dadapter9\\.$LIBEXT" | sed -e "s/^.*\\[\\(libd3dadapter9\\.$LIBEXT[^ ]*\\)\\].*$/\1/"';2,$d'`
+ if test "x$ac_cv_lib_soname_d3dadapter9" = x; then :
+ ac_cv_lib_soname_d3dadapter9=`$LDD conftest$ac_exeext | grep "libd3dadapter9\\.$LIBEXT" | sed -e "s/^.*\(libd3dadapter9\.$LIBEXT[^ ]*\).*$/\1/"';2,$d'`
+fi ;;
+ esac
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LIBS=$ac_check_soname_save_LIBS
+fi
+if test "x$ac_cv_lib_soname_d3dadapter9" = "x"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_soname_d3dadapter9" >&5
+$as_echo "$ac_cv_lib_soname_d3dadapter9" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define SONAME_LIBD3DADAPTER9 "$ac_cv_lib_soname_d3dadapter9"
+_ACEOF
+
+
+fi
+ if test "x$ac_cv_lib_soname_d3dadapter9" = "x"; then :
+ case "x$with_d3dadapter9" in
+ x) as_fn_append wine_notices "|libd3dadapter9 ${notice_platform}development files not found. Native Direct3D9 won't be supported." ;;
+ xno) ;;
+ *) as_fn_error $? "libd3dadapter9 ${notice_platform}development files not found. Native Direct3D9 won't be supported.
+This is an error since --with-d3dadapter9 was requested." "$LINENO" 5 ;;
+esac
+fi
+ fi
+
CPPFLAGS="$ac_save_CPPFLAGS"
else
X_CFLAGS=""
diff --git a/configure.ac b/configure.ac
index 7de7a87..1c8762e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -65,6 +65,7 @@ AC_ARG_WITH(openal, AS_HELP_STRING([--without-openal],[do not use OpenAL]),
AC_ARG_WITH(opencl, AS_HELP_STRING([--without-opencl],[do not use OpenCL]),
[if test "x$withval" = "xno"; then ac_cv_header_CL_cl_h=no; ac_cv_header_OpenCL_opencl_h=no; fi])
AC_ARG_WITH(opengl, AS_HELP_STRING([--without-opengl],[do not use OpenGL]))
+AC_ARG_WITH(d3dadapter,AS_HELP_STRING([--without-d3dadapter],[do not use native Direct3D]))
AC_ARG_WITH(osmesa, AS_HELP_STRING([--without-osmesa],[do not use the OSMesa library]))
AC_ARG_WITH(oss, AS_HELP_STRING([--without-oss],[do not use the OSS sound support]))
AC_ARG_WITH(pcap, AS_HELP_STRING([--without-pcap],[do not use the Packet Capture library]),
@@ -79,6 +80,8 @@ AC_ARG_WITH(xcomposite,AS_HELP_STRING([--without-xcomposite],[do not use the Xco
[if test "x$withval" = "xno"; then ac_cv_header_X11_extensions_Xcomposite_h=no; fi])
AC_ARG_WITH(xcursor, AS_HELP_STRING([--without-xcursor],[do not use the Xcursor extension]),
[if test "x$withval" = "xno"; then ac_cv_header_X11_Xcursor_Xcursor_h=no; fi])
+AC_ARG_WITH(xfixes, AS_HELP_STRING([--without-xfixes],[do not use the Xfixes extension]),
+ [if test "x$withval" = "xno"; then ac_cv_header_X11_extensions_Xfixes_h=no; fi])
AC_ARG_WITH(xinerama, AS_HELP_STRING([--without-xinerama],[do not use Xinerama (multi-monitor support)]),
[if test "x$withval" = "xno"; then ac_cv_header_X11_extensions_Xinerama_h=no; fi])
AC_ARG_WITH(xinput, AS_HELP_STRING([--without-xinput],[do not use the Xinput extension]),
@@ -1093,6 +1096,7 @@ then
X11/extensions/XInput2.h \
X11/extensions/XShm.h \
X11/extensions/Xcomposite.h \
+ X11/extensions/Xfixes.h \
X11/extensions/Xinerama.h \
X11/extensions/Xrandr.h \
X11/extensions/Xrender.h \
@@ -1208,6 +1212,14 @@ then
WINE_NOTICE_WITH(xcomposite,[test "x$ac_cv_lib_soname_Xcomposite" = "x"],
[libxcomposite ${notice_platform}development files not found, Xcomposite won't be supported.])
+ dnl *** Check for X Fixes extension
+ if test "$ac_cv_header_X11_extensions_Xfixes_h" = "yes"
+ then
+ WINE_CHECK_SONAME(Xfixes,XFixesCreateRegion,,,[$X_LIBS $XLIB $X_EXTRA_LIBS])
+ fi
+ WINE_NOTICE_WITH(xfixes,[test "x$ac_cv_lib_soname_Xfixes" = "x"],
+ [libxfixes ${notice_platform}development files not found, Xfixes won't be supported.])
+
dnl *** Check for XICCallback struct
AC_CHECK_MEMBERS([XICCallback.callback, XEvent.xcookie],,,
[#ifdef HAVE_X11_XLIB_H
@@ -1250,6 +1262,14 @@ This probably prevents linking to OpenGL. Try deleting the file and restarting c
WINE_WARNING_WITH(opengl,[test -n "$opengl_msg"],[$opengl_msg
OpenGL and Direct3D won't be supported.])
+ dnl Check for libd3dadapter9
+ if test "x$with_d3dadapter" != "xno"
+ then
+ WINE_CHECK_SONAME(d3dadapter9,D3DAdapter9GetProc)
+ WINE_NOTICE_WITH(d3dadapter9,[test "x$ac_cv_lib_soname_d3dadapter9" = "x"],
+ [libd3dadapter9 ${notice_platform}development files not found. Native Direct3D9 won't be supported.])
+ fi
+
CPPFLAGS="$ac_save_CPPFLAGS"
else
X_CFLAGS=""
diff --git a/dlls/d3d9/Makefile.in b/dlls/d3d9/Makefile.in
index 1c05f5a..92b458d 100644
--- a/dlls/d3d9/Makefile.in
+++ b/dlls/d3d9/Makefile.in
@@ -1,10 +1,11 @@
MODULE = d3d9.dll
IMPORTLIB = d3d9
-IMPORTS = dxguid uuid wined3d
+IMPORTS = dxguid uuid advapi32 gdi32 user32 wined3d
C_SRCS = \
buffer.c \
d3d9_main.c \
+ d3dadapter9.c \
device.c \
directx.c \
query.c \
diff --git a/dlls/d3d9/d3d9_main.c b/dlls/d3d9/d3d9_main.c
index 0afdc04..7f2600f 100644
--- a/dlls/d3d9/d3d9_main.c
+++ b/dlls/d3d9/d3d9_main.c
@@ -33,12 +33,59 @@ void WINAPI DebugSetMute(void) {
/* nothing to do */
}
+static BOOL try_native(void)
+{
+ HKEY defkey, appkey;
+ DWORD type, data = 0;
+ DWORD size = sizeof(DWORD);
+ DWORD len;
+ char buffer[MAX_PATH];
+
+ /* @@ Wine registry key: HKCU\Software\Wine\Direct3D */
+ if ( RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Direct3D", &defkey ) ) defkey = 0;
+
+ len = GetModuleFileNameA( 0, buffer, MAX_PATH );
+ if (len && len < MAX_PATH)
+ {
+ HKEY tmpkey;
+ /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\Direct3D */
+ if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
+ {
+ char *p, *appname = buffer;
+ if ((p = strrchr( appname, '/' ))) appname = p + 1;
+ if ((p = strrchr( appname, '\\' ))) appname = p + 1;
+ strcat( appname, "\\Direct3D" );
+ TRACE("appname = [%s]\n", appname);
+ if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
+ RegCloseKey( tmpkey );
+ }
+ }
+
+ if (!(appkey && !RegQueryValueExA(appkey, "UseNative", 0, &type, (BYTE *)&data, &size) && (type == REG_DWORD))) {
+ if (!(defkey && !RegQueryValueExA(defkey, "UseNative", 0, &type, (BYTE *)&data, &size) && (type == REG_DWORD))) {
+ data = 0;
+ }
+ }
+
+ if (appkey) RegCloseKey( appkey );
+ if (defkey) RegCloseKey( defkey );
+
+ return data ? TRUE : FALSE;
+}
+
IDirect3D9 * WINAPI DECLSPEC_HOTPATCH Direct3DCreate9(UINT sdk_version)
{
struct d3d9 *object;
TRACE("sdk_version %#x.\n", sdk_version);
+ if (try_native()) {
+ IDirect3D9 *native;
+ if (SUCCEEDED(d3dadapter9_new(FALSE, (IDirect3D9Ex **)&native))) {
+ return native;
+ }
+ }
+
if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
return NULL;
@@ -60,6 +107,10 @@ HRESULT WINAPI DECLSPEC_HOTPATCH Direct3DCreate9Ex(UINT sdk_version, IDirect3D9E
TRACE("sdk_version %#x, d3d9ex %p.\n", sdk_version, d3d9ex);
+ if (try_native()) {
+ if (SUCCEEDED(d3dadapter9_new(TRUE, d3d9ex))) { return D3D_OK; }
+ }
+
if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
return E_OUTOFMEMORY;
@@ -90,6 +141,25 @@ void* WINAPI Direct3DShaderValidatorCreate9(void)
return NULL;
}
+/*******************************************************************
+ * DllMain
+ */
+BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, void *reserved)
+{
+ switch (reason)
+ {
+ case DLL_PROCESS_ATTACH:
+ d3dadapter9_init(inst);
+ break;
+
+ case DLL_PROCESS_DETACH:
+ d3dadapter9_destroy(inst);
+ break;
+ }
+
+ return TRUE;
+}
+
/***********************************************************************
* D3DPERF_BeginEvent (D3D9.@)
*/
diff --git a/dlls/d3d9/d3d9_private.h b/dlls/d3d9/d3d9_private.h
index 8c685e4..851684e 100644
--- a/dlls/d3d9/d3d9_private.h
+++ b/dlls/d3d9/d3d9_private.h
@@ -39,6 +39,9 @@
#include "d3d9.h"
#include "wine/wined3d.h"
+extern void d3dadapter9_init(HINSTANCE hinst);
+extern void d3dadapter9_destroy(HINSTANCE hinst);
+
extern HRESULT vdecl_convert_fvf(DWORD FVF, D3DVERTEXELEMENT9 **ppVertexElements) DECLSPEC_HIDDEN;
D3DFORMAT d3dformat_from_wined3dformat(enum wined3d_format_id format) DECLSPEC_HIDDEN;
enum wined3d_format_id wined3dformat_from_d3dformat(D3DFORMAT format) DECLSPEC_HIDDEN;
@@ -132,6 +135,7 @@ struct d3d9
BOOL d3d9_init(struct d3d9 *d3d9, BOOL extended) DECLSPEC_HIDDEN;
void filter_caps(D3DCAPS9* pCaps) DECLSPEC_HIDDEN;
+HRESULT d3dadapter9_new(boolean ex, IDirect3D9Ex **ppOut);
struct fvf_declaration
{
diff --git a/dlls/d3d9/d3dadapter9.c b/dlls/d3d9/d3dadapter9.c
new file mode 100644
index 0000000..a5c6eb0
--- /dev/null
+++ b/dlls/d3d9/d3dadapter9.c
@@ -0,0 +1,924 @@
+/*
+ * X11DRV IDirect3D9 interface using ID3DAdapter9
+ *
+ * Copyright 2013 Joakim Sindholt
+ * Christoph Bumiller
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "wine/debug.h"
+
+#include <d3d9.h>
+
+#ifdef SONAME_LIBD3DADAPTER9
+
+#include "wine/d3dadapter.h"
+#include "wine/gdi_driver.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
+
+/* this represents a snapshot taken at the moment of creation */
+struct output
+{
+ D3DDISPLAYROTATION rotation; /* current rotation */
+ D3DDISPLAYMODEEX *modes;
+ unsigned nmodes;
+ unsigned nmodesalloc;
+ unsigned current; /* current mode num */
+
+ HMONITOR monitor;
+};
+
+struct adapter_group
+{
+ struct output *outputs;
+ unsigned noutputs;
+ unsigned noutputsalloc;
+
+ /* override driver provided DeviceName with this to homogenize device names
+ * with wine */
+ WCHAR devname[32];
+
+ /* driver stuff */
+ ID3DAdapter9 *adapter;
+};
+
+struct adapter_map
+{
+ unsigned group;
+ unsigned master;
+};
+
+struct d3dadapter9
+{
+ /* COM vtable */
+ void *vtable;
+ /* IUnknown reference count */
+ LONG refs;
+
+ /* adapter groups and mappings */
+ struct adapter_group *groups;
+ struct adapter_map *map;
+ unsigned nadapters;
+ unsigned ngroups;
+ unsigned ngroupsalloc;
+
+ struct d3dadapter_funcs *funcs;
+ /* fake window for getting driver funcs */
+ HWND hwnd;
+ HDC hdc;
+
+ /* true if it implements IDirect3D9Ex */
+ boolean ex;
+};
+
+/* convenience wrapper for calls into ID3D9Adapter */
+#define ADAPTER_GROUP \
+ This->groups[This->map[Adapter].group]
+
+#define ADAPTER_PROC(name, ...) \
+ ID3DAdapter9_##name(ADAPTER_GROUP.adapter, ## __VA_ARGS__)
+
+#define ADAPTER_OUTPUT \
+ ADAPTER_GROUP.outputs[Adapter-This->map[Adapter].master]
+
+static HRESULT WINAPI
+d3dadapter9_CheckDeviceFormat( struct d3dadapter9 *This,
+ UINT Adapter,
+ D3DDEVTYPE DeviceType,
+ D3DFORMAT AdapterFormat,
+ DWORD Usage,
+ D3DRESOURCETYPE RType,
+ D3DFORMAT CheckFormat );
+
+static ULONG WINAPI
+d3dadapter9_AddRef( struct d3dadapter9 *This )
+{
+ ULONG refs = InterlockedIncrement(&This->refs);
+ TRACE("%p increasing refcount to %u.\n", This, refs);
+ return refs;
+}
+
+static ULONG WINAPI
+d3dadapter9_Release( struct d3dadapter9 *This )
+{
+ ULONG refs = InterlockedDecrement(&This->refs);
+ TRACE("%p decreasing refcount to %u.\n", This, refs);
+ if (refs == 0) {
+ /* dtor */
+ if (This->map) {
+ HeapFree(GetProcessHeap(), 0, This->map);
+ }
+
+ if (This->groups) {
+ int i, j;
+ for (i = 0; i < This->ngroups; ++i) {
+ if (This->groups[i].outputs) {
+ for (j = 0; j < This->groups[i].noutputs; ++j) {
+ if (This->groups[i].outputs[j].modes) {
+ HeapFree(GetProcessHeap(), 0,
+ This->groups[i].outputs[j].modes);
+ }
+ }
+ HeapFree(GetProcessHeap(), 0, This->groups[i].outputs);
+ }
+
+ if (This->groups[i].adapter) {
+ ID3DAdapter9_Release(This->groups[i].adapter);
+ }
+ }
+ HeapFree(GetProcessHeap(), 0, This->groups);
+ }
+
+ if (This->hdc) { ReleaseDC(This->hwnd, This->hdc); }
+ if (This->hwnd) { DestroyWindow(This->hwnd); }
+
+ HeapFree(GetProcessHeap(), 0, This);
+ }
+ return refs;
+}
+
+static HRESULT WINAPI
+d3dadapter9_QueryInterface( struct d3dadapter9 *This,
+ REFIID riid,
+ void **ppvObject )
+{
+ if (!ppvObject) { return E_POINTER; }
+ if ((IsEqualGUID(&IID_IDirect3D9Ex, riid) && This->ex) ||
+ IsEqualGUID(&IID_IDirect3D9, riid) ||
+ IsEqualGUID(&IID_IUnknown, riid)) {
+ *ppvObject = This;
+ d3dadapter9_AddRef(This);
+ return S_OK;
+ }
+
+ WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+ *ppvObject = NULL;
+
+ return E_NOINTERFACE;
+}
+
+static HRESULT WINAPI
+d3dadapter9_RegisterSoftwareDevice( struct d3dadapter9 *This,
+ void *pInitializeFunction )
+{
+ FIXME("(%p, %p), stub!\n", This, pInitializeFunction);
+ return D3DERR_INVALIDCALL;
+}
+
+static UINT WINAPI
+d3dadapter9_GetAdapterCount( struct d3dadapter9 *This )
+{
+ return This->nadapters;
+}
+
+static HRESULT WINAPI
+d3dadapter9_GetAdapterIdentifier( struct d3dadapter9 *This,
+ UINT Adapter,
+ DWORD Flags,
+ D3DADAPTER_IDENTIFIER9 *pIdentifier )
+{
+ HRESULT hr;
+ HKEY regkey;
+
+ if (Adapter >= d3dadapter9_GetAdapterCount(This)) { return D3DERR_INVALIDCALL; }
+
+ hr = ADAPTER_PROC(GetAdapterIdentifier, Flags, pIdentifier);
+ if (SUCCEEDED(hr)) {
+ /* Override the driver provided DeviceName with what Wine provided */
+ ZeroMemory(pIdentifier->DeviceName, sizeof(pIdentifier->DeviceName));
+ if (!WideCharToMultiByte(CP_ACP, 0, ADAPTER_GROUP.devname, -1,
+ pIdentifier->DeviceName,
+ sizeof(pIdentifier->DeviceName),
+ NULL, NULL)) {
+ /* Wine does it */
+ return D3DERR_INVALIDCALL;
+ }
+ TRACE("DeviceName overriden: %s\n", pIdentifier->DeviceName);
+
+ /* Override PCI IDs when wined3d registry keys are set */
+ if (!RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Direct3D", &regkey)) {
+ DWORD type, data;
+ DWORD size = sizeof(DWORD);
+
+ if (!RegQueryValueExA(regkey, "VideoPciDeviceID", 0, &type, (BYTE *)&data, &size) && (type == REG_DWORD))
+ pIdentifier->DeviceId = data;
+ if (!RegQueryValueExA(regkey, "VideoPciVendorID", 0, &type, (BYTE *)&data, &size) && (type == REG_DWORD))
+ pIdentifier->VendorId = data;
+ RegCloseKey(regkey);
+
+ TRACE("DeviceId:VendorId overridden: %04X:%04X\n", pIdentifier->DeviceId, pIdentifier->VendorId);
+ }
+ }
+ return hr;
+}
+
+static UINT WINAPI
+d3dadapter9_GetAdapterModeCount( struct d3dadapter9 *This,
+ UINT Adapter,
+ D3DFORMAT Format )
+{
+ if (Adapter >= d3dadapter9_GetAdapterCount(This)) {
+ WARN("Adapter %u does not exist.\n", Adapter);
+ return 0;
+ }
+ if (FAILED(d3dadapter9_CheckDeviceFormat(This, Adapter, D3DDEVTYPE_HAL,
+ Format, D3DUSAGE_RENDERTARGET,
+ D3DRTYPE_SURFACE, Format))) {
+ WARN("DeviceFormat not available.\n");
+ return 0;
+ }
+
+ TRACE("%u modes.\n", ADAPTER_OUTPUT.nmodes);
+ return ADAPTER_OUTPUT.nmodes;
+}
+
+static HRESULT WINAPI
+d3dadapter9_EnumAdapterModes( struct d3dadapter9 *This,
+ UINT Adapter,
+ D3DFORMAT Format,
+ UINT Mode,
+ D3DDISPLAYMODE *pMode )
+{
+ HRESULT hr;
+
+ if (Adapter >= d3dadapter9_GetAdapterCount(This)) {
+ WARN("Adapter %u does not exist.\n", Adapter);
+ return D3DERR_INVALIDCALL;
+ }
+
+ hr = d3dadapter9_CheckDeviceFormat(This, Adapter, D3DDEVTYPE_HAL,
+ Format, D3DUSAGE_RENDERTARGET,
+ D3DRTYPE_SURFACE, Format);
+ if (FAILED(hr)) {
+ TRACE("DeviceFormat not available.\n");
+ return hr;
+ }
+
+ if (Mode >= ADAPTER_OUTPUT.nmodes) {
+ WARN("Mode %u does not exist.\n", Mode);
+ return D3DERR_INVALIDCALL;
+ }
+
+ pMode->Width = ADAPTER_OUTPUT.modes[Mode].Width;
+ pMode->Height = ADAPTER_OUTPUT.modes[Mode].Height;
+ pMode->RefreshRate = ADAPTER_OUTPUT.modes[Mode].RefreshRate;
+ pMode->Format = Format;
+
+ return D3D_OK;
+}
+
+static HRESULT WINAPI
+d3dadapter9_GetAdapterDisplayMode( struct d3dadapter9 *This,
+ UINT Adapter,
+ D3DDISPLAYMODE *pMode )
+{
+ UINT Mode;
+
+ if (Adapter >= d3dadapter9_GetAdapterCount(This)) {
+ WARN("Adapter %u does not exist.\n", Adapter);
+ return D3DERR_INVALIDCALL;
+ }
+
+ Mode = ADAPTER_OUTPUT.current;
+ pMode->Width = ADAPTER_OUTPUT.modes[Mode].Width;
+ pMode->Height = ADAPTER_OUTPUT.modes[Mode].Height;
+ pMode->RefreshRate = ADAPTER_OUTPUT.modes[Mode].RefreshRate;
+ pMode->Format = ADAPTER_OUTPUT.modes[Mode].Format;
+
+ return D3D_OK;
+}
+
+static HRESULT WINAPI
+d3dadapter9_CheckDeviceType( struct d3dadapter9 *This,
+ UINT Adapter,
+ D3DDEVTYPE DevType,
+ D3DFORMAT AdapterFormat,
+ D3DFORMAT BackBufferFormat,
+ BOOL bWindowed )
+{
+ if (Adapter >= d3dadapter9_GetAdapterCount(This)) { return D3DERR_INVALIDCALL; }
+ return ADAPTER_PROC(CheckDeviceType,
+ DevType, AdapterFormat, BackBufferFormat, bWindowed);
+}
+
+static HRESULT WINAPI
+d3dadapter9_CheckDeviceFormat( struct d3dadapter9 *This,
+ UINT Adapter,
+ D3DDEVTYPE DeviceType,
+ D3DFORMAT AdapterFormat,
+ DWORD Usage,
+ D3DRESOURCETYPE RType,
+ D3DFORMAT CheckFormat )
+{
+ if (Adapter >= d3dadapter9_GetAdapterCount(This)) { return D3DERR_INVALIDCALL; }
+ return ADAPTER_PROC(CheckDeviceFormat,
+ DeviceType, AdapterFormat, Usage, RType, CheckFormat);
+}
+
+static HRESULT WINAPI
+d3dadapter9_CheckDeviceMultiSampleType( struct d3dadapter9 *This,
+ UINT Adapter,
+ D3DDEVTYPE DeviceType,
+ D3DFORMAT SurfaceFormat,
+ BOOL Windowed,
+ D3DMULTISAMPLE_TYPE MultiSampleType,
+ DWORD *pQualityLevels )
+{
+ if (Adapter >= d3dadapter9_GetAdapterCount(This)) { return D3DERR_INVALIDCALL; }
+ return ADAPTER_PROC(CheckDeviceMultiSampleType, DeviceType, SurfaceFormat,
+ Windowed, MultiSampleType, pQualityLevels);
+}
+
+static HRESULT WINAPI
+d3dadapter9_CheckDepthStencilMatch( struct d3dadapter9 *This,
+ UINT Adapter,
+ D3DDEVTYPE DeviceType,
+ D3DFORMAT AdapterFormat,
+ D3DFORMAT RenderTargetFormat,
+ D3DFORMAT DepthStencilFormat )
+{
+ if (Adapter >= d3dadapter9_GetAdapterCount(This)) { return D3DERR_INVALIDCALL; }
+ return ADAPTER_PROC(CheckDepthStencilMatch, DeviceType, AdapterFormat,
+ RenderTargetFormat, DepthStencilFormat);
+}
+
+static HRESULT WINAPI
+d3dadapter9_CheckDeviceFormatConversion( struct d3dadapter9 *This,
+ UINT Adapter,
+ D3DDEVTYPE DeviceType,
+ D3DFORMAT SourceFormat,
+ D3DFORMAT TargetFormat )
+{
+ if (Adapter >= d3dadapter9_GetAdapterCount(This)) { return D3DERR_INVALIDCALL; }
+ return ADAPTER_PROC(CheckDeviceFormatConversion,
+ DeviceType, SourceFormat, TargetFormat);
+}
+
+static HRESULT WINAPI
+d3dadapter9_GetDeviceCaps( struct d3dadapter9 *This,
+ UINT Adapter,
+ D3DDEVTYPE DeviceType,
+ D3DCAPS9 *pCaps )
+{
+ HRESULT hr;
+
+ if (Adapter >= d3dadapter9_GetAdapterCount(This)) { return D3DERR_INVALIDCALL; }
+
+ hr = ADAPTER_PROC(GetDeviceCaps, DeviceType, pCaps);
+ if (FAILED(hr)) { return hr; }
+
+ pCaps->MasterAdapterOrdinal = This->map[Adapter].master;
+ pCaps->AdapterOrdinalInGroup = Adapter-This->map[Adapter].master;
+ pCaps->NumberOfAdaptersInGroup = ADAPTER_GROUP.noutputs;
+
+ return hr;
+}
+
+static HMONITOR WINAPI
+d3dadapter9_GetAdapterMonitor( struct d3dadapter9 *This,
+ UINT Adapter )
+{
+ if (Adapter >= d3dadapter9_GetAdapterCount(This)) { return (HMONITOR)0; }
+ return (HMONITOR)ADAPTER_OUTPUT.monitor;
+}
+
+static HRESULT WINAPI
+d3dadapter9_CreateDevice( struct d3dadapter9 *This,
+ UINT Adapter,
+ D3DDEVTYPE DeviceType,
+ HWND hFocusWindow,
+ DWORD BehaviorFlags,
+ D3DPRESENT_PARAMETERS *pPresentationParameters,
+ IDirect3DDevice9 **ppReturnedDeviceInterface )
+{
+ ID3DPresentGroup *present;
+ HRESULT hr;
+
+ if (Adapter >= d3dadapter9_GetAdapterCount(This)) {
+ WARN("Adapter %u does not exist.\n", Adapter);
+ return D3DERR_INVALIDCALL;
+ }
+
+ {
+ struct adapter_group *group = &ADAPTER_GROUP;
+ unsigned nparams, ordinal;
+
+ if (BehaviorFlags & D3DCREATE_ADAPTERGROUP_DEVICE) {
+ nparams = group->noutputs;
+ ordinal = 0;
+ } else {
+ nparams = 1;
+ ordinal = Adapter - This->map[Adapter].master;
+ }
+ hr = This->funcs->create_present_group(group->devname, ordinal,
+ hFocusWindow,
+ pPresentationParameters,
+ nparams, &present);
+ }
+
+ if (FAILED(hr)) {
+ WARN("Failed to create PresentGroup.\n");
+ return hr;
+ }
+
+ /* Looks like you should get a DeviceEx even if you don't call
+ * CreateDeviceEx. */
+ if (This->ex) {
+ hr = ADAPTER_PROC(CreateDeviceEx, Adapter, DeviceType, hFocusWindow,
+ BehaviorFlags, (IDirect3D9Ex *)This, present,
+ (IDirect3DDevice9Ex **)ppReturnedDeviceInterface);
+ } else {
+ hr = ADAPTER_PROC(CreateDevice, Adapter, DeviceType, hFocusWindow,
+ BehaviorFlags, (IDirect3D9 *)This, present,
+ ppReturnedDeviceInterface);
+ }
+ if (FAILED(hr)) {
+ WARN("ADAPTER_PROC failed.\n");
+ ID3DPresentGroup_Release(present);
+ }
+
+ return hr;
+}
+
+static UINT WINAPI
+d3dadapter9_GetAdapterModeCountEx( struct d3dadapter9 *This,
+ UINT Adapter,
+ const D3DDISPLAYMODEFILTER *pFilter )
+{
+ return 1;
+}
+
+static HRESULT WINAPI
+d3dadapter9_EnumAdapterModesEx( struct d3dadapter9 *This,
+ UINT Adapter,
+ const D3DDISPLAYMODEFILTER *pFilter,
+ UINT Mode,
+ D3DDISPLAYMODEEX *pMode )
+{
+ FIXME("(%p, %u, %p, %u, %p), stub!\n", This, Adapter, pFilter, Mode, pMode);
+ return D3DERR_INVALIDCALL;
+}
+
+static HRESULT WINAPI
+d3dadapter9_GetAdapterDisplayModeEx( struct d3dadapter9 *This,
+ UINT Adapter,
+ D3DDISPLAYMODEEX *pMode,
+ D3DDISPLAYROTATION *pRotation )
+{
+ FIXME("(%p, %u, %p, %p), stub!\n", This, Adapter, pMode, pRotation);
+ return D3DERR_INVALIDCALL;
+}
+
+static HRESULT WINAPI
+d3dadapter9_CreateDeviceEx( struct d3dadapter9 *This,
+ UINT Adapter,
+ D3DDEVTYPE DeviceType,
+ HWND hFocusWindow,
+ DWORD BehaviorFlags,
+ D3DPRESENT_PARAMETERS *pPresentationParameters,
+ D3DDISPLAYMODEEX *pFullscreenDisplayMode,
+ IDirect3DDevice9Ex **ppReturnedDeviceInterface )
+{
+ HRESULT hr;
+ hr = d3dadapter9_CreateDevice(This, Adapter, DeviceType, hFocusWindow,
+ BehaviorFlags, pPresentationParameters,
+ (IDirect3DDevice9 **)ppReturnedDeviceInterface);
+ if (FAILED(hr))
+ return hr;
+ WARN("ignoring pFullscreenDisplayMode: %p\n", pFullscreenDisplayMode);
+ return D3D_OK;
+}
+
+static HRESULT WINAPI
+d3dadapter9_GetAdapterLUID( struct d3dadapter9 *This,
+ UINT Adapter,
+ LUID *pLUID )
+{
+ FIXME("(%p, %u, %p), stub!\n", This, Adapter, pLUID);
+ return D3DERR_INVALIDCALL;
+}
+
+static struct adapter_group *
+add_group( struct d3dadapter9 *This )
+{
+ if (This->ngroups >= This->ngroupsalloc) {
+ void *r;
+
+ if (This->ngroupsalloc == 0) {
+ This->ngroupsalloc = 2;
+ r = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ This->ngroupsalloc*sizeof(struct adapter_group));
+ } else {
+ This->ngroupsalloc <<= 1;
+ r = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->groups,
+ This->ngroupsalloc*sizeof(struct adapter_group));
+ }
+
+ if (!r) { return NULL; }
+ This->groups = r;
+ }
+
+ return &This->groups[This->ngroups++];
+}
+
+static void
+remove_group( struct d3dadapter9 *This )
+{
+ struct adapter_group *group = &This->groups[This->ngroups-1];
+ int i;
+
+ for (i = 0; i < group->noutputs; ++i) {
+ HeapFree(GetProcessHeap(), 0, group->outputs[i].modes);
+ }
+ HeapFree(GetProcessHeap(), 0, group->outputs);
+
+ ZeroMemory(group, sizeof(struct adapter_group));
+ This->ngroups--;
+}
+
+static struct output *
+add_output( struct d3dadapter9 *This )
+{
+ struct adapter_group *group = &This->groups[This->ngroups-1];
+
+ if (group->noutputs >= group->noutputsalloc) {
+ void *r;
+
+ if (group->noutputsalloc == 0) {
+ group->noutputsalloc = 2;
+ r = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ group->noutputsalloc*sizeof(struct output));
+ } else {
+ group->noutputsalloc <<= 1;
+ r = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, group->outputs,
+ group->noutputsalloc*sizeof(struct output));
+ }
+
+ if (!r) { return NULL; }
+ group->outputs = r;
+ }
+
+ return &group->outputs[group->noutputs++];
+}
+
+static void
+remove_output( struct d3dadapter9 *This )
+{
+ struct adapter_group *group = &This->groups[This->ngroups-1];
+ struct output *out = &group->outputs[group->noutputs-1];
+
+ HeapFree(GetProcessHeap(), 0, out->modes);
+
+ ZeroMemory(out, sizeof(struct output));
+ group->noutputs--;
+}
+
+static D3DDISPLAYMODEEX *
+add_mode( struct d3dadapter9 *This )
+{
+ struct adapter_group *group = &This->groups[This->ngroups-1];
+ struct output *out = &group->outputs[group->noutputs-1];
+
+ if (out->nmodes >= out->nmodesalloc) {
+ void *r;
+
+ if (out->nmodesalloc == 0) {
+ out->nmodesalloc = 8;
+ r = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ out->nmodesalloc*sizeof(struct D3DDISPLAYMODEEX));
+ } else {
+ out->nmodesalloc <<= 1;
+ r = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, out->modes,
+ out->nmodesalloc*sizeof(struct D3DDISPLAYMODEEX));
+ }
+
+ if (!r) { return NULL; }
+ out->modes = r;
+ }
+
+ return &out->modes[out->nmodes++];
+}
+
+static void
+remove_mode( struct d3dadapter9 *This )
+{
+ struct adapter_group *group = &This->groups[This->ngroups-1];
+ struct output *out = &group->outputs[group->noutputs-1];
+ out->nmodes--;
+}
+
+#ifndef DM_INTERLACED
+#define DM_INTERLACED 2
+#endif /* DM_INTERLACED */
+
+static HRESULT
+fill_groups( struct d3dadapter9 *This )
+{
+ DISPLAY_DEVICEW dd;
+ DEVMODEW dm;
+ POINT pt;
+ HDC hdc;
+ HRESULT hr;
+ int i, j, k;
+
+ WCHAR wdisp[] = {'D','I','S','P','L','A','Y',0};
+
+ ZeroMemory(&dd, sizeof(dd));
+ ZeroMemory(&dm, sizeof(dm));
+ dd.cb = sizeof(dd);
+ dm.dmSize = sizeof(dm);
+
+ for (i = 0; EnumDisplayDevicesW(NULL, i, &dd, 0); ++i) {
+ struct adapter_group *group = add_group(This);
+ if (!group) {
+ ERR("Out of memory.\n");
+ return E_OUTOFMEMORY;
+ }
+
+ hdc = CreateDCW(wdisp, dd.DeviceName, NULL, NULL);
+ if (!hdc) {
+ remove_group(This);
+ WARN("Unable to create DC for display %d.\n", i);
+ goto end_group;
+ }
+
+ hr = This->funcs->create_adapter9(hdc, &group->adapter);
+ DeleteDC(hdc);
+ if (FAILED(hr)) {
+ remove_group(This);
+ goto end_group;
+ }
+
+ CopyMemory(group->devname, dd.DeviceName, sizeof(group->devname));
+ for (j = 0; EnumDisplayDevicesW(group->devname, j, &dd, 0); ++j) {
+ struct output *out = add_output(This);
+ boolean orient = FALSE, monit = FALSE;
+ if (!out) {
+ ERR("Out of memory.\n");
+ return E_OUTOFMEMORY;
+ }
+
+ for (k = 0; EnumDisplaySettingsExW(dd.DeviceName, k, &dm, 0); ++k) {
+ D3DDISPLAYMODEEX *mode = add_mode(This);
+ if (!out) {
+ ERR("Out of memory.\n");
+ return E_OUTOFMEMORY;
+ }
+
+ mode->Size = sizeof(D3DDISPLAYMODEEX);
+ mode->Width = dm.dmPelsWidth;
+ mode->Height = dm.dmPelsHeight;
+ mode->RefreshRate = dm.dmDisplayFrequency;
+ mode->ScanLineOrdering =
+ (dm.dmDisplayFlags & DM_INTERLACED) ?
+ D3DSCANLINEORDERING_INTERLACED :
+ D3DSCANLINEORDERING_PROGRESSIVE;
+
+ switch (dm.dmBitsPerPel) {
+ case 32: mode->Format = D3DFMT_X8R8G8B8; break;
+ case 24: mode->Format = D3DFMT_R8G8B8; break;
+ case 16: mode->Format = D3DFMT_R5G6B5; break;
+ case 8:
+ remove_mode(This);
+ goto end_mode;
+
+ default:
+ remove_mode(This);
+ WARN("Unknown format (%u bpp) in display %d, monitor "
+ "%d, mode %d.\n", dm.dmBitsPerPel, i, j, k);
+ goto end_mode;
+ }
+
+ if (!orient) {
+ switch (dm.dmDisplayOrientation) {
+ case DMDO_DEFAULT:
+ out->rotation = D3DDISPLAYROTATION_IDENTITY;
+ break;
+
+ case DMDO_90:
+ out->rotation = D3DDISPLAYROTATION_90;
+ break;
+
+ case DMDO_180:
+ out->rotation = D3DDISPLAYROTATION_180;
+ break;
+
+ case DMDO_270:
+ out->rotation = D3DDISPLAYROTATION_270;
+ break;
+
+ default:
+ remove_output(This);
+ WARN("Unknown display rotation in display %d, "
+ "monitor %d\n", i, j);
+ goto end_output;
+ }
+ orient = TRUE;
+ }
+
+ if (!monit) {
+ pt.x = dm.dmPosition.x;
+ pt.y = dm.dmPosition.y;
+ out->monitor = MonitorFromPoint(pt, 0);
+ if (!out->monitor) {
+ remove_output(This);
+ WARN("Unable to get monitor handle for display %d, "
+ "monitor %d.\n", i, j);
+ goto end_output;
+ }
+ monit = TRUE;
+ }
+
+end_mode:
+ ZeroMemory(&dm, sizeof(dm));
+ dm.dmSize = sizeof(dm);
+ }
+
+end_output:
+ ZeroMemory(&dd, sizeof(dd));
+ dd.cb = sizeof(dd);
+ }
+
+end_group:
+ ZeroMemory(&dd, sizeof(dd));
+ dd.cb = sizeof(dd);
+ }
+
+ return D3D_OK;
+}
+
+static IDirect3D9ExVtbl d3dadapter9_vtable = {
+ (void *)d3dadapter9_QueryInterface,
+ (void *)d3dadapter9_AddRef,
+ (void *)d3dadapter9_Release,
+ (void *)d3dadapter9_RegisterSoftwareDevice,
+ (void *)d3dadapter9_GetAdapterCount,
+ (void *)d3dadapter9_GetAdapterIdentifier,
+ (void *)d3dadapter9_GetAdapterModeCount,
+ (void *)d3dadapter9_EnumAdapterModes,
+ (void *)d3dadapter9_GetAdapterDisplayMode,
+ (void *)d3dadapter9_CheckDeviceType,
+ (void *)d3dadapter9_CheckDeviceFormat,
+ (void *)d3dadapter9_CheckDeviceMultiSampleType,
+ (void *)d3dadapter9_CheckDepthStencilMatch,
+ (void *)d3dadapter9_CheckDeviceFormatConversion,
+ (void *)d3dadapter9_GetDeviceCaps,
+ (void *)d3dadapter9_GetAdapterMonitor,
+ (void *)d3dadapter9_CreateDevice,
+ (void *)d3dadapter9_GetAdapterModeCountEx,
+ (void *)d3dadapter9_EnumAdapterModesEx,
+ (void *)d3dadapter9_GetAdapterDisplayModeEx,
+ (void *)d3dadapter9_CreateDeviceEx,
+ (void *)d3dadapter9_GetAdapterLUID
+};
+
+#define D3D9_FAKE_WNDCLASS "FAKED3D9WINDOW"
+
+void
+d3dadapter9_init( HINSTANCE hinst )
+{
+ WNDCLASSA wc;
+
+ wc.style = CS_HREDRAW | CS_VREDRAW;
+ wc.lpfnWndProc = DefWindowProcA;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = hinst;
+ wc.hIcon = LoadIconA(NULL, (LPCSTR)IDI_WINLOGO);
+ wc.hCursor = LoadCursorA(NULL, (LPCSTR)IDC_ARROW);
+ wc.hbrBackground = NULL;
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = D3D9_FAKE_WNDCLASS;
+
+ if (!RegisterClassA(&wc)) {
+ ERR("Unable to register window to retrieve driver info.\n");
+ }
+}
+
+void
+d3dadapter9_destroy( HINSTANCE hinst )
+{
+ UnregisterClassA(D3D9_FAKE_WNDCLASS, hinst);
+}
+
+static int
+load_adapter_funcs( struct d3dadapter9 *This )
+{
+ This->hwnd = CreateWindowA(D3D9_FAKE_WNDCLASS, "D3DAdapter9 fake window",
+ WS_OVERLAPPEDWINDOW, 10, 10, 10, 10,
+ NULL, NULL, NULL, NULL);
+ if (!This->hwnd) {
+ ERR("Unable to create fake window to retrieve driver info.\n");
+ return FALSE;
+ }
+ This->hdc = GetDC(This->hwnd);
+ if (!This->hdc) {
+ ERR("Unable to get fake window DC to retrieve driver info.\n");
+ return FALSE;
+ }
+
+ This->funcs =
+ __wine_get_d3dadapter_driver(This->hdc, WINE_D3DADAPTER_DRIVER_VERSION);
+ if (!This->funcs || !This->funcs->create_adapter9) {
+ WARN("Your display driver doesn't support native D3D9 adapters.\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+HRESULT
+d3dadapter9_new( boolean ex,
+ IDirect3D9Ex **ppOut )
+{
+ struct d3dadapter9 *This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof(struct d3dadapter9));
+ HRESULT hr;
+ unsigned i, j, k;
+
+ if (!This) {
+ ERR("Out of memory.\n");
+ return E_OUTOFMEMORY;
+ }
+
+ This->vtable = &d3dadapter9_vtable;
+ This->refs = 1;
+ This->ex = ex;
+
+ if (!load_adapter_funcs(This)) {
+ WARN("Your display driver doesn't support native D3D9 adapters.\n");
+ d3dadapter9_Release(This);
+ return D3DERR_NOTAVAILABLE;
+ }
+
+ hr = fill_groups(This);
+ if (FAILED(hr)) {
+ d3dadapter9_Release(This);
+ return hr;
+ }
+
+ /* map absolute adapter IDs with internal adapters */
+ for (i = 0; i < This->ngroups; ++i) {
+ for (j = 0; j < This->groups[i].noutputs; ++j) {
+ This->nadapters++;
+ }
+ }
+ if (This->nadapters == 0) {
+ WARN("No available native adapters in system.\n");
+ d3dadapter9_Release(This);
+ return D3DERR_NOTAVAILABLE;
+ }
+
+ This->map = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ This->nadapters*sizeof(struct adapter_map));
+ if (!This->map) {
+ d3dadapter9_Release(This);
+ ERR("Out of memory.\n");
+ return E_OUTOFMEMORY;
+ }
+ for (i = k = 0; i < This->ngroups; ++i) {
+ for (j = 0; j < This->groups[i].noutputs; ++j, ++k) {
+ This->map[k].master = k-j;
+ This->map[k].group = i;
+ }
+ }
+
+ *ppOut = (IDirect3D9Ex *)This;
+ return D3D_OK;
+}
+
+#else
+
+HRESULT
+d3dadapter9_new( boolean ex,
+ IDirect3D9Ex **ppOut )
+{
+ return D3DERR_NOTAVAILABLE;
+}
+
+void
+d3dadapter9_init( HINSTANCE hinst )
+{
+}
+
+void
+d3dadapter9_destroy( HINSTANCE hinst )
+{
+}
+
+#endif /* SONAME_LIBD3DADAPTER9 */
diff --git a/dlls/gdi32/Makefile.in b/dlls/gdi32/Makefile.in
index 6cc026c..703968d 100644
--- a/dlls/gdi32/Makefile.in
+++ b/dlls/gdi32/Makefile.in
@@ -12,6 +12,7 @@ C_SRCS = \
bitmap.c \
brush.c \
clipping.c \
+ d3dadapter.c \
dc.c \
dib.c \
dibdrv/bitblt.c \
diff --git a/dlls/gdi32/d3dadapter.c b/dlls/gdi32/d3dadapter.c
new file mode 100644
index 0000000..fbf2cd0
--- /dev/null
+++ b/dlls/gdi32/d3dadapter.c
@@ -0,0 +1,41 @@
+/*
+ * d3dadapter function forwarding to the display driver
+ *
+ * Copyright (c) 1999 Lionel Ulmer
+ * Copyright (c) 2005 Raphael Junqueira
+ * Copyright (c) 2006 Roderick Colenbrander
+ * Copyright (c) 2013 Joakim Sindholt
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "gdi_private.h"
+
+/***********************************************************************
+ * __wine_get_d3dadapter_driver (GDI32.@)
+ */
+struct d3dadapter_funcs * CDECL __wine_get_d3dadapter_driver( HDC hdc, UINT version )
+{
+ struct d3dadapter_funcs *ret = NULL;
+ DC * dc = get_dc_ptr( hdc );
+
+ if (dc)
+ {
+ PHYSDEV physdev = GET_DC_PHYSDEV( dc, wine_get_d3dadapter_driver );
+ ret = physdev->funcs->wine_get_d3dadapter_driver( physdev, version );
+ release_dc_ptr( dc );
+ }
+ return ret;
+}
diff --git a/dlls/gdi32/dibdrv/dc.c b/dlls/gdi32/dibdrv/dc.c
index 5ee1bd5..0a9e732 100644
--- a/dlls/gdi32/dibdrv/dc.c
+++ b/dlls/gdi32/dibdrv/dc.c
@@ -523,6 +523,7 @@ const struct gdi_dc_funcs dib_driver =
NULL, /* pUnrealizePalette */
NULL, /* pWidenPath */
dibdrv_wine_get_wgl_driver, /* wine_get_wgl_driver */
+ NULL, /* wine_get_d3dadapter_driver */
GDI_PRIORITY_DIB_DRV /* priority */
};
@@ -1143,5 +1144,6 @@ static const struct gdi_dc_funcs window_driver =
NULL, /* pUnrealizePalette */
NULL, /* pWidenPath */
windrv_wine_get_wgl_driver, /* wine_get_wgl_driver */
+ NULL, /* wine_get_d3dadapter_driver */
GDI_PRIORITY_DIB_DRV + 10 /* priority */
};
diff --git a/dlls/gdi32/driver.c b/dlls/gdi32/driver.c
index 4529562..85151fe 100644
--- a/dlls/gdi32/driver.c
+++ b/dlls/gdi32/driver.c
@@ -632,6 +632,11 @@ static struct opengl_funcs *nulldrv_wine_get_wgl_driver( PHYSDEV dev, UINT versi
return (void *)-1;
}
+static struct d3dadapter_funcs *nulldrv_wine_get_d3dadapter_driver( PHYSDEV dev, UINT version )
+{
+ return NULL;
+}
+
const struct gdi_dc_funcs null_driver =
{
nulldrv_AbortDoc, /* pAbortDoc */
@@ -761,6 +766,7 @@ const struct gdi_dc_funcs null_driver =
nulldrv_UnrealizePalette, /* pUnrealizePalette */
nulldrv_WidenPath, /* pWidenPath */
nulldrv_wine_get_wgl_driver, /* wine_get_wgl_driver */
+ nulldrv_wine_get_d3dadapter_driver, /* wine_get_d3dadapter_driver */
GDI_PRIORITY_NULL_DRV /* priority */
};
diff --git a/dlls/gdi32/enhmfdrv/init.c b/dlls/gdi32/enhmfdrv/init.c
index 682f412..6e467cc 100644
--- a/dlls/gdi32/enhmfdrv/init.c
+++ b/dlls/gdi32/enhmfdrv/init.c
@@ -163,6 +163,7 @@ static const struct gdi_dc_funcs EMFDRV_Funcs =
NULL, /* pUnrealizePalette */
EMFDRV_WidenPath, /* pWidenPath */
NULL, /* wine_get_wgl_driver */
+ NULL, /* wine_get_d3dadapter_driver */
GDI_PRIORITY_GRAPHICS_DRV /* priority */
};
diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c
index fae9ffe..03fa0db 100644
--- a/dlls/gdi32/freetype.c
+++ b/dlls/gdi32/freetype.c
@@ -8442,6 +8442,7 @@ static const struct gdi_dc_funcs freetype_funcs =
NULL, /* pUnrealizePalette */
NULL, /* pWidenPath */
NULL, /* wine_get_wgl_driver */
+ NULL, /* wine_get_d3dadapter_driver */
GDI_PRIORITY_FONT_DRV /* priority */
};
diff --git a/dlls/gdi32/gdi32.spec b/dlls/gdi32/gdi32.spec
index 6ebad3c..1a38c53 100644
--- a/dlls/gdi32/gdi32.spec
+++ b/dlls/gdi32/gdi32.spec
@@ -518,3 +518,6 @@
# OpenGL
@ cdecl __wine_get_wgl_driver(long long)
+
+# Native Direct3D
+@ cdecl __wine_get_d3dadapter_driver(long long)
diff --git a/dlls/gdi32/mfdrv/init.c b/dlls/gdi32/mfdrv/init.c
index 7b53244..574773c 100644
--- a/dlls/gdi32/mfdrv/init.c
+++ b/dlls/gdi32/mfdrv/init.c
@@ -226,6 +226,7 @@ static const struct gdi_dc_funcs MFDRV_Funcs =
NULL, /* pUnrealizePalette */
MFDRV_WidenPath, /* pWidenPath */
NULL, /* wine_get_wgl_driver */
+ NULL, /* wine_get_d3dadapter_driver */
GDI_PRIORITY_GRAPHICS_DRV /* priority */
};
diff --git a/dlls/gdi32/path.c b/dlls/gdi32/path.c
index 2c54e94..839e508 100644
--- a/dlls/gdi32/path.c
+++ b/dlls/gdi32/path.c
@@ -2345,5 +2345,6 @@ const struct gdi_dc_funcs path_driver =
NULL, /* pUnrealizePalette */
NULL, /* pWidenPath */
NULL, /* wine_get_wgl_driver */
+ NULL, /* wine_get_d3dadapter_driver */
GDI_PRIORITY_PATH_DRV /* priority */
};
diff --git a/dlls/winemac.drv/gdi.c b/dlls/winemac.drv/gdi.c
index 951b569..f38da8c 100644
--- a/dlls/winemac.drv/gdi.c
+++ b/dlls/winemac.drv/gdi.c
@@ -538,6 +538,7 @@ static const struct gdi_dc_funcs macdrv_funcs =
NULL, /* pUnrealizePalette */
NULL, /* pWidenPath */
macdrv_wine_get_wgl_driver, /* wine_get_wgl_driver */
+ NULL, /* wine_get_d3dadapter_driver */
GDI_PRIORITY_GRAPHICS_DRV /* priority */
};
diff --git a/dlls/wineps.drv/init.c b/dlls/wineps.drv/init.c
index fde65c2..22b7994 100644
--- a/dlls/wineps.drv/init.c
+++ b/dlls/wineps.drv/init.c
@@ -950,6 +950,7 @@ static const struct gdi_dc_funcs psdrv_funcs =
NULL, /* pUnrealizePalette */
NULL, /* pWidenPath */
NULL, /* wine_get_wgl_driver */
+ NULL, /* wine_get_d3dadapter_driver */
GDI_PRIORITY_GRAPHICS_DRV /* priority */
};
diff --git a/dlls/winex11.drv/Makefile.in b/dlls/winex11.drv/Makefile.in
index 463eefd..7b09215 100644
--- a/dlls/winex11.drv/Makefile.in
+++ b/dlls/winex11.drv/Makefile.in
@@ -8,7 +8,9 @@ C_SRCS = \
bitblt.c \
brush.c \
clipboard.c \
+ d3dadapter.c \
desktop.c \
+ dri2.c \
event.c \
graphics.c \
ime.c \
diff --git a/dlls/winex11.drv/d3dadapter.c b/dlls/winex11.drv/d3dadapter.c
new file mode 100644
index 0000000..20fe4c6
--- /dev/null
+++ b/dlls/winex11.drv/d3dadapter.c
@@ -0,0 +1,996 @@
+/*
+ * X11DRV ID3DAdapter9 support functions
+ *
+ * Copyright 2013 Joakim Sindholt
+ * Christoph Bumiller
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3dadapter);
+
+#if defined(SONAME_LIBXEXT) && \
+ defined(SONAME_LIBXFIXES) && \
+ defined(SONAME_LIBD3DADAPTER9)
+
+#include "wine/d3dadapter.h"
+#include "wine/library.h"
+#include "wine/unicode.h"
+
+#include "x11drv.h"
+
+#include <d3dadapter/drm.h>
+
+#include <X11/Xlib.h>
+#include "xfixes.h"
+#include "dri2.h"
+
+#include <libdrm/drm.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <fcntl.h>
+
+struct d3dadapter_info {
+ unsigned dri2_major, dri2_minor;
+};
+
+static const struct D3DAdapter9DRM *d3d9_drm = NULL;
+static struct d3dadapter_info d3d_info;
+
+static XContext d3d_hwnd_context;
+static CRITICAL_SECTION context_section;
+static CRITICAL_SECTION_DEBUG critsect_debug =
+{
+ 0, 0, &context_section,
+ { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
+ 0, 0, { (DWORD_PTR)(__FILE__ ": context_section") }
+};
+static CRITICAL_SECTION context_section = { &critsect_debug, -1, 0, 0, 0, 0 };
+
+const GUID IID_ID3DPresent = { 0x77D60E80, 0xF1E6, 0x11DF, { 0x9E, 0x39, 0x95, 0x0C, 0xDF, 0xD7, 0x20, 0x85 } };
+const GUID IID_ID3DPresentGroup = { 0xB9C3016E, 0xF32A, 0x11DF, { 0x9C, 0x18, 0x92, 0xEA, 0xDE, 0xD7, 0x20, 0x85 } };
+
+struct d3d_drawable
+{
+ Drawable drawable; /* X11 drawable */
+ HDC hdc;
+ HWND wnd; /* HWND (for convenience) */
+ RECT dc_rect; /* rect relative to the X11 drawable */
+ RECT dest_rect; /* dest rect used when creating the X11 region */
+ XserverRegion region; /* X11 region matching dc_rect */
+};
+
+struct DRI2Present
+{
+ /* COM vtable */
+ void *vtable;
+ /* IUnknown reference count */
+ LONG refs;
+
+ D3DPRESENT_PARAMETERS params;
+ HWND focus_wnd;
+
+ struct {
+ Drawable drawable;
+ XserverRegion region;
+ } cache;
+
+ WCHAR devname[32];
+ HCURSOR hCursor;
+};
+
+static void
+free_d3dadapter_drawable(struct d3d_drawable *d3d)
+{
+ DRI2DestroyDrawable(gdi_display, d3d->drawable);
+ ReleaseDC(d3d->wnd, d3d->hdc);
+ if (d3d->region) { pXFixesDestroyRegion(gdi_display, d3d->region); }
+ HeapFree(GetProcessHeap(), 0, d3d);
+}
+
+void
+destroy_d3dadapter_drawable(HWND hwnd)
+{
+ struct d3d_drawable *d3d;
+
+ EnterCriticalSection(&context_section);
+ if (!XFindContext(gdi_display, (XID)hwnd,
+ d3d_hwnd_context, (char **)&d3d)) {
+ XDeleteContext(gdi_display, (XID)hwnd, d3d_hwnd_context);
+ free_d3dadapter_drawable(d3d);
+ }
+ LeaveCriticalSection(&context_section);
+}
+
+static struct d3d_drawable *
+create_d3dadapter_drawable(HWND hwnd)
+{
+ struct x11drv_escape_get_drawable extesc = { X11DRV_GET_DRAWABLE };
+ struct d3d_drawable *d3d;
+
+ d3d = HeapAlloc(GetProcessHeap(), 0, sizeof(*d3d));
+ if (!d3d) {
+ ERR("Couldn't allocate d3d_drawable.\n");
+ return NULL;
+ }
+
+ d3d->hdc = GetDCEx(hwnd, 0, DCX_CACHE | DCX_CLIPSIBLINGS);
+ if (ExtEscape(d3d->hdc, X11DRV_ESCAPE, sizeof(extesc), (LPCSTR)&extesc,
+ sizeof(extesc), (LPSTR)&extesc) <= 0) {
+ ERR("Unexpected error in X Drawable lookup (hwnd=%p, hdc=%p)\n",
+ hwnd, d3d->hdc);
+ ReleaseDC(hwnd, d3d->hdc);
+ HeapFree(GetProcessHeap(), 0, d3d);
+ return NULL;
+ }
+
+ d3d->drawable = extesc.drawable;
+ d3d->wnd = hwnd;
+ d3d->dc_rect = extesc.dc_rect;
+ SetRect(&d3d->dest_rect, 0, 0, 0, 0);
+ d3d->region = 0; /* because of pDestRect, this is set later */
+
+ /*if (!DRI2CreateDrawable(gdi_display, d3d->drawable)) {
+ ERR("DRI2CreateDrawable failed (hwnd=%p, drawable=%u).\n",
+ hwnd, d3d->drawable);
+ HeapFree(GetProcessHeap(), 0, d3d);
+ return NULL;
+ }*/
+ DRI2CreateDrawable(gdi_display, d3d->drawable);
+
+ return d3d;
+}
+
+static struct d3d_drawable *
+get_d3d_drawable(HWND hwnd)
+{
+ struct d3d_drawable *d3d, *race;
+
+ EnterCriticalSection(&context_section);
+ if (!XFindContext(gdi_display, (XID)hwnd,
+ d3d_hwnd_context, (char **)&d3d)) {
+ struct x11drv_escape_get_drawable extesc = { X11DRV_GET_DRAWABLE };
+
+ /* check if the window has moved since last we used it */
+ if (ExtEscape(d3d->hdc, X11DRV_ESCAPE, sizeof(extesc), (LPCSTR)&extesc,
+ sizeof(extesc), (LPSTR)&extesc) <= 0) {
+ WARN("Window update check failed (hwnd=%p, hdc=%p)\n",
+ hwnd, d3d->hdc);
+ }
+
+ /* update the data and destroy the cached (now invalid) region */
+ if (!EqualRect(&d3d->dc_rect, &extesc.dc_rect)) {
+ d3d->dc_rect = extesc.dc_rect;
+ if (d3d->region) {
+ pXFixesDestroyRegion(gdi_display, d3d->region);
+ d3d->region = 0;
+ }
+ }
+
+ return d3d;
+ }
+ LeaveCriticalSection(&context_section);
+
+ TRACE("No d3d_drawable attached to hwnd %p, creating one.\n", hwnd);
+
+ d3d = create_d3dadapter_drawable(hwnd);
+ if (!d3d) { return NULL; }
+
+ EnterCriticalSection(&context_section);
+ if (!XFindContext(gdi_display, (XID)hwnd,
+ d3d_hwnd_context, (char **)&race)) {
+ /* apparently someone beat us to creating this d3d drawable. Let's not
+ waste more time with X11 calls and just use theirs instead. */
+ free_d3dadapter_drawable(d3d);
+ return race;
+ }
+ XSaveContext(gdi_display, (XID)hwnd, d3d_hwnd_context, (char *)d3d);
+ return d3d;
+}
+
+static void
+release_d3d_drawable(struct d3d_drawable *d3d)
+{
+ if (d3d) { LeaveCriticalSection(&context_section); }
+}
+
+static ULONG WINAPI
+DRI2Present_AddRef( struct DRI2Present *This )
+{
+ ULONG refs = InterlockedIncrement(&This->refs);
+ TRACE("%p increasing refcount to %u.\n", This, refs);
+ return refs;
+}
+
+static ULONG WINAPI
+DRI2Present_Release( struct DRI2Present *This )
+{
+ ULONG refs = InterlockedDecrement(&This->refs);
+ TRACE("%p decreasing refcount to %u.\n", This, refs);
+ if (refs == 0) {
+ /* dtor */
+ HeapFree(GetProcessHeap(), 0, This);
+ }
+ return refs;
+}
+
+static HRESULT WINAPI
+DRI2Present_QueryInterface( struct DRI2Present *This,
+ REFIID riid,
+ void **ppvObject )
+{
+ if (!ppvObject) { return E_POINTER; }
+
+ if (IsEqualGUID(&IID_ID3DPresent, riid) ||
+ IsEqualGUID(&IID_IUnknown, riid)) {
+ *ppvObject = This;
+ DRI2Present_AddRef(This);
+ return S_OK;
+ }
+
+ WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+ *ppvObject = NULL;
+
+ return E_NOINTERFACE;
+}
+
+static HRESULT WINAPI
+DRI2Present_GetPresentParameters( struct DRI2Present *This,
+ D3DPRESENT_PARAMETERS *pPresentationParameters )
+{
+ *pPresentationParameters = This->params;
+ return D3D_OK;
+}
+
+static HRESULT WINAPI
+DRI2Present_GetBuffer( struct DRI2Present *This,
+ HWND hWndOverride,
+ void *pBuffer,
+ const RECT *pDestRect,
+ RECT *pRect,
+ RGNDATA **ppRegion )
+{
+ static const unsigned attachments[] = { DRI2BufferBackLeft };
+
+ struct d3d_drawable *d3d;
+ D3DDRM_BUFFER *drmbuf = pBuffer;
+ DRI2Buffer *buffers;
+ RECT dest;
+ unsigned width, height, n;
+
+ TRACE("(This=%p, hWndOverride=%p, pBuffer=%p, pRect=%p, ppRegion=%p)\n",
+ This, hWndOverride, pBuffer, pRect, ppRegion);
+
+ if (hWndOverride) {
+ d3d = get_d3d_drawable(hWndOverride);
+ } else if (This->params.hDeviceWindow) {
+ d3d = get_d3d_drawable(This->params.hDeviceWindow);
+ } else {
+ d3d = get_d3d_drawable(This->focus_wnd);
+ }
+ if (!d3d) { return D3DERR_DRIVERINTERNALERROR; }
+
+ {
+ /* TODO: don't pass rgndata to the driver, but use it for DRI2CopyRegion
+ DWORD rgn_size;
+ HRGN hrgn = CreateRectRgn(0, 0, 0, 0);
+ if (GetWindowRgn(This->current_window.real, hrgn) != _ERROR) {
+ rgn_size = GetRegionData(hrgn, 0, NULL);
+ This->rgndata = HeapAlloc(GetProcessHeap(), 0, rgn_size);
+ GetRegionData(hrgn, rgn_size, This->rgndata);
+ }
+ DeleteObject(hrgn);
+ if (!This->rgndata) {
+ return D3DERR_DRIVERINTERNALERROR;
+ }*/
+ *ppRegion = NULL;
+ }
+
+ /* XXX base this on events instead of calling every single frame */
+ if ((n = DRI2GetBuffers(gdi_display, d3d->drawable, attachments, 1,
+ &width, &height, &buffers)) < 1) {
+ ERR("DRI2GetBuffers failed (drawable=%u, n=%u)\n",
+ (unsigned)d3d->drawable, n);
+ release_d3d_drawable(d3d);
+ return D3DERR_DRIVERINTERNALERROR;
+ }
+
+ drmbuf->iName = buffers[0].name;
+ drmbuf->dwWidth = width;
+ drmbuf->dwHeight = height;
+ drmbuf->dwStride = buffers[0].pitch;
+ drmbuf->dwCPP = buffers[0].cpp;
+ HeapFree(GetProcessHeap(), 0, buffers);
+
+ /* return the offset region to the driver */
+ pRect->left = d3d->dc_rect.left;
+ pRect->top = d3d->dc_rect.top;
+ pRect->right = d3d->dc_rect.right;
+ pRect->bottom = d3d->dc_rect.bottom;
+
+ TRACE("pRect=(%u..%u)x(%u..%u)\n",
+ pRect->left, pRect->right, pRect->top, pRect->bottom);
+
+ /* if pDestRect is set, calculate the final region */
+ dest = *pRect;
+ if (pDestRect) {
+ dest.left += pDestRect->left;
+ dest.top += pDestRect->top;
+ dest.right = pDestRect->right + dest.left;
+ dest.bottom = pDestRect->bottom + dest.top;
+ if (dest.left > pRect->right) { dest.left = pRect->right; }
+ if (dest.top > pRect->bottom) { dest.top = pRect->bottom; }
+ if (dest.right > pRect->right) { dest.right = pRect->right; }
+ if (dest.bottom > pRect->bottom) { dest.bottom = pRect->bottom; }
+
+ TRACE("dest=(%u..%u)x(%u..%u)\n",
+ dest.left, dest.right, dest.top, dest.bottom);
+ }
+
+ /* if the new dest region doesn't match the cached one, destroy it */
+ if (!EqualRect(&d3d->dest_rect, &dest) && d3d->region) {
+ pXFixesDestroyRegion(gdi_display, d3d->region);
+ d3d->region = 0;
+ }
+
+ /* create region to match the new destination */
+ if (!d3d->region) {
+ XRectangle xrect;
+
+ xrect.x = dest.left;
+ xrect.y = dest.top;
+ xrect.width = dest.right - dest.left;
+ xrect.height = dest.bottom - dest.top;
+
+ d3d->region = pXFixesCreateRegion(gdi_display, &xrect, 1);
+ d3d->dest_rect = dest;
+
+ TRACE("XFixes rect (x=%u, y=%u, w=%u, h=%u)\n",
+ xrect.x, xrect.y, xrect.width, xrect.height);
+ }
+
+ This->cache.drawable = d3d->drawable;
+ This->cache.region = d3d->region;
+
+ release_d3d_drawable(d3d);
+
+ return D3D_OK;
+}
+
+static HRESULT WINAPI
+DRI2Present_GetFrontBuffer( struct DRI2Present *This,
+ void *pBuffer )
+{
+ FIXME("(%p, %p), stub!\n", This, pBuffer);
+ return D3DERR_INVALIDCALL;
+}
+
+static HRESULT WINAPI
+DRI2Present_Present( struct DRI2Present *This,
+ DWORD Flags )
+{
+ TRACE("(This=%p, Flags=%x)\n", This, Flags);
+
+ XFlush(gdi_display);
+
+ if (1/*This->dri2_minor < 3*/) {
+ if (!DRI2CopyRegion(gdi_display, This->cache.drawable,
+ This->cache.region, DRI2BufferFrontLeft,
+ DRI2BufferBackLeft)) {
+ ERR("DRI2CopyRegion failed (drawable=%u, region=%u)\n",
+ (unsigned)This->cache.drawable, (unsigned)This->cache.region);
+ return D3DERR_DRIVERINTERNALERROR;
+ }
+ /* XXX if (!(Flags & D3DPRESENT_DONOTWAIT)) { */
+ }
+
+ return D3D_OK;
+}
+
+static HRESULT WINAPI
+DRI2Present_GetRasterStatus( struct DRI2Present *This,
+ D3DRASTER_STATUS *pRasterStatus )
+{
+ FIXME("(%p, %p), stub!\n", This, pRasterStatus);
+ return D3DERR_INVALIDCALL;
+}
+
+static HRESULT WINAPI
+DRI2Present_GetDisplayMode( struct DRI2Present *This,
+ D3DDISPLAYMODEEX *pMode,
+ D3DDISPLAYROTATION *pRotation )
+{
+ DEVMODEW dm;
+
+ ZeroMemory(&dm, sizeof(dm));
+ dm.dmSize = sizeof(dm);
+
+ EnumDisplaySettingsExW(This->devname, ENUM_CURRENT_SETTINGS, &dm, 0);
+ pMode->Width = dm.dmPelsWidth;
+ pMode->Height = dm.dmPelsHeight;
+ pMode->RefreshRate = dm.dmDisplayFrequency;
+ pMode->ScanLineOrdering = (dm.dmDisplayFlags & DM_INTERLACED) ?
+ D3DSCANLINEORDERING_INTERLACED :
+ D3DSCANLINEORDERING_PROGRESSIVE;
+
+ /* XXX This is called "guessing" */
+ switch (dm.dmBitsPerPel) {
+ case 32: pMode->Format = D3DFMT_X8R8G8B8; break;
+ case 24: pMode->Format = D3DFMT_R8G8B8; break;
+ case 16: pMode->Format = D3DFMT_R5G6B5; break;
+ default:
+ WARN("Unknown display format with %u bpp.\n", dm.dmBitsPerPel);
+ pMode->Format = D3DFMT_UNKNOWN;
+ }
+
+ switch (dm.dmDisplayOrientation) {
+ case DMDO_DEFAULT: *pRotation = D3DDISPLAYROTATION_IDENTITY; break;
+ case DMDO_90: *pRotation = D3DDISPLAYROTATION_90; break;
+ case DMDO_180: *pRotation = D3DDISPLAYROTATION_180; break;
+ case DMDO_270: *pRotation = D3DDISPLAYROTATION_270; break;
+ default:
+ WARN("Unknown display rotation %u.\n", dm.dmDisplayOrientation);
+ *pRotation = D3DDISPLAYROTATION_IDENTITY;
+ }
+
+ return D3D_OK;
+}
+
+static HRESULT WINAPI
+DRI2Present_GetPresentStats( struct DRI2Present *This,
+ D3DPRESENTSTATS *pStats )
+{
+ FIXME("(%p, %p), stub!\n", This, pStats);
+ return D3DERR_INVALIDCALL;
+}
+
+static HRESULT WINAPI
+DRI2Present_GetCursorPos( struct DRI2Present *This,
+ POINT *pPoint )
+{
+ BOOL ok;
+ if (!pPoint)
+ return D3DERR_INVALIDCALL;
+ ok = GetCursorPos(pPoint);
+ ok = ok && ScreenToClient(This->focus_wnd, pPoint);
+ return ok ? S_OK : D3DERR_DRIVERINTERNALERROR;
+}
+
+static HRESULT WINAPI
+DRI2Present_SetCursorPos( struct DRI2Present *This,
+ POINT *pPoint )
+{
+ if (!pPoint)
+ return D3DERR_INVALIDCALL;
+ return SetCursorPos(pPoint->x, pPoint->y);
+}
+
+static HRESULT WINAPI
+DRI2Present_SetCursor( struct DRI2Present *This,
+ void *pBitmap,
+ POINT *pHotspot,
+ BOOL bShow )
+{
+ if (pBitmap) {
+ ICONINFO info;
+ HCURSOR cursor;
+
+ DWORD mask[32];
+ memset(mask, ~0, sizeof(mask));
+
+ if (!pHotspot)
+ return D3DERR_INVALIDCALL;
+ info.fIcon = FALSE;
+ info.xHotspot = pHotspot->x;
+ info.yHotspot = pHotspot->y;
+ info.hbmMask = CreateBitmap(32, 32, 1, 1, mask);
+ info.hbmColor = CreateBitmap(32, 32, 1, 32, pBitmap);
+
+ cursor = CreateIconIndirect(&info);
+ if (info.hbmMask) DeleteObject(info.hbmMask);
+ if (info.hbmColor) DeleteObject(info.hbmColor);
+ if (cursor)
+ DestroyCursor(This->hCursor);
+ This->hCursor = cursor;
+ }
+ SetCursor(bShow ? This->hCursor : NULL);
+
+ return D3D_OK;
+}
+
+static HRESULT WINAPI
+DRI2Present_SetGammaRamp( struct DRI2Present *This,
+ const D3DGAMMARAMP *pRamp,
+ HWND hWndOverride )
+{
+ HWND hWnd = hWndOverride ? hWndOverride : This->focus_wnd;
+ HDC hdc;
+ BOOL ok;
+ if (!pRamp) {
+ return D3DERR_INVALIDCALL;
+ }
+ hdc = GetDC(hWnd);
+ ok = SetDeviceGammaRamp(hdc, (void *)pRamp);
+ ReleaseDC(hWnd, hdc);
+ return ok ? D3D_OK : D3DERR_DRIVERINTERNALERROR;
+}
+
+static HRESULT WINAPI
+DRI2Present_GetWindowRect( struct DRI2Present *This,
+ HWND hWnd,
+ LPRECT pRect )
+{
+ if (!hWnd)
+ hWnd = This->focus_wnd;
+ return GetClientRect(hWnd, pRect) ? D3D_OK : D3DERR_INVALIDCALL;
+}
+
+static ID3DPresentVtbl DRI2Present_vtable = {
+ (void *)DRI2Present_QueryInterface,
+ (void *)DRI2Present_AddRef,
+ (void *)DRI2Present_Release,
+ (void *)DRI2Present_GetPresentParameters,
+ (void *)DRI2Present_GetBuffer,
+ (void *)DRI2Present_GetFrontBuffer,
+ (void *)DRI2Present_Present,
+ (void *)DRI2Present_GetRasterStatus,
+ (void *)DRI2Present_GetDisplayMode,
+ (void *)DRI2Present_GetPresentStats,
+ (void *)DRI2Present_GetCursorPos,
+ (void *)DRI2Present_SetCursorPos,
+ (void *)DRI2Present_SetCursor,
+ (void *)DRI2Present_SetGammaRamp,
+ (void *)DRI2Present_GetWindowRect
+};
+
+static HRESULT
+DRI2Present_new( Display *dpy,
+ const WCHAR *devname,
+ D3DPRESENT_PARAMETERS *params,
+ HWND focus_wnd,
+ struct DRI2Present **out )
+{
+ struct DRI2Present *This;
+ HWND draw_window;
+ RECT rect;
+
+ if (!focus_wnd) { focus_wnd = params->hDeviceWindow; }
+ if (!focus_wnd) {
+ ERR("No focus HWND specified for presentation backend.\n");
+ return D3DERR_INVALIDCALL;
+ }
+ draw_window = params->hDeviceWindow ? params->hDeviceWindow : focus_wnd;
+
+ This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof(struct DRI2Present));
+ if (!This) {
+ ERR("Out of memory.\n");
+ return E_OUTOFMEMORY;
+ }
+
+ This->vtable = &DRI2Present_vtable;
+ This->refs = 1;
+ This->focus_wnd = focus_wnd;
+
+ /* sanitize presentation parameters */
+ if (params->SwapEffect == D3DSWAPEFFECT_COPY &&
+ params->BackBufferCount > 1) {
+ WARN("present: BackBufferCount > 1 when SwapEffect == "
+ "D3DSWAPEFFECT_COPY.\n");
+ params->BackBufferCount = 1;
+ }
+
+ /* XXX 30 for Ex */
+ if (params->BackBufferCount > 3) {
+ WARN("present: BackBufferCount > 3.\n");
+ params->BackBufferCount = 3;
+ }
+
+ if (params->BackBufferCount == 0) {
+ params->BackBufferCount = 1;
+ }
+
+ if (params->BackBufferFormat == D3DFMT_UNKNOWN) {
+ params->BackBufferFormat = D3DFMT_A8R8G8B8;
+ }
+
+ if (!GetClientRect(draw_window, &rect)) {
+ WARN("GetClientRect failed.\n");
+ rect.right = 640;
+ rect.bottom = 480;
+ }
+
+ if (params->BackBufferWidth == 0) {
+ params->BackBufferWidth = rect.right;
+ }
+ if (params->BackBufferHeight == 0) {
+ params->BackBufferHeight = rect.bottom;
+ }
+ This->params = *params;
+ strcpyW(This->devname, devname);
+
+ *out = This;
+
+ return D3D_OK;
+}
+
+struct DRI2PresentGroup
+{
+ /* COM vtable */
+ void *vtable;
+ /* IUnknown reference count */
+ LONG refs;
+
+ struct DRI2Present **present_backends;
+ unsigned npresent_backends;
+};
+
+static ULONG WINAPI
+DRI2PresentGroup_AddRef( struct DRI2PresentGroup *This )
+{
+ ULONG refs = InterlockedIncrement(&This->refs);
+ TRACE("%p increasing refcount to %u.\n", This, refs);
+ return refs;
+}
+
+static ULONG WINAPI
+DRI2PresentGroup_Release( struct DRI2PresentGroup *This )
+{
+ ULONG refs = InterlockedDecrement(&This->refs);
+ TRACE("%p decreasing refcount to %u.\n", This, refs);
+ if (refs == 0) {
+ unsigned i;
+ if (This->present_backends) {
+ for (i = 0; i < This->npresent_backends; ++i) {
+ DRI2Present_Release(This->present_backends[i]);
+ }
+ HeapFree(GetProcessHeap(), 0, This->present_backends);
+ }
+ HeapFree(GetProcessHeap(), 0, This);
+ }
+ return refs;
+}
+
+static HRESULT WINAPI
+DRI2PresentGroup_QueryInterface( struct DRI2PresentGroup *This,
+ REFIID riid,
+ void **ppvObject )
+{
+ if (!ppvObject) { return E_POINTER; }
+ if (IsEqualGUID(&IID_ID3DPresentGroup, riid) ||
+ IsEqualGUID(&IID_IUnknown, riid)) {
+ *ppvObject = This;
+ DRI2PresentGroup_AddRef(This);
+ return S_OK;
+ }
+
+ WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+ *ppvObject = NULL;
+
+ return E_NOINTERFACE;
+}
+
+static UINT WINAPI
+DRI2PresentGroup_GetMultiheadCount( struct DRI2PresentGroup *This )
+{
+ FIXME("(%p), stub!\n", This);
+ return 1;
+}
+
+static HRESULT WINAPI
+DRI2PresentGroup_GetPresent( struct DRI2PresentGroup *This,
+ UINT Index,
+ ID3DPresent **ppPresent )
+{
+ if (Index >= DRI2PresentGroup_GetMultiheadCount(This)) {
+ ERR("Index >= MultiHeadCount\n");
+ return D3DERR_INVALIDCALL;
+ }
+ DRI2Present_AddRef(This->present_backends[Index]);
+ *ppPresent = (ID3DPresent *)This->present_backends[Index];
+
+ return D3D_OK;
+}
+
+static HRESULT WINAPI
+DRI2PresentGroup_CreateAdditionalPresent( struct DRI2PresentGroup *This,
+ D3DPRESENT_PARAMETERS *pPresentationParameters,
+ ID3DPresent **ppPresent )
+{
+ FIXME("(%p, %p, %p), stub!\n", This, pPresentationParameters, ppPresent);
+ return D3DERR_INVALIDCALL;
+}
+
+static ID3DPresentGroupVtbl DRI2PresentGroup_vtable = {
+ (void *)DRI2PresentGroup_QueryInterface,
+ (void *)DRI2PresentGroup_AddRef,
+ (void *)DRI2PresentGroup_Release,
+ (void *)DRI2PresentGroup_GetMultiheadCount,
+ (void *)DRI2PresentGroup_GetPresent,
+ (void *)DRI2PresentGroup_CreateAdditionalPresent
+};
+
+static HRESULT
+dri2_create_present_group( const WCHAR *device_name,
+ UINT adapter,
+ HWND focus_wnd,
+ D3DPRESENT_PARAMETERS *params,
+ unsigned nparams,
+ ID3DPresentGroup **group )
+{
+ struct DRI2PresentGroup *This =
+ HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof(struct DRI2PresentGroup));
+ DISPLAY_DEVICEW dd;
+ HRESULT hr;
+ unsigned i;
+
+ if (!This) {
+ ERR("Out of memory.\n");
+ return E_OUTOFMEMORY;
+ }
+
+ This->vtable = &DRI2PresentGroup_vtable;
+ This->refs = 1;
+ This->npresent_backends = nparams;
+ This->present_backends = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ This->npresent_backends *
+ sizeof(struct DRI2Present *));
+ if (!This->present_backends) {
+ DRI2PresentGroup_Release(This);
+ ERR("Out of memory.\n");
+ return E_OUTOFMEMORY;
+ }
+
+ if (nparams != 1) { adapter = 0; }
+ for (i = 0; i < This->npresent_backends; ++i) {
+ /* find final device name */
+ if (!EnumDisplayDevicesW(device_name, adapter+i, &dd, 0)) {
+ WARN("Couldn't find subdevice %d from `%s'\n",
+ i, debugstr_w(device_name));
+ }
+
+ /* create an ID3DPresent for it */
+ hr = DRI2Present_new(gdi_display, dd.DeviceName, &params[i],
+ focus_wnd, &This->present_backends[i]);
+ if (FAILED(hr)) {
+ DRI2PresentGroup_Release(This);
+ return hr;
+ }
+ }
+
+ *group = (ID3DPresentGroup *)This;
+ TRACE("Returning %p\n", *group);
+
+ return D3D_OK;
+}
+
+static HRESULT
+dri2_create_adapter9( HDC hdc,
+ ID3DAdapter9 **out )
+{
+ struct x11drv_escape_get_drawable extesc = { X11DRV_GET_DRAWABLE };
+ drm_auth_t auth;
+ Window root;
+ HRESULT hr;
+ int fd;
+
+ if (!d3d9_drm) {
+ WARN("DRM drivers are not supported on your system.\n");
+ return D3DERR_DRIVERINTERNALERROR;
+ }
+
+ if (ExtEscape(hdc, X11DRV_ESCAPE, sizeof(extesc), (LPCSTR)&extesc,
+ sizeof(extesc), (LPSTR)&extesc) <= 0) {
+ WARN("X11 drawable lookup failed (hdc=%p)\n", hdc);
+ }
+
+ { /* XGetGeometry */
+ unsigned udummy;
+ int dummy;
+
+ if (!XGetGeometry(gdi_display, extesc.drawable, &root, &dummy, &dummy,
+ &udummy, &udummy, &udummy, &udummy)) {
+ WARN("XGetGeometry: Unable to get root window (drawable=%u)\n",
+ (unsigned)extesc.drawable);
+ root = (Window)extesc.drawable; /* cross your fingers */
+ }
+ }
+
+ { /* DRI2Connect */
+ char *driver, *device;
+
+ if (!DRI2Connect(gdi_display, root, DRI2DriverDRI, &driver, &device)) {
+ WARN("DRI2Connect: Unable to connect DRI2 (window=%u)\n",
+ (unsigned)root);
+ return D3DERR_DRIVERINTERNALERROR;
+ }
+
+ fd = open(device, O_RDWR);
+ if (fd < 0) {
+ WARN("Failed to open drm fd: %s (%s)\n", strerror(errno), device);
+ HeapFree(GetProcessHeap(), 0, driver);
+ HeapFree(GetProcessHeap(), 0, device);
+ return D3DERR_DRIVERINTERNALERROR;
+ }
+
+ /* authenticate */
+ if (ioctl(fd, DRM_IOCTL_GET_MAGIC, &auth) != 0) {
+ WARN("DRM_IOCTL_GET_MAGIC failed: %s (%s)\n",
+ strerror(errno), device);
+ HeapFree(GetProcessHeap(), 0, driver);
+ HeapFree(GetProcessHeap(), 0, device);
+ return D3DERR_DRIVERINTERNALERROR;
+ }
+
+ TRACE("Associated `%s' with fd %d opened from `%s'\n",
+ driver, fd, device);
+
+ HeapFree(GetProcessHeap(), 0, driver);
+ HeapFree(GetProcessHeap(), 0, device);
+ }
+
+ if (!DRI2Authenticate(gdi_display, root, auth.magic)) {
+ WARN("DRI2Authenticate failed (fd=%d)\n", fd);
+ return D3DERR_DRIVERINTERNALERROR;
+ }
+
+ hr = d3d9_drm->create_adapter(fd, out);
+ if (FAILED(hr)) {
+ WARN("Unable to create ID3DAdapter9 (fd=%d)\n", fd);
+ return hr;
+ }
+
+ TRACE("Created ID3DAdapter9 with fd %d\n", fd);
+
+ return D3D_OK;
+}
+
+static BOOL
+has_d3dadapter( void )
+{
+ static const void * WINAPI (*pD3DAdapter9GetProc)(const char *);
+ static void *handle = NULL;
+ static int done = 0;
+
+ int xfmaj, xfmin;
+ char errbuf[256];
+
+ /* like in opengl.c (single threaded assumption OK?) */
+ if (done) { return handle != NULL; }
+ done = 1;
+
+ /* */
+ if (!usexfixes) {
+ ERR("%s needs Xfixes.\n", SONAME_LIBD3DADAPTER9);
+ return FALSE;
+ }
+
+ handle = wine_dlopen(SONAME_LIBD3DADAPTER9, RTLD_GLOBAL|RTLD_NOW,
+ errbuf, sizeof(errbuf));
+ if (!handle) {
+ ERR("Failed to load %s: %s\n", SONAME_LIBD3DADAPTER9, errbuf);
+ goto cleanup;
+ }
+
+ /* find our entry point in libd3dadapter9 */
+ pD3DAdapter9GetProc = wine_dlsym(handle, "D3DAdapter9GetProc",
+ errbuf, sizeof(errbuf));
+ if (!pD3DAdapter9GetProc) {
+ ERR("Failed to get the entry point from %s: %s",
+ SONAME_LIBD3DADAPTER9, errbuf);
+ goto cleanup;
+ }
+
+ /* get a handle to the drm backend struct */
+ d3d9_drm = pD3DAdapter9GetProc(D3DADAPTER9DRM_NAME);
+ if (!d3d9_drm) {
+ ERR("%s doesn't support the `%s' backend.\n",
+ SONAME_LIBD3DADAPTER9, D3DADAPTER9DRM_NAME);
+ goto cleanup;
+ }
+
+ /* verify that we're binary compatible */
+ if (d3d9_drm->major_version != D3DADAPTER9DRM_MAJOR) {
+ ERR("Version mismatch. %s has %d.%d, was expecting %d.x\n",
+ SONAME_LIBD3DADAPTER9, d3d9_drm->major_version,
+ d3d9_drm->minor_version, D3DADAPTER9DRM_MAJOR);
+ goto cleanup;
+ }
+
+ /* this will be used to store d3d_drawables */
+ d3d_hwnd_context = XUniqueContext();
+
+ /* query DRI2 */
+ d3d_info.dri2_major = DRI2_MAJOR;
+ d3d_info.dri2_minor = DRI2_MINOR;
+ if (!DRI2QueryExtension(gdi_display)) {
+ ERR("Xserver doesn't support DRI2.\n");
+ return D3DERR_DRIVERINTERNALERROR;
+ }
+ if (!DRI2QueryVersion(gdi_display, &d3d_info.dri2_major,
+ &d3d_info.dri2_minor)) {
+ ERR("Unable to query DRI2 extension.\n");
+ return D3DERR_DRIVERINTERNALERROR;
+ }
+ TRACE("Got DRI2 version %u.%u\n", d3d_info.dri2_major, d3d_info.dri2_minor);
+
+ /* query XFixes */
+ if (!pXFixesQueryVersion(gdi_display, &xfmaj, &xfmin)) {
+ ERR("Unable to query XFixes extension.\n");
+ return D3DERR_DRIVERINTERNALERROR;
+ }
+ TRACE("Got XFixes version %u.%u\n", xfmaj, xfmin);
+
+ return TRUE;
+
+cleanup:
+ ERR("Native Direct3D9 will be unavailable.\n");
+ if (handle) {
+ wine_dlclose(handle, NULL, 0);
+ handle = NULL;
+ }
+
+ return FALSE;
+}
+
+static struct d3dadapter_funcs dri2_driver = {
+ dri2_create_present_group, /* create_present_group */
+ dri2_create_adapter9, /* create_adapter9 */
+};
+
+struct d3dadapter_funcs *
+get_d3d_dri2_driver(UINT version)
+{
+ if (version != WINE_D3DADAPTER_DRIVER_VERSION) {
+ ERR("Version mismatch. d3d* wants %u but winex11 has "
+ "version %u\n", version, WINE_D3DADAPTER_DRIVER_VERSION);
+ return NULL;
+ }
+ if (has_d3dadapter()) { return &dri2_driver; }
+ return NULL;
+}
+
+#else /* defined(SONAME_LIBXEXT) && \
+ defined(SONAME_LIBXFIXES) && \
+ defined(SONAME_LIBD3DADAPTER9) */
+
+struct d3dadapter_funcs;
+
+void
+destroy_d3dadapter_drawable(HWND hwnd)
+{
+}
+
+static BOOL
+has_d3dadapter( void )
+{
+ return FALSE;
+}
+
+struct d3dadapter_funcs *
+get_d3d_dri2_driver(UINT version)
+{
+ return NULL;
+}
+
+#endif /* defined(SONAME_LIBXEXT) && \
+ defined(SONAME_LIBXFIXES) && \
+ defined(SONAME_LIBD3DADAPTER9) */
diff --git a/dlls/winex11.drv/dri2.c b/dlls/winex11.drv/dri2.c
new file mode 100644
index 0000000..d42102c
--- /dev/null
+++ b/dlls/winex11.drv/dri2.c
@@ -0,0 +1,430 @@
+/*
+ * Wine X11DRV DRI2 interface
+ *
+ * Copyright 2013 Joakim Sindholt
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
+
+#if defined(SONAME_LIBXEXT) && defined(SONAME_LIBXFIXES)
+
+#include "x11drv.h"
+#include <X11/Xlibint.h>
+#include <X11/extensions/dri2proto.h>
+#include <X11/extensions/extutil.h>
+
+#include "dri2.h"
+
+#include <stdio.h>
+
+static XExtensionInfo _dri2_info_data;
+static XExtensionInfo *dri2_info = &_dri2_info_data;
+static char dri2_name[] = DRI2_NAME;
+
+#define DRI2CheckExtension(dpy, i, val) \
+ XextCheckExtension(dpy, i, dri2_name, val)
+
+static int
+close_display( Display *dpy,
+ XExtCodes *codes );
+
+static Bool
+wire_to_event( Display *dpy,
+ XEvent *re,
+ xEvent *event );
+
+static Status
+event_to_wire( Display *dpy,
+ XEvent *re,
+ xEvent *event );
+
+static int
+error( Display *dpy,
+ xError *err,
+ XExtCodes *codes,
+ int *ret_code );
+
+static XExtensionHooks dri2_hooks = {
+ NULL, /* create_gc */
+ NULL, /* copy_gc */
+ NULL, /* flush_gc */
+ NULL, /* free_gc */
+ NULL, /* create_font */
+ NULL, /* free_font */
+ close_display, /* close_display */
+ wire_to_event, /* wire_to_event */
+ event_to_wire, /* event_to_wire */
+ error, /* error */
+ NULL, /* error_string */
+};
+
+static XEXT_GENERATE_CLOSE_DISPLAY(close_display, dri2_info);
+static XEXT_GENERATE_FIND_DISPLAY(find_display, dri2_info,
+ dri2_name, &dri2_hooks, 0, NULL);
+
+
+static Bool
+wire_to_event( Display *dpy,
+ XEvent *re,
+ xEvent *event )
+{
+ XExtDisplayInfo *info = find_display(dpy);
+
+ DRI2CheckExtension(dpy, info, False);
+
+ TRACE("dri2 wire_to_event\n");
+
+ return False;
+}
+
+static Status
+event_to_wire( Display *dpy,
+ XEvent *re,
+ xEvent *event )
+{
+ XExtDisplayInfo *info = find_display(dpy);
+
+ DRI2CheckExtension(dpy, info, False);
+
+ TRACE("dri2 event_to_wire\n");
+
+ return False;
+}
+
+static int
+error( Display *dpy,
+ xError *err,
+ XExtCodes *codes,
+ int *ret_code )
+{
+ TRACE("dri2 error\n");
+
+ return False;
+}
+
+/*** Actual API begins here ***/
+
+Bool
+DRI2QueryExtension( Display * dpy/* , int *event_basep, int *error_basep */ )
+{
+ XExtDisplayInfo *info = find_display(dpy);
+
+ if (XextHasExtension(info)) {
+ /**event_basep = info->codes->first_event;
+ *error_basep = info->codes->first_error;*/
+ return True;
+ }
+
+ return False;
+}
+
+Bool
+DRI2QueryVersion( Display *dpy,
+ unsigned *major,
+ unsigned *minor )
+{
+ static const int nevents[] = { 0, 0, 1, 2 };
+ static const int nev = sizeof(nevents)/sizeof(*nevents) - 1;
+
+ XExtDisplayInfo *info = find_display(dpy);
+ xDRI2QueryVersionReply rep;
+ xDRI2QueryVersionReq *req;
+ int i, e;
+
+ DRI2CheckExtension(dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(DRI2QueryVersion, req);
+ req->reqType = info->codes->major_opcode;
+ req->dri2ReqType = X_DRI2QueryVersion;
+ req->majorVersion = *major;
+ req->minorVersion = *minor;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return False;
+ }
+ *major = rep.majorVersion;
+ *minor = rep.minorVersion;
+ UnlockDisplay(dpy);
+ SyncHandle();
+
+ e = (rep.minorVersion < nev) ? nevents[rep.minorVersion] : nevents[nev];
+ for (i = 0; i < e; ++i) {
+ XESetWireToEvent(dpy, info->codes->first_event + i, wire_to_event);
+ XESetEventToWire(dpy, info->codes->first_event + i, event_to_wire);
+ }
+
+ return True;
+}
+
+#define XALIGN(x) (((x) + 3) & (~3))
+
+Bool
+DRI2Connect( Display *dpy,
+ XID window,
+ unsigned driver_type,
+ char **driver,
+ char **device )
+{
+ XExtDisplayInfo *info = find_display(dpy);
+ xDRI2ConnectReply rep;
+ xDRI2ConnectReq *req;
+ int dev_len, driv_len;
+
+ DRI2CheckExtension(dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(DRI2Connect, req);
+ req->reqType = info->codes->major_opcode;
+ req->dri2ReqType = X_DRI2Connect;
+ req->window = window;
+ req->driverType = driver_type;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return False;
+ }
+
+ /* check string lengths */
+ dev_len = rep.deviceNameLength;
+ driv_len = rep.driverNameLength;
+ if (dev_len == 0 || driv_len == 0) {
+ _XEatData(dpy, XALIGN(dev_len) + XALIGN(driv_len));
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return False;
+ }
+
+ /* read out driver */
+ *driver = HeapAlloc(GetProcessHeap(), 0, driv_len + 1);
+ if (!*driver) {
+ _XEatData(dpy, XALIGN(dev_len) + XALIGN(driv_len));
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return False;
+ }
+ _XReadPad(dpy, *driver, driv_len);
+ (*driver)[driv_len] = '\0';
+
+ /* read out device */
+ *device = HeapAlloc(GetProcessHeap(), 0, dev_len + 1);
+ if (!*device) {
+ HeapFree(GetProcessHeap(), 0, *driver);
+ _XEatData(dpy, XALIGN(dev_len));
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return False;
+ }
+ _XReadPad(dpy, *device, dev_len);
+ (*device)[dev_len] = '\0';
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+
+ return True;
+}
+
+Bool
+DRI2Authenticate( Display *dpy,
+ XID window,
+ uint32_t token )
+{
+ XExtDisplayInfo *info = find_display(dpy);
+ xDRI2AuthenticateReply rep;
+ xDRI2AuthenticateReq *req;
+
+ DRI2CheckExtension(dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(DRI2Authenticate, req);
+ req->reqType = info->codes->major_opcode;
+ req->dri2ReqType = X_DRI2Authenticate;
+ req->window = window;
+ req->magic = token;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return False;
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+
+ return rep.authenticated ? True : False;
+}
+
+void
+DRI2CreateDrawable( Display *dpy,
+ XID drawable )
+{
+ XExtDisplayInfo *info = find_display(dpy);
+ xDRI2CreateDrawableReq *req;
+
+ DRI2CheckExtension(dpy, info, );
+
+ LockDisplay(dpy);
+ GetReq(DRI2CreateDrawable, req);
+ req->reqType = info->codes->major_opcode;
+ req->dri2ReqType = X_DRI2CreateDrawable;
+ req->drawable = drawable;
+ UnlockDisplay(dpy);
+ SyncHandle();
+}
+
+void
+DRI2DestroyDrawable( Display *dpy,
+ XID drawable )
+{
+ XExtDisplayInfo *info = find_display(dpy);
+ xDRI2DestroyDrawableReq *req;
+
+ DRI2CheckExtension(dpy, info, );
+
+ LockDisplay(dpy);
+ GetReq(DRI2DestroyDrawable, req);
+ req->reqType = info->codes->major_opcode;
+ req->dri2ReqType = X_DRI2DestroyDrawable;
+ req->drawable = drawable;
+ UnlockDisplay(dpy);
+ SyncHandle();
+}
+
+static unsigned
+get_buffers( Display *dpy,
+ unsigned reqtype,
+ XID drawable,
+ const unsigned *attachments,
+ unsigned attach_count,
+ unsigned *width,
+ unsigned *height,
+ DRI2Buffer **buffers )
+{
+ XExtDisplayInfo *info = find_display(dpy);
+ xDRI2GetBuffersReply rep;
+ xDRI2GetBuffersReq *req;
+ xDRI2Buffer buf;
+ unsigned i, mult = (reqtype == X_DRI2GetBuffersWithFormat) ? 2 : 1;
+
+ DRI2CheckExtension(dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReqExtra(DRI2GetBuffers, attach_count*sizeof(CARD32)*mult, req);
+ req->reqType = info->codes->major_opcode;
+ req->dri2ReqType = reqtype;
+ req->drawable = drawable;
+ req->count = attach_count;
+ /* copy in attachments */
+ for (i = 0; i < attach_count*mult; ++i) {
+ ((CARD32 *)&req[1])[i] = attachments[i];
+ }
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return False;
+ }
+
+ if (rep.count != 0) {
+ *buffers = HeapAlloc(GetProcessHeap(), 0,
+ rep.count * sizeof(DRI2Buffer));
+ if (!*buffers) {
+ _XEatData(dpy, rep.count * sizeof(buf));
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return False;
+ }
+
+ for (i = 0; i < rep.count; ++i) {
+ _XReadPad(dpy, (char *)&buf, sizeof(buf));
+ (*buffers)[i].attachment = buf.attachment;
+ (*buffers)[i].name = buf.name;
+ (*buffers)[i].pitch = buf.pitch;
+ (*buffers)[i].cpp = buf.cpp;
+ (*buffers)[i].flags = buf.flags;
+ }
+ }
+
+ *width = rep.width;
+ *height = rep.height;
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+
+ return rep.count;
+}
+
+unsigned
+DRI2GetBuffers( Display *dpy,
+ XID drawable,
+ const unsigned *attachments,
+ unsigned attach_count,
+ unsigned *width,
+ unsigned *height,
+ DRI2Buffer **buffers )
+{
+ return get_buffers(dpy, X_DRI2GetBuffers, drawable, attachments,
+ attach_count, width, height, buffers);
+}
+
+unsigned
+DRI2GetBuffersWithFormat( Display *dpy,
+ XID drawable,
+ const unsigned *attachments,
+ unsigned attach_count,
+ unsigned *width,
+ unsigned *height,
+ DRI2Buffer **buffers )
+{
+ return get_buffers(dpy, X_DRI2GetBuffersWithFormat, drawable, attachments,
+ attach_count, width, height, buffers);
+}
+
+Bool
+DRI2CopyRegion( Display *dpy,
+ XID drawable,
+ XserverRegion region,
+ unsigned dest,
+ unsigned src )
+{
+ XExtDisplayInfo *info = find_display(dpy);
+ xDRI2CopyRegionReply rep;
+ xDRI2CopyRegionReq *req;
+
+ DRI2CheckExtension(dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(DRI2CopyRegion, req);
+ req->reqType = info->codes->major_opcode;
+ req->dri2ReqType = X_DRI2CopyRegion;
+ req->drawable = drawable;
+ req->region = region;
+ req->dest = dest;
+ req->src = src;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return False;
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+
+ return True;
+}
+
+#endif /* defined(SONAME_LIBXEXT) && defined(SONAME_LIBXFIXES) */
diff --git a/dlls/winex11.drv/dri2.h b/dlls/winex11.drv/dri2.h
new file mode 100644
index 0000000..38c0252
--- /dev/null
+++ b/dlls/winex11.drv/dri2.h
@@ -0,0 +1,101 @@
+/*
+ * Wine X11DRV DRI2 interface
+ *
+ * Copyright 2013 Joakim Sindholt
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __WINE_DRI2_H
+#define __WINE_DRI2_H
+
+#ifndef __WINE_CONFIG_H
+# error You must include config.h to use this header
+#endif
+
+#if defined(SONAME_LIBXEXT) && defined(SONAME_LIBXFIXES)
+
+#include <X11/Xlib.h>
+#include <X11/extensions/Xfixes.h>
+#include <X11/extensions/dri2tokens.h>
+#include <X11/extensions/dri2proto.h>
+
+#include <stdint.h>
+
+typedef struct
+{
+ unsigned attachment;
+ unsigned name;
+ unsigned pitch;
+ unsigned cpp;
+ unsigned flags;
+} DRI2Buffer;
+
+Bool
+DRI2QueryExtension( Display * dpy/* , int *event_basep, int *error_basep */ );
+
+Bool
+DRI2QueryVersion( Display *dpy,
+ unsigned *major,
+ unsigned *minor );
+
+Bool
+DRI2Connect( Display *dpy,
+ XID window,
+ unsigned driver_type,
+ char **driver,
+ char **device );
+
+Bool
+DRI2Authenticate( Display *dpy,
+ XID window,
+ uint32_t token );
+
+void
+DRI2CreateDrawable( Display *dpy,
+ XID drawable );
+
+void
+DRI2DestroyDrawable( Display *dpy,
+ XID drawable );
+
+unsigned
+DRI2GetBuffers( Display *dpy,
+ XID drawable,
+ const unsigned *attachments,
+ unsigned attach_count,
+ unsigned *width,
+ unsigned *height,
+ DRI2Buffer **buffers );
+
+unsigned
+DRI2GetBuffersWithFormat( Display *dpy,
+ XID drawable,
+ const unsigned *attachments,
+ unsigned attach_count,
+ unsigned *width,
+ unsigned *height,
+ DRI2Buffer **buffers );
+
+Bool
+DRI2CopyRegion( Display *dpy,
+ XID drawable,
+ XserverRegion region,
+ unsigned dest,
+ unsigned src );
+
+#endif /* defined(SONAME_LIBXEXT) && defined(SONAME_LIBXFIXES) */
+
+#endif /* __WINE_DRI2_H */
diff --git a/dlls/winex11.drv/init.c b/dlls/winex11.drv/init.c
index 5a7d316..0964a29 100644
--- a/dlls/winex11.drv/init.c
+++ b/dlls/winex11.drv/init.c
@@ -365,6 +365,7 @@ static INT X11DRV_ExtEscape( PHYSDEV dev, INT escape, INT in_count, LPCVOID in_d
{
struct x11drv_escape_get_drawable *data = out_data;
data->drawable = physDev->drawable;
+ data->dc_rect = physDev->dc_rect;
return TRUE;
}
break;
@@ -464,6 +465,21 @@ static struct opengl_funcs * X11DRV_wine_get_wgl_driver( PHYSDEV dev, UINT versi
return ret;
}
+/**********************************************************************
+ * X11DRV_wine_get_d3dadapter_driver
+ */
+static struct d3dadapter_funcs * X11DRV_wine_get_d3dadapter_driver( PHYSDEV dev, UINT version )
+{
+ struct d3dadapter_funcs *ret;
+
+ if (!(ret = get_d3d_dri2_driver( version )))
+ {
+ dev = GET_NEXT_PHYSDEV( dev, wine_get_d3dadapter_driver );
+ ret = dev->funcs->wine_get_d3dadapter_driver( dev, version );
+ }
+ return ret;
+}
+
static const struct gdi_dc_funcs x11drv_funcs =
{
@@ -594,6 +610,7 @@ static const struct gdi_dc_funcs x11drv_funcs =
X11DRV_UnrealizePalette, /* pUnrealizePalette */
NULL, /* pWidenPath */
X11DRV_wine_get_wgl_driver, /* wine_get_wgl_driver */
+ X11DRV_wine_get_d3dadapter_driver, /* wine_get_d3dadapter_driver */
GDI_PRIORITY_GRAPHICS_DRV /* priority */
};
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c
index 06e2294..547e99c 100644
--- a/dlls/winex11.drv/window.c
+++ b/dlls/winex11.drv/window.c
@@ -1609,6 +1609,7 @@ void CDECL X11DRV_DestroyWindow( HWND hwnd )
struct x11drv_win_data *data;
destroy_gl_drawable( hwnd );
+ destroy_d3dadapter_drawable( hwnd );
if (!(data = get_win_data( hwnd ))) return;
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index bcbfe14..5b598d6 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -222,6 +222,7 @@ extern BOOL shape_layered_windows DECLSPEC_HIDDEN;
extern const struct gdi_dc_funcs *X11DRV_XRender_Init(void) DECLSPEC_HIDDEN;
extern struct opengl_funcs *get_glx_driver(UINT) DECLSPEC_HIDDEN;
+extern struct d3dadapter_funcs *get_d3d_dri2_driver(UINT) DECLSPEC_HIDDEN;
/* IME support */
extern void IME_SetOpenStatus(BOOL fOpen) DECLSPEC_HIDDEN;
@@ -295,6 +296,7 @@ struct x11drv_escape_get_drawable
Drawable drawable; /* X drawable */
Drawable gl_drawable; /* GL drawable */
int pixel_format; /* internal GL pixel format */
+ RECT dc_rect; /* DC rectangle relative to drawable */
};
struct x11drv_escape_flush_gl_drawable
@@ -375,6 +377,7 @@ extern BOOL show_systray DECLSPEC_HIDDEN;
extern BOOL grab_pointer DECLSPEC_HIDDEN;
extern BOOL grab_fullscreen DECLSPEC_HIDDEN;
extern BOOL usexcomposite DECLSPEC_HIDDEN;
+extern BOOL usexfixes DECLSPEC_HIDDEN;
extern BOOL managed_mode DECLSPEC_HIDDEN;
extern BOOL decorated_mode DECLSPEC_HIDDEN;
extern BOOL private_color_map DECLSPEC_HIDDEN;
@@ -576,6 +579,8 @@ extern void sync_gl_drawable( HWND hwnd, const RECT *visible_rect, const RECT *c
extern void set_gl_drawable_parent( HWND hwnd, HWND parent ) DECLSPEC_HIDDEN;
extern void destroy_gl_drawable( HWND hwnd ) DECLSPEC_HIDDEN;
+extern void destroy_d3dadapter_drawable( HWND hwnd ) DECLSPEC_HIDDEN;
+
extern void wait_for_withdrawn_state( HWND hwnd, BOOL set ) DECLSPEC_HIDDEN;
extern Window init_clip_window(void) DECLSPEC_HIDDEN;
extern void update_user_time( Time time ) DECLSPEC_HIDDEN;
diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c
index 85c69bf..3a8c3a1 100644
--- a/dlls/winex11.drv/x11drv_main.c
+++ b/dlls/winex11.drv/x11drv_main.c
@@ -48,6 +48,7 @@
#include "x11drv.h"
#include "xcomposite.h"
+#include "xfixes.h"
#include "wine/server.h"
#include "wine/debug.h"
#include "wine/library.h"
@@ -65,6 +66,7 @@ Window root_window;
BOOL usexvidmode = TRUE;
BOOL usexrandr = TRUE;
BOOL usexcomposite = TRUE;
+BOOL usexfixes = TRUE;
BOOL use_xkb = TRUE;
BOOL use_take_focus = TRUE;
BOOL use_primary_selection = FALSE;
@@ -476,6 +478,54 @@ sym_not_found:
}
#endif /* defined(SONAME_LIBXCOMPOSITE) */
+#ifdef SONAME_LIBXFIXES
+
+#define MAKE_FUNCPTR(f) typeof(f) * p##f;
+MAKE_FUNCPTR(XFixesQueryExtension)
+MAKE_FUNCPTR(XFixesQueryVersion)
+MAKE_FUNCPTR(XFixesCreateRegion)
+MAKE_FUNCPTR(XFixesDestroyRegion)
+#undef MAKE_FUNCPTR
+
+int xfixes_event_base;
+int xfixes_error_base;
+
+static void X11DRV_XFixes_Init(void)
+{
+ void *xfixes_handle = wine_dlopen(SONAME_LIBXFIXES, RTLD_NOW, NULL, 0);
+ if (!xfixes_handle)
+ {
+ TRACE("Unable to open %s, XFixes disabled\n", SONAME_LIBXFIXES);
+ usexfixes = 0;
+ return;
+ }
+
+#define LOAD_FUNCPTR(f) \
+ if((p##f = wine_dlsym(xfixes_handle, #f, NULL, 0)) == NULL) \
+ goto sym_not_found;
+ LOAD_FUNCPTR(XFixesQueryExtension)
+ LOAD_FUNCPTR(XFixesQueryVersion)
+ LOAD_FUNCPTR(XFixesCreateRegion)
+ LOAD_FUNCPTR(XFixesDestroyRegion)
+#undef LOAD_FUNCPTR
+
+ if(!pXFixesQueryExtension(gdi_display, &xfixes_event_base,
+ &xfixes_error_base)) {
+ TRACE("XFixes extension could not be queried; disabled\n");
+ wine_dlclose(xfixes_handle, NULL, 0);
+ usexfixes = 0;
+ return;
+ }
+ TRACE("XFixes is up and running error_base = %d\n", xfixes_error_base);
+ return;
+
+sym_not_found:
+ TRACE("Unable to load function pointers from %s, XFixes disabled\n", SONAME_LIBXFIXES);
+ wine_dlclose(xfixes_handle, NULL, 0);
+ usexfixes = 0;
+}
+#endif /* SONAME_LIBXFIXES */
+
static void init_visuals( Display *display, int screen )
{
int count;
@@ -582,6 +632,9 @@ static BOOL process_attach(void)
#ifdef SONAME_LIBXCOMPOSITE
X11DRV_XComposite_Init();
#endif
+#ifdef SONAME_LIBXFIXES
+ X11DRV_XFixes_Init();
+#endif
X11DRV_XInput2_Init();
#ifdef HAVE_XKB
diff --git a/dlls/winex11.drv/xfixes.h b/dlls/winex11.drv/xfixes.h
new file mode 100644
index 0000000..cc7e287
--- /dev/null
+++ b/dlls/winex11.drv/xfixes.h
@@ -0,0 +1,39 @@
+/*
+ * Wine X11DRV XFixes interface
+ *
+ * Copyright 2007 Chris Robinson
+ * 2013 Joakim Sindholt
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+#ifndef __WINE_XFIXES_H
+#define __WINE_XFIXES_H
+
+#ifndef __WINE_CONFIG_H
+# error You must include config.h to use this header
+#endif
+
+#ifdef SONAME_LIBXFIXES
+
+#include <X11/extensions/Xfixes.h>
+#define MAKE_FUNCPTR(f) extern typeof(f) * p##f DECLSPEC_HIDDEN;
+MAKE_FUNCPTR(XFixesQueryExtension)
+MAKE_FUNCPTR(XFixesQueryVersion)
+MAKE_FUNCPTR(XFixesCreateRegion)
+MAKE_FUNCPTR(XFixesDestroyRegion)
+#undef MAKE_FUNCPTR
+
+#endif /* defined(SONAME_LIBXFIXES) */
+#endif /* __WINE_XFIXES_H */
diff --git a/dlls/winex11.drv/xrender.c b/dlls/winex11.drv/xrender.c
index ca2d3da..e946611 100644
--- a/dlls/winex11.drv/xrender.c
+++ b/dlls/winex11.drv/xrender.c
@@ -2292,6 +2292,7 @@ static const struct gdi_dc_funcs xrender_funcs =
NULL, /* pUnrealizePalette */
NULL, /* pWidenPath */
NULL, /* wine_get_wgl_driver */
+ NULL, /* wine_get_d3dadapter_driver */
GDI_PRIORITY_GRAPHICS_DRV + 10 /* priority */
};
diff --git a/include/config.h.in b/include/config.h.in
index a58c0b5..922b75f 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -1113,6 +1113,9 @@
/* Define to 1 if you have the <X11/extensions/xf86vmproto.h> header file. */
#undef HAVE_X11_EXTENSIONS_XF86VMPROTO_H
+/* Define to 1 if you have the <X11/extensions/Xfixes.h> header file. */
+#undef HAVE_X11_EXTENSIONS_XFIXES_H
+
/* Define to 1 if you have the <X11/extensions/Xinerama.h> header file. */
#undef HAVE_X11_EXTENSIONS_XINERAMA_H
@@ -1254,6 +1257,9 @@
/* Define to the soname of the libcurses library. */
#undef SONAME_LIBCURSES
+/* Define to the soname of the libd3dadapter9 library. */
+#undef SONAME_LIBD3DADAPTER9
+
/* Define to the soname of the libdbus-1 library. */
#undef SONAME_LIBDBUS_1
@@ -1317,6 +1323,9 @@
/* Define to the soname of the libXext library. */
#undef SONAME_LIBXEXT
+/* Define to the soname of the libXfixes library. */
+#undef SONAME_LIBXFIXES
+
/* Define to the soname of the libXi library. */
#undef SONAME_LIBXI
diff --git a/include/wine/d3dadapter.h b/include/wine/d3dadapter.h
new file mode 100644
index 0000000..126dd58
--- /dev/null
+++ b/include/wine/d3dadapter.h
@@ -0,0 +1,42 @@
+/*
+ * d3dadapter display driver definitions
+ *
+ * Copyright (c) 2013 Joakim Sindholt
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __WINE_D3DADAPTER_H
+#define __WINE_D3DADAPTER_H
+
+#ifndef __WINE_CONFIG_H
+# error You must include config.h to use this header
+#endif
+
+#ifdef SONAME_LIBD3DADAPTER9
+
+#include <d3dadapter/d3dadapter9.h>
+
+#define WINE_D3DADAPTER_DRIVER_VERSION 0
+
+struct d3dadapter_funcs
+{
+ HRESULT (*create_present_group)(const WCHAR *device_name, UINT adapter, HWND focus, D3DPRESENT_PARAMETERS *params, unsigned nparams, ID3DPresentGroup **group);
+ HRESULT (*create_adapter9)(HDC hdc, ID3DAdapter9 **adapter);
+};
+
+#endif /* SONAME_LIBD3DADAPTER9 */
+
+#endif /* __WINE_D3DADAPTER_H */
diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h
index 06e4caa..d5ed856 100644
--- a/include/wine/gdi_driver.h
+++ b/include/wine/gdi_driver.h
@@ -25,6 +25,7 @@
struct gdi_dc_funcs;
struct opengl_funcs;
+struct d3dadapter_funcs;
typedef struct gdi_physdev
{
@@ -191,6 +192,7 @@ struct gdi_dc_funcs
BOOL (*pUnrealizePalette)(HPALETTE);
BOOL (*pWidenPath)(PHYSDEV);
struct opengl_funcs * (*wine_get_wgl_driver)(PHYSDEV,UINT);
+ struct d3dadapter_funcs * (*wine_get_d3dadapter_driver)(PHYSDEV,UINT);
/* priority order for the driver on the stack */
UINT priority;
@@ -278,5 +280,6 @@ extern void CDECL __wine_set_visible_region( HDC hdc, HRGN hrgn, const RECT *vis
const RECT *device_rect, struct window_surface *surface );
extern void CDECL __wine_set_display_driver( HMODULE module );
extern struct opengl_funcs * CDECL __wine_get_wgl_driver( HDC hdc, UINT version );
+extern struct d3dadapter_funcs * CDECL __wine_get_d3dadapter_driver( HDC hdc, UINT version );
#endif /* __WINE_WINE_GDI_DRIVER_H */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment