summaryrefslogtreecommitdiff
path: root/app-emulation/wine/files/wine-1.7.55-d3d9.patch
diff options
context:
space:
mode:
Diffstat (limited to 'app-emulation/wine/files/wine-1.7.55-d3d9.patch')
-rw-r--r--app-emulation/wine/files/wine-1.7.55-d3d9.patch5366
1 files changed, 0 insertions, 5366 deletions
diff --git a/app-emulation/wine/files/wine-1.7.55-d3d9.patch b/app-emulation/wine/files/wine-1.7.55-d3d9.patch
deleted file mode 100644
index 7497964b..00000000
--- a/app-emulation/wine/files/wine-1.7.55-d3d9.patch
+++ /dev/null
@@ -1,5366 +0,0 @@
-diff --git a/configure.ac b/configure.ac
-index 2d2a168..5f75a99 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -65,6 +65,8 @@ 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(d3dadapter-dri2-fallback, AS_HELP_STRING([--without-d3dadapter-dri2-fallback],[add a DRI2 fallback to d3dadapter DRI3 code]))
- 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]),
-@@ -381,6 +383,8 @@ AC_CHECK_LIB(ossaudio,_oss_ioctl)
-
- AC_SUBST(OPENGL_LIBS,"")
-
-+AC_SUBST(D3DADAPTER9_LIBS,"")
-+
- dnl **** Check for header files ****
-
- AC_SYS_LARGEFILE()
-@@ -1156,6 +1160,45 @@ 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 d3dadapter
-+ if test "x$with_d3dadapter" != "xno"
-+ then
-+ D3D_CFLAGS=`pkg-config --cflags d3d`
-+ D3D_LIBS=`pkg-config --libs d3d`
-+ AC_SUBST(D3D_CFLAGS)
-+ AC_SUBST(D3D_LIBS)
-+ AC_DEFINE(SONAME_D3DADAPTER9, ["d3dadapter9.so.1"], ["temporary hack"])
-+ AC_DEFINE_UNQUOTED(D3D_MODULE_DIR, ["`pkg-config --variable=moduledir d3d`"], ["module dir"])
-+ D3DADAPTER9_LIBS=""
-+ WINE_CHECK_SONAME(xcb,xcb_request_check, [D3DADAPTER9_LIBS="-lxcb $D3DADAPTER9_LIBS"])
-+ WINE_ERROR_WITH(d3dadapter,[test "x$D3DADAPTER9_LIBS" != "x-lxcb "],[D3Dadapter9 requires libxcb])
-+ WINE_CHECK_SONAME(xcb-dri3,xcb_dri3_open, [D3DADAPTER9_LIBS="-lxcb-dri3 $D3DADAPTER9_LIBS"])
-+ WINE_ERROR_WITH(d3dadapter,[test "x$D3DADAPTER9_LIBS" != "x-lxcb-dri3 -lxcb "],[D3Dadapter9 requires libxcb-dri3])
-+ WINE_CHECK_SONAME(xcb-present,xcb_present_notify_msc, [D3DADAPTER9_LIBS="-lxcb-present $D3DADAPTER9_LIBS"])
-+ WINE_ERROR_WITH(d3dadapter,[test "x$D3DADAPTER9_LIBS" != "x-lxcb-present -lxcb-dri3 -lxcb "],[D3Dadapter9 requires libxcb-present])
-+ WINE_CHECK_SONAME(X11-xcb,XGetXCBConnection, [D3DADAPTER9_LIBS="-lX11-xcb $D3DADAPTER9_LIBS"])
-+ WINE_ERROR_WITH(d3dadapter,[test "x$D3DADAPTER9_LIBS" != "x-lX11-xcb -lxcb-present -lxcb-dri3 -lxcb "],[D3Dadapter9 requires libX11-xcb])
-+ WINE_CHECK_SONAME(xcb-xfixes,xcb_xfixes_create_region, [D3DADAPTER9_LIBS="-lxcb-xfixes $D3DADAPTER9_LIBS"])
-+ WINE_ERROR_WITH(d3dadapter,[test "x$D3DADAPTER9_LIBS" != "x-lxcb-xfixes -lX11-xcb -lxcb-present -lxcb-dri3 -lxcb "],[D3Dadapter9 requires libxcb-xfixes])
-+ WINE_CHECK_SONAME(X11,XOpenDisplay, [D3DADAPTER9_LIBS="-lX11 $D3DADAPTER9_LIBS"])
-+ WINE_ERROR_WITH(d3dadapter,[test "x$D3DADAPTER9_LIBS" != "x-lX11 -lxcb-xfixes -lX11-xcb -lxcb-present -lxcb-dri3 -lxcb "],[D3Dadapter9 requires libX11])
-+ WINE_CHECK_SONAME(Xext,XextRemoveDisplay, [D3DADAPTER9_LIBS="-lXext $D3DADAPTER9_LIBS"])
-+ WINE_ERROR_WITH(d3dadapter,[test "x$D3DADAPTER9_LIBS" != "x-lXext -lX11 -lxcb-xfixes -lX11-xcb -lxcb-present -lxcb-dri3 -lxcb "],[D3Dadapter9 requires libXext])
-+ WINE_CHECK_SONAME(pthread,pthread_mutex_lock, [D3DADAPTER9_LIBS="-lpthread $D3DADAPTER9_LIBS"])
-+ WINE_ERROR_WITH(d3dadapter,[test "x$D3DADAPTER9_LIBS" != "x-lpthread -lXext -lX11 -lxcb-xfixes -lX11-xcb -lxcb-present -lxcb-dri3 -lxcb "],[D3Dadapter9 requires libpthread])
-+
-+ if test "x$with_d3dadapter_dri2_fallback" != "xno"
-+ then
-+ AC_DEFINE(D3DADAPTER9_DRI2, 1, [Whether d3dadapter9 DRI2 fallback is compiled])
-+ WINE_CHECK_SONAME(GL,glGenFramebuffers, [D3DADAPTER9_LIBS="-lGL $D3DADAPTER9_LIBS"])
-+ WINE_ERROR_WITH(d3dadapter,[test "x$D3DADAPTER9_LIBS" != "x-lGL -lpthread -lXext -lX11 -lxcb-xfixes -lX11-xcb -lxcb-present -lxcb-dri3 -lxcb "],[D3Dadapter9 DRI2 fallback requires libGL])
-+ WINE_CHECK_SONAME(EGL,eglCreateContext, [D3DADAPTER9_LIBS="-lEGL $D3DADAPTER9_LIBS"])
-+ WINE_ERROR_WITH(d3dadapter,[test "x$D3DADAPTER9_LIBS" != "x-lEGL -lGL -lpthread -lXext -lX11 -lxcb-xfixes -lX11-xcb -lxcb-present -lxcb-dri3 -lxcb "],[D3Dadapter9 DRI2 fallback requires libEGL])
-+ fi
-+ fi
-+
- CPPFLAGS="$ac_save_CPPFLAGS"
- else
- X_CFLAGS=""
-@@ -2764,6 +2807,7 @@ WINE_CONFIG_DLL(d3d8,,[implib])
- WINE_CONFIG_TEST(dlls/d3d8/tests)
- WINE_CONFIG_DLL(d3d9,,[implib])
- WINE_CONFIG_TEST(dlls/d3d9/tests)
-+WINE_CONFIG_DLL(d3d9-nine,,[implib])
- WINE_CONFIG_DLL(d3dcompiler_33)
- WINE_CONFIG_DLL(d3dcompiler_34)
- WINE_CONFIG_DLL(d3dcompiler_35)
-diff --git a/dlls/d3d9-nine/Makefile.in b/dlls/d3d9-nine/Makefile.in
-new file mode 100644
-index 0000000..a761cd7
---- /dev/null
-+++ b/dlls/d3d9-nine/Makefile.in
-@@ -0,0 +1,12 @@
-+MODULE = d3d9-nine.dll
-+IMPORTS = dxguid uuid advapi32 gdi32 user32
-+EXTRAINCL = $(X_CFLAGS)
-+EXTRALIBS = $(D3DADAPTER9_LIBS)
-+
-+C_SRCS = \
-+ d3d9_main.c \
-+ d3dadapter9.c \
-+ present.c \
-+ dri3.c
-+
-+RC_SRCS = version.rc
-diff --git a/dlls/d3d9-nine/d3d9-nine.spec b/dlls/d3d9-nine/d3d9-nine.spec
-new file mode 100644
-index 0000000..a33cba5
---- /dev/null
-+++ b/dlls/d3d9-nine/d3d9-nine.spec
-@@ -0,0 +1,14 @@
-+@ stdcall Direct3DShaderValidatorCreate9()
-+@ stub PSGPError
-+@ stub PSGPSampleTexture
-+@ stdcall D3DPERF_BeginEvent(long wstr)
-+@ stdcall D3DPERF_EndEvent()
-+@ stdcall D3DPERF_GetStatus()
-+@ stdcall D3DPERF_QueryRepeatFrame()
-+@ stdcall D3DPERF_SetMarker(long wstr)
-+@ stdcall D3DPERF_SetOptions(long)
-+@ stdcall D3DPERF_SetRegion(long wstr)
-+@ stub DebugSetLevel
-+@ stdcall DebugSetMute()
-+@ stdcall Direct3DCreate9(long)
-+@ stdcall Direct3DCreate9Ex(long ptr)
-diff --git a/dlls/d3d9-nine/d3d9_main.c b/dlls/d3d9-nine/d3d9_main.c
-new file mode 100644
-index 0000000..de20475
---- /dev/null
-+++ b/dlls/d3d9-nine/d3d9_main.c
-@@ -0,0 +1,163 @@
-+/*
-+ * Direct3D 9
-+ *
-+ * Copyright 2002-2003 Jason Edmeades
-+ * Copyright 2002-2003 Raphael Junqueira
-+ * Copyright 2005 Oliver Stieber
-+ * Copyright 2015 Patrick Rudolph
-+ *
-+ * 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 "initguid.h"
-+#include "wine/debug.h"
-+
-+#include <dlfcn.h>
-+#include <fcntl.h>
-+#include <stdarg.h>
-+#include <stdio.h>
-+#include <stdlib.h>
-+
-+#include <d3dadapter/d3dadapter9.h>
-+
-+#include "d3dadapter9.h"
-+
-+#include "wine/library.h"
-+
-+WINE_DEFAULT_DEBUG_CHANNEL(d3dadapter);
-+
-+static int D3DPERF_event_level = 0;
-+static Display *gdi_display;
-+
-+void WINAPI DebugSetMute(void) {
-+ /* nothing to do */
-+}
-+
-+IDirect3D9 * WINAPI DECLSPEC_HOTPATCH Direct3DCreate9(UINT sdk_version)
-+{
-+ IDirect3D9 *native;
-+ TRACE("sdk_version %#x.\n", sdk_version);
-+
-+ if (SUCCEEDED(d3dadapter9_new(gdi_display, FALSE, (IDirect3D9Ex **)&native))) {
-+ return native;
-+ }
-+
-+ return NULL;
-+}
-+
-+HRESULT WINAPI DECLSPEC_HOTPATCH Direct3DCreate9Ex(UINT sdk_version, IDirect3D9Ex **d3d9ex)
-+{
-+ TRACE("sdk_version %#x, d3d9ex %p.\n", sdk_version, d3d9ex);
-+
-+ return d3dadapter9_new(gdi_display, TRUE, d3d9ex);
-+}
-+
-+/*******************************************************************
-+ * Direct3DShaderValidatorCreate9 (D3D9.@)
-+ *
-+ * No documentation available for this function.
-+ * SDK only says it is internal and shouldn't be used.
-+ */
-+void* WINAPI Direct3DShaderValidatorCreate9(void)
-+{
-+ static int once;
-+
-+ if (!once++) FIXME("stub\n");
-+ return NULL;
-+}
-+
-+/*******************************************************************
-+ * DllMain
-+ */
-+BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, void *reserved)
-+{
-+ switch (reason)
-+ {
-+ case DLL_PROCESS_ATTACH:
-+ if (!(gdi_display = XOpenDisplay( NULL ))) {
-+ ERR("Failed to open display\n");
-+ return FALSE;
-+ }
-+
-+ fcntl( ConnectionNumber(gdi_display), F_SETFD, 1 ); /* set close on exec flag */
-+ break;
-+ }
-+
-+ return TRUE;
-+}
-+
-+/***********************************************************************
-+ * D3DPERF_BeginEvent (D3D9.@)
-+ */
-+int WINAPI D3DPERF_BeginEvent(D3DCOLOR color, const WCHAR *name)
-+{
-+ TRACE("color 0x%08x, name %s.\n", color, debugstr_w(name));
-+
-+ return D3DPERF_event_level++;
-+}
-+
-+/***********************************************************************
-+ * D3DPERF_EndEvent (D3D9.@)
-+ */
-+int WINAPI D3DPERF_EndEvent(void) {
-+ TRACE("(void) : stub\n");
-+
-+ return --D3DPERF_event_level;
-+}
-+
-+/***********************************************************************
-+ * D3DPERF_GetStatus (D3D9.@)
-+ */
-+DWORD WINAPI D3DPERF_GetStatus(void) {
-+ FIXME("(void) : stub\n");
-+
-+ return 0;
-+}
-+
-+/***********************************************************************
-+ * D3DPERF_SetOptions (D3D9.@)
-+ *
-+ */
-+void WINAPI D3DPERF_SetOptions(DWORD options)
-+{
-+ FIXME("(%#x) : stub\n", options);
-+}
-+
-+/***********************************************************************
-+ * D3DPERF_QueryRepeatFrame (D3D9.@)
-+ */
-+BOOL WINAPI D3DPERF_QueryRepeatFrame(void) {
-+ FIXME("(void) : stub\n");
-+
-+ return FALSE;
-+}
-+
-+/***********************************************************************
-+ * D3DPERF_SetMarker (D3D9.@)
-+ */
-+void WINAPI D3DPERF_SetMarker(D3DCOLOR color, const WCHAR *name)
-+{
-+ FIXME("color 0x%08x, name %s stub!\n", color, debugstr_w(name));
-+}
-+
-+/***********************************************************************
-+ * D3DPERF_SetRegion (D3D9.@)
-+ */
-+void WINAPI D3DPERF_SetRegion(D3DCOLOR color, const WCHAR *name)
-+{
-+ FIXME("color 0x%08x, name %s stub!\n", color, debugstr_w(name));
-+}
-diff --git a/dlls/d3d9-nine/d3dadapter9.c b/dlls/d3d9-nine/d3dadapter9.c
-new file mode 100644
-index 0000000..f15e44f
---- /dev/null
-+++ b/dlls/d3d9-nine/d3dadapter9.c
-@@ -0,0 +1,865 @@
-+/*
-+ * Wine IDirect3D9 interface using ID3DAdapter9
-+ *
-+ * Copyright 2013 Joakim Sindholt
-+ * Christoph Bumiller
-+ * Copyright 2014 David Heidelberger
-+ * Copyright 2014-2015 Axel Davy
-+ * Copyright 2015 Nick Sarnie
-+ * Patrick Rudolph
-+ *
-+ * 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(d3dadapter);
-+
-+#include <d3dadapter/d3dadapter9.h>
-+#include "present.h"
-+
-+/* 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;
-+
-+ /* true if it implements IDirect3D9Ex */
-+ boolean ex;
-+ Display *gdi_display;
-+};
-+
-+/* 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);
-+ }
-+
-+ 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) && (size == sizeof(DWORD)))
-+ pIdentifier->DeviceId = data;
-+ if(size != sizeof(DWORD)) {
-+ ERR("VideoPciDeviceID is not a DWORD\n");
-+ size = sizeof(DWORD);
-+ }
-+ if (!RegQueryValueExA(regkey, "VideoPciVendorID", 0, &type, (BYTE *)&data, &size) && (type == REG_DWORD) && (size == sizeof(DWORD)))
-+ pIdentifier->VendorId = data;
-+ if(size != sizeof(DWORD))
-+ ERR("VideoPciVendorID is not a DWORD\n");
-+ 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_CreateDeviceEx( struct d3dadapter9 *This,
-+ UINT Adapter,
-+ D3DDEVTYPE DeviceType,
-+ HWND hFocusWindow,
-+ DWORD BehaviorFlags,
-+ D3DPRESENT_PARAMETERS *pPresentationParameters,
-+ D3DDISPLAYMODEEX *pFullscreenDisplayMode,
-+ IDirect3DDevice9Ex **ppReturnedDeviceInterface );
-+
-+static HRESULT WINAPI
-+d3dadapter9_CreateDevice( struct d3dadapter9 *This,
-+ UINT Adapter,
-+ D3DDEVTYPE DeviceType,
-+ HWND hFocusWindow,
-+ DWORD BehaviorFlags,
-+ D3DPRESENT_PARAMETERS *pPresentationParameters,
-+ IDirect3DDevice9 **ppReturnedDeviceInterface )
-+{
-+ HRESULT hr;
-+ hr = d3dadapter9_CreateDeviceEx(This, Adapter, DeviceType, hFocusWindow,
-+ BehaviorFlags, pPresentationParameters,
-+ NULL,
-+ (IDirect3DDevice9Ex **)ppReturnedDeviceInterface);
-+ if (FAILED(hr))
-+ return hr;
-+ return D3D_OK;
-+}
-+
-+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 )
-+{
-+ ID3DPresentGroup *present;
-+ HRESULT hr;
-+ boolean no_window_changes;
-+
-+ 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;
-+ }
-+ no_window_changes = !!(BehaviorFlags & D3DCREATE_NOWINDOWCHANGES);
-+
-+ hr = present_create_present_group(This->gdi_display, group->devname, ordinal,
-+ hFocusWindow,
-+ pPresentationParameters,
-+ nparams, &present, This->ex, no_window_changes);
-+ }
-+
-+ if (FAILED(hr)) {
-+ WARN("Failed to create PresentGroup.\n");
-+ return hr;
-+ }
-+
-+ if (This->ex) {
-+ hr = ADAPTER_PROC(CreateDeviceEx, Adapter, DeviceType, hFocusWindow,
-+ BehaviorFlags, pPresentationParameters,
-+ pFullscreenDisplayMode,
-+ (IDirect3D9Ex *)This, present,
-+ ppReturnedDeviceInterface);
-+ } else { /* CreateDevice on non-ex */
-+ hr = ADAPTER_PROC(CreateDevice, Adapter, DeviceType, hFocusWindow,
-+ BehaviorFlags, pPresentationParameters,
-+ (IDirect3D9 *)This, present,
-+ (IDirect3DDevice9 **)ppReturnedDeviceInterface);
-+ }
-+ if (FAILED(hr)) {
-+ WARN("ADAPTER_PROC failed.\n");
-+ ID3DPresentGroup_Release(present);
-+ }
-+
-+ return hr;
-+}
-+
-+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 = present_create_adapter9(This->gdi_display, 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
-+};
-+
-+HRESULT
-+d3dadapter9_new( Display *gdi_display,
-+ 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;
-+ This->gdi_display = gdi_display;
-+
-+ if (!has_d3dadapter(gdi_display)) {
-+ ERR("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) {
-+ ERR("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;
-+ FIXME("\033[1;32m\nNative Direct3D 9 is active."
-+ "\nFor more information visit https://wiki.ixit.cz/d3d9\033[0m\n");
-+ return D3D_OK;
-+}
-diff --git a/dlls/d3d9-nine/d3dadapter9.h b/dlls/d3d9-nine/d3dadapter9.h
-new file mode 100644
-index 0000000..2fafdf2
---- /dev/null
-+++ b/dlls/d3d9-nine/d3dadapter9.h
-@@ -0,0 +1,30 @@
-+/*
-+ * D3DAdapter9 interface
-+ *
-+ * Copyright 2015 Patrick Rudolph
-+ *
-+ * 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_D3D9ADAPTER_H
-+#define __WINE_D3D9ADAPTER_H
-+
-+#include <X11/Xlib.h>
-+
-+void d3dadapter9_init(HINSTANCE hinst);
-+void d3dadapter9_destroy(HINSTANCE hinst);
-+HRESULT d3dadapter9_new(Display *gdi_display, boolean ex, IDirect3D9Ex **ppOut);
-+
-+#endif /* __WINE_D3D9ADAPTER_H */
-diff --git a/dlls/d3d9-nine/dri3.c b/dlls/d3d9-nine/dri3.c
-new file mode 100644
-index 0000000..d147b23
---- /dev/null
-+++ b/dlls/d3d9-nine/dri3.c
-@@ -0,0 +1,1344 @@
-+/*
-+ * Wine DRI3 interface
-+ *
-+ * Copyright 2014-2015 Axel Davy
-+ * Copyright 2015 Patrick Rudolph
-+ *
-+ * 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(d3dadapter);
-+
-+#include <d3dadapter/d3dadapter9.h>
-+#include <stdlib.h>
-+#include <fcntl.h>
-+#include <pthread.h>
-+
-+#include "dri3.h"
-+#include "winbase.h" /* for Sleep */
-+
-+#ifdef D3DADAPTER9_DRI2
-+#include <unistd.h>
-+#include <sys/ioctl.h>
-+#include <stdio.h>
-+#include <string.h>
-+
-+#define BOOL X_BOOL
-+#define BYTE X_BYTE
-+#define INT8 X_INT8
-+#define INT16 X_INT16
-+#define INT32 X_INT32
-+#define INT64 X_INT64
-+#include <X11/Xmd.h>
-+#include <X11/Xproto.h>
-+#undef BOOL
-+#undef BYTE
-+#undef INT8
-+#undef INT16
-+#undef INT32
-+#undef INT64
-+#undef LONG64
-+
-+#include <X11/Xlibint.h>
-+#include <X11/extensions/dri2tokens.h>
-+#include <X11/extensions/dri2proto.h>
-+#include <X11/extensions/extutil.h>
-+#define GL_GLEXT_PROTOTYPES 1
-+#define EGL_EGLEXT_PROTOTYPES 1
-+#define GL_GLEXT_LEGACY 1
-+#include <GL/gl.h>
-+/* workaround gl header bug */
-+#define glBlendColor glBlendColorLEV
-+#define glBlendEquation glBlendEquationLEV
-+#include <GL/glext.h>
-+#include <EGL/egl.h>
-+#include <EGL/eglext.h>
-+#include <libdrm/drm_fourcc.h>
-+#include <libdrm/drm.h>
-+/*GLAPI void GLAPIENTRY glFlush( void );
-+
-+GLAPI void APIENTRY glGenFramebuffers (GLsizei n, GLuint *framebuffers);
-+GLAPI void APIENTRY glBindFramebufferEXT (GLenum target, GLuint framebuffer);
-+GLAPI void APIENTRY glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
-+GLAPI void APIENTRY glFramebufferTexture2DEXT (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
-+GLAPI void APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
-+GLAPI void APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
-+GLAPI void APIENTRY glDeleteTexturesEXT (GLsizei n, const GLuint *textures);
-+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR (EGLDisplay dpy, EGLImageKHR image);*/
-+
-+typedef void (APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
-+typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
-+typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYEXTPROC) (EGLenum platform, void *native_display, const EGLint *attrib_list);
-+
-+#endif
-+
-+BOOL
-+DRI3CheckExtension(Display *dpy, int major, int minor)
-+{
-+ xcb_connection_t *xcb_connection = XGetXCBConnection(dpy);
-+ xcb_dri3_query_version_cookie_t dri3_cookie;
-+ xcb_dri3_query_version_reply_t *dri3_reply;
-+ xcb_generic_error_t *error;
-+ const xcb_query_extension_reply_t *extension;
-+ int fd;
-+
-+ xcb_prefetch_extension_data(xcb_connection, &xcb_dri3_id);
-+
-+ extension = xcb_get_extension_data(xcb_connection, &xcb_dri3_id);
-+ if (!(extension && extension->present)) {
-+ ERR("DRI3 extension is not present\n");
-+ return FALSE;
-+ }
-+
-+ dri3_cookie = xcb_dri3_query_version(xcb_connection, major, minor);
-+
-+ dri3_reply = xcb_dri3_query_version_reply(xcb_connection, dri3_cookie, &error);
-+ if (!dri3_reply) {
-+ free(error);
-+ ERR("Issue getting requested version of DRI3: %d,%d\n", major, minor);
-+ return FALSE;
-+ }
-+
-+ if (!DRI3Open(dpy, DefaultScreen(dpy), &fd)) {
-+ ERR("DRI3 advertised, but not working\n");
-+ return FALSE;
-+ }
-+ close(fd);
-+
-+ TRACE("DRI3 version %d,%d found. %d %d requested\n", major, minor, (int)dri3_reply->major_version, (int)dri3_reply->minor_version);
-+ free(dri3_reply);
-+
-+ return TRUE;
-+}
-+
-+#ifdef D3DADAPTER9_DRI2
-+
-+struct DRI2priv {
-+ Display *dpy;
-+ EGLDisplay display;
-+ EGLContext context;
-+ PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES_func;
-+ PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR_func;
-+ PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR_func;
-+};
-+
-+/* TODO: We don't free memory properly. When exiting, eglTerminate doesn't work well(crash), and things are freed automatically. Rely on it */
-+
-+BOOL
-+DRI2FallbackInit(Display *dpy, struct DRI2priv **priv)
-+{
-+ PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES_func;
-+ PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR_func;
-+ PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT_func;
-+ PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR_func;
-+ EGLDisplay display;
-+ EGLint major, minor;
-+ EGLConfig config;
-+ EGLContext context;
-+ EGLint i;
-+ EGLBoolean b;
-+ EGLenum current_api = 0;
-+ const char *extensions;
-+ EGLint config_attribs[] = {
-+ EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
-+ EGL_NONE
-+ };
-+ EGLint context_compatibility_attribs[] = {
-+ EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR,
-+ EGL_NONE
-+ };
-+
-+ current_api = eglQueryAPI();
-+ eglGetPlatformDisplayEXT_func = (PFNEGLGETPLATFORMDISPLAYEXTPROC) eglGetProcAddress("eglGetPlatformDisplayEXT");
-+ if (!eglGetPlatformDisplayEXT_func)
-+ return FALSE;
-+ display = eglGetPlatformDisplayEXT_func(EGL_PLATFORM_X11_EXT, dpy, NULL);
-+ if (!display)
-+ return FALSE;
-+ if (eglInitialize(display, &major, &minor) != EGL_TRUE)
-+ goto clean_egl_display;
-+
-+ extensions = eglQueryString(display, EGL_CLIENT_APIS);
-+ if (!extensions || !strstr(extensions, "OpenGL"))
-+ goto clean_egl_display;
-+
-+ extensions = eglQueryString(display, EGL_EXTENSIONS);
-+ if (!extensions || !strstr(extensions, "EGL_EXT_image_dma_buf_import") ||
-+ !strstr(extensions, "EGL_KHR_create_context") ||
-+ !strstr(extensions, "EGL_KHR_surfaceless_context") ||
-+ !strstr(extensions, "EGL_KHR_image_base"))
-+ goto clean_egl_display;
-+
-+ if (!eglChooseConfig(display, config_attribs, &config, 1, &i))
-+ goto clean_egl_display;
-+
-+ b = eglBindAPI(EGL_OPENGL_API);
-+ if (b == EGL_FALSE)
-+ goto clean_egl_display;
-+ context = eglCreateContext(display, config, EGL_NO_CONTEXT, context_compatibility_attribs);
-+ if (context == EGL_NO_CONTEXT)
-+ goto clean_egl_display;
-+
-+ glEGLImageTargetTexture2DOES_func = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) eglGetProcAddress("glEGLImageTargetTexture2DOES");
-+ eglCreateImageKHR_func = (PFNEGLCREATEIMAGEKHRPROC) eglGetProcAddress("eglCreateImageKHR");
-+ eglDestroyImageKHR_func = (PFNEGLDESTROYIMAGEKHRPROC) eglGetProcAddress("eglDestroyImageKHR");
-+ if (!eglCreateImageKHR_func || !glEGLImageTargetTexture2DOES_func || !eglDestroyImageKHR_func) {
-+ ERR("eglGetProcAddress failed !");
-+ goto clean_egl_display;
-+ }
-+
-+ eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-+
-+ *priv = calloc(1, sizeof(struct DRI2priv));
-+ if (!*priv)
-+ goto clean_egl;
-+ (*priv)->dpy = dpy;
-+ (*priv)->display = display;
-+ (*priv)->context = context;
-+ (*priv)->glEGLImageTargetTexture2DOES_func = glEGLImageTargetTexture2DOES_func;
-+ (*priv)->eglCreateImageKHR_func = eglCreateImageKHR_func;
-+ (*priv)->eglDestroyImageKHR_func = eglDestroyImageKHR_func;
-+ eglBindAPI(current_api);
-+ return TRUE;
-+
-+clean_egl:
-+clean_egl_display:
-+ eglTerminate(display);
-+ eglBindAPI(current_api);
-+ return FALSE;
-+}
-+
-+/* hypothesis: at this step all textures, etc are destroyed */
-+void
-+DRI2FallbackDestroy(struct DRI2priv *priv)
-+{
-+ EGLenum current_api;
-+ current_api = eglQueryAPI();
-+ eglBindAPI(EGL_OPENGL_API);
-+ eglMakeCurrent(priv->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-+ eglDestroyContext(priv->display, priv->context);
-+ eglTerminate(priv->display);
-+ eglBindAPI(current_api);
-+ free(priv);
-+}
-+
-+BOOL
-+DRI2FallbackCheckSupport(Display *dpy)
-+{
-+ struct DRI2priv *priv;
-+ int fd;
-+ if (!DRI2FallbackInit(dpy, &priv))
-+ return FALSE;
-+ DRI2FallbackDestroy(priv);
-+ if (!DRI2FallbackOpen(dpy, DefaultScreen(dpy), &fd))
-+ return FALSE;
-+ close(fd);
-+ return TRUE;
-+}
-+
-+#endif
-+
-+BOOL
-+PRESENTCheckExtension(Display *dpy, int major, int minor)
-+{
-+ xcb_connection_t *xcb_connection = XGetXCBConnection(dpy);
-+ xcb_present_query_version_cookie_t present_cookie;
-+ xcb_present_query_version_reply_t *present_reply;
-+ xcb_generic_error_t *error;
-+ const xcb_query_extension_reply_t *extension;
-+
-+ xcb_prefetch_extension_data(xcb_connection, &xcb_present_id);
-+
-+ extension = xcb_get_extension_data(xcb_connection, &xcb_present_id);
-+ if (!(extension && extension->present)) {
-+ ERR("PRESENT extension is not present\n");
-+ return FALSE;
-+ }
-+
-+ present_cookie = xcb_present_query_version(xcb_connection, major, minor);
-+
-+ present_reply = xcb_present_query_version_reply(xcb_connection, present_cookie, &error);
-+ if (!present_reply) {
-+ free(error);
-+ ERR("Issue getting requested version of PRESENT: %d,%d\n", major, minor);
-+ return FALSE;
-+ }
-+
-+ TRACE("PRESENT version %d,%d found. %d %d requested\n", major, minor, (int)present_reply->major_version, (int)present_reply->minor_version);
-+ free(present_reply);
-+
-+ return TRUE;
-+}
-+
-+BOOL
-+DRI3Open(Display *dpy, int screen, int *device_fd)
-+{
-+ xcb_dri3_open_cookie_t cookie;
-+ xcb_dri3_open_reply_t *reply;
-+ xcb_connection_t *xcb_connection = XGetXCBConnection(dpy);
-+ int fd;
-+ Window root = RootWindow(dpy, screen);
-+
-+ cookie = xcb_dri3_open(xcb_connection, root, 0);
-+
-+ reply = xcb_dri3_open_reply(xcb_connection, cookie, NULL);
-+ if (!reply)
-+ return FALSE;
-+
-+ if (reply->nfd != 1) {
-+ free(reply);
-+ return FALSE;
-+ }
-+
-+ fd = xcb_dri3_open_reply_fds(xcb_connection, reply)[0];
-+ fcntl(fd, F_SETFD, FD_CLOEXEC);
-+
-+ *device_fd = fd;
-+ free(reply);
-+
-+ return TRUE;
-+}
-+
-+#ifdef D3DADAPTER9_DRI2
-+
-+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;
-+}
-+
-+#define XALIGN(x) (((x) + 3) & (~3))
-+
-+static BOOL
-+DRI2Connect(Display *dpy,
-+ XID window,
-+ unsigned driver_type,
-+ char **device )
-+{
-+ XExtDisplayInfo *info = find_display(dpy);
-+ xDRI2ConnectReply rep;
-+ xDRI2ConnectReq *req;
-+ int dev_len, driv_len;
-+ char *driver;
-+
-+ 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);
-+ HeapFree(GetProcessHeap(), 0, driver); /* we don't need the driver */
-+
-+ /* read out device */
-+ *device = HeapAlloc(GetProcessHeap(), 0, dev_len + 1);
-+ if (!*device) {
-+ _XEatData(dpy, XALIGN(dev_len));
-+ UnlockDisplay(dpy);
-+ SyncHandle();
-+ return False;
-+ }
-+ _XReadPad(dpy, *device, dev_len);
-+ (*device)[dev_len] = '\0';
-+
-+ UnlockDisplay(dpy);
-+ SyncHandle();
-+
-+ return True;
-+}
-+
-+static 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;
-+}
-+
-+BOOL
-+DRI2FallbackOpen(Display *dpy, int screen, int *device_fd)
-+{
-+ char *device;
-+ int fd;
-+ Window root = RootWindow(dpy, screen);
-+ drm_auth_t auth;
-+
-+ if (!DRI2Connect(dpy, root, DRI2DriverDRI, &device))
-+ return FALSE;
-+
-+ fd = open(device, O_RDWR);
-+ HeapFree(GetProcessHeap(), 0, device);
-+ if (fd < 0)
-+ return FALSE;
-+
-+ if (ioctl(fd, DRM_IOCTL_GET_MAGIC, &auth) != 0) {
-+ close(fd);
-+ return FALSE;
-+ }
-+
-+ if (!DRI2Authenticate(dpy, root, auth.magic)) {
-+ close(fd);
-+ return FALSE;
-+ }
-+
-+ *device_fd = fd;
-+
-+ return TRUE;
-+}
-+
-+#endif
-+
-+
-+BOOL
-+DRI3PixmapFromDmaBuf(Display *dpy, int screen, int fd, int width, int height, int stride, int depth, int bpp, Pixmap *pixmap)
-+{
-+ xcb_connection_t *xcb_connection = XGetXCBConnection(dpy);
-+ Window root = RootWindow(dpy, screen);
-+ xcb_void_cookie_t cookie;
-+ xcb_generic_error_t *error;
-+
-+ cookie = xcb_dri3_pixmap_from_buffer_checked(xcb_connection,
-+ (*pixmap = xcb_generate_id(xcb_connection)),
-+ root,
-+ 0,
-+ width, height, stride,
-+ depth, bpp, fd);
-+ error = xcb_request_check(xcb_connection, cookie); /* performs a flush */
-+ if (error) {
-+ ERR("Error using DRI3 to convert a DmaBufFd to pixmap\n");
-+ return FALSE;
-+ }
-+ return TRUE;
-+}
-+
-+BOOL
-+DRI3DmaBufFromPixmap(Display *dpy, Pixmap pixmap, int *fd, int *width, int *height, int *stride, int *depth, int *bpp)
-+{
-+ xcb_connection_t *xcb_connection = XGetXCBConnection(dpy);
-+ xcb_dri3_buffer_from_pixmap_cookie_t bp_cookie;
-+ xcb_dri3_buffer_from_pixmap_reply_t *bp_reply;
-+
-+ bp_cookie = xcb_dri3_buffer_from_pixmap(xcb_connection, pixmap);
-+ bp_reply = xcb_dri3_buffer_from_pixmap_reply(xcb_connection, bp_cookie, NULL);
-+ if (!bp_reply)
-+ return FALSE;
-+ *fd = xcb_dri3_buffer_from_pixmap_reply_fds(xcb_connection, bp_reply)[0];
-+ *width = bp_reply->width;
-+ *height = bp_reply->height;
-+ *stride = bp_reply->stride;
-+ *depth = bp_reply->depth;
-+ *bpp = bp_reply->depth;
-+ return TRUE;
-+}
-+
-+struct PRESENTPriv {
-+ xcb_connection_t *xcb_connection;
-+ xcb_connection_t *xcb_connection_bis; /* to avoid libxcb thread bugs, use a different connection to present pixmaps */
-+ XID window;
-+ uint64_t last_msc;
-+ uint64_t last_target;
-+ uint32_t last_serial_given;
-+ xcb_special_event_t *special_event;
-+ PRESENTPixmapPriv *first_present_priv;
-+ int pixmap_present_pending;
-+ BOOL notify_with_serial_pending;
-+ pthread_mutex_t mutex_present; /* protect readind/writing present_priv things */
-+ pthread_mutex_t mutex_xcb_wait;
-+ BOOL xcb_wait;
-+};
-+
-+struct PRESENTPixmapPriv {
-+ PRESENTpriv *present_priv;
-+ Pixmap pixmap;
-+ BOOL released;
-+ unsigned int width;
-+ unsigned int height;
-+ unsigned int depth;
-+ BOOL present_complete_pending;
-+ uint32_t serial;
-+#ifdef D3DADAPTER9_DRI2
-+ struct {
-+ BOOL is_dri2;
-+ struct DRI2priv *dri2_priv;
-+ GLuint fbo_read;
-+ GLuint fbo_write;
-+ GLuint texture_read;
-+ GLuint texture_write;
-+ } dri2_info;
-+#endif
-+ BOOL last_present_was_flip;
-+ PRESENTPixmapPriv *next;
-+};
-+
-+static PRESENTPixmapPriv *PRESENTFindPixmapPriv(PRESENTpriv *present_priv, uint32_t serial)
-+{
-+ PRESENTPixmapPriv *current = present_priv->first_present_priv;
-+
-+ while (current) {
-+ if (current->serial == serial)
-+ return current;
-+ current = current->next;
-+ }
-+ return NULL;
-+}
-+
-+static void PRESENThandle_events(PRESENTpriv *present_priv, xcb_present_generic_event_t *ge)
-+{
-+ PRESENTPixmapPriv *present_pixmap_priv = NULL;
-+
-+ switch (ge->evtype) {
-+ case XCB_PRESENT_COMPLETE_NOTIFY: {
-+ xcb_present_complete_notify_event_t *ce = (void *) ge;
-+ if (ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC) {
-+ if (ce->serial)
-+ present_priv->notify_with_serial_pending = FALSE;
-+ free(ce);
-+ return;
-+ }
-+ present_pixmap_priv = PRESENTFindPixmapPriv(present_priv, ce->serial);
-+ if (!present_pixmap_priv || ce->kind != XCB_PRESENT_COMPLETE_KIND_PIXMAP) {
-+ ERR("FATAL ERROR: PRESENT handling failed\n");
-+ free(ce);
-+ return;
-+ }
-+ present_pixmap_priv->present_complete_pending = FALSE;
-+ switch (ce->mode) {
-+ case XCB_PRESENT_COMPLETE_MODE_FLIP:
-+ present_pixmap_priv->last_present_was_flip = TRUE;
-+ break;
-+ case XCB_PRESENT_COMPLETE_MODE_COPY:
-+ present_pixmap_priv->last_present_was_flip = FALSE;
-+ break;
-+ }
-+ present_priv->pixmap_present_pending--;
-+ present_priv->last_msc = ce->msc;
-+ break;
-+ }
-+ case XCB_PRESENT_EVENT_IDLE_NOTIFY: {
-+ xcb_present_idle_notify_event_t *ie = (void *) ge;
-+ present_pixmap_priv = PRESENTFindPixmapPriv(present_priv, ie->serial);
-+ if (!present_pixmap_priv || present_pixmap_priv->pixmap != ie->pixmap) {
-+ ERR("FATAL ERROR: PRESENT handling failed\n");
-+ free(ie);
-+ return;
-+ }
-+ present_pixmap_priv->released = TRUE;
-+ break;
-+ }
-+ }
-+ free(ge);
-+}
-+
-+static void PRESENTflush_events(PRESENTpriv *present_priv, BOOL assert_no_other_thread_waiting)
-+{
-+ xcb_generic_event_t *ev;
-+
-+ if ((present_priv->xcb_wait && !assert_no_other_thread_waiting) || /* don't steal events to someone waiting */
-+ !present_priv->special_event)
-+ return;
-+
-+ while ((ev = xcb_poll_for_special_event(present_priv->xcb_connection, present_priv->special_event)) != NULL) {
-+ PRESENThandle_events(present_priv, (void *) ev);
-+ }
-+}
-+
-+static BOOL PRESENTwait_events(PRESENTpriv *present_priv, BOOL allow_other_threads)
-+{
-+ xcb_generic_event_t *ev;
-+
-+ if (allow_other_threads) {
-+ present_priv->xcb_wait = TRUE;
-+ pthread_mutex_lock(&present_priv->mutex_xcb_wait);
-+ pthread_mutex_unlock(&present_priv->mutex_present);
-+ }
-+ ev = xcb_wait_for_special_event(present_priv->xcb_connection, present_priv->special_event);
-+ if (allow_other_threads) {
-+ pthread_mutex_unlock(&present_priv->mutex_xcb_wait);
-+ pthread_mutex_lock(&present_priv->mutex_present);
-+ present_priv->xcb_wait = FALSE;
-+ }
-+ if (!ev) {
-+ ERR("FATAL error: xcb had an error\n");
-+ return FALSE;
-+ }
-+
-+ PRESENThandle_events(present_priv, (void *) ev);
-+ return TRUE;
-+}
-+
-+static struct xcb_connection_t *
-+create_xcb_connection(Display *dpy)
-+{
-+ int screen_num = DefaultScreen(dpy);
-+ xcb_connection_t *ret;
-+ xcb_xfixes_query_version_cookie_t cookie;
-+ xcb_xfixes_query_version_reply_t *rep;
-+
-+ ret = xcb_connect(DisplayString(dpy), &screen_num);
-+ cookie = xcb_xfixes_query_version_unchecked(ret, XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MINOR_VERSION);
-+ rep = xcb_xfixes_query_version_reply(ret, cookie, NULL);
-+ if (rep)
-+ free(rep);
-+ return ret;
-+}
-+
-+BOOL
-+PRESENTInit(Display *dpy, PRESENTpriv **present_priv)
-+{
-+ *present_priv = (PRESENTpriv *) calloc(1, sizeof(PRESENTpriv));
-+ if (!*present_priv) {
-+ return FALSE;
-+ }
-+ (*present_priv)->xcb_connection = create_xcb_connection(dpy);
-+ (*present_priv)->xcb_connection_bis = create_xcb_connection(dpy);
-+ pthread_mutex_init(&(*present_priv)->mutex_present, NULL);
-+ pthread_mutex_init(&(*present_priv)->mutex_xcb_wait, NULL);
-+ return TRUE;
-+}
-+
-+static void PRESENTForceReleases(PRESENTpriv *present_priv)
-+{
-+ PRESENTPixmapPriv *current = NULL;
-+
-+ if (!present_priv->window)
-+ return;
-+
-+ /* There should be no other thread listening for events here.
-+ * This can happen when hDestWindowOverride changes without reset.
-+ * This case should never happen, but can happen in theory.*/
-+ if (present_priv->xcb_wait) {
-+ xcb_present_notify_msc(present_priv->xcb_connection, present_priv->window, 0, 0, 0, 0);
-+ xcb_flush(present_priv->xcb_connection);
-+ pthread_mutex_lock(&present_priv->mutex_xcb_wait);
-+ pthread_mutex_unlock(&present_priv->mutex_xcb_wait);
-+ /* the problem here is that we don't have access to the event the other thread got.
-+ * It is either presented event, idle event or notify event.
-+ */
-+ while (present_priv->pixmap_present_pending >= 2)
-+ PRESENTwait_events(present_priv, FALSE);
-+ PRESENTflush_events(present_priv, TRUE);
-+ /* Remaining events to come can be a pair of present/idle,
-+ * or an idle, or nothing. To be sure we are after all pixmaps
-+ * have been presented, add an event to the queue that can only
-+ * be after the present event, then if we receive an event more,
-+ * we are sure all pixmaps were presented */
-+ present_priv->notify_with_serial_pending = TRUE;
-+ xcb_present_notify_msc(present_priv->xcb_connection, present_priv->window, 1, present_priv->last_target + 5, 0, 0);
-+ xcb_flush(present_priv->xcb_connection);
-+ while (present_priv->notify_with_serial_pending)
-+ PRESENTwait_events(present_priv, FALSE);
-+ /* Now we are sure we are not expecting any new event */
-+ } else {
-+ while (present_priv->pixmap_present_pending) /* wait all sent pixmaps are presented */
-+ PRESENTwait_events(present_priv, FALSE);
-+ PRESENTflush_events(present_priv, TRUE); /* may be remaining idle event */
-+ /* Since idle events are send with the complete events when it is not flips,
-+ * we are not expecting any new event here */
-+ }
-+
-+ current = present_priv->first_present_priv;
-+ while (current) {
-+ if (!current->released) {
-+ if (!current->last_present_was_flip && !present_priv->xcb_wait) {
-+ ERR("ERROR: a pixmap seems not released by PRESENT for no reason. Code bug.\n");
-+ } else {
-+ /* Present the same pixmap with a non-valid part to force the copy mode and the releases */
-+ xcb_xfixes_region_t valid, update;
-+ xcb_rectangle_t rect_update;
-+ rect_update.x = 0;
-+ rect_update.y = 0;
-+ rect_update.width = 8;
-+ rect_update.height = 1;
-+ valid = xcb_generate_id(present_priv->xcb_connection);
-+ update = xcb_generate_id(present_priv->xcb_connection);
-+ xcb_xfixes_create_region(present_priv->xcb_connection, valid, 1, &rect_update);
-+ xcb_xfixes_create_region(present_priv->xcb_connection, update, 1, &rect_update);
-+ /* here we know the pixmap has been presented. Thus if it is on screen,
-+ * the following request can only make it released by the server if it is not */
-+ xcb_present_pixmap(present_priv->xcb_connection, present_priv->window,
-+ current->pixmap, 0, valid, update, 0, 0, None, None,
-+ None, XCB_PRESENT_OPTION_COPY | XCB_PRESENT_OPTION_ASYNC, 0, 0, 0, 0, NULL);
-+ xcb_flush(present_priv->xcb_connection);
-+ PRESENTwait_events(present_priv, FALSE); /* by assumption this can only be idle event */
-+ PRESENTflush_events(present_priv, TRUE); /* Shoudln't be needed */
-+ }
-+ }
-+ current = current->next;
-+ }
-+ /* Now all pixmaps are released (possibility if xcb_wait is true that one is not aware yet),
-+ * and we don't expect any new Present event to come from Xserver */
-+}
-+
-+static void PRESENTFreeXcbQueue(PRESENTpriv *present_priv)
-+{
-+ if (present_priv->window) {
-+ xcb_unregister_for_special_event(present_priv->xcb_connection, present_priv->special_event);
-+ present_priv->last_msc = 0;
-+ present_priv->last_target = 0;
-+ present_priv->special_event = NULL;
-+ }
-+}
-+
-+static BOOL PRESENTPrivChangeWindow(PRESENTpriv *present_priv, XID window)
-+{
-+ xcb_void_cookie_t cookie;
-+ xcb_generic_error_t *error;
-+ xcb_present_event_t eid;
-+
-+ PRESENTForceReleases(present_priv);
-+ PRESENTFreeXcbQueue(present_priv);
-+ present_priv->window = window;
-+
-+ if (window) {
-+ cookie = xcb_present_select_input_checked(present_priv->xcb_connection,
-+ (eid = xcb_generate_id(present_priv->xcb_connection)),
-+ window,
-+ XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY|
-+ XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY);
-+ present_priv->special_event = xcb_register_for_special_xge(present_priv->xcb_connection,
-+ &xcb_present_id,
-+ eid, NULL);
-+ error = xcb_request_check(present_priv->xcb_connection, cookie); /* performs a flush */
-+ if (error || !present_priv->special_event) {
-+ ERR("FAILED to use the X PRESENT extension. Was the destination a window ?\n");
-+ if (present_priv->special_event)
-+ xcb_unregister_for_special_event(present_priv->xcb_connection, present_priv->special_event);
-+ present_priv->special_event = NULL;
-+ present_priv->window = 0;
-+ }
-+ }
-+ return (present_priv->window != 0);
-+}
-+
-+/* Destroy the content, except the link and the struct mem */
-+static void
-+PRESENTDestroyPixmapContent(Display *dpy, PRESENTPixmapPriv *present_pixmap)
-+{
-+ XFreePixmap(dpy, present_pixmap->pixmap);
-+#ifdef D3DADAPTER9_DRI2
-+ if (present_pixmap->dri2_info.is_dri2) {
-+ struct DRI2priv *dri2_priv = present_pixmap->dri2_info.dri2_priv;
-+ EGLenum current_api;
-+ current_api = eglQueryAPI();
-+ eglBindAPI(EGL_OPENGL_API);
-+ if(eglMakeCurrent(dri2_priv->display, EGL_NO_SURFACE, EGL_NO_SURFACE, dri2_priv->context)) {
-+ glDeleteFramebuffers(1, &present_pixmap->dri2_info.fbo_read);
-+ glDeleteFramebuffers(1, &present_pixmap->dri2_info.fbo_write);
-+ glDeleteTextures(1, &present_pixmap->dri2_info.texture_read);
-+ glDeleteTextures(1, &present_pixmap->dri2_info.texture_write);
-+ } else {
-+ ERR("eglMakeCurrent failed with 0x%0X\n", eglGetError());
-+ }
-+ eglMakeCurrent(dri2_priv->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-+ eglBindAPI(current_api);
-+ }
-+#endif
-+}
-+
-+void
-+PRESENTDestroy(Display *dpy, PRESENTpriv *present_priv)
-+{
-+ PRESENTPixmapPriv *current = NULL;
-+
-+ pthread_mutex_lock(&present_priv->mutex_present);
-+
-+ PRESENTForceReleases(present_priv);
-+
-+ current = present_priv->first_present_priv;
-+ while (current) {
-+ PRESENTPixmapPriv *next = current->next;
-+ PRESENTDestroyPixmapContent(dpy, current);
-+ free(current);
-+ current = next;
-+ }
-+
-+ PRESENTFreeXcbQueue(present_priv);
-+
-+ xcb_disconnect(present_priv->xcb_connection);
-+ xcb_disconnect(present_priv->xcb_connection_bis);
-+ pthread_mutex_unlock(&present_priv->mutex_present);
-+ pthread_mutex_destroy(&present_priv->mutex_present);
-+ pthread_mutex_destroy(&present_priv->mutex_xcb_wait);
-+
-+ free(present_priv);
-+}
-+
-+BOOL
-+PRESENTPixmapInit(PRESENTpriv *present_priv, Pixmap pixmap, PRESENTPixmapPriv **present_pixmap_priv)
-+{
-+ xcb_get_geometry_cookie_t cookie;
-+ xcb_get_geometry_reply_t *reply;
-+
-+ cookie = xcb_get_geometry(present_priv->xcb_connection, pixmap);
-+ reply = xcb_get_geometry_reply(present_priv->xcb_connection, cookie, NULL);
-+
-+ if (!reply)
-+ return FALSE;
-+
-+ *present_pixmap_priv = (PRESENTPixmapPriv *) calloc(1, sizeof(PRESENTPixmapPriv));
-+ if (!*present_pixmap_priv) {
-+ free(reply);
-+ return FALSE;
-+ }
-+ pthread_mutex_lock(&present_priv->mutex_present);
-+
-+ (*present_pixmap_priv)->released = TRUE;
-+ (*present_pixmap_priv)->pixmap = pixmap;
-+ (*present_pixmap_priv)->present_priv = present_priv;
-+ (*present_pixmap_priv)->next = present_priv->first_present_priv;
-+ (*present_pixmap_priv)->width = reply->width;
-+ (*present_pixmap_priv)->height = reply->height;
-+ (*present_pixmap_priv)->depth = reply->depth;
-+#ifdef D3DADAPTER9_DRI2
-+ (*present_pixmap_priv)->dri2_info.is_dri2 = FALSE;
-+#endif
-+ free(reply);
-+
-+ present_priv->last_serial_given++;
-+ (*present_pixmap_priv)->serial = present_priv->last_serial_given;
-+ present_priv->first_present_priv = *present_pixmap_priv;
-+
-+ pthread_mutex_unlock(&present_priv->mutex_present);
-+ return TRUE;
-+}
-+
-+#ifdef D3DADAPTER9_DRI2
-+
-+BOOL
-+DRI2FallbackPRESENTPixmap(PRESENTpriv *present_priv, struct DRI2priv *dri2_priv,
-+ int fd, int width, int height, int stride, int depth,
-+ int bpp, PRESENTPixmapPriv **present_pixmap_priv)
-+{
-+ Window root = RootWindow(dri2_priv->dpy, DefaultScreen(dri2_priv->dpy));
-+ Pixmap pixmap;
-+ EGLImageKHR image;
-+ GLuint texture_read, texture_write, fbo_read, fbo_write;
-+ EGLint attribs[] = {
-+ EGL_WIDTH, 0,
-+ EGL_HEIGHT, 0,
-+ EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_ARGB8888,
-+ EGL_DMA_BUF_PLANE0_FD_EXT, 0,
-+ EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0,
-+ EGL_DMA_BUF_PLANE0_PITCH_EXT, 0,
-+ EGL_NONE
-+ };
-+ EGLenum current_api;
-+ int status;
-+
-+ pthread_mutex_lock(&present_priv->mutex_present);
-+
-+ pixmap = XCreatePixmap(dri2_priv->dpy, root, width, height, 24);
-+ if (!pixmap)
-+ goto fail;
-+
-+ attribs[1] = width;
-+ attribs[3] = height;
-+ attribs[7] = fd;
-+ attribs[11] = stride;
-+
-+ current_api = eglQueryAPI();
-+ eglBindAPI(EGL_OPENGL_API);
-+
-+ /* We bind the dma-buf to a EGLImage, then to a texture, and then to a fbo.
-+ * Note that we can delete the EGLImage, but we shouldn't delete the texture,
-+ * else the fbo is invalid */
-+
-+ image = dri2_priv->eglCreateImageKHR_func(dri2_priv->display,
-+ EGL_NO_CONTEXT,
-+ EGL_LINUX_DMA_BUF_EXT,
-+ NULL, attribs);
-+
-+ if (image == EGL_NO_IMAGE_KHR)
-+ goto fail;
-+ close(fd);
-+
-+ if(eglMakeCurrent(dri2_priv->display, EGL_NO_SURFACE, EGL_NO_SURFACE, dri2_priv->context)) {
-+ glGenTextures(1, &texture_read);
-+ glBindTexture(GL_TEXTURE_2D, texture_read);
-+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-+ dri2_priv->glEGLImageTargetTexture2DOES_func(GL_TEXTURE_2D, image);
-+ glGenFramebuffers(1, &fbo_read);
-+ glBindFramebuffer(GL_FRAMEBUFFER, fbo_read);
-+ glFramebufferTexture2D(GL_FRAMEBUFFER,
-+ GL_COLOR_ATTACHMENT0,
-+ GL_TEXTURE_2D, texture_read,
-+ 0);
-+ status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
-+ if (status != GL_FRAMEBUFFER_COMPLETE)
-+ goto fail;
-+ glBindTexture(GL_TEXTURE_2D, 0);
-+ dri2_priv->eglDestroyImageKHR_func(dri2_priv->display, image);
-+
-+ /* We bind a newly created pixmap (to which we want to copy the content)
-+ * to an EGLImage, then to a texture, then to a fbo. */
-+ image = dri2_priv->eglCreateImageKHR_func(dri2_priv->display,
-+ dri2_priv->context,
-+ EGL_NATIVE_PIXMAP_KHR,
-+ (void *)pixmap, NULL);
-+ if (image == EGL_NO_IMAGE_KHR)
-+ goto fail;
-+
-+ glGenTextures(1, &texture_write);
-+ glBindTexture(GL_TEXTURE_2D, texture_write);
-+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-+ dri2_priv->glEGLImageTargetTexture2DOES_func(GL_TEXTURE_2D, image);
-+ glGenFramebuffers(1, &fbo_write);
-+ glBindFramebuffer(GL_FRAMEBUFFER, fbo_write);
-+ glFramebufferTexture2D(GL_FRAMEBUFFER,
-+ GL_COLOR_ATTACHMENT0,
-+ GL_TEXTURE_2D, texture_write,
-+ 0);
-+ status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
-+ if (status != GL_FRAMEBUFFER_COMPLETE)
-+ goto fail;
-+ glBindTexture(GL_TEXTURE_2D, 0);
-+ dri2_priv->eglDestroyImageKHR_func(dri2_priv->display, image);
-+ } else {
-+ ERR("eglMakeCurrent failed with 0x%0X\n", eglGetError());
-+ }
-+ eglMakeCurrent(dri2_priv->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-+
-+ *present_pixmap_priv = (PRESENTPixmapPriv *) calloc(1, sizeof(PRESENTPixmapPriv));
-+ if (!*present_pixmap_priv) {
-+ goto fail;
-+ }
-+
-+ (*present_pixmap_priv)->released = TRUE;
-+ (*present_pixmap_priv)->pixmap = pixmap;
-+ (*present_pixmap_priv)->present_priv = present_priv;
-+ (*present_pixmap_priv)->next = present_priv->first_present_priv;
-+ (*present_pixmap_priv)->width = width;
-+ (*present_pixmap_priv)->height = height;
-+ (*present_pixmap_priv)->depth = depth;
-+ (*present_pixmap_priv)->dri2_info.is_dri2 = TRUE;
-+ (*present_pixmap_priv)->dri2_info.dri2_priv = dri2_priv;
-+ (*present_pixmap_priv)->dri2_info.fbo_read = fbo_read;
-+ (*present_pixmap_priv)->dri2_info.fbo_write = fbo_write;
-+ (*present_pixmap_priv)->dri2_info.texture_read = texture_read;
-+ (*present_pixmap_priv)->dri2_info.texture_write = texture_write;
-+
-+ present_priv->last_serial_given++;
-+ (*present_pixmap_priv)->serial = present_priv->last_serial_given;
-+ present_priv->first_present_priv = *present_pixmap_priv;
-+
-+ eglBindAPI(current_api);
-+
-+ pthread_mutex_unlock(&present_priv->mutex_present);
-+ return TRUE;
-+fail:
-+ eglMakeCurrent(dri2_priv->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-+ eglBindAPI(current_api);
-+ pthread_mutex_unlock(&present_priv->mutex_present);
-+ return FALSE;
-+}
-+
-+#endif
-+
-+BOOL
-+PRESENTTryFreePixmap(Display *dpy, PRESENTPixmapPriv *present_pixmap_priv)
-+{
-+ PRESENTpriv *present_priv = present_pixmap_priv->present_priv;
-+ PRESENTPixmapPriv *current;
-+
-+ pthread_mutex_lock(&present_priv->mutex_present);
-+
-+ if (!present_pixmap_priv->released || present_pixmap_priv->present_complete_pending) {
-+ pthread_mutex_unlock(&present_priv->mutex_present);
-+ return FALSE;
-+ }
-+
-+ if (present_priv->first_present_priv == present_pixmap_priv) {
-+ present_priv->first_present_priv = present_pixmap_priv->next;
-+ goto free_priv;
-+ }
-+
-+ current = present_priv->first_present_priv;
-+ while (current->next != present_pixmap_priv)
-+ current = current->next;
-+ current->next = present_pixmap_priv->next;
-+free_priv:
-+ PRESENTDestroyPixmapContent(dpy, present_pixmap_priv);
-+ free(present_pixmap_priv);
-+ pthread_mutex_unlock(&present_priv->mutex_present);
-+ return TRUE;
-+}
-+
-+BOOL
-+PRESENTHelperCopyFront(Display *dpy, PRESENTPixmapPriv *present_pixmap_priv)
-+{
-+ PRESENTpriv *present_priv = present_pixmap_priv->present_priv;
-+ xcb_void_cookie_t cookie;
-+ xcb_generic_error_t *error;
-+
-+ uint32_t v = 0;
-+ xcb_gcontext_t gc;
-+
-+ pthread_mutex_lock(&present_priv->mutex_present);
-+
-+ if (!present_priv->window) {
-+ pthread_mutex_unlock(&present_priv->mutex_present);
-+ return FALSE;
-+ }
-+
-+ xcb_create_gc(present_priv->xcb_connection,
-+ (gc = xcb_generate_id(present_priv->xcb_connection)),
-+ present_priv->window,
-+ XCB_GC_GRAPHICS_EXPOSURES,
-+ &v);
-+ cookie = xcb_copy_area_checked(present_priv->xcb_connection,
-+ present_priv->window,
-+ present_pixmap_priv->pixmap,
-+ gc,
-+ 0, 0, 0, 0,
-+ present_pixmap_priv->width,
-+ present_pixmap_priv->height);
-+ error = xcb_request_check(present_priv->xcb_connection, cookie);
-+ xcb_free_gc(present_priv->xcb_connection, gc);
-+ pthread_mutex_unlock(&present_priv->mutex_present);
-+ return (error != NULL);
-+}
-+
-+BOOL
-+PRESENTPixmap(Display *dpy, XID window,
-+ PRESENTPixmapPriv *present_pixmap_priv, D3DPRESENT_PARAMETERS *pPresentationParameters,
-+ const RECT *pSourceRect, const RECT *pDestRect, const RGNDATA *pDirtyRegion)
-+{
-+ PRESENTpriv *present_priv = present_pixmap_priv->present_priv;
-+#ifdef D3DADAPTER9_DRI2
-+ struct DRI2priv *dri2_priv = present_pixmap_priv->dri2_info.dri2_priv;
-+ EGLenum current_api;
-+#endif
-+ xcb_void_cookie_t cookie;
-+ xcb_generic_error_t *error;
-+ int64_t target_msc, presentationInterval;
-+ xcb_xfixes_region_t valid, update;
-+ int16_t x_off, y_off;
-+ uint32_t options = XCB_PRESENT_OPTION_NONE;
-+
-+ pthread_mutex_lock(&present_priv->mutex_present);
-+
-+ if (window != present_priv->window)
-+ PRESENTPrivChangeWindow(present_priv, window);
-+
-+ if (!window) {
-+ ERR("ERROR: Try to Present a pixmap on a NULL window\n");
-+ pthread_mutex_unlock(&present_priv->mutex_present);
-+ return FALSE;
-+ }
-+
-+ PRESENTflush_events(present_priv, FALSE);
-+ if (!present_pixmap_priv->released || present_pixmap_priv->present_complete_pending) {
-+ ERR("FATAL ERROR: Trying to Present a pixmap not released\n");
-+ pthread_mutex_unlock(&present_priv->mutex_present);
-+ return FALSE;
-+ }
-+#ifdef D3DADAPTER9_DRI2
-+ if (present_pixmap_priv->dri2_info.is_dri2) {
-+ current_api = eglQueryAPI();
-+ eglBindAPI(EGL_OPENGL_API);
-+ if(eglMakeCurrent(dri2_priv->display, EGL_NO_SURFACE, EGL_NO_SURFACE, dri2_priv->context)) {
-+ glBindFramebuffer(GL_READ_FRAMEBUFFER, present_pixmap_priv->dri2_info.fbo_read);
-+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, present_pixmap_priv->dri2_info.fbo_write);
-+
-+ glBlitFramebuffer(0, 0, present_pixmap_priv->width, present_pixmap_priv->height,
-+ 0, 0, present_pixmap_priv->width, present_pixmap_priv->height,
-+ GL_COLOR_BUFFER_BIT, GL_NEAREST);
-+ glFlush(); /* Perhaps useless */
-+ } else {
-+ ERR("eglMakeCurrent failed with 0x%0X\n", eglGetError());
-+ }
-+ eglMakeCurrent(dri2_priv->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-+ eglBindAPI(current_api);
-+ }
-+#endif
-+ target_msc = present_priv->last_msc;
-+ switch(pPresentationParameters->PresentationInterval) {
-+ case D3DPRESENT_INTERVAL_DEFAULT:
-+ case D3DPRESENT_INTERVAL_ONE:
-+ presentationInterval = 1;
-+ break;
-+ case D3DPRESENT_INTERVAL_TWO:
-+ presentationInterval = 2;
-+ break;
-+ case D3DPRESENT_INTERVAL_THREE:
-+ presentationInterval = 3;
-+ break;
-+ case D3DPRESENT_INTERVAL_FOUR:
-+ presentationInterval = 4;
-+ break;
-+ case D3DPRESENT_INTERVAL_IMMEDIATE:
-+ default:
-+ presentationInterval = 0;
-+ options |= XCB_PRESENT_OPTION_ASYNC;
-+ break;
-+ }
-+ target_msc += presentationInterval * (present_priv->pixmap_present_pending + 1);
-+
-+ /* Note: PRESENT defines some way to do partial copy:
-+ * presentproto:
-+ * 'x-off' and 'y-off' define the location in the window where
-+ * the 0,0 location of the pixmap will be presented. valid-area
-+ * and update-area are relative to the pixmap.
-+ */
-+ if (!pSourceRect && !pDestRect && !pDirtyRegion) {
-+ valid = 0;
-+ update = 0;
-+ x_off = 0;
-+ y_off = 0;
-+ } else {
-+ xcb_rectangle_t rect_update;
-+ xcb_rectangle_t *rect_updates;
-+ int i;
-+
-+ rect_update.x = 0;
-+ rect_update.y = 0;
-+ rect_update.width = present_pixmap_priv->width;
-+ rect_update.height = present_pixmap_priv->height;
-+ x_off = 0;
-+ y_off = 0;
-+ if (pSourceRect) {
-+ x_off = -pSourceRect->left;
-+ y_off = -pSourceRect->top;
-+ rect_update.x = pSourceRect->left;
-+ rect_update.y = pSourceRect->top;
-+ rect_update.width = pSourceRect->right - pSourceRect->left;
-+ rect_update.height = pSourceRect->bottom - pSourceRect->top;
-+ }
-+ if (pDestRect) {
-+ x_off += pDestRect->left;
-+ y_off += pDestRect->top;
-+ rect_update.width = pDestRect->right - pDestRect->left;
-+ rect_update.height = pDestRect->bottom - pDestRect->top;
-+ /* Note: the size of pDestRect and pSourceRect are supposed to be the same size
-+ * because the driver would have done things to assure that. */
-+ }
-+ valid = xcb_generate_id(present_priv->xcb_connection_bis);
-+ update = xcb_generate_id(present_priv->xcb_connection_bis);
-+ xcb_xfixes_create_region(present_priv->xcb_connection_bis, valid, 1, &rect_update);
-+ if (pDirtyRegion && pDirtyRegion->rdh.nCount) {
-+ rect_updates = (void *) calloc(pDirtyRegion->rdh.nCount, sizeof(xcb_rectangle_t));
-+ for (i = 0; i < pDirtyRegion->rdh.nCount; i++)
-+ {
-+ RECT rc;
-+ memcpy(&rc, pDirtyRegion->Buffer + i * sizeof(RECT), sizeof(RECT));
-+ rect_update.x = rc.left;
-+ rect_update.y = rc.top;
-+ rect_update.width = rc.right - rc.left;
-+ rect_update.height = rc.bottom - rc.top;
-+ memcpy(rect_updates + i * sizeof(xcb_rectangle_t), &rect_update, sizeof(xcb_rectangle_t));
-+ }
-+ xcb_xfixes_create_region(present_priv->xcb_connection_bis, update, pDirtyRegion->rdh.nCount, rect_updates);
-+ free(rect_updates);
-+ } else
-+ xcb_xfixes_create_region(present_priv->xcb_connection_bis, update, 1, &rect_update);
-+ }
-+ if (pPresentationParameters->SwapEffect == D3DSWAPEFFECT_COPY)
-+ options |= XCB_PRESENT_OPTION_COPY;
-+ cookie = xcb_present_pixmap_checked(present_priv->xcb_connection_bis,
-+ window,
-+ present_pixmap_priv->pixmap,
-+ present_pixmap_priv->serial,
-+ valid, update, x_off, y_off,
-+ None, None, None, options,
-+ target_msc, 0, 0, 0, NULL);
-+ error = xcb_request_check(present_priv->xcb_connection_bis, cookie); /* performs a flush */
-+
-+ if (update)
-+ xcb_xfixes_destroy_region(present_priv->xcb_connection_bis, update);
-+ if (valid)
-+ xcb_xfixes_destroy_region(present_priv->xcb_connection_bis, valid);
-+
-+ if (error) {
-+ xcb_get_geometry_cookie_t cookie_geom;
-+ xcb_get_geometry_reply_t *reply;
-+
-+ cookie_geom = xcb_get_geometry(present_priv->xcb_connection_bis, window);
-+ reply = xcb_get_geometry_reply(present_priv->xcb_connection_bis, cookie_geom, NULL);
-+
-+ ERR("Error using PRESENT. Here some debug info\n");
-+ if (!reply) {
-+ ERR("Error querying window info. Perhaps it doesn't exist anymore\n");
-+ pthread_mutex_unlock(&present_priv->mutex_present);
-+ return FALSE;
-+ }
-+ ERR("Pixmap: width=%d, height=%d, depth=%d\n",
-+ present_pixmap_priv->width, present_pixmap_priv->height,
-+ present_pixmap_priv->depth);
-+ ERR("Window: width=%d, height=%d, depth=%d, x=%d, y=%d\n",
-+ (int) reply->width, (int) reply->height,
-+ (int) reply->depth, (int) reply->x, (int) reply->y);
-+ ERR("Present parameter: PresentationInterval=%d, BackBufferCount=%d, Pending presentations=%d\n",
-+ pPresentationParameters->PresentationInterval,
-+ pPresentationParameters->BackBufferCount,
-+ present_priv->pixmap_present_pending
-+ );
-+ if (present_pixmap_priv->depth != reply->depth)
-+ ERR("Depths are different. PRESENT needs the pixmap and the window have same depth\n");
-+ free(reply);
-+ pthread_mutex_unlock(&present_priv->mutex_present);
-+ return FALSE;
-+ }
-+ present_priv->last_target = target_msc;
-+ present_priv->pixmap_present_pending++;
-+ present_pixmap_priv->present_complete_pending = TRUE;
-+ present_pixmap_priv->released = FALSE;
-+ pthread_mutex_unlock(&present_priv->mutex_present);
-+ return TRUE;
-+}
-+
-+BOOL
-+PRESENTWaitPixmapReleased(PRESENTPixmapPriv *present_pixmap_priv)
-+{
-+ PRESENTpriv *present_priv = present_pixmap_priv->present_priv;
-+
-+ pthread_mutex_lock(&present_priv->mutex_present);
-+
-+ PRESENTflush_events(present_priv, FALSE);
-+
-+ while (!present_pixmap_priv->released || present_pixmap_priv->present_complete_pending) {
-+ /* Note: following if should not happen because we'll never
-+ * use two PRESENTWaitPixmapReleased in parallels on same window.
-+ * However it would make it work in that case */
-+ if (present_priv->xcb_wait) { /* we allow only one thread to dispatch events */
-+ pthread_mutex_lock(&present_priv->mutex_xcb_wait);
-+ /* here the other thread got an event but hasn't treated it yet */
-+ pthread_mutex_unlock(&present_priv->mutex_xcb_wait);
-+ pthread_mutex_unlock(&present_priv->mutex_present);
-+ Sleep(10); /* Let it treat the event */
-+ pthread_mutex_lock(&present_priv->mutex_present);
-+ } else if (!PRESENTwait_events(present_priv, TRUE)) {
-+ pthread_mutex_unlock(&present_priv->mutex_present);
-+ return FALSE;
-+ }
-+ }
-+ pthread_mutex_unlock(&present_priv->mutex_present);
-+ return TRUE;
-+}
-diff --git a/dlls/d3d9-nine/dri3.h b/dlls/d3d9-nine/dri3.h
-new file mode 100644
-index 0000000..795c3c7
---- /dev/null
-+++ b/dlls/d3d9-nine/dri3.h
-@@ -0,0 +1,106 @@
-+/*
-+ * Wine X11DRV DRI3 interface
-+ *
-+ * Copyright 2014 Axel Davy
-+ *
-+ * 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_DRI3_H
-+#define __WINE_DRI3_H
-+
-+#ifndef __WINE_CONFIG_H
-+# error You must include config.h to use this header
-+#endif
-+
-+#include <X11/Xlib.h>
-+#include <X11/Xutil.h>
-+#include <X11/Xlib-xcb.h>
-+#include <xcb/xcb.h>
-+#include <xcb/dri3.h>
-+#include <xcb/present.h>
-+
-+BOOL
-+DRI3CheckExtension(Display *dpy, int major, int minor);
-+
-+#ifdef D3DADAPTER9_DRI2
-+struct DRI2priv;
-+
-+BOOL
-+DRI2FallbackInit(Display *dpy, struct DRI2priv **priv);
-+
-+void
-+DRI2FallbackDestroy(struct DRI2priv *priv);
-+
-+BOOL
-+DRI2FallbackCheckSupport(Display *dpy);
-+#endif
-+
-+BOOL
-+PRESENTCheckExtension(Display *dpy, int major, int minor);
-+
-+BOOL
-+DRI3Open(Display *dpy, int screen, int *device_fd);
-+
-+#ifdef D3DADAPTER9_DRI2
-+BOOL
-+DRI2FallbackOpen(Display *dpy, int screen, int *device_fd);
-+#endif
-+
-+BOOL
-+DRI3PixmapFromDmaBuf(Display *dpy, int screen, int fd, int width, int height, int stride, int depth, int bpp, Pixmap *pixmap);
-+
-+BOOL
-+DRI3DmaBufFromPixmap(Display *dpy, Pixmap pixmap, int *fd, int *width, int *height, int *stride, int *depth, int *bpp);
-+
-+typedef struct PRESENTPriv PRESENTpriv;
-+typedef struct PRESENTPixmapPriv PRESENTPixmapPriv;
-+
-+BOOL
-+PRESENTInit(Display *dpy, PRESENTpriv **present_priv);
-+
-+/* will clean properly and free all PRESENTPixmapPriv associated to PRESENTpriv.
-+ * PRESENTPixmapPriv should not be freed by something else.
-+ * If never a PRESENTPixmapPriv has to be destroyed,
-+ * please destroy the current PRESENTpriv and create a new one.
-+ * This will take care than all pixmaps are released */
-+void
-+PRESENTDestroy(Display *dpy, PRESENTpriv *present_priv);
-+
-+BOOL
-+PRESENTPixmapInit(PRESENTpriv *present_priv, Pixmap pixmap, PRESENTPixmapPriv **present_pixmap_priv);
-+
-+#ifdef D3DADAPTER9_DRI2
-+BOOL
-+DRI2FallbackPRESENTPixmap(PRESENTpriv *present_priv, struct DRI2priv *priv,
-+ int fd, int width, int height, int stride, int depth,
-+ int bpp, PRESENTPixmapPriv **present_pixmap_priv);
-+#endif
-+
-+BOOL
-+PRESENTTryFreePixmap(Display *dpy, PRESENTPixmapPriv *present_pixmap_priv);
-+
-+BOOL
-+PRESENTHelperCopyFront(Display *dpy, PRESENTPixmapPriv *present_pixmap_priv);
-+
-+BOOL
-+PRESENTPixmap(Display *dpy, XID window,
-+ PRESENTPixmapPriv *present_pixmap_priv, D3DPRESENT_PARAMETERS *pPresentationParameters,
-+ const RECT *pSourceRect, const RECT *pDestRect, const RGNDATA *pDirtyRegion);
-+
-+BOOL
-+PRESENTWaitPixmapReleased(PRESENTPixmapPriv *present_pixmap_priv);
-+
-+#endif /* __WINE_DRI3_H */
-diff --git a/dlls/d3d9-nine/libd3d9-nine.def b/dlls/d3d9-nine/libd3d9-nine.def
-new file mode 100644
-index 0000000..4f41fcb
---- /dev/null
-+++ b/dlls/d3d9-nine/libd3d9-nine.def
-@@ -0,0 +1,16 @@
-+; File generated automatically from ./dlls/d3d9-nine/d3d9-nine.spec; do not edit!
-+
-+LIBRARY d3d9-nine.dll
-+
-+EXPORTS
-+ Direct3DShaderValidatorCreate9@0 @1
-+ D3DPERF_BeginEvent@8 @4
-+ D3DPERF_EndEvent@0 @5
-+ D3DPERF_GetStatus@0 @6
-+ D3DPERF_QueryRepeatFrame@0 @7
-+ D3DPERF_SetMarker@8 @8
-+ D3DPERF_SetOptions@4 @9
-+ D3DPERF_SetRegion@8 @10
-+ DebugSetMute@0 @12
-+ Direct3DCreate9@4 @13
-+ Direct3DCreate9Ex@8 @14
-diff --git a/dlls/d3d9-nine/present.c b/dlls/d3d9-nine/present.c
-new file mode 100644
-index 0000000..931c784
---- /dev/null
-+++ b/dlls/d3d9-nine/present.c
-@@ -0,0 +1,1333 @@
-+/*
-+ * Wine ID3DAdapter9 support functions
-+ *
-+ * Copyright 2013 Joakim Sindholt
-+ * Christoph Bumiller
-+ * Copyright 2014 Tiziano Bacocco
-+ * David Heidelberger
-+ * Copyright 2014-2015 Axel Davy
-+ * Copyright 2015 Patrick Rudolph
-+ *
-+ * 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);
-+
-+#include <d3dadapter/d3dadapter9.h>
-+#include <d3dadapter/drm.h>
-+#include <libdrm/drm.h>
-+#include <errno.h>
-+#include <fcntl.h>
-+
-+#include "dri3.h"
-+#include "wine/library.h"
-+#include "wine/unicode.h"
-+
-+#ifndef D3DPRESENT_DONOTWAIT
-+#define D3DPRESENT_DONOTWAIT 0x00000001
-+#endif
-+
-+#define WINE_D3DADAPTER_DRIVER_PRESENT_VERSION_MAJOR 1
-+#ifdef ID3DPresent_GetWindowOccluded
-+#define WINE_D3DADAPTER_DRIVER_PRESENT_VERSION_MINOR 1
-+#else
-+#define WINE_D3DADAPTER_DRIVER_PRESENT_VERSION_MINOR 0
-+#endif
-+
-+static const struct D3DAdapter9DRM *d3d9_drm = NULL;
-+#ifdef D3DADAPTER9_DRI2
-+static int is_dri2_fallback = 0;
-+#endif
-+
-+#define X11DRV_ESCAPE 6789
-+enum x11drv_escape_codes
-+{
-+ X11DRV_SET_DRAWABLE, /* set current drawable for a DC */
-+ X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
-+ X11DRV_START_EXPOSURES, /* start graphics exposures */
-+ X11DRV_END_EXPOSURES, /* end graphics exposures */
-+ X11DRV_FLUSH_GL_DRAWABLE /* flush changes made to the gl drawable */
-+};
-+
-+struct x11drv_escape_get_drawable
-+{
-+ enum x11drv_escape_codes code; /* escape code (X11DRV_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 */
-+};
-+
-+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 */
-+ RECT dc_rect; /* rect relative to the X11 drawable */
-+ HDC hdc;
-+ HWND wnd; /* HWND (for convenience) */
-+};
-+
-+#ifdef ID3DPresent_GetWindowOccluded
-+static HHOOK hhook;
-+
-+struct d3d_wnd_hooks
-+{
-+ HWND focus_wnd;
-+ struct DRI3Present *present;
-+ struct d3d_wnd_hooks *prev;
-+ struct d3d_wnd_hooks *next;
-+};
-+
-+static HRESULT dri3_present_unregister_window_hook( struct DRI3Present *This );
-+static HRESULT dri3_present_register_window_hook( struct DRI3Present *This );
-+
-+static struct d3d_wnd_hooks d3d_hooks;
-+#endif
-+
-+struct DRI3Present
-+{
-+ /* COM vtable */
-+ void *vtable;
-+ /* IUnknown reference count */
-+ LONG refs;
-+
-+ D3DPRESENT_PARAMETERS params;
-+ HWND focus_wnd;
-+ PRESENTpriv *present_priv;
-+#ifdef D3DADAPTER9_DRI2
-+ struct DRI2priv *dri2_priv;
-+#endif
-+
-+ WCHAR devname[32];
-+ HCURSOR hCursor;
-+
-+ DEVMODEW initial_mode;
-+ BOOL device_needs_reset;
-+ BOOL occluded;
-+ Display *gdi_display;
-+ struct d3d_drawable *d3d;
-+ boolean ex;
-+ boolean no_window_changes;
-+ boolean mode_changed;
-+ long style;
-+ long style_ex;
-+ boolean drop_wnd_messages;
-+};
-+
-+struct D3DWindowBuffer
-+{
-+ PRESENTPixmapPriv *present_pixmap_priv;
-+};
-+
-+static void
-+free_d3dadapter_drawable(struct d3d_drawable *d3d)
-+{
-+ ReleaseDC(d3d->wnd, d3d->hdc);
-+ HeapFree(GetProcessHeap(), 0, d3d);
-+}
-+
-+void
-+destroy_d3dadapter_drawable(Display *gdi_display, 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;
-+
-+ return d3d;
-+}
-+
-+static struct d3d_drawable *
-+get_d3d_drawable(Display *gdi_display, 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);
-+ }
-+
-+ if (!EqualRect(&d3d->dc_rect, &extesc.dc_rect))
-+ d3d->dc_rect = extesc.dc_rect;
-+
-+ 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
-+DRI3Present_AddRef( struct DRI3Present *This )
-+{
-+ ULONG refs = InterlockedIncrement(&This->refs);
-+ TRACE("%p increasing refcount to %u.\n", This, refs);
-+ return refs;
-+}
-+
-+static ULONG WINAPI
-+DRI3Present_Release( struct DRI3Present *This )
-+{
-+ ULONG refs = InterlockedDecrement(&This->refs);
-+ TRACE("%p decreasing refcount to %u.\n", This, refs);
-+ if (refs == 0) {
-+ /* dtor */
-+#ifdef ID3DPresent_GetWindowOccluded
-+ dri3_present_unregister_window_hook(This);
-+#endif
-+ if (This->d3d)
-+ destroy_d3dadapter_drawable(This->gdi_display, This->d3d->wnd);
-+ ChangeDisplaySettingsExW(This->devname, &(This->initial_mode), 0, CDS_FULLSCREEN, NULL);
-+
-+ PRESENTDestroy(This->gdi_display, This->present_priv);
-+#ifdef D3DADAPTER9_DRI2
-+ if (is_dri2_fallback)
-+ DRI2FallbackDestroy(This->dri2_priv);
-+#endif
-+ HeapFree(GetProcessHeap(), 0, This);
-+ }
-+ return refs;
-+}
-+
-+static HRESULT WINAPI
-+DRI3Present_QueryInterface( struct DRI3Present *This,
-+ REFIID riid,
-+ void **ppvObject )
-+{
-+ if (!ppvObject) { return E_POINTER; }
-+
-+ if (IsEqualGUID(&IID_ID3DPresent, riid) ||
-+ IsEqualGUID(&IID_IUnknown, riid)) {
-+ *ppvObject = This;
-+ DRI3Present_AddRef(This);
-+ return S_OK;
-+ }
-+
-+ WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
-+ *ppvObject = NULL;
-+
-+ return E_NOINTERFACE;
-+}
-+
-+static HRESULT
-+DRI3Present_ChangePresentParameters( struct DRI3Present *This,
-+ D3DPRESENT_PARAMETERS *params);
-+
-+static HRESULT WINAPI
-+DRI3Present_SetPresentParameters( struct DRI3Present *This,
-+ D3DPRESENT_PARAMETERS *pPresentationParameters,
-+ D3DDISPLAYMODEEX *pFullscreenDisplayMode )
-+{
-+ if (pFullscreenDisplayMode)
-+ ERR("Ignoring pFullscreenDisplayMode\n");
-+ return DRI3Present_ChangePresentParameters(This, pPresentationParameters);
-+}
-+
-+static HRESULT WINAPI
-+DRI3Present_D3DWindowBufferFromDmaBuf( struct DRI3Present *This,
-+ int dmaBufFd,
-+ int width,
-+ int height,
-+ int stride,
-+ int depth,
-+ int bpp,
-+ struct D3DWindowBuffer **out)
-+{
-+ Pixmap pixmap;
-+
-+#ifdef D3DADAPTER9_DRI2
-+ if (is_dri2_fallback) {
-+ *out = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
-+ sizeof(struct D3DWindowBuffer));
-+ DRI2FallbackPRESENTPixmap(This->present_priv, This->dri2_priv,
-+ dmaBufFd, width, height, stride, depth,
-+ bpp,
-+ &((*out)->present_pixmap_priv));
-+ return D3D_OK;
-+ }
-+#endif
-+ if (!DRI3PixmapFromDmaBuf(This->gdi_display, DefaultScreen(This->gdi_display),
-+ dmaBufFd, width, height, stride, depth,
-+ bpp, &pixmap ))
-+ return D3DERR_DRIVERINTERNALERROR;
-+
-+ *out = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
-+ sizeof(struct D3DWindowBuffer));
-+ PRESENTPixmapInit(This->present_priv, pixmap, &((*out)->present_pixmap_priv));
-+ return D3D_OK;
-+}
-+
-+static HRESULT WINAPI
-+DRI3Present_DestroyD3DWindowBuffer( struct DRI3Present *This,
-+ struct D3DWindowBuffer *buffer )
-+{
-+ /* the pixmap is managed by the PRESENT backend.
-+ * But if it can delete it right away, we may have
-+ * better performance */
-+ PRESENTTryFreePixmap(This->gdi_display, buffer->present_pixmap_priv);
-+ HeapFree(GetProcessHeap(), 0, buffer);
-+ return D3D_OK;
-+}
-+
-+static HRESULT WINAPI
-+DRI3Present_WaitBufferReleased( struct DRI3Present *This,
-+ struct D3DWindowBuffer *buffer)
-+{
-+ PRESENTWaitPixmapReleased(buffer->present_pixmap_priv);
-+ return D3D_OK;
-+}
-+
-+static HRESULT WINAPI
-+DRI3Present_FrontBufferCopy( struct DRI3Present *This,
-+ struct D3DWindowBuffer *buffer )
-+{
-+#ifdef D3DADAPTER9_DRI2
-+ if (is_dri2_fallback)
-+ return D3DERR_DRIVERINTERNALERROR;
-+#endif
-+ /* TODO: use dc_rect */
-+ if (PRESENTHelperCopyFront(This->gdi_display, buffer->present_pixmap_priv))
-+ return D3D_OK;
-+ else
-+ return D3DERR_DRIVERINTERNALERROR;
-+}
-+
-+static HRESULT WINAPI
-+DRI3Present_PresentBuffer( struct DRI3Present *This,
-+ struct D3DWindowBuffer *buffer,
-+ HWND hWndOverride,
-+ const RECT *pSourceRect,
-+ const RECT *pDestRect,
-+ const RGNDATA *pDirtyRegion,
-+ DWORD Flags )
-+{
-+ struct d3d_drawable *d3d;
-+ RECT dest_translate;
-+
-+ if (hWndOverride) {
-+ d3d = get_d3d_drawable(This->gdi_display, hWndOverride);
-+ } else if (This->params.hDeviceWindow) {
-+ d3d = get_d3d_drawable(This->gdi_display, This->params.hDeviceWindow);
-+ } else {
-+ d3d = get_d3d_drawable(This->gdi_display, This->focus_wnd);
-+ }
-+ if (!d3d) { return D3DERR_DRIVERINTERNALERROR; }
-+
-+ /* TODO: should we use a list here instead ? */
-+ if (This->d3d && (This->d3d->wnd != d3d->wnd)) {
-+ destroy_d3dadapter_drawable(This->gdi_display, This->d3d->wnd);
-+ }
-+ This->d3d = d3d;
-+
-+ if (d3d->dc_rect.top != 0 &&
-+ d3d->dc_rect.left != 0) {
-+ if (!pDestRect)
-+ pDestRect = (const RECT *) &(d3d->dc_rect);
-+ else {
-+ dest_translate.top = pDestRect->top + d3d->dc_rect.top;
-+ dest_translate.left = pDestRect->left + d3d->dc_rect.left;
-+ dest_translate.bottom = pDestRect->bottom + d3d->dc_rect.bottom;
-+ dest_translate.right = pDestRect->right + d3d->dc_rect.right;
-+ pDestRect = (const RECT *) &dest_translate;
-+ }
-+ }
-+
-+ if (!PRESENTPixmap(This->gdi_display, d3d->drawable, buffer->present_pixmap_priv,
-+ &This->params, pSourceRect, pDestRect, pDirtyRegion))
-+ return D3DERR_DRIVERINTERNALERROR;
-+
-+ release_d3d_drawable(d3d);
-+
-+ return D3D_OK;
-+}
-+
-+static HRESULT WINAPI
-+DRI3Present_GetRasterStatus( struct DRI3Present *This,
-+ D3DRASTER_STATUS *pRasterStatus )
-+{
-+ FIXME("(%p, %p), stub!\n", This, pRasterStatus);
-+ return D3DERR_INVALIDCALL;
-+}
-+
-+static HRESULT WINAPI
-+DRI3Present_GetDisplayMode( struct DRI3Present *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
-+DRI3Present_GetPresentStats( struct DRI3Present *This,
-+ D3DPRESENTSTATS *pStats )
-+{
-+ FIXME("(%p, %p), stub!\n", This, pStats);
-+ return D3DERR_INVALIDCALL;
-+}
-+
-+static HRESULT WINAPI
-+DRI3Present_GetCursorPos( struct DRI3Present *This,
-+ POINT *pPoint )
-+{
-+ BOOL ok;
-+ HWND draw_window;
-+
-+ if (!pPoint)
-+ return D3DERR_INVALIDCALL;
-+
-+ draw_window = This->params.hDeviceWindow ?
-+ This->params.hDeviceWindow : This->focus_wnd;
-+
-+ ok = GetCursorPos(pPoint);
-+ ok = ok && ScreenToClient(draw_window, pPoint);
-+ return ok ? S_OK : D3DERR_DRIVERINTERNALERROR;
-+}
-+
-+static HRESULT WINAPI
-+DRI3Present_SetCursorPos( struct DRI3Present *This,
-+ POINT *pPoint )
-+{
-+ BOOL ok;
-+ POINT real_pos;
-+
-+ if (!pPoint)
-+ return D3DERR_INVALIDCALL;
-+
-+ ok = SetCursorPos(pPoint->x, pPoint->y);
-+ if (!ok)
-+ goto error;
-+
-+ ok = GetCursorPos(&real_pos);
-+ if (!ok || real_pos.x != pPoint->x || real_pos.y != pPoint->y)
-+ goto error;
-+
-+ return D3D_OK;
-+
-+error:
-+ SetCursor(NULL); /* Hide cursor rather than put wrong pos */
-+ return D3DERR_DRIVERINTERNALERROR;
-+}
-+
-+
-+/* Note: assuming 32x32 cursor */
-+static HRESULT WINAPI
-+DRI3Present_SetCursor( struct DRI3Present *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
-+DRI3Present_SetGammaRamp( struct DRI3Present *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
-+DRI3Present_GetWindowInfo( struct DRI3Present *This,
-+ HWND hWnd,
-+ int *width, int *height, int *depth )
-+{
-+ HRESULT hr;
-+ RECT pRect;
-+
-+ if (!hWnd)
-+ hWnd = This->focus_wnd;
-+ hr = GetClientRect(hWnd, &pRect);
-+ if (!hr)
-+ return D3DERR_INVALIDCALL;
-+ *width = pRect.right - pRect.left;
-+ *height = pRect.bottom - pRect.top;
-+ *depth = 24; //TODO
-+ return D3D_OK;
-+}
-+
-+static LONG fullscreen_style(LONG style)
-+{
-+ /* Make sure the window is managed, otherwise we won't get keyboard input. */
-+ style |= WS_POPUP | WS_SYSMENU;
-+ style &= ~(WS_CAPTION | WS_THICKFRAME);
-+
-+ return style;
-+}
-+
-+static LONG fullscreen_exstyle(LONG exstyle)
-+{
-+ /* Filter out window decorations. */
-+ exstyle &= ~(WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE);
-+
-+ return exstyle;
-+}
-+
-+static HRESULT
-+DRI3Present_ChangeDisplaySettingsIfNeccessary( struct DRI3Present *This, DEVMODEW *new_mode ) {
-+ DEVMODEW current_mode;
-+ LONG hr;
-+
-+ ZeroMemory(&current_mode, sizeof(DEVMODEW));
-+ /* Only change the mode if necessary. */
-+ if (!EnumDisplaySettingsW(This->devname, ENUM_CURRENT_SETTINGS, &current_mode))
-+ {
-+ ERR("Failed to get current display mode.\n");
-+ } else if (current_mode.dmPelsWidth != new_mode->dmPelsWidth
-+ || current_mode.dmPelsHeight != new_mode->dmPelsHeight
-+ || (current_mode.dmDisplayFrequency != new_mode->dmDisplayFrequency
-+ && (new_mode->dmFields & DM_DISPLAYFREQUENCY)))
-+ {
-+ hr = ChangeDisplaySettingsExW(This->devname, new_mode, 0, CDS_FULLSCREEN, NULL);
-+ if (hr != DISP_CHANGE_SUCCESSFUL) {
-+ /* try again without display RefreshRate */
-+ if (new_mode->dmFields & DM_DISPLAYFREQUENCY) {
-+ new_mode->dmFields &= ~DM_DISPLAYFREQUENCY;
-+ new_mode->dmDisplayFrequency = 0;
-+ hr = ChangeDisplaySettingsExW(This->devname, new_mode, 0, CDS_FULLSCREEN, NULL);
-+ if (hr != DISP_CHANGE_SUCCESSFUL) {
-+ ERR("ChangeDisplaySettingsExW failed with 0x%08X\n", hr);
-+ return D3DERR_INVALIDCALL;
-+ }
-+ } else {
-+ ERR("ChangeDisplaySettingsExW failed with 0x%08X\n", hr);
-+ return D3DERR_INVALIDCALL;
-+ }
-+ }
-+ }
-+ return D3D_OK;
-+}
-+
-+#ifdef ID3DPresent_GetWindowOccluded
-+static struct d3d_wnd_hooks *get_last_hook(void) {
-+ struct d3d_wnd_hooks *hook = &d3d_hooks;
-+ while (hook->next) {
-+ hook = hook->next;
-+ }
-+ return hook;
-+}
-+
-+LRESULT CALLBACK HookCallback(int nCode, WPARAM wParam, LPARAM lParam)
-+{
-+ struct d3d_wnd_hooks *hook = &d3d_hooks;
-+ boolean drop_wnd_messages;
-+
-+ if (nCode < 0) {
-+ return CallNextHookEx(hhook, nCode, wParam, lParam);
-+ }
-+
-+ if (lParam) {
-+ CWPSTRUCT wndprocparams = *((CWPSTRUCT*)lParam);
-+ while (hook->next) {
-+ hook = hook->next;
-+
-+ /* skip messages for other hwnds */
-+ if (hook->focus_wnd != wndprocparams.hwnd)
-+ continue;
-+ if (!hook->present)
-+ continue;
-+
-+ switch (wndprocparams.message) {
-+ case WM_ACTIVATEAPP:
-+ if (hook->present->drop_wnd_messages)
-+ return -1;
-+
-+ drop_wnd_messages = hook->present->drop_wnd_messages;
-+ hook->present->drop_wnd_messages = TRUE;
-+ if (wndprocparams.wParam == WA_INACTIVE) {
-+ hook->present->occluded = TRUE;
-+
-+ DRI3Present_ChangeDisplaySettingsIfNeccessary(hook->present, &(hook->present->initial_mode));
-+
-+ if (!hook->present->no_window_changes &&
-+ IsWindowVisible(hook->present->params.hDeviceWindow))
-+ ShowWindow(hook->present->params.hDeviceWindow, SW_MINIMIZE);
-+ } else {
-+ hook->present->device_needs_reset |= hook->present->occluded;
-+ hook->present->occluded = FALSE;
-+
-+ if (!hook->present->no_window_changes) {
-+ /* restore window */
-+ SetWindowPos(hook->present->params.hDeviceWindow, NULL, 0, 0,
-+ hook->present->params.BackBufferWidth, hook->present->params.BackBufferHeight,
-+ SWP_NOACTIVATE | SWP_NOZORDER);
-+ }
-+
-+ if (hook->present->ex) {
-+ DEVMODEW new_mode;
-+
-+ ZeroMemory(&new_mode, sizeof(DEVMODEW));
-+ new_mode.dmPelsWidth = hook->present->params.BackBufferWidth;
-+ new_mode.dmPelsHeight = hook->present->params.BackBufferHeight;
-+ new_mode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
-+ if (hook->present->params.FullScreen_RefreshRateInHz) {
-+ new_mode.dmFields |= DM_DISPLAYFREQUENCY;
-+ new_mode.dmDisplayFrequency = hook->present->params.FullScreen_RefreshRateInHz;
-+ }
-+ new_mode.dmSize = sizeof(DEVMODEW);
-+ DRI3Present_ChangeDisplaySettingsIfNeccessary(hook->present, &new_mode);
-+ }
-+ }
-+ hook->present->drop_wnd_messages = drop_wnd_messages;
-+ break;
-+ case WM_DISPLAYCHANGE:
-+ hook->present->mode_changed = TRUE;
-+ hook->present->device_needs_reset = TRUE;
-+ break;
-+ /* TODO: handle other window messages here */
-+ default:
-+ break;
-+ }
-+ }
-+ }
-+
-+ return CallNextHookEx(hhook, nCode, wParam, lParam);
-+}
-+
-+static HRESULT dri3_present_register_window_hook( struct DRI3Present *This ) {
-+ struct d3d_wnd_hooks *lasthook;
-+ struct d3d_wnd_hooks *hook = &d3d_hooks;
-+
-+ HWND hWnd = This->focus_wnd;
-+
-+ /* let's see if already hooked */
-+ while (hook->next) {
-+ hook = hook->next;
-+ if (hook->focus_wnd == hWnd && hook->present == This)
-+ return D3DERR_INVALIDCALL;
-+ }
-+ /* create single WindowsHook in this process */
-+ if (!hhook) {
-+ // TODO: do we need to handle different threadIDs ?
-+ DWORD threadID = GetWindowThreadProcessId(hWnd, NULL);
-+ hhook = SetWindowsHookExW(WH_CALLWNDPROC, HookCallback, NULL, threadID);
-+ if (!hhook) {
-+ ERR("SetWindowsHookEx failed with 0x%08x\n", GetLastError());
-+ return D3DERR_DRIVERINTERNALERROR;
-+ }
-+ }
-+ lasthook = get_last_hook();
-+ hook = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
-+ sizeof(struct d3d_wnd_hooks));
-+ if (!hook)
-+ return E_OUTOFMEMORY;
-+ /* add window hwnd to list */
-+ lasthook->next = hook;
-+ hook->prev = lasthook;
-+ hook->focus_wnd = hWnd;
-+ hook->present = This;
-+ return D3D_OK;
-+}
-+
-+static HRESULT dri3_present_unregister_window_hook( struct DRI3Present *This ) {
-+ struct d3d_wnd_hooks *hook = &d3d_hooks;
-+
-+ HWND hWnd = This->focus_wnd;
-+
-+ /* find hook and remove it */
-+ while (hook->next) {
-+ hook = hook->next;
-+ if(hook->focus_wnd == hWnd && hook->present == This) {
-+ /* remove hook */
-+ hook->prev->next = hook->next;
-+ HeapFree(GetProcessHeap(), 0, hook);
-+ /* start again at list head */
-+ hook = &d3d_hooks;
-+ }
-+ }
-+ /* remove single process WindowsHook */
-+ if (get_last_hook() == &d3d_hooks && hhook) {
-+ if (!UnhookWindowsHookEx(hhook)) {
-+ ERR("UnhookWindowsHookEx failed with 0x%08x\n", GetLastError());
-+ }
-+ hhook = NULL;
-+ }
-+
-+ return D3D_OK;
-+}
-+
-+static BOOL WINAPI
-+DRI3Present_GetWindowOccluded( struct DRI3Present *This )
-+{
-+ /* we missed to poll occluded */
-+ if (This->device_needs_reset) {
-+ This->device_needs_reset = FALSE;
-+ return TRUE;
-+ }
-+
-+ return This->occluded;
-+}
-+#endif
-+/*----------*/
-+
-+
-+static ID3DPresentVtbl DRI3Present_vtable = {
-+ (void *)DRI3Present_QueryInterface,
-+ (void *)DRI3Present_AddRef,
-+ (void *)DRI3Present_Release,
-+ (void *)DRI3Present_SetPresentParameters,
-+ (void *)DRI3Present_D3DWindowBufferFromDmaBuf,
-+ (void *)DRI3Present_DestroyD3DWindowBuffer,
-+ (void *)DRI3Present_WaitBufferReleased,
-+ (void *)DRI3Present_FrontBufferCopy,
-+ (void *)DRI3Present_PresentBuffer,
-+ (void *)DRI3Present_GetRasterStatus,
-+ (void *)DRI3Present_GetDisplayMode,
-+ (void *)DRI3Present_GetPresentStats,
-+ (void *)DRI3Present_GetCursorPos,
-+ (void *)DRI3Present_SetCursorPos,
-+ (void *)DRI3Present_SetCursor,
-+ (void *)DRI3Present_SetGammaRamp,
-+ (void *)DRI3Present_GetWindowInfo,
-+#ifdef ID3DPresent_GetWindowOccluded
-+ (void *)DRI3Present_GetWindowOccluded
-+#endif
-+};
-+
-+static HRESULT
-+DRI3Present_ChangePresentParameters( struct DRI3Present *This,
-+ D3DPRESENT_PARAMETERS *params )
-+{
-+ HWND draw_window = params->hDeviceWindow;
-+ RECT rect;
-+ DEVMODEW new_mode;
-+
-+ if (!GetClientRect(draw_window, &rect)) {
-+ WARN("GetClientRect failed.\n");
-+ rect.right = 640;
-+ rect.bottom = 480;
-+ }
-+
-+ if (params->BackBufferWidth == 0) {
-+ params->BackBufferWidth = rect.right - rect.left;
-+ }
-+ if (params->BackBufferHeight == 0) {
-+ params->BackBufferHeight = rect.bottom - rect.top;
-+ }
-+
-+ if ((This->params.BackBufferWidth != params->BackBufferWidth) ||
-+ (This->params.BackBufferHeight != params->BackBufferHeight)) {
-+ This->mode_changed = TRUE;
-+ }
-+
-+ if (This->mode_changed || (This->params.Windowed != params->Windowed)) {
-+ if (!params->Windowed) {
-+ /* switch display mode */
-+ ZeroMemory(&new_mode, sizeof(DEVMODEW));
-+ new_mode.dmPelsWidth = params->BackBufferWidth;
-+ new_mode.dmPelsHeight = params->BackBufferHeight;
-+ new_mode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
-+ if (params->FullScreen_RefreshRateInHz) {
-+ new_mode.dmFields |= DM_DISPLAYFREQUENCY;
-+ new_mode.dmDisplayFrequency = params->FullScreen_RefreshRateInHz;
-+ }
-+ new_mode.dmSize = sizeof(DEVMODEW);
-+ DRI3Present_ChangeDisplaySettingsIfNeccessary(This, &new_mode);
-+ } else {
-+ DRI3Present_ChangeDisplaySettingsIfNeccessary(This, &This->initial_mode);
-+ }
-+ This->mode_changed = FALSE;
-+
-+ if (This->params.Windowed) {
-+ if (!params->Windowed) {
-+ LONG style, style_ex;
-+ boolean drop_wnd_messages;
-+
-+ /* switch from window to fullscreen */
-+#ifdef ID3DPresent_GetWindowOccluded
-+ if (dri3_present_register_window_hook(This)) {
-+ SetWindowPos(This->focus_wnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
-+ }
-+#else
-+ SetWindowPos(This->focus_wnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
-+#endif
-+ This->style = GetWindowLongW(draw_window, GWL_STYLE);
-+ This->style_ex = GetWindowLongW(draw_window, GWL_EXSTYLE);
-+
-+ style = fullscreen_style(This->style);
-+ style_ex = fullscreen_exstyle(This->style_ex);
-+
-+ drop_wnd_messages = This->drop_wnd_messages;
-+ This->drop_wnd_messages = TRUE;
-+
-+ SetWindowLongW(draw_window, GWL_STYLE, style);
-+ SetWindowLongW(draw_window, GWL_EXSTYLE, style_ex);
-+ SetWindowPos(draw_window, HWND_TOPMOST, 0, 0, params->BackBufferWidth,
-+ params->BackBufferHeight,
-+ SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOACTIVATE);
-+ This->drop_wnd_messages = drop_wnd_messages;
-+ }
-+ } else {
-+ if (!params->Windowed) {
-+ /* switch from fullscreen to fullscreen */
-+ MoveWindow(draw_window, 0, 0,
-+ params->BackBufferWidth,
-+ params->BackBufferHeight,
-+ TRUE);
-+ } else {
-+ LONG style, style_ex;
-+ boolean drop_wnd_messages;
-+
-+ /* switch from fullscreen to window */
-+ style = GetWindowLongW(draw_window, GWL_STYLE);
-+ style_ex = GetWindowLongW(draw_window, GWL_EXSTYLE);
-+
-+ /* These flags are set by wined3d_device_setup_fullscreen_window, not the
-+ * application, and we want to ignore them in the test below, since it's
-+ * not the application's fault that they changed. Additionally, we want to
-+ * preserve the current status of these flags (i.e. don't restore them) to
-+ * more closely emulate the behavior of Direct3D, which leaves these flags
-+ * alone when returning to windowed mode. */
-+ This->style ^= (This->style ^ style) & WS_VISIBLE;
-+ This->style_ex ^= (This->style_ex ^ style_ex) & WS_EX_TOPMOST;
-+
-+ /* Only restore the style if the application didn't modify it during the
-+ * fullscreen phase. Some applications change it before calling Reset()
-+ * when switching between windowed and fullscreen modes (HL2), some
-+ * depend on the original style (Eve Online). */
-+ drop_wnd_messages = This->drop_wnd_messages;
-+ This->drop_wnd_messages = TRUE;
-+ if (style == fullscreen_style(This->style) && style_ex == fullscreen_exstyle(This->style_ex))
-+ {
-+ SetWindowLongW(draw_window, GWL_STYLE, style);
-+ SetWindowLongW(draw_window, GWL_EXSTYLE, style_ex);
-+ }
-+ SetWindowPos(draw_window, 0, 0, 0, 0, 0, SWP_FRAMECHANGED |
-+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
-+ SWP_NOACTIVATE);
-+ This->drop_wnd_messages = drop_wnd_messages;
-+
-+#ifdef ID3DPresent_GetWindowOccluded
-+ dri3_present_unregister_window_hook(This);
-+#endif
-+ This->style = 0;
-+ This->style_ex = 0;
-+ }
-+ }
-+ } else if (!params->Windowed) {
-+ LONG style, style_ex;
-+ /* move draw window back to place */
-+
-+ style = GetWindowLongW(draw_window, GWL_STYLE);
-+ style_ex = GetWindowLongW(draw_window, GWL_EXSTYLE);
-+
-+ style = fullscreen_style(style);
-+ style_ex = fullscreen_exstyle(style_ex);
-+
-+ SetWindowLongW(draw_window, GWL_STYLE, style);
-+ SetWindowLongW(draw_window, GWL_EXSTYLE, style_ex);
-+ SetWindowPos(draw_window, HWND_TOPMOST, 0, 0, params->BackBufferWidth,
-+ params->BackBufferHeight,
-+ SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOACTIVATE);
-+ }
-+
-+ This->params = *params;
-+ return D3D_OK;
-+}
-+
-+static HRESULT
-+DRI3Present_new( Display *gdi_display,
-+ const WCHAR *devname,
-+ D3DPRESENT_PARAMETERS *params,
-+ HWND focus_wnd,
-+ struct DRI3Present **out,
-+ boolean ex,
-+ boolean no_window_changes )
-+{
-+ struct DRI3Present *This;
-+
-+ if (!focus_wnd) { focus_wnd = params->hDeviceWindow; }
-+ if (!focus_wnd) {
-+ ERR("No focus HWND specified for presentation backend.\n");
-+ return D3DERR_INVALIDCALL;
-+ }
-+
-+ This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
-+ sizeof(struct DRI3Present));
-+ if (!This) {
-+ ERR("Out of memory.\n");
-+ return E_OUTOFMEMORY;
-+ }
-+
-+ This->gdi_display = gdi_display;
-+ This->vtable = &DRI3Present_vtable;
-+ This->refs = 1;
-+ This->focus_wnd = focus_wnd;
-+ This->params.Windowed = TRUE;
-+ This->ex = ex;
-+ This->no_window_changes = no_window_changes;
-+
-+ strcpyW(This->devname, devname);
-+
-+ ZeroMemory(&(This->initial_mode), sizeof(This->initial_mode));
-+ This->initial_mode.dmSize = sizeof(This->initial_mode);
-+
-+ EnumDisplaySettingsExW(This->devname, ENUM_CURRENT_SETTINGS, &(This->initial_mode), 0);
-+
-+ PRESENTInit(gdi_display, &(This->present_priv));
-+#ifdef D3DADAPTER9_DRI2
-+ if (is_dri2_fallback)
-+ DRI2FallbackInit(gdi_display, &(This->dri2_priv));
-+#endif
-+ *out = This;
-+
-+ return D3D_OK;
-+}
-+
-+struct DRI3PresentGroup
-+{
-+ /* COM vtable */
-+ void *vtable;
-+ /* IUnknown reference count */
-+ LONG refs;
-+
-+ struct DRI3Present **present_backends;
-+ unsigned npresent_backends;
-+ Display *gdi_display;
-+ boolean ex;
-+ boolean no_window_changes;
-+};
-+
-+static ULONG WINAPI
-+DRI3PresentGroup_AddRef( struct DRI3PresentGroup *This )
-+{
-+ ULONG refs = InterlockedIncrement(&This->refs);
-+ TRACE("%p increasing refcount to %u.\n", This, refs);
-+ return refs;
-+}
-+
-+static ULONG WINAPI
-+DRI3PresentGroup_Release( struct DRI3PresentGroup *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) {
-+ if (This->present_backends[i])
-+ DRI3Present_Release(This->present_backends[i]);
-+ }
-+ HeapFree(GetProcessHeap(), 0, This->present_backends);
-+ }
-+ HeapFree(GetProcessHeap(), 0, This);
-+ }
-+ return refs;
-+}
-+
-+static HRESULT WINAPI
-+DRI3PresentGroup_QueryInterface( struct DRI3PresentGroup *This,
-+ REFIID riid,
-+ void **ppvObject )
-+{
-+ if (!ppvObject) { return E_POINTER; }
-+ if (IsEqualGUID(&IID_ID3DPresentGroup, riid) ||
-+ IsEqualGUID(&IID_IUnknown, riid)) {
-+ *ppvObject = This;
-+ DRI3PresentGroup_AddRef(This);
-+ return S_OK;
-+ }
-+
-+ WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
-+ *ppvObject = NULL;
-+
-+ return E_NOINTERFACE;
-+}
-+
-+static UINT WINAPI
-+DRI3PresentGroup_GetMultiheadCount( struct DRI3PresentGroup *This )
-+{
-+ FIXME("(%p), stub!\n", This);
-+ return 1;
-+}
-+
-+static HRESULT WINAPI
-+DRI3PresentGroup_GetPresent( struct DRI3PresentGroup *This,
-+ UINT Index,
-+ ID3DPresent **ppPresent )
-+{
-+ if (Index >= DRI3PresentGroup_GetMultiheadCount(This)) {
-+ ERR("Index >= MultiHeadCount\n");
-+ return D3DERR_INVALIDCALL;
-+ }
-+ DRI3Present_AddRef(This->present_backends[Index]);
-+ *ppPresent = (ID3DPresent *)This->present_backends[Index];
-+
-+ return D3D_OK;
-+}
-+
-+static HRESULT WINAPI
-+DRI3PresentGroup_CreateAdditionalPresent( struct DRI3PresentGroup *This,
-+ D3DPRESENT_PARAMETERS *pPresentationParameters,
-+ ID3DPresent **ppPresent )
-+{
-+ HRESULT hr;
-+ hr = DRI3Present_new(This->gdi_display, This->present_backends[0]->devname,
-+ pPresentationParameters, 0, (struct DRI3Present **)ppPresent,
-+ This->ex, This->no_window_changes);
-+ return hr;
-+}
-+
-+static void WINAPI
-+DRI3PresentGroup_GetVersion( struct DRI3PresentGroup *This,
-+ int *major,
-+ int *minor)
-+{
-+ *major = WINE_D3DADAPTER_DRIVER_PRESENT_VERSION_MAJOR;
-+ *minor = WINE_D3DADAPTER_DRIVER_PRESENT_VERSION_MINOR;
-+}
-+
-+static ID3DPresentGroupVtbl DRI3PresentGroup_vtable = {
-+ (void *)DRI3PresentGroup_QueryInterface,
-+ (void *)DRI3PresentGroup_AddRef,
-+ (void *)DRI3PresentGroup_Release,
-+ (void *)DRI3PresentGroup_GetMultiheadCount,
-+ (void *)DRI3PresentGroup_GetPresent,
-+ (void *)DRI3PresentGroup_CreateAdditionalPresent,
-+ (void *)DRI3PresentGroup_GetVersion
-+};
-+
-+HRESULT
-+present_create_present_group( Display *gdi_display,
-+ const WCHAR *device_name,
-+ UINT adapter,
-+ HWND focus_wnd,
-+ D3DPRESENT_PARAMETERS *params,
-+ unsigned nparams,
-+ ID3DPresentGroup **group,
-+ boolean ex,
-+ boolean no_window_changes )
-+{
-+ struct DRI3PresentGroup *This =
-+ HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
-+ sizeof(struct DRI3PresentGroup));
-+ DISPLAY_DEVICEW dd;
-+ HRESULT hr;
-+ unsigned i;
-+
-+ if (!This) {
-+ ERR("Out of memory.\n");
-+ return E_OUTOFMEMORY;
-+ }
-+
-+ This->gdi_display = gdi_display;
-+ This->vtable = &DRI3PresentGroup_vtable;
-+ This->refs = 1;
-+ This->ex = ex;
-+ This->no_window_changes = no_window_changes;
-+ This->npresent_backends = nparams;
-+ This->present_backends = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
-+ This->npresent_backends *
-+ sizeof(struct DRI3Present *));
-+ if (!This->present_backends) {
-+ DRI3PresentGroup_Release(This);
-+ ERR("Out of memory.\n");
-+ return E_OUTOFMEMORY;
-+ }
-+
-+ if (nparams != 1) { adapter = 0; }
-+ for (i = 0; i < This->npresent_backends; ++i) {
-+ ZeroMemory(&dd, sizeof(dd));
-+ dd.cb = sizeof(dd);
-+ /* 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 = DRI3Present_new(gdi_display, dd.DeviceName, &params[i],
-+ focus_wnd, &This->present_backends[i],
-+ This->ex, This->no_window_changes);
-+ if (FAILED(hr)) {
-+ DRI3PresentGroup_Release(This);
-+ return hr;
-+ }
-+ }
-+
-+ *group = (ID3DPresentGroup *)This;
-+ TRACE("Returning %p\n", *group);
-+
-+ return D3D_OK;
-+}
-+
-+HRESULT
-+present_create_adapter9( Display *gdi_display,
-+ HDC hdc,
-+ ID3DAdapter9 **out )
-+{
-+ struct x11drv_escape_get_drawable extesc = { X11DRV_GET_DRAWABLE };
-+ HRESULT hr;
-+ int fd;
-+
-+ if (!d3d9_drm) {
-+ ERR("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) {
-+ ERR("X11 drawable lookup failed (hdc=%p)\n", hdc);
-+ }
-+
-+#ifdef D3DADAPTER9_DRI2
-+ if (!is_dri2_fallback && !DRI3Open(gdi_display, DefaultScreen(gdi_display), &fd)) {
-+#else
-+ if (!DRI3Open(gdi_display, DefaultScreen(gdi_display), &fd)) {
-+#endif
-+ ERR("DRI3Open failed (fd=%d)\n", fd);
-+ return D3DERR_DRIVERINTERNALERROR;
-+ }
-+#ifdef D3DADAPTER9_DRI2
-+ if (is_dri2_fallback && !DRI2FallbackOpen(gdi_display, DefaultScreen(gdi_display), &fd)) {
-+ ERR("DRI2Open failed (fd=%d)\n", fd);
-+ return D3DERR_DRIVERINTERNALERROR;
-+ }
-+#endif
-+ hr = d3d9_drm->create_adapter(fd, out);
-+ if (FAILED(hr)) {
-+ ERR("Unable to create ID3DAdapter9 (fd=%d)\n", fd);
-+ return hr;
-+ }
-+
-+ TRACE("Created ID3DAdapter9 with fd %d\n", fd);
-+
-+ return D3D_OK;
-+}
-+
-+BOOL
-+has_d3dadapter( Display *gdi_display )
-+{
-+ static const void * WINAPI (*pD3DAdapter9GetProc)(const char *);
-+ static void *handle = NULL;
-+ static int done = 0;
-+
-+ char errbuf[256];
-+
-+#if !defined(SONAME_D3DADAPTER9)
-+ return FALSE;
-+#endif
-+
-+ /* like in opengl.c (single threaded assumption OK?) */
-+ if (done) { return handle != NULL; }
-+ done = 1;
-+
-+ handle = wine_dlopen(D3D_MODULE_DIR "/" SONAME_D3DADAPTER9,
-+ RTLD_GLOBAL | RTLD_NOW, errbuf, sizeof(errbuf));
-+ if (!handle) {
-+ ERR("Failed to load %s: %s\n", SONAME_D3DADAPTER9, errbuf);
-+ goto cleanup;
-+ }
-+
-+ /* find our entry point in d3dadapter9 */
-+ pD3DAdapter9GetProc = wine_dlsym(handle, "D3DAdapter9GetProc",
-+ errbuf, sizeof(errbuf));
-+ if (!pD3DAdapter9GetProc) {
-+ ERR("Failed to get the entry point from %s: %s",
-+ SONAME_D3DADAPTER9, 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_D3DADAPTER9, 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_D3DADAPTER9, d3d9_drm->major_version,
-+ d3d9_drm->minor_version, D3DADAPTER9DRM_MAJOR);
-+ goto cleanup;
-+ }
-+
-+ /* this will be used to store d3d_drawables */
-+ d3d_hwnd_context = XUniqueContext();
-+
-+ if (!PRESENTCheckExtension(gdi_display, 1, 0)) {
-+ ERR("Unable to query PRESENT.\n");
-+ goto cleanup;
-+ }
-+
-+ if (!DRI3CheckExtension(gdi_display, 1, 0)) {
-+#ifndef D3DADAPTER9_DRI2
-+ ERR("Unable to query DRI3.\n");
-+ goto cleanup;
-+#else
-+ ERR("Unable to query DRI3. Trying DRI2 fallback (slower performance).\n");
-+ is_dri2_fallback = 1;
-+ if (!DRI2FallbackCheckSupport(gdi_display)) {
-+ ERR("DRI2 fallback unsupported\n");
-+ goto cleanup;
-+ }
-+#endif
-+ }
-+
-+ return TRUE;
-+
-+cleanup:
-+ ERR("\033[1;31m\nNative Direct3D 9 will be unavailable."
-+ "\nFor more information visit https://wiki.ixit.cz/d3d9\033[0m\n");
-+ if (handle) {
-+ wine_dlclose(handle, NULL, 0);
-+ handle = NULL;
-+ }
-+
-+ return FALSE;
-+}
-diff --git a/dlls/d3d9-nine/present.h b/dlls/d3d9-nine/present.h
-new file mode 100644
-index 0000000..52791a5
---- /dev/null
-+++ b/dlls/d3d9-nine/present.h
-@@ -0,0 +1,36 @@
-+/*
-+ * Wine present interface
-+ *
-+ * Copyright 2015 Patrick Rudolph
-+ *
-+ * 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_PRESENT_H
-+#define __WINE_PRESENT_H
-+
-+#ifndef __WINE_CONFIG_H
-+# error You must include config.h to use this header
-+#endif
-+
-+#include <X11/Xlib.h>
-+
-+HRESULT present_create_present_group(Display *gdi_display, const WCHAR *device_name, UINT adapter, HWND focus, D3DPRESENT_PARAMETERS *params, unsigned nparams, ID3DPresentGroup **group, boolean ex, boolean no_window_changes);
-+
-+HRESULT present_create_adapter9(Display *gdi_display, HDC hdc, ID3DAdapter9 **adapter);
-+
-+BOOL has_d3dadapter(Display *gdi_display);
-+
-+#endif /* __WINE_DRI3_H */
-diff --git a/dlls/d3d9-nine/version.rc b/dlls/d3d9-nine/version.rc
-new file mode 100644
-index 0000000..bfafc2f
---- /dev/null
-+++ b/dlls/d3d9-nine/version.rc
-@@ -0,0 +1,26 @@
-+/*
-+ * Copyright 2015 Patrick Rudolph
-+ *
-+ * 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
-+ */
-+
-+#define WINE_FILEDESCRIPTION_STR "Wine Gallium Nine Direct3D"
-+#define WINE_FILENAME_STR "d3d9-nine.dll"
-+#define WINE_FILEVERSION 5,3,1,904
-+#define WINE_FILEVERSION_STR "5.3.1.904"
-+#define WINE_PRODUCTVERSION 5,3,1,904
-+#define WINE_PRODUCTVERSION_STR "5.3.1.904"
-+
-+#include "wine/wine_common_ver.rc"
-diff --git a/dlls/d3d9/Makefile.in b/dlls/d3d9/Makefile.in
-index 1c05f5a..dc06d68 100644
---- a/dlls/d3d9/Makefile.in
-+++ b/dlls/d3d9/Makefile.in
-@@ -1,6 +1,6 @@
- MODULE = d3d9.dll
- IMPORTLIB = d3d9
--IMPORTS = dxguid uuid wined3d
-+IMPORTS = dxguid uuid advapi32 wined3d
-
- C_SRCS = \
- buffer.c \
-diff --git a/dlls/d3d9/tests/d3d9ex.c b/dlls/d3d9/tests/d3d9ex.c
-index 151db41..5314915 100644
---- a/dlls/d3d9/tests/d3d9ex.c
-+++ b/dlls/d3d9/tests/d3d9ex.c
-@@ -1410,6 +1410,7 @@ static void test_lost_device(void)
- HRESULT hr;
- BOOL ret;
- struct device_desc desc;
-+ IDirect3DSwapChain9 *swapchain;
-
- window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
- 0, 0, 640, 480, NULL, NULL, NULL, NULL);
-@@ -1434,6 +1435,12 @@ static void test_lost_device(void)
- hr = IDirect3DDevice9Ex_CheckDeviceState(device, NULL);
- ok(hr == S_PRESENT_OCCLUDED, "Got unexpected hr %#x.\n", hr);
-
-+ hr = IDirect3DDevice9Ex_GetSwapChain(device, 0, &swapchain);
-+ ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
-+ hr = IDirect3DSwapChain9_Present(swapchain, NULL, NULL, NULL, NULL, 0);
-+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
-+ IDirect3DSwapChain9_Release(swapchain);
-+
- ret = SetForegroundWindow(GetDesktopWindow());
- ok(ret, "Failed to set foreground window.\n");
- hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
-@@ -1447,6 +1454,12 @@ static void test_lost_device(void)
- hr = IDirect3DDevice9Ex_CheckDeviceState(device, NULL);
- ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
-
-+ hr = IDirect3DDevice9Ex_GetSwapChain(device, 0, &swapchain);
-+ ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
-+ hr = IDirect3DSwapChain9_Present(swapchain, NULL, NULL, NULL, NULL, 0);
-+ ok(hr == S_PRESENT_OCCLUDED, "Got unexpected hr %#x.\n", hr);
-+ IDirect3DSwapChain9_Release(swapchain);
-+
- ret = SetForegroundWindow(window);
- ok(ret, "Failed to set foreground window.\n");
- hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
-@@ -1460,6 +1473,12 @@ static void test_lost_device(void)
- hr = IDirect3DDevice9Ex_CheckDeviceState(device, NULL);
- ok(hr == S_PRESENT_OCCLUDED, "Got unexpected hr %#x.\n", hr);
-
-+ hr = IDirect3DDevice9Ex_GetSwapChain(device, 0, &swapchain);
-+ ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
-+ hr = IDirect3DSwapChain9_Present(swapchain, NULL, NULL, NULL, NULL, 0);
-+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
-+ IDirect3DSwapChain9_Release(swapchain);
-+
- desc.width = 1024;
- desc.height = 768;
- hr = reset_device(device, &desc);
-@@ -1489,6 +1508,12 @@ static void test_lost_device(void)
- hr = IDirect3DDevice9Ex_CheckDeviceState(device, NULL);
- todo_wine ok(hr == S_PRESENT_MODE_CHANGED, "Got unexpected hr %#x.\n", hr);
-
-+ hr = IDirect3DDevice9Ex_GetSwapChain(device, 0, &swapchain);
-+ ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
-+ hr = IDirect3DSwapChain9_Present(swapchain, NULL, NULL, NULL, NULL, 0);
-+ ok(hr == S_PRESENT_MODE_CHANGED, "Got unexpected hr %#x.\n", hr);
-+ IDirect3DSwapChain9_Release(swapchain);
-+
- hr = reset_device(device, &desc);
- ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
- hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
-@@ -1502,6 +1527,12 @@ static void test_lost_device(void)
- hr = IDirect3DDevice9Ex_CheckDeviceState(device, NULL);
- ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
-
-+ hr = IDirect3DDevice9Ex_GetSwapChain(device, 0, &swapchain);
-+ ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
-+ hr = IDirect3DSwapChain9_Present(swapchain, NULL, NULL, NULL, NULL, 0);
-+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
-+ IDirect3DSwapChain9_Release(swapchain);
-+
- ret = SetForegroundWindow(GetDesktopWindow());
- ok(ret, "Failed to set foreground window.\n");
- hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
-diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c
-index 326e789..0ff7211 100644
---- a/dlls/d3d9/tests/device.c
-+++ b/dlls/d3d9/tests/device.c
-@@ -8222,10 +8222,10 @@ done:
-
- static void test_vidmem_accounting(void)
- {
-- IDirect3DDevice9 *device;
-+ IDirect3DDevice9 *device, *device2;
- IDirect3D9 *d3d9;
- ULONG refcount;
-- HWND window;
-+ HWND window, window2;
- HRESULT hr = D3D_OK;
- IDirect3DTexture9 *textures[20];
- unsigned int i;
-@@ -8233,6 +8233,8 @@ static void test_vidmem_accounting(void)
-
- window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
- 0, 0, 640, 480, 0, 0, 0, 0);
-+ window2 = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
-+ 0, 0, 640, 480, 0, 0, 0, 0);
- d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
- ok(!!d3d9, "Failed to create a D3D object.\n");
- if (!(device = create_device(d3d9, window, NULL)))
-@@ -8267,6 +8269,43 @@ static void test_vidmem_accounting(void)
- IDirect3DTexture9_Release(textures[i]);
- }
-
-+ /* Multi-device testing */
-+ if (!(device2 = create_device(d3d9, window2, NULL)))
-+ {
-+ skip("Failed to create a D3D device, skipping tests.\n");
-+ refcount = IDirect3DDevice9_Release(device);
-+ ok(!refcount, "Device has %u references left.\n", refcount);
-+ IDirect3D9_Release(d3d9);
-+ DestroyWindow(window2);
-+ DestroyWindow(window);
-+ return;
-+ }
-+
-+ vidmem_start = IDirect3DDevice9_GetAvailableTextureMem(device);
-+ memset(textures, 0, sizeof(textures));
-+ for (i = 0; (i < sizeof(textures) / sizeof(*textures)) && SUCCEEDED(hr); i++)
-+ {
-+ hr = IDirect3DDevice9_CreateTexture(device2, 1024, 1024, 1, D3DUSAGE_RENDERTARGET,
-+ D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &textures[i], NULL);
-+ /* D3DERR_OUTOFVIDEOMEMORY is returned when the card runs out of video memory
-+ * E_FAIL is returned on address space or system memory exhaustion */
-+ ok(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY,
-+ "Failed to create texture, hr %#x.\n", hr);
-+ }
-+ vidmem_end = IDirect3DDevice9_GetAvailableTextureMem(device);
-+
-+ /* Windows 7 uses device private counters */
-+ ok(vidmem_start > vidmem_end || broken(vidmem_start == vidmem_end), "Expected available texture memory to decrease during texture creation.\n");
-+ diff = vidmem_start - vidmem_end;
-+ ok(diff > 1024 * 1024 * 2 * i || broken(diff == 0), "Expected a video memory difference of at least %u MB, got %u MB.\n",
-+ 2 * i, diff / 1024 / 1024);
-+
-+ for (i = 0; i < sizeof(textures) / sizeof(*textures); i++)
-+ {
-+ if (textures[i])
-+ IDirect3DTexture9_Release(textures[i]);
-+ }
-+
- refcount = IDirect3DDevice9_Release(device);
- ok(!refcount, "Device has %u references left.\n", refcount);
- IDirect3D9_Release(d3d9);
-@@ -9987,6 +10026,7 @@ static void test_lost_device(void)
- HWND window;
- HRESULT hr;
- BOOL ret;
-+ IDirect3DSwapChain9 *swapchain;
-
- window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
- 0, 0, 640, 480, NULL, NULL, NULL, NULL);
-@@ -10014,6 +10054,12 @@ static void test_lost_device(void)
- hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
- ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
-
-+ hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain);
-+ ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
-+ hr = IDirect3DSwapChain9_Present(swapchain, NULL, NULL, NULL, NULL, 0);
-+ ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
-+ IDirect3DSwapChain9_Release(swapchain);
-+
- ret = ShowWindow(window, SW_RESTORE);
- ok(ret, "Failed to restore window.\n");
- ret = SetForegroundWindow(window);
-@@ -10023,6 +10069,12 @@ static void test_lost_device(void)
- hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
- ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
-
-+ hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain);
-+ ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
-+ hr = IDirect3DSwapChain9_Present(swapchain, NULL, NULL, NULL, NULL, 0);
-+ ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
-+ IDirect3DSwapChain9_Release(swapchain);
-+
- hr = reset_device(device, &device_desc);
- ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
- hr = IDirect3DDevice9_TestCooperativeLevel(device);
-@@ -10030,6 +10082,12 @@ static void test_lost_device(void)
- hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
- ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
-
-+ hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain);
-+ ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
-+ hr = IDirect3DSwapChain9_Present(swapchain, NULL, NULL, NULL, NULL, 0);
-+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
-+ IDirect3DSwapChain9_Release(swapchain);
-+
- device_desc.flags = 0;
- hr = reset_device(device, &device_desc);
- ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
-diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c
-index b328b94..74d9dd9 100644
---- a/dlls/d3d9/tests/visual.c
-+++ b/dlls/d3d9/tests/visual.c
-@@ -8535,6 +8535,167 @@ done:
- DestroyWindow(window);
- }
-
-+static void test_blend_invalid_arg(void)
-+{
-+ IDirect3DSurface9 *backbuffer, *offscreen;
-+ IDirect3DTexture9 *offscreenTexture;
-+ IDirect3DDevice9 *device;
-+ IDirect3D9 *d3d;
-+ D3DCOLOR color;
-+ ULONG refcount;
-+ HWND window;
-+ HRESULT hr;
-+ DWORD rs;
-+
-+ static const struct
-+ {
-+ struct vec3 position;
-+ DWORD diffuse;
-+ }
-+ quad1[] =
-+ {
-+ {{-1.0f, -1.0f, 0.1f}, 0x4000ff00},
-+ {{-1.0f, 0.0f, 0.1f}, 0x4000ff00},
-+ {{ 0.0f, -1.0f, 0.1f}, 0x4000ff00},
-+ {{ 0.0f, 0.0f, 0.1f}, 0x4000ff00},
-+ },
-+ quad2[] =
-+ {
-+ {{ 0.0f, 0.0f, 0.1f}, 0x4000ff00},
-+ {{ 0.0f, 1.0f, 0.1f}, 0x4000ff00},
-+ {{ 1.0f, 0.0f, 0.1f}, 0x4000ff00},
-+ {{ 1.0f, 1.0f, 0.1f}, 0x4000ff00},
-+ },
-+ quad3[] =
-+ {
-+ {{-1.0f, 0.0f, 0.1f}, 0xc00000ff},
-+ {{-1.0f, 1.0f, 0.1f}, 0xc00000ff},
-+ {{ 0.0f, 0.0f, 0.1f}, 0xc00000ff},
-+ {{ 0.0f, 1.0f, 0.1f}, 0xc00000ff},
-+ },
-+ quad4[] =
-+ {
-+ {{ 0.0f, -1.0f, 0.1f}, 0xc00000ff},
-+ {{ 0.0f, 0.0f, 0.1f}, 0xc00000ff},
-+ {{ 1.0f, -1.0f, 0.1f}, 0xc00000ff},
-+ {{ 1.0f, 0.0f, 0.1f}, 0xc00000ff},
-+ };
-+
-+ window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
-+ 0, 0, 640, 480, NULL, NULL, NULL, NULL);
-+ d3d = Direct3DCreate9(D3D_SDK_VERSION);
-+ ok(!!d3d, "Failed to create a D3D object.\n");
-+ if (!(device = create_device(d3d, window, window, TRUE)))
-+ {
-+ skip("Failed to create a D3D device, skipping tests.\n");
-+ goto done;
-+ }
-+ /* Clear the render target with alpha = 0.5 */
-+ hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x80ff0000, 1.0f, 0);
-+ ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
-+
-+ hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET,
-+ D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &offscreenTexture, NULL);
-+ ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
-+
-+ hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
-+ ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
-+
-+ hr = IDirect3DTexture9_GetSurfaceLevel(offscreenTexture, 0, &offscreen);
-+ ok(hr == D3D_OK, "Can't get offscreen surface, hr = %08x\n", hr);
-+
-+ hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
-+ ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr = %#08x\n", hr);
-+
-+ hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
-+ ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
-+ hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
-+ ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
-+ hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
-+ ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
-+ hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
-+ ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
-+ hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
-+ ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
-+
-+ hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, TRUE);
-+ ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
-+ hr = IDirect3DDevice9_BeginScene(device);
-+ ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
-+
-+ /* draw quad to test default renderstate
-+ * expect D3DRS_SRCBLEND == D3DBLEND_ONE
-+ * expect D3DRS_DESTBLEND == D3DBLEND_ZERO */
-+ hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(quad1[0]));
-+ ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
-+
-+ /* set invalid value and expect D3DBLEND_ZERO instead */
-+ hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, 0);
-+ ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
-+ hr = IDirect3DDevice9_GetRenderState(device, D3DRS_SRCBLEND, &rs);
-+ ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
-+ ok(rs == 0, "Unexpected renderstate %#x.\n", rs);
-+ hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
-+ ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
-+
-+ hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0]));
-+ ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
-+ /* set non default valid values */
-+ hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
-+ ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
-+ hr = IDirect3DDevice9_GetRenderState(device, D3DRS_SRCBLEND, &rs);
-+ ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
-+ ok(rs == D3DBLEND_SRCALPHA, "Unexpected renderstate %#x.\n", rs);
-+ hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
-+ ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
-+ hr = IDirect3DDevice9_GetRenderState(device, D3DRS_DESTBLEND, &rs);
-+ ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
-+ ok(rs == D3DBLEND_INVSRCALPHA, "Failed to get render state, hr %#x.\n", hr);
-+
-+ hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(quad3[0]));
-+ ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
-+
-+ /* set invalid value and expect D3DBLEND_ZERO instead */
-+ hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, 200);
-+ ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
-+ hr = IDirect3DDevice9_GetRenderState(device, D3DRS_DESTBLEND, &rs);
-+ ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
-+ ok(rs == 200, "Failed to get render state, hr %#x.\n", hr);
-+
-+ hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, sizeof(quad4[0]));
-+ ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
-+
-+ hr = IDirect3DDevice9_EndScene(device);
-+ ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
-+
-+ color = getPixelColor(device, 160, 360);
-+ ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00), 1),
-+ "D3DRS_SRCBLEND ONE returned color %08x, expected 0x0000FF00\n", color);
-+
-+ color = getPixelColor(device, 480, 120);
-+ ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xbf, 0x00, 0x00), 1),
-+ "invalid D3DRS_SRCBLEND returned color %08x, expected 0x00bf0000\n", color);
-+
-+ color = getPixelColor(device, 160, 120);
-+ ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x3f, 0x00, 0xC0), 1),
-+ "D3DRS_SRCBLEND SRCALPHA returned color %08x, expected 0x003f00C0\n", color);
-+
-+ color = getPixelColor(device, 480, 360);
-+ ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0xC0), 1),
-+ "invalid D3DRS_DESTBLEND returned color %08x, expected 0x000000C0\n", color);
-+
-+ IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
-+
-+ IDirect3DSurface9_Release(backbuffer);
-+ IDirect3DTexture9_Release(offscreenTexture);
-+ IDirect3DSurface9_Release(offscreen);
-+ refcount = IDirect3DDevice9_Release(device);
-+ ok(!refcount, "Device has %u references left.\n", refcount);
-+done:
-+ IDirect3D9_Release(d3d);
-+ DestroyWindow(window);
-+}
-+
- static void fixed_function_decl_test(void)
- {
- IDirect3DVertexDeclaration9 *dcl_float = NULL, *dcl_short = NULL, *dcl_ubyte = NULL, *dcl_color = NULL;
-@@ -12734,6 +12895,9 @@ static void alphatest_test(void)
- }
- testdata[] =
- {
-+ /* test invalid values, D3DCMP_NEVER for values less than D3DCMP_NEVER,
-+ * D3DCMP_ALWAYS for values greater than D3DCMP_ALWAYS */
-+ {D3DCMP_NEVER-1, ALPHATEST_FAILED, ALPHATEST_FAILED, ALPHATEST_FAILED},
- {D3DCMP_NEVER, ALPHATEST_FAILED, ALPHATEST_FAILED, ALPHATEST_FAILED},
- {D3DCMP_LESS, ALPHATEST_PASSED, ALPHATEST_FAILED, ALPHATEST_FAILED},
- {D3DCMP_EQUAL, ALPHATEST_FAILED, ALPHATEST_PASSED, ALPHATEST_FAILED},
-@@ -12742,6 +12906,10 @@ static void alphatest_test(void)
- {D3DCMP_NOTEQUAL, ALPHATEST_PASSED, ALPHATEST_FAILED, ALPHATEST_PASSED},
- {D3DCMP_GREATEREQUAL, ALPHATEST_FAILED, ALPHATEST_PASSED, ALPHATEST_PASSED},
- {D3DCMP_ALWAYS, ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_PASSED},
-+ {D3DCMP_ALWAYS+1, ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_PASSED},
-+ {D3DCMP_ALWAYS+2, ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_PASSED},
-+ {D3DCMP_ALWAYS+3, ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_PASSED},
-+ {0xdeadbeef, ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_PASSED},
- };
- static const struct
- {
-@@ -18087,6 +18255,27 @@ static void test_negative_fixedfunction_fog(void)
- D3DFOG_LINEAR, D3DFOG_NONE, 0x0000ff00, 0x0000ff00, 0x0000ff00},
- {D3DFVF_XYZ, quad, sizeof(*quad), &zero, { 0.0f}, {1.0f},
- D3DFOG_EXP, D3DFOG_NONE, 0x009b6400, 0x009b6400, 0x009b6400},
-+ /* test invalid values, expect a modulo 4 on samplerstate */
-+ {D3DFVF_XYZ, quad, sizeof(*quad), &zero, { 0.0f}, {1.0f},
-+ D3DFOG_LINEAR+1, D3DFOG_NONE, 0x0000ff00, 0x009b6400, 0x009b6400},
-+ {D3DFVF_XYZ, quad, sizeof(*quad), &zero, { 0.0f}, {1.0f},
-+ D3DFOG_LINEAR+2, D3DFOG_NONE, 0x00c73800, 0x009b6400, 0x009b6400},
-+ {D3DFVF_XYZ, quad, sizeof(*quad), &zero, { 0.0f}, {1.0f},
-+ D3DFOG_LINEAR+3, D3DFOG_NONE, 0x00c73800, 0x009b6400, 0x009b6400},
-+ {D3DFVF_XYZ, quad, sizeof(*quad), &zero, { 0.0f}, {1.0f},
-+ D3DFOG_LINEAR+4, D3DFOG_NONE, 0x007f7f00, 0x009b6400, 0x009b6400},
-+ {D3DFVF_XYZ, quad, sizeof(*quad), &zero, { 0.0f}, {1.0f},
-+ D3DFOG_LINEAR+5, D3DFOG_NONE, 0x0000ff00, 0x009b6400, 0x009b6400},
-+ {D3DFVF_XYZ, quad, sizeof(*quad), &zero, { 0.0f}, {1.0f},
-+ D3DFOG_LINEAR+6, D3DFOG_NONE, 0x00c73800, 0x009b6400, 0x009b6400},
-+ {D3DFVF_XYZ, quad, sizeof(*quad), &zero, { 0.0f}, {1.0f},
-+ D3DFOG_LINEAR+7, D3DFOG_NONE, 0x00c73800, 0x009b6400, 0x009b6400},
-+ {D3DFVF_XYZ, quad, sizeof(*quad), &zero, { 0.0f}, {1.0f},
-+ D3DFOG_LINEAR+8, D3DFOG_NONE, 0x007f7f00, 0x009b6400, 0x009b6400},
-+ {D3DFVF_XYZ, quad, sizeof(*quad), &zero, { 0.0f}, {1.0f},
-+ D3DFOG_LINEAR+9, D3DFOG_NONE, 0x0000ff00, 0x009b6400, 0x009b6400},
-+ {D3DFVF_XYZ, quad, sizeof(*quad), &zero, { 0.0f}, {1.0f},
-+ D3DFOG_LINEAR+10, D3DFOG_NONE, 0x00c73800, 0x009b6400, 0x009b6400},
- };
- D3DCAPS9 caps;
-
-@@ -20511,4 +20700,5 @@ START_TEST(visual)
- test_depthbias();
- test_flip();
- test_uninitialized_varyings();
-+ test_blend_invalid_arg();
- }
-diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
-index 74feb97..d331513 100644
---- a/dlls/ntdll/loader.c
-+++ b/dlls/ntdll/loader.c
-@@ -92,6 +92,7 @@ struct builtin_load_info
- {
- const WCHAR *load_path;
- const WCHAR *filename;
-+ const WCHAR *fakemodule;
- NTSTATUS status;
- WINE_MODREF *wm;
- };
-@@ -117,7 +118,8 @@ static WINE_MODREF *cached_modref;
- static WINE_MODREF *current_modref;
- static WINE_MODREF *last_failed_modref;
-
--static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_MODREF** pwm );
-+static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, LPCWSTR fakemodule,
-+ DWORD flags, WINE_MODREF** pwm );
- static NTSTATUS process_attach( WINE_MODREF *wm, LPVOID lpReserved );
- static FARPROC find_ordinal_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY *exports,
- DWORD exp_size, DWORD ordinal, LPCWSTR load_path );
-@@ -443,7 +445,7 @@ static FARPROC find_forwarded_export( HMODULE module, const char *forward, LPCWS
- if (!(wm = find_basename_module( mod_name )))
- {
- TRACE( "delay loading %s for '%s'\n", debugstr_w(mod_name), forward );
-- if (load_dll( load_path, mod_name, 0, &wm ) == STATUS_SUCCESS &&
-+ if (load_dll( load_path, mod_name, NULL, 0, &wm ) == STATUS_SUCCESS &&
- !(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS))
- {
- if (process_attach( wm, NULL ) != STATUS_SUCCESS)
-@@ -592,7 +594,7 @@ static WINE_MODREF *import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *d
- {
- ascii_to_unicode( buffer, name, len );
- buffer[len] = 0;
-- status = load_dll( load_path, buffer, 0, &wmImp );
-+ status = load_dll( load_path, buffer, NULL, 0, &wmImp );
- }
- else /* need to allocate a larger buffer */
- {
-@@ -600,7 +602,7 @@ static WINE_MODREF *import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *d
- if (!ptr) return NULL;
- ascii_to_unicode( ptr, name, len );
- ptr[len] = 0;
-- status = load_dll( load_path, ptr, 0, &wmImp );
-+ status = load_dll( load_path, ptr, NULL, 0, &wmImp );
- RtlFreeHeap( GetProcessHeap(), 0, ptr );
- }
-
-@@ -916,7 +918,7 @@ static NTSTATUS fixup_imports( WINE_MODREF *wm, LPCWSTR load_path )
- * Allocate a WINE_MODREF structure and add it to the process list
- * The loader_section must be locked while calling this function.
- */
--static WINE_MODREF *alloc_module( HMODULE hModule, LPCWSTR filename )
-+static WINE_MODREF *alloc_module( HMODULE hModule, LPCWSTR filename, LPCWSTR fakemodule )
- {
- WINE_MODREF *wm;
- const WCHAR *p;
-@@ -939,7 +941,7 @@ static WINE_MODREF *alloc_module( HMODULE hModule, LPCWSTR filename )
- wm->ldr.TimeDateStamp = 0;
- wm->ldr.ActivationContext = 0;
-
-- RtlCreateUnicodeString( &wm->ldr.FullDllName, filename );
-+ RtlCreateUnicodeString( &wm->ldr.FullDllName, fakemodule ? fakemodule : filename );
- if ((p = strrchrW( wm->ldr.FullDllName.Buffer, '\\' ))) p++;
- else p = wm->ldr.FullDllName.Buffer;
- RtlInitUnicodeString( &wm->ldr.BaseDllName, p );
-@@ -1578,7 +1580,7 @@ static void load_builtin_callback( void *module, const char *filename )
- return;
- }
-
-- wm = alloc_module( module, fullname );
-+ wm = alloc_module( module, fullname, builtin_load_info->fakemodule );
- RtlFreeHeap( GetProcessHeap(), 0, fullname );
- if (!wm)
- {
-@@ -1760,8 +1762,8 @@ static NTSTATUS perform_relocations( void *module, SIZE_T len )
- /******************************************************************************
- * load_native_dll (internal)
- */
--static NTSTATUS load_native_dll( LPCWSTR load_path, LPCWSTR name, HANDLE file,
-- DWORD flags, WINE_MODREF** pwm )
-+static NTSTATUS load_native_dll( LPCWSTR load_path, LPCWSTR name, LPCWSTR fakemodule,
-+ HANDLE file, DWORD flags, WINE_MODREF** pwm )
- {
- void *module;
- HANDLE mapping;
-@@ -1795,7 +1797,7 @@ static NTSTATUS load_native_dll( LPCWSTR load_path, LPCWSTR name, HANDLE file,
-
- /* create the MODREF */
-
-- if (!(wm = alloc_module( module, name )))
-+ if (!(wm = alloc_module( module, name, fakemodule )))
- {
- status = STATUS_NO_MEMORY;
- goto done;
-@@ -1859,8 +1861,8 @@ done:
- /***********************************************************************
- * load_builtin_dll
- */
--static NTSTATUS load_builtin_dll( LPCWSTR load_path, LPCWSTR path, HANDLE file,
-- DWORD flags, WINE_MODREF** pwm )
-+static NTSTATUS load_builtin_dll( LPCWSTR load_path, LPCWSTR path, LPCWSTR fakemodule,
-+ HANDLE file, DWORD flags, WINE_MODREF** pwm )
- {
- char error[256], dllname[MAX_PATH];
- const WCHAR *name, *p;
-@@ -1880,6 +1882,7 @@ static NTSTATUS load_builtin_dll( LPCWSTR load_path, LPCWSTR path, HANDLE file,
- */
- info.load_path = load_path;
- info.filename = NULL;
-+ info.fakemodule = fakemodule;
- info.status = STATUS_SUCCESS;
- info.wm = NULL;
-
-@@ -2198,14 +2201,14 @@ overflow:
- return STATUS_BUFFER_TOO_SMALL;
- }
-
--
- /***********************************************************************
- * load_dll (internal)
- *
- * Load a PE style module according to the load order.
- * The loader_section must be locked while calling this function.
- */
--static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_MODREF** pwm )
-+static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, LPCWSTR fakemodule,
-+ DWORD flags, WINE_MODREF** pwm )
- {
- enum loadorder loadorder;
- WCHAR buffer[64];
-@@ -2242,6 +2245,25 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_
- }
-
- main_exe = get_modref( NtCurrentTeb()->Peb->ImageBaseAddress );
-+
-+ /* handle dll redirection */
-+ if (!fakemodule)
-+ {
-+ BYTE buffer2[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
-+ WCHAR *redirect = get_redirect( main_exe ? main_exe->ldr.BaseDllName.Buffer : NULL,
-+ filename, buffer2, sizeof(buffer2) );
-+ if (redirect)
-+ {
-+ FIXME("Loader redirect from %s to %s\n", debugstr_w(libname), debugstr_w(redirect));
-+
-+ nts = load_dll( load_path, redirect, filename, flags, pwm );
-+
-+ if (handle) NtClose( handle );
-+ if (filename != buffer) RtlFreeHeap( GetProcessHeap(), 0, filename );
-+ return nts;
-+ }
-+ }
-+
- loadorder = get_load_order( main_exe ? main_exe->ldr.BaseDllName.Buffer : NULL, filename );
-
- if (handle && is_fake_dll( handle ))
-@@ -2264,22 +2286,22 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_
- if (!handle) nts = STATUS_DLL_NOT_FOUND;
- else
- {
-- nts = load_native_dll( load_path, filename, handle, flags, pwm );
-+ nts = load_native_dll( load_path, filename, fakemodule, handle, flags, pwm );
- if (nts == STATUS_INVALID_IMAGE_NOT_MZ)
- /* not in PE format, maybe it's a builtin */
-- nts = load_builtin_dll( load_path, filename, handle, flags, pwm );
-+ nts = load_builtin_dll( load_path, filename, fakemodule, handle, flags, pwm );
- }
- if (nts == STATUS_DLL_NOT_FOUND && loadorder == LO_NATIVE_BUILTIN)
-- nts = load_builtin_dll( load_path, filename, 0, flags, pwm );
-+ nts = load_builtin_dll( load_path, filename, fakemodule, 0, flags, pwm );
- break;
- case LO_BUILTIN:
- case LO_BUILTIN_NATIVE:
- case LO_DEFAULT: /* default is builtin,native */
-- nts = load_builtin_dll( load_path, filename, handle, flags, pwm );
-+ nts = load_builtin_dll( load_path, filename, fakemodule, handle, flags, pwm );
- if (!handle) break; /* nothing else we can try */
- /* file is not a builtin library, try without using the specified file */
- if (nts != STATUS_SUCCESS)
-- nts = load_builtin_dll( load_path, filename, 0, flags, pwm );
-+ nts = load_builtin_dll( load_path, filename, fakemodule, 0, flags, pwm );
- if (nts == STATUS_SUCCESS && loadorder == LO_DEFAULT &&
- (MODULE_InitDLL( *pwm, DLL_WINE_PREATTACH, NULL ) != STATUS_SUCCESS))
- {
-@@ -2289,7 +2311,7 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_
- nts = STATUS_DLL_NOT_FOUND;
- }
- if (nts == STATUS_DLL_NOT_FOUND && loadorder != LO_BUILTIN)
-- nts = load_native_dll( load_path, filename, handle, flags, pwm );
-+ nts = load_native_dll( load_path, filename, fakemodule, handle, flags, pwm );
- break;
- }
-
-@@ -2322,7 +2344,7 @@ NTSTATUS WINAPI DECLSPEC_HOTPATCH LdrLoadDll(LPCWSTR path_name, DWORD flags,
- RtlEnterCriticalSection( &loader_section );
-
- if (!path_name) path_name = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer;
-- nts = load_dll( path_name, libname->Buffer, flags, &wm );
-+ nts = load_dll( path_name, libname->Buffer, NULL, flags, &wm );
-
- if (nts == STATUS_SUCCESS && !(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS))
- {
-@@ -3285,7 +3307,7 @@ void __wine_process_init(void)
- /* setup the load callback and create ntdll modref */
- wine_dll_set_callback( load_builtin_callback );
-
-- if ((status = load_builtin_dll( NULL, kernel32W, 0, 0, &wm )) != STATUS_SUCCESS)
-+ if ((status = load_builtin_dll( NULL, kernel32W, NULL, 0, 0, &wm )) != STATUS_SUCCESS)
- {
- MESSAGE( "wine: could not load kernel32.dll, status %x\n", status );
- exit(1);
-diff --git a/dlls/ntdll/loadorder.c b/dlls/ntdll/loadorder.c
-index 401d256..c7c4592 100644
---- a/dlls/ntdll/loadorder.c
-+++ b/dlls/ntdll/loadorder.c
-@@ -290,102 +290,165 @@ static inline enum loadorder get_env_load_order( const WCHAR *module )
-
-
- /***************************************************************************
-- * get_standard_key
-+ * open_user_reg_key
-+ *
-+ * Return a handle to a registry key under HKCU.
-+ */
-+static HANDLE open_user_reg_key(const WCHAR *key_name)
-+{
-+ HANDLE hkey, root;
-+ OBJECT_ATTRIBUTES attr;
-+ UNICODE_STRING nameW;
-+
-+ RtlOpenCurrentUser( KEY_ALL_ACCESS, &root );
-+ attr.Length = sizeof(attr);
-+ attr.RootDirectory = root;
-+ attr.ObjectName = &nameW;
-+ attr.Attributes = 0;
-+ attr.SecurityDescriptor = NULL;
-+ attr.SecurityQualityOfService = NULL;
-+ RtlInitUnicodeString( &nameW, key_name );
-+
-+ if (NtOpenKey( &hkey, KEY_ALL_ACCESS, &attr )) hkey = 0;
-+ NtClose( root );
-+
-+ return hkey;
-+}
-+
-+
-+/***************************************************************************
-+ * open_app_reg_key
-+ *
-+ * Return a handle to an app-specific registry key.
-+ */
-+static HANDLE open_app_reg_key( const WCHAR *sub_key, const WCHAR *app_name )
-+{
-+ static const WCHAR AppDefaultsW[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\',
-+ 'A','p','p','D','e','f','a','u','l','t','s','\\',0};
-+ WCHAR *str;
-+ HANDLE hkey;
-+
-+ str = RtlAllocateHeap( GetProcessHeap(), 0,
-+ sizeof(AppDefaultsW) +
-+ strlenW(sub_key) * sizeof(WCHAR) +
-+ strlenW(app_name) * sizeof(WCHAR) );
-+ if (!str) return 0;
-+ strcpyW( str, AppDefaultsW );
-+ strcatW( str, app_name );
-+ strcatW( str, sub_key );
-+
-+ hkey = open_user_reg_key( str );
-+ RtlFreeHeap( GetProcessHeap(), 0, str );
-+ return hkey;
-+}
-+
-+
-+/***************************************************************************
-+ * get_override_standard_key
- *
- * Return a handle to the standard DllOverrides registry section.
- */
--static HANDLE get_standard_key(void)
-+static HANDLE get_override_standard_key(void)
- {
- static const WCHAR DllOverridesW[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\',
- 'D','l','l','O','v','e','r','r','i','d','e','s',0};
- static HANDLE std_key = (HANDLE)-1;
-
- if (std_key == (HANDLE)-1)
-- {
-- OBJECT_ATTRIBUTES attr;
-- UNICODE_STRING nameW;
-- HANDLE root;
--
-- RtlOpenCurrentUser( KEY_ALL_ACCESS, &root );
-- attr.Length = sizeof(attr);
-- attr.RootDirectory = root;
-- attr.ObjectName = &nameW;
-- attr.Attributes = 0;
-- attr.SecurityDescriptor = NULL;
-- attr.SecurityQualityOfService = NULL;
-- RtlInitUnicodeString( &nameW, DllOverridesW );
--
-- /* @@ Wine registry key: HKCU\Software\Wine\DllOverrides */
-- if (NtOpenKey( &std_key, KEY_ALL_ACCESS, &attr )) std_key = 0;
-- NtClose( root );
-- }
-+ std_key = open_user_reg_key( DllOverridesW );
-+
- return std_key;
- }
-
-
- /***************************************************************************
-- * get_app_key
-+ * get_override_app_key
- *
- * Get the registry key for the app-specific DllOverrides list.
- */
--static HANDLE get_app_key( const WCHAR *app_name )
-+static HANDLE get_override_app_key( const WCHAR *app_name )
- {
-- OBJECT_ATTRIBUTES attr;
-- UNICODE_STRING nameW;
-- HANDLE root;
-- WCHAR *str;
-- static const WCHAR AppDefaultsW[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\',
-- 'A','p','p','D','e','f','a','u','l','t','s','\\',0};
- static const WCHAR DllOverridesW[] = {'\\','D','l','l','O','v','e','r','r','i','d','e','s',0};
- static HANDLE app_key = (HANDLE)-1;
-
-- if (app_key != (HANDLE)-1) return app_key;
-+ if (app_key == (HANDLE)-1)
-+ app_key = open_app_reg_key( DllOverridesW, app_name );
-
-- str = RtlAllocateHeap( GetProcessHeap(), 0,
-- sizeof(AppDefaultsW) + sizeof(DllOverridesW) +
-- strlenW(app_name) * sizeof(WCHAR) );
-- if (!str) return 0;
-- strcpyW( str, AppDefaultsW );
-- strcatW( str, app_name );
-- strcatW( str, DllOverridesW );
-+ return app_key;
-+}
-
-- RtlOpenCurrentUser( KEY_ALL_ACCESS, &root );
-- attr.Length = sizeof(attr);
-- attr.RootDirectory = root;
-- attr.ObjectName = &nameW;
-- attr.Attributes = 0;
-- attr.SecurityDescriptor = NULL;
-- attr.SecurityQualityOfService = NULL;
-- RtlInitUnicodeString( &nameW, str );
-
-- /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\DllOverrides */
-- if (NtOpenKey( &app_key, KEY_ALL_ACCESS, &attr )) app_key = 0;
-- NtClose( root );
-- RtlFreeHeap( GetProcessHeap(), 0, str );
-+/***************************************************************************
-+ * get_redirect_standard_key
-+ *
-+ * Return a handle to the standard DllRedirects registry section.
-+ */
-+static HANDLE get_redirect_standard_key(void)
-+{
-+ static const WCHAR DllRedirectsW[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\',
-+ 'D','l','l','R','e','d','i','r','e','c','t','s',0};
-+ static HANDLE std_key = (HANDLE)-1;
-+
-+ if (std_key == (HANDLE)-1)
-+ std_key = open_user_reg_key( DllRedirectsW );
-+
-+ return std_key;
-+}
-+
-+
-+/***************************************************************************
-+ * get_redirect_app_key
-+ *
-+ * Get the registry key for the app-specific DllRedirects list.
-+ */
-+static HANDLE get_redirect_app_key( const WCHAR *app_name )
-+{
-+ static const WCHAR DllRedirectsW[] = {'\\','D','l','l','R','e','d','i','r','e','c','t','s',0};
-+ static HANDLE app_key = (HANDLE)-1;
-+
-+ if (app_key == (HANDLE)-1)
-+ app_key = open_app_reg_key( DllRedirectsW, app_name );
-+
- return app_key;
- }
-
-
- /***************************************************************************
-- * get_registry_value
-+ * get_registry_string
- *
-- * Load the registry loadorder value for a given module.
-+ * Load a registry string for a given module.
- */
--static enum loadorder get_registry_value( HANDLE hkey, const WCHAR *module )
-+static WCHAR* get_registry_string( HANDLE hkey, const WCHAR *module, BYTE *buffer,
-+ ULONG size )
- {
- UNICODE_STRING valueW;
-- char buffer[80];
- DWORD count;
-+ WCHAR *ret = NULL;
-
- RtlInitUnicodeString( &valueW, module );
--
-- if (!NtQueryValueKey( hkey, &valueW, KeyValuePartialInformation,
-- buffer, sizeof(buffer), &count ))
-+ if (size >= sizeof(WCHAR) &&
-+ !NtQueryValueKey( hkey, &valueW, KeyValuePartialInformation,
-+ buffer, size - sizeof(WCHAR), &count ))
- {
-- WCHAR *str = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)buffer)->Data;
-- return parse_load_order( str );
-+ KEY_VALUE_PARTIAL_INFORMATION *info = (void *)buffer;
-+ ret = (WCHAR *)info->Data;
-+ ret[info->DataLength / sizeof(WCHAR)] = 0;
- }
-- return LO_INVALID;
-+
-+ return ret;
-+}
-+
-+
-+/***************************************************************************
-+ * get_registry_load_order
-+ *
-+ * Load the registry loadorder value for a given module.
-+ */
-+static enum loadorder get_registry_load_order( HANDLE hkey, const WCHAR *module )
-+{
-+ BYTE buffer[81];
-+ WCHAR *str = get_registry_string( hkey, module, buffer, sizeof(buffer) );
-+ return str ? parse_load_order( str ) : LO_INVALID;
- }
-
-
-@@ -407,13 +470,13 @@ static enum loadorder get_load_order_value( HANDLE std_key, HANDLE app_key, cons
- return ret;
- }
-
-- if (app_key && ((ret = get_registry_value( app_key, module )) != LO_INVALID))
-+ if (app_key && ((ret = get_registry_load_order( app_key, module )) != LO_INVALID))
- {
- TRACE( "got app defaults %s for %s\n", debugstr_loadorder(ret), debugstr_w(module) );
- return ret;
- }
-
-- if (std_key && ((ret = get_registry_value( std_key, module )) != LO_INVALID))
-+ if (std_key && ((ret = get_registry_load_order( std_key, module )) != LO_INVALID))
- {
- TRACE( "got standard key %s for %s\n", debugstr_loadorder(ret), debugstr_w(module) );
- return ret;
-@@ -424,24 +487,44 @@ static enum loadorder get_load_order_value( HANDLE std_key, HANDLE app_key, cons
-
-
- /***************************************************************************
-- * get_load_order (internal)
-+ * get_redirect_value
- *
-- * Return the loadorder of a module.
-- * The system directory and '.dll' extension is stripped from the path.
-+ * Get the redirect value for the exact specified module string, looking in:
-+ * 1. The per-application DllRedirects key
-+ * 2. The standard DllRedirects key
- */
--enum loadorder get_load_order( const WCHAR *app_name, const WCHAR *path )
-+static WCHAR* get_redirect_value( HANDLE std_key, HANDLE app_key, const WCHAR *module,
-+ BYTE *buffer, ULONG size )
- {
-- enum loadorder ret = LO_INVALID;
-- HANDLE std_key, app_key = 0;
-- WCHAR *module, *basename;
-- UNICODE_STRING path_str;
-- int len;
-+ WCHAR *ret = NULL;
-
-- if (!init_done) init_load_order();
-- std_key = get_standard_key();
-- if (app_name) app_key = get_app_key( app_name );
-+ if (app_key && (ret = get_registry_string( app_key, module, buffer, size )))
-+ {
-+ TRACE( "got app defaults %s for %s\n", debugstr_w(ret), debugstr_w(module) );
-+ return ret;
-+ }
-
-- TRACE("looking for %s\n", debugstr_w(path));
-+ if (std_key && (ret = get_registry_string( std_key, module, buffer, size )))
-+ {
-+ TRACE( "got standard key %s for %s\n", debugstr_w(ret), debugstr_w(module) );
-+ return ret;
-+ }
-+
-+ return ret;
-+}
-+
-+
-+/***************************************************************************
-+ * get_module_basename
-+ *
-+ * Determine the module basename. The caller is responsible for releasing
-+ * the memory.
-+ */
-+static WCHAR* get_module_basename( const WCHAR *path, WCHAR **basename )
-+{
-+ UNICODE_STRING path_str;
-+ WCHAR *module;
-+ int len;
-
- /* Strip path information if the module resides in the system directory
- */
-@@ -453,12 +536,36 @@ enum loadorder get_load_order( const WCHAR *app_name, const WCHAR *path )
- if (!strchrW( p, '\\' ) && !strchrW( p, '/' )) path = p;
- }
-
-- if (!(len = strlenW(path))) return ret;
-- if (!(module = RtlAllocateHeap( GetProcessHeap(), 0, (len + 2) * sizeof(WCHAR) ))) return ret;
-+ if (!(len = strlenW(path))) return NULL;
-+ if (!(module = RtlAllocateHeap( GetProcessHeap(), 0, (len + 2) * sizeof(WCHAR) ))) return NULL;
- strcpyW( module+1, path ); /* reserve module[0] for the wildcard char */
-- basename = (WCHAR *)get_basename( module+1 );
-+ *basename = (WCHAR *)get_basename( module+1 );
-
- if (len >= 4) remove_dll_ext( module + 1 + len - 4 );
-+ return module;
-+}
-+
-+
-+/***************************************************************************
-+ * get_load_order (internal)
-+ *
-+ * Return the loadorder of a module.
-+ * The system directory and '.dll' extension is stripped from the path.
-+ */
-+enum loadorder get_load_order( const WCHAR *app_name, const WCHAR *path )
-+{
-+ enum loadorder ret = LO_INVALID;
-+ HANDLE std_key, app_key = 0;
-+ WCHAR *module, *basename;
-+
-+ if (!init_done) init_load_order();
-+ std_key = get_override_standard_key();
-+ if (app_name) app_key = get_override_app_key( app_name );
-+
-+ TRACE("looking up loadorder for %s\n", debugstr_w(path));
-+
-+ if (!(module = get_module_basename(path, &basename)))
-+ return ret;
-
- /* first explicit module name */
- if ((ret = get_load_order_value( std_key, app_key, module+1 )) != LO_INVALID)
-@@ -489,3 +596,46 @@ enum loadorder get_load_order( const WCHAR *app_name, const WCHAR *path )
- RtlFreeHeap( GetProcessHeap(), 0, module );
- return ret;
- }
-+
-+
-+/***************************************************************************
-+ * get_redirect (internal)
-+ *
-+ * Return the redirect value of a module.
-+ * The system directory and '.dll' extension is stripped from the path.
-+ */
-+WCHAR* get_redirect( const WCHAR *app_name, const WCHAR *path, BYTE *buffer, ULONG size )
-+{
-+ WCHAR *ret = NULL;
-+ HANDLE std_key, app_key = 0;
-+ WCHAR *module, *basename;
-+
-+ std_key = get_redirect_standard_key();
-+ if (app_name) app_key = get_redirect_app_key( app_name );
-+
-+ TRACE("looking up redirection for %s\n", debugstr_w(path));
-+
-+ if (!(module = get_module_basename(path, &basename)))
-+ return ret;
-+
-+ /* first explicit module name */
-+ if ((ret = get_redirect_value( std_key, app_key, module+1, buffer, size )))
-+ goto done;
-+
-+ /* then module basename preceded by '*' */
-+ basename[-1] = '*';
-+ if ((ret = get_redirect_value( std_key, app_key, basename-1, buffer, size )))
-+ goto done;
-+
-+ /* then module basename without '*' (only if explicit path) */
-+ if (basename != module+1 && (ret = get_redirect_value( std_key, app_key, basename, buffer, size )))
-+ goto done;
-+
-+ /* and last the hard-coded default */
-+ ret = NULL;
-+ TRACE( "no redirection found for %s\n", debugstr_w(path) );
-+
-+ done:
-+ RtlFreeHeap( GetProcessHeap(), 0, module );
-+ return ret;
-+}
-diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
-index cbd19db..e522464 100644
---- a/dlls/ntdll/ntdll_misc.h
-+++ b/dlls/ntdll/ntdll_misc.h
-@@ -205,6 +205,7 @@ enum loadorder
- };
-
- extern enum loadorder get_load_order( const WCHAR *app_name, const WCHAR *path ) DECLSPEC_HIDDEN;
-+extern WCHAR* get_redirect( const WCHAR *app_name, const WCHAR *path, BYTE *buffer, ULONG size ) DECLSPEC_HIDDEN;
-
- struct debug_info
- {
-diff --git a/dlls/winex11.drv/init.c b/dlls/winex11.drv/init.c
-index 6bc4fb3..b0024a0 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;
-diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
-index 2694d23..3e94b64 100644
---- a/dlls/winex11.drv/x11drv.h
-+++ b/dlls/winex11.drv/x11drv.h
-@@ -292,6 +292,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
-diff --git a/programs/winecfg/Makefile.in b/programs/winecfg/Makefile.in
-index 7b52a69..c86fdd0 100644
---- a/programs/winecfg/Makefile.in
-+++ b/programs/winecfg/Makefile.in
-@@ -11,6 +11,7 @@ C_SRCS = \
- driveui.c \
- libraries.c \
- main.c \
-+ staging.c \
- theme.c \
- winecfg.c \
- x11drvdlg.c
-diff --git a/programs/winecfg/main.c b/programs/winecfg/main.c
-index b8a85fe..de209a9 100644
---- a/programs/winecfg/main.c
-+++ b/programs/winecfg/main.c
-@@ -58,7 +58,7 @@ PropSheetCallback (HWND hWnd, UINT uMsg, LPARAM lParam)
- return 0;
- }
-
--#define NUM_PROPERTY_PAGES 7
-+#define NUM_PROPERTY_PAGES 8
-
- static INT_PTR
- doPropertySheet (HINSTANCE hInstance, HWND hOwner)
-@@ -139,6 +139,16 @@ doPropertySheet (HINSTANCE hInstance, HWND hOwner)
- psp[pg].lParam = 0;
- pg++;
-
-+ psp[pg].dwSize = sizeof (PROPSHEETPAGEW);
-+ psp[pg].dwFlags = PSP_USETITLE;
-+ psp[pg].hInstance = hInstance;
-+ psp[pg].u.pszTemplate = MAKEINTRESOURCEW (IDD_STAGING);
-+ psp[pg].u2.pszIcon = NULL;
-+ psp[pg].pfnDlgProc = StagingDlgProc;
-+ psp[pg].pszTitle = load_string (IDS_TAB_STAGING);
-+ psp[pg].lParam = 0;
-+ pg++;
-+
- /*
- * Fill out the (General) PROPSHEETPAGE data structure
- * for the property sheet
-diff --git a/programs/winecfg/resource.h b/programs/winecfg/resource.h
-index 8604fb4..201e5c3 100644
---- a/programs/winecfg/resource.h
-+++ b/programs/winecfg/resource.h
-@@ -45,6 +45,7 @@
- #define IDS_SHELL_FOLDER 16
- #define IDS_LINKS_TO 17
- #define IDS_WINECFG_TITLE_APP 18 /* App specific title */
-+#define IDS_TAB_STAGING 19
- #define IDI_WINECFG 100
- #define IDI_LOGO 102
- #define IDD_ABOUTCFG 107
-@@ -54,6 +55,7 @@
- #define IDD_DLLCFG 111
- #define IDD_DRIVECFG 112
- #define IDD_DESKTOP_INTEGRATION 115
-+#define IDD_STAGING 116
- #define IDC_WINVER 1012
- #define IDC_DESKTOP_WIDTH 1023
- #define IDC_DESKTOP_HEIGHT 1024
-@@ -218,3 +220,6 @@
- #define IDC_ABT_TITLE_TEXT 8436
- #define IDC_ABT_WEB_LINK 8437
- #define IDC_ABT_LICENSE_TEXT 8438
-+
-+/* Staging tab */
-+#define IDC_ENABLE_NATIVE_D3D9 9001
-diff --git a/programs/winecfg/staging.c b/programs/winecfg/staging.c
-new file mode 100644
-index 0000000..4a53815
---- /dev/null
-+++ b/programs/winecfg/staging.c
-@@ -0,0 +1,93 @@
-+/*
-+ * WineCfg Staging panel
-+ *
-+ * Copyright 2014 Michael Müller
-+ * Copyright 2015 Sebastian Lackner
-+ *
-+ * 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
-+ *
-+ */
-+
-+#define COBJMACROS
-+
-+#include "config.h"
-+
-+#include <windows.h>
-+#include <wine/unicode.h>
-+#include <wine/debug.h>
-+
-+#include "resource.h"
-+#include "winecfg.h"
-+
-+WINE_DEFAULT_DEBUG_CHANNEL(winecfg);
-+
-+/*
-+ * Gallium nine
-+ */
-+static BOOL nine_get(void)
-+{
-+ BOOL ret;
-+ char *value = get_reg_key(config_key, keypath("DllRedirects"), "d3d9", NULL);
-+ ret = (value && !strcmp(value, "d3d9-nine.dll"));
-+ HeapFree(GetProcessHeap(), 0, value);
-+ return ret;
-+}
-+
-+static void nine_set(BOOL status)
-+{
-+ set_reg_key(config_key, keypath("DllRedirects"), "d3d9", status ? "d3d9-nine.dll" : NULL);
-+}
-+
-+
-+static void load_staging_settings(HWND dialog)
-+{
-+ CheckDlgButton(dialog, IDC_ENABLE_NATIVE_D3D9, nine_get() ? BST_CHECKED : BST_UNCHECKED);
-+#if !defined(SONAME_D3DADAPTER9)
-+ disable(IDC_ENABLE_NATIVE_D3D9);
-+#endif
-+}
-+
-+INT_PTR CALLBACK StagingDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
-+{
-+ switch (uMsg)
-+ {
-+ case WM_INITDIALOG:
-+ break;
-+
-+ case WM_NOTIFY:
-+ if (((LPNMHDR)lParam)->code == PSN_SETACTIVE)
-+ load_staging_settings(hDlg);
-+ break;
-+
-+ case WM_SHOWWINDOW:
-+ set_window_title(hDlg);
-+ break;
-+
-+ case WM_DESTROY:
-+ break;
-+
-+ case WM_COMMAND:
-+ if (HIWORD(wParam) != BN_CLICKED) break;
-+ switch (LOWORD(wParam))
-+ {
-+ case IDC_ENABLE_NATIVE_D3D9:
-+ nine_set(IsDlgButtonChecked(hDlg, IDC_ENABLE_NATIVE_D3D9) == BST_CHECKED);
-+ SendMessageW(GetParent(hDlg), PSM_CHANGED, 0, 0);
-+ return TRUE;
-+ }
-+ break;
-+ }
-+ return FALSE;
-+}
-diff --git a/programs/winecfg/winecfg.h b/programs/winecfg/winecfg.h
-index 110856a..a949474 100644
---- a/programs/winecfg/winecfg.h
-+++ b/programs/winecfg/winecfg.h
-@@ -87,6 +87,7 @@ INT_PTR CALLBACK AppDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
- INT_PTR CALLBACK LibrariesDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
- INT_PTR CALLBACK AudioDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
- INT_PTR CALLBACK ThemeDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
-+INT_PTR CALLBACK StagingDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
- INT_PTR CALLBACK AboutDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
-
- /* Drive management */
-diff --git a/programs/winecfg/winecfg.rc b/programs/winecfg/winecfg.rc
-index 221916b..ee4c55d 100644
---- a/programs/winecfg/winecfg.rc
-+++ b/programs/winecfg/winecfg.rc
-@@ -39,6 +39,7 @@ BEGIN
- IDS_TAB_GRAPHICS "Graphics"
- IDS_TAB_DESKTOP_INTEGRATION "Desktop Integration"
- IDS_TAB_AUDIO "Audio"
-+ IDS_TAB_STAGING "Staging"
- IDS_TAB_ABOUT "About"
- IDS_WINECFG_TITLE "Wine configuration"
- IDS_WINECFG_TITLE_APP "Wine configuration for %s"
-@@ -308,6 +309,15 @@ BEGIN
- PUSHBUTTON "B&rowse...",IDC_BROWSE_SFPATH,195,195,50,13,WS_DISABLED
- END
-
-+IDD_STAGING DIALOG 0, 0, 260, 220
-+STYLE WS_CHILD | WS_DISABLED
-+FONT 8, "MS Shell Dlg"
-+BEGIN
-+ GROUPBOX "Staging settings",IDC_STATIC,8,4,244,210
-+ LTEXT "The following settings are experimental and may break stuff!\nMake sure to reset them again in case of a problem.\nGallium Nine requires MESA graphic drivers and AMD/Nvidia GPU.\n",IDC_STATIC,16,16,230,24
-+ CONTROL "Enable &Gallium Nine for better D3D9 graphic performance.",IDC_ENABLE_NATIVE_D3D9,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,40,230,8
-+END
-+
- LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
-
- /* @makedep: winecfg.ico */