Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/Makefile.kmk	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/Makefile.kmk	(revision 46521)
@@ -0,0 +1,396 @@
+# $Id$
+## @file
+# Makefile for the Wine D3D related dlls for VirtualBox.
+#
+
+#
+# Copyright (C) 2009-2012 Oracle Corporation
+#
+# This file is part of VirtualBox Open Source Edition (OSE), as
+# available from http://www.virtualbox.org. This file is free software;
+# you can redistribute it and/or modify it under the terms of the GNU
+# General Public License (GPL) as published by the Free Software
+# Foundation, in version 2 as it comes in the "COPYING" file of the
+# VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+#
+
+
+SUB_DEPTH = ../../../../../..
+include $(KBUILD_PATH)/subheader.kmk
+
+#
+# Template for building wine stuff.
+#
+TEMPLATE_VBoxGuestWineDLL = Template for building a wine DLL.
+TEMPLATE_VBoxGuestWineDLL_EXTENDS = VBOXGUESTR3NPDLL
+TEMPLATE_VBoxGuestWineDLL_DEFS = $(TEMPLATE_VBOXGUESTR3NPDLL_DEFS) \
+	__WINESRC__ \
+	WINE_UNICODE_API="" \
+	_REENTRANT \
+	WINE_NOWINSOCK \
+	USE_WIN32_OPENGL \
+	DLLDIR=\"\" \
+	BINDIR=\"\" \
+	LIB_TO_BINDIR=\"\" \
+	LIB_TO_DLLDIR=\"\" \
+	BIN_TO_DLLDIR=\"\" \
+	LIB_TO_DATADIR=\"\" \
+	BIN_TO_DATADIR=\"\"
+
+TEMPLATE_VBoxGuestWineDLL_DEFS.x86 = __i386__
+
+#
+# Template for building the D3D[89] stuff.
+#
+TEMPLATE_VBoxGuestWineD3DxDLL = Template for building the D3D8/9 stuff.
+TEMPLATE_VBoxGuestWineD3DxDLL_EXTENDS    = VBOXGUESTR3NPDLL
+TEMPLATE_VBoxGuestWineD3DxDLL_EXTENDS_BY = appending
+TEMPLATE_VBoxGuestWineD3DxDLL_SDKS = ReorderCompilerIncs $(VBOX_WINDDK_GST_WLH)
+TEMPLATE_VBoxGuestWineD3DxDLL_DEFS = VBOX_USING_WINDDK_W7_OR_LATER
+TEMPLATE_VBoxGuestWineD3DxDLL_DEFS.x86   = __i386__
+#TEMPLATE_VBoxGuestWineD3DxDLL_INCS.x86   = vbox/libWineStub/include
+ifdef VBOX_WINE_WITH_IPRT
+ TEMPLATE_VBoxGuestWineD3DxDLL_DEFS = VBOX_WINE_WITH_IPRT
+ TEMPLATE_VBoxGuestWineD3DxDLL_LIBS = \
+ 	$(VBOX_LIB_IPRT_GUEST_R3) \
+ 	$(VBOX_LIB_VBGL_R3)
+endif
+
+
+if 0
+#
+# libWine - ???.
+#
+DLLS.x86 += libWine
+libWine_TEMPLATE     = VBoxGuestWineDLL
+libWine_INCS         = \
+	include
+libWine_SOURCES      := \
+	libWine/wine.def \
+	libWine/casemap.c \
+	libWine/collation.c \
+	libWine/compose.c \
+	libWine/config.c \
+	libWine/cptable.c \
+	libWine/debug.c \
+	libWine/fold.c \
+	libWine/ldt.c \
+	libWine/loader.c \
+	libWine/mbtowc.c \
+	libWine/mmap.c \
+	libWine/port.c \
+	libWine/sortkey.c \
+	libWine/string.c \
+	libWine/utf8.c \
+	libWine/wctomb.c \
+	libWine/wctype.c \
+	libWine/c_037.c \
+	libWine/c_424.c \
+	libWine/c_437.c \
+	libWine/c_500.c \
+	libWine/c_737.c \
+	libWine/c_775.c \
+	libWine/c_850.c \
+	libWine/c_852.c \
+	libWine/c_855.c \
+	libWine/c_856.c \
+	libWine/c_857.c \
+	libWine/c_860.c \
+	libWine/c_861.c \
+	libWine/c_862.c \
+	libWine/c_863.c \
+	libWine/c_864.c \
+	libWine/c_865.c \
+	libWine/c_866.c \
+	libWine/c_869.c \
+	libWine/c_874.c \
+	libWine/c_875.c \
+	libWine/c_878.c \
+	libWine/c_932.c \
+	libWine/c_936.c \
+	libWine/c_949.c \
+	libWine/c_950.c \
+	libWine/c_1006.c \
+	libWine/c_1026.c \
+	libWine/c_1250.c \
+	libWine/c_1251.c \
+	libWine/c_1252.c \
+	libWine/c_1253.c \
+	libWine/c_1254.c \
+	libWine/c_1255.c \
+	libWine/c_1256.c \
+	libWine/c_1257.c \
+	libWine/c_1258.c \
+	libWine/c_1361.c \
+	libWine/c_10000.c \
+	libWine/c_10006.c \
+	libWine/c_10007.c \
+	libWine/c_10029.c \
+	libWine/c_10079.c \
+	libWine/c_10081.c \
+	libWine/c_20127.c \
+	libWine/c_20866.c \
+	libWine/c_20932.c \
+	libWine/c_21866.c \
+	libWine/c_28591.c \
+	libWine/c_28592.c \
+	libWine/c_28593.c \
+	libWine/c_28594.c \
+	libWine/c_28595.c \
+	libWine/c_28596.c \
+	libWine/c_28597.c \
+	libWine/c_28598.c \
+	libWine/c_28599.c \
+	libWine/c_28600.c \
+	libWine/c_28603.c \
+	libWine/c_28604.c \
+	libWine/c_28605.c \
+	libWine/c_28606.c \
+	libWine/version.c
+endif # 0
+
+#
+# wined3d - ???.
+#
+DLLS += wined3d
+wined3d_TEMPLATE     = VBoxGuestWineDLL
+wined3d_SDKS         = ReorderCompilerIncs $(VBOX_WINDDK_GST_WLH)
+wined3d_DEFS         = \
+	_USE_MATH_DEFINES \
+	VBOX_USING_WINDDK_W7_OR_LATER \
+	VBOX_WINE_WITHOUT_LIBWINE \
+	VBOX_WINE_WITH_SINGLE_CONTEXT \
+	VBOX_WINE_WITH_IPRT
+# 	^^^^ wined3d is now using iprt/asm.h, which includes iprt/assert.h, so iprt is required.
+if "$(KBUILD_TYPE)" != "debug" || defined(VBOX_WINE_NO_DEBUG_MSGS)
+ wined3d_DEFS       += WINE_NO_DEBUG_MSGS
+endif
+wined3d_DEFS        += \
+	VBOX_WITH_WINE_FIX_IBMTMR \
+	VBOX_WITH_WINE_FIX_BUFOFFSET \
+	VBOX_WITH_WINE_FIX_QUIRKS \
+	VBOX_WITH_WINE_FIX_PBOPSM \
+	VBOX_WITH_WINE_FIX_INITCLEAR \
+	VBOX_WITH_WINE_DBG
+#wined3d_DEFS        += VBOX_WITH_WINE_FIXES
+wined3d_INCS        := \
+	vbox/libWineStub/include
+wined3d_SOURCES     := \
+	wined3d/arb_program_shader.c \
+	wined3d/ati_fragment_shader.c \
+	wined3d/buffer.c \
+	wined3d/context.c \
+	wined3d/device.c \
+	wined3d/directx.c \
+	wined3d/drawprim.c \
+	wined3d/gl_compat.c \
+	wined3d/glsl_shader.c \
+	wined3d/nvidia_texture_shader.c \
+	wined3d/palette.c \
+	wined3d/query.c \
+	wined3d/resource.c \
+	wined3d/shader.c \
+	wined3d/shader_sm1.c \
+	wined3d/shader_sm4.c \
+	wined3d/state.c \
+	wined3d/stateblock.c \
+	wined3d/surface.c \
+	wined3d/swapchain.c \
+	wined3d/texture.c \
+	wined3d/utils.c \
+	wined3d/vertexdeclaration.c \
+	wined3d/view.c \
+	wined3d/volume.c \
+	wined3d/wined3d_main.c \
+	wined3d/vboxext.c \
+	wined3d/sampler.c \
+	vbox/libWineStub/debug.c \
+	vbox/VBoxDbgGl.c \
+	wined3d/wined3d.def
+wined3d_LIBS        = \
+	$(VBOX_LIB_IPRT_GUEST_R3) \
+	$(VBOX_LIB_VBGL_R3) \
+	$(PATH_STAGE_LIB)/VBoxOGL$(VBOX_SUFF_LIB)
+
+ifdef VBOX_WITH_WDDM
+ #
+ # wined3dwddm - ???
+ #
+ DLLS += wined3dwddm
+ wined3dwddm_EXTENDS        = wined3d
+ if defined(VBOX_SIGNING_MODE)
+  wined3dwddm_INSTTYPE.win  = none
+  wined3dwddm_DEBUG_INSTTYPE.win = both
+ endif
+ wined3dwddm_DEFS           = $(wined3d_DEFS) \
+ 	VBOX_WITH_WDDM \
+	IN_VBOXLIBWINE \
+	VBOX_WINE_WITH_SHADER_CACHE
+ifdef VBOX_WINE_WITH_PROFILE
+ wined3dwddm_DEFS       += VBOX_WINE_WITH_PROFILE
+endif
+ wined3dwddm_INCS           = $(wined3d_INCS) \
+ 	$(PATH_ROOT)/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm
+ wined3dwddm_SOURCES        = $(subst wined3d.def,wined3dwddm.def,$(wined3d_SOURCES))
+ wined3dwddm_LIBS           = $(wined3d_LIBS) \
+ 	$(VBOX_PATH_ADDITIONS_LIB)/VBoxDispMpLogger$(VBOX_SUFF_LIB) \
+ 	$(VBOX_PATH_ADDITIONS_LIB)/VBoxCrHgsmi$(VBOX_SUFF_LIB)
+
+ #
+ # wined3dwddm-x86 - ???.
+ #
+ DLLS.amd64 += wined3dwddm-x86
+ wined3dwddm-x86_EXTENDS    = wined3dwddm
+ wined3dwddm-x86_BLD_TRG_ARCH = x86
+ wined3dwddm-x86_DEFS       = $(wined3dwddm_DEFS) VBOX_WDDM_WOW64
+ wined3dwddm-x86_LIBS       = \
+ 	$(VBOX_LIB_IPRT_GUEST_R3_X86) \
+ 	$(VBOX_LIB_VBGL_R3_X86) \
+ 	$(VBOX_PATH_ADDITIONS_LIB)/VBoxDispMpLogger-x86$(VBOX_SUFF_LIB) \
+ 	$(VBOX_PATH_ADDITIONS_LIB)/VBoxCrHgsmi-x86$(VBOX_SUFF_LIB) \
+ 	$(PATH_STAGE_LIB)/VBoxOGL-x86$(VBOX_SUFF_LIB)
+endif # ifdef VBOX_WITH_WDDM
+
+#
+# VBoxD3D8 - ???.
+#
+DLLS += VBoxD3D8
+VBoxD3D8_TEMPLATE     = VBoxGuestWineDLL
+VBoxD3D8_SDKS         = ReorderCompilerIncs $(VBOX_WINDDK_GST_WLH)
+VBoxD3D8_DEFS         = _USE_MATH_DEFINES \
+	VBOX_USING_WINDDK \
+	VBOX_WINE_WITHOUT_LIBWINE
+if "$(KBUILD_TYPE)" != "debug" || defined(VBOX_WINE_NO_DEBUG_MSGS)
+ VBoxD3D8_DEFS       += WINE_NO_DEBUG_MSGS
+endif
+VBoxD3D8_INCS        := \
+	vbox/libWineStub/include
+VBoxD3D8_SOURCES     := \
+	d3d8/d3d8_main.c \
+	d3d8/buffer.c \
+	d3d8/device.c \
+	d3d8/directx.c \
+	d3d8/shader.c \
+	d3d8/surface.c \
+	d3d8/swapchain.c \
+	d3d8/texture.c \
+	d3d8/vertexdeclaration.c \
+	d3d8/volume.c \
+	vbox/libWineStub/debug.c \
+	d3d8/d3d8.def
+VBoxD3D8_LIBS         = \
+	$(PATH_STAGE_LIB)/wined3d$(VBOX_SUFF_LIB)
+ifdef VBOX_WINE_WITH_IPRT
+ VBoxD3D8_DEFS       += VBOX_WINE_WITH_IPRT
+ VBoxD3D8_LIBS       += \
+ 	$(VBOX_LIB_IPRT_GUEST_R3) \
+ 	$(VBOX_LIB_VBGL_R3)
+endif
+
+#
+# VBoxD3D9 - ???.
+#
+DLLS += VBoxD3D9
+VBoxD3D9_TEMPLATE     = VBoxGuestWineDLL
+VBoxD3D9_SDKS         = ReorderCompilerIncs $(VBOX_WINDDK_GST_WLH)
+VBoxD3D9_DEFS         = _USE_MATH_DEFINES \
+	VBOX_USING_WINDDK \
+	VBOX_WINE_WITHOUT_LIBWINE
+if "$(KBUILD_TYPE)" != "debug" || defined(VBOX_WINE_NO_DEBUG_MSGS)
+ VBoxD3D9_DEFS        += WINE_NO_DEBUG_MSGS
+endif
+#@todo: do we actually need this?
+#VBoxD3D9_DEFS         += VBOX_WITH_WINE_FIX_NO9EX
+VBoxD3D9_INCS         := \
+	vbox/libWineStub/include
+VBoxD3D9_SOURCES      := \
+	d3d9/d3d9_main.c \
+	d3d9/buffer.c \
+	d3d9/device.c \
+	d3d9/directx.c \
+	d3d9/query.c \
+	d3d9/shader.c \
+	d3d9/stateblock.c \
+	d3d9/surface.c \
+	d3d9/swapchain.c \
+	d3d9/texture.c \
+	d3d9/vertexdeclaration.c \
+	d3d9/volume.c \
+	vbox/libWineStub/debug.c \
+	d3d9/d3d9xpdm.def
+VBoxD3D9_LIBS             = \
+	$(PATH_STAGE_LIB)/wined3d$(VBOX_SUFF_LIB)
+ifdef VBOX_WINE_WITH_IPRT
+ VBoxD3D9_DEFS         += VBOX_WINE_WITH_IPRT
+ VBoxD3D9_LIBS         += \
+ 	$(VBOX_LIB_IPRT_GUEST_R3) \
+ 	$(VBOX_LIB_VBGL_R3)
+endif
+
+ifdef VBOX_WITH_WDDM
+ #
+ # VBoxD3D9wddm - ???.
+ #
+ DLLS += VBoxD3D9wddm
+ VBoxD3D9wddm_EXTENDS  = VBoxD3D9
+ if defined(VBOX_SIGNING_MODE) && defined(VBOX_WITH_WDDM)
+  VBoxD3D9wddm_INSTTYPE = none
+  VBoxD3D9wddm_DEBUG_INSTTYPE = both
+ endif
+ VBoxD3D9wddm_INCS     = $(VBoxD3D9_INCS) \
+ 	$(PATH_ROOT)/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm
+ VBoxD3D9wddm_DEFS    += $(VBoxD3D9_DEFS) \
+ 	VBOX_WITH_WDDM \
+ 	IN_VBOXWINEEX \
+ 	VBOX_WINE_NO_LOCK
+ VBoxD3D9wddm_SOURCES  = $(subst d3d9xpdm.def,d3d9wddm.def,$(VBoxD3D9_SOURCES))
+ VBoxD3D9wddm_LIBS     = \
+ 	$(subst $(PATH_STAGE_LIB)/wined3d$(VBOX_SUFF_LIB),$(PATH_STAGE_LIB)/wined3dwddm$(VBOX_SUFF_LIB),$(VBoxD3D9_LIBS)) \
+ 	$(VBOX_PATH_ADDITIONS_LIB)/VBoxDispMpLogger$(VBOX_SUFF_LIB) \
+ 	$(VBOX_PATH_ADDITIONS_LIB)/VBoxCrHgsmi$(VBOX_SUFF_LIB)
+
+ #
+ # VBoxD3D9wddm-x86 - For WOW64.
+ #
+ DLLS.amd64 += VBoxD3D9wddm-x86
+ VBoxD3D9wddm-x86_EXTENDS      = VBoxD3D9wddm
+ VBoxD3D9wddm-x86_BLD_TRG_ARCH = x86
+ VBoxD3D9wddm-x86_DEFS         = $(VBoxD3D9wddm_DEFS) VBOX_WDDM_WOW64
+ VBoxD3D9wddm-x86_LIBS         = $(PATH_STAGE_LIB)/wined3dwddm-x86$(VBOX_SUFF_LIB)
+ ifdef VBOX_WINE_WITH_IPRT
+  VBoxD3D9wddm-x86_LIBS        += \
+  	$(VBOX_LIB_IPRT_GUEST_R3_X86) \
+  	$(VBOX_LIB_VBGL_R3_X86)
+ endif
+ VBoxD3D9wddm-x86_LIBS        += \
+  	$(VBOX_PATH_ADDITIONS_LIB)/VBoxDispMpLogger-x86$(VBOX_SUFF_LIB) \
+ 	$(VBOX_PATH_ADDITIONS_LIB)/VBoxCrHgsmi-x86$(VBOX_SUFF_LIB)
+endif # VBOX_WITH_WDDM
+
+#
+# d3d8 - ???.
+#
+DLLS += d3d8
+d3d8_TEMPLATE      = VBoxGuestWineD3DxDLL
+d3d8_SOURCES       = \
+	switcher/d3d8_main.c \
+	switcher/sw_common.c \
+	switcher/sw_d3d8.def \
+	switcher/d3d8.rc
+
+#
+# d3d9 - ???.
+#
+DLLS += d3d9
+d3d9_TEMPLATE      = VBoxGuestWineD3DxDLL
+d3d9_SOURCES       =  \
+	switcher/d3d9_main.c \
+	switcher/sw_common.c \
+	switcher/d3d9.rc
+d3d9_SOURCES.x86   =  \
+	switcher/sw_d3d9.def
+d3d9_SOURCES.amd64 =  \
+	switcher/sw_d3d9xpdm.def
+
+include $(FILE_KBUILD_SUB_FOOTER)
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/buffer.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/buffer.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/buffer.c	(revision 46521)
@@ -0,0 +1,611 @@
+/*
+ * Copyright 2005 Oliver Stieber
+ *
+ * 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 "d3d8_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d8);
+
+static inline struct d3d8_vertexbuffer *impl_from_IDirect3DVertexBuffer8(IDirect3DVertexBuffer8 *iface)
+{
+    return CONTAINING_RECORD(iface, struct d3d8_vertexbuffer, IDirect3DVertexBuffer8_iface);
+}
+
+static HRESULT WINAPI d3d8_vertexbuffer_QueryInterface(IDirect3DVertexBuffer8 *iface, REFIID riid, void **object)
+{
+    TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
+
+    if (IsEqualGUID(riid, &IID_IDirect3DVertexBuffer8)
+            || IsEqualGUID(riid, &IID_IDirect3DResource8)
+            || IsEqualGUID(riid, &IID_IUnknown))
+    {
+        IDirect3DVertexBuffer8_AddRef(iface);
+        *object = iface;
+        return S_OK;
+    }
+
+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+    *object = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI d3d8_vertexbuffer_AddRef(IDirect3DVertexBuffer8 *iface)
+{
+    struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
+    ULONG refcount = InterlockedIncrement(&buffer->refcount);
+
+    TRACE("%p increasing refcount to %u.\n", iface, refcount);
+
+    if (refcount == 1)
+    {
+        IDirect3DDevice8_AddRef(buffer->parent_device);
+        wined3d_mutex_lock();
+        wined3d_buffer_incref(buffer->wined3d_buffer);
+        wined3d_mutex_unlock();
+    }
+
+    return refcount;
+}
+
+static ULONG WINAPI d3d8_vertexbuffer_Release(IDirect3DVertexBuffer8 *iface)
+{
+    struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
+    ULONG refcount = InterlockedDecrement(&buffer->refcount);
+
+    TRACE("%p decreasing refcount to %u.\n", iface, refcount);
+
+    if (!refcount)
+    {
+        IDirect3DDevice8 *device = buffer->parent_device;
+
+        wined3d_mutex_lock();
+        wined3d_buffer_decref(buffer->wined3d_buffer);
+        wined3d_mutex_unlock();
+
+        /* Release the device last, as it may cause the device to be destroyed. */
+        IDirect3DDevice8_Release(device);
+    }
+
+    return refcount;
+}
+
+static HRESULT WINAPI d3d8_vertexbuffer_GetDevice(IDirect3DVertexBuffer8 *iface,
+        IDirect3DDevice8 **device)
+{
+    struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
+
+    TRACE("iface %p, device %p.\n", iface, device);
+
+    *device = buffer->parent_device;
+    IDirect3DDevice8_AddRef(*device);
+
+    TRACE("Returning device %p.\n", *device);
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_vertexbuffer_SetPrivateData(IDirect3DVertexBuffer8 *iface,
+        REFGUID guid, const void *data, DWORD data_size, DWORD flags)
+{
+    struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
+            iface, debugstr_guid(guid), data, data_size, flags);
+
+    wined3d_mutex_lock();
+    resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
+    hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_vertexbuffer_GetPrivateData(IDirect3DVertexBuffer8 *iface,
+        REFGUID guid, void *data, DWORD *data_size)
+{
+    struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s, data %p, data_size %p.\n",
+            iface, debugstr_guid(guid), data, data_size);
+
+    wined3d_mutex_lock();
+    resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
+    hr = wined3d_resource_get_private_data(resource, guid, data, data_size);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_vertexbuffer_FreePrivateData(IDirect3DVertexBuffer8 *iface, REFGUID guid)
+{
+    struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
+
+    wined3d_mutex_lock();
+    resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
+    hr = wined3d_resource_free_private_data(resource, guid);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static DWORD WINAPI d3d8_vertexbuffer_SetPriority(IDirect3DVertexBuffer8 *iface, DWORD priority)
+{
+    struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
+    DWORD previous;
+
+    TRACE("iface %p, priority %u.\n", iface, priority);
+
+    wined3d_mutex_lock();
+    previous = wined3d_buffer_set_priority(buffer->wined3d_buffer, priority);
+    wined3d_mutex_unlock();
+
+    return previous;
+}
+
+static DWORD WINAPI d3d8_vertexbuffer_GetPriority(IDirect3DVertexBuffer8 *iface)
+{
+    struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
+    DWORD priority;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    priority = wined3d_buffer_get_priority(buffer->wined3d_buffer);
+    wined3d_mutex_unlock();
+
+    return priority;
+}
+
+static void WINAPI d3d8_vertexbuffer_PreLoad(IDirect3DVertexBuffer8 *iface)
+{
+    struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    wined3d_buffer_preload(buffer->wined3d_buffer);
+    wined3d_mutex_unlock();
+}
+
+static D3DRESOURCETYPE WINAPI d3d8_vertexbuffer_GetType(IDirect3DVertexBuffer8 *iface)
+{
+    TRACE("iface %p.\n", iface);
+
+    return D3DRTYPE_VERTEXBUFFER;
+}
+
+static HRESULT WINAPI d3d8_vertexbuffer_Lock(IDirect3DVertexBuffer8 *iface, UINT offset, UINT size,
+        BYTE **data, DWORD flags)
+{
+    struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, offset %u, size %u, data %p, flags %#x.\n",
+            iface, offset, size, data, flags);
+
+    wined3d_mutex_lock();
+    hr = wined3d_buffer_map(buffer->wined3d_buffer, offset, size, data, flags);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_vertexbuffer_Unlock(IDirect3DVertexBuffer8 *iface)
+{
+    struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    wined3d_buffer_unmap(buffer->wined3d_buffer);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_vertexbuffer_GetDesc(IDirect3DVertexBuffer8 *iface,
+        D3DVERTEXBUFFER_DESC *desc)
+{
+    struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
+    struct wined3d_resource_desc wined3d_desc;
+    struct wined3d_resource *wined3d_resource;
+
+    TRACE("iface %p, desc %p.\n", iface, desc);
+
+    wined3d_mutex_lock();
+    wined3d_resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
+    wined3d_resource_get_desc(wined3d_resource, &wined3d_desc);
+    wined3d_mutex_unlock();
+
+    desc->Type = D3DRTYPE_VERTEXBUFFER;
+    desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
+    desc->Pool = wined3d_desc.pool;
+    desc->Size = wined3d_desc.size;
+    desc->FVF = buffer->fvf;
+    desc->Format = D3DFMT_VERTEXDATA;
+
+    return D3D_OK;
+}
+
+static const IDirect3DVertexBuffer8Vtbl Direct3DVertexBuffer8_Vtbl =
+{
+    /* IUnknown */
+    d3d8_vertexbuffer_QueryInterface,
+    d3d8_vertexbuffer_AddRef,
+    d3d8_vertexbuffer_Release,
+    /* IDirect3DResource8 */
+    d3d8_vertexbuffer_GetDevice,
+    d3d8_vertexbuffer_SetPrivateData,
+    d3d8_vertexbuffer_GetPrivateData,
+    d3d8_vertexbuffer_FreePrivateData,
+    d3d8_vertexbuffer_SetPriority,
+    d3d8_vertexbuffer_GetPriority,
+    d3d8_vertexbuffer_PreLoad,
+    d3d8_vertexbuffer_GetType,
+    /* IDirect3DVertexBuffer8 */
+    d3d8_vertexbuffer_Lock,
+    d3d8_vertexbuffer_Unlock,
+    d3d8_vertexbuffer_GetDesc,
+};
+
+static void STDMETHODCALLTYPE d3d8_vertexbuffer_wined3d_object_destroyed(void *parent)
+{
+    HeapFree(GetProcessHeap(), 0, parent);
+}
+
+static const struct wined3d_parent_ops d3d8_vertexbuffer_wined3d_parent_ops =
+{
+    d3d8_vertexbuffer_wined3d_object_destroyed,
+};
+
+HRESULT vertexbuffer_init(struct d3d8_vertexbuffer *buffer, struct d3d8_device *device,
+        UINT size, DWORD usage, DWORD fvf, D3DPOOL pool)
+{
+    HRESULT hr;
+
+    buffer->IDirect3DVertexBuffer8_iface.lpVtbl = &Direct3DVertexBuffer8_Vtbl;
+    buffer->refcount = 1;
+    buffer->fvf = fvf;
+
+    wined3d_mutex_lock();
+    hr = wined3d_buffer_create_vb(device->wined3d_device, size, usage & WINED3DUSAGE_MASK,
+            (enum wined3d_pool)pool, buffer, &d3d8_vertexbuffer_wined3d_parent_ops, &buffer->wined3d_buffer);
+    wined3d_mutex_unlock();
+    if (FAILED(hr))
+    {
+        WARN("Failed to create wined3d buffer, hr %#x.\n", hr);
+        return hr;
+    }
+
+    buffer->parent_device = &device->IDirect3DDevice8_iface;
+    IDirect3DDevice8_AddRef(buffer->parent_device);
+
+    return D3D_OK;
+}
+
+struct d3d8_vertexbuffer *unsafe_impl_from_IDirect3DVertexBuffer8(IDirect3DVertexBuffer8 *iface)
+{
+    if (!iface)
+        return NULL;
+    assert(iface->lpVtbl == &Direct3DVertexBuffer8_Vtbl);
+
+    return impl_from_IDirect3DVertexBuffer8(iface);
+}
+
+static inline struct d3d8_indexbuffer *impl_from_IDirect3DIndexBuffer8(IDirect3DIndexBuffer8 *iface)
+{
+    return CONTAINING_RECORD(iface, struct d3d8_indexbuffer, IDirect3DIndexBuffer8_iface);
+}
+
+static HRESULT WINAPI d3d8_indexbuffer_QueryInterface(IDirect3DIndexBuffer8 *iface, REFIID riid, void **object)
+{
+    TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
+
+    if (IsEqualGUID(riid, &IID_IDirect3DIndexBuffer8)
+            || IsEqualGUID(riid, &IID_IDirect3DResource8)
+            || IsEqualGUID(riid, &IID_IUnknown))
+    {
+        IDirect3DIndexBuffer8_AddRef(iface);
+        *object = iface;
+        return S_OK;
+    }
+
+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+    *object = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI d3d8_indexbuffer_AddRef(IDirect3DIndexBuffer8 *iface)
+{
+    struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
+    ULONG refcount = InterlockedIncrement(&buffer->refcount);
+
+    TRACE("%p increasing refcount to %u.\n", iface, refcount);
+
+    if (refcount == 1)
+    {
+        IDirect3DDevice8_AddRef(buffer->parent_device);
+        wined3d_mutex_lock();
+        wined3d_buffer_incref(buffer->wined3d_buffer);
+        wined3d_mutex_unlock();
+    }
+
+    return refcount;
+}
+
+static ULONG WINAPI d3d8_indexbuffer_Release(IDirect3DIndexBuffer8 *iface)
+{
+    struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
+    ULONG refcount = InterlockedDecrement(&buffer->refcount);
+
+    TRACE("%p decreasing refcount to %u.\n", iface, refcount);
+
+    if (!refcount)
+    {
+        IDirect3DDevice8 *device = buffer->parent_device;
+
+        wined3d_mutex_lock();
+        wined3d_buffer_decref(buffer->wined3d_buffer);
+        wined3d_mutex_unlock();
+
+        /* Release the device last, as it may cause the device to be destroyed. */
+        IDirect3DDevice8_Release(device);
+    }
+
+    return refcount;
+}
+
+static HRESULT WINAPI d3d8_indexbuffer_GetDevice(IDirect3DIndexBuffer8 *iface,
+        IDirect3DDevice8 **device)
+{
+    struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
+
+    TRACE("iface %p, device %p.\n", iface, device);
+
+    *device = buffer->parent_device;
+    IDirect3DDevice8_AddRef(*device);
+
+    TRACE("Returning device %p.\n", *device);
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_indexbuffer_SetPrivateData(IDirect3DIndexBuffer8 *iface,
+        REFGUID guid, const void *data, DWORD data_size, DWORD flags)
+{
+    struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
+            iface, debugstr_guid(guid), data, data_size, flags);
+
+    wined3d_mutex_lock();
+    resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
+    hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_indexbuffer_GetPrivateData(IDirect3DIndexBuffer8 *iface,
+        REFGUID guid, void *data, DWORD *data_size)
+{
+    struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s, data %p, data_size %p.\n",
+            iface, debugstr_guid(guid), data, data_size);
+
+    wined3d_mutex_lock();
+    resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
+    hr = wined3d_resource_get_private_data(resource, guid, data, data_size);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_indexbuffer_FreePrivateData(IDirect3DIndexBuffer8 *iface, REFGUID guid)
+{
+    struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
+
+    wined3d_mutex_lock();
+    resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
+    hr = wined3d_resource_free_private_data(resource, guid);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static DWORD WINAPI d3d8_indexbuffer_SetPriority(IDirect3DIndexBuffer8 *iface, DWORD priority)
+{
+    struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
+    DWORD previous;
+
+    TRACE("iface %p, priority %u.\n", iface, priority);
+
+    wined3d_mutex_lock();
+    previous = wined3d_buffer_set_priority(buffer->wined3d_buffer, priority);
+    wined3d_mutex_unlock();
+
+    return previous;
+}
+
+static DWORD WINAPI d3d8_indexbuffer_GetPriority(IDirect3DIndexBuffer8 *iface)
+{
+    struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
+    DWORD priority;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    priority = wined3d_buffer_get_priority(buffer->wined3d_buffer);
+    wined3d_mutex_unlock();
+
+    return priority;
+}
+
+static void WINAPI d3d8_indexbuffer_PreLoad(IDirect3DIndexBuffer8 *iface)
+{
+    struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    wined3d_buffer_preload(buffer->wined3d_buffer);
+    wined3d_mutex_unlock();
+}
+
+static D3DRESOURCETYPE WINAPI d3d8_indexbuffer_GetType(IDirect3DIndexBuffer8 *iface)
+{
+    TRACE("iface %p.\n", iface);
+
+    return D3DRTYPE_INDEXBUFFER;
+}
+
+static HRESULT WINAPI d3d8_indexbuffer_Lock(IDirect3DIndexBuffer8 *iface, UINT offset, UINT size,
+        BYTE **data, DWORD flags)
+{
+    struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, offset %u, size %u, data %p, flags %#x.\n",
+            iface, offset, size, data, flags);
+
+    wined3d_mutex_lock();
+    hr = wined3d_buffer_map(buffer->wined3d_buffer, offset, size, data, flags);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_indexbuffer_Unlock(IDirect3DIndexBuffer8 *iface)
+{
+    struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    wined3d_buffer_unmap(buffer->wined3d_buffer);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_indexbuffer_GetDesc(IDirect3DIndexBuffer8 *iface,
+        D3DINDEXBUFFER_DESC *desc)
+{
+    struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
+    struct wined3d_resource_desc wined3d_desc;
+    struct wined3d_resource *wined3d_resource;
+
+    TRACE("iface %p, desc %p.\n", iface, desc);
+
+    wined3d_mutex_lock();
+    wined3d_resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
+    wined3d_resource_get_desc(wined3d_resource, &wined3d_desc);
+    wined3d_mutex_unlock();
+
+    desc->Format = d3dformat_from_wined3dformat(buffer->format);
+    desc->Type = D3DRTYPE_INDEXBUFFER;
+    desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
+    desc->Pool = wined3d_desc.pool;
+    desc->Size = wined3d_desc.size;
+
+    return D3D_OK;
+}
+
+static const IDirect3DIndexBuffer8Vtbl d3d8_indexbuffer_vtbl =
+{
+    /* IUnknown */
+    d3d8_indexbuffer_QueryInterface,
+    d3d8_indexbuffer_AddRef,
+    d3d8_indexbuffer_Release,
+    /* IDirect3DResource8 */
+    d3d8_indexbuffer_GetDevice,
+    d3d8_indexbuffer_SetPrivateData,
+    d3d8_indexbuffer_GetPrivateData,
+    d3d8_indexbuffer_FreePrivateData,
+    d3d8_indexbuffer_SetPriority,
+    d3d8_indexbuffer_GetPriority,
+    d3d8_indexbuffer_PreLoad,
+    d3d8_indexbuffer_GetType,
+    /* IDirect3DIndexBuffer8 */
+    d3d8_indexbuffer_Lock,
+    d3d8_indexbuffer_Unlock,
+    d3d8_indexbuffer_GetDesc,
+};
+
+static void STDMETHODCALLTYPE d3d8_indexbuffer_wined3d_object_destroyed(void *parent)
+{
+    HeapFree(GetProcessHeap(), 0, parent);
+}
+
+static const struct wined3d_parent_ops d3d8_indexbuffer_wined3d_parent_ops =
+{
+    d3d8_indexbuffer_wined3d_object_destroyed,
+};
+
+HRESULT indexbuffer_init(struct d3d8_indexbuffer *buffer, struct d3d8_device *device,
+        UINT size, DWORD usage, D3DFORMAT format, D3DPOOL pool)
+{
+    HRESULT hr;
+
+    buffer->IDirect3DIndexBuffer8_iface.lpVtbl = &d3d8_indexbuffer_vtbl;
+    buffer->refcount = 1;
+    buffer->format = wined3dformat_from_d3dformat(format);
+
+    wined3d_mutex_lock();
+    hr = wined3d_buffer_create_ib(device->wined3d_device, size, usage & WINED3DUSAGE_MASK,
+            (enum wined3d_pool)pool, buffer, &d3d8_indexbuffer_wined3d_parent_ops, &buffer->wined3d_buffer);
+    wined3d_mutex_unlock();
+    if (FAILED(hr))
+    {
+        WARN("Failed to create wined3d buffer, hr %#x.\n", hr);
+        return hr;
+    }
+
+    buffer->parent_device = &device->IDirect3DDevice8_iface;
+    IDirect3DDevice8_AddRef(buffer->parent_device);
+
+    return D3D_OK;
+}
+
+struct d3d8_indexbuffer *unsafe_impl_from_IDirect3DIndexBuffer8(IDirect3DIndexBuffer8 *iface)
+{
+    if (!iface)
+        return NULL;
+    assert(iface->lpVtbl == &d3d8_indexbuffer_vtbl);
+
+    return impl_from_IDirect3DIndexBuffer8(iface);
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/d3d8.def
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/d3d8.def	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/d3d8.def	(revision 46521)
@@ -0,0 +1,10 @@
+; File generated automatically from ./dlls/d3d8/d3d8.spec; do not edit!
+
+LIBRARY d3d8.dll
+
+EXPORTS
+  D3D8GetSWInfo
+  DebugSetMute
+  Direct3DCreate8
+  ValidatePixelShader
+  ValidateVertexShader
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/d3d8_main.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/d3d8_main.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/d3d8_main.c	(revision 46521)
@@ -0,0 +1,140 @@
+/*
+ * Direct3D 8
+ *
+ * Copyright 2005 Oliver Stieber
+ *
+ * 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 "d3d8_private.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d8);
+
+HRESULT WINAPI D3D8GetSWInfo(void) {
+    FIXME("(void): stub\n");
+    return 0;
+}
+
+void WINAPI DebugSetMute(void) {
+    /* nothing to do */
+}
+
+IDirect3D8 * WINAPI DECLSPEC_HOTPATCH Direct3DCreate8(UINT sdk_version)
+{
+    struct d3d8 *object;
+
+    TRACE("sdk_version %#x.\n", sdk_version);
+
+    if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
+        return NULL;
+
+    if (!d3d8_init(object))
+    {
+        WARN("Failed to initialize d3d8.\n");
+        HeapFree(GetProcessHeap(), 0, object);
+        return NULL;
+    }
+
+    TRACE("Created d3d8 object %p.\n", object);
+
+    return &object->IDirect3D8_iface;
+}
+
+/* At process attach */
+BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
+{
+    TRACE("fdwReason=%d\n", fdwReason);
+    if (fdwReason == DLL_PROCESS_ATTACH)
+        DisableThreadLibraryCalls(hInstDLL);
+
+    return TRUE;
+}
+
+/***********************************************************************
+ *              ValidateVertexShader (D3D8.@)
+ *
+ * I've seen reserved1 and reserved2 always passed as 0's
+ * bool seems always passed as 0 or 1, but other values work as well...
+ * toto       result?
+ */
+HRESULT WINAPI ValidateVertexShader(DWORD* vertexshader, DWORD* reserved1, DWORD* reserved2, BOOL bool, DWORD* toto)
+{
+  HRESULT ret;
+  static BOOL warned;
+
+  if (TRACE_ON(d3d8) || !warned) {
+      FIXME("(%p %p %p %d %p): stub\n", vertexshader, reserved1, reserved2, bool, toto);
+      warned = TRUE;
+  }
+
+  if (!vertexshader)
+      return E_FAIL;
+
+  if (reserved1 || reserved2)
+      return E_FAIL;
+
+  switch(*vertexshader) {
+        case 0xFFFE0101:
+        case 0xFFFE0100:
+            ret=S_OK;
+            break;
+        default:
+            WARN("Invalid shader version token %#x.\n", *vertexshader);
+            ret=E_FAIL;
+        }
+
+  return ret;
+}
+
+/***********************************************************************
+ *              ValidatePixelShader (D3D8.@)
+ *
+ * PARAMS
+ * toto       result?
+ */
+HRESULT WINAPI ValidatePixelShader(DWORD* pixelshader, DWORD* reserved1, BOOL bool, DWORD* toto)
+{
+  HRESULT ret;
+  static BOOL warned;
+
+  if (TRACE_ON(d3d8) || !warned) {
+      FIXME("(%p %p %d %p): stub\n", pixelshader, reserved1, bool, toto);
+      warned = TRUE;
+  }
+
+  if (!pixelshader)
+      return E_FAIL;
+
+  if (reserved1)
+      return E_FAIL;
+
+  switch(*pixelshader) {
+        case 0xFFFF0100:
+        case 0xFFFF0101:
+        case 0xFFFF0102:
+        case 0xFFFF0103:
+        case 0xFFFF0104:
+            ret=S_OK;
+            break;
+        default:
+            WARN("Invalid shader version token %#x.\n", *pixelshader);
+            ret=E_FAIL;
+        }
+  return ret;
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/d3d8_private.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/d3d8_private.h	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/d3d8_private.h	(revision 46521)
@@ -0,0 +1,302 @@
+/*
+ * Direct3D 8 private include file
+ *
+ * Copyright 2002-2004 Jason Edmeades
+ * Copyright 2003-2004 Raphael Junqueira
+ * Copyright 2004 Christian Costa
+ *
+ * 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_D3D8_PRIVATE_H
+#define __WINE_D3D8_PRIVATE_H
+
+#include <assert.h>
+#include <stdarg.h>
+
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+#define COBJMACROS
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "wine/debug.h"
+#include "d3d8.h"
+#include "wine/wined3d.h"
+
+/* CreateVertexShader can return > 0xFFFF */
+#define VS_HIGHESTFIXEDFXF 0xF0000000
+
+/* ===========================================================================
+    Macros
+   =========================================================================== */
+/* Not nice, but it lets wined3d support different versions of directx */
+#define WINECAPSTOD3D8CAPS(_pD3D8Caps, _pWineCaps) \
+    _pD3D8Caps->DeviceType                        = (D3DDEVTYPE) _pWineCaps->DeviceType; \
+    _pD3D8Caps->AdapterOrdinal                    = _pWineCaps->AdapterOrdinal; \
+    _pD3D8Caps->Caps                              = _pWineCaps->Caps; \
+    _pD3D8Caps->Caps2                             = _pWineCaps->Caps2; \
+    _pD3D8Caps->Caps3                             = _pWineCaps->Caps3; \
+    _pD3D8Caps->PresentationIntervals             = _pWineCaps->PresentationIntervals; \
+    _pD3D8Caps->CursorCaps                        = _pWineCaps->CursorCaps; \
+    _pD3D8Caps->DevCaps                           = _pWineCaps->DevCaps; \
+    _pD3D8Caps->PrimitiveMiscCaps                 = _pWineCaps->PrimitiveMiscCaps; \
+    _pD3D8Caps->RasterCaps                        = _pWineCaps->RasterCaps; \
+    _pD3D8Caps->ZCmpCaps                          = _pWineCaps->ZCmpCaps; \
+    _pD3D8Caps->SrcBlendCaps                      = _pWineCaps->SrcBlendCaps; \
+    _pD3D8Caps->DestBlendCaps                     = _pWineCaps->DestBlendCaps; \
+    _pD3D8Caps->AlphaCmpCaps                      = _pWineCaps->AlphaCmpCaps; \
+    _pD3D8Caps->ShadeCaps                         = _pWineCaps->ShadeCaps; \
+    _pD3D8Caps->TextureCaps                       = _pWineCaps->TextureCaps; \
+    _pD3D8Caps->TextureFilterCaps                 = _pWineCaps->TextureFilterCaps; \
+    _pD3D8Caps->CubeTextureFilterCaps             = _pWineCaps->CubeTextureFilterCaps; \
+    _pD3D8Caps->VolumeTextureFilterCaps           = _pWineCaps->VolumeTextureFilterCaps; \
+    _pD3D8Caps->TextureAddressCaps                = _pWineCaps->TextureAddressCaps; \
+    _pD3D8Caps->VolumeTextureAddressCaps          = _pWineCaps->VolumeTextureAddressCaps; \
+    _pD3D8Caps->LineCaps                          = _pWineCaps->LineCaps; \
+    _pD3D8Caps->MaxTextureWidth                   = _pWineCaps->MaxTextureWidth; \
+    _pD3D8Caps->MaxTextureHeight                  = _pWineCaps->MaxTextureHeight; \
+    _pD3D8Caps->MaxVolumeExtent                   = _pWineCaps->MaxVolumeExtent; \
+    _pD3D8Caps->MaxTextureRepeat                  = _pWineCaps->MaxTextureRepeat; \
+    _pD3D8Caps->MaxTextureAspectRatio             = _pWineCaps->MaxTextureAspectRatio; \
+    _pD3D8Caps->MaxAnisotropy                     = _pWineCaps->MaxAnisotropy; \
+    _pD3D8Caps->MaxVertexW                        = _pWineCaps->MaxVertexW; \
+    _pD3D8Caps->GuardBandLeft                     = _pWineCaps->GuardBandLeft; \
+    _pD3D8Caps->GuardBandTop                      = _pWineCaps->GuardBandTop; \
+    _pD3D8Caps->GuardBandRight                    = _pWineCaps->GuardBandRight; \
+    _pD3D8Caps->GuardBandBottom                   = _pWineCaps->GuardBandBottom; \
+    _pD3D8Caps->ExtentsAdjust                     = _pWineCaps->ExtentsAdjust; \
+    _pD3D8Caps->StencilCaps                       = _pWineCaps->StencilCaps; \
+    _pD3D8Caps->FVFCaps                           = _pWineCaps->FVFCaps; \
+    _pD3D8Caps->TextureOpCaps                     = _pWineCaps->TextureOpCaps; \
+    _pD3D8Caps->MaxTextureBlendStages             = _pWineCaps->MaxTextureBlendStages; \
+    _pD3D8Caps->MaxSimultaneousTextures           = _pWineCaps->MaxSimultaneousTextures; \
+    _pD3D8Caps->VertexProcessingCaps              = _pWineCaps->VertexProcessingCaps; \
+    _pD3D8Caps->MaxActiveLights                   = _pWineCaps->MaxActiveLights; \
+    _pD3D8Caps->MaxUserClipPlanes                 = _pWineCaps->MaxUserClipPlanes; \
+    _pD3D8Caps->MaxVertexBlendMatrices            = _pWineCaps->MaxVertexBlendMatrices; \
+    _pD3D8Caps->MaxVertexBlendMatrixIndex         = _pWineCaps->MaxVertexBlendMatrixIndex; \
+    _pD3D8Caps->MaxPointSize                      = _pWineCaps->MaxPointSize; \
+    _pD3D8Caps->MaxPrimitiveCount                 = _pWineCaps->MaxPrimitiveCount; \
+    _pD3D8Caps->MaxVertexIndex                    = _pWineCaps->MaxVertexIndex; \
+    _pD3D8Caps->MaxStreams                        = _pWineCaps->MaxStreams; \
+    _pD3D8Caps->MaxStreamStride                   = _pWineCaps->MaxStreamStride; \
+    _pD3D8Caps->VertexShaderVersion               = _pWineCaps->VertexShaderVersion; \
+    _pD3D8Caps->MaxVertexShaderConst              = _pWineCaps->MaxVertexShaderConst; \
+    _pD3D8Caps->PixelShaderVersion                = _pWineCaps->PixelShaderVersion; \
+    _pD3D8Caps->MaxPixelShaderValue               = _pWineCaps->PixelShader1xMaxValue;
+
+void fixup_caps(WINED3DCAPS *pWineCaps) DECLSPEC_HIDDEN;
+
+struct d3d8
+{
+    IDirect3D8 IDirect3D8_iface;
+    LONG refcount;
+    struct wined3d *wined3d;
+};
+
+BOOL d3d8_init(struct d3d8 *d3d8) DECLSPEC_HIDDEN;
+
+/*****************************************************************************
+ * IDirect3DDevice8 implementation structure
+ */
+
+#define D3D8_INITIAL_HANDLE_TABLE_SIZE 64
+#define D3D8_INVALID_HANDLE ~0U
+
+enum d3d8_handle_type
+{
+    D3D8_HANDLE_FREE,
+    D3D8_HANDLE_VS,
+    D3D8_HANDLE_PS,
+    D3D8_HANDLE_SB,
+};
+
+struct d3d8_handle_entry
+{
+    void *object;
+    enum d3d8_handle_type type;
+};
+
+struct d3d8_handle_table
+{
+    struct d3d8_handle_entry *entries;
+    struct d3d8_handle_entry *free_entries;
+    UINT table_size;
+    UINT entry_count;
+};
+
+struct FvfToDecl
+{
+    DWORD fvf;
+    struct d3d8_vertex_declaration *declaration;
+};
+
+struct d3d8_device
+{
+    /* IUnknown fields */
+    IDirect3DDevice8        IDirect3DDevice8_iface;
+    struct wined3d_device_parent device_parent;
+    LONG                    ref;
+    struct wined3d_device  *wined3d_device;
+    IDirect3D8             *d3d_parent;
+    struct                  d3d8_handle_table handle_table;
+
+    /* FVF management */
+    struct FvfToDecl       *decls;
+    UINT                    numConvertedDecls, declArraySize;
+
+    /* User data draws */
+    struct wined3d_buffer *vertex_buffer;
+    UINT                   vertex_buffer_size;
+    UINT                   vertex_buffer_pos;
+    struct wined3d_buffer *index_buffer;
+    UINT                   index_buffer_size;
+    UINT                   index_buffer_pos;
+
+    /* Avoids recursion with nested ReleaseRef to 0 */
+    BOOL                    inDestruction;
+    BOOL lost;
+};
+
+HRESULT device_init(struct d3d8_device *device, struct d3d8 *parent, struct wined3d *wined3d, UINT adapter,
+        D3DDEVTYPE device_type, HWND focus_window, DWORD flags, D3DPRESENT_PARAMETERS *parameters) DECLSPEC_HIDDEN;
+
+struct d3d8_volume
+{
+    IDirect3DVolume8 IDirect3DVolume8_iface;
+    LONG refcount;
+    struct wined3d_volume *wined3d_volume;
+    IUnknown *container;
+    IUnknown *forwardReference;
+};
+
+HRESULT volume_init(struct d3d8_volume *volume, struct d3d8_device *device, UINT width, UINT height,
+        UINT depth, DWORD usage, enum wined3d_format_id format, enum wined3d_pool pool) DECLSPEC_HIDDEN;
+
+struct d3d8_swapchain
+{
+    IDirect3DSwapChain8 IDirect3DSwapChain8_iface;
+    LONG refcount;
+    struct wined3d_swapchain *wined3d_swapchain;
+    IDirect3DDevice8 *parent_device;
+};
+
+HRESULT d3d8_swapchain_create(struct d3d8_device *device, struct wined3d_swapchain_desc *desc,
+        struct d3d8_swapchain **swapchain) DECLSPEC_HIDDEN;
+
+struct d3d8_surface
+{
+    IDirect3DSurface8 IDirect3DSurface8_iface;
+    LONG refcount;
+    struct wined3d_surface *wined3d_surface;
+    IDirect3DDevice8 *parent_device;
+
+    /* The surface container */
+    IUnknown                    *container;
+
+    /* If set forward refcounting to this object */
+    IUnknown                    *forwardReference;
+};
+
+HRESULT surface_init(struct d3d8_surface *surface, struct d3d8_device *device, UINT width, UINT height,
+        D3DFORMAT format, DWORD flags, DWORD usage, D3DPOOL pool, D3DMULTISAMPLE_TYPE multisample_type,
+        DWORD multisample_quality) DECLSPEC_HIDDEN;
+struct d3d8_surface *unsafe_impl_from_IDirect3DSurface8(IDirect3DSurface8 *iface) DECLSPEC_HIDDEN;
+
+struct d3d8_vertexbuffer
+{
+    IDirect3DVertexBuffer8 IDirect3DVertexBuffer8_iface;
+    LONG refcount;
+    struct wined3d_buffer *wined3d_buffer;
+    IDirect3DDevice8 *parent_device;
+    DWORD fvf;
+};
+
+HRESULT vertexbuffer_init(struct d3d8_vertexbuffer *buffer, struct d3d8_device *device,
+        UINT size, DWORD usage, DWORD fvf, D3DPOOL pool) DECLSPEC_HIDDEN;
+struct d3d8_vertexbuffer *unsafe_impl_from_IDirect3DVertexBuffer8(IDirect3DVertexBuffer8 *iface) DECLSPEC_HIDDEN;
+
+struct d3d8_indexbuffer
+{
+    IDirect3DIndexBuffer8 IDirect3DIndexBuffer8_iface;
+    LONG refcount;
+    struct wined3d_buffer *wined3d_buffer;
+    IDirect3DDevice8 *parent_device;
+    enum wined3d_format_id format;
+};
+
+HRESULT indexbuffer_init(struct d3d8_indexbuffer *buffer, struct d3d8_device *device,
+        UINT size, DWORD usage, D3DFORMAT format, D3DPOOL pool) DECLSPEC_HIDDEN;
+struct d3d8_indexbuffer *unsafe_impl_from_IDirect3DIndexBuffer8(IDirect3DIndexBuffer8 *iface) DECLSPEC_HIDDEN;
+
+struct d3d8_texture
+{
+    IDirect3DBaseTexture8 IDirect3DBaseTexture8_iface;
+    LONG refcount;
+    struct wined3d_texture *wined3d_texture;
+    IDirect3DDevice8 *parent_device;
+};
+
+HRESULT cubetexture_init(struct d3d8_texture *texture, struct d3d8_device *device,
+        UINT edge_length, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool) DECLSPEC_HIDDEN;
+HRESULT texture_init(struct d3d8_texture *texture, struct d3d8_device *device,
+        UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool) DECLSPEC_HIDDEN;
+HRESULT volumetexture_init(struct d3d8_texture *texture, struct d3d8_device *device,
+        UINT width, UINT height, UINT depth, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool) DECLSPEC_HIDDEN;
+struct d3d8_texture *unsafe_impl_from_IDirect3DBaseTexture8(IDirect3DBaseTexture8 *iface) DECLSPEC_HIDDEN;
+
+struct d3d8_vertex_declaration
+{
+    DWORD *elements;
+    DWORD elements_size; /* Size of elements, in bytes */
+    struct wined3d_vertex_declaration *wined3d_vertex_declaration;
+    DWORD shader_handle;
+};
+
+void d3d8_vertex_declaration_destroy(struct d3d8_vertex_declaration *declaration) DECLSPEC_HIDDEN;
+HRESULT d3d8_vertex_declaration_init(struct d3d8_vertex_declaration *declaration,
+        struct d3d8_device *device, const DWORD *elements, DWORD shader_handle) DECLSPEC_HIDDEN;
+HRESULT d3d8_vertex_declaration_init_fvf(struct d3d8_vertex_declaration *declaration,
+        struct d3d8_device *device, DWORD fvf) DECLSPEC_HIDDEN;
+
+struct d3d8_vertex_shader
+{
+  struct d3d8_vertex_declaration *vertex_declaration;
+  struct wined3d_shader *wined3d_shader;
+};
+
+void d3d8_vertex_shader_destroy(struct d3d8_vertex_shader *shader) DECLSPEC_HIDDEN;
+HRESULT d3d8_vertex_shader_init(struct d3d8_vertex_shader *shader, struct d3d8_device *device,
+        const DWORD *declaration, const DWORD *byte_code, DWORD shader_handle, DWORD usage) DECLSPEC_HIDDEN;
+
+#define D3D8_MAX_VERTEX_SHADER_CONSTANTF 256
+
+struct d3d8_pixel_shader
+{
+    DWORD handle;
+    struct wined3d_shader *wined3d_shader;
+};
+
+void d3d8_pixel_shader_destroy(struct d3d8_pixel_shader *shader) DECLSPEC_HIDDEN;
+HRESULT d3d8_pixel_shader_init(struct d3d8_pixel_shader *shader, struct d3d8_device *device,
+        const DWORD *byte_code, DWORD shader_handle) DECLSPEC_HIDDEN;
+
+D3DFORMAT d3dformat_from_wined3dformat(enum wined3d_format_id format) DECLSPEC_HIDDEN;
+enum wined3d_format_id wined3dformat_from_d3dformat(D3DFORMAT format) DECLSPEC_HIDDEN;
+void load_local_constants(const DWORD *d3d8_elements, struct wined3d_shader *wined3d_vertex_shader) DECLSPEC_HIDDEN;
+size_t parse_token(const DWORD *pToken) DECLSPEC_HIDDEN;
+
+#endif /* __WINE_D3DX8_PRIVATE_H */
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/device.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/device.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/device.c	(revision 46521)
@@ -0,0 +1,3154 @@
+/*
+ * IDirect3DDevice8 implementation
+ *
+ * Copyright 2002-2004 Jason Edmeades
+ * Copyright 2004 Christian Costa
+ *
+ * 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 <math.h>
+#include <stdarg.h>
+
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "wingdi.h"
+#include "wine/debug.h"
+
+#include "d3d8_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d8);
+
+D3DFORMAT d3dformat_from_wined3dformat(enum wined3d_format_id format)
+{
+    BYTE *c = (BYTE *)&format;
+
+    /* Don't translate FOURCC formats */
+    if (isprint(c[0]) && isprint(c[1]) && isprint(c[2]) && isprint(c[3])) return format;
+
+    switch(format)
+    {
+        case WINED3DFMT_UNKNOWN: return D3DFMT_UNKNOWN;
+        case WINED3DFMT_B8G8R8_UNORM: return D3DFMT_R8G8B8;
+        case WINED3DFMT_B8G8R8A8_UNORM: return D3DFMT_A8R8G8B8;
+        case WINED3DFMT_B8G8R8X8_UNORM: return D3DFMT_X8R8G8B8;
+        case WINED3DFMT_B5G6R5_UNORM: return D3DFMT_R5G6B5;
+        case WINED3DFMT_B5G5R5X1_UNORM: return D3DFMT_X1R5G5B5;
+        case WINED3DFMT_B5G5R5A1_UNORM: return D3DFMT_A1R5G5B5;
+        case WINED3DFMT_B4G4R4A4_UNORM: return D3DFMT_A4R4G4B4;
+        case WINED3DFMT_B2G3R3_UNORM: return D3DFMT_R3G3B2;
+        case WINED3DFMT_A8_UNORM: return D3DFMT_A8;
+        case WINED3DFMT_B2G3R3A8_UNORM: return D3DFMT_A8R3G3B2;
+        case WINED3DFMT_B4G4R4X4_UNORM: return D3DFMT_X4R4G4B4;
+        case WINED3DFMT_R10G10B10A2_UNORM: return D3DFMT_A2B10G10R10;
+        case WINED3DFMT_R16G16_UNORM: return D3DFMT_G16R16;
+        case WINED3DFMT_P8_UINT_A8_UNORM: return D3DFMT_A8P8;
+        case WINED3DFMT_P8_UINT: return D3DFMT_P8;
+        case WINED3DFMT_L8_UNORM: return D3DFMT_L8;
+        case WINED3DFMT_L8A8_UNORM: return D3DFMT_A8L8;
+        case WINED3DFMT_L4A4_UNORM: return D3DFMT_A4L4;
+        case WINED3DFMT_R8G8_SNORM: return D3DFMT_V8U8;
+        case WINED3DFMT_R5G5_SNORM_L6_UNORM: return D3DFMT_L6V5U5;
+        case WINED3DFMT_R8G8_SNORM_L8X8_UNORM: return D3DFMT_X8L8V8U8;
+        case WINED3DFMT_R8G8B8A8_SNORM: return D3DFMT_Q8W8V8U8;
+        case WINED3DFMT_R16G16_SNORM: return D3DFMT_V16U16;
+        case WINED3DFMT_R10G11B11_SNORM: return D3DFMT_W11V11U10;
+        case WINED3DFMT_R10G10B10_SNORM_A2_UNORM: return D3DFMT_A2W10V10U10;
+        case WINED3DFMT_D16_LOCKABLE: return D3DFMT_D16_LOCKABLE;
+        case WINED3DFMT_D32_UNORM: return D3DFMT_D32;
+        case WINED3DFMT_S1_UINT_D15_UNORM: return D3DFMT_D15S1;
+        case WINED3DFMT_D24_UNORM_S8_UINT: return D3DFMT_D24S8;
+        case WINED3DFMT_X8D24_UNORM: return D3DFMT_D24X8;
+        case WINED3DFMT_S4X4_UINT_D24_UNORM: return D3DFMT_D24X4S4;
+        case WINED3DFMT_D16_UNORM: return D3DFMT_D16;
+        case WINED3DFMT_VERTEXDATA: return D3DFMT_VERTEXDATA;
+        case WINED3DFMT_R16_UINT: return D3DFMT_INDEX16;
+        case WINED3DFMT_R32_UINT: return D3DFMT_INDEX32;
+        default:
+            FIXME("Unhandled wined3d format %#x.\n", format);
+            return D3DFMT_UNKNOWN;
+    }
+}
+
+enum wined3d_format_id wined3dformat_from_d3dformat(D3DFORMAT format)
+{
+    BYTE *c = (BYTE *)&format;
+
+    /* Don't translate FOURCC formats */
+    if (isprint(c[0]) && isprint(c[1]) && isprint(c[2]) && isprint(c[3])) return format;
+
+    switch(format)
+    {
+        case D3DFMT_UNKNOWN: return WINED3DFMT_UNKNOWN;
+        case D3DFMT_R8G8B8: return WINED3DFMT_B8G8R8_UNORM;
+        case D3DFMT_A8R8G8B8: return WINED3DFMT_B8G8R8A8_UNORM;
+        case D3DFMT_X8R8G8B8: return WINED3DFMT_B8G8R8X8_UNORM;
+        case D3DFMT_R5G6B5: return WINED3DFMT_B5G6R5_UNORM;
+        case D3DFMT_X1R5G5B5: return WINED3DFMT_B5G5R5X1_UNORM;
+        case D3DFMT_A1R5G5B5: return WINED3DFMT_B5G5R5A1_UNORM;
+        case D3DFMT_A4R4G4B4: return WINED3DFMT_B4G4R4A4_UNORM;
+        case D3DFMT_R3G3B2: return WINED3DFMT_B2G3R3_UNORM;
+        case D3DFMT_A8: return WINED3DFMT_A8_UNORM;
+        case D3DFMT_A8R3G3B2: return WINED3DFMT_B2G3R3A8_UNORM;
+        case D3DFMT_X4R4G4B4: return WINED3DFMT_B4G4R4X4_UNORM;
+        case D3DFMT_A2B10G10R10: return WINED3DFMT_R10G10B10A2_UNORM;
+        case D3DFMT_G16R16: return WINED3DFMT_R16G16_UNORM;
+        case D3DFMT_A8P8: return WINED3DFMT_P8_UINT_A8_UNORM;
+        case D3DFMT_P8: return WINED3DFMT_P8_UINT;
+        case D3DFMT_L8: return WINED3DFMT_L8_UNORM;
+        case D3DFMT_A8L8: return WINED3DFMT_L8A8_UNORM;
+        case D3DFMT_A4L4: return WINED3DFMT_L4A4_UNORM;
+        case D3DFMT_V8U8: return WINED3DFMT_R8G8_SNORM;
+        case D3DFMT_L6V5U5: return WINED3DFMT_R5G5_SNORM_L6_UNORM;
+        case D3DFMT_X8L8V8U8: return WINED3DFMT_R8G8_SNORM_L8X8_UNORM;
+        case D3DFMT_Q8W8V8U8: return WINED3DFMT_R8G8B8A8_SNORM;
+        case D3DFMT_V16U16: return WINED3DFMT_R16G16_SNORM;
+        case D3DFMT_W11V11U10: return WINED3DFMT_R10G11B11_SNORM;
+        case D3DFMT_A2W10V10U10: return WINED3DFMT_R10G10B10_SNORM_A2_UNORM;
+        case D3DFMT_D16_LOCKABLE: return WINED3DFMT_D16_LOCKABLE;
+        case D3DFMT_D32: return WINED3DFMT_D32_UNORM;
+        case D3DFMT_D15S1: return WINED3DFMT_S1_UINT_D15_UNORM;
+        case D3DFMT_D24S8: return WINED3DFMT_D24_UNORM_S8_UINT;
+        case D3DFMT_D24X8: return WINED3DFMT_X8D24_UNORM;
+        case D3DFMT_D24X4S4: return WINED3DFMT_S4X4_UINT_D24_UNORM;
+        case D3DFMT_D16: return WINED3DFMT_D16_UNORM;
+        case D3DFMT_VERTEXDATA: return WINED3DFMT_VERTEXDATA;
+        case D3DFMT_INDEX16: return WINED3DFMT_R16_UINT;
+        case D3DFMT_INDEX32: return WINED3DFMT_R32_UINT;
+        default:
+            FIXME("Unhandled D3DFORMAT %#x\n", format);
+            return WINED3DFMT_UNKNOWN;
+    }
+}
+
+static UINT vertex_count_from_primitive_count(D3DPRIMITIVETYPE primitive_type, UINT primitive_count)
+{
+    switch(primitive_type)
+    {
+        case D3DPT_POINTLIST:
+            return primitive_count;
+
+        case D3DPT_LINELIST:
+            return primitive_count * 2;
+
+        case D3DPT_LINESTRIP:
+            return primitive_count + 1;
+
+        case D3DPT_TRIANGLELIST:
+            return primitive_count * 3;
+
+        case D3DPT_TRIANGLESTRIP:
+        case D3DPT_TRIANGLEFAN:
+            return primitive_count + 2;
+
+        default:
+            FIXME("Unhandled primitive type %#x\n", primitive_type);
+            return 0;
+    }
+}
+
+static void present_parameters_from_wined3d_swapchain_desc(D3DPRESENT_PARAMETERS *present_parameters,
+        const struct wined3d_swapchain_desc *swapchain_desc)
+{
+    present_parameters->BackBufferWidth = swapchain_desc->backbuffer_width;
+    present_parameters->BackBufferHeight = swapchain_desc->backbuffer_height;
+    present_parameters->BackBufferFormat = d3dformat_from_wined3dformat(swapchain_desc->backbuffer_format);
+    present_parameters->BackBufferCount = swapchain_desc->backbuffer_count;
+    present_parameters->MultiSampleType = swapchain_desc->multisample_type;
+    present_parameters->SwapEffect = swapchain_desc->swap_effect;
+    present_parameters->hDeviceWindow = swapchain_desc->device_window;
+    present_parameters->Windowed = swapchain_desc->windowed;
+    present_parameters->EnableAutoDepthStencil = swapchain_desc->enable_auto_depth_stencil;
+    present_parameters->AutoDepthStencilFormat
+            = d3dformat_from_wined3dformat(swapchain_desc->auto_depth_stencil_format);
+    present_parameters->Flags = swapchain_desc->flags;
+    present_parameters->FullScreen_RefreshRateInHz = swapchain_desc->refresh_rate;
+    present_parameters->FullScreen_PresentationInterval = swapchain_desc->swap_interval;
+}
+
+static void wined3d_swapchain_desc_from_present_parameters(struct wined3d_swapchain_desc *swapchain_desc,
+        const D3DPRESENT_PARAMETERS *present_parameters)
+{
+    swapchain_desc->backbuffer_width = present_parameters->BackBufferWidth;
+    swapchain_desc->backbuffer_height = present_parameters->BackBufferHeight;
+    swapchain_desc->backbuffer_format = wined3dformat_from_d3dformat(present_parameters->BackBufferFormat);
+    swapchain_desc->backbuffer_count = max(1, present_parameters->BackBufferCount);
+    swapchain_desc->multisample_type = present_parameters->MultiSampleType;
+    swapchain_desc->multisample_quality = 0; /* d3d9 only */
+    swapchain_desc->swap_effect = present_parameters->SwapEffect;
+    swapchain_desc->device_window = present_parameters->hDeviceWindow;
+    swapchain_desc->windowed = present_parameters->Windowed;
+    swapchain_desc->enable_auto_depth_stencil = present_parameters->EnableAutoDepthStencil;
+    swapchain_desc->auto_depth_stencil_format
+            = wined3dformat_from_d3dformat(present_parameters->AutoDepthStencilFormat);
+    swapchain_desc->flags = present_parameters->Flags;
+    swapchain_desc->refresh_rate = present_parameters->FullScreen_RefreshRateInHz;
+    swapchain_desc->swap_interval = present_parameters->FullScreen_PresentationInterval;
+    swapchain_desc->auto_restore_display_mode = TRUE;
+}
+
+/* Handle table functions */
+static DWORD d3d8_allocate_handle(struct d3d8_handle_table *t, void *object, enum d3d8_handle_type type)
+{
+    struct d3d8_handle_entry *entry;
+
+    if (t->free_entries)
+    {
+        DWORD index = t->free_entries - t->entries;
+        /* Use a free handle */
+        entry = t->free_entries;
+        if (entry->type != D3D8_HANDLE_FREE)
+        {
+            ERR("Handle %u(%p) is in the free list, but has type %#x.\n", index, entry, entry->type);
+            return D3D8_INVALID_HANDLE;
+        }
+        t->free_entries = entry->object;
+        entry->object = object;
+        entry->type = type;
+
+        return index;
+    }
+
+    if (!(t->entry_count < t->table_size))
+    {
+        /* Grow the table */
+        UINT new_size = t->table_size + (t->table_size >> 1);
+        struct d3d8_handle_entry *new_entries = HeapReAlloc(GetProcessHeap(),
+                0, t->entries, new_size * sizeof(*t->entries));
+        if (!new_entries)
+        {
+            ERR("Failed to grow the handle table.\n");
+            return D3D8_INVALID_HANDLE;
+        }
+        t->entries = new_entries;
+        t->table_size = new_size;
+    }
+
+    entry = &t->entries[t->entry_count];
+    entry->object = object;
+    entry->type = type;
+
+    return t->entry_count++;
+}
+
+static void *d3d8_free_handle(struct d3d8_handle_table *t, DWORD handle, enum d3d8_handle_type type)
+{
+    struct d3d8_handle_entry *entry;
+    void *object;
+
+    if (handle == D3D8_INVALID_HANDLE || handle >= t->entry_count)
+    {
+        WARN("Invalid handle %u passed.\n", handle);
+        return NULL;
+    }
+
+    entry = &t->entries[handle];
+    if (entry->type != type)
+    {
+        WARN("Handle %u(%p) is not of type %#x.\n", handle, entry, type);
+        return NULL;
+    }
+
+    object = entry->object;
+    entry->object = t->free_entries;
+    entry->type = D3D8_HANDLE_FREE;
+    t->free_entries = entry;
+
+    return object;
+}
+
+static void *d3d8_get_object(struct d3d8_handle_table *t, DWORD handle, enum d3d8_handle_type type)
+{
+    struct d3d8_handle_entry *entry;
+
+    if (handle == D3D8_INVALID_HANDLE || handle >= t->entry_count)
+    {
+        WARN("Invalid handle %u passed.\n", handle);
+        return NULL;
+    }
+
+    entry = &t->entries[handle];
+    if (entry->type != type)
+    {
+        WARN("Handle %u(%p) is not of type %#x.\n", handle, entry, type);
+        return NULL;
+    }
+
+    return entry->object;
+}
+
+static inline struct d3d8_device *impl_from_IDirect3DDevice8(IDirect3DDevice8 *iface)
+{
+    return CONTAINING_RECORD(iface, struct d3d8_device, IDirect3DDevice8_iface);
+}
+
+static HRESULT WINAPI d3d8_device_QueryInterface(IDirect3DDevice8 *iface, REFIID riid, void **out)
+{
+    TRACE("iface %p, riid %s, out %p.\n",
+            iface, debugstr_guid(riid), out);
+
+    if (IsEqualGUID(riid, &IID_IDirect3DDevice8)
+            || IsEqualGUID(riid, &IID_IUnknown))
+    {
+        IDirect3DDevice8_AddRef(iface);
+        *out = iface;
+        return S_OK;
+    }
+
+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+    *out = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI d3d8_device_AddRef(IDirect3DDevice8 *iface)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    ULONG ref = InterlockedIncrement(&device->ref);
+
+    TRACE("%p increasing refcount to %u.\n", iface, ref);
+
+    return ref;
+}
+
+static ULONG WINAPI d3d8_device_Release(IDirect3DDevice8 *iface)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    ULONG ref;
+
+    if (device->inDestruction)
+        return 0;
+
+    ref = InterlockedDecrement(&device->ref);
+
+    TRACE("%p decreasing refcount to %u.\n", iface, ref);
+
+    if (!ref)
+    {
+        IDirect3D8 *parent = device->d3d_parent;
+        unsigned i;
+
+        TRACE("Releasing wined3d device %p.\n", device->wined3d_device);
+
+        wined3d_mutex_lock();
+
+        device->inDestruction = TRUE;
+
+        for (i = 0; i < device->numConvertedDecls; ++i)
+        {
+            d3d8_vertex_declaration_destroy(device->decls[i].declaration);
+        }
+        HeapFree(GetProcessHeap(), 0, device->decls);
+
+        if (device->vertex_buffer)
+            wined3d_buffer_decref(device->vertex_buffer);
+        if (device->index_buffer)
+            wined3d_buffer_decref(device->index_buffer);
+
+        wined3d_device_uninit_3d(device->wined3d_device);
+        wined3d_device_release_focus_window(device->wined3d_device);
+        wined3d_device_decref(device->wined3d_device);
+        HeapFree(GetProcessHeap(), 0, device->handle_table.entries);
+        HeapFree(GetProcessHeap(), 0, device);
+
+        wined3d_mutex_unlock();
+
+        IDirect3D8_Release(parent);
+    }
+    return ref;
+}
+
+static HRESULT WINAPI d3d8_device_TestCooperativeLevel(IDirect3DDevice8 *iface)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    if (device->lost)
+    {
+        TRACE("Device is lost.\n");
+        return D3DERR_DEVICENOTRESET;
+    }
+
+    return D3D_OK;
+}
+
+static UINT WINAPI d3d8_device_GetAvailableTextureMem(IDirect3DDevice8 *iface)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_get_available_texture_mem(device->wined3d_device);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_ResourceManagerDiscardBytes(IDirect3DDevice8 *iface, DWORD byte_count)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+
+    TRACE("iface %p, byte_count %u.\n", iface, byte_count);
+
+    if (byte_count)
+        FIXME("Byte count ignored.\n");
+
+    wined3d_mutex_lock();
+    wined3d_device_evict_managed_resources(device->wined3d_device);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_GetDirect3D(IDirect3DDevice8 *iface, IDirect3D8 **d3d8)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+
+    TRACE("iface %p, d3d8 %p.\n", iface, d3d8);
+
+    if (!d3d8)
+        return D3DERR_INVALIDCALL;
+
+    return IDirect3D8_QueryInterface(device->d3d_parent, &IID_IDirect3D8, (void **)d3d8);
+}
+
+static HRESULT WINAPI d3d8_device_GetDeviceCaps(IDirect3DDevice8 *iface, D3DCAPS8 *caps)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    WINED3DCAPS *wined3d_caps;
+    HRESULT hr;
+
+    TRACE("iface %p, caps %p.\n", iface, caps);
+
+    if (!caps)
+        return D3DERR_INVALIDCALL;
+
+    if (!(wined3d_caps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*wined3d_caps))))
+        return D3DERR_INVALIDCALL; /* well this is what MSDN says to return */
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_get_device_caps(device->wined3d_device, wined3d_caps);
+    wined3d_mutex_unlock();
+
+    fixup_caps(wined3d_caps);
+    WINECAPSTOD3D8CAPS(caps, wined3d_caps)
+    HeapFree(GetProcessHeap(), 0, wined3d_caps);
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_GetDisplayMode(IDirect3DDevice8 *iface, D3DDISPLAYMODE *mode)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct wined3d_display_mode wined3d_mode;
+    HRESULT hr;
+
+    TRACE("iface %p, mode %p.\n", iface, mode);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_get_display_mode(device->wined3d_device, 0, &wined3d_mode, NULL);
+    wined3d_mutex_unlock();
+
+    if (SUCCEEDED(hr))
+    {
+        mode->Width = wined3d_mode.width;
+        mode->Height = wined3d_mode.height;
+        mode->RefreshRate = wined3d_mode.refresh_rate;
+        mode->Format = d3dformat_from_wined3dformat(wined3d_mode.format_id);
+    }
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_GetCreationParameters(IDirect3DDevice8 *iface,
+        D3DDEVICE_CREATION_PARAMETERS *parameters)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+
+    TRACE("iface %p, parameters %p.\n", iface, parameters);
+
+    wined3d_mutex_lock();
+    wined3d_device_get_creation_parameters(device->wined3d_device,
+            (struct wined3d_device_creation_parameters *)parameters);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_SetCursorProperties(IDirect3DDevice8 *iface,
+        UINT hotspot_x, UINT hotspot_y, IDirect3DSurface8 *bitmap)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct d3d8_surface *bitmap_impl = unsafe_impl_from_IDirect3DSurface8(bitmap);
+    HRESULT hr;
+
+    TRACE("iface %p, hotspot_x %u, hotspot_y %u, bitmap %p.\n",
+            iface, hotspot_x, hotspot_y, bitmap);
+
+    if (!bitmap)
+    {
+        WARN("No cursor bitmap, returning D3DERR_INVALIDCALL.\n");
+        return D3DERR_INVALIDCALL;
+    }
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_set_cursor_properties(device->wined3d_device,
+            hotspot_x, hotspot_y, bitmap_impl->wined3d_surface);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static void WINAPI d3d8_device_SetCursorPosition(IDirect3DDevice8 *iface, UINT x, UINT y, DWORD flags)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+
+    TRACE("iface %p, x %u, y %u, flags %#x.\n", iface, x, y, flags);
+
+    wined3d_mutex_lock();
+    wined3d_device_set_cursor_position(device->wined3d_device, x, y, flags);
+    wined3d_mutex_unlock();
+}
+
+static BOOL WINAPI d3d8_device_ShowCursor(IDirect3DDevice8 *iface, BOOL show)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    BOOL ret;
+
+    TRACE("iface %p, show %#x.\n", iface, show);
+
+    wined3d_mutex_lock();
+    ret = wined3d_device_show_cursor(device->wined3d_device, show);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static HRESULT WINAPI d3d8_device_CreateAdditionalSwapChain(IDirect3DDevice8 *iface,
+        D3DPRESENT_PARAMETERS *present_parameters, IDirect3DSwapChain8 **swapchain)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct wined3d_swapchain_desc desc;
+    struct d3d8_swapchain *object;
+
+    TRACE("iface %p, present_parameters %p, swapchain %p.\n",
+            iface, present_parameters, swapchain);
+
+    wined3d_swapchain_desc_from_present_parameters(&desc, present_parameters);
+    if (SUCCEEDED(d3d8_swapchain_create(device, &desc, &object)))
+        *swapchain = &object->IDirect3DSwapChain8_iface;
+    present_parameters_from_wined3d_swapchain_desc(present_parameters, &desc);
+
+    return D3D_OK;
+}
+
+static HRESULT CDECL reset_enum_callback(struct wined3d_resource *resource)
+{
+    struct wined3d_resource_desc desc;
+
+    wined3d_resource_get_desc(resource, &desc);
+    if (desc.pool == WINED3D_POOL_DEFAULT)
+    {
+        struct d3d8_surface *surface;
+
+        if (desc.resource_type == WINED3D_RTYPE_TEXTURE)
+        {
+            IUnknown *parent = wined3d_resource_get_parent(resource);
+            IDirect3DBaseTexture8 *texture;
+
+            if (SUCCEEDED(IUnknown_QueryInterface(parent, &IID_IDirect3DBaseTexture8, (void **)&texture)))
+            {
+                IDirect3DBaseTexture8_Release(texture);
+                WARN("Texture %p (resource %p) in pool D3DPOOL_DEFAULT blocks the Reset call.\n", texture, resource);
+                return D3DERR_DEVICELOST;
+            }
+
+            return D3D_OK;
+        }
+
+        if (desc.resource_type != WINED3D_RTYPE_SURFACE)
+        {
+            WARN("Resource %p in pool D3DPOOL_DEFAULT blocks the Reset call.\n", resource);
+            return D3DERR_DEVICELOST;
+        }
+
+        surface = wined3d_resource_get_parent(resource);
+        if (surface->refcount)
+        {
+            WARN("Surface %p (resource %p) in pool D3DPOOL_DEFAULT blocks the Reset call.\n", surface, resource);
+            return D3DERR_DEVICELOST;
+        }
+
+        WARN("Surface %p (resource %p) is an implicit resource with ref 0.\n", surface, resource);
+    }
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_Reset(IDirect3DDevice8 *iface,
+        D3DPRESENT_PARAMETERS *present_parameters)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct wined3d_swapchain_desc swapchain_desc;
+    HRESULT hr;
+
+    TRACE("iface %p, present_parameters %p.\n", iface, present_parameters);
+
+    wined3d_mutex_lock();
+
+    if (device->vertex_buffer)
+    {
+        wined3d_buffer_decref(device->vertex_buffer);
+        device->vertex_buffer = NULL;
+        device->vertex_buffer_size = 0;
+    }
+    if (device->index_buffer)
+    {
+        wined3d_buffer_decref(device->index_buffer);
+        device->index_buffer = NULL;
+        device->index_buffer_size = 0;
+    }
+
+    wined3d_swapchain_desc_from_present_parameters(&swapchain_desc, present_parameters);
+    if (SUCCEEDED(hr = wined3d_device_reset(device->wined3d_device, &swapchain_desc,
+            NULL, reset_enum_callback, TRUE)))
+    {
+        wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_POINTSIZE_MIN, 0);
+        device->lost = FALSE;
+    }
+    else
+    {
+        device->lost = TRUE;
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_Present(IDirect3DDevice8 *iface, const RECT *src_rect,
+        const RECT *dst_rect, HWND dst_window_override, const RGNDATA *dirty_region)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, src_rect %s, dst_rect %s, dst_window_override %p, dirty_region %p.\n",
+            iface, wine_dbgstr_rect(src_rect), wine_dbgstr_rect(dst_rect), dst_window_override, dirty_region);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_present(device->wined3d_device, src_rect, dst_rect,
+            dst_window_override, dirty_region, 0);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_GetBackBuffer(IDirect3DDevice8 *iface,
+        UINT backbuffer_idx, D3DBACKBUFFER_TYPE backbuffer_type, IDirect3DSurface8 **backbuffer)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct wined3d_surface *wined3d_surface = NULL;
+    struct d3d8_surface *surface_impl;
+    HRESULT hr;
+
+    TRACE("iface %p, backbuffer_idx %u, backbuffer_type %#x, backbuffer %p.\n",
+            iface, backbuffer_idx, backbuffer_type, backbuffer);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_get_back_buffer(device->wined3d_device, 0, backbuffer_idx,
+            (enum wined3d_backbuffer_type)backbuffer_type, &wined3d_surface);
+    if (SUCCEEDED(hr) && wined3d_surface && backbuffer)
+    {
+        surface_impl = wined3d_surface_get_parent(wined3d_surface);
+        *backbuffer = &surface_impl->IDirect3DSurface8_iface;
+        IDirect3DSurface8_AddRef(*backbuffer);
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_GetRasterStatus(IDirect3DDevice8 *iface, D3DRASTER_STATUS *raster_status)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, raster_status %p.\n", iface, raster_status);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_get_raster_status(device->wined3d_device, 0, (struct wined3d_raster_status *)raster_status);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static void WINAPI d3d8_device_SetGammaRamp(IDirect3DDevice8 *iface, DWORD flags, const D3DGAMMARAMP *ramp)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+
+    TRACE("iface %p, flags %#x, ramp %p.\n", iface, flags, ramp);
+
+    /* Note: D3DGAMMARAMP is compatible with struct wined3d_gamma_ramp. */
+    wined3d_mutex_lock();
+    wined3d_device_set_gamma_ramp(device->wined3d_device, 0, flags, (const struct wined3d_gamma_ramp *)ramp);
+    wined3d_mutex_unlock();
+}
+
+static void WINAPI d3d8_device_GetGammaRamp(IDirect3DDevice8 *iface, D3DGAMMARAMP *ramp)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+
+    TRACE("iface %p, ramp %p.\n", iface, ramp);
+
+    /* Note: D3DGAMMARAMP is compatible with struct wined3d_gamma_ramp. */
+    wined3d_mutex_lock();
+    wined3d_device_get_gamma_ramp(device->wined3d_device, 0, (struct wined3d_gamma_ramp *)ramp);
+    wined3d_mutex_unlock();
+}
+
+static HRESULT WINAPI d3d8_device_CreateTexture(IDirect3DDevice8 *iface,
+        UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format,
+        D3DPOOL pool, IDirect3DTexture8 **texture)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct d3d8_texture *object;
+    HRESULT hr;
+
+    TRACE("iface %p, width %u, height %u, levels %u, usage %#x, format %#x, pool %#x, texture %p.\n",
+            iface, width, height, levels, usage, format, pool, texture);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return D3DERR_OUTOFVIDEOMEMORY;
+
+    hr = texture_init(object, device, width, height, levels, usage, format, pool);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize texture, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created texture %p.\n", object);
+    *texture = (IDirect3DTexture8 *)&object->IDirect3DBaseTexture8_iface;
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_CreateVolumeTexture(IDirect3DDevice8 *iface,
+        UINT width, UINT height, UINT depth, UINT levels, DWORD usage, D3DFORMAT format,
+        D3DPOOL pool, IDirect3DVolumeTexture8 **texture)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct d3d8_texture *object;
+    HRESULT hr;
+
+    TRACE("iface %p, width %u, height %u, depth %u, levels %u, usage %#x, format %#x, pool %#x, texture %p.\n",
+            iface, width, height, depth, levels, usage, format, pool, texture);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return D3DERR_OUTOFVIDEOMEMORY;
+
+    hr = volumetexture_init(object, device, width, height, depth, levels, usage, format, pool);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize volume texture, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created volume texture %p.\n", object);
+    *texture = (IDirect3DVolumeTexture8 *)&object->IDirect3DBaseTexture8_iface;
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_CreateCubeTexture(IDirect3DDevice8 *iface, UINT edge_length,
+        UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool, IDirect3DCubeTexture8 **texture)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct d3d8_texture *object;
+    HRESULT hr;
+
+    TRACE("iface %p, edge_length %u, levels %u, usage %#x, format %#x, pool %#x, texture %p.\n",
+            iface, edge_length, levels, usage, format, pool, texture);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return D3DERR_OUTOFVIDEOMEMORY;
+
+    hr = cubetexture_init(object, device, edge_length, levels, usage, format, pool);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize cube texture, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created cube texture %p.\n", object);
+    *texture = (IDirect3DCubeTexture8 *)&object->IDirect3DBaseTexture8_iface;
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_CreateVertexBuffer(IDirect3DDevice8 *iface, UINT size,
+        DWORD usage, DWORD fvf, D3DPOOL pool, IDirect3DVertexBuffer8 **buffer)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct d3d8_vertexbuffer *object;
+    HRESULT hr;
+
+    TRACE("iface %p, size %u, usage %#x, fvf %#x, pool %#x, buffer %p.\n",
+            iface, size, usage, fvf, pool, buffer);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return D3DERR_OUTOFVIDEOMEMORY;
+
+    hr = vertexbuffer_init(object, device, size, usage, fvf, pool);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize vertex buffer, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created vertex buffer %p.\n", object);
+    *buffer = &object->IDirect3DVertexBuffer8_iface;
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_CreateIndexBuffer(IDirect3DDevice8 *iface, UINT size,
+        DWORD usage, D3DFORMAT format, D3DPOOL pool, IDirect3DIndexBuffer8 **buffer)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct d3d8_indexbuffer *object;
+    HRESULT hr;
+
+    TRACE("iface %p, size %u, usage %#x, format %#x, pool %#x, buffer %p.\n",
+            iface, size, usage, format, pool, buffer);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return D3DERR_OUTOFVIDEOMEMORY;
+
+    hr = indexbuffer_init(object, device, size, usage, format, pool);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize index buffer, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created index buffer %p.\n", object);
+    *buffer = &object->IDirect3DIndexBuffer8_iface;
+
+    return D3D_OK;
+}
+
+static HRESULT d3d8_device_create_surface(struct d3d8_device *device, UINT width, UINT height,
+        D3DFORMAT format, DWORD flags, IDirect3DSurface8 **surface, UINT usage, D3DPOOL pool,
+        D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality)
+{
+    struct d3d8_surface *object;
+    HRESULT hr;
+
+    TRACE("device %p, width %u, height %u, format %#x, flags %#x, surface %p,\n"
+            "\tusage %#x, pool %#x, multisample_type %#x, multisample_quality %u.\n",
+            device, width, height, format, flags, surface,
+            usage, pool, multisample_type, multisample_quality);
+
+    if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
+    {
+        FIXME("Failed to allocate surface memory.\n");
+        return D3DERR_OUTOFVIDEOMEMORY;
+    }
+
+    if (FAILED(hr = surface_init(object, device, width, height, format,
+            flags, usage, pool, multisample_type, multisample_quality)))
+    {
+        WARN("Failed to initialize surface, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created surface %p.\n", object);
+    *surface = &object->IDirect3DSurface8_iface;
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_CreateRenderTarget(IDirect3DDevice8 *iface, UINT width,
+        UINT height, D3DFORMAT format, D3DMULTISAMPLE_TYPE multisample_type, BOOL lockable,
+        IDirect3DSurface8 **surface)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    DWORD flags = 0;
+
+    TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, lockable %#x, surface %p.\n",
+            iface, width, height, format, multisample_type, lockable, surface);
+
+    if (lockable)
+        flags |= WINED3D_SURFACE_MAPPABLE;
+
+    return d3d8_device_create_surface(device, width, height, format, flags, surface,
+            D3DUSAGE_RENDERTARGET, D3DPOOL_DEFAULT, multisample_type, 0);
+}
+
+static HRESULT WINAPI d3d8_device_CreateDepthStencilSurface(IDirect3DDevice8 *iface,
+        UINT width, UINT height, D3DFORMAT format, D3DMULTISAMPLE_TYPE multisample_type,
+        IDirect3DSurface8 **surface)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+
+    TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, surface %p.\n",
+            iface, width, height, format, multisample_type, surface);
+
+    /* TODO: Verify that Discard is false */
+    return d3d8_device_create_surface(device, width, height, format, WINED3D_SURFACE_MAPPABLE,
+            surface, D3DUSAGE_DEPTHSTENCIL, D3DPOOL_DEFAULT, multisample_type, 0);
+}
+
+/*  IDirect3DDevice8Impl::CreateImageSurface returns surface with pool type SYSTEMMEM */
+static HRESULT WINAPI d3d8_device_CreateImageSurface(IDirect3DDevice8 *iface, UINT width,
+        UINT height, D3DFORMAT format, IDirect3DSurface8 **surface)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+
+    TRACE("iface %p, width %u, height %u, format %#x, surface %p.\n",
+            iface, width, height, format, surface);
+
+    return d3d8_device_create_surface(device, width, height, format, WINED3D_SURFACE_MAPPABLE,
+            surface, 0, D3DPOOL_SYSTEMMEM, D3DMULTISAMPLE_NONE, 0);
+}
+
+static HRESULT WINAPI d3d8_device_CopyRects(IDirect3DDevice8 *iface,
+        IDirect3DSurface8 *src_surface, const RECT *src_rects, UINT rect_count,
+        IDirect3DSurface8 *dst_surface, const POINT *dst_points)
+{
+    struct d3d8_surface *src = unsafe_impl_from_IDirect3DSurface8(src_surface);
+    struct d3d8_surface *dst = unsafe_impl_from_IDirect3DSurface8(dst_surface);
+    enum wined3d_format_id src_format, dst_format;
+    struct wined3d_resource_desc wined3d_desc;
+    struct wined3d_resource *wined3d_resource;
+    UINT src_w, src_h;
+    HRESULT hr;
+
+    TRACE("iface %p, src_surface %p, src_rects %p, rect_count %u, dst_surface %p, dst_points %p.\n",
+            iface, src_surface, src_rects, rect_count, dst_surface, dst_points);
+
+    /* Check that the source texture is in WINED3D_POOL_SYSTEM_MEM and the
+     * destination texture is in WINED3D_POOL_DEFAULT. */
+
+    wined3d_mutex_lock();
+    wined3d_resource = wined3d_surface_get_resource(src->wined3d_surface);
+    wined3d_resource_get_desc(wined3d_resource, &wined3d_desc);
+    if (wined3d_desc.usage & WINED3DUSAGE_DEPTHSTENCIL)
+    {
+        WARN("Source %p is a depth stencil surface, returning D3DERR_INVALIDCALL.\n", src_surface);
+        wined3d_mutex_unlock();
+        return D3DERR_INVALIDCALL;
+    }
+    src_format = wined3d_desc.format;
+    src_w = wined3d_desc.width;
+    src_h = wined3d_desc.height;
+
+    wined3d_resource = wined3d_surface_get_resource(dst->wined3d_surface);
+    wined3d_resource_get_desc(wined3d_resource, &wined3d_desc);
+    if (wined3d_desc.usage & WINED3DUSAGE_DEPTHSTENCIL)
+    {
+        WARN("Destination %p is a depth stencil surface, returning D3DERR_INVALIDCALL.\n", dst_surface);
+        wined3d_mutex_unlock();
+        return D3DERR_INVALIDCALL;
+    }
+    dst_format = wined3d_desc.format;
+
+    /* Check that the source and destination formats match */
+    if (src_format != dst_format && WINED3DFMT_UNKNOWN != dst_format)
+    {
+        WARN("Source %p format must match the destination %p format, returning D3DERR_INVALIDCALL.\n",
+                src_surface, dst_surface);
+        wined3d_mutex_unlock();
+        return D3DERR_INVALIDCALL;
+    }
+    else if (WINED3DFMT_UNKNOWN == dst_format)
+    {
+        TRACE("Converting destination surface from WINED3DFMT_UNKNOWN to the source format.\n");
+        if (FAILED(hr = wined3d_surface_update_desc(dst->wined3d_surface, wined3d_desc.width, wined3d_desc.height,
+                src_format, wined3d_desc.multisample_type, wined3d_desc.multisample_quality)))
+        {
+            WARN("Failed to update surface desc, hr %#x.\n", hr);
+            wined3d_mutex_unlock();
+            return hr;
+        }
+    }
+
+    /* Quick if complete copy ... */
+    if (!rect_count && !src_rects && !dst_points)
+    {
+        RECT rect = {0, 0, src_w, src_h};
+        wined3d_surface_blt(dst->wined3d_surface, &rect,
+                src->wined3d_surface, &rect, 0, NULL, WINED3D_TEXF_POINT);
+    }
+    else
+    {
+        unsigned int i;
+        /* Copy rect by rect */
+        if (src_rects && dst_points)
+        {
+            for (i = 0; i < rect_count; ++i)
+            {
+                UINT w = src_rects[i].right - src_rects[i].left;
+                UINT h = src_rects[i].bottom - src_rects[i].top;
+                RECT dst_rect = {dst_points[i].x, dst_points[i].y,
+                        dst_points[i].x + w, dst_points[i].y + h};
+
+                wined3d_surface_blt(dst->wined3d_surface, &dst_rect,
+                        src->wined3d_surface, &src_rects[i], 0, NULL, WINED3D_TEXF_POINT);
+            }
+        }
+        else
+        {
+            for (i = 0; i < rect_count; ++i)
+            {
+                UINT w = src_rects[i].right - src_rects[i].left;
+                UINT h = src_rects[i].bottom - src_rects[i].top;
+                RECT dst_rect = {0, 0, w, h};
+
+                wined3d_surface_blt(dst->wined3d_surface, &dst_rect,
+                        src->wined3d_surface, &src_rects[i], 0, NULL, WINED3D_TEXF_POINT);
+            }
+        }
+    }
+    wined3d_mutex_unlock();
+
+    return WINED3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_UpdateTexture(IDirect3DDevice8 *iface,
+        IDirect3DBaseTexture8 *src_texture, IDirect3DBaseTexture8 *dst_texture)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct d3d8_texture *src_impl, *dst_impl;
+    HRESULT hr;
+
+    TRACE("iface %p, src_texture %p, dst_texture %p.\n", iface, src_texture, dst_texture);
+
+    src_impl = unsafe_impl_from_IDirect3DBaseTexture8(src_texture);
+    dst_impl = unsafe_impl_from_IDirect3DBaseTexture8(dst_texture);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_update_texture(device->wined3d_device,
+            src_impl->wined3d_texture, dst_impl->wined3d_texture);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_GetFrontBuffer(IDirect3DDevice8 *iface, IDirect3DSurface8 *dst_surface)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct d3d8_surface *dst_impl = unsafe_impl_from_IDirect3DSurface8(dst_surface);
+    HRESULT hr;
+
+    TRACE("iface %p, dst_surface %p.\n", iface, dst_surface);
+
+    if (!dst_surface)
+    {
+        WARN("Invalid destination surface passed.\n");
+        return D3DERR_INVALIDCALL;
+    }
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_get_front_buffer_data(device->wined3d_device, 0, dst_impl->wined3d_surface);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_SetRenderTarget(IDirect3DDevice8 *iface,
+        IDirect3DSurface8 *render_target, IDirect3DSurface8 *depth_stencil)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct d3d8_surface *rt_impl = unsafe_impl_from_IDirect3DSurface8(render_target);
+    struct d3d8_surface *ds_impl = unsafe_impl_from_IDirect3DSurface8(depth_stencil);
+    struct wined3d_surface *original_ds = NULL;
+    HRESULT hr = D3D_OK;
+
+    TRACE("iface %p, render_target %p, depth_stencil %p.\n", iface, render_target, depth_stencil);
+
+    wined3d_mutex_lock();
+
+    if (ds_impl)
+    {
+        struct wined3d_resource_desc ds_desc, rt_desc;
+        struct wined3d_resource *wined3d_resource;
+        struct wined3d_surface *original_rt = NULL;
+
+        /* If no render target is passed in check the size against the current RT */
+        if (!render_target)
+        {
+            if (!(original_rt = wined3d_device_get_render_target(device->wined3d_device, 0)))
+            {
+                wined3d_mutex_unlock();
+                return D3DERR_NOTFOUND;
+            }
+            wined3d_resource = wined3d_surface_get_resource(original_rt);
+        }
+        else
+            wined3d_resource = wined3d_surface_get_resource(rt_impl->wined3d_surface);
+        wined3d_resource_get_desc(wined3d_resource, &rt_desc);
+
+        wined3d_resource = wined3d_surface_get_resource(ds_impl->wined3d_surface);
+        wined3d_resource_get_desc(wined3d_resource, &ds_desc);
+
+        if (ds_desc.width < rt_desc.width || ds_desc.height < rt_desc.height)
+        {
+            WARN("Depth stencil is smaller than the render target, returning D3DERR_INVALIDCALL\n");
+            wined3d_mutex_unlock();
+            return D3DERR_INVALIDCALL;
+        }
+    }
+
+    original_ds = wined3d_device_get_depth_stencil(device->wined3d_device);
+    wined3d_device_set_depth_stencil(device->wined3d_device, ds_impl ? ds_impl->wined3d_surface : NULL);
+    if (render_target)
+        {
+            hr = wined3d_device_set_render_target(device->wined3d_device, 0, rt_impl->wined3d_surface, TRUE);
+            if (FAILED(hr))
+                wined3d_device_set_depth_stencil(device->wined3d_device, original_ds);
+        }
+
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_GetRenderTarget(IDirect3DDevice8 *iface, IDirect3DSurface8 **render_target)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct wined3d_surface *wined3d_surface;
+    struct d3d8_surface *surface_impl;
+    HRESULT hr;
+
+    TRACE("iface %p, render_target %p.\n", iface, render_target);
+
+    if (!render_target)
+        return D3DERR_INVALIDCALL;
+
+    wined3d_mutex_lock();
+    if ((wined3d_surface = wined3d_device_get_render_target(device->wined3d_device, 0)))
+    {
+        surface_impl = wined3d_surface_get_parent(wined3d_surface);
+        *render_target = &surface_impl->IDirect3DSurface8_iface;
+        IDirect3DSurface8_AddRef(*render_target);
+        hr = D3D_OK;
+    }
+    else
+    {
+        ERR("Failed to get wined3d render target.\n");
+        *render_target = NULL;
+        hr = D3DERR_NOTFOUND;
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_GetDepthStencilSurface(IDirect3DDevice8 *iface, IDirect3DSurface8 **depth_stencil)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct wined3d_surface *wined3d_surface;
+    struct d3d8_surface *surface_impl;
+    HRESULT hr = D3D_OK;
+
+    TRACE("iface %p, depth_stencil %p.\n", iface, depth_stencil);
+
+    if (!depth_stencil)
+        return D3DERR_INVALIDCALL;
+
+    wined3d_mutex_lock();
+    if ((wined3d_surface = wined3d_device_get_depth_stencil(device->wined3d_device)))
+    {
+        surface_impl = wined3d_surface_get_parent(wined3d_surface);
+        *depth_stencil = &surface_impl->IDirect3DSurface8_iface;
+        IDirect3DSurface8_AddRef(*depth_stencil);
+    }
+    else
+    {
+        hr = WINED3DERR_NOTFOUND;
+        *depth_stencil = NULL;
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_BeginScene(IDirect3DDevice8 *iface)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_begin_scene(device->wined3d_device);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI DECLSPEC_HOTPATCH d3d8_device_EndScene(IDirect3DDevice8 *iface)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_end_scene(device->wined3d_device);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_Clear(IDirect3DDevice8 *iface, DWORD rect_count,
+        const D3DRECT *rects, DWORD flags, D3DCOLOR color, float z, DWORD stencil)
+{
+    const struct wined3d_color c =
+    {
+        ((color >> 16) & 0xff) / 255.0f,
+        ((color >>  8) & 0xff) / 255.0f,
+        (color & 0xff) / 255.0f,
+        ((color >> 24) & 0xff) / 255.0f,
+    };
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, rect_count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %u.\n",
+            iface, rect_count, rects, flags, color, z, stencil);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_clear(device->wined3d_device, rect_count, (const RECT *)rects, flags, &c, z, stencil);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_SetTransform(IDirect3DDevice8 *iface,
+        D3DTRANSFORMSTATETYPE state, const D3DMATRIX *matrix)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+
+    TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
+
+    /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
+    wined3d_mutex_lock();
+    wined3d_device_set_transform(device->wined3d_device, state, (const struct wined3d_matrix *)matrix);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_GetTransform(IDirect3DDevice8 *iface,
+        D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+
+    TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
+
+    /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
+    wined3d_mutex_lock();
+    wined3d_device_get_transform(device->wined3d_device, state, (struct wined3d_matrix *)matrix);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_MultiplyTransform(IDirect3DDevice8 *iface,
+        D3DTRANSFORMSTATETYPE state, const D3DMATRIX *matrix)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+
+    TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
+
+    /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
+    wined3d_mutex_lock();
+    wined3d_device_multiply_transform(device->wined3d_device, state, (const struct wined3d_matrix *)matrix);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_SetViewport(IDirect3DDevice8 *iface, const D3DVIEWPORT8 *viewport)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+
+    TRACE("iface %p, viewport %p.\n", iface, viewport);
+
+    /* Note: D3DVIEWPORT8 is compatible with struct wined3d_viewport. */
+    wined3d_mutex_lock();
+    wined3d_device_set_viewport(device->wined3d_device, (const struct wined3d_viewport *)viewport);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_GetViewport(IDirect3DDevice8 *iface, D3DVIEWPORT8 *viewport)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+
+    TRACE("iface %p, viewport %p.\n", iface, viewport);
+
+    /* Note: D3DVIEWPORT8 is compatible with struct wined3d_viewport. */
+    wined3d_mutex_lock();
+    wined3d_device_get_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_SetMaterial(IDirect3DDevice8 *iface, const D3DMATERIAL8 *material)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+
+    TRACE("iface %p, material %p.\n", iface, material);
+
+    /* Note: D3DMATERIAL8 is compatible with struct wined3d_material. */
+    wined3d_mutex_lock();
+    wined3d_device_set_material(device->wined3d_device, (const struct wined3d_material *)material);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_GetMaterial(IDirect3DDevice8 *iface, D3DMATERIAL8 *material)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+
+    TRACE("iface %p, material %p.\n", iface, material);
+
+    /* Note: D3DMATERIAL8 is compatible with struct wined3d_material. */
+    wined3d_mutex_lock();
+    wined3d_device_get_material(device->wined3d_device, (struct wined3d_material *)material);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_SetLight(IDirect3DDevice8 *iface, DWORD index, const D3DLIGHT8 *light)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, index %u, light %p.\n", iface, index, light);
+
+    /* Note: D3DLIGHT8 is compatible with struct wined3d_light. */
+    wined3d_mutex_lock();
+    hr = wined3d_device_set_light(device->wined3d_device, index, (const struct wined3d_light *)light);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_GetLight(IDirect3DDevice8 *iface, DWORD index, D3DLIGHT8 *light)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, index %u, light %p.\n", iface, index, light);
+
+    /* Note: D3DLIGHT8 is compatible with struct wined3d_light. */
+    wined3d_mutex_lock();
+    hr = wined3d_device_get_light(device->wined3d_device, index, (struct wined3d_light *)light);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_LightEnable(IDirect3DDevice8 *iface, DWORD index, BOOL enable)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, index %u, enable %#x.\n", iface, index, enable);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_set_light_enable(device->wined3d_device, index, enable);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_GetLightEnable(IDirect3DDevice8 *iface, DWORD index, BOOL *enable)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, index %u, enable %p.\n", iface, index, enable);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_get_light_enable(device->wined3d_device, index, enable);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_SetClipPlane(IDirect3DDevice8 *iface, DWORD index, const float *plane)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, index %u, plane %p.\n", iface, index, plane);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_set_clip_plane(device->wined3d_device, index, (const struct wined3d_vec4 *)plane);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_GetClipPlane(IDirect3DDevice8 *iface, DWORD index, float *plane)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, index %u, plane %p.\n", iface, index, plane);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_get_clip_plane(device->wined3d_device, index, (struct wined3d_vec4 *)plane);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_SetRenderState(IDirect3DDevice8 *iface,
+        D3DRENDERSTATETYPE state, DWORD value)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+
+    TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
+
+    wined3d_mutex_lock();
+    switch (state)
+    {
+        case D3DRS_ZBIAS:
+            wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS, value);
+            break;
+
+        default:
+            wined3d_device_set_render_state(device->wined3d_device, state, value);
+    }
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_GetRenderState(IDirect3DDevice8 *iface,
+        D3DRENDERSTATETYPE state, DWORD *value)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+
+    TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
+
+    wined3d_mutex_lock();
+    switch (state)
+    {
+        case D3DRS_ZBIAS:
+            *value = wined3d_device_get_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS);
+            break;
+
+        default:
+            *value = wined3d_device_get_render_state(device->wined3d_device, state);
+    }
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_BeginStateBlock(IDirect3DDevice8 *iface)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_begin_stateblock(device->wined3d_device);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_EndStateBlock(IDirect3DDevice8 *iface, DWORD *token)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct wined3d_stateblock *stateblock;
+    HRESULT hr;
+
+    TRACE("iface %p, token %p.\n", iface, token);
+
+    /* Tell wineD3D to endstateblock before anything else (in case we run out
+     * of memory later and cause locking problems)
+     */
+    wined3d_mutex_lock();
+    hr = wined3d_device_end_stateblock(device->wined3d_device, &stateblock);
+    if (FAILED(hr))
+    {
+        WARN("IWineD3DDevice_EndStateBlock returned an error\n");
+        wined3d_mutex_unlock();
+        return hr;
+    }
+
+    *token = d3d8_allocate_handle(&device->handle_table, stateblock, D3D8_HANDLE_SB);
+    wined3d_mutex_unlock();
+
+    if (*token == D3D8_INVALID_HANDLE)
+    {
+        ERR("Failed to create a handle\n");
+        wined3d_mutex_lock();
+        wined3d_stateblock_decref(stateblock);
+        wined3d_mutex_unlock();
+        return E_FAIL;
+    }
+    ++*token;
+
+    TRACE("Returning %#x (%p).\n", *token, stateblock);
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_ApplyStateBlock(IDirect3DDevice8 *iface, DWORD token)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct wined3d_stateblock *stateblock;
+
+    TRACE("iface %p, token %#x.\n", iface, token);
+
+    if (!token)
+        return D3D_OK;
+
+    wined3d_mutex_lock();
+    stateblock = d3d8_get_object(&device->handle_table, token - 1, D3D8_HANDLE_SB);
+    if (!stateblock)
+    {
+        WARN("Invalid handle (%#x) passed.\n", token);
+        wined3d_mutex_unlock();
+        return D3DERR_INVALIDCALL;
+    }
+    wined3d_stateblock_apply(stateblock);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_CaptureStateBlock(IDirect3DDevice8 *iface, DWORD token)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct wined3d_stateblock *stateblock;
+
+    TRACE("iface %p, token %#x.\n", iface, token);
+
+    wined3d_mutex_lock();
+    stateblock = d3d8_get_object(&device->handle_table, token - 1, D3D8_HANDLE_SB);
+    if (!stateblock)
+    {
+        WARN("Invalid handle (%#x) passed.\n", token);
+        wined3d_mutex_unlock();
+        return D3DERR_INVALIDCALL;
+    }
+    wined3d_stateblock_capture(stateblock);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_DeleteStateBlock(IDirect3DDevice8 *iface, DWORD token)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct wined3d_stateblock *stateblock;
+
+    TRACE("iface %p, token %#x.\n", iface, token);
+
+    wined3d_mutex_lock();
+    stateblock = d3d8_free_handle(&device->handle_table, token - 1, D3D8_HANDLE_SB);
+
+    if (!stateblock)
+    {
+        WARN("Invalid handle (%#x) passed.\n", token);
+        wined3d_mutex_unlock();
+        return D3DERR_INVALIDCALL;
+    }
+
+    if (wined3d_stateblock_decref(stateblock))
+    {
+        ERR("Stateblock %p has references left, this shouldn't happen.\n", stateblock);
+    }
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_CreateStateBlock(IDirect3DDevice8 *iface,
+        D3DSTATEBLOCKTYPE type, DWORD *handle)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct wined3d_stateblock *stateblock;
+    HRESULT hr;
+
+    TRACE("iface %p, type %#x, handle %p.\n", iface, type, handle);
+
+    if (type != D3DSBT_ALL
+            && type != D3DSBT_PIXELSTATE
+            && type != D3DSBT_VERTEXSTATE)
+    {
+        WARN("Unexpected stateblock type, returning D3DERR_INVALIDCALL\n");
+        return D3DERR_INVALIDCALL;
+    }
+
+    wined3d_mutex_lock();
+    hr = wined3d_stateblock_create(device->wined3d_device, (enum wined3d_stateblock_type)type, &stateblock);
+    if (FAILED(hr))
+    {
+        wined3d_mutex_unlock();
+        ERR("IWineD3DDevice_CreateStateBlock failed, hr %#x\n", hr);
+        return hr;
+    }
+
+    *handle = d3d8_allocate_handle(&device->handle_table, stateblock, D3D8_HANDLE_SB);
+    wined3d_mutex_unlock();
+
+    if (*handle == D3D8_INVALID_HANDLE)
+    {
+        ERR("Failed to allocate a handle.\n");
+        wined3d_mutex_lock();
+        wined3d_stateblock_decref(stateblock);
+        wined3d_mutex_unlock();
+        return E_FAIL;
+    }
+    ++*handle;
+
+    TRACE("Returning %#x (%p).\n", *handle, stateblock);
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_SetClipStatus(IDirect3DDevice8 *iface, const D3DCLIPSTATUS8 *clip_status)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, clip_status %p.\n", iface, clip_status);
+    /* FIXME: Verify that D3DCLIPSTATUS8 ~= struct wined3d_clip_status. */
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_set_clip_status(device->wined3d_device, (const struct wined3d_clip_status *)clip_status);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_GetClipStatus(IDirect3DDevice8 *iface, D3DCLIPSTATUS8 *clip_status)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, clip_status %p.\n", iface, clip_status);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_get_clip_status(device->wined3d_device, (struct wined3d_clip_status *)clip_status);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_GetTexture(IDirect3DDevice8 *iface, DWORD stage, IDirect3DBaseTexture8 **texture)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct wined3d_texture *wined3d_texture;
+    struct d3d8_texture *texture_impl;
+
+    TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
+
+    if (!texture)
+        return D3DERR_INVALIDCALL;
+
+    wined3d_mutex_lock();
+    if ((wined3d_texture = wined3d_device_get_texture(device->wined3d_device, stage)))
+    {
+        texture_impl = wined3d_texture_get_parent(wined3d_texture);
+        *texture = &texture_impl->IDirect3DBaseTexture8_iface;
+        IDirect3DBaseTexture8_AddRef(*texture);
+    }
+    else
+    {
+        *texture = NULL;
+    }
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_SetTexture(IDirect3DDevice8 *iface, DWORD stage, IDirect3DBaseTexture8 *texture)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct d3d8_texture *texture_impl;
+    HRESULT hr;
+
+    TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
+
+    texture_impl = unsafe_impl_from_IDirect3DBaseTexture8(texture);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_set_texture(device->wined3d_device, stage,
+            texture_impl ? texture_impl->wined3d_texture : NULL);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static const struct tss_lookup
+{
+    BOOL sampler_state;
+    enum wined3d_texture_stage_state state;
+}
+tss_lookup[] =
+{
+    {FALSE, WINED3D_TSS_INVALID},                   /*  0, unused */
+    {FALSE, WINED3D_TSS_COLOR_OP},                  /*  1, D3DTSS_COLOROP */
+    {FALSE, WINED3D_TSS_COLOR_ARG1},                /*  2, D3DTSS_COLORARG1 */
+    {FALSE, WINED3D_TSS_COLOR_ARG2},                /*  3, D3DTSS_COLORARG2 */
+    {FALSE, WINED3D_TSS_ALPHA_OP},                  /*  4, D3DTSS_ALPHAOP */
+    {FALSE, WINED3D_TSS_ALPHA_ARG1},                /*  5, D3DTSS_ALPHAARG1 */
+    {FALSE, WINED3D_TSS_ALPHA_ARG2},                /*  6, D3DTSS_ALPHAARG2 */
+    {FALSE, WINED3D_TSS_BUMPENV_MAT00},             /*  7, D3DTSS_BUMPENVMAT00 */
+    {FALSE, WINED3D_TSS_BUMPENV_MAT01},             /*  8, D3DTSS_BUMPENVMAT01 */
+    {FALSE, WINED3D_TSS_BUMPENV_MAT10},             /*  9, D3DTSS_BUMPENVMAT10 */
+    {FALSE, WINED3D_TSS_BUMPENV_MAT11},             /* 10, D3DTSS_BUMPENVMAT11 */
+    {FALSE, WINED3D_TSS_TEXCOORD_INDEX},            /* 11, D3DTSS_TEXCOORDINDEX */
+    {FALSE, WINED3D_TSS_INVALID},                   /* 12, unused */
+    {TRUE,  WINED3D_SAMP_ADDRESS_U},                /* 13, D3DTSS_ADDRESSU */
+    {TRUE,  WINED3D_SAMP_ADDRESS_V},                /* 14, D3DTSS_ADDRESSV */
+    {TRUE,  WINED3D_SAMP_BORDER_COLOR},             /* 15, D3DTSS_BORDERCOLOR */
+    {TRUE,  WINED3D_SAMP_MAG_FILTER},               /* 16, D3DTSS_MAGFILTER */
+    {TRUE,  WINED3D_SAMP_MIN_FILTER},               /* 17, D3DTSS_MINFILTER */
+    {TRUE,  WINED3D_SAMP_MIP_FILTER},               /* 18, D3DTSS_MIPFILTER */
+    {TRUE,  WINED3D_SAMP_MIPMAP_LOD_BIAS},          /* 19, D3DTSS_MIPMAPLODBIAS */
+    {TRUE,  WINED3D_SAMP_MAX_MIP_LEVEL},            /* 20, D3DTSS_MAXMIPLEVEL */
+    {TRUE,  WINED3D_SAMP_MAX_ANISOTROPY},           /* 21, D3DTSS_MAXANISOTROPY */
+    {FALSE, WINED3D_TSS_BUMPENV_LSCALE},            /* 22, D3DTSS_BUMPENVLSCALE */
+    {FALSE, WINED3D_TSS_BUMPENV_LOFFSET},           /* 23, D3DTSS_BUMPENVLOFFSET */
+    {FALSE, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS},   /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
+    {TRUE,  WINED3D_SAMP_ADDRESS_W},                /* 25, D3DTSS_ADDRESSW */
+    {FALSE, WINED3D_TSS_COLOR_ARG0},                /* 26, D3DTSS_COLORARG0 */
+    {FALSE, WINED3D_TSS_ALPHA_ARG0},                /* 27, D3DTSS_ALPHAARG0 */
+    {FALSE, WINED3D_TSS_RESULT_ARG},                /* 28, D3DTSS_RESULTARG */
+};
+
+static HRESULT WINAPI d3d8_device_GetTextureStageState(IDirect3DDevice8 *iface,
+        DWORD stage, D3DTEXTURESTAGESTATETYPE Type, DWORD *value)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    const struct tss_lookup *l;
+
+    TRACE("iface %p, stage %u, state %#x, value %p.\n", iface, stage, Type, value);
+
+    if (Type >= sizeof(tss_lookup) / sizeof(*tss_lookup))
+    {
+        WARN("Invalid Type %#x passed.\n", Type);
+        return D3D_OK;
+    }
+
+    l = &tss_lookup[Type];
+
+    wined3d_mutex_lock();
+    if (l->sampler_state)
+        *value = wined3d_device_get_sampler_state(device->wined3d_device, stage, l->state);
+    else
+        *value = wined3d_device_get_texture_stage_state(device->wined3d_device, stage, l->state);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_SetTextureStageState(IDirect3DDevice8 *iface,
+        DWORD stage, D3DTEXTURESTAGESTATETYPE type, DWORD value)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    const struct tss_lookup *l;
+
+    TRACE("iface %p, stage %u, state %#x, value %#x.\n", iface, stage, type, value);
+
+    if (type >= sizeof(tss_lookup) / sizeof(*tss_lookup))
+    {
+        WARN("Invalid type %#x passed.\n", type);
+        return D3D_OK;
+    }
+
+    l = &tss_lookup[type];
+
+    wined3d_mutex_lock();
+    if (l->sampler_state)
+        wined3d_device_set_sampler_state(device->wined3d_device, stage, l->state, value);
+    else
+        wined3d_device_set_texture_stage_state(device->wined3d_device, stage, l->state, value);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_ValidateDevice(IDirect3DDevice8 *iface, DWORD *pass_count)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, pass_count %p.\n", iface, pass_count);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_validate_device(device->wined3d_device, pass_count);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_GetInfo(IDirect3DDevice8 *iface,
+        DWORD info_id, void *info, DWORD info_size)
+{
+    FIXME("iface %p, info_id %#x, info %p, info_size %u stub!\n", iface, info_id, info, info_size);
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_SetPaletteEntries(IDirect3DDevice8 *iface,
+        UINT palette_idx, const PALETTEENTRY *entries)
+{
+    WARN("iface %p, palette_idx %u, entries %p unimplemented\n", iface, palette_idx, entries);
+
+    /* GPUs stopped supporting palettized textures with the Shader Model 1 generation. Wined3d
+     * does not have a d3d8/9-style palette API */
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_GetPaletteEntries(IDirect3DDevice8 *iface,
+        UINT palette_idx, PALETTEENTRY *entries)
+{
+    FIXME("iface %p, palette_idx %u, entries %p unimplemented.\n", iface, palette_idx, entries);
+
+    return D3DERR_INVALIDCALL;
+}
+
+static HRESULT WINAPI d3d8_device_SetCurrentTexturePalette(IDirect3DDevice8 *iface, UINT palette_idx)
+{
+    WARN("iface %p, palette_idx %u unimplemented.\n", iface, palette_idx);
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_GetCurrentTexturePalette(IDirect3DDevice8 *iface, UINT *palette_idx)
+{
+    FIXME("iface %p, palette_idx %p unimplemented.\n", iface, palette_idx);
+
+    return D3DERR_INVALIDCALL;
+}
+
+static HRESULT WINAPI d3d8_device_DrawPrimitive(IDirect3DDevice8 *iface,
+        D3DPRIMITIVETYPE primitive_type, UINT start_vertex, UINT primitive_count)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, primitive_type %#x, start_vertex %u, primitive_count %u.\n",
+            iface, primitive_type, start_vertex, primitive_count);
+
+    wined3d_mutex_lock();
+    wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
+    hr = wined3d_device_draw_primitive(device->wined3d_device, start_vertex,
+            vertex_count_from_primitive_count(primitive_type, primitive_count));
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_DrawIndexedPrimitive(IDirect3DDevice8 *iface,
+        D3DPRIMITIVETYPE primitive_type, UINT min_vertex_idx, UINT vertex_count,
+        UINT start_idx, UINT primitive_count)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, primitive_type %#x, min_vertex_idx %u, vertex_count %u, start_idx %u, primitive_count %u.\n",
+            iface, primitive_type, min_vertex_idx, vertex_count, start_idx, primitive_count);
+
+    wined3d_mutex_lock();
+    wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
+    hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, start_idx,
+            vertex_count_from_primitive_count(primitive_type, primitive_count));
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static void STDMETHODCALLTYPE d3d8_null_wined3d_object_destroyed(void *parent) {}
+
+static const struct wined3d_parent_ops d3d8_null_wined3d_parent_ops =
+{
+    d3d8_null_wined3d_object_destroyed,
+};
+
+/* The caller is responsible for wined3d locking */
+static HRESULT d3d8_device_prepare_vertex_buffer(struct d3d8_device *device, UINT min_size)
+{
+    HRESULT hr;
+
+    if (device->vertex_buffer_size < min_size || !device->vertex_buffer)
+    {
+        UINT size = max(device->vertex_buffer_size * 2, min_size);
+        struct wined3d_buffer *buffer;
+
+        TRACE("Growing vertex buffer to %u bytes\n", size);
+
+        hr = wined3d_buffer_create_vb(device->wined3d_device, size, WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY,
+                WINED3D_POOL_DEFAULT, NULL, &d3d8_null_wined3d_parent_ops, &buffer);
+        if (FAILED(hr))
+        {
+            ERR("(%p) wined3d_buffer_create_vb failed with hr = %08x\n", device, hr);
+            return hr;
+        }
+
+        if (device->vertex_buffer)
+            wined3d_buffer_decref(device->vertex_buffer);
+
+        device->vertex_buffer = buffer;
+        device->vertex_buffer_size = size;
+        device->vertex_buffer_pos = 0;
+    }
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_DrawPrimitiveUP(IDirect3DDevice8 *iface,
+        D3DPRIMITIVETYPE primitive_type, UINT primitive_count, const void *data,
+        UINT stride)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    HRESULT hr;
+    UINT vtx_count = vertex_count_from_primitive_count(primitive_type, primitive_count);
+    UINT size = vtx_count * stride;
+    UINT vb_pos, align;
+    BYTE *buffer_data;
+
+    TRACE("iface %p, primitive_type %#x, primitive_count %u, data %p, stride %u.\n",
+            iface, primitive_type, primitive_count, data, stride);
+
+    if (!primitive_count)
+    {
+        WARN("primitive_count is 0, returning D3D_OK\n");
+        return D3D_OK;
+    }
+
+    wined3d_mutex_lock();
+    hr = d3d8_device_prepare_vertex_buffer(device, size);
+    if (FAILED(hr))
+        goto done;
+
+    vb_pos = device->vertex_buffer_pos;
+    align = vb_pos % stride;
+    if (align) align = stride - align;
+    if (vb_pos + size + align > device->vertex_buffer_size)
+        vb_pos = 0;
+    else
+        vb_pos += align;
+
+    hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, size, &buffer_data,
+            vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
+    if (FAILED(hr))
+        goto done;
+    memcpy(buffer_data, data, size);
+    wined3d_buffer_unmap(device->vertex_buffer);
+    device->vertex_buffer_pos = vb_pos + size;
+
+    hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
+    if (FAILED(hr))
+        goto done;
+
+    wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
+    hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / stride, vtx_count);
+    wined3d_device_set_stream_source(device->wined3d_device, 0, NULL, 0, 0);
+
+done:
+    wined3d_mutex_unlock();
+    return hr;
+}
+
+/* The caller is responsible for wined3d locking */
+static HRESULT d3d8_device_prepare_index_buffer(struct d3d8_device *device, UINT min_size)
+{
+    HRESULT hr;
+
+    if (device->index_buffer_size < min_size || !device->index_buffer)
+    {
+        UINT size = max(device->index_buffer_size * 2, min_size);
+        struct wined3d_buffer *buffer;
+
+        TRACE("Growing index buffer to %u bytes\n", size);
+
+        hr = wined3d_buffer_create_ib(device->wined3d_device, size, WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY,
+                WINED3D_POOL_DEFAULT, NULL, &d3d8_null_wined3d_parent_ops, &buffer);
+        if (FAILED(hr))
+        {
+            ERR("(%p) wined3d_buffer_create_ib failed with hr = %08x\n", device, hr);
+    return hr;
+        }
+
+        if (device->index_buffer)
+            wined3d_buffer_decref(device->index_buffer);
+
+        device->index_buffer = buffer;
+        device->index_buffer_size = size;
+        device->index_buffer_pos = 0;
+    }
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_DrawIndexedPrimitiveUP(IDirect3DDevice8 *iface,
+        D3DPRIMITIVETYPE primitive_type, UINT min_vertex_idx, UINT vertex_count,
+        UINT primitive_count, const void *index_data, D3DFORMAT index_format,
+        const void *vertex_data, UINT vertex_stride)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    HRESULT hr;
+    BYTE *buffer_data;
+
+    UINT idx_count = vertex_count_from_primitive_count(primitive_type, primitive_count);
+    UINT idx_fmt_size = index_format == D3DFMT_INDEX16 ? 2 : 4;
+    UINT idx_size = idx_count * idx_fmt_size;
+    UINT ib_pos;
+
+    UINT vtx_size = vertex_count * vertex_stride;
+    UINT vb_pos, align;
+
+    TRACE("iface %p, primitive_type %#x, min_vertex_idx %u, vertex_count %u, primitive_count %u,\n"
+            "index_data %p, index_format %#x, vertex_data %p, vertex_stride %u.\n",
+            iface, primitive_type, min_vertex_idx, vertex_count, primitive_count,
+            index_data, index_format, vertex_data, vertex_stride);
+
+    if (!primitive_count)
+    {
+        WARN("primitive_count is 0, returning D3D_OK\n");
+        return D3D_OK;
+    }
+
+    wined3d_mutex_lock();
+
+    hr = d3d8_device_prepare_vertex_buffer(device, vtx_size);
+    if (FAILED(hr))
+        goto done;
+
+    vb_pos = device->vertex_buffer_pos;
+    align = vb_pos % vertex_stride;
+    if (align) align = vertex_stride - align;
+    if (vb_pos + vtx_size + align > device->vertex_buffer_size)
+        vb_pos = 0;
+    else
+        vb_pos += align;
+
+    hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, vtx_size, &buffer_data,
+            vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
+    if (FAILED(hr))
+        goto done;
+    memcpy(buffer_data, vertex_data, vtx_size);
+    wined3d_buffer_unmap(device->vertex_buffer);
+    device->vertex_buffer_pos = vb_pos + vtx_size;
+
+    hr = d3d8_device_prepare_index_buffer(device, idx_size);
+    if (FAILED(hr))
+        goto done;
+
+    ib_pos = device->index_buffer_pos;
+    align = ib_pos % idx_fmt_size;
+    if (align) align = idx_fmt_size - align;
+    if (ib_pos + idx_size + align > device->index_buffer_size)
+        ib_pos = 0;
+    else
+        ib_pos += align;
+
+    hr = wined3d_buffer_map(device->index_buffer, ib_pos, idx_size, &buffer_data,
+            ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
+    if (FAILED(hr))
+        goto done;
+    memcpy(buffer_data, index_data, idx_size);
+    wined3d_buffer_unmap(device->index_buffer);
+    device->index_buffer_pos = ib_pos + idx_size;
+
+    hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, vertex_stride);
+    if (FAILED(hr))
+        goto done;
+
+    wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer,
+            wined3dformat_from_d3dformat(index_format));
+    wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / vertex_stride);
+
+    wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
+    hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / idx_fmt_size, idx_count);
+
+    wined3d_device_set_stream_source(device->wined3d_device, 0, NULL, 0, 0);
+    wined3d_device_set_index_buffer(device->wined3d_device, NULL, WINED3DFMT_UNKNOWN);
+    wined3d_device_set_base_vertex_index(device->wined3d_device, 0);
+
+done:
+    wined3d_mutex_unlock();
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_ProcessVertices(IDirect3DDevice8 *iface, UINT src_start_idx,
+        UINT dst_idx, UINT vertex_count, IDirect3DVertexBuffer8 *dst_buffer, DWORD flags)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct d3d8_vertexbuffer *dst = unsafe_impl_from_IDirect3DVertexBuffer8(dst_buffer);
+    HRESULT hr;
+
+    TRACE("iface %p, src_start_idx %u, dst_idx %u, vertex_count %u, dst_buffer %p, flags %#x.\n",
+            iface, src_start_idx, dst_idx, vertex_count, dst_buffer, flags);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_process_vertices(device->wined3d_device, src_start_idx, dst_idx,
+            vertex_count, dst->wined3d_buffer, NULL, flags, dst->fvf);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_CreateVertexShader(IDirect3DDevice8 *iface,
+        const DWORD *declaration, const DWORD *byte_code, DWORD *shader, DWORD usage)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct d3d8_vertex_shader *object;
+    DWORD shader_handle;
+    DWORD handle;
+    HRESULT hr;
+
+    TRACE("iface %p, declaration %p, byte_code %p, shader %p, usage %#x.\n",
+            iface, declaration, byte_code, shader, usage);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+    {
+        *shader = 0;
+        return E_OUTOFMEMORY;
+    }
+
+    wined3d_mutex_lock();
+    handle = d3d8_allocate_handle(&device->handle_table, object, D3D8_HANDLE_VS);
+    wined3d_mutex_unlock();
+    if (handle == D3D8_INVALID_HANDLE)
+    {
+        ERR("Failed to allocate vertex shader handle.\n");
+        HeapFree(GetProcessHeap(), 0, object);
+        *shader = 0;
+        return E_OUTOFMEMORY;
+    }
+
+    shader_handle = handle + VS_HIGHESTFIXEDFXF + 1;
+
+    hr = d3d8_vertex_shader_init(object, device, declaration, byte_code, shader_handle, usage);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize vertex shader, hr %#x.\n", hr);
+        wined3d_mutex_lock();
+        d3d8_free_handle(&device->handle_table, handle, D3D8_HANDLE_VS);
+        wined3d_mutex_unlock();
+        HeapFree(GetProcessHeap(), 0, object);
+        *shader = 0;
+        return hr;
+    }
+
+    TRACE("Created vertex shader %p (handle %#x).\n", object, shader_handle);
+    *shader = shader_handle;
+
+    return D3D_OK;
+}
+
+static struct d3d8_vertex_declaration *d3d8_device_get_fvf_declaration(struct d3d8_device *device, DWORD fvf)
+{
+    struct d3d8_vertex_declaration *d3d8_declaration;
+    struct FvfToDecl *convertedDecls = device->decls;
+    int p, low, high; /* deliberately signed */
+    HRESULT hr;
+
+    TRACE("Searching for declaration for fvf %08x... ", fvf);
+
+    low = 0;
+    high = device->numConvertedDecls - 1;
+    while (low <= high)
+    {
+        p = (low + high) >> 1;
+        TRACE("%d ", p);
+
+        if (convertedDecls[p].fvf == fvf)
+        {
+            TRACE("found %p\n", convertedDecls[p].declaration);
+            return convertedDecls[p].declaration;
+        }
+
+        if (convertedDecls[p].fvf < fvf)
+            low = p + 1;
+        else
+            high = p - 1;
+    }
+    TRACE("not found. Creating and inserting at position %d.\n", low);
+
+    if (!(d3d8_declaration = HeapAlloc(GetProcessHeap(), 0, sizeof(*d3d8_declaration))))
+        return NULL;
+
+    if (FAILED(hr = d3d8_vertex_declaration_init_fvf(d3d8_declaration, device, fvf)))
+    {
+        WARN("Failed to initialize vertex declaration, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, d3d8_declaration);
+        return NULL;
+    }
+
+    if (device->declArraySize == device->numConvertedDecls)
+    {
+        UINT grow = device->declArraySize / 2;
+
+        convertedDecls = HeapReAlloc(GetProcessHeap(), 0, convertedDecls,
+                sizeof(*convertedDecls) * (device->numConvertedDecls + grow));
+        if (!convertedDecls)
+        {
+            d3d8_vertex_declaration_destroy(d3d8_declaration);
+            return NULL;
+        }
+        device->decls = convertedDecls;
+        device->declArraySize += grow;
+    }
+
+    memmove(convertedDecls + low + 1, convertedDecls + low,
+            sizeof(*convertedDecls) * (device->numConvertedDecls - low));
+    convertedDecls[low].declaration = d3d8_declaration;
+    convertedDecls[low].fvf = fvf;
+    ++device->numConvertedDecls;
+
+    TRACE("Returning %p. %u decls in array.\n", d3d8_declaration, device->numConvertedDecls);
+
+    return d3d8_declaration;
+}
+
+static HRESULT WINAPI d3d8_device_SetVertexShader(IDirect3DDevice8 *iface, DWORD shader)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct d3d8_vertex_shader *shader_impl;
+
+    TRACE("iface %p, shader %#x.\n", iface, shader);
+
+    if (VS_HIGHESTFIXEDFXF >= shader)
+    {
+        TRACE("Setting FVF, %#x\n", shader);
+
+        wined3d_mutex_lock();
+        wined3d_device_set_vertex_declaration(device->wined3d_device,
+                d3d8_device_get_fvf_declaration(device, shader)->wined3d_vertex_declaration);
+        wined3d_device_set_vertex_shader(device->wined3d_device, NULL);
+        wined3d_mutex_unlock();
+
+        return D3D_OK;
+    }
+
+    TRACE("Setting shader\n");
+
+    wined3d_mutex_lock();
+    if (!(shader_impl = d3d8_get_object(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_VS)))
+    {
+        WARN("Invalid handle (%#x) passed.\n", shader);
+        wined3d_mutex_unlock();
+
+        return D3DERR_INVALIDCALL;
+    }
+
+    wined3d_device_set_vertex_declaration(device->wined3d_device,
+            shader_impl->vertex_declaration->wined3d_vertex_declaration);
+    wined3d_device_set_vertex_shader(device->wined3d_device, shader_impl->wined3d_shader);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_GetVertexShader(IDirect3DDevice8 *iface, DWORD *shader)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct wined3d_vertex_declaration *wined3d_declaration;
+    struct d3d8_vertex_declaration *d3d8_declaration;
+
+    TRACE("iface %p, shader %p.\n", iface, shader);
+
+    wined3d_mutex_lock();
+    if ((wined3d_declaration = wined3d_device_get_vertex_declaration(device->wined3d_device)))
+    {
+        d3d8_declaration = wined3d_vertex_declaration_get_parent(wined3d_declaration);
+        *shader = d3d8_declaration->shader_handle;
+    }
+    else
+    {
+        *shader = 0;
+    }
+    wined3d_mutex_unlock();
+
+    TRACE("Returning %#x.\n", *shader);
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_DeleteVertexShader(IDirect3DDevice8 *iface, DWORD shader)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct d3d8_vertex_shader *shader_impl;
+
+    TRACE("iface %p, shader %#x.\n", iface, shader);
+
+    wined3d_mutex_lock();
+    if (!(shader_impl = d3d8_free_handle(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_VS)))
+    {
+        WARN("Invalid handle (%#x) passed.\n", shader);
+        wined3d_mutex_unlock();
+
+        return D3DERR_INVALIDCALL;
+    }
+
+    if (shader_impl->wined3d_shader
+            && wined3d_device_get_vertex_shader(device->wined3d_device) == shader_impl->wined3d_shader)
+        IDirect3DDevice8_SetVertexShader(iface, 0);
+
+    wined3d_mutex_unlock();
+
+    d3d8_vertex_shader_destroy(shader_impl);
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_SetVertexShaderConstant(IDirect3DDevice8 *iface,
+        DWORD start_register, const void *data, DWORD count)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, start_register %u, data %p, count %u.\n",
+            iface, start_register, data, count);
+
+    if (start_register + count > D3D8_MAX_VERTEX_SHADER_CONSTANTF)
+    {
+        WARN("Trying to access %u constants, but d3d8 only supports %u\n",
+             start_register + count, D3D8_MAX_VERTEX_SHADER_CONSTANTF);
+        return D3DERR_INVALIDCALL;
+    }
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_set_vs_consts_f(device->wined3d_device, start_register, data, count);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_GetVertexShaderConstant(IDirect3DDevice8 *iface,
+        DWORD start_register, void *data, DWORD count)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, start_register %u, data %p, count %u.\n",
+            iface, start_register, data, count);
+
+    if (start_register + count > D3D8_MAX_VERTEX_SHADER_CONSTANTF)
+    {
+        WARN("Trying to access %u constants, but d3d8 only supports %u\n",
+             start_register + count, D3D8_MAX_VERTEX_SHADER_CONSTANTF);
+        return D3DERR_INVALIDCALL;
+    }
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_get_vs_consts_f(device->wined3d_device, start_register, data, count);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_GetVertexShaderDeclaration(IDirect3DDevice8 *iface,
+        DWORD shader, void *data, DWORD *data_size)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct d3d8_vertex_declaration *declaration;
+    struct d3d8_vertex_shader *shader_impl;
+
+    TRACE("iface %p, shader %#x, data %p, data_size %p.\n",
+            iface, shader, data, data_size);
+
+    wined3d_mutex_lock();
+    shader_impl = d3d8_get_object(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_VS);
+    wined3d_mutex_unlock();
+
+    if (!shader_impl)
+    {
+        WARN("Invalid handle (%#x) passed.\n", shader);
+        return D3DERR_INVALIDCALL;
+    }
+    declaration = shader_impl->vertex_declaration;
+
+    if (!data)
+    {
+        *data_size = declaration->elements_size;
+        return D3D_OK;
+    }
+
+    /* MSDN claims that if *data_size is smaller than the required size
+     * we should write the required size and return D3DERR_MOREDATA.
+     * That's not actually true. */
+    if (*data_size < declaration->elements_size)
+        return D3DERR_INVALIDCALL;
+
+    memcpy(data, declaration->elements, declaration->elements_size);
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_GetVertexShaderFunction(IDirect3DDevice8 *iface,
+        DWORD shader, void *data, DWORD *data_size)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct d3d8_vertex_shader *shader_impl = NULL;
+    HRESULT hr;
+
+    TRACE("iface %p, shader %#x, data %p, data_size %p.\n",
+            iface, shader, data, data_size);
+
+    wined3d_mutex_lock();
+    if (!(shader_impl = d3d8_get_object(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_VS)))
+    {
+        WARN("Invalid handle (%#x) passed.\n", shader);
+        wined3d_mutex_unlock();
+
+        return D3DERR_INVALIDCALL;
+    }
+
+    if (!shader_impl->wined3d_shader)
+    {
+        wined3d_mutex_unlock();
+        *data_size = 0;
+        return D3D_OK;
+    }
+
+    hr = wined3d_shader_get_byte_code(shader_impl->wined3d_shader, data, data_size);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_SetIndices(IDirect3DDevice8 *iface,
+        IDirect3DIndexBuffer8 *buffer, UINT base_vertex_idx)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct d3d8_indexbuffer *ib = unsafe_impl_from_IDirect3DIndexBuffer8(buffer);
+
+    TRACE("iface %p, buffer %p, base_vertex_idx %u.\n", iface, buffer, base_vertex_idx);
+
+    /* WineD3D takes an INT(due to d3d9), but d3d8 uses UINTs. Do I have to add a check here that
+     * the UINT doesn't cause an overflow in the INT? It seems rather unlikely because such large
+     * vertex buffers can't be created to address them with an index that requires the 32nd bit
+     * (4 Byte minimum vertex size * 2^31-1 -> 8 gb buffer. The index sign would be the least
+     * problem)
+     */
+    wined3d_mutex_lock();
+    wined3d_device_set_base_vertex_index(device->wined3d_device, base_vertex_idx);
+    wined3d_device_set_index_buffer(device->wined3d_device,
+            ib ? ib->wined3d_buffer : NULL,
+            ib ? ib->format : WINED3DFMT_UNKNOWN);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_GetIndices(IDirect3DDevice8 *iface,
+        IDirect3DIndexBuffer8 **buffer, UINT *base_vertex_index)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    enum wined3d_format_id wined3d_format;
+    struct wined3d_buffer *wined3d_buffer;
+    struct d3d8_indexbuffer *buffer_impl;
+
+    TRACE("iface %p, buffer %p, base_vertex_index %p.\n", iface, buffer, base_vertex_index);
+
+    if (!buffer)
+        return D3DERR_INVALIDCALL;
+
+    /* The case from UINT to INT is safe because d3d8 will never set negative values */
+    wined3d_mutex_lock();
+    *base_vertex_index = wined3d_device_get_base_vertex_index(device->wined3d_device);
+    if ((wined3d_buffer = wined3d_device_get_index_buffer(device->wined3d_device, &wined3d_format)))
+    {
+        buffer_impl = wined3d_buffer_get_parent(wined3d_buffer);
+        *buffer = &buffer_impl->IDirect3DIndexBuffer8_iface;
+        IDirect3DIndexBuffer8_AddRef(*buffer);
+    }
+    else
+    {
+        *buffer = NULL;
+    }
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_CreatePixelShader(IDirect3DDevice8 *iface,
+        const DWORD *byte_code, DWORD *shader)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct d3d8_pixel_shader *object;
+    DWORD shader_handle;
+    DWORD handle;
+    HRESULT hr;
+
+    TRACE("iface %p, byte_code %p, shader %p.\n", iface, byte_code, shader);
+
+    if (!shader)
+        return D3DERR_INVALIDCALL;
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return E_OUTOFMEMORY;
+
+    wined3d_mutex_lock();
+    handle = d3d8_allocate_handle(&device->handle_table, object, D3D8_HANDLE_PS);
+    wined3d_mutex_unlock();
+    if (handle == D3D8_INVALID_HANDLE)
+    {
+        ERR("Failed to allocate pixel shader handle.\n");
+        HeapFree(GetProcessHeap(), 0, object);
+        return E_OUTOFMEMORY;
+    }
+
+    shader_handle = handle + VS_HIGHESTFIXEDFXF + 1;
+
+    hr = d3d8_pixel_shader_init(object, device, byte_code, shader_handle);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize pixel shader, hr %#x.\n", hr);
+        wined3d_mutex_lock();
+        d3d8_free_handle(&device->handle_table, handle, D3D8_HANDLE_PS);
+        wined3d_mutex_unlock();
+        HeapFree(GetProcessHeap(), 0, object);
+        *shader = 0;
+        return hr;
+    }
+
+    TRACE("Created pixel shader %p (handle %#x).\n", object, shader_handle);
+    *shader = shader_handle;
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_SetPixelShader(IDirect3DDevice8 *iface, DWORD shader)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct d3d8_pixel_shader *shader_impl;
+
+    TRACE("iface %p, shader %#x.\n", iface, shader);
+
+    wined3d_mutex_lock();
+
+    if (!shader)
+    {
+        wined3d_device_set_pixel_shader(device->wined3d_device, NULL);
+        wined3d_mutex_unlock();
+        return D3D_OK;
+    }
+
+    if (!(shader_impl = d3d8_get_object(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_PS)))
+    {
+        WARN("Invalid handle (%#x) passed.\n", shader);
+        wined3d_mutex_unlock();
+        return D3DERR_INVALIDCALL;
+    }
+
+    TRACE("Setting shader %p.\n", shader_impl);
+    wined3d_device_set_pixel_shader(device->wined3d_device, shader_impl->wined3d_shader);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_GetPixelShader(IDirect3DDevice8 *iface, DWORD *shader)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct wined3d_shader *object;
+
+    TRACE("iface %p, shader %p.\n", iface, shader);
+
+    if (!shader)
+        return D3DERR_INVALIDCALL;
+
+    wined3d_mutex_lock();
+    if ((object = wined3d_device_get_pixel_shader(device->wined3d_device)))
+    {
+        struct d3d8_pixel_shader *d3d8_shader;
+        d3d8_shader = wined3d_shader_get_parent(object);
+        *shader = d3d8_shader->handle;
+    }
+    else
+    {
+        *shader = 0;
+    }
+    wined3d_mutex_unlock();
+
+    TRACE("Returning %#x.\n", *shader);
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_DeletePixelShader(IDirect3DDevice8 *iface, DWORD shader)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct d3d8_pixel_shader *shader_impl;
+
+    TRACE("iface %p, shader %#x.\n", iface, shader);
+
+    wined3d_mutex_lock();
+
+    if (!(shader_impl = d3d8_free_handle(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_PS)))
+    {
+        WARN("Invalid handle (%#x) passed.\n", shader);
+        wined3d_mutex_unlock();
+        return D3DERR_INVALIDCALL;
+    }
+
+    if (wined3d_device_get_pixel_shader(device->wined3d_device) == shader_impl->wined3d_shader)
+        IDirect3DDevice8_SetPixelShader(iface, 0);
+
+    wined3d_mutex_unlock();
+
+    d3d8_pixel_shader_destroy(shader_impl);
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_SetPixelShaderConstant(IDirect3DDevice8 *iface,
+        DWORD start_register, const void *data, DWORD count)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, start_register %u, data %p, count %u.\n",
+            iface, start_register, data, count);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_set_ps_consts_f(device->wined3d_device, start_register, data, count);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_GetPixelShaderConstant(IDirect3DDevice8 *iface,
+        DWORD start_register, void *data, DWORD count)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, start_register %u, data %p, count %u.\n",
+            iface, start_register, data, count);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_get_ps_consts_f(device->wined3d_device, start_register, data, count);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_GetPixelShaderFunction(IDirect3DDevice8 *iface,
+        DWORD shader, void *data, DWORD *data_size)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct d3d8_pixel_shader *shader_impl = NULL;
+    HRESULT hr;
+
+    TRACE("iface %p, shader %#x, data %p, data_size %p.\n",
+            iface, shader, data, data_size);
+
+    wined3d_mutex_lock();
+    if (!(shader_impl = d3d8_get_object(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_PS)))
+    {
+        WARN("Invalid handle (%#x) passed.\n", shader);
+        wined3d_mutex_unlock();
+
+        return D3DERR_INVALIDCALL;
+    }
+
+    hr = wined3d_shader_get_byte_code(shader_impl->wined3d_shader, data, data_size);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_DrawRectPatch(IDirect3DDevice8 *iface, UINT handle,
+        const float *segment_count, const D3DRECTPATCH_INFO *patch_info)
+{
+    FIXME("iface %p, handle %#x, segment_count %p, patch_info %p unimplemented.\n",
+            iface, handle, segment_count, patch_info);
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_DrawTriPatch(IDirect3DDevice8 *iface, UINT handle,
+        const float *segment_count, const D3DTRIPATCH_INFO *patch_info)
+{
+    FIXME("iface %p, handle %#x, segment_count %p, patch_info %p unimplemented.\n",
+            iface, handle, segment_count, patch_info);
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_device_DeletePatch(IDirect3DDevice8 *iface, UINT handle)
+{
+    FIXME("iface %p, handle %#x unimplemented.\n", iface, handle);
+    return D3DERR_INVALIDCALL;
+}
+
+static HRESULT WINAPI d3d8_device_SetStreamSource(IDirect3DDevice8 *iface,
+        UINT stream_idx, IDirect3DVertexBuffer8 *buffer, UINT stride)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct d3d8_vertexbuffer *buffer_impl = unsafe_impl_from_IDirect3DVertexBuffer8(buffer);
+    HRESULT hr;
+
+    TRACE("iface %p, stream_idx %u, buffer %p, stride %u.\n",
+            iface, stream_idx, buffer, stride);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_set_stream_source(device->wined3d_device, stream_idx,
+            buffer_impl ? buffer_impl->wined3d_buffer : NULL, 0, stride);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_device_GetStreamSource(IDirect3DDevice8 *iface,
+        UINT stream_idx, IDirect3DVertexBuffer8 **buffer, UINT *stride)
+{
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct d3d8_vertexbuffer *buffer_impl;
+    struct wined3d_buffer *wined3d_buffer = NULL;
+    HRESULT hr;
+
+    TRACE("iface %p, stream_idx %u, buffer %p, stride %p.\n",
+            iface, stream_idx, buffer, stride);
+
+    if (!buffer)
+        return D3DERR_INVALIDCALL;
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_get_stream_source(device->wined3d_device, stream_idx, &wined3d_buffer, 0, stride);
+    if (SUCCEEDED(hr) && wined3d_buffer)
+    {
+        buffer_impl = wined3d_buffer_get_parent(wined3d_buffer);
+        *buffer = &buffer_impl->IDirect3DVertexBuffer8_iface;
+        IDirect3DVertexBuffer8_AddRef(*buffer);
+        wined3d_buffer_decref(wined3d_buffer);
+    }
+    else
+    {
+        if (FAILED(hr))
+            ERR("Failed to get wined3d stream source, hr %#x.\n", hr);
+        *buffer = NULL;
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static const struct IDirect3DDevice8Vtbl d3d8_device_vtbl =
+{
+    d3d8_device_QueryInterface,
+    d3d8_device_AddRef,
+    d3d8_device_Release,
+    d3d8_device_TestCooperativeLevel,
+    d3d8_device_GetAvailableTextureMem,
+    d3d8_device_ResourceManagerDiscardBytes,
+    d3d8_device_GetDirect3D,
+    d3d8_device_GetDeviceCaps,
+    d3d8_device_GetDisplayMode,
+    d3d8_device_GetCreationParameters,
+    d3d8_device_SetCursorProperties,
+    d3d8_device_SetCursorPosition,
+    d3d8_device_ShowCursor,
+    d3d8_device_CreateAdditionalSwapChain,
+    d3d8_device_Reset,
+    d3d8_device_Present,
+    d3d8_device_GetBackBuffer,
+    d3d8_device_GetRasterStatus,
+    d3d8_device_SetGammaRamp,
+    d3d8_device_GetGammaRamp,
+    d3d8_device_CreateTexture,
+    d3d8_device_CreateVolumeTexture,
+    d3d8_device_CreateCubeTexture,
+    d3d8_device_CreateVertexBuffer,
+    d3d8_device_CreateIndexBuffer,
+    d3d8_device_CreateRenderTarget,
+    d3d8_device_CreateDepthStencilSurface,
+    d3d8_device_CreateImageSurface,
+    d3d8_device_CopyRects,
+    d3d8_device_UpdateTexture,
+    d3d8_device_GetFrontBuffer,
+    d3d8_device_SetRenderTarget,
+    d3d8_device_GetRenderTarget,
+    d3d8_device_GetDepthStencilSurface,
+    d3d8_device_BeginScene,
+    d3d8_device_EndScene,
+    d3d8_device_Clear,
+    d3d8_device_SetTransform,
+    d3d8_device_GetTransform,
+    d3d8_device_MultiplyTransform,
+    d3d8_device_SetViewport,
+    d3d8_device_GetViewport,
+    d3d8_device_SetMaterial,
+    d3d8_device_GetMaterial,
+    d3d8_device_SetLight,
+    d3d8_device_GetLight,
+    d3d8_device_LightEnable,
+    d3d8_device_GetLightEnable,
+    d3d8_device_SetClipPlane,
+    d3d8_device_GetClipPlane,
+    d3d8_device_SetRenderState,
+    d3d8_device_GetRenderState,
+    d3d8_device_BeginStateBlock,
+    d3d8_device_EndStateBlock,
+    d3d8_device_ApplyStateBlock,
+    d3d8_device_CaptureStateBlock,
+    d3d8_device_DeleteStateBlock,
+    d3d8_device_CreateStateBlock,
+    d3d8_device_SetClipStatus,
+    d3d8_device_GetClipStatus,
+    d3d8_device_GetTexture,
+    d3d8_device_SetTexture,
+    d3d8_device_GetTextureStageState,
+    d3d8_device_SetTextureStageState,
+    d3d8_device_ValidateDevice,
+    d3d8_device_GetInfo,
+    d3d8_device_SetPaletteEntries,
+    d3d8_device_GetPaletteEntries,
+    d3d8_device_SetCurrentTexturePalette,
+    d3d8_device_GetCurrentTexturePalette,
+    d3d8_device_DrawPrimitive,
+    d3d8_device_DrawIndexedPrimitive,
+    d3d8_device_DrawPrimitiveUP,
+    d3d8_device_DrawIndexedPrimitiveUP,
+    d3d8_device_ProcessVertices,
+    d3d8_device_CreateVertexShader,
+    d3d8_device_SetVertexShader,
+    d3d8_device_GetVertexShader,
+    d3d8_device_DeleteVertexShader,
+    d3d8_device_SetVertexShaderConstant,
+    d3d8_device_GetVertexShaderConstant,
+    d3d8_device_GetVertexShaderDeclaration,
+    d3d8_device_GetVertexShaderFunction,
+    d3d8_device_SetStreamSource,
+    d3d8_device_GetStreamSource,
+    d3d8_device_SetIndices,
+    d3d8_device_GetIndices,
+    d3d8_device_CreatePixelShader,
+    d3d8_device_SetPixelShader,
+    d3d8_device_GetPixelShader,
+    d3d8_device_DeletePixelShader,
+    d3d8_device_SetPixelShaderConstant,
+    d3d8_device_GetPixelShaderConstant,
+    d3d8_device_GetPixelShaderFunction,
+    d3d8_device_DrawRectPatch,
+    d3d8_device_DrawTriPatch,
+    d3d8_device_DeletePatch,
+};
+
+static inline struct d3d8_device *device_from_device_parent(struct wined3d_device_parent *device_parent)
+{
+    return CONTAINING_RECORD(device_parent, struct d3d8_device, device_parent);
+}
+
+static void CDECL device_parent_wined3d_device_created(struct wined3d_device_parent *device_parent,
+        struct wined3d_device *device)
+{
+    TRACE("device_parent %p, device %p\n", device_parent, device);
+}
+
+static void CDECL device_parent_mode_changed(struct wined3d_device_parent *device_parent)
+{
+    TRACE("device_parent %p.\n", device_parent);
+}
+
+static HRESULT CDECL device_parent_create_texture_surface(struct wined3d_device_parent *device_parent,
+        void *container_parent, const struct wined3d_resource_desc *desc, UINT sub_resource_idx,
+        DWORD flags, struct wined3d_surface **surface)
+{
+    struct d3d8_device *device = device_from_device_parent(device_parent);
+    struct d3d8_surface *d3d_surface;
+    HRESULT hr;
+
+    TRACE("device_parent %p, container_parent %p, desc %p, sub_resource_idx %u, flags %#x, surface %p.\n",
+            device_parent, container_parent, desc, sub_resource_idx, flags, surface);
+
+    if (FAILED(hr = d3d8_device_create_surface(device, desc->width, desc->height,
+            d3dformat_from_wined3dformat(desc->format), flags, (IDirect3DSurface8 **)&d3d_surface,
+            desc->usage, desc->pool, desc->multisample_type, desc->multisample_quality)))
+    {
+        WARN("Failed to create surface, hr %#x.\n", hr);
+        return hr;
+    }
+
+    *surface = d3d_surface->wined3d_surface;
+    wined3d_surface_incref(*surface);
+
+    d3d_surface->container = container_parent;
+    IDirect3DDevice8_Release(d3d_surface->parent_device);
+    d3d_surface->parent_device = NULL;
+
+    IDirect3DSurface8_Release(&d3d_surface->IDirect3DSurface8_iface);
+    d3d_surface->forwardReference = container_parent;
+
+    return hr;
+}
+
+static HRESULT CDECL device_parent_create_swapchain_surface(struct wined3d_device_parent *device_parent,
+        void *container_parent, const struct wined3d_resource_desc *desc, struct wined3d_surface **surface)
+{
+    struct d3d8_device *device = device_from_device_parent(device_parent);
+    struct wined3d_resource_desc texture_desc;
+    struct d3d8_surface *d3d_surface;
+    struct wined3d_texture *texture;
+    HRESULT hr;
+
+    TRACE("device_parent %p, container_parent %p, desc %p, surface %p.\n",
+            device_parent, container_parent, desc, surface);
+
+    texture_desc = *desc;
+    texture_desc.resource_type = WINED3D_RTYPE_TEXTURE;
+    if (FAILED(hr = wined3d_texture_create_2d(device->wined3d_device, &texture_desc, 1,
+            WINED3D_SURFACE_MAPPABLE, &device->IDirect3DDevice8_iface, &d3d8_null_wined3d_parent_ops, &texture)))
+    {
+        WARN("Failed to create texture, hr %#x.\n", hr);
+        return hr;
+    }
+
+    *surface = wined3d_surface_from_resource(wined3d_texture_get_sub_resource(texture, 0));
+    wined3d_surface_incref(*surface);
+    wined3d_texture_decref(texture);
+
+    d3d_surface = wined3d_surface_get_parent(*surface);
+    d3d_surface->forwardReference = NULL;
+    d3d_surface->parent_device = &device->IDirect3DDevice8_iface;
+
+    return hr;
+}
+
+static HRESULT CDECL device_parent_create_volume(struct wined3d_device_parent *device_parent,
+        void *container_parent, UINT width, UINT height, UINT depth, enum wined3d_format_id format,
+        enum wined3d_pool pool, DWORD usage, struct wined3d_volume **volume)
+{
+    struct d3d8_device *device = device_from_device_parent(device_parent);
+    struct d3d8_volume *object;
+    HRESULT hr;
+
+    TRACE("device_parent %p, container_parent %p, width %u, height %u, depth %u, "
+            "format %#x, pool %#x, usage %#x, volume %p.\n",
+            device_parent, container_parent, width, height, depth,
+            format, pool, usage, volume);
+
+    /* Allocate the storage for the device */
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+    {
+        FIXME("Allocation of memory failed\n");
+        *volume = NULL;
+        return D3DERR_OUTOFVIDEOMEMORY;
+    }
+
+    hr = volume_init(object, device, width, height, depth, usage, format, pool);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize volume, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    *volume = object->wined3d_volume;
+    wined3d_volume_incref(*volume);
+    IDirect3DVolume8_Release(&object->IDirect3DVolume8_iface);
+
+    object->container = container_parent;
+    object->forwardReference = container_parent;
+
+    TRACE("Created volume %p.\n", object);
+
+    return hr;
+}
+
+static HRESULT CDECL device_parent_create_swapchain(struct wined3d_device_parent *device_parent,
+        struct wined3d_swapchain_desc *desc, struct wined3d_swapchain **swapchain)
+{
+    struct d3d8_device *device = device_from_device_parent(device_parent);
+    struct d3d8_swapchain *d3d_swapchain;
+    HRESULT hr;
+
+    TRACE("device_parent %p, desc %p, swapchain %p.\n", device_parent, desc, swapchain);
+
+    if (FAILED(hr = d3d8_swapchain_create(device, desc, &d3d_swapchain)))
+    {
+        WARN("Failed to create swapchain, hr %#x.\n", hr);
+        *swapchain = NULL;
+        return hr;
+    }
+
+    *swapchain = d3d_swapchain->wined3d_swapchain;
+    wined3d_swapchain_incref(*swapchain);
+    IDirect3DSwapChain8_Release(&d3d_swapchain->IDirect3DSwapChain8_iface);
+
+    return hr;
+}
+
+static const struct wined3d_device_parent_ops d3d8_wined3d_device_parent_ops =
+{
+    device_parent_wined3d_device_created,
+    device_parent_mode_changed,
+    device_parent_create_swapchain_surface,
+    device_parent_create_texture_surface,
+    device_parent_create_volume,
+    device_parent_create_swapchain,
+};
+
+static void setup_fpu(void)
+{
+#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+    WORD cw;
+    __asm__ volatile ("fnstcw %0" : "=m" (cw));
+    cw = (cw & ~0xf3f) | 0x3f;
+    __asm__ volatile ("fldcw %0" : : "m" (cw));
+#elif defined(__i386__) && defined(_MSC_VER)
+    WORD cw;
+    __asm fnstcw cw;
+    cw = (cw & ~0xf3f) | 0x3f;
+    __asm fldcw cw;
+#elif defined(RT_ARCH_AMD64)
+    unsigned int currentControl = 0;
+    _controlfp_s(&currentControl, 0x3f, 0xf3f);
+#else
+    FIXME("FPU setup not implemented for this platform.\n");
+#endif
+}
+
+HRESULT device_init(struct d3d8_device *device, struct d3d8 *parent, struct wined3d *wined3d, UINT adapter,
+        D3DDEVTYPE device_type, HWND focus_window, DWORD flags, D3DPRESENT_PARAMETERS *parameters)
+{
+    struct wined3d_swapchain_desc swapchain_desc;
+    HRESULT hr;
+
+    device->IDirect3DDevice8_iface.lpVtbl = &d3d8_device_vtbl;
+    device->device_parent.ops = &d3d8_wined3d_device_parent_ops;
+    device->ref = 1;
+    device->handle_table.entries = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+            D3D8_INITIAL_HANDLE_TABLE_SIZE * sizeof(*device->handle_table.entries));
+    if (!device->handle_table.entries)
+    {
+        ERR("Failed to allocate handle table memory.\n");
+        return E_OUTOFMEMORY;
+    }
+    device->handle_table.table_size = D3D8_INITIAL_HANDLE_TABLE_SIZE;
+
+    if (!(flags & D3DCREATE_FPU_PRESERVE)) setup_fpu();
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_create(wined3d, adapter, device_type, focus_window, flags, 4,
+            &device->device_parent, &device->wined3d_device);
+    if (FAILED(hr))
+    {
+        WARN("Failed to create wined3d device, hr %#x.\n", hr);
+        wined3d_mutex_unlock();
+        HeapFree(GetProcessHeap(), 0, device->handle_table.entries);
+        return hr;
+    }
+
+    if (!parameters->Windowed)
+    {
+        HWND device_window = parameters->hDeviceWindow;
+
+        if (!focus_window)
+            focus_window = device_window;
+        if (FAILED(hr = wined3d_device_acquire_focus_window(device->wined3d_device, focus_window)))
+        {
+            ERR("Failed to acquire focus window, hr %#x.\n", hr);
+            wined3d_device_decref(device->wined3d_device);
+            wined3d_mutex_unlock();
+            HeapFree(GetProcessHeap(), 0, device->handle_table.entries);
+            return hr;
+        }
+
+        if (!device_window)
+            device_window = focus_window;
+        wined3d_device_setup_fullscreen_window(device->wined3d_device, device_window,
+                parameters->BackBufferWidth,
+                parameters->BackBufferHeight);
+    }
+
+    if (flags & D3DCREATE_MULTITHREADED)
+        wined3d_device_set_multithreaded(device->wined3d_device);
+
+    wined3d_swapchain_desc_from_present_parameters(&swapchain_desc, parameters);
+
+    hr = wined3d_device_init_3d(device->wined3d_device, &swapchain_desc);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize 3D, hr %#x.\n", hr);
+        wined3d_device_release_focus_window(device->wined3d_device);
+        wined3d_device_decref(device->wined3d_device);
+        wined3d_mutex_unlock();
+        HeapFree(GetProcessHeap(), 0, device->handle_table.entries);
+        return hr;
+    }
+
+    wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_POINTSIZE_MIN, 0);
+    wined3d_mutex_unlock();
+
+    present_parameters_from_wined3d_swapchain_desc(parameters, &swapchain_desc);
+
+    device->declArraySize = 16;
+    device->decls = HeapAlloc(GetProcessHeap(), 0, device->declArraySize * sizeof(*device->decls));
+    if (!device->decls)
+    {
+        ERR("Failed to allocate FVF vertex declaration map memory.\n");
+        hr = E_OUTOFMEMORY;
+        goto err;
+    }
+
+    device->d3d_parent = &parent->IDirect3D8_iface;
+    IDirect3D8_AddRef(device->d3d_parent);
+
+    return D3D_OK;
+
+err:
+    wined3d_mutex_lock();
+    wined3d_device_uninit_3d(device->wined3d_device);
+    wined3d_device_release_focus_window(device->wined3d_device);
+    wined3d_device_decref(device->wined3d_device);
+    wined3d_mutex_unlock();
+    HeapFree(GetProcessHeap(), 0, device->handle_table.entries);
+    return hr;
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/directx.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/directx.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/directx.c	(revision 46521)
@@ -0,0 +1,419 @@
+/*
+ * IDirect3D8 implementation
+ *
+ * Copyright 2002-2004 Jason Edmeades
+ * Copyright 2003-2004 Raphael Junqueira
+ * Copyright 2004 Christian Costa
+ *
+ * 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 <stdarg.h>
+
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "wine/debug.h"
+#include "wine/unicode.h"
+
+#include "d3d8_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d8);
+
+static inline struct d3d8 *impl_from_IDirect3D8(IDirect3D8 *iface)
+{
+    return CONTAINING_RECORD(iface, struct d3d8, IDirect3D8_iface);
+}
+
+static HRESULT WINAPI d3d8_QueryInterface(IDirect3D8 *iface, REFIID riid, void **out)
+{
+    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
+
+    if (IsEqualGUID(riid, &IID_IDirect3D8)
+            || IsEqualGUID(riid, &IID_IUnknown))
+    {
+        IDirect3D8_AddRef(iface);
+        *out = iface;
+        return S_OK;
+    }
+
+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+    *out = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI d3d8_AddRef(IDirect3D8 *iface)
+{
+    struct d3d8 *d3d8 = impl_from_IDirect3D8(iface);
+    ULONG refcount = InterlockedIncrement(&d3d8->refcount);
+
+    TRACE("%p increasing refcount to %u.\n", iface, refcount);
+
+    return refcount;
+}
+
+static ULONG WINAPI d3d8_Release(IDirect3D8 *iface)
+{
+    struct d3d8 *d3d8 = impl_from_IDirect3D8(iface);
+    ULONG refcount = InterlockedDecrement(&d3d8->refcount);
+
+    TRACE("%p decreasing refcount to %u.\n", iface, refcount);
+
+    if (!refcount)
+    {
+        wined3d_mutex_lock();
+        wined3d_decref(d3d8->wined3d);
+        wined3d_mutex_unlock();
+
+        HeapFree(GetProcessHeap(), 0, d3d8);
+    }
+
+    return refcount;
+}
+
+static HRESULT WINAPI d3d8_RegisterSoftwareDevice(IDirect3D8 *iface, void *init_function)
+{
+    struct d3d8 *d3d8 = impl_from_IDirect3D8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, init_function %p.\n", iface, init_function);
+
+    wined3d_mutex_lock();
+    hr = wined3d_register_software_device(d3d8->wined3d, init_function);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static UINT WINAPI d3d8_GetAdapterCount(IDirect3D8 *iface)
+{
+    struct d3d8 *d3d8 = impl_from_IDirect3D8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    hr = wined3d_get_adapter_count(d3d8->wined3d);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_GetAdapterIdentifier(IDirect3D8 *iface, UINT adapter,
+        DWORD flags, D3DADAPTER_IDENTIFIER8 *identifier)
+{
+    struct d3d8 *d3d8 = impl_from_IDirect3D8(iface);
+    struct wined3d_adapter_identifier adapter_id;
+    HRESULT hr;
+
+    TRACE("iface %p, adapter %u, flags %#x, identifier %p.\n",
+            iface, adapter, flags, identifier);
+
+    adapter_id.driver = identifier->Driver;
+    adapter_id.driver_size = sizeof(identifier->Driver);
+    adapter_id.description = identifier->Description;
+    adapter_id.description_size = sizeof(identifier->Description);
+    adapter_id.device_name = NULL; /* d3d9 only */
+    adapter_id.device_name_size = 0; /* d3d9 only */
+
+    wined3d_mutex_lock();
+    hr = wined3d_get_adapter_identifier(d3d8->wined3d, adapter, flags, &adapter_id);
+    wined3d_mutex_unlock();
+
+    identifier->DriverVersion = adapter_id.driver_version;
+    identifier->VendorId = adapter_id.vendor_id;
+    identifier->DeviceId = adapter_id.device_id;
+    identifier->SubSysId = adapter_id.subsystem_id;
+    identifier->Revision = adapter_id.revision;
+    memcpy(&identifier->DeviceIdentifier, &adapter_id.device_identifier, sizeof(identifier->DeviceIdentifier));
+    identifier->WHQLLevel = adapter_id.whql_level;
+
+    return hr;
+}
+
+static UINT WINAPI d3d8_GetAdapterModeCount(IDirect3D8 *iface, UINT adapter)
+{
+    struct d3d8 *d3d8 = impl_from_IDirect3D8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, adapter %u.\n", iface, adapter);
+
+    wined3d_mutex_lock();
+    hr = wined3d_get_adapter_mode_count(d3d8->wined3d, adapter,
+            WINED3DFMT_UNKNOWN, WINED3D_SCANLINE_ORDERING_UNKNOWN);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_EnumAdapterModes(IDirect3D8 *iface, UINT adapter, UINT mode_idx, D3DDISPLAYMODE *mode)
+{
+    struct d3d8 *d3d8 = impl_from_IDirect3D8(iface);
+    struct wined3d_display_mode wined3d_mode;
+    HRESULT hr;
+
+    TRACE("iface %p, adapter %u, mode_idx %u, mode %p.\n",
+            iface, adapter, mode_idx, mode);
+
+    wined3d_mutex_lock();
+    hr = wined3d_enum_adapter_modes(d3d8->wined3d, adapter, WINED3DFMT_UNKNOWN,
+            WINED3D_SCANLINE_ORDERING_UNKNOWN, mode_idx, &wined3d_mode);
+    wined3d_mutex_unlock();
+
+    if (SUCCEEDED(hr))
+    {
+        mode->Width = wined3d_mode.width;
+        mode->Height = wined3d_mode.height;
+        mode->RefreshRate = wined3d_mode.refresh_rate;
+        mode->Format = d3dformat_from_wined3dformat(wined3d_mode.format_id);
+    }
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_GetAdapterDisplayMode(IDirect3D8 *iface, UINT adapter, D3DDISPLAYMODE *mode)
+{
+    struct d3d8 *d3d8 = impl_from_IDirect3D8(iface);
+    struct wined3d_display_mode wined3d_mode;
+    HRESULT hr;
+
+    TRACE("iface %p, adapter %u, mode %p.\n",
+            iface, adapter, mode);
+
+    wined3d_mutex_lock();
+    hr = wined3d_get_adapter_display_mode(d3d8->wined3d, adapter, &wined3d_mode, NULL);
+    wined3d_mutex_unlock();
+
+    if (SUCCEEDED(hr))
+    {
+        mode->Width = wined3d_mode.width;
+        mode->Height = wined3d_mode.height;
+        mode->RefreshRate = wined3d_mode.refresh_rate;
+        mode->Format = d3dformat_from_wined3dformat(wined3d_mode.format_id);
+    }
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_CheckDeviceType(IDirect3D8 *iface, UINT adapter, D3DDEVTYPE device_type,
+        D3DFORMAT display_format, D3DFORMAT backbuffer_format, BOOL windowed)
+{
+    struct d3d8 *d3d8 = impl_from_IDirect3D8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, adapter %u, device_type %#x, display_format %#x, backbuffer_format %#x, windowed %#x.\n",
+            iface, adapter, device_type, display_format, backbuffer_format, windowed);
+
+    wined3d_mutex_lock();
+    hr = wined3d_check_device_type(d3d8->wined3d, adapter, device_type, wined3dformat_from_d3dformat(display_format),
+            wined3dformat_from_d3dformat(backbuffer_format), windowed);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_CheckDeviceFormat(IDirect3D8 *iface, UINT adapter, D3DDEVTYPE device_type,
+        D3DFORMAT adapter_format, DWORD usage, D3DRESOURCETYPE resource_type, D3DFORMAT format)
+{
+    struct d3d8 *d3d8 = impl_from_IDirect3D8(iface);
+    enum wined3d_resource_type wined3d_rtype;
+    HRESULT hr;
+
+    TRACE("iface %p, adapter %u, device_type %#x, adapter_format %#x, usage %#x, resource_type %#x, format %#x.\n",
+            iface, adapter, device_type, adapter_format, usage, resource_type, format);
+
+    switch (resource_type)
+    {
+        case D3DRTYPE_VERTEXBUFFER:
+        case D3DRTYPE_INDEXBUFFER:
+            wined3d_rtype = WINED3D_RTYPE_BUFFER;
+            break;
+
+        default:
+            wined3d_rtype = resource_type;
+            break;
+    }
+
+    wined3d_mutex_lock();
+    hr = wined3d_check_device_format(d3d8->wined3d, adapter, device_type, wined3dformat_from_d3dformat(adapter_format),
+            usage, wined3d_rtype, wined3dformat_from_d3dformat(format));
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_CheckDeviceMultiSampleType(IDirect3D8 *iface, UINT adapter, D3DDEVTYPE device_type,
+        D3DFORMAT format, BOOL windowed, D3DMULTISAMPLE_TYPE multisample_type)
+{
+    struct d3d8 *d3d8 = impl_from_IDirect3D8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, adapter %u, device_type %#x, format %#x, windowed %#x, multisample_type %#x.\n",
+            iface, adapter, device_type, format, windowed, multisample_type);
+
+    wined3d_mutex_lock();
+    hr = wined3d_check_device_multisample_type(d3d8->wined3d, adapter, device_type,
+            wined3dformat_from_d3dformat(format), windowed,
+            (enum wined3d_multisample_type)multisample_type, NULL);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_CheckDepthStencilMatch(IDirect3D8 *iface, UINT adapter, D3DDEVTYPE device_type,
+        D3DFORMAT adapter_format, D3DFORMAT rt_format, D3DFORMAT ds_format)
+{
+    struct d3d8 *d3d8 = impl_from_IDirect3D8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, adapter %u, device_type %#x, adapter_format %#x, rt_format %#x, ds_format %#x.\n",
+            iface, adapter, device_type, adapter_format, rt_format, ds_format);
+
+    wined3d_mutex_lock();
+    hr = wined3d_check_depth_stencil_match(d3d8->wined3d, adapter, device_type,
+            wined3dformat_from_d3dformat(adapter_format), wined3dformat_from_d3dformat(rt_format),
+            wined3dformat_from_d3dformat(ds_format));
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+void fixup_caps(WINED3DCAPS *caps)
+{
+    /* D3D8 doesn't support SM 2.0 or higher, so clamp to 1.x */
+    if (caps->PixelShaderVersion)
+        caps->PixelShaderVersion = D3DPS_VERSION(1,4);
+    else
+        caps->PixelShaderVersion = D3DPS_VERSION(0,0);
+    if (caps->VertexShaderVersion)
+        caps->VertexShaderVersion = D3DVS_VERSION(1,1);
+    else
+        caps->VertexShaderVersion = D3DVS_VERSION(0,0);
+    caps->MaxVertexShaderConst = min(D3D8_MAX_VERTEX_SHADER_CONSTANTF, caps->MaxVertexShaderConst);
+
+    caps->StencilCaps &= ~WINED3DSTENCILCAPS_TWOSIDED;
+}
+
+static HRESULT WINAPI d3d8_GetDeviceCaps(IDirect3D8 *iface, UINT adapter, D3DDEVTYPE device_type, D3DCAPS8 *caps)
+{
+    struct d3d8 *d3d8 = impl_from_IDirect3D8(iface);
+    WINED3DCAPS *wined3d_caps;
+    HRESULT hr;
+
+    TRACE("iface %p, adapter %u, device_type %#x, caps %p.\n", iface, adapter, device_type, caps);
+
+    if (!caps)
+        return D3DERR_INVALIDCALL;
+
+    if (!(wined3d_caps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*wined3d_caps))))
+        return D3DERR_INVALIDCALL;
+
+    wined3d_mutex_lock();
+    hr = wined3d_get_device_caps(d3d8->wined3d, adapter, device_type, wined3d_caps);
+    wined3d_mutex_unlock();
+
+    fixup_caps(wined3d_caps);
+    WINECAPSTOD3D8CAPS(caps, wined3d_caps)
+    HeapFree(GetProcessHeap(), 0, wined3d_caps);
+
+    return hr;
+}
+
+static HMONITOR WINAPI d3d8_GetAdapterMonitor(IDirect3D8 *iface, UINT adapter)
+{
+    struct d3d8 *d3d8 = impl_from_IDirect3D8(iface);
+    HMONITOR ret;
+
+    TRACE("iface %p, adapter %u.\n", iface, adapter);
+
+    wined3d_mutex_lock();
+    ret = wined3d_get_adapter_monitor(d3d8->wined3d, adapter);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static HRESULT WINAPI d3d8_CreateDevice(IDirect3D8 *iface, UINT adapter,
+        D3DDEVTYPE device_type, HWND focus_window, DWORD flags, D3DPRESENT_PARAMETERS *parameters,
+        IDirect3DDevice8 **device)
+{
+    struct d3d8 *d3d8 = impl_from_IDirect3D8(iface);
+    struct d3d8_device *object;
+    HRESULT hr;
+
+    TRACE("iface %p, adapter %u, device_type %#x, focus_window %p, flags %#x, parameters %p, device %p.\n",
+            iface, adapter, device_type, focus_window, flags, parameters, device);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return E_OUTOFMEMORY;
+
+    hr = device_init(object, d3d8, d3d8->wined3d, adapter, device_type, focus_window, flags, parameters);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize device, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created device %p.\n", object);
+    *device = &object->IDirect3DDevice8_iface;
+
+    return D3D_OK;
+}
+
+static const struct IDirect3D8Vtbl d3d8_vtbl =
+{
+    /* IUnknown */
+    d3d8_QueryInterface,
+    d3d8_AddRef,
+    d3d8_Release,
+    /* IDirect3D8 */
+    d3d8_RegisterSoftwareDevice,
+    d3d8_GetAdapterCount,
+    d3d8_GetAdapterIdentifier,
+    d3d8_GetAdapterModeCount,
+    d3d8_EnumAdapterModes,
+    d3d8_GetAdapterDisplayMode,
+    d3d8_CheckDeviceType,
+    d3d8_CheckDeviceFormat,
+    d3d8_CheckDeviceMultiSampleType,
+    d3d8_CheckDepthStencilMatch,
+    d3d8_GetDeviceCaps,
+    d3d8_GetAdapterMonitor,
+    d3d8_CreateDevice,
+};
+
+BOOL d3d8_init(struct d3d8 *d3d8)
+{
+    DWORD flags = WINED3D_LEGACY_DEPTH_BIAS | WINED3D_VIDMEM_ACCOUNTING;
+
+    d3d8->IDirect3D8_iface.lpVtbl = &d3d8_vtbl;
+    d3d8->refcount = 1;
+
+    wined3d_mutex_lock();
+    d3d8->wined3d = wined3d_create(8, flags);
+    wined3d_mutex_unlock();
+    if (!d3d8->wined3d)
+        return FALSE;
+
+    return TRUE;
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/shader.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/shader.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/shader.c	(revision 46521)
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2002-2003 Jason Edmeades
+ *                     Raphael Junqueira
+ *
+ * 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 "d3d8_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d8);
+
+static void STDMETHODCALLTYPE d3d8_vertexshader_wined3d_object_destroyed(void *parent)
+{
+    struct d3d8_vertex_shader *shader = parent;
+    d3d8_vertex_declaration_destroy(shader->vertex_declaration);
+    HeapFree(GetProcessHeap(), 0, shader);
+}
+
+void d3d8_vertex_shader_destroy(struct d3d8_vertex_shader *shader)
+{
+    TRACE("shader %p.\n", shader);
+
+    if (shader->wined3d_shader)
+    {
+        wined3d_mutex_lock();
+        wined3d_shader_decref(shader->wined3d_shader);
+        wined3d_mutex_unlock();
+    }
+    else
+    {
+        d3d8_vertexshader_wined3d_object_destroyed(shader);
+    }
+}
+
+static const struct wined3d_parent_ops d3d8_vertexshader_wined3d_parent_ops =
+{
+    d3d8_vertexshader_wined3d_object_destroyed,
+};
+
+static HRESULT d3d8_vertexshader_create_vertexdeclaration(struct d3d8_device *device,
+        const DWORD *declaration, DWORD shader_handle, struct d3d8_vertex_declaration **decl_ptr)
+{
+    struct d3d8_vertex_declaration *object;
+    HRESULT hr;
+
+    TRACE("device %p, declaration %p, shader_handle %#x, decl_ptr %p.\n",
+            device, declaration, shader_handle, decl_ptr);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return E_OUTOFMEMORY;
+
+    hr = d3d8_vertex_declaration_init(object, device, declaration, shader_handle);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize vertex declaration, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created vertex declaration %p.\n", object);
+    *decl_ptr = object;
+
+    return D3D_OK;
+}
+
+HRESULT d3d8_vertex_shader_init(struct d3d8_vertex_shader *shader, struct d3d8_device *device,
+        const DWORD *declaration, const DWORD *byte_code, DWORD shader_handle, DWORD usage)
+{
+    const DWORD *token = declaration;
+    HRESULT hr;
+
+    /* Test if the vertex declaration is valid. */
+    while (D3DVSD_END() != *token)
+    {
+        D3DVSD_TOKENTYPE token_type = ((*token & D3DVSD_TOKENTYPEMASK) >> D3DVSD_TOKENTYPESHIFT);
+
+        if (token_type == D3DVSD_TOKEN_STREAMDATA && !(token_type & 0x10000000))
+        {
+            DWORD type = ((*token & D3DVSD_DATATYPEMASK) >> D3DVSD_DATATYPESHIFT);
+            DWORD reg  = ((*token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT);
+
+            if (reg == D3DVSDE_NORMAL && type != D3DVSDT_FLOAT3 && !byte_code)
+            {
+                WARN("Attempt to use a non-FLOAT3 normal with the fixed function function\n");
+                return D3DERR_INVALIDCALL;
+            }
+        }
+        token += parse_token(token);
+    }
+
+    hr = d3d8_vertexshader_create_vertexdeclaration(device, declaration, shader_handle, &shader->vertex_declaration);
+    if (FAILED(hr))
+    {
+        WARN("Failed to create vertex declaration, hr %#x.\n", hr);
+        return hr;
+    }
+
+    if (byte_code)
+    {
+        if (usage) FIXME("Usage %#x not implemented.\n", usage);
+
+        wined3d_mutex_lock();
+        hr = wined3d_shader_create_vs(device->wined3d_device, byte_code, NULL /* output signature */,
+                shader, &d3d8_vertexshader_wined3d_parent_ops, &shader->wined3d_shader, 1);
+        wined3d_mutex_unlock();
+        if (FAILED(hr))
+        {
+            WARN("Failed to create wined3d vertex shader, hr %#x.\n", hr);
+            d3d8_vertex_declaration_destroy(shader->vertex_declaration);
+            return hr;
+        }
+
+        load_local_constants(declaration, shader->wined3d_shader);
+    }
+
+    return D3D_OK;
+}
+
+static void STDMETHODCALLTYPE d3d8_pixelshader_wined3d_object_destroyed(void *parent)
+{
+    HeapFree(GetProcessHeap(), 0, parent);
+}
+
+void d3d8_pixel_shader_destroy(struct d3d8_pixel_shader *shader)
+{
+    TRACE("shader %p.\n", shader);
+
+    wined3d_mutex_lock();
+    wined3d_shader_decref(shader->wined3d_shader);
+    wined3d_mutex_unlock();
+}
+
+static const struct wined3d_parent_ops d3d8_pixelshader_wined3d_parent_ops =
+{
+    d3d8_pixelshader_wined3d_object_destroyed,
+};
+
+HRESULT d3d8_pixel_shader_init(struct d3d8_pixel_shader *shader, struct d3d8_device *device,
+        const DWORD *byte_code, DWORD shader_handle)
+{
+    HRESULT hr;
+
+    shader->handle = shader_handle;
+
+    wined3d_mutex_lock();
+    hr = wined3d_shader_create_ps(device->wined3d_device, byte_code, NULL, shader,
+            &d3d8_pixelshader_wined3d_parent_ops, &shader->wined3d_shader, 1);
+    wined3d_mutex_unlock();
+    if (FAILED(hr))
+    {
+        WARN("Failed to create wined3d pixel shader, hr %#x.\n", hr);
+        return hr;
+    }
+
+    return D3D_OK;
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/surface.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/surface.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/surface.c	(revision 46521)
@@ -0,0 +1,368 @@
+/*
+ * IDirect3DSurface8 implementation
+ *
+ * Copyright 2005 Oliver Stieber
+ *
+ * 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 "d3d8_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d8);
+
+static inline struct d3d8_surface *impl_from_IDirect3DSurface8(IDirect3DSurface8 *iface)
+{
+    return CONTAINING_RECORD(iface, struct d3d8_surface, IDirect3DSurface8_iface);
+}
+
+static HRESULT WINAPI d3d8_surface_QueryInterface(IDirect3DSurface8 *iface, REFIID riid, void **out)
+{
+    TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), out);
+
+    if (IsEqualGUID(riid, &IID_IDirect3DSurface8)
+            || IsEqualGUID(riid, &IID_IDirect3DResource8)
+            || IsEqualGUID(riid, &IID_IUnknown))
+    {
+        IDirect3DSurface8_AddRef(iface);
+        *out = iface;
+        return S_OK;
+    }
+
+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+    *out = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI d3d8_surface_AddRef(IDirect3DSurface8 *iface)
+{
+    struct d3d8_surface *surface = impl_from_IDirect3DSurface8(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    if (surface->forwardReference)
+    {
+        /* Forward refcounting */
+        TRACE("Forwarding to %p.\n", surface->forwardReference);
+        return IUnknown_AddRef(surface->forwardReference);
+    }
+    else
+    {
+        /* No container, handle our own refcounting */
+        ULONG ref = InterlockedIncrement(&surface->refcount);
+
+        TRACE("%p increasing refcount to %u.\n", iface, ref);
+
+        if (ref == 1)
+        {
+            if (surface->parent_device)
+                IDirect3DDevice8_AddRef(surface->parent_device);
+            wined3d_mutex_lock();
+            wined3d_surface_incref(surface->wined3d_surface);
+            wined3d_mutex_unlock();
+        }
+
+        return ref;
+    }
+}
+
+static ULONG WINAPI d3d8_surface_Release(IDirect3DSurface8 *iface)
+{
+    struct d3d8_surface *surface = impl_from_IDirect3DSurface8(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    if (surface->forwardReference)
+    {
+        /* Forward refcounting */
+        TRACE("Forwarding to %p.\n", surface->forwardReference);
+        return IUnknown_Release(surface->forwardReference);
+    }
+    else
+    {
+        /* No container, handle our own refcounting */
+        ULONG ref = InterlockedDecrement(&surface->refcount);
+
+        TRACE("%p decreasing refcount to %u.\n", iface, ref);
+
+        if (!ref)
+        {
+            IDirect3DDevice8 *parent_device = surface->parent_device;
+
+            /* Implicit surfaces are destroyed with the device, not if refcount reaches 0. */
+            wined3d_mutex_lock();
+            wined3d_surface_decref(surface->wined3d_surface);
+            wined3d_mutex_unlock();
+
+            if (parent_device)
+                IDirect3DDevice8_Release(parent_device);
+        }
+
+        return ref;
+    }
+}
+
+static HRESULT WINAPI d3d8_surface_GetDevice(IDirect3DSurface8 *iface, IDirect3DDevice8 **device)
+{
+    struct d3d8_surface *surface = impl_from_IDirect3DSurface8(iface);
+
+    TRACE("iface %p, device %p.\n", iface, device);
+
+    if (surface->forwardReference)
+    {
+        IDirect3DResource8 *resource;
+        HRESULT hr;
+
+        hr = IUnknown_QueryInterface(surface->forwardReference, &IID_IDirect3DResource8, (void **)&resource);
+        if (SUCCEEDED(hr))
+        {
+            hr = IDirect3DResource8_GetDevice(resource, device);
+            IDirect3DResource8_Release(resource);
+
+            TRACE("Returning device %p.\n", *device);
+        }
+
+        return hr;
+    }
+
+    *device = surface->parent_device;
+    IDirect3DDevice8_AddRef(*device);
+
+    TRACE("Returning device %p.\n", *device);
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_surface_SetPrivateData(IDirect3DSurface8 *iface, REFGUID guid,
+        const void *data, DWORD data_size, DWORD flags)
+{
+    struct d3d8_surface *surface = impl_from_IDirect3DSurface8(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
+            iface, debugstr_guid(guid), data, data_size, flags);
+
+    wined3d_mutex_lock();
+    resource = wined3d_surface_get_resource(surface->wined3d_surface);
+    hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_surface_GetPrivateData(IDirect3DSurface8 *iface, REFGUID guid,
+        void *data, DWORD *data_size)
+{
+    struct d3d8_surface *surface = impl_from_IDirect3DSurface8(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s, data %p, data_size %p.\n",
+            iface, debugstr_guid(guid), data, data_size);
+
+    wined3d_mutex_lock();
+    resource = wined3d_surface_get_resource(surface->wined3d_surface);
+    hr = wined3d_resource_get_private_data(resource, guid, data, data_size);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_surface_FreePrivateData(IDirect3DSurface8 *iface, REFGUID guid)
+{
+    struct d3d8_surface *surface = impl_from_IDirect3DSurface8(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
+
+    wined3d_mutex_lock();
+    resource = wined3d_surface_get_resource(surface->wined3d_surface);
+    hr = wined3d_resource_free_private_data(resource, guid);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_surface_GetContainer(IDirect3DSurface8 *iface, REFIID riid, void **container)
+{
+    struct d3d8_surface *surface = impl_from_IDirect3DSurface8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, riid %s, container %p.\n", iface, debugstr_guid(riid), container);
+
+    if (!surface->container)
+        return E_NOINTERFACE;
+
+    hr = IUnknown_QueryInterface(surface->container, riid, container);
+
+    TRACE("Returning %p.\n", *container);
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_surface_GetDesc(IDirect3DSurface8 *iface, D3DSURFACE_DESC *desc)
+{
+    struct d3d8_surface *surface = impl_from_IDirect3DSurface8(iface);
+    struct wined3d_resource_desc wined3d_desc;
+    struct wined3d_resource *wined3d_resource;
+
+    TRACE("iface %p, desc %p.\n", iface, desc);
+
+    wined3d_mutex_lock();
+    wined3d_resource = wined3d_surface_get_resource(surface->wined3d_surface);
+    wined3d_resource_get_desc(wined3d_resource, &wined3d_desc);
+    wined3d_mutex_unlock();
+
+    desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format);
+    desc->Type = wined3d_desc.resource_type;
+    desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
+    desc->Pool = wined3d_desc.pool;
+    desc->Size = wined3d_desc.size;
+    desc->MultiSampleType = wined3d_desc.multisample_type;
+    desc->Width = wined3d_desc.width;
+    desc->Height = wined3d_desc.height;
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_surface_LockRect(IDirect3DSurface8 *iface,
+        D3DLOCKED_RECT *locked_rect, const RECT *rect, DWORD flags)
+{
+    struct d3d8_surface *surface = impl_from_IDirect3DSurface8(iface);
+    struct wined3d_map_desc map_desc;
+    HRESULT hr;
+
+    TRACE("iface %p, locked_rect %p, rect %s, flags %#x.\n",
+            iface, locked_rect, wine_dbgstr_rect(rect), flags);
+
+    wined3d_mutex_lock();
+    if (rect)
+    {
+        D3DSURFACE_DESC desc;
+        IDirect3DSurface8_GetDesc(iface, &desc);
+
+        if ((rect->left < 0)
+                || (rect->top < 0)
+                || (rect->left >= rect->right)
+                || (rect->top >= rect->bottom)
+                || (rect->right > desc.Width)
+                || (rect->bottom > desc.Height))
+        {
+            WARN("Trying to lock an invalid rectangle, returning D3DERR_INVALIDCALL\n");
+            wined3d_mutex_unlock();
+
+            return D3DERR_INVALIDCALL;
+        }
+    }
+
+    hr = wined3d_surface_map(surface->wined3d_surface, &map_desc, rect, flags);
+    wined3d_mutex_unlock();
+
+    locked_rect->Pitch = map_desc.row_pitch;
+    locked_rect->pBits = map_desc.data;
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_surface_UnlockRect(IDirect3DSurface8 *iface)
+{
+    struct d3d8_surface *surface = impl_from_IDirect3DSurface8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    hr = wined3d_surface_unmap(surface->wined3d_surface);
+    wined3d_mutex_unlock();
+
+    switch(hr)
+    {
+        case WINEDDERR_NOTLOCKED:       return D3DERR_INVALIDCALL;
+        default:                        return hr;
+    }
+}
+
+static const IDirect3DSurface8Vtbl d3d8_surface_vtbl =
+{
+    /* IUnknown */
+    d3d8_surface_QueryInterface,
+    d3d8_surface_AddRef,
+    d3d8_surface_Release,
+    /* IDirect3DResource8 */
+    d3d8_surface_GetDevice,
+    d3d8_surface_SetPrivateData,
+    d3d8_surface_GetPrivateData,
+    d3d8_surface_FreePrivateData,
+    /* IDirect3DSurface8 */
+    d3d8_surface_GetContainer,
+    d3d8_surface_GetDesc,
+    d3d8_surface_LockRect,
+    d3d8_surface_UnlockRect,
+};
+
+static void STDMETHODCALLTYPE surface_wined3d_object_destroyed(void *parent)
+{
+    HeapFree(GetProcessHeap(), 0, parent);
+}
+
+static const struct wined3d_parent_ops d3d8_surface_wined3d_parent_ops =
+{
+    surface_wined3d_object_destroyed,
+};
+
+HRESULT surface_init(struct d3d8_surface *surface, struct d3d8_device *device, UINT width, UINT height,
+        D3DFORMAT format, DWORD flags, DWORD usage, D3DPOOL pool, D3DMULTISAMPLE_TYPE multisample_type,
+        DWORD multisample_quality)
+{
+    HRESULT hr;
+
+    surface->IDirect3DSurface8_iface.lpVtbl = &d3d8_surface_vtbl;
+    surface->refcount = 1;
+
+    /* FIXME: Check MAX bounds of MultisampleQuality. */
+    if (multisample_quality > 0)
+    {
+        FIXME("Multisample quality set to %u, substituting 0.\n", multisample_quality);
+        multisample_quality = 0;
+    }
+
+    wined3d_mutex_lock();
+    hr = wined3d_surface_create(device->wined3d_device, width, height, wined3dformat_from_d3dformat(format),
+            usage & WINED3DUSAGE_MASK, (enum wined3d_pool)pool, multisample_type, multisample_quality,
+            flags, surface, &d3d8_surface_wined3d_parent_ops, &surface->wined3d_surface);
+    wined3d_mutex_unlock();
+    if (FAILED(hr))
+    {
+        WARN("Failed to create wined3d surface, hr %#x.\n", hr);
+        return hr;
+    }
+
+    surface->parent_device = &device->IDirect3DDevice8_iface;
+    IDirect3DDevice8_AddRef(surface->parent_device);
+
+    return D3D_OK;
+}
+
+struct d3d8_surface *unsafe_impl_from_IDirect3DSurface8(IDirect3DSurface8 *iface)
+{
+    if (!iface)
+        return NULL;
+    assert(iface->lpVtbl == &d3d8_surface_vtbl);
+
+    return impl_from_IDirect3DSurface8(iface);
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/swapchain.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/swapchain.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/swapchain.c	(revision 46521)
@@ -0,0 +1,199 @@
+/*
+ * IDirect3DSwapChain8 implementation
+ *
+ * Copyright 2005 Oliver Stieber
+ *
+ * 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 "d3d8_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d8);
+
+static inline struct d3d8_swapchain *impl_from_IDirect3DSwapChain8(IDirect3DSwapChain8 *iface)
+{
+    return CONTAINING_RECORD(iface, struct d3d8_swapchain, IDirect3DSwapChain8_iface);
+}
+
+static HRESULT WINAPI d3d8_swapchain_QueryInterface(IDirect3DSwapChain8 *iface, REFIID riid, void **out)
+{
+    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
+
+    if (IsEqualGUID(riid, &IID_IDirect3DSwapChain8)
+            || IsEqualGUID(riid, &IID_IUnknown))
+    {
+        IDirect3DSwapChain8_AddRef(iface);
+        *out = iface;
+        return S_OK;
+    }
+
+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+    *out = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI d3d8_swapchain_AddRef(IDirect3DSwapChain8 *iface)
+{
+    struct d3d8_swapchain *swapchain = impl_from_IDirect3DSwapChain8(iface);
+    ULONG ref = InterlockedIncrement(&swapchain->refcount);
+
+    TRACE("%p increasing refcount to %u.\n", iface, ref);
+
+    if (ref == 1)
+    {
+        if (swapchain->parent_device)
+            IDirect3DDevice8_AddRef(swapchain->parent_device);
+        wined3d_mutex_lock();
+        wined3d_swapchain_incref(swapchain->wined3d_swapchain);
+        wined3d_mutex_unlock();
+    }
+
+    return ref;
+}
+
+static ULONG WINAPI d3d8_swapchain_Release(IDirect3DSwapChain8 *iface)
+{
+    struct d3d8_swapchain *swapchain = impl_from_IDirect3DSwapChain8(iface);
+    ULONG ref = InterlockedDecrement(&swapchain->refcount);
+
+    TRACE("%p decreasing refcount to %u.\n", iface, ref);
+
+    if (!ref)
+    {
+        IDirect3DDevice8 *parent_device = swapchain->parent_device;
+
+        wined3d_mutex_lock();
+        wined3d_swapchain_decref(swapchain->wined3d_swapchain);
+        wined3d_mutex_unlock();
+
+        if (parent_device)
+            IDirect3DDevice8_Release(parent_device);
+    }
+    return ref;
+}
+
+static HRESULT WINAPI d3d8_swapchain_Present(IDirect3DSwapChain8 *iface,
+        const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override,
+        const RGNDATA *dirty_region)
+{
+    struct d3d8_swapchain *swapchain = impl_from_IDirect3DSwapChain8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, src_rect %s, dst_rect %s, dst_window_override %p, dirty_region %p.\n",
+            iface, wine_dbgstr_rect(src_rect), wine_dbgstr_rect(dst_rect), dst_window_override, dirty_region);
+
+    wined3d_mutex_lock();
+    hr = wined3d_swapchain_present(swapchain->wined3d_swapchain, src_rect,
+            dst_rect, dst_window_override, dirty_region, 0);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_swapchain_GetBackBuffer(IDirect3DSwapChain8 *iface,
+        UINT backbuffer_idx, D3DBACKBUFFER_TYPE backbuffer_type, IDirect3DSurface8 **backbuffer)
+{
+    struct d3d8_swapchain *swapchain = impl_from_IDirect3DSwapChain8(iface);
+    struct wined3d_surface *wined3d_surface = NULL;
+    struct d3d8_surface *surface_impl;
+    HRESULT hr = D3D_OK;
+
+    TRACE("iface %p, backbuffer_idx %u, backbuffer_type %#x, backbuffer %p.\n",
+            iface, backbuffer_idx, backbuffer_type, backbuffer);
+
+    wined3d_mutex_lock();
+    if ((wined3d_surface = wined3d_swapchain_get_back_buffer(swapchain->wined3d_swapchain,
+            backbuffer_idx, (enum wined3d_backbuffer_type)backbuffer_type)))
+    {
+        surface_impl = wined3d_surface_get_parent(wined3d_surface);
+        *backbuffer = &surface_impl->IDirect3DSurface8_iface;
+        IDirect3DSurface8_AddRef(*backbuffer);
+    }
+    else
+    {
+        hr = D3DERR_INVALIDCALL;
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static const IDirect3DSwapChain8Vtbl d3d8_swapchain_vtbl =
+{
+    d3d8_swapchain_QueryInterface,
+    d3d8_swapchain_AddRef,
+    d3d8_swapchain_Release,
+    d3d8_swapchain_Present,
+    d3d8_swapchain_GetBackBuffer
+};
+
+static void STDMETHODCALLTYPE d3d8_swapchain_wined3d_object_released(void *parent)
+{
+    HeapFree(GetProcessHeap(), 0, parent);
+}
+
+static const struct wined3d_parent_ops d3d8_swapchain_wined3d_parent_ops =
+{
+    d3d8_swapchain_wined3d_object_released,
+};
+
+static HRESULT swapchain_init(struct d3d8_swapchain *swapchain, struct d3d8_device *device,
+        struct wined3d_swapchain_desc *desc)
+{
+    HRESULT hr;
+
+    swapchain->refcount = 1;
+    swapchain->IDirect3DSwapChain8_iface.lpVtbl = &d3d8_swapchain_vtbl;
+
+    wined3d_mutex_lock();
+    hr = wined3d_swapchain_create(device->wined3d_device, desc, swapchain,
+            &d3d8_swapchain_wined3d_parent_ops, &swapchain->wined3d_swapchain);
+    wined3d_mutex_unlock();
+
+    if (FAILED(hr))
+    {
+        WARN("Failed to create wined3d swapchain, hr %#x.\n", hr);
+        return hr;
+    }
+
+    swapchain->parent_device = &device->IDirect3DDevice8_iface;
+    IDirect3DDevice8_AddRef(swapchain->parent_device);
+
+    return D3D_OK;
+}
+
+HRESULT d3d8_swapchain_create(struct d3d8_device *device, struct wined3d_swapchain_desc *desc,
+        struct d3d8_swapchain **swapchain)
+{
+    struct d3d8_swapchain *object;
+    HRESULT hr;
+
+    if (!(object = HeapAlloc(GetProcessHeap(),  HEAP_ZERO_MEMORY, sizeof(*object))))
+        return E_OUTOFMEMORY;
+
+    if (FAILED(hr = swapchain_init(object, device, desc)))
+    {
+        WARN("Failed to initialize swapchain, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created swapchain %p.\n", object);
+    *swapchain = object;
+
+    return D3D_OK;
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/texture.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/texture.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/texture.c	(revision 46521)
@@ -0,0 +1,1299 @@
+/*
+ * Copyright 2005 Oliver Stieber
+ *
+ * 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 "d3d8_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d8);
+
+static inline struct d3d8_texture *impl_from_IDirect3DTexture8(IDirect3DTexture8 *iface)
+{
+    return CONTAINING_RECORD(iface, struct d3d8_texture, IDirect3DBaseTexture8_iface);
+}
+
+static inline struct d3d8_texture *impl_from_IDirect3DCubeTexture8(IDirect3DCubeTexture8 *iface)
+{
+    return CONTAINING_RECORD(iface, struct d3d8_texture, IDirect3DBaseTexture8_iface);
+}
+
+static inline struct d3d8_texture *impl_from_IDirect3DVolumeTexture8(IDirect3DVolumeTexture8 *iface)
+{
+    return CONTAINING_RECORD(iface, struct d3d8_texture, IDirect3DBaseTexture8_iface);
+}
+
+static HRESULT WINAPI d3d8_texture_2d_QueryInterface(IDirect3DTexture8 *iface, REFIID riid, void **out)
+{
+    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
+
+    if (IsEqualGUID(riid, &IID_IDirect3DTexture8)
+            || IsEqualGUID(riid, &IID_IDirect3DBaseTexture8)
+            || IsEqualGUID(riid, &IID_IDirect3DResource8)
+            || IsEqualGUID(riid, &IID_IUnknown))
+    {
+        IDirect3DTexture8_AddRef(iface);
+        *out = iface;
+        return S_OK;
+    }
+
+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+    *out = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI d3d8_texture_2d_AddRef(IDirect3DTexture8 *iface)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
+    ULONG ref = InterlockedIncrement(&texture->refcount);
+
+    TRACE("%p increasing refcount to %u.\n", iface, ref);
+
+    if (ref == 1)
+    {
+        IDirect3DDevice8_AddRef(texture->parent_device);
+        wined3d_mutex_lock();
+        wined3d_texture_incref(texture->wined3d_texture);
+        wined3d_mutex_unlock();
+    }
+
+    return ref;
+}
+
+static ULONG WINAPI d3d8_texture_2d_Release(IDirect3DTexture8 *iface)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
+    ULONG ref = InterlockedDecrement(&texture->refcount);
+
+    TRACE("%p decreasing refcount to %u.\n", iface, ref);
+
+    if (!ref)
+    {
+        IDirect3DDevice8 *parent_device = texture->parent_device;
+
+        wined3d_mutex_lock();
+        wined3d_texture_decref(texture->wined3d_texture);
+        wined3d_mutex_unlock();
+
+        /* Release the device last, as it may cause the device to be destroyed. */
+        IDirect3DDevice8_Release(parent_device);
+    }
+    return ref;
+}
+
+static HRESULT WINAPI d3d8_texture_2d_GetDevice(IDirect3DTexture8 *iface, IDirect3DDevice8 **device)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
+
+    TRACE("iface %p, device %p.\n", iface, device);
+
+    *device = texture->parent_device;
+    IDirect3DDevice8_AddRef(*device);
+
+    TRACE("Returning device %p.\n", *device);
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_texture_2d_SetPrivateData(IDirect3DTexture8 *iface,
+        REFGUID guid, const void *data, DWORD data_size, DWORD flags)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
+            iface, debugstr_guid(guid), data, data_size, flags);
+
+    wined3d_mutex_lock();
+    resource = wined3d_texture_get_resource(texture->wined3d_texture);
+    hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_texture_2d_GetPrivateData(IDirect3DTexture8 *iface,
+        REFGUID guid, void *data, DWORD *data_size)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s, data %p, data_size %p.\n",
+            iface, debugstr_guid(guid), data, data_size);
+
+    wined3d_mutex_lock();
+    resource = wined3d_texture_get_resource(texture->wined3d_texture);
+    hr = wined3d_resource_get_private_data(resource, guid, data, data_size);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_texture_2d_FreePrivateData(IDirect3DTexture8 *iface, REFGUID guid)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
+
+    wined3d_mutex_lock();
+    resource = wined3d_texture_get_resource(texture->wined3d_texture);
+    hr = wined3d_resource_free_private_data(resource, guid);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static DWORD WINAPI d3d8_texture_2d_SetPriority(IDirect3DTexture8 *iface, DWORD priority)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
+    DWORD ret;
+
+    TRACE("iface %p, priority %u.\n", iface, priority);
+
+    wined3d_mutex_lock();
+    ret = wined3d_texture_set_priority(texture->wined3d_texture, priority);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static DWORD WINAPI d3d8_texture_2d_GetPriority(IDirect3DTexture8 *iface)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
+    DWORD ret;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    ret = wined3d_texture_get_priority(texture->wined3d_texture);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static void WINAPI d3d8_texture_2d_PreLoad(IDirect3DTexture8 *iface)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    wined3d_texture_preload(texture->wined3d_texture);
+    wined3d_mutex_unlock();
+}
+
+static D3DRESOURCETYPE WINAPI d3d8_texture_2d_GetType(IDirect3DTexture8 *iface)
+{
+    TRACE("iface %p.\n", iface);
+
+    return D3DRTYPE_TEXTURE;
+}
+
+static DWORD WINAPI d3d8_texture_2d_SetLOD(IDirect3DTexture8 *iface, DWORD lod)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
+    DWORD ret;
+
+    TRACE("iface %p, lod %u.\n", iface, lod);
+
+    wined3d_mutex_lock();
+    ret = wined3d_texture_set_lod(texture->wined3d_texture, lod);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static DWORD WINAPI d3d8_texture_2d_GetLOD(IDirect3DTexture8 *iface)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
+    DWORD ret;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    ret = wined3d_texture_get_lod(texture->wined3d_texture);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static DWORD WINAPI d3d8_texture_2d_GetLevelCount(IDirect3DTexture8 *iface)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
+    DWORD ret;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    ret = wined3d_texture_get_level_count(texture->wined3d_texture);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static HRESULT WINAPI d3d8_texture_2d_GetLevelDesc(IDirect3DTexture8 *iface, UINT level, D3DSURFACE_DESC *desc)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
+    struct wined3d_resource *sub_resource;
+    HRESULT hr = D3D_OK;
+
+    TRACE("iface %p, level %u, desc %p.\n", iface, level, desc);
+
+    wined3d_mutex_lock();
+    if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
+        hr = D3DERR_INVALIDCALL;
+    else
+    {
+        struct wined3d_resource_desc wined3d_desc;
+
+        wined3d_resource_get_desc(sub_resource, &wined3d_desc);
+        desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format);
+        desc->Type = wined3d_desc.resource_type;
+        desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
+        desc->Pool = wined3d_desc.pool;
+        desc->Size = wined3d_desc.size;
+        desc->MultiSampleType = wined3d_desc.multisample_type;
+        desc->Width = wined3d_desc.width;
+        desc->Height = wined3d_desc.height;
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_texture_2d_GetSurfaceLevel(IDirect3DTexture8 *iface,
+        UINT level, IDirect3DSurface8 **surface)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
+    struct wined3d_resource *sub_resource;
+    struct d3d8_surface *surface_impl;
+
+    TRACE("iface %p, level %u, surface %p.\n", iface, level, surface);
+
+    wined3d_mutex_lock();
+    if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
+    {
+        wined3d_mutex_unlock();
+        return D3DERR_INVALIDCALL;
+    }
+
+    surface_impl = wined3d_resource_get_parent(sub_resource);
+    *surface = &surface_impl->IDirect3DSurface8_iface;
+    IDirect3DSurface8_AddRef(*surface);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_texture_2d_LockRect(IDirect3DTexture8 *iface, UINT level,
+        D3DLOCKED_RECT *locked_rect, const RECT *rect, DWORD flags)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
+    struct wined3d_resource *sub_resource;
+    struct d3d8_surface *surface_impl;
+    HRESULT hr;
+
+    TRACE("iface %p, level %u, locked_rect %p, rect %p, flags %#x.\n",
+            iface, level, locked_rect, rect, flags);
+
+    wined3d_mutex_lock();
+    if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
+        hr = D3DERR_INVALIDCALL;
+    else
+    {
+        surface_impl = wined3d_resource_get_parent(sub_resource);
+        hr = IDirect3DSurface8_LockRect(&surface_impl->IDirect3DSurface8_iface, locked_rect, rect, flags);
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_texture_2d_UnlockRect(IDirect3DTexture8 *iface, UINT level)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
+    struct wined3d_resource *sub_resource;
+    struct d3d8_surface *surface_impl;
+    HRESULT hr;
+
+    TRACE("iface %p, level %u.\n", iface, level);
+
+    wined3d_mutex_lock();
+    if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
+        hr = D3DERR_INVALIDCALL;
+    else
+    {
+        surface_impl = wined3d_resource_get_parent(sub_resource);
+        hr = IDirect3DSurface8_UnlockRect(&surface_impl->IDirect3DSurface8_iface);
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_texture_2d_AddDirtyRect(IDirect3DTexture8 *iface, const RECT *dirty_rect)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, dirty_rect %s.\n",
+            iface, wine_dbgstr_rect(dirty_rect));
+
+    wined3d_mutex_lock();
+    if (!dirty_rect)
+        hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, 0, NULL);
+    else
+    {
+        struct wined3d_box dirty_region;
+
+        dirty_region.left = dirty_rect->left;
+        dirty_region.top = dirty_rect->top;
+        dirty_region.right = dirty_rect->right;
+        dirty_region.bottom = dirty_rect->bottom;
+        dirty_region.front = 0;
+        dirty_region.back = 1;
+        hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, 0, &dirty_region);
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static const IDirect3DTexture8Vtbl Direct3DTexture8_Vtbl =
+{
+    /* IUnknown */
+    d3d8_texture_2d_QueryInterface,
+    d3d8_texture_2d_AddRef,
+    d3d8_texture_2d_Release,
+    /* IDirect3DResource8 */
+    d3d8_texture_2d_GetDevice,
+    d3d8_texture_2d_SetPrivateData,
+    d3d8_texture_2d_GetPrivateData,
+    d3d8_texture_2d_FreePrivateData,
+    d3d8_texture_2d_SetPriority,
+    d3d8_texture_2d_GetPriority,
+    d3d8_texture_2d_PreLoad,
+    d3d8_texture_2d_GetType,
+    /* IDirect3dBaseTexture8 */
+    d3d8_texture_2d_SetLOD,
+    d3d8_texture_2d_GetLOD,
+    d3d8_texture_2d_GetLevelCount,
+    /* IDirect3DTexture8 */
+    d3d8_texture_2d_GetLevelDesc,
+    d3d8_texture_2d_GetSurfaceLevel,
+    d3d8_texture_2d_LockRect,
+    d3d8_texture_2d_UnlockRect,
+    d3d8_texture_2d_AddDirtyRect,
+};
+
+static HRESULT WINAPI d3d8_texture_cube_QueryInterface(IDirect3DCubeTexture8 *iface, REFIID riid, void **out)
+{
+    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
+
+    if (IsEqualGUID(riid, &IID_IDirect3DCubeTexture8)
+            || IsEqualGUID(riid, &IID_IDirect3DBaseTexture8)
+            || IsEqualGUID(riid, &IID_IDirect3DResource8)
+            || IsEqualGUID(riid, &IID_IUnknown))
+    {
+        IDirect3DCubeTexture8_AddRef(iface);
+        *out = iface;
+        return S_OK;
+    }
+
+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+    *out = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI d3d8_texture_cube_AddRef(IDirect3DCubeTexture8 *iface)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
+    ULONG ref = InterlockedIncrement(&texture->refcount);
+
+    TRACE("%p increasing refcount to %u.\n", iface, ref);
+
+    if (ref == 1)
+    {
+        IDirect3DDevice8_AddRef(texture->parent_device);
+        wined3d_mutex_lock();
+        wined3d_texture_incref(texture->wined3d_texture);
+        wined3d_mutex_unlock();
+    }
+
+    return ref;
+}
+
+static ULONG WINAPI d3d8_texture_cube_Release(IDirect3DCubeTexture8 *iface)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
+    ULONG ref = InterlockedDecrement(&texture->refcount);
+
+    TRACE("%p decreasing refcount to %u.\n", iface, ref);
+
+    if (!ref)
+    {
+        IDirect3DDevice8 *parent_device = texture->parent_device;
+
+        TRACE("Releasing child %p.\n", texture->wined3d_texture);
+
+        wined3d_mutex_lock();
+        wined3d_texture_decref(texture->wined3d_texture);
+        wined3d_mutex_unlock();
+
+        /* Release the device last, as it may cause the device to be destroyed. */
+        IDirect3DDevice8_Release(parent_device);
+    }
+    return ref;
+}
+
+static HRESULT WINAPI d3d8_texture_cube_GetDevice(IDirect3DCubeTexture8 *iface, IDirect3DDevice8 **device)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
+
+    TRACE("iface %p, device %p.\n", iface, device);
+
+    *device = texture->parent_device;
+    IDirect3DDevice8_AddRef(*device);
+
+    TRACE("Returning device %p.\n", *device);
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_texture_cube_SetPrivateData(IDirect3DCubeTexture8 *iface,
+        REFGUID guid, const void *data, DWORD data_size, DWORD flags)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
+            iface, debugstr_guid(guid), data, data_size, flags);
+
+    wined3d_mutex_lock();
+    resource = wined3d_texture_get_resource(texture->wined3d_texture);
+    hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_texture_cube_GetPrivateData(IDirect3DCubeTexture8 *iface,
+        REFGUID guid, void *data, DWORD *data_size)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s, data %p, data_size %p.\n",
+            iface, debugstr_guid(guid), data, data_size);
+
+    wined3d_mutex_lock();
+    resource = wined3d_texture_get_resource(texture->wined3d_texture);
+    hr = wined3d_resource_get_private_data(resource, guid, data, data_size);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_texture_cube_FreePrivateData(IDirect3DCubeTexture8 *iface, REFGUID guid)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
+
+    wined3d_mutex_lock();
+    resource = wined3d_texture_get_resource(texture->wined3d_texture);
+    hr = wined3d_resource_free_private_data(resource, guid);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static DWORD WINAPI d3d8_texture_cube_SetPriority(IDirect3DCubeTexture8 *iface, DWORD priority)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
+    DWORD ret;
+
+    TRACE("iface %p, priority %u.\n", iface, priority);
+
+    wined3d_mutex_lock();
+    ret = wined3d_texture_set_priority(texture->wined3d_texture, priority);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static DWORD WINAPI d3d8_texture_cube_GetPriority(IDirect3DCubeTexture8 *iface)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
+    DWORD ret;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    ret =  wined3d_texture_get_priority(texture->wined3d_texture);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static void WINAPI d3d8_texture_cube_PreLoad(IDirect3DCubeTexture8 *iface)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    wined3d_texture_preload(texture->wined3d_texture);
+    wined3d_mutex_unlock();
+}
+
+static D3DRESOURCETYPE WINAPI d3d8_texture_cube_GetType(IDirect3DCubeTexture8 *iface)
+{
+    TRACE("iface %p.\n", iface);
+
+    return D3DRTYPE_CUBETEXTURE;
+}
+
+static DWORD WINAPI d3d8_texture_cube_SetLOD(IDirect3DCubeTexture8 *iface, DWORD lod)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
+    DWORD ret;
+
+    TRACE("iface %p, lod %u.\n", iface, lod);
+
+    wined3d_mutex_lock();
+    ret = wined3d_texture_set_lod(texture->wined3d_texture, lod);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static DWORD WINAPI d3d8_texture_cube_GetLOD(IDirect3DCubeTexture8 *iface)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
+    DWORD ret;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    ret = wined3d_texture_get_lod(texture->wined3d_texture);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static DWORD WINAPI d3d8_texture_cube_GetLevelCount(IDirect3DCubeTexture8 *iface)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
+    DWORD ret;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    ret = wined3d_texture_get_level_count(texture->wined3d_texture);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static HRESULT WINAPI d3d8_texture_cube_GetLevelDesc(IDirect3DCubeTexture8 *iface, UINT level, D3DSURFACE_DESC *desc)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
+    struct wined3d_resource *sub_resource;
+    HRESULT hr = D3D_OK;
+
+    TRACE("iface %p, level %u, desc %p.\n", iface, level, desc);
+
+    wined3d_mutex_lock();
+    if (level >= wined3d_texture_get_level_count(texture->wined3d_texture))
+    {
+        wined3d_mutex_unlock();
+        return D3DERR_INVALIDCALL;
+    }
+
+    if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
+        hr = D3DERR_INVALIDCALL;
+    else
+    {
+        struct wined3d_resource_desc wined3d_desc;
+
+        wined3d_resource_get_desc(sub_resource, &wined3d_desc);
+        desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format);
+        desc->Type = wined3d_desc.resource_type;
+        desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
+        desc->Pool = wined3d_desc.pool;
+        desc->Size = wined3d_desc.size;
+        desc->MultiSampleType = wined3d_desc.multisample_type;
+        desc->Width = wined3d_desc.width;
+        desc->Height = wined3d_desc.height;
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_texture_cube_GetCubeMapSurface(IDirect3DCubeTexture8 *iface,
+        D3DCUBEMAP_FACES face, UINT level, IDirect3DSurface8 **surface)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
+    struct wined3d_resource *sub_resource;
+    struct d3d8_surface *surface_impl;
+    UINT sub_resource_idx;
+    DWORD level_count;
+
+    TRACE("iface %p, face %#x, level %u, surface %p.\n", iface, face, level, surface);
+
+    wined3d_mutex_lock();
+    level_count = wined3d_texture_get_level_count(texture->wined3d_texture);
+    if (level >= level_count)
+    {
+        wined3d_mutex_unlock();
+        return D3DERR_INVALIDCALL;
+    }
+
+    sub_resource_idx = level_count * face + level;
+    if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, sub_resource_idx)))
+    {
+        wined3d_mutex_unlock();
+        return D3DERR_INVALIDCALL;
+    }
+
+    surface_impl = wined3d_resource_get_parent(sub_resource);
+    *surface = &surface_impl->IDirect3DSurface8_iface;
+    IDirect3DSurface8_AddRef(*surface);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_texture_cube_LockRect(IDirect3DCubeTexture8 *iface,
+        D3DCUBEMAP_FACES face, UINT level, D3DLOCKED_RECT *locked_rect, const RECT *rect,
+        DWORD flags)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
+    struct wined3d_resource *sub_resource;
+    struct d3d8_surface *surface_impl;
+    UINT sub_resource_idx;
+    HRESULT hr;
+
+    TRACE("iface %p, face %#x, level %u, locked_rect %p, rect %p, flags %#x.\n",
+            iface, face, level, locked_rect, rect, flags);
+
+    wined3d_mutex_lock();
+    sub_resource_idx = wined3d_texture_get_level_count(texture->wined3d_texture) * face + level;
+    if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, sub_resource_idx)))
+        hr = D3DERR_INVALIDCALL;
+    else
+    {
+        surface_impl = wined3d_resource_get_parent(sub_resource);
+        hr = IDirect3DSurface8_LockRect(&surface_impl->IDirect3DSurface8_iface, locked_rect, rect, flags);
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_texture_cube_UnlockRect(IDirect3DCubeTexture8 *iface,
+        D3DCUBEMAP_FACES face, UINT level)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
+    struct wined3d_resource *sub_resource;
+    struct d3d8_surface *surface_impl;
+    UINT sub_resource_idx;
+    HRESULT hr;
+
+    TRACE("iface %p, face %#x, level %u.\n", iface, face, level);
+
+    wined3d_mutex_lock();
+    sub_resource_idx = wined3d_texture_get_level_count(texture->wined3d_texture) * face + level;
+    if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, sub_resource_idx)))
+        hr = D3DERR_INVALIDCALL;
+    else
+    {
+        surface_impl = wined3d_resource_get_parent(sub_resource);
+        hr = IDirect3DSurface8_UnlockRect(&surface_impl->IDirect3DSurface8_iface);
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_texture_cube_AddDirtyRect(IDirect3DCubeTexture8 *iface,
+        D3DCUBEMAP_FACES face, const RECT *dirty_rect)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, face %#x, dirty_rect %s.\n",
+            iface, face, wine_dbgstr_rect(dirty_rect));
+
+    wined3d_mutex_lock();
+    if (!dirty_rect)
+        hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, face, NULL);
+    else
+    {
+        struct wined3d_box dirty_region;
+
+        dirty_region.left = dirty_rect->left;
+        dirty_region.top = dirty_rect->top;
+        dirty_region.right = dirty_rect->right;
+        dirty_region.bottom = dirty_rect->bottom;
+        dirty_region.front = 0;
+        dirty_region.back = 1;
+        hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, face, &dirty_region);
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static const IDirect3DCubeTexture8Vtbl Direct3DCubeTexture8_Vtbl =
+{
+    /* IUnknown */
+    d3d8_texture_cube_QueryInterface,
+    d3d8_texture_cube_AddRef,
+    d3d8_texture_cube_Release,
+    /* IDirect3DResource8 */
+    d3d8_texture_cube_GetDevice,
+    d3d8_texture_cube_SetPrivateData,
+    d3d8_texture_cube_GetPrivateData,
+    d3d8_texture_cube_FreePrivateData,
+    d3d8_texture_cube_SetPriority,
+    d3d8_texture_cube_GetPriority,
+    d3d8_texture_cube_PreLoad,
+    d3d8_texture_cube_GetType,
+    /* IDirect3DBaseTexture8 */
+    d3d8_texture_cube_SetLOD,
+    d3d8_texture_cube_GetLOD,
+    d3d8_texture_cube_GetLevelCount,
+    /* IDirect3DCubeTexture8 */
+    d3d8_texture_cube_GetLevelDesc,
+    d3d8_texture_cube_GetCubeMapSurface,
+    d3d8_texture_cube_LockRect,
+    d3d8_texture_cube_UnlockRect,
+    d3d8_texture_cube_AddDirtyRect,
+};
+
+static HRESULT WINAPI d3d8_texture_3d_QueryInterface(IDirect3DVolumeTexture8 *iface, REFIID riid, void **out)
+{
+    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
+
+    if (IsEqualGUID(riid, &IID_IDirect3DVolumeTexture8)
+            || IsEqualGUID(riid, &IID_IDirect3DBaseTexture8)
+            || IsEqualGUID(riid, &IID_IDirect3DResource8)
+            || IsEqualGUID(riid, &IID_IUnknown))
+    {
+        IDirect3DVolumeTexture8_AddRef(iface);
+        *out = iface;
+        return S_OK;
+    }
+
+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+    *out = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI d3d8_texture_3d_AddRef(IDirect3DVolumeTexture8 *iface)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
+    ULONG ref = InterlockedIncrement(&texture->refcount);
+
+    TRACE("%p increasing refcount to %u.\n", iface, ref);
+
+    if (ref == 1)
+    {
+        IDirect3DDevice8_AddRef(texture->parent_device);
+        wined3d_mutex_lock();
+        wined3d_texture_incref(texture->wined3d_texture);
+        wined3d_mutex_unlock();
+    }
+
+    return ref;
+}
+
+static ULONG WINAPI d3d8_texture_3d_Release(IDirect3DVolumeTexture8 *iface)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
+    ULONG ref = InterlockedDecrement(&texture->refcount);
+
+    TRACE("%p decreasing refcount to %u.\n", iface, ref);
+
+    if (!ref)
+    {
+        IDirect3DDevice8 *parent_device = texture->parent_device;
+
+        wined3d_mutex_lock();
+        wined3d_texture_decref(texture->wined3d_texture);
+        wined3d_mutex_unlock();
+
+        /* Release the device last, as it may cause the device to be destroyed. */
+        IDirect3DDevice8_Release(parent_device);
+    }
+    return ref;
+}
+
+static HRESULT WINAPI d3d8_texture_3d_GetDevice(IDirect3DVolumeTexture8 *iface, IDirect3DDevice8 **device)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
+
+    TRACE("iface %p, device %p.\n", iface, device);
+
+    *device = texture->parent_device;
+    IDirect3DDevice8_AddRef(*device);
+
+    TRACE("Returning device %p.\n", *device);
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_texture_3d_SetPrivateData(IDirect3DVolumeTexture8 *iface,
+        REFGUID guid, const void *data, DWORD data_size, DWORD flags)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
+            iface, debugstr_guid(guid), data, data_size, flags);
+
+    wined3d_mutex_lock();
+    resource = wined3d_texture_get_resource(texture->wined3d_texture);
+    hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_texture_3d_GetPrivateData(IDirect3DVolumeTexture8 *iface,
+        REFGUID guid, void *data, DWORD *data_size)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s, data %p, data_size %p.\n",
+            iface, debugstr_guid(guid), data, data_size);
+
+    wined3d_mutex_lock();
+    resource = wined3d_texture_get_resource(texture->wined3d_texture);
+    hr = wined3d_resource_get_private_data(resource, guid, data, data_size);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_texture_3d_FreePrivateData(IDirect3DVolumeTexture8 *iface, REFGUID guid)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
+
+    wined3d_mutex_lock();
+    resource = wined3d_texture_get_resource(texture->wined3d_texture);
+    hr = wined3d_resource_free_private_data(resource, guid);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static DWORD WINAPI d3d8_texture_3d_SetPriority(IDirect3DVolumeTexture8 *iface, DWORD priority)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
+    DWORD ret;
+
+    TRACE("iface %p, priority %u.\n", iface, priority);
+
+    wined3d_mutex_lock();
+    ret = wined3d_texture_set_priority(texture->wined3d_texture, priority);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static DWORD WINAPI d3d8_texture_3d_GetPriority(IDirect3DVolumeTexture8 *iface)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
+    DWORD ret;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    ret = wined3d_texture_get_priority(texture->wined3d_texture);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static void WINAPI d3d8_texture_3d_PreLoad(IDirect3DVolumeTexture8 *iface)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    wined3d_texture_preload(texture->wined3d_texture);
+    wined3d_mutex_unlock();
+}
+
+static D3DRESOURCETYPE WINAPI d3d8_texture_3d_GetType(IDirect3DVolumeTexture8 *iface)
+{
+    TRACE("iface %p.\n", iface);
+
+    return D3DRTYPE_VOLUMETEXTURE;
+}
+
+static DWORD WINAPI d3d8_texture_3d_SetLOD(IDirect3DVolumeTexture8 *iface, DWORD lod)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
+    DWORD ret;
+
+    TRACE("iface %p, lod %u.\n", iface, lod);
+
+    wined3d_mutex_lock();
+    ret = wined3d_texture_set_lod(texture->wined3d_texture, lod);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static DWORD WINAPI d3d8_texture_3d_GetLOD(IDirect3DVolumeTexture8 *iface)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
+    DWORD ret;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    ret = wined3d_texture_get_lod(texture->wined3d_texture);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static DWORD WINAPI d3d8_texture_3d_GetLevelCount(IDirect3DVolumeTexture8 *iface)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
+    DWORD ret;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    ret = wined3d_texture_get_level_count(texture->wined3d_texture);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static HRESULT WINAPI d3d8_texture_3d_GetLevelDesc(IDirect3DVolumeTexture8 *iface, UINT level, D3DVOLUME_DESC *desc)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
+    struct wined3d_resource *sub_resource;
+    HRESULT hr = D3D_OK;
+
+    TRACE("iface %p, level %u, desc %p.\n", iface, level, desc);
+
+    wined3d_mutex_lock();
+    if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
+        hr = D3DERR_INVALIDCALL;
+    else
+    {
+        struct wined3d_resource_desc wined3d_desc;
+
+        wined3d_resource_get_desc(sub_resource, &wined3d_desc);
+        desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format);
+        desc->Type = wined3d_desc.resource_type;
+        desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
+        desc->Pool = wined3d_desc.pool;
+        desc->Size = wined3d_desc.size;
+        desc->Width = wined3d_desc.width;
+        desc->Height = wined3d_desc.height;
+        desc->Depth = wined3d_desc.depth;
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_texture_3d_GetVolumeLevel(IDirect3DVolumeTexture8 *iface,
+        UINT level, IDirect3DVolume8 **volume)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
+    struct wined3d_resource *sub_resource;
+    struct d3d8_volume *volume_impl;
+
+    TRACE("iface %p, level %u, volume %p.\n", iface, level, volume);
+
+    wined3d_mutex_lock();
+    if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
+    {
+        wined3d_mutex_unlock();
+        return D3DERR_INVALIDCALL;
+    }
+
+    volume_impl = wined3d_resource_get_parent(sub_resource);
+    *volume = &volume_impl->IDirect3DVolume8_iface;
+    IDirect3DVolume8_AddRef(*volume);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_texture_3d_LockBox(IDirect3DVolumeTexture8 *iface,
+        UINT level, D3DLOCKED_BOX *locked_box, const D3DBOX *box, DWORD flags)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
+    struct wined3d_resource *sub_resource;
+    struct d3d8_volume *volume_impl;
+    HRESULT hr;
+
+    TRACE("iface %p, level %u, locked_box %p, box %p, flags %#x.\n",
+            iface, level, locked_box, box, flags);
+
+    wined3d_mutex_lock();
+    if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
+        hr = D3DERR_INVALIDCALL;
+    else
+    {
+        volume_impl = wined3d_resource_get_parent(sub_resource);
+        hr = IDirect3DVolume8_LockBox(&volume_impl->IDirect3DVolume8_iface, locked_box, box, flags);
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_texture_3d_UnlockBox(IDirect3DVolumeTexture8 *iface, UINT level)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
+    struct wined3d_resource *sub_resource;
+    struct d3d8_volume *volume_impl;
+    HRESULT hr;
+
+    TRACE("iface %p, level %u.\n", iface, level);
+
+    wined3d_mutex_lock();
+    if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
+        hr = D3DERR_INVALIDCALL;
+    else
+    {
+        volume_impl = wined3d_resource_get_parent(sub_resource);
+        hr = IDirect3DVolume8_UnlockBox(&volume_impl->IDirect3DVolume8_iface);
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_texture_3d_AddDirtyBox(IDirect3DVolumeTexture8 *iface, const D3DBOX *dirty_box)
+{
+    struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, dirty_box %p.\n", iface, dirty_box);
+
+    wined3d_mutex_lock();
+    hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, 0, (const struct wined3d_box *)dirty_box);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static const IDirect3DVolumeTexture8Vtbl Direct3DVolumeTexture8_Vtbl =
+{
+    /* IUnknown */
+    d3d8_texture_3d_QueryInterface,
+    d3d8_texture_3d_AddRef,
+    d3d8_texture_3d_Release,
+    /* IDirect3DResource8 */
+    d3d8_texture_3d_GetDevice,
+    d3d8_texture_3d_SetPrivateData,
+    d3d8_texture_3d_GetPrivateData,
+    d3d8_texture_3d_FreePrivateData,
+    d3d8_texture_3d_SetPriority,
+    d3d8_texture_3d_GetPriority,
+    d3d8_texture_3d_PreLoad,
+    d3d8_texture_3d_GetType,
+    /* IDirect3DBaseTexture8 */
+    d3d8_texture_3d_SetLOD,
+    d3d8_texture_3d_GetLOD,
+    d3d8_texture_3d_GetLevelCount,
+    /* IDirect3DVolumeTexture8 */
+    d3d8_texture_3d_GetLevelDesc,
+    d3d8_texture_3d_GetVolumeLevel,
+    d3d8_texture_3d_LockBox,
+    d3d8_texture_3d_UnlockBox,
+    d3d8_texture_3d_AddDirtyBox
+};
+
+struct d3d8_texture *unsafe_impl_from_IDirect3DBaseTexture8(IDirect3DBaseTexture8 *iface)
+{
+    if (!iface)
+        return NULL;
+
+    /* SetTexture() in particular doesn't do a lot of validation on the pointer
+     * that gets passed in, and passing an invalid pointer works as long as the
+     * application doesn't try to actually render anything with it, so we print
+     * a WARN and return NULL instead of having the usual assert() here.
+     * One application affected by this is Fishdom 2. */
+    if (iface->lpVtbl != (const IDirect3DBaseTexture8Vtbl *)&Direct3DTexture8_Vtbl
+            && iface->lpVtbl != (const IDirect3DBaseTexture8Vtbl *)&Direct3DCubeTexture8_Vtbl
+            && iface->lpVtbl != (const IDirect3DBaseTexture8Vtbl *)&Direct3DVolumeTexture8_Vtbl)
+    {
+        WARN("%p is not a valid IDirect3DBaseTexture8 interface.\n", iface);
+        return NULL;
+    }
+
+    return CONTAINING_RECORD(iface, struct d3d8_texture, IDirect3DBaseTexture8_iface);
+}
+
+static void STDMETHODCALLTYPE d3d8_texture_wined3d_object_destroyed(void *parent)
+{
+    HeapFree(GetProcessHeap(), 0, parent);
+}
+
+static const struct wined3d_parent_ops d3d8_texture_wined3d_parent_ops =
+{
+    d3d8_texture_wined3d_object_destroyed,
+};
+
+HRESULT texture_init(struct d3d8_texture *texture, struct d3d8_device *device,
+        UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool)
+{
+    struct wined3d_resource_desc desc;
+    DWORD surface_flags = 0;
+    HRESULT hr;
+
+    texture->IDirect3DBaseTexture8_iface.lpVtbl = (const IDirect3DBaseTexture8Vtbl *)&Direct3DTexture8_Vtbl;
+    texture->refcount = 1;
+
+    desc.resource_type = WINED3D_RTYPE_TEXTURE;
+    desc.format = wined3dformat_from_d3dformat(format);
+    desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
+    desc.multisample_quality = 0;
+    desc.usage = usage & WINED3DUSAGE_MASK;
+    desc.pool = pool;
+    desc.width = width;
+    desc.height = height;
+    desc.depth = 1;
+    desc.size = 0;
+
+    if (pool != D3DPOOL_DEFAULT || (usage & D3DUSAGE_DYNAMIC))
+        surface_flags |= WINED3D_SURFACE_MAPPABLE;
+
+    wined3d_mutex_lock();
+    hr = wined3d_texture_create_2d(device->wined3d_device, &desc, levels, surface_flags,
+            texture, &d3d8_texture_wined3d_parent_ops, &texture->wined3d_texture);
+    wined3d_mutex_unlock();
+    if (FAILED(hr))
+    {
+        WARN("Failed to create wined3d texture, hr %#x.\n", hr);
+        return hr;
+    }
+
+    texture->parent_device = &device->IDirect3DDevice8_iface;
+    IDirect3DDevice8_AddRef(texture->parent_device);
+
+    return D3D_OK;
+}
+
+HRESULT cubetexture_init(struct d3d8_texture *texture, struct d3d8_device *device,
+        UINT edge_length, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool)
+{
+    struct wined3d_resource_desc desc;
+    DWORD surface_flags = 0;
+    HRESULT hr;
+
+    texture->IDirect3DBaseTexture8_iface.lpVtbl = (const IDirect3DBaseTexture8Vtbl *)&Direct3DCubeTexture8_Vtbl;
+    texture->refcount = 1;
+
+    desc.resource_type = WINED3D_RTYPE_CUBE_TEXTURE;
+    desc.format = wined3dformat_from_d3dformat(format);
+    desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
+    desc.multisample_quality = 0;
+    desc.usage = usage & WINED3DUSAGE_MASK;
+    desc.pool = pool;
+    desc.width = edge_length;
+    desc.height = edge_length;
+    desc.depth = 1;
+    desc.size = 0;
+
+    if (pool != D3DPOOL_DEFAULT || (usage & D3DUSAGE_DYNAMIC))
+        surface_flags |= WINED3D_SURFACE_MAPPABLE;
+
+    wined3d_mutex_lock();
+    hr = wined3d_texture_create_cube(device->wined3d_device, &desc, levels, surface_flags,
+            texture, &d3d8_texture_wined3d_parent_ops, &texture->wined3d_texture);
+    wined3d_mutex_unlock();
+    if (FAILED(hr))
+    {
+        WARN("Failed to create wined3d cube texture, hr %#x.\n", hr);
+        return hr;
+    }
+
+    texture->parent_device = &device->IDirect3DDevice8_iface;
+    IDirect3DDevice8_AddRef(texture->parent_device);
+
+    return D3D_OK;
+}
+
+HRESULT volumetexture_init(struct d3d8_texture *texture, struct d3d8_device *device,
+        UINT width, UINT height, UINT depth, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool)
+{
+    struct wined3d_resource_desc desc;
+    HRESULT hr;
+
+    texture->IDirect3DBaseTexture8_iface.lpVtbl = (const IDirect3DBaseTexture8Vtbl *)&Direct3DVolumeTexture8_Vtbl;
+    texture->refcount = 1;
+
+    desc.resource_type = WINED3D_RTYPE_VOLUME_TEXTURE;
+    desc.format = wined3dformat_from_d3dformat(format);
+    desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
+    desc.multisample_quality = 0;
+    desc.usage = usage & WINED3DUSAGE_MASK;
+    desc.pool = pool;
+    desc.width = width;
+    desc.height = height;
+    desc.depth = depth;
+    desc.size = 0;
+
+    wined3d_mutex_lock();
+    hr = wined3d_texture_create_3d(device->wined3d_device, &desc, levels,
+            texture, &d3d8_texture_wined3d_parent_ops, &texture->wined3d_texture);
+    wined3d_mutex_unlock();
+    if (FAILED(hr))
+    {
+        WARN("Failed to create wined3d volume texture, hr %#x.\n", hr);
+        return hr;
+    }
+
+    texture->parent_device = &device->IDirect3DDevice8_iface;
+    IDirect3DDevice8_AddRef(texture->parent_device);
+
+    return D3D_OK;
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/version.rc
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/version.rc	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/version.rc	(revision 46521)
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2001 Ove Kaaven
+ *
+ * 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 Direct3D"
+#define WINE_FILENAME_STR "d3d8.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"
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/vertexdeclaration.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/vertexdeclaration.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/vertexdeclaration.c	(revision 46521)
@@ -0,0 +1,391 @@
+/*
+ * IDirect3DVertexDeclaration8 implementation
+ *
+ * Copyright 2007 Henri Verbeet
+ *
+ * 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
+ */
+
+/* IDirect3DVertexDeclaration8 is internal to our implementation.
+ * It's not visible in the API. */
+
+#include "config.h"
+#include "d3d8_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d8);
+
+#ifdef VBOX_WINE_WITHOUT_LIBWINE
+typedef DWORD D3DVSDT_TYPE;
+typedef DWORD D3DVSDE_REGISTER;
+#endif
+
+static const char *debug_d3dvsdt_type(D3DVSDT_TYPE d3dvsdt_type)
+{
+    switch (d3dvsdt_type)
+    {
+#define D3DVSDT_TYPE_TO_STR(u) case u: return #u
+        D3DVSDT_TYPE_TO_STR(D3DVSDT_FLOAT1);
+        D3DVSDT_TYPE_TO_STR(D3DVSDT_FLOAT2);
+        D3DVSDT_TYPE_TO_STR(D3DVSDT_FLOAT3);
+        D3DVSDT_TYPE_TO_STR(D3DVSDT_FLOAT4);
+        D3DVSDT_TYPE_TO_STR(D3DVSDT_D3DCOLOR);
+        D3DVSDT_TYPE_TO_STR(D3DVSDT_UBYTE4);
+        D3DVSDT_TYPE_TO_STR(D3DVSDT_SHORT2);
+        D3DVSDT_TYPE_TO_STR(D3DVSDT_SHORT4);
+#undef D3DVSDT_TYPE_TO_STR
+        default:
+            FIXME("Unrecognized D3DVSDT_TYPE %#x\n", d3dvsdt_type);
+            return "unrecognized";
+    }
+}
+
+static const char *debug_d3dvsde_register(D3DVSDE_REGISTER d3dvsde_register)
+{
+    switch (d3dvsde_register)
+    {
+#define D3DVSDE_REGISTER_TO_STR(u) case u: return #u
+        D3DVSDE_REGISTER_TO_STR(D3DVSDE_POSITION);
+        D3DVSDE_REGISTER_TO_STR(D3DVSDE_BLENDWEIGHT);
+        D3DVSDE_REGISTER_TO_STR(D3DVSDE_BLENDINDICES);
+        D3DVSDE_REGISTER_TO_STR(D3DVSDE_NORMAL);
+        D3DVSDE_REGISTER_TO_STR(D3DVSDE_PSIZE);
+        D3DVSDE_REGISTER_TO_STR(D3DVSDE_DIFFUSE);
+        D3DVSDE_REGISTER_TO_STR(D3DVSDE_SPECULAR);
+        D3DVSDE_REGISTER_TO_STR(D3DVSDE_TEXCOORD0);
+        D3DVSDE_REGISTER_TO_STR(D3DVSDE_TEXCOORD1);
+        D3DVSDE_REGISTER_TO_STR(D3DVSDE_TEXCOORD2);
+        D3DVSDE_REGISTER_TO_STR(D3DVSDE_TEXCOORD3);
+        D3DVSDE_REGISTER_TO_STR(D3DVSDE_TEXCOORD4);
+        D3DVSDE_REGISTER_TO_STR(D3DVSDE_TEXCOORD5);
+        D3DVSDE_REGISTER_TO_STR(D3DVSDE_TEXCOORD6);
+        D3DVSDE_REGISTER_TO_STR(D3DVSDE_TEXCOORD7);
+        D3DVSDE_REGISTER_TO_STR(D3DVSDE_POSITION2);
+        D3DVSDE_REGISTER_TO_STR(D3DVSDE_NORMAL2);
+#undef D3DVSDE_REGISTER_TO_STR
+        default:
+            FIXME("Unrecognized D3DVSDE_REGISTER %#x\n", d3dvsde_register);
+            return "unrecognized";
+    }
+}
+
+size_t parse_token(const DWORD* pToken)
+{
+    const DWORD token = *pToken;
+    size_t tokenlen = 1;
+
+    switch ((token & D3DVSD_TOKENTYPEMASK) >> D3DVSD_TOKENTYPESHIFT) { /* maybe a macro to inverse ... */
+        case D3DVSD_TOKEN_NOP:
+            TRACE(" 0x%08x NOP()\n", token);
+            break;
+
+        case D3DVSD_TOKEN_STREAM:
+            if (token & D3DVSD_STREAMTESSMASK)
+            {
+                TRACE(" 0x%08x STREAM_TESS()\n", token);
+            } else {
+                TRACE(" 0x%08x STREAM(%u)\n", token, ((token & D3DVSD_STREAMNUMBERMASK) >> D3DVSD_STREAMNUMBERSHIFT));
+            }
+            break;
+
+        case D3DVSD_TOKEN_STREAMDATA:
+            if (token & 0x10000000)
+            {
+                TRACE(" 0x%08x SKIP(%u)\n", token, ((token & D3DVSD_SKIPCOUNTMASK) >> D3DVSD_SKIPCOUNTSHIFT));
+            } else {
+                DWORD type = ((token & D3DVSD_DATATYPEMASK)  >> D3DVSD_DATATYPESHIFT);
+                DWORD reg = ((token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT);
+                TRACE(" 0x%08x REG(%s, %s)\n", token, debug_d3dvsde_register(reg), debug_d3dvsdt_type(type));
+            }
+            break;
+
+        case D3DVSD_TOKEN_TESSELLATOR:
+            if (token & 0x10000000)
+            {
+                DWORD type = ((token & D3DVSD_DATATYPEMASK)  >> D3DVSD_DATATYPESHIFT);
+                DWORD reg = ((token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT);
+                TRACE(" 0x%08x TESSUV(%s) as %s\n", token, debug_d3dvsde_register(reg), debug_d3dvsdt_type(type));
+            } else {
+                DWORD type = ((token & D3DVSD_DATATYPEMASK)    >> D3DVSD_DATATYPESHIFT);
+                DWORD regout = ((token & D3DVSD_VERTEXREGMASK)   >> D3DVSD_VERTEXREGSHIFT);
+                DWORD regin = ((token & D3DVSD_VERTEXREGINMASK) >> D3DVSD_VERTEXREGINSHIFT);
+                TRACE(" 0x%08x TESSNORMAL(%s, %s) as %s\n", token, debug_d3dvsde_register(regin),
+                        debug_d3dvsde_register(regout), debug_d3dvsdt_type(type));
+            }
+            break;
+
+        case D3DVSD_TOKEN_CONSTMEM:
+            {
+                DWORD count = ((token & D3DVSD_CONSTCOUNTMASK)   >> D3DVSD_CONSTCOUNTSHIFT);
+                tokenlen = (4 * count) + 1;
+            }
+            break;
+
+        case D3DVSD_TOKEN_EXT:
+            {
+                DWORD count = ((token & D3DVSD_CONSTCOUNTMASK) >> D3DVSD_CONSTCOUNTSHIFT);
+                DWORD extinfo = ((token & D3DVSD_EXTINFOMASK)    >> D3DVSD_EXTINFOSHIFT);
+                TRACE(" 0x%08x EXT(%u, %u)\n", token, count, extinfo);
+                /* todo ... print extension */
+                tokenlen = count + 1;
+            }
+            break;
+
+        case D3DVSD_TOKEN_END:
+            TRACE(" 0x%08x END()\n", token);
+            break;
+
+        default:
+            TRACE(" 0x%08x UNKNOWN\n", token);
+            /* arg error */
+    }
+
+    return tokenlen;
+}
+
+void load_local_constants(const DWORD *d3d8_elements, struct wined3d_shader *wined3d_vertex_shader)
+{
+    const DWORD *token = d3d8_elements;
+
+    while (*token != D3DVSD_END())
+    {
+        if (((*token & D3DVSD_TOKENTYPEMASK) >> D3DVSD_TOKENTYPESHIFT) == D3DVSD_TOKEN_CONSTMEM)
+        {
+            DWORD count = ((*token & D3DVSD_CONSTCOUNTMASK) >> D3DVSD_CONSTCOUNTSHIFT);
+            DWORD constant_idx = ((*token & D3DVSD_CONSTADDRESSMASK) >> D3DVSD_CONSTADDRESSSHIFT);
+            HRESULT hr;
+
+            if (TRACE_ON(d3d8))
+            {
+                DWORD i;
+                for (i = 0; i < count; ++i)
+                {
+                    TRACE("c[%u] = (%8f, %8f, %8f, %8f)\n",
+                            constant_idx,
+                            *(const float *)(token + i * 4 + 1),
+                            *(const float *)(token + i * 4 + 2),
+                            *(const float *)(token + i * 4 + 3),
+                            *(const float *)(token + i * 4 + 4));
+                }
+            }
+            hr = wined3d_shader_set_local_constants_float(wined3d_vertex_shader,
+                    constant_idx, (const float *)token + 1, count);
+            if (FAILED(hr)) ERR("Failed setting shader constants\n");
+        }
+
+        token += parse_token(token);
+    }
+}
+
+/* NOTE: Make sure these are in the correct numerical order. (see /include/wined3d_types.h) */
+static const size_t wined3d_type_sizes[] =
+{
+    /*WINED3DDECLTYPE_FLOAT1*/    1 * sizeof(float),
+    /*WINED3DDECLTYPE_FLOAT2*/    2 * sizeof(float),
+    /*WINED3DDECLTYPE_FLOAT3*/    3 * sizeof(float),
+    /*WINED3DDECLTYPE_FLOAT4*/    4 * sizeof(float),
+    /*WINED3DDECLTYPE_D3DCOLOR*/  4 * sizeof(BYTE),
+    /*WINED3DDECLTYPE_UBYTE4*/    4 * sizeof(BYTE),
+    /*WINED3DDECLTYPE_SHORT2*/    2 * sizeof(short int),
+    /*WINED3DDECLTYPE_SHORT4*/    4 * sizeof(short int),
+    /*WINED3DDECLTYPE_UBYTE4N*/   4 * sizeof(BYTE),
+    /*WINED3DDECLTYPE_SHORT2N*/   2 * sizeof(short int),
+    /*WINED3DDECLTYPE_SHORT4N*/   4 * sizeof(short int),
+    /*WINED3DDECLTYPE_USHORT2N*/  2 * sizeof(short int),
+    /*WINED3DDECLTYPE_USHORT4N*/  4 * sizeof(short int),
+    /*WINED3DDECLTYPE_UDEC3*/     3 * sizeof(short int),
+    /*WINED3DDECLTYPE_DEC3N*/     3 * sizeof(short int),
+    /*WINED3DDECLTYPE_FLOAT16_2*/ 2 * sizeof(short int),
+    /*WINED3DDECLTYPE_FLOAT16_4*/ 4 * sizeof(short int)
+};
+
+static const enum wined3d_format_id wined3d_format_lookup[] =
+{
+    /*WINED3DDECLTYPE_FLOAT1*/    WINED3DFMT_R32_FLOAT,
+    /*WINED3DDECLTYPE_FLOAT2*/    WINED3DFMT_R32G32_FLOAT,
+    /*WINED3DDECLTYPE_FLOAT3*/    WINED3DFMT_R32G32B32_FLOAT,
+    /*WINED3DDECLTYPE_FLOAT4*/    WINED3DFMT_R32G32B32A32_FLOAT,
+    /*WINED3DDECLTYPE_D3DCOLOR*/  WINED3DFMT_B8G8R8A8_UNORM,
+    /*WINED3DDECLTYPE_UBYTE4*/    WINED3DFMT_R8G8B8A8_UINT,
+    /*WINED3DDECLTYPE_SHORT2*/    WINED3DFMT_R16G16_SINT,
+    /*WINED3DDECLTYPE_SHORT4*/    WINED3DFMT_R16G16B16A16_SINT,
+    /*WINED3DDECLTYPE_UBYTE4N*/   WINED3DFMT_R8G8B8A8_UNORM,
+    /*WINED3DDECLTYPE_SHORT2N*/   WINED3DFMT_R16G16_SNORM,
+    /*WINED3DDECLTYPE_SHORT4N*/   WINED3DFMT_R16G16B16A16_SNORM,
+    /*WINED3DDECLTYPE_USHORT2N*/  WINED3DFMT_R16G16_UNORM,
+    /*WINED3DDECLTYPE_USHORT4N*/  WINED3DFMT_R16G16B16A16_UNORM,
+    /*WINED3DDECLTYPE_UDEC3*/     WINED3DFMT_R10G10B10A2_UINT,
+    /*WINED3DDECLTYPE_DEC3N*/     WINED3DFMT_R10G10B10A2_SNORM,
+    /*WINED3DDECLTYPE_FLOAT16_2*/ WINED3DFMT_R16G16_FLOAT,
+    /*WINED3DDECLTYPE_FLOAT16_4*/ WINED3DFMT_R16G16B16A16_FLOAT,
+};
+
+static const struct
+{
+    BYTE usage;
+    BYTE usage_idx;
+}
+wined3d_usage_lookup[] =
+{
+    /* D3DVSDE_POSITION */      {WINED3D_DECL_USAGE_POSITION,      0},
+    /* D3DVSDE_BLENDWEIGHT */   {WINED3D_DECL_USAGE_BLEND_WEIGHT,  0},
+    /* D3DVSDE_BLENDINDICES */  {WINED3D_DECL_USAGE_BLEND_INDICES, 0},
+    /* D3DVSDE_NORMAL */        {WINED3D_DECL_USAGE_NORMAL,        0},
+    /* D3DVSDE_PSIZE */         {WINED3D_DECL_USAGE_PSIZE,         0},
+    /* D3DVSDE_DIFFUSE */       {WINED3D_DECL_USAGE_COLOR,         0},
+    /* D3DVSDE_SPECULAR */      {WINED3D_DECL_USAGE_COLOR,         1},
+    /* D3DVSDE_TEXCOORD0 */     {WINED3D_DECL_USAGE_TEXCOORD,      0},
+    /* D3DVSDE_TEXCOORD1 */     {WINED3D_DECL_USAGE_TEXCOORD,      1},
+    /* D3DVSDE_TEXCOORD2 */     {WINED3D_DECL_USAGE_TEXCOORD,      2},
+    /* D3DVSDE_TEXCOORD3 */     {WINED3D_DECL_USAGE_TEXCOORD,      3},
+    /* D3DVSDE_TEXCOORD4 */     {WINED3D_DECL_USAGE_TEXCOORD,      4},
+    /* D3DVSDE_TEXCOORD5 */     {WINED3D_DECL_USAGE_TEXCOORD,      5},
+    /* D3DVSDE_TEXCOORD6 */     {WINED3D_DECL_USAGE_TEXCOORD,      6},
+    /* D3DVSDE_TEXCOORD7 */     {WINED3D_DECL_USAGE_TEXCOORD,      7},
+    /* D3DVSDE_POSITION2 */     {WINED3D_DECL_USAGE_POSITION,      1},
+    /* D3DVSDE_NORMAL2 */       {WINED3D_DECL_USAGE_NORMAL,        1},
+};
+
+/* TODO: find out where rhw (or positionT) is for declaration8 */
+static UINT convert_to_wined3d_declaration(const DWORD *d3d8_elements, DWORD *d3d8_elements_size,
+        struct wined3d_vertex_element **wined3d_elements)
+{
+    struct wined3d_vertex_element *element;
+    const DWORD *token = d3d8_elements;
+    D3DVSD_TOKENTYPE token_type;
+    unsigned int element_count = 0;
+    WORD stream = 0;
+    int offset = 0;
+
+    TRACE("d3d8_elements %p, wined3d_elements %p\n", d3d8_elements, wined3d_elements);
+
+    /* 128 should be enough for anyone... */
+    *wined3d_elements = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 128 * sizeof(**wined3d_elements));
+    while (D3DVSD_END() != *token)
+    {
+        token_type = ((*token & D3DVSD_TOKENTYPEMASK) >> D3DVSD_TOKENTYPESHIFT);
+
+        if (token_type == D3DVSD_TOKEN_STREAM && !(*token & D3DVSD_STREAMTESSMASK))
+        {
+            stream = ((*token & D3DVSD_STREAMNUMBERMASK) >> D3DVSD_STREAMNUMBERSHIFT);
+            offset = 0;
+        } else if (token_type == D3DVSD_TOKEN_STREAMDATA && !(token_type & 0x10000000)) {
+            DWORD type = ((*token & D3DVSD_DATATYPEMASK) >> D3DVSD_DATATYPESHIFT);
+            DWORD reg  = ((*token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT);
+
+            TRACE("Adding element %d:\n", element_count);
+
+            element = *wined3d_elements + element_count++;
+            element->format = wined3d_format_lookup[type];
+            element->input_slot = stream;
+            element->offset = offset;
+            element->output_slot = reg;
+            element->method = WINED3D_DECL_METHOD_DEFAULT;
+            element->usage = wined3d_usage_lookup[reg].usage;
+            element->usage_idx = wined3d_usage_lookup[reg].usage_idx;
+
+            offset += wined3d_type_sizes[type];
+        } else if (token_type == D3DVSD_TOKEN_STREAMDATA && (token_type & 0x10000000)) {
+            TRACE(" 0x%08x SKIP(%u)\n", token_type, ((token_type & D3DVSD_SKIPCOUNTMASK) >> D3DVSD_SKIPCOUNTSHIFT));
+            offset += sizeof(DWORD) * ((token_type & D3DVSD_SKIPCOUNTMASK) >> D3DVSD_SKIPCOUNTSHIFT);
+        }
+
+        if (element_count >= 127) {
+            ERR("More than 127 elements?\n");
+            break;
+        }
+
+        token += parse_token(token);
+    }
+
+    *d3d8_elements_size = (++token - d3d8_elements) * sizeof(DWORD);
+
+    return element_count;
+}
+
+static void STDMETHODCALLTYPE d3d8_vertexdeclaration_wined3d_object_destroyed(void *parent)
+{
+    struct d3d8_vertex_declaration *declaration = parent;
+    HeapFree(GetProcessHeap(), 0, declaration->elements);
+    HeapFree(GetProcessHeap(), 0, declaration);
+}
+
+void d3d8_vertex_declaration_destroy(struct d3d8_vertex_declaration *declaration)
+{
+    TRACE("declaration %p.\n", declaration);
+
+    wined3d_mutex_lock();
+    wined3d_vertex_declaration_decref(declaration->wined3d_vertex_declaration);
+    wined3d_mutex_unlock();
+}
+
+static const struct wined3d_parent_ops d3d8_vertexdeclaration_wined3d_parent_ops =
+{
+    d3d8_vertexdeclaration_wined3d_object_destroyed,
+};
+
+HRESULT d3d8_vertex_declaration_init(struct d3d8_vertex_declaration *declaration,
+        struct d3d8_device *device, const DWORD *elements, DWORD shader_handle)
+{
+    struct wined3d_vertex_element *wined3d_elements;
+    UINT wined3d_element_count;
+    HRESULT hr;
+
+    declaration->shader_handle = shader_handle;
+
+    wined3d_element_count = convert_to_wined3d_declaration(elements, &declaration->elements_size, &wined3d_elements);
+    declaration->elements = HeapAlloc(GetProcessHeap(), 0, declaration->elements_size);
+    if (!declaration->elements)
+    {
+        ERR("Failed to allocate vertex declaration elements memory.\n");
+        HeapFree(GetProcessHeap(), 0, wined3d_elements);
+        return E_OUTOFMEMORY;
+    }
+
+    memcpy(declaration->elements, elements, declaration->elements_size);
+
+    wined3d_mutex_lock();
+    hr = wined3d_vertex_declaration_create(device->wined3d_device, wined3d_elements, wined3d_element_count,
+            declaration, &d3d8_vertexdeclaration_wined3d_parent_ops, &declaration->wined3d_vertex_declaration);
+    wined3d_mutex_unlock();
+    HeapFree(GetProcessHeap(), 0, wined3d_elements);
+    if (FAILED(hr))
+    {
+        WARN("Failed to create wined3d vertex declaration, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, declaration->elements);
+        return hr;
+    }
+
+    return D3D_OK;
+}
+
+HRESULT d3d8_vertex_declaration_init_fvf(struct d3d8_vertex_declaration *declaration,
+        struct d3d8_device *device, DWORD fvf)
+{
+    HRESULT hr;
+
+    declaration->elements = NULL;
+    declaration->elements_size = 0;
+    declaration->shader_handle = fvf;
+
+    hr = wined3d_vertex_declaration_create_from_fvf(device->wined3d_device, fvf, declaration,
+            &d3d8_vertexdeclaration_wined3d_parent_ops, &declaration->wined3d_vertex_declaration);
+    if (FAILED(hr))
+    {
+        WARN("Failed to create wined3d vertex declaration, hr %#x.\n", hr);
+        return hr;
+    }
+
+    return D3D_OK;
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/volume.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/volume.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/volume.c	(revision 46521)
@@ -0,0 +1,303 @@
+/*
+ * IDirect3DVolume8 implementation
+ *
+ * Copyright 2005 Oliver Stieber
+ *
+ * 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 "d3d8_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d8);
+
+static inline struct d3d8_volume *impl_from_IDirect3DVolume8(IDirect3DVolume8 *iface)
+{
+    return CONTAINING_RECORD(iface, struct d3d8_volume, IDirect3DVolume8_iface);
+}
+
+static HRESULT WINAPI d3d8_volume_QueryInterface(IDirect3DVolume8 *iface, REFIID riid, void **out)
+{
+    TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), out);
+
+    if (IsEqualGUID(riid, &IID_IDirect3DVolume8)
+            || IsEqualGUID(riid, &IID_IUnknown))
+    {
+        IDirect3DVolume8_AddRef(iface);
+        *out = iface;
+        return S_OK;
+    }
+
+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+    *out = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI d3d8_volume_AddRef(IDirect3DVolume8 *iface)
+{
+    struct d3d8_volume *volume = impl_from_IDirect3DVolume8(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    if (volume->forwardReference)
+    {
+        /* Forward to the containerParent */
+        TRACE("Forwarding to %p,\n", volume->forwardReference);
+        return IUnknown_AddRef(volume->forwardReference);
+    }
+    else
+    {
+        /* No container, handle our own refcounting */
+        ULONG ref = InterlockedIncrement(&volume->refcount);
+
+        TRACE("%p increasing refcount to %u.\n", iface, ref);
+
+        if (ref == 1)
+        {
+            wined3d_mutex_lock();
+            wined3d_volume_incref(volume->wined3d_volume);
+            wined3d_mutex_unlock();
+        }
+
+        return ref;
+    }
+}
+
+static ULONG WINAPI d3d8_volume_Release(IDirect3DVolume8 *iface)
+{
+    struct d3d8_volume *volume = impl_from_IDirect3DVolume8(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    if (volume->forwardReference)
+    {
+        /* Forward to the containerParent */
+        TRACE("Forwarding to %p.\n", volume->forwardReference);
+        return IUnknown_Release(volume->forwardReference);
+    }
+    else
+    {
+        /* No container, handle our own refcounting */
+        ULONG ref = InterlockedDecrement(&volume->refcount);
+
+        TRACE("%p decreasing refcount to %u.\n", iface, ref);
+
+        if (!ref)
+        {
+            wined3d_mutex_lock();
+            wined3d_volume_decref(volume->wined3d_volume);
+            wined3d_mutex_unlock();
+        }
+
+        return ref;
+    }
+}
+
+static HRESULT WINAPI d3d8_volume_GetDevice(IDirect3DVolume8 *iface, IDirect3DDevice8 **device)
+{
+    struct d3d8_volume *volume = impl_from_IDirect3DVolume8(iface);
+    IDirect3DResource8 *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, device %p.\n", iface, device);
+
+    hr = IUnknown_QueryInterface(volume->forwardReference, &IID_IDirect3DResource8, (void **)&resource);
+    if (SUCCEEDED(hr))
+    {
+        hr = IDirect3DResource8_GetDevice(resource, device);
+        IDirect3DResource8_Release(resource);
+
+        TRACE("Returning device %p.\n", *device);
+    }
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_volume_SetPrivateData(IDirect3DVolume8 *iface, REFGUID guid,
+        const void *data, DWORD data_size, DWORD flags)
+{
+    struct d3d8_volume *volume = impl_from_IDirect3DVolume8(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
+            iface, debugstr_guid(guid), data, data_size, flags);
+
+    wined3d_mutex_lock();
+    resource = wined3d_volume_get_resource(volume->wined3d_volume);
+    hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_volume_GetPrivateData(IDirect3DVolume8 *iface, REFGUID  guid,
+        void *data, DWORD *data_size)
+{
+    struct d3d8_volume *volume = impl_from_IDirect3DVolume8(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s, data %p, data_size %p.\n",
+            iface, debugstr_guid(guid), data, data_size);
+
+    wined3d_mutex_lock();
+    resource = wined3d_volume_get_resource(volume->wined3d_volume);
+    hr = wined3d_resource_get_private_data(resource, guid, data, data_size);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_volume_FreePrivateData(IDirect3DVolume8 *iface, REFGUID guid)
+{
+    struct d3d8_volume *volume = impl_from_IDirect3DVolume8(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
+
+    wined3d_mutex_lock();
+    resource = wined3d_volume_get_resource(volume->wined3d_volume);
+    hr = wined3d_resource_free_private_data(resource, guid);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_volume_GetContainer(IDirect3DVolume8 *iface, REFIID riid, void **container)
+{
+    struct d3d8_volume *volume = impl_from_IDirect3DVolume8(iface);
+    HRESULT res;
+
+    TRACE("iface %p, riid %s, container %p.\n",
+            iface, debugstr_guid(riid), container);
+
+    if (!volume->container)
+        return E_NOINTERFACE;
+
+    res = IUnknown_QueryInterface(volume->container, riid, container);
+
+    TRACE("Returning %p.\n", *container);
+
+    return res;
+}
+
+static HRESULT WINAPI d3d8_volume_GetDesc(IDirect3DVolume8 *iface, D3DVOLUME_DESC *desc)
+{
+    struct d3d8_volume *volume = impl_from_IDirect3DVolume8(iface);
+    struct wined3d_resource_desc wined3d_desc;
+    struct wined3d_resource *wined3d_resource;
+
+    TRACE("iface %p, desc %p.\n", iface, desc);
+
+    wined3d_mutex_lock();
+    wined3d_resource = wined3d_volume_get_resource(volume->wined3d_volume);
+    wined3d_resource_get_desc(wined3d_resource, &wined3d_desc);
+    wined3d_mutex_unlock();
+
+    desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format);
+    desc->Type = wined3d_desc.resource_type;
+    desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
+    desc->Pool = wined3d_desc.pool;
+    desc->Size = wined3d_desc.size;
+    desc->Width = wined3d_desc.width;
+    desc->Height = wined3d_desc.height;
+    desc->Depth = wined3d_desc.depth;
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d8_volume_LockBox(IDirect3DVolume8 *iface,
+        D3DLOCKED_BOX *locked_box, const D3DBOX *box, DWORD flags)
+{
+    struct d3d8_volume *volume = impl_from_IDirect3DVolume8(iface);
+    struct wined3d_map_desc map_desc;
+    HRESULT hr;
+
+    TRACE("iface %p, locked_box %p, box %p, flags %#x.\n",
+            iface, locked_box, box, flags);
+
+    wined3d_mutex_lock();
+    hr = wined3d_volume_map(volume->wined3d_volume, &map_desc, (const struct wined3d_box *)box, flags);
+    wined3d_mutex_unlock();
+
+    locked_box->RowPitch = map_desc.row_pitch;
+    locked_box->SlicePitch = map_desc.slice_pitch;
+    locked_box->pBits = map_desc.data;
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d8_volume_UnlockBox(IDirect3DVolume8 *iface)
+{
+    struct d3d8_volume *volume = impl_from_IDirect3DVolume8(iface);
+    HRESULT hr;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    hr = wined3d_volume_unmap(volume->wined3d_volume);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static const IDirect3DVolume8Vtbl d3d8_volume_vtbl =
+{
+    /* IUnknown */
+    d3d8_volume_QueryInterface,
+    d3d8_volume_AddRef,
+    d3d8_volume_Release,
+    /* IDirect3DVolume8 */
+    d3d8_volume_GetDevice,
+    d3d8_volume_SetPrivateData,
+    d3d8_volume_GetPrivateData,
+    d3d8_volume_FreePrivateData,
+    d3d8_volume_GetContainer,
+    d3d8_volume_GetDesc,
+    d3d8_volume_LockBox,
+    d3d8_volume_UnlockBox,
+};
+
+static void STDMETHODCALLTYPE volume_wined3d_object_destroyed(void *parent)
+{
+    HeapFree(GetProcessHeap(), 0, parent);
+}
+
+static const struct wined3d_parent_ops d3d8_volume_wined3d_parent_ops =
+{
+    volume_wined3d_object_destroyed,
+};
+
+HRESULT volume_init(struct d3d8_volume *volume, struct d3d8_device *device, UINT width, UINT height,
+        UINT depth, DWORD usage, enum wined3d_format_id format, enum wined3d_pool pool)
+{
+    HRESULT hr;
+
+    volume->IDirect3DVolume8_iface.lpVtbl = &d3d8_volume_vtbl;
+    volume->refcount = 1;
+
+    hr = wined3d_volume_create(device->wined3d_device, width, height, depth, usage,
+            format, pool, volume, &d3d8_volume_wined3d_parent_ops, &volume->wined3d_volume);
+    if (FAILED(hr))
+    {
+        WARN("Failed to create wined3d volume, hr %#x.\n", hr);
+        return hr;
+    }
+
+    return D3D_OK;
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/buffer.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/buffer.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/buffer.c	(revision 46521)
@@ -0,0 +1,610 @@
+/*
+ * Copyright 2002-2004 Jason Edmeades
+ * Copyright 2002-2004 Raphael Junqueira
+ * Copyright 2005 Oliver Stieber
+ *
+ * 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 "d3d9_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
+
+static inline struct d3d9_vertexbuffer *impl_from_IDirect3DVertexBuffer9(IDirect3DVertexBuffer9 *iface)
+{
+    return CONTAINING_RECORD(iface, struct d3d9_vertexbuffer, IDirect3DVertexBuffer9_iface);
+}
+
+static HRESULT WINAPI d3d9_vertexbuffer_QueryInterface(IDirect3DVertexBuffer9 *iface, REFIID riid, void **out)
+{
+    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
+
+    if (IsEqualGUID(riid, &IID_IDirect3DVertexBuffer9)
+            || IsEqualGUID(riid, &IID_IDirect3DResource9)
+            || IsEqualGUID(riid, &IID_IUnknown))
+    {
+        IDirect3DVertexBuffer9_AddRef(iface);
+        *out = iface;
+        return S_OK;
+    }
+
+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+    *out = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI d3d9_vertexbuffer_AddRef(IDirect3DVertexBuffer9 *iface)
+{
+    struct d3d9_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer9(iface);
+    ULONG refcount = InterlockedIncrement(&buffer->refcount);
+
+    TRACE("%p increasing refcount to %u.\n", iface, refcount);
+
+    if (refcount == 1)
+    {
+        IDirect3DDevice9Ex_AddRef(buffer->parent_device);
+        wined3d_mutex_lock();
+        wined3d_buffer_incref(buffer->wined3d_buffer);
+        wined3d_mutex_unlock();
+    }
+
+    return refcount;
+}
+
+static ULONG WINAPI d3d9_vertexbuffer_Release(IDirect3DVertexBuffer9 *iface)
+{
+    struct d3d9_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer9(iface);
+    ULONG refcount = InterlockedDecrement(&buffer->refcount);
+
+    TRACE("%p decreasing refcount to %u.\n", iface, refcount);
+
+    if (!refcount)
+    {
+        IDirect3DDevice9Ex *device = buffer->parent_device;
+
+        wined3d_mutex_lock();
+        wined3d_buffer_decref(buffer->wined3d_buffer);
+        wined3d_mutex_unlock();
+
+        /* Release the device last, as it may cause the device to be destroyed. */
+        IDirect3DDevice9Ex_Release(device);
+    }
+
+    return refcount;
+}
+
+static HRESULT WINAPI d3d9_vertexbuffer_GetDevice(IDirect3DVertexBuffer9 *iface, IDirect3DDevice9 **device)
+{
+    struct d3d9_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer9(iface);
+
+    TRACE("iface %p, device %p.\n", iface, device);
+
+    *device = (IDirect3DDevice9 *)buffer->parent_device;
+    IDirect3DDevice9_AddRef(*device);
+
+    TRACE("Returning device %p.\n", *device);
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_vertexbuffer_SetPrivateData(IDirect3DVertexBuffer9 *iface,
+        REFGUID guid, const void *data, DWORD data_size, DWORD flags)
+{
+    struct d3d9_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer9(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
+            iface, debugstr_guid(guid), data, data_size, flags);
+
+    wined3d_mutex_lock();
+    resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
+    hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_vertexbuffer_GetPrivateData(IDirect3DVertexBuffer9 *iface,
+        REFGUID guid, void *data, DWORD *data_size)
+{
+    struct d3d9_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer9(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s, data %p, data_size %p.\n",
+            iface, debugstr_guid(guid), data, data_size);
+
+    wined3d_mutex_lock();
+    resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
+    hr = wined3d_resource_get_private_data(resource, guid, data, data_size);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_vertexbuffer_FreePrivateData(IDirect3DVertexBuffer9 *iface, REFGUID guid)
+{
+    struct d3d9_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer9(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
+
+    wined3d_mutex_lock();
+    resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
+    hr = wined3d_resource_free_private_data(resource, guid);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static DWORD WINAPI d3d9_vertexbuffer_SetPriority(IDirect3DVertexBuffer9 *iface, DWORD priority)
+{
+    struct d3d9_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer9(iface);
+    DWORD previous;
+
+    TRACE("iface %p, priority %u.\n", iface, priority);
+
+    wined3d_mutex_lock();
+    previous = wined3d_buffer_set_priority(buffer->wined3d_buffer, priority);
+    wined3d_mutex_unlock();
+
+    return previous;
+}
+
+static DWORD WINAPI d3d9_vertexbuffer_GetPriority(IDirect3DVertexBuffer9 *iface)
+{
+    struct d3d9_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer9(iface);
+    DWORD priority;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    priority = wined3d_buffer_get_priority(buffer->wined3d_buffer);
+    wined3d_mutex_unlock();
+
+    return priority;
+}
+
+static void WINAPI d3d9_vertexbuffer_PreLoad(IDirect3DVertexBuffer9 *iface)
+{
+    struct d3d9_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer9(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    wined3d_buffer_preload(buffer->wined3d_buffer);
+    wined3d_mutex_unlock();
+}
+
+static D3DRESOURCETYPE WINAPI d3d9_vertexbuffer_GetType(IDirect3DVertexBuffer9 *iface)
+{
+    TRACE("iface %p.\n", iface);
+
+    return D3DRTYPE_VERTEXBUFFER;
+}
+
+static HRESULT WINAPI d3d9_vertexbuffer_Lock(IDirect3DVertexBuffer9 *iface, UINT offset, UINT size,
+        void **data, DWORD flags)
+{
+    struct d3d9_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer9(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, offset %u, size %u, data %p, flags %#x.\n",
+            iface, offset, size, data, flags);
+
+    wined3d_mutex_lock();
+    hr = wined3d_buffer_map(buffer->wined3d_buffer, offset, size, (BYTE **)data, flags);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_vertexbuffer_Unlock(IDirect3DVertexBuffer9 *iface)
+{
+    struct d3d9_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer9(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    wined3d_buffer_unmap(buffer->wined3d_buffer);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_vertexbuffer_GetDesc(IDirect3DVertexBuffer9 *iface,
+        D3DVERTEXBUFFER_DESC *desc)
+{
+    struct d3d9_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer9(iface);
+    struct wined3d_resource_desc wined3d_desc;
+    struct wined3d_resource *wined3d_resource;
+
+    TRACE("iface %p, desc %p.\n", iface, desc);
+
+    wined3d_mutex_lock();
+    wined3d_resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
+    wined3d_resource_get_desc(wined3d_resource, &wined3d_desc);
+    wined3d_mutex_unlock();
+
+    desc->Format = D3DFMT_VERTEXDATA;
+    desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
+    desc->Pool = wined3d_desc.pool;
+    desc->Size = wined3d_desc.size;
+    desc->Type = D3DRTYPE_VERTEXBUFFER;
+    desc->FVF = buffer->fvf;
+
+    return D3D_OK;
+}
+
+static const IDirect3DVertexBuffer9Vtbl d3d9_vertexbuffer_vtbl =
+{
+    /* IUnknown */
+    d3d9_vertexbuffer_QueryInterface,
+    d3d9_vertexbuffer_AddRef,
+    d3d9_vertexbuffer_Release,
+    /* IDirect3DResource9 */
+    d3d9_vertexbuffer_GetDevice,
+    d3d9_vertexbuffer_SetPrivateData,
+    d3d9_vertexbuffer_GetPrivateData,
+    d3d9_vertexbuffer_FreePrivateData,
+    d3d9_vertexbuffer_SetPriority,
+    d3d9_vertexbuffer_GetPriority,
+    d3d9_vertexbuffer_PreLoad,
+    d3d9_vertexbuffer_GetType,
+    /* IDirect3DVertexBuffer9 */
+    d3d9_vertexbuffer_Lock,
+    d3d9_vertexbuffer_Unlock,
+    d3d9_vertexbuffer_GetDesc,
+};
+
+static void STDMETHODCALLTYPE d3d9_vertexbuffer_wined3d_object_destroyed(void *parent)
+{
+    HeapFree(GetProcessHeap(), 0, parent);
+}
+
+static const struct wined3d_parent_ops d3d9_vertexbuffer_wined3d_parent_ops =
+{
+    d3d9_vertexbuffer_wined3d_object_destroyed,
+};
+
+HRESULT vertexbuffer_init(struct d3d9_vertexbuffer *buffer, struct d3d9_device *device,
+        UINT size, UINT usage, DWORD fvf, D3DPOOL pool)
+{
+    HRESULT hr;
+
+    buffer->IDirect3DVertexBuffer9_iface.lpVtbl = &d3d9_vertexbuffer_vtbl;
+    buffer->refcount = 1;
+    buffer->fvf = fvf;
+
+    wined3d_mutex_lock();
+    hr = wined3d_buffer_create_vb(device->wined3d_device, size, usage & WINED3DUSAGE_MASK,
+            (enum wined3d_pool)pool, buffer, &d3d9_vertexbuffer_wined3d_parent_ops, &buffer->wined3d_buffer);
+    wined3d_mutex_unlock();
+    if (FAILED(hr))
+    {
+        WARN("Failed to create wined3d buffer, hr %#x.\n", hr);
+        return hr;
+    }
+
+    buffer->parent_device = &device->IDirect3DDevice9Ex_iface;
+    IDirect3DDevice9Ex_AddRef(buffer->parent_device);
+
+    return D3D_OK;
+}
+
+struct d3d9_vertexbuffer *unsafe_impl_from_IDirect3DVertexBuffer9(IDirect3DVertexBuffer9 *iface)
+{
+    if (!iface)
+        return NULL;
+    assert(iface->lpVtbl == &d3d9_vertexbuffer_vtbl);
+
+    return impl_from_IDirect3DVertexBuffer9(iface);
+}
+
+static inline struct d3d9_indexbuffer *impl_from_IDirect3DIndexBuffer9(IDirect3DIndexBuffer9 *iface)
+{
+    return CONTAINING_RECORD(iface, struct d3d9_indexbuffer, IDirect3DIndexBuffer9_iface);
+}
+
+static HRESULT WINAPI d3d9_indexbuffer_QueryInterface(IDirect3DIndexBuffer9 *iface, REFIID riid, void **out)
+{
+    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
+
+    if (IsEqualGUID(riid, &IID_IDirect3DIndexBuffer9)
+            || IsEqualGUID(riid, &IID_IDirect3DResource9)
+            || IsEqualGUID(riid, &IID_IUnknown))
+    {
+        IDirect3DIndexBuffer9_AddRef(iface);
+        *out = iface;
+        return S_OK;
+    }
+
+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+    *out = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI d3d9_indexbuffer_AddRef(IDirect3DIndexBuffer9 *iface)
+{
+    struct d3d9_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer9(iface);
+    ULONG refcount = InterlockedIncrement(&buffer->refcount);
+
+    TRACE("%p increasing refcount to %u.\n", iface, refcount);
+
+    if (refcount == 1)
+    {
+        IDirect3DDevice9Ex_AddRef(buffer->parent_device);
+        wined3d_mutex_lock();
+        wined3d_buffer_incref(buffer->wined3d_buffer);
+        wined3d_mutex_unlock();
+    }
+
+    return refcount;
+}
+
+static ULONG WINAPI d3d9_indexbuffer_Release(IDirect3DIndexBuffer9 *iface)
+{
+    struct d3d9_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer9(iface);
+    ULONG refcount = InterlockedDecrement(&buffer->refcount);
+
+    TRACE("%p decreasing refcount to %u.\n", iface, refcount);
+
+    if (!refcount)
+    {
+        IDirect3DDevice9Ex *device = buffer->parent_device;
+
+        wined3d_mutex_lock();
+        wined3d_buffer_decref(buffer->wined3d_buffer);
+        wined3d_mutex_unlock();
+
+        /* Release the device last, as it may cause the device to be destroyed. */
+        IDirect3DDevice9Ex_Release(device);
+    }
+
+    return refcount;
+}
+
+static HRESULT WINAPI d3d9_indexbuffer_GetDevice(IDirect3DIndexBuffer9 *iface, IDirect3DDevice9 **device)
+{
+    struct d3d9_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer9(iface);
+
+    TRACE("iface %p, device %p.\n", iface, device);
+
+    *device = (IDirect3DDevice9 *)buffer->parent_device;
+    IDirect3DDevice9_AddRef(*device);
+
+    TRACE("Returning device %p.\n", *device);
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_indexbuffer_SetPrivateData(IDirect3DIndexBuffer9 *iface,
+        REFGUID guid, const void *data, DWORD data_size, DWORD flags)
+{
+    struct d3d9_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer9(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
+            iface, debugstr_guid(guid), data, data_size, flags);
+
+    wined3d_mutex_lock();
+    resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
+    hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_indexbuffer_GetPrivateData(IDirect3DIndexBuffer9 *iface,
+        REFGUID guid, void *data, DWORD *data_size)
+{
+    struct d3d9_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer9(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s, data %p, data_size %p.\n",
+            iface, debugstr_guid(guid), data, data_size);
+
+    wined3d_mutex_lock();
+    resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
+    hr = wined3d_resource_get_private_data(resource, guid, data, data_size);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_indexbuffer_FreePrivateData(IDirect3DIndexBuffer9 *iface, REFGUID guid)
+{
+    struct d3d9_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer9(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
+
+    wined3d_mutex_lock();
+    resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
+    hr = wined3d_resource_free_private_data(resource, guid);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static DWORD WINAPI d3d9_indexbuffer_SetPriority(IDirect3DIndexBuffer9 *iface, DWORD priority)
+{
+    struct d3d9_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer9(iface);
+    DWORD previous;
+
+    TRACE("iface %p, priority %u.\n", iface, priority);
+
+    wined3d_mutex_lock();
+    previous = wined3d_buffer_set_priority(buffer->wined3d_buffer, priority);
+    wined3d_mutex_unlock();
+
+    return previous;
+}
+
+static DWORD WINAPI d3d9_indexbuffer_GetPriority(IDirect3DIndexBuffer9 *iface)
+{
+    struct d3d9_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer9(iface);
+    DWORD priority;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    priority = wined3d_buffer_get_priority(buffer->wined3d_buffer);
+    wined3d_mutex_unlock();
+
+    return priority;
+}
+
+static void WINAPI d3d9_indexbuffer_PreLoad(IDirect3DIndexBuffer9 *iface)
+{
+    struct d3d9_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer9(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    wined3d_buffer_preload(buffer->wined3d_buffer);
+    wined3d_mutex_unlock();
+}
+
+static D3DRESOURCETYPE WINAPI d3d9_indexbuffer_GetType(IDirect3DIndexBuffer9 *iface)
+{
+    TRACE("iface %p.\n", iface);
+
+    return D3DRTYPE_INDEXBUFFER;
+}
+
+static HRESULT WINAPI d3d9_indexbuffer_Lock(IDirect3DIndexBuffer9 *iface,
+        UINT offset, UINT size, void **data, DWORD flags)
+{
+    struct d3d9_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer9(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, offset %u, size %u, data %p, flags %#x.\n",
+            iface, offset, size, data, flags);
+
+    wined3d_mutex_lock();
+    hr = wined3d_buffer_map(buffer->wined3d_buffer, offset, size, (BYTE **)data, flags);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_indexbuffer_Unlock(IDirect3DIndexBuffer9 *iface)
+{
+    struct d3d9_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer9(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    wined3d_buffer_unmap(buffer->wined3d_buffer);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_indexbuffer_GetDesc(IDirect3DIndexBuffer9 *iface, D3DINDEXBUFFER_DESC *desc)
+{
+    struct d3d9_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer9(iface);
+    struct wined3d_resource_desc wined3d_desc;
+    struct wined3d_resource *wined3d_resource;
+
+    TRACE("iface %p, desc %p.\n", iface, desc);
+
+    wined3d_mutex_lock();
+    wined3d_resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
+    wined3d_resource_get_desc(wined3d_resource, &wined3d_desc);
+    wined3d_mutex_unlock();
+
+    desc->Format = d3dformat_from_wined3dformat(buffer->format);
+    desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
+    desc->Pool = wined3d_desc.pool;
+    desc->Size = wined3d_desc.size;
+    desc->Type = D3DRTYPE_INDEXBUFFER;
+
+    return D3D_OK;
+}
+
+static const IDirect3DIndexBuffer9Vtbl d3d9_indexbuffer_vtbl =
+{
+    /* IUnknown */
+    d3d9_indexbuffer_QueryInterface,
+    d3d9_indexbuffer_AddRef,
+    d3d9_indexbuffer_Release,
+    /* IDirect3DResource9 */
+    d3d9_indexbuffer_GetDevice,
+    d3d9_indexbuffer_SetPrivateData,
+    d3d9_indexbuffer_GetPrivateData,
+    d3d9_indexbuffer_FreePrivateData,
+    d3d9_indexbuffer_SetPriority,
+    d3d9_indexbuffer_GetPriority,
+    d3d9_indexbuffer_PreLoad,
+    d3d9_indexbuffer_GetType,
+    /* IDirect3DIndexBuffer9 */
+    d3d9_indexbuffer_Lock,
+    d3d9_indexbuffer_Unlock,
+    d3d9_indexbuffer_GetDesc,
+};
+
+static void STDMETHODCALLTYPE d3d9_indexbuffer_wined3d_object_destroyed(void *parent)
+{
+    HeapFree(GetProcessHeap(), 0, parent);
+}
+
+static const struct wined3d_parent_ops d3d9_indexbuffer_wined3d_parent_ops =
+{
+    d3d9_indexbuffer_wined3d_object_destroyed,
+};
+
+HRESULT indexbuffer_init(struct d3d9_indexbuffer *buffer, struct d3d9_device *device,
+        UINT size, DWORD usage, D3DFORMAT format, D3DPOOL pool)
+{
+    HRESULT hr;
+
+    buffer->IDirect3DIndexBuffer9_iface.lpVtbl = &d3d9_indexbuffer_vtbl;
+    buffer->refcount = 1;
+    buffer->format = wined3dformat_from_d3dformat(format);
+
+    wined3d_mutex_lock();
+    hr = wined3d_buffer_create_ib(device->wined3d_device, size, usage & WINED3DUSAGE_MASK,
+            (enum wined3d_pool)pool, buffer, &d3d9_indexbuffer_wined3d_parent_ops, &buffer->wined3d_buffer);
+    wined3d_mutex_unlock();
+    if (FAILED(hr))
+    {
+        WARN("Failed to create wined3d buffer, hr %#x.\n", hr);
+        return hr;
+    }
+
+    buffer->parent_device = &device->IDirect3DDevice9Ex_iface;
+    IDirect3DDevice9Ex_AddRef(buffer->parent_device);
+
+    return D3D_OK;
+}
+
+struct d3d9_indexbuffer *unsafe_impl_from_IDirect3DIndexBuffer9(IDirect3DIndexBuffer9 *iface)
+{
+    if (!iface)
+        return NULL;
+    assert(iface->lpVtbl == &d3d9_indexbuffer_vtbl);
+
+    return impl_from_IDirect3DIndexBuffer9(iface);
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/d3d9_main.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/d3d9_main.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/d3d9_main.c	(revision 46521)
@@ -0,0 +1,170 @@
+/*
+ * Direct3D 9
+ *
+ * Copyright 2002-2003 Jason Edmeades
+ * Copyright 2002-2003 Raphael Junqueira
+ * Copyright 2005 Oliver Stieber
+ *
+ * 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 "d3d9_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
+
+static int D3DPERF_event_level = 0;
+
+void WINAPI DebugSetMute(void) {
+    /* nothing to do */
+}
+
+IDirect3D9 * WINAPI DECLSPEC_HOTPATCH Direct3DCreate9(UINT sdk_version)
+{
+    struct d3d9 *object;
+
+    TRACE("sdk_version %#x.\n", sdk_version);
+
+    if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
+        return NULL;
+
+    if (!d3d9_init(object, FALSE))
+    {
+        WARN("Failed to initialize d3d9.\n");
+        HeapFree(GetProcessHeap(), 0, object);
+        return NULL;
+    }
+
+    TRACE("Created d3d9 object %p.\n", object);
+
+    return (IDirect3D9 *)&object->IDirect3D9Ex_iface;
+}
+
+HRESULT WINAPI DECLSPEC_HOTPATCH Direct3DCreate9Ex(UINT sdk_version, IDirect3D9Ex **d3d9ex)
+{
+#if defined(VBOX_WITH_WINE_FIX_NO9EX) && !defined(VBOX_WITH_WDDM)
+    /* real D3D lib does not allow 9Ex creation if no WDDM driver is installed,
+     * the Direct3DCreate9Ex should return D3DERR_NOTAVAILABLE in that case.
+     * do it that way for our XPDM case */
+    return D3DERR_NOTAVAILABLE;
+#else
+    struct d3d9 *object;
+
+    TRACE("sdk_version %#x, d3d9ex %p.\n", sdk_version, d3d9ex);
+
+    if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
+        return E_OUTOFMEMORY;
+
+    if (!d3d9_init(object, TRUE))
+    {
+        WARN("Failed to initialize d3d9.\n");
+        HeapFree(GetProcessHeap(), 0, object);
+        return D3DERR_NOTAVAILABLE;
+    }
+
+    TRACE("Created d3d9 object %p.\n", object);
+    *d3d9ex = &object->IDirect3D9Ex_iface;
+
+    return D3D_OK;
+#endif
+}
+
+/*******************************************************************
+ *       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 hInstDLL, DWORD fdwReason, LPVOID lpv)
+{
+    /* At process attach */
+    TRACE("fdwReason=%d\n", fdwReason);
+    if (fdwReason == DLL_PROCESS_ATTACH)
+        DisableThreadLibraryCalls(hInstDLL);
+
+    return TRUE;
+}
+
+/***********************************************************************
+ *              D3DPERF_BeginEvent (D3D9.@)
+ */
+int WINAPI D3DPERF_BeginEvent(D3DCOLOR color, LPCWSTR name) {
+    TRACE("(color %#x, name %s) : stub\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, LPCWSTR name) {
+    FIXME("(color %#x, name %s) : stub\n", color, debugstr_w(name));
+}
+
+/***********************************************************************
+ *              D3DPERF_SetRegion (D3D9.@)
+ */
+void WINAPI D3DPERF_SetRegion(D3DCOLOR color, LPCWSTR name) {
+    FIXME("(color %#x, name %s) : stub\n", color, debugstr_w(name));
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/d3d9_private.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/d3d9_private.h	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/d3d9_private.h	(revision 46521)
@@ -0,0 +1,352 @@
+/*
+ * Direct3D 9 private include file
+ *
+ * Copyright 2002-2003 Jason Edmeades
+ * Copyright 2002-2003 Raphael Junqueira
+ * Copyright 2005 Oliver Stieber
+ *
+ * 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_D3D9_PRIVATE_H
+#define __WINE_D3D9_PRIVATE_H
+
+#include <assert.h>
+#include <stdarg.h>
+
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+#define COBJMACROS
+#ifndef VBOX_WINE_WITHOUT_LIBWINE
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#else
+#include <windows.h>
+#endif
+#include "wine/debug.h"
+#include "wine/unicode.h"
+
+#include "d3d9.h"
+#include "wine/wined3d.h"
+
+extern HRESULT vdecl_convert_fvf(DWORD FVF, D3DVERTEXELEMENT9 **ppVertexElements) DECLSPEC_HIDDEN;
+D3DFORMAT d3dformat_from_wined3dformat(enum wined3d_format_id format) DECLSPEC_HIDDEN;
+enum wined3d_format_id wined3dformat_from_d3dformat(D3DFORMAT format) DECLSPEC_HIDDEN;
+void present_parameters_from_wined3d_swapchain_desc(D3DPRESENT_PARAMETERS *present_parameters,
+        const struct wined3d_swapchain_desc *swapchain_desc) DECLSPEC_HIDDEN;
+
+#define WINECAPSTOD3D9CAPS(_pD3D9Caps, _pWineCaps) \
+    _pD3D9Caps->DeviceType                        = (D3DDEVTYPE) _pWineCaps->DeviceType; \
+    _pD3D9Caps->AdapterOrdinal                    = _pWineCaps->AdapterOrdinal; \
+    _pD3D9Caps->Caps                              = _pWineCaps->Caps; \
+    _pD3D9Caps->Caps2                             = _pWineCaps->Caps2; \
+    _pD3D9Caps->Caps3                             = _pWineCaps->Caps3; \
+    _pD3D9Caps->PresentationIntervals             = _pWineCaps->PresentationIntervals; \
+    _pD3D9Caps->CursorCaps                        = _pWineCaps->CursorCaps; \
+    _pD3D9Caps->DevCaps                           = _pWineCaps->DevCaps; \
+    _pD3D9Caps->PrimitiveMiscCaps                 = _pWineCaps->PrimitiveMiscCaps; \
+    _pD3D9Caps->RasterCaps                        = _pWineCaps->RasterCaps; \
+    _pD3D9Caps->ZCmpCaps                          = _pWineCaps->ZCmpCaps; \
+    _pD3D9Caps->SrcBlendCaps                      = _pWineCaps->SrcBlendCaps; \
+    _pD3D9Caps->DestBlendCaps                     = _pWineCaps->DestBlendCaps; \
+    _pD3D9Caps->AlphaCmpCaps                      = _pWineCaps->AlphaCmpCaps; \
+    _pD3D9Caps->ShadeCaps                         = _pWineCaps->ShadeCaps; \
+    _pD3D9Caps->TextureCaps                       = _pWineCaps->TextureCaps; \
+    _pD3D9Caps->TextureFilterCaps                 = _pWineCaps->TextureFilterCaps; \
+    _pD3D9Caps->CubeTextureFilterCaps             = _pWineCaps->CubeTextureFilterCaps; \
+    _pD3D9Caps->VolumeTextureFilterCaps           = _pWineCaps->VolumeTextureFilterCaps; \
+    _pD3D9Caps->TextureAddressCaps                = _pWineCaps->TextureAddressCaps; \
+    _pD3D9Caps->VolumeTextureAddressCaps          = _pWineCaps->VolumeTextureAddressCaps; \
+    _pD3D9Caps->LineCaps                          = _pWineCaps->LineCaps; \
+    _pD3D9Caps->MaxTextureWidth                   = _pWineCaps->MaxTextureWidth; \
+    _pD3D9Caps->MaxTextureHeight                  = _pWineCaps->MaxTextureHeight; \
+    _pD3D9Caps->MaxVolumeExtent                   = _pWineCaps->MaxVolumeExtent; \
+    _pD3D9Caps->MaxTextureRepeat                  = _pWineCaps->MaxTextureRepeat; \
+    _pD3D9Caps->MaxTextureAspectRatio             = _pWineCaps->MaxTextureAspectRatio; \
+    _pD3D9Caps->MaxAnisotropy                     = _pWineCaps->MaxAnisotropy; \
+    _pD3D9Caps->MaxVertexW                        = _pWineCaps->MaxVertexW; \
+    _pD3D9Caps->GuardBandLeft                     = _pWineCaps->GuardBandLeft; \
+    _pD3D9Caps->GuardBandTop                      = _pWineCaps->GuardBandTop; \
+    _pD3D9Caps->GuardBandRight                    = _pWineCaps->GuardBandRight; \
+    _pD3D9Caps->GuardBandBottom                   = _pWineCaps->GuardBandBottom; \
+    _pD3D9Caps->ExtentsAdjust                     = _pWineCaps->ExtentsAdjust; \
+    _pD3D9Caps->StencilCaps                       = _pWineCaps->StencilCaps; \
+    _pD3D9Caps->FVFCaps                           = _pWineCaps->FVFCaps; \
+    _pD3D9Caps->TextureOpCaps                     = _pWineCaps->TextureOpCaps; \
+    _pD3D9Caps->MaxTextureBlendStages             = _pWineCaps->MaxTextureBlendStages; \
+    _pD3D9Caps->MaxSimultaneousTextures           = _pWineCaps->MaxSimultaneousTextures; \
+    _pD3D9Caps->VertexProcessingCaps              = _pWineCaps->VertexProcessingCaps; \
+    _pD3D9Caps->MaxActiveLights                   = _pWineCaps->MaxActiveLights; \
+    _pD3D9Caps->MaxUserClipPlanes                 = _pWineCaps->MaxUserClipPlanes; \
+    _pD3D9Caps->MaxVertexBlendMatrices            = _pWineCaps->MaxVertexBlendMatrices; \
+    _pD3D9Caps->MaxVertexBlendMatrixIndex         = _pWineCaps->MaxVertexBlendMatrixIndex; \
+    _pD3D9Caps->MaxPointSize                      = _pWineCaps->MaxPointSize; \
+    _pD3D9Caps->MaxPrimitiveCount                 = _pWineCaps->MaxPrimitiveCount; \
+    _pD3D9Caps->MaxVertexIndex                    = _pWineCaps->MaxVertexIndex; \
+    _pD3D9Caps->MaxStreams                        = _pWineCaps->MaxStreams; \
+    _pD3D9Caps->MaxStreamStride                   = _pWineCaps->MaxStreamStride; \
+    _pD3D9Caps->VertexShaderVersion               = _pWineCaps->VertexShaderVersion; \
+    _pD3D9Caps->MaxVertexShaderConst              = _pWineCaps->MaxVertexShaderConst; \
+    _pD3D9Caps->PixelShaderVersion                = _pWineCaps->PixelShaderVersion; \
+    _pD3D9Caps->PixelShader1xMaxValue             = _pWineCaps->PixelShader1xMaxValue; \
+    _pD3D9Caps->DevCaps2                          = _pWineCaps->DevCaps2; \
+    _pD3D9Caps->MaxNpatchTessellationLevel        = _pWineCaps->MaxNpatchTessellationLevel; \
+    _pD3D9Caps->MasterAdapterOrdinal              = _pWineCaps->MasterAdapterOrdinal; \
+    _pD3D9Caps->AdapterOrdinalInGroup             = _pWineCaps->AdapterOrdinalInGroup; \
+    _pD3D9Caps->NumberOfAdaptersInGroup           = _pWineCaps->NumberOfAdaptersInGroup; \
+    _pD3D9Caps->DeclTypes                         = _pWineCaps->DeclTypes; \
+    _pD3D9Caps->NumSimultaneousRTs                = _pWineCaps->NumSimultaneousRTs; \
+    _pD3D9Caps->StretchRectFilterCaps             = _pWineCaps->StretchRectFilterCaps; \
+    _pD3D9Caps->VS20Caps.Caps                     = _pWineCaps->VS20Caps.caps; \
+    _pD3D9Caps->VS20Caps.DynamicFlowControlDepth  = _pWineCaps->VS20Caps.dynamic_flow_control_depth; \
+    _pD3D9Caps->VS20Caps.NumTemps                 = _pWineCaps->VS20Caps.temp_count; \
+    _pD3D9Caps->VS20Caps.StaticFlowControlDepth   = _pWineCaps->VS20Caps.static_flow_control_depth; \
+    _pD3D9Caps->PS20Caps.Caps                     = _pWineCaps->PS20Caps.caps; \
+    _pD3D9Caps->PS20Caps.DynamicFlowControlDepth  = _pWineCaps->PS20Caps.dynamic_flow_control_depth; \
+    _pD3D9Caps->PS20Caps.NumTemps                 = _pWineCaps->PS20Caps.temp_count; \
+    _pD3D9Caps->PS20Caps.StaticFlowControlDepth   = _pWineCaps->PS20Caps.static_flow_control_depth; \
+    _pD3D9Caps->PS20Caps.NumInstructionSlots      = _pWineCaps->PS20Caps.instruction_slot_count; \
+    _pD3D9Caps->VertexTextureFilterCaps           = _pWineCaps->VertexTextureFilterCaps; \
+    _pD3D9Caps->MaxVShaderInstructionsExecuted    = _pWineCaps->MaxVShaderInstructionsExecuted; \
+    _pD3D9Caps->MaxPShaderInstructionsExecuted    = _pWineCaps->MaxPShaderInstructionsExecuted; \
+    _pD3D9Caps->MaxVertexShader30InstructionSlots = _pWineCaps->MaxVertexShader30InstructionSlots; \
+    _pD3D9Caps->MaxPixelShader30InstructionSlots  = _pWineCaps->MaxPixelShader30InstructionSlots;
+
+struct d3d9
+{
+    IDirect3D9Ex IDirect3D9Ex_iface;
+    LONG refcount;
+    struct wined3d *wined3d;
+    BOOL extended;
+};
+
+BOOL d3d9_init(struct d3d9 *d3d9, BOOL extended) DECLSPEC_HIDDEN;
+void filter_caps(D3DCAPS9* pCaps) DECLSPEC_HIDDEN;
+
+struct fvf_declaration
+{
+    struct wined3d_vertex_declaration *decl;
+    DWORD fvf;
+};
+
+struct d3d9_device
+{
+    IDirect3DDevice9Ex IDirect3DDevice9Ex_iface;
+    struct wined3d_device_parent device_parent;
+    LONG refcount;
+    struct wined3d_device *wined3d_device;
+    struct d3d9 *d3d_parent;
+
+    struct fvf_declaration *fvf_decls;
+    UINT fvf_decl_count, fvf_decl_size;
+
+    struct wined3d_buffer *vertex_buffer;
+    UINT vertex_buffer_size;
+    UINT vertex_buffer_pos;
+    struct wined3d_buffer *index_buffer;
+    UINT index_buffer_size;
+    UINT index_buffer_pos;
+
+    BOOL in_destruction;
+    BOOL not_reset;
+    BOOL in_scene;
+};
+
+HRESULT device_init(struct d3d9_device *device, struct d3d9 *parent, struct wined3d *wined3d,
+        UINT adapter, D3DDEVTYPE device_type, HWND focus_window, DWORD flags
+#ifdef VBOX_WITH_WDDM
+        , VBOXWINEEX_D3DPRESENT_PARAMETERS *parameters
+#else
+        , D3DPRESENT_PARAMETERS *parameters
+#endif
+        , D3DDISPLAYMODEEX *mode) DECLSPEC_HIDDEN;
+
+struct d3d9_volume
+{
+    IDirect3DVolume9 IDirect3DVolume9_iface;
+    LONG refcount;
+    struct wined3d_volume *wined3d_volume;
+    IUnknown *container;
+    IUnknown *forwardReference;
+};
+
+HRESULT volume_init(struct d3d9_volume *volume, struct d3d9_device *device, UINT width, UINT height,
+        UINT depth, DWORD usage, enum wined3d_format_id format, enum wined3d_pool pool
+#ifdef VBOX_WITH_WDDM
+        , HANDLE *shared_handle
+        , void *pvClientMem
+#endif
+        ) DECLSPEC_HIDDEN;
+
+struct d3d9_swapchain
+{
+    IDirect3DSwapChain9 IDirect3DSwapChain9_iface;
+    LONG refcount;
+    struct wined3d_swapchain *wined3d_swapchain;
+    IDirect3DDevice9Ex *parent_device;
+};
+
+HRESULT d3d9_swapchain_create(struct d3d9_device *device, struct wined3d_swapchain_desc *desc,
+        struct d3d9_swapchain **swapchain) DECLSPEC_HIDDEN;
+
+struct d3d9_surface
+{
+    IDirect3DSurface9 IDirect3DSurface9_iface;
+    LONG refcount;
+    struct wined3d_surface *wined3d_surface;
+    IDirect3DDevice9Ex *parent_device;
+    IUnknown *container;
+    IUnknown *forwardReference;
+    BOOL getdc_supported;
+};
+
+HRESULT surface_init(struct d3d9_surface *surface, struct d3d9_device *device, UINT width, UINT height,
+        D3DFORMAT format, DWORD flags, DWORD usage, D3DPOOL pool, D3DMULTISAMPLE_TYPE multisample_type,
+        DWORD multisample_quality
+#ifdef VBOX_WITH_WDDM
+        , HANDLE *shared_handle
+        , void *pvClientMem
+#endif
+        ) DECLSPEC_HIDDEN;
+struct d3d9_surface *unsafe_impl_from_IDirect3DSurface9(IDirect3DSurface9 *iface) DECLSPEC_HIDDEN;
+
+struct d3d9_vertexbuffer
+{
+    IDirect3DVertexBuffer9 IDirect3DVertexBuffer9_iface;
+    LONG refcount;
+    struct wined3d_buffer *wined3d_buffer;
+    IDirect3DDevice9Ex *parent_device;
+    DWORD fvf;
+};
+
+HRESULT vertexbuffer_init(struct d3d9_vertexbuffer *buffer, struct d3d9_device *device,
+        UINT size, UINT usage, DWORD fvf, D3DPOOL pool) DECLSPEC_HIDDEN;
+struct d3d9_vertexbuffer *unsafe_impl_from_IDirect3DVertexBuffer9(IDirect3DVertexBuffer9 *iface) DECLSPEC_HIDDEN;
+
+struct d3d9_indexbuffer
+{
+    IDirect3DIndexBuffer9 IDirect3DIndexBuffer9_iface;
+    LONG refcount;
+    struct wined3d_buffer *wined3d_buffer;
+    IDirect3DDevice9Ex *parent_device;
+    enum wined3d_format_id format;
+};
+
+HRESULT indexbuffer_init(struct d3d9_indexbuffer *buffer, struct d3d9_device *device,
+        UINT size, DWORD usage, D3DFORMAT format, D3DPOOL pool) DECLSPEC_HIDDEN;
+struct d3d9_indexbuffer *unsafe_impl_from_IDirect3DIndexBuffer9(IDirect3DIndexBuffer9 *iface) DECLSPEC_HIDDEN;
+
+struct d3d9_texture
+{
+    IDirect3DBaseTexture9 IDirect3DBaseTexture9_iface;
+    LONG refcount;
+    struct wined3d_texture *wined3d_texture;
+    IDirect3DDevice9Ex *parent_device;
+};
+
+HRESULT cubetexture_init(struct d3d9_texture *texture, struct d3d9_device *device,
+        UINT edge_length, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool
+#ifdef VBOX_WITH_WDDM
+        , HANDLE *shared_handle
+        , void **pavClientMem
+#endif
+        ) DECLSPEC_HIDDEN;
+HRESULT texture_init(struct d3d9_texture *texture, struct d3d9_device *device,
+        UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool
+#ifdef VBOX_WITH_WDDM
+        , HANDLE *shared_handle
+        , void **pavClientMem
+#endif
+        ) DECLSPEC_HIDDEN;
+HRESULT volumetexture_init(struct d3d9_texture *texture, struct d3d9_device *device,
+        UINT width, UINT height, UINT depth, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool
+#ifdef VBOX_WITH_WDDM
+        , HANDLE *shared_handle
+        , void **pavClientMem
+#endif
+        ) DECLSPEC_HIDDEN;
+struct d3d9_texture *unsafe_impl_from_IDirect3DBaseTexture9(IDirect3DBaseTexture9 *iface) DECLSPEC_HIDDEN;
+
+struct d3d9_stateblock
+{
+    IDirect3DStateBlock9 IDirect3DStateBlock9_iface;
+    LONG refcount;
+    struct wined3d_stateblock *wined3d_stateblock;
+    IDirect3DDevice9Ex *parent_device;
+};
+
+HRESULT stateblock_init(struct d3d9_stateblock *stateblock, struct d3d9_device *device,
+        D3DSTATEBLOCKTYPE type, struct wined3d_stateblock *wined3d_stateblock) DECLSPEC_HIDDEN;
+
+struct d3d9_vertex_declaration
+{
+    IDirect3DVertexDeclaration9 IDirect3DVertexDeclaration9_iface;
+    LONG refcount;
+    D3DVERTEXELEMENT9 *elements;
+    UINT element_count;
+    struct wined3d_vertex_declaration *wined3d_declaration;
+    DWORD fvf;
+    IDirect3DDevice9Ex *parent_device;
+};
+
+HRESULT d3d9_vertex_declaration_create(struct d3d9_device *device,
+        const D3DVERTEXELEMENT9 *elements, struct d3d9_vertex_declaration **declaration) DECLSPEC_HIDDEN;
+struct d3d9_vertex_declaration *unsafe_impl_from_IDirect3DVertexDeclaration9(
+        IDirect3DVertexDeclaration9 *iface) DECLSPEC_HIDDEN;
+
+struct d3d9_vertexshader
+{
+    IDirect3DVertexShader9 IDirect3DVertexShader9_iface;
+    LONG refcount;
+    struct wined3d_shader *wined3d_shader;
+    IDirect3DDevice9Ex *parent_device;
+};
+
+HRESULT vertexshader_init(struct d3d9_vertexshader *shader,
+        struct d3d9_device *device, const DWORD *byte_code) DECLSPEC_HIDDEN;
+struct d3d9_vertexshader *unsafe_impl_from_IDirect3DVertexShader9(IDirect3DVertexShader9 *iface) DECLSPEC_HIDDEN;
+
+#define D3D9_MAX_VERTEX_SHADER_CONSTANTF 256
+#define D3D9_MAX_SIMULTANEOUS_RENDERTARGETS 4
+
+struct d3d9_pixelshader
+{
+    IDirect3DPixelShader9 IDirect3DPixelShader9_iface;
+    LONG refcount;
+    struct wined3d_shader *wined3d_shader;
+    IDirect3DDevice9Ex *parent_device;
+};
+
+HRESULT pixelshader_init(struct d3d9_pixelshader *shader,
+        struct d3d9_device *device, const DWORD *byte_code) DECLSPEC_HIDDEN;
+struct d3d9_pixelshader *unsafe_impl_from_IDirect3DPixelShader9(IDirect3DPixelShader9 *iface) DECLSPEC_HIDDEN;
+
+struct d3d9_query
+{
+    IDirect3DQuery9 IDirect3DQuery9_iface;
+    LONG refcount;
+    struct wined3d_query *wined3d_query;
+    IDirect3DDevice9Ex *parent_device;
+};
+
+HRESULT query_init(struct d3d9_query *query, struct d3d9_device *device, D3DQUERYTYPE type) DECLSPEC_HIDDEN;
+
+#ifdef VBOX_WITH_WDDM
+struct d3d9_volume *unsafe_impl_from_IDirect3DVolume9(IDirect3DVolume9 *iface) DECLSPEC_HIDDEN;
+#endif
+
+#endif /* __WINE_D3D9_PRIVATE_H */
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/d3d9wddm.def
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/d3d9wddm.def	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/d3d9wddm.def	(revision 46521)
@@ -0,0 +1,23 @@
+
+EXPORTS
+  Direct3DShaderValidatorCreate9
+  D3DPERF_BeginEvent
+  D3DPERF_EndEvent
+  D3DPERF_GetStatus
+  D3DPERF_QueryRepeatFrame
+  D3DPERF_SetMarker
+  D3DPERF_SetOptions
+  D3DPERF_SetRegion
+  DebugSetMute
+  Direct3DCreate9
+  Direct3DCreate9Ex
+  VBoxWineExD3DDev9Flush
+  VBoxWineExD3DDev9FlushToHost
+  VBoxWineExD3DDev9Finish
+  VBoxWineExD3DDev9CreateTexture
+  VBoxWineExD3DDev9CreateCubeTexture
+  VBoxWineExD3DDev9CreateVolumeTexture
+  VBoxWineExD3DDev9Term
+  VBoxWineExD3DSwapchain9Present
+  VBoxWineExD3DDev9VolBlt
+  VBoxWineExD3DDev9VolTexBlt
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/d3d9xpdm.def
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/d3d9xpdm.def	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/d3d9xpdm.def	(revision 46521)
@@ -0,0 +1,14 @@
+LIBRARY VBoxD3D9.dll
+
+EXPORTS
+  Direct3DShaderValidatorCreate9
+  D3DPERF_BeginEvent
+  D3DPERF_EndEvent
+  D3DPERF_GetStatus
+  D3DPERF_QueryRepeatFrame
+  D3DPERF_SetMarker
+  D3DPERF_SetOptions
+  D3DPERF_SetRegion
+  DebugSetMute
+  Direct3DCreate9
+  Direct3DCreate9Ex
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/device.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/device.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/device.c	(revision 46521)
@@ -0,0 +1,3927 @@
+/*
+ * IDirect3DDevice9 implementation
+ *
+ * Copyright 2002-2005 Jason Edmeades
+ * Copyright 2002-2005 Raphael Junqueira
+ * Copyright 2005 Oliver Stieber
+ *
+ * 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 "d3d9_private.h"
+
+#ifdef VBOX_WITH_WDDM
+# include <iprt/assert.h>
+# include "../../common/VBoxVideoTools.h"
+#endif
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
+
+D3DFORMAT d3dformat_from_wined3dformat(enum wined3d_format_id format)
+{
+    BYTE *c = (BYTE *)&format;
+
+    /* Don't translate FOURCC formats */
+    if (isprint(c[0]) && isprint(c[1]) && isprint(c[2]) && isprint(c[3])) return format;
+
+    switch(format)
+    {
+        case WINED3DFMT_UNKNOWN: return D3DFMT_UNKNOWN;
+        case WINED3DFMT_B8G8R8_UNORM: return D3DFMT_R8G8B8;
+        case WINED3DFMT_B8G8R8A8_UNORM: return D3DFMT_A8R8G8B8;
+        case WINED3DFMT_B8G8R8X8_UNORM: return D3DFMT_X8R8G8B8;
+        case WINED3DFMT_B5G6R5_UNORM: return D3DFMT_R5G6B5;
+        case WINED3DFMT_B5G5R5X1_UNORM: return D3DFMT_X1R5G5B5;
+        case WINED3DFMT_B5G5R5A1_UNORM: return D3DFMT_A1R5G5B5;
+        case WINED3DFMT_B4G4R4A4_UNORM: return D3DFMT_A4R4G4B4;
+        case WINED3DFMT_B2G3R3_UNORM: return D3DFMT_R3G3B2;
+        case WINED3DFMT_A8_UNORM: return D3DFMT_A8;
+        case WINED3DFMT_B2G3R3A8_UNORM: return D3DFMT_A8R3G3B2;
+        case WINED3DFMT_B4G4R4X4_UNORM: return D3DFMT_X4R4G4B4;
+        case WINED3DFMT_R10G10B10A2_UNORM: return D3DFMT_A2B10G10R10;
+        case WINED3DFMT_R8G8B8A8_UNORM: return D3DFMT_A8B8G8R8;
+        case WINED3DFMT_R8G8B8X8_UNORM: return D3DFMT_X8B8G8R8;
+        case WINED3DFMT_R16G16_UNORM: return D3DFMT_G16R16;
+        case WINED3DFMT_B10G10R10A2_UNORM: return D3DFMT_A2R10G10B10;
+        case WINED3DFMT_R16G16B16A16_UNORM: return D3DFMT_A16B16G16R16;
+        case WINED3DFMT_P8_UINT_A8_UNORM: return D3DFMT_A8P8;
+        case WINED3DFMT_P8_UINT: return D3DFMT_P8;
+        case WINED3DFMT_L8_UNORM: return D3DFMT_L8;
+        case WINED3DFMT_L8A8_UNORM: return D3DFMT_A8L8;
+        case WINED3DFMT_L4A4_UNORM: return D3DFMT_A4L4;
+        case WINED3DFMT_R8G8_SNORM: return D3DFMT_V8U8;
+        case WINED3DFMT_R5G5_SNORM_L6_UNORM: return D3DFMT_L6V5U5;
+        case WINED3DFMT_R8G8_SNORM_L8X8_UNORM: return D3DFMT_X8L8V8U8;
+        case WINED3DFMT_R8G8B8A8_SNORM: return D3DFMT_Q8W8V8U8;
+        case WINED3DFMT_R16G16_SNORM: return D3DFMT_V16U16;
+        case WINED3DFMT_R10G10B10_SNORM_A2_UNORM: return D3DFMT_A2W10V10U10;
+        case WINED3DFMT_D16_LOCKABLE: return D3DFMT_D16_LOCKABLE;
+        case WINED3DFMT_D32_UNORM: return D3DFMT_D32;
+        case WINED3DFMT_S1_UINT_D15_UNORM: return D3DFMT_D15S1;
+        case WINED3DFMT_D24_UNORM_S8_UINT: return D3DFMT_D24S8;
+        case WINED3DFMT_X8D24_UNORM: return D3DFMT_D24X8;
+        case WINED3DFMT_S4X4_UINT_D24_UNORM: return D3DFMT_D24X4S4;
+        case WINED3DFMT_D16_UNORM: return D3DFMT_D16;
+        case WINED3DFMT_L16_UNORM: return D3DFMT_L16;
+        case WINED3DFMT_D32_FLOAT: return D3DFMT_D32F_LOCKABLE;
+        case WINED3DFMT_S8_UINT_D24_FLOAT: return D3DFMT_D24FS8;
+        case WINED3DFMT_VERTEXDATA: return D3DFMT_VERTEXDATA;
+        case WINED3DFMT_R16_UINT: return D3DFMT_INDEX16;
+        case WINED3DFMT_R32_UINT: return D3DFMT_INDEX32;
+        case WINED3DFMT_R16G16B16A16_SNORM: return D3DFMT_Q16W16V16U16;
+        case WINED3DFMT_R16_FLOAT: return D3DFMT_R16F;
+        case WINED3DFMT_R16G16_FLOAT: return D3DFMT_G16R16F;
+        case WINED3DFMT_R16G16B16A16_FLOAT: return D3DFMT_A16B16G16R16F;
+        case WINED3DFMT_R32_FLOAT: return D3DFMT_R32F;
+        case WINED3DFMT_R32G32_FLOAT: return D3DFMT_G32R32F;
+        case WINED3DFMT_R32G32B32A32_FLOAT: return D3DFMT_A32B32G32R32F;
+        case WINED3DFMT_R8G8_SNORM_Cx: return D3DFMT_CxV8U8;
+        default:
+            FIXME("Unhandled wined3d format %#x.\n", format);
+            return D3DFMT_UNKNOWN;
+    }
+}
+
+enum wined3d_format_id wined3dformat_from_d3dformat(D3DFORMAT format)
+{
+    BYTE *c = (BYTE *)&format;
+
+    /* Don't translate FOURCC formats */
+    if (isprint(c[0]) && isprint(c[1]) && isprint(c[2]) && isprint(c[3])) return format;
+
+    switch(format)
+    {
+        case D3DFMT_UNKNOWN: return WINED3DFMT_UNKNOWN;
+        case D3DFMT_R8G8B8: return WINED3DFMT_B8G8R8_UNORM;
+        case D3DFMT_A8R8G8B8: return WINED3DFMT_B8G8R8A8_UNORM;
+        case D3DFMT_X8R8G8B8: return WINED3DFMT_B8G8R8X8_UNORM;
+        case D3DFMT_R5G6B5: return WINED3DFMT_B5G6R5_UNORM;
+        case D3DFMT_X1R5G5B5: return WINED3DFMT_B5G5R5X1_UNORM;
+        case D3DFMT_A1R5G5B5: return WINED3DFMT_B5G5R5A1_UNORM;
+        case D3DFMT_A4R4G4B4: return WINED3DFMT_B4G4R4A4_UNORM;
+        case D3DFMT_R3G3B2: return WINED3DFMT_B2G3R3_UNORM;
+        case D3DFMT_A8: return WINED3DFMT_A8_UNORM;
+        case D3DFMT_A8R3G3B2: return WINED3DFMT_B2G3R3A8_UNORM;
+        case D3DFMT_X4R4G4B4: return WINED3DFMT_B4G4R4X4_UNORM;
+        case D3DFMT_A2B10G10R10: return WINED3DFMT_R10G10B10A2_UNORM;
+        case D3DFMT_A8B8G8R8: return WINED3DFMT_R8G8B8A8_UNORM;
+        case D3DFMT_X8B8G8R8: return WINED3DFMT_R8G8B8X8_UNORM;
+        case D3DFMT_G16R16: return WINED3DFMT_R16G16_UNORM;
+        case D3DFMT_A2R10G10B10: return WINED3DFMT_B10G10R10A2_UNORM;
+        case D3DFMT_A16B16G16R16: return WINED3DFMT_R16G16B16A16_UNORM;
+        case D3DFMT_A8P8: return WINED3DFMT_P8_UINT_A8_UNORM;
+        case D3DFMT_P8: return WINED3DFMT_P8_UINT;
+        case D3DFMT_L8: return WINED3DFMT_L8_UNORM;
+        case D3DFMT_A8L8: return WINED3DFMT_L8A8_UNORM;
+        case D3DFMT_A4L4: return WINED3DFMT_L4A4_UNORM;
+        case D3DFMT_V8U8: return WINED3DFMT_R8G8_SNORM;
+        case D3DFMT_L6V5U5: return WINED3DFMT_R5G5_SNORM_L6_UNORM;
+        case D3DFMT_X8L8V8U8: return WINED3DFMT_R8G8_SNORM_L8X8_UNORM;
+        case D3DFMT_Q8W8V8U8: return WINED3DFMT_R8G8B8A8_SNORM;
+        case D3DFMT_V16U16: return WINED3DFMT_R16G16_SNORM;
+        case D3DFMT_A2W10V10U10: return WINED3DFMT_R10G10B10_SNORM_A2_UNORM;
+        case D3DFMT_D16_LOCKABLE: return WINED3DFMT_D16_LOCKABLE;
+        case D3DFMT_D32: return WINED3DFMT_D32_UNORM;
+        case D3DFMT_D15S1: return WINED3DFMT_S1_UINT_D15_UNORM;
+        case D3DFMT_D24S8: return WINED3DFMT_D24_UNORM_S8_UINT;
+        case D3DFMT_D24X8: return WINED3DFMT_X8D24_UNORM;
+        case D3DFMT_D24X4S4: return WINED3DFMT_S4X4_UINT_D24_UNORM;
+        case D3DFMT_D16: return WINED3DFMT_D16_UNORM;
+        case D3DFMT_L16: return WINED3DFMT_L16_UNORM;
+        case D3DFMT_D32F_LOCKABLE: return WINED3DFMT_D32_FLOAT;
+        case D3DFMT_D24FS8: return WINED3DFMT_S8_UINT_D24_FLOAT;
+        case D3DFMT_VERTEXDATA: return WINED3DFMT_VERTEXDATA;
+        case D3DFMT_INDEX16: return WINED3DFMT_R16_UINT;
+        case D3DFMT_INDEX32: return WINED3DFMT_R32_UINT;
+        case D3DFMT_Q16W16V16U16: return WINED3DFMT_R16G16B16A16_SNORM;
+        case D3DFMT_R16F: return WINED3DFMT_R16_FLOAT;
+        case D3DFMT_G16R16F: return WINED3DFMT_R16G16_FLOAT;
+        case D3DFMT_A16B16G16R16F: return WINED3DFMT_R16G16B16A16_FLOAT;
+        case D3DFMT_R32F: return WINED3DFMT_R32_FLOAT;
+        case D3DFMT_G32R32F: return WINED3DFMT_R32G32_FLOAT;
+        case D3DFMT_A32B32G32R32F: return WINED3DFMT_R32G32B32A32_FLOAT;
+        case D3DFMT_CxV8U8: return WINED3DFMT_R8G8_SNORM_Cx;
+        default:
+            FIXME("Unhandled D3DFORMAT %#x\n", format);
+            return WINED3DFMT_UNKNOWN;
+    }
+}
+
+static UINT vertex_count_from_primitive_count(D3DPRIMITIVETYPE primitive_type, UINT primitive_count)
+{
+    switch(primitive_type)
+    {
+        case D3DPT_POINTLIST:
+            return primitive_count;
+
+        case D3DPT_LINELIST:
+            return primitive_count * 2;
+
+        case D3DPT_LINESTRIP:
+            return primitive_count + 1;
+
+        case D3DPT_TRIANGLELIST:
+            return primitive_count * 3;
+
+        case D3DPT_TRIANGLESTRIP:
+        case D3DPT_TRIANGLEFAN:
+            return primitive_count + 2;
+
+        default:
+            FIXME("Unhandled primitive type %#x\n", primitive_type);
+            return 0;
+    }
+}
+
+void present_parameters_from_wined3d_swapchain_desc(D3DPRESENT_PARAMETERS *present_parameters,
+        const struct wined3d_swapchain_desc *swapchain_desc)
+{
+    present_parameters->BackBufferWidth = swapchain_desc->backbuffer_width;
+    present_parameters->BackBufferHeight = swapchain_desc->backbuffer_height;
+    present_parameters->BackBufferFormat = d3dformat_from_wined3dformat(swapchain_desc->backbuffer_format);
+    present_parameters->BackBufferCount = swapchain_desc->backbuffer_count;
+    present_parameters->MultiSampleType = swapchain_desc->multisample_type;
+    present_parameters->MultiSampleQuality = swapchain_desc->multisample_quality;
+    present_parameters->SwapEffect = swapchain_desc->swap_effect;
+    present_parameters->hDeviceWindow = swapchain_desc->device_window;
+    present_parameters->Windowed = swapchain_desc->windowed;
+    present_parameters->EnableAutoDepthStencil = swapchain_desc->enable_auto_depth_stencil;
+    present_parameters->AutoDepthStencilFormat
+            = d3dformat_from_wined3dformat(swapchain_desc->auto_depth_stencil_format);
+    present_parameters->Flags = swapchain_desc->flags;
+    present_parameters->FullScreen_RefreshRateInHz = swapchain_desc->refresh_rate;
+    present_parameters->PresentationInterval = swapchain_desc->swap_interval;
+}
+
+static void wined3d_swapchain_desc_from_present_parameters(struct wined3d_swapchain_desc *swapchain_desc,
+        const D3DPRESENT_PARAMETERS *present_parameters)
+{
+    swapchain_desc->backbuffer_width = present_parameters->BackBufferWidth;
+    swapchain_desc->backbuffer_height = present_parameters->BackBufferHeight;
+    swapchain_desc->backbuffer_format = wined3dformat_from_d3dformat(present_parameters->BackBufferFormat);
+    swapchain_desc->backbuffer_count = max(1, present_parameters->BackBufferCount);
+    swapchain_desc->multisample_type = present_parameters->MultiSampleType;
+    swapchain_desc->multisample_quality = present_parameters->MultiSampleQuality;
+    swapchain_desc->swap_effect = present_parameters->SwapEffect;
+    swapchain_desc->device_window = present_parameters->hDeviceWindow;
+    swapchain_desc->windowed = present_parameters->Windowed;
+    swapchain_desc->enable_auto_depth_stencil = present_parameters->EnableAutoDepthStencil;
+    swapchain_desc->auto_depth_stencil_format
+            = wined3dformat_from_d3dformat(present_parameters->AutoDepthStencilFormat);
+    swapchain_desc->flags = present_parameters->Flags;
+    swapchain_desc->refresh_rate = present_parameters->FullScreen_RefreshRateInHz;
+    swapchain_desc->swap_interval = present_parameters->PresentationInterval;
+    swapchain_desc->auto_restore_display_mode = TRUE;
+#ifdef VBOX_WITH_WDDM
+    swapchain_desc->pHgsmi = NULL;
+#endif
+
+}
+
+static inline struct d3d9_device *impl_from_IDirect3DDevice9Ex(IDirect3DDevice9Ex *iface)
+{
+    return CONTAINING_RECORD(iface, struct d3d9_device, IDirect3DDevice9Ex_iface);
+}
+
+static HRESULT WINAPI d3d9_device_QueryInterface(IDirect3DDevice9Ex *iface, REFIID riid, void **out)
+{
+    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
+
+    if (IsEqualGUID(riid, &IID_IDirect3DDevice9)
+            || IsEqualGUID(riid, &IID_IUnknown))
+    {
+        IDirect3DDevice9Ex_AddRef(iface);
+        *out = iface;
+        return S_OK;
+    }
+
+    if (IsEqualGUID(riid, &IID_IDirect3DDevice9Ex))
+    {
+        struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+
+        /* Find out if the creating d3d9 interface was created with Direct3DCreate9Ex.
+         * It doesn't matter with which function the device was created. */
+        if (!device->d3d_parent->extended)
+        {
+            WARN("IDirect3D9 instance wasn't created with CreateDirect3D9Ex, returning E_NOINTERFACE.\n");
+            *out = NULL;
+            return E_NOINTERFACE;
+        }
+
+        IDirect3DDevice9Ex_AddRef(iface);
+        *out = iface;
+        return S_OK;
+    }
+
+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+    *out = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI d3d9_device_AddRef(IDirect3DDevice9Ex *iface)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    ULONG refcount = InterlockedIncrement(&device->refcount);
+
+    TRACE("%p increasing refcount to %u.\n", iface, refcount);
+
+    return refcount;
+}
+
+#ifdef VBOX
+static LONG d3d9_device_Term(struct d3d9_device *device)
+{
+    unsigned i;
+    LONG refs = device->refcount;
+    device->in_destruction = TRUE;
+
+    if (refs != 1)
+    {
+        ERR("unexpected ref count %d, destroying in anyway", refs);
+    }
+
+    wined3d_mutex_lock();
+    for (i = 0; i < device->fvf_decl_count; ++i)
+    {
+        wined3d_vertex_declaration_decref(device->fvf_decls[i].decl);
+    }
+    HeapFree(GetProcessHeap(), 0, device->fvf_decls);
+
+    if (device->vertex_buffer)
+        wined3d_buffer_decref(device->vertex_buffer);
+    if (device->index_buffer)
+        wined3d_buffer_decref(device->index_buffer);
+
+    wined3d_device_uninit_3d(device->wined3d_device);
+# ifndef VBOX_WITH_WDDM
+    wined3d_device_release_focus_window(device->wined3d_device);
+# endif
+    wined3d_device_decref(device->wined3d_device);
+    wined3d_mutex_unlock();
+
+    IDirect3D9Ex_Release(&device->d3d_parent->IDirect3D9Ex_iface);
+
+    HeapFree(GetProcessHeap(), 0, device);
+
+    return refs - 1;
+}
+#endif
+
+static ULONG WINAPI DECLSPEC_HOTPATCH d3d9_device_Release(IDirect3DDevice9Ex *iface)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    ULONG refcount;
+
+    if (device->in_destruction)
+        return 0;
+
+    refcount = InterlockedDecrement(&device->refcount);
+
+    TRACE("%p decreasing refcount to %u.\n", iface, refcount);
+
+    if (!refcount)
+    {
+#ifdef VBOX
+    	d3d9_device_Term(device);
+#else
+        unsigned i;
+        device->in_destruction = TRUE;
+
+        wined3d_mutex_lock();
+        for (i = 0; i < device->fvf_decl_count; ++i)
+        {
+            wined3d_vertex_declaration_decref(device->fvf_decls[i].decl);
+        }
+        HeapFree(GetProcessHeap(), 0, device->fvf_decls);
+
+        if (device->vertex_buffer)
+            wined3d_buffer_decref(device->vertex_buffer);
+        if (device->index_buffer)
+            wined3d_buffer_decref(device->index_buffer);
+
+        wined3d_device_uninit_3d(device->wined3d_device);
+        wined3d_device_release_focus_window(device->wined3d_device);
+        wined3d_device_decref(device->wined3d_device);
+        wined3d_mutex_unlock();
+
+        IDirect3D9Ex_Release(&device->d3d_parent->IDirect3D9Ex_iface);
+
+        HeapFree(GetProcessHeap(), 0, device);
+#endif
+    }
+
+    return refcount;
+}
+
+static HRESULT WINAPI d3d9_device_TestCooperativeLevel(IDirect3DDevice9Ex *iface)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    if (device->not_reset)
+    {
+        TRACE("D3D9 device is marked not reset.\n");
+        return D3DERR_DEVICENOTRESET;
+    }
+
+    return D3D_OK;
+}
+
+static UINT WINAPI d3d9_device_GetAvailableTextureMem(IDirect3DDevice9Ex *iface)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_get_available_texture_mem(device->wined3d_device);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_EvictManagedResources(IDirect3DDevice9Ex *iface)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    wined3d_device_evict_managed_resources(device->wined3d_device);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_GetDirect3D(IDirect3DDevice9Ex *iface, IDirect3D9 **d3d9)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+
+    TRACE("iface %p, d3d9 %p.\n", iface, d3d9);
+
+    if (!d3d9)
+        return D3DERR_INVALIDCALL;
+
+    return IDirect3D9Ex_QueryInterface(&device->d3d_parent->IDirect3D9Ex_iface, &IID_IDirect3D9, (void **)d3d9);
+}
+
+static HRESULT WINAPI d3d9_device_GetDeviceCaps(IDirect3DDevice9Ex *iface, D3DCAPS9 *caps)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    WINED3DCAPS *wined3d_caps;
+    HRESULT hr;
+
+    TRACE("iface %p, caps %p.\n", iface, caps);
+
+    if (!caps)
+        return D3DERR_INVALIDCALL;
+
+    if (!(wined3d_caps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*wined3d_caps))))
+        return D3DERR_INVALIDCALL; /* well this is what MSDN says to return */
+
+    memset(caps, 0, sizeof(*caps));
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_get_device_caps(device->wined3d_device, wined3d_caps);
+    wined3d_mutex_unlock();
+
+    WINECAPSTOD3D9CAPS(caps, wined3d_caps)
+    HeapFree(GetProcessHeap(), 0, wined3d_caps);
+
+    /* Some functionality is implemented in d3d9.dll, not wined3d.dll. Add the needed caps */
+    caps->DevCaps2 |= D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES;
+
+    filter_caps(caps);
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_GetDisplayMode(IDirect3DDevice9Ex *iface, UINT swapchain, D3DDISPLAYMODE *mode)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct wined3d_display_mode wined3d_mode;
+    HRESULT hr;
+
+    TRACE("iface %p, swapchain %u, mode %p.\n", iface, swapchain, mode);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_get_display_mode(device->wined3d_device, swapchain, &wined3d_mode, NULL);
+    wined3d_mutex_unlock();
+
+    if (SUCCEEDED(hr))
+    {
+        mode->Width = wined3d_mode.width;
+        mode->Height = wined3d_mode.height;
+        mode->RefreshRate = wined3d_mode.refresh_rate;
+        mode->Format = d3dformat_from_wined3dformat(wined3d_mode.format_id);
+    }
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_GetCreationParameters(IDirect3DDevice9Ex *iface,
+        D3DDEVICE_CREATION_PARAMETERS *parameters)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+
+    TRACE("iface %p, parameters %p.\n", iface, parameters);
+
+    wined3d_mutex_lock();
+    wined3d_device_get_creation_parameters(device->wined3d_device,
+            (struct wined3d_device_creation_parameters *)parameters);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_SetCursorProperties(IDirect3DDevice9Ex *iface,
+        UINT hotspot_x, UINT hotspot_y, IDirect3DSurface9 *bitmap)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_surface *bitmap_impl = unsafe_impl_from_IDirect3DSurface9(bitmap);
+    HRESULT hr;
+
+    TRACE("iface %p, hotspot_x %u, hotspot_y %u, bitmap %p.\n",
+            iface, hotspot_x, hotspot_y, bitmap);
+
+    if (!bitmap)
+    {
+        WARN("No cursor bitmap, returning D3DERR_INVALIDCALL.\n");
+        return D3DERR_INVALIDCALL;
+    }
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_set_cursor_properties(device->wined3d_device,
+            hotspot_x, hotspot_y, bitmap_impl->wined3d_surface);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static void WINAPI d3d9_device_SetCursorPosition(IDirect3DDevice9Ex *iface, int x, int y, DWORD flags)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+
+    TRACE("iface %p, x %u, y %u, flags %#x.\n", iface, x, y, flags);
+
+    wined3d_mutex_lock();
+    wined3d_device_set_cursor_position(device->wined3d_device, x, y, flags);
+    wined3d_mutex_unlock();
+}
+
+static BOOL WINAPI d3d9_device_ShowCursor(IDirect3DDevice9Ex *iface, BOOL show)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    BOOL ret;
+
+    TRACE("iface %p, show %#x.\n", iface, show);
+
+    wined3d_mutex_lock();
+    ret = wined3d_device_show_cursor(device->wined3d_device, show);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_CreateAdditionalSwapChain(IDirect3DDevice9Ex *iface,
+        D3DPRESENT_PARAMETERS *present_parameters, IDirect3DSwapChain9 **swapchain)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct wined3d_swapchain_desc desc;
+    struct d3d9_swapchain *object;
+    HRESULT hr;
+
+    TRACE("iface %p, present_parameters %p, swapchain %p.\n",
+            iface, present_parameters, swapchain);
+
+    wined3d_swapchain_desc_from_present_parameters(&desc, present_parameters);
+    if (SUCCEEDED(hr = d3d9_swapchain_create(device, &desc, &object)))
+        *swapchain = &object->IDirect3DSwapChain9_iface;
+    present_parameters_from_wined3d_swapchain_desc(present_parameters, &desc);
+
+    return hr;
+}
+
+static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_GetSwapChain(IDirect3DDevice9Ex *iface,
+        UINT swapchain_idx, IDirect3DSwapChain9 **swapchain)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct wined3d_swapchain *wined3d_swapchain;
+    struct d3d9_swapchain *swapchain_impl;
+    HRESULT hr;
+
+    TRACE("iface %p, swapchain_idx %u, swapchain %p.\n", iface, swapchain_idx, swapchain);
+
+    wined3d_mutex_lock();
+    if ((wined3d_swapchain = wined3d_device_get_swapchain(device->wined3d_device, swapchain_idx)))
+    {
+       swapchain_impl = wined3d_swapchain_get_parent(wined3d_swapchain);
+       *swapchain = &swapchain_impl->IDirect3DSwapChain9_iface;
+       IDirect3DSwapChain9_AddRef(*swapchain);
+       hr = D3D_OK;
+    }
+    else
+    {
+        *swapchain = NULL;
+        hr = D3DERR_INVALIDCALL;
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static UINT WINAPI d3d9_device_GetNumberOfSwapChains(IDirect3DDevice9Ex *iface)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    UINT count;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    count = wined3d_device_get_swapchain_count(device->wined3d_device);
+    wined3d_mutex_unlock();
+
+    return count;
+}
+
+static HRESULT CDECL reset_enum_callback(struct wined3d_resource *resource)
+{
+    struct wined3d_resource_desc desc;
+
+    wined3d_resource_get_desc(resource, &desc);
+    if (desc.pool == WINED3D_POOL_DEFAULT)
+    {
+        struct d3d9_surface *surface;
+
+        if (desc.resource_type == WINED3D_RTYPE_TEXTURE)
+        {
+            IUnknown *parent = wined3d_resource_get_parent(resource);
+            IDirect3DBaseTexture9 *texture;
+
+            if (SUCCEEDED(IUnknown_QueryInterface(parent, &IID_IDirect3DBaseTexture9, (void **)&texture)))
+            {
+                IDirect3DBaseTexture9_Release(texture);
+                WARN("Texture %p (resource %p) in pool D3DPOOL_DEFAULT blocks the Reset call.\n", texture, resource);
+                return D3DERR_INVALIDCALL;
+            }
+
+            return D3D_OK;
+        }
+
+        if (desc.resource_type != WINED3D_RTYPE_SURFACE)
+        {
+            WARN("Resource %p in pool D3DPOOL_DEFAULT blocks the Reset call.\n", resource);
+            return D3DERR_INVALIDCALL;
+        }
+
+        surface = wined3d_resource_get_parent(resource);
+        if (surface->refcount)
+        {
+            WARN("Surface %p (resource %p) in pool D3DPOOL_DEFAULT blocks the Reset call.\n", surface, resource);
+            return D3DERR_INVALIDCALL;
+        }
+
+        WARN("Surface %p (resource %p) is an implicit resource with ref 0.\n", surface, resource);
+    }
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_Reset(IDirect3DDevice9Ex *iface,
+        D3DPRESENT_PARAMETERS *present_parameters)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct wined3d_swapchain_desc swapchain_desc;
+    HRESULT hr;
+
+    TRACE("iface %p, present_parameters %p.\n", iface, present_parameters);
+
+    wined3d_mutex_lock();
+
+    if (device->vertex_buffer)
+    {
+        wined3d_buffer_decref(device->vertex_buffer);
+        device->vertex_buffer = NULL;
+        device->vertex_buffer_size = 0;
+    }
+    if (device->index_buffer)
+    {
+        wined3d_buffer_decref(device->index_buffer);
+        device->index_buffer = NULL;
+        device->index_buffer_size = 0;
+    }
+
+    wined3d_swapchain_desc_from_present_parameters(&swapchain_desc, present_parameters);
+    hr = wined3d_device_reset(device->wined3d_device, &swapchain_desc,
+            NULL, reset_enum_callback, !device->d3d_parent->extended);
+    if (FAILED(hr) && !device->d3d_parent->extended)
+        device->not_reset = TRUE;
+    else
+        device->not_reset = FALSE;
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_Present(IDirect3DDevice9Ex *iface,
+        const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, const RGNDATA *dirty_region)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, src_rect %p, dst_rect %p, dst_window_override %p, dirty_region %p.\n",
+            iface, src_rect, dst_rect, dst_window_override, dirty_region);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_present(device->wined3d_device, src_rect, dst_rect,
+            dst_window_override, dirty_region, 0);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_GetBackBuffer(IDirect3DDevice9Ex *iface, UINT swapchain,
+        UINT backbuffer_idx, D3DBACKBUFFER_TYPE backbuffer_type, IDirect3DSurface9 **backbuffer)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct wined3d_surface *wined3d_surface = NULL;
+    struct d3d9_surface *surface_impl;
+    HRESULT hr;
+
+    TRACE("iface %p, swapchain %u, backbuffer_idx %u, backbuffer_type %#x, backbuffer %p.\n",
+            iface, swapchain, backbuffer_idx, backbuffer_type, backbuffer);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_get_back_buffer(device->wined3d_device, swapchain,
+            backbuffer_idx, (enum wined3d_backbuffer_type)backbuffer_type, &wined3d_surface);
+    if (SUCCEEDED(hr) && wined3d_surface && backbuffer)
+    {
+        surface_impl = wined3d_surface_get_parent(wined3d_surface);
+        *backbuffer = &surface_impl->IDirect3DSurface9_iface;
+        IDirect3DSurface9_AddRef(*backbuffer);
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+static HRESULT WINAPI d3d9_device_GetRasterStatus(IDirect3DDevice9Ex *iface,
+        UINT swapchain, D3DRASTER_STATUS *raster_status)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, swapchain %u, raster_status %p.\n", iface, swapchain, raster_status);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_get_raster_status(device->wined3d_device,
+            swapchain, (struct wined3d_raster_status *)raster_status);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_SetDialogBoxMode(IDirect3DDevice9Ex *iface, BOOL enable)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, enable %#x.\n", iface, enable);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_set_dialog_box_mode(device->wined3d_device, enable);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static void WINAPI d3d9_device_SetGammaRamp(IDirect3DDevice9Ex *iface,
+        UINT swapchain, DWORD flags, const D3DGAMMARAMP *ramp)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+
+    TRACE("iface %p, swapchain %u, flags %#x, ramp %p.\n", iface, swapchain, flags, ramp);
+
+    /* Note: D3DGAMMARAMP is compatible with struct wined3d_gamma_ramp. */
+    wined3d_mutex_lock();
+    wined3d_device_set_gamma_ramp(device->wined3d_device, swapchain, flags, (const struct wined3d_gamma_ramp *)ramp);
+    wined3d_mutex_unlock();
+}
+
+static void WINAPI d3d9_device_GetGammaRamp(IDirect3DDevice9Ex *iface, UINT swapchain, D3DGAMMARAMP *ramp)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+
+    TRACE("iface %p, swapchain %u, ramp %p.\n", iface, swapchain, ramp);
+
+    /* Note: D3DGAMMARAMP is compatible with struct wined3d_gamma_ramp. */
+    wined3d_mutex_lock();
+    wined3d_device_get_gamma_ramp(device->wined3d_device, swapchain, (struct wined3d_gamma_ramp *)ramp);
+    wined3d_mutex_unlock();
+}
+
+#ifdef VBOX_WITH_WDDM
+//#pragma comment(linker, "/export:VBoxWineExD3DDev9Flush=_VBoxWineExD3DDev9Flush@4")
+
+VBOXWINEEX_DECL(HRESULT) VBoxWineExD3DDev9Flush(IDirect3DDevice9Ex *iface)
+{
+	struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, Flush\n", iface);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_flush(device->wined3d_device);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+VBOXWINEEX_DECL(HRESULT) VBoxWineExD3DDev9FlushToHost(IDirect3DDevice9Ex *iface)
+{
+	struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, FlushToHost\n", iface);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_flush_to_host(device->wined3d_device);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+VBOXWINEEX_DECL(HRESULT) VBoxWineExD3DDev9Finish(IDirect3DDevice9Ex *iface)
+{
+	struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, FlushToHost\n", iface);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_finish(device->wined3d_device);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+//#pragma comment(linker, "/export:VBoxWineExD3DDev9CreateTexture=_VBoxWineExD3DDev9CreateTexture@40")
+
+VBOXWINEEX_DECL(HRESULT) VBoxWineExD3DDev9CreateTexture(IDirect3DDevice9Ex *iface,
+        UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format,
+        D3DPOOL pool, IDirect3DTexture9 **texture, HANDLE *shared_handle,
+        void **pavClientMem) /* <- extension arg to pass in the client memory buffer,
+                            *    applicable ONLY for SYSMEM textures */
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_texture *object;
+    HRESULT hr;
+
+    TRACE("iface %p, width %u, height %u, levels %u, usage %#x, format %#x, pool %#x, texture %p, shared_handle %p.\n",
+            iface, width, height, levels, usage, format, pool, texture, shared_handle);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return D3DERR_OUTOFVIDEOMEMORY;
+
+    hr = texture_init(object, device, width, height, levels, usage, format, pool, shared_handle, pavClientMem);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize texture, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created texture %p.\n", object);
+    *texture = (IDirect3DTexture9 *)&object->IDirect3DBaseTexture9_iface;
+
+    return D3D_OK;
+}
+
+VBOXWINEEX_DECL(HRESULT) VBoxWineExD3DDev9CreateVolumeTexture(IDirect3DDevice9Ex *iface,
+        UINT width, UINT height, UINT depth, UINT levels, DWORD usage, D3DFORMAT format,
+        D3DPOOL pool, IDirect3DVolumeTexture9 **texture, HANDLE *shared_handle,
+        void **pavClientMem)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_texture *object;
+    HRESULT hr;
+
+    TRACE("iface %p, width %u, height %u, depth %u, levels %u\n",
+            iface, width, height, depth, levels);
+    TRACE("usage %#x, format %#x, pool %#x, texture %p, shared_handle %p.\n",
+            usage, format, pool, texture, shared_handle);
+
+    if (shared_handle)
+        FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return D3DERR_OUTOFVIDEOMEMORY;
+
+    hr = volumetexture_init(object, device, width, height, depth, levels, usage, format, pool, shared_handle, pavClientMem);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize volume texture, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created volume texture %p.\n", object);
+    *texture = (IDirect3DVolumeTexture9 *)&object->IDirect3DBaseTexture9_iface;
+
+    return D3D_OK;
+}
+
+VBOXWINEEX_DECL(HRESULT) VBoxWineExD3DDev9CreateCubeTexture(IDirect3DDevice9Ex *iface,
+            UINT edge_length, UINT levels, DWORD usage, D3DFORMAT format,
+            D3DPOOL pool, IDirect3DCubeTexture9 **texture, HANDLE *shared_handle,
+            void **pavClientMem) /* <- extension arg to pass in the client memory buffer,
+                                *    applicable ONLY for SYSMEM textures */
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_texture *object;
+    HRESULT hr;
+
+    TRACE("iface %p, edge_length %u, levels %u, usage %#x, format %#x, pool %#x, texture %p, shared_handle %p.\n",
+            iface, edge_length, levels, usage, format, pool, texture, shared_handle);
+
+    if (shared_handle)
+        FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return D3DERR_OUTOFVIDEOMEMORY;
+
+    hr = cubetexture_init(object, device, edge_length, levels, usage, format, pool, shared_handle, pavClientMem);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize cube texture, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created cube texture %p.\n", object);
+    *texture = (IDirect3DCubeTexture9 *)&object->IDirect3DBaseTexture9_iface;
+
+    return D3D_OK;
+}
+
+#endif
+
+static HRESULT WINAPI d3d9_device_CreateTexture(IDirect3DDevice9Ex *iface,
+        UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format,
+        D3DPOOL pool, IDirect3DTexture9 **texture, HANDLE *shared_handle)
+{
+#ifdef VBOX_WITH_WDDM
+	return VBoxWineExD3DDev9CreateTexture(iface, width, height, levels, usage, format,
+	        pool, texture, shared_handle,
+	        NULL);
+#else
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_texture *object;
+    BOOL set_mem = FALSE;
+    HRESULT hr;
+
+    TRACE("iface %p, width %u, height %u, levels %u, usage %#x, format %#x, pool %#x, texture %p, shared_handle %p.\n",
+            iface, width, height, levels, usage, format, pool, texture, shared_handle);
+
+    if (shared_handle)
+    {
+        if (pool == D3DPOOL_SYSTEMMEM)
+        {
+            if (levels != 1)
+                return D3DERR_INVALIDCALL;
+            set_mem = TRUE;
+        }
+        else
+            FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
+    }
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return D3DERR_OUTOFVIDEOMEMORY;
+
+    hr = texture_init(object, device, width, height, levels, usage, format, pool);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize texture, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    if (set_mem)
+    {
+        struct wined3d_resource *resource;
+        struct d3d9_surface *surface;
+
+        resource = wined3d_texture_get_sub_resource(object->wined3d_texture, 0);
+        surface = wined3d_resource_get_parent(resource);
+        wined3d_surface_set_mem(surface->wined3d_surface, *shared_handle);
+    }
+
+    TRACE("Created texture %p.\n", object);
+    *texture = (IDirect3DTexture9 *)&object->IDirect3DBaseTexture9_iface;
+
+    return D3D_OK;
+#endif
+}
+
+static HRESULT WINAPI d3d9_device_CreateVolumeTexture(IDirect3DDevice9Ex *iface,
+        UINT width, UINT height, UINT depth, UINT levels, DWORD usage, D3DFORMAT format,
+        D3DPOOL pool, IDirect3DVolumeTexture9 **texture, HANDLE *shared_handle)
+{
+#ifdef VBOX_WITH_WDDM
+    return VBoxWineExD3DDev9CreateVolumeTexture(iface, width, height, depth, levels, usage, format,
+            pool, texture, shared_handle, NULL);
+#else
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_texture *object;
+    HRESULT hr;
+
+    TRACE("iface %p, width %u, height %u, depth %u, levels %u\n",
+            iface, width, height, depth, levels);
+    TRACE("usage %#x, format %#x, pool %#x, texture %p, shared_handle %p.\n",
+            usage, format, pool, texture, shared_handle);
+
+    if (shared_handle)
+        FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return D3DERR_OUTOFVIDEOMEMORY;
+
+    hr = volumetexture_init(object, device, width, height, depth, levels, usage, format, pool);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize volume texture, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created volume texture %p.\n", object);
+    *texture = (IDirect3DVolumeTexture9 *)&object->IDirect3DBaseTexture9_iface;
+
+    return D3D_OK;
+#endif
+}
+
+static HRESULT WINAPI d3d9_device_CreateCubeTexture(IDirect3DDevice9Ex *iface,
+        UINT edge_length, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool,
+        IDirect3DCubeTexture9 **texture, HANDLE *shared_handle)
+{
+#ifdef VBOX_WITH_WDDM
+    return VBoxWineExD3DDev9CreateCubeTexture(iface, edge_length, levels, usage, format,
+            pool, texture, shared_handle, NULL);
+#else
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_texture *object;
+    HRESULT hr;
+
+    TRACE("iface %p, edge_length %u, levels %u, usage %#x, format %#x, pool %#x, texture %p, shared_handle %p.\n",
+            iface, edge_length, levels, usage, format, pool, texture, shared_handle);
+
+    if (shared_handle)
+        FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return D3DERR_OUTOFVIDEOMEMORY;
+
+    hr = cubetexture_init(object, device, edge_length, levels, usage, format, pool);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize cube texture, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created cube texture %p.\n", object);
+    *texture = (IDirect3DCubeTexture9 *)&object->IDirect3DBaseTexture9_iface;
+
+    return D3D_OK;
+#endif
+}
+
+static HRESULT WINAPI d3d9_device_CreateVertexBuffer(IDirect3DDevice9Ex *iface, UINT size,
+        DWORD usage, DWORD fvf, D3DPOOL pool, IDirect3DVertexBuffer9 **buffer,
+        HANDLE *shared_handle)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_vertexbuffer *object;
+    HRESULT hr;
+
+    TRACE("iface %p, size %u, usage %#x, fvf %#x, pool %#x, buffer %p, shared_handle %p.\n",
+            iface, size, usage, fvf, pool, buffer, shared_handle);
+
+    if (shared_handle)
+        FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return D3DERR_OUTOFVIDEOMEMORY;
+
+    hr = vertexbuffer_init(object, device, size, usage, fvf, pool);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize vertex buffer, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created vertex buffer %p.\n", object);
+    *buffer = &object->IDirect3DVertexBuffer9_iface;
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_CreateIndexBuffer(IDirect3DDevice9Ex *iface, UINT size,
+        DWORD usage, D3DFORMAT format, D3DPOOL pool, IDirect3DIndexBuffer9 **buffer,
+        HANDLE *shared_handle)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_indexbuffer *object;
+    HRESULT hr;
+
+    TRACE("iface %p, size %u, usage %#x, format %#x, pool %#x, buffer %p, shared_handle %p.\n",
+            iface, size, usage, format, pool, buffer, shared_handle);
+
+    if (shared_handle)
+        FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return D3DERR_OUTOFVIDEOMEMORY;
+
+    hr = indexbuffer_init(object, device, size, usage, format, pool);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize index buffer, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created index buffer %p.\n", object);
+    *buffer = &object->IDirect3DIndexBuffer9_iface;
+
+    return D3D_OK;
+}
+
+static HRESULT d3d9_device_create_surface(struct d3d9_device *device, UINT width, UINT height,
+        D3DFORMAT format, DWORD flags, IDirect3DSurface9 **surface, UINT usage, D3DPOOL pool,
+        D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality
+#ifdef VBOX_WITH_WDDM
+        , HANDLE *shared_handle
+        , void *pvClientMem
+#endif
+        )
+{
+    struct d3d9_surface *object;
+    HRESULT hr;
+
+    TRACE("device %p, width %u, height %u, format %#x, flags %#x, surface %p.\n"
+            "usage %#x, pool %#x, multisample_type %#x, multisample_quality %u.\n",
+            device, width, height, format, flags, surface, usage, pool,
+            multisample_type, multisample_quality);
+
+    if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
+    {
+        FIXME("Failed to allocate surface memory.\n");
+        return D3DERR_OUTOFVIDEOMEMORY;
+    }
+
+#ifdef VBOX_WITH_WDDM
+    if (FAILED(hr = surface_init(object, device, width, height, format,
+            flags, usage, pool, multisample_type, multisample_quality
+            , shared_handle
+            , pvClientMem
+            )))
+#else
+    if (FAILED(hr = surface_init(object, device, width, height, format,
+            flags, usage, pool, multisample_type, multisample_quality)))
+#endif
+    {
+        WARN("Failed to initialize surface, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created surface %p.\n", object);
+    *surface = &object->IDirect3DSurface9_iface;
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_CreateRenderTarget(IDirect3DDevice9Ex *iface, UINT width, UINT height,
+        D3DFORMAT format, D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality,
+        BOOL lockable, IDirect3DSurface9 **surface, HANDLE *shared_handle)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    DWORD flags = 0;
+
+    TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, multisample_quality %u.\n"
+            "lockable %#x, surface %p, shared_handle %p.\n",
+            iface, width, height, format, multisample_type, multisample_quality,
+            lockable, surface, shared_handle);
+
+    if (shared_handle)
+        FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
+
+    if (lockable)
+        flags |= WINED3D_SURFACE_MAPPABLE;
+
+    return d3d9_device_create_surface(device, width, height, format, flags, surface,
+            D3DUSAGE_RENDERTARGET, D3DPOOL_DEFAULT, multisample_type, multisample_quality
+#ifdef VBOX_WITH_WDDM
+                , shared_handle
+                , NULL
+#endif
+                 );
+}
+
+static HRESULT WINAPI d3d9_device_CreateDepthStencilSurface(IDirect3DDevice9Ex *iface, UINT width, UINT height,
+        D3DFORMAT format, D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality,
+        BOOL discard, IDirect3DSurface9 **surface, HANDLE *shared_handle)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    DWORD flags = WINED3D_SURFACE_MAPPABLE;
+
+    TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, multisample_quality %u.\n"
+            "discard %#x, surface %p, shared_handle %p.\n",
+            iface, width, height, format, multisample_type, multisample_quality,
+            discard, surface, shared_handle);
+
+    if (shared_handle)
+        FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
+
+    if (discard)
+        flags |= WINED3D_SURFACE_DISCARD;
+
+    return d3d9_device_create_surface(device, width, height, format, flags, surface,
+                 D3DUSAGE_DEPTHSTENCIL, D3DPOOL_DEFAULT, multisample_type, multisample_quality
+#ifdef VBOX_WITH_WDDM
+                , shared_handle
+                , NULL
+#endif
+                 );
+}
+
+
+static HRESULT WINAPI d3d9_device_UpdateSurface(IDirect3DDevice9Ex *iface,
+        IDirect3DSurface9 *src_surface, const RECT *src_rect,
+        IDirect3DSurface9 *dst_surface, const POINT *dst_point)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_surface *src = unsafe_impl_from_IDirect3DSurface9(src_surface);
+    struct d3d9_surface *dst = unsafe_impl_from_IDirect3DSurface9(dst_surface);
+    HRESULT hr;
+
+    TRACE("iface %p, src_surface %p, src_rect %p, dst_surface %p, dst_point %p.\n",
+            iface, src_surface, src_rect, dst_surface, dst_point);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_update_surface(device->wined3d_device, src->wined3d_surface, src_rect,
+            dst->wined3d_surface, dst_point);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_UpdateTexture(IDirect3DDevice9Ex *iface,
+        IDirect3DBaseTexture9 *src_texture, IDirect3DBaseTexture9 *dst_texture)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_texture *src_impl, *dst_impl;
+    HRESULT hr;
+
+    TRACE("iface %p, src_texture %p, dst_texture %p.\n", iface, src_texture, dst_texture);
+
+    src_impl = unsafe_impl_from_IDirect3DBaseTexture9(src_texture);
+    dst_impl = unsafe_impl_from_IDirect3DBaseTexture9(dst_texture);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_update_texture(device->wined3d_device,
+            src_impl->wined3d_texture, dst_impl->wined3d_texture);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_GetRenderTargetData(IDirect3DDevice9Ex *iface,
+        IDirect3DSurface9 *render_target, IDirect3DSurface9 *dst_surface)
+{
+    struct d3d9_surface *rt_impl = unsafe_impl_from_IDirect3DSurface9(render_target);
+    struct d3d9_surface *dst_impl = unsafe_impl_from_IDirect3DSurface9(dst_surface);
+    HRESULT hr;
+
+    TRACE("iface %p, render_target %p, dst_surface %p.\n", iface, render_target, dst_surface);
+
+    wined3d_mutex_lock();
+    hr = wined3d_surface_get_render_target_data(dst_impl->wined3d_surface, rt_impl->wined3d_surface);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_GetFrontBufferData(IDirect3DDevice9Ex *iface,
+        UINT swapchain, IDirect3DSurface9 *dst_surface)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_surface *dst_impl = unsafe_impl_from_IDirect3DSurface9(dst_surface);
+    HRESULT hr;
+
+    TRACE("iface %p, swapchain %u, dst_surface %p.\n", iface, swapchain, dst_surface);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_get_front_buffer_data(device->wined3d_device, swapchain, dst_impl->wined3d_surface);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_StretchRect(IDirect3DDevice9Ex *iface, IDirect3DSurface9 *src_surface,
+        const RECT *src_rect, IDirect3DSurface9 *dst_surface, const RECT *dst_rect, D3DTEXTUREFILTERTYPE filter)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_surface *src = unsafe_impl_from_IDirect3DSurface9(src_surface);
+    struct d3d9_surface *dst = unsafe_impl_from_IDirect3DSurface9(dst_surface);
+    HRESULT hr = D3DERR_INVALIDCALL;
+    struct wined3d_resource_desc src_desc, dst_desc;
+    struct wined3d_resource *wined3d_resource;
+
+    TRACE("iface %p, src_surface %p, src_rect %p, dst_surface %p, dst_rect %p, filter %#x.\n",
+            iface, src_surface, src_rect, dst_surface, dst_rect, filter);
+
+    wined3d_mutex_lock();
+    wined3d_resource = wined3d_surface_get_resource(dst->wined3d_surface);
+    wined3d_resource_get_desc(wined3d_resource, &dst_desc);
+
+    wined3d_resource = wined3d_surface_get_resource(src->wined3d_surface);
+    wined3d_resource_get_desc(wined3d_resource, &src_desc);
+
+    if (src_desc.usage & WINED3DUSAGE_DEPTHSTENCIL)
+    {
+        if (device->in_scene)
+        {
+            WARN("Rejecting depth / stencil blit while in scene.\n");
+            goto done;
+        }
+
+        if (src_rect)
+        {
+            if (src_rect->left || src_rect->top || src_rect->right != src_desc.width
+                    || src_rect->bottom != src_desc.height)
+            {
+                WARN("Rejecting depth / stencil blit with invalid source rect %s.\n",
+                        wine_dbgstr_rect(src_rect));
+                goto done;
+            }
+        }
+        if (dst_rect)
+        {
+            if (dst_rect->left || dst_rect->top || dst_rect->right != dst_desc.width
+                    || dst_rect->bottom != dst_desc.height)
+            {
+                WARN("Rejecting depth / stencil blit with invalid destination rect %s.\n",
+                        wine_dbgstr_rect(dst_rect));
+                goto done;
+            }
+        }
+        if (src_desc.width != dst_desc.width || src_desc.height != dst_desc.height)
+        {
+            WARN("Rejecting depth / stencil blit with mismatched surface sizes.\n");
+            goto done;
+        }
+    }
+
+    hr = wined3d_surface_blt(dst->wined3d_surface, dst_rect, src->wined3d_surface, src_rect, 0, NULL, filter);
+    if (hr == WINEDDERR_INVALIDRECT)
+        hr = D3DERR_INVALIDCALL;
+
+done:
+    wined3d_mutex_unlock();
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_ColorFill(IDirect3DDevice9Ex *iface,
+        IDirect3DSurface9 *surface, const RECT *rect, D3DCOLOR color)
+{
+    const struct wined3d_color c =
+    {
+        ((color >> 16) & 0xff) / 255.0f,
+        ((color >>  8) & 0xff) / 255.0f,
+        (color & 0xff) / 255.0f,
+        ((color >> 24) & 0xff) / 255.0f,
+    };
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_surface *surface_impl = unsafe_impl_from_IDirect3DSurface9(surface);
+    struct wined3d_resource *wined3d_resource;
+    struct wined3d_resource_desc desc;
+    HRESULT hr;
+
+    TRACE("iface %p, surface %p, rect %p, color 0x%08x.\n", iface, surface, rect, color);
+
+    wined3d_mutex_lock();
+
+    wined3d_resource = wined3d_surface_get_resource(surface_impl->wined3d_surface);
+    wined3d_resource_get_desc(wined3d_resource, &desc);
+
+    /* This method is only allowed with surfaces that are render targets, or
+     * offscreen plain surfaces in D3DPOOL_DEFAULT. */
+    if (!(desc.usage & WINED3DUSAGE_RENDERTARGET) && desc.pool != WINED3D_POOL_DEFAULT)
+    {
+        wined3d_mutex_unlock();
+        WARN("Surface is not a render target, or not a stand-alone D3DPOOL_DEFAULT surface\n");
+        return D3DERR_INVALIDCALL;
+    }
+
+    /* Colorfill can only be used on rendertarget surfaces, or offscreen plain surfaces in D3DPOOL_DEFAULT */
+    hr = wined3d_device_color_fill(device->wined3d_device, surface_impl->wined3d_surface, rect, &c);
+
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_CreateOffscreenPlainSurface(IDirect3DDevice9Ex *iface,
+        UINT width, UINT height, D3DFORMAT format, D3DPOOL pool, IDirect3DSurface9 **surface,
+        HANDLE *shared_handle)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+
+    TRACE("iface %p, width %u, height %u, format %#x, pool %#x, surface %p, shared_handle %p.\n",
+            iface, width, height, format, pool, surface, shared_handle);
+
+    if (shared_handle)
+        FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
+
+    if (pool == D3DPOOL_MANAGED)
+    {
+        WARN("Attempting to create a managed offscreen plain surface.\n");
+        return D3DERR_INVALIDCALL;
+    }
+    /* FIXME: Offscreen surfaces are supposed to be always lockable,
+     * regardless of the pool they're created in. Should we set dynamic usage
+     * here? */
+    return d3d9_device_create_surface(device, width, height, format,
+            WINED3D_SURFACE_MAPPABLE, surface, 0, pool, D3DMULTISAMPLE_NONE, 0
+#ifdef VBOX_WITH_WDDM
+            , shared_handle
+            , NULL
+#endif
+            );
+}
+
+static HRESULT WINAPI d3d9_device_SetRenderTarget(IDirect3DDevice9Ex *iface, DWORD idx, IDirect3DSurface9 *surface)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_surface *surface_impl = unsafe_impl_from_IDirect3DSurface9(surface);
+    HRESULT hr;
+
+    TRACE("iface %p, idx %u, surface %p.\n", iface, idx, surface);
+
+    if (idx >= D3D9_MAX_SIMULTANEOUS_RENDERTARGETS)
+    {
+        WARN("Invalid index %u specified.\n", idx);
+        return D3DERR_INVALIDCALL;
+    }
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_set_render_target(device->wined3d_device, idx,
+            surface_impl ? surface_impl->wined3d_surface : NULL, TRUE);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_GetRenderTarget(IDirect3DDevice9Ex *iface, DWORD idx, IDirect3DSurface9 **surface)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct wined3d_surface *wined3d_surface;
+    struct d3d9_surface *surface_impl;
+    HRESULT hr = D3D_OK;
+
+    TRACE("iface %p, idx %u, surface %p.\n", iface, idx, surface);
+
+    if (!surface)
+        return D3DERR_INVALIDCALL;
+
+    if (idx >= D3D9_MAX_SIMULTANEOUS_RENDERTARGETS)
+    {
+        WARN("Invalid index %u specified.\n", idx);
+        return D3DERR_INVALIDCALL;
+    }
+
+    wined3d_mutex_lock();
+    if ((wined3d_surface = wined3d_device_get_render_target(device->wined3d_device, idx)))
+    {
+        surface_impl = wined3d_surface_get_parent(wined3d_surface);
+        *surface = &surface_impl->IDirect3DSurface9_iface;
+        IDirect3DSurface9_AddRef(*surface);
+    }
+    else
+    {
+        hr = WINED3DERR_NOTFOUND;
+        *surface = NULL;
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_SetDepthStencilSurface(IDirect3DDevice9Ex *iface, IDirect3DSurface9 *depth_stencil)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_surface *ds_impl = unsafe_impl_from_IDirect3DSurface9(depth_stencil);
+
+    TRACE("iface %p, depth_stencil %p.\n", iface, depth_stencil);
+
+    wined3d_mutex_lock();
+    wined3d_device_set_depth_stencil(device->wined3d_device, ds_impl ? ds_impl->wined3d_surface : NULL);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_GetDepthStencilSurface(IDirect3DDevice9Ex *iface, IDirect3DSurface9 **depth_stencil)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct wined3d_surface *wined3d_surface;
+    struct d3d9_surface *surface_impl;
+    HRESULT hr = D3D_OK;
+
+    TRACE("iface %p, depth_stencil %p.\n", iface, depth_stencil);
+
+    if (!depth_stencil)
+        return D3DERR_INVALIDCALL;
+
+    wined3d_mutex_lock();
+    if ((wined3d_surface = wined3d_device_get_depth_stencil(device->wined3d_device)))
+    {
+        surface_impl = wined3d_surface_get_parent(wined3d_surface);
+        *depth_stencil = &surface_impl->IDirect3DSurface9_iface;
+        IDirect3DSurface9_AddRef(*depth_stencil);
+    }
+    else
+    {
+        hr = WINED3DERR_NOTFOUND;
+        *depth_stencil = NULL;
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_BeginScene(IDirect3DDevice9Ex *iface)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    if (SUCCEEDED(hr = wined3d_device_begin_scene(device->wined3d_device)))
+        device->in_scene = TRUE;
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_EndScene(IDirect3DDevice9Ex *iface)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    if (SUCCEEDED(hr = wined3d_device_end_scene(device->wined3d_device)))
+        device->in_scene = FALSE;
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_Clear(IDirect3DDevice9Ex *iface, DWORD rect_count,
+        const D3DRECT *rects, DWORD flags, D3DCOLOR color, float z, DWORD stencil)
+{
+    const struct wined3d_color c =
+    {
+        ((color >> 16) & 0xff) / 255.0f,
+        ((color >>  8) & 0xff) / 255.0f,
+        (color & 0xff) / 255.0f,
+        ((color >> 24) & 0xff) / 255.0f,
+    };
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, rect_count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %u.\n",
+            iface, rect_count, rects, flags, color, z, stencil);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_clear(device->wined3d_device, rect_count, (const RECT *)rects, flags, &c, z, stencil);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_SetTransform(IDirect3DDevice9Ex *iface,
+        D3DTRANSFORMSTATETYPE state, const D3DMATRIX *matrix)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+
+    TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
+
+    /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
+    wined3d_mutex_lock();
+    wined3d_device_set_transform(device->wined3d_device, state, (const struct wined3d_matrix *)matrix);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_GetTransform(IDirect3DDevice9Ex *iface,
+        D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+
+    TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
+
+    /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
+    wined3d_mutex_lock();
+    wined3d_device_get_transform(device->wined3d_device, state, (struct wined3d_matrix *)matrix);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_MultiplyTransform(IDirect3DDevice9Ex *iface,
+        D3DTRANSFORMSTATETYPE state, const D3DMATRIX *matrix)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+
+    TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
+
+    /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
+    wined3d_mutex_lock();
+    wined3d_device_multiply_transform(device->wined3d_device, state, (const struct wined3d_matrix *)matrix);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_SetViewport(IDirect3DDevice9Ex *iface, const D3DVIEWPORT9 *viewport)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+
+    TRACE("iface %p, viewport %p.\n", iface, viewport);
+
+    /* Note: D3DVIEWPORT9 is compatible with struct wined3d_viewport. */
+    wined3d_mutex_lock();
+    wined3d_device_set_viewport(device->wined3d_device, (const struct wined3d_viewport *)viewport);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_GetViewport(IDirect3DDevice9Ex *iface, D3DVIEWPORT9 *viewport)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+
+    TRACE("iface %p, viewport %p.\n", iface, viewport);
+
+    /* Note: D3DVIEWPORT9 is compatible with struct wined3d_viewport. */
+    wined3d_mutex_lock();
+    wined3d_device_get_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_SetMaterial(IDirect3DDevice9Ex *iface, const D3DMATERIAL9 *material)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+
+    TRACE("iface %p, material %p.\n", iface, material);
+
+    /* Note: D3DMATERIAL9 is compatible with struct wined3d_material. */
+    wined3d_mutex_lock();
+    wined3d_device_set_material(device->wined3d_device, (const struct wined3d_material *)material);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_GetMaterial(IDirect3DDevice9Ex *iface, D3DMATERIAL9 *material)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+
+    TRACE("iface %p, material %p.\n", iface, material);
+
+    /* Note: D3DMATERIAL9 is compatible with struct wined3d_material. */
+    wined3d_mutex_lock();
+    wined3d_device_get_material(device->wined3d_device, (struct wined3d_material *)material);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_SetLight(IDirect3DDevice9Ex *iface, DWORD index, const D3DLIGHT9 *light)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, index %u, light %p.\n", iface, index, light);
+
+    /* Note: D3DLIGHT9 is compatible with struct wined3d_light. */
+    wined3d_mutex_lock();
+    hr = wined3d_device_set_light(device->wined3d_device, index, (const struct wined3d_light *)light);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_GetLight(IDirect3DDevice9Ex *iface, DWORD index, D3DLIGHT9 *light)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, index %u, light %p.\n", iface, index, light);
+
+    /* Note: D3DLIGHT9 is compatible with struct wined3d_light. */
+    wined3d_mutex_lock();
+    hr = wined3d_device_get_light(device->wined3d_device, index, (struct wined3d_light *)light);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_LightEnable(IDirect3DDevice9Ex *iface, DWORD index, BOOL enable)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, index %u, enable %#x.\n", iface, index, enable);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_set_light_enable(device->wined3d_device, index, enable);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_GetLightEnable(IDirect3DDevice9Ex *iface, DWORD index, BOOL *enable)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, index %u, enable %p.\n", iface, index, enable);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_get_light_enable(device->wined3d_device, index, enable);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_SetClipPlane(IDirect3DDevice9Ex *iface, DWORD index, const float *plane)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, index %u, plane %p.\n", iface, index, plane);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_set_clip_plane(device->wined3d_device, index, (const struct wined3d_vec4 *)plane);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_GetClipPlane(IDirect3DDevice9Ex *iface, DWORD index, float *plane)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, index %u, plane %p.\n", iface, index, plane);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_get_clip_plane(device->wined3d_device, index, (struct wined3d_vec4 *)plane);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_SetRenderState(IDirect3DDevice9Ex *iface,
+        D3DRENDERSTATETYPE state, DWORD value)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+
+    TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
+
+    wined3d_mutex_lock();
+    wined3d_device_set_render_state(device->wined3d_device, state, value);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_GetRenderState(IDirect3DDevice9Ex *iface,
+        D3DRENDERSTATETYPE state, DWORD *value)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+
+    TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
+
+    wined3d_mutex_lock();
+    *value = wined3d_device_get_render_state(device->wined3d_device, state);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_CreateStateBlock(IDirect3DDevice9Ex *iface,
+        D3DSTATEBLOCKTYPE type, IDirect3DStateBlock9 **stateblock)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_stateblock *object;
+    HRESULT hr;
+
+    TRACE("iface %p, type %#x, stateblock %p.\n", iface, type, stateblock);
+
+    if (type != D3DSBT_ALL && type != D3DSBT_PIXELSTATE && type != D3DSBT_VERTEXSTATE)
+    {
+        WARN("Unexpected stateblock type, returning D3DERR_INVALIDCALL.\n");
+        return D3DERR_INVALIDCALL;
+    }
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return E_OUTOFMEMORY;
+
+    hr = stateblock_init(object, device, type, NULL);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize stateblock, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created stateblock %p.\n", object);
+    *stateblock = &object->IDirect3DStateBlock9_iface;
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_BeginStateBlock(IDirect3DDevice9Ex *iface)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_begin_stateblock(device->wined3d_device);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_EndStateBlock(IDirect3DDevice9Ex *iface, IDirect3DStateBlock9 **stateblock)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct wined3d_stateblock *wined3d_stateblock;
+    struct d3d9_stateblock *object;
+    HRESULT hr;
+
+    TRACE("iface %p, stateblock %p.\n", iface, stateblock);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_end_stateblock(device->wined3d_device, &wined3d_stateblock);
+    wined3d_mutex_unlock();
+    if (FAILED(hr))
+    {
+       WARN("IWineD3DDevice_EndStateBlock() failed, hr %#x.\n", hr);
+       return hr;
+    }
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+    {
+        wined3d_mutex_lock();
+        wined3d_stateblock_decref(wined3d_stateblock);
+        wined3d_mutex_unlock();
+        return E_OUTOFMEMORY;
+    }
+
+    hr = stateblock_init(object, device, 0, wined3d_stateblock);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize stateblock, hr %#x.\n", hr);
+        wined3d_mutex_lock();
+        wined3d_stateblock_decref(wined3d_stateblock);
+        wined3d_mutex_unlock();
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created stateblock %p.\n", object);
+    *stateblock = &object->IDirect3DStateBlock9_iface;
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_SetClipStatus(IDirect3DDevice9Ex *iface, const D3DCLIPSTATUS9 *clip_status)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, clip_status %p.\n", iface, clip_status);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_set_clip_status(device->wined3d_device, (const struct wined3d_clip_status *)clip_status);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_GetClipStatus(IDirect3DDevice9Ex *iface, D3DCLIPSTATUS9 *clip_status)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, clip_status %p.\n", iface, clip_status);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_get_clip_status(device->wined3d_device, (struct wined3d_clip_status *)clip_status);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_GetTexture(IDirect3DDevice9Ex *iface, DWORD stage, IDirect3DBaseTexture9 **texture)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct wined3d_texture *wined3d_texture = NULL;
+    struct d3d9_texture *texture_impl;
+
+    TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
+
+    if (!texture)
+        return D3DERR_INVALIDCALL;
+
+    wined3d_mutex_lock();
+    if ((wined3d_texture = wined3d_device_get_texture(device->wined3d_device, stage)))
+    {
+        texture_impl = wined3d_texture_get_parent(wined3d_texture);
+        *texture = &texture_impl->IDirect3DBaseTexture9_iface;
+        IDirect3DBaseTexture9_AddRef(*texture);
+    }
+    else
+    {
+        *texture = NULL;
+    }
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_SetTexture(IDirect3DDevice9Ex *iface, DWORD stage, IDirect3DBaseTexture9 *texture)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_texture *texture_impl;
+    HRESULT hr;
+
+    TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
+
+    texture_impl = unsafe_impl_from_IDirect3DBaseTexture9(texture);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_set_texture(device->wined3d_device, stage,
+            texture_impl ? texture_impl->wined3d_texture : NULL);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static const enum wined3d_texture_stage_state tss_lookup[] =
+{
+    WINED3D_TSS_INVALID,                    /*  0, unused */
+    WINED3D_TSS_COLOR_OP,                   /*  1, D3DTSS_COLOROP */
+    WINED3D_TSS_COLOR_ARG1,                 /*  2, D3DTSS_COLORARG1 */
+    WINED3D_TSS_COLOR_ARG2,                 /*  3, D3DTSS_COLORARG2 */
+    WINED3D_TSS_ALPHA_OP,                   /*  4, D3DTSS_ALPHAOP */
+    WINED3D_TSS_ALPHA_ARG1,                 /*  5, D3DTSS_ALPHAARG1 */
+    WINED3D_TSS_ALPHA_ARG2,                 /*  6, D3DTSS_ALPHAARG2 */
+    WINED3D_TSS_BUMPENV_MAT00,              /*  7, D3DTSS_BUMPENVMAT00 */
+    WINED3D_TSS_BUMPENV_MAT01,              /*  8, D3DTSS_BUMPENVMAT01 */
+    WINED3D_TSS_BUMPENV_MAT10,              /*  9, D3DTSS_BUMPENVMAT10 */
+    WINED3D_TSS_BUMPENV_MAT11,              /* 10, D3DTSS_BUMPENVMAT11 */
+    WINED3D_TSS_TEXCOORD_INDEX,             /* 11, D3DTSS_TEXCOORDINDEX */
+    WINED3D_TSS_INVALID,                    /* 12, unused */
+    WINED3D_TSS_INVALID,                    /* 13, unused */
+    WINED3D_TSS_INVALID,                    /* 14, unused */
+    WINED3D_TSS_INVALID,                    /* 15, unused */
+    WINED3D_TSS_INVALID,                    /* 16, unused */
+    WINED3D_TSS_INVALID,                    /* 17, unused */
+    WINED3D_TSS_INVALID,                    /* 18, unused */
+    WINED3D_TSS_INVALID,                    /* 19, unused */
+    WINED3D_TSS_INVALID,                    /* 20, unused */
+    WINED3D_TSS_INVALID,                    /* 21, unused */
+    WINED3D_TSS_BUMPENV_LSCALE,             /* 22, D3DTSS_BUMPENVLSCALE */
+    WINED3D_TSS_BUMPENV_LOFFSET,            /* 23, D3DTSS_BUMPENVLOFFSET */
+    WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS,    /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
+    WINED3D_TSS_INVALID,                    /* 25, unused */
+    WINED3D_TSS_COLOR_ARG0,                 /* 26, D3DTSS_COLORARG0 */
+    WINED3D_TSS_ALPHA_ARG0,                 /* 27, D3DTSS_ALPHAARG0 */
+    WINED3D_TSS_RESULT_ARG,                 /* 28, D3DTSS_RESULTARG */
+    WINED3D_TSS_INVALID,                    /* 29, unused */
+    WINED3D_TSS_INVALID,                    /* 30, unused */
+    WINED3D_TSS_INVALID,                    /* 31, unused */
+    WINED3D_TSS_CONSTANT,                   /* 32, D3DTSS_CONSTANT */
+};
+
+static HRESULT WINAPI d3d9_device_GetTextureStageState(IDirect3DDevice9Ex *iface,
+        DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+
+    TRACE("iface %p, stage %u, state %#x, value %p.\n", iface, stage, state, value);
+
+    if (state >= sizeof(tss_lookup) / sizeof(*tss_lookup))
+    {
+        WARN("Invalid state %#x passed.\n", state);
+        return D3D_OK;
+    }
+
+    wined3d_mutex_lock();
+    *value = wined3d_device_get_texture_stage_state(device->wined3d_device, stage, tss_lookup[state]);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_SetTextureStageState(IDirect3DDevice9Ex *iface,
+        DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+
+    TRACE("iface %p, stage %u, state %#x, value %#x.\n", iface, stage, state, value);
+
+    if (state >= sizeof(tss_lookup) / sizeof(*tss_lookup))
+    {
+        WARN("Invalid state %#x passed.\n", state);
+        return D3D_OK;
+    }
+
+    wined3d_mutex_lock();
+    wined3d_device_set_texture_stage_state(device->wined3d_device, stage, tss_lookup[state], value);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_GetSamplerState(IDirect3DDevice9Ex *iface,
+        DWORD sampler, D3DSAMPLERSTATETYPE state, DWORD *value)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+
+    TRACE("iface %p, sampler %u, state %#x, value %p.\n", iface, sampler, state, value);
+
+    wined3d_mutex_lock();
+    *value = wined3d_device_get_sampler_state(device->wined3d_device, sampler, state);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_SetSamplerState(IDirect3DDevice9Ex *iface,
+        DWORD sampler, D3DSAMPLERSTATETYPE state, DWORD value)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+
+    TRACE("iface %p, sampler %u, state %#x, value %#x.\n", iface, sampler, state, value);
+
+    wined3d_mutex_lock();
+    wined3d_device_set_sampler_state(device->wined3d_device, sampler, state, value);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_ValidateDevice(IDirect3DDevice9Ex *iface, DWORD *pass_count)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, pass_count %p.\n", iface, pass_count);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_validate_device(device->wined3d_device, pass_count);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_SetPaletteEntries(IDirect3DDevice9Ex *iface,
+        UINT palette_idx, const PALETTEENTRY *entries)
+{
+    WARN("iface %p, palette_idx %u, entries %p unimplemented.\n", iface, palette_idx, entries);
+
+    /* The d3d9 palette API is non-functional on Windows. Getters and setters are implemented,
+     * and some drivers allow the creation of P8 surfaces. These surfaces can be copied to
+     * other P8 surfaces with StretchRect, but cannot be converted to (A)RGB.
+     *
+     * Some older(dx7) cards may have support for P8 textures, but games cannot rely on this. */
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_GetPaletteEntries(IDirect3DDevice9Ex *iface,
+        UINT palette_idx, PALETTEENTRY *entries)
+{
+    FIXME("iface %p, palette_idx %u, entries %p unimplemented.\n", iface, palette_idx, entries);
+
+    return D3DERR_INVALIDCALL;
+}
+
+static HRESULT WINAPI d3d9_device_SetCurrentTexturePalette(IDirect3DDevice9Ex *iface, UINT palette_idx)
+{
+    WARN("iface %p, palette_idx %u unimplemented.\n", iface, palette_idx);
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_GetCurrentTexturePalette(IDirect3DDevice9Ex *iface, UINT *palette_idx)
+{
+    FIXME("iface %p, palette_idx %p.\n", iface, palette_idx);
+
+    return D3DERR_INVALIDCALL;
+}
+
+static HRESULT WINAPI d3d9_device_SetScissorRect(IDirect3DDevice9Ex *iface, const RECT *rect)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+
+    TRACE("iface %p, rect %p.\n", iface, rect);
+
+    wined3d_mutex_lock();
+    wined3d_device_set_scissor_rect(device->wined3d_device, rect);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_GetScissorRect(IDirect3DDevice9Ex *iface, RECT *rect)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+
+    TRACE("iface %p, rect %p.\n", iface, rect);
+
+    wined3d_mutex_lock();
+    wined3d_device_get_scissor_rect(device->wined3d_device, rect);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_SetSoftwareVertexProcessing(IDirect3DDevice9Ex *iface, BOOL software)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+
+    TRACE("iface %p, software %#x.\n", iface, software);
+
+    wined3d_mutex_lock();
+    wined3d_device_set_software_vertex_processing(device->wined3d_device, software);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static BOOL WINAPI d3d9_device_GetSoftwareVertexProcessing(IDirect3DDevice9Ex *iface)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    BOOL ret;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    ret = wined3d_device_get_software_vertex_processing(device->wined3d_device);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static HRESULT WINAPI d3d9_device_SetNPatchMode(IDirect3DDevice9Ex *iface, float segment_count)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, segment_count %.8e.\n", iface, segment_count);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_set_npatch_mode(device->wined3d_device, segment_count);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static float WINAPI d3d9_device_GetNPatchMode(IDirect3DDevice9Ex *iface)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    float ret;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    ret = wined3d_device_get_npatch_mode(device->wined3d_device);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static HRESULT WINAPI d3d9_device_DrawPrimitive(IDirect3DDevice9Ex *iface,
+        D3DPRIMITIVETYPE primitive_type, UINT start_vertex, UINT primitive_count)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, primitive_type %#x, start_vertex %u, primitive_count %u.\n",
+            iface, primitive_type, start_vertex, primitive_count);
+
+    wined3d_mutex_lock();
+    wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
+    hr = wined3d_device_draw_primitive(device->wined3d_device, start_vertex,
+            vertex_count_from_primitive_count(primitive_type, primitive_count));
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_DrawIndexedPrimitive(IDirect3DDevice9Ex *iface,
+        D3DPRIMITIVETYPE primitive_type, INT base_vertex_idx, UINT min_vertex_idx,
+        UINT vertex_count, UINT start_idx, UINT primitive_count)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, primitive_type %#x, base_vertex_idx %u, min_vertex_idx %u,\n"
+            "vertex_count %u, start_idx %u, primitive_count %u.\n",
+            iface, primitive_type, base_vertex_idx, min_vertex_idx,
+            vertex_count, start_idx, primitive_count);
+
+    wined3d_mutex_lock();
+    wined3d_device_set_base_vertex_index(device->wined3d_device, base_vertex_idx);
+    wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
+    hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, start_idx,
+            vertex_count_from_primitive_count(primitive_type, primitive_count));
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static void STDMETHODCALLTYPE d3d9_null_wined3d_object_destroyed(void *parent) {}
+
+static const struct wined3d_parent_ops d3d9_null_wined3d_parent_ops =
+{
+    d3d9_null_wined3d_object_destroyed,
+};
+
+/* The caller is responsible for wined3d locking */
+static HRESULT d3d9_device_prepare_vertex_buffer(struct d3d9_device *device, UINT min_size)
+{
+    HRESULT hr;
+
+    if (device->vertex_buffer_size < min_size || !device->vertex_buffer)
+    {
+        UINT size = max(device->vertex_buffer_size * 2, min_size);
+        struct wined3d_buffer *buffer;
+
+        TRACE("Growing vertex buffer to %u bytes\n", size);
+
+        hr = wined3d_buffer_create_vb(device->wined3d_device, size, WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY,
+                WINED3D_POOL_DEFAULT, NULL, &d3d9_null_wined3d_parent_ops, &buffer);
+        if (FAILED(hr))
+        {
+            ERR("(%p) wined3d_buffer_create_vb failed with hr = %08x\n", device, hr);
+            return hr;
+        }
+
+        if (device->vertex_buffer)
+            wined3d_buffer_decref(device->vertex_buffer);
+
+        device->vertex_buffer = buffer;
+        device->vertex_buffer_size = size;
+        device->vertex_buffer_pos = 0;
+    }
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_DrawPrimitiveUP(IDirect3DDevice9Ex *iface,
+        D3DPRIMITIVETYPE primitive_type, UINT primitive_count, const void *data, UINT stride)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+    UINT vtx_count = vertex_count_from_primitive_count(primitive_type, primitive_count);
+    UINT size = vtx_count * stride;
+    UINT vb_pos, align;
+    BYTE *buffer_data;
+
+    TRACE("iface %p, primitive_type %#x, primitive_count %u, data %p, stride %u.\n",
+            iface, primitive_type, primitive_count, data, stride);
+
+    if (!primitive_count)
+    {
+        WARN("primitive_count is 0, returning D3D_OK\n");
+        return D3D_OK;
+    }
+
+    wined3d_mutex_lock();
+
+    hr = d3d9_device_prepare_vertex_buffer(device, size);
+    if (FAILED(hr))
+        goto done;
+
+    vb_pos = device->vertex_buffer_pos;
+    align = vb_pos % stride;
+    if (align) align = stride - align;
+    if (vb_pos + size + align > device->vertex_buffer_size)
+        vb_pos = 0;
+    else
+        vb_pos += align;
+
+    hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, size, &buffer_data,
+            vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
+    if (FAILED(hr))
+        goto done;
+    memcpy(buffer_data, data, size);
+    wined3d_buffer_unmap(device->vertex_buffer);
+    device->vertex_buffer_pos = vb_pos + size;
+
+    hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
+    if (FAILED(hr))
+        goto done;
+
+    wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
+    hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / stride, vtx_count);
+    wined3d_device_set_stream_source(device->wined3d_device, 0, NULL, 0, 0);
+
+done:
+    wined3d_mutex_unlock();
+    return hr;
+}
+
+/* The caller is responsible for wined3d locking */
+static HRESULT d3d9_device_prepare_index_buffer(struct d3d9_device *device, UINT min_size)
+{
+    HRESULT hr;
+
+    if (device->index_buffer_size < min_size || !device->index_buffer)
+    {
+        UINT size = max(device->index_buffer_size * 2, min_size);
+        struct wined3d_buffer *buffer;
+
+        TRACE("Growing index buffer to %u bytes\n", size);
+
+        hr = wined3d_buffer_create_ib(device->wined3d_device, size, WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY,
+                WINED3D_POOL_DEFAULT, NULL, &d3d9_null_wined3d_parent_ops, &buffer);
+        if (FAILED(hr))
+        {
+            ERR("(%p) wined3d_buffer_create_ib failed with hr = %08x\n", device, hr);
+            return hr;
+        }
+
+        if (device->index_buffer)
+            wined3d_buffer_decref(device->index_buffer);
+
+        device->index_buffer = buffer;
+        device->index_buffer_size = size;
+        device->index_buffer_pos = 0;
+    }
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_DrawIndexedPrimitiveUP(IDirect3DDevice9Ex *iface,
+        D3DPRIMITIVETYPE primitive_type, UINT min_vertex_idx, UINT vertex_count,
+        UINT primitive_count, const void *index_data, D3DFORMAT index_format,
+        const void *vertex_data, UINT vertex_stride)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+    BYTE *buffer_data;
+
+    UINT idx_count = vertex_count_from_primitive_count(primitive_type, primitive_count);
+    UINT idx_fmt_size = index_format == D3DFMT_INDEX16 ? 2 : 4;
+    UINT idx_size = idx_count * idx_fmt_size;
+    UINT ib_pos;
+
+    UINT vtx_size = vertex_count * vertex_stride;
+    UINT vb_pos, align;
+
+    TRACE("iface %p, primitive_type %#x, min_vertex_idx %u, vertex_count %u, primitive_count %u,\n"
+            "index_data %p, index_format %#x, vertex_data %p, vertex_stride %u.\n",
+            iface, primitive_type, min_vertex_idx, vertex_count, primitive_count,
+            index_data, index_format, vertex_data, vertex_stride);
+
+    if (!primitive_count)
+    {
+        WARN("primitive_count is 0, returning D3D_OK\n");
+        return D3D_OK;
+    }
+
+    wined3d_mutex_lock();
+
+    hr = d3d9_device_prepare_vertex_buffer(device, vtx_size);
+    if (FAILED(hr))
+        goto done;
+
+    vb_pos = device->vertex_buffer_pos;
+    align = vb_pos % vertex_stride;
+    if (align) align = vertex_stride - align;
+    if (vb_pos + vtx_size + align > device->vertex_buffer_size)
+        vb_pos = 0;
+    else
+        vb_pos += align;
+
+    hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, vtx_size, &buffer_data,
+            vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
+    if (FAILED(hr))
+        goto done;
+    memcpy(buffer_data, vertex_data, vtx_size);
+    wined3d_buffer_unmap(device->vertex_buffer);
+    device->vertex_buffer_pos = vb_pos + vtx_size;
+
+    hr = d3d9_device_prepare_index_buffer(device, idx_size);
+    if (FAILED(hr))
+        goto done;
+
+    ib_pos = device->index_buffer_pos;
+    align = ib_pos % idx_fmt_size;
+    if (align) align = idx_fmt_size - align;
+    if (ib_pos + idx_size + align > device->index_buffer_size)
+        ib_pos = 0;
+    else
+        ib_pos += align;
+
+    hr = wined3d_buffer_map(device->index_buffer, ib_pos, idx_size, &buffer_data,
+            ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
+    if (FAILED(hr))
+        goto done;
+    memcpy(buffer_data, index_data, idx_size);
+    wined3d_buffer_unmap(device->index_buffer);
+    device->index_buffer_pos = ib_pos + idx_size;
+
+    hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, vertex_stride);
+    if (FAILED(hr))
+        goto done;
+
+    wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer,
+            wined3dformat_from_d3dformat(index_format));
+    wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / vertex_stride);
+
+    wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
+    hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / idx_fmt_size, idx_count);
+
+    wined3d_device_set_stream_source(device->wined3d_device, 0, NULL, 0, 0);
+    wined3d_device_set_index_buffer(device->wined3d_device, NULL, WINED3DFMT_UNKNOWN);
+    wined3d_device_set_base_vertex_index(device->wined3d_device, 0);
+
+done:
+    wined3d_mutex_unlock();
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_ProcessVertices(IDirect3DDevice9Ex *iface,
+        UINT src_start_idx, UINT dst_idx, UINT vertex_count, IDirect3DVertexBuffer9 *dst_buffer,
+        IDirect3DVertexDeclaration9 *declaration, DWORD flags)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_vertexbuffer *dst_impl = unsafe_impl_from_IDirect3DVertexBuffer9(dst_buffer);
+    struct d3d9_vertex_declaration *decl_impl = unsafe_impl_from_IDirect3DVertexDeclaration9(declaration);
+    HRESULT hr;
+
+    TRACE("iface %p, src_start_idx %u, dst_idx %u, vertex_count %u, dst_buffer %p, declaration %p, flags %#x.\n",
+            iface, src_start_idx, dst_idx, vertex_count, dst_buffer, declaration, flags);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_process_vertices(device->wined3d_device, src_start_idx, dst_idx, vertex_count,
+            dst_impl->wined3d_buffer, decl_impl ? decl_impl->wined3d_declaration : NULL,
+            flags, dst_impl->fvf);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_CreateVertexDeclaration(IDirect3DDevice9Ex *iface,
+        const D3DVERTEXELEMENT9 *elements, IDirect3DVertexDeclaration9 **declaration)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_vertex_declaration *object;
+    HRESULT hr;
+
+    TRACE("iface %p, elements %p, declaration %p.\n", iface, elements, declaration);
+
+    if (!declaration)
+    {
+        WARN("Caller passed a NULL declaration, returning D3DERR_INVALIDCALL.\n");
+        return D3DERR_INVALIDCALL;
+    }
+
+    if (SUCCEEDED(hr = d3d9_vertex_declaration_create(device, elements, &object)))
+        *declaration = &object->IDirect3DVertexDeclaration9_iface;
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_SetVertexDeclaration(IDirect3DDevice9Ex *iface,
+        IDirect3DVertexDeclaration9 *declaration)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_vertex_declaration *decl_impl = unsafe_impl_from_IDirect3DVertexDeclaration9(declaration);
+
+    TRACE("iface %p, declaration %p.\n", iface, declaration);
+
+    wined3d_mutex_lock();
+    wined3d_device_set_vertex_declaration(device->wined3d_device,
+            decl_impl ? decl_impl->wined3d_declaration : NULL);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_GetVertexDeclaration(IDirect3DDevice9Ex *iface,
+        IDirect3DVertexDeclaration9 **declaration)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct wined3d_vertex_declaration *wined3d_declaration;
+    struct d3d9_vertex_declaration *declaration_impl;
+
+    TRACE("iface %p, declaration %p.\n", iface, declaration);
+
+    if (!declaration) return D3DERR_INVALIDCALL;
+
+    wined3d_mutex_lock();
+    if ((wined3d_declaration = wined3d_device_get_vertex_declaration(device->wined3d_device)))
+    {
+        declaration_impl = wined3d_vertex_declaration_get_parent(wined3d_declaration);
+        *declaration = &declaration_impl->IDirect3DVertexDeclaration9_iface;
+        IDirect3DVertexDeclaration9_AddRef(*declaration);
+    }
+    else
+    {
+        *declaration = NULL;
+    }
+    wined3d_mutex_unlock();
+
+    TRACE("Returning %p.\n", *declaration);
+    return D3D_OK;
+}
+
+static struct wined3d_vertex_declaration *device_get_fvf_declaration(struct d3d9_device *device, DWORD fvf)
+{
+    struct wined3d_vertex_declaration *wined3d_declaration;
+    struct fvf_declaration *fvf_decls = device->fvf_decls;
+    struct d3d9_vertex_declaration *d3d9_declaration;
+    D3DVERTEXELEMENT9 *elements;
+    int p, low, high; /* deliberately signed */
+    HRESULT hr;
+
+    TRACE("Searching for declaration for fvf %08x... ", fvf);
+
+    low = 0;
+    high = device->fvf_decl_count - 1;
+    while (low <= high)
+    {
+        p = (low + high) >> 1;
+        TRACE("%d ", p);
+
+        if (fvf_decls[p].fvf == fvf)
+        {
+            TRACE("found %p.\n", fvf_decls[p].decl);
+            return fvf_decls[p].decl;
+        }
+
+        if (fvf_decls[p].fvf < fvf)
+            low = p + 1;
+        else
+            high = p - 1;
+    }
+    TRACE("not found. Creating and inserting at position %d.\n", low);
+
+    if (FAILED(hr = vdecl_convert_fvf(fvf, &elements)))
+        return NULL;
+
+    hr = d3d9_vertex_declaration_create(device, elements, &d3d9_declaration);
+    HeapFree(GetProcessHeap(), 0, elements);
+    if (FAILED(hr))
+        return NULL;
+
+    if (device->fvf_decl_size == device->fvf_decl_count)
+    {
+        UINT grow = max(device->fvf_decl_size / 2, 8);
+
+        fvf_decls = HeapReAlloc(GetProcessHeap(), 0, fvf_decls, sizeof(*fvf_decls) * (device->fvf_decl_size + grow));
+        if (!fvf_decls)
+        {
+            IDirect3DVertexDeclaration9_Release(&d3d9_declaration->IDirect3DVertexDeclaration9_iface);
+            return NULL;
+        }
+        device->fvf_decls = fvf_decls;
+        device->fvf_decl_size += grow;
+    }
+
+    d3d9_declaration->fvf = fvf;
+    wined3d_declaration = d3d9_declaration->wined3d_declaration;
+    wined3d_vertex_declaration_incref(wined3d_declaration);
+    IDirect3DVertexDeclaration9_Release(&d3d9_declaration->IDirect3DVertexDeclaration9_iface);
+
+    memmove(fvf_decls + low + 1, fvf_decls + low, sizeof(*fvf_decls) * (device->fvf_decl_count - low));
+    fvf_decls[low].decl = wined3d_declaration;
+    fvf_decls[low].fvf = fvf;
+    ++device->fvf_decl_count;
+
+    TRACE("Returning %p. %u declatations in array.\n", wined3d_declaration, device->fvf_decl_count);
+
+    return wined3d_declaration;
+}
+
+static HRESULT WINAPI d3d9_device_SetFVF(IDirect3DDevice9Ex *iface, DWORD fvf)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct wined3d_vertex_declaration *decl;
+
+    TRACE("iface %p, fvf %#x.\n", iface, fvf);
+
+    if (!fvf)
+    {
+        WARN("%#x is not a valid FVF.\n", fvf);
+        return D3D_OK;
+    }
+
+    wined3d_mutex_lock();
+    if (!(decl = device_get_fvf_declaration(device, fvf)))
+    {
+        wined3d_mutex_unlock();
+        ERR("Failed to create a vertex declaration for fvf %#x.\n", fvf);
+        return D3DERR_DRIVERINTERNALERROR;
+    }
+
+    wined3d_device_set_vertex_declaration(device->wined3d_device, decl);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_GetFVF(IDirect3DDevice9Ex *iface, DWORD *fvf)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct wined3d_vertex_declaration *wined3d_declaration;
+    struct d3d9_vertex_declaration *d3d9_declaration;
+
+    TRACE("iface %p, fvf %p.\n", iface, fvf);
+
+    wined3d_mutex_lock();
+    if ((wined3d_declaration = wined3d_device_get_vertex_declaration(device->wined3d_device)))
+    {
+        d3d9_declaration = wined3d_vertex_declaration_get_parent(wined3d_declaration);
+        *fvf = d3d9_declaration->fvf;
+    }
+    else
+    {
+        *fvf = 0;
+    }
+    wined3d_mutex_unlock();
+
+    TRACE("Returning FVF %#x.\n", *fvf);
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_CreateVertexShader(IDirect3DDevice9Ex *iface,
+        const DWORD *byte_code, IDirect3DVertexShader9 **shader)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_vertexshader *object;
+    HRESULT hr;
+
+    TRACE("iface %p, byte_code %p, shader %p.\n", iface, byte_code, shader);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return E_OUTOFMEMORY;
+
+    hr = vertexshader_init(object, device, byte_code);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize vertex shader, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created vertex shader %p.\n", object);
+    *shader = &object->IDirect3DVertexShader9_iface;
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_SetVertexShader(IDirect3DDevice9Ex *iface, IDirect3DVertexShader9 *shader)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_vertexshader *shader_obj = unsafe_impl_from_IDirect3DVertexShader9(shader);
+
+    TRACE("iface %p, shader %p.\n", iface, shader);
+
+    wined3d_mutex_lock();
+    wined3d_device_set_vertex_shader(device->wined3d_device,
+            shader_obj ? shader_obj->wined3d_shader : NULL);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_GetVertexShader(IDirect3DDevice9Ex *iface, IDirect3DVertexShader9 **shader)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_vertexshader *shader_impl;
+    struct wined3d_shader *wined3d_shader;
+
+    TRACE("iface %p, shader %p.\n", iface, shader);
+
+    wined3d_mutex_lock();
+    if ((wined3d_shader = wined3d_device_get_vertex_shader(device->wined3d_device)))
+    {
+        shader_impl = wined3d_shader_get_parent(wined3d_shader);
+        *shader = &shader_impl->IDirect3DVertexShader9_iface;
+        IDirect3DVertexShader9_AddRef(*shader);
+    }
+    else
+    {
+        *shader = NULL;
+    }
+    wined3d_mutex_unlock();
+
+    TRACE("Returning %p.\n", *shader);
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_SetVertexShaderConstantF(IDirect3DDevice9Ex *iface,
+        UINT reg_idx, const float *data, UINT count)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
+
+    if (reg_idx + count > D3D9_MAX_VERTEX_SHADER_CONSTANTF)
+    {
+        WARN("Trying to access %u constants, but d3d9 only supports %u\n",
+             reg_idx + count, D3D9_MAX_VERTEX_SHADER_CONSTANTF);
+        return D3DERR_INVALIDCALL;
+    }
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_set_vs_consts_f(device->wined3d_device, reg_idx, data, count);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_GetVertexShaderConstantF(IDirect3DDevice9Ex *iface,
+        UINT reg_idx, float *data, UINT count)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
+
+    if (reg_idx + count > D3D9_MAX_VERTEX_SHADER_CONSTANTF)
+    {
+        WARN("Trying to access %u constants, but d3d9 only supports %u\n",
+             reg_idx + count, D3D9_MAX_VERTEX_SHADER_CONSTANTF);
+        return D3DERR_INVALIDCALL;
+    }
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_get_vs_consts_f(device->wined3d_device, reg_idx, data, count);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_SetVertexShaderConstantI(IDirect3DDevice9Ex *iface,
+        UINT reg_idx, const int *data, UINT count)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_set_vs_consts_i(device->wined3d_device, reg_idx, data, count);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_GetVertexShaderConstantI(IDirect3DDevice9Ex *iface,
+        UINT reg_idx, int *data, UINT count)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_get_vs_consts_i(device->wined3d_device, reg_idx, data, count);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_SetVertexShaderConstantB(IDirect3DDevice9Ex *iface,
+        UINT reg_idx, const BOOL *data, UINT count)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_set_vs_consts_b(device->wined3d_device, reg_idx, data, count);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_GetVertexShaderConstantB(IDirect3DDevice9Ex *iface,
+        UINT reg_idx, BOOL *data, UINT count)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_get_vs_consts_b(device->wined3d_device, reg_idx, data, count);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_SetStreamSource(IDirect3DDevice9Ex *iface,
+        UINT stream_idx, IDirect3DVertexBuffer9 *buffer, UINT offset, UINT stride)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_vertexbuffer *buffer_impl = unsafe_impl_from_IDirect3DVertexBuffer9(buffer);
+    HRESULT hr;
+
+    TRACE("iface %p, stream_idx %u, buffer %p, offset %u, stride %u.\n",
+            iface, stream_idx, buffer, offset, stride);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_set_stream_source(device->wined3d_device, stream_idx,
+            buffer_impl ? buffer_impl->wined3d_buffer : NULL, offset, stride);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_GetStreamSource(IDirect3DDevice9Ex *iface,
+        UINT stream_idx, IDirect3DVertexBuffer9 **buffer, UINT *offset, UINT *stride)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_vertexbuffer *buffer_impl;
+    struct wined3d_buffer *wined3d_buffer;
+    HRESULT hr;
+
+    TRACE("iface %p, stream_idx %u, buffer %p, offset %p, stride %p.\n",
+            iface, stream_idx, buffer, offset, stride);
+
+    if (!buffer)
+        return D3DERR_INVALIDCALL;
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_get_stream_source(device->wined3d_device, stream_idx, &wined3d_buffer, offset, stride);
+    if (SUCCEEDED(hr) && wined3d_buffer)
+    {
+        buffer_impl = wined3d_buffer_get_parent(wined3d_buffer);
+        *buffer = &buffer_impl->IDirect3DVertexBuffer9_iface;
+        IDirect3DVertexBuffer9_AddRef(*buffer);
+        wined3d_buffer_decref(wined3d_buffer);
+    }
+    else
+    {
+        if (FAILED(hr))
+            FIXME("Call to GetStreamSource failed %p %p\n", offset, stride);
+        *buffer = NULL;
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_SetStreamSourceFreq(IDirect3DDevice9Ex *iface, UINT stream_idx, UINT freq)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, stream_idx %u, freq %u.\n", iface, stream_idx, freq);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_set_stream_source_freq(device->wined3d_device, stream_idx, freq);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_GetStreamSourceFreq(IDirect3DDevice9Ex *iface, UINT stream_idx, UINT *freq)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, stream_idx %u, freq %p.\n", iface, stream_idx, freq);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_get_stream_source_freq(device->wined3d_device, stream_idx, freq);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_SetIndices(IDirect3DDevice9Ex *iface, IDirect3DIndexBuffer9 *buffer)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_indexbuffer *ib = unsafe_impl_from_IDirect3DIndexBuffer9(buffer);
+
+    TRACE("iface %p, buffer %p.\n", iface, buffer);
+
+    wined3d_mutex_lock();
+    wined3d_device_set_index_buffer(device->wined3d_device,
+            ib ? ib->wined3d_buffer : NULL,
+            ib ? ib->format : WINED3DFMT_UNKNOWN);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_GetIndices(IDirect3DDevice9Ex *iface, IDirect3DIndexBuffer9 **buffer)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    enum wined3d_format_id wined3d_format;
+    struct wined3d_buffer *wined3d_buffer;
+    struct d3d9_indexbuffer *buffer_impl;
+
+    TRACE("iface %p, buffer %p.\n", iface, buffer);
+
+    if (!buffer)
+        return D3DERR_INVALIDCALL;
+
+    wined3d_mutex_lock();
+    if ((wined3d_buffer = wined3d_device_get_index_buffer(device->wined3d_device, &wined3d_format)))
+    {
+        buffer_impl = wined3d_buffer_get_parent(wined3d_buffer);
+        *buffer = &buffer_impl->IDirect3DIndexBuffer9_iface;
+        IDirect3DIndexBuffer9_AddRef(*buffer);
+    }
+    else
+    {
+        *buffer = NULL;
+    }
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_CreatePixelShader(IDirect3DDevice9Ex *iface,
+        const DWORD *byte_code, IDirect3DPixelShader9 **shader)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_pixelshader *object;
+    HRESULT hr;
+
+    TRACE("iface %p, byte_code %p, shader %p.\n", iface, byte_code, shader);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+    {
+        FIXME("Failed to allocate pixel shader memory.\n");
+        return E_OUTOFMEMORY;
+    }
+
+    hr = pixelshader_init(object, device, byte_code);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize pixel shader, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created pixel shader %p.\n", object);
+    *shader = &object->IDirect3DPixelShader9_iface;
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_SetPixelShader(IDirect3DDevice9Ex *iface, IDirect3DPixelShader9 *shader)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_pixelshader *shader_obj = unsafe_impl_from_IDirect3DPixelShader9(shader);
+
+    TRACE("iface %p, shader %p.\n", iface, shader);
+
+    wined3d_mutex_lock();
+    wined3d_device_set_pixel_shader(device->wined3d_device,
+            shader_obj ? shader_obj->wined3d_shader : NULL);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_GetPixelShader(IDirect3DDevice9Ex *iface, IDirect3DPixelShader9 **shader)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_pixelshader *shader_impl;
+    struct wined3d_shader *wined3d_shader;
+
+    TRACE("iface %p, shader %p.\n", iface, shader);
+
+    if (!shader) return D3DERR_INVALIDCALL;
+
+    wined3d_mutex_lock();
+    if ((wined3d_shader = wined3d_device_get_pixel_shader(device->wined3d_device)))
+    {
+        shader_impl = wined3d_shader_get_parent(wined3d_shader);
+        *shader = &shader_impl->IDirect3DPixelShader9_iface;
+        IDirect3DPixelShader9_AddRef(*shader);
+    }
+    else
+    {
+        *shader = NULL;
+    }
+    wined3d_mutex_unlock();
+
+    TRACE("Returning %p.\n", *shader);
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_SetPixelShaderConstantF(IDirect3DDevice9Ex *iface,
+        UINT reg_idx, const float *data, UINT count)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_set_ps_consts_f(device->wined3d_device, reg_idx, data, count);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_GetPixelShaderConstantF(IDirect3DDevice9Ex *iface,
+        UINT reg_idx, float *data, UINT count)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_get_ps_consts_f(device->wined3d_device, reg_idx, data, count);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_SetPixelShaderConstantI(IDirect3DDevice9Ex *iface,
+        UINT reg_idx, const int *data, UINT count)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_set_ps_consts_i(device->wined3d_device, reg_idx, data, count);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_GetPixelShaderConstantI(IDirect3DDevice9Ex *iface,
+        UINT reg_idx, int *data, UINT count)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_get_ps_consts_i(device->wined3d_device, reg_idx, data, count);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_SetPixelShaderConstantB(IDirect3DDevice9Ex *iface,
+        UINT reg_idx, const BOOL *data, UINT count)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_set_ps_consts_b(device->wined3d_device, reg_idx, data, count);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_GetPixelShaderConstantB(IDirect3DDevice9Ex *iface,
+        UINT reg_idx, BOOL *data, UINT count)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_get_ps_consts_b(device->wined3d_device, reg_idx, data, count);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_DrawRectPatch(IDirect3DDevice9Ex *iface, UINT handle,
+        const float *segment_count, const D3DRECTPATCH_INFO *patch_info)
+{
+    FIXME("iface %p, handle %#x, segment_count %p, patch_info %p unimplemented.\n",
+            iface, handle, segment_count, patch_info);
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_DrawTriPatch(IDirect3DDevice9Ex *iface, UINT handle,
+        const float *segment_count, const D3DTRIPATCH_INFO *patch_info)
+{
+    FIXME("iface %p, handle %#x, segment_count %p, patch_info %p unimplemented.\n",
+            iface, handle, segment_count, patch_info);
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_DeletePatch(IDirect3DDevice9Ex *iface, UINT handle)
+{
+    FIXME("iface %p, handle %#x unimplemented.\n", iface, handle);
+    return D3DERR_INVALIDCALL;
+}
+
+static HRESULT WINAPI d3d9_device_CreateQuery(IDirect3DDevice9Ex *iface, D3DQUERYTYPE type, IDirect3DQuery9 **query)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_query *object;
+    HRESULT hr;
+
+    TRACE("iface %p, type %#x, query %p.\n", iface, type, query);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return E_OUTOFMEMORY;
+
+    hr = query_init(object, device, type);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize query, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created query %p.\n", object);
+    if (query) *query = &object->IDirect3DQuery9_iface;
+    else IDirect3DQuery9_Release(&object->IDirect3DQuery9_iface);
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_SetConvolutionMonoKernel(IDirect3DDevice9Ex *iface,
+        UINT width, UINT height, float *rows, float *columns)
+{
+    FIXME("iface %p, width %u, height %u, rows %p, columns %p stub!\n",
+            iface, width, height, rows, columns);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3d9_device_ComposeRects(IDirect3DDevice9Ex *iface,
+        IDirect3DSurface9 *src_surface, IDirect3DSurface9 *dst_surface, IDirect3DVertexBuffer9 *src_descs,
+        UINT rect_count, IDirect3DVertexBuffer9 *dst_descs, D3DCOMPOSERECTSOP operation, INT offset_x, INT offset_y)
+{
+    FIXME("iface %p, src_surface %p, dst_surface %p, src_descs %p, rect_count %u,\n"
+            "dst_descs %p, operation %#x, offset_x %u, offset_y %u stub!\n",
+            iface, src_surface, dst_surface, src_descs, rect_count,
+            dst_descs, operation, offset_x, offset_y);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3d9_device_PresentEx(IDirect3DDevice9Ex *iface,
+        const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override,
+        const RGNDATA *dirty_region, DWORD flags)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, src_rect %s, dst_rect %s, dst_window_override %p, dirty_region %p, flags %#x.\n",
+            iface, wine_dbgstr_rect(src_rect), wine_dbgstr_rect(dst_rect),
+            dst_window_override, dirty_region, flags);
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_present(device->wined3d_device, src_rect, dst_rect,
+            dst_window_override, dirty_region, flags);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_GetGPUThreadPriority(IDirect3DDevice9Ex *iface, INT *priority)
+{
+    FIXME("iface %p, priority %p stub!\n", iface, priority);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3d9_device_SetGPUThreadPriority(IDirect3DDevice9Ex *iface, INT priority)
+{
+    FIXME("iface %p, priority %d stub!\n", iface, priority);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3d9_device_WaitForVBlank(IDirect3DDevice9Ex *iface, UINT swapchain_idx)
+{
+    FIXME("iface %p, swapchain_idx %u stub!\n", iface, swapchain_idx);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3d9_device_CheckResourceResidency(IDirect3DDevice9Ex *iface,
+        IDirect3DResource9 **resources, UINT32 resource_count)
+{
+    FIXME("iface %p, resources %p, resource_count %u stub!\n",
+            iface, resources, resource_count);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3d9_device_SetMaximumFrameLatency(IDirect3DDevice9Ex *iface, UINT max_latency)
+{
+    FIXME("iface %p, max_latency %u stub!\n", iface, max_latency);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3d9_device_GetMaximumFrameLatency(IDirect3DDevice9Ex *iface, UINT *max_latency)
+{
+    FIXME("iface %p, max_latency %p stub!\n", iface, max_latency);
+
+    *max_latency = 2;
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3d9_device_CheckDeviceState(IDirect3DDevice9Ex *iface, HWND dst_window)
+{
+    static int i;
+
+    TRACE("iface %p, dst_window %p stub!\n", iface, dst_window);
+
+    if (!i++)
+        FIXME("iface %p, dst_window %p stub!\n", iface, dst_window);
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_device_CreateRenderTargetEx(IDirect3DDevice9Ex *iface,
+        UINT width, UINT height, D3DFORMAT format, D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality,
+        BOOL lockable, IDirect3DSurface9 **surface, HANDLE *shared_handle, DWORD usage)
+{
+    FIXME("iface %p, width %u, height %u, format %#x, multisample_type %#x, multisample_quality %u,\n"
+            "lockable %#x, surface %p, shared_handle %p, usage %#x stub!\n",
+            iface, width, height, format, multisample_type, multisample_quality,
+            lockable, surface, shared_handle, usage);
+
+    if (shared_handle)
+        FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3d9_device_CreateOffscreenPlainSurfaceEx(IDirect3DDevice9Ex *iface,
+        UINT width, UINT height, D3DFORMAT format, D3DPOOL pool, IDirect3DSurface9 **surface,
+        HANDLE *shared_handle, DWORD usage)
+{
+    FIXME("iface %p, width %u, height %u, format %#x, pool %#x, surface %p, shared_handle %p, usage %#x stub!\n",
+            iface, width, height, format, pool, surface, shared_handle, usage);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3d9_device_CreateDepthStencilSurfaceEx(IDirect3DDevice9Ex *iface,
+        UINT width, UINT height, D3DFORMAT format, D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality,
+        BOOL discard, IDirect3DSurface9 **surface, HANDLE *shared_handle, DWORD usage)
+{
+    FIXME("iface %p, width %u, height %u, format %#x, multisample_type %#x, multisample_quality %u,\n"
+            "discard %#x, surface %p, shared_handle %p, usage %#x stub!\n",
+            iface, width, height, format, multisample_type, multisample_quality,
+            discard, surface, shared_handle, usage);
+
+    if (shared_handle)
+        FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3d9_device_ResetEx(IDirect3DDevice9Ex *iface,
+        D3DPRESENT_PARAMETERS *present_parameters, D3DDISPLAYMODEEX *mode)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct wined3d_swapchain_desc swapchain_desc;
+    struct wined3d_display_mode wined3d_mode;
+    HRESULT hr;
+
+    TRACE("iface %p, present_parameters %p, mode %p.\n", iface, present_parameters, mode);
+
+    if (mode)
+    {
+        wined3d_mode.width = mode->Width;
+        wined3d_mode.height = mode->Height;
+        wined3d_mode.refresh_rate = mode->RefreshRate;
+        wined3d_mode.format_id = wined3dformat_from_d3dformat(mode->Format);
+        wined3d_mode.scanline_ordering = mode->ScanLineOrdering;
+    }
+
+    wined3d_mutex_lock();
+
+    if (device->vertex_buffer)
+    {
+        wined3d_buffer_decref(device->vertex_buffer);
+        device->vertex_buffer = NULL;
+        device->vertex_buffer_size = 0;
+    }
+    if (device->index_buffer)
+    {
+        wined3d_buffer_decref(device->index_buffer);
+        device->index_buffer = NULL;
+        device->index_buffer_size = 0;
+    }
+
+    wined3d_swapchain_desc_from_present_parameters(&swapchain_desc, present_parameters);
+    hr = wined3d_device_reset(device->wined3d_device, &swapchain_desc,
+            mode ? &wined3d_mode : NULL, reset_enum_callback, FALSE);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_device_GetDisplayModeEx(IDirect3DDevice9Ex *iface,
+        UINT swapchain_idx, D3DDISPLAYMODEEX *mode, D3DDISPLAYROTATION *rotation)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct wined3d_display_mode wined3d_mode;
+    HRESULT hr;
+
+    TRACE("iface %p, swapchain_idx %u, mode %p, rotation %p.\n",
+            iface, swapchain_idx, mode, rotation);
+
+    if (mode->Size != sizeof(*mode))
+        return D3DERR_INVALIDCALL;
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_get_display_mode(device->wined3d_device, swapchain_idx, &wined3d_mode,
+            (enum wined3d_display_rotation *)rotation);
+    wined3d_mutex_unlock();
+
+    if (SUCCEEDED(hr))
+    {
+        mode->Width = wined3d_mode.width;
+        mode->Height = wined3d_mode.height;
+        mode->RefreshRate = wined3d_mode.refresh_rate;
+        mode->Format = d3dformat_from_wined3dformat(wined3d_mode.format_id);
+        mode->ScanLineOrdering = wined3d_mode.scanline_ordering;
+    }
+
+    return hr;
+}
+
+static const struct IDirect3DDevice9ExVtbl d3d9_device_vtbl =
+{
+    /* IUnknown */
+    d3d9_device_QueryInterface,
+    d3d9_device_AddRef,
+    d3d9_device_Release,
+    /* IDirect3DDevice9 */
+    d3d9_device_TestCooperativeLevel,
+    d3d9_device_GetAvailableTextureMem,
+    d3d9_device_EvictManagedResources,
+    d3d9_device_GetDirect3D,
+    d3d9_device_GetDeviceCaps,
+    d3d9_device_GetDisplayMode,
+    d3d9_device_GetCreationParameters,
+    d3d9_device_SetCursorProperties,
+    d3d9_device_SetCursorPosition,
+    d3d9_device_ShowCursor,
+    d3d9_device_CreateAdditionalSwapChain,
+    d3d9_device_GetSwapChain,
+    d3d9_device_GetNumberOfSwapChains,
+    d3d9_device_Reset,
+    d3d9_device_Present,
+    d3d9_device_GetBackBuffer,
+    d3d9_device_GetRasterStatus,
+    d3d9_device_SetDialogBoxMode,
+    d3d9_device_SetGammaRamp,
+    d3d9_device_GetGammaRamp,
+    d3d9_device_CreateTexture,
+    d3d9_device_CreateVolumeTexture,
+    d3d9_device_CreateCubeTexture,
+    d3d9_device_CreateVertexBuffer,
+    d3d9_device_CreateIndexBuffer,
+    d3d9_device_CreateRenderTarget,
+    d3d9_device_CreateDepthStencilSurface,
+    d3d9_device_UpdateSurface,
+    d3d9_device_UpdateTexture,
+    d3d9_device_GetRenderTargetData,
+    d3d9_device_GetFrontBufferData,
+    d3d9_device_StretchRect,
+    d3d9_device_ColorFill,
+    d3d9_device_CreateOffscreenPlainSurface,
+    d3d9_device_SetRenderTarget,
+    d3d9_device_GetRenderTarget,
+    d3d9_device_SetDepthStencilSurface,
+    d3d9_device_GetDepthStencilSurface,
+    d3d9_device_BeginScene,
+    d3d9_device_EndScene,
+    d3d9_device_Clear,
+    d3d9_device_SetTransform,
+    d3d9_device_GetTransform,
+    d3d9_device_MultiplyTransform,
+    d3d9_device_SetViewport,
+    d3d9_device_GetViewport,
+    d3d9_device_SetMaterial,
+    d3d9_device_GetMaterial,
+    d3d9_device_SetLight,
+    d3d9_device_GetLight,
+    d3d9_device_LightEnable,
+    d3d9_device_GetLightEnable,
+    d3d9_device_SetClipPlane,
+    d3d9_device_GetClipPlane,
+    d3d9_device_SetRenderState,
+    d3d9_device_GetRenderState,
+    d3d9_device_CreateStateBlock,
+    d3d9_device_BeginStateBlock,
+    d3d9_device_EndStateBlock,
+    d3d9_device_SetClipStatus,
+    d3d9_device_GetClipStatus,
+    d3d9_device_GetTexture,
+    d3d9_device_SetTexture,
+    d3d9_device_GetTextureStageState,
+    d3d9_device_SetTextureStageState,
+    d3d9_device_GetSamplerState,
+    d3d9_device_SetSamplerState,
+    d3d9_device_ValidateDevice,
+    d3d9_device_SetPaletteEntries,
+    d3d9_device_GetPaletteEntries,
+    d3d9_device_SetCurrentTexturePalette,
+    d3d9_device_GetCurrentTexturePalette,
+    d3d9_device_SetScissorRect,
+    d3d9_device_GetScissorRect,
+    d3d9_device_SetSoftwareVertexProcessing,
+    d3d9_device_GetSoftwareVertexProcessing,
+    d3d9_device_SetNPatchMode,
+    d3d9_device_GetNPatchMode,
+    d3d9_device_DrawPrimitive,
+    d3d9_device_DrawIndexedPrimitive,
+    d3d9_device_DrawPrimitiveUP,
+    d3d9_device_DrawIndexedPrimitiveUP,
+    d3d9_device_ProcessVertices,
+    d3d9_device_CreateVertexDeclaration,
+    d3d9_device_SetVertexDeclaration,
+    d3d9_device_GetVertexDeclaration,
+    d3d9_device_SetFVF,
+    d3d9_device_GetFVF,
+    d3d9_device_CreateVertexShader,
+    d3d9_device_SetVertexShader,
+    d3d9_device_GetVertexShader,
+    d3d9_device_SetVertexShaderConstantF,
+    d3d9_device_GetVertexShaderConstantF,
+    d3d9_device_SetVertexShaderConstantI,
+    d3d9_device_GetVertexShaderConstantI,
+    d3d9_device_SetVertexShaderConstantB,
+    d3d9_device_GetVertexShaderConstantB,
+    d3d9_device_SetStreamSource,
+    d3d9_device_GetStreamSource,
+    d3d9_device_SetStreamSourceFreq,
+    d3d9_device_GetStreamSourceFreq,
+    d3d9_device_SetIndices,
+    d3d9_device_GetIndices,
+    d3d9_device_CreatePixelShader,
+    d3d9_device_SetPixelShader,
+    d3d9_device_GetPixelShader,
+    d3d9_device_SetPixelShaderConstantF,
+    d3d9_device_GetPixelShaderConstantF,
+    d3d9_device_SetPixelShaderConstantI,
+    d3d9_device_GetPixelShaderConstantI,
+    d3d9_device_SetPixelShaderConstantB,
+    d3d9_device_GetPixelShaderConstantB,
+    d3d9_device_DrawRectPatch,
+    d3d9_device_DrawTriPatch,
+    d3d9_device_DeletePatch,
+    d3d9_device_CreateQuery,
+    /* IDirect3DDevice9Ex */
+    d3d9_device_SetConvolutionMonoKernel,
+    d3d9_device_ComposeRects,
+    d3d9_device_PresentEx,
+    d3d9_device_GetGPUThreadPriority,
+    d3d9_device_SetGPUThreadPriority,
+    d3d9_device_WaitForVBlank,
+    d3d9_device_CheckResourceResidency,
+    d3d9_device_SetMaximumFrameLatency,
+    d3d9_device_GetMaximumFrameLatency,
+    d3d9_device_CheckDeviceState,
+    d3d9_device_CreateRenderTargetEx,
+    d3d9_device_CreateOffscreenPlainSurfaceEx,
+    d3d9_device_CreateDepthStencilSurfaceEx,
+    d3d9_device_ResetEx,
+    d3d9_device_GetDisplayModeEx,
+};
+
+static inline struct d3d9_device *device_from_device_parent(struct wined3d_device_parent *device_parent)
+{
+    return CONTAINING_RECORD(device_parent, struct d3d9_device, device_parent);
+}
+
+static void CDECL device_parent_wined3d_device_created(struct wined3d_device_parent *device_parent,
+        struct wined3d_device *device)
+{
+    TRACE("device_parent %p, device %p.\n", device_parent, device);
+}
+
+static void CDECL device_parent_mode_changed(struct wined3d_device_parent *device_parent)
+{
+    TRACE("device_parent %p.\n", device_parent);
+}
+
+static HRESULT CDECL device_parent_create_texture_surface(struct wined3d_device_parent *device_parent,
+        void *container_parent, const struct wined3d_resource_desc *desc, UINT sub_resource_idx,
+        DWORD flags, struct wined3d_surface **surface
+#ifdef VBOX_WITH_WDDM
+        , HANDLE *shared_handle
+        , void *pvClientMem
+#endif
+        )
+{
+    struct d3d9_device *device = device_from_device_parent(device_parent);
+    struct d3d9_surface *d3d_surface;
+    HRESULT hr;
+
+    TRACE("device_parent %p, container_parent %p, desc %p, sub_resource_idx %u, flags %#x, surface %p.\n",
+            device_parent, container_parent, desc, sub_resource_idx, flags, surface);
+
+#ifdef VBOX_WITH_WDDM
+    if (FAILED(hr = d3d9_device_create_surface(device, desc->width, desc->height,
+            d3dformat_from_wined3dformat(desc->format), flags, (IDirect3DSurface9 **)&d3d_surface,
+            desc->usage, desc->pool, desc->multisample_type, desc->multisample_quality
+            , shared_handle
+            , pvClientMem
+            )))
+#else
+    if (FAILED(hr = d3d9_device_create_surface(device, desc->width, desc->height,
+            d3dformat_from_wined3dformat(desc->format), flags, (IDirect3DSurface9 **)&d3d_surface,
+            desc->usage, desc->pool, desc->multisample_type, desc->multisample_quality)))
+#endif
+    {
+        WARN("Failed to create surface, hr %#x.\n", hr);
+        return hr;
+    }
+
+    *surface = d3d_surface->wined3d_surface;
+    wined3d_surface_incref(*surface);
+
+    d3d_surface->container = container_parent;
+    IDirect3DDevice9Ex_Release(d3d_surface->parent_device);
+    d3d_surface->parent_device = NULL;
+
+    IDirect3DSurface9_Release(&d3d_surface->IDirect3DSurface9_iface);
+    d3d_surface->forwardReference = container_parent;
+
+    return hr;
+}
+
+static HRESULT CDECL device_parent_create_swapchain_surface(struct wined3d_device_parent *device_parent,
+        void *container_parent, const struct wined3d_resource_desc *desc, struct wined3d_surface **surface)
+{
+    struct d3d9_device *device = device_from_device_parent(device_parent);
+    struct wined3d_resource_desc texture_desc;
+    struct d3d9_surface *d3d_surface;
+    struct wined3d_texture *texture;
+    HRESULT hr;
+
+    TRACE("device_parent %p, container_parent %p, desc %p, surface %p.\n",
+            device_parent, container_parent, desc, surface);
+
+    if (container_parent == device_parent)
+        container_parent = &device->IDirect3DDevice9Ex_iface;
+
+    texture_desc = *desc;
+    texture_desc.resource_type = WINED3D_RTYPE_TEXTURE;
+#ifdef VBOX_WITH_WDDM
+    if (FAILED(hr = wined3d_texture_create_2d(device->wined3d_device, &texture_desc, 1,
+            WINED3D_SURFACE_MAPPABLE, container_parent, &d3d9_null_wined3d_parent_ops, &texture
+            , NULL, NULL)))
+#else
+    if (FAILED(hr = wined3d_texture_create_2d(device->wined3d_device, &texture_desc, 1,
+            WINED3D_SURFACE_MAPPABLE, container_parent, &d3d9_null_wined3d_parent_ops, &texture)))
+#endif
+    {
+        WARN("Failed to create texture, hr %#x.\n", hr);
+        return hr;
+    }
+
+    *surface = wined3d_surface_from_resource(wined3d_texture_get_sub_resource(texture, 0));
+    wined3d_surface_incref(*surface);
+    wined3d_texture_decref(texture);
+
+    d3d_surface = wined3d_surface_get_parent(*surface);
+    d3d_surface->forwardReference = NULL;
+    d3d_surface->parent_device = &device->IDirect3DDevice9Ex_iface;
+    return hr;
+}
+
+static HRESULT CDECL device_parent_create_volume(struct wined3d_device_parent *device_parent,
+        void *container_parent, UINT width, UINT height, UINT depth, enum wined3d_format_id format,
+        enum wined3d_pool pool, DWORD usage, struct wined3d_volume **volume
+#ifdef VBOX_WITH_WDDM
+        , HANDLE *shared_handle
+        , void *pvClientMem
+#endif
+        )
+{
+    struct d3d9_device *device = device_from_device_parent(device_parent);
+    struct d3d9_volume *object;
+    HRESULT hr;
+
+    TRACE("device_parent %p, container_parent %p, width %u, height %u, depth %u, "
+            "format %#x, pool %#x, usage %#x, volume %p\n",
+            device_parent, container_parent, width, height, depth,
+            format, pool, usage, volume);
+
+    /* Allocate the storage for the device */
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+    {
+        FIXME("Allocation of memory failed\n");
+        *volume = NULL;
+        return D3DERR_OUTOFVIDEOMEMORY;
+    }
+
+    hr = volume_init(object, device, width, height, depth, usage, format, pool
+#ifdef VBOX_WITH_WDDM
+        , shared_handle
+        , pvClientMem
+#endif
+        );
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize volume, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    *volume = object->wined3d_volume;
+    wined3d_volume_incref(*volume);
+    IDirect3DVolume9_Release(&object->IDirect3DVolume9_iface);
+
+    object->container = container_parent;
+    object->forwardReference = container_parent;
+
+    TRACE("Created volume %p.\n", object);
+
+    return hr;
+}
+
+static HRESULT CDECL device_parent_create_swapchain(struct wined3d_device_parent *device_parent,
+        struct wined3d_swapchain_desc *desc, struct wined3d_swapchain **swapchain)
+{
+    struct d3d9_device *device = device_from_device_parent(device_parent);
+    struct d3d9_swapchain *d3d_swapchain;
+    HRESULT hr;
+
+    TRACE("device_parent %p, desc %p, swapchain %p\n", device_parent, desc, swapchain);
+
+    hr = d3d9_swapchain_create(device, desc, &d3d_swapchain);
+    if (FAILED(hr))
+    {
+        WARN("Failed to create swapchain, hr %#x.\n", hr);
+        *swapchain = NULL;
+        return hr;
+    }
+
+    *swapchain = d3d_swapchain->wined3d_swapchain;
+    wined3d_swapchain_incref(*swapchain);
+    IDirect3DSwapChain9_Release(&d3d_swapchain->IDirect3DSwapChain9_iface);
+
+    return hr;
+}
+
+static const struct wined3d_device_parent_ops d3d9_wined3d_device_parent_ops =
+{
+    device_parent_wined3d_device_created,
+    device_parent_mode_changed,
+    device_parent_create_swapchain_surface,
+    device_parent_create_texture_surface,
+    device_parent_create_volume,
+    device_parent_create_swapchain,
+};
+
+static void setup_fpu(void)
+{
+#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+    WORD cw;
+    __asm__ volatile ("fnstcw %0" : "=m" (cw));
+    cw = (cw & ~0xf3f) | 0x3f;
+    __asm__ volatile ("fldcw %0" : : "m" (cw));
+#elif defined(__i386__) && defined(_MSC_VER)
+    WORD cw;
+    __asm fnstcw cw;
+    cw = (cw & ~0xf3f) | 0x3f;
+    __asm fldcw cw;
+#elif defined(RT_ARCH_AMD64)
+    unsigned int currentControl = 0;
+    _controlfp_s(&currentControl, 0x3f, 0xf3f);
+#else
+    FIXME("FPU setup not implemented for this platform.\n");
+#endif
+}
+
+HRESULT device_init(struct d3d9_device *device, struct d3d9 *parent, struct wined3d *wined3d,
+        UINT adapter, D3DDEVTYPE device_type, HWND focus_window, DWORD flags
+#ifdef VBOX_WITH_WDDM
+        , VBOXWINEEX_D3DPRESENT_PARAMETERS *parameters
+#else
+        , D3DPRESENT_PARAMETERS *parameters
+#endif
+        , D3DDISPLAYMODEEX *mode)
+{
+    struct wined3d_swapchain_desc *swapchain_desc;
+    UINT i, count = 1;
+    HRESULT hr;
+
+    if (mode)
+        FIXME("Ignoring display mode.\n");
+
+    device->IDirect3DDevice9Ex_iface.lpVtbl = &d3d9_device_vtbl;
+    device->device_parent.ops = &d3d9_wined3d_device_parent_ops;
+    device->refcount = 1;
+
+    if (!(flags & D3DCREATE_FPU_PRESERVE)) setup_fpu();
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_create(wined3d, adapter, device_type, focus_window, flags, 4,
+            &device->device_parent, &device->wined3d_device);
+    if (FAILED(hr))
+    {
+        WARN("Failed to create wined3d device, hr %#x.\n", hr);
+        wined3d_mutex_unlock();
+        return hr;
+    }
+
+    if (flags & D3DCREATE_ADAPTERGROUP_DEVICE)
+    {
+        WINED3DCAPS caps;
+
+        wined3d_get_device_caps(wined3d, adapter, device_type, &caps);
+        count = caps.NumberOfAdaptersInGroup;
+    }
+
+    if (flags & D3DCREATE_MULTITHREADED)
+        wined3d_device_set_multithreaded(device->wined3d_device);
+
+#ifndef VBOX_WITH_WDDM
+    if (!parameters->Windowed)
+    {
+        if (!focus_window)
+            focus_window = parameters->hDeviceWindow;
+        if (FAILED(hr = wined3d_device_acquire_focus_window(device->wined3d_device, focus_window)))
+        {
+            ERR("Failed to acquire focus window, hr %#x.\n", hr);
+            wined3d_device_decref(device->wined3d_device);
+            wined3d_mutex_unlock();
+            return hr;
+        }
+
+        for (i = 0; i < count; ++i)
+        {
+            HWND device_window = parameters[i].hDeviceWindow;
+
+            if (!device_window) device_window = focus_window;
+            wined3d_device_setup_fullscreen_window(device->wined3d_device, device_window,
+                    parameters[i].BackBufferWidth,
+                    parameters[i].BackBufferHeight);
+        }
+    }
+#else
+    if (!parameters->Base.Windowed)
+    {
+        ERR("non-windowed mode unsupported!");
+        parameters->Base.Windowed = TRUE;
+    }
+#endif
+
+    swapchain_desc = HeapAlloc(GetProcessHeap(), 0, sizeof(*swapchain_desc) * count);
+    if (!swapchain_desc)
+    {
+        ERR("Failed to allocate wined3d parameters.\n");
+        wined3d_device_decref(device->wined3d_device);
+        wined3d_mutex_unlock();
+        return E_OUTOFMEMORY;
+    }
+
+    for (i = 0; i < count; ++i)
+    {
+#ifdef VBOX_WITH_WDDM
+        wined3d_swapchain_desc_from_present_parameters(&swapchain_desc[i], &parameters[i].Base);
+        swapchain_desc[i].pHgsmi = parameters[i].pHgsmi;
+#else
+        wined3d_swapchain_desc_from_present_parameters(&swapchain_desc[i], &parameters[i]);
+#endif
+    }
+
+    hr = wined3d_device_init_3d(device->wined3d_device, swapchain_desc);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize 3D, hr %#x.\n", hr);
+#ifndef VBOX_WITH_WDDM
+        wined3d_device_release_focus_window(device->wined3d_device);
+#endif
+        HeapFree(GetProcessHeap(), 0, swapchain_desc);
+        wined3d_device_decref(device->wined3d_device);
+        wined3d_mutex_unlock();
+        return hr;
+    }
+
+    wined3d_mutex_unlock();
+
+    for (i = 0; i < count; ++i)
+    {
+#ifndef VBOX_WITH_WDDM
+        present_parameters_from_wined3d_swapchain_desc(&parameters[i], &swapchain_desc[i]);
+#else
+        present_parameters_from_wined3d_swapchain_desc(&parameters[i].Base, &swapchain_desc[i]);
+#endif
+    }
+    HeapFree(GetProcessHeap(), 0, swapchain_desc);
+
+    /* Initialize the converted declaration array. This creates a valid pointer
+     * and when adding decls HeapReAlloc() can be used without further checking. */
+    device->fvf_decls = HeapAlloc(GetProcessHeap(), 0, 0);
+    if (!device->fvf_decls)
+    {
+        ERR("Failed to allocate FVF vertex declaration map memory.\n");
+        wined3d_mutex_lock();
+        wined3d_device_uninit_3d(device->wined3d_device);
+#ifndef VBOX_WITH_WDDM
+        wined3d_device_release_focus_window(device->wined3d_device);
+#endif
+        wined3d_device_decref(device->wined3d_device);
+        wined3d_mutex_unlock();
+        return E_OUTOFMEMORY;
+    }
+
+    IDirect3D9Ex_AddRef(&parent->IDirect3D9Ex_iface);
+    device->d3d_parent = parent;
+
+    return D3D_OK;
+}
+
+#ifdef VBOX_WITH_WDDM
+AssertCompile(sizeof (struct wined3d_box) == sizeof (VBOXBOX3D));
+AssertCompile(RT_SIZEOFMEMB(struct wined3d_box, left) == RT_SIZEOFMEMB(VBOXBOX3D, Left));
+AssertCompile(RT_SIZEOFMEMB(struct wined3d_box, top) == RT_SIZEOFMEMB(VBOXBOX3D, Top));
+AssertCompile(RT_SIZEOFMEMB(struct wined3d_box, right) == RT_SIZEOFMEMB(VBOXBOX3D, Right));
+AssertCompile(RT_SIZEOFMEMB(struct wined3d_box, bottom) == RT_SIZEOFMEMB(VBOXBOX3D, Bottom));
+AssertCompile(RT_SIZEOFMEMB(struct wined3d_box, front) == RT_SIZEOFMEMB(VBOXBOX3D, Front));
+AssertCompile(RT_SIZEOFMEMB(struct wined3d_box, back) == RT_SIZEOFMEMB(VBOXBOX3D, Back));
+
+AssertCompile(RT_OFFSETOF(struct wined3d_box, left) == RT_OFFSETOF(VBOXBOX3D, Left));
+AssertCompile(RT_OFFSETOF(struct wined3d_box, top) == RT_OFFSETOF(VBOXBOX3D, Top));
+AssertCompile(RT_OFFSETOF(struct wined3d_box, right) == RT_OFFSETOF(VBOXBOX3D, Right));
+AssertCompile(RT_OFFSETOF(struct wined3d_box, bottom) == RT_OFFSETOF(VBOXBOX3D, Bottom));
+AssertCompile(RT_OFFSETOF(struct wined3d_box, front) == RT_OFFSETOF(VBOXBOX3D, Front));
+AssertCompile(RT_OFFSETOF(struct wined3d_box, back) == RT_OFFSETOF(VBOXBOX3D, Back));
+
+VBOXWINEEX_DECL(HRESULT) VBoxWineExD3DDev9VolBlt(IDirect3DDevice9Ex *iface,
+                                                    IDirect3DVolume9 *pSourceVolume, IDirect3DVolume9 *pDestinationVolume,
+                                                    const VBOXBOX3D *pSrcBoxArg,
+                                                    const VBOXPOINT3D *pDstPoin3D)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_volume *src = unsafe_impl_from_IDirect3DVolume9(pSourceVolume);
+    struct d3d9_volume *dst = unsafe_impl_from_IDirect3DVolume9(pDestinationVolume);
+    HRESULT hr;
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_blt_vol(device->wined3d_device, src->wined3d_volume, dst->wined3d_volume, (struct wined3d_box*)pSrcBoxArg, pDstPoin3D);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+VBOXWINEEX_DECL(HRESULT) VBoxWineExD3DDev9VolTexBlt(IDirect3DDevice9Ex *iface,
+                                                    IDirect3DVolumeTexture9 *pSourceTexture, IDirect3DVolumeTexture9 *pDestinationTexture,
+                                                    const VBOXBOX3D *pSrcBoxArg,
+                                                    const VBOXPOINT3D *pDstPoin3D)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_texture *src = unsafe_impl_from_IDirect3DBaseTexture9((IDirect3DBaseTexture9*)pSourceTexture);
+    struct d3d9_texture *dst = unsafe_impl_from_IDirect3DBaseTexture9((IDirect3DBaseTexture9*)pDestinationTexture);
+    HRESULT hr;
+
+    wined3d_mutex_lock();
+    hr = wined3d_device_blt_voltex(device->wined3d_device, src->wined3d_texture, dst->wined3d_texture, (struct wined3d_box*)pSrcBoxArg, pDstPoin3D);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+VBOXWINEEX_DECL(HRESULT) VBoxWineExD3DDev9Term(IDirect3DDevice9Ex *iface)
+{
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    LONG wined3d_refs;
+    if (device->refcount != 1)
+    {
+        ERR("unexpected ref count %d, destroying in anyway", device->refcount);
+    }
+    wined3d_refs = d3d9_device_Term(device);
+    if (wined3d_refs)
+    {
+        ERR("unexpected wined3dRefs %d, destroying in anyway", wined3d_refs);
+        while (wined3d_device_decref(device->wined3d_device)) {}
+    }
+    return D3D_OK;
+}
+#endif
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/directx.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/directx.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/directx.c	(revision 46521)
@@ -0,0 +1,655 @@
+/*
+ * IDirect3D9 implementation
+ *
+ * Copyright 2002 Jason Edmeades
+ * Copyright 2005 Oliver Stieber
+ *
+ * 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 "d3d9_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
+
+static inline struct d3d9 *impl_from_IDirect3D9Ex(IDirect3D9Ex *iface)
+{
+    return CONTAINING_RECORD(iface, struct d3d9, IDirect3D9Ex_iface);
+}
+
+static HRESULT WINAPI d3d9_QueryInterface(IDirect3D9Ex *iface, REFIID riid, void **out)
+{
+    struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
+
+    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
+
+    if (IsEqualGUID(riid, &IID_IDirect3D9)
+            || IsEqualGUID(riid, &IID_IUnknown))
+    {
+        IDirect3D9Ex_AddRef(&d3d9->IDirect3D9Ex_iface);
+        *out = &d3d9->IDirect3D9Ex_iface;
+        return S_OK;
+    }
+
+    if (IsEqualGUID(riid, &IID_IDirect3D9Ex))
+    {
+        if (!d3d9->extended)
+        {
+            WARN("Application asks for IDirect3D9Ex, but this instance wasn't created with Direct3DCreate9Ex.\n");
+            *out = NULL;
+            return E_NOINTERFACE;
+        }
+
+        IDirect3D9Ex_AddRef(&d3d9->IDirect3D9Ex_iface);
+        *out = &d3d9->IDirect3D9Ex_iface;
+        return S_OK;
+    }
+
+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+    *out = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI d3d9_AddRef(IDirect3D9Ex *iface)
+{
+    struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
+    ULONG refcount = InterlockedIncrement(&d3d9->refcount);
+
+    TRACE("%p increasing refcount to %u.\n", iface, refcount);
+
+    return refcount;
+}
+
+static ULONG WINAPI d3d9_Release(IDirect3D9Ex *iface)
+{
+    struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
+    ULONG refcount = InterlockedDecrement(&d3d9->refcount);
+
+    TRACE("%p decreasing refcount to %u.\n", iface, refcount);
+
+    if (!refcount)
+    {
+        wined3d_mutex_lock();
+        wined3d_decref(d3d9->wined3d);
+        wined3d_mutex_unlock();
+
+        HeapFree(GetProcessHeap(), 0, d3d9);
+    }
+
+    return refcount;
+}
+
+static HRESULT WINAPI d3d9_RegisterSoftwareDevice(IDirect3D9Ex *iface, void *init_function)
+{
+    struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, init_function %p.\n", iface, init_function);
+
+    wined3d_mutex_lock();
+    hr = wined3d_register_software_device(d3d9->wined3d, init_function);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static UINT WINAPI d3d9_GetAdapterCount(IDirect3D9Ex *iface)
+{
+    struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
+    UINT ret;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    ret = wined3d_get_adapter_count(d3d9->wined3d);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static HRESULT WINAPI d3d9_GetAdapterIdentifier(IDirect3D9Ex *iface, UINT adapter,
+        DWORD flags, D3DADAPTER_IDENTIFIER9 *identifier)
+{
+    struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
+    struct wined3d_adapter_identifier adapter_id;
+    HRESULT hr;
+
+    TRACE("iface %p, adapter %u, flags %#x, identifier %p.\n",
+            iface, adapter, flags, identifier);
+
+    adapter_id.driver = identifier->Driver;
+    adapter_id.driver_size = sizeof(identifier->Driver);
+    adapter_id.description = identifier->Description;
+    adapter_id.description_size = sizeof(identifier->Description);
+    adapter_id.device_name = identifier->DeviceName;
+    adapter_id.device_name_size = sizeof(identifier->DeviceName);
+
+    wined3d_mutex_lock();
+    hr = wined3d_get_adapter_identifier(d3d9->wined3d, adapter, flags, &adapter_id);
+    wined3d_mutex_unlock();
+
+    identifier->DriverVersion = adapter_id.driver_version;
+    identifier->VendorId = adapter_id.vendor_id;
+    identifier->DeviceId = adapter_id.device_id;
+    identifier->SubSysId = adapter_id.subsystem_id;
+    identifier->Revision = adapter_id.revision;
+    memcpy(&identifier->DeviceIdentifier, &adapter_id.device_identifier, sizeof(identifier->DeviceIdentifier));
+    identifier->WHQLLevel = adapter_id.whql_level;
+
+    return hr;
+}
+
+static UINT WINAPI d3d9_GetAdapterModeCount(IDirect3D9Ex *iface, UINT adapter, D3DFORMAT format)
+{
+    struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
+    UINT ret;
+
+    TRACE("iface %p, adapter %u, format %#x.\n", iface, adapter, format);
+
+    /* Others than that not supported by d3d9, but reported by wined3d for ddraw. Filter them out. */
+    if (format != D3DFMT_X8R8G8B8 && format != D3DFMT_R5G6B5)
+        return 0;
+
+    wined3d_mutex_lock();
+    ret = wined3d_get_adapter_mode_count(d3d9->wined3d, adapter,
+            wined3dformat_from_d3dformat(format), WINED3D_SCANLINE_ORDERING_UNKNOWN);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static HRESULT WINAPI d3d9_EnumAdapterModes(IDirect3D9Ex *iface, UINT adapter,
+        D3DFORMAT format, UINT mode_idx, D3DDISPLAYMODE *mode)
+{
+    struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
+    struct wined3d_display_mode wined3d_mode;
+    HRESULT hr;
+
+    TRACE("iface %p, adapter %u, format %#x, mode_idx %u, mode %p.\n",
+            iface, adapter, format, mode_idx, mode);
+
+    if (format != D3DFMT_X8R8G8B8 && format != D3DFMT_R5G6B5)
+        return D3DERR_INVALIDCALL;
+
+    wined3d_mutex_lock();
+    hr = wined3d_enum_adapter_modes(d3d9->wined3d, adapter, wined3dformat_from_d3dformat(format),
+            WINED3D_SCANLINE_ORDERING_UNKNOWN, mode_idx, &wined3d_mode);
+    wined3d_mutex_unlock();
+
+    if (SUCCEEDED(hr))
+    {
+        mode->Width = wined3d_mode.width;
+        mode->Height = wined3d_mode.height;
+        mode->RefreshRate = wined3d_mode.refresh_rate;
+        mode->Format = d3dformat_from_wined3dformat(wined3d_mode.format_id);
+    }
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_GetAdapterDisplayMode(IDirect3D9Ex *iface, UINT adapter, D3DDISPLAYMODE *mode)
+{
+    struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
+    struct wined3d_display_mode wined3d_mode;
+    HRESULT hr;
+
+    TRACE("iface %p, adapter %u, mode %p.\n", iface, adapter, mode);
+
+    wined3d_mutex_lock();
+    hr = wined3d_get_adapter_display_mode(d3d9->wined3d, adapter, &wined3d_mode, NULL);
+    wined3d_mutex_unlock();
+
+    if (SUCCEEDED(hr))
+    {
+        mode->Width = wined3d_mode.width;
+        mode->Height = wined3d_mode.height;
+        mode->RefreshRate = wined3d_mode.refresh_rate;
+        mode->Format = d3dformat_from_wined3dformat(wined3d_mode.format_id);
+    }
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_CheckDeviceType(IDirect3D9Ex *iface, UINT adapter, D3DDEVTYPE device_type,
+        D3DFORMAT display_format, D3DFORMAT backbuffer_format, BOOL windowed)
+{
+    struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, adapter %u, device_type %#x, display_format %#x, backbuffer_format %#x, windowed %#x.\n",
+            iface, adapter, device_type, display_format, backbuffer_format, windowed);
+
+    wined3d_mutex_lock();
+    hr = wined3d_check_device_type(d3d9->wined3d, adapter, device_type, wined3dformat_from_d3dformat(display_format),
+            wined3dformat_from_d3dformat(backbuffer_format), windowed);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_CheckDeviceFormat(IDirect3D9Ex *iface, UINT adapter, D3DDEVTYPE device_type,
+        D3DFORMAT adapter_format, DWORD usage, D3DRESOURCETYPE resource_type, D3DFORMAT format)
+{
+    struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
+    enum wined3d_resource_type wined3d_rtype;
+    HRESULT hr;
+
+    TRACE("iface %p, adapter %u, device_type %#x, adapter_format %#x, usage %#x, resource_type %#x, format %#x.\n",
+            iface, adapter, device_type, adapter_format, usage, resource_type, format);
+
+    switch (resource_type)
+    {
+        case D3DRTYPE_VERTEXBUFFER:
+        case D3DRTYPE_INDEXBUFFER:
+            wined3d_rtype = WINED3D_RTYPE_BUFFER;
+            break;
+
+        default:
+            wined3d_rtype = resource_type;
+            break;
+    }
+
+    wined3d_mutex_lock();
+    hr = wined3d_check_device_format(d3d9->wined3d, adapter, device_type, wined3dformat_from_d3dformat(adapter_format),
+            usage, wined3d_rtype, wined3dformat_from_d3dformat(format));
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_CheckDeviceMultiSampleType(IDirect3D9Ex *iface, UINT adapter, D3DDEVTYPE device_type,
+        D3DFORMAT format, BOOL windowed, D3DMULTISAMPLE_TYPE multisample_type, DWORD *levels)
+{
+    struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, adapter %u, device_type %#x, format %#x, windowed %#x, multisample_type %#x, levels %p.\n",
+            iface, adapter, device_type, format, windowed, multisample_type, levels);
+
+    wined3d_mutex_lock();
+    hr = wined3d_check_device_multisample_type(d3d9->wined3d, adapter, device_type,
+            wined3dformat_from_d3dformat(format), windowed, multisample_type, levels);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_CheckDepthStencilMatch(IDirect3D9Ex *iface, UINT adapter, D3DDEVTYPE device_type,
+        D3DFORMAT adapter_format, D3DFORMAT rt_format, D3DFORMAT ds_format)
+{
+    struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, adapter %u, device_type %#x, adapter_format %#x, rt_format %#x, ds_format %#x.\n",
+            iface, adapter, device_type, adapter_format, rt_format, ds_format);
+
+    wined3d_mutex_lock();
+    hr = wined3d_check_depth_stencil_match(d3d9->wined3d, adapter, device_type,
+            wined3dformat_from_d3dformat(adapter_format), wined3dformat_from_d3dformat(rt_format),
+            wined3dformat_from_d3dformat(ds_format));
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_CheckDeviceFormatConversion(IDirect3D9Ex *iface, UINT adapter,
+        D3DDEVTYPE device_type, D3DFORMAT src_format, D3DFORMAT dst_format)
+{
+    struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, adapter %u, device_type %#x, src_format %#x, dst_format %#x.\n",
+            iface, adapter, device_type, src_format, dst_format);
+
+    wined3d_mutex_lock();
+    hr = wined3d_check_device_format_conversion(d3d9->wined3d, adapter, device_type,
+            wined3dformat_from_d3dformat(src_format), wined3dformat_from_d3dformat(dst_format));
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+void filter_caps(D3DCAPS9* pCaps)
+{
+    DWORD ps_minor_version[] = {0, 4, 0, 0};
+    DWORD vs_minor_version[] = {0, 1, 0, 0};
+    DWORD textureFilterCaps =
+        D3DPTFILTERCAPS_MINFPOINT      | D3DPTFILTERCAPS_MINFLINEAR    | D3DPTFILTERCAPS_MINFANISOTROPIC |
+        D3DPTFILTERCAPS_MINFPYRAMIDALQUAD                              | D3DPTFILTERCAPS_MINFGAUSSIANQUAD|
+        D3DPTFILTERCAPS_MIPFPOINT      | D3DPTFILTERCAPS_MIPFLINEAR    | D3DPTFILTERCAPS_MAGFPOINT       |
+        D3DPTFILTERCAPS_MAGFLINEAR     |D3DPTFILTERCAPS_MAGFANISOTROPIC|D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD|
+        D3DPTFILTERCAPS_MAGFGAUSSIANQUAD;
+    pCaps->TextureFilterCaps &= textureFilterCaps;
+    pCaps->CubeTextureFilterCaps &= textureFilterCaps;
+    pCaps->VolumeTextureFilterCaps &= textureFilterCaps;
+
+    pCaps->DevCaps &=
+        D3DDEVCAPS_EXECUTESYSTEMMEMORY | D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY |
+        D3DDEVCAPS_TLVERTEXVIDEOMEMORY | D3DDEVCAPS_TEXTURESYSTEMMEMORY| D3DDEVCAPS_TEXTUREVIDEOMEMORY   |
+        D3DDEVCAPS_DRAWPRIMTLVERTEX    | D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_TEXTURENONLOCALVIDMEM|
+        D3DDEVCAPS_DRAWPRIMITIVES2     | D3DDEVCAPS_SEPARATETEXTUREMEMORIES                              |
+        D3DDEVCAPS_DRAWPRIMITIVES2EX   | D3DDEVCAPS_HWTRANSFORMANDLIGHT| D3DDEVCAPS_CANBLTSYSTONONLOCAL  |
+        D3DDEVCAPS_HWRASTERIZATION     | D3DDEVCAPS_PUREDEVICE         | D3DDEVCAPS_QUINTICRTPATCHES     |
+        D3DDEVCAPS_RTPATCHES           | D3DDEVCAPS_RTPATCHHANDLEZERO  | D3DDEVCAPS_NPATCHES;
+
+    pCaps->ShadeCaps &=
+        D3DPSHADECAPS_COLORGOURAUDRGB  | D3DPSHADECAPS_SPECULARGOURAUDRGB |
+        D3DPSHADECAPS_ALPHAGOURAUDBLEND | D3DPSHADECAPS_FOGGOURAUD;
+
+    pCaps->RasterCaps &=
+        D3DPRASTERCAPS_DITHER          | D3DPRASTERCAPS_ZTEST          | D3DPRASTERCAPS_FOGVERTEX        |
+        D3DPRASTERCAPS_FOGTABLE        | D3DPRASTERCAPS_MIPMAPLODBIAS  | D3DPRASTERCAPS_ZBUFFERLESSHSR   |
+        D3DPRASTERCAPS_FOGRANGE        | D3DPRASTERCAPS_ANISOTROPY     | D3DPRASTERCAPS_WBUFFER          |
+        D3DPRASTERCAPS_WFOG            | D3DPRASTERCAPS_ZFOG           | D3DPRASTERCAPS_COLORPERSPECTIVE |
+        D3DPRASTERCAPS_SCISSORTEST     | D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS                              |
+        D3DPRASTERCAPS_DEPTHBIAS       | D3DPRASTERCAPS_MULTISAMPLE_TOGGLE;
+
+    pCaps->DevCaps2 &=
+        D3DDEVCAPS2_STREAMOFFSET       | D3DDEVCAPS2_DMAPNPATCH        | D3DDEVCAPS2_ADAPTIVETESSRTPATCH |
+        D3DDEVCAPS2_ADAPTIVETESSNPATCH | D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES                       |
+        D3DDEVCAPS2_PRESAMPLEDDMAPNPATCH| D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET;
+
+    pCaps->Caps2 &=
+        D3DCAPS2_FULLSCREENGAMMA       | D3DCAPS2_CANCALIBRATEGAMMA    | D3DCAPS2_RESERVED               |
+        D3DCAPS2_CANMANAGERESOURCE     | D3DCAPS2_DYNAMICTEXTURES      | D3DCAPS2_CANAUTOGENMIPMAP;
+
+    pCaps->VertexProcessingCaps &=
+        D3DVTXPCAPS_TEXGEN             | D3DVTXPCAPS_MATERIALSOURCE7   | D3DVTXPCAPS_DIRECTIONALLIGHTS   |
+        D3DVTXPCAPS_POSITIONALLIGHTS   | D3DVTXPCAPS_LOCALVIEWER       | D3DVTXPCAPS_TWEENING            |
+        D3DVTXPCAPS_TEXGEN_SPHEREMAP   | D3DVTXPCAPS_NO_TEXGEN_NONLOCALVIEWER;
+
+    pCaps->TextureCaps &=
+        D3DPTEXTURECAPS_PERSPECTIVE    | D3DPTEXTURECAPS_POW2          | D3DPTEXTURECAPS_ALPHA           |
+        D3DPTEXTURECAPS_SQUAREONLY     | D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE                        |
+        D3DPTEXTURECAPS_ALPHAPALETTE   | D3DPTEXTURECAPS_NONPOW2CONDITIONAL                              |
+        D3DPTEXTURECAPS_PROJECTED      | D3DPTEXTURECAPS_CUBEMAP       | D3DPTEXTURECAPS_VOLUMEMAP       |
+        D3DPTEXTURECAPS_MIPMAP         | D3DPTEXTURECAPS_MIPVOLUMEMAP  | D3DPTEXTURECAPS_MIPCUBEMAP      |
+        D3DPTEXTURECAPS_CUBEMAP_POW2   | D3DPTEXTURECAPS_VOLUMEMAP_POW2| D3DPTEXTURECAPS_NOPROJECTEDBUMPENV;
+
+    pCaps->MaxVertexShaderConst = min(D3D9_MAX_VERTEX_SHADER_CONSTANTF, pCaps->MaxVertexShaderConst);
+    pCaps->NumSimultaneousRTs = min(D3D9_MAX_SIMULTANEOUS_RENDERTARGETS, pCaps->NumSimultaneousRTs);
+
+    if (pCaps->PixelShaderVersion > 3)
+        pCaps->PixelShaderVersion = D3DPS_VERSION(3,0);
+    else
+    {
+        DWORD major = pCaps->PixelShaderVersion;
+        pCaps->PixelShaderVersion = D3DPS_VERSION(major,ps_minor_version[major]);
+    }
+
+    if (pCaps->VertexShaderVersion > 3)
+        pCaps->VertexShaderVersion = D3DVS_VERSION(3,0);
+    else
+    {
+        DWORD major = pCaps->VertexShaderVersion;
+        pCaps->VertexShaderVersion = D3DVS_VERSION(major,vs_minor_version[major]);
+    }
+}
+
+static HRESULT WINAPI d3d9_GetDeviceCaps(IDirect3D9Ex *iface, UINT adapter, D3DDEVTYPE device_type, D3DCAPS9 *caps)
+{
+    struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
+    WINED3DCAPS *wined3d_caps;
+    HRESULT hr;
+
+    TRACE("iface %p, adapter %u, device_type %#x, caps %p.\n", iface, adapter, device_type, caps);
+
+    if (!caps)
+        return D3DERR_INVALIDCALL;
+
+    if (!(wined3d_caps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINED3DCAPS))))
+        return D3DERR_INVALIDCALL; /*well this is what MSDN says to return*/
+    memset(caps, 0, sizeof(*caps));
+
+    wined3d_mutex_lock();
+    hr = wined3d_get_device_caps(d3d9->wined3d, adapter, device_type, wined3d_caps);
+    wined3d_mutex_unlock();
+
+    WINECAPSTOD3D9CAPS(caps, wined3d_caps)
+    HeapFree(GetProcessHeap(), 0, wined3d_caps);
+
+    /* Some functionality is implemented in d3d9.dll, not wined3d.dll. Add the needed caps */
+    caps->DevCaps2 |= D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES;
+
+    filter_caps(caps);
+
+    return hr;
+}
+
+static HMONITOR WINAPI d3d9_GetAdapterMonitor(IDirect3D9Ex *iface, UINT adapter)
+{
+    struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
+    HMONITOR ret;
+
+    TRACE("iface %p, adapter %u.\n", iface, adapter);
+
+    wined3d_mutex_lock();
+    ret = wined3d_get_adapter_monitor(d3d9->wined3d, adapter);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_CreateDevice(IDirect3D9Ex *iface, UINT adapter,
+        D3DDEVTYPE device_type, HWND focus_window, DWORD flags, D3DPRESENT_PARAMETERS *parameters,
+        IDirect3DDevice9 **device)
+{
+    struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
+    struct d3d9_device *object;
+    HRESULT hr;
+
+    TRACE("iface %p, adapter %u, device_type %#x, focus_window %p, flags %#x, parameters %p, device %p.\n",
+            iface, adapter, device_type, focus_window, flags, parameters, device);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return E_OUTOFMEMORY;
+
+    hr = device_init(object, d3d9, d3d9->wined3d, adapter, device_type, focus_window, flags,
+#ifdef VBOX_WITH_WDDM
+        (VBOXWINEEX_D3DPRESENT_PARAMETERS *)
+#endif
+            parameters, NULL);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize device, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created device %p.\n", object);
+    *device = (IDirect3DDevice9 *)object;
+
+    return D3D_OK;
+}
+
+static UINT WINAPI d3d9_GetAdapterModeCountEx(IDirect3D9Ex *iface,
+        UINT adapter, const D3DDISPLAYMODEFILTER *filter)
+{
+    struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
+    UINT ret;
+
+    TRACE("iface %p, adapter %u, filter %p.\n", iface, adapter, filter);
+
+    if (filter->Format != D3DFMT_X8R8G8B8 && filter->Format != D3DFMT_R5G6B5)
+        return 0;
+
+    wined3d_mutex_lock();
+    ret = wined3d_get_adapter_mode_count(d3d9->wined3d, adapter,
+            wined3dformat_from_d3dformat(filter->Format), filter->ScanLineOrdering);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static HRESULT WINAPI d3d9_EnumAdapterModesEx(IDirect3D9Ex *iface,
+        UINT adapter, const D3DDISPLAYMODEFILTER *filter, UINT mode_idx, D3DDISPLAYMODEEX *mode)
+{
+    struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
+    struct wined3d_display_mode wined3d_mode;
+    HRESULT hr;
+
+    TRACE("iface %p, adapter %u, filter %p, mode_idx %u, mode %p.\n",
+            iface, adapter, filter, mode_idx, mode);
+
+    if (filter->Format != D3DFMT_X8R8G8B8 && filter->Format != D3DFMT_R5G6B5)
+        return D3DERR_INVALIDCALL;
+
+    wined3d_mutex_lock();
+    hr = wined3d_enum_adapter_modes(d3d9->wined3d, adapter, wined3dformat_from_d3dformat(filter->Format),
+            filter->ScanLineOrdering, mode_idx, &wined3d_mode);
+    wined3d_mutex_unlock();
+
+    if (SUCCEEDED(hr))
+    {
+        mode->Width = wined3d_mode.width;
+        mode->Height = wined3d_mode.height;
+        mode->RefreshRate = wined3d_mode.refresh_rate;
+        mode->Format = d3dformat_from_wined3dformat(wined3d_mode.format_id);
+        mode->ScanLineOrdering = wined3d_mode.scanline_ordering;
+    }
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_GetAdapterDisplayModeEx(IDirect3D9Ex *iface,
+        UINT adapter, D3DDISPLAYMODEEX *mode, D3DDISPLAYROTATION *rotation)
+{
+    struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
+    struct wined3d_display_mode wined3d_mode;
+    HRESULT hr;
+
+    TRACE("iface %p, adapter %u, mode %p, rotation %p.\n",
+            iface, adapter, mode, rotation);
+
+    if (mode->Size != sizeof(*mode))
+        return D3DERR_INVALIDCALL;
+
+    wined3d_mutex_lock();
+    hr = wined3d_get_adapter_display_mode(d3d9->wined3d, adapter, &wined3d_mode,
+            (enum wined3d_display_rotation *)rotation);
+    wined3d_mutex_unlock();
+
+    if (SUCCEEDED(hr))
+    {
+        mode->Width = wined3d_mode.width;
+        mode->Height = wined3d_mode.height;
+        mode->RefreshRate = wined3d_mode.refresh_rate;
+        mode->Format = d3dformat_from_wined3dformat(wined3d_mode.format_id);
+        mode->ScanLineOrdering = wined3d_mode.scanline_ordering;
+    }
+
+    return hr;
+}
+
+static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_CreateDeviceEx(IDirect3D9Ex *iface,
+        UINT adapter, D3DDEVTYPE device_type, HWND focus_window, DWORD flags,
+        D3DPRESENT_PARAMETERS *parameters, D3DDISPLAYMODEEX *mode, IDirect3DDevice9Ex **device)
+{
+    struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
+    struct d3d9_device *object;
+    HRESULT hr;
+
+    TRACE("iface %p, adapter %u, device_type %#x, focus_window %p, flags %#x, parameters %p, mode %p, device %p.\n",
+            iface, adapter, device_type, focus_window, flags, parameters, mode, device);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return E_OUTOFMEMORY;
+
+    hr = device_init(object, d3d9, d3d9->wined3d, adapter, device_type, focus_window, flags,
+#ifdef VBOX_WITH_WDDM
+        (VBOXWINEEX_D3DPRESENT_PARAMETERS *)
+#endif
+        parameters, mode);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize device, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created device %p.\n", object);
+    *device = &object->IDirect3DDevice9Ex_iface;
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_GetAdapterLUID(IDirect3D9Ex *iface, UINT adapter, LUID *luid)
+{
+    struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
+    struct wined3d_adapter_identifier adapter_id;
+    HRESULT hr;
+
+    TRACE("iface %p, adapter %u, luid %p.\n", iface, adapter, luid);
+
+    adapter_id.driver_size = 0;
+    adapter_id.description_size = 0;
+    adapter_id.device_name_size = 0;
+
+    wined3d_mutex_lock();
+    hr = wined3d_get_adapter_identifier(d3d9->wined3d, adapter, 0, &adapter_id);
+    wined3d_mutex_unlock();
+
+    memcpy(luid, &adapter_id.adapter_luid, sizeof(*luid));
+
+    return hr;
+}
+
+static const struct IDirect3D9ExVtbl d3d9_vtbl =
+{
+    /* IUnknown */
+    d3d9_QueryInterface,
+    d3d9_AddRef,
+    d3d9_Release,
+    /* IDirect3D9 */
+    d3d9_RegisterSoftwareDevice,
+    d3d9_GetAdapterCount,
+    d3d9_GetAdapterIdentifier,
+    d3d9_GetAdapterModeCount,
+    d3d9_EnumAdapterModes,
+    d3d9_GetAdapterDisplayMode,
+    d3d9_CheckDeviceType,
+    d3d9_CheckDeviceFormat,
+    d3d9_CheckDeviceMultiSampleType,
+    d3d9_CheckDepthStencilMatch,
+    d3d9_CheckDeviceFormatConversion,
+    d3d9_GetDeviceCaps,
+    d3d9_GetAdapterMonitor,
+    d3d9_CreateDevice,
+    /* IDirect3D9Ex */
+    d3d9_GetAdapterModeCountEx,
+    d3d9_EnumAdapterModesEx,
+    d3d9_GetAdapterDisplayModeEx,
+    d3d9_CreateDeviceEx,
+    d3d9_GetAdapterLUID,
+};
+
+BOOL d3d9_init(struct d3d9 *d3d9, BOOL extended)
+{
+    DWORD flags = extended ? 0 : WINED3D_VIDMEM_ACCOUNTING;
+    d3d9->IDirect3D9Ex_iface.lpVtbl = &d3d9_vtbl;
+    d3d9->refcount = 1;
+
+    wined3d_mutex_lock();
+    d3d9->wined3d = wined3d_create(9, flags);
+    wined3d_mutex_unlock();
+    if (!d3d9->wined3d)
+        return FALSE;
+    d3d9->extended = extended;
+
+    return TRUE;
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/query.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/query.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/query.c	(revision 46521)
@@ -0,0 +1,184 @@
+/*
+ * IDirect3DQuery9 implementation
+ *
+ * Copyright 2002-2003 Raphael Junqueira
+ * Copyright 2002-2003 Jason Edmeades
+ * Copyright 2005 Oliver Stieber
+ *
+ * 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 "d3d9_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
+
+static inline struct d3d9_query *impl_from_IDirect3DQuery9(IDirect3DQuery9 *iface)
+{
+    return CONTAINING_RECORD(iface, struct d3d9_query, IDirect3DQuery9_iface);
+}
+
+static HRESULT WINAPI d3d9_query_QueryInterface(IDirect3DQuery9 *iface, REFIID riid, void **out)
+{
+    TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), out);
+
+    if (IsEqualGUID(riid, &IID_IDirect3DQuery9)
+            || IsEqualGUID(riid, &IID_IUnknown))
+    {
+        IDirect3DQuery9_AddRef(iface);
+        *out = iface;
+        return S_OK;
+    }
+
+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+    *out = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI d3d9_query_AddRef(IDirect3DQuery9 *iface)
+{
+    struct d3d9_query *query = impl_from_IDirect3DQuery9(iface);
+    ULONG refcount = InterlockedIncrement(&query->refcount);
+
+    TRACE("%p increasing refcount to %u.\n", iface, refcount);
+
+    return refcount;
+}
+
+static ULONG WINAPI d3d9_query_Release(IDirect3DQuery9 *iface)
+{
+    struct d3d9_query *query = impl_from_IDirect3DQuery9(iface);
+    ULONG refcount = InterlockedDecrement(&query->refcount);
+
+    TRACE("%p decreasing refcount to %u.\n", iface, refcount);
+
+    if (!refcount)
+    {
+        wined3d_mutex_lock();
+        wined3d_query_decref(query->wined3d_query);
+        wined3d_mutex_unlock();
+
+        IDirect3DDevice9Ex_Release(query->parent_device);
+        HeapFree(GetProcessHeap(), 0, query);
+    }
+    return refcount;
+}
+
+static HRESULT WINAPI d3d9_query_GetDevice(IDirect3DQuery9 *iface, IDirect3DDevice9 **device)
+{
+    struct d3d9_query *query = impl_from_IDirect3DQuery9(iface);
+
+    TRACE("iface %p, device %p.\n", iface, device);
+
+    *device = (IDirect3DDevice9 *)query->parent_device;
+    IDirect3DDevice9_AddRef(*device);
+
+    TRACE("Returning device %p.\n", *device);
+
+    return D3D_OK;
+}
+
+static D3DQUERYTYPE WINAPI d3d9_query_GetType(IDirect3DQuery9 *iface)
+{
+    struct d3d9_query *query = impl_from_IDirect3DQuery9(iface);
+    D3DQUERYTYPE type;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    type = wined3d_query_get_type(query->wined3d_query);
+    wined3d_mutex_unlock();
+
+    return type;
+}
+
+static DWORD WINAPI d3d9_query_GetDataSize(IDirect3DQuery9 *iface)
+{
+    struct d3d9_query *query = impl_from_IDirect3DQuery9(iface);
+    DWORD ret;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    ret = wined3d_query_get_data_size(query->wined3d_query);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static HRESULT WINAPI d3d9_query_Issue(IDirect3DQuery9 *iface, DWORD flags)
+{
+    struct d3d9_query *query = impl_from_IDirect3DQuery9(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, flags %#x.\n", iface, flags);
+
+    wined3d_mutex_lock();
+    hr = wined3d_query_issue(query->wined3d_query, flags);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_query_GetData(IDirect3DQuery9 *iface, void *data, DWORD size, DWORD flags)
+{
+    struct d3d9_query *query = impl_from_IDirect3DQuery9(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, data %p, size %u, flags %#x.\n",
+            iface, data, size, flags);
+
+    wined3d_mutex_lock();
+    hr = wined3d_query_get_data(query->wined3d_query, data, size, flags);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+
+static const struct IDirect3DQuery9Vtbl d3d9_query_vtbl =
+{
+    d3d9_query_QueryInterface,
+    d3d9_query_AddRef,
+    d3d9_query_Release,
+    d3d9_query_GetDevice,
+    d3d9_query_GetType,
+    d3d9_query_GetDataSize,
+    d3d9_query_Issue,
+    d3d9_query_GetData,
+};
+
+HRESULT query_init(struct d3d9_query *query, struct d3d9_device *device, D3DQUERYTYPE type)
+{
+    HRESULT hr;
+
+    query->IDirect3DQuery9_iface.lpVtbl = &d3d9_query_vtbl;
+    query->refcount = 1;
+
+    wined3d_mutex_lock();
+    hr = wined3d_query_create(device->wined3d_device, type, &query->wined3d_query);
+    wined3d_mutex_unlock();
+    if (FAILED(hr))
+    {
+        WARN("Failed to create wined3d query, hr %#x.\n", hr);
+        return hr;
+    }
+
+    query->parent_device = &device->IDirect3DDevice9Ex_iface;
+    IDirect3DDevice9Ex_AddRef(query->parent_device);
+
+    return D3D_OK;
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/shader.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/shader.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/shader.c	(revision 46521)
@@ -0,0 +1,311 @@
+/*
+ * Copyright 2002-2003 Jason Edmeades
+ *                     Raphael Junqueira
+ *
+ * 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 "d3d9_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
+
+static inline struct d3d9_vertexshader *impl_from_IDirect3DVertexShader9(IDirect3DVertexShader9 *iface)
+{
+    return CONTAINING_RECORD(iface, struct d3d9_vertexshader, IDirect3DVertexShader9_iface);
+}
+
+static HRESULT WINAPI d3d9_vertexshader_QueryInterface(IDirect3DVertexShader9 *iface, REFIID riid, void **out)
+{
+    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
+
+    if (IsEqualGUID(riid, &IID_IDirect3DVertexShader9)
+            || IsEqualGUID(riid, &IID_IUnknown))
+    {
+        IDirect3DVertexShader9_AddRef(iface);
+        *out = iface;
+        return S_OK;
+    }
+
+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+    *out = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI d3d9_vertexshader_AddRef(IDirect3DVertexShader9 *iface)
+{
+    struct d3d9_vertexshader *shader = impl_from_IDirect3DVertexShader9(iface);
+    ULONG refcount = InterlockedIncrement(&shader->refcount);
+
+    TRACE("%p increasing refcount to %u.\n", iface, refcount);
+
+    if (refcount == 1)
+    {
+        IDirect3DDevice9Ex_AddRef(shader->parent_device);
+        wined3d_mutex_lock();
+        wined3d_shader_incref(shader->wined3d_shader);
+        wined3d_mutex_unlock();
+    }
+
+    return refcount;
+}
+
+static ULONG WINAPI d3d9_vertexshader_Release(IDirect3DVertexShader9 *iface)
+{
+    struct d3d9_vertexshader *shader = impl_from_IDirect3DVertexShader9(iface);
+    ULONG refcount = InterlockedDecrement(&shader->refcount);
+
+    TRACE("%p decreasing refcount to %u.\n", iface, refcount);
+
+    if (!refcount)
+    {
+        IDirect3DDevice9Ex *device = shader->parent_device;
+
+        wined3d_mutex_lock();
+        wined3d_shader_decref(shader->wined3d_shader);
+        wined3d_mutex_unlock();
+
+        /* Release the device last, as it may cause the device to be destroyed. */
+        IDirect3DDevice9Ex_Release(device);
+    }
+
+    return refcount;
+}
+
+static HRESULT WINAPI d3d9_vertexshader_GetDevice(IDirect3DVertexShader9 *iface, IDirect3DDevice9 **device)
+{
+    struct d3d9_vertexshader *shader = impl_from_IDirect3DVertexShader9(iface);
+
+    TRACE("iface %p, device %p.\n", iface, device);
+
+    *device = (IDirect3DDevice9 *)shader->parent_device;
+    IDirect3DDevice9_AddRef(*device);
+
+    TRACE("Returning device %p.\n", *device);
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_vertexshader_GetFunction(IDirect3DVertexShader9 *iface, void *data, UINT *data_size)
+{
+    struct d3d9_vertexshader *shader = impl_from_IDirect3DVertexShader9(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, data %p, data_size %p.\n", iface, data, data_size);
+
+    wined3d_mutex_lock();
+    hr = wined3d_shader_get_byte_code(shader->wined3d_shader, data, data_size);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static const IDirect3DVertexShader9Vtbl d3d9_vertexshader_vtbl =
+{
+    /* IUnknown */
+    d3d9_vertexshader_QueryInterface,
+    d3d9_vertexshader_AddRef,
+    d3d9_vertexshader_Release,
+    /* IDirect3DVertexShader9 */
+    d3d9_vertexshader_GetDevice,
+    d3d9_vertexshader_GetFunction,
+};
+
+static void STDMETHODCALLTYPE d3d9_vertexshader_wined3d_object_destroyed(void *parent)
+{
+    HeapFree(GetProcessHeap(), 0, parent);
+}
+
+static const struct wined3d_parent_ops d3d9_vertexshader_wined3d_parent_ops =
+{
+    d3d9_vertexshader_wined3d_object_destroyed,
+};
+
+HRESULT vertexshader_init(struct d3d9_vertexshader *shader, struct d3d9_device *device, const DWORD *byte_code)
+{
+    HRESULT hr;
+
+    shader->refcount = 1;
+    shader->IDirect3DVertexShader9_iface.lpVtbl = &d3d9_vertexshader_vtbl;
+
+    wined3d_mutex_lock();
+    hr = wined3d_shader_create_vs(device->wined3d_device, byte_code, NULL,
+            shader, &d3d9_vertexshader_wined3d_parent_ops, &shader->wined3d_shader, 3);
+    wined3d_mutex_unlock();
+    if (FAILED(hr))
+    {
+        WARN("Failed to create wined3d vertex shader, hr %#x.\n", hr);
+        return hr;
+    }
+
+    shader->parent_device = &device->IDirect3DDevice9Ex_iface;
+    IDirect3DDevice9Ex_AddRef(shader->parent_device);
+
+    return D3D_OK;
+}
+
+struct d3d9_vertexshader *unsafe_impl_from_IDirect3DVertexShader9(IDirect3DVertexShader9 *iface)
+{
+    if (!iface)
+        return NULL;
+    assert(iface->lpVtbl == &d3d9_vertexshader_vtbl);
+
+    return impl_from_IDirect3DVertexShader9(iface);
+}
+
+static inline struct d3d9_pixelshader *impl_from_IDirect3DPixelShader9(IDirect3DPixelShader9 *iface)
+{
+    return CONTAINING_RECORD(iface, struct d3d9_pixelshader, IDirect3DPixelShader9_iface);
+}
+
+static HRESULT WINAPI d3d9_pixelshader_QueryInterface(IDirect3DPixelShader9 *iface, REFIID riid, void **out)
+{
+    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
+
+    if (IsEqualGUID(riid, &IID_IDirect3DPixelShader9)
+            || IsEqualGUID(riid, &IID_IUnknown))
+    {
+        IDirect3DPixelShader9_AddRef(iface);
+        *out = iface;
+        return S_OK;
+    }
+
+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+    *out = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI d3d9_pixelshader_AddRef(IDirect3DPixelShader9 *iface)
+{
+    struct d3d9_pixelshader *shader = impl_from_IDirect3DPixelShader9(iface);
+    ULONG refcount = InterlockedIncrement(&shader->refcount);
+
+    TRACE("%p increasing refcount to %u.\n", iface, refcount);
+
+    if (refcount == 1)
+    {
+        IDirect3DDevice9Ex_AddRef(shader->parent_device);
+        wined3d_mutex_lock();
+        wined3d_shader_incref(shader->wined3d_shader);
+        wined3d_mutex_unlock();
+    }
+
+    return refcount;
+}
+
+static ULONG WINAPI d3d9_pixelshader_Release(IDirect3DPixelShader9 *iface)
+{
+    struct d3d9_pixelshader *shader = impl_from_IDirect3DPixelShader9(iface);
+    ULONG refcount = InterlockedDecrement(&shader->refcount);
+
+    TRACE("%p decreasing refcount to %u.\n", iface, refcount);
+
+    if (!refcount)
+    {
+        IDirect3DDevice9Ex *device = shader->parent_device;
+
+        wined3d_mutex_lock();
+        wined3d_shader_decref(shader->wined3d_shader);
+        wined3d_mutex_unlock();
+
+        /* Release the device last, as it may cause the device to be destroyed. */
+        IDirect3DDevice9Ex_Release(device);
+    }
+
+    return refcount;
+}
+
+static HRESULT WINAPI d3d9_pixelshader_GetDevice(IDirect3DPixelShader9 *iface, IDirect3DDevice9 **device)
+{
+    struct d3d9_pixelshader *shader = impl_from_IDirect3DPixelShader9(iface);
+
+    TRACE("iface %p, device %p.\n", iface, device);
+
+    *device = (IDirect3DDevice9 *)shader->parent_device;
+    IDirect3DDevice9_AddRef(*device);
+
+    TRACE("Returning device %p.\n", *device);
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_pixelshader_GetFunction(IDirect3DPixelShader9 *iface, void *data, UINT *data_size)
+{
+    struct d3d9_pixelshader *shader = impl_from_IDirect3DPixelShader9(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, data %p, data_size %p.\n", iface, data, data_size);
+
+    wined3d_mutex_lock();
+    hr = wined3d_shader_get_byte_code(shader->wined3d_shader, data, data_size);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static const IDirect3DPixelShader9Vtbl d3d9_pixelshader_vtbl =
+{
+    /* IUnknown */
+    d3d9_pixelshader_QueryInterface,
+    d3d9_pixelshader_AddRef,
+    d3d9_pixelshader_Release,
+    /* IDirect3DPixelShader9 */
+    d3d9_pixelshader_GetDevice,
+    d3d9_pixelshader_GetFunction,
+};
+
+static void STDMETHODCALLTYPE d3d9_pixelshader_wined3d_object_destroyed(void *parent)
+{
+    HeapFree(GetProcessHeap(), 0, parent);
+}
+
+static const struct wined3d_parent_ops d3d9_pixelshader_wined3d_parent_ops =
+{
+    d3d9_pixelshader_wined3d_object_destroyed,
+};
+
+HRESULT pixelshader_init(struct d3d9_pixelshader *shader, struct d3d9_device *device, const DWORD *byte_code)
+{
+    HRESULT hr;
+
+    shader->refcount = 1;
+    shader->IDirect3DPixelShader9_iface.lpVtbl = &d3d9_pixelshader_vtbl;
+
+    wined3d_mutex_lock();
+    hr = wined3d_shader_create_ps(device->wined3d_device, byte_code, NULL, shader,
+            &d3d9_pixelshader_wined3d_parent_ops, &shader->wined3d_shader, 3);
+    wined3d_mutex_unlock();
+    if (FAILED(hr))
+    {
+        WARN("Failed to created wined3d pixel shader, hr %#x.\n", hr);
+        return hr;
+    }
+
+    shader->parent_device = &device->IDirect3DDevice9Ex_iface;
+    IDirect3DDevice9Ex_AddRef(shader->parent_device);
+
+    return D3D_OK;
+}
+
+struct d3d9_pixelshader *unsafe_impl_from_IDirect3DPixelShader9(IDirect3DPixelShader9 *iface)
+{
+    if (!iface)
+        return NULL;
+    assert(iface->lpVtbl == &d3d9_pixelshader_vtbl);
+
+    return impl_from_IDirect3DPixelShader9(iface);
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/stateblock.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/stateblock.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/stateblock.c	(revision 46521)
@@ -0,0 +1,163 @@
+/*
+ * IDirect3DStateBlock9 implementation
+ *
+ * Copyright 2002-2003 Raphael Junqueira
+ * Copyright 2002-2003 Jason Edmeades
+ * Copyright 2005 Oliver Stieber
+ *
+ * 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 "d3d9_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
+
+static inline struct d3d9_stateblock *impl_from_IDirect3DStateBlock9(IDirect3DStateBlock9 *iface)
+{
+    return CONTAINING_RECORD(iface, struct d3d9_stateblock, IDirect3DStateBlock9_iface);
+}
+
+static HRESULT WINAPI d3d9_stateblock_QueryInterface(IDirect3DStateBlock9 *iface, REFIID riid, void **out)
+{
+    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
+
+    if (IsEqualGUID(riid, &IID_IDirect3DStateBlock9)
+            || IsEqualGUID(riid, &IID_IUnknown))
+    {
+        IDirect3DStateBlock9_AddRef(iface);
+        *out = iface;
+        return S_OK;
+    }
+
+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+    *out = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI d3d9_stateblock_AddRef(IDirect3DStateBlock9 *iface)
+{
+    struct d3d9_stateblock *stateblock = impl_from_IDirect3DStateBlock9(iface);
+    ULONG refcount = InterlockedIncrement(&stateblock->refcount);
+
+    TRACE("%p increasing refcount to %u.\n", iface, refcount);
+
+    return refcount;
+}
+
+static ULONG WINAPI d3d9_stateblock_Release(IDirect3DStateBlock9 *iface)
+{
+    struct d3d9_stateblock *stateblock = impl_from_IDirect3DStateBlock9(iface);
+    ULONG refcount = InterlockedDecrement(&stateblock->refcount);
+
+    TRACE("%p decreasing refcount to %u.\n", iface, refcount);
+
+    if (!refcount)
+    {
+        wined3d_mutex_lock();
+        wined3d_stateblock_decref(stateblock->wined3d_stateblock);
+        wined3d_mutex_unlock();
+
+        IDirect3DDevice9Ex_Release(stateblock->parent_device);
+        HeapFree(GetProcessHeap(), 0, stateblock);
+    }
+
+    return refcount;
+}
+
+static HRESULT WINAPI d3d9_stateblock_GetDevice(IDirect3DStateBlock9 *iface, IDirect3DDevice9 **device)
+{
+    struct d3d9_stateblock *stateblock = impl_from_IDirect3DStateBlock9(iface);
+
+    TRACE("iface %p, device %p.\n", iface, device);
+
+    *device = (IDirect3DDevice9 *)stateblock->parent_device;
+    IDirect3DDevice9_AddRef(*device);
+
+    TRACE("Returning device %p.\n", *device);
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_stateblock_Capture(IDirect3DStateBlock9 *iface)
+{
+    struct d3d9_stateblock *stateblock = impl_from_IDirect3DStateBlock9(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    wined3d_stateblock_capture(stateblock->wined3d_stateblock);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_stateblock_Apply(IDirect3DStateBlock9 *iface)
+{
+    struct d3d9_stateblock *stateblock = impl_from_IDirect3DStateBlock9(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    wined3d_stateblock_apply(stateblock->wined3d_stateblock);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+
+static const struct IDirect3DStateBlock9Vtbl d3d9_stateblock_vtbl =
+{
+    /* IUnknown */
+    d3d9_stateblock_QueryInterface,
+    d3d9_stateblock_AddRef,
+    d3d9_stateblock_Release,
+    /* IDirect3DStateBlock9 */
+    d3d9_stateblock_GetDevice,
+    d3d9_stateblock_Capture,
+    d3d9_stateblock_Apply,
+};
+
+HRESULT stateblock_init(struct d3d9_stateblock *stateblock, struct d3d9_device *device,
+        D3DSTATEBLOCKTYPE type, struct wined3d_stateblock *wined3d_stateblock)
+{
+    HRESULT hr;
+
+    stateblock->IDirect3DStateBlock9_iface.lpVtbl = &d3d9_stateblock_vtbl;
+    stateblock->refcount = 1;
+
+    if (wined3d_stateblock)
+    {
+        stateblock->wined3d_stateblock = wined3d_stateblock;
+    }
+    else
+    {
+        wined3d_mutex_lock();
+        hr = wined3d_stateblock_create(device->wined3d_device,
+                (enum wined3d_stateblock_type)type, &stateblock->wined3d_stateblock);
+        wined3d_mutex_unlock();
+        if (FAILED(hr))
+        {
+            WARN("Failed to create wined3d stateblock, hr %#x.\n", hr);
+            return hr;
+        }
+    }
+
+    stateblock->parent_device = &device->IDirect3DDevice9Ex_iface;
+    IDirect3DDevice9Ex_AddRef(stateblock->parent_device);
+
+    return D3D_OK;
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/surface.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/surface.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/surface.c	(revision 46521)
@@ -0,0 +1,459 @@
+/*
+ * IDirect3DSurface9 implementation
+ *
+ * Copyright 2002-2005 Jason Edmeades
+ *                     Raphael Junqueira
+ *
+ * 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 "d3d9_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
+
+static inline struct d3d9_surface *impl_from_IDirect3DSurface9(IDirect3DSurface9 *iface)
+{
+    return CONTAINING_RECORD(iface, struct d3d9_surface, IDirect3DSurface9_iface);
+}
+
+static HRESULT WINAPI d3d9_surface_QueryInterface(IDirect3DSurface9 *iface, REFIID riid, void **out)
+{
+    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
+
+    if (IsEqualGUID(riid, &IID_IDirect3DSurface9)
+            || IsEqualGUID(riid, &IID_IDirect3DResource9)
+            || IsEqualGUID(riid, &IID_IUnknown))
+    {
+        IDirect3DSurface9_AddRef(iface);
+        *out = iface;
+        return S_OK;
+    }
+
+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+    *out = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI d3d9_surface_AddRef(IDirect3DSurface9 *iface)
+{
+    struct d3d9_surface *surface = impl_from_IDirect3DSurface9(iface);
+    ULONG refcount;
+
+    TRACE("iface %p.\n", iface);
+
+    if (surface->forwardReference)
+    {
+        TRACE("Forwarding to %p.\n", surface->forwardReference);
+        return IUnknown_AddRef(surface->forwardReference);
+    }
+
+    refcount = InterlockedIncrement(&surface->refcount);
+    TRACE("%p increasing refcount to %u.\n", iface, refcount);
+
+    if (refcount == 1)
+    {
+        if (surface->parent_device)
+            IDirect3DDevice9Ex_AddRef(surface->parent_device);
+        wined3d_mutex_lock();
+        wined3d_surface_incref(surface->wined3d_surface);
+        wined3d_mutex_unlock();
+    }
+
+    return refcount;
+}
+
+static ULONG WINAPI d3d9_surface_Release(IDirect3DSurface9 *iface)
+{
+    struct d3d9_surface *surface = impl_from_IDirect3DSurface9(iface);
+    ULONG refcount;
+
+    TRACE("iface %p.\n", iface);
+
+    if (surface->forwardReference)
+    {
+        TRACE("Forwarding to %p.\n", surface->forwardReference);
+        return IUnknown_Release(surface->forwardReference);
+    }
+
+    refcount = InterlockedDecrement(&surface->refcount);
+    TRACE("%p decreasing refcount to %u.\n", iface, refcount);
+
+    if (!refcount)
+    {
+        IDirect3DDevice9Ex *parent_device = surface->parent_device;
+
+        wined3d_mutex_lock();
+        wined3d_surface_decref(surface->wined3d_surface);
+        wined3d_mutex_unlock();
+
+        /* Release the device last, as it may cause the device to be destroyed. */
+        if (parent_device)
+            IDirect3DDevice9Ex_Release(parent_device);
+    }
+
+    return refcount;
+}
+
+static HRESULT WINAPI d3d9_surface_GetDevice(IDirect3DSurface9 *iface, IDirect3DDevice9 **device)
+{
+    struct d3d9_surface *surface = impl_from_IDirect3DSurface9(iface);
+
+    TRACE("iface %p, device %p.\n", iface, device);
+
+    if (surface->forwardReference)
+    {
+        IDirect3DResource9 *resource;
+        HRESULT hr;
+
+        hr = IUnknown_QueryInterface(surface->forwardReference, &IID_IDirect3DResource9, (void **)&resource);
+        if (SUCCEEDED(hr))
+        {
+            hr = IDirect3DResource9_GetDevice(resource, device);
+            IDirect3DResource9_Release(resource);
+
+            TRACE("Returning device %p.\n", *device);
+        }
+
+        return hr;
+    }
+
+    *device = (IDirect3DDevice9 *)surface->parent_device;
+    IDirect3DDevice9_AddRef(*device);
+
+    TRACE("Returning device %p.\n", *device);
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_surface_SetPrivateData(IDirect3DSurface9 *iface, REFGUID guid,
+        const void *data, DWORD data_size, DWORD flags)
+{
+    struct d3d9_surface *surface = impl_from_IDirect3DSurface9(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
+            iface, debugstr_guid(guid), data, data_size, flags);
+
+    wined3d_mutex_lock();
+    resource = wined3d_surface_get_resource(surface->wined3d_surface);
+    hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_surface_GetPrivateData(IDirect3DSurface9 *iface, REFGUID guid,
+        void *data, DWORD *data_size)
+{
+    struct d3d9_surface *surface = impl_from_IDirect3DSurface9(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s, data %p, data_size %p.\n",
+            iface, debugstr_guid(guid), data, data_size);
+
+    wined3d_mutex_lock();
+    resource = wined3d_surface_get_resource(surface->wined3d_surface);
+    hr = wined3d_resource_get_private_data(resource, guid, data, data_size);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_surface_FreePrivateData(IDirect3DSurface9 *iface, REFGUID guid)
+{
+    struct d3d9_surface *surface = impl_from_IDirect3DSurface9(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
+
+    wined3d_mutex_lock();
+    resource = wined3d_surface_get_resource(surface->wined3d_surface);
+    hr = wined3d_resource_free_private_data(resource, guid);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static DWORD WINAPI d3d9_surface_SetPriority(IDirect3DSurface9 *iface, DWORD priority)
+{
+    struct d3d9_surface *surface = impl_from_IDirect3DSurface9(iface);
+    DWORD ret;
+
+    TRACE("iface %p, priority %u.\n", iface, priority);
+
+    wined3d_mutex_lock();
+    ret = wined3d_surface_set_priority(surface->wined3d_surface, priority);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static DWORD WINAPI d3d9_surface_GetPriority(IDirect3DSurface9 *iface)
+{
+    struct d3d9_surface *surface = impl_from_IDirect3DSurface9(iface);
+    DWORD ret;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    ret = wined3d_surface_get_priority(surface->wined3d_surface);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static void WINAPI d3d9_surface_PreLoad(IDirect3DSurface9 *iface)
+{
+    struct d3d9_surface *surface = impl_from_IDirect3DSurface9(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    wined3d_surface_preload(surface->wined3d_surface);
+    wined3d_mutex_unlock();
+}
+
+static D3DRESOURCETYPE WINAPI d3d9_surface_GetType(IDirect3DSurface9 *iface)
+{
+    TRACE("iface %p.\n", iface);
+
+    return D3DRTYPE_SURFACE;
+}
+
+static HRESULT WINAPI d3d9_surface_GetContainer(IDirect3DSurface9 *iface, REFIID riid, void **container)
+{
+    struct d3d9_surface *surface = impl_from_IDirect3DSurface9(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, riid %s, container %p.\n", iface, debugstr_guid(riid), container);
+
+    if (!surface->container)
+        return E_NOINTERFACE;
+
+    hr = IUnknown_QueryInterface(surface->container, riid, container);
+
+    TRACE("Returning %p.\n", *container);
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_surface_GetDesc(IDirect3DSurface9 *iface, D3DSURFACE_DESC *desc)
+{
+    struct d3d9_surface *surface = impl_from_IDirect3DSurface9(iface);
+    struct wined3d_resource_desc wined3d_desc;
+    struct wined3d_resource *wined3d_resource;
+
+    TRACE("iface %p, desc %p.\n", iface, desc);
+
+    wined3d_mutex_lock();
+    wined3d_resource = wined3d_surface_get_resource(surface->wined3d_surface);
+    wined3d_resource_get_desc(wined3d_resource, &wined3d_desc);
+    wined3d_mutex_unlock();
+
+    desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format);
+    desc->Type = wined3d_desc.resource_type;
+    desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
+    desc->Pool = wined3d_desc.pool;
+    desc->MultiSampleType = wined3d_desc.multisample_type;
+    desc->MultiSampleQuality = wined3d_desc.multisample_quality;
+    desc->Width = wined3d_desc.width;
+    desc->Height = wined3d_desc.height;
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_surface_LockRect(IDirect3DSurface9 *iface,
+        D3DLOCKED_RECT *locked_rect, const RECT *rect, DWORD flags)
+{
+    struct d3d9_surface *surface = impl_from_IDirect3DSurface9(iface);
+    struct wined3d_map_desc map_desc;
+    HRESULT hr;
+
+    TRACE("iface %p, locked_rect %p, rect %s, flags %#x.\n",
+            iface, locked_rect, wine_dbgstr_rect(rect), flags);
+
+    wined3d_mutex_lock();
+    hr = wined3d_surface_map(surface->wined3d_surface, &map_desc, rect, flags);
+    wined3d_mutex_unlock();
+
+    locked_rect->Pitch = map_desc.row_pitch;
+    locked_rect->pBits = map_desc.data;
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_surface_UnlockRect(IDirect3DSurface9 *iface)
+{
+    struct d3d9_surface *surface = impl_from_IDirect3DSurface9(iface);
+    HRESULT hr;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    hr = wined3d_surface_unmap(surface->wined3d_surface);
+    wined3d_mutex_unlock();
+
+    switch(hr)
+    {
+        case WINEDDERR_NOTLOCKED:       return D3DERR_INVALIDCALL;
+        default:                        return hr;
+    }
+}
+
+static HRESULT WINAPI d3d9_surface_GetDC(IDirect3DSurface9 *iface, HDC *dc)
+{
+    struct d3d9_surface *surface = impl_from_IDirect3DSurface9(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, dc %p.\n", iface, dc);
+
+    if (!surface->getdc_supported)
+    {
+        WARN("Surface does not support GetDC, returning D3DERR_INVALIDCALL\n");
+        /* Don't touch the DC */
+        return D3DERR_INVALIDCALL;
+    }
+
+    wined3d_mutex_lock();
+    hr = wined3d_surface_getdc(surface->wined3d_surface, dc);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_surface_ReleaseDC(IDirect3DSurface9 *iface, HDC dc)
+{
+    struct d3d9_surface *surface = impl_from_IDirect3DSurface9(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, dc %p.\n", iface, dc);
+
+    wined3d_mutex_lock();
+    hr = wined3d_surface_releasedc(surface->wined3d_surface, dc);
+    wined3d_mutex_unlock();
+
+    switch (hr)
+    {
+        case WINEDDERR_NODC:    return D3DERR_INVALIDCALL;
+        default:                return hr;
+    }
+}
+
+static const struct IDirect3DSurface9Vtbl d3d9_surface_vtbl =
+{
+    /* IUnknown */
+    d3d9_surface_QueryInterface,
+    d3d9_surface_AddRef,
+    d3d9_surface_Release,
+    /* IDirect3DResource9 */
+    d3d9_surface_GetDevice,
+    d3d9_surface_SetPrivateData,
+    d3d9_surface_GetPrivateData,
+    d3d9_surface_FreePrivateData,
+    d3d9_surface_SetPriority,
+    d3d9_surface_GetPriority,
+    d3d9_surface_PreLoad,
+    d3d9_surface_GetType,
+    /* IDirect3DSurface9 */
+    d3d9_surface_GetContainer,
+    d3d9_surface_GetDesc,
+    d3d9_surface_LockRect,
+    d3d9_surface_UnlockRect,
+    d3d9_surface_GetDC,
+    d3d9_surface_ReleaseDC,
+};
+
+static void STDMETHODCALLTYPE surface_wined3d_object_destroyed(void *parent)
+{
+    HeapFree(GetProcessHeap(), 0, parent);
+}
+
+static const struct wined3d_parent_ops d3d9_surface_wined3d_parent_ops =
+{
+    surface_wined3d_object_destroyed,
+};
+
+HRESULT surface_init(struct d3d9_surface *surface, struct d3d9_device *device, UINT width, UINT height,
+        D3DFORMAT format, DWORD flags, DWORD usage, D3DPOOL pool, D3DMULTISAMPLE_TYPE multisample_type,
+        DWORD multisample_quality
+#ifdef VBOX_WITH_WDDM
+        , HANDLE *shared_handle
+        , void *pvClientMem
+#endif
+        )
+{
+    HRESULT hr;
+
+    surface->IDirect3DSurface9_iface.lpVtbl = &d3d9_surface_vtbl;
+    surface->refcount = 1;
+
+    switch (format)
+    {
+        case D3DFMT_A8R8G8B8:
+        case D3DFMT_X8R8G8B8:
+        case D3DFMT_R5G6B5:
+        case D3DFMT_X1R5G5B5:
+        case D3DFMT_A1R5G5B5:
+        case D3DFMT_R8G8B8:
+            surface->getdc_supported = TRUE;
+            break;
+
+        default:
+            surface->getdc_supported = FALSE;
+            break;
+    }
+
+    /* FIXME: Check MAX bounds of MultisampleQuality. */
+    if (multisample_quality > 0)
+    {
+        FIXME("Multisample quality set to %u, substituting 0.\n", multisample_quality);
+        multisample_quality = 0;
+    }
+
+    wined3d_mutex_lock();
+    hr = wined3d_surface_create(device->wined3d_device, width, height, wined3dformat_from_d3dformat(format),
+            usage & WINED3DUSAGE_MASK, (enum wined3d_pool)pool, multisample_type, multisample_quality,
+            flags, surface, &d3d9_surface_wined3d_parent_ops, &surface->wined3d_surface
+#ifdef VBOX_WITH_WDDM
+            , shared_handle
+            , pvClientMem
+#endif
+            );
+    wined3d_mutex_unlock();
+    if (FAILED(hr))
+    {
+        WARN("Failed to create wined3d surface, hr %#x.\n", hr);
+        return hr;
+    }
+
+    surface->parent_device = &device->IDirect3DDevice9Ex_iface;
+    IDirect3DDevice9Ex_AddRef(surface->parent_device);
+
+    return D3D_OK;
+}
+
+struct d3d9_surface *unsafe_impl_from_IDirect3DSurface9(IDirect3DSurface9 *iface)
+{
+    if (!iface)
+        return NULL;
+    assert(iface->lpVtbl == &d3d9_surface_vtbl);
+
+    return impl_from_IDirect3DSurface9(iface);
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/swapchain.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/swapchain.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/swapchain.c	(revision 46521)
@@ -0,0 +1,308 @@
+/*
+ * IDirect3DSwapChain9 implementation
+ *
+ * Copyright 2002-2003 Jason Edmeades
+ *                     Raphael Junqueira
+ * Copyright 2005 Oliver Stieber
+ *
+ * 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 "d3d9_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
+
+static inline struct d3d9_swapchain *impl_from_IDirect3DSwapChain9(IDirect3DSwapChain9 *iface)
+{
+    return CONTAINING_RECORD(iface, struct d3d9_swapchain, IDirect3DSwapChain9_iface);
+}
+
+static HRESULT WINAPI d3d9_swapchain_QueryInterface(IDirect3DSwapChain9 *iface, REFIID riid, void **out)
+{
+    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
+
+    if (IsEqualGUID(riid, &IID_IDirect3DSwapChain9)
+            || IsEqualGUID(riid, &IID_IUnknown))
+    {
+        IDirect3DSwapChain9_AddRef(iface);
+        *out = iface;
+        return S_OK;
+    }
+
+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+    *out = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI d3d9_swapchain_AddRef(IDirect3DSwapChain9 *iface)
+{
+    struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9(iface);
+    ULONG refcount = InterlockedIncrement(&swapchain->refcount);
+
+    TRACE("%p increasing refcount to %u.\n", iface, refcount);
+
+    if (refcount == 1)
+    {
+        if (swapchain->parent_device)
+            IDirect3DDevice9Ex_AddRef(swapchain->parent_device);
+
+        wined3d_mutex_lock();
+        wined3d_swapchain_incref(swapchain->wined3d_swapchain);
+        wined3d_mutex_unlock();
+    }
+
+    return refcount;
+}
+
+static ULONG WINAPI d3d9_swapchain_Release(IDirect3DSwapChain9 *iface)
+{
+    struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9(iface);
+    ULONG refcount = InterlockedDecrement(&swapchain->refcount);
+
+    TRACE("%p decreasing refcount to %u.\n", iface, refcount);
+
+    if (!refcount)
+    {
+        IDirect3DDevice9Ex *parent_device = swapchain->parent_device;
+
+        wined3d_mutex_lock();
+        wined3d_swapchain_decref(swapchain->wined3d_swapchain);
+        wined3d_mutex_unlock();
+
+        /* Release the device last, as it may cause the device to be destroyed. */
+        if (parent_device)
+            IDirect3DDevice9Ex_Release(parent_device);
+    }
+
+    return refcount;
+}
+
+static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_swapchain_Present(IDirect3DSwapChain9 *iface,
+        const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override,
+        const RGNDATA *dirty_region, DWORD flags)
+{
+    struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, src_rect %s, dst_rect %s, dst_window_override %p, dirty_region %p, flags %#x.\n",
+            iface, wine_dbgstr_rect(src_rect), wine_dbgstr_rect(dst_rect),
+            dst_window_override, dirty_region, flags);
+
+    wined3d_mutex_lock();
+    hr = wined3d_swapchain_present(swapchain->wined3d_swapchain, src_rect,
+            dst_rect, dst_window_override, dirty_region, flags);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_swapchain_GetFrontBufferData(IDirect3DSwapChain9 *iface, IDirect3DSurface9 *surface)
+{
+    struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9(iface);
+    struct d3d9_surface *dst = unsafe_impl_from_IDirect3DSurface9(surface);
+    HRESULT hr;
+
+    TRACE("iface %p, surface %p.\n", iface, surface);
+
+    wined3d_mutex_lock();
+    hr = wined3d_swapchain_get_front_buffer_data(swapchain->wined3d_swapchain, dst->wined3d_surface);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_swapchain_GetBackBuffer(IDirect3DSwapChain9 *iface,
+        UINT backbuffer_idx, D3DBACKBUFFER_TYPE backbuffer_type, IDirect3DSurface9 **backbuffer)
+{
+    struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9(iface);
+    struct wined3d_surface *wined3d_surface = NULL;
+    struct d3d9_surface *surface_impl;
+    HRESULT hr = D3D_OK;
+
+    TRACE("iface %p, backbuffer_idx %u, backbuffer_type %#x, backbuffer %p.\n",
+            iface, backbuffer_idx, backbuffer_type, backbuffer);
+
+    wined3d_mutex_lock();
+    if ((wined3d_surface = wined3d_swapchain_get_back_buffer(swapchain->wined3d_swapchain,
+            backbuffer_idx, (enum wined3d_backbuffer_type)backbuffer_type)))
+    {
+       surface_impl = wined3d_surface_get_parent(wined3d_surface);
+       *backbuffer = &surface_impl->IDirect3DSurface9_iface;
+       IDirect3DSurface9_AddRef(*backbuffer);
+    }
+    else
+    {
+        hr = D3DERR_INVALIDCALL;
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_swapchain_GetRasterStatus(IDirect3DSwapChain9 *iface, D3DRASTER_STATUS *raster_status)
+{
+    struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, raster_status %p.\n", iface, raster_status);
+
+    wined3d_mutex_lock();
+    hr = wined3d_swapchain_get_raster_status(swapchain->wined3d_swapchain,
+            (struct wined3d_raster_status *)raster_status);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_swapchain_GetDisplayMode(IDirect3DSwapChain9 *iface, D3DDISPLAYMODE *mode)
+{
+    struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9(iface);
+    struct wined3d_display_mode wined3d_mode;
+    HRESULT hr;
+
+    TRACE("iface %p, mode %p.\n", iface, mode);
+
+    wined3d_mutex_lock();
+    hr = wined3d_swapchain_get_display_mode(swapchain->wined3d_swapchain, &wined3d_mode, NULL);
+    wined3d_mutex_unlock();
+
+    if (SUCCEEDED(hr))
+    {
+        mode->Width = wined3d_mode.width;
+        mode->Height = wined3d_mode.height;
+        mode->RefreshRate = wined3d_mode.refresh_rate;
+        mode->Format = d3dformat_from_wined3dformat(wined3d_mode.format_id);
+    }
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_swapchain_GetDevice(IDirect3DSwapChain9 *iface, IDirect3DDevice9 **device)
+{
+    struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9(iface);
+
+    TRACE("iface %p, device %p.\n", iface, device);
+
+    *device = (IDirect3DDevice9 *)swapchain->parent_device;
+    IDirect3DDevice9_AddRef(*device);
+
+    TRACE("Returning device %p.\n", *device);
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_swapchain_GetPresentParameters(IDirect3DSwapChain9 *iface,
+        D3DPRESENT_PARAMETERS *parameters)
+{
+    struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9(iface);
+    struct wined3d_swapchain_desc desc;
+
+    TRACE("iface %p, parameters %p.\n", iface, parameters);
+
+    wined3d_mutex_lock();
+    wined3d_swapchain_get_desc(swapchain->wined3d_swapchain, &desc);
+    wined3d_mutex_unlock();
+    present_parameters_from_wined3d_swapchain_desc(parameters, &desc);
+
+    return D3D_OK;
+}
+
+
+static const struct IDirect3DSwapChain9Vtbl d3d9_swapchain_vtbl =
+{
+    d3d9_swapchain_QueryInterface,
+    d3d9_swapchain_AddRef,
+    d3d9_swapchain_Release,
+    d3d9_swapchain_Present,
+    d3d9_swapchain_GetFrontBufferData,
+    d3d9_swapchain_GetBackBuffer,
+    d3d9_swapchain_GetRasterStatus,
+    d3d9_swapchain_GetDisplayMode,
+    d3d9_swapchain_GetDevice,
+    d3d9_swapchain_GetPresentParameters,
+};
+
+static void STDMETHODCALLTYPE d3d9_swapchain_wined3d_object_released(void *parent)
+{
+    HeapFree(GetProcessHeap(), 0, parent);
+}
+
+static const struct wined3d_parent_ops d3d9_swapchain_wined3d_parent_ops =
+{
+    d3d9_swapchain_wined3d_object_released,
+};
+
+static HRESULT swapchain_init(struct d3d9_swapchain *swapchain, struct d3d9_device *device,
+        struct wined3d_swapchain_desc *desc)
+{
+    HRESULT hr;
+
+    swapchain->refcount = 1;
+    swapchain->IDirect3DSwapChain9_iface.lpVtbl = &d3d9_swapchain_vtbl;
+
+    wined3d_mutex_lock();
+    hr = wined3d_swapchain_create(device->wined3d_device, desc, swapchain,
+            &d3d9_swapchain_wined3d_parent_ops, &swapchain->wined3d_swapchain);
+    wined3d_mutex_unlock();
+
+    if (FAILED(hr))
+    {
+        WARN("Failed to create wined3d swapchain, hr %#x.\n", hr);
+        return hr;
+    }
+
+    swapchain->parent_device = &device->IDirect3DDevice9Ex_iface;
+    IDirect3DDevice9Ex_AddRef(swapchain->parent_device);
+
+    return D3D_OK;
+}
+
+HRESULT d3d9_swapchain_create(struct d3d9_device *device, struct wined3d_swapchain_desc *desc,
+        struct d3d9_swapchain **swapchain)
+{
+    struct d3d9_swapchain *object;
+    HRESULT hr;
+
+    if (!(object = HeapAlloc(GetProcessHeap(),  HEAP_ZERO_MEMORY, sizeof(*object))))
+        return E_OUTOFMEMORY;
+
+    if (FAILED(hr = swapchain_init(object, device, desc)))
+    {
+        WARN("Failed to initialize swapchain, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created swapchain %p.\n", object);
+    *swapchain = object;
+
+    return D3D_OK;
+}
+
+#ifdef VBOX_WITH_WDDM
+VBOXWINEEX_DECL(HRESULT) VBoxWineExD3DSwapchain9Present(IDirect3DSwapChain9 *iface,
+                                IDirect3DSurface9 *surf) /* use the given surface as a frontbuffer content source */
+{
+    struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9(iface);
+    struct d3d9_surface *rt = unsafe_impl_from_IDirect3DSurface9(surf);
+    HRESULT hr;
+    wined3d_mutex_lock();
+    hr = wined3d_swapchain_present_rt(swapchain->wined3d_swapchain, rt->wined3d_surface);
+    wined3d_mutex_unlock();
+    return hr;
+}
+#endif
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/texture.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/texture.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/texture.c	(revision 46521)
@@ -0,0 +1,1453 @@
+/*
+ * Copyright 2002-2005 Jason Edmeades
+ * Copyright 2002-2005 Raphael Junqueira
+ * Copyright 2005 Oliver Stieber
+ *
+ * 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 "d3d9_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
+
+static inline struct d3d9_texture *impl_from_IDirect3DTexture9(IDirect3DTexture9 *iface)
+{
+    return CONTAINING_RECORD(iface, struct d3d9_texture, IDirect3DBaseTexture9_iface);
+}
+
+static inline struct d3d9_texture *impl_from_IDirect3DCubeTexture9(IDirect3DCubeTexture9 *iface)
+{
+    return CONTAINING_RECORD(iface, struct d3d9_texture, IDirect3DBaseTexture9_iface);
+}
+
+static inline struct d3d9_texture *impl_from_IDirect3DVolumeTexture9(IDirect3DVolumeTexture9 *iface)
+{
+    return CONTAINING_RECORD(iface, struct d3d9_texture, IDirect3DBaseTexture9_iface);
+}
+
+static HRESULT WINAPI d3d9_texture_2d_QueryInterface(IDirect3DTexture9 *iface, REFIID riid, void **out)
+{
+    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
+
+    if (IsEqualGUID(riid, &IID_IDirect3DTexture9)
+            || IsEqualGUID(riid, &IID_IDirect3DBaseTexture9)
+            || IsEqualGUID(riid, &IID_IDirect3DResource9)
+            || IsEqualGUID(riid, &IID_IUnknown))
+    {
+        IDirect3DTexture9_AddRef(iface);
+        *out = iface;
+        return S_OK;
+    }
+
+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+    *out = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI d3d9_texture_2d_AddRef(IDirect3DTexture9 *iface)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
+    ULONG ref = InterlockedIncrement(&texture->refcount);
+
+    TRACE("%p increasing refcount to %u.\n", iface, ref);
+
+    if (ref == 1)
+    {
+        IDirect3DDevice9Ex_AddRef(texture->parent_device);
+        wined3d_mutex_lock();
+        wined3d_texture_incref(texture->wined3d_texture);
+        wined3d_mutex_unlock();
+    }
+
+    return ref;
+}
+
+static ULONG WINAPI d3d9_texture_2d_Release(IDirect3DTexture9 *iface)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
+    ULONG ref = InterlockedDecrement(&texture->refcount);
+
+    TRACE("%p decreasing refcount to %u.\n", iface, ref);
+
+    if (!ref)
+    {
+        IDirect3DDevice9Ex *parent_device = texture->parent_device;
+
+        wined3d_mutex_lock();
+        wined3d_texture_decref(texture->wined3d_texture);
+        wined3d_mutex_unlock();
+
+        /* Release the device last, as it may cause the device to be destroyed. */
+        IDirect3DDevice9Ex_Release(parent_device);
+    }
+    return ref;
+}
+
+static HRESULT WINAPI d3d9_texture_2d_GetDevice(IDirect3DTexture9 *iface, IDirect3DDevice9 **device)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
+
+    TRACE("iface %p, device %p.\n", iface, device);
+
+    *device = (IDirect3DDevice9 *)texture->parent_device;
+    IDirect3DDevice9_AddRef(*device);
+
+    TRACE("Returning device %p.\n", *device);
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_texture_2d_SetPrivateData(IDirect3DTexture9 *iface,
+        REFGUID guid, const void *data, DWORD data_size, DWORD flags)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
+            iface, debugstr_guid(guid), data, data_size, flags);
+
+    wined3d_mutex_lock();
+    resource = wined3d_texture_get_resource(texture->wined3d_texture);
+    hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_texture_2d_GetPrivateData(IDirect3DTexture9 *iface,
+        REFGUID guid, void *data, DWORD *data_size)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s, data %p, data_size %p.\n",
+            iface, debugstr_guid(guid), data, data_size);
+
+    wined3d_mutex_lock();
+    resource = wined3d_texture_get_resource(texture->wined3d_texture);
+    hr = wined3d_resource_get_private_data(resource, guid, data, data_size);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_texture_2d_FreePrivateData(IDirect3DTexture9 *iface, REFGUID guid)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
+
+    wined3d_mutex_lock();
+    resource = wined3d_texture_get_resource(texture->wined3d_texture);
+    hr = wined3d_resource_free_private_data(resource, guid);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static DWORD WINAPI d3d9_texture_2d_SetPriority(IDirect3DTexture9 *iface, DWORD priority)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
+    DWORD ret;
+
+    TRACE("iface %p, priority %u.\n", iface, priority);
+
+    wined3d_mutex_lock();
+    ret = wined3d_texture_set_priority(texture->wined3d_texture, priority);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static DWORD WINAPI d3d9_texture_2d_GetPriority(IDirect3DTexture9 *iface)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
+    DWORD ret;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    ret = wined3d_texture_get_priority(texture->wined3d_texture);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static void WINAPI d3d9_texture_2d_PreLoad(IDirect3DTexture9 *iface)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    wined3d_texture_preload(texture->wined3d_texture);
+    wined3d_mutex_unlock();
+}
+
+static D3DRESOURCETYPE WINAPI d3d9_texture_2d_GetType(IDirect3DTexture9 *iface)
+{
+    TRACE("iface %p.\n", iface);
+
+    return D3DRTYPE_TEXTURE;
+}
+
+static DWORD WINAPI d3d9_texture_2d_SetLOD(IDirect3DTexture9 *iface, DWORD lod)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
+    DWORD ret;
+
+    TRACE("iface %p, lod %u.\n", iface, lod);
+
+    wined3d_mutex_lock();
+    ret = wined3d_texture_set_lod(texture->wined3d_texture, lod);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static DWORD WINAPI d3d9_texture_2d_GetLOD(IDirect3DTexture9 *iface)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
+    DWORD ret;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    ret = wined3d_texture_get_lod(texture->wined3d_texture);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static DWORD WINAPI d3d9_texture_2d_GetLevelCount(IDirect3DTexture9 *iface)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
+    DWORD ret;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    ret = wined3d_texture_get_level_count(texture->wined3d_texture);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static HRESULT WINAPI d3d9_texture_2d_SetAutoGenFilterType(IDirect3DTexture9 *iface, D3DTEXTUREFILTERTYPE filter_type)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, filter_type %#x.\n", iface, filter_type);
+
+    wined3d_mutex_lock();
+    hr = wined3d_texture_set_autogen_filter_type(texture->wined3d_texture,
+            (enum wined3d_texture_filter_type)filter_type);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static D3DTEXTUREFILTERTYPE WINAPI d3d9_texture_2d_GetAutoGenFilterType(IDirect3DTexture9 *iface)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
+    D3DTEXTUREFILTERTYPE ret;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    ret = (D3DTEXTUREFILTERTYPE)wined3d_texture_get_autogen_filter_type(texture->wined3d_texture);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static void WINAPI d3d9_texture_2d_GenerateMipSubLevels(IDirect3DTexture9 *iface)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    wined3d_texture_generate_mipmaps(texture->wined3d_texture);
+    wined3d_mutex_unlock();
+}
+
+static HRESULT WINAPI d3d9_texture_2d_GetLevelDesc(IDirect3DTexture9 *iface, UINT level, D3DSURFACE_DESC *desc)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
+    struct wined3d_resource *sub_resource;
+    HRESULT hr = D3D_OK;
+
+    TRACE("iface %p, level %u, desc %p.\n", iface, level, desc);
+
+    wined3d_mutex_lock();
+    if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
+        hr = D3DERR_INVALIDCALL;
+    else
+    {
+        struct wined3d_resource_desc wined3d_desc;
+
+        wined3d_resource_get_desc(sub_resource, &wined3d_desc);
+        desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format);
+        desc->Type = wined3d_desc.resource_type;
+        desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
+        desc->Pool = wined3d_desc.pool;
+        desc->MultiSampleType = wined3d_desc.multisample_type;
+        desc->MultiSampleQuality = wined3d_desc.multisample_quality;
+        desc->Width = wined3d_desc.width;
+        desc->Height = wined3d_desc.height;
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_texture_2d_GetSurfaceLevel(IDirect3DTexture9 *iface,
+        UINT level, IDirect3DSurface9 **surface)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
+    struct wined3d_resource *sub_resource;
+    struct d3d9_surface *surface_impl;
+
+    TRACE("iface %p, level %u, surface %p.\n", iface, level, surface);
+
+    wined3d_mutex_lock();
+    if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
+    {
+        wined3d_mutex_unlock();
+        return D3DERR_INVALIDCALL;
+    }
+
+    surface_impl = wined3d_resource_get_parent(sub_resource);
+    *surface = &surface_impl->IDirect3DSurface9_iface;
+    IDirect3DSurface9_AddRef(*surface);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_texture_2d_LockRect(IDirect3DTexture9 *iface,
+        UINT level, D3DLOCKED_RECT *locked_rect, const RECT *rect, DWORD flags)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
+    struct wined3d_resource *sub_resource;
+    struct d3d9_surface *surface_impl;
+    HRESULT hr;
+
+    TRACE("iface %p, level %u, locked_rect %p, rect %p, flags %#x.\n",
+            iface, level, locked_rect, rect, flags);
+
+    wined3d_mutex_lock();
+    if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
+        hr = D3DERR_INVALIDCALL;
+    else
+    {
+        surface_impl = wined3d_resource_get_parent(sub_resource);
+        hr = IDirect3DSurface9_LockRect(&surface_impl->IDirect3DSurface9_iface, locked_rect, rect, flags);
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_texture_2d_UnlockRect(IDirect3DTexture9 *iface, UINT level)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
+    struct wined3d_resource *sub_resource;
+    struct d3d9_surface *surface_impl;
+    HRESULT hr;
+
+    TRACE("iface %p, level %u.\n", iface, level);
+
+    wined3d_mutex_lock();
+    if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
+        hr = D3DERR_INVALIDCALL;
+    else
+    {
+        surface_impl = wined3d_resource_get_parent(sub_resource);
+        hr = IDirect3DSurface9_UnlockRect(&surface_impl->IDirect3DSurface9_iface);
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_texture_2d_AddDirtyRect(IDirect3DTexture9 *iface, const RECT *dirty_rect)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, dirty_rect %s.\n",
+            iface, wine_dbgstr_rect(dirty_rect));
+
+    wined3d_mutex_lock();
+    if (!dirty_rect)
+        hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, 0, NULL);
+    else
+    {
+        struct wined3d_box dirty_region;
+
+        dirty_region.left = dirty_rect->left;
+        dirty_region.top = dirty_rect->top;
+        dirty_region.right = dirty_rect->right;
+        dirty_region.bottom = dirty_rect->bottom;
+        dirty_region.front = 0;
+        dirty_region.back = 1;
+        hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, 0, &dirty_region);
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static const IDirect3DTexture9Vtbl d3d9_texture_2d_vtbl =
+{
+    /* IUnknown */
+    d3d9_texture_2d_QueryInterface,
+    d3d9_texture_2d_AddRef,
+    d3d9_texture_2d_Release,
+     /* IDirect3DResource9 */
+    d3d9_texture_2d_GetDevice,
+    d3d9_texture_2d_SetPrivateData,
+    d3d9_texture_2d_GetPrivateData,
+    d3d9_texture_2d_FreePrivateData,
+    d3d9_texture_2d_SetPriority,
+    d3d9_texture_2d_GetPriority,
+    d3d9_texture_2d_PreLoad,
+    d3d9_texture_2d_GetType,
+    /* IDirect3dBaseTexture9 */
+    d3d9_texture_2d_SetLOD,
+    d3d9_texture_2d_GetLOD,
+    d3d9_texture_2d_GetLevelCount,
+    d3d9_texture_2d_SetAutoGenFilterType,
+    d3d9_texture_2d_GetAutoGenFilterType,
+    d3d9_texture_2d_GenerateMipSubLevels,
+    /* IDirect3DTexture9 */
+    d3d9_texture_2d_GetLevelDesc,
+    d3d9_texture_2d_GetSurfaceLevel,
+    d3d9_texture_2d_LockRect,
+    d3d9_texture_2d_UnlockRect,
+    d3d9_texture_2d_AddDirtyRect,
+};
+
+static HRESULT WINAPI d3d9_texture_cube_QueryInterface(IDirect3DCubeTexture9 *iface, REFIID riid, void **out)
+{
+    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
+
+    if (IsEqualGUID(riid, &IID_IDirect3DCubeTexture9)
+            || IsEqualGUID(riid, &IID_IDirect3DBaseTexture9)
+            || IsEqualGUID(riid, &IID_IDirect3DResource9)
+            || IsEqualGUID(riid, &IID_IUnknown))
+    {
+        IDirect3DCubeTexture9_AddRef(iface);
+        *out = iface;
+        return S_OK;
+    }
+
+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+    *out = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI d3d9_texture_cube_AddRef(IDirect3DCubeTexture9 *iface)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
+    ULONG ref = InterlockedIncrement(&texture->refcount);
+
+    TRACE("%p increasing refcount to %u.\n", iface, ref);
+
+    if (ref == 1)
+    {
+        IDirect3DDevice9Ex_AddRef(texture->parent_device);
+        wined3d_mutex_lock();
+        wined3d_texture_incref(texture->wined3d_texture);
+        wined3d_mutex_unlock();
+    }
+
+    return ref;
+}
+
+static ULONG WINAPI d3d9_texture_cube_Release(IDirect3DCubeTexture9 *iface)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
+    ULONG ref = InterlockedDecrement(&texture->refcount);
+
+    TRACE("%p decreasing refcount to %u.\n", iface, ref);
+
+    if (!ref)
+    {
+        IDirect3DDevice9Ex *parent_device = texture->parent_device;
+
+        TRACE("Releasing child %p.\n", texture->wined3d_texture);
+
+        wined3d_mutex_lock();
+        wined3d_texture_decref(texture->wined3d_texture);
+        wined3d_mutex_unlock();
+
+        /* Release the device last, as it may cause the device to be destroyed. */
+        IDirect3DDevice9Ex_Release(parent_device);
+    }
+    return ref;
+}
+
+static HRESULT WINAPI d3d9_texture_cube_GetDevice(IDirect3DCubeTexture9 *iface, IDirect3DDevice9 **device)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
+
+    TRACE("iface %p, device %p.\n", iface, device);
+
+    *device = (IDirect3DDevice9 *)texture->parent_device;
+    IDirect3DDevice9_AddRef(*device);
+
+    TRACE("Returning device %p.\n", *device);
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_texture_cube_SetPrivateData(IDirect3DCubeTexture9 *iface,
+        REFGUID guid, const void *data, DWORD data_size, DWORD flags)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
+            iface, debugstr_guid(guid), data, data_size, flags);
+
+    wined3d_mutex_lock();
+    resource = wined3d_texture_get_resource(texture->wined3d_texture);
+    hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_texture_cube_GetPrivateData(IDirect3DCubeTexture9 *iface,
+        REFGUID guid, void *data, DWORD *data_size)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s, data %p, data_size %p.\n",
+            iface, debugstr_guid(guid), data, data_size);
+
+    wined3d_mutex_lock();
+    resource = wined3d_texture_get_resource(texture->wined3d_texture);
+    hr = wined3d_resource_get_private_data(resource, guid, data, data_size);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_texture_cube_FreePrivateData(IDirect3DCubeTexture9 *iface, REFGUID guid)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
+
+    wined3d_mutex_lock();
+    resource = wined3d_texture_get_resource(texture->wined3d_texture);
+    hr = wined3d_resource_free_private_data(resource, guid);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static DWORD WINAPI d3d9_texture_cube_SetPriority(IDirect3DCubeTexture9 *iface, DWORD priority)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
+    DWORD ret;
+
+    TRACE("iface %p, priority %u.\n", iface, priority);
+
+    wined3d_mutex_lock();
+    ret = wined3d_texture_set_priority(texture->wined3d_texture, priority);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static DWORD WINAPI d3d9_texture_cube_GetPriority(IDirect3DCubeTexture9 *iface)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
+    DWORD ret;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    ret = wined3d_texture_get_priority(texture->wined3d_texture);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static void WINAPI d3d9_texture_cube_PreLoad(IDirect3DCubeTexture9 *iface)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    wined3d_texture_preload(texture->wined3d_texture);
+    wined3d_mutex_unlock();
+}
+
+static D3DRESOURCETYPE WINAPI d3d9_texture_cube_GetType(IDirect3DCubeTexture9 *iface)
+{
+    TRACE("iface %p.\n", iface);
+
+    return D3DRTYPE_CUBETEXTURE;
+}
+
+static DWORD WINAPI d3d9_texture_cube_SetLOD(IDirect3DCubeTexture9 *iface, DWORD lod)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
+    DWORD ret;
+
+    TRACE("iface %p, lod %u.\n", iface, lod);
+
+    wined3d_mutex_lock();
+    ret = wined3d_texture_set_lod(texture->wined3d_texture, lod);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static DWORD WINAPI d3d9_texture_cube_GetLOD(IDirect3DCubeTexture9 *iface)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
+    DWORD ret;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    ret = wined3d_texture_get_lod(texture->wined3d_texture);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static DWORD WINAPI d3d9_texture_cube_GetLevelCount(IDirect3DCubeTexture9 *iface)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
+    DWORD ret;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    ret = wined3d_texture_get_level_count(texture->wined3d_texture);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static HRESULT WINAPI d3d9_texture_cube_SetAutoGenFilterType(IDirect3DCubeTexture9 *iface,
+        D3DTEXTUREFILTERTYPE filter_type)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, filter_type %#x.\n", iface, filter_type);
+
+    wined3d_mutex_lock();
+    hr = wined3d_texture_set_autogen_filter_type(texture->wined3d_texture,
+            (enum wined3d_texture_filter_type)filter_type);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static D3DTEXTUREFILTERTYPE WINAPI d3d9_texture_cube_GetAutoGenFilterType(IDirect3DCubeTexture9 *iface)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
+    D3DTEXTUREFILTERTYPE ret;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    ret = (D3DTEXTUREFILTERTYPE)wined3d_texture_get_autogen_filter_type(texture->wined3d_texture);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static void WINAPI d3d9_texture_cube_GenerateMipSubLevels(IDirect3DCubeTexture9 *iface)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    wined3d_texture_generate_mipmaps(texture->wined3d_texture);
+    wined3d_mutex_unlock();
+}
+
+static HRESULT WINAPI d3d9_texture_cube_GetLevelDesc(IDirect3DCubeTexture9 *iface, UINT level, D3DSURFACE_DESC *desc)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
+    struct wined3d_resource *sub_resource;
+    HRESULT hr = D3D_OK;
+    DWORD level_count;
+
+    TRACE("iface %p, level %u, desc %p.\n", iface, level, desc);
+
+    wined3d_mutex_lock();
+    level_count = wined3d_texture_get_level_count(texture->wined3d_texture);
+    if (level >= level_count)
+    {
+        wined3d_mutex_unlock();
+        return D3DERR_INVALIDCALL;
+    }
+
+    if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
+        hr = D3DERR_INVALIDCALL;
+    else
+    {
+        struct wined3d_resource_desc wined3d_desc;
+
+        wined3d_resource_get_desc(sub_resource, &wined3d_desc);
+        desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format);
+        desc->Type = wined3d_desc.resource_type;
+        desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
+        desc->Pool = wined3d_desc.pool;
+        desc->MultiSampleType = wined3d_desc.multisample_type;
+        desc->MultiSampleQuality = wined3d_desc.multisample_quality;
+        desc->Width = wined3d_desc.width;
+        desc->Height = wined3d_desc.height;
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_texture_cube_GetCubeMapSurface(IDirect3DCubeTexture9 *iface,
+        D3DCUBEMAP_FACES face, UINT level, IDirect3DSurface9 **surface)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
+    struct wined3d_resource *sub_resource;
+    struct d3d9_surface *surface_impl;
+    UINT sub_resource_idx;
+    DWORD level_count;
+
+    TRACE("iface %p, face %#x, level %u, surface %p.\n", iface, face, level, surface);
+
+    wined3d_mutex_lock();
+    level_count = wined3d_texture_get_level_count(texture->wined3d_texture);
+    if (level >= level_count)
+    {
+        wined3d_mutex_unlock();
+        return D3DERR_INVALIDCALL;
+    }
+
+    sub_resource_idx = level_count * face + level;
+    if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, sub_resource_idx)))
+    {
+        wined3d_mutex_unlock();
+        return D3DERR_INVALIDCALL;
+    }
+
+    surface_impl = wined3d_resource_get_parent(sub_resource);
+    *surface = &surface_impl->IDirect3DSurface9_iface;
+    IDirect3DSurface9_AddRef(*surface);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_texture_cube_LockRect(IDirect3DCubeTexture9 *iface,
+        D3DCUBEMAP_FACES face, UINT level, D3DLOCKED_RECT *locked_rect, const RECT *rect,
+        DWORD flags)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
+    struct wined3d_resource *sub_resource;
+    struct d3d9_surface *surface_impl;
+    UINT sub_resource_idx;
+    HRESULT hr;
+
+    TRACE("iface %p, face %#x, level %u, locked_rect %p, rect %p, flags %#x.\n",
+            iface, face, level, locked_rect, rect, flags);
+
+    wined3d_mutex_lock();
+    sub_resource_idx = wined3d_texture_get_level_count(texture->wined3d_texture) * face + level;
+    if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, sub_resource_idx)))
+        hr = D3DERR_INVALIDCALL;
+    else
+    {
+        surface_impl = wined3d_resource_get_parent(sub_resource);
+        hr = IDirect3DSurface9_LockRect(&surface_impl->IDirect3DSurface9_iface, locked_rect, rect, flags);
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_texture_cube_UnlockRect(IDirect3DCubeTexture9 *iface,
+        D3DCUBEMAP_FACES face, UINT level)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
+    struct wined3d_resource *sub_resource;
+    struct d3d9_surface *surface_impl;
+    UINT sub_resource_idx;
+    HRESULT hr;
+
+    TRACE("iface %p, face %#x, level %u.\n", iface, face, level);
+
+    wined3d_mutex_lock();
+    sub_resource_idx = wined3d_texture_get_level_count(texture->wined3d_texture) * face + level;
+    if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, sub_resource_idx)))
+        hr = D3DERR_INVALIDCALL;
+    else
+    {
+        surface_impl = wined3d_resource_get_parent(sub_resource);
+        hr = IDirect3DSurface9_UnlockRect(&surface_impl->IDirect3DSurface9_iface);
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT  WINAPI d3d9_texture_cube_AddDirtyRect(IDirect3DCubeTexture9 *iface,
+        D3DCUBEMAP_FACES face, const RECT *dirty_rect)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, face %#x, dirty_rect %s.\n",
+            iface, face, wine_dbgstr_rect(dirty_rect));
+
+    wined3d_mutex_lock();
+    if (!dirty_rect)
+        hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, face, NULL);
+    else
+    {
+        struct wined3d_box dirty_region;
+
+        dirty_region.left = dirty_rect->left;
+        dirty_region.top = dirty_rect->top;
+        dirty_region.right = dirty_rect->right;
+        dirty_region.bottom = dirty_rect->bottom;
+        dirty_region.front = 0;
+        dirty_region.back = 1;
+        hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, face, &dirty_region);
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static const IDirect3DCubeTexture9Vtbl d3d9_texture_cube_vtbl =
+{
+    /* IUnknown */
+    d3d9_texture_cube_QueryInterface,
+    d3d9_texture_cube_AddRef,
+    d3d9_texture_cube_Release,
+    /* IDirect3DResource9 */
+    d3d9_texture_cube_GetDevice,
+    d3d9_texture_cube_SetPrivateData,
+    d3d9_texture_cube_GetPrivateData,
+    d3d9_texture_cube_FreePrivateData,
+    d3d9_texture_cube_SetPriority,
+    d3d9_texture_cube_GetPriority,
+    d3d9_texture_cube_PreLoad,
+    d3d9_texture_cube_GetType,
+    /* IDirect3DBaseTexture9 */
+    d3d9_texture_cube_SetLOD,
+    d3d9_texture_cube_GetLOD,
+    d3d9_texture_cube_GetLevelCount,
+    d3d9_texture_cube_SetAutoGenFilterType,
+    d3d9_texture_cube_GetAutoGenFilterType,
+    d3d9_texture_cube_GenerateMipSubLevels,
+    /* IDirect3DCubeTexture9 */
+    d3d9_texture_cube_GetLevelDesc,
+    d3d9_texture_cube_GetCubeMapSurface,
+    d3d9_texture_cube_LockRect,
+    d3d9_texture_cube_UnlockRect,
+    d3d9_texture_cube_AddDirtyRect,
+};
+
+static HRESULT WINAPI d3d9_texture_3d_QueryInterface(IDirect3DVolumeTexture9 *iface, REFIID riid, void **out)
+{
+    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
+
+    if (IsEqualGUID(riid, &IID_IDirect3DVolumeTexture9)
+            || IsEqualGUID(riid, &IID_IDirect3DBaseTexture9)
+            || IsEqualGUID(riid, &IID_IDirect3DResource9)
+            || IsEqualGUID(riid, &IID_IUnknown))
+    {
+        IDirect3DVolumeTexture9_AddRef(iface);
+        *out = iface;
+        return S_OK;
+    }
+
+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+    *out = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI d3d9_texture_3d_AddRef(IDirect3DVolumeTexture9 *iface)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
+    ULONG ref = InterlockedIncrement(&texture->refcount);
+
+    TRACE("%p increasing refcount to %u.\n", iface, ref);
+
+    if (ref == 1)
+    {
+        IDirect3DDevice9Ex_AddRef(texture->parent_device);
+        wined3d_mutex_lock();
+        wined3d_texture_incref(texture->wined3d_texture);
+        wined3d_mutex_unlock();
+    }
+
+    return ref;
+}
+
+static ULONG WINAPI d3d9_texture_3d_Release(IDirect3DVolumeTexture9 *iface)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
+    ULONG ref = InterlockedDecrement(&texture->refcount);
+
+    TRACE("%p decreasing refcount to %u.\n", iface, ref);
+
+    if (!ref)
+    {
+        IDirect3DDevice9Ex *parent_device = texture->parent_device;
+
+        wined3d_mutex_lock();
+        wined3d_texture_decref(texture->wined3d_texture);
+        wined3d_mutex_unlock();
+
+        /* Release the device last, as it may cause the device to be destroyed. */
+        IDirect3DDevice9Ex_Release(parent_device);
+    }
+    return ref;
+}
+
+static HRESULT WINAPI d3d9_texture_3d_GetDevice(IDirect3DVolumeTexture9 *iface, IDirect3DDevice9 **device)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
+
+    TRACE("iface %p, device %p.\n", iface, device);
+
+    *device = (IDirect3DDevice9 *)texture->parent_device;
+    IDirect3DDevice9_AddRef(*device);
+
+    TRACE("Returning device %p.\n", *device);
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_texture_3d_SetPrivateData(IDirect3DVolumeTexture9 *iface,
+        REFGUID guid, const void *data, DWORD data_size, DWORD flags)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
+            iface, debugstr_guid(guid), data, data_size, flags);
+
+    wined3d_mutex_lock();
+    resource = wined3d_texture_get_resource(texture->wined3d_texture);
+    hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_texture_3d_GetPrivateData(IDirect3DVolumeTexture9 *iface,
+        REFGUID guid, void *data, DWORD *data_size)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s, data %p, data_size %p.\n",
+            iface, debugstr_guid(guid), data, data_size);
+
+    wined3d_mutex_lock();
+    resource = wined3d_texture_get_resource(texture->wined3d_texture);
+    hr = wined3d_resource_get_private_data(resource, guid, data, data_size);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_texture_3d_FreePrivateData(IDirect3DVolumeTexture9 *iface, REFGUID guid)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
+
+    wined3d_mutex_lock();
+    resource = wined3d_texture_get_resource(texture->wined3d_texture);
+    hr = wined3d_resource_free_private_data(resource, guid);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static DWORD WINAPI d3d9_texture_3d_SetPriority(IDirect3DVolumeTexture9 *iface, DWORD priority)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
+    DWORD ret;
+
+    TRACE("iface %p, priority %u.\n", iface, priority);
+
+    wined3d_mutex_lock();
+    ret = wined3d_texture_set_priority(texture->wined3d_texture, priority);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static DWORD WINAPI d3d9_texture_3d_GetPriority(IDirect3DVolumeTexture9 *iface)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
+    DWORD ret;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    ret = wined3d_texture_get_priority(texture->wined3d_texture);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static void WINAPI d3d9_texture_3d_PreLoad(IDirect3DVolumeTexture9 *iface)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    wined3d_texture_preload(texture->wined3d_texture);
+    wined3d_mutex_unlock();
+}
+
+static D3DRESOURCETYPE WINAPI d3d9_texture_3d_GetType(IDirect3DVolumeTexture9 *iface)
+{
+    TRACE("iface %p.\n", iface);
+
+    return D3DRTYPE_VOLUMETEXTURE;
+}
+
+static DWORD WINAPI d3d9_texture_3d_SetLOD(IDirect3DVolumeTexture9 *iface, DWORD lod)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
+    DWORD ret;
+
+    TRACE("iface %p, lod %u.\n", iface, lod);
+
+    wined3d_mutex_lock();
+    ret = wined3d_texture_set_lod(texture->wined3d_texture, lod);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static DWORD WINAPI d3d9_texture_3d_GetLOD(IDirect3DVolumeTexture9 *iface)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
+    DWORD ret;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    ret = wined3d_texture_get_lod(texture->wined3d_texture);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static DWORD WINAPI d3d9_texture_3d_GetLevelCount(IDirect3DVolumeTexture9 *iface)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
+    DWORD ret;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    ret = wined3d_texture_get_level_count(texture->wined3d_texture);
+    wined3d_mutex_unlock();
+
+    return ret;
+}
+
+static HRESULT WINAPI d3d9_texture_3d_SetAutoGenFilterType(IDirect3DVolumeTexture9 *iface,
+        D3DTEXTUREFILTERTYPE filter_type)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, filter_type %#x.\n", iface, filter_type);
+
+    wined3d_mutex_lock();
+    hr = wined3d_texture_set_autogen_filter_type(texture->wined3d_texture,
+            (enum wined3d_texture_filter_type)filter_type);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static D3DTEXTUREFILTERTYPE WINAPI d3d9_texture_3d_GetAutoGenFilterType(IDirect3DVolumeTexture9 *iface)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
+    D3DTEXTUREFILTERTYPE filter_type;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    filter_type = (D3DTEXTUREFILTERTYPE)wined3d_texture_get_autogen_filter_type(texture->wined3d_texture);
+    wined3d_mutex_unlock();
+
+    return filter_type;
+}
+
+static void WINAPI d3d9_texture_3d_GenerateMipSubLevels(IDirect3DVolumeTexture9 *iface)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    wined3d_texture_generate_mipmaps(texture->wined3d_texture);
+    wined3d_mutex_unlock();
+}
+
+static HRESULT WINAPI d3d9_texture_3d_GetLevelDesc(IDirect3DVolumeTexture9 *iface, UINT level, D3DVOLUME_DESC *desc)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
+    struct wined3d_resource *sub_resource;
+    HRESULT hr = D3D_OK;
+
+    TRACE("iface %p, level %u, desc %p.\n", iface, level, desc);
+
+    wined3d_mutex_lock();
+    if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
+        hr = D3DERR_INVALIDCALL;
+    else
+    {
+        struct wined3d_resource_desc wined3d_desc;
+
+        wined3d_resource_get_desc(sub_resource, &wined3d_desc);
+        desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format);
+        desc->Type = wined3d_desc.resource_type;
+        desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
+        desc->Pool = wined3d_desc.pool;
+        desc->Width = wined3d_desc.width;
+        desc->Height = wined3d_desc.height;
+        desc->Depth = wined3d_desc.depth;
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_texture_3d_GetVolumeLevel(IDirect3DVolumeTexture9 *iface,
+        UINT level, IDirect3DVolume9 **volume)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
+    struct wined3d_resource *sub_resource;
+    struct d3d9_volume *volume_impl;
+
+    TRACE("iface %p, level %u, volume %p.\n", iface, level, volume);
+
+    wined3d_mutex_lock();
+    if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
+    {
+        wined3d_mutex_unlock();
+        return D3DERR_INVALIDCALL;
+    }
+
+    volume_impl = wined3d_resource_get_parent(sub_resource);
+    *volume = &volume_impl->IDirect3DVolume9_iface;
+    IDirect3DVolume9_AddRef(*volume);
+    wined3d_mutex_unlock();
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_texture_3d_LockBox(IDirect3DVolumeTexture9 *iface,
+        UINT level, D3DLOCKED_BOX *locked_box, const D3DBOX *box, DWORD flags)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
+    struct wined3d_resource *sub_resource;
+    struct d3d9_volume *volume_impl;
+    HRESULT hr;
+
+    TRACE("iface %p, level %u, locked_box %p, box %p, flags %#x.\n",
+            iface, level, locked_box, box, flags);
+
+    wined3d_mutex_lock();
+    if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
+        hr = D3DERR_INVALIDCALL;
+    else
+    {
+        volume_impl = wined3d_resource_get_parent(sub_resource);
+        hr = IDirect3DVolume9_LockBox(&volume_impl->IDirect3DVolume9_iface, locked_box, box, flags);
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_texture_3d_UnlockBox(IDirect3DVolumeTexture9 *iface, UINT level)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
+    struct wined3d_resource *sub_resource;
+    struct d3d9_volume *volume_impl;
+    HRESULT hr;
+
+    TRACE("iface %p, level %u.\n", iface, level);
+
+    wined3d_mutex_lock();
+    if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
+        hr = D3DERR_INVALIDCALL;
+    else
+    {
+        volume_impl = wined3d_resource_get_parent(sub_resource);
+        hr = IDirect3DVolume9_UnlockBox(&volume_impl->IDirect3DVolume9_iface);
+    }
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_texture_3d_AddDirtyBox(IDirect3DVolumeTexture9 *iface, const D3DBOX *dirty_box)
+{
+    struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, dirty_box %p.\n", iface, dirty_box);
+
+    wined3d_mutex_lock();
+    hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, 0, (const struct wined3d_box *)dirty_box);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+
+static const IDirect3DVolumeTexture9Vtbl d3d9_texture_3d_vtbl =
+{
+    /* IUnknown */
+    d3d9_texture_3d_QueryInterface,
+    d3d9_texture_3d_AddRef,
+    d3d9_texture_3d_Release,
+    /* IDirect3DResource9 */
+    d3d9_texture_3d_GetDevice,
+    d3d9_texture_3d_SetPrivateData,
+    d3d9_texture_3d_GetPrivateData,
+    d3d9_texture_3d_FreePrivateData,
+    d3d9_texture_3d_SetPriority,
+    d3d9_texture_3d_GetPriority,
+    d3d9_texture_3d_PreLoad,
+    d3d9_texture_3d_GetType,
+    /* IDirect3DBaseTexture9 */
+    d3d9_texture_3d_SetLOD,
+    d3d9_texture_3d_GetLOD,
+    d3d9_texture_3d_GetLevelCount,
+    d3d9_texture_3d_SetAutoGenFilterType,
+    d3d9_texture_3d_GetAutoGenFilterType,
+    d3d9_texture_3d_GenerateMipSubLevels,
+    /* IDirect3DVolumeTexture9 */
+    d3d9_texture_3d_GetLevelDesc,
+    d3d9_texture_3d_GetVolumeLevel,
+    d3d9_texture_3d_LockBox,
+    d3d9_texture_3d_UnlockBox,
+    d3d9_texture_3d_AddDirtyBox,
+};
+
+struct d3d9_texture *unsafe_impl_from_IDirect3DBaseTexture9(IDirect3DBaseTexture9 *iface)
+{
+    if (!iface)
+        return NULL;
+    assert(iface->lpVtbl == (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_2d_vtbl
+            || iface->lpVtbl == (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_cube_vtbl
+            || iface->lpVtbl == (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_3d_vtbl);
+    return CONTAINING_RECORD(iface, struct d3d9_texture, IDirect3DBaseTexture9_iface);
+}
+
+static void STDMETHODCALLTYPE d3d9_texture_wined3d_object_destroyed(void *parent)
+{
+    HeapFree(GetProcessHeap(), 0, parent);
+}
+
+static const struct wined3d_parent_ops d3d9_texture_wined3d_parent_ops =
+{
+    d3d9_texture_wined3d_object_destroyed,
+};
+
+HRESULT texture_init(struct d3d9_texture *texture, struct d3d9_device *device,
+        UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool
+#ifdef VBOX_WITH_WDDM
+        , HANDLE *shared_handle
+        , void **pavClientMem
+#endif
+        )
+{
+    struct wined3d_resource_desc desc;
+    DWORD surface_flags = 0;
+    HRESULT hr;
+
+    texture->IDirect3DBaseTexture9_iface.lpVtbl = (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_2d_vtbl;
+    texture->refcount = 1;
+
+    desc.resource_type = WINED3D_RTYPE_TEXTURE;
+    desc.format = wined3dformat_from_d3dformat(format);
+    desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
+    desc.multisample_quality = 0;
+    desc.usage = usage & WINED3DUSAGE_MASK;
+    desc.pool = pool;
+    desc.width = width;
+    desc.height = height;
+    desc.depth = 1;
+    desc.size = 0;
+
+    if (pool != D3DPOOL_DEFAULT || (usage & D3DUSAGE_DYNAMIC))
+        surface_flags |= WINED3D_SURFACE_MAPPABLE;
+
+    wined3d_mutex_lock();
+    hr = wined3d_texture_create_2d(device->wined3d_device, &desc, levels, surface_flags,
+            texture, &d3d9_texture_wined3d_parent_ops, &texture->wined3d_texture
+#ifdef VBOX_WITH_WDDM
+			, shared_handle
+			, pavClientMem
+#endif
+            );
+    wined3d_mutex_unlock();
+    if (FAILED(hr))
+    {
+        WARN("Failed to create wined3d texture, hr %#x.\n", hr);
+        return hr;
+    }
+
+    texture->parent_device = &device->IDirect3DDevice9Ex_iface;
+    IDirect3DDevice9Ex_AddRef(texture->parent_device);
+
+    return D3D_OK;
+}
+
+HRESULT cubetexture_init(struct d3d9_texture *texture, struct d3d9_device *device,
+        UINT edge_length, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool
+#ifdef VBOX_WITH_WDDM
+        , HANDLE *shared_handle
+        , void **pavClientMem
+#endif
+        )
+{
+    struct wined3d_resource_desc desc;
+    DWORD surface_flags = 0;
+    HRESULT hr;
+
+    texture->IDirect3DBaseTexture9_iface.lpVtbl = (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_cube_vtbl;
+    texture->refcount = 1;
+
+    desc.resource_type = WINED3D_RTYPE_CUBE_TEXTURE;
+    desc.format = wined3dformat_from_d3dformat(format);
+    desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
+    desc.multisample_quality = 0;
+    desc.usage = usage & WINED3DUSAGE_MASK;
+    desc.pool = pool;
+    desc.width = edge_length;
+    desc.height = edge_length;
+    desc.depth = 1;
+    desc.size = 0;
+
+    if (pool != D3DPOOL_DEFAULT || (usage & D3DUSAGE_DYNAMIC))
+        surface_flags |= WINED3D_SURFACE_MAPPABLE;
+
+    wined3d_mutex_lock();
+    hr = wined3d_texture_create_cube(device->wined3d_device, &desc, levels, surface_flags,
+            texture, &d3d9_texture_wined3d_parent_ops, &texture->wined3d_texture
+#ifdef VBOX_WITH_WDDM
+            , shared_handle
+            , pavClientMem
+#endif
+            );
+    wined3d_mutex_unlock();
+    if (FAILED(hr))
+    {
+        WARN("Failed to create wined3d cube texture, hr %#x.\n", hr);
+        return hr;
+    }
+
+    texture->parent_device = &device->IDirect3DDevice9Ex_iface;
+    IDirect3DDevice9Ex_AddRef(texture->parent_device);
+
+    return D3D_OK;
+}
+
+HRESULT volumetexture_init(struct d3d9_texture *texture, struct d3d9_device *device,
+        UINT width, UINT height, UINT depth, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool
+#ifdef VBOX_WITH_WDDM
+        , HANDLE *shared_handle
+        , void **pavClientMem
+#endif
+        )
+{
+    struct wined3d_resource_desc desc;
+    HRESULT hr;
+
+    texture->IDirect3DBaseTexture9_iface.lpVtbl = (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_3d_vtbl;
+    texture->refcount = 1;
+
+    desc.resource_type = WINED3D_RTYPE_VOLUME_TEXTURE;
+    desc.format = wined3dformat_from_d3dformat(format);
+    desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
+    desc.multisample_quality = 0;
+    desc.usage = usage & WINED3DUSAGE_MASK;
+    desc.pool = pool;
+    desc.width = width;
+    desc.height = height;
+    desc.depth = depth;
+    desc.size = 0;
+
+    wined3d_mutex_lock();
+    hr = wined3d_texture_create_3d(device->wined3d_device, &desc, levels,
+            texture, &d3d9_texture_wined3d_parent_ops, &texture->wined3d_texture
+#ifdef VBOX_WITH_WDDM
+            , shared_handle
+            , pavClientMem
+#endif
+            );
+    wined3d_mutex_unlock();
+    if (FAILED(hr))
+    {
+        WARN("Failed to create wined3d volume texture, hr %#x.\n", hr);
+        return hr;
+    }
+
+    texture->parent_device = &device->IDirect3DDevice9Ex_iface;
+    IDirect3DDevice9Ex_AddRef(texture->parent_device);
+
+    return D3D_OK;
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/version.rc
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/version.rc	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/version.rc	(revision 46521)
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2001 Ove Kaaven
+ *
+ * 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 Direct3D"
+#define WINE_FILENAME_STR "d3d9.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"
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/vertexdeclaration.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/vertexdeclaration.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/vertexdeclaration.c	(revision 46521)
@@ -0,0 +1,436 @@
+/*
+ * IDirect3DVertexDeclaration9 implementation
+ *
+ * Copyright 2002-2003 Raphael Junqueira
+ *                     Jason Edmeades
+ *
+ * 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 "d3d9_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
+
+static const struct
+{
+    enum wined3d_format_id format;
+    unsigned int component_count;
+    unsigned int component_size;
+}
+d3d_dtype_lookup[] =
+{
+    /* D3DDECLTYPE_FLOAT1    */ {WINED3DFMT_R32_FLOAT,          1, sizeof(float)},
+    /* D3DDECLTYPE_FLOAT2    */ {WINED3DFMT_R32G32_FLOAT,       2, sizeof(float)},
+    /* D3DDECLTYPE_FLOAT3    */ {WINED3DFMT_R32G32B32_FLOAT,    3, sizeof(float)},
+    /* D3DDECLTYPE_FLOAT4    */ {WINED3DFMT_R32G32B32A32_FLOAT, 4, sizeof(float)},
+    /* D3DDECLTYPE_D3DCOLOR  */ {WINED3DFMT_B8G8R8A8_UNORM,     4, sizeof(BYTE)},
+    /* D3DDECLTYPE_UBYTE4    */ {WINED3DFMT_R8G8B8A8_UINT,      4, sizeof(BYTE)},
+    /* D3DDECLTYPE_SHORT2    */ {WINED3DFMT_R16G16_SINT,        2, sizeof(short int)},
+    /* D3DDECLTYPE_SHORT4    */ {WINED3DFMT_R16G16B16A16_SINT,  4, sizeof(short int)},
+    /* D3DDECLTYPE_UBYTE4N   */ {WINED3DFMT_R8G8B8A8_UNORM,     4, sizeof(BYTE)},
+    /* D3DDECLTYPE_SHORT2N   */ {WINED3DFMT_R16G16_SNORM,       2, sizeof(short int)},
+    /* D3DDECLTYPE_SHORT4N   */ {WINED3DFMT_R16G16B16A16_SNORM, 4, sizeof(short int)},
+    /* D3DDECLTYPE_USHORT2N  */ {WINED3DFMT_R16G16_UNORM,       2, sizeof(short int)},
+    /* D3DDECLTYPE_USHORT4N  */ {WINED3DFMT_R16G16B16A16_UNORM, 4, sizeof(short int)},
+    /* D3DDECLTYPE_UDEC3     */ {WINED3DFMT_R10G10B10A2_UINT,   3, sizeof(short int)},
+    /* D3DDECLTYPE_DEC3N     */ {WINED3DFMT_R10G10B10A2_SNORM,  3, sizeof(short int)},
+    /* D3DDECLTYPE_FLOAT16_2 */ {WINED3DFMT_R16G16_FLOAT,       2, sizeof(short int)},
+    /* D3DDECLTYPE_FLOAT16_4 */ {WINED3DFMT_R16G16B16A16_FLOAT, 4, sizeof(short int)}
+};
+
+static inline struct d3d9_vertex_declaration *impl_from_IDirect3DVertexDeclaration9(IDirect3DVertexDeclaration9 *iface)
+{
+    return CONTAINING_RECORD(iface, struct d3d9_vertex_declaration, IDirect3DVertexDeclaration9_iface);
+}
+
+HRESULT vdecl_convert_fvf(
+    DWORD fvf,
+    D3DVERTEXELEMENT9** ppVertexElements) {
+
+    unsigned int idx, idx2;
+    unsigned int offset;
+    BOOL has_pos = (fvf & D3DFVF_POSITION_MASK) != 0;
+    BOOL has_blend = (fvf & D3DFVF_XYZB5) > D3DFVF_XYZRHW;
+    BOOL has_blend_idx = has_blend &&
+       (((fvf & D3DFVF_XYZB5) == D3DFVF_XYZB5) ||
+        (fvf & D3DFVF_LASTBETA_D3DCOLOR) ||
+        (fvf & D3DFVF_LASTBETA_UBYTE4));
+    BOOL has_normal = (fvf & D3DFVF_NORMAL) != 0;
+    BOOL has_psize = (fvf & D3DFVF_PSIZE) != 0;
+
+    BOOL has_diffuse = (fvf & D3DFVF_DIFFUSE) != 0;
+    BOOL has_specular = (fvf & D3DFVF_SPECULAR) !=0;
+
+    DWORD num_textures = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
+    DWORD texcoords = (fvf & 0xFFFF0000) >> 16;
+
+    D3DVERTEXELEMENT9 end_element = D3DDECL_END();
+    D3DVERTEXELEMENT9 *elements = NULL;
+
+    unsigned int size;
+    DWORD num_blends = 1 + (((fvf & D3DFVF_XYZB5) - D3DFVF_XYZB1) >> 1);
+    if (has_blend_idx) num_blends--;
+
+    /* Compute declaration size */
+    size = has_pos + (has_blend && num_blends > 0) + has_blend_idx + has_normal +
+           has_psize + has_diffuse + has_specular + num_textures + 1;
+
+    /* convert the declaration */
+    elements = HeapAlloc(GetProcessHeap(), 0, size * sizeof(D3DVERTEXELEMENT9));
+    if (!elements) return D3DERR_OUTOFVIDEOMEMORY;
+
+    elements[size-1] = end_element;
+    idx = 0;
+    if (has_pos) {
+        if (!has_blend && (fvf & D3DFVF_XYZRHW)) {
+            elements[idx].Type = D3DDECLTYPE_FLOAT4;
+            elements[idx].Usage = D3DDECLUSAGE_POSITIONT;
+        }
+        else if (!has_blend && (fvf & D3DFVF_XYZW) == D3DFVF_XYZW) {
+            elements[idx].Type = D3DDECLTYPE_FLOAT4;
+            elements[idx].Usage = D3DDECLUSAGE_POSITION;
+        }
+        else {
+            elements[idx].Type = D3DDECLTYPE_FLOAT3;
+            elements[idx].Usage = D3DDECLUSAGE_POSITION;
+        }
+        elements[idx].UsageIndex = 0;
+        idx++;
+    }
+    if (has_blend && (num_blends > 0)) {
+        if (((fvf & D3DFVF_XYZB5) == D3DFVF_XYZB2) && (fvf & D3DFVF_LASTBETA_D3DCOLOR))
+            elements[idx].Type = D3DDECLTYPE_D3DCOLOR;
+        else {
+            switch(num_blends) {
+                case 1: elements[idx].Type = D3DDECLTYPE_FLOAT1; break;
+                case 2: elements[idx].Type = D3DDECLTYPE_FLOAT2; break;
+                case 3: elements[idx].Type = D3DDECLTYPE_FLOAT3; break;
+                case 4: elements[idx].Type = D3DDECLTYPE_FLOAT4; break;
+                default:
+                    ERR("Unexpected amount of blend values: %u\n", num_blends);
+            }
+        }
+        elements[idx].Usage = D3DDECLUSAGE_BLENDWEIGHT;
+        elements[idx].UsageIndex = 0;
+        idx++;
+    }
+    if (has_blend_idx) {
+        if (fvf & D3DFVF_LASTBETA_UBYTE4 ||
+            (((fvf & D3DFVF_XYZB5) == D3DFVF_XYZB2) && (fvf & D3DFVF_LASTBETA_D3DCOLOR)))
+            elements[idx].Type = D3DDECLTYPE_UBYTE4;
+        else if (fvf & D3DFVF_LASTBETA_D3DCOLOR)
+            elements[idx].Type = D3DDECLTYPE_D3DCOLOR;
+        else
+            elements[idx].Type = D3DDECLTYPE_FLOAT1;
+        elements[idx].Usage = D3DDECLUSAGE_BLENDINDICES;
+        elements[idx].UsageIndex = 0;
+        idx++;
+    }
+    if (has_normal) {
+        elements[idx].Type = D3DDECLTYPE_FLOAT3;
+        elements[idx].Usage = D3DDECLUSAGE_NORMAL;
+        elements[idx].UsageIndex = 0;
+        idx++;
+    }
+    if (has_psize) {
+        elements[idx].Type = D3DDECLTYPE_FLOAT1;
+        elements[idx].Usage = D3DDECLUSAGE_PSIZE;
+        elements[idx].UsageIndex = 0;
+        idx++;
+    }
+    if (has_diffuse) {
+        elements[idx].Type = D3DDECLTYPE_D3DCOLOR;
+        elements[idx].Usage = D3DDECLUSAGE_COLOR;
+        elements[idx].UsageIndex = 0;
+        idx++;
+    }
+    if (has_specular) {
+        elements[idx].Type = D3DDECLTYPE_D3DCOLOR;
+        elements[idx].Usage = D3DDECLUSAGE_COLOR;
+        elements[idx].UsageIndex = 1;
+        idx++;
+    }
+    for (idx2 = 0; idx2 < num_textures; idx2++) {
+        unsigned int numcoords = (texcoords >> (idx2*2)) & 0x03;
+        switch (numcoords) {
+            case D3DFVF_TEXTUREFORMAT1:
+                elements[idx].Type = D3DDECLTYPE_FLOAT1;
+                break;
+            case D3DFVF_TEXTUREFORMAT2:
+                elements[idx].Type = D3DDECLTYPE_FLOAT2;
+                break;
+            case D3DFVF_TEXTUREFORMAT3:
+                elements[idx].Type = D3DDECLTYPE_FLOAT3;
+                break;
+            case D3DFVF_TEXTUREFORMAT4:
+                elements[idx].Type = D3DDECLTYPE_FLOAT4;
+                break;
+        }
+        elements[idx].Usage = D3DDECLUSAGE_TEXCOORD;
+        elements[idx].UsageIndex = idx2;
+        idx++;
+    }
+
+    /* Now compute offsets, and initialize the rest of the fields */
+    for (idx = 0, offset = 0; idx < size-1; idx++) {
+        elements[idx].Stream = 0;
+        elements[idx].Method = D3DDECLMETHOD_DEFAULT;
+        elements[idx].Offset = offset;
+        offset += d3d_dtype_lookup[elements[idx].Type].component_count
+                * d3d_dtype_lookup[elements[idx].Type].component_size;
+    }
+
+    *ppVertexElements = elements;
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_vertex_declaration_QueryInterface(IDirect3DVertexDeclaration9 *iface,
+        REFIID riid, void **out)
+{
+    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
+
+    if (IsEqualGUID(riid, &IID_IDirect3DVertexDeclaration9)
+            || IsEqualGUID(riid, &IID_IUnknown))
+    {
+        IDirect3DVertexDeclaration9_AddRef(iface);
+        *out = iface;
+        return S_OK;
+    }
+
+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+    *out = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI d3d9_vertex_declaration_AddRef(IDirect3DVertexDeclaration9 *iface)
+{
+    struct d3d9_vertex_declaration *declaration = impl_from_IDirect3DVertexDeclaration9(iface);
+    ULONG refcount = InterlockedIncrement(&declaration->refcount);
+
+    TRACE("%p increasing refcount to %u.\n", iface, refcount);
+
+    if (refcount == 1)
+    {
+        IDirect3DDevice9Ex_AddRef(declaration->parent_device);
+        wined3d_mutex_lock();
+        wined3d_vertex_declaration_incref(declaration->wined3d_declaration);
+        wined3d_mutex_unlock();
+    }
+
+    return refcount;
+}
+
+static ULONG WINAPI d3d9_vertex_declaration_Release(IDirect3DVertexDeclaration9 *iface)
+{
+    struct d3d9_vertex_declaration *declaration = impl_from_IDirect3DVertexDeclaration9(iface);
+    ULONG refcount = InterlockedDecrement(&declaration->refcount);
+
+    TRACE("%p decreasing refcount to %u.\n", iface, refcount);
+
+    if (!refcount)
+    {
+        IDirect3DDevice9Ex *parent_device = declaration->parent_device;
+        wined3d_mutex_lock();
+        wined3d_vertex_declaration_decref(declaration->wined3d_declaration);
+        wined3d_mutex_unlock();
+
+        /* Release the device last, as it may cause the device to be destroyed. */
+        IDirect3DDevice9Ex_Release(parent_device);
+    }
+
+    return refcount;
+}
+
+static HRESULT WINAPI d3d9_vertex_declaration_GetDevice(IDirect3DVertexDeclaration9 *iface, IDirect3DDevice9 **device)
+{
+    struct d3d9_vertex_declaration *declaration = impl_from_IDirect3DVertexDeclaration9(iface);
+
+    TRACE("iface %p, device %p.\n", iface, device);
+
+    *device = (IDirect3DDevice9 *)declaration->parent_device;
+    IDirect3DDevice9_AddRef(*device);
+
+    TRACE("Returning device %p.\n", *device);
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_vertex_declaration_GetDeclaration(IDirect3DVertexDeclaration9 *iface,
+        D3DVERTEXELEMENT9 *elements, UINT *element_count)
+{
+    struct d3d9_vertex_declaration *declaration = impl_from_IDirect3DVertexDeclaration9(iface);
+
+    TRACE("iface %p, elements %p, element_count %p.\n", iface, elements, element_count);
+
+    *element_count = declaration->element_count;
+
+    /* Passing a NULL elements is used to just retrieve the number of elements */
+    if (!elements)
+        return D3D_OK;
+
+    TRACE("Copying %p to %p.\n", declaration->elements, elements);
+    memcpy(elements, declaration->elements, sizeof(*declaration->elements) * declaration->element_count);
+
+    return D3D_OK;
+}
+
+static const struct IDirect3DVertexDeclaration9Vtbl d3d9_vertex_declaration_vtbl =
+{
+    /* IUnknown */
+    d3d9_vertex_declaration_QueryInterface,
+    d3d9_vertex_declaration_AddRef,
+    d3d9_vertex_declaration_Release,
+    /* IDirect3DVertexDeclaration9 */
+    d3d9_vertex_declaration_GetDevice,
+    d3d9_vertex_declaration_GetDeclaration,
+};
+
+struct d3d9_vertex_declaration *unsafe_impl_from_IDirect3DVertexDeclaration9(IDirect3DVertexDeclaration9 *iface)
+{
+    if (!iface)
+        return NULL;
+    assert(iface->lpVtbl == &d3d9_vertex_declaration_vtbl);
+    return CONTAINING_RECORD(iface, struct d3d9_vertex_declaration, IDirect3DVertexDeclaration9_iface);
+}
+
+static void STDMETHODCALLTYPE d3d9_vertexdeclaration_wined3d_object_destroyed(void *parent)
+{
+    struct d3d9_vertex_declaration *declaration = parent;
+    HeapFree(GetProcessHeap(), 0, declaration->elements);
+    HeapFree(GetProcessHeap(), 0, declaration);
+}
+
+static const struct wined3d_parent_ops d3d9_vertexdeclaration_wined3d_parent_ops =
+{
+    d3d9_vertexdeclaration_wined3d_object_destroyed,
+};
+
+static HRESULT convert_to_wined3d_declaration(const D3DVERTEXELEMENT9 *d3d9_elements,
+        struct wined3d_vertex_element **wined3d_elements, UINT *element_count)
+{
+    const D3DVERTEXELEMENT9* element;
+    UINT count = 1;
+    UINT i;
+
+    TRACE("d3d9_elements %p, wined3d_elements %p\n", d3d9_elements, wined3d_elements);
+
+    element = d3d9_elements;
+    while (element++->Stream != 0xff && count++ < 128);
+
+    if (count == 128) return E_FAIL;
+
+    /* Skip the END element */
+    --count;
+
+    *wined3d_elements = HeapAlloc(GetProcessHeap(), 0, count * sizeof(**wined3d_elements));
+    if (!*wined3d_elements) {
+        FIXME("Memory allocation failed\n");
+        return D3DERR_OUTOFVIDEOMEMORY;
+    }
+
+    for (i = 0; i < count; ++i)
+    {
+        if (d3d9_elements[i].Type >= (sizeof(d3d_dtype_lookup) / sizeof(*d3d_dtype_lookup)))
+        {
+            WARN("Invalid element type %#x.\n", d3d9_elements[i].Type);
+            HeapFree(GetProcessHeap(), 0, *wined3d_elements);
+            return E_FAIL;
+        }
+        (*wined3d_elements)[i].format = d3d_dtype_lookup[d3d9_elements[i].Type].format;
+        (*wined3d_elements)[i].input_slot = d3d9_elements[i].Stream;
+        (*wined3d_elements)[i].offset = d3d9_elements[i].Offset;
+        (*wined3d_elements)[i].output_slot = ~0U;
+        (*wined3d_elements)[i].method = d3d9_elements[i].Method;
+        (*wined3d_elements)[i].usage = d3d9_elements[i].Usage;
+        (*wined3d_elements)[i].usage_idx = d3d9_elements[i].UsageIndex;
+    }
+
+    *element_count = count;
+
+    return D3D_OK;
+}
+
+static HRESULT vertexdeclaration_init(struct d3d9_vertex_declaration *declaration,
+        struct d3d9_device *device, const D3DVERTEXELEMENT9 *elements)
+{
+    struct wined3d_vertex_element *wined3d_elements;
+    UINT wined3d_element_count;
+    UINT element_count;
+    HRESULT hr;
+
+    hr = convert_to_wined3d_declaration(elements, &wined3d_elements, &wined3d_element_count);
+    if (FAILED(hr))
+    {
+        WARN("Failed to create wined3d vertex declaration elements, hr %#x.\n", hr);
+        return hr;
+    }
+
+    declaration->IDirect3DVertexDeclaration9_iface.lpVtbl = &d3d9_vertex_declaration_vtbl;
+    declaration->refcount = 1;
+
+    element_count = wined3d_element_count + 1;
+    declaration->elements = HeapAlloc(GetProcessHeap(), 0, element_count * sizeof(*declaration->elements));
+    if (!declaration->elements)
+    {
+        HeapFree(GetProcessHeap(), 0, wined3d_elements);
+        ERR("Failed to allocate vertex declaration elements memory.\n");
+        return D3DERR_OUTOFVIDEOMEMORY;
+    }
+    memcpy(declaration->elements, elements, element_count * sizeof(*elements));
+    declaration->element_count = element_count;
+
+    wined3d_mutex_lock();
+    hr = wined3d_vertex_declaration_create(device->wined3d_device, wined3d_elements, wined3d_element_count,
+            declaration, &d3d9_vertexdeclaration_wined3d_parent_ops, &declaration->wined3d_declaration);
+    wined3d_mutex_unlock();
+    HeapFree(GetProcessHeap(), 0, wined3d_elements);
+    if (FAILED(hr))
+    {
+        HeapFree(GetProcessHeap(), 0, declaration->elements);
+        WARN("Failed to create wined3d vertex declaration, hr %#x.\n", hr);
+        return hr;
+    }
+
+    declaration->parent_device = &device->IDirect3DDevice9Ex_iface;
+    IDirect3DDevice9Ex_AddRef(declaration->parent_device);
+
+    return D3D_OK;
+}
+
+HRESULT d3d9_vertex_declaration_create(struct d3d9_device *device,
+        const D3DVERTEXELEMENT9 *elements, struct d3d9_vertex_declaration **declaration)
+{
+    struct d3d9_vertex_declaration *object;
+    HRESULT hr;
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return E_OUTOFMEMORY;
+
+    hr = vertexdeclaration_init(object, device, elements);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize vertex declaration, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created vertex declaration %p.\n", object);
+    *declaration = object;
+
+    return D3D_OK;
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/volume.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/volume.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d9/volume.c	(revision 46521)
@@ -0,0 +1,314 @@
+/*
+ * IDirect3DVolume9 implementation
+ *
+ * Copyright 2002-2005 Jason Edmeades
+ *                     Raphael Junqueira
+ *
+ * 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 "d3d9_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
+
+static inline struct d3d9_volume *impl_from_IDirect3DVolume9(IDirect3DVolume9 *iface)
+{
+    return CONTAINING_RECORD(iface, struct d3d9_volume, IDirect3DVolume9_iface);
+}
+
+static HRESULT WINAPI d3d9_volume_QueryInterface(IDirect3DVolume9 *iface, REFIID riid, void **out)
+{
+    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
+
+    if (IsEqualGUID(riid, &IID_IDirect3DVolume9)
+            || IsEqualGUID(riid, &IID_IUnknown))
+    {
+        IDirect3DVolume9_AddRef(iface);
+        *out = iface;
+        return S_OK;
+    }
+
+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+    *out = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI d3d9_volume_AddRef(IDirect3DVolume9 *iface)
+{
+    struct d3d9_volume *volume = impl_from_IDirect3DVolume9(iface);
+    ULONG refcount;
+
+    TRACE("iface %p.\n", iface);
+
+    if (volume->forwardReference)
+    {
+        TRACE("Forwarding to %p.\n", volume->forwardReference);
+        return IUnknown_AddRef(volume->forwardReference);
+    }
+
+    refcount = InterlockedIncrement(&volume->refcount);
+    TRACE("%p increasing refcount to %u.\n", iface, refcount);
+
+    if (refcount == 1)
+    {
+        wined3d_mutex_lock();
+        wined3d_volume_incref(volume->wined3d_volume);
+        wined3d_mutex_unlock();
+    }
+
+    return refcount;
+}
+
+static ULONG WINAPI d3d9_volume_Release(IDirect3DVolume9 *iface)
+{
+    struct d3d9_volume *volume = impl_from_IDirect3DVolume9(iface);
+    ULONG refcount;
+
+    TRACE("iface %p.\n", iface);
+
+    if (volume->forwardReference)
+    {
+        TRACE("Forwarding to %p.\n", volume->forwardReference);
+        return IUnknown_Release(volume->forwardReference);
+    }
+
+    refcount = InterlockedDecrement(&volume->refcount);
+    TRACE("%p decreasing refcount to %u.\n", iface, refcount);
+
+    if (!refcount)
+    {
+        wined3d_mutex_lock();
+        wined3d_volume_decref(volume->wined3d_volume);
+        wined3d_mutex_unlock();
+    }
+
+    return refcount;
+}
+
+static HRESULT WINAPI d3d9_volume_GetDevice(IDirect3DVolume9 *iface, IDirect3DDevice9 **device)
+{
+    struct d3d9_volume *volume = impl_from_IDirect3DVolume9(iface);
+    IDirect3DResource9 *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, device %p.\n", iface, device);
+
+    hr = IUnknown_QueryInterface(volume->forwardReference, &IID_IDirect3DResource9, (void **)&resource);
+    if (SUCCEEDED(hr))
+    {
+        hr = IDirect3DResource9_GetDevice(resource, device);
+        IDirect3DResource9_Release(resource);
+
+        TRACE("Returning device %p.\n", *device);
+    }
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_volume_SetPrivateData(IDirect3DVolume9 *iface, REFGUID guid,
+        const void *data, DWORD data_size, DWORD flags)
+{
+    struct d3d9_volume *volume = impl_from_IDirect3DVolume9(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
+            iface, debugstr_guid(guid), data, data_size, flags);
+
+    wined3d_mutex_lock();
+    resource = wined3d_volume_get_resource(volume->wined3d_volume);
+    hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_volume_GetPrivateData(IDirect3DVolume9 *iface, REFGUID guid,
+        void *data, DWORD *data_size)
+{
+    struct d3d9_volume *volume = impl_from_IDirect3DVolume9(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s, data %p, data_size %p.\n",
+            iface, debugstr_guid(guid), data, data_size);
+
+    wined3d_mutex_lock();
+    resource = wined3d_volume_get_resource(volume->wined3d_volume);
+    hr = wined3d_resource_get_private_data(resource, guid, data, data_size);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_volume_FreePrivateData(IDirect3DVolume9 *iface, REFGUID guid)
+{
+    struct d3d9_volume *volume = impl_from_IDirect3DVolume9(iface);
+    struct wined3d_resource *resource;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
+
+    wined3d_mutex_lock();
+    resource = wined3d_volume_get_resource(volume->wined3d_volume);
+    hr = wined3d_resource_free_private_data(resource, guid);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_volume_GetContainer(IDirect3DVolume9 *iface, REFIID riid, void **container)
+{
+    struct d3d9_volume *volume = impl_from_IDirect3DVolume9(iface);
+    HRESULT hr;
+
+    TRACE("iface %p, riid %s, container %p.\n", iface, debugstr_guid(riid), container);
+
+    if (!volume->container)
+        return E_NOINTERFACE;
+
+    hr = IUnknown_QueryInterface(volume->container, riid, container);
+
+    TRACE("Returning %p,\n", *container);
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_volume_GetDesc(IDirect3DVolume9 *iface, D3DVOLUME_DESC *desc)
+{
+    struct d3d9_volume *volume = impl_from_IDirect3DVolume9(iface);
+    struct wined3d_resource_desc wined3d_desc;
+    struct wined3d_resource *wined3d_resource;
+
+    TRACE("iface %p, desc %p.\n", iface, desc);
+
+    wined3d_mutex_lock();
+    wined3d_resource = wined3d_volume_get_resource(volume->wined3d_volume);
+    wined3d_resource_get_desc(wined3d_resource, &wined3d_desc);
+    wined3d_mutex_unlock();
+
+    desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format);
+    desc->Type = wined3d_desc.resource_type;
+    desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
+    desc->Pool = wined3d_desc.pool;
+    desc->Width = wined3d_desc.width;
+    desc->Height = wined3d_desc.height;
+    desc->Depth = wined3d_desc.depth;
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_volume_LockBox(IDirect3DVolume9 *iface,
+        D3DLOCKED_BOX *locked_box, const D3DBOX *box, DWORD flags)
+{
+    struct d3d9_volume *volume = impl_from_IDirect3DVolume9(iface);
+    struct wined3d_map_desc map_desc;
+    HRESULT hr;
+
+    TRACE("iface %p, locked_box %p, box %p, flags %#x.\n",
+            iface, locked_box, box, flags);
+
+    wined3d_mutex_lock();
+    hr = wined3d_volume_map(volume->wined3d_volume, &map_desc, (const struct wined3d_box *)box, flags);
+    wined3d_mutex_unlock();
+
+    locked_box->RowPitch = map_desc.row_pitch;
+    locked_box->SlicePitch = map_desc.slice_pitch;
+    locked_box->pBits = map_desc.data;
+
+    return hr;
+}
+
+static HRESULT WINAPI d3d9_volume_UnlockBox(IDirect3DVolume9 *iface)
+{
+    struct d3d9_volume *volume = impl_from_IDirect3DVolume9(iface);
+    HRESULT hr;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    hr = wined3d_volume_unmap(volume->wined3d_volume);
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static const struct IDirect3DVolume9Vtbl d3d9_volume_vtbl =
+{
+    /* IUnknown */
+    d3d9_volume_QueryInterface,
+    d3d9_volume_AddRef,
+    d3d9_volume_Release,
+    /* IDirect3DVolume9 */
+    d3d9_volume_GetDevice,
+    d3d9_volume_SetPrivateData,
+    d3d9_volume_GetPrivateData,
+    d3d9_volume_FreePrivateData,
+    d3d9_volume_GetContainer,
+    d3d9_volume_GetDesc,
+    d3d9_volume_LockBox,
+    d3d9_volume_UnlockBox,
+};
+
+static void STDMETHODCALLTYPE volume_wined3d_object_destroyed(void *parent)
+{
+    HeapFree(GetProcessHeap(), 0, parent);
+}
+
+static const struct wined3d_parent_ops d3d9_volume_wined3d_parent_ops =
+{
+    volume_wined3d_object_destroyed,
+};
+
+HRESULT volume_init(struct d3d9_volume *volume, struct d3d9_device *device, UINT width, UINT height,
+        UINT depth, DWORD usage, enum wined3d_format_id format, enum wined3d_pool pool
+#ifdef VBOX_WITH_WDDM
+        , HANDLE *shared_handle
+        , void *pvClientMem
+#endif
+)
+{
+    HRESULT hr;
+
+    volume->IDirect3DVolume9_iface.lpVtbl = &d3d9_volume_vtbl;
+    volume->refcount = 1;
+
+    hr = wined3d_volume_create(device->wined3d_device, width, height, depth, usage & WINED3DUSAGE_MASK,
+            format, pool, volume, &d3d9_volume_wined3d_parent_ops, &volume->wined3d_volume
+#ifdef VBOX_WITH_WDDM
+            , shared_handle
+            , pvClientMem
+#endif
+            );
+    if (FAILED(hr))
+    {
+        WARN("Failed to create wined3d volume, hr %#x.\n", hr);
+        return hr;
+    }
+
+    return D3D_OK;
+}
+
+#ifdef VBOX_WITH_WDDM
+struct d3d9_volume *unsafe_impl_from_IDirect3DVolume9(IDirect3DVolume9 *iface)
+{
+    if (!iface)
+        return NULL;
+    assert(iface->lpVtbl == (const IDirect3DVolume9Vtbl *)&d3d9_volume_vtbl);
+    return CONTAINING_RECORD(iface, struct d3d9_volume, IDirect3DVolume9_iface);
+}
+#endif
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/switcher/d3d8.rc
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/switcher/d3d8.rc	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/switcher/d3d8.rc	(revision 46521)
@@ -0,0 +1,64 @@
+/* $Id$ */
+/** @file
+ * VBoxD3D8 - Resource file containing version info and icon.
+ */
+
+/*
+ * Copyright (C) 2009-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include <windows.h>
+#include <VBox/version.h>
+
+LANGUAGE 0x09, 0x01
+
+VS_VERSION_INFO VERSIONINFO
+   FILEVERSION          VBOX_VERSION_MAJOR_NR,VBOX_VERSION_MINOR_NR,VBOX_VERSION_BUILD_NR,0
+   PRODUCTVERSION       VBOX_VERSION_MAJOR_NR,VBOX_VERSION_MINOR_NR,VBOX_VERSION_BUILD_NR,0
+   FILEFLAGSMASK        0x3fL
+   FILEFLAGS            0x0L
+   FILEOS               0x40004L
+   FILETYPE             0x3L
+   FILESUBTYPE          0x4L
+BEGIN
+   BLOCK "StringFileInfo"
+   BEGIN
+      BLOCK "040904b0"
+      BEGIN
+         VALUE "CompanyName",      VBOX_RC_COMPANY_NAME
+         VALUE "FileDescription",  "VirtualBox D3D8 switcher\0"
+         VALUE "FileVersion",      VBOX_VERSION_MAJOR "." VBOX_VERSION_MINOR "." VBOX_VERSION_BUILD "." VBOX_SVN_REV "\0"
+         VALUE "InternalName",     "D3D8\0"
+         VALUE "LegalCopyright",   VBOX_RC_LEGAL_COPYRIGHT
+         VALUE "OriginalFilename", "D3D8.dll\0"
+         VALUE "ProductName",      VBOX_PRODUCT " Guest Additions\0"
+         VALUE "ProductVersion",   VBOX_VERSION_MAJOR "." VBOX_VERSION_MINOR "." VBOX_VERSION_BUILD ".r" VBOX_SVN_REV "\0"
+      END
+   END
+   BLOCK "VarFileInfo"
+   BEGIN
+      VALUE "Translation", 0x409, 1200
+   END
+END
+
+1 RCDATA
+BEGIN
+// Machine dependent parameters
+    17,     // Height of vertical thumb
+    17,     // Width of horizontal thumb
+    2,      // Icon horiz compression factor
+    2,      // Icon vert compression factor
+    1,      // Cursor horz compression factor
+    1,      // Cursor vert compression factor
+    0,      // Kanji window height
+    1,      // cxBorder (thickness of vertical lines)
+    1       // cyBorder (thickness of horizontal lines)
+END
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/switcher/d3d8_main.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/switcher/d3d8_main.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/switcher/d3d8_main.c	(revision 46521)
@@ -0,0 +1,104 @@
+/* $Id$ */
+
+/** @file
+ * VBox D3D8 dll switcher
+ */
+
+/*
+ * Copyright (C) 2009 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include "d3d8.h"
+#include "switcher.h"
+
+typedef HRESULT (WINAPI *D3D8GetSWInfoProc)(void);
+typedef void (WINAPI *DebugSetMuteProc)(void);
+typedef IDirect3D8* (WINAPI *Direct3DCreate8Proc)(UINT SDKVersion);
+typedef HRESULT (WINAPI *ValidatePixelShaderProc)(DWORD* pixelshader, DWORD* reserved1, BOOL bool, DWORD* toto);
+typedef HRESULT (WINAPI *ValidateVertexShaderProc)(DWORD* vertexshader, DWORD* reserved1, DWORD* reserved2, BOOL bool, DWORD* toto);
+
+static HRESULT WINAPI vboxD3D8GetSWInfoStub(void)
+{
+    return E_FAIL;
+}
+
+static void WINAPI vboxDebugSetMuteStub(void)
+{
+
+}
+
+static IDirect3D8* WINAPI vboxDirect3DCreate8Stub(UINT SDKVersion)
+{
+    return NULL;
+}
+
+static HRESULT WINAPI vboxValidatePixelShaderStub(DWORD* pixelshader, DWORD* reserved1, BOOL bool, DWORD* toto)
+{
+    return E_FAIL;
+}
+
+static HRESULT WINAPI vboxValidateVertexShaderStub(DWORD* vertexshader, DWORD* reserved1, DWORD* reserved2, BOOL bool, DWORD* toto)
+{
+    return E_FAIL;
+}
+
+typedef struct _D3D8ExTag
+{
+    int                      initialized;
+    const char              *vboxName;
+    const char              *msName;
+    D3D8GetSWInfoProc        pD3D8GetSWInfo;
+    DebugSetMuteProc         pDebugSetMute;
+    Direct3DCreate8Proc      pDirect3DCreate8;
+    ValidatePixelShaderProc  pValidatePixelShader;
+    ValidateVertexShaderProc pValidateVertexShader;
+} D3D8Export;
+
+static D3D8Export g_swd3d8 = {0, "VBoxD3D8.dll", "MSD3D8.dll",};
+
+void FillD3DExports(HANDLE hDLL)
+{
+    SW_FILLPROC(g_swd3d8, hDLL, D3D8GetSWInfo);
+    SW_FILLPROC(g_swd3d8, hDLL, DebugSetMute);
+    SW_FILLPROC(g_swd3d8, hDLL, Direct3DCreate8);
+    SW_FILLPROC(g_swd3d8, hDLL, ValidatePixelShader);
+    SW_FILLPROC(g_swd3d8, hDLL, ValidateVertexShader);
+}
+
+HRESULT WINAPI D3D8GetSWInfo(void)
+{
+    SW_CHECKRET(g_swd3d8, D3D8GetSWInfo, E_FAIL);
+    return g_swd3d8.pD3D8GetSWInfo();
+}
+
+void WINAPI DebugSetMute(void)
+{
+    SW_CHECKCALL(g_swd3d8, DebugSetMute);
+    g_swd3d8.pDebugSetMute();    
+}
+
+IDirect3D8* WINAPI Direct3DCreate8(UINT SDKVersion)
+{
+    SW_CHECKRET(g_swd3d8, Direct3DCreate8, NULL);
+    return g_swd3d8.pDirect3DCreate8(SDKVersion);
+}
+
+HRESULT WINAPI ValidatePixelShader(DWORD* pixelshader, DWORD* reserved1, BOOL bool, DWORD* toto)
+{
+    SW_CHECKRET(g_swd3d8, ValidatePixelShader, E_FAIL);
+    return g_swd3d8.pValidatePixelShader(pixelshader, reserved1, bool, toto);
+}
+
+HRESULT WINAPI ValidateVertexShader(DWORD* vertexshader, DWORD* reserved1, DWORD* reserved2, BOOL bool, DWORD* toto)
+{
+    SW_CHECKRET(g_swd3d8, ValidateVertexShader, E_FAIL)
+    return g_swd3d8.pValidateVertexShader(vertexshader, reserved1, reserved2, bool, toto);
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/switcher/d3d9.rc
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/switcher/d3d9.rc	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/switcher/d3d9.rc	(revision 46521)
@@ -0,0 +1,64 @@
+/* $Id$ */
+/** @file
+ * VBoxD3D9 - Resource file containing version info and icon.
+ */
+
+/*
+ * Copyright (C) 2009-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include <windows.h>
+#include <VBox/version.h>
+
+LANGUAGE 0x09, 0x01
+
+VS_VERSION_INFO VERSIONINFO
+   FILEVERSION          VBOX_VERSION_MAJOR_NR,VBOX_VERSION_MINOR_NR,VBOX_VERSION_BUILD_NR,0
+   PRODUCTVERSION       VBOX_VERSION_MAJOR_NR,VBOX_VERSION_MINOR_NR,VBOX_VERSION_BUILD_NR,0
+   FILEFLAGSMASK        0x3fL
+   FILEFLAGS            0x0L
+   FILEOS               0x40004L
+   FILETYPE             0x3L
+   FILESUBTYPE          0x4L
+BEGIN
+   BLOCK "StringFileInfo"
+   BEGIN
+      BLOCK "040904b0"
+      BEGIN
+         VALUE "CompanyName",      VBOX_RC_COMPANY_NAME
+         VALUE "FileDescription",  "VirtualBox D3D9 switcher\0"
+         VALUE "FileVersion",      VBOX_VERSION_MAJOR "." VBOX_VERSION_MINOR "." VBOX_VERSION_BUILD "." VBOX_SVN_REV "\0"
+         VALUE "InternalName",     "D3D9\0"
+         VALUE "LegalCopyright",   VBOX_RC_LEGAL_COPYRIGHT
+         VALUE "OriginalFilename", "D3D9.dll\0"
+         VALUE "ProductName",      VBOX_PRODUCT " Guest Additions\0"
+         VALUE "ProductVersion",   VBOX_VERSION_MAJOR "." VBOX_VERSION_MINOR "." VBOX_VERSION_BUILD ".r" VBOX_SVN_REV "\0"
+      END
+   END
+   BLOCK "VarFileInfo"
+   BEGIN
+      VALUE "Translation", 0x409, 1200
+   END
+END
+
+1 RCDATA
+BEGIN
+// Machine dependent parameters
+    17,     // Height of vertical thumb
+    17,     // Width of horizontal thumb
+    2,      // Icon horiz compression factor
+    2,      // Icon vert compression factor
+    1,      // Cursor horz compression factor
+    1,      // Cursor vert compression factor
+    0,      // Kanji window height
+    1,      // cxBorder (thickness of vertical lines)
+    1       // cyBorder (thickness of horizontal lines)
+END
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/switcher/d3d9_main.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/switcher/d3d9_main.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/switcher/d3d9_main.c	(revision 46521)
@@ -0,0 +1,195 @@
+/* $Id$ */
+
+/** @file
+ * VBox D3D8 dll switcher
+ */
+
+/*
+ * Copyright (C) 2009 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include "d3d9.h"
+#include "switcher.h"
+
+typedef void (WINAPI *DebugSetMuteProc)(void);
+typedef IDirect3D9* (WINAPI *Direct3DCreate9Proc)(UINT SDKVersion);
+typedef HRESULT (WINAPI *Direct3DCreate9ExProc)(UINT SDKVersion, IDirect3D9Ex **direct3d9ex);
+/* @todo: this does not return a value according to MSDN */
+typedef void* (WINAPI *Direct3DShaderValidatorCreate9Proc)(void);
+typedef int (WINAPI *D3DPERF_BeginEventProc)(D3DCOLOR color, LPCWSTR name);
+typedef int (WINAPI *D3DPERF_EndEventProc)(void);
+typedef DWORD (WINAPI *D3DPERF_GetStatusProc)(void);
+typedef void (WINAPI *D3DPERF_SetOptionsProc)(DWORD options);
+typedef BOOL (WINAPI *D3DPERF_QueryRepeatFrameProc)(void);
+typedef void (WINAPI *D3DPERF_SetMarkerProc)(D3DCOLOR color, LPCWSTR name);
+typedef void (WINAPI *D3DPERF_SetRegionProc)(D3DCOLOR color, LPCWSTR name);
+
+static void WINAPI vboxDebugSetMuteStub(void)
+{
+}
+
+static IDirect3D9* WINAPI vboxDirect3DCreate9Stub(UINT SDKVersion)
+{
+    return NULL;
+}
+
+static HRESULT WINAPI vboxDirect3DCreate9ExStub(UINT SDKVersion, IDirect3D9Ex **direct3d9ex)
+{
+    if (direct3d9ex)
+        *direct3d9ex = NULL;
+    return E_FAIL;
+}
+
+static void* WINAPI vboxDirect3DShaderValidatorCreate9Stub(void)
+{
+    return NULL;
+}
+
+static int WINAPI vboxD3DPERF_BeginEventStub(D3DCOLOR color, LPCWSTR name)
+{
+    return 0;
+}
+
+static int WINAPI vboxD3DPERF_EndEventStub(void)
+{
+    return 0;
+}
+
+static DWORD WINAPI vboxD3DPERF_GetStatusStub(void)
+{
+    return 0;
+}
+
+static void WINAPI vboxD3DPERF_SetOptionsStub(DWORD options)
+{
+
+}
+
+static BOOL WINAPI vboxD3DPERF_QueryRepeatFrameStub(void)
+{
+    return 0;
+}
+
+static void WINAPI vboxD3DPERF_SetMarkerStub(D3DCOLOR color, LPCWSTR name)
+{
+
+}
+
+static void WINAPI vboxD3DPERF_SetRegionStub(D3DCOLOR color, LPCWSTR name)
+{
+
+}
+
+
+typedef struct _D3D9ExTag
+{
+    int                     initialized;
+    const char              *vboxName;
+    const char              *msName;
+    DebugSetMuteProc        pDebugSetMute;
+    Direct3DCreate9Proc     pDirect3DCreate9;
+    Direct3DCreate9ExProc   pDirect3DCreate9Ex;
+    Direct3DShaderValidatorCreate9Proc pDirect3DShaderValidatorCreate9;
+    D3DPERF_BeginEventProc  pD3DPERF_BeginEvent;
+    D3DPERF_EndEventProc    pD3DPERF_EndEvent;
+    D3DPERF_GetStatusProc   pD3DPERF_GetStatus;
+    D3DPERF_SetOptionsProc  pD3DPERF_SetOptions;
+    D3DPERF_QueryRepeatFrameProc pD3DPERF_QueryRepeatFrame;
+    D3DPERF_SetMarkerProc   pD3DPERF_SetMarker;
+    D3DPERF_SetRegionProc   pD3DPERF_SetRegion;
+} D3D9Export;
+
+#ifdef VBOX_WDDM_WOW64
+static D3D9Export g_swd3d9 = {0, "VBoxD3D9-x86.dll", "MSD3D9.dll",};
+#else
+static D3D9Export g_swd3d9 = {0, "VBoxD3D9.dll", "MSD3D9.dll",};
+#endif
+
+void FillD3DExports(HANDLE hDLL)
+{
+    SW_FILLPROC(g_swd3d9, hDLL, DebugSetMute);
+    SW_FILLPROC(g_swd3d9, hDLL, Direct3DCreate9);
+    SW_FILLPROC(g_swd3d9, hDLL, Direct3DCreate9Ex);
+    SW_FILLPROC(g_swd3d9, hDLL, Direct3DShaderValidatorCreate9);
+    SW_FILLPROC(g_swd3d9, hDLL, D3DPERF_BeginEvent);
+    SW_FILLPROC(g_swd3d9, hDLL, D3DPERF_EndEvent);
+    SW_FILLPROC(g_swd3d9, hDLL, D3DPERF_GetStatus);
+    SW_FILLPROC(g_swd3d9, hDLL, D3DPERF_SetOptions);
+    SW_FILLPROC(g_swd3d9, hDLL, D3DPERF_QueryRepeatFrame);
+    SW_FILLPROC(g_swd3d9, hDLL, D3DPERF_SetMarker);
+    SW_FILLPROC(g_swd3d9, hDLL, D3DPERF_SetRegion);
+}
+
+void WINAPI DebugSetMute(void) 
+{
+    SW_CHECKCALL(g_swd3d9, DebugSetMute);
+    g_swd3d9.pDebugSetMute();    
+}
+
+IDirect3D9* WINAPI Direct3DCreate9(UINT SDKVersion)
+{
+    SW_CHECKRET(g_swd3d9, Direct3DCreate9, NULL);
+    return g_swd3d9.pDirect3DCreate9(SDKVersion);
+}
+
+HRESULT WINAPI Direct3DCreate9Ex(UINT SDKVersion, IDirect3D9Ex **direct3d9ex)
+{
+    SW_CHECKRET(g_swd3d9, Direct3DCreate9Ex, E_FAIL);
+    return g_swd3d9.pDirect3DCreate9Ex(SDKVersion, direct3d9ex);
+}
+
+void* WINAPI Direct3DShaderValidatorCreate9(void)
+{
+    SW_CHECKRET(g_swd3d9, Direct3DShaderValidatorCreate9, NULL);
+    return g_swd3d9.pDirect3DShaderValidatorCreate9();
+}
+
+int WINAPI D3DPERF_BeginEvent(D3DCOLOR color, LPCWSTR name)
+{
+    SW_CHECKRET(g_swd3d9, D3DPERF_BeginEvent, -1);
+    return g_swd3d9.pD3DPERF_BeginEvent(color, name);
+}
+
+int WINAPI D3DPERF_EndEvent(void)
+{
+    SW_CHECKRET(g_swd3d9, D3DPERF_EndEvent, -1);
+    return g_swd3d9.pD3DPERF_EndEvent();
+}
+
+DWORD WINAPI D3DPERF_GetStatus(void)
+{
+    SW_CHECKRET(g_swd3d9, D3DPERF_EndEvent, 0);
+    return g_swd3d9.pD3DPERF_GetStatus();
+}
+
+void WINAPI D3DPERF_SetOptions(DWORD options)
+{
+    SW_CHECKCALL(g_swd3d9, D3DPERF_SetOptions);
+    g_swd3d9.pD3DPERF_SetOptions(options);
+}
+
+BOOL WINAPI D3DPERF_QueryRepeatFrame(void)
+{
+    SW_CHECKRET(g_swd3d9, D3DPERF_QueryRepeatFrame, FALSE);
+    return g_swd3d9.pD3DPERF_QueryRepeatFrame();
+}
+
+void WINAPI D3DPERF_SetMarker(D3DCOLOR color, LPCWSTR name)
+{
+    SW_CHECKCALL(g_swd3d9, D3DPERF_SetMarker);
+    g_swd3d9.pD3DPERF_SetMarker(color, name);
+}
+
+void WINAPI D3DPERF_SetRegion(D3DCOLOR color, LPCWSTR name)
+{
+    SW_CHECKCALL(g_swd3d9, D3DPERF_SetRegion);
+    g_swd3d9.pD3DPERF_SetRegion(color, name);
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/switcher/sw_common.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/switcher/sw_common.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/switcher/sw_common.c	(revision 46521)
@@ -0,0 +1,119 @@
+/* $Id$ */
+
+/** @file
+ * VBox D3D8/9 dll switcher
+ */
+
+/*
+ * Copyright (C) 2009 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include <windows.h>
+#include "switcher.h"
+
+static char* gsBlackListExe[] = {"Dwm.exe", "java.exe", "javaw.exe", "javaws.exe"/*, "taskeng.exe"*/, NULL};
+static char* gsBlackListDll[] = {"awt.dll", "wpfgfx_v0400.dll", "wpfgfx_v0300.dll", NULL};
+
+/* Checks if 3D is enabled for VM and it works on host machine */
+BOOL isVBox3DEnabled(void)
+{
+    DrvValidateVersionProc pDrvValidateVersion;
+    HANDLE hDLL;
+    BOOL result = FALSE;
+
+#ifdef VBOX_WDDM_WOW64
+    hDLL = LoadLibrary("VBoxOGL-x86.dll");
+#else
+    hDLL = LoadLibrary("VBoxOGL.dll");
+#endif
+
+    /* note: this isn't really needed as our library will refuse to load if it can't connect to host.
+       so it's in case we'd change it one day.
+    */
+    pDrvValidateVersion = (DrvValidateVersionProc) GetProcAddress(hDLL, "DrvValidateVersion");
+    if (pDrvValidateVersion)
+    {
+        result = pDrvValidateVersion(0);
+    }
+    FreeLibrary(hDLL);
+    return result;
+}
+
+BOOL checkOptionsDll(void)
+{
+    int i;
+    for (i=0; gsBlackListDll[i]; ++i)
+    {
+        if (GetModuleHandleA(gsBlackListDll[i]))
+            return FALSE;
+    }
+
+    return TRUE;
+}
+
+BOOL checkOptionsExe(void)
+{
+    char name[1000];
+    char *filename = name, *pName;
+    int i;
+
+	if (!GetModuleFileName(NULL, name, 1000))
+		return TRUE;
+
+    /*Extract filename*/
+    for (pName=name; *pName; ++pName)
+    {
+        switch (*pName)
+        {
+            case ':':
+            case '\\':
+            case '/':
+                filename = pName + 1;
+                break;
+        }
+    }
+
+    for (i=0; gsBlackListExe[i]; ++i)
+    {
+        if (!stricmp(filename, gsBlackListExe[i]))
+            return FALSE;
+    }
+
+    return TRUE;
+}
+
+BOOL checkOptions(void)
+{
+    if (!checkOptionsDll())
+        return FALSE;
+
+    if (!checkOptionsExe())
+        return FALSE;
+
+    return TRUE;
+}
+
+void InitD3DExports(const char *vboxName, const char *msName)
+{
+    const char *dllName;
+    HANDLE hDLL;
+
+    if (isVBox3DEnabled() && checkOptions())
+    {
+        dllName = vboxName;
+    } else
+    {
+        dllName = msName;
+    }
+
+    hDLL = LoadLibrary(dllName);
+    FillD3DExports(hDLL); 
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/switcher/sw_d3d8.def
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/switcher/sw_d3d8.def	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/switcher/sw_d3d8.def	(revision 46521)
@@ -0,0 +1,6 @@
+EXPORTS
+  D3D8GetSWInfo
+  DebugSetMute
+  Direct3DCreate8
+  ValidatePixelShader
+  ValidateVertexShader
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/switcher/sw_d3d9.def
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/switcher/sw_d3d9.def	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/switcher/sw_d3d9.def	(revision 46521)
@@ -0,0 +1,12 @@
+EXPORTS
+  Direct3DShaderValidatorCreate9@0=Direct3DShaderValidatorCreate9
+  D3DPERF_BeginEvent@8=D3DPERF_BeginEvent
+  D3DPERF_EndEvent@0=D3DPERF_EndEvent
+  D3DPERF_GetStatus@0=D3DPERF_GetStatus
+  D3DPERF_QueryRepeatFrame@0=D3DPERF_QueryRepeatFrame
+  D3DPERF_SetMarker@8=D3DPERF_SetMarker
+  D3DPERF_SetOptions@4=D3DPERF_SetOptions
+  D3DPERF_SetRegion@8=D3DPERF_SetRegion
+  DebugSetMute@0=DebugSetMute
+  Direct3DCreate9@4=Direct3DCreate9
+  Direct3DCreate9Ex@8=Direct3DCreate9Ex
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/switcher/sw_d3d9xpdm.def
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/switcher/sw_d3d9xpdm.def	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/switcher/sw_d3d9xpdm.def	(revision 46521)
@@ -0,0 +1,12 @@
+EXPORTS
+  Direct3DShaderValidatorCreate9
+  D3DPERF_BeginEvent
+  D3DPERF_EndEvent
+  D3DPERF_GetStatus
+  D3DPERF_QueryRepeatFrame
+  D3DPERF_SetMarker
+  D3DPERF_SetOptions
+  D3DPERF_SetRegion
+  DebugSetMute
+  Direct3DCreate9
+  Direct3DCreate9Ex
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/switcher/switcher.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/switcher/switcher.h	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/switcher/switcher.h	(revision 46521)
@@ -0,0 +1,54 @@
+/* $Id$ */
+
+/** @file
+ * VBox D3D8/9 dll switcher
+ */
+
+/*
+ * Copyright (C) 2009 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef ___CROPENGL_SWITCHER_H_
+#define ___CROPENGL_SWITCHER_H_
+
+typedef BOOL (APIENTRY *DrvValidateVersionProc)(DWORD version);
+
+#define SW_FILLPROC(dispatch, hdll, name) \
+    dispatch.p##name = ((hdll) != NULL) ? (name##Proc) GetProcAddress((hdll), #name) : vbox##name##Stub;
+
+#define SW_DISPINIT(dispatch)                                   \
+    {                                                           \
+        if (!dispatch.initialized)                              \
+        {                                                       \
+            InitD3DExports(dispatch.vboxName, dispatch.msName); \
+            dispatch.initialized = 1;                           \
+        }                                                       \
+    }
+
+#define SW_CHECKRET(dispatch, func, failret)   \
+    {                                          \
+        SW_DISPINIT(dispatch)                  \
+        if (!dispatch.p##func)                 \
+            return failret;                    \
+    }
+
+#define SW_CHECKCALL(dispatch, func)    \
+    {                                   \
+        SW_DISPINIT(dispatch)           \
+        if (!dispatch.p##func) return;  \
+    }
+
+extern BOOL IsVBox3DEnabled(void);
+extern BOOL CheckOptions(void);
+extern void FillD3DExports(HANDLE hDLL);
+extern void InitD3DExports(const char *vboxName, const char *msName);
+
+#endif /* #ifndef ___CROPENGL_SWITCHER_H_ */
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/VBoxDbgGl.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/VBoxDbgGl.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/VBoxDbgGl.c	(revision 46521)
@@ -0,0 +1,389 @@
+/* $Id$ */
+
+/** @file
+ * VBox wine & ogl debugging stuff
+ */
+
+/*
+ * Copyright (C) 2011 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdio.h>
+#ifdef HAVE_FLOAT_H
+# include <float.h>
+#endif
+
+#include "../wined3d/wined3d_private.h"
+
+#include "VBoxDbgGl.h"
+
+#include <iprt/ctype.h>
+
+
+DWORD g_VBoxDbgGlFCheckDrawPrim = 0;
+DWORD g_VBoxDbgGlFBreakDrawPrimIfCanNotMatch = 0;
+
+void dbglFree(void *pvData)
+{
+    HeapFree(GetProcessHeap(),  0, pvData);
+}
+
+void* dbglAlloc(DWORD cbSize)
+{
+    return HeapAlloc(GetProcessHeap(),  0, cbSize);
+}
+
+GLint dbglFmtGetNumComponents(GLenum format)
+{
+    switch(format)
+    {
+        case GL_COLOR_INDEX:
+        case GL_RED:
+        case GL_GREEN:
+        case GL_BLUE:
+        case GL_ALPHA:
+            return 1;
+        case GL_RGB:
+        case GL_BGR:
+            return 3;
+        case GL_RGBA:
+        case GL_BGRA:
+            return 4;
+        case GL_LUMINANCE:
+            return 1;
+        case GL_LUMINANCE_ALPHA:
+            return 2;
+        default:
+            Assert(0);
+            return 1;
+    }
+}
+
+GLint dbglFmtGetBpp(GLenum format, GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE_3_3_2:
+            return 8;
+        case GL_UNSIGNED_BYTE_2_3_3_REV:
+            return 8;
+        case GL_UNSIGNED_SHORT_5_6_5:
+            return 16;
+        case GL_UNSIGNED_SHORT_5_6_5_REV:
+            return 16;
+        case GL_UNSIGNED_SHORT_4_4_4_4:
+            return 16;
+        case GL_UNSIGNED_SHORT_4_4_4_4_REV:
+            return 16;
+        case GL_UNSIGNED_SHORT_5_5_5_1:
+            return 16;
+        case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+            return 16;
+        case GL_UNSIGNED_INT_8_8_8_8:
+            return 32;
+        case GL_UNSIGNED_INT_8_8_8_8_REV:
+            return 32;
+        case GL_UNSIGNED_INT_10_10_10_2:
+            return 32;
+        case GL_UNSIGNED_INT_2_10_10_10_REV:
+            return 32;
+        case GL_BYTE:
+        case GL_UNSIGNED_BYTE:
+            return dbglFmtGetNumComponents(format) * 8;
+        case GL_SHORT:
+        case GL_UNSIGNED_SHORT:
+            return dbglFmtGetNumComponents(format) * 16;
+        case GL_INT:
+        case GL_UNSIGNED_INT:
+        case GL_FLOAT:
+            return dbglFmtGetNumComponents(format) * 32;
+        case GL_DOUBLE:
+            return dbglFmtGetNumComponents(format) * 64;
+        case GL_2_BYTES:
+            return dbglFmtGetNumComponents(format) * 16;
+        case GL_3_BYTES:
+            return dbglFmtGetNumComponents(format) * 24;
+        case GL_4_BYTES:
+            return dbglFmtGetNumComponents(format) * 32;
+        default:
+            Assert(0);
+            return 8;
+    }
+}
+
+#define DBGL_OP(_op) gl##_op
+#define DBGL_FBO_OP(_op) (gl_info->fbo_ops.gl##_op)
+#define DBGL_EXT_OP(_op)  (gl_info->gl_ops.ext.p_gl##_op)
+
+void dbglGetTexImage2D(const struct wined3d_gl_info *gl_info, GLint texTarget, GLint texName, GLint level, GLvoid **ppvImage, GLint *pw, GLint *ph, GLenum format, GLenum type)
+{
+    GLint ppb, pub, dstw, dsth, otex;
+    GLint pa, pr, psp, psr, ua, ur, usp, usr;
+    GLvoid *pvImage;
+    GLint rfb, dfb, rb, db;
+    GLint bpp = dbglFmtGetBpp(format, type);
+
+    DBGL_OP(GetIntegerv(GL_READ_FRAMEBUFFER_BINDING_EXT, &rfb));
+    DBGL_OP(GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING_EXT, &dfb));
+    DBGL_OP(GetIntegerv(GL_READ_BUFFER, &rb));
+    DBGL_OP(GetIntegerv(GL_DRAW_BUFFER, &db));
+
+    DBGL_FBO_OP(BindFramebuffer)(GL_READ_FRAMEBUFFER_BINDING_EXT, 0);
+    DBGL_FBO_OP(BindFramebuffer)(GL_DRAW_FRAMEBUFFER_BINDING_EXT, 0);
+    DBGL_OP(ReadBuffer(GL_BACK));
+    DBGL_OP(DrawBuffer(GL_BACK));
+
+    DBGL_OP(GetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING_ARB, &ppb));
+    DBGL_OP(GetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING_ARB, &pub));
+    DBGL_OP(GetIntegerv(GL_TEXTURE_BINDING_2D, &otex));
+
+    DBGL_OP(GetIntegerv(GL_PACK_ROW_LENGTH, &pr));
+    DBGL_OP(GetIntegerv(GL_PACK_ALIGNMENT, &pa));
+    DBGL_OP(GetIntegerv(GL_PACK_SKIP_PIXELS, &psp));
+    DBGL_OP(GetIntegerv(GL_PACK_SKIP_ROWS, &psr));
+
+    DBGL_OP(GetIntegerv(GL_UNPACK_ROW_LENGTH, &ur));
+    DBGL_OP(GetIntegerv(GL_UNPACK_ALIGNMENT, &ua));
+    DBGL_OP(GetIntegerv(GL_UNPACK_SKIP_PIXELS, &usp));
+    DBGL_OP(GetIntegerv(GL_UNPACK_SKIP_ROWS, &usr));
+
+    DBGL_OP(BindTexture(texTarget, texName));
+    DBGL_OP(GetTexLevelParameteriv(texTarget, level, GL_TEXTURE_WIDTH, &dstw));
+    DBGL_OP(GetTexLevelParameteriv(texTarget, level, GL_TEXTURE_HEIGHT, &dsth));
+
+    DBGL_OP(PixelStorei(GL_PACK_ROW_LENGTH, 0));
+    DBGL_OP(PixelStorei(GL_PACK_ALIGNMENT, 1));
+    DBGL_OP(PixelStorei(GL_PACK_SKIP_PIXELS, 0));
+    DBGL_OP(PixelStorei(GL_PACK_SKIP_ROWS, 0));
+
+    DBGL_OP(PixelStorei(GL_UNPACK_ROW_LENGTH, 0));
+    DBGL_OP(PixelStorei(GL_UNPACK_ALIGNMENT, 1));
+    DBGL_OP(PixelStorei(GL_UNPACK_SKIP_PIXELS, 0));
+    DBGL_OP(PixelStorei(GL_UNPACK_SKIP_ROWS, 0));
+
+    DBGL_EXT_OP(BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0));
+    DBGL_EXT_OP(BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
+
+    pvImage = dbglAlloc(((bpp*dstw + 7) >> 3)*dsth);
+    DBGL_OP(GetTexImage(texTarget, level, format, type, pvImage));
+
+    DBGL_OP(BindTexture(texTarget, otex));
+
+    DBGL_OP(PixelStorei(GL_PACK_ROW_LENGTH, pr));
+    DBGL_OP(PixelStorei(GL_PACK_ALIGNMENT, pa));
+    DBGL_OP(PixelStorei(GL_PACK_SKIP_PIXELS, psp));
+    DBGL_OP(PixelStorei(GL_PACK_SKIP_ROWS, psr));
+
+    DBGL_OP(PixelStorei(GL_UNPACK_ROW_LENGTH, ur));
+    DBGL_OP(PixelStorei(GL_UNPACK_ALIGNMENT, ua));
+    DBGL_OP(PixelStorei(GL_UNPACK_SKIP_PIXELS, usp));
+    DBGL_OP(PixelStorei(GL_UNPACK_SKIP_ROWS, usr));
+
+    DBGL_EXT_OP(BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ppb));
+    DBGL_EXT_OP(BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pub));
+
+    DBGL_FBO_OP(BindFramebuffer)(GL_READ_FRAMEBUFFER_BINDING_EXT, rfb);
+    DBGL_FBO_OP(BindFramebuffer)(GL_DRAW_FRAMEBUFFER_BINDING_EXT, dfb);
+    DBGL_OP(ReadBuffer(rb));
+    DBGL_OP(DrawBuffer(db));
+
+    *ppvImage = pvImage;
+    *pw = dstw;
+    *ph = dsth;
+}
+
+DECLEXPORT(void) dbglPrint(const char *format, ... )
+{
+    va_list args;
+    static char txt[8092];
+
+    va_start( args, format );
+    vsprintf( txt, format, args );
+
+    OutputDebugString(txt);
+}
+
+void dbglDumpImage2D(const char* pszDesc, const void *pvData, uint32_t width, uint32_t height, uint32_t bpp, uint32_t pitch)
+{
+    dbglPrint("<?dml?><exec cmd=\"!vbvdbg.ms 0x%p 0n%d 0n%d 0n%d 0n%d\">%s</exec>, ( !vbvdbg.ms 0x%p 0n%d 0n%d 0n%d 0n%d )\n",
+            pvData, width, height, bpp, pitch,
+            pszDesc,
+            pvData, width, height, bpp, pitch);
+}
+
+void dbglDumpTexImage2D(const struct wined3d_gl_info *gl_info, const char* pszDesc, GLint texTarget, GLint texName, GLint level, GLboolean fBreak)
+{
+    GLvoid *pvImage;
+    GLint w, h;
+    dbglGetTexImage2D(gl_info, texTarget, texName, level, &pvImage, &w, &h, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV);
+    dbglPrint("%s target(%d), name(%d), width(%d), height(%d)\n", pszDesc, texTarget, texName, w, h);
+    dbglDumpImage2D("texture data", pvImage, w, h, 32, (32 * w)/8);
+    if (fBreak)
+    {
+        Assert(0);
+    }
+    dbglFree(pvImage);
+}
+
+void dbglCmpTexImage2D(const struct wined3d_gl_info *gl_info, const char* pszDesc, GLint texTarget, GLint texName, GLint level, void *pvImage,
+        GLint width, GLint height, GLenum format, GLenum type)
+{
+    GLvoid *pvTexImg;
+    GLint w, h;
+    GLint bpp = dbglFmtGetBpp(format, type);
+    GLint pitch, texPitch;
+
+    dbglGetTexImage2D(gl_info, texTarget, texName, level, &pvTexImg, &w, &h, format, type);
+
+    pitch = ((bpp * width + 7) >> 3)/8;
+    texPitch = ((bpp * w + 7) >> 3)/8;
+
+    if (w != width)
+    {
+        dbglPrint("width mismatch was %d, but expected %d\n", w, width);
+        dbglDumpImage2D("expected texture data:", pvImage, width, height, bpp, pitch);
+        dbglDumpImage2D("stored texture data:", pvTexImg, w, h, bpp, texPitch);
+
+        Assert(0);
+
+        dbglFree(pvTexImg);
+        return;
+    }
+    if (h != height)
+    {
+        dbglPrint("height mismatch was %d, but expected %d\n", h, height);
+        dbglDumpImage2D("expected texture data:", pvImage, width, height, bpp, pitch);
+        dbglDumpImage2D("stored texture data:", pvTexImg, w, h, bpp, texPitch);
+
+        Assert(0);
+
+        dbglFree(pvTexImg);
+        return;
+    }
+
+    if (memcmp(pvImage, pvTexImg, w * h * 4))
+    {
+        dbglPrint("tex data mismatch\n");
+        dbglDumpImage2D("expected texture data:", pvImage, width, height, bpp, pitch);
+        dbglDumpImage2D("stored texture data:", pvTexImg, w, h, bpp, texPitch);
+
+        Assert(0);
+    }
+
+    dbglFree(pvTexImg);
+}
+
+void dbglCheckTexUnits(const struct wined3d_gl_info *gl_info, struct wined3d_device *pDevice, BOOL fBreakIfCanNotMatch)
+{
+    int iStage;
+    GLint ActiveTexUnit = 0;
+    GLint CheckTexUnit = 0;
+    DBGL_OP(GetIntegerv(GL_ACTIVE_TEXTURE, &ActiveTexUnit));
+
+    Assert(ActiveTexUnit >= GL_TEXTURE0);
+    Assert(gl_info->limits.combined_samplers <= RT_ELEMENTS(pDevice->stateBlock->state.textures));
+    Assert(ActiveTexUnit < GL_TEXTURE0 + gl_info->limits.combined_samplers);
+
+    CheckTexUnit = ActiveTexUnit;
+
+    Assert(ActiveTexUnit == pDevice->contexts[0]->active_texture + GL_TEXTURE0);
+
+    for (iStage = 0; iStage < gl_info->limits.combined_samplers; ++iStage)
+    {
+        GLint curTex = 0;
+        int iLevel;
+        struct gl_texture *pGlTex;
+        const struct wined3d_texture *pTexture = (const struct wined3d_texture*)pDevice->stateBlock->state.textures[iStage];
+
+        if (CheckTexUnit != iStage + GL_TEXTURE0)
+        {
+            DBGL_EXT_OP(ActiveTextureARB(iStage + GL_TEXTURE0));
+            CheckTexUnit = iStage + GL_TEXTURE0;
+        }
+
+        DBGL_OP(GetIntegerv(GL_TEXTURE_BINDING_2D, &curTex));
+
+        if (!pTexture)
+        {
+            Assert(curTex == 0 || curTex == pDevice->dummy_texture_2d[iStage]);
+            continue;
+        }
+
+        if(pTexture->flags & WINED3D_TEXTURE_IS_SRGB)
+        {
+            Assert(0);
+            pGlTex = &pTexture->texture_srgb;
+        }
+        else
+            pGlTex = &pTexture->texture_rgb;
+
+        /* not implemented */
+        Assert(pTexture->target == GL_TEXTURE_2D);
+        Assert(curTex);
+        Assert(pGlTex->name);
+        Assert(pGlTex->name == curTex);
+        Assert(DBGL_OP(IsEnabled(pTexture->target)));
+
+        /* not implemented */
+        Assert(pTexture->layer_count == 1);
+
+        for (iLevel = 0; iLevel < (int)pTexture->level_count; ++iLevel)
+        {
+            struct wined3d_surface *surface = (struct wined3d_surface *)pTexture->sub_resources[iLevel];
+            Assert(surface);
+
+            Assert(surface->flags & SFLAG_INTEXTURE);
+
+            Assert(surface->texture_target == pTexture->target);
+            Assert(surface->texture_name == (pTexture->flags & WINED3D_TEXTURE_IS_SRGB) ? pTexture->texture_srgb.name : pTexture->texture_rgb.name);
+#if 0
+            if (pSurf->flags & SFLAG_INSYSMEM && !pSurf->Flags & SFLAG_PBO)
+            {
+                Assert(pSurf->resource.allocatedMemory);
+                /* we can match GPU & our state */
+                dbglCmpTexImage2D(gl_info, "matching tex data state", pSurf->texture_target, pSurf->texture_name, iLevel, pSurf->resource.allocatedMemory,
+                        pSurf->currentDesc.Width, pSurf->currentDesc.Height, pSurf->resource.format_desc->glFormat, pSurf->resource.format_desc->glType);
+            }
+            else
+            {
+                GLint w,h;
+                if (fBreakIfCanNotMatch)
+                {
+                    GLvoid* pvImage;
+                    dbglGetTexImage2D(gl_info, pSurf->texture_target, pSurf->texture_name, iLevel, &pvImage, &w, &h, GL_BGRA, GL_UNSIGNED_BYTE);
+                    Assert(w == pSurf->currentDesc.Width);
+                    Assert(h == pSurf->currentDesc.Height);
+                    dbglDumpImage2D("matching texture data", pvImage, w, h, 32, (32 * w)/8);
+                    Assert(0);
+                    dbglFree(pvImage);
+                }
+                else
+                {
+                    /* just check width & height */
+                    /* since we already asserted current texture binding, we can just quiry its parameters */
+                    DBGL_OP(GetTexLevelParameteriv(pSurf->texture_target, iLevel, GL_TEXTURE_WIDTH, &w));
+                    DBGL_OP(GetTexLevelParameteriv(pSurf->texture_target, iLevel, GL_TEXTURE_HEIGHT, &h));
+                    Assert(w == pSurf->currentDesc.Width);
+                    Assert(h == pSurf->currentDesc.Height);
+                }
+            }
+#endif
+        }
+    }
+
+    if (CheckTexUnit != ActiveTexUnit)
+    {
+        DBGL_EXT_OP(ActiveTextureARB(ActiveTexUnit));
+    }
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/VBoxDbgGl.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/VBoxDbgGl.h	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/VBoxDbgGl.h	(revision 46521)
@@ -0,0 +1,43 @@
+/* $Id$ */
+
+/** @file
+ * VBox wine & ogl debugging stuff
+ */
+
+/*
+ * Copyright (C) 2011 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef ___VBoxDbgGl_h__
+#define ___VBoxDbgGl_h__
+
+//#include <windows.h>
+//#include "../wined3d/wined3d_gl.h"
+
+void dbglGetTexImage2D(const struct wined3d_gl_info *gl_info, GLint texTarget, GLint texName, GLint level, GLvoid **ppvImage, GLint *pw, GLint *ph, GLenum format, GLenum type);
+void dbglDumpTexImage2D(const struct wined3d_gl_info *gl_info, const char* pszDesc, GLint texTarget, GLint texName, GLint level, GLboolean fBreak);
+void dbglCmpTexImage2D(const struct wined3d_gl_info *gl_info, const char* pszDesc, GLint texTarget, GLint texName, GLint level, void *pvImage, GLint width, GLint height, GLenum format, GLenum type);
+void dbglCheckTexUnits(const struct wined3d_gl_info *gl_info, struct wined3d_device *pDevice, BOOL fBreakIfCanNotMatch);
+
+#ifdef DEBUG_misha
+#define DBGL_CHECK_DRAWPRIM(_gl_info, _pDevice) do { \
+        if (g_VBoxDbgGlFCheckDrawPrim) { \
+            dbglCheckTexUnits((_gl_info), (_pDevice), g_VBoxDbgGlFBreakDrawPrimIfCanNotMatch); \
+        } \
+    } while (0)
+#else
+#define DBGL_CHECK_DRAWPRIM(_gl_info, _pDevice) do {} while (0)
+#endif
+
+extern DWORD g_VBoxDbgGlFCheckDrawPrim;
+extern DWORD g_VBoxDbgGlFBreakDrawPrimIfCanNotMatch;
+
+#endif /* #ifndef ___VBoxDbgGl_h__ */
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/VBoxWineEx.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/VBoxWineEx.h	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/VBoxWineEx.h	(revision 46521)
@@ -0,0 +1,136 @@
+/** @file
+ *
+ * VBox extension to Wine D3D
+ *
+ * Copyright (C) 2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+#ifndef ___VBoxWineEx_h__
+#define ___VBoxWineEx_h__
+
+typedef enum
+{
+    VBOXWINEEX_SHRC_STATE_UNDEFINED = 0,
+    /* the underlying GL resource can not be used because it can be removed concurrently by other SHRC client */
+    VBOXWINEEX_SHRC_STATE_GL_DISABLE,
+    /* the given client is requested to delete the underlying GL resource on SHRC termination */
+    VBOXWINEEX_SHRC_STATE_GL_DELETE
+} VBOXWINEEX_SHRC_STATE;
+
+
+#ifndef IN_VBOXLIBWINE
+
+#define VBOXWINEEX_VERSION 1
+
+#ifndef IN_VBOXWINEEX
+# define VBOXWINEEX_DECL(_type)   __declspec(dllimport) _type WINAPI
+# else
+# define VBOXWINEEX_DECL(_type)  __declspec(dllexport) _type WINAPI
+#endif
+
+typedef VBOXWINEEX_DECL(HRESULT) FNVBOXWINEEXD3DDEV9_CREATETEXTURE(IDirect3DDevice9Ex *iface,
+            UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format,
+            D3DPOOL pool, IDirect3DTexture9 **texture, HANDLE *shared_handle,
+            void **pavClientMem);
+typedef FNVBOXWINEEXD3DDEV9_CREATETEXTURE *PFNVBOXWINEEXD3DDEV9_CREATETEXTURE;
+
+typedef VBOXWINEEX_DECL(HRESULT) FNVBOXWINEEXD3DDEV9_CREATECUBETEXTURE(IDirect3DDevice9Ex *iface,
+            UINT edge_length, UINT levels, DWORD usage, D3DFORMAT format, 
+            D3DPOOL pool, IDirect3DCubeTexture9 **texture, HANDLE *shared_handle,
+            void **pavClientMem);
+typedef FNVBOXWINEEXD3DDEV9_CREATECUBETEXTURE *PFNVBOXWINEEXD3DDEV9_CREATECUBETEXTURE;
+
+typedef VBOXWINEEX_DECL(HRESULT) FNVBOXWINEEXD3DDEV9_CREATEVOLUMETEXTURE(IDirect3DDevice9Ex *iface,
+            UINT width, UINT height, UINT depth, UINT levels, DWORD usage, D3DFORMAT Format, D3DPOOL Pool,
+            IDirect3DVolumeTexture9 **ppVolumeTexture, HANDLE *pSharedHandle,
+            void **pavClientMem);
+typedef FNVBOXWINEEXD3DDEV9_CREATEVOLUMETEXTURE *PFNVBOXWINEEXD3DDEV9_CREATEVOLUMETEXTURE;
+
+typedef VBOXWINEEX_DECL(HRESULT) FNVBOXWINEEXD3DDEV9_VOLBLT(IDirect3DDevice9Ex *iface,
+                                                    IDirect3DVolume9 *pSourceVolume, IDirect3DVolume9 *pDestinationVolume,
+                                                    const struct VBOXBOX3D *pSrcBoxArg,
+                                                    const struct VBOXPOINT3D *pDstPoin3D);
+typedef FNVBOXWINEEXD3DDEV9_VOLBLT *PFNVBOXWINEEXD3DDEV9_VOLBLT;
+
+typedef VBOXWINEEX_DECL(HRESULT) FNVBOXWINEEXD3DDEV9_VOLTEXBLT(IDirect3DDevice9Ex *iface,
+                                                    IDirect3DVolumeTexture9 *pSourceTexture, IDirect3DVolumeTexture9 *pDestinationTexture,
+                                                    const struct VBOXBOX3D *pSrcBoxArg,
+                                                    const struct VBOXPOINT3D *pDstPoin3D);
+typedef FNVBOXWINEEXD3DDEV9_VOLTEXBLT *PFNVBOXWINEEXD3DDEV9_VOLTEXBLT;
+
+typedef VBOXWINEEX_DECL(HRESULT) FNVBOXWINEEXD3DDEV9_FLUSH(IDirect3DDevice9Ex *iface);
+typedef FNVBOXWINEEXD3DDEV9_FLUSH *PFNVBOXWINEEXD3DDEV9_FLUSH;
+
+typedef VBOXWINEEX_DECL(HRESULT) FNVBOXWINEEXD3DDEV9_FLUSHTOHOST(IDirect3DDevice9Ex *iface);
+typedef FNVBOXWINEEXD3DDEV9_FLUSHTOHOST *PFNVBOXWINEEXD3DDEV9_FLUSHTOHOST;
+
+typedef VBOXWINEEX_DECL(HRESULT) FNVBOXWINEEXD3DDEV9_FINISH(IDirect3DDevice9Ex *iface);
+typedef FNVBOXWINEEXD3DDEV9_FINISH *PFNVBOXWINEEXD3DDEV9_FINISH;
+
+typedef VBOXWINEEX_DECL(HRESULT) FNVBOXWINEEXD3DDEV9_TERM(IDirect3DDevice9Ex *iface);
+typedef FNVBOXWINEEXD3DDEV9_TERM *PFNVBOXWINEEXD3DDEV9_TERM;
+
+typedef VBOXWINEEX_DECL(HRESULT) FNVBOXWINEEXD3DSWAPCHAIN9_PRESENT(IDirect3DSwapChain9 *iface, IDirect3DSurface9 *surf);
+typedef FNVBOXWINEEXD3DSWAPCHAIN9_PRESENT *PFNVBOXWINEEXD3DSWAPCHAIN9_PRESENT;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+VBOXWINEEX_DECL(HRESULT) VBoxWineExD3DDev9CreateTexture(IDirect3DDevice9Ex *iface,
+            UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format,
+            D3DPOOL pool, IDirect3DTexture9 **texture, HANDLE *shared_handle,
+            void **pavClientMem); /* <- extension arg to pass in the client memory buffer,
+                                 *    applicable ONLY for SYSMEM textures */
+
+VBOXWINEEX_DECL(HRESULT) VBoxWineExD3DDev9CreateCubeTexture(IDirect3DDevice9Ex *iface,
+            UINT edge_length, UINT levels, DWORD usage, D3DFORMAT format,
+            D3DPOOL pool, IDirect3DCubeTexture9 **texture, HANDLE *shared_handle,
+            void **pavClientMem); /* <- extension arg to pass in the client memory buffer,
+                                 *    applicable ONLY for SYSMEM textures */
+
+VBOXWINEEX_DECL(HRESULT) VBoxWineExD3DDev9CreateVolumeTexture(IDirect3DDevice9Ex *iface,
+            UINT width, UINT height, UINT depth, UINT levels, DWORD usage, D3DFORMAT Format, D3DPOOL Pool,
+            IDirect3DVolumeTexture9 **ppVolumeTexture, HANDLE *pSharedHandle,
+            void **pavClientMem);
+
+VBOXWINEEX_DECL(HRESULT) VBoxWineExD3DDev9VolBlt(IDirect3DDevice9Ex *iface,
+                                                    IDirect3DVolume9 *pSourceVolume, IDirect3DVolume9 *pDestinationVolume,
+                                                    const struct VBOXBOX3D *pSrcBoxArg,
+                                                    const struct VBOXPOINT3D *pDstPoin3D);
+
+VBOXWINEEX_DECL(HRESULT) VBoxWineExD3DDev9VolTexBlt(IDirect3DDevice9Ex *iface,
+                                                    IDirect3DVolumeTexture9 *pSourceTexture, IDirect3DVolumeTexture9 *pDestinationTexture,
+                                                    const struct VBOXBOX3D *pSrcBoxArg,
+                                                    const struct VBOXPOINT3D *pDstPoin3D);
+
+VBOXWINEEX_DECL(HRESULT) VBoxWineExD3DDev9Flush(IDirect3DDevice9Ex *iface); /* perform glFlush */
+
+VBOXWINEEX_DECL(HRESULT) VBoxWineExD3DDev9Finish(IDirect3DDevice9Ex *iface); /* perform glFinish */
+
+VBOXWINEEX_DECL(HRESULT) VBoxWineExD3DDev9FlushToHost(IDirect3DDevice9Ex *iface); /* flash data to host */
+
+VBOXWINEEX_DECL(HRESULT) VBoxWineExD3DDev9Term(IDirect3DDevice9Ex *iface);
+
+VBOXWINEEX_DECL(HRESULT) VBoxWineExD3DSwapchain9Present(IDirect3DSwapChain9 *iface,
+                                IDirect3DSurface9 *surf); /* use the given surface as a frontbuffer content source */
+
+typedef struct VBOXWINEEX_D3DPRESENT_PARAMETERS
+{
+    D3DPRESENT_PARAMETERS Base;
+    struct VBOXUHGSMI *pHgsmi;
+} VBOXWINEEX_D3DPRESENT_PARAMETERS, *PVBOXWINEEX_D3DPRESENT_PARAMETERS;
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* #ifndef IN_VBOXLIBWINE */
+
+#endif
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/debug.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/debug.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/debug.c	(revision 46521)
@@ -0,0 +1,498 @@
+/*
+ * Management of the debugging channels
+ *
+ * Copyright 2000 Alexandre Julliard
+ *
+ * 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
+ */
+
+/*
+ * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
+ * a choice of LGPL license versions is made available with the language indicating
+ * that LGPLv2 or any later version may be used, or where a choice of which version
+ * of the LGPL is applied is otherwise unspecified.
+ */
+
+#include <windows.h>
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "wine/debug.h"
+//#include "wine/library.h"
+
+#ifdef VBOX_WITH_WDDM
+#include <VBoxDispMpLogger.h>
+#include <iprt/err.h>
+#else
+#include <iprt/log.h>
+#endif
+
+static const char * const debug_classes[] = { "fixme", "err", "warn", "trace" };
+
+#define MAX_DEBUG_OPTIONS 256
+
+typedef DECLCALLBACK(void) FNVBOXWINELOGBACKDOOR(char* pcszStr);
+typedef FNVBOXWINELOGBACKDOOR *PFNVBOXWINELOGBACKDOOR;
+static PFNVBOXWINELOGBACKDOOR vbox_log_backdoor = NULL;
+static unsigned char default_flags = (1 << __WINE_DBCL_ERR) | (1 << __WINE_DBCL_FIXME) | (1 << __WINE_DBCL_WARN);
+static int nb_debug_options = -1;
+static struct __wine_debug_channel debug_options[MAX_DEBUG_OPTIONS];
+
+static struct __wine_debug_functions funcs;
+
+static void debug_init(void);
+
+static int cmp_name( const void *p1, const void *p2 )
+{
+    const char *name = p1;
+    const struct __wine_debug_channel *chan = p2;
+    return strcmp( name, chan->name );
+}
+
+/* get the flags to use for a given channel, possibly setting them too in case of lazy init */
+unsigned char __wine_dbg_get_channel_flags( struct __wine_debug_channel *channel )
+{
+    if (nb_debug_options == -1) debug_init();
+
+    if (nb_debug_options)
+    {
+        struct __wine_debug_channel *opt = bsearch( channel->name, debug_options, nb_debug_options,
+                                                    sizeof(debug_options[0]), cmp_name );
+        if (opt) return opt->flags;
+    }
+    /* no option for this channel */
+    if (channel->flags & (1 << __WINE_DBCL_INIT)) channel->flags = default_flags;
+    return default_flags;
+}
+
+/* set the flags to use for a given channel; return 0 if the channel is not available to set */
+int __wine_dbg_set_channel_flags( struct __wine_debug_channel *channel,
+                                  unsigned char set, unsigned char clear )
+{
+    if (nb_debug_options == -1) debug_init();
+
+    if (nb_debug_options)
+    {
+        struct __wine_debug_channel *opt = bsearch( channel->name, debug_options, nb_debug_options,
+                                                    sizeof(debug_options[0]), cmp_name );
+        if (opt)
+        {
+            opt->flags = (opt->flags & ~clear) | set;
+            return 1;
+        }
+    }
+    return 0;
+}
+
+/* add a new debug option at the end of the option list */
+static void add_option( const char *name, unsigned char set, unsigned char clear )
+{
+    int min = 0, max = nb_debug_options - 1, pos, res;
+
+    if (!name[0])  /* "all" option */
+    {
+        default_flags = (default_flags & ~clear) | set;
+        return;
+    }
+    if (strlen(name) >= sizeof(debug_options[0].name)) return;
+
+    while (min <= max)
+    {
+        pos = (min + max) / 2;
+        res = strcmp( name, debug_options[pos].name );
+        if (!res)
+        {
+            debug_options[pos].flags = (debug_options[pos].flags & ~clear) | set;
+            return;
+        }
+        if (res < 0) max = pos - 1;
+        else min = pos + 1;
+    }
+    if (nb_debug_options >= MAX_DEBUG_OPTIONS) return;
+
+    pos = min;
+    if (pos < nb_debug_options) memmove( &debug_options[pos + 1], &debug_options[pos],
+                                         (nb_debug_options - pos) * sizeof(debug_options[0]) );
+    strcpy( debug_options[pos].name, name );
+    debug_options[pos].flags = (default_flags & ~clear) | set;
+    nb_debug_options++;
+}
+
+/* parse a set of debugging option specifications and add them to the option list */
+static void parse_options( const char *str )
+{
+    char *opt, *next, *options;
+    unsigned int i;
+
+    if (!(options = strdup(str))) return;
+    for (opt = options; opt; opt = next)
+    {
+        const char *p;
+        unsigned char set = 0, clear = 0;
+
+        if ((next = strchr( opt, ',' ))) *next++ = 0;
+
+        p = opt + strcspn( opt, "+-" );
+        if (!p[0]) p = opt;  /* assume it's a debug channel name */
+
+        if (p > opt)
+        {
+            for (i = 0; i < sizeof(debug_classes)/sizeof(debug_classes[0]); i++)
+            {
+                int len = strlen(debug_classes[i]);
+                if (len != (p - opt)) continue;
+                if (!memcmp( opt, debug_classes[i], len ))  /* found it */
+                {
+                    if (*p == '+') set |= 1 << i;
+                    else clear |= 1 << i;
+                    break;
+                }
+            }
+            if (i == sizeof(debug_classes)/sizeof(debug_classes[0])) /* bad class name, skip it */
+                continue;
+        }
+        else
+        {
+            if (*p == '-') clear = ~0;
+            else set = ~0;
+        }
+        if (*p == '+' || *p == '-') p++;
+        if (!p[0]) continue;
+
+        if (!strcmp( p, "all" ))
+            default_flags = (default_flags & ~clear) | set;
+        else
+            add_option( p, set, clear );
+    }
+    free( options );
+}
+
+
+/* print the usage message */
+static void debug_usage(void)
+{
+    static const char usage[] =
+        "Syntax of the WINEDEBUG variable:\n"
+        "  WINEDEBUG=[class]+xxx,[class]-yyy,...\n\n"
+        "Example: WINEDEBUG=+all,warn-heap\n"
+        "    turns on all messages except warning heap messages\n"
+        "Available message classes: err, warn, fixme, trace\n";
+    write( 2, usage, sizeof(usage) - 1 );
+    exit(1);
+}
+
+#ifndef VBOX_WITH_WDDM
+static DECLCALLBACK(void) vbox_log_backdoor_rt(char* pcszStr)
+{
+    RTLogBackdoorPrintf("%s", pcszStr);
+}
+#else
+static DECLCALLBACK(void) vbox_log_backdoor_dispmp(char* pcszStr)
+{
+    VBoxDispMpLoggerLog(pcszStr);
+}
+#endif
+static void vbox_log_v(const char *pszFormat, va_list args)
+{
+    if (vbox_log_backdoor)
+    {
+        static char buf[8092];
+        int offset = sprintf(buf, "[0x%lx.0x%lx] Wine Debug: ", GetCurrentProcessId(), GetCurrentThreadId());
+        vsprintf(buf + offset, pszFormat, args);
+        vbox_log_backdoor(buf);
+    }
+}
+
+/* initialize all options at startup */
+static void debug_init(void)
+{
+    char *wine_debug;
+
+    if (nb_debug_options != -1) return;  /* already initialized */
+    nb_debug_options = 0;
+    if ((wine_debug = getenv("WINEDEBUG")))
+    {
+        Assert(0);
+        if (!strcmp( wine_debug, "help" ))
+            debug_usage();
+        else if (getenv("WINEDEBUG_BACKDOOR"))
+        {
+#ifdef VBOX_WITH_WDDM
+            int rc = VBoxDispMpLoggerInit();
+            if (RT_SUCCESS(rc))
+                vbox_log_backdoor = vbox_log_backdoor_dispmp;
+//            else
+#else
+                vbox_log_backdoor = vbox_log_backdoor_rt;
+#endif
+        }
+        parse_options( wine_debug );
+    }
+}
+
+/* varargs wrapper for funcs.dbg_vprintf */
+int wine_dbg_printf( const char *format, ... )
+{
+    int ret;
+    va_list valist;
+
+    va_start(valist, format);
+    ret = funcs.dbg_vprintf( format, valist );
+    va_end(valist);
+    return ret;
+}
+
+/* printf with temp buffer allocation */
+const char *wine_dbg_sprintf( const char *format, ... )
+{
+    static const int max_size = 200;
+    char *ret;
+    int len;
+    va_list valist;
+
+    va_start(valist, format);
+    ret = funcs.get_temp_buffer( max_size );
+    len = vsnprintf( ret, max_size, format, valist );
+    if (len == -1 || len >= max_size) ret[max_size-1] = 0;
+    else funcs.release_temp_buffer( ret, len + 1 );
+    va_end(valist);
+    return ret;
+}
+
+
+/* varargs wrapper for funcs.dbg_vlog */
+int wine_dbg_log( enum __wine_debug_class cls, struct __wine_debug_channel *channel,
+                  const char *func, const char *format, ... )
+{
+    int ret;
+    va_list valist;
+
+    if (!(__wine_dbg_get_channel_flags( channel ) & (1 << cls))) return -1;
+
+    va_start(valist, format);
+    ret = funcs.dbg_vlog( cls, channel, func, format, valist );
+    va_end(valist);
+    return ret;
+}
+
+int interlocked_xchg_add( int *dest, int incr )
+{
+    return InterlockedExchangeAdd(dest, incr);
+}
+
+/* allocate some tmp string space */
+/* FIXME: this is not 100% thread-safe */
+static char *get_temp_buffer( size_t size )
+{
+    static char *list[32];
+    static int pos;
+    char *ret;
+    int idx;
+
+    idx = interlocked_xchg_add( &pos, 1 ) % (sizeof(list)/sizeof(list[0]));
+    if ((ret = realloc( list[idx], size ))) list[idx] = ret;
+    return ret;
+}
+
+
+/* release unused part of the buffer */
+static void release_temp_buffer( char *buffer, size_t size )
+{
+    /* don't bother doing anything */
+}
+
+
+/* default implementation of wine_dbgstr_an */
+static const char *default_dbgstr_an( const char *str, int n )
+{
+    static const char hex[16] = "0123456789abcdef";
+    char *dst, *res;
+    size_t size;
+
+    if (!((ULONG_PTR)str >> 16))
+    {
+        if (!str) return "(null)";
+        res = funcs.get_temp_buffer( 6 );
+        sprintf( res, "#%04x", LOWORD(str) );
+        return res;
+    }
+    if (n == -1) n = strlen(str);
+    if (n < 0) n = 0;
+    size = 10 + min( 300, n * 4 );
+    dst = res = funcs.get_temp_buffer( size );
+    *dst++ = '"';
+    while (n-- > 0 && dst <= res + size - 9)
+    {
+        unsigned char c = *str++;
+        switch (c)
+        {
+        case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
+        case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
+        case '\t': *dst++ = '\\'; *dst++ = 't'; break;
+        case '"':  *dst++ = '\\'; *dst++ = '"'; break;
+        case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
+        default:
+            if (c >= ' ' && c <= 126)
+                *dst++ = c;
+            else
+            {
+                *dst++ = '\\';
+                *dst++ = 'x';
+                *dst++ = hex[(c >> 4) & 0x0f];
+                *dst++ = hex[c & 0x0f];
+            }
+        }
+    }
+    *dst++ = '"';
+    if (n > 0)
+    {
+        *dst++ = '.';
+        *dst++ = '.';
+        *dst++ = '.';
+    }
+    *dst++ = 0;
+    funcs.release_temp_buffer( res, dst - res );
+    return res;
+}
+
+
+/* default implementation of wine_dbgstr_wn */
+static const char *default_dbgstr_wn( const WCHAR *str, int n )
+{
+    char *dst, *res;
+    size_t size;
+
+    if (!((ULONG_PTR)str >> 16))
+    {
+        if (!str) return "(null)";
+        res = funcs.get_temp_buffer( 6 );
+        sprintf( res, "#%04x", LOWORD(str) );
+        return res;
+    }
+    if (n == -1)
+    {
+        const WCHAR *end = str;
+        while (*end) end++;
+        n = end - str;
+    }
+    if (n < 0) n = 0;
+    size = 12 + min( 300, n * 5 );
+    dst = res = funcs.get_temp_buffer( size );
+    *dst++ = 'L';
+    *dst++ = '"';
+    while (n-- > 0 && dst <= res + size - 10)
+    {
+        WCHAR c = *str++;
+        switch (c)
+        {
+        case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
+        case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
+        case '\t': *dst++ = '\\'; *dst++ = 't'; break;
+        case '"':  *dst++ = '\\'; *dst++ = '"'; break;
+        case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
+        default:
+            if (c >= ' ' && c <= 126)
+                *dst++ = c;
+            else
+            {
+                *dst++ = '\\';
+                sprintf(dst,"%04x",c);
+                dst+=4;
+            }
+        }
+    }
+    *dst++ = '"';
+    if (n > 0)
+    {
+        *dst++ = '.';
+        *dst++ = '.';
+        *dst++ = '.';
+    }
+    *dst++ = 0;
+    funcs.release_temp_buffer( res, dst - res );
+    return res;
+}
+
+
+/* default implementation of wine_dbg_vprintf */
+static int default_dbg_vprintf( const char *format, va_list args )
+{
+    vbox_log_v(format, args);
+#ifdef DEBUG_leo
+    static FILE *output=NULL;
+    static int first_time = 1;
+
+    if (first_time)
+    {   
+        first_time = 0;
+        output = fopen( "winelog.txt", "w" );
+    }
+
+    if (output) vfprintf( output, format, args );
+#endif
+    return vfprintf( stdout, format, args );
+}
+
+
+/* default implementation of wine_dbg_vlog */
+static int default_dbg_vlog( enum __wine_debug_class cls, struct __wine_debug_channel *channel,
+                             const char *func, const char *format, va_list args )
+{
+    int ret = 0;
+
+    if (cls < sizeof(debug_classes)/sizeof(debug_classes[0]))
+        ret += wine_dbg_printf( "%s:[%#x]:%s:%s ", debug_classes[cls], GetCurrentThreadId(), channel->name, func );
+    if (format)
+        ret += funcs.dbg_vprintf( format, args );
+    return ret;
+}
+
+/* wrappers to use the function pointers */
+
+const char *wine_dbgstr_an( const char * s, int n )
+{
+    return funcs.dbgstr_an(s, n);
+}
+
+const char *wine_dbgstr_wn( const WCHAR *s, int n )
+{
+    return funcs.dbgstr_wn(s, n);
+}
+
+void __wine_dbg_set_functions( const struct __wine_debug_functions *new_funcs,
+                               struct __wine_debug_functions *old_funcs, size_t size )
+{
+    if (old_funcs) memcpy( old_funcs, &funcs, min(sizeof(funcs),size) );
+    if (new_funcs) memcpy( &funcs, new_funcs, min(sizeof(funcs),size) );
+}
+
+static struct __wine_debug_functions funcs =
+{
+    get_temp_buffer,
+    release_temp_buffer,
+    default_dbgstr_an,
+    default_dbgstr_wn,
+    default_dbg_vprintf,
+    default_dbg_vlog
+};
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/include/config.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/include/config.h	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/include/config.h	(revision 46521)
@@ -0,0 +1,1275 @@
+/* include/config.h.  Generated from config.h.in by configure.  */
+/* include/config.h.in.  Generated from configure.ac by autoheader.  */
+
+#include <stddef.h>
+
+#define __WINE_CONFIG_H
+
+/* Define to a function attribute for Microsoft hotpatch assembly prefix. */
+#define DECLSPEC_HOTPATCH /* */
+
+/* Define to the file extension for executables. */
+#define EXEEXT ".exe"
+
+/* Define to 1 if you have the <alias.h> header file. */
+/* #undef HAVE_ALIAS_H */
+
+/* Define if you have ALSA 1.x including devel headers */
+/* #undef HAVE_ALSA */
+
+/* Define to 1 if you have the <alsa/asoundlib.h> header file. */
+/* #undef HAVE_ALSA_ASOUNDLIB_H */
+
+/* Define to 1 if you have the <AL/al.h> header file. */
+/* #undef HAVE_AL_AL_H */
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H 1
+
+/* Define to 1 if you have the <arpa/nameser.h> header file. */
+/* #undef HAVE_ARPA_NAMESER_H */
+
+/* Define to 1 if you have the `asctime_r' function. */
+#define HAVE_ASCTIME_R 1
+
+/* Define to 1 if you have the <asm/types.h> header file. */
+#define HAVE_ASM_TYPES_H 1
+
+/* Define to 1 if you have the <AudioUnit/AudioUnit.h> header file. */
+/* #undef HAVE_AUDIOUNIT_AUDIOUNIT_H */
+
+/* Define to 1 if you have the <audio/audiolib.h> header file. */
+/* #undef HAVE_AUDIO_AUDIOLIB_H */
+
+/* Define to 1 if you have the <audio/soundlib.h> header file. */
+/* #undef HAVE_AUDIO_SOUNDLIB_H */
+
+/* Define to 1 if you have the <capi20.h> header file. */
+/* #undef HAVE_CAPI20_H */
+
+/* Define to 1 if you have the <Carbon/Carbon.h> header file. */
+/* #undef HAVE_CARBON_CARBON_H */
+
+/* Define to 1 if you have the `chsize' function. */
+/* #undef HAVE_CHSIZE */
+
+/* Define to 1 if you have the <CoreAudio/CoreAudio.h> header file. */
+/* #undef HAVE_COREAUDIO_COREAUDIO_H */
+
+/* Define to 1 if you have the <cups/cups.h> header file. */
+/* #undef HAVE_CUPS_CUPS_H */
+
+/* Define to 1 if you have the <curses.h> header file. */
+/* #undef HAVE_CURSES_H */
+
+/* Define if you have the daylight variable */
+/* #undef HAVE_DAYLIGHT*/
+
+/* Define to 1 if you have the <dbus/dbus.h> header file. */
+/* #undef HAVE_DBUS_DBUS_H */
+
+/* Define to 1 if you have the <direct.h> header file. */
+/* #undef HAVE_DIRECT_H */
+
+/* Define to 1 if you have the <dirent.h> header file. */
+#define HAVE_DIRENT_H 1
+
+/* Define to 1 if you have the <DiskArbitration/DiskArbitration.h> header
+   file. */
+/* #undef HAVE_DISKARBITRATION_DISKARBITRATION_H */
+
+/* Define to 1 if you have the `dladdr' function. */
+/* #undef HAVE_DLADDR */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+/* #undef HAVE_DLFCN_H*/
+
+/* Define to 1 if you have the `dlopen' function. */
+/* #undef HAVE_DLOPEN*/
+
+/* Define to 1 if you have the <elf.h> header file. */
+/* #undef HAVE_ELF_H*/
+
+/* Define to 1 if you have the `epoll_create' function. */
+/* #undef HAVE_EPOLL_CREATE */
+
+/* Define if you have EsounD sound server */
+/* #undef HAVE_ESD */
+
+/* Define to 1 if you have the `ffs' function. */
+#define HAVE_FFS 1
+
+/* Define to 1 if you have the `finite' function. */
+#define HAVE_FINITE 1
+
+/* Define to 1 if you have the <float.h> header file. */
+#define HAVE_FLOAT_H 1
+
+/* Define to 1 if you have the `fnmatch' function. */
+#define HAVE_FNMATCH 1
+
+/* Define to 1 if you have the <fnmatch.h> header file. */
+#define HAVE_FNMATCH_H 1
+
+/* Define to 1 if you have the <fontconfig/fontconfig.h> header file. */
+/* #undef HAVE_FONTCONFIG_FONTCONFIG_H */
+
+/* Define to 1 if you have the `fork' function. */
+#define HAVE_FORK 1
+
+/* Define to 1 if you have the `fpclass' function. */
+/* #undef HAVE_FPCLASS */
+
+/* Define if FreeType 2 is installed */
+/* #undef HAVE_FREETYPE */
+
+/* Define to 1 if you have the <freetype/freetype.h> header file. */
+/* #undef HAVE_FREETYPE_FREETYPE_H */
+
+/* Define to 1 if you have the <freetype/ftglyph.h> header file. */
+/* #undef HAVE_FREETYPE_FTGLYPH_H */
+
+/* Define to 1 if you have the <freetype/ftlcdfil.h> header file. */
+/* #undef HAVE_FREETYPE_FTLCDFIL_H */
+
+/* Define to 1 if you have the <freetype/ftmodapi.h> header file. */
+/* #undef HAVE_FREETYPE_FTMODAPI_H */
+
+/* Define to 1 if you have the <freetype/ftoutln.h> header file. */
+/* #undef HAVE_FREETYPE_FTOUTLN_H */
+
+/* Define to 1 if you have the <freetype/ftsnames.h> header file. */
+/* #undef HAVE_FREETYPE_FTSNAMES_H */
+
+/* Define if you have the <freetype/fttrigon.h> header file. */
+/* #undef HAVE_FREETYPE_FTTRIGON_H */
+
+/* Define to 1 if you have the <freetype/fttypes.h> header file. */
+/* #undef HAVE_FREETYPE_FTTYPES_H */
+
+/* Define to 1 if you have the <freetype/ftwinfnt.h> header file. */
+/* #undef HAVE_FREETYPE_FTWINFNT_H */
+
+/* Define to 1 if you have the <freetype/internal/sfnt.h> header file. */
+/* #undef HAVE_FREETYPE_INTERNAL_SFNT_H */
+
+/* Define to 1 if you have the <freetype/ttnameid.h> header file. */
+/* #undef HAVE_FREETYPE_TTNAMEID_H */
+
+/* Define to 1 if you have the <freetype/tttables.h> header file. */
+/* #undef HAVE_FREETYPE_TTTABLES_H */
+
+/* Define to 1 if the system has the type `fsblkcnt_t'. */
+#define HAVE_FSBLKCNT_T 1
+
+/* Define to 1 if the system has the type `fsfilcnt_t'. */
+#define HAVE_FSFILCNT_T 1
+
+/* Define to 1 if you have the `fstatfs' function. */
+#define HAVE_FSTATFS 1
+
+/* Define to 1 if you have the `fstatvfs' function. */
+#define HAVE_FSTATVFS 1
+
+/* Define to 1 if you have the <ft2build.h> header file. */
+/* #undef HAVE_FT2BUILD_H */
+
+/* Define to 1 if you have the `ftruncate' function. */
+#define HAVE_FTRUNCATE 1
+
+/* Define to 1 if you have the `FT_Load_Sfnt_Table' function. */
+/* #undef HAVE_FT_LOAD_SFNT_TABLE */
+
+/* Define to 1 if the system has the type `FT_TrueTypeEngineType'. */
+/* #undef HAVE_FT_TRUETYPEENGINETYPE */
+
+/* Define to 1 if you have the `futimes' function. */
+#define HAVE_FUTIMES 1
+
+/* Define to 1 if you have the `futimesat' function. */
+/* #undef HAVE_FUTIMESAT */
+
+/* Define to 1 if you have the `getaddrinfo' function. */
+/* #undef HAVE_GETADDRINFO */
+
+/* Define to 1 if you have the `getdirentries' function. */
+/* #undef HAVE_GETDIRENTRIES */
+
+/* Define to 1 if you have the `getnameinfo' function. */
+/* #undef HAVE_GETNAMEINFO */
+
+/* Define to 1 if you have the `getnetbyname' function. */
+/* #undef HAVE_GETNETBYNAME */
+
+/* Define to 1 if you have the <getopt.h> header file. */
+#define HAVE_GETOPT_H 1
+
+/* Define to 1 if you have the `getopt_long' function. */
+#define HAVE_GETOPT_LONG 1
+
+/* Define to 1 if you have the `getpagesize' function. */
+/* #undef HAVE_GETPAGESIZE */
+
+/* Define to 1 if you have the `getprotobyname' function. */
+#define HAVE_GETPROTOBYNAME 1
+
+/* Define to 1 if you have the `getprotobynumber' function. */
+#define HAVE_GETPROTOBYNUMBER 1
+
+/* Define to 1 if you have the `getpwuid' function. */
+/* #undef HAVE_GETPWUID */
+
+/* Define to 1 if you have the `getservbyport' function. */
+#define HAVE_GETSERVBYPORT 1
+
+/* Define to 1 if you have the `gettid' function. */
+/* #undef HAVE_GETTID */
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define to 1 if you have the `getuid' function. */
+/* #undef HAVE_GETUID */
+
+/* Define to 1 if you have the <GL/glu.h> header file. */
+/* #undef HAVE_GL_GLU_H */
+
+/* Define to 1 if you have the <GL/glx.h> header file. */
+/* #undef HAVE_GL_GLX_H */
+
+/* Define to 1 if you have the <GL/gl.h> header file. */
+/* #undef HAVE_GL_GL_H */
+
+/* Define if we have libgphoto2 development environment */
+/* #undef HAVE_GPHOTO2 */
+
+/* Define to 1 if you have the <grp.h> header file. */
+/* #undef HAVE_GRP_H */
+
+/* Define to 1 if you have the <gsm/gsm.h> header file. */
+/* #undef HAVE_GSM_GSM_H */
+
+/* Define to 1 if you have the <gsm.h> header file. */
+/* #undef HAVE_GSM_H */
+
+/* Define to 1 if you have the <hal/libhal.h> header file. */
+/* #undef HAVE_HAL_LIBHAL_H */
+
+/* Define to 1 if you have the <ieeefp.h> header file. */
+#define HAVE_IEEEFP_H 1
+
+/* Define to 1 if you have the <inet/mib2.h> header file. */
+/* #undef HAVE_INET_MIB2_H */
+
+/* Define to 1 if you have the `inet_network' function. */
+#define HAVE_INET_NETWORK 1
+
+/* Define to 1 if you have the `inet_ntop' function. */
+#define HAVE_INET_NTOP 1
+
+/* Define to 1 if you have the `inet_pton' function. */
+#define HAVE_INET_PTON 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `IOHIDManagerCreate' function. */
+/* #undef HAVE_IOHIDMANAGERCREATE */
+
+/* Define to 1 if you have the <IOKit/hid/IOHIDLib.h> header file. */
+/* #undef HAVE_IOKIT_HID_IOHIDLIB_H */
+
+/* Define to 1 if you have the <IOKit/IOKitLib.h> header file. */
+/* #undef HAVE_IOKIT_IOKITLIB_H */
+
+/* Define to 1 if you have the <io.h> header file. */
+#define HAVE_IO_H 1
+
+/* Define to 1 if you have the `isinf' function. */
+/* #undef HAVE_ISINF */
+
+/* Define to 1 if you have the `isnan' function. */
+/* #undef HAVE_ISNAN */
+
+/* Define to 1 if you have the <jack/jack.h> header file. */
+/* #undef HAVE_JACK_JACK_H */
+
+/* Define to 1 if you have the <jpeglib.h> header file. */
+/* #undef HAVE_JPEGLIB_H */
+
+/* Define to 1 if you have the `kqueue' function. */
+/* #undef HAVE_KQUEUE */
+
+/* Define to 1 if you have the <kstat.h> header file. */
+/* #undef HAVE_KSTAT_H */
+
+/* Define to 1 if you have the <lber.h> header file. */
+/* #undef HAVE_LBER_H */
+
+/* Define if you have the LittleCMS development environment */
+/* #undef HAVE_LCMS */
+
+/* Define to 1 if you have the <lcms.h> header file. */
+/* #undef HAVE_LCMS_H */
+
+/* Define to 1 if you have the <lcms/lcms.h> header file. */
+/* #undef HAVE_LCMS_LCMS_H */
+
+/* Define if you have the OpenLDAP development environment */
+/* #undef HAVE_LDAP */
+
+/* Define to 1 if you have the `ldap_count_references' function. */
+/* #undef HAVE_LDAP_COUNT_REFERENCES */
+
+/* Define to 1 if you have the `ldap_first_reference' function. */
+/* #undef HAVE_LDAP_FIRST_REFERENCE */
+
+/* Define to 1 if you have the <ldap.h> header file. */
+/* #undef HAVE_LDAP_H */
+
+/* Define to 1 if you have the `ldap_next_reference' function. */
+/* #undef HAVE_LDAP_NEXT_REFERENCE */
+
+/* Define to 1 if you have the `ldap_parse_reference' function. */
+/* #undef HAVE_LDAP_PARSE_REFERENCE */
+
+/* Define to 1 if you have the `ldap_parse_sortresponse_control' function. */
+/* #undef HAVE_LDAP_PARSE_SORTRESPONSE_CONTROL */
+
+/* Define to 1 if you have the `ldap_parse_sort_control' function. */
+/* #undef HAVE_LDAP_PARSE_SORT_CONTROL */
+
+/* Define to 1 if you have the `ldap_parse_vlvresponse_control' function. */
+/* #undef HAVE_LDAP_PARSE_VLVRESPONSE_CONTROL */
+
+/* Define to 1 if you have the `ldap_parse_vlv_control' function. */
+/* #undef HAVE_LDAP_PARSE_VLV_CONTROL */
+
+/* Define if you have libaudioIO */
+/* #undef HAVE_LIBAUDIOIO */
+
+/* Define to 1 if you have the <libaudioio.h> header file. */
+/* #undef HAVE_LIBAUDIOIO_H */
+
+/* Define to 1 if you have the `i386' library (-li386). */
+/* #undef HAVE_LIBI386 */
+
+/* Define to 1 if you have the `kstat' library (-lkstat). */
+/* #undef HAVE_LIBKSTAT */
+
+/* Define to 1 if you have the `ossaudio' library (-lossaudio). */
+/* #undef HAVE_LIBOSSAUDIO */
+
+/* Define if you have the libxml2 library */
+/* #undef HAVE_LIBXML2 */
+
+/* Define to 1 if you have the <libxml/parser.h> header file. */
+/* #undef HAVE_LIBXML_PARSER_H */
+
+/* Define if you have the X Shape extension */
+/* #undef HAVE_LIBXSHAPE */
+
+/* Define to 1 if you have the <libxslt/pattern.h> header file. */
+/* #undef HAVE_LIBXSLT_PATTERN_H */
+
+/* Define to 1 if you have the <libxslt/transform.h> header file. */
+/* #undef HAVE_LIBXSLT_TRANSFORM_H */
+
+/* Define if you have the X Shm extension */
+/* #undef HAVE_LIBXXSHM */
+
+/* Define to 1 if you have the <link.h> header file. */
+/* #undef HAVE_LINK_H */
+
+/* Define if <linux/joystick.h> defines the Linux 2.2 joystick API */
+/* #undef HAVE_LINUX_22_JOYSTICK_API */
+
+/* Define to 1 if you have the <linux/capi.h> header file. */
+/* #undef HAVE_LINUX_CAPI_H */
+
+/* Define to 1 if you have the <linux/cdrom.h> header file. */
+/* #undef HAVE_LINUX_CDROM_H */
+
+/* Define to 1 if you have the <linux/compiler.h> header file. */
+/* #undef HAVE_LINUX_COMPILER_H */
+
+/* Define if Linux-style gethostbyname_r and gethostbyaddr_r are available */
+/* #undef HAVE_LINUX_GETHOSTBYNAME_R_6 */
+
+/* Define to 1 if you have the <linux/hdreg.h> header file. */
+/* #undef HAVE_LINUX_HDREG_H */
+
+/* Define to 1 if you have the <linux/input.h> header file. */
+/* #undef HAVE_LINUX_INPUT_H */
+
+/* Define to 1 if you have the <linux/ioctl.h> header file. */
+/* #undef HAVE_LINUX_IOCTL_H */
+
+/* Define to 1 if you have the <linux/ipx.h> header file. */
+/* #undef HAVE_LINUX_IPX_H */
+
+/* Define to 1 if you have the <linux/irda.h> header file. */
+/* #undef HAVE_LINUX_IRDA_H */
+
+/* Define to 1 if you have the <linux/joystick.h> header file. */
+/* #undef HAVE_LINUX_JOYSTICK_H */
+
+/* Define to 1 if you have the <linux/major.h> header file. */
+/* #undef HAVE_LINUX_MAJOR_H */
+
+/* Define to 1 if you have the <linux/param.h> header file. */
+/* #undef HAVE_LINUX_PARAM_H */
+
+/* Define to 1 if you have the <linux/serial.h> header file. */
+/* #undef HAVE_LINUX_SERIAL_H */
+
+/* Define to 1 if you have the <linux/types.h> header file. */
+/* #undef HAVE_LINUX_TYPES_H */
+
+/* Define to 1 if you have the <linux/ucdrom.h> header file. */
+/* #undef HAVE_LINUX_UCDROM_H */
+
+/* Define to 1 if you have the <linux/videodev.h> header file. */
+/* #undef HAVE_LINUX_VIDEODEV_H */
+
+/* Define to 1 if the system has the type `long long'. */
+#define HAVE_LONG_LONG 1
+
+/* Define to 1 if you have the `lstat' function. */
+#define HAVE_LSTAT 1
+
+/* Define to 1 if you have the <machine/cpu.h> header file. */
+/* #undef HAVE_MACHINE_CPU_H */
+
+/* Define to 1 if you have the <machine/limits.h> header file. */
+/* #undef HAVE_MACHINE_LIMITS_H */
+
+/* Define to 1 if you have the <machine/soundcard.h> header file. */
+/* #undef HAVE_MACHINE_SOUNDCARD_H */
+
+/* Define to 1 if you have the <mach/machine.h> header file. */
+/* #undef HAVE_MACH_MACHINE_H */
+
+/* Define to 1 if you have the <mach/mach.h> header file. */
+/* #undef HAVE_MACH_MACH_H */
+
+/* Define to 1 if you have the <mach-o/dyld_images.h> header file. */
+/* #undef HAVE_MACH_O_DYLD_IMAGES_H */
+
+/* Define to 1 if you have the <mach-o/nlist.h> header file. */
+/* #undef HAVE_MACH_O_NLIST_H */
+
+/* Define to 1 if you have the `memmove' function. */
+#define HAVE_MEMMOVE 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `mmap' function. */
+/* #undef HAVE_MMAP */
+
+/* Define to 1 if you have the <mntent.h> header file. */
+#define HAVE_MNTENT_H 1
+
+/* Define to 1 if the system has the type `mode_t'. */
+#define HAVE_MODE_T 1
+
+/* Define to 1 if you have the `mousemask' function. */
+/* #undef HAVE_MOUSEMASK */
+
+/* Define to 1 if you have the <mpg123.h> header file. */
+/* #undef HAVE_MPG123_H */
+
+/* Define if you have NAS including devel headers */
+/* #undef HAVE_NAS */
+
+/* Define to 1 if you have the <ncurses.h> header file. */
+/* #undef HAVE_NCURSES_H */
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define to 1 if you have the <netinet/icmp_var.h> header file. */
+/* #undef HAVE_NETINET_ICMP_VAR_H */
+
+/* Define to 1 if you have the <netinet/if_ether.h> header file. */
+/* #undef HAVE_NETINET_IF_ETHER_H */
+
+/* Define to 1 if you have the <netinet/if_inarp.h> header file. */
+/* #undef HAVE_NETINET_IF_INARP_H */
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+/* #undef HAVE_NETINET_IN_H */
+
+/* Define to 1 if you have the <netinet/in_pcb.h> header file. */
+/* #undef HAVE_NETINET_IN_PCB_H */
+
+/* Define to 1 if you have the <netinet/in_systm.h> header file. */
+/* #undef HAVE_NETINET_IN_SYSTM_H */
+
+/* Define to 1 if you have the <netinet/ip.h> header file. */
+/* #undef HAVE_NETINET_IP_H */
+
+/* Define to 1 if you have the <netinet/ip_icmp.h> header file. */
+/* #undef HAVE_NETINET_IP_ICMP_H */
+
+/* Define to 1 if you have the <netinet/ip_var.h> header file. */
+/* #undef HAVE_NETINET_IP_VAR_H */
+
+/* Define to 1 if you have the <netinet/tcp_fsm.h> header file. */
+/* #undef HAVE_NETINET_TCP_FSM_H */
+
+/* Define to 1 if you have the <netinet/tcp.h> header file. */
+/* #undef HAVE_NETINET_TCP_H */
+
+/* Define to 1 if you have the <netinet/tcp_timer.h> header file. */
+/* #undef HAVE_NETINET_TCP_TIMER_H */
+
+/* Define to 1 if you have the <netinet/tcp_var.h> header file. */
+/* #undef HAVE_NETINET_TCP_VAR_H */
+
+/* Define to 1 if you have the <netinet/udp.h> header file. */
+/* #undef HAVE_NETINET_UDP_H */
+
+/* Define to 1 if you have the <netinet/udp_var.h> header file. */
+/* #undef HAVE_NETINET_UDP_VAR_H */
+
+/* Define to 1 if you have the <netipx/ipx.h> header file. */
+/* #undef HAVE_NETIPX_IPX_H */
+
+/* Define to 1 if you have the <net/if_arp.h> header file. */
+/* #undef HAVE_NET_IF_ARP_H */
+
+/* Define to 1 if you have the <net/if_dl.h> header file. */
+/* #undef HAVE_NET_IF_DL_H */
+
+/* Define to 1 if you have the <net/if.h> header file. */
+/* #undef HAVE_NET_IF_H */
+
+/* Define to 1 if you have the <net/if_types.h> header file. */
+/* #undef HAVE_NET_IF_TYPES_H */
+
+/* Define to 1 if you have the <net/route.h> header file. */
+/* #undef HAVE_NET_ROUTE_H */
+
+/* Define to 1 if `_msg_ptr' is a member of `ns_msg'. */
+/* #undef HAVE_NS_MSG__MSG_PTR */
+
+/* Define to 1 if the system has the type `off_t'. */
+#define HAVE_OFF_T 1
+
+/* Define if mkdir takes only one argument */
+/* #undef HAVE_ONE_ARG_MKDIR */
+
+/* Define to 1 if you have the <OpenAL/al.h> header file. */
+/* #undef HAVE_OPENAL_AL_H */
+
+/* Define if OpenGL is present on the system */
+/* #undef HAVE_OPENGL */
+
+/* Define to 1 if you have the <openssl/err.h> header file. */
+/* #undef HAVE_OPENSSL_ERR_H */
+
+/* Define to 1 if you have the <openssl/ssl.h> header file. */
+/* #undef HAVE_OPENSSL_SSL_H */
+
+/* Define to 1 if you have the `pclose' function. */
+#define HAVE_PCLOSE 1
+
+/* Define to 1 if the system has the type `pid_t'. */
+/* #undef HAVE_PID_T */
+
+/* Define to 1 if you have the `pipe2' function. */
+/* #undef HAVE_PIPE2 */
+
+/* Define to 1 if you have the <png.h> header file. */
+/* #undef HAVE_PNG_H */
+
+/* Define to 1 if you have the `poll' function. */
+#define HAVE_POLL 1
+
+/* Define to 1 if you have the <poll.h> header file. */
+#define HAVE_POLL_H 1
+
+/* Define to 1 if you have the `popen' function. */
+#define HAVE_POPEN 1
+
+/* Define to 1 if you have the `port_create' function. */
+/* #undef HAVE_PORT_CREATE */
+
+/* Define to 1 if you have the <port.h> header file. */
+/* #undef HAVE_PORT_H */
+
+/* Define if we can use ppdev.h for parallel port access */
+/* #undef HAVE_PPDEV */
+
+/* Define to 1 if you have the `prctl' function. */
+/* #undef HAVE_PRCTL */
+
+/* Define to 1 if you have the `pread' function. */
+#define HAVE_PREAD 1
+
+/* Define to 1 if you have the <process.h> header file. */
+#define HAVE_PROCESS_H 1
+
+/* Define to 1 if you have the `pthread_attr_get_np' function. */
+/* #undef HAVE_PTHREAD_ATTR_GET_NP */
+
+/* Define to 1 if you have the `pthread_getattr_np' function. */
+/* #undef HAVE_PTHREAD_GETATTR_NP */
+
+/* Define to 1 if you have the `pthread_get_stackaddr_np' function. */
+/* #undef HAVE_PTHREAD_GET_STACKADDR_NP */
+
+/* Define to 1 if you have the `pthread_get_stacksize_np' function. */
+/* #undef HAVE_PTHREAD_GET_STACKSIZE_NP */
+
+/* Define to 1 if you have the <pthread.h> header file. */
+/* #undef HAVE_PTHREAD_H */
+
+/* Define to 1 if you have the <pthread_np.h> header file. */
+/* #undef HAVE_PTHREAD_NP_H */
+
+/* Define to 1 if you have the <pwd.h> header file. */
+/* #undef HAVE_PWD_H */
+
+/* Define to 1 if you have the `pwrite' function. */
+#define HAVE_PWRITE 1
+
+/* Define to 1 if you have the `readdir' function. */
+#define HAVE_READDIR 1
+
+/* Define to 1 if you have the `readlink' function. */
+#define HAVE_READLINK 1
+
+/* Define to 1 if you have the <regex.h> header file. */
+#define HAVE_REGEX_H 1
+
+/* Define to 1 if the system has the type `request_sense'. */
+/* #undef HAVE_REQUEST_SENSE */
+
+/* Define if you have the resolver library and header */
+/* #undef HAVE_RESOLV */
+
+/* Define to 1 if you have the <resolv.h> header file. */
+/* #undef HAVE_RESOLV_H */
+
+/* Define to 1 if you have the <sched.h> header file. */
+#define HAVE_SCHED_H 1
+
+/* Define to 1 if you have the `sched_setaffinity' function. */
+/* #undef HAVE_SCHED_SETAFFINITY */
+
+/* Define to 1 if you have the `sched_yield' function. */
+#define HAVE_SCHED_YIELD 1
+
+/* Define to 1 if `cmd' is a member of `scsireq_t'. */
+/* #undef HAVE_SCSIREQ_T_CMD */
+
+/* Define to 1 if you have the <scsi/scsi.h> header file. */
+/* #undef HAVE_SCSI_SCSI_H */
+
+/* Define to 1 if you have the <scsi/scsi_ioctl.h> header file. */
+/* #undef HAVE_SCSI_SCSI_IOCTL_H */
+
+/* Define to 1 if you have the <scsi/sg.h> header file. */
+/* #undef HAVE_SCSI_SG_H */
+
+/* Define to 1 if you have the `select' function. */
+#define HAVE_SELECT 1
+
+/* Define to 1 if you have the `sendmsg' function. */
+#define HAVE_SENDMSG 1
+
+/* Define to 1 if you have the `setproctitle' function. */
+/* #undef HAVE_SETPROCTITLE */
+
+/* Define to 1 if you have the `setrlimit' function. */
+/* #undef HAVE_SETRLIMIT */
+
+/* Define to 1 if you have the `settimeofday' function. */
+#define HAVE_SETTIMEOFDAY 1
+
+/* Define to 1 if `interface_id' is a member of `sg_io_hdr_t'. */
+/* #undef HAVE_SG_IO_HDR_T_INTERFACE_ID */
+
+/* Define if sigaddset is supported */
+#define HAVE_SIGADDSET 1
+
+/* Define to 1 if you have the `sigaltstack' function. */
+/* #undef HAVE_SIGALTSTACK */
+
+/* Define to 1 if `si_fd' is a member of `siginfo_t'. */
+/* #undef HAVE_SIGINFO_T_SI_FD */
+
+/* Define to 1 if you have the `sigprocmask' function. */
+#define HAVE_SIGPROCMASK 1
+
+/* Define to 1 if the system has the type `sigset_t'. */
+#define HAVE_SIGSET_T 1
+
+/* Define to 1 if the system has the type `size_t'. */
+#define HAVE_SIZE_T 1
+
+/* Define to 1 if you have the `snprintf' function. */
+/* #undef HAVE_SNPRINTF */
+
+/* Define to 1 if you have the `socketpair' function. */
+#define HAVE_SOCKETPAIR 1
+
+/* Define to 1 if you have the <soundcard.h> header file. */
+/* #undef HAVE_SOUNDCARD_H */
+
+/* Define to 1 if you have the `spawnvp' function. */
+#define HAVE_SPAWNVP 1
+
+/* Define to 1 if the system has the type `ssize_t'. */
+#define HAVE_SSIZE_T 1
+
+/* Define to 1 if you have the `statfs' function. */
+#define HAVE_STATFS 1
+
+/* Define to 1 if you have the `statvfs' function. */
+#define HAVE_STATVFS 1
+
+/* Define to 1 if you have the <stdbool.h> header file. */
+#define HAVE_STDBOOL_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+/* #undef HAVE_STDINT_H */
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strncasecmp' function. */
+#define HAVE_STRNCASECMP 1
+
+/* Define to 1 if you have the <stropts.h> header file. */
+/* #undef HAVE_STROPTS_H */
+
+/* Define to 1 if you have the `strtold' function. */
+/* #undef HAVE_STRTOLD */
+
+/* Define to 1 if you have the `strtoll' function. */
+#define HAVE_STRTOLL 1
+
+/* Define to 1 if you have the `strtoull' function. */
+#define HAVE_STRTOULL 1
+
+/* Define to 1 if `direction' is a member of `struct ff_effect'. */
+/* #undef HAVE_STRUCT_FF_EFFECT_DIRECTION */
+
+/* Define to 1 if `icps_outhist' is a member of `struct icmpstat'. */
+/* #undef HAVE_STRUCT_ICMPSTAT_ICPS_OUTHIST */
+
+/* Define to 1 if `msg_accrights' is a member of `struct msghdr'. */
+/* #undef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
+
+/* Define to 1 if `mt_blkno' is a member of `struct mtget'. */
+#define HAVE_STRUCT_MTGET_MT_BLKNO 1
+
+/* Define to 1 if `mt_blksiz' is a member of `struct mtget'. */
+/* #undef HAVE_STRUCT_MTGET_MT_BLKSIZ */
+
+/* Define to 1 if `mt_gstat' is a member of `struct mtget'. */
+#define HAVE_STRUCT_MTGET_MT_GSTAT 1
+
+/* Define to 1 if `name' is a member of `struct option'. */
+#define HAVE_STRUCT_OPTION_NAME 1
+
+/* Define to 1 if `sin6_scope_id' is a member of `struct sockaddr_in6'. */
+/* #undef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID */
+
+/* Define to 1 if `sa_len' is a member of `struct sockaddr'. */
+/* #undef HAVE_STRUCT_SOCKADDR_SA_LEN */
+
+/* Define to 1 if `sun_len' is a member of `struct sockaddr_un'. */
+/* #undef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN */
+
+/* Define to 1 if `f_bavail' is a member of `struct statfs'. */
+#define HAVE_STRUCT_STATFS_F_BAVAIL 1
+
+/* Define to 1 if `f_bfree' is a member of `struct statfs'. */
+#define HAVE_STRUCT_STATFS_F_BFREE 1
+
+/* Define to 1 if `f_favail' is a member of `struct statfs'. */
+/* #undef HAVE_STRUCT_STATFS_F_FAVAIL */
+
+/* Define to 1 if `f_ffree' is a member of `struct statfs'. */
+#define HAVE_STRUCT_STATFS_F_FFREE 1
+
+/* Define to 1 if `f_frsize' is a member of `struct statfs'. */
+/* #undef HAVE_STRUCT_STATFS_F_FRSIZE */
+
+/* Define to 1 if `f_namelen' is a member of `struct statfs'. */
+#define HAVE_STRUCT_STATFS_F_NAMELEN 1
+
+/* Define to 1 if `f_blocks' is a member of `struct statvfs'. */
+#define HAVE_STRUCT_STATVFS_F_BLOCKS 1
+
+/* Define to 1 if `st_atim' is a member of `struct stat'. */
+#define HAVE_STRUCT_STAT_ST_ATIM 1
+
+/* Define to 1 if `st_blocks' is a member of `struct stat'. */
+#define HAVE_STRUCT_STAT_ST_BLOCKS 1
+
+/* Define to 1 if `st_ctim' is a member of `struct stat'. */
+#define HAVE_STRUCT_STAT_ST_CTIM 1
+
+/* Define to 1 if `st_mtim' is a member of `struct stat'. */
+#define HAVE_STRUCT_STAT_ST_MTIM 1
+
+/* Define to 1 if the system has the type `struct xinpgen'. */
+/* #undef HAVE_STRUCT_XINPGEN */
+
+/* Define to 1 if you have the `symlink' function. */
+/* #undef HAVE_SYMLINK */
+
+/* Define to 1 if you have the <syscall.h> header file. */
+/* #undef HAVE_SYSCALL_H */
+
+/* Define to 1 if you have the <sys/asoundlib.h> header file. */
+/* #undef HAVE_SYS_ASOUNDLIB_H */
+
+/* Define to 1 if you have the <sys/cdio.h> header file. */
+/* #undef HAVE_SYS_CDIO_H */
+
+/* Define to 1 if you have the <sys/elf32.h> header file. */
+#define HAVE_SYS_ELF32_H 1
+
+/* Define to 1 if you have the <sys/epoll.h> header file. */
+/* #undef HAVE_SYS_EPOLL_H */
+
+/* Define to 1 if you have the <sys/errno.h> header file. */
+#define HAVE_SYS_ERRNO_H 1
+
+/* Define to 1 if you have the <sys/event.h> header file. */
+/* #undef HAVE_SYS_EVENT_H */
+
+/* Define to 1 if you have the <sys/exec_elf.h> header file. */
+/* #undef HAVE_SYS_EXEC_ELF_H */
+
+/* Define to 1 if you have the <sys/filio.h> header file. */
+/* #undef HAVE_SYS_FILIO_H */
+
+/* Define to 1 if you have the <sys/inotify.h> header file. */
+/* #undef HAVE_SYS_INOTIFY_H */
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define to 1 if you have the <sys/ipc.h> header file. */
+#define HAVE_SYS_IPC_H 1
+
+/* Define to 1 if you have the <sys/limits.h> header file. */
+/* #undef HAVE_SYS_LIMITS_H */
+
+/* Define to 1 if you have the <sys/link.h> header file. */
+/* #undef HAVE_SYS_LINK_H */
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+/* #undef HAVE_SYS_MMAN_H */
+
+/* Define to 1 if you have the <sys/modem.h> header file. */
+/* #undef HAVE_SYS_MODEM_H */
+
+/* Define to 1 if you have the <sys/mount.h> header file. */
+#define HAVE_SYS_MOUNT_H 1
+
+/* Define to 1 if you have the <sys/msg.h> header file. */
+#define HAVE_SYS_MSG_H 1
+
+/* Define to 1 if you have the <sys/mtio.h> header file. */
+#define HAVE_SYS_MTIO_H 1
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/poll.h> header file. */
+#define HAVE_SYS_POLL_H 1
+
+/* Define to 1 if you have the <sys/prctl.h> header file. */
+/* #undef HAVE_SYS_PRCTL_H */
+
+/* Define to 1 if you have the <sys/protosw.h> header file. */
+/* #undef HAVE_SYS_PROTOSW_H */
+
+/* Define to 1 if you have the <sys/ptrace.h> header file. */
+/* #undef HAVE_SYS_PTRACE_H */
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+/* #undef HAVE_SYS_RESOURCE_H */
+
+/* Define to 1 if you have the <sys/scsiio.h> header file. */
+/* #undef HAVE_SYS_SCSIIO_H */
+
+/* Define to 1 if you have the <sys/shm.h> header file. */
+/* #undef HAVE_SYS_SHM_H */
+
+/* Define to 1 if you have the <sys/signal.h> header file. */
+/* #undef HAVE_SYS_SIGNAL_H */
+
+/* Define to 1 if you have the <sys/socketvar.h> header file. */
+/* #undef HAVE_SYS_SOCKETVAR_H */
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+/* #undef HAVE_SYS_SOCKIO_H */
+
+/* Define to 1 if you have the <sys/soundcard.h> header file. */
+#define HAVE_SYS_SOUNDCARD_H 1
+
+/* Define to 1 if you have the <sys/statfs.h> header file. */
+#define HAVE_SYS_STATFS_H 1
+
+/* Define to 1 if you have the <sys/statvfs.h> header file. */
+#define HAVE_SYS_STATVFS_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/strtio.h> header file. */
+/* #undef HAVE_SYS_STRTIO_H */
+
+/* Define to 1 if you have the <sys/syscall.h> header file. */
+/* #undef HAVE_SYS_SYSCALL_H */
+
+/* Define to 1 if you have the <sys/sysctl.h> header file. */
+/* #undef HAVE_SYS_SYSCTL_H */
+
+/* Define to 1 if you have the <sys/thr.h> header file. */
+/* #undef HAVE_SYS_THR_H */
+
+/* Define to 1 if you have the <sys/tihdr.h> header file. */
+/* #undef HAVE_SYS_TIHDR_H */
+
+/* Define to 1 if you have the <sys/timeout.h> header file. */
+/* #undef HAVE_SYS_TIMEOUT_H */
+
+/* Define to 1 if you have the <sys/times.h> header file. */
+#define HAVE_SYS_TIMES_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/uio.h> header file. */
+#define HAVE_SYS_UIO_H 1
+
+/* Define to 1 if you have the <sys/un.h> header file. */
+#define HAVE_SYS_UN_H 1
+
+/* Define to 1 if you have the <sys/user.h> header file. */
+/* #undef HAVE_SYS_USER_H */
+
+/* Define to 1 if you have the <sys/utsname.h> header file. */
+/* #undef HAVE_SYS_UTSNAME_H */
+
+/* Define to 1 if you have the <sys/vfs.h> header file. */
+#define HAVE_SYS_VFS_H 1
+
+/* Define to 1 if you have the <sys/vm86.h> header file. */
+/* #undef HAVE_SYS_VM86_H */
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to 1 if you have the `tcgetattr' function. */
+#define HAVE_TCGETATTR 1
+
+/* Define to 1 if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define to 1 if you have the `thr_kill2' function. */
+/* #undef HAVE_THR_KILL2 */
+
+/* Define to 1 if you have the `timegm' function. */
+#define HAVE_TIMEGM 1
+
+/* Define if you have the timezone variable */
+#define HAVE_TIMEZONE 1
+
+/* Define to 1 if you have the <ucontext.h> header file. */
+/* #undef HAVE_UCONTEXT_H */
+
+/* Define to 1 if you have the <unistd.h> header file. */
+/* #undef HAVE_UNISTD_H */
+
+/* Define to 1 if you have the `usleep' function. */
+#define HAVE_USLEEP 1
+
+/* Define to 1 if you have the <utime.h> header file. */
+#define HAVE_UTIME_H 1
+
+/* Define to 1 if you have the <valgrind/memcheck.h> header file. */
+/* #undef HAVE_VALGRIND_MEMCHECK_H */
+
+/* Define to 1 if you have the <valgrind/valgrind.h> header file. */
+/* #undef HAVE_VALGRIND_VALGRIND_H */
+
+/* Define to 1 if you have the `vsnprintf' function. */
+/* #undef HAVE_VSNPRINTF */
+
+/* Define to 1 if you have the `wait4' function. */
+#define HAVE_WAIT4 1
+
+/* Define to 1 if you have the `waitpid' function. */
+#define HAVE_WAITPID 1
+
+/* Define to 1 if you have the <X11/extensions/shape.h> header file. */
+/* #undef HAVE_X11_EXTENSIONS_SHAPE_H */
+
+/* Define to 1 if you have the <X11/extensions/Xcomposite.h> header file. */
+/* #undef HAVE_X11_EXTENSIONS_XCOMPOSITE_H */
+
+/* Define to 1 if you have the <X11/extensions/xf86vmode.h> header file. */
+/* #undef HAVE_X11_EXTENSIONS_XF86VMODE_H */
+
+/* Define to 1 if you have the <X11/extensions/xf86vmproto.h> header file. */
+/* #undef HAVE_X11_EXTENSIONS_XF86VMPROTO_H */
+
+/* Define to 1 if you have the <X11/extensions/Xinerama.h> header file. */
+/* #undef HAVE_X11_EXTENSIONS_XINERAMA_H */
+
+/* Define to 1 if you have the <X11/extensions/XInput.h> header file. */
+/* #undef HAVE_X11_EXTENSIONS_XINPUT_H */
+
+/* Define to 1 if you have the <X11/extensions/Xrandr.h> header file. */
+/* #undef HAVE_X11_EXTENSIONS_XRANDR_H */
+
+/* Define to 1 if you have the <X11/extensions/Xrender.h> header file. */
+/* #undef HAVE_X11_EXTENSIONS_XRENDER_H */
+
+/* Define to 1 if you have the <X11/extensions/XShm.h> header file. */
+/* #undef HAVE_X11_EXTENSIONS_XSHM_H */
+
+/* Define to 1 if you have the <X11/Xcursor/Xcursor.h> header file. */
+/* #undef HAVE_X11_XCURSOR_XCURSOR_H */
+
+/* Define to 1 if you have the <X11/XKBlib.h> header file. */
+/* #undef HAVE_X11_XKBLIB_H */
+
+/* Define to 1 if you have the <X11/Xlib.h> header file. */
+/* #undef HAVE_X11_XLIB_H */
+
+/* Define to 1 if you have the <X11/Xutil.h> header file. */
+/* #undef HAVE_X11_XUTIL_H */
+
+/* Define to 1 if `callback' is a member of `XICCallback'. */
+/* #undef HAVE_XICCALLBACK_CALLBACK */
+
+/* Define if you have the XKB extension */
+/* #undef HAVE_XKB */
+
+/* Define if libxml2 has the xmlNewDocPI function */
+/* #undef HAVE_XMLNEWDOCPI */
+
+/* Define if libxml2 has the xmlReadMemory function */
+/* #undef HAVE_XMLREADMEMORY */
+
+/* Define if Xrender has the XRenderSetPictureTransform function */
+/* #undef HAVE_XRENDERSETPICTURETRANSFORM */
+
+/* Define to 1 if you have the `z' library (-lz). */
+#define HAVE_ZLIB 1
+
+/* Define to 1 if you have the <zlib.h> header file. */
+#define HAVE_ZLIB_H 1
+
+/* Define to 1 if you have the `_pclose' function. */
+#define HAVE__PCLOSE 1
+
+/* Define to 1 if you have the `_popen' function. */
+#define HAVE__POPEN 1
+
+/* Define to 1 if you have the `_snprintf' function. */
+#define HAVE__SNPRINTF 1
+
+/* Define to 1 if you have the `_spawnvp' function. */
+#define HAVE__SPAWNVP 1
+
+/* Define to 1 if you have the `_strdup' function. */
+#define HAVE__STRDUP 1
+
+/* Define to 1 if you have the `_stricmp' function. */
+/* #undef HAVE__STRICMP */
+
+/* Define to 1 if you have the `_strnicmp' function. */
+/* #undef HAVE__STRNICMP */
+
+/* Define to 1 if you have the `_strtoi64' function. */
+/* #undef HAVE__STRTOI64 */
+
+/* Define to 1 if you have the `_strtoui64' function. */
+/* #undef HAVE__STRTOUI64 */
+
+/* Define to 1 if you have the `_vsnprintf' function. */
+#define HAVE__VSNPRINTF 1
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "wine-devel@winehq.org"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "Wine"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "Wine 1.1.36"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "wine"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL "http://www.winehq.org"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "1.1.36"
+
+/* Define to the soname of the libcapi20 library. */
+/* #undef SONAME_LIBCAPI20 */
+
+/* Define to the soname of the libcrypto library. */
+/* #undef SONAME_LIBCRYPTO */
+
+/* Define to the soname of the libcups library. */
+/* #undef SONAME_LIBCUPS */
+
+/* Define to the soname of the libcurses library. */
+/* #undef SONAME_LIBCURSES */
+
+/* Define to the soname of the libfontconfig library. */
+/* #undef SONAME_LIBFONTCONFIG */
+
+/* Define to the soname of the libfreetype library. */
+/* #undef SONAME_LIBFREETYPE */
+
+/* Define to the soname of the libGL library. */
+/* #undef SONAME_LIBGL */
+
+/* Define to the soname of the libGLU library. */
+/* #undef SONAME_LIBGLU */
+
+/* Define to the soname of the libgnutls library. */
+/* #undef SONAME_LIBGNUTLS */
+
+/* Define to the soname of the libgsm library. */
+/* #undef SONAME_LIBGSM */
+
+/* Define to the soname of the libhal library. */
+/* #undef SONAME_LIBHAL */
+
+/* Define to the soname of the libjack library. */
+/* #undef SONAME_LIBJACK */
+
+/* Define to the soname of the libjpeg library. */
+/* #undef SONAME_LIBJPEG */
+
+/* Define to the soname of the libncurses library. */
+/* #undef SONAME_LIBNCURSES */
+
+/* Define to the soname of the libodbc library. */
+#define SONAME_LIBODBC "libodbc.dll"
+
+/* Define to the soname of the libpng library. */
+/* #undef SONAME_LIBPNG */
+
+/* Define to the soname of the libsane library. */
+/* #undef SONAME_LIBSANE */
+
+/* Define to the soname of the libssl library. */
+/* #undef SONAME_LIBSSL */
+
+/* Define to the soname of the libX11 library. */
+/* #undef SONAME_LIBX11 */
+
+/* Define to the soname of the libXcomposite library. */
+/* #undef SONAME_LIBXCOMPOSITE */
+
+/* Define to the soname of the libXcursor library. */
+/* #undef SONAME_LIBXCURSOR */
+
+/* Define to the soname of the libXext library. */
+/* #undef SONAME_LIBXEXT */
+
+/* Define to the soname of the libXi library. */
+/* #undef SONAME_LIBXI */
+
+/* Define to the soname of the libXinerama library. */
+/* #undef SONAME_LIBXINERAMA */
+
+/* Define to the soname of the libXrandr library. */
+/* #undef SONAME_LIBXRANDR */
+
+/* Define to the soname of the libXrender library. */
+/* #undef SONAME_LIBXRENDER */
+
+/* Define to the soname of the libxslt library. */
+/* #undef SONAME_LIBXSLT */
+
+/* Define to the soname of the libXxf86vm library. */
+/* #undef SONAME_LIBXXF86VM */
+
+/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */
+/* #undef STAT_MACROS_BROKEN */
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if the X Window System is missing or not being used. */
+#define X_DISPLAY_MISSING 1
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to a macro to output a .cfi assembly pseudo-op */
+#define __ASM_CFI(str) str
+
+/* Define to a macro to define an assembly function */
+#define __ASM_DEFINE_FUNC(name,suffix,code) asm(".text\n\t.align 4\n\t.globl _" #name suffix "\n\t.def _" #name suffix "; .scl 2; .type 32; .endef\n_" #name suffix ":\n\t.cfi_startproc\n\t" code "\n\t.cfi_endproc");
+
+/* Define to a macro to generate an assembly function directive */
+#define __ASM_FUNC(name) ".def " __ASM_NAME(name) "; .scl 2; .type 32; .endef"
+
+/* Define to a macro to generate an assembly function with C calling
+   convention */
+#define __ASM_GLOBAL_FUNC(name,code) __ASM_DEFINE_FUNC(name,"",code)
+
+/* Define to a macro to generate an assembly name from a C symbol */
+#define __ASM_NAME(name) "_" name
+
+/* Define to a macro to generate an stdcall suffix */
+#define __ASM_STDCALL(args) "@" #args
+
+/* Define to a macro to generate an assembly function with stdcall calling
+   convention */
+#define __ASM_STDCALL_FUNC(name,args,code) __ASM_DEFINE_FUNC(name,__ASM_STDCALL(args),code)
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/include/d3d8.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/include/d3d8.h	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/include/d3d8.h	(revision 46521)
@@ -0,0 +1,1144 @@
+/*
+ * Copyright (C) 2002 Jason Edmeades
+ *
+ * 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_D3D8_H
+#define __WINE_D3D8_H
+
+#ifndef DIRECT3D_VERSION
+#define DIRECT3D_VERSION  0x0800
+#endif
+
+#include <stdlib.h>
+
+#define COM_NO_WINDOWS_H
+#include <objbase.h>
+#include <windows.h>
+#include <d3d8types.h>
+#include <d3d8caps.h>
+
+#define __MSABI_LONG(_n) _n##L
+
+/*****************************************************************************
+ * Behavior Flags for IDirect3D8::CreateDevice
+ */
+#define D3DCREATE_FPU_PRESERVE                  __MSABI_LONG(0x00000002)
+#define D3DCREATE_MULTITHREADED                 __MSABI_LONG(0x00000004)
+#define D3DCREATE_PUREDEVICE                    __MSABI_LONG(0x00000010)
+#define D3DCREATE_SOFTWARE_VERTEXPROCESSING     __MSABI_LONG(0x00000020)
+#define D3DCREATE_HARDWARE_VERTEXPROCESSING     __MSABI_LONG(0x00000040)
+#define D3DCREATE_MIXED_VERTEXPROCESSING        __MSABI_LONG(0x00000080)
+
+/*****************************************************************************
+ * Flags for SetPrivateData
+ */
+#define D3DSPD_IUNKNOWN                         __MSABI_LONG(0x00000001)
+
+/*****************************************************************************
+ * #defines and error codes
+ */
+#define D3D_SDK_VERSION              220
+#define D3DADAPTER_DEFAULT           0
+#define D3DENUM_NO_WHQL_LEVEL        2
+
+#define _FACD3D  0x876
+#define MAKE_D3DHRESULT( code )  MAKE_HRESULT( 1, _FACD3D, code )
+
+/*
+ * Direct3D Errors
+ */
+#define D3D_OK                                  S_OK
+#define D3DERR_WRONGTEXTUREFORMAT               MAKE_D3DHRESULT(2072)
+#define D3DERR_UNSUPPORTEDCOLOROPERATION        MAKE_D3DHRESULT(2073)
+#define D3DERR_UNSUPPORTEDCOLORARG              MAKE_D3DHRESULT(2074)
+#define D3DERR_UNSUPPORTEDALPHAOPERATION        MAKE_D3DHRESULT(2075)
+#define D3DERR_UNSUPPORTEDALPHAARG              MAKE_D3DHRESULT(2076)
+#define D3DERR_TOOMANYOPERATIONS                MAKE_D3DHRESULT(2077)
+#define D3DERR_CONFLICTINGTEXTUREFILTER         MAKE_D3DHRESULT(2078)
+#define D3DERR_UNSUPPORTEDFACTORVALUE           MAKE_D3DHRESULT(2079)
+#define D3DERR_CONFLICTINGRENDERSTATE           MAKE_D3DHRESULT(2081)
+#define D3DERR_UNSUPPORTEDTEXTUREFILTER         MAKE_D3DHRESULT(2082)
+#define D3DERR_CONFLICTINGTEXTUREPALETTE        MAKE_D3DHRESULT(2086)
+#define D3DERR_DRIVERINTERNALERROR              MAKE_D3DHRESULT(2087)
+
+#define D3DERR_NOTFOUND                         MAKE_D3DHRESULT(2150)
+#define D3DERR_MOREDATA                         MAKE_D3DHRESULT(2151)
+#define D3DERR_DEVICELOST                       MAKE_D3DHRESULT(2152)
+#define D3DERR_DEVICENOTRESET                   MAKE_D3DHRESULT(2153)
+#define D3DERR_NOTAVAILABLE                     MAKE_D3DHRESULT(2154)
+#define D3DERR_OUTOFVIDEOMEMORY                 MAKE_D3DHRESULT(380)
+#define D3DERR_INVALIDDEVICE                    MAKE_D3DHRESULT(2155)
+#define D3DERR_INVALIDCALL                      MAKE_D3DHRESULT(2156)
+#define D3DERR_DRIVERINVALIDCALL                MAKE_D3DHRESULT(2157)
+
+/*****************************************************************************
+ * Predeclare the interfaces
+ */
+DEFINE_GUID(IID_IDirect3D8,              0x1DD9E8DA,0x1C77,0x4D40,0xB0,0xCF,0x98,0xFE,0xFD,0xFF,0x95,0x12);
+typedef struct IDirect3D8 *LPDIRECT3D8;
+
+DEFINE_GUID(IID_IDirect3DDevice8,        0x7385E5DF,0x8FE8,0x41D5,0x86,0xB6,0xD7,0xB4,0x85,0x47,0xB6,0xCF);
+typedef struct IDirect3DDevice8 *LPDIRECT3DDEVICE8;
+
+DEFINE_GUID(IID_IDirect3DResource8,      0x1B36BB7B,0x09B7,0x410A,0xB4,0x45,0x7D,0x14,0x30,0xD7,0xB3,0x3F);
+typedef struct IDirect3DResource8 *LPDIRECT3DRESOURCE8, *PDIRECT3DRESOURCE8;
+
+DEFINE_GUID(IID_IDirect3DVertexBuffer8,  0x8AEEEAC7,0x05F9,0x44D4,0xB5,0x91,0x00,0x0B,0x0D,0xF1,0xCB,0x95);
+typedef struct IDirect3DVertexBuffer8 *LPDIRECT3DVERTEXBUFFER8, *PDIRECT3DVERTEXBUFFER8;
+
+DEFINE_GUID(IID_IDirect3DVolume8,        0xBD7349F5,0x14F1,0x42E4,0x9C,0x79,0x97,0x23,0x80,0xDB,0x40,0xC0);
+typedef struct IDirect3DVolume8 *LPDIRECT3DVOLUME8, *PDIRECT3DVOLUME8;
+
+DEFINE_GUID(IID_IDirect3DSwapChain8,     0x928C088B,0x76B9,0x4C6B,0xA5,0x36,0xA5,0x90,0x85,0x38,0x76,0xCD);
+typedef struct IDirect3DSwapChain8 *LPDIRECT3DSWAPCHAIN8, *PDIRECT3DSWAPCHAIN8;
+
+DEFINE_GUID(IID_IDirect3DSurface8,       0xB96EEBCA,0xB326,0x4EA5,0x88,0x2F,0x2F,0xF5,0xBA,0xE0,0x21,0xDD);
+typedef struct IDirect3DSurface8 *LPDIRECT3DSURFACE8, *PDIRECT3DSURFACE8;
+
+DEFINE_GUID(IID_IDirect3DIndexBuffer8,   0x0E689C9A,0x053D,0x44A0,0x9D,0x92,0xDB,0x0E,0x3D,0x75,0x0F,0x86);
+typedef struct IDirect3DIndexBuffer8 *LPDIRECT3DINDEXBUFFER8, *PDIRECT3DINDEXBUFFER8;
+
+DEFINE_GUID(IID_IDirect3DBaseTexture8,   0xB4211CFA,0x51B9,0x4A9F,0xAB,0x78,0xDB,0x99,0xB2,0xBB,0x67,0x8E);
+typedef struct IDirect3DBaseTexture8 *LPDIRECT3DBASETEXTURE8, *PDIRECT3DBASETEXTURE8;
+
+DEFINE_GUID(IID_IDirect3DTexture8,       0xE4CDD575,0x2866,0x4F01,0xB1,0x2E,0x7E,0xEC,0xE1,0xEC,0x93,0x58);
+typedef struct IDirect3DTexture8 *LPDIRECT3DTEXTURE8, *PDIRECT3DTEXTURE8;
+
+DEFINE_GUID(IID_IDirect3DCubeTexture8,   0x3EE5B968,0x2ACA,0x4C34,0x8B,0xB5,0x7E,0x0C,0x3D,0x19,0xB7,0x50);
+typedef struct IDirect3DCubeTexture8 *LPDIRECT3DCUBETEXTURE8, *PDIRECT3DCUBETEXTURE8;
+
+DEFINE_GUID(IID_IDirect3DVolumeTexture8, 0x4B8AAAFA,0x140F,0x42BA,0x91,0x31,0x59,0x7E,0xAF,0xAA,0x2E,0xAD);
+typedef struct IDirect3DVolumeTexture8 *LPDIRECT3DVOLUMETEXTURE8, *PDIRECT3DVOLUMETEXTURE8;
+
+/*****************************************************************************
+ * IDirect3D8 interface
+ */
+#undef INTERFACE
+#define INTERFACE IDirect3D8
+DECLARE_INTERFACE_(IDirect3D8,IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IDirect3D8 methods ***/
+    STDMETHOD(RegisterSoftwareDevice)(THIS_ void * pInitializeFunction) PURE;
+    STDMETHOD_(UINT,GetAdapterCount             )(THIS) PURE;
+    STDMETHOD(GetAdapterIdentifier)(THIS_ UINT  Adapter, DWORD  Flags, D3DADAPTER_IDENTIFIER8 * pIdentifier) PURE;
+    STDMETHOD_(UINT,GetAdapterModeCount)(THIS_ UINT  Adapter) PURE;
+    STDMETHOD(EnumAdapterModes)(THIS_ UINT  Adapter, UINT  Mode, D3DDISPLAYMODE * pMode) PURE;
+    STDMETHOD(GetAdapterDisplayMode)(THIS_ UINT  Adapter, D3DDISPLAYMODE * pMode) PURE;
+    STDMETHOD(CheckDeviceType)(THIS_ UINT  Adapter, D3DDEVTYPE  CheckType, D3DFORMAT  DisplayFormat, D3DFORMAT  BackBufferFormat, BOOL  Windowed) PURE;
+    STDMETHOD(CheckDeviceFormat)(THIS_ UINT  Adapter, D3DDEVTYPE  DeviceType, D3DFORMAT  AdapterFormat, DWORD  Usage, D3DRESOURCETYPE  RType, D3DFORMAT  CheckFormat) PURE;
+    STDMETHOD(CheckDeviceMultiSampleType)(THIS_ UINT  Adapter, D3DDEVTYPE  DeviceType, D3DFORMAT  SurfaceFormat, BOOL  Windowed, D3DMULTISAMPLE_TYPE  MultiSampleType) PURE;
+    STDMETHOD(CheckDepthStencilMatch)(THIS_ UINT  Adapter, D3DDEVTYPE  DeviceType, D3DFORMAT  AdapterFormat, D3DFORMAT  RenderTargetFormat, D3DFORMAT  DepthStencilFormat) PURE;
+    STDMETHOD(GetDeviceCaps)(THIS_ UINT  Adapter, D3DDEVTYPE  DeviceType, D3DCAPS8 * pCaps) PURE;
+    STDMETHOD_(HMONITOR,GetAdapterMonitor)(THIS_ UINT  Adapter) PURE;
+    STDMETHOD(CreateDevice)(THIS_ UINT  Adapter, D3DDEVTYPE  DeviceType,HWND  hFocusWindow, DWORD  BehaviorFlags, D3DPRESENT_PARAMETERS * pPresentationParameters, struct IDirect3DDevice8 ** ppReturnedDeviceInterface) PURE;
+};
+#undef INTERFACE
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+/*** IUnknown methods ***/
+#define IDirect3D8_QueryInterface(p,a,b)                    (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3D8_AddRef(p)                                (p)->lpVtbl->AddRef(p)
+#define IDirect3D8_Release(p)                               (p)->lpVtbl->Release(p)
+/*** IDirect3D8 methods ***/
+#define IDirect3D8_RegisterSoftwareDevice(p,a)              (p)->lpVtbl->RegisterSoftwareDevice(p,a)
+#define IDirect3D8_GetAdapterCount(p)                       (p)->lpVtbl->GetAdapterCount(p)
+#define IDirect3D8_GetAdapterIdentifier(p,a,b,c)            (p)->lpVtbl->GetAdapterIdentifier(p,a,b,c)
+#define IDirect3D8_GetAdapterModeCount(p,a)                 (p)->lpVtbl->GetAdapterModeCount(p,a)
+#define IDirect3D8_EnumAdapterModes(p,a,b,c)                (p)->lpVtbl->EnumAdapterModes(p,a,b,c)
+#define IDirect3D8_GetAdapterDisplayMode(p,a,b)             (p)->lpVtbl->GetAdapterDisplayMode(p,a,b)
+#define IDirect3D8_CheckDeviceType(p,a,b,c,d,e)             (p)->lpVtbl->CheckDeviceType(p,a,b,c,d,e)
+#define IDirect3D8_CheckDeviceFormat(p,a,b,c,d,e,f)         (p)->lpVtbl->CheckDeviceFormat(p,a,b,c,d,e,f)
+#define IDirect3D8_CheckDeviceMultiSampleType(p,a,b,c,d,e)  (p)->lpVtbl->CheckDeviceMultiSampleType(p,a,b,c,d,e)
+#define IDirect3D8_CheckDepthStencilMatch(p,a,b,c,d,e)      (p)->lpVtbl->CheckDepthStencilMatch(p,a,b,c,d,e)
+#define IDirect3D8_GetDeviceCaps(p,a,b,c)                   (p)->lpVtbl->GetDeviceCaps(p,a,b,c)
+#define IDirect3D8_GetAdapterMonitor(p,a)                   (p)->lpVtbl->GetAdapterMonitor(p,a)
+#define IDirect3D8_CreateDevice(p,a,b,c,d,e,f)              (p)->lpVtbl->CreateDevice(p,a,b,c,d,e,f)
+#else
+/*** IUnknown methods ***/
+#define IDirect3D8_QueryInterface(p,a,b)                    (p)->QueryInterface(a,b)
+#define IDirect3D8_AddRef(p)                                (p)->AddRef()
+#define IDirect3D8_Release(p)                               (p)->Release()
+/*** IDirect3D8 methods ***/
+#define IDirect3D8_RegisterSoftwareDevice(p,a)              (p)->RegisterSoftwareDevice(a)
+#define IDirect3D8_GetAdapterCount(p)                       (p)->GetAdapterCount()
+#define IDirect3D8_GetAdapterIdentifier(p,a,b,c)            (p)->GetAdapterIdentifier(a,b,c)
+#define IDirect3D8_GetAdapterModeCount(p,a)                 (p)->GetAdapterModeCount(a)
+#define IDirect3D8_EnumAdapterModes(p,a,b,c)                (p)->EnumAdapterModes(a,b,c)
+#define IDirect3D8_GetAdapterDisplayMode(p,a,b)             (p)->GetAdapterDisplayMode(a,b)
+#define IDirect3D8_CheckDeviceType(p,a,b,c,d,e)             (p)->CheckDeviceType(a,b,c,d,e)
+#define IDirect3D8_CheckDeviceFormat(p,a,b,c,d,e,f)         (p)->CheckDeviceFormat(a,b,c,d,e,f)
+#define IDirect3D8_CheckDeviceMultiSampleType(p,a,b,c,d,e)  (p)->CheckDeviceMultiSampleType(a,b,c,d,e)
+#define IDirect3D8_CheckDepthStencilMatch(p,a,b,c,d,e)      (p)->CheckDepthStencilMatch(a,b,c,d,e)
+#define IDirect3D8_GetDeviceCaps(p,a,b,c)                   (p)->GetDeviceCaps(a,b,c)
+#define IDirect3D8_GetAdapterMonitor(p,a)                   (p)->GetAdapterMonitor(a)
+#define IDirect3D8_CreateDevice(p,a,b,c,d,e,f)              (p)->CreateDevice(a,b,c,d,e,f)
+#endif
+
+/*****************************************************************************
+ * IDirect3DVolume8 interface
+ */
+#define INTERFACE IDirect3DVolume8
+DECLARE_INTERFACE_(IDirect3DVolume8,IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IDirect3DVolume8 methods ***/
+    STDMETHOD(GetDevice)(THIS_ struct IDirect3DDevice8 ** ppDevice) PURE;
+    STDMETHOD(SetPrivateData)(THIS_ REFGUID  refguid,CONST void * pData, DWORD  SizeOfData, DWORD  Flags) PURE;
+    STDMETHOD(GetPrivateData)(THIS_ REFGUID   refguid,void * pData, DWORD * pSizeOfData) PURE;
+    STDMETHOD(FreePrivateData)(THIS_ REFGUID  refguid) PURE;
+    STDMETHOD(GetContainer)(THIS_ REFIID  riid, void ** ppContainer) PURE;
+    STDMETHOD(GetDesc)(THIS_ D3DVOLUME_DESC * pDesc) PURE;
+    STDMETHOD(LockBox)(THIS_ D3DLOCKED_BOX * pLockedVolume,CONST D3DBOX * pBox, DWORD  Flags) PURE;
+    STDMETHOD(UnlockBox)(THIS) PURE;
+};
+#undef INTERFACE
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+/*** IUnknown methods ***/
+#define IDirect3DVolume8_QueryInterface(p,a,b)        (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DVolume8_AddRef(p)                    (p)->lpVtbl->AddRef(p)
+#define IDirect3DVolume8_Release(p)                   (p)->lpVtbl->Release(p)
+/*** IDirect3DVolume8 methods ***/
+#define IDirect3DVolume8_GetDevice(p,a)               (p)->lpVtbl->GetDevice(p,a)
+#define IDirect3DVolume8_SetPrivateData(p,a,b,c,d)    (p)->lpVtbl->SetPrivateData(p,a,b,c,d)
+#define IDirect3DVolume8_GetPrivateData(p,a,b,c)      (p)->lpVtbl->GetPrivateData(p,a,b,c)
+#define IDirect3DVolume8_FreePrivateData(p,a)         (p)->lpVtbl->FreePrivateData(p,a)
+#define IDirect3DVolume8_GetContainer(p,a,b)          (p)->lpVtbl->GetContainer(p,a,b)
+#define IDirect3DVolume8_GetDesc(p,a)                 (p)->lpVtbl->GetDesc(p,a)
+#define IDirect3DVolume8_LockBox(p,a,b,c)             (p)->lpVtbl->LockBox(p,a,b,c)
+#define IDirect3DVolume8_UnlockBox(p)                 (p)->lpVtbl->UnlockBox(p)
+#else
+/*** IUnknown methods ***/
+#define IDirect3DVolume8_QueryInterface(p,a,b)        (p)->QueryInterface(a,b)
+#define IDirect3DVolume8_AddRef(p)                    (p)->AddRef()
+#define IDirect3DVolume8_Release(p)                   (p)->Release()
+/*** IDirect3DVolume8 methods ***/
+#define IDirect3DVolume8_GetDevice(p,a)               (p)->GetDevice(a)
+#define IDirect3DVolume8_SetPrivateData(p,a,b,c,d)    (p)->SetPrivateData(a,b,c,d)
+#define IDirect3DVolume8_GetPrivateData(p,a,b,c)      (p)->GetPrivateData(a,b,c)
+#define IDirect3DVolume8_FreePrivateData(p,a)         (p)->FreePrivateData(a)
+#define IDirect3DVolume8_GetContainer(p,a,b)          (p)->GetContainer(a,b)
+#define IDirect3DVolume8_GetDesc(p,a)                 (p)->GetDesc(a)
+#define IDirect3DVolume8_LockBox(p,a,b,c)             (p)->LockBox(a,b,c)
+#define IDirect3DVolume8_UnlockBox(p)                 (p)->UnlockBox()
+#endif
+
+/*****************************************************************************
+ * IDirect3DSwapChain8 interface
+ */
+#define INTERFACE IDirect3DSwapChain8
+DECLARE_INTERFACE_(IDirect3DSwapChain8,IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IDirect3DSwapChain8 methods ***/
+    STDMETHOD(Present)(THIS_ CONST RECT * pSourceRect, CONST RECT * pDestRect, HWND  hDestWindowOverride,CONST RGNDATA * pDirtyRegion) PURE;
+    STDMETHOD(GetBackBuffer)(THIS_ UINT  BackBuffer, D3DBACKBUFFER_TYPE  Type, struct IDirect3DSurface8 ** ppBackBuffer) PURE;
+};
+#undef INTERFACE
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+/*** IUnknown methods ***/
+#define IDirect3DSwapChain8_QueryInterface(p,a,b)        (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DSwapChain8_AddRef(p)                    (p)->lpVtbl->AddRef(p)
+#define IDirect3DSwapChain8_Release(p)                   (p)->lpVtbl->Release(p)
+/*** IDirect3DSwapChain8 methods ***/
+#define IDirect3DSwapChain8_Present(p,a,b,c)             (p)->lpVtbl->Present(p,a,b,c)
+#define IDirect3DSwapChain8_GetBackBuffer(p,a,b,c)       (p)->lpVtbl->GetBackBuffer(p,a,b,c)
+#else
+/*** IUnknown methods ***/
+#define IDirect3DSwapChain8_QueryInterface(p,a,b)        (p)->QueryInterface(a,b)
+#define IDirect3DSwapChain8_AddRef(p)                    (p)->AddRef()
+#define IDirect3DSwapChain8_Release(p)                   (p)->Release()
+/*** IDirect3DSwapChain8 methods ***/
+#define IDirect3DSwapChain8_Present(p,a,b,c)             (p)->Present(a,b,c)
+#define IDirect3DSwapChain8_GetBackBuffer(p,a,b,c)       (p)->GetBackBuffer(a,b,c)
+#endif
+
+/*****************************************************************************
+ * IDirect3DSurface8 interface
+ */
+#define INTERFACE IDirect3DSurface8
+DECLARE_INTERFACE_(IDirect3DSurface8,IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IDirect3DSurface8 methods ***/
+    STDMETHOD(GetDevice)(THIS_ struct IDirect3DDevice8 ** ppDevice) PURE;
+    STDMETHOD(SetPrivateData)(THIS_ REFGUID  refguid,CONST void * pData,DWORD  SizeOfData,DWORD  Flags) PURE;
+    STDMETHOD(GetPrivateData)(THIS_ REFGUID  refguid,void * pData,DWORD * pSizeOfData) PURE;
+    STDMETHOD(FreePrivateData)(THIS_ REFGUID  refguid) PURE;
+    STDMETHOD(GetContainer)(THIS_ REFIID  riid, void ** ppContainer) PURE;
+    STDMETHOD(GetDesc)(THIS_ D3DSURFACE_DESC * pDesc) PURE;
+    STDMETHOD(LockRect)(THIS_ D3DLOCKED_RECT * pLockedRect, CONST RECT * pRect,DWORD  Flags) PURE;
+    STDMETHOD(UnlockRect)(THIS) PURE;
+};
+#undef INTERFACE
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+/*** IUnknown methods ***/
+#define IDirect3DSurface8_QueryInterface(p,a,b)        (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DSurface8_AddRef(p)                    (p)->lpVtbl->AddRef(p)
+#define IDirect3DSurface8_Release(p)                   (p)->lpVtbl->Release(p)
+/*** IDirect3DSurface8 methods ***/
+#define IDirect3DSurface8_GetDevice(p,a)               (p)->lpVtbl->GetDevice(p,a)
+#define IDirect3DSurface8_SetPrivateData(p,a,b,c,d)    (p)->lpVtbl->SetPrivateData(p,a,b,c,d)
+#define IDirect3DSurface8_GetPrivateData(p,a,b,c)      (p)->lpVtbl->GetPrivateData(p,a,b,c)
+#define IDirect3DSurface8_FreePrivateData(p,a)         (p)->lpVtbl->FreePrivateData(p,a)
+#define IDirect3DSurface8_GetContainer(p,a,b)          (p)->lpVtbl->GetContainer(p,a,b)
+#define IDirect3DSurface8_GetDesc(p,a)                 (p)->lpVtbl->GetDesc(p,a)
+#define IDirect3DSurface8_LockRect(p,a,b,c)            (p)->lpVtbl->LockRect(p,a,b,c)
+#define IDirect3DSurface8_UnlockRect(p)                (p)->lpVtbl->UnlockRect(p)
+#else
+/*** IUnknown methods ***/
+#define IDirect3DSurface8_QueryInterface(p,a,b)        (p)->QueryInterface(a,b)
+#define IDirect3DSurface8_AddRef(p)                    (p)->AddRef()
+#define IDirect3DSurface8_Release(p)                   (p)->Release()
+/*** IDirect3DSurface8 methods ***/
+#define IDirect3DSurface8_GetDevice(p,a)               (p)->GetDevice(a)
+#define IDirect3DSurface8_SetPrivateData(p,a,b,c,d)    (p)->SetPrivateData(a,b,c,d)
+#define IDirect3DSurface8_GetPrivateData(p,a,b,c)      (p)->GetPrivateData(a,b,c)
+#define IDirect3DSurface8_FreePrivateData(p,a)         (p)->FreePrivateData(a)
+#define IDirect3DSurface8_GetContainer(p,a,b)          (p)->GetContainer(a,b)
+#define IDirect3DSurface8_GetDesc(p,a)                 (p)->GetDesc(a)
+#define IDirect3DSurface8_LockRect(p,a,b,c)            (p)->LockRect(a,b,c)
+#define IDirect3DSurface8_UnlockRect(p)                (p)->UnlockRect()
+#endif
+
+/*****************************************************************************
+ * IDirect3DResource8 interface
+ */
+#define INTERFACE IDirect3DResource8
+DECLARE_INTERFACE_(IDirect3DResource8,IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IDirect3DResource8 methods ***/
+    STDMETHOD(GetDevice)(THIS_ struct IDirect3DDevice8 ** ppDevice) PURE;
+    STDMETHOD(SetPrivateData)(THIS_ REFGUID  refguid, CONST void * pData, DWORD  SizeOfData, DWORD  Flags) PURE;
+    STDMETHOD(GetPrivateData)(THIS_ REFGUID  refguid, void * pData, DWORD * pSizeOfData) PURE;
+    STDMETHOD(FreePrivateData)(THIS_ REFGUID  refguid) PURE;
+    STDMETHOD_(DWORD,SetPriority)(THIS_ DWORD  PriorityNew) PURE;
+    STDMETHOD_(DWORD,GetPriority)(THIS) PURE;
+    STDMETHOD_(void,PreLoad)(THIS) PURE;
+    STDMETHOD_(D3DRESOURCETYPE,GetType)(THIS) PURE;
+};
+#undef INTERFACE
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+/*** IUnknown methods ***/
+#define IDirect3DResource8_QueryInterface(p,a,b)        (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DResource8_AddRef(p)                    (p)->lpVtbl->AddRef(p)
+#define IDirect3DResource8_Release(p)                   (p)->lpVtbl->Release(p)
+/*** IDirect3DResource8 methods ***/
+#define IDirect3DResource8_GetDevice(p,a)               (p)->lpVtbl->GetDevice(p,a)
+#define IDirect3DResource8_SetPrivateData(p,a,b,c,d)    (p)->lpVtbl->SetPrivateData(p,a,b,c,d)
+#define IDirect3DResource8_GetPrivateData(p,a,b,c)      (p)->lpVtbl->GetPrivateData(p,a,b,c)
+#define IDirect3DResource8_FreePrivateData(p,a)         (p)->lpVtbl->FreePrivateData(p,a)
+#define IDirect3DResource8_SetPriority(p,a)             (p)->lpVtbl->SetPriority(p,a)
+#define IDirect3DResource8_GetPriority(p)               (p)->lpVtbl->GetPriority(p)
+#define IDirect3DResource8_PreLoad(p)                   (p)->lpVtbl->PreLoad(p)
+#define IDirect3DResource8_GetType(p)                   (p)->lpVtbl->GetType(p)
+#else
+/*** IUnknown methods ***/
+#define IDirect3DResource8_QueryInterface(p,a,b)        (p)->QueryInterface(a,b)
+#define IDirect3DResource8_AddRef(p)                    (p)->AddRef()
+#define IDirect3DResource8_Release(p)                   (p)->Release()
+/*** IDirect3DResource8 methods ***/
+#define IDirect3DResource8_GetDevice(p,a)               (p)->GetDevice(a)
+#define IDirect3DResource8_SetPrivateData(p,a,b,c,d)    (p)->SetPrivateData(a,b,c,d)
+#define IDirect3DResource8_GetPrivateData(p,a,b,c)      (p)->GetPrivateData(a,b,c)
+#define IDirect3DResource8_FreePrivateData(p,a)         (p)->FreePrivateData(a)
+#define IDirect3DResource8_SetPriority(p,a)             (p)->SetPriority(a)
+#define IDirect3DResource8_GetPriority(p)               (p)->GetPriority()
+#define IDirect3DResource8_PreLoad(p)                   (p)->PreLoad()
+#define IDirect3DResource8_GetType(p)                   (p)->GetType()
+#endif
+
+/*****************************************************************************
+ * IDirect3DVertexBuffer8 interface
+ */
+#define INTERFACE IDirect3DVertexBuffer8
+DECLARE_INTERFACE_(IDirect3DVertexBuffer8,IDirect3DResource8)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IDirect3DResource8 methods ***/
+    STDMETHOD(GetDevice)(THIS_ struct IDirect3DDevice8 ** ppDevice) PURE;
+    STDMETHOD(SetPrivateData)(THIS_ REFGUID  refguid, CONST void * pData, DWORD  SizeOfData, DWORD  Flags) PURE;
+    STDMETHOD(GetPrivateData)(THIS_ REFGUID  refguid, void * pData, DWORD * pSizeOfData) PURE;
+    STDMETHOD(FreePrivateData)(THIS_ REFGUID  refguid) PURE;
+    STDMETHOD_(DWORD,SetPriority)(THIS_ DWORD  PriorityNew) PURE;
+    STDMETHOD_(DWORD,GetPriority)(THIS) PURE;
+    STDMETHOD_(void,PreLoad)(THIS) PURE;
+    STDMETHOD_(D3DRESOURCETYPE,GetType)(THIS) PURE;
+    /*** IDirect3DVertexBuffer8 methods ***/
+    STDMETHOD(Lock)(THIS_ UINT  OffsetToLock, UINT  SizeToLock, BYTE ** ppbData, DWORD  Flags) PURE;
+    STDMETHOD(Unlock)(THIS) PURE;
+    STDMETHOD(GetDesc)(THIS_ D3DVERTEXBUFFER_DESC  * pDesc) PURE;
+};
+#undef INTERFACE
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+/*** IUnknown methods ***/
+#define IDirect3DVertexBuffer8_QueryInterface(p,a,b)        (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DVertexBuffer8_AddRef(p)                    (p)->lpVtbl->AddRef(p)
+#define IDirect3DVertexBuffer8_Release(p)                   (p)->lpVtbl->Release(p)
+/*** IDirect3DVertexBuffer8 methods: IDirect3DResource8 ***/
+#define IDirect3DVertexBuffer8_GetDevice(p,a)               (p)->lpVtbl->GetDevice(p,a)
+#define IDirect3DVertexBuffer8_SetPrivateData(p,a,b,c,d)    (p)->lpVtbl->SetPrivateData(p,a,b,c,d)
+#define IDirect3DVertexBuffer8_GetPrivateData(p,a,b,c)      (p)->lpVtbl->GetPrivateData(p,a,b,c)
+#define IDirect3DVertexBuffer8_FreePrivateData(p,a)         (p)->lpVtbl->FreePrivateData(p,a)
+#define IDirect3DVertexBuffer8_SetPriority(p,a)             (p)->lpVtbl->SetPriority(p,a)
+#define IDirect3DVertexBuffer8_GetPriority(p)               (p)->lpVtbl->GetPriority(p)
+#define IDirect3DVertexBuffer8_PreLoad(p)                   (p)->lpVtbl->PreLoad(p)
+#define IDirect3DVertexBuffer8_GetType(p)                   (p)->lpVtbl->GetType(p)
+/*** IDirect3DVertexBuffer8 methods ***/
+#define IDirect3DVertexBuffer8_Lock(p,a,b,c,d)              (p)->lpVtbl->Lock(p,a,b,c,d)
+#define IDirect3DVertexBuffer8_Unlock(p)                    (p)->lpVtbl->Unlock(p)
+#define IDirect3DVertexBuffer8_GetDesc(p,a)                 (p)->lpVtbl->GetDesc(p,a)
+#else
+/*** IUnknown methods ***/
+#define IDirect3DVertexBuffer8_QueryInterface(p,a,b)        (p)->QueryInterface(a,b)
+#define IDirect3DVertexBuffer8_AddRef(p)                    (p)->AddRef()
+#define IDirect3DVertexBuffer8_Release(p)                   (p)->Release()
+/*** IDirect3DVertexBuffer8 methods: IDirect3DResource8 ***/
+#define IDirect3DVertexBuffer8_GetDevice(p,a)               (p)->GetDevice(a)
+#define IDirect3DVertexBuffer8_SetPrivateData(p,a,b,c,d)    (p)->SetPrivateData(a,b,c,d)
+#define IDirect3DVertexBuffer8_GetPrivateData(p,a,b,c)      (p)->GetPrivateData(a,b,c)
+#define IDirect3DVertexBuffer8_FreePrivateData(p,a)         (p)->FreePrivateData(a)
+#define IDirect3DVertexBuffer8_SetPriority(p,a)             (p)->SetPriority(a)
+#define IDirect3DVertexBuffer8_GetPriority(p)               (p)->GetPriority()
+#define IDirect3DVertexBuffer8_PreLoad(p)                   (p)->PreLoad()
+#define IDirect3DVertexBuffer8_GetType(p)                   (p)->GetType()
+/*** IDirect3DVertexBuffer8 methods ***/
+#define IDirect3DVertexBuffer8_Lock(p,a,b,c,d)              (p)->Lock(a,b,c,d)
+#define IDirect3DVertexBuffer8_Unlock(p)                    (p)->Unlock()
+#define IDirect3DVertexBuffer8_GetDesc(p,a)                 (p)->GetDesc(a)
+#endif
+
+/*****************************************************************************
+ * IDirect3DIndexBuffer8 interface
+ */
+#define INTERFACE IDirect3DIndexBuffer8
+DECLARE_INTERFACE_(IDirect3DIndexBuffer8,IDirect3DResource8)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IDirect3DResource8 methods ***/
+    STDMETHOD(GetDevice)(THIS_ struct IDirect3DDevice8 ** ppDevice) PURE;
+    STDMETHOD(SetPrivateData)(THIS_ REFGUID  refguid, CONST void * pData, DWORD  SizeOfData, DWORD  Flags) PURE;
+    STDMETHOD(GetPrivateData)(THIS_ REFGUID  refguid, void * pData, DWORD * pSizeOfData) PURE;
+    STDMETHOD(FreePrivateData)(THIS_ REFGUID  refguid) PURE;
+    STDMETHOD_(DWORD,SetPriority)(THIS_ DWORD  PriorityNew) PURE;
+    STDMETHOD_(DWORD,GetPriority)(THIS) PURE;
+    STDMETHOD_(void,PreLoad)(THIS) PURE;
+    STDMETHOD_(D3DRESOURCETYPE,GetType)(THIS) PURE;
+    /*** IDirect3DIndexBuffer8 methods ***/
+    STDMETHOD(Lock)(THIS_ UINT  OffsetToLock, UINT  SizeToLock, BYTE ** ppbData, DWORD  Flags) PURE;
+    STDMETHOD(Unlock)(THIS) PURE;
+    STDMETHOD(GetDesc)(THIS_ D3DINDEXBUFFER_DESC * pDesc) PURE;
+};
+#undef INTERFACE
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+/*** IUnknown methods ***/
+#define IDirect3DIndexBuffer8_QueryInterface(p,a,b)        (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DIndexBuffer8_AddRef(p)                    (p)->lpVtbl->AddRef(p)
+#define IDirect3DIndexBuffer8_Release(p)                   (p)->lpVtbl->Release(p)
+/*** IDirect3DIndexBuffer8 methods: IDirect3DResource8 ***/
+#define IDirect3DIndexBuffer8_GetDevice(p,a)               (p)->lpVtbl->GetDevice(p,a)
+#define IDirect3DIndexBuffer8_SetPrivateData(p,a,b,c,d)    (p)->lpVtbl->SetPrivateData(p,a,b,c,d)
+#define IDirect3DIndexBuffer8_GetPrivateData(p,a,b,c)      (p)->lpVtbl->GetPrivateData(p,a,b,c)
+#define IDirect3DIndexBuffer8_FreePrivateData(p,a)         (p)->lpVtbl->FreePrivateData(p,a)
+#define IDirect3DIndexBuffer8_SetPriority(p,a)             (p)->lpVtbl->SetPriority(p,a)
+#define IDirect3DIndexBuffer8_GetPriority(p)               (p)->lpVtbl->GetPriority(p)
+#define IDirect3DIndexBuffer8_PreLoad(p)                   (p)->lpVtbl->PreLoad(p)
+#define IDirect3DIndexBuffer8_GetType(p)                   (p)->lpVtbl->GetType(p)
+/*** IDirect3DIndexBuffer8 methods ***/
+#define IDirect3DIndexBuffer8_Lock(p,a,b,c,d)              (p)->lpVtbl->Lock(p,a,b,c,d)
+#define IDirect3DIndexBuffer8_Unlock(p)                    (p)->lpVtbl->Unlock(p)
+#define IDirect3DIndexBuffer8_GetDesc(p,a)                 (p)->lpVtbl->GetDesc(p,a)
+#else
+/*** IUnknown methods ***/
+#define IDirect3DIndexBuffer8_QueryInterface(p,a,b)        (p)->QueryInterface(a,b)
+#define IDirect3DIndexBuffer8_AddRef(p)                    (p)->AddRef()
+#define IDirect3DIndexBuffer8_Release(p)                   (p)->Release()
+/*** IDirect3DIndexBuffer8 methods: IDirect3DResource8 ***/
+#define IDirect3DIndexBuffer8_GetDevice(p,a)               (p)->GetDevice(a)
+#define IDirect3DIndexBuffer8_SetPrivateData(p,a,b,c,d)    (p)->SetPrivateData(a,b,c,d)
+#define IDirect3DIndexBuffer8_GetPrivateData(p,a,b,c)      (p)->GetPrivateData(a,b,c)
+#define IDirect3DIndexBuffer8_FreePrivateData(p,a)         (p)->FreePrivateData(a)
+#define IDirect3DIndexBuffer8_SetPriority(p,a)             (p)->SetPriority(a)
+#define IDirect3DIndexBuffer8_GetPriority(p)               (p)->GetPriority()
+#define IDirect3DIndexBuffer8_PreLoad(p)                   (p)->PreLoad()
+#define IDirect3DIndexBuffer8_GetType(p)                   (p)->GetType()
+/*** IDirect3DIndexBuffer8 methods ***/
+#define IDirect3DIndexBuffer8_Lock(p,a,b,c,d)              (p)->Lock(a,b,c,d)
+#define IDirect3DIndexBuffer8_Unlock(p)                    (p)->Unlock()
+#define IDirect3DIndexBuffer8_GetDesc(p,a)                 (p)->GetDesc(a)
+#endif
+
+/*****************************************************************************
+ * IDirect3DBaseTexture8 interface
+ */
+#define INTERFACE IDirect3DBaseTexture8
+DECLARE_INTERFACE_(IDirect3DBaseTexture8,IDirect3DResource8)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IDirect3DResource8 methods ***/
+    STDMETHOD(GetDevice)(THIS_ struct IDirect3DDevice8 ** ppDevice) PURE;
+    STDMETHOD(SetPrivateData)(THIS_ REFGUID  refguid, CONST void * pData, DWORD  SizeOfData, DWORD  Flags) PURE;
+    STDMETHOD(GetPrivateData)(THIS_ REFGUID  refguid, void * pData, DWORD * pSizeOfData) PURE;
+    STDMETHOD(FreePrivateData)(THIS_ REFGUID  refguid) PURE;
+    STDMETHOD_(DWORD,SetPriority)(THIS_ DWORD  PriorityNew) PURE;
+    STDMETHOD_(DWORD,GetPriority)(THIS) PURE;
+    STDMETHOD_(void,PreLoad)(THIS) PURE;
+    STDMETHOD_(D3DRESOURCETYPE,GetType)(THIS) PURE;
+    /*** IDirect3DBaseTexture8 methods ***/
+    STDMETHOD_(DWORD,SetLOD)(THIS_ DWORD  LODNew) PURE;
+    STDMETHOD_(DWORD,GetLOD)(THIS) PURE;
+    STDMETHOD_(DWORD,GetLevelCount)(THIS) PURE;
+};
+#undef INTERFACE
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+/*** IUnknown methods ***/
+#define IDirect3DBaseTexture8_QueryInterface(p,a,b)        (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DBaseTexture8_AddRef(p)                    (p)->lpVtbl->AddRef(p)
+#define IDirect3DBaseTexture8_Release(p)                   (p)->lpVtbl->Release(p)
+/*** IDirect3DBaseTexture8 methods: IDirect3DResource8 ***/
+#define IDirect3DBaseTexture8_GetDevice(p,a)               (p)->lpVtbl->GetDevice(p,a)
+#define IDirect3DBaseTexture8_SetPrivateData(p,a,b,c,d)    (p)->lpVtbl->SetPrivateData(p,a,b,c,d)
+#define IDirect3DBaseTexture8_GetPrivateData(p,a,b,c)      (p)->lpVtbl->GetPrivateData(p,a,b,c)
+#define IDirect3DBaseTexture8_FreePrivateData(p,a)         (p)->lpVtbl->FreePrivateData(p,a)
+#define IDirect3DBaseTexture8_SetPriority(p,a)             (p)->lpVtbl->SetPriority(p,a)
+#define IDirect3DBaseTexture8_GetPriority(p)               (p)->lpVtbl->GetPriority(p)
+#define IDirect3DBaseTexture8_PreLoad(p)                   (p)->lpVtbl->PreLoad(p)
+#define IDirect3DBaseTexture8_GetType(p)                   (p)->lpVtbl->GetType(p)
+/*** IDirect3DBaseTexture8 methods ***/
+#define IDirect3DBaseTexture8_SetLOD(p,a)                  (p)->lpVtbl->SetLOD(p,a)
+#define IDirect3DBaseTexture8_GetLOD(p)                    (p)->lpVtbl->GetLOD(p)
+#define IDirect3DBaseTexture8_GetLevelCount(p)             (p)->lpVtbl->GetLevelCount(p)
+#else
+/*** IUnknown methods ***/
+#define IDirect3DBaseTexture8_QueryInterface(p,a,b)        (p)->QueryInterface(a,b)
+#define IDirect3DBaseTexture8_AddRef(p)                    (p)->AddRef()
+#define IDirect3DBaseTexture8_Release(p)                   (p)->Release()
+/*** IDirect3DBaseTexture8 methods: IDirect3DResource8 ***/
+#define IDirect3DBaseTexture8_GetDevice(p,a)               (p)->GetDevice(a)
+#define IDirect3DBaseTexture8_SetPrivateData(p,a,b,c,d)    (p)->SetPrivateData(a,b,c,d)
+#define IDirect3DBaseTexture8_GetPrivateData(p,a,b,c)      (p)->GetPrivateData(a,b,c)
+#define IDirect3DBaseTexture8_FreePrivateData(p,a)         (p)->FreePrivateData(a)
+#define IDirect3DBaseTexture8_SetPriority(p,a)             (p)->SetPriority(a)
+#define IDirect3DBaseTexture8_GetPriority(p)               (p)->GetPriority()
+#define IDirect3DBaseTexture8_PreLoad(p)                   (p)->PreLoad()
+#define IDirect3DBaseTexture8_GetType(p)                   (p)->GetType()
+/*** IDirect3DBaseTexture8 methods ***/
+#define IDirect3DBaseTexture8_SetLOD(p,a)                  (p)->SetLOD(a)
+#define IDirect3DBaseTexture8_GetLOD(p)                    (p)->GetLOD()
+#define IDirect3DBaseTexture8_GetLevelCount(p)             (p)->GetLevelCount()
+#endif
+
+/*****************************************************************************
+ * IDirect3DCubeTexture8 interface
+ */
+#define INTERFACE IDirect3DCubeTexture8
+DECLARE_INTERFACE_(IDirect3DCubeTexture8,IDirect3DBaseTexture8)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IDirect3DResource8 methods ***/
+    STDMETHOD(GetDevice)(THIS_ struct IDirect3DDevice8 ** ppDevice) PURE;
+    STDMETHOD(SetPrivateData)(THIS_ REFGUID  refguid, CONST void * pData, DWORD  SizeOfData, DWORD  Flags) PURE;
+    STDMETHOD(GetPrivateData)(THIS_ REFGUID  refguid, void * pData, DWORD * pSizeOfData) PURE;
+    STDMETHOD(FreePrivateData)(THIS_ REFGUID  refguid) PURE;
+    STDMETHOD_(DWORD,SetPriority)(THIS_ DWORD  PriorityNew) PURE;
+    STDMETHOD_(DWORD,GetPriority)(THIS) PURE;
+    STDMETHOD_(void,PreLoad)(THIS) PURE;
+    STDMETHOD_(D3DRESOURCETYPE,GetType)(THIS) PURE;
+    /*** IDirect3DBaseTexture8 methods ***/
+    STDMETHOD_(DWORD,SetLOD)(THIS_ DWORD  LODNew) PURE;
+    STDMETHOD_(DWORD,GetLOD)(THIS) PURE;
+    STDMETHOD_(DWORD,GetLevelCount)(THIS) PURE;
+    /*** IDirect3DCubeTexture8 methods ***/
+    STDMETHOD(GetLevelDesc)(THIS_ UINT  Level,D3DSURFACE_DESC * pDesc) PURE;
+    STDMETHOD(GetCubeMapSurface)(THIS_ D3DCUBEMAP_FACES  FaceType,UINT  Level,IDirect3DSurface8 ** ppCubeMapSurface) PURE;
+    STDMETHOD(LockRect)(THIS_ D3DCUBEMAP_FACES  FaceType,UINT  Level,D3DLOCKED_RECT * pLockedRect,CONST RECT * pRect,DWORD  Flags) PURE;
+    STDMETHOD(UnlockRect)(THIS_ D3DCUBEMAP_FACES  FaceType,UINT  Level) PURE;
+    STDMETHOD(AddDirtyRect)(THIS_ D3DCUBEMAP_FACES  FaceType,CONST RECT * pDirtyRect) PURE;
+};
+#undef INTERFACE
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+/*** IUnknown methods ***/
+#define IDirect3DCubeTexture8_QueryInterface(p,a,b)        (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DCubeTexture8_AddRef(p)                    (p)->lpVtbl->AddRef(p)
+#define IDirect3DCubeTexture8_Release(p)                   (p)->lpVtbl->Release(p)
+/*** IDirect3DCubeTexture8 methods: IDirect3DResource8 ***/
+#define IDirect3DCubeTexture8_GetDevice(p,a)               (p)->lpVtbl->GetDevice(p,a)
+#define IDirect3DCubeTexture8_SetPrivateData(p,a,b,c,d)    (p)->lpVtbl->SetPrivateData(p,a,b,c,d)
+#define IDirect3DCubeTexture8_GetPrivateData(p,a,b,c)      (p)->lpVtbl->GetPrivateData(p,a,b,c)
+#define IDirect3DCubeTexture8_FreePrivateData(p,a)         (p)->lpVtbl->FreePrivateData(p,a)
+#define IDirect3DCubeTexture8_SetPriority(p,a)             (p)->lpVtbl->SetPriority(p,a)
+#define IDirect3DCubeTexture8_GetPriority(p)               (p)->lpVtbl->GetPriority(p)
+#define IDirect3DCubeTexture8_PreLoad(p)                   (p)->lpVtbl->PreLoad(p)
+#define IDirect3DCubeTexture8_GetType(p)                   (p)->lpVtbl->GetType(p)
+/*** IDirect3DCubeTexture8 methods: IDirect3DBaseTexture8 ***/
+#define IDirect3DCubeTexture8_SetLOD(p,a)                  (p)->lpVtbl->SetLOD(p,a)
+#define IDirect3DCubeTexture8_GetLOD(p)                    (p)->lpVtbl->GetLOD(p)
+#define IDirect3DCubeTexture8_GetLevelCount(p)             (p)->lpVtbl->GetLevelCount(p)
+/*** IDirect3DCubeTexture8 methods ***/
+#define IDirect3DCubeTexture8_GetLevelDesc(p,a,b)          (p)->lpVtbl->GetLevelDesc(p,a,b)
+#define IDirect3DCubeTexture8_GetCubeMapSurface(p,a,b,c)   (p)->lpVtbl->GetCubeMapSurface(p,a,b,c)
+#define IDirect3DCubeTexture8_LockRect(p,a,b,c,d,e)        (p)->lpVtbl->LockRect(p,a,b,c,d,e)
+#define IDirect3DCubeTexture8_UnlockRect(p,a,b)            (p)->lpVtbl->UnlockRect(p,a,b)
+#define IDirect3DCubeTexture8_AddDirtyRect(p,a,b)          (p)->lpVtbl->AddDirtyRect(p,a,b)
+#else
+/*** IUnknown methods ***/
+#define IDirect3DCubeTexture8_QueryInterface(p,a,b)        (p)->QueryInterface(a,b)
+#define IDirect3DCubeTexture8_AddRef(p)                    (p)->AddRef()
+#define IDirect3DCubeTexture8_Release(p)                   (p)->Release()
+/*** IDirect3DCubeTexture8 methods: IDirect3DResource8 ***/
+#define IDirect3DCubeTexture8_GetDevice(p,a)               (p)->GetDevice(a)
+#define IDirect3DCubeTexture8_SetPrivateData(p,a,b,c,d)    (p)->SetPrivateData(a,b,c,d)
+#define IDirect3DCubeTexture8_GetPrivateData(p,a,b,c)      (p)->GetPrivateData(a,b,c)
+#define IDirect3DCubeTexture8_FreePrivateData(p,a)         (p)->FreePrivateData(a)
+#define IDirect3DCubeTexture8_SetPriority(p,a)             (p)->SetPriority(a)
+#define IDirect3DCubeTexture8_GetPriority(p)               (p)->GetPriority()
+#define IDirect3DCubeTexture8_PreLoad(p)                   (p)->PreLoad()
+#define IDirect3DCubeTexture8_GetType(p)                   (p)->GetType()
+/*** IDirect3DCubeTexture8 methods: IDirect3DBaseTexture8 ***/
+#define IDirect3DCubeTexture8_SetLOD(p,a)                  (p)->SetLOD(a)
+#define IDirect3DCubeTexture8_GetLOD(p)                    (p)->GetLOD()
+#define IDirect3DCubeTexture8_GetLevelCount(p)             (p)->GetLevelCount()
+/*** IDirect3DCubeTexture8 methods ***/
+#define IDirect3DCubeTexture8_GetLevelDesc(p,a,b)          (p)->GetLevelDesc(a,b)
+#define IDirect3DCubeTexture8_GetCubeMapSurface(p,a,b,c)   (p)->GetCubeMapSurface(a,b,c)
+#define IDirect3DCubeTexture8_LockRect(p,a,b,c,d,e)        (p)->LockRect(a,b,c,d,e)
+#define IDirect3DCubeTexture8_UnlockRect(p,a,b)            (p)->UnlockRect(a,b)
+#define IDirect3DCubeTexture8_AddDirtyRect(p,a,b)          (p)->AddDirtyRect(a,b)
+#endif
+
+/*****************************************************************************
+ * IDirect3DTexture8 interface
+ */
+#define INTERFACE IDirect3DTexture8
+DECLARE_INTERFACE_(IDirect3DTexture8,IDirect3DBaseTexture8)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IDirect3DResource8 methods ***/
+    STDMETHOD(GetDevice)(THIS_ struct IDirect3DDevice8 ** ppDevice) PURE;
+    STDMETHOD(SetPrivateData)(THIS_ REFGUID  refguid, CONST void * pData, DWORD  SizeOfData, DWORD  Flags) PURE;
+    STDMETHOD(GetPrivateData)(THIS_ REFGUID  refguid, void * pData, DWORD * pSizeOfData) PURE;
+    STDMETHOD(FreePrivateData)(THIS_ REFGUID  refguid) PURE;
+    STDMETHOD_(DWORD,SetPriority)(THIS_ DWORD  PriorityNew) PURE;
+    STDMETHOD_(DWORD,GetPriority)(THIS) PURE;
+    STDMETHOD_(void,PreLoad)(THIS) PURE;
+    STDMETHOD_(D3DRESOURCETYPE,GetType)(THIS) PURE;
+    /*** IDirect3DBaseTexture8 methods ***/
+    STDMETHOD_(DWORD,SetLOD)(THIS_ DWORD  LODNew) PURE;
+    STDMETHOD_(DWORD,GetLOD)(THIS) PURE;
+    STDMETHOD_(DWORD,GetLevelCount)(THIS) PURE;
+    /*** IDirect3DTexture8 methods ***/
+    STDMETHOD(GetLevelDesc)(THIS_ UINT  Level,D3DSURFACE_DESC * pDesc) PURE;
+    STDMETHOD(GetSurfaceLevel)(THIS_ UINT  Level,IDirect3DSurface8 ** ppSurfaceLevel) PURE;
+    STDMETHOD(LockRect)(THIS_ UINT  Level,D3DLOCKED_RECT * pLockedRect,CONST RECT * pRect,DWORD  Flags) PURE;
+    STDMETHOD(UnlockRect)(THIS_ UINT  Level) PURE;
+    STDMETHOD(AddDirtyRect)(THIS_ CONST RECT * pDirtyRect) PURE;
+};
+#undef INTERFACE
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+/*** IUnknown methods ***/
+#define IDirect3DTexture8_QueryInterface(p,a,b)        (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DTexture8_AddRef(p)                    (p)->lpVtbl->AddRef(p)
+#define IDirect3DTexture8_Release(p)                   (p)->lpVtbl->Release(p)
+/*** IDirect3DTexture8 methods: IDirect3DResource8 ***/
+#define IDirect3DTexture8_GetDevice(p,a)               (p)->lpVtbl->GetDevice(p,a)
+#define IDirect3DTexture8_SetPrivateData(p,a,b,c,d)    (p)->lpVtbl->SetPrivateData(p,a,b,c,d)
+#define IDirect3DTexture8_GetPrivateData(p,a,b,c)      (p)->lpVtbl->GetPrivateData(p,a,b,c)
+#define IDirect3DTexture8_FreePrivateData(p,a)         (p)->lpVtbl->FreePrivateData(p,a)
+#define IDirect3DTexture8_SetPriority(p,a)             (p)->lpVtbl->SetPriority(p,a)
+#define IDirect3DTexture8_GetPriority(p)               (p)->lpVtbl->GetPriority(p)
+#define IDirect3DTexture8_PreLoad(p)                   (p)->lpVtbl->PreLoad(p)
+#define IDirect3DTexture8_GetType(p)                   (p)->lpVtbl->GetType(p)
+/*** IDirect3DTexture8 methods: IDirect3DBaseTexture8 ***/
+#define IDirect3DTexture8_SetLOD(p,a)                  (p)->lpVtbl->SetLOD(p,a)
+#define IDirect3DTexture8_GetLOD(p)                    (p)->lpVtbl->GetLOD(p)
+#define IDirect3DTexture8_GetLevelCount(p)             (p)->lpVtbl->GetLevelCount(p)
+/*** IDirect3DTexture8 methods ***/
+#define IDirect3DTexture8_GetLevelDesc(p,a,b)          (p)->lpVtbl->GetLevelDesc(p,a,b)
+#define IDirect3DTexture8_GetSurfaceLevel(p,a,b)       (p)->lpVtbl->GetSurfaceLevel(p,a,b)
+#define IDirect3DTexture8_LockRect(p,a,b,c,d)          (p)->lpVtbl->LockRect(p,a,b,c,d)
+#define IDirect3DTexture8_UnlockRect(p,a)              (p)->lpVtbl->UnlockRect(p,a)
+#define IDirect3DTexture8_AddDirtyRect(p,a)            (p)->lpVtbl->AddDirtyRect(p,a)
+#else
+/*** IUnknown methods ***/
+#define IDirect3DTexture8_QueryInterface(p,a,b)        (p)->QueryInterface(a,b)
+#define IDirect3DTexture8_AddRef(p)                    (p)->AddRef()
+#define IDirect3DTexture8_Release(p)                   (p)->Release()
+/*** IDirect3DTexture8 methods: IDirect3DResource8 ***/
+#define IDirect3DTexture8_GetDevice(p,a)               (p)->GetDevice(a)
+#define IDirect3DTexture8_SetPrivateData(p,a,b,c,d)    (p)->SetPrivateData(a,b,c,d)
+#define IDirect3DTexture8_GetPrivateData(p,a,b,c)      (p)->GetPrivateData(a,b,c)
+#define IDirect3DTexture8_FreePrivateData(p,a)         (p)->FreePrivateData(a)
+#define IDirect3DTexture8_SetPriority(p,a)             (p)->SetPriority(a)
+#define IDirect3DTexture8_GetPriority(p)               (p)->GetPriority()
+#define IDirect3DTexture8_PreLoad(p)                   (p)->PreLoad()
+#define IDirect3DTexture8_GetType(p)                   (p)->GetType()
+/*** IDirect3DTexture8 methods: IDirect3DBaseTexture8 ***/
+#define IDirect3DTexture8_SetLOD(p,a)                  (p)->SetLOD(a)
+#define IDirect3DTexture8_GetLOD(p)                    (p)->GetLOD()
+#define IDirect3DTexture8_GetLevelCount(p)             (p)->GetLevelCount()
+/*** IDirect3DTexture8 methods ***/
+#define IDirect3DTexture8_GetLevelDesc(p,a,b)          (p)->GetLevelDesc(a,b)
+#define IDirect3DTexture8_GetSurfaceLevel(p,a,b)       (p)->GetSurfaceLevel(a,b)
+#define IDirect3DTexture8_LockRect(p,a,b,c,d)          (p)->LockRect(a,b,c,d)
+#define IDirect3DTexture8_UnlockRect(p,a)              (p)->UnlockRect(a)
+#define IDirect3DTexture8_AddDirtyRect(p,a)            (p)->AddDirtyRect(a)
+#endif
+
+/*****************************************************************************
+ * IDirect3DVolumeTexture8 interface
+ */
+#define INTERFACE IDirect3DVolumeTexture8
+DECLARE_INTERFACE_(IDirect3DVolumeTexture8,IDirect3DBaseTexture8)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IDirect3DResource8 methods ***/
+    STDMETHOD(GetDevice)(THIS_ struct IDirect3DDevice8 ** ppDevice) PURE;
+    STDMETHOD(SetPrivateData)(THIS_ REFGUID  refguid, CONST void * pData, DWORD  SizeOfData, DWORD  Flags) PURE;
+    STDMETHOD(GetPrivateData)(THIS_ REFGUID  refguid, void * pData, DWORD * pSizeOfData) PURE;
+    STDMETHOD(FreePrivateData)(THIS_ REFGUID  refguid) PURE;
+    STDMETHOD_(DWORD,SetPriority)(THIS_ DWORD  PriorityNew) PURE;
+    STDMETHOD_(DWORD,GetPriority)(THIS) PURE;
+    STDMETHOD_(void,PreLoad)(THIS) PURE;
+    STDMETHOD_(D3DRESOURCETYPE,GetType)(THIS) PURE;
+    /*** IDirect3DBaseTexture8 methods ***/
+    STDMETHOD_(DWORD,SetLOD)(THIS_ DWORD  LODNew) PURE;
+    STDMETHOD_(DWORD,GetLOD)(THIS) PURE;
+    STDMETHOD_(DWORD,GetLevelCount)(THIS) PURE;
+    /*** IDirect3DVolumeTexture8 methods ***/
+    STDMETHOD(GetLevelDesc)(THIS_ UINT  Level,D3DVOLUME_DESC * pDesc) PURE;
+    STDMETHOD(GetVolumeLevel)(THIS_ UINT  Level,IDirect3DVolume8 ** ppVolumeLevel) PURE;
+    STDMETHOD(LockBox)(THIS_ UINT  Level,D3DLOCKED_BOX * pLockedVolume,CONST D3DBOX * pBox,DWORD  Flags) PURE;
+    STDMETHOD(UnlockBox)(THIS_ UINT  Level) PURE;
+    STDMETHOD(AddDirtyBox)(THIS_ CONST D3DBOX * pDirtyBox) PURE;
+};
+#undef INTERFACE
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+/*** IUnknown methods ***/
+#define IDirect3DVolumeTexture8_QueryInterface(p,a,b)        (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DVolumeTexture8_AddRef(p)                    (p)->lpVtbl->AddRef(p)
+#define IDirect3DVolumeTexture8_Release(p)                   (p)->lpVtbl->Release(p)
+/*** IDirect3DVolumeTexture8 methods: IDirect3DResource8 ***/
+#define IDirect3DVolumeTexture8_GetDevice(p,a)               (p)->lpVtbl->GetDevice(p,a)
+#define IDirect3DVolumeTexture8_SetPrivateData(p,a,b,c,d)    (p)->lpVtbl->SetPrivateData(p,a,b,c,d)
+#define IDirect3DVolumeTexture8_GetPrivateData(p,a,b,c)      (p)->lpVtbl->GetPrivateData(p,a,b,c)
+#define IDirect3DVolumeTexture8_FreePrivateData(p,a)         (p)->lpVtbl->FreePrivateData(p,a)
+#define IDirect3DVolumeTexture8_SetPriority(p,a)             (p)->lpVtbl->SetPriority(p,a)
+#define IDirect3DVolumeTexture8_GetPriority(p)               (p)->lpVtbl->GetPriority(p)
+#define IDirect3DVolumeTexture8_PreLoad(p)                   (p)->lpVtbl->PreLoad(p)
+#define IDirect3DVolumeTexture8_GetType(p)                   (p)->lpVtbl->GetType(p)
+/*** IDirect3DVolumeTexture8 methods: IDirect3DBaseTexture8 ***/
+#define IDirect3DVolumeTexture8_SetLOD(p,a)                  (p)->lpVtbl->SetLOD(p,a)
+#define IDirect3DVolumeTexture8_GetLOD(p)                    (p)->lpVtbl->GetLOD(p)
+#define IDirect3DVolumeTexture8_GetLevelCount(p)             (p)->lpVtbl->GetLevelCount(p)
+/*** IDirect3DVolumeTexture8 methods ***/
+#define IDirect3DVolumeTexture8_GetLevelDesc(p,a,b)          (p)->lpVtbl->GetLevelDesc(p,a,b)
+#define IDirect3DVolumeTexture8_GetVolumeLevel(p,a,b)        (p)->lpVtbl->GetVolumeLevel(p,a,b)
+#define IDirect3DVolumeTexture8_LockBox(p,a,b,c,d)           (p)->lpVtbl->LockBox(p,a,b,c,d)
+#define IDirect3DVolumeTexture8_UnlockBox(p,a)               (p)->lpVtbl->UnlockBox(p,a)
+#define IDirect3DVolumeTexture8_AddDirtyBox(p,a)             (p)->lpVtbl->AddDirtyBox(p,a)
+#else
+/*** IUnknown methods ***/
+#define IDirect3DVolumeTexture8_QueryInterface(p,a,b)        (p)->QueryInterface(a,b)
+#define IDirect3DVolumeTexture8_AddRef(p)                    (p)->AddRef()
+#define IDirect3DVolumeTexture8_Release(p)                   (p)->Release()
+/*** IDirect3DVolumeTexture8 methods: IDirect3DResource8 ***/
+#define IDirect3DVolumeTexture8_GetDevice(p,a)               (p)->GetDevice(a)
+#define IDirect3DVolumeTexture8_SetPrivateData(p,a,b,c,d)    (p)->SetPrivateData(a,b,c,d)
+#define IDirect3DVolumeTexture8_GetPrivateData(p,a,b,c)      (p)->GetPrivateData(a,b,c)
+#define IDirect3DVolumeTexture8_FreePrivateData(p,a)         (p)->FreePrivateData(a)
+#define IDirect3DVolumeTexture8_SetPriority(p,a)             (p)->SetPriority(a)
+#define IDirect3DVolumeTexture8_GetPriority(p)               (p)->GetPriority()
+#define IDirect3DVolumeTexture8_PreLoad(p)                   (p)->PreLoad()
+#define IDirect3DVolumeTexture8_GetType(p)                   (p)->GetType()
+/*** IDirect3DVolumeTexture8 methods: IDirect3DBaseTexture8 ***/
+#define IDirect3DVolumeTexture8_SetLOD(p,a)                  (p)->SetLOD(a)
+#define IDirect3DVolumeTexture8_GetLOD(p)                    (p)->GetLOD()
+#define IDirect3DVolumeTexture8_GetLevelCount(p)             (p)->GetLevelCount()
+/*** IDirect3DVolumeTexture8 methods ***/
+#define IDirect3DVolumeTexture8_GetLevelDesc(p,a,b)          (p)->GetLevelDesc(a,b)
+#define IDirect3DVolumeTexture8_GetVolumeLevel(p,a,b)        (p)->GetVolumeLevel(a,b)
+#define IDirect3DVolumeTexture8_LockBox(p,a,b,c,d)           (p)->LockBox(a,b,c,d)
+#define IDirect3DVolumeTexture8_UnlockBox(p,a)               (p)->UnlockBox(a)
+#define IDirect3DVolumeTexture8_AddDirtyBox(p,a)             (p)->AddDirtyBox(a)
+#endif
+
+/*****************************************************************************
+ * IDirect3DDevice8 interface
+ */
+#define INTERFACE IDirect3DDevice8
+DECLARE_INTERFACE_(IDirect3DDevice8,IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IDirect3DDevice8 methods ***/
+    STDMETHOD(TestCooperativeLevel)(THIS) PURE;
+    STDMETHOD_(UINT,GetAvailableTextureMem)(THIS) PURE;
+    STDMETHOD(ResourceManagerDiscardBytes)(THIS_ DWORD  Bytes) PURE;
+    STDMETHOD(GetDirect3D)(THIS_ IDirect3D8 ** ppD3D8) PURE;
+    STDMETHOD(GetDeviceCaps)(THIS_ D3DCAPS8 * pCaps) PURE;
+    STDMETHOD(GetDisplayMode)(THIS_ D3DDISPLAYMODE * pMode) PURE;
+    STDMETHOD(GetCreationParameters)(THIS_ D3DDEVICE_CREATION_PARAMETERS  * pParameters) PURE;
+    STDMETHOD(SetCursorProperties)(THIS_ UINT  XHotSpot, UINT  YHotSpot, IDirect3DSurface8 * pCursorBitmap) PURE;
+    STDMETHOD_(void,SetCursorPosition)(THIS_ UINT  XScreenSpace, UINT  YScreenSpace,DWORD  Flags) PURE;
+    STDMETHOD_(BOOL,ShowCursor)(THIS_ BOOL  bShow) PURE;
+    STDMETHOD(CreateAdditionalSwapChain)(THIS_ D3DPRESENT_PARAMETERS * pPresentationParameters, IDirect3DSwapChain8 ** pSwapChain) PURE;
+    STDMETHOD(Reset)(THIS_ D3DPRESENT_PARAMETERS * pPresentationParameters) PURE;
+    STDMETHOD(Present)(THIS_ CONST RECT * pSourceRect,CONST RECT * pDestRect,HWND  hDestWindowOverride,CONST RGNDATA * pDirtyRegion) PURE;
+    STDMETHOD(GetBackBuffer)(THIS_ UINT  BackBuffer,D3DBACKBUFFER_TYPE  Type,IDirect3DSurface8 ** ppBackBuffer) PURE;
+    STDMETHOD(GetRasterStatus)(THIS_ D3DRASTER_STATUS * pRasterStatus) PURE;
+    STDMETHOD_(void,SetGammaRamp)(THIS_ DWORD  Flags,CONST D3DGAMMARAMP * pRamp) PURE;
+    STDMETHOD_(void,GetGammaRamp)(THIS_ D3DGAMMARAMP * pRamp) PURE;
+    STDMETHOD(CreateTexture)(THIS_ UINT  Width,UINT  Height,UINT  Levels,DWORD  Usage,D3DFORMAT  Format,D3DPOOL  Pool,IDirect3DTexture8 ** ppTexture) PURE;
+    STDMETHOD(CreateVolumeTexture)(THIS_ UINT  Width,UINT  Height,UINT  Depth,UINT  Levels,DWORD  Usage,D3DFORMAT  Format,D3DPOOL  Pool,IDirect3DVolumeTexture8 ** ppVolumeTexture) PURE;
+    STDMETHOD(CreateCubeTexture)(THIS_ UINT  EdgeLength,UINT  Levels,DWORD  Usage,D3DFORMAT  Format,D3DPOOL  Pool,IDirect3DCubeTexture8 ** ppCubeTexture) PURE;
+    STDMETHOD(CreateVertexBuffer)(THIS_ UINT  Length,DWORD  Usage,DWORD  FVF,D3DPOOL  Pool,IDirect3DVertexBuffer8 ** ppVertexBuffer) PURE;
+    STDMETHOD(CreateIndexBuffer)(THIS_ UINT  Length,DWORD  Usage,D3DFORMAT  Format,D3DPOOL  Pool,IDirect3DIndexBuffer8 ** ppIndexBuffer) PURE;
+    STDMETHOD(CreateRenderTarget)(THIS_ UINT  Width,UINT  Height,D3DFORMAT  Format,D3DMULTISAMPLE_TYPE  MultiSample,BOOL  Lockable,IDirect3DSurface8 ** ppSurface) PURE;
+    STDMETHOD(CreateDepthStencilSurface)(THIS_ UINT  Width,UINT  Height,D3DFORMAT  Format,D3DMULTISAMPLE_TYPE  MultiSample,IDirect3DSurface8 ** ppSurface) PURE;
+    STDMETHOD(CreateImageSurface)(THIS_ UINT  Width,UINT  Height,D3DFORMAT  Format,IDirect3DSurface8 ** ppSurface) PURE;
+    STDMETHOD(CopyRects)(THIS_ IDirect3DSurface8 * pSourceSurface,CONST RECT * pSourceRectsArray,UINT  cRects,IDirect3DSurface8 * pDestinationSurface,CONST POINT * pDestPointsArray) PURE;
+    STDMETHOD(UpdateTexture)(THIS_ IDirect3DBaseTexture8 * pSourceTexture,IDirect3DBaseTexture8 * pDestinationTexture) PURE;
+    STDMETHOD(GetFrontBuffer)(THIS_ IDirect3DSurface8 * pDestSurface) PURE;
+    STDMETHOD(SetRenderTarget)(THIS_ IDirect3DSurface8 * pRenderTarget,IDirect3DSurface8 * pNewZStencil) PURE;
+    STDMETHOD(GetRenderTarget)(THIS_ IDirect3DSurface8 ** ppRenderTarget) PURE;
+    STDMETHOD(GetDepthStencilSurface)(THIS_ IDirect3DSurface8 ** ppZStencilSurface) PURE;
+    STDMETHOD(BeginScene)(THIS) PURE;
+    STDMETHOD(EndScene)(THIS) PURE;
+    STDMETHOD(Clear)(THIS_ DWORD  Count,CONST D3DRECT * pRects,DWORD  Flags,D3DCOLOR  Color,float  Z,DWORD  Stencil) PURE;
+    STDMETHOD(SetTransform)(THIS_ D3DTRANSFORMSTATETYPE  State,CONST D3DMATRIX * pMatrix) PURE;
+    STDMETHOD(GetTransform)(THIS_ D3DTRANSFORMSTATETYPE  State,D3DMATRIX * pMatrix) PURE;
+    STDMETHOD(MultiplyTransform)(THIS_ D3DTRANSFORMSTATETYPE  State, CONST D3DMATRIX * pMatrix) PURE;
+    STDMETHOD(SetViewport)(THIS_ CONST D3DVIEWPORT8 * pViewport) PURE;
+    STDMETHOD(GetViewport)(THIS_ D3DVIEWPORT8 * pViewport) PURE;
+    STDMETHOD(SetMaterial)(THIS_ CONST D3DMATERIAL8 * pMaterial) PURE;
+    STDMETHOD(GetMaterial)(THIS_ D3DMATERIAL8 *pMaterial) PURE;
+    STDMETHOD(SetLight)(THIS_ DWORD  Index,CONST D3DLIGHT8 * pLight) PURE;
+    STDMETHOD(GetLight)(THIS_ DWORD  Index,D3DLIGHT8 * pLight) PURE;
+    STDMETHOD(LightEnable)(THIS_ DWORD  Index,BOOL  Enable) PURE;
+    STDMETHOD(GetLightEnable)(THIS_ DWORD  Index,BOOL * pEnable) PURE;
+    STDMETHOD(SetClipPlane)(THIS_ DWORD  Index,CONST float * pPlane) PURE;
+    STDMETHOD(GetClipPlane)(THIS_ DWORD  Index,float * pPlane) PURE;
+    STDMETHOD(SetRenderState)(THIS_ D3DRENDERSTATETYPE  State,DWORD  Value) PURE;
+    STDMETHOD(GetRenderState)(THIS_ D3DRENDERSTATETYPE  State,DWORD * pValue) PURE;
+    STDMETHOD(BeginStateBlock)(THIS) PURE;
+    STDMETHOD(EndStateBlock)(THIS_ DWORD * pToken) PURE;
+    STDMETHOD(ApplyStateBlock)(THIS_ DWORD  Token) PURE;
+    STDMETHOD(CaptureStateBlock)(THIS_ DWORD  Token) PURE;
+    STDMETHOD(DeleteStateBlock)(THIS_ DWORD  Token) PURE;
+    STDMETHOD(CreateStateBlock)(THIS_ D3DSTATEBLOCKTYPE  Type,DWORD * pToken) PURE;
+    STDMETHOD(SetClipStatus)(THIS_ CONST D3DCLIPSTATUS8 * pClipStatus) PURE;
+    STDMETHOD(GetClipStatus)(THIS_ D3DCLIPSTATUS8 * pClipStatus) PURE;
+    STDMETHOD(GetTexture)(THIS_ DWORD  Stage,IDirect3DBaseTexture8 ** ppTexture) PURE;
+    STDMETHOD(SetTexture)(THIS_ DWORD  Stage,IDirect3DBaseTexture8 * pTexture) PURE;
+    STDMETHOD(GetTextureStageState)(THIS_ DWORD  Stage,D3DTEXTURESTAGESTATETYPE  Type,DWORD * pValue) PURE;
+    STDMETHOD(SetTextureStageState)(THIS_ DWORD  Stage,D3DTEXTURESTAGESTATETYPE  Type,DWORD  Value) PURE;
+    STDMETHOD(ValidateDevice)(THIS_ DWORD * pNumPasses) PURE;
+    STDMETHOD(GetInfo)(THIS_ DWORD  DevInfoID,void * pDevInfoStruct,DWORD  DevInfoStructSize) PURE;
+    STDMETHOD(SetPaletteEntries)(THIS_ UINT  PaletteNumber,CONST PALETTEENTRY * pEntries) PURE;
+    STDMETHOD(GetPaletteEntries)(THIS_ UINT  PaletteNumber,PALETTEENTRY * pEntries) PURE;
+    STDMETHOD(SetCurrentTexturePalette)(THIS_ UINT  PaletteNumber) PURE;
+    STDMETHOD(GetCurrentTexturePalette)(THIS_ UINT  * PaletteNumber) PURE;
+    STDMETHOD(DrawPrimitive)(THIS_ D3DPRIMITIVETYPE  PrimitiveType,UINT  StartVertex,UINT  PrimitiveCount) PURE;
+    STDMETHOD(DrawIndexedPrimitive)(THIS_ D3DPRIMITIVETYPE  PrimitiveType,UINT  minIndex,UINT  NumVertices,UINT  startIndex,UINT  primCount) PURE;
+    STDMETHOD(DrawPrimitiveUP)(THIS_ D3DPRIMITIVETYPE  PrimitiveType,UINT  PrimitiveCount,CONST void * pVertexStreamZeroData,UINT  VertexStreamZeroStride) PURE;
+    STDMETHOD(DrawIndexedPrimitiveUP)(THIS_ D3DPRIMITIVETYPE  PrimitiveType,UINT  MinVertexIndex,UINT  NumVertexIndices,UINT  PrimitiveCount,CONST void * pIndexData,D3DFORMAT  IndexDataFormat,CONST void * pVertexStreamZeroData,UINT  VertexStreamZeroStride) PURE;
+    STDMETHOD(ProcessVertices)(THIS_ UINT  SrcStartIndex,UINT  DestIndex,UINT  VertexCount,IDirect3DVertexBuffer8 * pDestBuffer,DWORD  Flags) PURE;
+    STDMETHOD(CreateVertexShader)(THIS_ CONST DWORD * pDeclaration,CONST DWORD * pFunction,DWORD * pHandle,DWORD  Usage) PURE;
+    STDMETHOD(SetVertexShader)(THIS_ DWORD  Handle) PURE;
+    STDMETHOD(GetVertexShader)(THIS_ DWORD * pHandle) PURE;
+    STDMETHOD(DeleteVertexShader)(THIS_ DWORD  Handle) PURE;
+    STDMETHOD(SetVertexShaderConstant)(THIS_ DWORD  Register,CONST void * pConstantData,DWORD  ConstantCount) PURE;
+    STDMETHOD(GetVertexShaderConstant)(THIS_ DWORD  Register,void * pConstantData,DWORD  ConstantCount) PURE;
+    STDMETHOD(GetVertexShaderDeclaration)(THIS_ DWORD  Handle,void * pData,DWORD * pSizeOfData) PURE;
+    STDMETHOD(GetVertexShaderFunction)(THIS_ DWORD  Handle,void * pData,DWORD * pSizeOfData) PURE;
+    STDMETHOD(SetStreamSource)(THIS_ UINT  StreamNumber,IDirect3DVertexBuffer8 * pStreamData,UINT  Stride) PURE;
+    STDMETHOD(GetStreamSource)(THIS_ UINT  StreamNumber,IDirect3DVertexBuffer8 ** ppStreamData,UINT * pStride) PURE;
+    STDMETHOD(SetIndices)(THIS_ IDirect3DIndexBuffer8 * pIndexData,UINT  BaseVertexIndex) PURE;
+    STDMETHOD(GetIndices)(THIS_ IDirect3DIndexBuffer8 ** ppIndexData,UINT * pBaseVertexIndex) PURE;
+    STDMETHOD(CreatePixelShader)(THIS_ CONST DWORD * pFunction,DWORD * pHandle) PURE;
+    STDMETHOD(SetPixelShader)(THIS_ DWORD  Handle) PURE;
+    STDMETHOD(GetPixelShader)(THIS_ DWORD * pHandle) PURE;
+    STDMETHOD(DeletePixelShader)(THIS_ DWORD  Handle) PURE;
+    STDMETHOD(SetPixelShaderConstant)(THIS_ DWORD  Register,CONST void * pConstantData,DWORD  ConstantCount) PURE;
+    STDMETHOD(GetPixelShaderConstant)(THIS_ DWORD  Register,void * pConstantData,DWORD  ConstantCount) PURE;
+    STDMETHOD(GetPixelShaderFunction)(THIS_ DWORD  Handle,void * pData,DWORD * pSizeOfData) PURE;
+    STDMETHOD(DrawRectPatch)(THIS_ UINT  Handle,CONST float * pNumSegs,CONST D3DRECTPATCH_INFO * pRectPatchInfo) PURE;
+    STDMETHOD(DrawTriPatch)(THIS_ UINT  Handle,CONST float * pNumSegs,CONST D3DTRIPATCH_INFO * pTriPatchInfo) PURE;
+    STDMETHOD(DeletePatch)(THIS_ UINT  Handle) PURE;
+};
+#undef INTERFACE
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+/*** IUnknown methods ***/
+#define IDirect3DDevice8_QueryInterface(p,a,b)                     (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DDevice8_AddRef(p)                                 (p)->lpVtbl->AddRef(p)
+#define IDirect3DDevice8_Release(p)                                (p)->lpVtbl->Release(p)
+/*** IDirect3DDevice8 methods ***/
+#define IDirect3DDevice8_TestCooperativeLevel(p)                   (p)->lpVtbl->TestCooperativeLevel(p)
+#define IDirect3DDevice8_GetAvailableTextureMem(p)                 (p)->lpVtbl->GetAvailableTextureMem(p)
+#define IDirect3DDevice8_ResourceManagerDiscardBytes(p,a)          (p)->lpVtbl->ResourceManagerDiscardBytes(p,a)
+#define IDirect3DDevice8_GetDirect3D(p,a)                          (p)->lpVtbl->GetDirect3D(p,a)
+#define IDirect3DDevice8_GetDeviceCaps(p,a)                        (p)->lpVtbl->GetDeviceCaps(p,a)
+#define IDirect3DDevice8_GetDisplayMode(p,a)                       (p)->lpVtbl->GetDisplayMode(p,a)
+#define IDirect3DDevice8_GetCreationParameters(p,a)                (p)->lpVtbl->GetCreationParameters(p,a)
+#define IDirect3DDevice8_SetCursorProperties(p,a,b,c)              (p)->lpVtbl->SetCursorProperties(p,a,b,c)
+#define IDirect3DDevice8_SetCursorPosition(p,a,b,c)                (p)->lpVtbl->SetCursorPosition(p,a,b,c)
+#define IDirect3DDevice8_ShowCursor(p,a)                           (p)->lpVtbl->ShowCursor(p,a)
+#define IDirect3DDevice8_CreateAdditionalSwapChain(p,a,b)          (p)->lpVtbl->CreateAdditionalSwapChain(p,a,b)
+#define IDirect3DDevice8_Reset(p,a)                                (p)->lpVtbl->Reset(p,a)
+#define IDirect3DDevice8_Present(p,a,b,c,d)                        (p)->lpVtbl->Present(p,a,b,c,d)
+#define IDirect3DDevice8_GetBackBuffer(p,a,b,c)                    (p)->lpVtbl->GetBackBuffer(p,a,b,c)
+#define IDirect3DDevice8_GetRasterStatus(p,a)                      (p)->lpVtbl->GetRasterStatus(p,a)
+#define IDirect3DDevice8_SetGammaRamp(p,a,b)                       (p)->lpVtbl->SetGammaRamp(p,a,b)
+#define IDirect3DDevice8_GetGammaRamp(p,a)                         (p)->lpVtbl->GetGammaRamp(p,a)
+#define IDirect3DDevice8_CreateTexture(p,a,b,c,d,e,f,g)            (p)->lpVtbl->CreateTexture(p,a,b,c,d,e,f,g)
+#define IDirect3DDevice8_CreateVolumeTexture(p,a,b,c,d,e,f,g,h)    (p)->lpVtbl->CreateVolumeTexture(p,a,b,c,d,e,f,g,h)
+#define IDirect3DDevice8_CreateCubeTexture(p,a,b,c,d,e,f)          (p)->lpVtbl->CreateCubeTexture(p,a,b,c,d,e,f)
+#define IDirect3DDevice8_CreateVertexBuffer(p,a,b,c,d,e)           (p)->lpVtbl->CreateVertexBuffer(p,a,b,c,d,e)
+#define IDirect3DDevice8_CreateIndexBuffer(p,a,b,c,d,e)            (p)->lpVtbl->CreateIndexBuffer(p,a,b,c,d,e)
+#define IDirect3DDevice8_CreateRenderTarget(p,a,b,c,d,e,f)         (p)->lpVtbl->CreateRenderTarget(p,a,b,c,d,e,f)
+#define IDirect3DDevice8_CreateDepthStencilSurface(p,a,b,c,d,e)    (p)->lpVtbl->CreateDepthStencilSurface(p,a,b,c,d,e)
+#define IDirect3DDevice8_CreateImageSurface(p,a,b,c,d)             (p)->lpVtbl->CreateImageSurface(p,a,b,c,d)
+#define IDirect3DDevice8_CopyRects(p,a,b,c,d,e)                    (p)->lpVtbl->CopyRects(p,a,b,c,d,e)
+#define IDirect3DDevice8_UpdateTexture(p,a,b)                      (p)->lpVtbl->UpdateTexture(p,a,b)
+#define IDirect3DDevice8_GetFrontBuffer(p,a)                       (p)->lpVtbl->GetFrontBuffer(p,a)
+#define IDirect3DDevice8_SetRenderTarget(p,a,b)                    (p)->lpVtbl->SetRenderTarget(p,a,b)
+#define IDirect3DDevice8_GetRenderTarget(p,a)                      (p)->lpVtbl->GetRenderTarget(p,a)
+#define IDirect3DDevice8_GetDepthStencilSurface(p,a)               (p)->lpVtbl->GetDepthStencilSurface(p,a)
+#define IDirect3DDevice8_BeginScene(p)                             (p)->lpVtbl->BeginScene(p)
+#define IDirect3DDevice8_EndScene(p)                               (p)->lpVtbl->EndScene(p)
+#define IDirect3DDevice8_Clear(p,a,b,c,d,e,f)                      (p)->lpVtbl->Clear(p,a,b,c,d,e,f)
+#define IDirect3DDevice8_SetTransform(p,a,b)                       (p)->lpVtbl->SetTransform(p,a,b)
+#define IDirect3DDevice8_GetTransform(p,a,b)                       (p)->lpVtbl->GetTransform(p,a,b)
+#define IDirect3DDevice8_MultiplyTransform(p,a,b)                  (p)->lpVtbl->MultiplyTransform(p,a,b)
+#define IDirect3DDevice8_SetViewport(p,a)                          (p)->lpVtbl->SetViewport(p,a)
+#define IDirect3DDevice8_GetViewport(p,a)                          (p)->lpVtbl->GetViewport(p,a)
+#define IDirect3DDevice8_SetMaterial(p,a)                          (p)->lpVtbl->SetMaterial(p,a)
+#define IDirect3DDevice8_GetMaterial(p,a)                          (p)->lpVtbl->GetMaterial(p,a)
+#define IDirect3DDevice8_SetLight(p,a,b)                           (p)->lpVtbl->SetLight(p,a,b)
+#define IDirect3DDevice8_GetLight(p,a,b)                           (p)->lpVtbl->GetLight(p,a,b)
+#define IDirect3DDevice8_LightEnable(p,a,b)                        (p)->lpVtbl->LightEnable(p,a,b)
+#define IDirect3DDevice8_GetLightEnable(p,a,b)                     (p)->lpVtbl->GetLightEnable(p,a,b)
+#define IDirect3DDevice8_SetClipPlane(p,a,b)                       (p)->lpVtbl->SetClipPlane(p,a,b)
+#define IDirect3DDevice8_GetClipPlane(p,a,b)                       (p)->lpVtbl->GetClipPlane(p,a,b)
+#define IDirect3DDevice8_SetRenderState(p,a,b)                     (p)->lpVtbl->SetRenderState(p,a,b)
+#define IDirect3DDevice8_GetRenderState(p,a,b)                     (p)->lpVtbl->GetRenderState(p,a,b)
+#define IDirect3DDevice8_BeginStateBlock(p)                        (p)->lpVtbl->BeginStateBlock(p)
+#define IDirect3DDevice8_EndStateBlock(p,a)                        (p)->lpVtbl->EndStateBlock(p,a)
+#define IDirect3DDevice8_ApplyStateBlock(p,a)                      (p)->lpVtbl->ApplyStateBlock(p,a)
+#define IDirect3DDevice8_CaptureStateBlock(p,a)                    (p)->lpVtbl->CaptureStateBlock(p,a)
+#define IDirect3DDevice8_DeleteStateBlock(p,a)                     (p)->lpVtbl->DeleteStateBlock(p,a)
+#define IDirect3DDevice8_CreateStateBlock(p,a,b)                   (p)->lpVtbl->CreateStateBlock(p,a,b)
+#define IDirect3DDevice8_SetClipStatus(p,a)                        (p)->lpVtbl->SetClipStatus(p,a)
+#define IDirect3DDevice8_GetClipStatus(p,a)                        (p)->lpVtbl->GetClipStatus(p,a)
+#define IDirect3DDevice8_GetTexture(p,a,b)                         (p)->lpVtbl->GetTexture(p,a,b)
+#define IDirect3DDevice8_SetTexture(p,a,b)                         (p)->lpVtbl->SetTexture(p,a,b)
+#define IDirect3DDevice8_GetTextureStageState(p,a,b,c)             (p)->lpVtbl->GetTextureStageState(p,a,b,c)
+#define IDirect3DDevice8_SetTextureStageState(p,a,b,c)             (p)->lpVtbl->SetTextureStageState(p,a,b,c)
+#define IDirect3DDevice8_ValidateDevice(p,a)                       (p)->lpVtbl->ValidateDevice(p,a)
+#define IDirect3DDevice8_GetInfo(p,a,b,c)                          (p)->lpVtbl->GetInfo(p,a,b,c)
+#define IDirect3DDevice8_SetPaletteEntries(p,a,b)                  (p)->lpVtbl->SetPaletteEntries(p,a,b)
+#define IDirect3DDevice8_GetPaletteEntries(p,a,b)                  (p)->lpVtbl->GetPaletteEntries(p,a,b)
+#define IDirect3DDevice8_SetCurrentTexturePalette(p,a)             (p)->lpVtbl->SetCurrentTexturePalette(p,a)
+#define IDirect3DDevice8_GetCurrentTexturePalette(p,a)             (p)->lpVtbl->GetCurrentTexturePalette(p,a)
+#define IDirect3DDevice8_DrawPrimitive(p,a,b,c)                    (p)->lpVtbl->DrawPrimitive(p,a,b,c)
+#define IDirect3DDevice8_DrawIndexedPrimitive(p,a,b,c,d,e)         (p)->lpVtbl->DrawIndexedPrimitive(p,a,b,c,d,e)
+#define IDirect3DDevice8_DrawPrimitiveUP(p,a,b,c,d)                (p)->lpVtbl->DrawPrimitiveUP(p,a,b,c,d)
+#define IDirect3DDevice8_DrawIndexedPrimitiveUP(p,a,b,c,d,e,f,g,h) (p)->lpVtbl->DrawIndexedPrimitiveUP(p,a,b,c,d,e,f,g,h)
+#define IDirect3DDevice8_ProcessVertices(p,a,b,c,d,e)              (p)->lpVtbl->processVertices(p,a,b,c,d,e)
+#define IDirect3DDevice8_CreateVertexShader(p,a,b,c,d)             (p)->lpVtbl->CreateVertexShader(p,a,b,c,d)
+#define IDirect3DDevice8_SetVertexShader(p,a)                      (p)->lpVtbl->SetVertexShader(p,a)
+#define IDirect3DDevice8_GetVertexShader(p,a)                      (p)->lpVtbl->GetVertexShader(p,a)
+#define IDirect3DDevice8_DeleteVertexShader(p,a)                   (p)->lpVtbl->DeleteVertexShader(p,a)
+#define IDirect3DDevice8_SetVertexShaderConstant(p,a,b,c)          (p)->lpVtbl->SetVertexShaderConstant(p,a,b,c)
+#define IDirect3DDevice8_GetVertexShaderConstant(p,a,b,c)          (p)->lpVtbl->GetVertexShaderConstant(p,a,b,c)
+#define IDirect3DDevice8_GetVertexShaderDeclaration(p,a,b,c)       (p)->lpVtbl->GetVertexShaderDeclaration(p,a,b,c)
+#define IDirect3DDevice8_GetVertexShaderFunction(p,a,b,c)          (p)->lpVtbl->GetVertexShaderFunction(p,a,b,c)
+#define IDirect3DDevice8_SetStreamSource(p,a,b,c)                  (p)->lpVtbl->SetStreamSource(p,a,b,c)
+#define IDirect3DDevice8_GetStreamSource(p,a,b,c)                  (p)->lpVtbl->GetStreamSource(p,a,b,c)
+#define IDirect3DDevice8_SetIndices(p,a,b)                         (p)->lpVtbl->SetIndices(p,a,b)
+#define IDirect3DDevice8_GetIndices(p,a,b)                         (p)->lpVtbl->GetIndices(p,a,b)
+#define IDirect3DDevice8_CreatePixelShader(p,a,b)                  (p)->lpVtbl->CreatePixelShader(p,a,b)
+#define IDirect3DDevice8_SetPixelShader(p,a)                       (p)->lpVtbl->SetPixelShader(p,a)
+#define IDirect3DDevice8_GetPixelShader(p,a)                       (p)->lpVtbl->GetPixelShader(p,a)
+#define IDirect3DDevice8_DeletePixelShader(p,a)                    (p)->lpVtbl->DeletePixelShader(p,a)
+#define IDirect3DDevice8_SetPixelShaderConstant(p,a,b,c)           (p)->lpVtbl->SetPixelShaderConstant(p,a,b,c)
+#define IDirect3DDevice8_GetPixelShaderConstant(p,a,b,c)           (p)->lpVtbl->GetPixelShaderConstant(p,a,b,c)
+#define IDirect3DDevice8_GetPixelShaderFunction(p,a,b,c)           (p)->lpVtbl->GetPixelShaderFunction(p,a,b,c)
+#define IDirect3DDevice8_DrawRectPatch(p,a,b,c)                    (p)->lpVtbl->DrawRectPatch(p,a,b,c)
+#define IDirect3DDevice8_DrawTriPatch(p,a,b,c)                     (p)->lpVtbl->DrawTriPatch(p,a,b,c)
+#define IDirect3DDevice8_DeletePatch(p,a)                          (p)->lpVtbl->DeletePatch(p,a)
+#else
+/*** IUnknown methods ***/
+#define IDirect3DDevice8_QueryInterface(p,a,b)                     (p)->QueryInterface(a,b)
+#define IDirect3DDevice8_AddRef(p)                                 (p)->AddRef()
+#define IDirect3DDevice8_Release(p)                                (p)->Release()
+/*** IDirect3DDevice8 methods ***/
+#define IDirect3DDevice8_TestCooperativeLevel(p)                   (p)->TestCooperativeLevel()
+#define IDirect3DDevice8_GetAvailableTextureMem(p)                 (p)->GetAvailableTextureMem()
+#define IDirect3DDevice8_ResourceManagerDiscardBytes(p,a)          (p)->ResourceManagerDiscardBytes(a)
+#define IDirect3DDevice8_GetDirect3D(p,a)                          (p)->GetDirect3D(a)
+#define IDirect3DDevice8_GetDeviceCaps(p,a)                        (p)->GetDeviceCaps(a)
+#define IDirect3DDevice8_GetDisplayMode(p,a)                       (p)->GetDisplayMode(a)
+#define IDirect3DDevice8_GetCreationParameters(p,a)                (p)->GetCreationParameters(a)
+#define IDirect3DDevice8_SetCursorProperties(p,a,b,c)              (p)->SetCursorProperties(a,b,c)
+#define IDirect3DDevice8_SetCursorPosition(p,a,b,c)                (p)->SetCursorPosition(a,b,c)
+#define IDirect3DDevice8_ShowCursor(p,a)                           (p)->ShowCursor(a)
+#define IDirect3DDevice8_CreateAdditionalSwapChain(p,a,b)          (p)->CreateAdditionalSwapChain(a,b)
+#define IDirect3DDevice8_Reset(p,a)                                (p)->Reset(a)
+#define IDirect3DDevice8_Present(p,a,b,c,d)                        (p)->Present(a,b,c,d)
+#define IDirect3DDevice8_GetBackBuffer(p,a,b,c)                    (p)->GetBackBuffer(a,b,c)
+#define IDirect3DDevice8_GetRasterStatus(p,a)                      (p)->GetRasterStatus(a)
+#define IDirect3DDevice8_SetGammaRamp(p,a,b)                       (p)->SetGammaRamp(a,b)
+#define IDirect3DDevice8_GetGammaRamp(p,a)                         (p)->GetGammaRamp(a)
+#define IDirect3DDevice8_CreateTexture(p,a,b,c,d,e,f,g)            (p)->CreateTexture(a,b,c,d,e,f,g)
+#define IDirect3DDevice8_CreateVolumeTexture(p,a,b,c,d,e,f,g,h)    (p)->CreateVolumeTexture(a,b,c,d,e,f,g,h)
+#define IDirect3DDevice8_CreateCubeTexture(p,a,b,c,d,e,f)          (p)->CreateCubeTexture(a,b,c,d,e,f)
+#define IDirect3DDevice8_CreateVertexBuffer(p,a,b,c,d,e)           (p)->CreateVertexBuffer(a,b,c,d,e)
+#define IDirect3DDevice8_CreateIndexBuffer(p,a,b,c,d,e)            (p)->CreateIndexBuffer(a,b,c,d,e)
+#define IDirect3DDevice8_CreateRenderTarget(p,a,b,c,d,e,f)         (p)->CreateRenderTarget(a,b,c,d,e,f)
+#define IDirect3DDevice8_CreateDepthStencilSurface(p,a,b,c,d,e)    (p)->CreateDepthStencilSurface(a,b,c,d,e)
+#define IDirect3DDevice8_CreateImageSurface(p,a,b,c,d)             (p)->CreateImageSurface(a,b,c,d)
+#define IDirect3DDevice8_CopyRects(p,a,b,c,d,e)                    (p)->CopyRects(a,b,c,d,e)
+#define IDirect3DDevice8_UpdateTexture(p,a,b)                      (p)->UpdateTexture(a,b)
+#define IDirect3DDevice8_GetFrontBuffer(p,a)                       (p)->GetFrontBuffer(a)
+#define IDirect3DDevice8_SetRenderTarget(p,a,b)                    (p)->SetRenderTarget(a,b)
+#define IDirect3DDevice8_GetRenderTarget(p,a)                      (p)->GetRenderTarget(a)
+#define IDirect3DDevice8_GetDepthStencilSurface(p,a)               (p)->GetDepthStencilSurface(a)
+#define IDirect3DDevice8_BeginScene(p)                             (p)->BeginScene()
+#define IDirect3DDevice8_EndScene(p)                               (p)->EndScene()
+#define IDirect3DDevice8_Clear(p,a,b,c,d,e,f)                      (p)->Clear(a,b,c,d,e,f)
+#define IDirect3DDevice8_SetTransform(p,a,b)                       (p)->SetTransform(a,b)
+#define IDirect3DDevice8_GetTransform(p,a,b)                       (p)->GetTransform(a,b)
+#define IDirect3DDevice8_MultiplyTransform(p,a,b)                  (p)->MultiplyTransform(a,b)
+#define IDirect3DDevice8_SetViewport(p,a)                          (p)->SetViewport(a)
+#define IDirect3DDevice8_GetViewport(p,a)                          (p)->GetViewport(a)
+#define IDirect3DDevice8_SetMaterial(p,a)                          (p)->SetMaterial(a)
+#define IDirect3DDevice8_GetMaterial(p,a)                          (p)->GetMaterial(a)
+#define IDirect3DDevice8_SetLight(p,a,b)                           (p)->SetLight(a,b)
+#define IDirect3DDevice8_GetLight(p,a,b)                           (p)->GetLight(a,b)
+#define IDirect3DDevice8_LightEnable(p,a,b)                        (p)->LightEnable(a,b)
+#define IDirect3DDevice8_GetLightEnable(p,a,b)                     (p)->GetLightEnable(a,b)
+#define IDirect3DDevice8_SetClipPlane(p,a,b)                       (p)->SetClipPlane(a,b)
+#define IDirect3DDevice8_GetClipPlane(p,a,b)                       (p)->GetClipPlane(a,b)
+#define IDirect3DDevice8_SetRenderState(p,a,b)                     (p)->SetRenderState(a,b)
+#define IDirect3DDevice8_GetRenderState(p,a,b)                     (p)->GetRenderState(a,b)
+#define IDirect3DDevice8_BeginStateBlock(p)                        (p)->BeginStateBlock()
+#define IDirect3DDevice8_EndStateBlock(p,a)                        (p)->EndStateBlock(a)
+#define IDirect3DDevice8_ApplyStateBlock(p,a)                      (p)->ApplyStateBlock(a)
+#define IDirect3DDevice8_CaptureStateBlock(p,a)                    (p)->CaptureStateBlock(a)
+#define IDirect3DDevice8_DeleteStateBlock(p,a)                     (p)->DeleteStateBlock(a)
+#define IDirect3DDevice8_CreateStateBlock(p,a,b)                   (p)->CreateStateBlock(a,b)
+#define IDirect3DDevice8_SetClipStatus(p,a)                        (p)->SetClipStatus(a)
+#define IDirect3DDevice8_GetClipStatus(p,a)                        (p)->GetClipStatus(a)
+#define IDirect3DDevice8_GetTexture(p,a,b)                         (p)->GetTexture(a,b)
+#define IDirect3DDevice8_SetTexture(p,a,b)                         (p)->SetTexture(a,b)
+#define IDirect3DDevice8_GetTextureStageState(p,a,b,c)             (p)->GetTextureStageState(a,b,c)
+#define IDirect3DDevice8_SetTextureStageState(p,a,b,c)             (p)->SetTextureStageState(a,b,c)
+#define IDirect3DDevice8_ValidateDevice(p,a)                       (p)->ValidateDevice(a)
+#define IDirect3DDevice8_GetInfo(p,a,b,c)                          (p)->GetInfo(a,b,c)
+#define IDirect3DDevice8_SetPaletteEntries(p,a,b)                  (p)->SetPaletteEntries(a,b)
+#define IDirect3DDevice8_GetPaletteEntries(p,a,b)                  (p)->GetPaletteEntries(a,b)
+#define IDirect3DDevice8_SetCurrentTexturePalette(p,a)             (p)->SetCurrentTexturePalette(a)
+#define IDirect3DDevice8_GetCurrentTexturePalette(p,a)             (p)->GetCurrentTexturePalette(a)
+#define IDirect3DDevice8_DrawPrimitive(p,a,b,c)                    (p)->DrawPrimitive(a,b,c)
+#define IDirect3DDevice8_DrawIndexedPrimitive(p,a,b,c,d,e)         (p)->DrawIndexedPrimitive(a,b,c,d,e)
+#define IDirect3DDevice8_DrawPrimitiveUP(p,a,b,c,d)                (p)->DrawPrimitiveUP(a,b,c,d)
+#define IDirect3DDevice8_DrawIndexedPrimitiveUP(p,a,b,c,d,e,f,g,h) (p)->DrawIndexedPrimitiveUP(a,b,c,d,e,f,g,h)
+#define IDirect3DDevice8_ProcessVertices(p,a,b,c,d,e)              (p)->processVertices(a,b,c,d,e)
+#define IDirect3DDevice8_CreateVertexShader(p,a,b,c,d)             (p)->CreateVertexShader(a,b,c,d)
+#define IDirect3DDevice8_SetVertexShader(p,a)                      (p)->SetVertexShader(a)
+#define IDirect3DDevice8_GetVertexShader(p,a)                      (p)->GetVertexShader(a)
+#define IDirect3DDevice8_DeleteVertexShader(p,a)                   (p)->DeleteVertexShader(a)
+#define IDirect3DDevice8_SetVertexShaderConstant(p,a,b,c)          (p)->SetVertexShaderConstant(a,b,c)
+#define IDirect3DDevice8_GetVertexShaderConstant(p,a,b,c)          (p)->GetVertexShaderConstant(a,b,c)
+#define IDirect3DDevice8_GetVertexShaderDeclaration(p,a,b,c)       (p)->GetVertexShaderDeclaration(a,b,c)
+#define IDirect3DDevice8_GetVertexShaderFunction(p,a,b,c)          (p)->GetVertexShaderFunction(a,b,c)
+#define IDirect3DDevice8_SetStreamSource(p,a,b,c)                  (p)->SetStreamSource(a,b,c)
+#define IDirect3DDevice8_GetStreamSource(p,a,b,c)                  (p)->GetStreamSource(a,b,c)
+#define IDirect3DDevice8_SetIndices(p,a,b)                         (p)->SetIndices(a,b)
+#define IDirect3DDevice8_GetIndices(p,a,b)                         (p)->GetIndices(a,b)
+#define IDirect3DDevice8_CreatePixelShader(p,a,b)                  (p)->CreatePixelShader(a,b)
+#define IDirect3DDevice8_SetPixelShader(p,a)                       (p)->SetPixelShader(a)
+#define IDirect3DDevice8_GetPixelShader(p,a)                       (p)->GetPixelShader(a)
+#define IDirect3DDevice8_DeletePixelShader(p,a)                    (p)->DeletePixelShader(a)
+#define IDirect3DDevice8_SetPixelShaderConstant(p,a,b,c)           (p)->SetPixelShaderConstant(a,b,c)
+#define IDirect3DDevice8_GetPixelShaderConstant(p,a,b,c)           (p)->GetPixelShaderConstant(a,b,c)
+#define IDirect3DDevice8_GetPixelShaderFunction(p,a,b,c)           (p)->GetPixelShaderFunction(a,b,c)
+#define IDirect3DDevice8_DrawRectPatch(p,a,b,c)                    (p)->DrawRectPatch(a,b,c)
+#define IDirect3DDevice8_DrawTriPatch(p,a,b,c)                     (p)->DrawTriPatch(a,b,c)
+#define IDirect3DDevice8_DeletePatch(p,a)                          (p)->DeletePatch(a)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif  /* defined(__cplusplus) */
+
+/* Define the main entrypoint as well */
+IDirect3D8* WINAPI Direct3DCreate8(UINT SDKVersion);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* defined(__cplusplus) */
+
+#endif /* __WINE_D3D8_H */
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/include/d3d9.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/include/d3d9.h	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/include/d3d9.h	(revision 46521)
@@ -0,0 +1,2054 @@
+/*
+ * Copyright (C) 2002-2003 Jason Edmeades
+ *                         Raphael Junqueira
+ *
+ * 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_D3D9_H
+#define __WINE_D3D9_H
+
+#ifndef DIRECT3D_VERSION
+#define DIRECT3D_VERSION  0x0900
+#endif
+
+#ifndef VBOX_WINE_WITHOUT_LIBWINE
+#include <stdlib.h>
+
+#define COM_NO_WINDOWS_H
+#include <objbase.h>
+#include <windows.h>
+#endif
+#include <d3d9types.h>
+#include <d3d9caps.h>
+#ifndef VBOX_WINE_WITHOUT_LIBWINE
+# include <d3dhal.h>
+# include <d3dtypes.h>
+# include <d3dcaps.h>
+#endif
+
+#define __MSABI_LONG(_n) _n##L
+
+/*****************************************************************************
+ * Behavior Flags for IDirect3D8::CreateDevice
+ */
+#define D3DCREATE_FPU_PRESERVE                  __MSABI_LONG(0x00000002)
+#define D3DCREATE_MULTITHREADED                 __MSABI_LONG(0x00000004)
+#define D3DCREATE_PUREDEVICE                    __MSABI_LONG(0x00000010)
+#define D3DCREATE_SOFTWARE_VERTEXPROCESSING     __MSABI_LONG(0x00000020)
+#define D3DCREATE_HARDWARE_VERTEXPROCESSING     __MSABI_LONG(0x00000040)
+#define D3DCREATE_MIXED_VERTEXPROCESSING        __MSABI_LONG(0x00000080)
+#define D3DCREATE_DISABLE_DRIVER_MANAGEMENT     __MSABI_LONG(0x00000100)
+#define D3DCREATE_ADAPTERGROUP_DEVICE           __MSABI_LONG(0x00000200)
+#define D3DCREATE_DISABLE_DRIVER_MANAGEMENT_EX  __MSABI_LONG(0x00000400)
+#define D3DCREATE_NOWINDOWCHANGES               __MSABI_LONG(0x00000800)
+#define D3DCREATE_DISABLE_PSGP_THREADING        __MSABI_LONG(0x00002000)
+#define D3DCREATE_ENABLE_PRESENTSTATS           __MSABI_LONG(0x00004000)
+#define D3DCREATE_DISABLE_PRINTSCREEN           __MSABI_LONG(0x00008000)
+#define D3DCREATE_SCREENSAVER                   __MSABI_LONG(0x10000000)
+
+/*****************************************************************************
+ * Flags for SetPrivateData
+ */
+#define D3DSPD_IUNKNOWN                         __MSABI_LONG(0x00000001)
+
+
+/*****************************************************************************
+ * #defines and error codes
+ */
+#define D3D_SDK_VERSION                         32
+#define D3DADAPTER_DEFAULT                      0
+#define D3DENUM_NO_WHQL_LEVEL                   __MSABI_LONG(0x00000002)
+#define D3DPRESENT_BACK_BUFFERS_MAX             __MSABI_LONG(3)
+#define D3DSGR_NO_CALIBRATION                   __MSABI_LONG(0x00000000)
+#define D3DSGR_CALIBRATE                        __MSABI_LONG(0x00000001)
+
+#define _FACD3D  0x876
+#define MAKE_D3DHRESULT( code )                 MAKE_HRESULT( 1, _FACD3D, code )
+#define MAKE_D3DSTATUS( code )                  MAKE_HRESULT( 0, _FACD3D, code )
+
+/*****************************************************************************
+ * Direct3D Errors
+ */
+#define D3D_OK                                  S_OK
+#define D3DERR_WRONGTEXTUREFORMAT               MAKE_D3DHRESULT(2072)
+#define D3DERR_UNSUPPORTEDCOLOROPERATION        MAKE_D3DHRESULT(2073)
+#define D3DERR_UNSUPPORTEDCOLORARG              MAKE_D3DHRESULT(2074)
+#define D3DERR_UNSUPPORTEDALPHAOPERATION        MAKE_D3DHRESULT(2075)
+#define D3DERR_UNSUPPORTEDALPHAARG              MAKE_D3DHRESULT(2076)
+#define D3DERR_TOOMANYOPERATIONS                MAKE_D3DHRESULT(2077)
+#define D3DERR_CONFLICTINGTEXTUREFILTER         MAKE_D3DHRESULT(2078)
+#define D3DERR_UNSUPPORTEDFACTORVALUE           MAKE_D3DHRESULT(2079)
+#define D3DERR_CONFLICTINGRENDERSTATE           MAKE_D3DHRESULT(2081)
+#define D3DERR_UNSUPPORTEDTEXTUREFILTER         MAKE_D3DHRESULT(2082)
+#define D3DERR_CONFLICTINGTEXTUREPALETTE        MAKE_D3DHRESULT(2086)
+#define D3DERR_DRIVERINTERNALERROR              MAKE_D3DHRESULT(2087)
+#define D3DERR_NOTFOUND                         MAKE_D3DHRESULT(2150)
+#define D3DERR_MOREDATA                         MAKE_D3DHRESULT(2151)
+#define D3DERR_DEVICELOST                       MAKE_D3DHRESULT(2152)
+#define D3DERR_DEVICENOTRESET                   MAKE_D3DHRESULT(2153)
+#define D3DERR_NOTAVAILABLE                     MAKE_D3DHRESULT(2154)
+#define D3DERR_OUTOFVIDEOMEMORY                 MAKE_D3DHRESULT(380)
+#define D3DERR_INVALIDDEVICE                    MAKE_D3DHRESULT(2155)
+#define D3DERR_INVALIDCALL                      MAKE_D3DHRESULT(2156)
+#define D3DERR_DRIVERINVALIDCALL                MAKE_D3DHRESULT(2157)
+#define D3DERR_WASSTILLDRAWING                  MAKE_D3DHRESULT(540)
+#define D3DOK_NOAUTOGEN                         MAKE_D3DSTATUS(2159)
+
+#define D3DERR_DEVICEREMOVED                    MAKE_D3DHRESULT(2160)
+#define D3DERR_DEVICEHUNG                       MAKE_D3DHRESULT(2164)
+#define S_NOT_RESIDENT                          MAKE_D3DSTATUS(2165)
+#define S_RESIDENT_IN_SHARED_MEMORY             MAKE_D3DSTATUS(2166)
+#define S_PRESENT_MODE_CHANGED                  MAKE_D3DSTATUS(2167)
+#define S_PRESENT_OCCLUDED                      MAKE_D3DSTATUS(2168)
+#define D3DERR_UNSUPPORTEDOVERLAY               MAKE_D3DHRESULT(2171)
+#define D3DERR_UNSUPPORTEDOVERLAYFORMAT         MAKE_D3DHRESULT(2172)
+#define D3DERR_CANNOTPROTECTCONTENT             MAKE_D3DHRESULT(2173)
+#define D3DERR_UNSUPPORTEDCRYPTO                MAKE_D3DHRESULT(2174)
+#define D3DERR_PRESENT_STATISTICS_DISJOINT      MAKE_D3DHRESULT(2180)
+
+
+/*****************************************************************************
+ * Predeclare the interfaces
+ */
+DEFINE_GUID(IID_IDirect3D9,                   0x81BDCBCA, 0x64D4, 0x426D, 0xAE, 0x8D, 0xAD, 0x1, 0x47, 0xF4, 0x27, 0x5C);
+typedef struct IDirect3D9 *LPDIRECT3D9, *PDIRECT3D9;
+
+DEFINE_GUID(IID_IDirect3D9Ex,                 0x02177241, 0x69FC, 0x400C, 0x8F, 0xF1, 0x93, 0xA4, 0x4D, 0xF6, 0x86, 0x1D);
+typedef struct IDirect3D9Ex *LPDIRECT3D9EX, *PDIRECT3D9EX;
+
+DEFINE_GUID(IID_IDirect3DDevice9,             0xd0223b96, 0xbf7a, 0x43fd, 0x92, 0xbd, 0xa4, 0x3b, 0xd, 0x82, 0xb9, 0xeb);
+typedef struct IDirect3DDevice9 *LPDIRECT3DDEVICE9;
+
+DEFINE_GUID(IID_IDirect3DDevice9Ex,           0xb18b10ce, 0x2649, 0x405a, 0x87, 0xf, 0x95, 0xf7, 0x77, 0xd4, 0x31, 0x3a);
+typedef struct IDirect3DDevice9Ex *LPDIRECT3DDEVICE9EX, *PDIRECT3DDEVICE9EX;
+
+DEFINE_GUID(IID_IDirect3DResource9,           0x5eec05d, 0x8f7d, 0x4362, 0xb9, 0x99, 0xd1, 0xba, 0xf3, 0x57, 0xc7, 0x4);
+typedef struct IDirect3DResource9 *LPDIRECT3DRESOURCE9, *PDIRECT3DRESOURCE9;
+
+DEFINE_GUID(IID_IDirect3DVertexBuffer9,       0xb64bb1b5, 0xfd70, 0x4df6, 0xbf, 0x91, 0x19, 0xd0, 0xa1, 0x24, 0x55, 0xe3);
+typedef struct IDirect3DVertexBuffer9 *LPDIRECT3DVERTEXBUFFER9, *PDIRECT3DVERTEXBUFFER9;
+
+DEFINE_GUID(IID_IDirect3DVolume9,             0x24f416e6, 0x1f67, 0x4aa7, 0xb8, 0x8e, 0xd3, 0x3f, 0x6f, 0x31, 0x28, 0xa1);
+typedef struct IDirect3DVolume9 *LPDIRECT3DVOLUME9, *PDIRECT3DVOLUME9;
+
+DEFINE_GUID(IID_IDirect3DSwapChain9,          0x794950f2, 0xadfc, 0x458a, 0x90, 0x5e, 0x10, 0xa1, 0xb, 0xb, 0x50, 0x3b);
+typedef struct IDirect3DSwapChain9 *LPDIRECT3DSWAPCHAIN9, *PDIRECT3DSWAPCHAIN9;
+
+DEFINE_GUID(IID_IDirect3DSwapChain9Ex,        0x91886caf, 0x1c3d, 0x4d2e, 0xa0, 0xab, 0x3e, 0x4c, 0x7d, 0x8d, 0x33, 0x3);
+typedef struct IDirect3DSwapChain9Ex *LPDIRECT3DSWAPCHAIN9EX, *PDIRECT3DSWAPCHAIN9EX;
+
+DEFINE_GUID(IID_IDirect3DSurface9,            0xcfbaf3a, 0x9ff6, 0x429a, 0x99, 0xb3, 0xa2, 0x79, 0x6a, 0xf8, 0xb8, 0x9b);
+typedef struct IDirect3DSurface9 *LPDIRECT3DSURFACE9, *PDIRECT3DSURFACE9;
+
+DEFINE_GUID(IID_IDirect3DIndexBuffer9,        0x7c9dd65e, 0xd3f7, 0x4529, 0xac, 0xee, 0x78, 0x58, 0x30, 0xac, 0xde, 0x35);
+typedef struct IDirect3DIndexBuffer9 *LPDIRECT3DINDEXBUFFER9, *PDIRECT3DINDEXBUFFER9;
+
+DEFINE_GUID(IID_IDirect3DBaseTexture9,        0x580ca87e, 0x1d3c, 0x4d54, 0x99, 0x1d, 0xb7, 0xd3, 0xe3, 0xc2, 0x98, 0xce);
+typedef struct IDirect3DBaseTexture9 *LPDIRECT3DBASETEXTURE9, *PDIRECT3DBASETEXTURE9;
+
+DEFINE_GUID(IID_IDirect3DTexture9,            0x85c31227, 0x3de5, 0x4f00, 0x9b, 0x3a, 0xf1, 0x1a, 0xc3, 0x8c, 0x18, 0xb5);
+typedef struct IDirect3DTexture9 *LPDIRECT3DTEXTURE9, *PDIRECT3DTEXTURE9;
+
+DEFINE_GUID(IID_IDirect3DCubeTexture9,        0xfff32f81, 0xd953, 0x473a, 0x92, 0x23, 0x93, 0xd6, 0x52, 0xab, 0xa9, 0x3f);
+typedef struct IDirect3DCubeTexture9 *LPDIRECT3DCUBETEXTURE9, *PDIRECT3DCUBETEXTURE9;
+
+DEFINE_GUID(IID_IDirect3DVolumeTexture9,      0x2518526c, 0xe789, 0x4111, 0xa7, 0xb9, 0x47, 0xef, 0x32, 0x8d, 0x13, 0xe6);
+typedef struct IDirect3DVolumeTexture9 *LPDIRECT3DVOLUMETEXTURE9, *PDIRECT3DVOLUMETEXTURE9;
+
+DEFINE_GUID(IID_IDirect3DVertexDeclaration9,  0xdd13c59c, 0x36fa, 0x4098, 0xa8, 0xfb, 0xc7, 0xed, 0x39, 0xdc, 0x85, 0x46);
+typedef struct IDirect3DVertexDeclaration9 *LPDIRECT3DVERTEXDECLARATION9;
+
+DEFINE_GUID(IID_IDirect3DVertexShader9,       0xefc5557e, 0x6265, 0x4613, 0x8a, 0x94, 0x43, 0x85, 0x78, 0x89, 0xeb, 0x36);
+typedef struct IDirect3DVertexShader9 *LPDIRECT3DVERTEXSHADER9;
+
+DEFINE_GUID(IID_IDirect3DPixelShader9,        0x6d3bdbdc, 0x5b02, 0x4415, 0xb8, 0x52, 0xce, 0x5e, 0x8b, 0xcc, 0xb2, 0x89);
+typedef struct IDirect3DPixelShader9 *LPDIRECT3DPIXELSHADER9;
+
+DEFINE_GUID(IID_IDirect3DStateBlock9,         0xb07c4fe5, 0x310d, 0x4ba8, 0xa2, 0x3c, 0x4f, 0xf, 0x20, 0x6f, 0x21, 0x8b);
+typedef struct IDirect3DStateBlock9 *LPDIRECT3DSTATEBLOCK9;
+
+DEFINE_GUID(IID_IDirect3DQuery9,              0xd9771460, 0xa695, 0x4f26, 0xbb, 0xd3, 0x27, 0xb8, 0x40, 0xb5, 0x41, 0xcc);
+typedef struct IDirect3DQuery9 *LPDIRECT3DQUERY9, *PDIRECT3DQUERY9;
+
+/*****************************************************************************
+ * IDirect3D9 interface
+ */
+#undef INTERFACE
+#define INTERFACE IDirect3D9
+DECLARE_INTERFACE_(IDirect3D9,IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IDirect3D9 methods ***/
+    STDMETHOD(RegisterSoftwareDevice)(THIS_ void* pInitializeFunction) PURE;
+    STDMETHOD_(UINT, GetAdapterCount)(THIS) PURE;
+    STDMETHOD(GetAdapterIdentifier)(THIS_ UINT Adapter, DWORD Flags, D3DADAPTER_IDENTIFIER9* pIdentifier) PURE;
+    STDMETHOD_(UINT, GetAdapterModeCount)(THIS_ UINT Adapter, D3DFORMAT Format) PURE;
+    STDMETHOD(EnumAdapterModes)(THIS_ UINT Adapter, D3DFORMAT Format, UINT Mode, D3DDISPLAYMODE* pMode) PURE;
+    STDMETHOD(GetAdapterDisplayMode)(THIS_ UINT Adapter, D3DDISPLAYMODE* pMode) PURE;
+    STDMETHOD(CheckDeviceType)(THIS_ UINT iAdapter, D3DDEVTYPE DevType, D3DFORMAT DisplayFormat, D3DFORMAT BackBufferFormat, BOOL bWindowed) PURE;
+    STDMETHOD(CheckDeviceFormat)(THIS_ UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, DWORD Usage, D3DRESOURCETYPE RType, D3DFORMAT CheckFormat) PURE;
+    STDMETHOD(CheckDeviceMultiSampleType)(THIS_ UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SurfaceFormat, BOOL Windowed, D3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) PURE;
+    STDMETHOD(CheckDepthStencilMatch)(THIS_ UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, D3DFORMAT RenderTargetFormat, D3DFORMAT DepthStencilFormat) PURE;
+    STDMETHOD(CheckDeviceFormatConversion)(THIS_ UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SourceFormat, D3DFORMAT TargetFormat) PURE;
+    STDMETHOD(GetDeviceCaps)(THIS_ UINT Adapter, D3DDEVTYPE DeviceType, D3DCAPS9* pCaps) PURE;
+    STDMETHOD_(HMONITOR, GetAdapterMonitor)(THIS_ UINT Adapter) PURE;
+    STDMETHOD(CreateDevice)(THIS_ UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, struct IDirect3DDevice9** ppReturnedDeviceInterface) PURE;
+};
+#undef INTERFACE
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+/*** IUnknown methods ***/
+#define IDirect3D9_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3D9_AddRef(p)             (p)->lpVtbl->AddRef(p)
+#define IDirect3D9_Release(p)            (p)->lpVtbl->Release(p)
+/*** IDirect3D9 methods ***/
+#define IDirect3D9_RegisterSoftwareDevice(p,a)                (p)->lpVtbl->RegisterSoftwareDevice(p,a)
+#define IDirect3D9_GetAdapterCount(p)                         (p)->lpVtbl->GetAdapterCount(p)
+#define IDirect3D9_GetAdapterIdentifier(p,a,b,c)              (p)->lpVtbl->GetAdapterIdentifier(p,a,b,c)
+#define IDirect3D9_GetAdapterModeCount(p,a,b)                 (p)->lpVtbl->GetAdapterModeCount(p,a,b)
+#define IDirect3D9_EnumAdapterModes(p,a,b,c,d)                (p)->lpVtbl->EnumAdapterModes(p,a,b,c,d)
+#define IDirect3D9_GetAdapterDisplayMode(p,a,b)               (p)->lpVtbl->GetAdapterDisplayMode(p,a,b)
+#define IDirect3D9_CheckDeviceType(p,a,b,c,d,e)               (p)->lpVtbl->CheckDeviceType(p,a,b,c,d,e)
+#define IDirect3D9_CheckDeviceFormat(p,a,b,c,d,e,f)           (p)->lpVtbl->CheckDeviceFormat(p,a,b,c,d,e,f)
+#define IDirect3D9_CheckDeviceMultiSampleType(p,a,b,c,d,e,f)  (p)->lpVtbl->CheckDeviceMultiSampleType(p,a,b,c,d,e,f)
+#define IDirect3D9_CheckDepthStencilMatch(p,a,b,c,d,e)        (p)->lpVtbl->CheckDepthStencilMatch(p,a,b,c,d,e)
+#define IDirect3D9_CheckDeviceFormatConversion(p,a,b,c,d)     (p)->lpVtbl->CheckDeviceFormatConversion(p,a,b,c,d)
+#define IDirect3D9_GetDeviceCaps(p,a,b,c)                     (p)->lpVtbl->GetDeviceCaps(p,a,b,c)
+#define IDirect3D9_GetAdapterMonitor(p,a)                     (p)->lpVtbl->GetAdapterMonitor(p,a)
+#define IDirect3D9_CreateDevice(p,a,b,c,d,e,f)                (p)->lpVtbl->CreateDevice(p,a,b,c,d,e,f)
+#else
+/*** IUnknown methods ***/
+#define IDirect3D9_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirect3D9_AddRef(p)             (p)->AddRef()
+#define IDirect3D9_Release(p)            (p)->Release()
+/*** IDirect3D9 methods ***/
+#define IDirect3D9_RegisterSoftwareDevice(p,a)                (p)->RegisterSoftwareDevice(a)
+#define IDirect3D9_GetAdapterCount(p)                         (p)->GetAdapterCount()
+#define IDirect3D9_GetAdapterIdentifier(p,a,b,c)              (p)->GetAdapterIdentifier(a,b,c)
+#define IDirect3D9_GetAdapterModeCount(p,a,b)                 (p)->GetAdapterModeCount(a,b)
+#define IDirect3D9_EnumAdapterModes(p,a,b,c,d)                (p)->EnumAdapterModes(a,b,c,d)
+#define IDirect3D9_GetAdapterDisplayMode(p,a,b)               (p)->GetAdapterDisplayMode(a,b)
+#define IDirect3D9_CheckDeviceType(p,a,b,c,d,e)               (p)->CheckDeviceType(a,b,c,d,e)
+#define IDirect3D9_CheckDeviceFormat(p,a,b,c,d,e,f)           (p)->CheckDeviceFormat(a,b,c,d,e,f)
+#define IDirect3D9_CheckDeviceMultiSampleType(p,a,b,c,d,e,f)  (p)->CheckDeviceMultiSampleType(a,b,c,d,e,f)
+#define IDirect3D9_CheckDepthStencilMatch(p,a,b,c,d,e)        (p)->CheckDepthStencilMatch(a,b,c,d,e)
+#define IDirect3D9_CheckDeviceFormatConversion(p,a,b,c,d)     (p)->CheckDeviceFormatConversion(a,b,c,d)
+#define IDirect3D9_GetDeviceCaps(p,a,b,c)                     (p)->GetDeviceCaps(a,b,c)
+#define IDirect3D9_GetAdapterMonitor(p,a)                     (p)->GetAdapterMonitor(a)
+#define IDirect3D9_CreateDevice(p,a,b,c,d,e,f)                (p)->CreateDevice(a,b,c,d,e,f)
+#endif
+
+/*****************************************************************************
+ * IDirect3D9Ex interface
+ */
+#define INTERFACE IDirect3D9Ex
+DECLARE_INTERFACE_(IDirect3D9Ex,IDirect3D9)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IDirect3D9 methods ***/
+
+    /* Note: Microsoft's d3d9.h does not declare IDirect3D9Ex::RegisterSoftwareDevice . This would mean that
+     * the offsets of the other methods in the Vtable change too. This is wrong. In Microsoft's
+     * d3d9.dll, the offsets for the other functions are still compatible with IDirect3D9.
+     * This is probably because even in MS header IDirect3D9Ex inherits from IDirect3D9, which makes the
+     * C++ interface compatible, and nobody uses the C interface in Windows world.
+     */
+    STDMETHOD(RegisterSoftwareDevice)(THIS_ void* pInitializeFunction) PURE;
+
+    STDMETHOD_(UINT, GetAdapterCount)(THIS) PURE;
+    STDMETHOD(GetAdapterIdentifier)(THIS_ UINT Adapter, DWORD Flags, D3DADAPTER_IDENTIFIER9* pIdentifier) PURE;
+    STDMETHOD_(UINT, GetAdapterModeCount)(THIS_ UINT Adapter, D3DFORMAT Format) PURE;
+    STDMETHOD(EnumAdapterModes)(THIS_ UINT Adapter, D3DFORMAT Format, UINT Mode, D3DDISPLAYMODE* pMode) PURE;
+    STDMETHOD(GetAdapterDisplayMode)(THIS_ UINT Adapter, D3DDISPLAYMODE* pMode) PURE;
+    STDMETHOD(CheckDeviceType)(THIS_ UINT iAdapter, D3DDEVTYPE DevType, D3DFORMAT DisplayFormat, D3DFORMAT BackBufferFormat, BOOL bWindowed) PURE;
+    STDMETHOD(CheckDeviceFormat)(THIS_ UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, DWORD Usage, D3DRESOURCETYPE RType, D3DFORMAT CheckFormat) PURE;
+    STDMETHOD(CheckDeviceMultiSampleType)(THIS_ UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SurfaceFormat, BOOL Windowed, D3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) PURE;
+    STDMETHOD(CheckDepthStencilMatch)(THIS_ UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, D3DFORMAT RenderTargetFormat, D3DFORMAT DepthStencilFormat) PURE;
+    STDMETHOD(CheckDeviceFormatConversion)(THIS_ UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SourceFormat, D3DFORMAT TargetFormat) PURE;
+    STDMETHOD(GetDeviceCaps)(THIS_ UINT Adapter, D3DDEVTYPE DeviceType, D3DCAPS9* pCaps) PURE;
+    STDMETHOD_(HMONITOR, GetAdapterMonitor)(THIS_ UINT Adapter) PURE;
+    STDMETHOD(CreateDevice)(THIS_ UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, struct IDirect3DDevice9** ppReturnedDeviceInterface) PURE;
+    /*** IDirect3D9Ex methods ***/
+    STDMETHOD_(UINT, GetAdapterModeCountEx)(THIS_ UINT Adapter, CONST D3DDISPLAYMODEFILTER *pFilter) PURE;
+    STDMETHOD(EnumAdapterModesEx)(THIS_ UINT Adapter, CONST D3DDISPLAYMODEFILTER *pFilter, UINT Mode, D3DDISPLAYMODEEX* pMode) PURE;
+    STDMETHOD(GetAdapterDisplayModeEx)(THIS_ UINT Adapter, D3DDISPLAYMODEEX *pMode, D3DDISPLAYROTATION *pRotation);
+    STDMETHOD(CreateDeviceEx)(THIS_ UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, D3DDISPLAYMODEEX* pFullscreenDisplayMode, struct IDirect3DDevice9Ex **ppReturnedDeviceInterface) PURE;
+    STDMETHOD(GetAdapterLUID)(THIS_ UINT Adatper, LUID *pLUID) PURE;
+};
+#undef INTERFACE
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+/*** IUnknown methods ***/
+#define IDirect3D9Ex_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3D9Ex_AddRef(p)             (p)->lpVtbl->AddRef(p)
+#define IDirect3D9Ex_Release(p)            (p)->lpVtbl->Release(p)
+/*** IDirect3D9 methods ***/
+#define IDirect3D9Ex_RegisterSoftwareDevice(p,a)                (p)->lpVtbl->RegisterSoftwareDevice(p,a)
+#define IDirect3D9Ex_GetAdapterCount(p)                         (p)->lpVtbl->GetAdapterCount(p)
+#define IDirect3D9Ex_GetAdapterIdentifier(p,a,b,c)              (p)->lpVtbl->GetAdapterIdentifier(p,a,b,c)
+#define IDirect3D9Ex_GetAdapterModeCount(p,a,b)                 (p)->lpVtbl->GetAdapterModeCount(p,a,b)
+#define IDirect3D9Ex_EnumAdapterModes(p,a,b,c,d)                (p)->lpVtbl->EnumAdapterModes(p,a,b,c,d)
+#define IDirect3D9Ex_GetAdapterDisplayMode(p,a,b)               (p)->lpVtbl->GetAdapterDisplayMode(p,a,b)
+#define IDirect3D9Ex_CheckDeviceType(p,a,b,c,d,e)               (p)->lpVtbl->CheckDeviceType(p,a,b,c,d,e)
+#define IDirect3D9Ex_CheckDeviceFormat(p,a,b,c,d,e,f)           (p)->lpVtbl->CheckDeviceFormat(p,a,b,c,d,e,f)
+#define IDirect3D9Ex_CheckDeviceMultiSampleType(p,a,b,c,d,e,f)  (p)->lpVtbl->CheckDeviceMultiSampleType(p,a,b,c,d,e,f)
+#define IDirect3D9Ex_CheckDepthStencilMatch(p,a,b,c,d,e)        (p)->lpVtbl->CheckDepthStencilMatch(p,a,b,c,d,e)
+#define IDirect3D9Ex_CheckDeviceFormatConversion(p,a,b,c,d)     (p)->lpVtbl->CheckDeviceFormatConversion(p,a,b,c,d)
+#define IDirect3D9Ex_GetDeviceCaps(p,a,b,c)                     (p)->lpVtbl->GetDeviceCaps(p,a,b,c)
+#define IDirect3D9Ex_GetAdapterMonitor(p,a)                     (p)->lpVtbl->GetAdapterMonitor(p,a)
+#define IDirect3D9Ex_CreateDevice(p,a,b,c,d,e,f)                (p)->lpVtbl->CreateDevice(p,a,b,c,d,e,f)
+/*** IDirect3D9Ex methods ***/
+#define IDirect3D9Ex_GetAdapterModeCountEx(p,a,b)               (p)->lpVtbl->GetAdapterModeCountEx(p,a,b)
+#define IDirect3D9Ex_EnumAdapterModesEx(p,a,b,c,d)              (p)->lpVtbl->EnumAdapterModesEx(p,a,b,c,d)
+#define IDirect3D9Ex_GetAdapterDisplayModeEx(p,a,b,c)           (p)->lpVtbl->GetAdapterDisplayModeEx(p,a,b,c)
+#define IDirect3D9Ex_CreateDeviceEx(p,a,b,c,d,e,f,g)            (p)->lpVtbl->CreateDeviceEx(p,a,b,c,d,e,f,g)
+#define IDirect3D9Ex_GetAdapterLUID(p,a,b)                      (p)->lpVtbl->GetAdapterLUID(p,a,b)
+#else
+/*** IUnknown methods ***/
+#define IDirect3D9Ex_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirect3D9Ex_AddRef(p)             (p)->AddRef()
+#define IDirect3D9Ex_Release(p)            (p)->Release()
+/*** IDirect3D9 methods ***/
+#define IDirect3D9Ex_RegisterSoftwareDevice(p,a)                (p)->RegisterSoftwareDevice(a)
+#define IDirect3D9Ex_GetAdapterCount(p)                         (p)->GetAdapterCount()
+#define IDirect3D9Ex_GetAdapterIdentifier(p,a,b,c)              (p)->GetAdapterIdentifier(a,b,c)
+#define IDirect3D9Ex_GetAdapterModeCount(p,a,b)                 (p)->GetAdapterModeCount(a,b)
+#define IDirect3D9Ex_EnumAdapterModes(p,a,b,c,d)                (p)->EnumAdapterModes(a,b,c,d)
+#define IDirect3D9Ex_GetAdapterDisplayMode(p,a,b)               (p)->GetAdapterDisplayMode(a,b)
+#define IDirect3D9Ex_CheckDeviceType(p,a,b,c,d,e)               (p)->CheckDeviceType(a,b,c,d,e)
+#define IDirect3D9Ex_CheckDeviceFormat(p,a,b,c,d,e,f)           (p)->CheckDeviceFormat(a,b,c,d,e,f)
+#define IDirect3D9Ex_CheckDeviceMultiSampleType(p,a,b,c,d,e,f)  (p)->CheckDeviceMultiSampleType(a,b,c,d,e,f)
+#define IDirect3D9Ex_CheckDepthStencilMatch(p,a,b,c,d,e)        (p)->CheckDepthStencilMatch(a,b,c,d,e)
+#define IDirect3D9Ex_CheckDeviceFormatConversion(p,a,b,c,d)     (p)->CheckDeviceFormatConversion(a,b,c,d)
+#define IDirect3D9Ex_GetDeviceCaps(p,a,b,c)                     (p)->GetDeviceCaps(a,b,c)
+#define IDirect3D9Ex_GetAdapterMonitor(p,a)                     (p)->GetAdapterMonitor(a)
+#define IDirect3D9Ex_CreateDevice(p,a,b,c,d,e,f)                (p)->CreateDevice(a,b,c,d,e,f)
+#endif
+
+/*****************************************************************************
+ * IDirect3DVolume9 interface
+ */
+#define INTERFACE IDirect3DVolume9
+DECLARE_INTERFACE_(IDirect3DVolume9,IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IDirect3DVolume9 methods ***/
+    STDMETHOD(GetDevice)(THIS_ struct IDirect3DDevice9** ppDevice) PURE;
+    STDMETHOD(SetPrivateData)(THIS_ REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) PURE;
+    STDMETHOD(GetPrivateData)(THIS_ REFGUID refguid, void* pData, DWORD* pSizeOfData) PURE;
+    STDMETHOD(FreePrivateData)(THIS_ REFGUID refguid) PURE;
+    STDMETHOD(GetContainer)(THIS_ REFIID riid, void** ppContainer) PURE;
+    STDMETHOD(GetDesc)(THIS_ D3DVOLUME_DESC* pDesc) PURE;
+    STDMETHOD(LockBox)(THIS_ D3DLOCKED_BOX* pLockedVolume, CONST D3DBOX* pBox, DWORD Flags) PURE;
+    STDMETHOD(UnlockBox)(THIS) PURE;
+};
+#undef INTERFACE
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+/*** IUnknown methods ***/
+#define IDirect3DVolume9_QueryInterface(p,a,b)        (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DVolume9_AddRef(p)                    (p)->lpVtbl->AddRef(p)
+#define IDirect3DVolume9_Release(p)                   (p)->lpVtbl->Release(p)
+/*** IDirect3DVolume9 methods ***/
+#define IDirect3DVolume9_GetDevice(p,a)               (p)->lpVtbl->GetDevice(p,a)
+#define IDirect3DVolume9_SetPrivateData(p,a,b,c,d)    (p)->lpVtbl->SetPrivateData(p,a,b,c,d)
+#define IDirect3DVolume9_GetPrivateData(p,a,b,c)      (p)->lpVtbl->GetPrivateData(p,a,b,c)
+#define IDirect3DVolume9_FreePrivateData(p,a)         (p)->lpVtbl->FreePrivateData(p,a)
+#define IDirect3DVolume9_GetContainer(p,a,b)          (p)->lpVtbl->GetContainer(p,a,b)
+#define IDirect3DVolume9_GetDesc(p,a)                 (p)->lpVtbl->GetDesc(p,a)
+#define IDirect3DVolume9_LockBox(p,a,b,c)             (p)->lpVtbl->LockBox(p,a,b,c)
+#define IDirect3DVolume9_UnlockBox(p)                 (p)->lpVtbl->UnlockBox(p)
+#else
+/*** IUnknown methods ***/
+#define IDirect3DVolume9_QueryInterface(p,a,b)        (p)->QueryInterface(a,b)
+#define IDirect3DVolume9_AddRef(p)                    (p)->AddRef()
+#define IDirect3DVolume9_Release(p)                   (p)->Release()
+/*** IDirect3DVolume9 methods ***/
+#define IDirect3DVolume9_GetDevice(p,a)               (p)->GetDevice(a)
+#define IDirect3DVolume9_SetPrivateData(p,a,b,c,d)    (p)->SetPrivateData(a,b,c,d)
+#define IDirect3DVolume9_GetPrivateData(p,a,b,c)      (p)->GetPrivateData(a,b,c)
+#define IDirect3DVolume9_FreePrivateData(p,a)         (p)->FreePrivateData(a)
+#define IDirect3DVolume9_GetContainer(p,a,b)          (p)->GetContainer(a,b)
+#define IDirect3DVolume9_GetDesc(p,a)                 (p)->GetDesc(a)
+#define IDirect3DVolume9_LockBox(p,a,b,c)             (p)->LockBox(a,b,c)
+#define IDirect3DVolume9_UnlockBox(p)                 (p)->UnlockBox()
+#endif
+
+/*****************************************************************************
+ * IDirect3DSwapChain9 interface
+ */
+#define INTERFACE IDirect3DSwapChain9
+DECLARE_INTERFACE_(IDirect3DSwapChain9,IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IDirect3DSwapChain9 methods ***/
+    STDMETHOD(Present)(THIS_ CONST RECT* pSourceRect, CONST RECT* pDestRect, HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion, DWORD dwFlags) PURE;
+    STDMETHOD(GetFrontBufferData)(THIS_ struct IDirect3DSurface9* pDestSurface) PURE;
+    STDMETHOD(GetBackBuffer)(THIS_ UINT iBackBuffer, D3DBACKBUFFER_TYPE Type, struct IDirect3DSurface9** ppBackBuffer) PURE;
+    STDMETHOD(GetRasterStatus)(THIS_ D3DRASTER_STATUS* pRasterStatus) PURE;
+    STDMETHOD(GetDisplayMode)(THIS_ D3DDISPLAYMODE* pMode) PURE;
+    STDMETHOD(GetDevice)(THIS_ struct IDirect3DDevice9** ppDevice) PURE;
+    STDMETHOD(GetPresentParameters)(THIS_ D3DPRESENT_PARAMETERS* pPresentationParameters) PURE;
+};
+#undef INTERFACE
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+/*** IUnknown methods ***/
+#define IDirect3DSwapChain9_QueryInterface(p,a,b)        (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DSwapChain9_AddRef(p)                    (p)->lpVtbl->AddRef(p)
+#define IDirect3DSwapChain9_Release(p)                   (p)->lpVtbl->Release(p)
+/*** IDirect3DSwapChain9 methods ***/
+#define IDirect3DSwapChain9_Present(p,a,b,c,d,e)         (p)->lpVtbl->Present(p,a,b,c,d,e)
+#define IDirect3DSwapChain9_GetFrontBufferData(p,a)      (p)->lpVtbl->GetFrontBufferData(p,a)
+#define IDirect3DSwapChain9_GetBackBuffer(p,a,b,c)       (p)->lpVtbl->GetBackBuffer(p,a,b,c)
+#define IDirect3DSwapChain9_GetRasterStatus(p,a)         (p)->lpVtbl->GetRasterStatus(p,a)
+#define IDirect3DSwapChain9_GetDisplayMode(p,a)          (p)->lpVtbl->GetDisplayMode(p,a)
+#define IDirect3DSwapChain9_GetDevice(p,a)               (p)->lpVtbl->GetDevice(p,a)
+#define IDirect3DSwapChain9_GetPresentParameters(p,a)    (p)->lpVtbl->GetPresentParameters(p,a)
+#else
+/*** IUnknown methods ***/
+#define IDirect3DSwapChain9_QueryInterface(p,a,b)        (p)->QueryInterface(a,b)
+#define IDirect3DSwapChain9_AddRef(p)                    (p)->AddRef()
+#define IDirect3DSwapChain9_Release(p)                   (p)->Release()
+/*** IDirect3DSwapChain9 methods ***/
+#define IDirect3DSwapChain9_Present(p,a,b,c,d,e)         (p)->Present(a,b,c,d,e)
+#define IDirect3DSwapChain9_GetFrontBufferData(p,a)      (p)->GetFrontBufferData(a)
+#define IDirect3DSwapChain9_GetBackBuffer(p,a,b,c)       (p)->GetBackBuffer(a,b,c)
+#define IDirect3DSwapChain9_GetRasterStatus(p,a)         (p)->GetRasterStatus(a)
+#define IDirect3DSwapChain9_GetDisplayMode(p,a)          (p)->GetDisplayMode(a)
+#define IDirect3DSwapChain9_GetDevice(p,a)               (p)->GetDevice(a)
+#define IDirect3DSwapChain9_GetPresentParameters(p,a)    (p)->GetPresentParameters(a)
+#endif
+
+/*****************************************************************************
+ * IDirect3DResource9 interface
+ */
+#define INTERFACE IDirect3DResource9
+DECLARE_INTERFACE_(IDirect3DResource9,IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IDirect3DResource9 methods ***/
+    STDMETHOD(GetDevice)(THIS_ struct IDirect3DDevice9** ppDevice) PURE;
+    STDMETHOD(SetPrivateData)(THIS_ REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) PURE;
+    STDMETHOD(GetPrivateData)(THIS_ REFGUID refguid, void* pData, DWORD* pSizeOfData) PURE;
+    STDMETHOD(FreePrivateData)(THIS_ REFGUID refguid) PURE;
+    STDMETHOD_(DWORD, SetPriority)(THIS_ DWORD PriorityNew) PURE;
+    STDMETHOD_(DWORD, GetPriority)(THIS) PURE;
+    STDMETHOD_(void, PreLoad)(THIS) PURE;
+    STDMETHOD_(D3DRESOURCETYPE, GetType)(THIS) PURE;
+};
+#undef INTERFACE
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+/*** IUnknown methods ***/
+#define IDirect3DResource9_QueryInterface(p,a,b)        (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DResource9_AddRef(p)                    (p)->lpVtbl->AddRef(p)
+#define IDirect3DResource9_Release(p)                   (p)->lpVtbl->Release(p)
+/*** IDirect3DResource9 methods ***/
+#define IDirect3DResource9_GetDevice(p,a)               (p)->lpVtbl->GetDevice(p,a)
+#define IDirect3DResource9_SetPrivateData(p,a,b,c,d)    (p)->lpVtbl->SetPrivateData(p,a,b,c,d)
+#define IDirect3DResource9_GetPrivateData(p,a,b,c)      (p)->lpVtbl->GetPrivateData(p,a,b,c)
+#define IDirect3DResource9_FreePrivateData(p,a)         (p)->lpVtbl->FreePrivateData(p,a)
+#define IDirect3DResource9_SetPriority(p,a)             (p)->lpVtbl->SetPriority(p,a)
+#define IDirect3DResource9_GetPriority(p)               (p)->lpVtbl->GetPriority(p)
+#define IDirect3DResource9_PreLoad(p)                   (p)->lpVtbl->PreLoad(p)
+#define IDirect3DResource9_GetType(p)                   (p)->lpVtbl->GetType(p)
+#else
+/*** IUnknown methods ***/
+#define IDirect3DResource9_QueryInterface(p,a,b)        (p)->QueryInterface(a,b)
+#define IDirect3DResource9_AddRef(p)                    (p)->AddRef()
+#define IDirect3DResource9_Release(p)                   (p)->Release()
+/*** IDirect3DResource9 methods ***/
+#define IDirect3DResource9_GetDevice(p,a)               (p)->GetDevice(a)
+#define IDirect3DResource9_SetPrivateData(p,a,b,c,d)    (p)->SetPrivateData(a,b,c,d)
+#define IDirect3DResource9_GetPrivateData(p,a,b,c)      (p)->GetPrivateData(a,b,c)
+#define IDirect3DResource9_FreePrivateData(p,a)         (p)->FreePrivateData(a)
+#define IDirect3DResource9_SetPriority(p,a)             (p)->SetPriority(a)
+#define IDirect3DResource9_GetPriority(p)               (p)->GetPriority()
+#define IDirect3DResource9_PreLoad(p)                   (p)->PreLoad()
+#define IDirect3DResource9_GetType(p)                   (p)->GetType()
+#endif
+
+/*****************************************************************************
+ * IDirect3DSurface9 interface
+ */
+#define INTERFACE IDirect3DSurface9
+DECLARE_INTERFACE_(IDirect3DSurface9,IDirect3DResource9)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IDirect3DResource9 methods ***/
+    STDMETHOD(GetDevice)(THIS_ struct IDirect3DDevice9** ppDevice) PURE;
+    STDMETHOD(SetPrivateData)(THIS_ REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) PURE;
+    STDMETHOD(GetPrivateData)(THIS_ REFGUID refguid, void* pData, DWORD* pSizeOfData) PURE;
+    STDMETHOD(FreePrivateData)(THIS_ REFGUID refguid) PURE;
+    STDMETHOD_(DWORD, SetPriority)(THIS_ DWORD PriorityNew) PURE;
+    STDMETHOD_(DWORD, GetPriority)(THIS) PURE;
+    STDMETHOD_(void, PreLoad)(THIS) PURE;
+    STDMETHOD_(D3DRESOURCETYPE, GetType)(THIS) PURE;
+    /*** IDirect3DSurface9 methods ***/
+    STDMETHOD(GetContainer)(THIS_ REFIID riid, void** ppContainer) PURE;
+    STDMETHOD(GetDesc)(THIS_ D3DSURFACE_DESC* pDesc) PURE;
+    STDMETHOD(LockRect)(THIS_ D3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) PURE;
+    STDMETHOD(UnlockRect)(THIS) PURE;
+    STDMETHOD(GetDC)(THIS_ HDC* phdc) PURE;
+    STDMETHOD(ReleaseDC)(THIS_ HDC hdc) PURE;
+};
+#undef INTERFACE
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+/*** IUnknown methods ***/
+#define IDirect3DSurface9_QueryInterface(p,a,b)        (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DSurface9_AddRef(p)                    (p)->lpVtbl->AddRef(p)
+#define IDirect3DSurface9_Release(p)                   (p)->lpVtbl->Release(p)
+/*** IDirect3DSurface9 methods: IDirect3DResource9 ***/
+#define IDirect3DSurface9_GetDevice(p,a)               (p)->lpVtbl->GetDevice(p,a)
+#define IDirect3DSurface9_SetPrivateData(p,a,b,c,d)    (p)->lpVtbl->SetPrivateData(p,a,b,c,d)
+#define IDirect3DSurface9_GetPrivateData(p,a,b,c)      (p)->lpVtbl->GetPrivateData(p,a,b,c)
+#define IDirect3DSurface9_FreePrivateData(p,a)         (p)->lpVtbl->FreePrivateData(p,a)
+#define IDirect3DSurface9_SetPriority(p,a)             (p)->lpVtbl->SetPriority(p,a)
+#define IDirect3DSurface9_GetPriority(p)               (p)->lpVtbl->GetPriority(p)
+#define IDirect3DSurface9_PreLoad(p)                   (p)->lpVtbl->PreLoad(p)
+#define IDirect3DSurface9_GetType(p)                   (p)->lpVtbl->GetType(p)
+/*** IDirect3DSurface9 methods ***/
+#define IDirect3DSurface9_GetContainer(p,a,b)          (p)->lpVtbl->GetContainer(p,a,b)
+#define IDirect3DSurface9_GetDesc(p,a)                 (p)->lpVtbl->GetDesc(p,a)
+#define IDirect3DSurface9_LockRect(p,a,b,c)            (p)->lpVtbl->LockRect(p,a,b,c)
+#define IDirect3DSurface9_UnlockRect(p)                (p)->lpVtbl->UnlockRect(p)
+#define IDirect3DSurface9_GetDC(p,a)                   (p)->lpVtbl->GetDC(p,a)
+#define IDirect3DSurface9_ReleaseDC(p,a)               (p)->lpVtbl->ReleaseDC(p,a)
+#else
+/*** IUnknown methods ***/
+#define IDirect3DSurface9_QueryInterface(p,a,b)        (p)->QueryInterface(a,b)
+#define IDirect3DSurface9_AddRef(p)                    (p)->AddRef()
+#define IDirect3DSurface9_Release(p)                   (p)->Release()
+/*** IDirect3DSurface9 methods: IDirect3DResource9 ***/
+#define IDirect3DSurface9_GetDevice(p,a)               (p)->GetDevice(a)
+#define IDirect3DSurface9_SetPrivateData(p,a,b,c,d)    (p)->SetPrivateData(a,b,c,d)
+#define IDirect3DSurface9_GetPrivateData(p,a,b,c)      (p)->GetPrivateData(a,b,c)
+#define IDirect3DSurface9_FreePrivateData(p,a)         (p)->FreePrivateData(a)
+#define IDirect3DSurface9_SetPriority(p,a)             (p)->SetPriority(a)
+#define IDirect3DSurface9_GetPriority(p)               (p)->GetPriority()
+#define IDirect3DSurface9_PreLoad(p)                   (p)->PreLoad()
+#define IDirect3DSurface9_GetType(p)                   (p)->GetType()
+/*** IDirect3DSurface9 methods ***/
+#define IDirect3DSurface9_GetContainer(p,a,b)          (p)->GetContainer(a,b)
+#define IDirect3DSurface9_GetDesc(p,a)                 (p)->GetDesc(a)
+#define IDirect3DSurface9_LockRect(p,a,b,c)            (p)->LockRect(a,b,c)
+#define IDirect3DSurface9_UnlockRect(p)                (p)->UnlockRect()
+#define IDirect3DSurface9_GetDC(p,a)                   (p)->GetDC(a)
+#define IDirect3DSurface9_ReleaseDC(p,a)               (p)->ReleaseDC(a)
+#endif
+
+/*****************************************************************************
+ * IDirect3DVertexBuffer9 interface
+ */
+#define INTERFACE IDirect3DVertexBuffer9
+DECLARE_INTERFACE_(IDirect3DVertexBuffer9,IDirect3DResource9)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IDirect3DResource9 methods ***/
+    STDMETHOD(GetDevice)(THIS_ struct IDirect3DDevice9** ppDevice) PURE;
+    STDMETHOD(SetPrivateData)(THIS_ REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) PURE;
+    STDMETHOD(GetPrivateData)(THIS_ REFGUID refguid, void* pData, DWORD* pSizeOfData) PURE;
+    STDMETHOD(FreePrivateData)(THIS_ REFGUID refguid) PURE;
+    STDMETHOD_(DWORD, SetPriority)(THIS_ DWORD PriorityNew) PURE;
+    STDMETHOD_(DWORD, GetPriority)(THIS) PURE;
+    STDMETHOD_(void, PreLoad)(THIS) PURE;
+    STDMETHOD_(D3DRESOURCETYPE, GetType)(THIS) PURE;
+    /*** IDirect3DVertexBuffer9 methods ***/
+    STDMETHOD(Lock)(THIS_ UINT OffsetToLock, UINT SizeToLock, void** ppbData, DWORD Flags) PURE;
+    STDMETHOD(Unlock)(THIS) PURE;
+    STDMETHOD(GetDesc)(THIS_ D3DVERTEXBUFFER_DESC* pDesc) PURE;
+};
+#undef INTERFACE
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+/*** IUnknown methods ***/
+#define IDirect3DVertexBuffer9_QueryInterface(p,a,b)        (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DVertexBuffer9_AddRef(p)                    (p)->lpVtbl->AddRef(p)
+#define IDirect3DVertexBuffer9_Release(p)                   (p)->lpVtbl->Release(p)
+/*** IDirect3DVertexBuffer9 methods: IDirect3DResource9 ***/
+#define IDirect3DVertexBuffer9_GetDevice(p,a)               (p)->lpVtbl->GetDevice(p,a)
+#define IDirect3DVertexBuffer9_SetPrivateData(p,a,b,c,d)    (p)->lpVtbl->SetPrivateData(p,a,b,c,d)
+#define IDirect3DVertexBuffer9_GetPrivateData(p,a,b,c)      (p)->lpVtbl->GetPrivateData(p,a,b,c)
+#define IDirect3DVertexBuffer9_FreePrivateData(p,a)         (p)->lpVtbl->FreePrivateData(p,a)
+#define IDirect3DVertexBuffer9_SetPriority(p,a)             (p)->lpVtbl->SetPriority(p,a)
+#define IDirect3DVertexBuffer9_GetPriority(p)               (p)->lpVtbl->GetPriority(p)
+#define IDirect3DVertexBuffer9_PreLoad(p)                   (p)->lpVtbl->PreLoad(p)
+#define IDirect3DVertexBuffer9_GetType(p)                   (p)->lpVtbl->GetType(p)
+/*** IDirect3DVertexBuffer9 methods ***/
+#define IDirect3DVertexBuffer9_Lock(p,a,b,c,d)              (p)->lpVtbl->Lock(p,a,b,c,d)
+#define IDirect3DVertexBuffer9_Unlock(p)                    (p)->lpVtbl->Unlock(p)
+#define IDirect3DVertexBuffer9_GetDesc(p,a)                 (p)->lpVtbl->GetDesc(p,a)
+#else
+/*** IUnknown methods ***/
+#define IDirect3DVertexBuffer9_QueryInterface(p,a,b)        (p)->QueryInterface(a,b)
+#define IDirect3DVertexBuffer9_AddRef(p)                    (p)->AddRef()
+#define IDirect3DVertexBuffer9_Release(p)                   (p)->Release()
+/*** IDirect3DVertexBuffer9 methods: IDirect3DResource9 ***/
+#define IDirect3DVertexBuffer9_GetDevice(p,a)               (p)->GetDevice(a)
+#define IDirect3DVertexBuffer9_SetPrivateData(p,a,b,c,d)    (p)->SetPrivateData(a,b,c,d)
+#define IDirect3DVertexBuffer9_GetPrivateData(p,a,b,c)      (p)->GetPrivateData(a,b,c)
+#define IDirect3DVertexBuffer9_FreePrivateData(p,a)         (p)->FreePrivateData(a)
+#define IDirect3DVertexBuffer9_SetPriority(p,a)             (p)->SetPriority(a)
+#define IDirect3DVertexBuffer9_GetPriority(p)               (p)->GetPriority()
+#define IDirect3DVertexBuffer9_PreLoad(p)                   (p)->PreLoad()
+#define IDirect3DVertexBuffer9_GetType(p)                   (p)->GetType()
+/*** IDirect3DVertexBuffer9 methods ***/
+#define IDirect3DVertexBuffer9_Lock(p,a,b,c,d)              (p)->Lock(a,b,c,d)
+#define IDirect3DVertexBuffer9_Unlock(p)                    (p)->Unlock()
+#define IDirect3DVertexBuffer9_GetDesc(p,a)                 (p)->GetDesc(a)
+#endif
+
+/*****************************************************************************
+ * IDirect3DIndexBuffer9 interface
+ */
+#define INTERFACE IDirect3DIndexBuffer9
+DECLARE_INTERFACE_(IDirect3DIndexBuffer9,IDirect3DResource9)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IDirect3DResource9 methods ***/
+    STDMETHOD(GetDevice)(THIS_ struct IDirect3DDevice9** ppDevice) PURE;
+    STDMETHOD(SetPrivateData)(THIS_ REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) PURE;
+    STDMETHOD(GetPrivateData)(THIS_ REFGUID refguid, void* pData, DWORD* pSizeOfData) PURE;
+    STDMETHOD(FreePrivateData)(THIS_ REFGUID refguid) PURE;
+    STDMETHOD_(DWORD, SetPriority)(THIS_ DWORD PriorityNew) PURE;
+    STDMETHOD_(DWORD, GetPriority)(THIS) PURE;
+    STDMETHOD_(void, PreLoad)(THIS) PURE;
+    STDMETHOD_(D3DRESOURCETYPE, GetType)(THIS) PURE;
+    /*** IDirect3DIndexBuffer9 methods ***/
+    STDMETHOD(Lock)(THIS_ UINT OffsetToLock, UINT SizeToLock, void** ppbData, DWORD Flags) PURE;
+    STDMETHOD(Unlock)(THIS) PURE;
+    STDMETHOD(GetDesc)(THIS_ D3DINDEXBUFFER_DESC* pDesc) PURE;
+};
+#undef INTERFACE
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+/*** IUnknown methods ***/
+#define IDirect3DIndexBuffer9_QueryInterface(p,a,b)        (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DIndexBuffer9_AddRef(p)                    (p)->lpVtbl->AddRef(p)
+#define IDirect3DIndexBuffer9_Release(p)                   (p)->lpVtbl->Release(p)
+/*** IDirect3DIndexBuffer9 methods: IDirect3DResource9 ***/
+#define IDirect3DIndexBuffer9_GetDevice(p,a)               (p)->lpVtbl->GetDevice(p,a)
+#define IDirect3DIndexBuffer9_SetPrivateData(p,a,b,c,d)    (p)->lpVtbl->SetPrivateData(p,a,b,c,d)
+#define IDirect3DIndexBuffer9_GetPrivateData(p,a,b,c)      (p)->lpVtbl->GetPrivateData(p,a,b,c)
+#define IDirect3DIndexBuffer9_FreePrivateData(p,a)         (p)->lpVtbl->FreePrivateData(p,a)
+#define IDirect3DIndexBuffer9_SetPriority(p,a)             (p)->lpVtbl->SetPriority(p,a)
+#define IDirect3DIndexBuffer9_GetPriority(p)               (p)->lpVtbl->GetPriority(p)
+#define IDirect3DIndexBuffer9_PreLoad(p)                   (p)->lpVtbl->PreLoad(p)
+#define IDirect3DIndexBuffer9_GetType(p)                   (p)->lpVtbl->GetType(p)
+/*** IDirect3DIndexBuffer9 methods ***/
+#define IDirect3DIndexBuffer9_Lock(p,a,b,c,d)              (p)->lpVtbl->Lock(p,a,b,c,d)
+#define IDirect3DIndexBuffer9_Unlock(p)                    (p)->lpVtbl->Unlock(p)
+#define IDirect3DIndexBuffer9_GetDesc(p,a)                 (p)->lpVtbl->GetDesc(p,a)
+#else
+/*** IUnknown methods ***/
+#define IDirect3DIndexBuffer9_QueryInterface(p,a,b)        (p)->QueryInterface(a,b)
+#define IDirect3DIndexBuffer9_AddRef(p)                    (p)->AddRef()
+#define IDirect3DIndexBuffer9_Release(p)                   (p)->Release()
+/*** IDirect3DIndexBuffer9 methods: IDirect3DResource9 ***/
+#define IDirect3DIndexBuffer9_GetDevice(p,a)               (p)->GetDevice(a)
+#define IDirect3DIndexBuffer9_SetPrivateData(p,a,b,c,d)    (p)->SetPrivateData(a,b,c,d)
+#define IDirect3DIndexBuffer9_GetPrivateData(p,a,b,c)      (p)->GetPrivateData(a,b,c)
+#define IDirect3DIndexBuffer9_FreePrivateData(p,a)         (p)->FreePrivateData(a)
+#define IDirect3DIndexBuffer9_SetPriority(p,a)             (p)->SetPriority(a)
+#define IDirect3DIndexBuffer9_GetPriority(p)               (p)->GetPriority()
+#define IDirect3DIndexBuffer9_PreLoad(p)                   (p)->PreLoad()
+#define IDirect3DIndexBuffer9_GetType(p)                   (p)->GetType()
+/*** IDirect3DIndexBuffer9 methods ***/
+#define IDirect3DIndexBuffer9_Lock(p,a,b,c,d)              (p)->Lock(a,b,c,d)
+#define IDirect3DIndexBuffer9_Unlock(p)                    (p)->Unlock()
+#define IDirect3DIndexBuffer9_GetDesc(p,a)                 (p)->GetDesc(a)
+#endif
+
+/*****************************************************************************
+ * IDirect3DBaseTexture9 interface
+ */
+#define INTERFACE IDirect3DBaseTexture9
+DECLARE_INTERFACE_(IDirect3DBaseTexture9,IDirect3DResource9)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IDirect3DResource9 methods ***/
+    STDMETHOD(GetDevice)(THIS_ struct IDirect3DDevice9** ppDevice) PURE;
+    STDMETHOD(SetPrivateData)(THIS_ REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) PURE;
+    STDMETHOD(GetPrivateData)(THIS_ REFGUID refguid, void* pData, DWORD* pSizeOfData) PURE;
+    STDMETHOD(FreePrivateData)(THIS_ REFGUID refguid) PURE;
+    STDMETHOD_(DWORD, SetPriority)(THIS_ DWORD PriorityNew) PURE;
+    STDMETHOD_(DWORD, GetPriority)(THIS) PURE;
+    STDMETHOD_(void, PreLoad)(THIS) PURE;
+    STDMETHOD_(D3DRESOURCETYPE, GetType)(THIS) PURE;
+    /*** IDirect3DBaseTexture9 methods ***/
+    STDMETHOD_(DWORD, SetLOD)(THIS_ DWORD LODNew) PURE;
+    STDMETHOD_(DWORD, GetLOD)(THIS) PURE;
+    STDMETHOD_(DWORD, GetLevelCount)(THIS) PURE;
+    STDMETHOD(SetAutoGenFilterType)(THIS_ D3DTEXTUREFILTERTYPE FilterType) PURE;
+    STDMETHOD_(D3DTEXTUREFILTERTYPE, GetAutoGenFilterType)(THIS) PURE;
+    STDMETHOD_(void, GenerateMipSubLevels)(THIS) PURE;
+};
+#undef INTERFACE
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+/*** IUnknown methods ***/
+#define IDirect3DBaseTexture9_QueryInterface(p,a,b)  (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DBaseTexture9_AddRef(p)              (p)->lpVtbl->AddRef(p)
+#define IDirect3DBaseTexture9_Release(p)             (p)->lpVtbl->Release(p)
+/*** IDirect3DBaseTexture9 methods: IDirect3DResource9 ***/
+#define IDirect3DBaseTexture9_GetDevice(p,a)             (p)->lpVtbl->GetDevice(p,a)
+#define IDirect3DBaseTexture9_SetPrivateData(p,a,b,c,d)  (p)->lpVtbl->SetPrivateData(p,a,b,c,d)
+#define IDirect3DBaseTexture9_GetPrivateData(p,a,b,c)    (p)->lpVtbl->GetPrivateData(p,a,b,c)
+#define IDirect3DBaseTexture9_FreePrivateData(p,a)       (p)->lpVtbl->FreePrivateData(p,a)
+#define IDirect3DBaseTexture9_SetPriority(p,a)           (p)->lpVtbl->SetPriority(p,a)
+#define IDirect3DBaseTexture9_GetPriority(p)             (p)->lpVtbl->GetPriority(p)
+#define IDirect3DBaseTexture9_PreLoad(p)                 (p)->lpVtbl->PreLoad(p)
+#define IDirect3DBaseTexture9_GetType(p)                 (p)->lpVtbl->GetType(p)
+/*** IDirect3DBaseTexture9 methods ***/
+#define IDirect3DBaseTexture9_SetLOD(p,a)                (p)->lpVtbl->SetLOD(p,a)
+#define IDirect3DBaseTexture9_GetLOD(p)                  (p)->lpVtbl->GetLOD(p)
+#define IDirect3DBaseTexture9_GetLevelCount(p)           (p)->lpVtbl->GetLevelCount(p)
+#define IDirect3DBaseTexture9_SetAutoGenFilterType(p,a)  (p)->lpVtbl->SetAutoGenFilterType(p,a)
+#define IDirect3DBaseTexture9_GetAutoGenFilterType(p)    (p)->lpVtbl->GetAutoGenFilterType(p)
+#define IDirect3DBaseTexture9_GenerateMipSubLevels(p)    (p)->lpVtbl->GenerateMipSubLevels(p)
+#else
+/*** IUnknown methods ***/
+#define IDirect3DBaseTexture9_QueryInterface(p,a,b)  (p)->QueryInterface(a,b)
+#define IDirect3DBaseTexture9_AddRef(p)              (p)->AddRef()
+#define IDirect3DBaseTexture9_Release(p)             (p)->Release()
+/*** IDirect3DBaseTexture9 methods: IDirect3DResource9 ***/
+#define IDirect3DBaseTexture9_GetDevice(p,a)             (p)->GetDevice(a)
+#define IDirect3DBaseTexture9_SetPrivateData(p,a,b,c,d)  (p)->SetPrivateData(a,b,c,d)
+#define IDirect3DBaseTexture9_GetPrivateData(p,a,b,c)    (p)->GetPrivateData(a,b,c)
+#define IDirect3DBaseTexture9_FreePrivateData(p,a)       (p)->FreePrivateData(a)
+#define IDirect3DBaseTexture9_SetPriority(p,a)           (p)->SetPriority(a)
+#define IDirect3DBaseTexture9_GetPriority(p)             (p)->GetPriority()
+#define IDirect3DBaseTexture9_PreLoad(p)                 (p)->PreLoad()
+#define IDirect3DBaseTexture9_GetType(p)                 (p)->GetType()
+/*** IDirect3DBaseTexture9 methods ***/
+#define IDirect3DBaseTexture9_SetLOD(p,a)                (p)->SetLOD(a)
+#define IDirect3DBaseTexture9_GetLOD(p)                  (p)->GetLOD()
+#define IDirect3DBaseTexture9_GetLevelCount(p)           (p)->GetLevelCount()
+#define IDirect3DBaseTexture9_SetAutoGenFilterType(p,a)  (p)->SetAutoGenFilterType(a)
+#define IDirect3DBaseTexture9_GetAutoGenFilterType(p)    (p)->GetAutoGenFilterType()
+#define IDirect3DBaseTexture9_GenerateMipSubLevels(p)    (p)->GenerateMipSubLevels()
+#endif
+
+/*****************************************************************************
+ * IDirect3DCubeTexture9 interface
+ */
+#define INTERFACE IDirect3DCubeTexture9
+DECLARE_INTERFACE_(IDirect3DCubeTexture9,IDirect3DBaseTexture9)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IDirect3DResource9 methods ***/
+    STDMETHOD(GetDevice)(THIS_ struct IDirect3DDevice9** ppDevice) PURE;
+    STDMETHOD(SetPrivateData)(THIS_ REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) PURE;
+    STDMETHOD(GetPrivateData)(THIS_ REFGUID refguid, void* pData, DWORD* pSizeOfData) PURE;
+    STDMETHOD(FreePrivateData)(THIS_ REFGUID refguid) PURE;
+    STDMETHOD_(DWORD, SetPriority)(THIS_ DWORD PriorityNew) PURE;
+    STDMETHOD_(DWORD, GetPriority)(THIS) PURE;
+    STDMETHOD_(void, PreLoad)(THIS) PURE;
+    STDMETHOD_(D3DRESOURCETYPE, GetType)(THIS) PURE;
+    /*** IDirect3DBaseTexture9 methods ***/
+    STDMETHOD_(DWORD, SetLOD)(THIS_ DWORD LODNew) PURE;
+    STDMETHOD_(DWORD, GetLOD)(THIS) PURE;
+    STDMETHOD_(DWORD, GetLevelCount)(THIS) PURE;
+    STDMETHOD(SetAutoGenFilterType)(THIS_ D3DTEXTUREFILTERTYPE FilterType) PURE;
+    STDMETHOD_(D3DTEXTUREFILTERTYPE, GetAutoGenFilterType)(THIS) PURE;
+    STDMETHOD_(void, GenerateMipSubLevels)(THIS) PURE;
+    /*** IDirect3DCubeTexture9 methods ***/
+    STDMETHOD(GetLevelDesc)(THIS_ UINT Level,D3DSURFACE_DESC* pDesc) PURE;
+    STDMETHOD(GetCubeMapSurface)(THIS_ D3DCUBEMAP_FACES FaceType, UINT Level, IDirect3DSurface9** ppCubeMapSurface) PURE;
+    STDMETHOD(LockRect)(THIS_ D3DCUBEMAP_FACES FaceType, UINT Level, D3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) PURE;
+    STDMETHOD(UnlockRect)(THIS_ D3DCUBEMAP_FACES FaceType, UINT Level) PURE;
+    STDMETHOD(AddDirtyRect)(THIS_ D3DCUBEMAP_FACES FaceType, CONST RECT* pDirtyRect) PURE;
+};
+#undef INTERFACE
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+/*** IUnknown methods ***/
+#define IDirect3DCubeTexture9_QueryInterface(p,a,b)       (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DCubeTexture9_AddRef(p)                   (p)->lpVtbl->AddRef(p)
+#define IDirect3DCubeTexture9_Release(p)                  (p)->lpVtbl->Release(p)
+/*** IDirect3DCubeTexture9 methods: IDirect3DResource9 ***/
+#define IDirect3DCubeTexture9_GetDevice(p,a)              (p)->lpVtbl->GetDevice(p,a)
+#define IDirect3DCubeTexture9_SetPrivateData(p,a,b,c,d)   (p)->lpVtbl->SetPrivateData(p,a,b,c,d)
+#define IDirect3DCubeTexture9_GetPrivateData(p,a,b,c)     (p)->lpVtbl->GetPrivateData(p,a,b,c)
+#define IDirect3DCubeTexture9_FreePrivateData(p,a)        (p)->lpVtbl->FreePrivateData(p,a)
+#define IDirect3DCubeTexture9_SetPriority(p,a)            (p)->lpVtbl->SetPriority(p,a)
+#define IDirect3DCubeTexture9_GetPriority(p)              (p)->lpVtbl->GetPriority(p)
+#define IDirect3DCubeTexture9_PreLoad(p)                  (p)->lpVtbl->PreLoad(p)
+#define IDirect3DCubeTexture9_GetType(p)                  (p)->lpVtbl->GetType(p)
+/*** IDirect3DCubeTexture9 methods: IDirect3DBaseTexture9 ***/
+#define IDirect3DCubeTexture9_SetLOD(p,a)                 (p)->lpVtbl->SetLOD(p,a)
+#define IDirect3DCubeTexture9_GetLOD(p)                   (p)->lpVtbl->GetLOD(p)
+#define IDirect3DCubeTexture9_GetLevelCount(p)            (p)->lpVtbl->GetLevelCount(p)
+#define IDirect3DCubeTexture9_SetAutoGenFilterType(p,a)   (p)->lpVtbl->SetAutoGenFilterType(p,a)
+#define IDirect3DCubeTexture9_GetAutoGenFilterType(p)     (p)->lpVtbl->GetAutoGenFilterType(p)
+#define IDirect3DCubeTexture9_GenerateMipSubLevels(p)     (p)->lpVtbl->GenerateMipSubLevels(p)
+/*** IDirect3DCubeTexture9 methods ***/
+#define IDirect3DCubeTexture9_GetLevelDesc(p,a,b)         (p)->lpVtbl->GetLevelDesc(p,a,b)
+#define IDirect3DCubeTexture9_GetCubeMapSurface(p,a,b,c)  (p)->lpVtbl->GetCubeMapSurface(p,a,b,c)
+#define IDirect3DCubeTexture9_LockRect(p,a,b,c,d,e)       (p)->lpVtbl->LockRect(p,a,b,c,d,e)
+#define IDirect3DCubeTexture9_UnlockRect(p,a,b)           (p)->lpVtbl->UnlockRect(p,a,b)
+#define IDirect3DCubeTexture9_AddDirtyRect(p,a,b)         (p)->lpVtbl->AddDirtyRect(p,a,b)
+#else
+/*** IUnknown methods ***/
+#define IDirect3DCubeTexture9_QueryInterface(p,a,b)       (p)->QueryInterface(a,b)
+#define IDirect3DCubeTexture9_AddRef(p)                   (p)->AddRef()
+#define IDirect3DCubeTexture9_Release(p)                  (p)->Release()
+/*** IDirect3DCubeTexture9 methods: IDirect3DResource9 ***/
+#define IDirect3DCubeTexture9_GetDevice(p,a)              (p)->GetDevice(a)
+#define IDirect3DCubeTexture9_SetPrivateData(p,a,b,c,d)   (p)->SetPrivateData(a,b,c,d)
+#define IDirect3DCubeTexture9_GetPrivateData(p,a,b,c)     (p)->GetPrivateData(a,b,c)
+#define IDirect3DCubeTexture9_FreePrivateData(p,a)        (p)->FreePrivateData(a)
+#define IDirect3DCubeTexture9_SetPriority(p,a)            (p)->SetPriority(a)
+#define IDirect3DCubeTexture9_GetPriority(p)              (p)->GetPriority()
+#define IDirect3DCubeTexture9_PreLoad(p)                  (p)->PreLoad()
+#define IDirect3DCubeTexture9_GetType(p)                  (p)->GetType()
+/*** IDirect3DCubeTexture9 methods: IDirect3DBaseTexture9 ***/
+#define IDirect3DCubeTexture9_SetLOD(p,a)                 (p)->SetLOD(a)
+#define IDirect3DCubeTexture9_GetLOD(p)                   (p)->GetLOD()
+#define IDirect3DCubeTexture9_GetLevelCount(p)            (p)->GetLevelCount()
+#define IDirect3DCubeTexture9_SetAutoGenFilterType(p,a)   (p)->SetAutoGenFilterType(a)
+#define IDirect3DCubeTexture9_GetAutoGenFilterType(p)     (p)->GetAutoGenFilterType()
+#define IDirect3DCubeTexture9_GenerateMipSubLevels(p)     (p)->GenerateMipSubLevels()
+/*** IDirect3DCubeTexture9 methods ***/
+#define IDirect3DCubeTexture9_GetLevelDesc(p,a,b)         (p)->GetLevelDesc(a,b)
+#define IDirect3DCubeTexture9_GetCubeMapSurface(p,a,b,c)  (p)->GetCubeMapSurface(a,b,c)
+#define IDirect3DCubeTexture9_LockRect(p,a,b,c,d,e)       (p)->LockRect(a,b,c,d,e)
+#define IDirect3DCubeTexture9_UnlockRect(p,a,b)           (p)->UnlockRect(a,b)
+#define IDirect3DCubeTexture9_AddDirtyRect(p,a,b)         (p)->AddDirtyRect(a,b)
+#endif
+
+/*****************************************************************************
+ * IDirect3DTexture9 interface
+ */
+#define INTERFACE IDirect3DTexture9
+DECLARE_INTERFACE_(IDirect3DTexture9,IDirect3DBaseTexture9)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IDirect3DResource9 methods ***/
+    STDMETHOD(GetDevice)(THIS_ struct IDirect3DDevice9** ppDevice) PURE;
+    STDMETHOD(SetPrivateData)(THIS_ REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) PURE;
+    STDMETHOD(GetPrivateData)(THIS_ REFGUID refguid, void* pData, DWORD* pSizeOfData) PURE;
+    STDMETHOD(FreePrivateData)(THIS_ REFGUID refguid) PURE;
+    STDMETHOD_(DWORD, SetPriority)(THIS_ DWORD PriorityNew) PURE;
+    STDMETHOD_(DWORD, GetPriority)(THIS) PURE;
+    STDMETHOD_(void, PreLoad)(THIS) PURE;
+    STDMETHOD_(D3DRESOURCETYPE, GetType)(THIS) PURE;
+    /*** IDirect3DBaseTexture9 methods ***/
+    STDMETHOD_(DWORD, SetLOD)(THIS_ DWORD LODNew) PURE;
+    STDMETHOD_(DWORD, GetLOD)(THIS) PURE;
+    STDMETHOD_(DWORD, GetLevelCount)(THIS) PURE;
+    STDMETHOD(SetAutoGenFilterType)(THIS_ D3DTEXTUREFILTERTYPE FilterType) PURE;
+    STDMETHOD_(D3DTEXTUREFILTERTYPE, GetAutoGenFilterType)(THIS) PURE;
+    STDMETHOD_(void, GenerateMipSubLevels)(THIS) PURE;
+    /*** IDirect3DTexture9 methods ***/
+    STDMETHOD(GetLevelDesc)(THIS_ UINT Level, D3DSURFACE_DESC* pDesc) PURE;
+    STDMETHOD(GetSurfaceLevel)(THIS_ UINT Level, IDirect3DSurface9** ppSurfaceLevel) PURE;
+    STDMETHOD(LockRect)(THIS_ UINT Level, D3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) PURE;
+    STDMETHOD(UnlockRect)(THIS_ UINT Level) PURE;
+    STDMETHOD(AddDirtyRect)(THIS_ CONST RECT* pDirtyRect) PURE;
+};
+#undef INTERFACE
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+/*** IUnknown methods ***/
+#define IDirect3DTexture9_QueryInterface(p,a,b)      (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DTexture9_AddRef(p)                  (p)->lpVtbl->AddRef(p)
+#define IDirect3DTexture9_Release(p)                 (p)->lpVtbl->Release(p)
+/*** IDirect3DTexture9 methods: IDirect3DResource9 ***/
+#define IDirect3DTexture9_GetDevice(p,a)             (p)->lpVtbl->GetDevice(p,a)
+#define IDirect3DTexture9_SetPrivateData(p,a,b,c,d)  (p)->lpVtbl->SetPrivateData(p,a,b,c,d)
+#define IDirect3DTexture9_GetPrivateData(p,a,b,c)    (p)->lpVtbl->GetPrivateData(p,a,b,c)
+#define IDirect3DTexture9_FreePrivateData(p,a)       (p)->lpVtbl->FreePrivateData(p,a)
+#define IDirect3DTexture9_SetPriority(p,a)           (p)->lpVtbl->SetPriority(p,a)
+#define IDirect3DTexture9_GetPriority(p)             (p)->lpVtbl->GetPriority(p)
+#define IDirect3DTexture9_PreLoad(p)                 (p)->lpVtbl->PreLoad(p)
+#define IDirect3DTexture9_GetType(p)                 (p)->lpVtbl->GetType(p)
+/*** IDirect3DTexture9 methods: IDirect3DBaseTexture9 ***/
+#define IDirect3DTexture9_SetLOD(p,a)                (p)->lpVtbl->SetLOD(p,a)
+#define IDirect3DTexture9_GetLOD(p)                  (p)->lpVtbl->GetLOD(p)
+#define IDirect3DTexture9_GetLevelCount(p)           (p)->lpVtbl->GetLevelCount(p)
+#define IDirect3DTexture9_SetAutoGenFilterType(p,a)  (p)->lpVtbl->SetAutoGenFilterType(p,a)
+#define IDirect3DTexture9_GetAutoGenFilterType(p)    (p)->lpVtbl->GetAutoGenFilterType(p)
+#define IDirect3DTexture9_GenerateMipSubLevels(p)    (p)->lpVtbl->GenerateMipSubLevels(p)
+/*** IDirect3DTexture9 methods ***/
+#define IDirect3DTexture9_GetLevelDesc(p,a,b)        (p)->lpVtbl->GetLevelDesc(p,a,b)
+#define IDirect3DTexture9_GetSurfaceLevel(p,a,b)     (p)->lpVtbl->GetSurfaceLevel(p,a,b)
+#define IDirect3DTexture9_LockRect(p,a,b,c,d)        (p)->lpVtbl->LockRect(p,a,b,c,d)
+#define IDirect3DTexture9_UnlockRect(p,a)            (p)->lpVtbl->UnlockRect(p,a)
+#define IDirect3DTexture9_AddDirtyRect(p,a)          (p)->lpVtbl->AddDirtyRect(p,a)
+#else
+/*** IUnknown methods ***/
+#define IDirect3DTexture9_QueryInterface(p,a,b)      (p)->QueryInterface(a,b)
+#define IDirect3DTexture9_AddRef(p)                  (p)->AddRef()
+#define IDirect3DTexture9_Release(p)                 (p)->Release()
+/*** IDirect3DTexture9 methods: IDirect3DResource9 ***/
+#define IDirect3DTexture9_GetDevice(p,a)             (p)->GetDevice(a)
+#define IDirect3DTexture9_SetPrivateData(p,a,b,c,d)  (p)->SetPrivateData(a,b,c,d)
+#define IDirect3DTexture9_GetPrivateData(p,a,b,c)    (p)->GetPrivateData(a,b,c)
+#define IDirect3DTexture9_FreePrivateData(p,a)       (p)->FreePrivateData(a)
+#define IDirect3DTexture9_SetPriority(p,a)           (p)->SetPriority(a)
+#define IDirect3DTexture9_GetPriority(p)             (p)->GetPriority()
+#define IDirect3DTexture9_PreLoad(p)                 (p)->PreLoad()
+#define IDirect3DTexture9_GetType(p)                 (p)->GetType()
+/*** IDirect3DTexture9 methods: IDirect3DBaseTexture9 ***/
+#define IDirect3DTexture9_SetLOD(p,a)                (p)->SetLOD(a)
+#define IDirect3DTexture9_GetLOD(p)                  (p)->GetLOD()
+#define IDirect3DTexture9_GetLevelCount(p)           (p)->GetLevelCount()
+#define IDirect3DTexture9_SetAutoGenFilterType(p,a)  (p)->SetAutoGenFilterType(a)
+#define IDirect3DTexture9_GetAutoGenFilterType(p)    (p)->GetAutoGenFilterType()
+#define IDirect3DTexture9_GenerateMipSubLevels(p)    (p)->GenerateMipSubLevels()
+/*** IDirect3DTexture9 methods ***/
+#define IDirect3DTexture9_GetLevelDesc(p,a,b)        (p)->GetLevelDesc(a,b)
+#define IDirect3DTexture9_GetSurfaceLevel(p,a,b)     (p)->GetSurfaceLevel(a,b)
+#define IDirect3DTexture9_LockRect(p,a,b,c,d)        (p)->LockRect(a,b,c,d)
+#define IDirect3DTexture9_UnlockRect(p,a)            (p)->UnlockRect(a)
+#define IDirect3DTexture9_AddDirtyRect(p,a)          (p)->AddDirtyRect(a)
+#endif
+
+/*****************************************************************************
+ * IDirect3DVolumeTexture9 interface
+ */
+#define INTERFACE IDirect3DVolumeTexture9
+DECLARE_INTERFACE_(IDirect3DVolumeTexture9,IDirect3DBaseTexture9)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IDirect3DResource9 methods ***/
+    STDMETHOD(GetDevice)(THIS_ struct IDirect3DDevice9** ppDevice) PURE;
+    STDMETHOD(SetPrivateData)(THIS_ REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) PURE;
+    STDMETHOD(GetPrivateData)(THIS_ REFGUID refguid, void* pData, DWORD* pSizeOfData) PURE;
+    STDMETHOD(FreePrivateData)(THIS_ REFGUID refguid) PURE;
+    STDMETHOD_(DWORD, SetPriority)(THIS_ DWORD PriorityNew) PURE;
+    STDMETHOD_(DWORD, GetPriority)(THIS) PURE;
+    STDMETHOD_(void, PreLoad)(THIS) PURE;
+    STDMETHOD_(D3DRESOURCETYPE, GetType)(THIS) PURE;
+    /*** IDirect3DBaseTexture9 methods ***/
+    STDMETHOD_(DWORD, SetLOD)(THIS_ DWORD LODNew) PURE;
+    STDMETHOD_(DWORD, GetLOD)(THIS) PURE;
+    STDMETHOD_(DWORD, GetLevelCount)(THIS) PURE;
+    STDMETHOD(SetAutoGenFilterType)(THIS_ D3DTEXTUREFILTERTYPE FilterType) PURE;
+    STDMETHOD_(D3DTEXTUREFILTERTYPE, GetAutoGenFilterType)(THIS) PURE;
+    STDMETHOD_(void, GenerateMipSubLevels)(THIS) PURE;
+    /*** IDirect3DVolumeTexture9 methods ***/
+    STDMETHOD(GetLevelDesc)(THIS_ UINT Level, D3DVOLUME_DESC *pDesc) PURE;
+    STDMETHOD(GetVolumeLevel)(THIS_ UINT Level, IDirect3DVolume9** ppVolumeLevel) PURE;
+    STDMETHOD(LockBox)(THIS_ UINT Level, D3DLOCKED_BOX* pLockedVolume, CONST D3DBOX* pBox, DWORD Flags) PURE;
+    STDMETHOD(UnlockBox)(THIS_ UINT Level) PURE;
+    STDMETHOD(AddDirtyBox)(THIS_ CONST D3DBOX* pDirtyBox) PURE;
+};
+#undef INTERFACE
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+/*** IUnknown methods ***/
+#define IDirect3DVolumeTexture9_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DVolumeTexture9_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirect3DVolumeTexture9_Release(p) (p)->lpVtbl->Release(p)
+/*** IDirect3DVolumeTexture9 methods: IDirect3DResource9 ***/
+#define IDirect3DVolumeTexture9_GetDevice(p,a) (p)->lpVtbl->GetDevice(p,a)
+#define IDirect3DVolumeTexture9_SetPrivateData(p,a,b,c,d) (p)->lpVtbl->SetPrivateData(p,a,b,c,d)
+#define IDirect3DVolumeTexture9_GetPrivateData(p,a,b,c) (p)->lpVtbl->GetPrivateData(p,a,b,c)
+#define IDirect3DVolumeTexture9_FreePrivateData(p,a) (p)->lpVtbl->FreePrivateData(p,a)
+#define IDirect3DVolumeTexture9_SetPriority(p,a) (p)->lpVtbl->SetPriority(p,a)
+#define IDirect3DVolumeTexture9_GetPriority(p) (p)->lpVtbl->GetPriority(p)
+#define IDirect3DVolumeTexture9_PreLoad(p) (p)->lpVtbl->PreLoad(p)
+#define IDirect3DVolumeTexture9_GetType(p) (p)->lpVtbl->GetType(p)
+/*** IDirect3DVolumeTexture9 methods: IDirect3DBaseTexture9 ***/
+#define IDirect3DVolumeTexture9_SetLOD(p,a) (p)->lpVtbl->SetLOD(p,a)
+#define IDirect3DVolumeTexture9_GetLOD(p) (p)->lpVtbl->GetLOD(p)
+#define IDirect3DVolumeTexture9_GetLevelCount(p) (p)->lpVtbl->GetLevelCount(p)
+#define IDirect3DVolumeTexture9_SetAutoGenFilterType(p,a) (p)->lpVtbl->SetAutoGenFilterType(p,a)
+#define IDirect3DVolumeTexture9_GetAutoGenFilterType(p) (p)->lpVtbl->GetAutoGenFilterType(p)
+#define IDirect3DVolumeTexture9_GenerateMipSubLevels(p) (p)->lpVtbl->GenerateMipSubLevels(p)
+/*** IDirect3DVolumeTexture9 methods ***/
+#define IDirect3DVolumeTexture9_GetLevelDesc(p,a,b) (p)->lpVtbl->GetLevelDesc(p,a,b)
+#define IDirect3DVolumeTexture9_GetVolumeLevel(p,a,b) (p)->lpVtbl->GetVolumeLevel(p,a,b)
+#define IDirect3DVolumeTexture9_LockBox(p,a,b,c,d) (p)->lpVtbl->LockBox(p,a,b,c,d)
+#define IDirect3DVolumeTexture9_UnlockBox(p,a) (p)->lpVtbl->UnlockBox(p,a)
+#define IDirect3DVolumeTexture9_AddDirtyBox(p,a) (p)->lpVtbl->AddDirtyBox(p,a)
+#else
+/*** IUnknown methods ***/
+#define IDirect3DVolumeTexture9_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirect3DVolumeTexture9_AddRef(p) (p)->AddRef()
+#define IDirect3DVolumeTexture9_Release(p) (p)->Release()
+/*** IDirect3DVolumeTexture9 methods: IDirect3DResource9 ***/
+#define IDirect3DVolumeTexture9_GetDevice(p,a) (p)->GetDevice(a)
+#define IDirect3DVolumeTexture9_SetPrivateData(p,a,b,c,d) (p)->SetPrivateData(a,b,c,d)
+#define IDirect3DVolumeTexture9_GetPrivateData(p,a,b,c) (p)->GetPrivateData(a,b,c)
+#define IDirect3DVolumeTexture9_FreePrivateData(p,a) (p)->FreePrivateData(a)
+#define IDirect3DVolumeTexture9_SetPriority(p,a) (p)->SetPriority(a)
+#define IDirect3DVolumeTexture9_GetPriority(p) (p)->GetPriority()
+#define IDirect3DVolumeTexture9_PreLoad(p) (p)->PreLoad()
+#define IDirect3DVolumeTexture9_GetType(p) (p)->GetType()
+/*** IDirect3DVolumeTexture9 methods: IDirect3DBaseTexture9 ***/
+#define IDirect3DVolumeTexture9_SetLOD(p,a) (p)->SetLOD(a)
+#define IDirect3DVolumeTexture9_GetLOD(p) (p)->GetLOD()
+#define IDirect3DVolumeTexture9_GetLevelCount(p) (p)->GetLevelCount()
+#define IDirect3DVolumeTexture9_SetAutoGenFilterType(p,a) (p)->SetAutoGenFilterType(a)
+#define IDirect3DVolumeTexture9_GetAutoGenFilterType(p) (p)->GetAutoGenFilterType()
+#define IDirect3DVolumeTexture9_GenerateMipSubLevels(p) (p)->GenerateMipSubLevels()
+/*** IDirect3DVolumeTexture9 methods ***/
+#define IDirect3DVolumeTexture9_GetLevelDesc(p,a,b) (p)->GetLevelDesc(a,b)
+#define IDirect3DVolumeTexture9_GetVolumeLevel(p,a,b) (p)->GetVolumeLevel(a,b)
+#define IDirect3DVolumeTexture9_LockBox(p,a,b,c,d) (p)->LockBox(a,b,c,d)
+#define IDirect3DVolumeTexture9_UnlockBox(p,a) (p)->UnlockBox(a)
+#define IDirect3DVolumeTexture9_AddDirtyBox(p,a) (p)->AddDirtyBox(a)
+#endif
+
+/*****************************************************************************
+ * IDirect3DVertexDeclaration9 interface
+ */
+#define INTERFACE IDirect3DVertexDeclaration9
+DECLARE_INTERFACE_(IDirect3DVertexDeclaration9,IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IDirect3DVertexDeclaration9 methods ***/
+    STDMETHOD(GetDevice)(THIS_ struct IDirect3DDevice9** ppDevice) PURE;
+    STDMETHOD(GetDeclaration)(THIS_ D3DVERTEXELEMENT9*, UINT* pNumElements) PURE;
+};
+#undef INTERFACE
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+/*** IUnknown methods ***/
+#define IDirect3DVertexDeclaration9_QueryInterface(p,a,b)  (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DVertexDeclaration9_AddRef(p)              (p)->lpVtbl->AddRef(p)
+#define IDirect3DVertexDeclaration9_Release(p)             (p)->lpVtbl->Release(p)
+/*** IDirect3DVertexShader9 methods ***/
+#define IDirect3DVertexDeclaration9_GetDevice(p,a)         (p)->lpVtbl->GetDevice(p,a)
+#define IDirect3DVertexDeclaration9_GetDeclaration(p,a,b)  (p)->lpVtbl->GetDeclaration(p,a,b)
+#else
+/*** IUnknown methods ***/
+#define IDirect3DVertexDeclaration9_QueryInterface(p,a,b)  (p)->QueryInterface(a,b)
+#define IDirect3DVertexDeclaration9_AddRef(p)              (p)->AddRef()
+#define IDirect3DVertexDeclaration9_Release(p)             (p)->Release()
+/*** IDirect3DVertexShader9 methods ***/
+#define IDirect3DVertexDeclaration9_GetDevice(p,a)         (p)->GetDevice(a)
+#define IDirect3DVertexDeclaration9_GetDeclaration(p,a,b)  (p)->GetDeclaration(a,b)
+#endif
+
+/*****************************************************************************
+ * IDirect3DVertexShader9 interface
+ */
+#define INTERFACE IDirect3DVertexShader9
+DECLARE_INTERFACE_(IDirect3DVertexShader9,IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IDirect3DVertexShader9 methods ***/
+    STDMETHOD(GetDevice)(THIS_ struct IDirect3DDevice9** ppDevice) PURE;
+    STDMETHOD(GetFunction)(THIS_ void*, UINT* pSizeOfData) PURE;
+};
+#undef INTERFACE
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+/*** IUnknown methods ***/
+#define IDirect3DVertexShader9_QueryInterface(p,a,b)  (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DVertexShader9_AddRef(p)              (p)->lpVtbl->AddRef(p)
+#define IDirect3DVertexShader9_Release(p)             (p)->lpVtbl->Release(p)
+/*** IDirect3DVertexShader9 methods ***/
+#define IDirect3DVertexShader9_GetDevice(p,a)         (p)->lpVtbl->GetDevice(p,a)
+#define IDirect3DVertexShader9_GetFunction(p,a,b)     (p)->lpVtbl->GetFunction(p,a,b)
+#else
+/*** IUnknown methods ***/
+#define IDirect3DVertexShader9_QueryInterface(p,a,b)  (p)->QueryInterface(a,b)
+#define IDirect3DVertexShader9_AddRef(p)              (p)->AddRef()
+#define IDirect3DVertexShader9_Release(p)             (p)->Release()
+/*** IDirect3DVertexShader9 methods ***/
+#define IDirect3DVertexShader9_GetDevice(p,a)         (p)->GetDevice(a)
+#define IDirect3DVertexShader9_GetFunction(p,a,b)     (p)->GetFunction(a,b)
+#endif
+
+/*****************************************************************************
+ * IDirect3DPixelShader9 interface
+ */
+#define INTERFACE IDirect3DPixelShader9
+DECLARE_INTERFACE_(IDirect3DPixelShader9,IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IDirect3DPixelShader9 methods ***/
+    STDMETHOD(GetDevice)(THIS_ struct IDirect3DDevice9** ppDevice) PURE;
+    STDMETHOD(GetFunction)(THIS_ void*, UINT* pSizeOfData) PURE;
+};
+#undef INTERFACE
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+/*** IUnknown methods ***/
+#define IDirect3DPixelShader9_QueryInterface(p,a,b)  (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DPixelShader9_AddRef(p)              (p)->lpVtbl->AddRef(p)
+#define IDirect3DPixelShader9_Release(p)             (p)->lpVtbl->Release(p)
+/*** IDirect3DPixelShader9 methods ***/
+#define IDirect3DPixelShader9_GetDevice(p,a)         (p)->lpVtbl->GetDevice(p,a)
+#define IDirect3DPixelShader9_GetFunction(p,a,b)     (p)->lpVtbl->GetFunction(p,a,b)
+#else
+/*** IUnknown methods ***/
+#define IDirect3DPixelShader9_QueryInterface(p,a,b)  (p)->QueryInterface(a,b)
+#define IDirect3DPixelShader9_AddRef(p)              (p)->AddRef()
+#define IDirect3DPixelShader9_Release(p)             (p)->Release()
+/*** IDirect3DPixelShader9 methods ***/
+#define IDirect3DPixelShader9_GetDevice(p,a)         (p)->GetDevice(a)
+#define IDirect3DPixelShader9_GetFunction(p,a,b)     (p)->GetFunction(a,b)
+#endif
+
+/*****************************************************************************
+ * IDirect3DStateBlock9 interface
+ */
+#define INTERFACE IDirect3DStateBlock9
+DECLARE_INTERFACE_(IDirect3DStateBlock9,IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IDirect3DStateBlock9 methods ***/
+    STDMETHOD(GetDevice)(THIS_ struct IDirect3DDevice9** ppDevice) PURE;
+    STDMETHOD(Capture)(THIS) PURE;
+    STDMETHOD(Apply)(THIS) PURE;
+};
+#undef INTERFACE
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+/*** IUnknown methods ***/
+#define IDirect3DStateBlock9_QueryInterface(p,a,b)  (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DStateBlock9_AddRef(p)              (p)->lpVtbl->AddRef(p)
+#define IDirect3DStateBlock9_Release(p)             (p)->lpVtbl->Release(p)
+/*** IDirect3DStateBlock9 methods ***/
+#define IDirect3DStateBlock9_GetDevice(p,a)         (p)->lpVtbl->GetDevice(p,a)
+#define IDirect3DStateBlock9_Capture(p)             (p)->lpVtbl->Capture(p)
+#define IDirect3DStateBlock9_Apply(p)               (p)->lpVtbl->Apply(p)
+#else
+/*** IUnknown methods ***/
+#define IDirect3DStateBlock9_QueryInterface(p,a,b)  (p)->QueryInterface(a,b)
+#define IDirect3DStateBlock9_AddRef(p)              (p)->AddRef()
+#define IDirect3DStateBlock9_Release(p)             (p)->Release()
+/*** IDirect3DStateBlock9 methods ***/
+#define IDirect3DStateBlock9_GetDevice(p,a)         (p)->GetDevice(a)
+#define IDirect3DStateBlock9_Capture(p)             (p)->Capture()
+#define IDirect3DStateBlock9_Apply(p)               (p)->Apply()
+#endif
+
+/*****************************************************************************
+ * IDirect3DQuery9 interface
+ */
+#define INTERFACE IDirect3DQuery9
+DECLARE_INTERFACE_(IDirect3DQuery9,IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IDirect3DQuery9 methods ***/
+    STDMETHOD(GetDevice)(THIS_ struct IDirect3DDevice9** ppDevice) PURE;
+    STDMETHOD_(D3DQUERYTYPE, GetType)(THIS) PURE;
+    STDMETHOD_(DWORD, GetDataSize)(THIS) PURE;
+    STDMETHOD(Issue)(THIS_ DWORD dwIssueFlags) PURE;
+    STDMETHOD(GetData)(THIS_ void* pData, DWORD dwSize, DWORD dwGetDataFlags) PURE;
+};
+#undef INTERFACE
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+/*** IUnknown methods ***/
+#define IDirect3DQuery9_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DQuery9_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirect3DQuery9_Release(p) (p)->lpVtbl->Release(p)
+/*** IDirect3DQuery9 ***/
+#define IDirect3DQuery9_GetDevice(p,a) (p)->lpVtbl->GetDevice(p,a)
+#define IDirect3DQuery9_GetType(p) (p)->lpVtbl->GetType(p)
+#define IDirect3DQuery9_GetDataSize(p) (p)->lpVtbl->GetDataSize(p)
+#define IDirect3DQuery9_Issue(p,a) (p)->lpVtbl->Issue(p,a)
+#define IDirect3DQuery9_GetData(p,a,b,c) (p)->lpVtbl->GetData(p,a,b,c)
+#else
+/*** IUnknown methods ***/
+#define IDirect3DQuery9_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirect3DQuery9_AddRef(p) (p)->AddRef()
+#define IDirect3DQuery9_Release(p) (p)->Release()
+/*** IDirect3DQuery9 ***/
+#define IDirect3DQuery9_GetDevice(p,a) (p)->GetDevice(a)
+#define IDirect3DQuery9_GetType(p) (p)->GetType()
+#define IDirect3DQuery9_GetDataSize(p) (p)->GetDataSize()
+#define IDirect3DQuery9_Issue(p,a) (p)->Issue(a)
+#define IDirect3DQuery9_GetData(p,a,b,c) (p)->GetData(a,b,c)
+#endif
+
+/*****************************************************************************
+ * IDirect3DDevice9 interface
+ */
+#define INTERFACE IDirect3DDevice9
+DECLARE_INTERFACE_(IDirect3DDevice9,IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IDirect3DDevice9 methods ***/
+    STDMETHOD(TestCooperativeLevel)(THIS) PURE;
+    STDMETHOD_(UINT, GetAvailableTextureMem)(THIS) PURE;
+    STDMETHOD(EvictManagedResources)(THIS) PURE;
+    STDMETHOD(GetDirect3D)(THIS_ IDirect3D9** ppD3D9) PURE;
+    STDMETHOD(GetDeviceCaps)(THIS_ D3DCAPS9* pCaps) PURE;
+    STDMETHOD(GetDisplayMode)(THIS_ UINT iSwapChain, D3DDISPLAYMODE* pMode) PURE;
+    STDMETHOD(GetCreationParameters)(THIS_ D3DDEVICE_CREATION_PARAMETERS *pParameters) PURE;
+    STDMETHOD(SetCursorProperties)(THIS_ UINT XHotSpot, UINT YHotSpot, IDirect3DSurface9* pCursorBitmap) PURE;
+    STDMETHOD_(void, SetCursorPosition)(THIS_ int X,int Y, DWORD Flags) PURE;
+    STDMETHOD_(BOOL, ShowCursor)(THIS_ BOOL bShow) PURE;
+    STDMETHOD(CreateAdditionalSwapChain)(THIS_ D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain9** pSwapChain) PURE;
+    STDMETHOD(GetSwapChain)(THIS_ UINT iSwapChain, IDirect3DSwapChain9** pSwapChain) PURE;
+    STDMETHOD_(UINT, GetNumberOfSwapChains)(THIS) PURE;
+    STDMETHOD(Reset)(THIS_ D3DPRESENT_PARAMETERS* pPresentationParameters) PURE;
+    STDMETHOD(Present)(THIS_ CONST RECT* pSourceRect, CONST RECT* pDestRect, HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) PURE;
+    STDMETHOD(GetBackBuffer)(THIS_ UINT iSwapChain, UINT iBackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9** ppBackBuffer) PURE;
+    STDMETHOD(GetRasterStatus)(THIS_ UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) PURE;
+    STDMETHOD(SetDialogBoxMode)(THIS_ BOOL bEnableDialogs) PURE;
+    STDMETHOD_(void, SetGammaRamp)(THIS_ UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) PURE;
+    STDMETHOD_(void, GetGammaRamp)(THIS_ UINT iSwapChain, D3DGAMMARAMP* pRamp) PURE;
+    STDMETHOD(CreateTexture)(THIS_ UINT Width, UINT Height, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture9** ppTexture, HANDLE* pSharedHandle) PURE;
+    STDMETHOD(CreateVolumeTexture)(THIS_ UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture9** ppVolumeTexture, HANDLE* pSharedHandle) PURE;
+    STDMETHOD(CreateCubeTexture)(THIS_ UINT EdgeLength, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture9** ppCubeTexture, HANDLE* pSharedHandle) PURE;
+    STDMETHOD(CreateVertexBuffer)(THIS_ UINT Length, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer9** ppVertexBuffer, HANDLE* pSharedHandle) PURE;
+    STDMETHOD(CreateIndexBuffer)(THIS_ UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer9** ppIndexBuffer, HANDLE* pSharedHandle) PURE;
+    STDMETHOD(CreateRenderTarget)(THIS_ UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Lockable, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle) PURE;
+    STDMETHOD(CreateDepthStencilSurface)(THIS_ UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Discard, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle) PURE;
+    STDMETHOD(UpdateSurface)(THIS_ IDirect3DSurface9* pSourceSurface, CONST RECT* pSourceRect, IDirect3DSurface9* pDestinationSurface, CONST POINT* pDestPoint) PURE;
+    STDMETHOD(UpdateTexture)(THIS_ IDirect3DBaseTexture9* pSourceTexture, IDirect3DBaseTexture9* pDestinationTexture) PURE;
+    STDMETHOD(GetRenderTargetData)(THIS_ IDirect3DSurface9* pRenderTarget, IDirect3DSurface9* pDestSurface) PURE;
+    STDMETHOD(GetFrontBufferData)(THIS_ UINT iSwapChain, IDirect3DSurface9* pDestSurface) PURE;
+    STDMETHOD(StretchRect)(THIS_ IDirect3DSurface9* pSourceSurface, CONST RECT* pSourceRect, IDirect3DSurface9* pDestSurface, CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) PURE;
+    STDMETHOD(ColorFill)(THIS_ IDirect3DSurface9* pSurface, CONST RECT* pRect, D3DCOLOR color) PURE;
+    STDMETHOD(CreateOffscreenPlainSurface)(THIS_ UINT Width, UINT Height, D3DFORMAT Format, D3DPOOL Pool, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle) PURE;
+    STDMETHOD(SetRenderTarget)(THIS_ DWORD RenderTargetIndex, IDirect3DSurface9* pRenderTarget) PURE;
+    STDMETHOD(GetRenderTarget)(THIS_ DWORD RenderTargetIndex, IDirect3DSurface9** ppRenderTarget) PURE;
+    STDMETHOD(SetDepthStencilSurface)(THIS_ IDirect3DSurface9* pNewZStencil) PURE;
+    STDMETHOD(GetDepthStencilSurface)(THIS_ IDirect3DSurface9** ppZStencilSurface) PURE;
+    STDMETHOD(BeginScene)(THIS) PURE;
+    STDMETHOD(EndScene)(THIS) PURE;
+    STDMETHOD(Clear)(THIS_ DWORD Count, CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) PURE;
+    STDMETHOD(SetTransform)(THIS_ D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) PURE;
+    STDMETHOD(GetTransform)(THIS_ D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) PURE;
+    STDMETHOD(MultiplyTransform)(THIS_ D3DTRANSFORMSTATETYPE, CONST D3DMATRIX*) PURE;
+    STDMETHOD(SetViewport)(THIS_ CONST D3DVIEWPORT9* pViewport) PURE;
+    STDMETHOD(GetViewport)(THIS_ D3DVIEWPORT9* pViewport) PURE;
+    STDMETHOD(SetMaterial)(THIS_ CONST D3DMATERIAL9* pMaterial) PURE;
+    STDMETHOD(GetMaterial)(THIS_ D3DMATERIAL9* pMaterial) PURE;
+    STDMETHOD(SetLight)(THIS_ DWORD Index, CONST D3DLIGHT9*) PURE;
+    STDMETHOD(GetLight)(THIS_ DWORD Index, D3DLIGHT9*) PURE;
+    STDMETHOD(LightEnable)(THIS_ DWORD Index, BOOL Enable) PURE;
+    STDMETHOD(GetLightEnable)(THIS_ DWORD Index, BOOL* pEnable) PURE;
+    STDMETHOD(SetClipPlane)(THIS_ DWORD Index, CONST float* pPlane) PURE;
+    STDMETHOD(GetClipPlane)(THIS_ DWORD Index, float* pPlane) PURE;
+    STDMETHOD(SetRenderState)(THIS_ D3DRENDERSTATETYPE State, DWORD Value) PURE;
+    STDMETHOD(GetRenderState)(THIS_ D3DRENDERSTATETYPE State, DWORD* pValue) PURE;
+    STDMETHOD(CreateStateBlock)(THIS_ D3DSTATEBLOCKTYPE Type, IDirect3DStateBlock9** ppSB) PURE;
+    STDMETHOD(BeginStateBlock)(THIS) PURE;
+    STDMETHOD(EndStateBlock)(THIS_ IDirect3DStateBlock9** ppSB) PURE;
+    STDMETHOD(SetClipStatus)(THIS_ CONST D3DCLIPSTATUS9* pClipStatus) PURE;
+    STDMETHOD(GetClipStatus)(THIS_ D3DCLIPSTATUS9* pClipStatus) PURE;
+    STDMETHOD(GetTexture)(THIS_ DWORD Stage, IDirect3DBaseTexture9** ppTexture) PURE;
+    STDMETHOD(SetTexture)(THIS_ DWORD Stage, IDirect3DBaseTexture9* pTexture) PURE;
+    STDMETHOD(GetTextureStageState)(THIS_ DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) PURE;
+    STDMETHOD(SetTextureStageState)(THIS_ DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) PURE;
+    STDMETHOD(GetSamplerState)(THIS_ DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD* pValue) PURE;
+    STDMETHOD(SetSamplerState)(THIS_ DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value) PURE;
+    STDMETHOD(ValidateDevice)(THIS_ DWORD* pNumPasses) PURE;
+    STDMETHOD(SetPaletteEntries)(THIS_ UINT PaletteNumber, CONST PALETTEENTRY* pEntries) PURE;
+    STDMETHOD(GetPaletteEntries)(THIS_ UINT PaletteNumber,PALETTEENTRY* pEntries) PURE;
+    STDMETHOD(SetCurrentTexturePalette)(THIS_ UINT PaletteNumber) PURE;
+    STDMETHOD(GetCurrentTexturePalette)(THIS_ UINT *PaletteNumber) PURE;
+    STDMETHOD(SetScissorRect)(THIS_ CONST RECT* pRect) PURE;
+    STDMETHOD(GetScissorRect)(THIS_ RECT* pRect) PURE;
+    STDMETHOD(SetSoftwareVertexProcessing)(THIS_ BOOL bSoftware) PURE;
+    STDMETHOD_(BOOL, GetSoftwareVertexProcessing)(THIS) PURE;
+    STDMETHOD(SetNPatchMode)(THIS_ float nSegments) PURE;
+    STDMETHOD_(float, GetNPatchMode)(THIS) PURE;
+    STDMETHOD(DrawPrimitive)(THIS_ D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) PURE;
+    STDMETHOD(DrawIndexedPrimitive)(THIS_ D3DPRIMITIVETYPE, INT BaseVertexIndex, UINT MinVertexIndex, UINT NumVertices, UINT startIndex, UINT primCount) PURE;
+    STDMETHOD(DrawPrimitiveUP)(THIS_ D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, CONST void* pVertexStreamZeroData, UINT VertexStreamZeroStride) PURE;
+    STDMETHOD(DrawIndexedPrimitiveUP)(THIS_ D3DPRIMITIVETYPE PrimitiveType, UINT MinVertexIndex, UINT NumVertices, UINT PrimitiveCount, CONST void* pIndexData, D3DFORMAT IndexDataFormat, CONST void* pVertexStreamZeroData, UINT VertexStreamZeroStride) PURE;
+    STDMETHOD(ProcessVertices)(THIS_ UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IDirect3DVertexBuffer9* pDestBuffer, IDirect3DVertexDeclaration9* pVertexDecl, DWORD Flags) PURE;
+    STDMETHOD(CreateVertexDeclaration)(THIS_ CONST D3DVERTEXELEMENT9* pVertexElements, IDirect3DVertexDeclaration9** ppDecl) PURE;
+    STDMETHOD(SetVertexDeclaration)(THIS_ IDirect3DVertexDeclaration9* pDecl) PURE;
+    STDMETHOD(GetVertexDeclaration)(THIS_ IDirect3DVertexDeclaration9** ppDecl) PURE;
+    STDMETHOD(SetFVF)(THIS_ DWORD FVF) PURE;
+    STDMETHOD(GetFVF)(THIS_ DWORD* pFVF) PURE;
+    STDMETHOD(CreateVertexShader)(THIS_ CONST DWORD* pFunction, IDirect3DVertexShader9** ppShader) PURE;
+    STDMETHOD(SetVertexShader)(THIS_ IDirect3DVertexShader9* pShader) PURE;
+    STDMETHOD(GetVertexShader)(THIS_ IDirect3DVertexShader9** ppShader) PURE;
+    STDMETHOD(SetVertexShaderConstantF)(THIS_ UINT StartRegister, CONST float* pConstantData, UINT Vector4fCount) PURE;
+    STDMETHOD(GetVertexShaderConstantF)(THIS_ UINT StartRegister, float* pConstantData, UINT Vector4fCount) PURE;
+    STDMETHOD(SetVertexShaderConstantI)(THIS_ UINT StartRegister, CONST int* pConstantData, UINT Vector4iCount) PURE;
+    STDMETHOD(GetVertexShaderConstantI)(THIS_ UINT StartRegister, int* pConstantData, UINT Vector4iCount) PURE;
+    STDMETHOD(SetVertexShaderConstantB)(THIS_ UINT StartRegister, CONST BOOL* pConstantData, UINT  BoolCount) PURE;
+    STDMETHOD(GetVertexShaderConstantB)(THIS_ UINT StartRegister, BOOL* pConstantData, UINT BoolCount) PURE;
+    STDMETHOD(SetStreamSource)(THIS_ UINT StreamNumber, IDirect3DVertexBuffer9* pStreamData, UINT OffsetInBytes, UINT Stride) PURE;
+    STDMETHOD(GetStreamSource)(THIS_ UINT StreamNumber, IDirect3DVertexBuffer9** ppStreamData, UINT* OffsetInBytes, UINT* pStride) PURE;
+    STDMETHOD(SetStreamSourceFreq)(THIS_ UINT StreamNumber, UINT Divider) PURE;
+    STDMETHOD(GetStreamSourceFreq)(THIS_ UINT StreamNumber, UINT* Divider) PURE;
+    STDMETHOD(SetIndices)(THIS_ IDirect3DIndexBuffer9* pIndexData) PURE;
+    STDMETHOD(GetIndices)(THIS_ IDirect3DIndexBuffer9** ppIndexData) PURE;
+    STDMETHOD(CreatePixelShader)(THIS_ CONST DWORD* pFunction, IDirect3DPixelShader9** ppShader) PURE;
+    STDMETHOD(SetPixelShader)(THIS_ IDirect3DPixelShader9* pShader) PURE;
+    STDMETHOD(GetPixelShader)(THIS_ IDirect3DPixelShader9** ppShader) PURE;
+    STDMETHOD(SetPixelShaderConstantF)(THIS_ UINT StartRegister, CONST float* pConstantData, UINT Vector4fCount) PURE;
+    STDMETHOD(GetPixelShaderConstantF)(THIS_ UINT StartRegister, float* pConstantData, UINT Vector4fCount) PURE;
+    STDMETHOD(SetPixelShaderConstantI)(THIS_ UINT StartRegister, CONST int* pConstantData, UINT Vector4iCount) PURE;
+    STDMETHOD(GetPixelShaderConstantI)(THIS_ UINT StartRegister, int* pConstantData, UINT Vector4iCount) PURE;
+    STDMETHOD(SetPixelShaderConstantB)(THIS_ UINT StartRegister, CONST BOOL* pConstantData, UINT  BoolCount) PURE;
+    STDMETHOD(GetPixelShaderConstantB)(THIS_ UINT StartRegister, BOOL* pConstantData, UINT BoolCount) PURE;
+    STDMETHOD(DrawRectPatch)(THIS_ UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo) PURE;
+    STDMETHOD(DrawTriPatch)(THIS_ UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo) PURE;
+    STDMETHOD(DeletePatch)(THIS_ UINT Handle) PURE;
+    STDMETHOD(CreateQuery)(THIS_ D3DQUERYTYPE Type, IDirect3DQuery9** ppQuery) PURE;
+};
+#undef INTERFACE
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+/*** IUnknown methods ***/
+#define IDirect3DDevice9_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DDevice9_AddRef(p)             (p)->lpVtbl->AddRef(p)
+#define IDirect3DDevice9_Release(p)            (p)->lpVtbl->Release(p)
+/*** IDirect3DDevice9 methods ***/
+#define IDirect3DDevice9_TestCooperativeLevel(p)                       (p)->lpVtbl->TestCooperativeLevel(p)
+#define IDirect3DDevice9_GetAvailableTextureMem(p)                     (p)->lpVtbl->GetAvailableTextureMem(p)
+#define IDirect3DDevice9_EvictManagedResources(p)                      (p)->lpVtbl->EvictManagedResources(p)
+#define IDirect3DDevice9_GetDirect3D(p,a)                              (p)->lpVtbl->GetDirect3D(p,a)
+#define IDirect3DDevice9_GetDeviceCaps(p,a)                            (p)->lpVtbl->GetDeviceCaps(p,a)
+#define IDirect3DDevice9_GetDisplayMode(p,a,b)                         (p)->lpVtbl->GetDisplayMode(p,a,b)
+#define IDirect3DDevice9_GetCreationParameters(p,a)                    (p)->lpVtbl->GetCreationParameters(p,a)
+#define IDirect3DDevice9_SetCursorProperties(p,a,b,c)                  (p)->lpVtbl->SetCursorProperties(p,a,b,c)
+#define IDirect3DDevice9_SetCursorPosition(p,a,b,c)                    (p)->lpVtbl->SetCursorPosition(p,a,b,c)
+#define IDirect3DDevice9_ShowCursor(p,a)                               (p)->lpVtbl->ShowCursor(p,a)
+#define IDirect3DDevice9_CreateAdditionalSwapChain(p,a,b)              (p)->lpVtbl->CreateAdditionalSwapChain(p,a,b)
+#define IDirect3DDevice9_GetSwapChain(p,a,b)                           (p)->lpVtbl->GetSwapChain(p,a,b)
+#define IDirect3DDevice9_GetNumberOfSwapChains(p)                      (p)->lpVtbl->GetNumberOfSwapChains(p)
+#define IDirect3DDevice9_Reset(p,a)                                    (p)->lpVtbl->Reset(p,a)
+#define IDirect3DDevice9_Present(p,a,b,c,d)                            (p)->lpVtbl->Present(p,a,b,c,d)
+#define IDirect3DDevice9_GetBackBuffer(p,a,b,c,d)                      (p)->lpVtbl->GetBackBuffer(p,a,b,c,d)
+#define IDirect3DDevice9_GetRasterStatus(p,a,b)                        (p)->lpVtbl->GetRasterStatus(p,a,b)
+#define IDirect3DDevice9_SetDialogBoxMode(p,a)                         (p)->lpVtbl->SetDialogBoxMode(p,a)
+#define IDirect3DDevice9_SetGammaRamp(p,a,b,c)                         (p)->lpVtbl->SetGammaRamp(p,a,b,c)
+#define IDirect3DDevice9_GetGammaRamp(p,a,b)                           (p)->lpVtbl->GetGammaRamp(p,a,b)
+#define IDirect3DDevice9_CreateTexture(p,a,b,c,d,e,f,g,h)              (p)->lpVtbl->CreateTexture(p,a,b,c,d,e,f,g,h)
+#define IDirect3DDevice9_CreateVolumeTexture(p,a,b,c,d,e,f,g,h,i)      (p)->lpVtbl->CreateVolumeTexture(p,a,b,c,d,e,f,g,h,i)
+#define IDirect3DDevice9_CreateCubeTexture(p,a,b,c,d,e,f,g)            (p)->lpVtbl->CreateCubeTexture(p,a,b,c,d,e,f,g)
+#define IDirect3DDevice9_CreateVertexBuffer(p,a,b,c,d,e,f)             (p)->lpVtbl->CreateVertexBuffer(p,a,b,c,d,e,f)
+#define IDirect3DDevice9_CreateIndexBuffer(p,a,b,c,d,e,f)              (p)->lpVtbl->CreateIndexBuffer(p,a,b,c,d,e,f)
+#define IDirect3DDevice9_CreateRenderTarget(p,a,b,c,d,e,f,g,h)         (p)->lpVtbl->CreateRenderTarget(p,a,b,c,d,e,f,g,h)
+#define IDirect3DDevice9_CreateDepthStencilSurface(p,a,b,c,d,e,f,g,h)  (p)->lpVtbl->CreateDepthStencilSurface(p,a,b,c,d,e,f,g,h)
+#define IDirect3DDevice9_UpdateSurface(p,a,b,c,d)                      (p)->lpVtbl->UpdateSurface(p,a,b,c,d)
+#define IDirect3DDevice9_UpdateTexture(p,a,b)                          (p)->lpVtbl->UpdateTexture(p,a,b)
+#define IDirect3DDevice9_GetRenderTargetData(p,a,b)                    (p)->lpVtbl->GetRenderTargetData(p,a,b)
+#define IDirect3DDevice9_GetFrontBufferData(p,a,b)                     (p)->lpVtbl->GetFrontBufferData(p,a,b)
+#define IDirect3DDevice9_StretchRect(p,a,b,c,d,e)                      (p)->lpVtbl->StretchRect(p,a,b,c,d,e)
+#define IDirect3DDevice9_ColorFill(p,a,b,c)                            (p)->lpVtbl->ColorFill(p,a,b,c)
+#define IDirect3DDevice9_CreateOffscreenPlainSurface(p,a,b,c,d,e,f)    (p)->lpVtbl->CreateOffscreenPlainSurface(p,a,b,c,d,e,f)
+#define IDirect3DDevice9_SetRenderTarget(p,a,b)                        (p)->lpVtbl->SetRenderTarget(p,a,b)
+#define IDirect3DDevice9_GetRenderTarget(p,a,b)                        (p)->lpVtbl->GetRenderTarget(p,a,b)
+#define IDirect3DDevice9_SetDepthStencilSurface(p,a)                   (p)->lpVtbl->SetDepthStencilSurface(p,a)
+#define IDirect3DDevice9_GetDepthStencilSurface(p,a)                   (p)->lpVtbl->GetDepthStencilSurface(p,a)
+#define IDirect3DDevice9_BeginScene(p)                                 (p)->lpVtbl->BeginScene(p)
+#define IDirect3DDevice9_EndScene(p)                                   (p)->lpVtbl->EndScene(p)
+#define IDirect3DDevice9_Clear(p,a,b,c,d,e,f)                          (p)->lpVtbl->Clear(p,a,b,c,d,e,f)
+#define IDirect3DDevice9_SetTransform(p,a,b)                           (p)->lpVtbl->SetTransform(p,a,b)
+#define IDirect3DDevice9_GetTransform(p,a,b)                           (p)->lpVtbl->GetTransform(p,a,b)
+#define IDirect3DDevice9_MultiplyTransform(p,a,b)                      (p)->lpVtbl->MultiplyTransform(p,a,b)
+#define IDirect3DDevice9_SetViewport(p,a)                              (p)->lpVtbl->SetViewport(p,a)
+#define IDirect3DDevice9_GetViewport(p,a)                              (p)->lpVtbl->GetViewport(p,a)
+#define IDirect3DDevice9_SetMaterial(p,a)                              (p)->lpVtbl->SetMaterial(p,a)
+#define IDirect3DDevice9_GetMaterial(p,a)                              (p)->lpVtbl->GetMaterial(p,a)
+#define IDirect3DDevice9_SetLight(p,a,b)                               (p)->lpVtbl->SetLight(p,a,b)
+#define IDirect3DDevice9_GetLight(p,a,b)                               (p)->lpVtbl->GetLight(p,a,b)
+#define IDirect3DDevice9_LightEnable(p,a,b)                            (p)->lpVtbl->LightEnable(p,a,b)
+#define IDirect3DDevice9_GetLightEnable(p,a,b)                         (p)->lpVtbl->GetLightEnable(p,a,b)
+#define IDirect3DDevice9_SetClipPlane(p,a,b)                           (p)->lpVtbl->SetClipPlane(p,a,b)
+#define IDirect3DDevice9_GetClipPlane(p,a,b)                           (p)->lpVtbl->GetClipPlane(p,a,b)
+#define IDirect3DDevice9_SetRenderState(p,a,b)                         (p)->lpVtbl->SetRenderState(p,a,b)
+#define IDirect3DDevice9_GetRenderState(p,a,b)                         (p)->lpVtbl->GetRenderState(p,a,b)
+#define IDirect3DDevice9_CreateStateBlock(p,a,b)                       (p)->lpVtbl->CreateStateBlock(p,a,b)
+#define IDirect3DDevice9_BeginStateBlock(p)                            (p)->lpVtbl->BeginStateBlock(p)
+#define IDirect3DDevice9_EndStateBlock(p,a)                            (p)->lpVtbl->EndStateBlock(p,a)
+#define IDirect3DDevice9_SetClipStatus(p,a)                            (p)->lpVtbl->SetClipStatus(p,a)
+#define IDirect3DDevice9_GetClipStatus(p,a)                            (p)->lpVtbl->GetClipStatus(p,a)
+#define IDirect3DDevice9_GetTexture(p,a,b)                             (p)->lpVtbl->GetTexture(p,a,b)
+#define IDirect3DDevice9_SetTexture(p,a,b)                             (p)->lpVtbl->SetTexture(p,a,b)
+#define IDirect3DDevice9_GetTextureStageState(p,a,b,c)                 (p)->lpVtbl->GetTextureStageState(p,a,b,c)
+#define IDirect3DDevice9_SetTextureStageState(p,a,b,c)                 (p)->lpVtbl->SetTextureStageState(p,a,b,c)
+#define IDirect3DDevice9_GetSamplerState(p,a,b,c)                      (p)->lpVtbl->GetSamplerState(p,a,b,c)
+#define IDirect3DDevice9_SetSamplerState(p,a,b,c)                      (p)->lpVtbl->SetSamplerState(p,a,b,c)
+#define IDirect3DDevice9_ValidateDevice(p,a)                           (p)->lpVtbl->ValidateDevice(p,a)
+#define IDirect3DDevice9_SetPaletteEntries(p,a,b)                      (p)->lpVtbl->SetPaletteEntries(p,a,b)
+#define IDirect3DDevice9_GetPaletteEntries(p,a,b)                      (p)->lpVtbl->GetPaletteEntries(p,a,b)
+#define IDirect3DDevice9_SetCurrentTexturePalette(p,a)                 (p)->lpVtbl->SetCurrentTexturePalette(p,a)
+#define IDirect3DDevice9_GetCurrentTexturePalette(p,a)                 (p)->lpVtbl->GetCurrentTexturePalette(p,a)
+#define IDirect3DDevice9_SetScissorRect(p,a)                           (p)->lpVtbl->SetScissorRect(p,a)
+#define IDirect3DDevice9_GetScissorRect(p,a)                           (p)->lpVtbl->GetScissorRect(p,a)
+#define IDirect3DDevice9_SetSoftwareVertexProcessing(p,a)              (p)->lpVtbl->SetSoftwareVertexProcessing(p,a)
+#define IDirect3DDevice9_GetSoftwareVertexProcessing(p)                (p)->lpVtbl->GetSoftwareVertexProcessing(p)
+#define IDirect3DDevice9_SetNPatchMode(p,a)                            (p)->lpVtbl->SetNPatchMode(p,a)
+#define IDirect3DDevice9_GetNPatchMode(p)                              (p)->lpVtbl->GetNPatchMode(p)
+#define IDirect3DDevice9_DrawPrimitive(p,a,b,c)                        (p)->lpVtbl->DrawPrimitive(p,a,b,c)
+#define IDirect3DDevice9_DrawIndexedPrimitive(p,a,b,c,d,e,f)           (p)->lpVtbl->DrawIndexedPrimitive(p,a,b,c,d,e,f)
+#define IDirect3DDevice9_DrawPrimitiveUP(p,a,b,c,d)                    (p)->lpVtbl->DrawPrimitiveUP(p,a,b,c,d)
+#define IDirect3DDevice9_DrawIndexedPrimitiveUP(p,a,b,c,d,e,f,g,h)     (p)->lpVtbl->DrawIndexedPrimitiveUP(p,a,b,c,d,e,f,g,h)
+#define IDirect3DDevice9_ProcessVertices(p,a,b,c,d,e,f)                (p)->lpVtbl->ProcessVertices(p,a,b,c,d,e,f)
+#define IDirect3DDevice9_CreateVertexDeclaration(p,a,b)                (p)->lpVtbl->CreateVertexDeclaration(p,a,b)
+#define IDirect3DDevice9_SetVertexDeclaration(p,a)                     (p)->lpVtbl->SetVertexDeclaration(p,a)
+#define IDirect3DDevice9_GetVertexDeclaration(p,a)                     (p)->lpVtbl->GetVertexDeclaration(p,a)
+#define IDirect3DDevice9_SetFVF(p,a)                                   (p)->lpVtbl->SetFVF(p,a)
+#define IDirect3DDevice9_GetFVF(p,a)                                   (p)->lpVtbl->GetFVF(p,a)
+#define IDirect3DDevice9_CreateVertexShader(p,a,b)                     (p)->lpVtbl->CreateVertexShader(p,a,b)
+#define IDirect3DDevice9_SetVertexShader(p,a)                          (p)->lpVtbl->SetVertexShader(p,a)
+#define IDirect3DDevice9_GetVertexShader(p,a)                          (p)->lpVtbl->GetVertexShader(p,a)
+#define IDirect3DDevice9_SetVertexShaderConstantF(p,a,b,c)             (p)->lpVtbl->SetVertexShaderConstantF(p,a,b,c)
+#define IDirect3DDevice9_GetVertexShaderConstantF(p,a,b,c)             (p)->lpVtbl->GetVertexShaderConstantF(p,a,b,c)
+#define IDirect3DDevice9_SetVertexShaderConstantI(p,a,b,c)             (p)->lpVtbl->SetVertexShaderConstantI(p,a,b,c)
+#define IDirect3DDevice9_GetVertexShaderConstantI(p,a,b,c)             (p)->lpVtbl->GetVertexShaderConstantI(p,a,b,c)
+#define IDirect3DDevice9_SetVertexShaderConstantB(p,a,b,c)             (p)->lpVtbl->SetVertexShaderConstantB(p,a,b,c)
+#define IDirect3DDevice9_GetVertexShaderConstantB(p,a,b,c)             (p)->lpVtbl->GetVertexShaderConstantB(p,a,b,c)
+#define IDirect3DDevice9_SetStreamSource(p,a,b,c,d)                    (p)->lpVtbl->SetStreamSource(p,a,b,c,d)
+#define IDirect3DDevice9_GetStreamSource(p,a,b,c,d)                    (p)->lpVtbl->GetStreamSource(p,a,b,c,d)
+#define IDirect3DDevice9_SetStreamSourceFreq(p,a,b)                    (p)->lpVtbl->SetStreamSourceFreq(p,a,b)
+#define IDirect3DDevice9_GetStreamSourceFreq(p,a,b)                    (p)->lpVtbl->GetStreamSourceFreq(p,a,b)
+#define IDirect3DDevice9_SetIndices(p,a)                               (p)->lpVtbl->SetIndices(p,a)
+#define IDirect3DDevice9_GetIndices(p,a)                               (p)->lpVtbl->GetIndices(p,a)
+#define IDirect3DDevice9_CreatePixelShader(p,a,b)                      (p)->lpVtbl->CreatePixelShader(p,a,b)
+#define IDirect3DDevice9_SetPixelShader(p,a)                           (p)->lpVtbl->SetPixelShader(p,a)
+#define IDirect3DDevice9_GetPixelShader(p,a)                           (p)->lpVtbl->GetPixelShader(p,a)
+#define IDirect3DDevice9_SetPixelShaderConstantF(p,a,b,c)              (p)->lpVtbl->SetPixelShaderConstantF(p,a,b,c)
+#define IDirect3DDevice9_GetPixelShaderConstantF(p,a,b,c)              (p)->lpVtbl->GetPixelShaderConstantF(p,a,b,c)
+#define IDirect3DDevice9_SetPixelShaderConstantI(p,a,b,c)              (p)->lpVtbl->SetPixelShaderConstantI(p,a,b,c)
+#define IDirect3DDevice9_GetPixelShaderConstantI(p,a,b,c)              (p)->lpVtbl->GetPixelShaderConstantI(p,a,b,c)
+#define IDirect3DDevice9_SetPixelShaderConstantB(p,a,b,c)              (p)->lpVtbl->SetPixelShaderConstantB(p,a,b,c)
+#define IDirect3DDevice9_GetPixelShaderConstantB(p,a,b,c)              (p)->lpVtbl->GetPixelShaderConstantB(p,a,b,c)
+#define IDirect3DDevice9_DrawRectPatch(p,a,b,c)                        (p)->lpVtbl->DrawRectPatch(p,a,b,c)
+#define IDirect3DDevice9_DrawTriPatch(p,a,b,c)                         (p)->lpVtbl->DrawTriPatch(p,a,b,c)
+#define IDirect3DDevice9_DeletePatch(p,a)                              (p)->lpVtbl->DeletePatch(p,a)
+#define IDirect3DDevice9_CreateQuery(p,a,b)                            (p)->lpVtbl->CreateQuery(p,a,b)
+#else
+/*** IUnknown methods ***/
+#define IDirect3DDevice9_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirect3DDevice9_AddRef(p)             (p)->AddRef()
+#define IDirect3DDevice9_Release(p)            (p)->Release()
+/*** IDirect3DDevice9 methods ***/
+#define IDirect3DDevice9_TestCooperativeLevel(p)                       (p)->TestCooperativeLevel()
+#define IDirect3DDevice9_GetAvailableTextureMem(p)                     (p)->GetAvailableTextureMem()
+#define IDirect3DDevice9_EvictManagedResources(p)                      (p)->EvictManagedResources()
+#define IDirect3DDevice9_GetDirect3D(p,a)                              (p)->GetDirect3D(a)
+#define IDirect3DDevice9_GetDeviceCaps(p,a)                            (p)->GetDeviceCaps(a)
+#define IDirect3DDevice9_GetDisplayMode(p,a,b)                         (p)->GetDisplayMode(a,b)
+#define IDirect3DDevice9_GetCreationParameters(p,a)                    (p)->GetCreationParameters(a)
+#define IDirect3DDevice9_SetCursorProperties(p,a,b,c)                  (p)->SetCursorProperties(a,b,c)
+#define IDirect3DDevice9_SetCursorPosition(p,a,b,c)                    (p)->SetCursorPosition(a,b,c)
+#define IDirect3DDevice9_ShowCursor(p,a)                               (p)->ShowCursor(a)
+#define IDirect3DDevice9_CreateAdditionalSwapChain(p,a,b)              (p)->CreateAdditionalSwapChain(a,b)
+#define IDirect3DDevice9_GetSwapChain(p,a,b)                           (p)->GetSwapChain(a,b)
+#define IDirect3DDevice9_GetNumberOfSwapChains(p)                      (p)->GetNumberOfSwapChains()
+#define IDirect3DDevice9_Reset(p,a)                                    (p)->Reset(a)
+#define IDirect3DDevice9_Present(p,a,b,c,d)                            (p)->Present(a,b,c,d)
+#define IDirect3DDevice9_GetBackBuffer(p,a,b,c,d)                      (p)->GetBackBuffer(a,b,c,d)
+#define IDirect3DDevice9_GetRasterStatus(p,a,b)                        (p)->GetRasterStatus(a,b)
+#define IDirect3DDevice9_SetDialogBoxMode(p,a)                         (p)->SetDialogBoxMode(a)
+#define IDirect3DDevice9_SetGammaRamp(p,a,b,c)                         (p)->SetGammaRamp(a,b,c)
+#define IDirect3DDevice9_GetGammaRamp(p,a,b)                           (p)->GetGammaRamp(a,b)
+#define IDirect3DDevice9_CreateTexture(p,a,b,c,d,e,f,g,h)              (p)->CreateTexture(a,b,c,d,e,f,g,h)
+#define IDirect3DDevice9_CreateVolumeTexture(p,a,b,c,d,e,f,g,h,i)      (p)->CreateVolumeTexture(a,b,c,d,e,f,g,h,i)
+#define IDirect3DDevice9_CreateCubeTexture(p,a,b,c,d,e,f,g)            (p)->CreateCubeTexture(a,b,c,d,e,f,g)
+#define IDirect3DDevice9_CreateVertexBuffer(p,a,b,c,d,e,f)             (p)->CreateVertexBuffer(a,b,c,d,e,f)
+#define IDirect3DDevice9_CreateIndexBuffer(p,a,b,c,d,e,f)              (p)->CreateIndexBuffer(a,b,c,d,e,f)
+#define IDirect3DDevice9_CreateRenderTarget(p,a,b,c,d,e,f,g,h)         (p)->CreateRenderTarget(a,b,c,d,e,f,g,h)
+#define IDirect3DDevice9_CreateDepthStencilSurface(p,a,b,c,d,e,f,g,h)  (p)->CreateDepthStencilSurface(a,b,c,d,e,f,g,h)
+#define IDirect3DDevice9_UpdateSurface(p,a,b,c,d)                      (p)->UpdateSurface(a,b,c,d)
+#define IDirect3DDevice9_UpdateTexture(p,a,b)                          (p)->UpdateTexture(a,b)
+#define IDirect3DDevice9_GetRenderTargetData(p,a,b)                    (p)->GetRenderTargetData(a,b)
+#define IDirect3DDevice9_GetFrontBufferData(p,a,b)                     (p)->GetFrontBufferData(a,b)
+#define IDirect3DDevice9_StretchRect(p,a,b,c,d,e)                      (p)->StretchRect(a,b,c,d,e)
+#define IDirect3DDevice9_ColorFill(p,a,b,c)                            (p)->ColorFill(a,b,c)
+#define IDirect3DDevice9_CreateOffscreenPlainSurface(p,a,b,c,d,e,f)    (p)->CreateOffscreenPlainSurface(a,b,c,d,e,f)
+#define IDirect3DDevice9_SetRenderTarget(p,a,b)                        (p)->SetRenderTarget(a,b)
+#define IDirect3DDevice9_GetRenderTarget(p,a,b)                        (p)->GetRenderTarget(a,b)
+#define IDirect3DDevice9_SetDepthStencilSurface(p,a)                   (p)->SetDepthStencilSurface(a)
+#define IDirect3DDevice9_GetDepthStencilSurface(p,a)                   (p)->GetDepthStencilSurface(a)
+#define IDirect3DDevice9_BeginScene(p)                                 (p)->BeginScene()
+#define IDirect3DDevice9_EndScene(p)                                   (p)->EndScene()
+#define IDirect3DDevice9_Clear(p,a,b,c,d,e,f)                          (p)->Clear(a,b,c,d,e,f)
+#define IDirect3DDevice9_SetTransform(p,a,b)                           (p)->SetTransform(a,b)
+#define IDirect3DDevice9_GetTransform(p,a,b)                           (p)->GetTransform(a,b)
+#define IDirect3DDevice9_MultiplyTransform(p,a,b)                      (p)->MultiplyTransform(a,b)
+#define IDirect3DDevice9_SetViewport(p,a)                              (p)->SetViewport(a)
+#define IDirect3DDevice9_GetViewport(p,a)                              (p)->GetViewport(a)
+#define IDirect3DDevice9_SetMaterial(p,a)                              (p)->SetMaterial(a)
+#define IDirect3DDevice9_GetMaterial(p,a)                              (p)->GetMaterial(a)
+#define IDirect3DDevice9_SetLight(p,a,b)                               (p)->SetLight(a,b)
+#define IDirect3DDevice9_GetLight(p,a,b)                               (p)->GetLight(a,b)
+#define IDirect3DDevice9_LightEnable(p,a,b)                            (p)->LightEnable(a,b)
+#define IDirect3DDevice9_GetLightEnable(p,a,b)                         (p)->GetLightEnable(a,b)
+#define IDirect3DDevice9_SetClipPlane(p,a,b)                           (p)->SetClipPlane(a,b)
+#define IDirect3DDevice9_GetClipPlane(p,a,b)                           (p)->GetClipPlane(a,b)
+#define IDirect3DDevice9_SetRenderState(p,a,b)                         (p)->SetRenderState(a,b)
+#define IDirect3DDevice9_GetRenderState(p,a,b)                         (p)->GetRenderState(a,b)
+#define IDirect3DDevice9_CreateStateBlock(p,a,b)                       (p)->CreateStateBlock(a,b)
+#define IDirect3DDevice9_BeginStateBlock(p)                            (p)->BeginStateBlock()
+#define IDirect3DDevice9_EndStateBlock(p,a)                            (p)->EndStateBlock(a)
+#define IDirect3DDevice9_SetClipStatus(p,a)                            (p)->SetClipStatus(a)
+#define IDirect3DDevice9_GetClipStatus(p,a)                            (p)->GetClipStatus(a)
+#define IDirect3DDevice9_GetTexture(p,a,b)                             (p)->GetTexture(a,b)
+#define IDirect3DDevice9_SetTexture(p,a,b)                             (p)->SetTexture(a,b)
+#define IDirect3DDevice9_GetTextureStageState(p,a,b,c)                 (p)->GetTextureStageState(a,b,c)
+#define IDirect3DDevice9_SetTextureStageState(p,a,b,c)                 (p)->SetTextureStageState(a,b,c)
+#define IDirect3DDevice9_GetSamplerState(p,a,b,c)                      (p)->GetSamplerState(a,b,c)
+#define IDirect3DDevice9_SetSamplerState(p,a,b,c)                      (p)->SetSamplerState(a,b,c)
+#define IDirect3DDevice9_ValidateDevice(p,a)                           (p)->ValidateDevice(a)
+#define IDirect3DDevice9_SetPaletteEntries(p,a,b)                      (p)->SetPaletteEntries(a,b)
+#define IDirect3DDevice9_GetPaletteEntries(p,a,b)                      (p)->GetPaletteEntries(a,b)
+#define IDirect3DDevice9_SetCurrentTexturePalette(p,a)                 (p)->SetCurrentTexturePalette(a)
+#define IDirect3DDevice9_GetCurrentTexturePalette(p,a)                 (p)->GetCurrentTexturePalette(a)
+#define IDirect3DDevice9_SetScissorRect(p,a)                           (p)->SetScissorRect(a)
+#define IDirect3DDevice9_GetScissorRect(p,a)                           (p)->GetScissorRect(a)
+#define IDirect3DDevice9_SetSoftwareVertexProcessing(p,a)              (p)->SetSoftwareVertexProcessing(a)
+#define IDirect3DDevice9_GetSoftwareVertexProcessing(p)                (p)->GetSoftwareVertexProcessing()
+#define IDirect3DDevice9_SetNPatchMode(p,a)                            (p)->SetNPatchMode(a)
+#define IDirect3DDevice9_GetNPatchMode(p)                              (p)->GetNPatchMode()
+#define IDirect3DDevice9_DrawPrimitive(p,a,b,c)                        (p)->DrawPrimitive(a,b,c)
+#define IDirect3DDevice9_DrawIndexedPrimitive(p,a,b,c,d,e,f)           (p)->DrawIndexedPrimitive(a,b,c,d,e,f)
+#define IDirect3DDevice9_DrawPrimitiveUP(p,a,b,c,d)                    (p)->DrawPrimitiveUP(a,b,c,d)
+#define IDirect3DDevice9_DrawIndexedPrimitiveUP(p,a,b,c,d,e,f,g,h)     (p)->DrawIndexedPrimitiveUP(a,b,c,d,e,f,g,h)
+#define IDirect3DDevice9_ProcessVertices(p,a,b,c,d,e,f)                (p)->ProcessVertices(a,b,c,d,e,f)
+#define IDirect3DDevice9_CreateVertexDeclaration(p,a,b)                (p)->CreateVertexDeclaration(a,b)
+#define IDirect3DDevice9_SetVertexDeclaration(p,a)                     (p)->SetVertexDeclaration(a)
+#define IDirect3DDevice9_GetVertexDeclaration(p,a)                     (p)->GetVertexDeclaration(a)
+#define IDirect3DDevice9_SetFVF(p,a)                                   (p)->SetFVF(a)
+#define IDirect3DDevice9_GetFVF(p,a)                                   (p)->GetFVF(a)
+#define IDirect3DDevice9_CreateVertexShader(p,a,b)                     (p)->CreateVertexShader(a,b)
+#define IDirect3DDevice9_SetVertexShader(p,a)                          (p)->SetVertexShader(a)
+#define IDirect3DDevice9_GetVertexShader(p,a)                          (p)->GetVertexShader(a)
+#define IDirect3DDevice9_SetVertexShaderConstantF(p,a,b,c)             (p)->SetVertexShaderConstantF(a,b,c)
+#define IDirect3DDevice9_GetVertexShaderConstantF(p,a,b,c)             (p)->GetVertexShaderConstantF(a,b,c)
+#define IDirect3DDevice9_SetVertexShaderConstantI(p,a,b,c)             (p)->SetVertexShaderConstantI(a,b,c)
+#define IDirect3DDevice9_GetVertexShaderConstantI(p,a,b,c)             (p)->GetVertexShaderConstantI(a,b,c)
+#define IDirect3DDevice9_SetVertexShaderConstantB(p,a,b,c)             (p)->SetVertexShaderConstantB(a,b,c)
+#define IDirect3DDevice9_GetVertexShaderConstantB(p,a,b,c)             (p)->GetVertexShaderConstantB(a,b,c)
+#define IDirect3DDevice9_SetStreamSource(p,a,b,c,d)                    (p)->SetStreamSource(a,b,c,d)
+#define IDirect3DDevice9_GetStreamSource(p,a,b,c,d)                    (p)->GetStreamSource(a,b,c,d)
+#define IDirect3DDevice9_SetStreamSourceFreq(p,a,b)                    (p)->SetStreamSourceFreq(a,b)
+#define IDirect3DDevice9_GetStreamSourceFreq(p,a,b)                    (p)->GetStreamSourceFreq(a,b)
+#define IDirect3DDevice9_SetIndices(p,a)                               (p)->SetIndices(a)
+#define IDirect3DDevice9_GetIndices(p,a)                               (p)->GetIndices(a)
+#define IDirect3DDevice9_CreatePixelShader(p,a,b)                      (p)->CreatePixelShader(a,b)
+#define IDirect3DDevice9_SetPixelShader(p,a)                           (p)->SetPixelShader(a)
+#define IDirect3DDevice9_GetPixelShader(p,a)                           (p)->GetPixelShader(a)
+#define IDirect3DDevice9_SetPixelShaderConstantF(p,a,b,c)              (p)->SetPixelShaderConstantF(a,b,c)
+#define IDirect3DDevice9_GetPixelShaderConstantF(p,a,b,c)              (p)->GetPixelShaderConstantF(a,b,c)
+#define IDirect3DDevice9_SetPixelShaderConstantI(p,a,b,c)              (p)->SetPixelShaderConstantI(a,b,c)
+#define IDirect3DDevice9_GetPixelShaderConstantI(p,a,b,c)              (p)->GetPixelShaderConstantI(a,b,c)
+#define IDirect3DDevice9_SetPixelShaderConstantB(p,a,b,c)              (p)->SetPixelShaderConstantB(a,b,c)
+#define IDirect3DDevice9_GetPixelShaderConstantB(p,a,b,c)              (p)->GetPixelShaderConstantB(a,b,c)
+#define IDirect3DDevice9_DrawRectPatch(p,a,b,c)                        (p)->DrawRectPatch(a,b,c)
+#define IDirect3DDevice9_DrawTriPatch(p,a,b,c)                         (p)->DrawTriPatch(a,b,c)
+#define IDirect3DDevice9_DeletePatch(p,a)                              (p)->DeletePatch(a)
+#define IDirect3DDevice9_CreateQuery(p,a,b)                            (p)->CreateQuery(a,b)
+#endif
+
+
+/*****************************************************************************
+ * IDirect3DDevice9Ex interface
+ */
+#define INTERFACE IDirect3DDevice9Ex
+DECLARE_INTERFACE_(IDirect3DDevice9Ex,IDirect3DDevice9)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IDirect3DDevice9 methods ***/
+    STDMETHOD(TestCooperativeLevel)(THIS) PURE;
+    STDMETHOD_(UINT, GetAvailableTextureMem)(THIS) PURE;
+    STDMETHOD(EvictManagedResources)(THIS) PURE;
+    STDMETHOD(GetDirect3D)(THIS_ IDirect3D9** ppD3D9) PURE;
+    STDMETHOD(GetDeviceCaps)(THIS_ D3DCAPS9* pCaps) PURE;
+    STDMETHOD(GetDisplayMode)(THIS_ UINT iSwapChain, D3DDISPLAYMODE* pMode) PURE;
+    STDMETHOD(GetCreationParameters)(THIS_ D3DDEVICE_CREATION_PARAMETERS *pParameters) PURE;
+    STDMETHOD(SetCursorProperties)(THIS_ UINT XHotSpot, UINT YHotSpot, IDirect3DSurface9* pCursorBitmap) PURE;
+    STDMETHOD_(void, SetCursorPosition)(THIS_ int X,int Y, DWORD Flags) PURE;
+    STDMETHOD_(BOOL, ShowCursor)(THIS_ BOOL bShow) PURE;
+    STDMETHOD(CreateAdditionalSwapChain)(THIS_ D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain9** pSwapChain) PURE;
+    STDMETHOD(GetSwapChain)(THIS_ UINT iSwapChain, IDirect3DSwapChain9** pSwapChain) PURE;
+    STDMETHOD_(UINT, GetNumberOfSwapChains)(THIS) PURE;
+    STDMETHOD(Reset)(THIS_ D3DPRESENT_PARAMETERS* pPresentationParameters) PURE;
+    STDMETHOD(Present)(THIS_ CONST RECT* pSourceRect, CONST RECT* pDestRect, HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) PURE;
+    STDMETHOD(GetBackBuffer)(THIS_ UINT iSwapChain, UINT iBackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9** ppBackBuffer) PURE;
+    STDMETHOD(GetRasterStatus)(THIS_ UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) PURE;
+    STDMETHOD(SetDialogBoxMode)(THIS_ BOOL bEnableDialogs) PURE;
+    STDMETHOD_(void, SetGammaRamp)(THIS_ UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) PURE;
+    STDMETHOD_(void, GetGammaRamp)(THIS_ UINT iSwapChain, D3DGAMMARAMP* pRamp) PURE;
+    STDMETHOD(CreateTexture)(THIS_ UINT Width, UINT Height, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture9** ppTexture, HANDLE* pSharedHandle) PURE;
+    STDMETHOD(CreateVolumeTexture)(THIS_ UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture9** ppVolumeTexture, HANDLE* pSharedHandle) PURE;
+    STDMETHOD(CreateCubeTexture)(THIS_ UINT EdgeLength, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture9** ppCubeTexture, HANDLE* pSharedHandle) PURE;
+    STDMETHOD(CreateVertexBuffer)(THIS_ UINT Length, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer9** ppVertexBuffer, HANDLE* pSharedHandle) PURE;
+    STDMETHOD(CreateIndexBuffer)(THIS_ UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer9** ppIndexBuffer, HANDLE* pSharedHandle) PURE;
+    STDMETHOD(CreateRenderTarget)(THIS_ UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Lockable, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle) PURE;
+    STDMETHOD(CreateDepthStencilSurface)(THIS_ UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Discard, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle) PURE;
+    STDMETHOD(UpdateSurface)(THIS_ IDirect3DSurface9* pSourceSurface, CONST RECT* pSourceRect, IDirect3DSurface9* pDestinationSurface, CONST POINT* pDestPoint) PURE;
+    STDMETHOD(UpdateTexture)(THIS_ IDirect3DBaseTexture9* pSourceTexture, IDirect3DBaseTexture9* pDestinationTexture) PURE;
+    STDMETHOD(GetRenderTargetData)(THIS_ IDirect3DSurface9* pRenderTarget, IDirect3DSurface9* pDestSurface) PURE;
+    STDMETHOD(GetFrontBufferData)(THIS_ UINT iSwapChain, IDirect3DSurface9* pDestSurface) PURE;
+    STDMETHOD(StretchRect)(THIS_ IDirect3DSurface9* pSourceSurface, CONST RECT* pSourceRect, IDirect3DSurface9* pDestSurface, CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) PURE;
+    STDMETHOD(ColorFill)(THIS_ IDirect3DSurface9* pSurface, CONST RECT* pRect, D3DCOLOR color) PURE;
+    STDMETHOD(CreateOffscreenPlainSurface)(THIS_ UINT Width, UINT Height, D3DFORMAT Format, D3DPOOL Pool, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle) PURE;
+    STDMETHOD(SetRenderTarget)(THIS_ DWORD RenderTargetIndex, IDirect3DSurface9* pRenderTarget) PURE;
+    STDMETHOD(GetRenderTarget)(THIS_ DWORD RenderTargetIndex, IDirect3DSurface9** ppRenderTarget) PURE;
+    STDMETHOD(SetDepthStencilSurface)(THIS_ IDirect3DSurface9* pNewZStencil) PURE;
+    STDMETHOD(GetDepthStencilSurface)(THIS_ IDirect3DSurface9** ppZStencilSurface) PURE;
+    STDMETHOD(BeginScene)(THIS) PURE;
+    STDMETHOD(EndScene)(THIS) PURE;
+    STDMETHOD(Clear)(THIS_ DWORD Count, CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) PURE;
+    STDMETHOD(SetTransform)(THIS_ D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) PURE;
+    STDMETHOD(GetTransform)(THIS_ D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) PURE;
+    STDMETHOD(MultiplyTransform)(THIS_ D3DTRANSFORMSTATETYPE, CONST D3DMATRIX*) PURE;
+    STDMETHOD(SetViewport)(THIS_ CONST D3DVIEWPORT9* pViewport) PURE;
+    STDMETHOD(GetViewport)(THIS_ D3DVIEWPORT9* pViewport) PURE;
+    STDMETHOD(SetMaterial)(THIS_ CONST D3DMATERIAL9* pMaterial) PURE;
+    STDMETHOD(GetMaterial)(THIS_ D3DMATERIAL9* pMaterial) PURE;
+    STDMETHOD(SetLight)(THIS_ DWORD Index, CONST D3DLIGHT9*) PURE;
+    STDMETHOD(GetLight)(THIS_ DWORD Index, D3DLIGHT9*) PURE;
+    STDMETHOD(LightEnable)(THIS_ DWORD Index, BOOL Enable) PURE;
+    STDMETHOD(GetLightEnable)(THIS_ DWORD Index, BOOL* pEnable) PURE;
+    STDMETHOD(SetClipPlane)(THIS_ DWORD Index, CONST float* pPlane) PURE;
+    STDMETHOD(GetClipPlane)(THIS_ DWORD Index, float* pPlane) PURE;
+    STDMETHOD(SetRenderState)(THIS_ D3DRENDERSTATETYPE State, DWORD Value) PURE;
+    STDMETHOD(GetRenderState)(THIS_ D3DRENDERSTATETYPE State, DWORD* pValue) PURE;
+    STDMETHOD(CreateStateBlock)(THIS_ D3DSTATEBLOCKTYPE Type, IDirect3DStateBlock9** ppSB) PURE;
+    STDMETHOD(BeginStateBlock)(THIS) PURE;
+    STDMETHOD(EndStateBlock)(THIS_ IDirect3DStateBlock9** ppSB) PURE;
+    STDMETHOD(SetClipStatus)(THIS_ CONST D3DCLIPSTATUS9* pClipStatus) PURE;
+    STDMETHOD(GetClipStatus)(THIS_ D3DCLIPSTATUS9* pClipStatus) PURE;
+    STDMETHOD(GetTexture)(THIS_ DWORD Stage, IDirect3DBaseTexture9** ppTexture) PURE;
+    STDMETHOD(SetTexture)(THIS_ DWORD Stage, IDirect3DBaseTexture9* pTexture) PURE;
+    STDMETHOD(GetTextureStageState)(THIS_ DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) PURE;
+    STDMETHOD(SetTextureStageState)(THIS_ DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) PURE;
+    STDMETHOD(GetSamplerState)(THIS_ DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD* pValue) PURE;
+    STDMETHOD(SetSamplerState)(THIS_ DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value) PURE;
+    STDMETHOD(ValidateDevice)(THIS_ DWORD* pNumPasses) PURE;
+    STDMETHOD(SetPaletteEntries)(THIS_ UINT PaletteNumber, CONST PALETTEENTRY* pEntries) PURE;
+    STDMETHOD(GetPaletteEntries)(THIS_ UINT PaletteNumber,PALETTEENTRY* pEntries) PURE;
+    STDMETHOD(SetCurrentTexturePalette)(THIS_ UINT PaletteNumber) PURE;
+    STDMETHOD(GetCurrentTexturePalette)(THIS_ UINT *PaletteNumber) PURE;
+    STDMETHOD(SetScissorRect)(THIS_ CONST RECT* pRect) PURE;
+    STDMETHOD(GetScissorRect)(THIS_ RECT* pRect) PURE;
+    STDMETHOD(SetSoftwareVertexProcessing)(THIS_ BOOL bSoftware) PURE;
+    STDMETHOD_(BOOL, GetSoftwareVertexProcessing)(THIS) PURE;
+    STDMETHOD(SetNPatchMode)(THIS_ float nSegments) PURE;
+    STDMETHOD_(float, GetNPatchMode)(THIS) PURE;
+    STDMETHOD(DrawPrimitive)(THIS_ D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) PURE;
+    STDMETHOD(DrawIndexedPrimitive)(THIS_ D3DPRIMITIVETYPE, INT BaseVertexIndex, UINT MinVertexIndex, UINT NumVertices, UINT startIndex, UINT primCount) PURE;
+    STDMETHOD(DrawPrimitiveUP)(THIS_ D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, CONST void* pVertexStreamZeroData, UINT VertexStreamZeroStride) PURE;
+    STDMETHOD(DrawIndexedPrimitiveUP)(THIS_ D3DPRIMITIVETYPE PrimitiveType, UINT MinVertexIndex, UINT NumVertices, UINT PrimitiveCount, CONST void* pIndexData, D3DFORMAT IndexDataFormat, CONST void* pVertexStreamZeroData, UINT VertexStreamZeroStride) PURE;
+    STDMETHOD(ProcessVertices)(THIS_ UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IDirect3DVertexBuffer9* pDestBuffer, IDirect3DVertexDeclaration9* pVertexDecl, DWORD Flags) PURE;
+    STDMETHOD(CreateVertexDeclaration)(THIS_ CONST D3DVERTEXELEMENT9* pVertexElements, IDirect3DVertexDeclaration9** ppDecl) PURE;
+    STDMETHOD(SetVertexDeclaration)(THIS_ IDirect3DVertexDeclaration9* pDecl) PURE;
+    STDMETHOD(GetVertexDeclaration)(THIS_ IDirect3DVertexDeclaration9** ppDecl) PURE;
+    STDMETHOD(SetFVF)(THIS_ DWORD FVF) PURE;
+    STDMETHOD(GetFVF)(THIS_ DWORD* pFVF) PURE;
+    STDMETHOD(CreateVertexShader)(THIS_ CONST DWORD* pFunction, IDirect3DVertexShader9** ppShader) PURE;
+    STDMETHOD(SetVertexShader)(THIS_ IDirect3DVertexShader9* pShader) PURE;
+    STDMETHOD(GetVertexShader)(THIS_ IDirect3DVertexShader9** ppShader) PURE;
+    STDMETHOD(SetVertexShaderConstantF)(THIS_ UINT StartRegister, CONST float* pConstantData, UINT Vector4fCount) PURE;
+    STDMETHOD(GetVertexShaderConstantF)(THIS_ UINT StartRegister, float* pConstantData, UINT Vector4fCount) PURE;
+    STDMETHOD(SetVertexShaderConstantI)(THIS_ UINT StartRegister, CONST int* pConstantData, UINT Vector4iCount) PURE;
+    STDMETHOD(GetVertexShaderConstantI)(THIS_ UINT StartRegister, int* pConstantData, UINT Vector4iCount) PURE;
+    STDMETHOD(SetVertexShaderConstantB)(THIS_ UINT StartRegister, CONST BOOL* pConstantData, UINT  BoolCount) PURE;
+    STDMETHOD(GetVertexShaderConstantB)(THIS_ UINT StartRegister, BOOL* pConstantData, UINT BoolCount) PURE;
+    STDMETHOD(SetStreamSource)(THIS_ UINT StreamNumber, IDirect3DVertexBuffer9* pStreamData, UINT OffsetInBytes, UINT Stride) PURE;
+    STDMETHOD(GetStreamSource)(THIS_ UINT StreamNumber, IDirect3DVertexBuffer9** ppStreamData, UINT* OffsetInBytes, UINT* pStride) PURE;
+    STDMETHOD(SetStreamSourceFreq)(THIS_ UINT StreamNumber, UINT Divider) PURE;
+    STDMETHOD(GetStreamSourceFreq)(THIS_ UINT StreamNumber, UINT* Divider) PURE;
+    STDMETHOD(SetIndices)(THIS_ IDirect3DIndexBuffer9* pIndexData) PURE;
+    STDMETHOD(GetIndices)(THIS_ IDirect3DIndexBuffer9** ppIndexData) PURE;
+    STDMETHOD(CreatePixelShader)(THIS_ CONST DWORD* pFunction, IDirect3DPixelShader9** ppShader) PURE;
+    STDMETHOD(SetPixelShader)(THIS_ IDirect3DPixelShader9* pShader) PURE;
+    STDMETHOD(GetPixelShader)(THIS_ IDirect3DPixelShader9** ppShader) PURE;
+    STDMETHOD(SetPixelShaderConstantF)(THIS_ UINT StartRegister, CONST float* pConstantData, UINT Vector4fCount) PURE;
+    STDMETHOD(GetPixelShaderConstantF)(THIS_ UINT StartRegister, float* pConstantData, UINT Vector4fCount) PURE;
+    STDMETHOD(SetPixelShaderConstantI)(THIS_ UINT StartRegister, CONST int* pConstantData, UINT Vector4iCount) PURE;
+    STDMETHOD(GetPixelShaderConstantI)(THIS_ UINT StartRegister, int* pConstantData, UINT Vector4iCount) PURE;
+    STDMETHOD(SetPixelShaderConstantB)(THIS_ UINT StartRegister, CONST BOOL* pConstantData, UINT  BoolCount) PURE;
+    STDMETHOD(GetPixelShaderConstantB)(THIS_ UINT StartRegister, BOOL* pConstantData, UINT BoolCount) PURE;
+    STDMETHOD(DrawRectPatch)(THIS_ UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo) PURE;
+    STDMETHOD(DrawTriPatch)(THIS_ UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo) PURE;
+    STDMETHOD(DeletePatch)(THIS_ UINT Handle) PURE;
+    STDMETHOD(CreateQuery)(THIS_ D3DQUERYTYPE Type, IDirect3DQuery9** ppQuery) PURE;
+    /* IDirect3DDevice9Ex methods */
+    STDMETHOD(SetConvolutionMonoKernel)(THIS_ UINT width, UINT height, float *rows, float *columns) PURE;
+    STDMETHOD(ComposeRects)(THIS_ IDirect3DSurface9 *src_surface, IDirect3DSurface9 *dst_surface,
+            IDirect3DVertexBuffer9 *src_descs, UINT rect_count, IDirect3DVertexBuffer9 *dst_descs,
+            D3DCOMPOSERECTSOP operation, INT offset_x, INT offset_y) PURE;
+    STDMETHOD(PresentEx)(THIS_ CONST RECT *pSourceRect, CONST RECT *pDestRect, HWND hDestWindowOverride, CONST RGNDATA *pDirtyRegion, DWORD dwFlags) PURE;
+    STDMETHOD(GetGPUThreadPriority)(THIS_ INT *pPriority) PURE;
+    STDMETHOD(SetGPUThreadPriority)(THIS_ INT Priority) PURE;
+    STDMETHOD(WaitForVBlank)(THIS_ UINT iSwapChain) PURE;
+    STDMETHOD(CheckResourceResidency)(THIS_ IDirect3DResource9 **resources, UINT32 resource_count) PURE;
+    STDMETHOD(SetMaximumFrameLatency)(THIS_ UINT MaxLatency) PURE;
+    STDMETHOD(GetMaximumFrameLatency)(THIS_ UINT *pMaxLatenxy) PURE;
+    STDMETHOD(CheckDeviceState)(THIS_ HWND dst_window) PURE;
+    STDMETHOD(CreateRenderTargetEx)(THIS_ UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultiSampleQuality, BOOL Lockable, IDirect3DSurface9 ** ppSurface, HANDLE *pSharedHandle, DWORD Usage) PURE;
+    STDMETHOD(CreateOffscreenPlainSurfaceEx)(THIS_ UINT Width, UINT Height, D3DFORMAT Format, D3DPOOL Pool, IDirect3DSurface9 **ppSurface, HANDLE *pSharedHandle, DWORD Usage) PURE;
+    STDMETHOD(CreateDepthStencilSurfaceEx)(THIS_ UINT width, UINT height, D3DFORMAT format,
+            D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality, BOOL discard,
+            IDirect3DSurface9 **surface, HANDLE *shared_handle, DWORD usage) PURE;
+    STDMETHOD(ResetEx)(THIS_ D3DPRESENT_PARAMETERS *pPresentationParameters, D3DDISPLAYMODEEX *pFullscreenDisplayMode) PURE;
+    STDMETHOD(GetDisplayModeEx)(THIS_ UINT iSwapChain, D3DDISPLAYMODEEX *pMode, D3DDISPLAYROTATION *pRotation) PURE;
+};
+#undef INTERFACE
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+/*** IUnknown methods ***/
+#define IDirect3DDevice9Ex_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirect3DDevice9Ex_AddRef(p)             (p)->lpVtbl->AddRef(p)
+#define IDirect3DDevice9Ex_Release(p)            (p)->lpVtbl->Release(p)
+/*** IDirect3DDevice9 methods ***/
+#define IDirect3DDevice9Ex_TestCooperativeLevel(p)                       (p)->lpVtbl->TestCooperativeLevel(p)
+#define IDirect3DDevice9Ex_GetAvailableTextureMem(p)                     (p)->lpVtbl->GetAvailableTextureMem(p)
+#define IDirect3DDevice9Ex_EvictManagedResources(p)                      (p)->lpVtbl->EvictManagedResources(p)
+#define IDirect3DDevice9Ex_GetDirect3D(p,a)                              (p)->lpVtbl->GetDirect3D(p,a)
+#define IDirect3DDevice9Ex_GetDeviceCaps(p,a)                            (p)->lpVtbl->GetDeviceCaps(p,a)
+#define IDirect3DDevice9Ex_GetDisplayMode(p,a,b)                         (p)->lpVtbl->GetDisplayMode(p,a,b)
+#define IDirect3DDevice9Ex_GetCreationParameters(p,a)                    (p)->lpVtbl->GetCreationParameters(p,a)
+#define IDirect3DDevice9Ex_SetCursorProperties(p,a,b,c)                  (p)->lpVtbl->SetCursorProperties(p,a,b,c)
+#define IDirect3DDevice9Ex_SetCursorPosition(p,a,b,c)                    (p)->lpVtbl->SetCursorPosition(p,a,b,c)
+#define IDirect3DDevice9Ex_ShowCursor(p,a)                               (p)->lpVtbl->ShowCursor(p,a)
+#define IDirect3DDevice9Ex_CreateAdditionalSwapChain(p,a,b)              (p)->lpVtbl->CreateAdditionalSwapChain(p,a,b)
+#define IDirect3DDevice9Ex_GetSwapChain(p,a,b)                           (p)->lpVtbl->GetSwapChain(p,a,b)
+#define IDirect3DDevice9Ex_GetNumberOfSwapChains(p)                      (p)->lpVtbl->GetNumberOfSwapChains(p)
+#define IDirect3DDevice9Ex_Reset(p,a)                                    (p)->lpVtbl->Reset(p,a)
+#define IDirect3DDevice9Ex_Present(p,a,b,c,d)                            (p)->lpVtbl->Present(p,a,b,c,d)
+#define IDirect3DDevice9Ex_GetBackBuffer(p,a,b,c,d)                      (p)->lpVtbl->GetBackBuffer(p,a,b,c,d)
+#define IDirect3DDevice9Ex_GetRasterStatus(p,a,b)                        (p)->lpVtbl->GetRasterStatus(p,a,b)
+#define IDirect3DDevice9Ex_SetDialogBoxMode(p,a)                         (p)->lpVtbl->SetDialogBoxMode(p,a)
+#define IDirect3DDevice9Ex_SetGammaRamp(p,a,b,c)                         (p)->lpVtbl->SetGammaRamp(p,a,b,c)
+#define IDirect3DDevice9Ex_GetGammaRamp(p,a,b)                           (p)->lpVtbl->GetGammaRamp(p,a,b)
+#define IDirect3DDevice9Ex_CreateTexture(p,a,b,c,d,e,f,g,h)              (p)->lpVtbl->CreateTexture(p,a,b,c,d,e,f,g,h)
+#define IDirect3DDevice9Ex_CreateVolumeTexture(p,a,b,c,d,e,f,g,h,i)      (p)->lpVtbl->CreateVolumeTexture(p,a,b,c,d,e,f,g,h,i)
+#define IDirect3DDevice9Ex_CreateCubeTexture(p,a,b,c,d,e,f,g)            (p)->lpVtbl->CreateCubeTexture(p,a,b,c,d,e,f,g)
+#define IDirect3DDevice9Ex_CreateVertexBuffer(p,a,b,c,d,e,f)             (p)->lpVtbl->CreateVertexBuffer(p,a,b,c,d,e,f)
+#define IDirect3DDevice9Ex_CreateIndexBuffer(p,a,b,c,d,e,f)              (p)->lpVtbl->CreateIndexBuffer(p,a,b,c,d,e,f)
+#define IDirect3DDevice9Ex_CreateRenderTarget(p,a,b,c,d,e,f,g,h)         (p)->lpVtbl->CreateRenderTarget(p,a,b,c,d,e,f,g,h)
+#define IDirect3DDevice9Ex_CreateDepthStencilSurface(p,a,b,c,d,e,f,g,h)  (p)->lpVtbl->CreateDepthStencilSurface(p,a,b,c,d,e,f,g,h)
+#define IDirect3DDevice9Ex_UpdateSurface(p,a,b,c,d)                      (p)->lpVtbl->UpdateSurface(p,a,b,c,d)
+#define IDirect3DDevice9Ex_UpdateTexture(p,a,b)                          (p)->lpVtbl->UpdateTexture(p,a,b)
+#define IDirect3DDevice9Ex_GetRenderTargetData(p,a,b)                    (p)->lpVtbl->GetRenderTargetData(p,a,b)
+#define IDirect3DDevice9Ex_GetFrontBufferData(p,a,b)                     (p)->lpVtbl->GetFrontBufferData(p,a,b)
+#define IDirect3DDevice9Ex_StretchRect(p,a,b,c,d,e)                      (p)->lpVtbl->StretchRect(p,a,b,c,d,e)
+#define IDirect3DDevice9Ex_ColorFill(p,a,b,c)                            (p)->lpVtbl->ColorFill(p,a,b,c)
+#define IDirect3DDevice9Ex_CreateOffscreenPlainSurface(p,a,b,c,d,e,f)    (p)->lpVtbl->CreateOffscreenPlainSurface(p,a,b,c,d,e,f)
+#define IDirect3DDevice9Ex_SetRenderTarget(p,a,b)                        (p)->lpVtbl->SetRenderTarget(p,a,b)
+#define IDirect3DDevice9Ex_GetRenderTarget(p,a,b)                        (p)->lpVtbl->GetRenderTarget(p,a,b)
+#define IDirect3DDevice9Ex_SetDepthStencilSurface(p,a)                   (p)->lpVtbl->SetDepthStencilSurface(p,a)
+#define IDirect3DDevice9Ex_GetDepthStencilSurface(p,a)                   (p)->lpVtbl->GetDepthStencilSurface(p,a)
+#define IDirect3DDevice9Ex_BeginScene(p)                                 (p)->lpVtbl->BeginScene(p)
+#define IDirect3DDevice9Ex_EndScene(p)                                   (p)->lpVtbl->EndScene(p)
+#define IDirect3DDevice9Ex_Clear(p,a,b,c,d,e,f)                          (p)->lpVtbl->Clear(p,a,b,c,d,e,f)
+#define IDirect3DDevice9Ex_SetTransform(p,a,b)                           (p)->lpVtbl->SetTransform(p,a,b)
+#define IDirect3DDevice9Ex_GetTransform(p,a,b)                           (p)->lpVtbl->GetTransform(p,a,b)
+#define IDirect3DDevice9Ex_MultiplyTransform(p,a,b)                      (p)->lpVtbl->MultiplyTransform(p,a,b)
+#define IDirect3DDevice9Ex_SetViewport(p,a)                              (p)->lpVtbl->SetViewport(p,a)
+#define IDirect3DDevice9Ex_GetViewport(p,a)                              (p)->lpVtbl->GetViewport(p,a)
+#define IDirect3DDevice9Ex_SetMaterial(p,a)                              (p)->lpVtbl->SetMaterial(p,a)
+#define IDirect3DDevice9Ex_GetMaterial(p,a)                              (p)->lpVtbl->GetMaterial(p,a)
+#define IDirect3DDevice9Ex_SetLight(p,a,b)                               (p)->lpVtbl->SetLight(p,a,b)
+#define IDirect3DDevice9Ex_GetLight(p,a,b)                               (p)->lpVtbl->GetLight(p,a,b)
+#define IDirect3DDevice9Ex_LightEnable(p,a,b)                            (p)->lpVtbl->LightEnable(p,a,b)
+#define IDirect3DDevice9Ex_GetLightEnable(p,a,b)                         (p)->lpVtbl->GetLightEnable(p,a,b)
+#define IDirect3DDevice9Ex_SetClipPlane(p,a,b)                           (p)->lpVtbl->SetClipPlane(p,a,b)
+#define IDirect3DDevice9Ex_GetClipPlane(p,a,b)                           (p)->lpVtbl->GetClipPlane(p,a,b)
+#define IDirect3DDevice9Ex_SetRenderState(p,a,b)                         (p)->lpVtbl->SetRenderState(p,a,b)
+#define IDirect3DDevice9Ex_GetRenderState(p,a,b)                         (p)->lpVtbl->GetRenderState(p,a,b)
+#define IDirect3DDevice9Ex_CreateStateBlock(p,a,b)                       (p)->lpVtbl->CreateStateBlock(p,a,b)
+#define IDirect3DDevice9Ex_BeginStateBlock(p)                            (p)->lpVtbl->BeginStateBlock(p)
+#define IDirect3DDevice9Ex_EndStateBlock(p,a)                            (p)->lpVtbl->EndStateBlock(p,a)
+#define IDirect3DDevice9Ex_SetClipStatus(p,a)                            (p)->lpVtbl->SetClipStatus(p,a)
+#define IDirect3DDevice9Ex_GetClipStatus(p,a)                            (p)->lpVtbl->GetClipStatus(p,a)
+#define IDirect3DDevice9Ex_GetTexture(p,a,b)                             (p)->lpVtbl->GetTexture(p,a,b)
+#define IDirect3DDevice9Ex_SetTexture(p,a,b)                             (p)->lpVtbl->SetTexture(p,a,b)
+#define IDirect3DDevice9Ex_GetTextureStageState(p,a,b,c)                 (p)->lpVtbl->GetTextureStageState(p,a,b,c)
+#define IDirect3DDevice9Ex_SetTextureStageState(p,a,b,c)                 (p)->lpVtbl->SetTextureStageState(p,a,b,c)
+#define IDirect3DDevice9Ex_GetSamplerState(p,a,b,c)                      (p)->lpVtbl->GetSamplerState(p,a,b,c)
+#define IDirect3DDevice9Ex_SetSamplerState(p,a,b,c)                      (p)->lpVtbl->SetSamplerState(p,a,b,c)
+#define IDirect3DDevice9Ex_ValidateDevice(p,a)                           (p)->lpVtbl->ValidateDevice(p,a)
+#define IDirect3DDevice9Ex_SetPaletteEntries(p,a,b)                      (p)->lpVtbl->SetPaletteEntries(p,a,b)
+#define IDirect3DDevice9Ex_GetPaletteEntries(p,a,b)                      (p)->lpVtbl->GetPaletteEntries(p,a,b)
+#define IDirect3DDevice9Ex_SetCurrentTexturePalette(p,a)                 (p)->lpVtbl->SetCurrentTexturePalette(p,a)
+#define IDirect3DDevice9Ex_GetCurrentTexturePalette(p,a)                 (p)->lpVtbl->GetCurrentTexturePalette(p,a)
+#define IDirect3DDevice9Ex_SetScissorRect(p,a)                           (p)->lpVtbl->SetScissorRect(p,a)
+#define IDirect3DDevice9Ex_GetScissorRect(p,a)                           (p)->lpVtbl->GetScissorRect(p,a)
+#define IDirect3DDevice9Ex_SetSoftwareVertexProcessing(p,a)              (p)->lpVtbl->SetSoftwareVertexProcessing(p,a)
+#define IDirect3DDevice9Ex_GetSoftwareVertexProcessing(p)                (p)->lpVtbl->GetSoftwareVertexProcessing(p)
+#define IDirect3DDevice9Ex_SetNPatchMode(p,a)                            (p)->lpVtbl->SetNPatchMode(p,a)
+#define IDirect3DDevice9Ex_GetNPatchMode(p)                              (p)->lpVtbl->GetNPatchMode(p)
+#define IDirect3DDevice9Ex_DrawPrimitive(p,a,b,c)                        (p)->lpVtbl->DrawPrimitive(p,a,b,c)
+#define IDirect3DDevice9Ex_DrawIndexedPrimitive(p,a,b,c,d,e,f)           (p)->lpVtbl->DrawIndexedPrimitive(p,a,b,c,d,e,f)
+#define IDirect3DDevice9Ex_DrawPrimitiveUP(p,a,b,c,d)                    (p)->lpVtbl->DrawPrimitiveUP(p,a,b,c,d)
+#define IDirect3DDevice9Ex_DrawIndexedPrimitiveUP(p,a,b,c,d,e,f,g,h)     (p)->lpVtbl->DrawIndexedPrimitiveUP(p,a,b,c,d,e,f,g,h)
+#define IDirect3DDevice9Ex_ProcessVertices(p,a,b,c,d,e,f)                (p)->lpVtbl->ProcessVertices(p,a,b,c,d,e,f)
+#define IDirect3DDevice9Ex_CreateVertexDeclaration(p,a,b)                (p)->lpVtbl->CreateVertexDeclaration(p,a,b)
+#define IDirect3DDevice9Ex_SetVertexDeclaration(p,a)                     (p)->lpVtbl->SetVertexDeclaration(p,a)
+#define IDirect3DDevice9Ex_GetVertexDeclaration(p,a)                     (p)->lpVtbl->GetVertexDeclaration(p,a)
+#define IDirect3DDevice9Ex_SetFVF(p,a)                                   (p)->lpVtbl->SetFVF(p,a)
+#define IDirect3DDevice9Ex_GetFVF(p,a)                                   (p)->lpVtbl->GetFVF(p,a)
+#define IDirect3DDevice9Ex_CreateVertexShader(p,a,b)                     (p)->lpVtbl->CreateVertexShader(p,a,b)
+#define IDirect3DDevice9Ex_SetVertexShader(p,a)                          (p)->lpVtbl->SetVertexShader(p,a)
+#define IDirect3DDevice9Ex_GetVertexShader(p,a)                          (p)->lpVtbl->GetVertexShader(p,a)
+#define IDirect3DDevice9Ex_SetVertexShaderConstantF(p,a,b,c)             (p)->lpVtbl->SetVertexShaderConstantF(p,a,b,c)
+#define IDirect3DDevice9Ex_GetVertexShaderConstantF(p,a,b,c)             (p)->lpVtbl->GetVertexShaderConstantF(p,a,b,c)
+#define IDirect3DDevice9Ex_SetVertexShaderConstantI(p,a,b,c)             (p)->lpVtbl->SetVertexShaderConstantI(p,a,b,c)
+#define IDirect3DDevice9Ex_GetVertexShaderConstantI(p,a,b,c)             (p)->lpVtbl->GetVertexShaderConstantI(p,a,b,c)
+#define IDirect3DDevice9Ex_SetVertexShaderConstantB(p,a,b,c)             (p)->lpVtbl->SetVertexShaderConstantB(p,a,b,c)
+#define IDirect3DDevice9Ex_GetVertexShaderConstantB(p,a,b,c)             (p)->lpVtbl->GetVertexShaderConstantB(p,a,b,c)
+#define IDirect3DDevice9Ex_SetStreamSource(p,a,b,c,d)                    (p)->lpVtbl->SetStreamSource(p,a,b,c,d)
+#define IDirect3DDevice9Ex_GetStreamSource(p,a,b,c,d)                    (p)->lpVtbl->GetStreamSource(p,a,b,c,d)
+#define IDirect3DDevice9Ex_SetStreamSourceFreq(p,a,b)                    (p)->lpVtbl->SetStreamSourceFreq(p,a,b)
+#define IDirect3DDevice9Ex_GetStreamSourceFreq(p,a,b)                    (p)->lpVtbl->GetStreamSourceFreq(p,a,b)
+#define IDirect3DDevice9Ex_SetIndices(p,a)                               (p)->lpVtbl->SetIndices(p,a)
+#define IDirect3DDevice9Ex_GetIndices(p,a)                               (p)->lpVtbl->GetIndices(p,a)
+#define IDirect3DDevice9Ex_CreatePixelShader(p,a,b)                      (p)->lpVtbl->CreatePixelShader(p,a,b)
+#define IDirect3DDevice9Ex_SetPixelShader(p,a)                           (p)->lpVtbl->SetPixelShader(p,a)
+#define IDirect3DDevice9Ex_GetPixelShader(p,a)                           (p)->lpVtbl->GetPixelShader(p,a)
+#define IDirect3DDevice9Ex_SetPixelShaderConstantF(p,a,b,c)              (p)->lpVtbl->SetPixelShaderConstantF(p,a,b,c)
+#define IDirect3DDevice9Ex_GetPixelShaderConstantF(p,a,b,c)              (p)->lpVtbl->GetPixelShaderConstantF(p,a,b,c)
+#define IDirect3DDevice9Ex_SetPixelShaderConstantI(p,a,b,c)              (p)->lpVtbl->SetPixelShaderConstantI(p,a,b,c)
+#define IDirect3DDevice9Ex_GetPixelShaderConstantI(p,a,b,c)              (p)->lpVtbl->GetPixelShaderConstantI(p,a,b,c)
+#define IDirect3DDevice9Ex_SetPixelShaderConstantB(p,a,b,c)              (p)->lpVtbl->SetPixelShaderConstantB(p,a,b,c)
+#define IDirect3DDevice9Ex_GetPixelShaderConstantB(p,a,b,c)              (p)->lpVtbl->GetPixelShaderConstantB(p,a,b,c)
+#define IDirect3DDevice9Ex_DrawRectPatch(p,a,b,c)                        (p)->lpVtbl->DrawRectPatch(p,a,b,c)
+#define IDirect3DDevice9Ex_DrawTriPatch(p,a,b,c)                         (p)->lpVtbl->DrawTriPatch(p,a,b,c)
+#define IDirect3DDevice9Ex_DeletePatch(p,a)                              (p)->lpVtbl->DeletePatch(p,a)
+#define IDirect3DDevice9Ex_CreateQuery(p,a,b)                            (p)->lpVtbl->CreateQuery(p,a,b)
+/* IDirect3DDevice9Ex */
+#define IDirect3DDevice9Ex_SetConvolutionMonoKernel(p,a,b,c,d)           (p)->lpVtbl->SetConvolutionMonoKernel(p,a,b,c,d)
+#define IDirect3DDevice9Ex_ComposeRects(p,a,b,c,d,e,f,g,h)               (p)->lpVtbl->ComposeRects(p,a,b,c,d,e,f,g,h)
+#define IDirect3DDevice9Ex_PresentEx(p,a,b,c,d,e)                        (p)->lpVtbl->PresentEx(p,a,b,c,d,e)
+#define IDirect3DDevice9Ex_GetGPUThreadPriority(p,a)                     (p)->lpVtbl->GetGPUThreadPriority(p,a)
+#define IDirect3DDevice9Ex_SetGPUThreadPriority(p,a)                     (p)->lpVtbl->SetGPUThreadPriority(p,a)
+#define IDirect3DDevice9Ex_WaitForVBlank(p,a)                            (p)->lpVtbl->WaitForVBlank(p,a)
+#define IDirect3DDevice9Ex_CheckResourceResidency(p,a,b)                 (p)->lpVtbl->CheckResourceResidency(p,a,b)
+#define IDirect3DDevice9Ex_SetMaximumFrameLatency(p,a)                   (p)->lpVtbl->SetMaximumFrameLatency(p,a)
+#define IDirect3DDevice9Ex_GetMaximumFrameLatency(p,a)                   (p)->lpVtbl->GetMaximumFrameLatency(p,a)
+#define IDirect3DDevice9Ex_CheckDeviceState(p,a)                         (p)->lpVtbl->CheckDeviceState(p,a)
+#define IDirect3DDevice9Ex_CreateRenderTargetEx(p,a,b,c,d,e,f,g,h,i)     (p)->lpVtbl->CreateRenderTargetEx(p,a,b,c,d,e,f,g,h,i)
+#define IDirect3DDevice9Ex_CreateOffscreenPlainSurfaceEx(p,a,b,c,d,e,f,g)(p)->lpVtbl->CreateOffscreenPlainSurfaceEx(p,a,b,c,d,e,f,g)
+#define IDirect3DDevice9Ex_CreateDepthStencilSurfaceEx(p,a,b,c,d,e,f,g,h,i)(p)->lpVtbl->CreateDepthStencilSurfaceEx(p,a,b,c,d,e,f,g,h,i)
+#define IDirect3DDevice9Ex_ResetEx(p,a,b)                                 (p)->lpVtbl->ResetEx(p,a,b)
+#define IDirect3DDevice9Ex_GetDisplayModeEx(p,a,b,c)                     (p)->lpVtbl->GetDisplayModeEx(p,a,b,c)
+#else
+/*** IUnknown methods ***/
+#define IDirect3DDevice9Ex_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirect3DDevice9Ex_AddRef(p)             (p)->AddRef()
+#define IDirect3DDevice9Ex_Release(p)            (p)->Release()
+/*** IDirect3DDevice9 methods ***/
+#define IDirect3DDevice9Ex_TestCooperativeLevel(p)                       (p)->TestCooperativeLevel()
+#define IDirect3DDevice9Ex_GetAvailableTextureMem(p)                     (p)->GetAvailableTextureMem()
+#define IDirect3DDevice9Ex_EvictManagedResources(p)                      (p)->EvictManagedResources()
+#define IDirect3DDevice9Ex_GetDirect3D(p,a)                              (p)->GetDirect3D(a)
+#define IDirect3DDevice9Ex_GetDeviceCaps(p,a)                            (p)->GetDeviceCaps(a)
+#define IDirect3DDevice9Ex_GetDisplayMode(p,a,b)                         (p)->GetDisplayMode(a,b)
+#define IDirect3DDevice9Ex_GetCreationParameters(p,a)                    (p)->GetCreationParameters(a)
+#define IDirect3DDevice9Ex_SetCursorProperties(p,a,b,c)                  (p)->SetCursorProperties(a,b,c)
+#define IDirect3DDevice9Ex_SetCursorPosition(p,a,b,c)                    (p)->SetCursorPosition(a,b,c)
+#define IDirect3DDevice9Ex_ShowCursor(p,a)                               (p)->ShowCursor(a)
+#define IDirect3DDevice9Ex_CreateAdditionalSwapChain(p,a,b)              (p)->CreateAdditionalSwapChain(a,b)
+#define IDirect3DDevice9Ex_GetSwapChain(p,a,b)                           (p)->GetSwapChain(a,b)
+#define IDirect3DDevice9Ex_GetNumberOfSwapChains(p)                      (p)->GetNumberOfSwapChains()
+#define IDirect3DDevice9Ex_Reset(p,a)                                    (p)->Reset(a)
+#define IDirect3DDevice9Ex_Present(p,a,b,c,d)                            (p)->Present(a,b,c,d)
+#define IDirect3DDevice9Ex_GetBackBuffer(p,a,b,c,d)                      (p)->GetBackBuffer(a,b,c,d)
+#define IDirect3DDevice9Ex_GetRasterStatus(p,a,b)                        (p)->GetRasterStatus(a,b)
+#define IDirect3DDevice9Ex_SetDialogBoxMode(p,a)                         (p)->SetDialogBoxMode(a)
+#define IDirect3DDevice9Ex_SetGammaRamp(p,a,b,c)                         (p)->SetGammaRamp(a,b,c)
+#define IDirect3DDevice9Ex_GetGammaRamp(p,a,b)                           (p)->GetGammaRamp(a,b)
+#define IDirect3DDevice9Ex_CreateTexture(p,a,b,c,d,e,f,g,h)              (p)->CreateTexture(a,b,c,d,e,f,g,h)
+#define IDirect3DDevice9Ex_CreateVolumeTexture(p,a,b,c,d,e,f,g,h,i)      (p)->CreateVolumeTexture(a,b,c,d,e,f,g,h,i)
+#define IDirect3DDevice9Ex_CreateCubeTexture(p,a,b,c,d,e,f,g)            (p)->CreateCubeTexture(a,b,c,d,e,f,g)
+#define IDirect3DDevice9Ex_CreateVertexBuffer(p,a,b,c,d,e,f)             (p)->CreateVertexBuffer(a,b,c,d,e,f)
+#define IDirect3DDevice9Ex_CreateIndexBuffer(p,a,b,c,d,e,f)              (p)->CreateIndexBuffer(a,b,c,d,e,f)
+#define IDirect3DDevice9Ex_CreateRenderTarget(p,a,b,c,d,e,f,g,h)         (p)->CreateRenderTarget(a,b,c,d,e,f,g,h)
+#define IDirect3DDevice9Ex_CreateDepthStencilSurface(p,a,b,c,d,e,f,g,h)  (p)->CreateDepthStencilSurface(a,b,c,d,e,f,g,h)
+#define IDirect3DDevice9Ex_UpdateSurface(p,a,b,c,d)                      (p)->UpdateSurface(a,b,c,d)
+#define IDirect3DDevice9Ex_UpdateTexture(p,a,b)                          (p)->UpdateTexture(a,b)
+#define IDirect3DDevice9Ex_GetRenderTargetData(p,a,b)                    (p)->GetRenderTargetData(a,b)
+#define IDirect3DDevice9Ex_GetFrontBufferData(p,a,b)                     (p)->GetFrontBufferData(a,b)
+#define IDirect3DDevice9Ex_StretchRect(p,a,b,c,d,e)                      (p)->StretchRect(a,b,c,d,e)
+#define IDirect3DDevice9Ex_ColorFill(p,a,b,c)                            (p)->ColorFill(a,b,c)
+#define IDirect3DDevice9Ex_CreateOffscreenPlainSurface(p,a,b,c,d,e,f)    (p)->CreateOffscreenPlainSurface(a,b,c,d,e,f)
+#define IDirect3DDevice9Ex_SetRenderTarget(p,a,b)                        (p)->SetRenderTarget(a,b)
+#define IDirect3DDevice9Ex_GetRenderTarget(p,a,b)                        (p)->GetRenderTarget(a,b)
+#define IDirect3DDevice9Ex_SetDepthStencilSurface(p,a)                   (p)->SetDepthStencilSurface(a)
+#define IDirect3DDevice9Ex_GetDepthStencilSurface(p,a)                   (p)->GetDepthStencilSurface(a)
+#define IDirect3DDevice9Ex_BeginScene(p)                                 (p)->BeginScene()
+#define IDirect3DDevice9Ex_EndScene(p)                                   (p)->EndScene()
+#define IDirect3DDevice9Ex_Clear(p,a,b,c,d,e,f)                          (p)->Clear(a,b,c,d,e,f)
+#define IDirect3DDevice9Ex_SetTransform(p,a,b)                           (p)->SetTransform(a,b)
+#define IDirect3DDevice9Ex_GetTransform(p,a,b)                           (p)->GetTransform(a,b)
+#define IDirect3DDevice9Ex_MultiplyTransform(p,a,b)                      (p)->MultiplyTransform(a,b)
+#define IDirect3DDevice9Ex_SetViewport(p,a)                              (p)->SetViewport(a)
+#define IDirect3DDevice9Ex_GetViewport(p,a)                              (p)->GetViewport(a)
+#define IDirect3DDevice9Ex_SetMaterial(p,a)                              (p)->SetMaterial(a)
+#define IDirect3DDevice9Ex_GetMaterial(p,a)                              (p)->GetMaterial(a)
+#define IDirect3DDevice9Ex_SetLight(p,a,b)                               (p)->SetLight(a,b)
+#define IDirect3DDevice9Ex_GetLight(p,a,b)                               (p)->GetLight(a,b)
+#define IDirect3DDevice9Ex_LightEnable(p,a,b)                            (p)->LightEnable(a,b)
+#define IDirect3DDevice9Ex_GetLightEnable(p,a,b)                         (p)->GetLightEnable(a,b)
+#define IDirect3DDevice9Ex_SetClipPlane(p,a,b)                           (p)->SetClipPlane(a,b)
+#define IDirect3DDevice9Ex_GetClipPlane(p,a,b)                           (p)->GetClipPlane(a,b)
+#define IDirect3DDevice9Ex_SetRenderState(p,a,b)                         (p)->SetRenderState(a,b)
+#define IDirect3DDevice9Ex_GetRenderState(p,a,b)                         (p)->GetRenderState(a,b)
+#define IDirect3DDevice9Ex_CreateStateBlock(p,a,b)                       (p)->CreateStateBlock(a,b)
+#define IDirect3DDevice9Ex_BeginStateBlock(p)                            (p)->BeginStateBlock()
+#define IDirect3DDevice9Ex_EndStateBlock(p,a)                            (p)->EndStateBlock(a)
+#define IDirect3DDevice9Ex_SetClipStatus(p,a)                            (p)->SetClipStatus(a)
+#define IDirect3DDevice9Ex_GetClipStatus(p,a)                            (p)->GetClipStatus(a)
+#define IDirect3DDevice9Ex_GetTexture(p,a,b)                             (p)->GetTexture(a,b)
+#define IDirect3DDevice9Ex_SetTexture(p,a,b)                             (p)->SetTexture(a,b)
+#define IDirect3DDevice9Ex_GetTextureStageState(p,a,b,c)                 (p)->GetTextureStageState(a,b,c)
+#define IDirect3DDevice9Ex_SetTextureStageState(p,a,b,c)                 (p)->SetTextureStageState(a,b,c)
+#define IDirect3DDevice9Ex_GetSamplerState(p,a,b,c)                      (p)->GetSamplerState(a,b,c)
+#define IDirect3DDevice9Ex_SetSamplerState(p,a,b,c)                      (p)->SetSamplerState(a,b,c)
+#define IDirect3DDevice9Ex_ValidateDevice(p,a)                           (p)->ValidateDevice(a)
+#define IDirect3DDevice9Ex_SetPaletteEntries(p,a,b)                      (p)->SetPaletteEntries(a,b)
+#define IDirect3DDevice9Ex_GetPaletteEntries(p,a,b)                      (p)->GetPaletteEntries(a,b)
+#define IDirect3DDevice9Ex_SetCurrentTexturePalette(p,a)                 (p)->SetCurrentTexturePalette(a)
+#define IDirect3DDevice9Ex_GetCurrentTexturePalette(p,a)                 (p)->GetCurrentTexturePalette(a)
+#define IDirect3DDevice9Ex_SetScissorRect(p,a)                           (p)->SetScissorRect(a)
+#define IDirect3DDevice9Ex_GetScissorRect(p,a)                           (p)->GetScissorRect(a)
+#define IDirect3DDevice9Ex_SetSoftwareVertexProcessing(p,a)              (p)->SetSoftwareVertexProcessing(a)
+#define IDirect3DDevice9Ex_GetSoftwareVertexProcessing(p)                (p)->GetSoftwareVertexProcessing()
+#define IDirect3DDevice9Ex_SetNPatchMode(p,a)                            (p)->SetNPatchMode(a)
+#define IDirect3DDevice9Ex_GetNPatchMode(p)                              (p)->GetNPatchMode()
+#define IDirect3DDevice9Ex_DrawPrimitive(p,a,b,c)                        (p)->DrawPrimitive(a,b,c)
+#define IDirect3DDevice9Ex_DrawIndexedPrimitive(p,a,b,c,d,e,f)           (p)->DrawIndexedPrimitive(a,b,c,d,e,f)
+#define IDirect3DDevice9Ex_DrawPrimitiveUP(p,a,b,c,d)                    (p)->DrawPrimitiveUP(a,b,c,d)
+#define IDirect3DDevice9Ex_DrawIndexedPrimitiveUP(p,a,b,c,d,e,f,g,h)     (p)->DrawIndexedPrimitiveUP(a,b,c,d,e,f,g,h)
+#define IDirect3DDevice9Ex_ProcessVertices(p,a,b,c,d,e,f)                (p)->ProcessVertices(a,b,c,d,e,f)
+#define IDirect3DDevice9Ex_CreateVertexDeclaration(p,a,b)                (p)->CreateVertexDeclaration(a,b)
+#define IDirect3DDevice9Ex_SetVertexDeclaration(p,a)                     (p)->SetVertexDeclaration(a)
+#define IDirect3DDevice9Ex_GetVertexDeclaration(p,a)                     (p)->GetVertexDeclaration(a)
+#define IDirect3DDevice9Ex_SetFVF(p,a)                                   (p)->SetFVF(a)
+#define IDirect3DDevice9Ex_GetFVF(p,a)                                   (p)->GetFVF(a)
+#define IDirect3DDevice9Ex_CreateVertexShader(p,a,b)                     (p)->CreateVertexShader(a,b)
+#define IDirect3DDevice9Ex_SetVertexShader(p,a)                          (p)->SetVertexShader(a)
+#define IDirect3DDevice9Ex_GetVertexShader(p,a)                          (p)->GetVertexShader(a)
+#define IDirect3DDevice9Ex_SetVertexShaderConstantF(p,a,b,c)             (p)->SetVertexShaderConstantF(a,b,c)
+#define IDirect3DDevice9Ex_GetVertexShaderConstantF(p,a,b,c)             (p)->GetVertexShaderConstantF(a,b,c)
+#define IDirect3DDevice9Ex_SetVertexShaderConstantI(p,a,b,c)             (p)->SetVertexShaderConstantI(a,b,c)
+#define IDirect3DDevice9Ex_GetVertexShaderConstantI(p,a,b,c)             (p)->GetVertexShaderConstantI(a,b,c)
+#define IDirect3DDevice9Ex_SetVertexShaderConstantB(p,a,b,c)             (p)->SetVertexShaderConstantB(a,b,c)
+#define IDirect3DDevice9Ex_GetVertexShaderConstantB(p,a,b,c)             (p)->GetVertexShaderConstantB(a,b,c)
+#define IDirect3DDevice9Ex_SetStreamSource(p,a,b,c,d)                    (p)->SetStreamSource(a,b,c,d)
+#define IDirect3DDevice9Ex_GetStreamSource(p,a,b,c,d)                    (p)->GetStreamSource(a,b,c,d)
+#define IDirect3DDevice9Ex_SetStreamSourceFreq(p,a,b)                    (p)->SetStreamSourceFreq(a,b)
+#define IDirect3DDevice9Ex_GetStreamSourceFreq(p,a,b)                    (p)->GetStreamSourceFreq(a,b)
+#define IDirect3DDevice9Ex_SetIndices(p,a)                               (p)->SetIndices(a)
+#define IDirect3DDevice9Ex_GetIndices(p,a)                               (p)->GetIndices(a)
+#define IDirect3DDevice9Ex_CreatePixelShader(p,a,b)                      (p)->CreatePixelShader(a,b)
+#define IDirect3DDevice9Ex_SetPixelShader(p,a)                           (p)->SetPixelShader(a)
+#define IDirect3DDevice9Ex_GetPixelShader(p,a)                           (p)->GetPixelShader(a)
+#define IDirect3DDevice9Ex_SetPixelShaderConstantF(p,a,b,c)              (p)->SetPixelShaderConstantF(a,b,c)
+#define IDirect3DDevice9Ex_GetPixelShaderConstantF(p,a,b,c)              (p)->GetPixelShaderConstantF(a,b,c)
+#define IDirect3DDevice9Ex_SetPixelShaderConstantI(p,a,b,c)              (p)->SetPixelShaderConstantI(a,b,c)
+#define IDirect3DDevice9Ex_GetPixelShaderConstantI(p,a,b,c)              (p)->GetPixelShaderConstantI(a,b,c)
+#define IDirect3DDevice9Ex_SetPixelShaderConstantB(p,a,b,c)              (p)->SetPixelShaderConstantB(a,b,c)
+#define IDirect3DDevice9Ex_GetPixelShaderConstantB(p,a,b,c)              (p)->GetPixelShaderConstantB(a,b,c)
+#define IDirect3DDevice9Ex_DrawRectPatch(p,a,b,c)                        (p)->DrawRectPatch(a,b,c)
+#define IDirect3DDevice9Ex_DrawTriPatch(p,a,b,c)                         (p)->DrawTriPatch(a,b,c)
+#define IDirect3DDevice9Ex_DeletePatch(p,a)                              (p)->DeletePatch(a)
+#define IDirect3DDevice9Ex_CreateQuery(p,a,b)                            (p)->CreateQuery(a,b)
+/* IDirect3DDevice9Ex */
+#define IDirect3DDevice9Ex_SetConvolutionMonoKernel(p,a,b,c,d)           (p)->SetConvolutionMonoKernel(a,b,c,d)
+#define IDirect3DDevice9Ex_ComposeRects(p,a,b,c,d,e,f,g,h)               (p)->ComposeRects(a,b,c,d,e,f,g,h)
+#define IDirect3DDevice9Ex_PresentEx(p,a,b,c,d,e)                        (p)->PresentEx(a,b,c,d,e)
+#define IDirect3DDevice9Ex_GetGPUThreadPriority(p,a)                     (p)->GetGPUThreadPriority(a)
+#define IDirect3DDevice9Ex_SetGPUThreadPriority(p,a)                     (p)->SetGPUThreadPriority(a)
+#define IDirect3DDevice9Ex_WaitForVBlank(p,a)                            (p)->WaitForVBlank(a)
+#define IDirect3DDevice9Ex_CheckResourceResidency(p,a,b)                 (p)->CheckResourceResidency(a,b)
+#define IDirect3DDevice9Ex_SetMaximumFrameLatency(p,a)                   (p)->SetMaximumFrameLatency(a)
+#define IDirect3DDevice9Ex_GetMaximumFrameLatency(p,a)                   (p)->GetMaximumFrameLatency(a)
+#define IDirect3DDevice9Ex_CheckDeviceState(p,a)                         (p)->CheckDeviceState(a)
+#define IDirect3DDevice9Ex_CreateRenderTargetEx(p,a,b,c,d,e,f,g,h,i)     (p)->CreateRenderTargetEx(a,b,c,d,e,f,g,h,i)
+#define IDirect3DDevice9Ex_CreateOffscreenPlainSurfaceEx(p,a,b,c,d,e,f,g)(p)->CreateOffscreenPlainSurfaceEx(a,b,c,d,e,f,g)
+#define IDirect3DDevice9Ex_CreateDepthStencilSurfaceEx(p,a,b,c,d,e,f,g,h,i)(p)->CreateDepthStencilSurfaceEx(a,b,c,d,e,f,g,h,i)
+#define IDirect3DDevice9Ex_ResetEx(p,a,b)                                (p)->ResetEx(a,b)
+#define IDirect3DDevice9Ex_GetDisplayModeEx(p,a,b,c)                     (p)->GetDisplayModeEx(a,b,c)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif  /* defined(__cplusplus) */
+
+int         WINAPI D3DPERF_BeginEvent(D3DCOLOR,LPCWSTR);
+int         WINAPI D3DPERF_EndEvent(void);
+DWORD       WINAPI D3DPERF_GetStatus(void);
+BOOL        WINAPI D3DPERF_QueryRepeatFrame(void);
+void        WINAPI D3DPERF_SetMarker(D3DCOLOR,LPCWSTR);
+void        WINAPI D3DPERF_SetOptions(DWORD);
+void        WINAPI D3DPERF_SetRegion(D3DCOLOR,LPCWSTR);
+
+/* Define the main entrypoint as well */
+IDirect3D9* WINAPI Direct3DCreate9(UINT SDKVersion);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* defined(__cplusplus) */
+
+
+#endif /* __WINE_D3D9_H */
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/include/wine/debug.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/include/wine/debug.h	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/include/wine/debug.h	(revision 46521)
@@ -0,0 +1,313 @@
+/*
+ * Wine debugging interface
+ *
+ * Copyright 1999 Patrik Stridvall
+ *
+ * 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_WINE_DEBUG_H
+#define __WINE_WINE_DEBUG_H
+
+#include <stdarg.h>
+#include <windef.h>
+#ifndef GUID_DEFINED
+#include <guiddef.h>
+#endif
+
+#ifdef __WINE_WINE_TEST_H
+#error This file should not be used in Wine tests
+#endif
+
+//#ifdef VBOX_WINE_WITH_IPRT
+# include <iprt/assert.h>
+//#else
+//# define AssertBreakpoint() do { } while (0)
+//# define Assert(_expr) do { } while (0)
+//# ifdef DEBUG_misha
+//#  include <iprt/cdefs.h>
+//# endif
+//#endif
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct _GUID;
+
+#if !defined(__cplusplus) && !defined(inline)
+# define inline _inline
+#endif
+
+
+/*
+ * Internal definitions (do not use these directly)
+ */
+
+enum __wine_debug_class
+{
+    __WINE_DBCL_FIXME,
+    __WINE_DBCL_ERR,
+    __WINE_DBCL_WARN,
+    __WINE_DBCL_TRACE,
+
+    __WINE_DBCL_INIT = 7  /* lazy init flag */
+};
+
+struct __wine_debug_channel
+{
+    unsigned char flags;
+    char name[15];
+};
+
+#ifdef VBOX_WINE_BEAK_ON_TRACE
+extern DWORD g_VDbgBreakOnTrace;
+#endif
+#ifndef WINE_NO_TRACE_MSGS
+# ifdef VBOX_WINE_BEAK_ON_TRACE
+#  define __WINE_GET_DEBUGGING_TRACE(dbch) ((g_VDbgBreakOnTrace ? (RT_BREAKPOINT(),NULL) : NULL), ((dbch)->flags & (1 << __WINE_DBCL_TRACE)))
+# else
+# define __WINE_GET_DEBUGGING_TRACE(dbch) ((dbch)->flags & (1 << __WINE_DBCL_TRACE))
+# endif
+#else
+# define __WINE_GET_DEBUGGING_TRACE(dbch) 0
+#endif
+
+#ifndef WINE_NO_DEBUG_MSGS
+# define __WINE_GET_DEBUGGING_WARN(dbch)  ((dbch)->flags & (1 << __WINE_DBCL_WARN))
+# define __WINE_GET_DEBUGGING_FIXME(dbch) ((dbch)->flags & (1 << __WINE_DBCL_FIXME))
+#else
+# define __WINE_GET_DEBUGGING_WARN(dbch)  0
+# define __WINE_GET_DEBUGGING_FIXME(dbch) 0
+#endif
+
+/* define error macro regardless of what is configured */
+#ifdef DEBUG_misha
+#define __WINE_GET_DEBUGGING_ERR(dbch)  (RT_BREAKPOINT(), ((dbch)->flags & (1 << __WINE_DBCL_ERR)))
+#else
+#define __WINE_GET_DEBUGGING_ERR(dbch)  ((dbch)->flags & (1 << __WINE_DBCL_ERR))
+#endif
+
+#define __WINE_GET_DEBUGGING(dbcl,dbch)  __WINE_GET_DEBUGGING##dbcl(dbch)
+
+#define __WINE_IS_DEBUG_ON(dbcl,dbch) \
+  (__WINE_GET_DEBUGGING##dbcl(dbch) && (__wine_dbg_get_channel_flags(dbch) & (1 << __WINE_DBCL##dbcl)))
+
+#ifdef __GNUC__
+
+#define __WINE_DPRINTF(dbcl,dbch) \
+  do { if(__WINE_GET_DEBUGGING(dbcl,(dbch))) { \
+       struct __wine_debug_channel * const __dbch = (dbch); \
+       const enum __wine_debug_class __dbcl = __WINE_DBCL##dbcl; \
+       __WINE_DBG_LOG
+
+#define __WINE_DBG_LOG(args...) \
+    wine_dbg_log( __dbcl, __dbch, __FUNCTION__, args); } } while(0)
+
+#define __WINE_PRINTF_ATTR(fmt,args) __attribute__((format (printf,fmt,args)))
+
+
+#ifdef WINE_NO_TRACE_MSGS
+#define WINE_TRACE(args...) do { } while(0)
+#define WINE_TRACE_(ch) WINE_TRACE
+#endif
+
+#ifdef WINE_NO_DEBUG_MSGS
+#define WINE_WARN(args...) do { } while(0)
+#define WINE_WARN_(ch) WINE_WARN
+#define WINE_FIXME(args...) do { } while(0)
+#define WINE_FIXME_(ch) WINE_FIXME
+#endif
+
+#elif defined(__SUNPRO_C)
+
+#define __WINE_DPRINTF(dbcl,dbch) \
+  do { if(__WINE_GET_DEBUGGING(dbcl,(dbch))) { \
+       struct __wine_debug_channel * const __dbch = (dbch); \
+       const enum __WINE_DEBUG_CLASS __dbcl = __WINE_DBCL##dbcl; \
+       __WINE_DBG_LOG
+
+#define __WINE_DBG_LOG(...) \
+   wine_dbg_log( __dbcl, __dbch, __func__, __VA_ARGS__); } } while(0)
+
+#define __WINE_PRINTF_ATTR(fmt,args)
+
+#ifdef WINE_NO_TRACE_MSGS
+#define WINE_TRACE(...) do { } while(0)
+#define WINE_TRACE_(ch) WINE_TRACE
+#endif
+
+#ifdef WINE_NO_DEBUG_MSGS
+#define WINE_WARN(...) do { } while(0)
+#define WINE_WARN_(ch) WINE_WARN
+#define WINE_FIXME(...) do { } while(0)
+#define WINE_FIXME_(ch) WINE_FIXME
+#endif
+
+#else  /* !__GNUC__ && !__SUNPRO_C */
+
+#define __WINE_DPRINTF(dbcl,dbch) \
+    (!__WINE_GET_DEBUGGING(dbcl,(dbch)) || \
+     (wine_dbg_log(__WINE_DBCL##dbcl,(dbch),__FILE__,"%d: ",__LINE__) == -1)) ? \
+     (void)0 : (void)wine_dbg_printf
+
+#define __WINE_PRINTF_ATTR(fmt, args)
+
+#endif  /* !__GNUC__ && !__SUNPRO_C */
+
+struct __wine_debug_functions
+{
+    char * (*get_temp_buffer)( size_t n );
+    void   (*release_temp_buffer)( char *buffer, size_t n );
+    const char * (*dbgstr_an)( const char * s, int n );
+    const char * (*dbgstr_wn)( const WCHAR *s, int n );
+    int (*dbg_vprintf)( const char *format, va_list args );
+    int (*dbg_vlog)( enum __wine_debug_class cls, struct __wine_debug_channel *channel,
+                     const char *function, const char *format, va_list args );
+};
+
+extern unsigned char __wine_dbg_get_channel_flags( struct __wine_debug_channel *channel );
+extern int __wine_dbg_set_channel_flags( struct __wine_debug_channel *channel,
+                                         unsigned char set, unsigned char clear );
+extern void __wine_dbg_set_functions( const struct __wine_debug_functions *new_funcs,
+                                      struct __wine_debug_functions *old_funcs, size_t size );
+
+/*
+ * Exported definitions and macros
+ */
+
+/* These functions return a printable version of a string, including
+   quotes.  The string will be valid for some time, but not indefinitely
+   as strings are re-used.  */
+extern const char *wine_dbgstr_an( const char * s, int n );
+extern const char *wine_dbgstr_wn( const WCHAR *s, int n );
+extern const char *wine_dbg_sprintf( const char *format, ... ) __WINE_PRINTF_ATTR(1,2);
+
+extern int wine_dbg_printf( const char *format, ... ) __WINE_PRINTF_ATTR(1,2);
+extern int wine_dbg_log( enum __wine_debug_class cls, struct __wine_debug_channel *ch, const char *func,
+                         const char *format, ... ) __WINE_PRINTF_ATTR(4,5);
+
+static inline const char *wine_dbgstr_a( const char *s )
+{
+    return wine_dbgstr_an( s, -1 );
+}
+
+static inline const char *wine_dbgstr_w( const WCHAR *s )
+{
+    return wine_dbgstr_wn( s, -1 );
+}
+
+static inline const char *wine_dbgstr_guid( const GUID *id )
+{
+    if (!id) return "(null)";
+    if (!((ULONG_PTR)id >> 16)) return wine_dbg_sprintf( "<guid-0x%04hx>", (WORD)(ULONG_PTR)id );
+    return wine_dbg_sprintf( "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
+                             id->Data1, id->Data2, id->Data3,
+                             id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3],
+                             id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7] );
+}
+
+static inline const char *wine_dbgstr_point( const POINT *pt )
+{
+    if (!pt) return "(null)";
+    return wine_dbg_sprintf( "(%d,%d)", pt->x, pt->y );
+}
+
+static inline const char *wine_dbgstr_size( const SIZE *size )
+{
+    if (!size) return "(null)";
+    return wine_dbg_sprintf( "(%d,%d)", size->cx, size->cy );
+}
+
+static inline const char *wine_dbgstr_rect( const RECT *rect )
+{
+    if (!rect) return "(null)";
+    return wine_dbg_sprintf( "(%d,%d)-(%d,%d)", rect->left, rect->top,
+                             rect->right, rect->bottom );
+}
+
+static inline const char *wine_dbgstr_longlong( ULONGLONG ll )
+{
+    if (sizeof(ll) > sizeof(unsigned long) && ll >> 32)
+        return wine_dbg_sprintf( "%lx%08lx", (unsigned long)(ll >> 32), (unsigned long)ll );
+    else return wine_dbg_sprintf( "%lx", (unsigned long)ll );
+}
+
+#ifndef WINE_TRACE
+#define WINE_TRACE                 __WINE_DPRINTF(_TRACE,__wine_dbch___default)
+#define WINE_TRACE_(ch)            __WINE_DPRINTF(_TRACE,&__wine_dbch_##ch)
+#endif
+#define WINE_TRACE_ON(ch)          __WINE_IS_DEBUG_ON(_TRACE,&__wine_dbch_##ch)
+
+#ifndef WINE_WARN
+#define WINE_WARN                  __WINE_DPRINTF(_WARN,__wine_dbch___default)
+#define WINE_WARN_(ch)             __WINE_DPRINTF(_WARN,&__wine_dbch_##ch)
+#endif
+#define WINE_WARN_ON(ch)           __WINE_IS_DEBUG_ON(_WARN,&__wine_dbch_##ch)
+
+#ifndef WINE_FIXME
+#define WINE_FIXME                 __WINE_DPRINTF(_FIXME,__wine_dbch___default)
+#define WINE_FIXME_(ch)            __WINE_DPRINTF(_FIXME,&__wine_dbch_##ch)
+#endif
+#define WINE_FIXME_ON(ch)          __WINE_IS_DEBUG_ON(_FIXME,&__wine_dbch_##ch)
+
+#define WINE_ERR                   __WINE_DPRINTF(_ERR,__wine_dbch___default)
+#define WINE_ERR_(ch)              __WINE_DPRINTF(_ERR,&__wine_dbch_##ch)
+#define WINE_ERR_ON(ch)            __WINE_IS_DEBUG_ON(_ERR,&__wine_dbch_##ch)
+
+#define WINE_DECLARE_DEBUG_CHANNEL(ch) \
+    static struct __wine_debug_channel __wine_dbch_##ch = { ~0, #ch }
+#define WINE_DEFAULT_DEBUG_CHANNEL(ch) \
+    static struct __wine_debug_channel __wine_dbch_##ch = { ~0, #ch }; \
+    static struct __wine_debug_channel * const __wine_dbch___default = &__wine_dbch_##ch
+
+#define WINE_DPRINTF               wine_dbg_printf
+#define WINE_MESSAGE               wine_dbg_printf
+
+#ifdef __WINESRC__
+/* Wine uses shorter names that are very likely to conflict with other software */
+
+static inline const char *debugstr_an( const char * s, int n ) { return wine_dbgstr_an( s, n ); }
+static inline const char *debugstr_wn( const WCHAR *s, int n ) { return wine_dbgstr_wn( s, n ); }
+static inline const char *debugstr_guid( const struct _GUID *id ) { return wine_dbgstr_guid(id); }
+static inline const char *debugstr_a( const char *s )  { return wine_dbgstr_an( s, -1 ); }
+static inline const char *debugstr_w( const WCHAR *s ) { return wine_dbgstr_wn( s, -1 ); }
+
+#define TRACE                      WINE_TRACE
+#define TRACE_(ch)                 WINE_TRACE_(ch)
+#define TRACE_ON(ch)               WINE_TRACE_ON(ch)
+
+#define WARN                       WINE_WARN
+#define WARN_(ch)                  WINE_WARN_(ch)
+#define WARN_ON(ch)                WINE_WARN_ON(ch)
+
+#define FIXME                      WINE_FIXME
+#define FIXME_(ch)                 WINE_FIXME_(ch)
+#define FIXME_ON(ch)               WINE_FIXME_ON(ch)
+
+#undef ERR  /* Solaris got an 'ERR' define in <sys/reg.h> */
+#define ERR                        WINE_ERR
+#define ERR_(ch)                   WINE_ERR_(ch)
+#define ERR_ON(ch)                 WINE_ERR_ON(ch)
+
+#define DPRINTF                    WINE_DPRINTF
+#define MESSAGE                    WINE_MESSAGE
+
+#endif /* __WINESRC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* __WINE_WINE_DEBUG_H */
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/include/wine/list.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/include/wine/list.h	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/include/wine/list.h	(revision 46521)
@@ -0,0 +1,234 @@
+/*
+ * Linked lists support
+ *
+ * Copyright (C) 2002 Alexandre Julliard
+ *
+ * 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_SERVER_LIST_H
+#define __WINE_SERVER_LIST_H
+
+#include <stddef.h>
+
+struct list
+{
+    struct list *next;
+    struct list *prev;
+};
+
+/* Define a list like so:
+ *
+ *   struct gadget
+ *   {
+ *       struct list  entry;   <-- doesn't have to be the first item in the struct
+ *       int          a, b;
+ *   };
+ *
+ *   static struct list global_gadgets = LIST_INIT( global_gadgets );
+ *
+ * or
+ *
+ *   struct some_global_thing
+ *   {
+ *       struct list gadgets;
+ *   };
+ *
+ *   list_init( &some_global_thing->gadgets );
+ *
+ * Manipulate it like this:
+ *
+ *   list_add_head( &global_gadgets, &new_gadget->entry );
+ *   list_remove( &new_gadget->entry );
+ *   list_add_after( &some_random_gadget->entry, &new_gadget->entry );
+ *
+ * And to iterate over it:
+ *
+ *   struct gadget *gadget;
+ *   LIST_FOR_EACH_ENTRY( gadget, &global_gadgets, struct gadget, entry )
+ *   {
+ *       ...
+ *   }
+ *
+ */
+
+/* add an element after the specified one */
+static inline void list_add_after( struct list *elem, struct list *to_add )
+{
+    to_add->next = elem->next;
+    to_add->prev = elem;
+    elem->next->prev = to_add;
+    elem->next = to_add;
+}
+
+/* add an element before the specified one */
+static inline void list_add_before( struct list *elem, struct list *to_add )
+{
+    to_add->next = elem;
+    to_add->prev = elem->prev;
+    elem->prev->next = to_add;
+    elem->prev = to_add;
+}
+
+/* add element at the head of the list */
+static inline void list_add_head( struct list *list, struct list *elem )
+{
+    list_add_after( list, elem );
+}
+
+/* add element at the tail of the list */
+static inline void list_add_tail( struct list *list, struct list *elem )
+{
+    list_add_before( list, elem );
+}
+
+/* remove an element from its list */
+static inline void list_remove( struct list *elem )
+{
+    elem->next->prev = elem->prev;
+    elem->prev->next = elem->next;
+}
+
+/* get the next element */
+static inline struct list *list_next( const struct list *list, const struct list *elem )
+{
+    struct list *ret = elem->next;
+    if (elem->next == list) ret = NULL;
+    return ret;
+}
+
+/* get the previous element */
+static inline struct list *list_prev( const struct list *list, const struct list *elem )
+{
+    struct list *ret = elem->prev;
+    if (elem->prev == list) ret = NULL;
+    return ret;
+}
+
+/* get the first element */
+static inline struct list *list_head( const struct list *list )
+{
+    return list_next( list, list );
+}
+
+/* get the last element */
+static inline struct list *list_tail( const struct list *list )
+{
+    return list_prev( list, list );
+}
+
+/* check if a list is empty */
+static inline int list_empty( const struct list *list )
+{
+    return list->next == list;
+}
+
+/* initialize a list */
+static inline void list_init( struct list *list )
+{
+    list->next = list->prev = list;
+}
+
+/* count the elements of a list */
+static inline unsigned int list_count( const struct list *list )
+{
+    unsigned count = 0;
+    const struct list *ptr;
+    for (ptr = list->next; ptr != list; ptr = ptr->next) count++;
+    return count;
+}
+
+/* move all elements from src to the tail of dst */
+static inline void list_move_tail( struct list *dst, struct list *src )
+{
+    if (list_empty(src)) return;
+
+    dst->prev->next = src->next;
+    src->next->prev = dst->prev;
+    dst->prev = src->prev;
+    src->prev->next = dst;
+    list_init(src);
+}
+
+/* move all elements from src to the head of dst */
+static inline void list_move_head( struct list *dst, struct list *src )
+{
+    if (list_empty(src)) return;
+
+    dst->next->prev = src->prev;
+    src->prev->next = dst->next;
+    dst->next = src->next;
+    src->next->prev = dst;
+    list_init(src);
+}
+
+/* iterate through the list */
+#define LIST_FOR_EACH(cursor,list) \
+    for ((cursor) = (list)->next; (cursor) != (list); (cursor) = (cursor)->next)
+
+/* iterate through the list, with safety against removal */
+#define LIST_FOR_EACH_SAFE(cursor, cursor2, list) \
+    for ((cursor) = (list)->next, (cursor2) = (cursor)->next; \
+         (cursor) != (list); \
+         (cursor) = (cursor2), (cursor2) = (cursor)->next)
+
+/* iterate through the list using a list entry */
+#define LIST_FOR_EACH_ENTRY(elem, list, type, field) \
+    for ((elem) = LIST_ENTRY((list)->next, type, field); \
+         &(elem)->field != (list); \
+         (elem) = LIST_ENTRY((elem)->field.next, type, field))
+
+/* iterate through the list using a list entry, with safety against removal */
+#define LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, list, type, field) \
+    for ((cursor) = LIST_ENTRY((list)->next, type, field), \
+         (cursor2) = LIST_ENTRY((cursor)->field.next, type, field); \
+         &(cursor)->field != (list); \
+         (cursor) = (cursor2), \
+         (cursor2) = LIST_ENTRY((cursor)->field.next, type, field))
+
+/* iterate through the list in reverse order */
+#define LIST_FOR_EACH_REV(cursor,list) \
+    for ((cursor) = (list)->prev; (cursor) != (list); (cursor) = (cursor)->prev)
+
+/* iterate through the list in reverse order, with safety against removal */
+#define LIST_FOR_EACH_SAFE_REV(cursor, cursor2, list) \
+    for ((cursor) = (list)->prev, (cursor2) = (cursor)->prev; \
+         (cursor) != (list); \
+         (cursor) = (cursor2), (cursor2) = (cursor)->prev)
+
+/* iterate through the list in reverse order using a list entry */
+#define LIST_FOR_EACH_ENTRY_REV(elem, list, type, field) \
+    for ((elem) = LIST_ENTRY((list)->prev, type, field); \
+         &(elem)->field != (list); \
+         (elem) = LIST_ENTRY((elem)->field.prev, type, field))
+
+/* iterate through the list in reverse order using a list entry, with safety against removal */
+#define LIST_FOR_EACH_ENTRY_SAFE_REV(cursor, cursor2, list, type, field) \
+    for ((cursor) = LIST_ENTRY((list)->prev, type, field), \
+         (cursor2) = LIST_ENTRY((cursor)->field.prev, type, field); \
+         &(cursor)->field != (list); \
+         (cursor) = (cursor2), \
+         (cursor2) = LIST_ENTRY((cursor)->field.prev, type, field))
+
+/* macros for statically initialized lists */
+#undef LIST_INIT
+#define LIST_INIT(list)  { &(list), &(list) }
+
+/* get pointer to object containing list element */
+#undef LIST_ENTRY
+#define LIST_ENTRY(elem, type, field) \
+    ((type *)((char *)(elem) - offsetof(type, field)))
+
+#endif  /* __WINE_SERVER_LIST_H */
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/include/wine/port.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/include/wine/port.h	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/include/wine/port.h	(revision 46521)
@@ -0,0 +1,480 @@
+/*
+ * Wine porting definitions
+ *
+ * Copyright 1996 Alexandre Julliard
+ *
+ * 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_WINE_PORT_H
+#define __WINE_WINE_PORT_H
+
+#ifndef __WINE_CONFIG_H
+# error You must include config.h to use this header
+#endif
+
+#ifdef __WINE_BASETSD_H
+# error You must include port.h before all other headers
+#endif
+
+#define _GNU_SOURCE  /* for pread/pwrite */
+#include <fcntl.h>
+#include <math.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef HAVE_DIRECT_H
+# include <direct.h>
+#endif
+#ifdef HAVE_IO_H
+# include <io.h>
+#endif
+#ifdef HAVE_PROCESS_H
+# include <process.h>
+#endif
+#include <string.h>
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+
+/****************************************************************
+ * Type definitions
+ */
+
+#if !defined(_MSC_VER) && !defined(__int64)
+#  if defined(__x86_64__) || defined(__aarch64__) || defined(_WIN64)
+#    define __int64 long
+#  else
+#    define __int64 long long
+#  endif
+#endif
+
+#ifndef HAVE_MODE_T
+typedef int mode_t;
+#endif
+#ifndef HAVE_OFF_T
+typedef long off_t;
+#endif
+#ifndef HAVE_PID_T
+typedef int pid_t;
+#endif
+#ifndef HAVE_SIZE_T
+typedef unsigned int size_t;
+#endif
+#ifndef HAVE_SSIZE_T
+typedef int ssize_t;
+#endif
+#ifndef HAVE_FSBLKCNT_T
+typedef unsigned long fsblkcnt_t;
+#endif
+#ifndef HAVE_FSFILCNT_T
+typedef unsigned long fsfilcnt_t;
+#endif
+
+#ifndef HAVE_STRUCT_STATVFS_F_BLOCKS
+struct statvfs
+{
+    unsigned long f_bsize;
+    unsigned long f_frsize;
+    fsblkcnt_t    f_blocks;
+    fsblkcnt_t    f_bfree;
+    fsblkcnt_t    f_bavail;
+    fsfilcnt_t    f_files;
+    fsfilcnt_t    f_ffree;
+    fsfilcnt_t    f_favail;
+    unsigned long f_fsid;
+    unsigned long f_flag;
+    unsigned long f_namemax;
+};
+#endif /* HAVE_STRUCT_STATVFS_F_BLOCKS */
+
+
+/****************************************************************
+ * Macro definitions
+ */
+
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#else
+#define RTLD_LAZY    0x001
+#define RTLD_NOW     0x002
+#define RTLD_GLOBAL  0x100
+#endif
+
+#ifdef HAVE_ONE_ARG_MKDIR
+#define mkdir(path,mode) mkdir(path)
+#endif
+
+#if !defined(HAVE_FTRUNCATE) && defined(HAVE_CHSIZE)
+#define ftruncate chsize
+#endif
+
+#if !defined(HAVE_POPEN) && defined(HAVE__POPEN)
+#define popen _popen
+#endif
+
+#if !defined(HAVE_PCLOSE) && defined(HAVE__PCLOSE)
+#define pclose _pclose
+#endif
+
+#if !defined(HAVE_STRDUP) && defined(HAVE__STRDUP)
+#define strdup _strdup
+#endif
+
+#if !defined(HAVE_SNPRINTF) && defined(HAVE__SNPRINTF)
+#define snprintf _snprintf
+#endif
+
+#if !defined(HAVE_VSNPRINTF) && defined(HAVE__VSNPRINTF)
+#define vsnprintf _vsnprintf
+#endif
+
+#if !defined(HAVE_STRTOLL) && defined(HAVE__STRTOI64)
+#define strtoll _strtoi64
+#endif
+
+#if !defined(HAVE_STRTOULL) && defined(HAVE__STRTOUI64)
+#define strtoull _strtoui64
+#endif
+
+#ifndef S_ISLNK
+# define S_ISLNK(mod) (0)
+#endif
+
+#ifndef S_ISSOCK
+# define S_ISSOCK(mod) (0)
+#endif
+
+#ifndef S_ISDIR
+# define S_ISDIR(mod) (((mod) & _S_IFMT) == _S_IFDIR)
+#endif
+
+#ifndef S_ISCHR
+# define S_ISCHR(mod) (((mod) & _S_IFMT) == _S_IFCHR)
+#endif
+
+#ifndef S_ISFIFO
+# define S_ISFIFO(mod) (((mod) & _S_IFMT) == _S_IFIFO)
+#endif
+
+#ifndef S_ISREG
+# define S_ISREG(mod) (((mod) & _S_IFMT) == _S_IFREG)
+#endif
+
+/* So we open files in 64 bit access mode on Linux */
+#ifndef O_LARGEFILE
+# define O_LARGEFILE 0
+#endif
+
+#ifndef O_NONBLOCK
+# define O_NONBLOCK 0
+#endif
+
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif
+
+
+/****************************************************************
+ * Constants
+ */
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+#ifndef M_PI_2
+#define M_PI_2 1.570796326794896619
+#endif
+
+#ifdef VBOX
+# if !defined(__cplusplus)
+#  define inline _inline
+# endif
+#endif
+
+
+#ifndef INFINITY
+static inline float __port_infinity(void)
+{
+    static const unsigned __inf_bytes = 0x7f800000;
+    return *(const float *)&__inf_bytes;
+}
+#define INFINITY __port_infinity()
+#endif
+
+#ifndef NAN
+static inline float __port_nan(void)
+{
+    static const unsigned __nan_bytes = 0x7fc00000;
+    return *(const float *)&__nan_bytes;
+}
+#define NAN __port_nan()
+#endif
+
+
+/****************************************************************
+ * Function definitions (only when using libwine_port)
+ */
+
+#ifndef NO_LIBWINE_PORT
+
+#ifndef HAVE_FSTATVFS
+int fstatvfs( int fd, struct statvfs *buf );
+#endif
+
+#ifndef HAVE_GETOPT_LONG
+extern char *optarg;
+extern int optind;
+extern int opterr;
+extern int optopt;
+struct option;
+
+#ifndef HAVE_STRUCT_OPTION_NAME
+struct option
+{
+    const char *name;
+    int has_arg;
+    int *flag;
+    int val;
+};
+#endif
+
+extern int getopt_long (int ___argc, char *const *___argv,
+                        const char *__shortopts,
+                        const struct option *__longopts, int *__longind);
+extern int getopt_long_only (int ___argc, char *const *___argv,
+                             const char *__shortopts,
+                             const struct option *__longopts, int *__longind);
+#endif  /* HAVE_GETOPT_LONG */
+
+#ifndef HAVE_FFS
+int ffs( int x );
+#endif
+
+#ifndef HAVE_ISINF
+int isinf(double x);
+#endif
+
+#ifndef HAVE_ISNAN
+int isnan(double x);
+#endif
+
+#ifndef HAVE_LSTAT
+int lstat(const char *file_name, struct stat *buf);
+#endif /* HAVE_LSTAT */
+
+#ifndef HAVE_MEMMOVE
+void *memmove(void *dest, const void *src, size_t len);
+#endif /* !defined(HAVE_MEMMOVE) */
+
+#ifndef HAVE_POLL
+struct pollfd
+{
+    int fd;
+    short events;
+    short revents;
+};
+#define POLLIN   0x01
+#define POLLPRI  0x02
+#define POLLOUT  0x04
+#define POLLERR  0x08
+#define POLLHUP  0x10
+#define POLLNVAL 0x20
+int poll( struct pollfd *fds, unsigned int count, int timeout );
+#endif /* HAVE_POLL */
+
+#ifndef HAVE_PREAD
+ssize_t pread( int fd, void *buf, size_t count, off_t offset );
+#endif /* HAVE_PREAD */
+
+#ifndef HAVE_PWRITE
+ssize_t pwrite( int fd, const void *buf, size_t count, off_t offset );
+#endif /* HAVE_PWRITE */
+
+#ifndef HAVE_READLINK
+int readlink( const char *path, char *buf, size_t size );
+#endif /* HAVE_READLINK */
+
+#ifndef HAVE_STATVFS
+int statvfs( const char *path, struct statvfs *buf );
+#endif
+
+#ifndef HAVE_STRNCASECMP
+# ifndef HAVE__STRNICMP
+int strncasecmp(const char *str1, const char *str2, size_t n);
+# else
+# define strncasecmp _strnicmp
+# endif
+#endif /* !defined(HAVE_STRNCASECMP) */
+
+#ifndef HAVE_STRERROR
+const char *strerror(int err);
+#endif /* !defined(HAVE_STRERROR) */
+
+#ifndef HAVE_STRCASECMP
+# ifndef HAVE__STRICMP
+int strcasecmp(const char *str1, const char *str2);
+# else
+# define strcasecmp _stricmp
+# endif
+#endif /* !defined(HAVE_STRCASECMP) */
+
+#ifndef HAVE_SYMLINK
+int symlink(const char *from, const char *to);
+#endif
+
+#ifndef HAVE_USLEEP
+int usleep (unsigned int useconds);
+#endif /* !defined(HAVE_USLEEP) */
+
+#ifdef __i386__
+static inline void *memcpy_unaligned( void *dst, const void *src, size_t size )
+{
+    return memcpy( dst, src, size );
+}
+#else
+extern void *memcpy_unaligned( void *dst, const void *src, size_t size );
+#endif /* __i386__ */
+
+extern int mkstemps(char *template, int suffix_len);
+
+/* Process creation flags */
+#ifndef _P_WAIT
+# define _P_WAIT    0
+# define _P_NOWAIT  1
+# define _P_OVERLAY 2
+# define _P_NOWAITO 3
+# define _P_DETACH  4
+#endif
+#ifndef HAVE__SPAWNVP
+extern int _spawnvp(int mode, const char *cmdname, const char * const argv[]);
+#endif
+
+/* Interlocked functions */
+
+#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+
+extern __int64 interlocked_cmpxchg64( __int64 *dest, __int64 xchg, __int64 compare );
+
+static inline int interlocked_cmpxchg( int *dest, int xchg, int compare )
+{
+    int ret;
+    __asm__ __volatile__( "lock; cmpxchgl %2,(%1)"
+                          : "=a" (ret) : "r" (dest), "r" (xchg), "0" (compare) : "memory" );
+    return ret;
+}
+
+static inline void *interlocked_cmpxchg_ptr( void **dest, void *xchg, void *compare )
+{
+    void *ret;
+#ifdef __x86_64__
+    __asm__ __volatile__( "lock; cmpxchgq %2,(%1)"
+                          : "=a" (ret) : "r" (dest), "r" (xchg), "0" (compare) : "memory" );
+#else
+    __asm__ __volatile__( "lock; cmpxchgl %2,(%1)"
+                          : "=a" (ret) : "r" (dest), "r" (xchg), "0" (compare) : "memory" );
+#endif
+    return ret;
+}
+
+static inline int interlocked_xchg( int *dest, int val )
+{
+    int ret;
+    __asm__ __volatile__( "lock; xchgl %0,(%1)"
+                          : "=r" (ret) : "r" (dest), "0" (val) : "memory" );
+    return ret;
+}
+
+static inline void *interlocked_xchg_ptr( void **dest, void *val )
+{
+    void *ret;
+#ifdef __x86_64__
+    __asm__ __volatile__( "lock; xchgq %0,(%1)"
+                          : "=r" (ret) :"r" (dest), "0" (val) : "memory" );
+#else
+    __asm__ __volatile__( "lock; xchgl %0,(%1)"
+                          : "=r" (ret) : "r" (dest), "0" (val) : "memory" );
+#endif
+    return ret;
+}
+
+static inline int interlocked_xchg_add( int *dest, int incr )
+{
+    int ret;
+    __asm__ __volatile__( "lock; xaddl %0,(%1)"
+                          : "=r" (ret) : "r" (dest), "0" (incr) : "memory" );
+    return ret;
+}
+
+#ifdef __x86_64__
+static inline unsigned char interlocked_cmpxchg128( __int64 *dest, __int64 xchg_high,
+                                                    __int64 xchg_low, __int64 *compare )
+{
+    unsigned char ret;
+    __asm__ __volatile__( "lock cmpxchg16b %0; setz %b2"
+                          : "=m" (dest[0]), "=m" (dest[1]), "=r" (ret),
+                            "=a" (compare[0]), "=d" (compare[1])
+                          : "m" (dest[0]), "m" (dest[1]), "3" (compare[0]), "4" (compare[1]),
+                            "c" (xchg_high), "b" (xchg_low) );
+    return ret;
+}
+#endif
+
+#else  /* __GNUC__ */
+
+extern int interlocked_cmpxchg( int *dest, int xchg, int compare );
+extern void *interlocked_cmpxchg_ptr( void **dest, void *xchg, void *compare );
+extern __int64 interlocked_cmpxchg64( __int64 *dest, __int64 xchg, __int64 compare );
+extern int interlocked_xchg( int *dest, int val );
+extern void *interlocked_xchg_ptr( void **dest, void *val );
+extern int interlocked_xchg_add( int *dest, int incr );
+#if defined(__x86_64__) || defined(__aarch64__) || defined(_WIN64)
+extern unsigned char interlocked_cmpxchg128( __int64 *dest, __int64 xchg_high,
+                                             __int64 xchg_low, __int64 *compare );
+#endif
+
+#endif  /* __GNUC__ */
+
+#else /* NO_LIBWINE_PORT */
+
+#define __WINE_NOT_PORTABLE(func) func##_is_not_portable func##_is_not_portable
+
+#define ffs                     __WINE_NOT_PORTABLE(ffs)
+#define fstatvfs                __WINE_NOT_PORTABLE(fstatvfs)
+#define getopt_long             __WINE_NOT_PORTABLE(getopt_long)
+#define getopt_long_only        __WINE_NOT_PORTABLE(getopt_long_only)
+#define interlocked_cmpxchg     __WINE_NOT_PORTABLE(interlocked_cmpxchg)
+#define interlocked_cmpxchg_ptr __WINE_NOT_PORTABLE(interlocked_cmpxchg_ptr)
+#define interlocked_xchg        __WINE_NOT_PORTABLE(interlocked_xchg)
+#define interlocked_xchg_ptr    __WINE_NOT_PORTABLE(interlocked_xchg_ptr)
+#define interlocked_xchg_add    __WINE_NOT_PORTABLE(interlocked_xchg_add)
+#define lstat                   __WINE_NOT_PORTABLE(lstat)
+#define memcpy_unaligned        __WINE_NOT_PORTABLE(memcpy_unaligned)
+#undef memmove
+#define memmove                 __WINE_NOT_PORTABLE(memmove)
+#define pread                   __WINE_NOT_PORTABLE(pread)
+#define pwrite                  __WINE_NOT_PORTABLE(pwrite)
+#define spawnvp                 __WINE_NOT_PORTABLE(spawnvp)
+#define statvfs                 __WINE_NOT_PORTABLE(statvfs)
+#define strcasecmp              __WINE_NOT_PORTABLE(strcasecmp)
+#define strerror                __WINE_NOT_PORTABLE(strerror)
+#define strncasecmp             __WINE_NOT_PORTABLE(strncasecmp)
+#define usleep                  __WINE_NOT_PORTABLE(usleep)
+
+#endif /* NO_LIBWINE_PORT */
+
+#endif /* !defined(__WINE_WINE_PORT_H) */
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/include/wine/rbtree.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/include/wine/rbtree.h	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/include/wine/rbtree.h	(revision 46521)
@@ -0,0 +1,342 @@
+/*
+ * Red-black search tree support
+ *
+ * Copyright 2009 Henri Verbeet
+ * Copyright 2009 Andrew Riedi
+ *
+ * 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_WINE_RBTREE_H
+#define __WINE_WINE_RBTREE_H
+
+#define WINE_RB_ENTRY_VALUE(element, type, field) \
+    ((type *)((char *)(element) - offsetof(type, field)))
+
+struct wine_rb_entry
+{
+    struct wine_rb_entry *left;
+    struct wine_rb_entry *right;
+    unsigned int flags;
+};
+
+struct wine_rb_stack
+{
+    struct wine_rb_entry ***entries;
+    size_t count;
+    size_t size;
+};
+
+struct wine_rb_functions
+{
+    void *(*alloc)(size_t size);
+    void *(*realloc)(void *ptr, size_t size);
+    void (*free)(void *ptr);
+    int (*compare)(const void *key, const struct wine_rb_entry *entry);
+};
+
+struct wine_rb_tree
+{
+    const struct wine_rb_functions *functions;
+    struct wine_rb_entry *root;
+    struct wine_rb_stack stack;
+};
+
+typedef void (wine_rb_traverse_func_t)(struct wine_rb_entry *entry, void *context);
+
+#define WINE_RB_FLAG_RED                0x1
+#define WINE_RB_FLAG_STOP               0x2
+#define WINE_RB_FLAG_TRAVERSED_LEFT     0x4
+#define WINE_RB_FLAG_TRAVERSED_RIGHT    0x8
+
+static inline void wine_rb_stack_clear(struct wine_rb_stack *stack)
+{
+    stack->count = 0;
+}
+
+static inline void wine_rb_stack_push(struct wine_rb_stack *stack, struct wine_rb_entry **entry)
+{
+    stack->entries[stack->count++] = entry;
+}
+
+static inline int wine_rb_ensure_stack_size(struct wine_rb_tree *tree, size_t size)
+{
+    struct wine_rb_stack *stack = &tree->stack;
+
+    if (size > stack->size)
+    {
+        size_t new_size = stack->size << 1;
+        struct wine_rb_entry ***new_entries = tree->functions->realloc(stack->entries,
+                new_size * sizeof(*stack->entries));
+
+        if (!new_entries) return -1;
+
+        stack->entries = new_entries;
+        stack->size = new_size;
+    }
+
+    return 0;
+}
+
+static inline int wine_rb_is_red(struct wine_rb_entry *entry)
+{
+    return entry && (entry->flags & WINE_RB_FLAG_RED);
+}
+
+static inline void wine_rb_rotate_left(struct wine_rb_entry **entry)
+{
+    struct wine_rb_entry *e = *entry;
+    struct wine_rb_entry *right = e->right;
+
+    e->right = right->left;
+    right->left = e;
+    right->flags &= ~WINE_RB_FLAG_RED;
+    right->flags |= e->flags & WINE_RB_FLAG_RED;
+    e->flags |= WINE_RB_FLAG_RED;
+    *entry = right;
+}
+
+static inline void wine_rb_rotate_right(struct wine_rb_entry **entry)
+{
+    struct wine_rb_entry *e = *entry;
+    struct wine_rb_entry *left = e->left;
+
+    e->left = left->right;
+    left->right = e;
+    left->flags &= ~WINE_RB_FLAG_RED;
+    left->flags |= e->flags & WINE_RB_FLAG_RED;
+    e->flags |= WINE_RB_FLAG_RED;
+    *entry = left;
+}
+
+static inline void wine_rb_flip_color(struct wine_rb_entry *entry)
+{
+    entry->flags ^= WINE_RB_FLAG_RED;
+    entry->left->flags ^= WINE_RB_FLAG_RED;
+    entry->right->flags ^= WINE_RB_FLAG_RED;
+}
+
+static inline void wine_rb_fixup(struct wine_rb_stack *stack)
+{
+    while (stack->count)
+    {
+        struct wine_rb_entry **entry = stack->entries[stack->count - 1];
+
+        if ((*entry)->flags & WINE_RB_FLAG_STOP)
+        {
+            (*entry)->flags &= ~WINE_RB_FLAG_STOP;
+            return;
+        }
+
+        if (wine_rb_is_red((*entry)->right) && !wine_rb_is_red((*entry)->left)) wine_rb_rotate_left(entry);
+        if (wine_rb_is_red((*entry)->left) && wine_rb_is_red((*entry)->left->left)) wine_rb_rotate_right(entry);
+        if (wine_rb_is_red((*entry)->left) && wine_rb_is_red((*entry)->right)) wine_rb_flip_color(*entry);
+        --stack->count;
+    }
+}
+
+static inline void wine_rb_move_red_left(struct wine_rb_entry **entry)
+{
+    wine_rb_flip_color(*entry);
+    if (wine_rb_is_red((*entry)->right->left))
+    {
+        wine_rb_rotate_right(&(*entry)->right);
+        wine_rb_rotate_left(entry);
+        wine_rb_flip_color(*entry);
+    }
+}
+
+static inline void wine_rb_move_red_right(struct wine_rb_entry **entry)
+{
+    wine_rb_flip_color(*entry);
+    if (wine_rb_is_red((*entry)->left->left))
+    {
+        wine_rb_rotate_right(entry);
+        wine_rb_flip_color(*entry);
+    }
+}
+
+static inline void wine_rb_postorder(struct wine_rb_tree *tree, wine_rb_traverse_func_t *callback, void *context)
+{
+    struct wine_rb_entry **entry;
+
+    if (!tree->root) return;
+
+    for (entry = &tree->root;;)
+    {
+        struct wine_rb_entry *e = *entry;
+
+        if (e->left && !(e->flags & WINE_RB_FLAG_TRAVERSED_LEFT))
+        {
+            wine_rb_stack_push(&tree->stack, entry);
+            e->flags |= WINE_RB_FLAG_TRAVERSED_LEFT;
+            entry = &e->left;
+            continue;
+        }
+
+        if (e->right && !(e->flags & WINE_RB_FLAG_TRAVERSED_RIGHT))
+        {
+            wine_rb_stack_push(&tree->stack, entry);
+            e->flags |= WINE_RB_FLAG_TRAVERSED_RIGHT;
+            entry = &e->right;
+            continue;
+        }
+
+        e->flags &= ~(WINE_RB_FLAG_TRAVERSED_LEFT | WINE_RB_FLAG_TRAVERSED_RIGHT);
+        callback(e, context);
+
+        if (!tree->stack.count) break;
+        entry = tree->stack.entries[--tree->stack.count];
+    }
+}
+
+static inline int wine_rb_init(struct wine_rb_tree *tree, const struct wine_rb_functions *functions)
+{
+    tree->functions = functions;
+    tree->root = NULL;
+
+    tree->stack.entries = functions->alloc(16 * sizeof(*tree->stack.entries));
+    if (!tree->stack.entries) return -1;
+    tree->stack.size = 16;
+    tree->stack.count = 0;
+
+    return 0;
+}
+
+static inline void wine_rb_for_each_entry(struct wine_rb_tree *tree, wine_rb_traverse_func_t *callback, void *context)
+{
+    wine_rb_postorder(tree, callback, context);
+}
+
+static inline void wine_rb_destroy(struct wine_rb_tree *tree, wine_rb_traverse_func_t *callback, void *context)
+{
+    /* Note that we use postorder here because the callback will likely free the entry. */
+    if (callback) wine_rb_postorder(tree, callback, context);
+
+    tree->root = NULL;
+    tree->functions->free(tree->stack.entries);
+}
+
+static inline struct wine_rb_entry *wine_rb_get(const struct wine_rb_tree *tree, const void *key)
+{
+    struct wine_rb_entry *entry = tree->root;
+    while (entry)
+    {
+        int c = tree->functions->compare(key, entry);
+        if (!c) return entry;
+        entry = c < 0 ? entry->left : entry->right;
+    }
+    return NULL;
+}
+
+static inline int wine_rb_put(struct wine_rb_tree *tree, const void *key, struct wine_rb_entry *entry)
+{
+    struct wine_rb_entry **parent = &tree->root;
+    size_t black_height = 1;
+
+    while (*parent)
+    {
+        int c;
+
+        if (!wine_rb_is_red(*parent)) ++black_height;
+
+        wine_rb_stack_push(&tree->stack, parent);
+
+        c = tree->functions->compare(key, *parent);
+        if (!c)
+        {
+            wine_rb_stack_clear(&tree->stack);
+            return -1;
+        }
+        else if (c < 0) parent = &(*parent)->left;
+        else parent = &(*parent)->right;
+    }
+
+    /* After insertion, the path length to any node should be <= (black_height + 1) * 2. */
+    if (wine_rb_ensure_stack_size(tree, black_height << 1) == -1)
+    {
+        wine_rb_stack_clear(&tree->stack);
+        return -1;
+    }
+
+    entry->flags = WINE_RB_FLAG_RED;
+    entry->left = NULL;
+    entry->right = NULL;
+    *parent = entry;
+
+    wine_rb_fixup(&tree->stack);
+    tree->root->flags &= ~WINE_RB_FLAG_RED;
+
+    return 0;
+}
+
+static inline void wine_rb_remove(struct wine_rb_tree *tree, const void *key)
+{
+    struct wine_rb_entry **entry = &tree->root;
+
+    while (*entry)
+    {
+        if (tree->functions->compare(key, *entry) < 0)
+        {
+            wine_rb_stack_push(&tree->stack, entry);
+            if (!wine_rb_is_red((*entry)->left) && !wine_rb_is_red((*entry)->left->left)) wine_rb_move_red_left(entry);
+            entry = &(*entry)->left;
+        }
+        else
+        {
+            if (wine_rb_is_red((*entry)->left)) wine_rb_rotate_right(entry);
+            if (!tree->functions->compare(key, *entry) && !(*entry)->right)
+            {
+                *entry = NULL;
+                break;
+            }
+            if (!wine_rb_is_red((*entry)->right) && !wine_rb_is_red((*entry)->right->left))
+                wine_rb_move_red_right(entry);
+            if (!tree->functions->compare(key, *entry))
+            {
+                struct wine_rb_entry **e = &(*entry)->right;
+                struct wine_rb_entry *m = *e;
+                while (m->left) m = m->left;
+
+                wine_rb_stack_push(&tree->stack, entry);
+                (*entry)->flags |= WINE_RB_FLAG_STOP;
+
+                while ((*e)->left)
+                {
+                    wine_rb_stack_push(&tree->stack, e);
+                    if (!wine_rb_is_red((*e)->left) && !wine_rb_is_red((*e)->left->left)) wine_rb_move_red_left(e);
+                    e = &(*e)->left;
+                }
+                *e = NULL;
+                wine_rb_fixup(&tree->stack);
+
+                *m = **entry;
+                *entry = m;
+
+                break;
+            }
+            else
+            {
+                wine_rb_stack_push(&tree->stack, entry);
+                entry = &(*entry)->right;
+            }
+        }
+    }
+
+    wine_rb_fixup(&tree->stack);
+    if (tree->root) tree->root->flags &= ~WINE_RB_FLAG_RED;
+}
+
+#endif  /* __WINE_WINE_RBTREE_H */
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/include/wine/unicode.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/include/wine/unicode.h	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/include/wine/unicode.h	(revision 46521)
@@ -0,0 +1,311 @@
+/*
+ * Wine internal Unicode definitions
+ *
+ * Copyright 2000 Alexandre Julliard
+ *
+ * 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_WINE_UNICODE_H
+#define __WINE_WINE_UNICODE_H
+
+#include <stdarg.h>
+
+#include <windef.h>
+#include <winbase.h>
+#include <winnls.h>
+
+#ifdef __WINE_WINE_TEST_H
+#error This file should not be used in Wine tests
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef WINE_UNICODE_API
+# if defined(_MSC_VER) || defined(__MINGW32__)
+#  define WINE_UNICODE_API DECLSPEC_IMPORT
+# else
+#  define WINE_UNICODE_API
+# endif
+#endif
+
+#ifndef WINE_UNICODE_INLINE
+#define WINE_UNICODE_INLINE static inline
+#endif
+
+/* code page info common to SBCS and DBCS */
+struct cp_info
+{
+    unsigned int          codepage;          /* codepage id */
+    unsigned int          char_size;         /* char size (1 or 2 bytes) */
+    WCHAR                 def_char;          /* default char value (can be double-byte) */
+    WCHAR                 def_unicode_char;  /* default Unicode char value */
+    const char           *name;              /* code page name */
+};
+
+struct sbcs_table
+{
+    struct cp_info        info;
+    const WCHAR          *cp2uni;            /* code page -> Unicode map */
+    const WCHAR          *cp2uni_glyphs;     /* code page -> Unicode map with glyph chars */
+    const unsigned char  *uni2cp_low;        /* Unicode -> code page map */
+    const unsigned short *uni2cp_high;
+};
+
+struct dbcs_table
+{
+    struct cp_info        info;
+    const WCHAR          *cp2uni;            /* code page -> Unicode map */
+    const unsigned char  *cp2uni_leadbytes;
+    const unsigned short *uni2cp_low;        /* Unicode -> code page map */
+    const unsigned short *uni2cp_high;
+    unsigned char         lead_bytes[12];    /* lead bytes ranges */
+};
+
+union cptable
+{
+    struct cp_info    info;
+    struct sbcs_table sbcs;
+    struct dbcs_table dbcs;
+};
+
+extern const union cptable *wine_cp_get_table( unsigned int codepage );
+extern const union cptable *wine_cp_enum_table( unsigned int index );
+
+extern int wine_cp_mbstowcs( const union cptable *table, int flags,
+                             const char *src, int srclen,
+                             WCHAR *dst, int dstlen );
+extern int wine_cp_wcstombs( const union cptable *table, int flags,
+                             const WCHAR *src, int srclen,
+                             char *dst, int dstlen, const char *defchar, int *used );
+extern int wine_cpsymbol_mbstowcs( const char *src, int srclen, WCHAR *dst, int dstlen );
+extern int wine_cpsymbol_wcstombs( const WCHAR *src, int srclen, char *dst, int dstlen );
+extern int wine_utf8_mbstowcs( int flags, const char *src, int srclen, WCHAR *dst, int dstlen );
+extern int wine_utf8_wcstombs( int flags, const WCHAR *src, int srclen, char *dst, int dstlen );
+
+extern int wine_compare_string( int flags, const WCHAR *str1, int len1, const WCHAR *str2, int len2 );
+extern int wine_get_sortkey( int flags, const WCHAR *src, int srclen, char *dst, int dstlen );
+extern int wine_fold_string( int flags, const WCHAR *src, int srclen , WCHAR *dst, int dstlen );
+
+extern int strcmpiW( const WCHAR *str1, const WCHAR *str2 );
+extern int strncmpiW( const WCHAR *str1, const WCHAR *str2, int n );
+extern int memicmpW( const WCHAR *str1, const WCHAR *str2, int n );
+extern WCHAR *strstrW( const WCHAR *str, const WCHAR *sub );
+extern long int strtolW( const WCHAR *nptr, WCHAR **endptr, int base );
+extern unsigned long int strtoulW( const WCHAR *nptr, WCHAR **endptr, int base );
+extern int sprintfW( WCHAR *str, const WCHAR *format, ... );
+extern int snprintfW( WCHAR *str, size_t len, const WCHAR *format, ... );
+extern int vsprintfW( WCHAR *str, const WCHAR *format, va_list valist );
+extern int vsnprintfW( WCHAR *str, size_t len, const WCHAR *format, va_list valist );
+
+WINE_UNICODE_INLINE int wine_is_dbcs_leadbyte( const union cptable *table, unsigned char ch )
+{
+    return (table->info.char_size == 2) && (table->dbcs.cp2uni_leadbytes[ch]);
+}
+
+WINE_UNICODE_INLINE WCHAR tolowerW( WCHAR ch )
+{
+    extern WINE_UNICODE_API const WCHAR wine_casemap_lower[];
+    return ch + wine_casemap_lower[wine_casemap_lower[ch >> 8] + (ch & 0xff)];
+}
+
+WINE_UNICODE_INLINE WCHAR toupperW( WCHAR ch )
+{
+    extern WINE_UNICODE_API const WCHAR wine_casemap_upper[];
+    return ch + wine_casemap_upper[wine_casemap_upper[ch >> 8] + (ch & 0xff)];
+}
+
+/* the character type contains the C1_* flags in the low 12 bits */
+/* and the C2_* type in the high 4 bits */
+WINE_UNICODE_INLINE unsigned short get_char_typeW( WCHAR ch )
+{
+    extern WINE_UNICODE_API const unsigned short wine_wctype_table[];
+    return wine_wctype_table[wine_wctype_table[ch >> 8] + (ch & 0xff)];
+}
+
+WINE_UNICODE_INLINE int iscntrlW( WCHAR wc )
+{
+    return get_char_typeW(wc) & C1_CNTRL;
+}
+
+WINE_UNICODE_INLINE int ispunctW( WCHAR wc )
+{
+    return get_char_typeW(wc) & C1_PUNCT;
+}
+
+WINE_UNICODE_INLINE int isspaceW( WCHAR wc )
+{
+    return get_char_typeW(wc) & C1_SPACE;
+}
+
+WINE_UNICODE_INLINE int isdigitW( WCHAR wc )
+{
+    return get_char_typeW(wc) & C1_DIGIT;
+}
+
+WINE_UNICODE_INLINE int isxdigitW( WCHAR wc )
+{
+    return get_char_typeW(wc) & C1_XDIGIT;
+}
+
+WINE_UNICODE_INLINE int islowerW( WCHAR wc )
+{
+    return get_char_typeW(wc) & C1_LOWER;
+}
+
+WINE_UNICODE_INLINE int isupperW( WCHAR wc )
+{
+    return get_char_typeW(wc) & C1_UPPER;
+}
+
+WINE_UNICODE_INLINE int isalnumW( WCHAR wc )
+{
+    return get_char_typeW(wc) & (C1_ALPHA|C1_DIGIT|C1_LOWER|C1_UPPER);
+}
+
+WINE_UNICODE_INLINE int isalphaW( WCHAR wc )
+{
+    return get_char_typeW(wc) & (C1_ALPHA|C1_LOWER|C1_UPPER);
+}
+
+WINE_UNICODE_INLINE int isgraphW( WCHAR wc )
+{
+    return get_char_typeW(wc) & (C1_ALPHA|C1_PUNCT|C1_DIGIT|C1_LOWER|C1_UPPER);
+}
+
+WINE_UNICODE_INLINE int isprintW( WCHAR wc )
+{
+    return get_char_typeW(wc) & (C1_ALPHA|C1_BLANK|C1_PUNCT|C1_DIGIT|C1_LOWER|C1_UPPER);
+}
+
+/* some useful string manipulation routines */
+
+WINE_UNICODE_INLINE unsigned int strlenW( const WCHAR *str )
+{
+    const WCHAR *s = str;
+    while (*s) s++;
+    return s - str;
+}
+
+WINE_UNICODE_INLINE WCHAR *strcpyW( WCHAR *dst, const WCHAR *src )
+{
+    WCHAR *p = dst;
+    while ((*p++ = *src++));
+    return dst;
+}
+
+/* strncpy doesn't do what you think, don't use it */
+#define strncpyW(d,s,n) error do_not_use_strncpyW_use_lstrcpynW_or_memcpy_instead
+
+WINE_UNICODE_INLINE int strcmpW( const WCHAR *str1, const WCHAR *str2 )
+{
+    while (*str1 && (*str1 == *str2)) { str1++; str2++; }
+    return *str1 - *str2;
+}
+
+WINE_UNICODE_INLINE int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
+{
+    if (n <= 0) return 0;
+    while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
+    return *str1 - *str2;
+}
+
+WINE_UNICODE_INLINE WCHAR *strcatW( WCHAR *dst, const WCHAR *src )
+{
+    strcpyW( dst + strlenW(dst), src );
+    return dst;
+}
+
+WINE_UNICODE_INLINE WCHAR *strchrW( const WCHAR *str, WCHAR ch )
+{
+    do { if (*str == ch) return (WCHAR *)(ULONG_PTR)str; } while (*str++);
+    return NULL;
+}
+
+WINE_UNICODE_INLINE WCHAR *strrchrW( const WCHAR *str, WCHAR ch )
+{
+    WCHAR *ret = NULL;
+    do { if (*str == ch) ret = (WCHAR *)(ULONG_PTR)str; } while (*str++);
+    return ret;
+}
+
+WINE_UNICODE_INLINE WCHAR *strpbrkW( const WCHAR *str, const WCHAR *accept )
+{
+    for ( ; *str; str++) if (strchrW( accept, *str )) return (WCHAR *)(ULONG_PTR)str;
+    return NULL;
+}
+
+WINE_UNICODE_INLINE size_t strspnW( const WCHAR *str, const WCHAR *accept )
+{
+    const WCHAR *ptr;
+    for (ptr = str; *ptr; ptr++) if (!strchrW( accept, *ptr )) break;
+    return ptr - str;
+}
+
+WINE_UNICODE_INLINE size_t strcspnW( const WCHAR *str, const WCHAR *reject )
+{
+    const WCHAR *ptr;
+    for (ptr = str; *ptr; ptr++) if (strchrW( reject, *ptr )) break;
+    return ptr - str;
+}
+
+WINE_UNICODE_INLINE WCHAR *strlwrW( WCHAR *str )
+{
+    WCHAR *ret;
+    for (ret = str; *str; str++) *str = tolowerW(*str);
+    return ret;
+}
+
+WINE_UNICODE_INLINE WCHAR *struprW( WCHAR *str )
+{
+    WCHAR *ret;
+    for (ret = str; *str; str++) *str = toupperW(*str);
+    return ret;
+}
+
+WINE_UNICODE_INLINE WCHAR *memchrW( const WCHAR *ptr, WCHAR ch, size_t n )
+{
+    const WCHAR *end;
+    for (end = ptr + n; ptr < end; ptr++) if (*ptr == ch) return (WCHAR *)(ULONG_PTR)ptr;
+    return NULL;
+}
+
+WINE_UNICODE_INLINE WCHAR *memrchrW( const WCHAR *ptr, WCHAR ch, size_t n )
+{
+    const WCHAR *end;
+    WCHAR *ret = NULL;
+    for (end = ptr + n; ptr < end; ptr++) if (*ptr == ch) ret = (WCHAR *)(ULONG_PTR)ptr;
+    return ret;
+}
+
+WINE_UNICODE_INLINE long int atolW( const WCHAR *str )
+{
+    return strtolW( str, (WCHAR **)0, 10 );
+}
+
+WINE_UNICODE_INLINE int atoiW( const WCHAR *str )
+{
+    return (int)atolW( str );
+}
+
+#undef WINE_UNICODE_INLINE
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* __WINE_WINE_UNICODE_H */
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/include/wine/wgl_driver.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/include/wine/wgl_driver.h	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/include/wine/wgl_driver.h	(revision 46521)
@@ -0,0 +1,2862 @@
+/* Automatically generated from http://www.opengl.org/registry/api files; DO NOT EDIT! */
+
+#ifndef __WINE_WGL_DRIVER_H
+#define __WINE_WGL_DRIVER_H
+
+#ifndef WINE_GLAPI
+#define WINE_GLAPI
+#endif
+
+#define WINE_WGL_DRIVER_VERSION 10
+
+struct wgl_context;
+struct wgl_pbuffer;
+
+struct opengl_funcs
+{
+    struct
+    {
+        BOOL       (WINE_GLAPI *p_wglCopyContext)(struct wgl_context *,struct wgl_context *,UINT);
+        struct wgl_context * (WINE_GLAPI *p_wglCreateContext)(HDC);
+        void       (WINE_GLAPI *p_wglDeleteContext)(struct wgl_context *);
+        INT        (WINE_GLAPI *p_wglDescribePixelFormat)(HDC,INT,UINT,PIXELFORMATDESCRIPTOR *);
+        INT        (WINE_GLAPI *p_wglGetPixelFormat)(HDC);
+        PROC       (WINE_GLAPI *p_wglGetProcAddress)(LPCSTR);
+        BOOL       (WINE_GLAPI *p_wglMakeCurrent)(HDC,struct wgl_context *);
+        BOOL       (WINE_GLAPI *p_wglSetPixelFormat)(HDC,INT,const PIXELFORMATDESCRIPTOR *);
+        BOOL       (WINE_GLAPI *p_wglShareLists)(struct wgl_context *,struct wgl_context *);
+        BOOL       (WINE_GLAPI *p_wglSwapBuffers)(HDC);
+    } wgl;
+
+    struct
+    {
+        void       (WINE_GLAPI *p_glAccum)(GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glAlphaFunc)(GLenum,GLfloat);
+        GLboolean  (WINE_GLAPI *p_glAreTexturesResident)(GLsizei,const GLuint*,GLboolean*);
+        void       (WINE_GLAPI *p_glArrayElement)(GLint);
+        void       (WINE_GLAPI *p_glBegin)(GLenum);
+        void       (WINE_GLAPI *p_glBindTexture)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glBitmap)(GLsizei,GLsizei,GLfloat,GLfloat,GLfloat,GLfloat,const GLubyte*);
+        void       (WINE_GLAPI *p_glBlendFunc)(GLenum,GLenum);
+        void       (WINE_GLAPI *p_glCallList)(GLuint);
+        void       (WINE_GLAPI *p_glCallLists)(GLsizei,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glClear)(GLbitfield);
+        void       (WINE_GLAPI *p_glClearAccum)(GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glClearColor)(GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glClearDepth)(GLdouble);
+        void       (WINE_GLAPI *p_glClearIndex)(GLfloat);
+        void       (WINE_GLAPI *p_glClearStencil)(GLint);
+        void       (WINE_GLAPI *p_glClipPlane)(GLenum,const GLdouble*);
+        void       (WINE_GLAPI *p_glColor3b)(GLbyte,GLbyte,GLbyte);
+        void       (WINE_GLAPI *p_glColor3bv)(const GLbyte*);
+        void       (WINE_GLAPI *p_glColor3d)(GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glColor3dv)(const GLdouble*);
+        void       (WINE_GLAPI *p_glColor3f)(GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glColor3fv)(const GLfloat*);
+        void       (WINE_GLAPI *p_glColor3i)(GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glColor3iv)(const GLint*);
+        void       (WINE_GLAPI *p_glColor3s)(GLshort,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glColor3sv)(const GLshort*);
+        void       (WINE_GLAPI *p_glColor3ub)(GLubyte,GLubyte,GLubyte);
+        void       (WINE_GLAPI *p_glColor3ubv)(const GLubyte*);
+        void       (WINE_GLAPI *p_glColor3ui)(GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glColor3uiv)(const GLuint*);
+        void       (WINE_GLAPI *p_glColor3us)(GLushort,GLushort,GLushort);
+        void       (WINE_GLAPI *p_glColor3usv)(const GLushort*);
+        void       (WINE_GLAPI *p_glColor4b)(GLbyte,GLbyte,GLbyte,GLbyte);
+        void       (WINE_GLAPI *p_glColor4bv)(const GLbyte*);
+        void       (WINE_GLAPI *p_glColor4d)(GLdouble,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glColor4dv)(const GLdouble*);
+        void       (WINE_GLAPI *p_glColor4f)(GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glColor4fv)(const GLfloat*);
+        void       (WINE_GLAPI *p_glColor4i)(GLint,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glColor4iv)(const GLint*);
+        void       (WINE_GLAPI *p_glColor4s)(GLshort,GLshort,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glColor4sv)(const GLshort*);
+        void       (WINE_GLAPI *p_glColor4ub)(GLubyte,GLubyte,GLubyte,GLubyte);
+        void       (WINE_GLAPI *p_glColor4ubv)(const GLubyte*);
+        void       (WINE_GLAPI *p_glColor4ui)(GLuint,GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glColor4uiv)(const GLuint*);
+        void       (WINE_GLAPI *p_glColor4us)(GLushort,GLushort,GLushort,GLushort);
+        void       (WINE_GLAPI *p_glColor4usv)(const GLushort*);
+        void       (WINE_GLAPI *p_glColorMask)(GLboolean,GLboolean,GLboolean,GLboolean);
+        void       (WINE_GLAPI *p_glColorMaterial)(GLenum,GLenum);
+        void       (WINE_GLAPI *p_glColorPointer)(GLint,GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glCopyPixels)(GLint,GLint,GLsizei,GLsizei,GLenum);
+        void       (WINE_GLAPI *p_glCopyTexImage1D)(GLenum,GLint,GLenum,GLint,GLint,GLsizei,GLint);
+        void       (WINE_GLAPI *p_glCopyTexImage2D)(GLenum,GLint,GLenum,GLint,GLint,GLsizei,GLsizei,GLint);
+        void       (WINE_GLAPI *p_glCopyTexSubImage1D)(GLenum,GLint,GLint,GLint,GLint,GLsizei);
+        void       (WINE_GLAPI *p_glCopyTexSubImage2D)(GLenum,GLint,GLint,GLint,GLint,GLint,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glCullFace)(GLenum);
+        void       (WINE_GLAPI *p_glDeleteLists)(GLuint,GLsizei);
+        void       (WINE_GLAPI *p_glDeleteTextures)(GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glDepthFunc)(GLenum);
+        void       (WINE_GLAPI *p_glDepthMask)(GLboolean);
+        void       (WINE_GLAPI *p_glDepthRange)(GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glDisable)(GLenum);
+        void       (WINE_GLAPI *p_glDisableClientState)(GLenum);
+        void       (WINE_GLAPI *p_glDrawArrays)(GLenum,GLint,GLsizei);
+        void       (WINE_GLAPI *p_glDrawBuffer)(GLenum);
+        void       (WINE_GLAPI *p_glDrawElements)(GLenum,GLsizei,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glDrawPixels)(GLsizei,GLsizei,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glEdgeFlag)(GLboolean);
+        void       (WINE_GLAPI *p_glEdgeFlagPointer)(GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glEdgeFlagv)(const GLboolean*);
+        void       (WINE_GLAPI *p_glEnable)(GLenum);
+        void       (WINE_GLAPI *p_glEnableClientState)(GLenum);
+        void       (WINE_GLAPI *p_glEnd)(void);
+        void       (WINE_GLAPI *p_glEndList)(void);
+        void       (WINE_GLAPI *p_glEvalCoord1d)(GLdouble);
+        void       (WINE_GLAPI *p_glEvalCoord1dv)(const GLdouble*);
+        void       (WINE_GLAPI *p_glEvalCoord1f)(GLfloat);
+        void       (WINE_GLAPI *p_glEvalCoord1fv)(const GLfloat*);
+        void       (WINE_GLAPI *p_glEvalCoord2d)(GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glEvalCoord2dv)(const GLdouble*);
+        void       (WINE_GLAPI *p_glEvalCoord2f)(GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glEvalCoord2fv)(const GLfloat*);
+        void       (WINE_GLAPI *p_glEvalMesh1)(GLenum,GLint,GLint);
+        void       (WINE_GLAPI *p_glEvalMesh2)(GLenum,GLint,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glEvalPoint1)(GLint);
+        void       (WINE_GLAPI *p_glEvalPoint2)(GLint,GLint);
+        void       (WINE_GLAPI *p_glFeedbackBuffer)(GLsizei,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glFinish)(void);
+        void       (WINE_GLAPI *p_glFlush)(void);
+        void       (WINE_GLAPI *p_glFogf)(GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glFogfv)(GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glFogi)(GLenum,GLint);
+        void       (WINE_GLAPI *p_glFogiv)(GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glFrontFace)(GLenum);
+        void       (WINE_GLAPI *p_glFrustum)(GLdouble,GLdouble,GLdouble,GLdouble,GLdouble,GLdouble);
+        GLuint     (WINE_GLAPI *p_glGenLists)(GLsizei);
+        void       (WINE_GLAPI *p_glGenTextures)(GLsizei,GLuint*);
+        void       (WINE_GLAPI *p_glGetBooleanv)(GLenum,GLboolean*);
+        void       (WINE_GLAPI *p_glGetClipPlane)(GLenum,GLdouble*);
+        void       (WINE_GLAPI *p_glGetDoublev)(GLenum,GLdouble*);
+        GLenum     (WINE_GLAPI *p_glGetError)(void);
+        void       (WINE_GLAPI *p_glGetFloatv)(GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetIntegerv)(GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetLightfv)(GLenum,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetLightiv)(GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetMapdv)(GLenum,GLenum,GLdouble*);
+        void       (WINE_GLAPI *p_glGetMapfv)(GLenum,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetMapiv)(GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetMaterialfv)(GLenum,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetMaterialiv)(GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetPixelMapfv)(GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetPixelMapuiv)(GLenum,GLuint*);
+        void       (WINE_GLAPI *p_glGetPixelMapusv)(GLenum,GLushort*);
+        void       (WINE_GLAPI *p_glGetPointerv)(GLenum,GLvoid**);
+        void       (WINE_GLAPI *p_glGetPolygonStipple)(GLubyte*);
+        const GLubyte * (WINE_GLAPI *p_glGetString)(GLenum);
+        void       (WINE_GLAPI *p_glGetTexEnvfv)(GLenum,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetTexEnviv)(GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetTexGendv)(GLenum,GLenum,GLdouble*);
+        void       (WINE_GLAPI *p_glGetTexGenfv)(GLenum,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetTexGeniv)(GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetTexImage)(GLenum,GLint,GLenum,GLenum,GLvoid*);
+        void       (WINE_GLAPI *p_glGetTexLevelParameterfv)(GLenum,GLint,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetTexLevelParameteriv)(GLenum,GLint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetTexParameterfv)(GLenum,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetTexParameteriv)(GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glHint)(GLenum,GLenum);
+        void       (WINE_GLAPI *p_glIndexMask)(GLuint);
+        void       (WINE_GLAPI *p_glIndexPointer)(GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glIndexd)(GLdouble);
+        void       (WINE_GLAPI *p_glIndexdv)(const GLdouble*);
+        void       (WINE_GLAPI *p_glIndexf)(GLfloat);
+        void       (WINE_GLAPI *p_glIndexfv)(const GLfloat*);
+        void       (WINE_GLAPI *p_glIndexi)(GLint);
+        void       (WINE_GLAPI *p_glIndexiv)(const GLint*);
+        void       (WINE_GLAPI *p_glIndexs)(GLshort);
+        void       (WINE_GLAPI *p_glIndexsv)(const GLshort*);
+        void       (WINE_GLAPI *p_glIndexub)(GLubyte);
+        void       (WINE_GLAPI *p_glIndexubv)(const GLubyte*);
+        void       (WINE_GLAPI *p_glInitNames)(void);
+        void       (WINE_GLAPI *p_glInterleavedArrays)(GLenum,GLsizei,const GLvoid*);
+        GLboolean  (WINE_GLAPI *p_glIsEnabled)(GLenum);
+        GLboolean  (WINE_GLAPI *p_glIsList)(GLuint);
+        GLboolean  (WINE_GLAPI *p_glIsTexture)(GLuint);
+        void       (WINE_GLAPI *p_glLightModelf)(GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glLightModelfv)(GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glLightModeli)(GLenum,GLint);
+        void       (WINE_GLAPI *p_glLightModeliv)(GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glLightf)(GLenum,GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glLightfv)(GLenum,GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glLighti)(GLenum,GLenum,GLint);
+        void       (WINE_GLAPI *p_glLightiv)(GLenum,GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glLineStipple)(GLint,GLushort);
+        void       (WINE_GLAPI *p_glLineWidth)(GLfloat);
+        void       (WINE_GLAPI *p_glListBase)(GLuint);
+        void       (WINE_GLAPI *p_glLoadIdentity)(void);
+        void       (WINE_GLAPI *p_glLoadMatrixd)(const GLdouble*);
+        void       (WINE_GLAPI *p_glLoadMatrixf)(const GLfloat*);
+        void       (WINE_GLAPI *p_glLoadName)(GLuint);
+        void       (WINE_GLAPI *p_glLogicOp)(GLenum);
+        void       (WINE_GLAPI *p_glMap1d)(GLenum,GLdouble,GLdouble,GLint,GLint,const GLdouble*);
+        void       (WINE_GLAPI *p_glMap1f)(GLenum,GLfloat,GLfloat,GLint,GLint,const GLfloat*);
+        void       (WINE_GLAPI *p_glMap2d)(GLenum,GLdouble,GLdouble,GLint,GLint,GLdouble,GLdouble,GLint,GLint,const GLdouble*);
+        void       (WINE_GLAPI *p_glMap2f)(GLenum,GLfloat,GLfloat,GLint,GLint,GLfloat,GLfloat,GLint,GLint,const GLfloat*);
+        void       (WINE_GLAPI *p_glMapGrid1d)(GLint,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glMapGrid1f)(GLint,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glMapGrid2d)(GLint,GLdouble,GLdouble,GLint,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glMapGrid2f)(GLint,GLfloat,GLfloat,GLint,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glMaterialf)(GLenum,GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glMaterialfv)(GLenum,GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glMateriali)(GLenum,GLenum,GLint);
+        void       (WINE_GLAPI *p_glMaterialiv)(GLenum,GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glMatrixMode)(GLenum);
+        void       (WINE_GLAPI *p_glMultMatrixd)(const GLdouble*);
+        void       (WINE_GLAPI *p_glMultMatrixf)(const GLfloat*);
+        void       (WINE_GLAPI *p_glNewList)(GLuint,GLenum);
+        void       (WINE_GLAPI *p_glNormal3b)(GLbyte,GLbyte,GLbyte);
+        void       (WINE_GLAPI *p_glNormal3bv)(const GLbyte*);
+        void       (WINE_GLAPI *p_glNormal3d)(GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glNormal3dv)(const GLdouble*);
+        void       (WINE_GLAPI *p_glNormal3f)(GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glNormal3fv)(const GLfloat*);
+        void       (WINE_GLAPI *p_glNormal3i)(GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glNormal3iv)(const GLint*);
+        void       (WINE_GLAPI *p_glNormal3s)(GLshort,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glNormal3sv)(const GLshort*);
+        void       (WINE_GLAPI *p_glNormalPointer)(GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glOrtho)(GLdouble,GLdouble,GLdouble,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glPassThrough)(GLfloat);
+        void       (WINE_GLAPI *p_glPixelMapfv)(GLenum,GLint,const GLfloat*);
+        void       (WINE_GLAPI *p_glPixelMapuiv)(GLenum,GLint,const GLuint*);
+        void       (WINE_GLAPI *p_glPixelMapusv)(GLenum,GLint,const GLushort*);
+        void       (WINE_GLAPI *p_glPixelStoref)(GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glPixelStorei)(GLenum,GLint);
+        void       (WINE_GLAPI *p_glPixelTransferf)(GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glPixelTransferi)(GLenum,GLint);
+        void       (WINE_GLAPI *p_glPixelZoom)(GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glPointSize)(GLfloat);
+        void       (WINE_GLAPI *p_glPolygonMode)(GLenum,GLenum);
+        void       (WINE_GLAPI *p_glPolygonOffset)(GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glPolygonStipple)(const GLubyte*);
+        void       (WINE_GLAPI *p_glPopAttrib)(void);
+        void       (WINE_GLAPI *p_glPopClientAttrib)(void);
+        void       (WINE_GLAPI *p_glPopMatrix)(void);
+        void       (WINE_GLAPI *p_glPopName)(void);
+        void       (WINE_GLAPI *p_glPrioritizeTextures)(GLsizei,const GLuint*,const GLfloat*);
+        void       (WINE_GLAPI *p_glPushAttrib)(GLbitfield);
+        void       (WINE_GLAPI *p_glPushClientAttrib)(GLbitfield);
+        void       (WINE_GLAPI *p_glPushMatrix)(void);
+        void       (WINE_GLAPI *p_glPushName)(GLuint);
+        void       (WINE_GLAPI *p_glRasterPos2d)(GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glRasterPos2dv)(const GLdouble*);
+        void       (WINE_GLAPI *p_glRasterPos2f)(GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glRasterPos2fv)(const GLfloat*);
+        void       (WINE_GLAPI *p_glRasterPos2i)(GLint,GLint);
+        void       (WINE_GLAPI *p_glRasterPos2iv)(const GLint*);
+        void       (WINE_GLAPI *p_glRasterPos2s)(GLshort,GLshort);
+        void       (WINE_GLAPI *p_glRasterPos2sv)(const GLshort*);
+        void       (WINE_GLAPI *p_glRasterPos3d)(GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glRasterPos3dv)(const GLdouble*);
+        void       (WINE_GLAPI *p_glRasterPos3f)(GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glRasterPos3fv)(const GLfloat*);
+        void       (WINE_GLAPI *p_glRasterPos3i)(GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glRasterPos3iv)(const GLint*);
+        void       (WINE_GLAPI *p_glRasterPos3s)(GLshort,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glRasterPos3sv)(const GLshort*);
+        void       (WINE_GLAPI *p_glRasterPos4d)(GLdouble,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glRasterPos4dv)(const GLdouble*);
+        void       (WINE_GLAPI *p_glRasterPos4f)(GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glRasterPos4fv)(const GLfloat*);
+        void       (WINE_GLAPI *p_glRasterPos4i)(GLint,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glRasterPos4iv)(const GLint*);
+        void       (WINE_GLAPI *p_glRasterPos4s)(GLshort,GLshort,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glRasterPos4sv)(const GLshort*);
+        void       (WINE_GLAPI *p_glReadBuffer)(GLenum);
+        void       (WINE_GLAPI *p_glReadPixels)(GLint,GLint,GLsizei,GLsizei,GLenum,GLenum,GLvoid*);
+        void       (WINE_GLAPI *p_glRectd)(GLdouble,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glRectdv)(const GLdouble*,const GLdouble*);
+        void       (WINE_GLAPI *p_glRectf)(GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glRectfv)(const GLfloat*,const GLfloat*);
+        void       (WINE_GLAPI *p_glRecti)(GLint,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glRectiv)(const GLint*,const GLint*);
+        void       (WINE_GLAPI *p_glRects)(GLshort,GLshort,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glRectsv)(const GLshort*,const GLshort*);
+        GLint      (WINE_GLAPI *p_glRenderMode)(GLenum);
+        void       (WINE_GLAPI *p_glRotated)(GLdouble,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glRotatef)(GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glScaled)(GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glScalef)(GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glScissor)(GLint,GLint,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glSelectBuffer)(GLsizei,GLuint*);
+        void       (WINE_GLAPI *p_glShadeModel)(GLenum);
+        void       (WINE_GLAPI *p_glStencilFunc)(GLenum,GLint,GLuint);
+        void       (WINE_GLAPI *p_glStencilMask)(GLuint);
+        void       (WINE_GLAPI *p_glStencilOp)(GLenum,GLenum,GLenum);
+        void       (WINE_GLAPI *p_glTexCoord1d)(GLdouble);
+        void       (WINE_GLAPI *p_glTexCoord1dv)(const GLdouble*);
+        void       (WINE_GLAPI *p_glTexCoord1f)(GLfloat);
+        void       (WINE_GLAPI *p_glTexCoord1fv)(const GLfloat*);
+        void       (WINE_GLAPI *p_glTexCoord1i)(GLint);
+        void       (WINE_GLAPI *p_glTexCoord1iv)(const GLint*);
+        void       (WINE_GLAPI *p_glTexCoord1s)(GLshort);
+        void       (WINE_GLAPI *p_glTexCoord1sv)(const GLshort*);
+        void       (WINE_GLAPI *p_glTexCoord2d)(GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glTexCoord2dv)(const GLdouble*);
+        void       (WINE_GLAPI *p_glTexCoord2f)(GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glTexCoord2fv)(const GLfloat*);
+        void       (WINE_GLAPI *p_glTexCoord2i)(GLint,GLint);
+        void       (WINE_GLAPI *p_glTexCoord2iv)(const GLint*);
+        void       (WINE_GLAPI *p_glTexCoord2s)(GLshort,GLshort);
+        void       (WINE_GLAPI *p_glTexCoord2sv)(const GLshort*);
+        void       (WINE_GLAPI *p_glTexCoord3d)(GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glTexCoord3dv)(const GLdouble*);
+        void       (WINE_GLAPI *p_glTexCoord3f)(GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glTexCoord3fv)(const GLfloat*);
+        void       (WINE_GLAPI *p_glTexCoord3i)(GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glTexCoord3iv)(const GLint*);
+        void       (WINE_GLAPI *p_glTexCoord3s)(GLshort,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glTexCoord3sv)(const GLshort*);
+        void       (WINE_GLAPI *p_glTexCoord4d)(GLdouble,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glTexCoord4dv)(const GLdouble*);
+        void       (WINE_GLAPI *p_glTexCoord4f)(GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glTexCoord4fv)(const GLfloat*);
+        void       (WINE_GLAPI *p_glTexCoord4i)(GLint,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glTexCoord4iv)(const GLint*);
+        void       (WINE_GLAPI *p_glTexCoord4s)(GLshort,GLshort,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glTexCoord4sv)(const GLshort*);
+        void       (WINE_GLAPI *p_glTexCoordPointer)(GLint,GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glTexEnvf)(GLenum,GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glTexEnvfv)(GLenum,GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glTexEnvi)(GLenum,GLenum,GLint);
+        void       (WINE_GLAPI *p_glTexEnviv)(GLenum,GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glTexGend)(GLenum,GLenum,GLdouble);
+        void       (WINE_GLAPI *p_glTexGendv)(GLenum,GLenum,const GLdouble*);
+        void       (WINE_GLAPI *p_glTexGenf)(GLenum,GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glTexGenfv)(GLenum,GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glTexGeni)(GLenum,GLenum,GLint);
+        void       (WINE_GLAPI *p_glTexGeniv)(GLenum,GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glTexImage1D)(GLenum,GLint,GLint,GLsizei,GLint,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glTexImage2D)(GLenum,GLint,GLint,GLsizei,GLsizei,GLint,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glTexParameterf)(GLenum,GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glTexParameterfv)(GLenum,GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glTexParameteri)(GLenum,GLenum,GLint);
+        void       (WINE_GLAPI *p_glTexParameteriv)(GLenum,GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glTexSubImage1D)(GLenum,GLint,GLint,GLsizei,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glTexSubImage2D)(GLenum,GLint,GLint,GLint,GLsizei,GLsizei,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glTranslated)(GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glTranslatef)(GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glVertex2d)(GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glVertex2dv)(const GLdouble*);
+        void       (WINE_GLAPI *p_glVertex2f)(GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glVertex2fv)(const GLfloat*);
+        void       (WINE_GLAPI *p_glVertex2i)(GLint,GLint);
+        void       (WINE_GLAPI *p_glVertex2iv)(const GLint*);
+        void       (WINE_GLAPI *p_glVertex2s)(GLshort,GLshort);
+        void       (WINE_GLAPI *p_glVertex2sv)(const GLshort*);
+        void       (WINE_GLAPI *p_glVertex3d)(GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glVertex3dv)(const GLdouble*);
+        void       (WINE_GLAPI *p_glVertex3f)(GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glVertex3fv)(const GLfloat*);
+        void       (WINE_GLAPI *p_glVertex3i)(GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glVertex3iv)(const GLint*);
+        void       (WINE_GLAPI *p_glVertex3s)(GLshort,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glVertex3sv)(const GLshort*);
+        void       (WINE_GLAPI *p_glVertex4d)(GLdouble,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glVertex4dv)(const GLdouble*);
+        void       (WINE_GLAPI *p_glVertex4f)(GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glVertex4fv)(const GLfloat*);
+        void       (WINE_GLAPI *p_glVertex4i)(GLint,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glVertex4iv)(const GLint*);
+        void       (WINE_GLAPI *p_glVertex4s)(GLshort,GLshort,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glVertex4sv)(const GLshort*);
+        void       (WINE_GLAPI *p_glVertexPointer)(GLint,GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glViewport)(GLint,GLint,GLsizei,GLsizei);
+    } gl;
+
+    struct
+    {
+        void       (WINE_GLAPI *p_glActiveProgramEXT)(GLuint);
+        void       (WINE_GLAPI *p_glActiveShaderProgram)(GLuint,GLuint);
+        void       (WINE_GLAPI *p_glActiveStencilFaceEXT)(GLenum);
+        void       (WINE_GLAPI *p_glActiveTexture)(GLenum);
+        void       (WINE_GLAPI *p_glActiveTextureARB)(GLenum);
+        void       (WINE_GLAPI *p_glActiveVaryingNV)(GLuint,const GLchar*);
+        void       (WINE_GLAPI *p_glAlphaFragmentOp1ATI)(GLenum,GLuint,GLuint,GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glAlphaFragmentOp2ATI)(GLenum,GLuint,GLuint,GLuint,GLuint,GLuint,GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glAlphaFragmentOp3ATI)(GLenum,GLuint,GLuint,GLuint,GLuint,GLuint,GLuint,GLuint,GLuint,GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glApplyTextureEXT)(GLenum);
+        GLboolean  (WINE_GLAPI *p_glAreProgramsResidentNV)(GLsizei,const GLuint*,GLboolean*);
+        GLboolean  (WINE_GLAPI *p_glAreTexturesResidentEXT)(GLsizei,const GLuint*,GLboolean*);
+        void       (WINE_GLAPI *p_glArrayElementEXT)(GLint);
+        void       (WINE_GLAPI *p_glArrayObjectATI)(GLenum,GLint,GLenum,GLsizei,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glAsyncMarkerSGIX)(GLuint);
+        void       (WINE_GLAPI *p_glAttachObjectARB)(GLhandleARB,GLhandleARB);
+        void       (WINE_GLAPI *p_glAttachShader)(GLuint,GLuint);
+        void       (WINE_GLAPI *p_glBeginConditionalRender)(GLuint,GLenum);
+        void       (WINE_GLAPI *p_glBeginConditionalRenderNV)(GLuint,GLenum);
+        void       (WINE_GLAPI *p_glBeginFragmentShaderATI)(void);
+        void       (WINE_GLAPI *p_glBeginOcclusionQueryNV)(GLuint);
+        void       (WINE_GLAPI *p_glBeginPerfMonitorAMD)(GLuint);
+        void       (WINE_GLAPI *p_glBeginQuery)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glBeginQueryARB)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glBeginQueryIndexed)(GLenum,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glBeginTransformFeedback)(GLenum);
+        void       (WINE_GLAPI *p_glBeginTransformFeedbackEXT)(GLenum);
+        void       (WINE_GLAPI *p_glBeginTransformFeedbackNV)(GLenum);
+        void       (WINE_GLAPI *p_glBeginVertexShaderEXT)(void);
+        void       (WINE_GLAPI *p_glBeginVideoCaptureNV)(GLuint);
+        void       (WINE_GLAPI *p_glBindAttribLocation)(GLuint,GLuint,const GLchar*);
+        void       (WINE_GLAPI *p_glBindAttribLocationARB)(GLhandleARB,GLuint,const GLcharARB*);
+        void       (WINE_GLAPI *p_glBindBuffer)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glBindBufferARB)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glBindBufferBase)(GLenum,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glBindBufferBaseEXT)(GLenum,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glBindBufferBaseNV)(GLenum,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glBindBufferOffsetEXT)(GLenum,GLuint,GLuint,GLintptr);
+        void       (WINE_GLAPI *p_glBindBufferOffsetNV)(GLenum,GLuint,GLuint,GLintptr);
+        void       (WINE_GLAPI *p_glBindBufferRange)(GLenum,GLuint,GLuint,GLintptr,GLsizeiptr);
+        void       (WINE_GLAPI *p_glBindBufferRangeEXT)(GLenum,GLuint,GLuint,GLintptr,GLsizeiptr);
+        void       (WINE_GLAPI *p_glBindBufferRangeNV)(GLenum,GLuint,GLuint,GLintptr,GLsizeiptr);
+        void       (WINE_GLAPI *p_glBindFragDataLocation)(GLuint,GLuint,const GLchar*);
+        void       (WINE_GLAPI *p_glBindFragDataLocationEXT)(GLuint,GLuint,const GLchar*);
+        void       (WINE_GLAPI *p_glBindFragDataLocationIndexed)(GLuint,GLuint,GLuint,const GLchar*);
+        void       (WINE_GLAPI *p_glBindFragmentShaderATI)(GLuint);
+        void       (WINE_GLAPI *p_glBindFramebuffer)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glBindFramebufferEXT)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glBindImageTexture)(GLuint,GLuint,GLint,GLboolean,GLint,GLenum,GLenum);
+        void       (WINE_GLAPI *p_glBindImageTextureEXT)(GLuint,GLuint,GLint,GLboolean,GLint,GLenum,GLint);
+        GLuint     (WINE_GLAPI *p_glBindLightParameterEXT)(GLenum,GLenum);
+        GLuint     (WINE_GLAPI *p_glBindMaterialParameterEXT)(GLenum,GLenum);
+        void       (WINE_GLAPI *p_glBindMultiTextureEXT)(GLenum,GLenum,GLuint);
+        GLuint     (WINE_GLAPI *p_glBindParameterEXT)(GLenum);
+        void       (WINE_GLAPI *p_glBindProgramARB)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glBindProgramNV)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glBindProgramPipeline)(GLuint);
+        void       (WINE_GLAPI *p_glBindRenderbuffer)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glBindRenderbufferEXT)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glBindSampler)(GLuint,GLuint);
+        GLuint     (WINE_GLAPI *p_glBindTexGenParameterEXT)(GLenum,GLenum,GLenum);
+        void       (WINE_GLAPI *p_glBindTextureEXT)(GLenum,GLuint);
+        GLuint     (WINE_GLAPI *p_glBindTextureUnitParameterEXT)(GLenum,GLenum);
+        void       (WINE_GLAPI *p_glBindTransformFeedback)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glBindTransformFeedbackNV)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glBindVertexArray)(GLuint);
+        void       (WINE_GLAPI *p_glBindVertexArrayAPPLE)(GLuint);
+        void       (WINE_GLAPI *p_glBindVertexBuffer)(GLuint,GLuint,GLintptr,GLsizei);
+        void       (WINE_GLAPI *p_glBindVertexShaderEXT)(GLuint);
+        void       (WINE_GLAPI *p_glBindVideoCaptureStreamBufferNV)(GLuint,GLuint,GLenum,GLintptrARB);
+        void       (WINE_GLAPI *p_glBindVideoCaptureStreamTextureNV)(GLuint,GLuint,GLenum,GLenum,GLuint);
+        void       (WINE_GLAPI *p_glBinormal3bEXT)(GLbyte,GLbyte,GLbyte);
+        void       (WINE_GLAPI *p_glBinormal3bvEXT)(const GLbyte*);
+        void       (WINE_GLAPI *p_glBinormal3dEXT)(GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glBinormal3dvEXT)(const GLdouble*);
+        void       (WINE_GLAPI *p_glBinormal3fEXT)(GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glBinormal3fvEXT)(const GLfloat*);
+        void       (WINE_GLAPI *p_glBinormal3iEXT)(GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glBinormal3ivEXT)(const GLint*);
+        void       (WINE_GLAPI *p_glBinormal3sEXT)(GLshort,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glBinormal3svEXT)(const GLshort*);
+        void       (WINE_GLAPI *p_glBinormalPointerEXT)(GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glBlendColor)(GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glBlendColorEXT)(GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glBlendEquation)(GLenum);
+        void       (WINE_GLAPI *p_glBlendEquationEXT)(GLenum);
+        void       (WINE_GLAPI *p_glBlendEquationIndexedAMD)(GLuint,GLenum);
+        void       (WINE_GLAPI *p_glBlendEquationSeparate)(GLenum,GLenum);
+        void       (WINE_GLAPI *p_glBlendEquationSeparateEXT)(GLenum,GLenum);
+        void       (WINE_GLAPI *p_glBlendEquationSeparateIndexedAMD)(GLuint,GLenum,GLenum);
+        void       (WINE_GLAPI *p_glBlendEquationSeparatei)(GLuint,GLenum,GLenum);
+        void       (WINE_GLAPI *p_glBlendEquationSeparateiARB)(GLuint,GLenum,GLenum);
+        void       (WINE_GLAPI *p_glBlendEquationi)(GLuint,GLenum);
+        void       (WINE_GLAPI *p_glBlendEquationiARB)(GLuint,GLenum);
+        void       (WINE_GLAPI *p_glBlendFuncIndexedAMD)(GLuint,GLenum,GLenum);
+        void       (WINE_GLAPI *p_glBlendFuncSeparate)(GLenum,GLenum,GLenum,GLenum);
+        void       (WINE_GLAPI *p_glBlendFuncSeparateEXT)(GLenum,GLenum,GLenum,GLenum);
+        void       (WINE_GLAPI *p_glBlendFuncSeparateINGR)(GLenum,GLenum,GLenum,GLenum);
+        void       (WINE_GLAPI *p_glBlendFuncSeparateIndexedAMD)(GLuint,GLenum,GLenum,GLenum,GLenum);
+        void       (WINE_GLAPI *p_glBlendFuncSeparatei)(GLuint,GLenum,GLenum,GLenum,GLenum);
+        void       (WINE_GLAPI *p_glBlendFuncSeparateiARB)(GLuint,GLenum,GLenum,GLenum,GLenum);
+        void       (WINE_GLAPI *p_glBlendFunci)(GLuint,GLenum,GLenum);
+        void       (WINE_GLAPI *p_glBlendFunciARB)(GLuint,GLenum,GLenum);
+        void       (WINE_GLAPI *p_glBlitFramebuffer)(GLint,GLint,GLint,GLint,GLint,GLint,GLint,GLint,GLbitfield,GLenum);
+        void       (WINE_GLAPI *p_glBlitFramebufferEXT)(GLint,GLint,GLint,GLint,GLint,GLint,GLint,GLint,GLbitfield,GLenum);
+        void       (WINE_GLAPI *p_glBufferAddressRangeNV)(GLenum,GLuint,UINT64,GLsizeiptr);
+        void       (WINE_GLAPI *p_glBufferData)(GLenum,GLsizeiptr,const GLvoid*,GLenum);
+        void       (WINE_GLAPI *p_glBufferDataARB)(GLenum,GLsizeiptrARB,const GLvoid*,GLenum);
+        void       (WINE_GLAPI *p_glBufferParameteriAPPLE)(GLenum,GLenum,GLint);
+        GLuint     (WINE_GLAPI *p_glBufferRegionEnabled)(void);
+        void       (WINE_GLAPI *p_glBufferSubData)(GLenum,GLintptr,GLsizeiptr,const GLvoid*);
+        void       (WINE_GLAPI *p_glBufferSubDataARB)(GLenum,GLintptrARB,GLsizeiptrARB,const GLvoid*);
+        GLenum     (WINE_GLAPI *p_glCheckFramebufferStatus)(GLenum);
+        GLenum     (WINE_GLAPI *p_glCheckFramebufferStatusEXT)(GLenum);
+        GLenum     (WINE_GLAPI *p_glCheckNamedFramebufferStatusEXT)(GLuint,GLenum);
+        void       (WINE_GLAPI *p_glClampColor)(GLenum,GLenum);
+        void       (WINE_GLAPI *p_glClampColorARB)(GLenum,GLenum);
+        void       (WINE_GLAPI *p_glClearBufferData)(GLenum,GLenum,GLenum,GLenum,const void*);
+        void       (WINE_GLAPI *p_glClearBufferSubData)(GLenum,GLenum,GLintptr,GLsizeiptr,GLenum,GLenum,const void*);
+        void       (WINE_GLAPI *p_glClearBufferfi)(GLenum,GLint,GLfloat,GLint);
+        void       (WINE_GLAPI *p_glClearBufferfv)(GLenum,GLint,const GLfloat*);
+        void       (WINE_GLAPI *p_glClearBufferiv)(GLenum,GLint,const GLint*);
+        void       (WINE_GLAPI *p_glClearBufferuiv)(GLenum,GLint,const GLuint*);
+        void       (WINE_GLAPI *p_glClearColorIiEXT)(GLint,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glClearColorIuiEXT)(GLuint,GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glClearDepthdNV)(GLdouble);
+        void       (WINE_GLAPI *p_glClearDepthf)(GLfloat);
+        void       (WINE_GLAPI *p_glClearNamedBufferDataEXT)(GLuint,GLenum,GLenum,GLenum,const void*);
+        void       (WINE_GLAPI *p_glClearNamedBufferSubDataEXT)(GLuint,GLenum,GLenum,GLenum,GLsizeiptr,GLsizeiptr,const void*);
+        void       (WINE_GLAPI *p_glClientActiveTexture)(GLenum);
+        void       (WINE_GLAPI *p_glClientActiveTextureARB)(GLenum);
+        void       (WINE_GLAPI *p_glClientActiveVertexStreamATI)(GLenum);
+        void       (WINE_GLAPI *p_glClientAttribDefaultEXT)(GLbitfield);
+        GLenum     (WINE_GLAPI *p_glClientWaitSync)(GLvoid*,GLbitfield,UINT64);
+        void       (WINE_GLAPI *p_glColor3fVertex3fSUN)(GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glColor3fVertex3fvSUN)(const GLfloat*,const GLfloat*);
+        void       (WINE_GLAPI *p_glColor3hNV)(GLhalfNV,GLhalfNV,GLhalfNV);
+        void       (WINE_GLAPI *p_glColor3hvNV)(const GLhalfNV*);
+        void       (WINE_GLAPI *p_glColor4fNormal3fVertex3fSUN)(GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glColor4fNormal3fVertex3fvSUN)(const GLfloat*,const GLfloat*,const GLfloat*);
+        void       (WINE_GLAPI *p_glColor4hNV)(GLhalfNV,GLhalfNV,GLhalfNV,GLhalfNV);
+        void       (WINE_GLAPI *p_glColor4hvNV)(const GLhalfNV*);
+        void       (WINE_GLAPI *p_glColor4ubVertex2fSUN)(GLubyte,GLubyte,GLubyte,GLubyte,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glColor4ubVertex2fvSUN)(const GLubyte*,const GLfloat*);
+        void       (WINE_GLAPI *p_glColor4ubVertex3fSUN)(GLubyte,GLubyte,GLubyte,GLubyte,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glColor4ubVertex3fvSUN)(const GLubyte*,const GLfloat*);
+        void       (WINE_GLAPI *p_glColorFormatNV)(GLint,GLenum,GLsizei);
+        void       (WINE_GLAPI *p_glColorFragmentOp1ATI)(GLenum,GLuint,GLuint,GLuint,GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glColorFragmentOp2ATI)(GLenum,GLuint,GLuint,GLuint,GLuint,GLuint,GLuint,GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glColorFragmentOp3ATI)(GLenum,GLuint,GLuint,GLuint,GLuint,GLuint,GLuint,GLuint,GLuint,GLuint,GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glColorMaskIndexedEXT)(GLuint,GLboolean,GLboolean,GLboolean,GLboolean);
+        void       (WINE_GLAPI *p_glColorMaski)(GLuint,GLboolean,GLboolean,GLboolean,GLboolean);
+        void       (WINE_GLAPI *p_glColorP3ui)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glColorP3uiv)(GLenum,const GLuint*);
+        void       (WINE_GLAPI *p_glColorP4ui)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glColorP4uiv)(GLenum,const GLuint*);
+        void       (WINE_GLAPI *p_glColorPointerEXT)(GLint,GLenum,GLsizei,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glColorPointerListIBM)(GLint,GLenum,GLint,const GLvoid**,GLint);
+        void       (WINE_GLAPI *p_glColorPointervINTEL)(GLint,GLenum,const GLvoid**);
+        void       (WINE_GLAPI *p_glColorSubTable)(GLenum,GLsizei,GLsizei,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glColorSubTableEXT)(GLenum,GLsizei,GLsizei,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glColorTable)(GLenum,GLenum,GLsizei,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glColorTableEXT)(GLenum,GLenum,GLsizei,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glColorTableParameterfv)(GLenum,GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glColorTableParameterfvSGI)(GLenum,GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glColorTableParameteriv)(GLenum,GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glColorTableParameterivSGI)(GLenum,GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glColorTableSGI)(GLenum,GLenum,GLsizei,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glCombinerInputNV)(GLenum,GLenum,GLenum,GLenum,GLenum,GLenum);
+        void       (WINE_GLAPI *p_glCombinerOutputNV)(GLenum,GLenum,GLenum,GLenum,GLenum,GLenum,GLenum,GLboolean,GLboolean,GLboolean);
+        void       (WINE_GLAPI *p_glCombinerParameterfNV)(GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glCombinerParameterfvNV)(GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glCombinerParameteriNV)(GLenum,GLint);
+        void       (WINE_GLAPI *p_glCombinerParameterivNV)(GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glCombinerStageParameterfvNV)(GLenum,GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glCompileShader)(GLuint);
+        void       (WINE_GLAPI *p_glCompileShaderARB)(GLhandleARB);
+        void       (WINE_GLAPI *p_glCompileShaderIncludeARB)(GLuint,GLsizei,const GLchar**,const GLint*);
+        void       (WINE_GLAPI *p_glCompressedMultiTexImage1DEXT)(GLenum,GLenum,GLint,GLenum,GLsizei,GLint,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glCompressedMultiTexImage2DEXT)(GLenum,GLenum,GLint,GLenum,GLsizei,GLsizei,GLint,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glCompressedMultiTexImage3DEXT)(GLenum,GLenum,GLint,GLenum,GLsizei,GLsizei,GLsizei,GLint,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glCompressedMultiTexSubImage1DEXT)(GLenum,GLenum,GLint,GLint,GLsizei,GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glCompressedMultiTexSubImage2DEXT)(GLenum,GLenum,GLint,GLint,GLint,GLsizei,GLsizei,GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glCompressedMultiTexSubImage3DEXT)(GLenum,GLenum,GLint,GLint,GLint,GLint,GLsizei,GLsizei,GLsizei,GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glCompressedTexImage1D)(GLenum,GLint,GLenum,GLsizei,GLint,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glCompressedTexImage1DARB)(GLenum,GLint,GLenum,GLsizei,GLint,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glCompressedTexImage2D)(GLenum,GLint,GLenum,GLsizei,GLsizei,GLint,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glCompressedTexImage2DARB)(GLenum,GLint,GLenum,GLsizei,GLsizei,GLint,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glCompressedTexImage3D)(GLenum,GLint,GLenum,GLsizei,GLsizei,GLsizei,GLint,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glCompressedTexImage3DARB)(GLenum,GLint,GLenum,GLsizei,GLsizei,GLsizei,GLint,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glCompressedTexSubImage1D)(GLenum,GLint,GLint,GLsizei,GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glCompressedTexSubImage1DARB)(GLenum,GLint,GLint,GLsizei,GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glCompressedTexSubImage2D)(GLenum,GLint,GLint,GLint,GLsizei,GLsizei,GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glCompressedTexSubImage2DARB)(GLenum,GLint,GLint,GLint,GLsizei,GLsizei,GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glCompressedTexSubImage3D)(GLenum,GLint,GLint,GLint,GLint,GLsizei,GLsizei,GLsizei,GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glCompressedTexSubImage3DARB)(GLenum,GLint,GLint,GLint,GLint,GLsizei,GLsizei,GLsizei,GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glCompressedTextureImage1DEXT)(GLuint,GLenum,GLint,GLenum,GLsizei,GLint,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glCompressedTextureImage2DEXT)(GLuint,GLenum,GLint,GLenum,GLsizei,GLsizei,GLint,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glCompressedTextureImage3DEXT)(GLuint,GLenum,GLint,GLenum,GLsizei,GLsizei,GLsizei,GLint,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glCompressedTextureSubImage1DEXT)(GLuint,GLenum,GLint,GLint,GLsizei,GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glCompressedTextureSubImage2DEXT)(GLuint,GLenum,GLint,GLint,GLint,GLsizei,GLsizei,GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glCompressedTextureSubImage3DEXT)(GLuint,GLenum,GLint,GLint,GLint,GLint,GLsizei,GLsizei,GLsizei,GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glConvolutionFilter1D)(GLenum,GLenum,GLsizei,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glConvolutionFilter1DEXT)(GLenum,GLenum,GLsizei,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glConvolutionFilter2D)(GLenum,GLenum,GLsizei,GLsizei,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glConvolutionFilter2DEXT)(GLenum,GLenum,GLsizei,GLsizei,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glConvolutionParameterf)(GLenum,GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glConvolutionParameterfEXT)(GLenum,GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glConvolutionParameterfv)(GLenum,GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glConvolutionParameterfvEXT)(GLenum,GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glConvolutionParameteri)(GLenum,GLenum,GLint);
+        void       (WINE_GLAPI *p_glConvolutionParameteriEXT)(GLenum,GLenum,GLint);
+        void       (WINE_GLAPI *p_glConvolutionParameteriv)(GLenum,GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glConvolutionParameterivEXT)(GLenum,GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glCopyBufferSubData)(GLenum,GLenum,GLintptr,GLintptr,GLsizeiptr);
+        void       (WINE_GLAPI *p_glCopyColorSubTable)(GLenum,GLsizei,GLint,GLint,GLsizei);
+        void       (WINE_GLAPI *p_glCopyColorSubTableEXT)(GLenum,GLsizei,GLint,GLint,GLsizei);
+        void       (WINE_GLAPI *p_glCopyColorTable)(GLenum,GLenum,GLint,GLint,GLsizei);
+        void       (WINE_GLAPI *p_glCopyColorTableSGI)(GLenum,GLenum,GLint,GLint,GLsizei);
+        void       (WINE_GLAPI *p_glCopyConvolutionFilter1D)(GLenum,GLenum,GLint,GLint,GLsizei);
+        void       (WINE_GLAPI *p_glCopyConvolutionFilter1DEXT)(GLenum,GLenum,GLint,GLint,GLsizei);
+        void       (WINE_GLAPI *p_glCopyConvolutionFilter2D)(GLenum,GLenum,GLint,GLint,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glCopyConvolutionFilter2DEXT)(GLenum,GLenum,GLint,GLint,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glCopyImageSubData)(GLuint,GLenum,GLint,GLint,GLint,GLint,GLuint,GLenum,GLint,GLint,GLint,GLint,GLsizei,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glCopyImageSubDataNV)(GLuint,GLenum,GLint,GLint,GLint,GLint,GLuint,GLenum,GLint,GLint,GLint,GLint,GLsizei,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glCopyMultiTexImage1DEXT)(GLenum,GLenum,GLint,GLenum,GLint,GLint,GLsizei,GLint);
+        void       (WINE_GLAPI *p_glCopyMultiTexImage2DEXT)(GLenum,GLenum,GLint,GLenum,GLint,GLint,GLsizei,GLsizei,GLint);
+        void       (WINE_GLAPI *p_glCopyMultiTexSubImage1DEXT)(GLenum,GLenum,GLint,GLint,GLint,GLint,GLsizei);
+        void       (WINE_GLAPI *p_glCopyMultiTexSubImage2DEXT)(GLenum,GLenum,GLint,GLint,GLint,GLint,GLint,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glCopyMultiTexSubImage3DEXT)(GLenum,GLenum,GLint,GLint,GLint,GLint,GLint,GLint,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glCopyPathNV)(GLuint,GLuint);
+        void       (WINE_GLAPI *p_glCopyTexImage1DEXT)(GLenum,GLint,GLenum,GLint,GLint,GLsizei,GLint);
+        void       (WINE_GLAPI *p_glCopyTexImage2DEXT)(GLenum,GLint,GLenum,GLint,GLint,GLsizei,GLsizei,GLint);
+        void       (WINE_GLAPI *p_glCopyTexSubImage1DEXT)(GLenum,GLint,GLint,GLint,GLint,GLsizei);
+        void       (WINE_GLAPI *p_glCopyTexSubImage2DEXT)(GLenum,GLint,GLint,GLint,GLint,GLint,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glCopyTexSubImage3D)(GLenum,GLint,GLint,GLint,GLint,GLint,GLint,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glCopyTexSubImage3DEXT)(GLenum,GLint,GLint,GLint,GLint,GLint,GLint,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glCopyTextureImage1DEXT)(GLuint,GLenum,GLint,GLenum,GLint,GLint,GLsizei,GLint);
+        void       (WINE_GLAPI *p_glCopyTextureImage2DEXT)(GLuint,GLenum,GLint,GLenum,GLint,GLint,GLsizei,GLsizei,GLint);
+        void       (WINE_GLAPI *p_glCopyTextureSubImage1DEXT)(GLuint,GLenum,GLint,GLint,GLint,GLint,GLsizei);
+        void       (WINE_GLAPI *p_glCopyTextureSubImage2DEXT)(GLuint,GLenum,GLint,GLint,GLint,GLint,GLint,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glCopyTextureSubImage3DEXT)(GLuint,GLenum,GLint,GLint,GLint,GLint,GLint,GLint,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glCoverFillPathInstancedNV)(GLsizei,GLenum,const GLvoid*,GLuint,GLenum,GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glCoverFillPathNV)(GLuint,GLenum);
+        void       (WINE_GLAPI *p_glCoverStrokePathInstancedNV)(GLsizei,GLenum,const GLvoid*,GLuint,GLenum,GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glCoverStrokePathNV)(GLuint,GLenum);
+        GLuint     (WINE_GLAPI *p_glCreateProgram)(void);
+        GLhandleARB (WINE_GLAPI *p_glCreateProgramObjectARB)(void);
+        GLuint     (WINE_GLAPI *p_glCreateShader)(GLenum);
+        GLhandleARB (WINE_GLAPI *p_glCreateShaderObjectARB)(GLenum);
+        GLuint     (WINE_GLAPI *p_glCreateShaderProgramEXT)(GLenum,const GLchar*);
+        GLuint     (WINE_GLAPI *p_glCreateShaderProgramv)(GLenum,GLsizei,const GLchar* const*);
+        GLvoid*    (WINE_GLAPI *p_glCreateSyncFromCLeventARB)(void *,void *,GLbitfield);
+        void       (WINE_GLAPI *p_glCullParameterdvEXT)(GLenum,GLdouble*);
+        void       (WINE_GLAPI *p_glCullParameterfvEXT)(GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glCurrentPaletteMatrixARB)(GLint);
+        void       (WINE_GLAPI *p_glDebugMessageCallback)(void *,const void*);
+        void       (WINE_GLAPI *p_glDebugMessageCallbackAMD)(void *,GLvoid*);
+        void       (WINE_GLAPI *p_glDebugMessageCallbackARB)(void *,const GLvoid*);
+        void       (WINE_GLAPI *p_glDebugMessageControl)(GLenum,GLenum,GLenum,GLsizei,const GLuint*,GLboolean);
+        void       (WINE_GLAPI *p_glDebugMessageControlARB)(GLenum,GLenum,GLenum,GLsizei,const GLuint*,GLboolean);
+        void       (WINE_GLAPI *p_glDebugMessageEnableAMD)(GLenum,GLenum,GLsizei,const GLuint*,GLboolean);
+        void       (WINE_GLAPI *p_glDebugMessageInsert)(GLenum,GLenum,GLuint,GLenum,GLsizei,const GLchar*);
+        void       (WINE_GLAPI *p_glDebugMessageInsertAMD)(GLenum,GLenum,GLuint,GLsizei,const GLchar*);
+        void       (WINE_GLAPI *p_glDebugMessageInsertARB)(GLenum,GLenum,GLuint,GLenum,GLsizei,const GLchar*);
+        void       (WINE_GLAPI *p_glDeformSGIX)(GLbitfield);
+        void       (WINE_GLAPI *p_glDeformationMap3dSGIX)(GLenum,GLdouble,GLdouble,GLint,GLint,GLdouble,GLdouble,GLint,GLint,GLdouble,GLdouble,GLint,GLint,const GLdouble*);
+        void       (WINE_GLAPI *p_glDeformationMap3fSGIX)(GLenum,GLfloat,GLfloat,GLint,GLint,GLfloat,GLfloat,GLint,GLint,GLfloat,GLfloat,GLint,GLint,const GLfloat*);
+        void       (WINE_GLAPI *p_glDeleteAsyncMarkersSGIX)(GLuint,GLsizei);
+        void       (WINE_GLAPI *p_glDeleteBufferRegion)(GLenum);
+        void       (WINE_GLAPI *p_glDeleteBuffers)(GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glDeleteBuffersARB)(GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glDeleteFencesAPPLE)(GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glDeleteFencesNV)(GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glDeleteFragmentShaderATI)(GLuint);
+        void       (WINE_GLAPI *p_glDeleteFramebuffers)(GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glDeleteFramebuffersEXT)(GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glDeleteNamedStringARB)(GLint,const GLchar*);
+        void       (WINE_GLAPI *p_glDeleteNamesAMD)(GLenum,GLuint,const GLuint*);
+        void       (WINE_GLAPI *p_glDeleteObjectARB)(GLhandleARB);
+        void       (WINE_GLAPI *p_glDeleteObjectBufferATI)(GLuint);
+        void       (WINE_GLAPI *p_glDeleteOcclusionQueriesNV)(GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glDeletePathsNV)(GLuint,GLsizei);
+        void       (WINE_GLAPI *p_glDeletePerfMonitorsAMD)(GLsizei,GLuint*);
+        void       (WINE_GLAPI *p_glDeleteProgram)(GLuint);
+        void       (WINE_GLAPI *p_glDeleteProgramPipelines)(GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glDeleteProgramsARB)(GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glDeleteProgramsNV)(GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glDeleteQueries)(GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glDeleteQueriesARB)(GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glDeleteRenderbuffers)(GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glDeleteRenderbuffersEXT)(GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glDeleteSamplers)(GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glDeleteShader)(GLuint);
+        void       (WINE_GLAPI *p_glDeleteSync)(GLvoid*);
+        void       (WINE_GLAPI *p_glDeleteTexturesEXT)(GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glDeleteTransformFeedbacks)(GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glDeleteTransformFeedbacksNV)(GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glDeleteVertexArrays)(GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glDeleteVertexArraysAPPLE)(GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glDeleteVertexShaderEXT)(GLuint);
+        void       (WINE_GLAPI *p_glDepthBoundsEXT)(GLclampd,GLclampd);
+        void       (WINE_GLAPI *p_glDepthBoundsdNV)(GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glDepthRangeArrayv)(GLuint,GLsizei,const GLdouble*);
+        void       (WINE_GLAPI *p_glDepthRangeIndexed)(GLuint,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glDepthRangedNV)(GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glDepthRangef)(GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glDetachObjectARB)(GLhandleARB,GLhandleARB);
+        void       (WINE_GLAPI *p_glDetachShader)(GLuint,GLuint);
+        void       (WINE_GLAPI *p_glDetailTexFuncSGIS)(GLenum,GLsizei,const GLfloat*);
+        void       (WINE_GLAPI *p_glDisableClientStateIndexedEXT)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glDisableIndexedEXT)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glDisableVariantClientStateEXT)(GLuint);
+        void       (WINE_GLAPI *p_glDisableVertexAttribAPPLE)(GLuint,GLenum);
+        void       (WINE_GLAPI *p_glDisableVertexAttribArray)(GLuint);
+        void       (WINE_GLAPI *p_glDisableVertexAttribArrayARB)(GLuint);
+        void       (WINE_GLAPI *p_glDisablei)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glDispatchCompute)(GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glDispatchComputeIndirect)(GLintptr);
+        void       (WINE_GLAPI *p_glDrawArraysEXT)(GLenum,GLint,GLsizei);
+        void       (WINE_GLAPI *p_glDrawArraysIndirect)(GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glDrawArraysInstanced)(GLenum,GLint,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glDrawArraysInstancedARB)(GLenum,GLint,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glDrawArraysInstancedBaseInstance)(GLenum,GLint,GLsizei,GLsizei,GLuint);
+        void       (WINE_GLAPI *p_glDrawArraysInstancedEXT)(GLenum,GLint,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glDrawBufferRegion)(GLenum,GLint,GLint,GLsizei,GLsizei,GLint,GLint);
+        void       (WINE_GLAPI *p_glDrawBuffers)(GLsizei,const GLenum*);
+        void       (WINE_GLAPI *p_glDrawBuffersARB)(GLsizei,const GLenum*);
+        void       (WINE_GLAPI *p_glDrawBuffersATI)(GLsizei,const GLenum*);
+        void       (WINE_GLAPI *p_glDrawElementArrayAPPLE)(GLenum,GLint,GLsizei);
+        void       (WINE_GLAPI *p_glDrawElementArrayATI)(GLenum,GLsizei);
+        void       (WINE_GLAPI *p_glDrawElementsBaseVertex)(GLenum,GLsizei,GLenum,const GLvoid*,GLint);
+        void       (WINE_GLAPI *p_glDrawElementsIndirect)(GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glDrawElementsInstanced)(GLenum,GLsizei,GLenum,const GLvoid*,GLsizei);
+        void       (WINE_GLAPI *p_glDrawElementsInstancedARB)(GLenum,GLsizei,GLenum,const GLvoid*,GLsizei);
+        void       (WINE_GLAPI *p_glDrawElementsInstancedBaseInstance)(GLenum,GLsizei,GLenum,const void*,GLsizei,GLuint);
+        void       (WINE_GLAPI *p_glDrawElementsInstancedBaseVertex)(GLenum,GLsizei,GLenum,const GLvoid*,GLsizei,GLint);
+        void       (WINE_GLAPI *p_glDrawElementsInstancedBaseVertexBaseInstance)(GLenum,GLsizei,GLenum,const void*,GLsizei,GLint,GLuint);
+        void       (WINE_GLAPI *p_glDrawElementsInstancedEXT)(GLenum,GLsizei,GLenum,const GLvoid*,GLsizei);
+        void       (WINE_GLAPI *p_glDrawMeshArraysSUN)(GLenum,GLint,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glDrawRangeElementArrayAPPLE)(GLenum,GLuint,GLuint,GLint,GLsizei);
+        void       (WINE_GLAPI *p_glDrawRangeElementArrayATI)(GLenum,GLuint,GLuint,GLsizei);
+        void       (WINE_GLAPI *p_glDrawRangeElements)(GLenum,GLuint,GLuint,GLsizei,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glDrawRangeElementsBaseVertex)(GLenum,GLuint,GLuint,GLsizei,GLenum,const GLvoid*,GLint);
+        void       (WINE_GLAPI *p_glDrawRangeElementsEXT)(GLenum,GLuint,GLuint,GLsizei,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glDrawTransformFeedback)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glDrawTransformFeedbackInstanced)(GLenum,GLuint,GLsizei);
+        void       (WINE_GLAPI *p_glDrawTransformFeedbackNV)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glDrawTransformFeedbackStream)(GLenum,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glDrawTransformFeedbackStreamInstanced)(GLenum,GLuint,GLuint,GLsizei);
+        void       (WINE_GLAPI *p_glEdgeFlagFormatNV)(GLsizei);
+        void       (WINE_GLAPI *p_glEdgeFlagPointerEXT)(GLsizei,GLsizei,const GLboolean*);
+        void       (WINE_GLAPI *p_glEdgeFlagPointerListIBM)(GLint,const GLboolean**,GLint);
+        void       (WINE_GLAPI *p_glElementPointerAPPLE)(GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glElementPointerATI)(GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glEnableClientStateIndexedEXT)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glEnableIndexedEXT)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glEnableVariantClientStateEXT)(GLuint);
+        void       (WINE_GLAPI *p_glEnableVertexAttribAPPLE)(GLuint,GLenum);
+        void       (WINE_GLAPI *p_glEnableVertexAttribArray)(GLuint);
+        void       (WINE_GLAPI *p_glEnableVertexAttribArrayARB)(GLuint);
+        void       (WINE_GLAPI *p_glEnablei)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glEndConditionalRender)(void);
+        void       (WINE_GLAPI *p_glEndConditionalRenderNV)(void);
+        void       (WINE_GLAPI *p_glEndFragmentShaderATI)(void);
+        void       (WINE_GLAPI *p_glEndOcclusionQueryNV)(void);
+        void       (WINE_GLAPI *p_glEndPerfMonitorAMD)(GLuint);
+        void       (WINE_GLAPI *p_glEndQuery)(GLenum);
+        void       (WINE_GLAPI *p_glEndQueryARB)(GLenum);
+        void       (WINE_GLAPI *p_glEndQueryIndexed)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glEndTransformFeedback)(void);
+        void       (WINE_GLAPI *p_glEndTransformFeedbackEXT)(void);
+        void       (WINE_GLAPI *p_glEndTransformFeedbackNV)(void);
+        void       (WINE_GLAPI *p_glEndVertexShaderEXT)(void);
+        void       (WINE_GLAPI *p_glEndVideoCaptureNV)(GLuint);
+        void       (WINE_GLAPI *p_glEvalMapsNV)(GLenum,GLenum);
+        void       (WINE_GLAPI *p_glExecuteProgramNV)(GLenum,GLuint,const GLfloat*);
+        void       (WINE_GLAPI *p_glExtractComponentEXT)(GLuint,GLuint,GLuint);
+        GLvoid*    (WINE_GLAPI *p_glFenceSync)(GLenum,GLbitfield);
+        void       (WINE_GLAPI *p_glFinalCombinerInputNV)(GLenum,GLenum,GLenum,GLenum);
+        GLint      (WINE_GLAPI *p_glFinishAsyncSGIX)(GLuint*);
+        void       (WINE_GLAPI *p_glFinishFenceAPPLE)(GLuint);
+        void       (WINE_GLAPI *p_glFinishFenceNV)(GLuint);
+        void       (WINE_GLAPI *p_glFinishObjectAPPLE)(GLenum,GLint);
+        void       (WINE_GLAPI *p_glFinishTextureSUNX)(void);
+        void       (WINE_GLAPI *p_glFlushMappedBufferRange)(GLenum,GLintptr,GLsizeiptr);
+        void       (WINE_GLAPI *p_glFlushMappedBufferRangeAPPLE)(GLenum,GLintptr,GLsizeiptr);
+        void       (WINE_GLAPI *p_glFlushMappedNamedBufferRangeEXT)(GLuint,GLintptr,GLsizeiptr);
+        void       (WINE_GLAPI *p_glFlushPixelDataRangeNV)(GLenum);
+        void       (WINE_GLAPI *p_glFlushRasterSGIX)(void);
+        void       (WINE_GLAPI *p_glFlushVertexArrayRangeAPPLE)(GLsizei,GLvoid*);
+        void       (WINE_GLAPI *p_glFlushVertexArrayRangeNV)(void);
+        void       (WINE_GLAPI *p_glFogCoordFormatNV)(GLenum,GLsizei);
+        void       (WINE_GLAPI *p_glFogCoordPointer)(GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glFogCoordPointerEXT)(GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glFogCoordPointerListIBM)(GLenum,GLint,const GLvoid**,GLint);
+        void       (WINE_GLAPI *p_glFogCoordd)(GLdouble);
+        void       (WINE_GLAPI *p_glFogCoorddEXT)(GLdouble);
+        void       (WINE_GLAPI *p_glFogCoorddv)(const GLdouble*);
+        void       (WINE_GLAPI *p_glFogCoorddvEXT)(const GLdouble*);
+        void       (WINE_GLAPI *p_glFogCoordf)(GLfloat);
+        void       (WINE_GLAPI *p_glFogCoordfEXT)(GLfloat);
+        void       (WINE_GLAPI *p_glFogCoordfv)(const GLfloat*);
+        void       (WINE_GLAPI *p_glFogCoordfvEXT)(const GLfloat*);
+        void       (WINE_GLAPI *p_glFogCoordhNV)(GLhalfNV);
+        void       (WINE_GLAPI *p_glFogCoordhvNV)(const GLhalfNV*);
+        void       (WINE_GLAPI *p_glFogFuncSGIS)(GLsizei,const GLfloat*);
+        void       (WINE_GLAPI *p_glFragmentColorMaterialSGIX)(GLenum,GLenum);
+        void       (WINE_GLAPI *p_glFragmentLightModelfSGIX)(GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glFragmentLightModelfvSGIX)(GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glFragmentLightModeliSGIX)(GLenum,GLint);
+        void       (WINE_GLAPI *p_glFragmentLightModelivSGIX)(GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glFragmentLightfSGIX)(GLenum,GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glFragmentLightfvSGIX)(GLenum,GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glFragmentLightiSGIX)(GLenum,GLenum,GLint);
+        void       (WINE_GLAPI *p_glFragmentLightivSGIX)(GLenum,GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glFragmentMaterialfSGIX)(GLenum,GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glFragmentMaterialfvSGIX)(GLenum,GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glFragmentMaterialiSGIX)(GLenum,GLenum,GLint);
+        void       (WINE_GLAPI *p_glFragmentMaterialivSGIX)(GLenum,GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glFrameTerminatorGREMEDY)(void);
+        void       (WINE_GLAPI *p_glFrameZoomSGIX)(GLint);
+        void       (WINE_GLAPI *p_glFramebufferDrawBufferEXT)(GLuint,GLenum);
+        void       (WINE_GLAPI *p_glFramebufferDrawBuffersEXT)(GLuint,GLsizei,const GLenum*);
+        void       (WINE_GLAPI *p_glFramebufferParameteri)(GLenum,GLenum,GLint);
+        void       (WINE_GLAPI *p_glFramebufferReadBufferEXT)(GLuint,GLenum);
+        void       (WINE_GLAPI *p_glFramebufferRenderbuffer)(GLenum,GLenum,GLenum,GLuint);
+        void       (WINE_GLAPI *p_glFramebufferRenderbufferEXT)(GLenum,GLenum,GLenum,GLuint);
+        void       (WINE_GLAPI *p_glFramebufferTexture)(GLenum,GLenum,GLuint,GLint);
+        void       (WINE_GLAPI *p_glFramebufferTexture1D)(GLenum,GLenum,GLenum,GLuint,GLint);
+        void       (WINE_GLAPI *p_glFramebufferTexture1DEXT)(GLenum,GLenum,GLenum,GLuint,GLint);
+        void       (WINE_GLAPI *p_glFramebufferTexture2D)(GLenum,GLenum,GLenum,GLuint,GLint);
+        void       (WINE_GLAPI *p_glFramebufferTexture2DEXT)(GLenum,GLenum,GLenum,GLuint,GLint);
+        void       (WINE_GLAPI *p_glFramebufferTexture3D)(GLenum,GLenum,GLenum,GLuint,GLint,GLint);
+        void       (WINE_GLAPI *p_glFramebufferTexture3DEXT)(GLenum,GLenum,GLenum,GLuint,GLint,GLint);
+        void       (WINE_GLAPI *p_glFramebufferTextureARB)(GLenum,GLenum,GLuint,GLint);
+        void       (WINE_GLAPI *p_glFramebufferTextureEXT)(GLenum,GLenum,GLuint,GLint);
+        void       (WINE_GLAPI *p_glFramebufferTextureFaceARB)(GLenum,GLenum,GLuint,GLint,GLenum);
+        void       (WINE_GLAPI *p_glFramebufferTextureFaceEXT)(GLenum,GLenum,GLuint,GLint,GLenum);
+        void       (WINE_GLAPI *p_glFramebufferTextureLayer)(GLenum,GLenum,GLuint,GLint,GLint);
+        void       (WINE_GLAPI *p_glFramebufferTextureLayerARB)(GLenum,GLenum,GLuint,GLint,GLint);
+        void       (WINE_GLAPI *p_glFramebufferTextureLayerEXT)(GLenum,GLenum,GLuint,GLint,GLint);
+        void       (WINE_GLAPI *p_glFreeObjectBufferATI)(GLuint);
+        GLuint     (WINE_GLAPI *p_glGenAsyncMarkersSGIX)(GLsizei);
+        void       (WINE_GLAPI *p_glGenBuffers)(GLsizei,GLuint*);
+        void       (WINE_GLAPI *p_glGenBuffersARB)(GLsizei,GLuint*);
+        void       (WINE_GLAPI *p_glGenFencesAPPLE)(GLsizei,GLuint*);
+        void       (WINE_GLAPI *p_glGenFencesNV)(GLsizei,GLuint*);
+        GLuint     (WINE_GLAPI *p_glGenFragmentShadersATI)(GLuint);
+        void       (WINE_GLAPI *p_glGenFramebuffers)(GLsizei,GLuint*);
+        void       (WINE_GLAPI *p_glGenFramebuffersEXT)(GLsizei,GLuint*);
+        void       (WINE_GLAPI *p_glGenNamesAMD)(GLenum,GLuint,GLuint*);
+        void       (WINE_GLAPI *p_glGenOcclusionQueriesNV)(GLsizei,GLuint*);
+        GLuint     (WINE_GLAPI *p_glGenPathsNV)(GLsizei);
+        void       (WINE_GLAPI *p_glGenPerfMonitorsAMD)(GLsizei,GLuint*);
+        void       (WINE_GLAPI *p_glGenProgramPipelines)(GLsizei,GLuint*);
+        void       (WINE_GLAPI *p_glGenProgramsARB)(GLsizei,GLuint*);
+        void       (WINE_GLAPI *p_glGenProgramsNV)(GLsizei,GLuint*);
+        void       (WINE_GLAPI *p_glGenQueries)(GLsizei,GLuint*);
+        void       (WINE_GLAPI *p_glGenQueriesARB)(GLsizei,GLuint*);
+        void       (WINE_GLAPI *p_glGenRenderbuffers)(GLsizei,GLuint*);
+        void       (WINE_GLAPI *p_glGenRenderbuffersEXT)(GLsizei,GLuint*);
+        void       (WINE_GLAPI *p_glGenSamplers)(GLsizei,GLuint*);
+        GLuint     (WINE_GLAPI *p_glGenSymbolsEXT)(GLenum,GLenum,GLenum,GLuint);
+        void       (WINE_GLAPI *p_glGenTexturesEXT)(GLsizei,GLuint*);
+        void       (WINE_GLAPI *p_glGenTransformFeedbacks)(GLsizei,GLuint*);
+        void       (WINE_GLAPI *p_glGenTransformFeedbacksNV)(GLsizei,GLuint*);
+        void       (WINE_GLAPI *p_glGenVertexArrays)(GLsizei,GLuint*);
+        void       (WINE_GLAPI *p_glGenVertexArraysAPPLE)(GLsizei,GLuint*);
+        GLuint     (WINE_GLAPI *p_glGenVertexShadersEXT)(GLuint);
+        void       (WINE_GLAPI *p_glGenerateMipmap)(GLenum);
+        void       (WINE_GLAPI *p_glGenerateMipmapEXT)(GLenum);
+        void       (WINE_GLAPI *p_glGenerateMultiTexMipmapEXT)(GLenum,GLenum);
+        void       (WINE_GLAPI *p_glGenerateTextureMipmapEXT)(GLuint,GLenum);
+        void       (WINE_GLAPI *p_glGetActiveAtomicCounterBufferiv)(GLuint,GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetActiveAttrib)(GLuint,GLuint,GLsizei,GLsizei*,GLint*,GLenum*,GLchar*);
+        void       (WINE_GLAPI *p_glGetActiveAttribARB)(GLhandleARB,GLuint,GLsizei,GLsizei*,GLint*,GLenum*,GLcharARB*);
+        void       (WINE_GLAPI *p_glGetActiveSubroutineName)(GLuint,GLenum,GLuint,GLsizei,GLsizei*,GLchar*);
+        void       (WINE_GLAPI *p_glGetActiveSubroutineUniformName)(GLuint,GLenum,GLuint,GLsizei,GLsizei*,GLchar*);
+        void       (WINE_GLAPI *p_glGetActiveSubroutineUniformiv)(GLuint,GLenum,GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetActiveUniform)(GLuint,GLuint,GLsizei,GLsizei*,GLint*,GLenum*,GLchar*);
+        void       (WINE_GLAPI *p_glGetActiveUniformARB)(GLhandleARB,GLuint,GLsizei,GLsizei*,GLint*,GLenum*,GLcharARB*);
+        void       (WINE_GLAPI *p_glGetActiveUniformBlockName)(GLuint,GLuint,GLsizei,GLsizei*,GLchar*);
+        void       (WINE_GLAPI *p_glGetActiveUniformBlockiv)(GLuint,GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetActiveUniformName)(GLuint,GLuint,GLsizei,GLsizei*,GLchar*);
+        void       (WINE_GLAPI *p_glGetActiveUniformsiv)(GLuint,GLsizei,const GLuint*,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetActiveVaryingNV)(GLuint,GLuint,GLsizei,GLsizei*,GLsizei*,GLenum*,GLchar*);
+        void       (WINE_GLAPI *p_glGetArrayObjectfvATI)(GLenum,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetArrayObjectivATI)(GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetAttachedObjectsARB)(GLhandleARB,GLsizei,GLsizei*,GLhandleARB*);
+        void       (WINE_GLAPI *p_glGetAttachedShaders)(GLuint,GLsizei,GLsizei*,GLuint*);
+        GLint      (WINE_GLAPI *p_glGetAttribLocation)(GLuint,const GLchar*);
+        GLint      (WINE_GLAPI *p_glGetAttribLocationARB)(GLhandleARB,const GLcharARB*);
+        void       (WINE_GLAPI *p_glGetBooleanIndexedvEXT)(GLenum,GLuint,GLboolean*);
+        void       (WINE_GLAPI *p_glGetBooleani_v)(GLenum,GLuint,GLboolean*);
+        void       (WINE_GLAPI *p_glGetBufferParameteri64v)(GLenum,GLenum,INT64*);
+        void       (WINE_GLAPI *p_glGetBufferParameteriv)(GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetBufferParameterivARB)(GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetBufferParameterui64vNV)(GLenum,GLenum,UINT64*);
+        void       (WINE_GLAPI *p_glGetBufferPointerv)(GLenum,GLenum,GLvoid**);
+        void       (WINE_GLAPI *p_glGetBufferPointervARB)(GLenum,GLenum,GLvoid**);
+        void       (WINE_GLAPI *p_glGetBufferSubData)(GLenum,GLintptr,GLsizeiptr,GLvoid*);
+        void       (WINE_GLAPI *p_glGetBufferSubDataARB)(GLenum,GLintptrARB,GLsizeiptrARB,GLvoid*);
+        void       (WINE_GLAPI *p_glGetColorTable)(GLenum,GLenum,GLenum,GLvoid*);
+        void       (WINE_GLAPI *p_glGetColorTableEXT)(GLenum,GLenum,GLenum,GLvoid*);
+        void       (WINE_GLAPI *p_glGetColorTableParameterfv)(GLenum,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetColorTableParameterfvEXT)(GLenum,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetColorTableParameterfvSGI)(GLenum,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetColorTableParameteriv)(GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetColorTableParameterivEXT)(GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetColorTableParameterivSGI)(GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetColorTableSGI)(GLenum,GLenum,GLenum,GLvoid*);
+        void       (WINE_GLAPI *p_glGetCombinerInputParameterfvNV)(GLenum,GLenum,GLenum,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetCombinerInputParameterivNV)(GLenum,GLenum,GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetCombinerOutputParameterfvNV)(GLenum,GLenum,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetCombinerOutputParameterivNV)(GLenum,GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetCombinerStageParameterfvNV)(GLenum,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetCompressedMultiTexImageEXT)(GLenum,GLenum,GLint,GLvoid*);
+        void       (WINE_GLAPI *p_glGetCompressedTexImage)(GLenum,GLint,GLvoid*);
+        void       (WINE_GLAPI *p_glGetCompressedTexImageARB)(GLenum,GLint,GLvoid*);
+        void       (WINE_GLAPI *p_glGetCompressedTextureImageEXT)(GLuint,GLenum,GLint,GLvoid*);
+        void       (WINE_GLAPI *p_glGetConvolutionFilter)(GLenum,GLenum,GLenum,GLvoid*);
+        void       (WINE_GLAPI *p_glGetConvolutionFilterEXT)(GLenum,GLenum,GLenum,GLvoid*);
+        void       (WINE_GLAPI *p_glGetConvolutionParameterfv)(GLenum,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetConvolutionParameterfvEXT)(GLenum,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetConvolutionParameteriv)(GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetConvolutionParameterivEXT)(GLenum,GLenum,GLint*);
+        GLuint     (WINE_GLAPI *p_glGetDebugMessageLog)(GLuint,GLsizei,GLenum*,GLenum*,GLuint*,GLenum*,GLsizei*,GLchar*);
+        GLuint     (WINE_GLAPI *p_glGetDebugMessageLogAMD)(GLuint,GLsizei,GLenum*,GLuint*,GLuint*,GLsizei*,GLchar*);
+        GLuint     (WINE_GLAPI *p_glGetDebugMessageLogARB)(GLuint,GLsizei,GLenum*,GLenum*,GLuint*,GLenum*,GLsizei*,GLchar*);
+        void       (WINE_GLAPI *p_glGetDetailTexFuncSGIS)(GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetDoubleIndexedvEXT)(GLenum,GLuint,GLdouble*);
+        void       (WINE_GLAPI *p_glGetDoublei_v)(GLenum,GLuint,GLdouble*);
+        void       (WINE_GLAPI *p_glGetFenceivNV)(GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetFinalCombinerInputParameterfvNV)(GLenum,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetFinalCombinerInputParameterivNV)(GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetFloatIndexedvEXT)(GLenum,GLuint,GLfloat*);
+        void       (WINE_GLAPI *p_glGetFloati_v)(GLenum,GLuint,GLfloat*);
+        void       (WINE_GLAPI *p_glGetFogFuncSGIS)(GLfloat*);
+        GLint      (WINE_GLAPI *p_glGetFragDataIndex)(GLuint,const GLchar*);
+        GLint      (WINE_GLAPI *p_glGetFragDataLocation)(GLuint,const GLchar*);
+        GLint      (WINE_GLAPI *p_glGetFragDataLocationEXT)(GLuint,const GLchar*);
+        void       (WINE_GLAPI *p_glGetFragmentLightfvSGIX)(GLenum,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetFragmentLightivSGIX)(GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetFragmentMaterialfvSGIX)(GLenum,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetFragmentMaterialivSGIX)(GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetFramebufferAttachmentParameteriv)(GLenum,GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetFramebufferAttachmentParameterivEXT)(GLenum,GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetFramebufferParameteriv)(GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetFramebufferParameterivEXT)(GLuint,GLenum,GLint*);
+        GLenum     (WINE_GLAPI *p_glGetGraphicsResetStatusARB)(void);
+        GLhandleARB (WINE_GLAPI *p_glGetHandleARB)(GLenum);
+        void       (WINE_GLAPI *p_glGetHistogram)(GLenum,GLboolean,GLenum,GLenum,GLvoid*);
+        void       (WINE_GLAPI *p_glGetHistogramEXT)(GLenum,GLboolean,GLenum,GLenum,GLvoid*);
+        void       (WINE_GLAPI *p_glGetHistogramParameterfv)(GLenum,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetHistogramParameterfvEXT)(GLenum,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetHistogramParameteriv)(GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetHistogramParameterivEXT)(GLenum,GLenum,GLint*);
+        UINT64     (WINE_GLAPI *p_glGetImageHandleNV)(GLuint,GLint,GLboolean,GLint,GLenum);
+        void       (WINE_GLAPI *p_glGetImageTransformParameterfvHP)(GLenum,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetImageTransformParameterivHP)(GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetInfoLogARB)(GLhandleARB,GLsizei,GLsizei*,GLcharARB*);
+        GLint      (WINE_GLAPI *p_glGetInstrumentsSGIX)(void);
+        void       (WINE_GLAPI *p_glGetInteger64i_v)(GLenum,GLuint,INT64*);
+        void       (WINE_GLAPI *p_glGetInteger64v)(GLenum,INT64*);
+        void       (WINE_GLAPI *p_glGetIntegerIndexedvEXT)(GLenum,GLuint,GLint*);
+        void       (WINE_GLAPI *p_glGetIntegeri_v)(GLenum,GLuint,GLint*);
+        void       (WINE_GLAPI *p_glGetIntegerui64i_vNV)(GLenum,GLuint,UINT64*);
+        void       (WINE_GLAPI *p_glGetIntegerui64vNV)(GLenum,UINT64*);
+        void       (WINE_GLAPI *p_glGetInternalformati64v)(GLenum,GLenum,GLenum,GLsizei,INT64*);
+        void       (WINE_GLAPI *p_glGetInternalformativ)(GLenum,GLenum,GLenum,GLsizei,GLint*);
+        void       (WINE_GLAPI *p_glGetInvariantBooleanvEXT)(GLuint,GLenum,GLboolean*);
+        void       (WINE_GLAPI *p_glGetInvariantFloatvEXT)(GLuint,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetInvariantIntegervEXT)(GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetListParameterfvSGIX)(GLuint,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetListParameterivSGIX)(GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetLocalConstantBooleanvEXT)(GLuint,GLenum,GLboolean*);
+        void       (WINE_GLAPI *p_glGetLocalConstantFloatvEXT)(GLuint,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetLocalConstantIntegervEXT)(GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetMapAttribParameterfvNV)(GLenum,GLuint,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetMapAttribParameterivNV)(GLenum,GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetMapControlPointsNV)(GLenum,GLuint,GLenum,GLsizei,GLsizei,GLboolean,GLvoid*);
+        void       (WINE_GLAPI *p_glGetMapParameterfvNV)(GLenum,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetMapParameterivNV)(GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetMinmax)(GLenum,GLboolean,GLenum,GLenum,GLvoid*);
+        void       (WINE_GLAPI *p_glGetMinmaxEXT)(GLenum,GLboolean,GLenum,GLenum,GLvoid*);
+        void       (WINE_GLAPI *p_glGetMinmaxParameterfv)(GLenum,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetMinmaxParameterfvEXT)(GLenum,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetMinmaxParameteriv)(GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetMinmaxParameterivEXT)(GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetMultiTexEnvfvEXT)(GLenum,GLenum,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetMultiTexEnvivEXT)(GLenum,GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetMultiTexGendvEXT)(GLenum,GLenum,GLenum,GLdouble*);
+        void       (WINE_GLAPI *p_glGetMultiTexGenfvEXT)(GLenum,GLenum,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetMultiTexGenivEXT)(GLenum,GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetMultiTexImageEXT)(GLenum,GLenum,GLint,GLenum,GLenum,GLvoid*);
+        void       (WINE_GLAPI *p_glGetMultiTexLevelParameterfvEXT)(GLenum,GLenum,GLint,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetMultiTexLevelParameterivEXT)(GLenum,GLenum,GLint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetMultiTexParameterIivEXT)(GLenum,GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetMultiTexParameterIuivEXT)(GLenum,GLenum,GLenum,GLuint*);
+        void       (WINE_GLAPI *p_glGetMultiTexParameterfvEXT)(GLenum,GLenum,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetMultiTexParameterivEXT)(GLenum,GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetMultisamplefv)(GLenum,GLuint,GLfloat*);
+        void       (WINE_GLAPI *p_glGetMultisamplefvNV)(GLenum,GLuint,GLfloat*);
+        void       (WINE_GLAPI *p_glGetNamedBufferParameterivEXT)(GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetNamedBufferParameterui64vNV)(GLuint,GLenum,UINT64*);
+        void       (WINE_GLAPI *p_glGetNamedBufferPointervEXT)(GLuint,GLenum,GLvoid**);
+        void       (WINE_GLAPI *p_glGetNamedBufferSubDataEXT)(GLuint,GLintptr,GLsizeiptr,GLvoid*);
+        void       (WINE_GLAPI *p_glGetNamedFramebufferAttachmentParameterivEXT)(GLuint,GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetNamedFramebufferParameterivEXT)(GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetNamedProgramLocalParameterIivEXT)(GLuint,GLenum,GLuint,GLint*);
+        void       (WINE_GLAPI *p_glGetNamedProgramLocalParameterIuivEXT)(GLuint,GLenum,GLuint,GLuint*);
+        void       (WINE_GLAPI *p_glGetNamedProgramLocalParameterdvEXT)(GLuint,GLenum,GLuint,GLdouble*);
+        void       (WINE_GLAPI *p_glGetNamedProgramLocalParameterfvEXT)(GLuint,GLenum,GLuint,GLfloat*);
+        void       (WINE_GLAPI *p_glGetNamedProgramStringEXT)(GLuint,GLenum,GLenum,GLvoid*);
+        void       (WINE_GLAPI *p_glGetNamedProgramivEXT)(GLuint,GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetNamedRenderbufferParameterivEXT)(GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetNamedStringARB)(GLint,const GLchar*,GLsizei,GLint*,GLchar*);
+        void       (WINE_GLAPI *p_glGetNamedStringivARB)(GLint,const GLchar*,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetObjectBufferfvATI)(GLuint,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetObjectBufferivATI)(GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetObjectLabel)(GLenum,GLuint,GLsizei,GLsizei*,GLchar*);
+        void       (WINE_GLAPI *p_glGetObjectParameterfvARB)(GLhandleARB,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetObjectParameterivAPPLE)(GLenum,GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetObjectParameterivARB)(GLhandleARB,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetObjectPtrLabel)(const void*,GLsizei,GLsizei*,GLchar*);
+        void       (WINE_GLAPI *p_glGetOcclusionQueryivNV)(GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetOcclusionQueryuivNV)(GLuint,GLenum,GLuint*);
+        void       (WINE_GLAPI *p_glGetPathColorGenfvNV)(GLenum,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetPathColorGenivNV)(GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetPathCommandsNV)(GLuint,GLubyte*);
+        void       (WINE_GLAPI *p_glGetPathCoordsNV)(GLuint,GLfloat*);
+        void       (WINE_GLAPI *p_glGetPathDashArrayNV)(GLuint,GLfloat*);
+        GLfloat    (WINE_GLAPI *p_glGetPathLengthNV)(GLuint,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glGetPathMetricRangeNV)(GLbitfield,GLuint,GLsizei,GLsizei,GLfloat*);
+        void       (WINE_GLAPI *p_glGetPathMetricsNV)(GLbitfield,GLsizei,GLenum,const GLvoid*,GLuint,GLsizei,GLfloat*);
+        void       (WINE_GLAPI *p_glGetPathParameterfvNV)(GLuint,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetPathParameterivNV)(GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetPathSpacingNV)(GLenum,GLsizei,GLenum,const GLvoid*,GLuint,GLfloat,GLfloat,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetPathTexGenfvNV)(GLenum,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetPathTexGenivNV)(GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetPerfMonitorCounterDataAMD)(GLuint,GLenum,GLsizei,GLuint*,GLint*);
+        void       (WINE_GLAPI *p_glGetPerfMonitorCounterInfoAMD)(GLuint,GLuint,GLenum,GLvoid*);
+        void       (WINE_GLAPI *p_glGetPerfMonitorCounterStringAMD)(GLuint,GLuint,GLsizei,GLsizei*,GLchar*);
+        void       (WINE_GLAPI *p_glGetPerfMonitorCountersAMD)(GLuint,GLint*,GLint*,GLsizei,GLuint*);
+        void       (WINE_GLAPI *p_glGetPerfMonitorGroupStringAMD)(GLuint,GLsizei,GLsizei*,GLchar*);
+        void       (WINE_GLAPI *p_glGetPerfMonitorGroupsAMD)(GLint*,GLsizei,GLuint*);
+        void       (WINE_GLAPI *p_glGetPixelTexGenParameterfvSGIS)(GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetPixelTexGenParameterivSGIS)(GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetPixelTransformParameterfvEXT)(GLenum,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetPixelTransformParameterivEXT)(GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetPointerIndexedvEXT)(GLenum,GLuint,GLvoid**);
+        void       (WINE_GLAPI *p_glGetPointervEXT)(GLenum,GLvoid**);
+        void       (WINE_GLAPI *p_glGetProgramBinary)(GLuint,GLsizei,GLsizei*,GLenum*,GLvoid*);
+        void       (WINE_GLAPI *p_glGetProgramEnvParameterIivNV)(GLenum,GLuint,GLint*);
+        void       (WINE_GLAPI *p_glGetProgramEnvParameterIuivNV)(GLenum,GLuint,GLuint*);
+        void       (WINE_GLAPI *p_glGetProgramEnvParameterdvARB)(GLenum,GLuint,GLdouble*);
+        void       (WINE_GLAPI *p_glGetProgramEnvParameterfvARB)(GLenum,GLuint,GLfloat*);
+        void       (WINE_GLAPI *p_glGetProgramInfoLog)(GLuint,GLsizei,GLsizei*,GLchar*);
+        void       (WINE_GLAPI *p_glGetProgramInterfaceiv)(GLuint,GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetProgramLocalParameterIivNV)(GLenum,GLuint,GLint*);
+        void       (WINE_GLAPI *p_glGetProgramLocalParameterIuivNV)(GLenum,GLuint,GLuint*);
+        void       (WINE_GLAPI *p_glGetProgramLocalParameterdvARB)(GLenum,GLuint,GLdouble*);
+        void       (WINE_GLAPI *p_glGetProgramLocalParameterfvARB)(GLenum,GLuint,GLfloat*);
+        void       (WINE_GLAPI *p_glGetProgramNamedParameterdvNV)(GLuint,GLsizei,const GLubyte*,GLdouble*);
+        void       (WINE_GLAPI *p_glGetProgramNamedParameterfvNV)(GLuint,GLsizei,const GLubyte*,GLfloat*);
+        void       (WINE_GLAPI *p_glGetProgramParameterdvNV)(GLenum,GLuint,GLenum,GLdouble*);
+        void       (WINE_GLAPI *p_glGetProgramParameterfvNV)(GLenum,GLuint,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetProgramPipelineInfoLog)(GLuint,GLsizei,GLsizei*,GLchar*);
+        void       (WINE_GLAPI *p_glGetProgramPipelineiv)(GLuint,GLenum,GLint*);
+        GLuint     (WINE_GLAPI *p_glGetProgramResourceIndex)(GLuint,GLenum,const GLchar*);
+        GLint      (WINE_GLAPI *p_glGetProgramResourceLocation)(GLuint,GLenum,const GLchar*);
+        GLint      (WINE_GLAPI *p_glGetProgramResourceLocationIndex)(GLuint,GLenum,const GLchar*);
+        void       (WINE_GLAPI *p_glGetProgramResourceName)(GLuint,GLenum,GLuint,GLsizei,GLsizei*,GLchar*);
+        void       (WINE_GLAPI *p_glGetProgramResourceiv)(GLuint,GLenum,GLuint,GLsizei,const GLenum*,GLsizei,GLsizei*,GLint*);
+        void       (WINE_GLAPI *p_glGetProgramStageiv)(GLuint,GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetProgramStringARB)(GLenum,GLenum,GLvoid*);
+        void       (WINE_GLAPI *p_glGetProgramStringNV)(GLuint,GLenum,GLubyte*);
+        void       (WINE_GLAPI *p_glGetProgramSubroutineParameteruivNV)(GLenum,GLuint,GLuint*);
+        void       (WINE_GLAPI *p_glGetProgramiv)(GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetProgramivARB)(GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetProgramivNV)(GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetQueryIndexediv)(GLenum,GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetQueryObjecti64v)(GLuint,GLenum,INT64*);
+        void       (WINE_GLAPI *p_glGetQueryObjecti64vEXT)(GLuint,GLenum,INT64*);
+        void       (WINE_GLAPI *p_glGetQueryObjectiv)(GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetQueryObjectivARB)(GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetQueryObjectui64v)(GLuint,GLenum,UINT64*);
+        void       (WINE_GLAPI *p_glGetQueryObjectui64vEXT)(GLuint,GLenum,UINT64*);
+        void       (WINE_GLAPI *p_glGetQueryObjectuiv)(GLuint,GLenum,GLuint*);
+        void       (WINE_GLAPI *p_glGetQueryObjectuivARB)(GLuint,GLenum,GLuint*);
+        void       (WINE_GLAPI *p_glGetQueryiv)(GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetQueryivARB)(GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetRenderbufferParameteriv)(GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetRenderbufferParameterivEXT)(GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetSamplerParameterIiv)(GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetSamplerParameterIuiv)(GLuint,GLenum,GLuint*);
+        void       (WINE_GLAPI *p_glGetSamplerParameterfv)(GLuint,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetSamplerParameteriv)(GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetSeparableFilter)(GLenum,GLenum,GLenum,GLvoid*,GLvoid*,GLvoid*);
+        void       (WINE_GLAPI *p_glGetSeparableFilterEXT)(GLenum,GLenum,GLenum,GLvoid*,GLvoid*,GLvoid*);
+        void       (WINE_GLAPI *p_glGetShaderInfoLog)(GLuint,GLsizei,GLsizei*,GLchar*);
+        void       (WINE_GLAPI *p_glGetShaderPrecisionFormat)(GLenum,GLenum,GLint*,GLint*);
+        void       (WINE_GLAPI *p_glGetShaderSource)(GLuint,GLsizei,GLsizei*,GLchar*);
+        void       (WINE_GLAPI *p_glGetShaderSourceARB)(GLhandleARB,GLsizei,GLsizei*,GLcharARB*);
+        void       (WINE_GLAPI *p_glGetShaderiv)(GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetSharpenTexFuncSGIS)(GLenum,GLfloat*);
+        const GLubyte * (WINE_GLAPI *p_glGetStringi)(GLenum,GLuint);
+        GLuint     (WINE_GLAPI *p_glGetSubroutineIndex)(GLuint,GLenum,const GLchar*);
+        GLint      (WINE_GLAPI *p_glGetSubroutineUniformLocation)(GLuint,GLenum,const GLchar*);
+        void       (WINE_GLAPI *p_glGetSynciv)(GLvoid*,GLenum,GLsizei,GLsizei*,GLint*);
+        void       (WINE_GLAPI *p_glGetTexBumpParameterfvATI)(GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetTexBumpParameterivATI)(GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetTexFilterFuncSGIS)(GLenum,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetTexParameterIiv)(GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetTexParameterIivEXT)(GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetTexParameterIuiv)(GLenum,GLenum,GLuint*);
+        void       (WINE_GLAPI *p_glGetTexParameterIuivEXT)(GLenum,GLenum,GLuint*);
+        void       (WINE_GLAPI *p_glGetTexParameterPointervAPPLE)(GLenum,GLenum,GLvoid**);
+        UINT64     (WINE_GLAPI *p_glGetTextureHandleNV)(GLuint);
+        void       (WINE_GLAPI *p_glGetTextureImageEXT)(GLuint,GLenum,GLint,GLenum,GLenum,GLvoid*);
+        void       (WINE_GLAPI *p_glGetTextureLevelParameterfvEXT)(GLuint,GLenum,GLint,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetTextureLevelParameterivEXT)(GLuint,GLenum,GLint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetTextureParameterIivEXT)(GLuint,GLenum,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetTextureParameterIuivEXT)(GLuint,GLenum,GLenum,GLuint*);
+        void       (WINE_GLAPI *p_glGetTextureParameterfvEXT)(GLuint,GLenum,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetTextureParameterivEXT)(GLuint,GLenum,GLenum,GLint*);
+        UINT64     (WINE_GLAPI *p_glGetTextureSamplerHandleNV)(GLuint,GLuint);
+        void       (WINE_GLAPI *p_glGetTrackMatrixivNV)(GLenum,GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetTransformFeedbackVarying)(GLuint,GLuint,GLsizei,GLsizei*,GLsizei*,GLenum*,GLchar*);
+        void       (WINE_GLAPI *p_glGetTransformFeedbackVaryingEXT)(GLuint,GLuint,GLsizei,GLsizei*,GLsizei*,GLenum*,GLchar*);
+        void       (WINE_GLAPI *p_glGetTransformFeedbackVaryingNV)(GLuint,GLuint,GLint*);
+        GLuint     (WINE_GLAPI *p_glGetUniformBlockIndex)(GLuint,const GLchar*);
+        GLint      (WINE_GLAPI *p_glGetUniformBufferSizeEXT)(GLuint,GLint);
+        void       (WINE_GLAPI *p_glGetUniformIndices)(GLuint,GLsizei,const GLchar* const*,GLuint*);
+        GLint      (WINE_GLAPI *p_glGetUniformLocation)(GLuint,const GLchar*);
+        GLint      (WINE_GLAPI *p_glGetUniformLocationARB)(GLhandleARB,const GLcharARB*);
+        GLintptr   (WINE_GLAPI *p_glGetUniformOffsetEXT)(GLuint,GLint);
+        void       (WINE_GLAPI *p_glGetUniformSubroutineuiv)(GLenum,GLint,GLuint*);
+        void       (WINE_GLAPI *p_glGetUniformdv)(GLuint,GLint,GLdouble*);
+        void       (WINE_GLAPI *p_glGetUniformfv)(GLuint,GLint,GLfloat*);
+        void       (WINE_GLAPI *p_glGetUniformfvARB)(GLhandleARB,GLint,GLfloat*);
+        void       (WINE_GLAPI *p_glGetUniformi64vNV)(GLuint,GLint,INT64*);
+        void       (WINE_GLAPI *p_glGetUniformiv)(GLuint,GLint,GLint*);
+        void       (WINE_GLAPI *p_glGetUniformivARB)(GLhandleARB,GLint,GLint*);
+        void       (WINE_GLAPI *p_glGetUniformui64vNV)(GLuint,GLint,UINT64*);
+        void       (WINE_GLAPI *p_glGetUniformuiv)(GLuint,GLint,GLuint*);
+        void       (WINE_GLAPI *p_glGetUniformuivEXT)(GLuint,GLint,GLuint*);
+        void       (WINE_GLAPI *p_glGetVariantArrayObjectfvATI)(GLuint,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetVariantArrayObjectivATI)(GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetVariantBooleanvEXT)(GLuint,GLenum,GLboolean*);
+        void       (WINE_GLAPI *p_glGetVariantFloatvEXT)(GLuint,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetVariantIntegervEXT)(GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetVariantPointervEXT)(GLuint,GLenum,GLvoid**);
+        GLint      (WINE_GLAPI *p_glGetVaryingLocationNV)(GLuint,const GLchar*);
+        void       (WINE_GLAPI *p_glGetVertexAttribArrayObjectfvATI)(GLuint,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetVertexAttribArrayObjectivATI)(GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetVertexAttribIiv)(GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetVertexAttribIivEXT)(GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetVertexAttribIuiv)(GLuint,GLenum,GLuint*);
+        void       (WINE_GLAPI *p_glGetVertexAttribIuivEXT)(GLuint,GLenum,GLuint*);
+        void       (WINE_GLAPI *p_glGetVertexAttribLdv)(GLuint,GLenum,GLdouble*);
+        void       (WINE_GLAPI *p_glGetVertexAttribLdvEXT)(GLuint,GLenum,GLdouble*);
+        void       (WINE_GLAPI *p_glGetVertexAttribLi64vNV)(GLuint,GLenum,INT64*);
+        void       (WINE_GLAPI *p_glGetVertexAttribLui64vNV)(GLuint,GLenum,UINT64*);
+        void       (WINE_GLAPI *p_glGetVertexAttribPointerv)(GLuint,GLenum,GLvoid**);
+        void       (WINE_GLAPI *p_glGetVertexAttribPointervARB)(GLuint,GLenum,GLvoid**);
+        void       (WINE_GLAPI *p_glGetVertexAttribPointervNV)(GLuint,GLenum,GLvoid**);
+        void       (WINE_GLAPI *p_glGetVertexAttribdv)(GLuint,GLenum,GLdouble*);
+        void       (WINE_GLAPI *p_glGetVertexAttribdvARB)(GLuint,GLenum,GLdouble*);
+        void       (WINE_GLAPI *p_glGetVertexAttribdvNV)(GLuint,GLenum,GLdouble*);
+        void       (WINE_GLAPI *p_glGetVertexAttribfv)(GLuint,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetVertexAttribfvARB)(GLuint,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetVertexAttribfvNV)(GLuint,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetVertexAttribiv)(GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetVertexAttribivARB)(GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetVertexAttribivNV)(GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetVideoCaptureStreamdvNV)(GLuint,GLuint,GLenum,GLdouble*);
+        void       (WINE_GLAPI *p_glGetVideoCaptureStreamfvNV)(GLuint,GLuint,GLenum,GLfloat*);
+        void       (WINE_GLAPI *p_glGetVideoCaptureStreamivNV)(GLuint,GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetVideoCaptureivNV)(GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetVideoi64vNV)(GLuint,GLenum,INT64*);
+        void       (WINE_GLAPI *p_glGetVideoivNV)(GLuint,GLenum,GLint*);
+        void       (WINE_GLAPI *p_glGetVideoui64vNV)(GLuint,GLenum,UINT64*);
+        void       (WINE_GLAPI *p_glGetVideouivNV)(GLuint,GLenum,GLuint*);
+        void       (WINE_GLAPI *p_glGetnColorTableARB)(GLenum,GLenum,GLenum,GLsizei,GLvoid*);
+        void       (WINE_GLAPI *p_glGetnCompressedTexImageARB)(GLenum,GLint,GLsizei,GLvoid*);
+        void       (WINE_GLAPI *p_glGetnConvolutionFilterARB)(GLenum,GLenum,GLenum,GLsizei,GLvoid*);
+        void       (WINE_GLAPI *p_glGetnHistogramARB)(GLenum,GLboolean,GLenum,GLenum,GLsizei,GLvoid*);
+        void       (WINE_GLAPI *p_glGetnMapdvARB)(GLenum,GLenum,GLsizei,GLdouble*);
+        void       (WINE_GLAPI *p_glGetnMapfvARB)(GLenum,GLenum,GLsizei,GLfloat*);
+        void       (WINE_GLAPI *p_glGetnMapivARB)(GLenum,GLenum,GLsizei,GLint*);
+        void       (WINE_GLAPI *p_glGetnMinmaxARB)(GLenum,GLboolean,GLenum,GLenum,GLsizei,GLvoid*);
+        void       (WINE_GLAPI *p_glGetnPixelMapfvARB)(GLenum,GLsizei,GLfloat*);
+        void       (WINE_GLAPI *p_glGetnPixelMapuivARB)(GLenum,GLsizei,GLuint*);
+        void       (WINE_GLAPI *p_glGetnPixelMapusvARB)(GLenum,GLsizei,GLushort*);
+        void       (WINE_GLAPI *p_glGetnPolygonStippleARB)(GLsizei,GLubyte*);
+        void       (WINE_GLAPI *p_glGetnSeparableFilterARB)(GLenum,GLenum,GLenum,GLsizei,GLvoid*,GLsizei,GLvoid*,GLvoid*);
+        void       (WINE_GLAPI *p_glGetnTexImageARB)(GLenum,GLint,GLenum,GLenum,GLsizei,GLvoid*);
+        void       (WINE_GLAPI *p_glGetnUniformdvARB)(GLuint,GLint,GLsizei,GLdouble*);
+        void       (WINE_GLAPI *p_glGetnUniformfvARB)(GLuint,GLint,GLsizei,GLfloat*);
+        void       (WINE_GLAPI *p_glGetnUniformivARB)(GLuint,GLint,GLsizei,GLint*);
+        void       (WINE_GLAPI *p_glGetnUniformuivARB)(GLuint,GLint,GLsizei,GLuint*);
+        void       (WINE_GLAPI *p_glGlobalAlphaFactorbSUN)(GLbyte);
+        void       (WINE_GLAPI *p_glGlobalAlphaFactordSUN)(GLdouble);
+        void       (WINE_GLAPI *p_glGlobalAlphaFactorfSUN)(GLfloat);
+        void       (WINE_GLAPI *p_glGlobalAlphaFactoriSUN)(GLint);
+        void       (WINE_GLAPI *p_glGlobalAlphaFactorsSUN)(GLshort);
+        void       (WINE_GLAPI *p_glGlobalAlphaFactorubSUN)(GLubyte);
+        void       (WINE_GLAPI *p_glGlobalAlphaFactoruiSUN)(GLuint);
+        void       (WINE_GLAPI *p_glGlobalAlphaFactorusSUN)(GLushort);
+        void       (WINE_GLAPI *p_glHintPGI)(GLenum,GLint);
+        void       (WINE_GLAPI *p_glHistogram)(GLenum,GLsizei,GLenum,GLboolean);
+        void       (WINE_GLAPI *p_glHistogramEXT)(GLenum,GLsizei,GLenum,GLboolean);
+        void       (WINE_GLAPI *p_glIglooInterfaceSGIX)(GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glImageTransformParameterfHP)(GLenum,GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glImageTransformParameterfvHP)(GLenum,GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glImageTransformParameteriHP)(GLenum,GLenum,GLint);
+        void       (WINE_GLAPI *p_glImageTransformParameterivHP)(GLenum,GLenum,const GLint*);
+        GLvoid*    (WINE_GLAPI *p_glImportSyncEXT)(GLenum,GLintptr,GLbitfield);
+        void       (WINE_GLAPI *p_glIndexFormatNV)(GLenum,GLsizei);
+        void       (WINE_GLAPI *p_glIndexFuncEXT)(GLenum,GLclampf);
+        void       (WINE_GLAPI *p_glIndexMaterialEXT)(GLenum,GLenum);
+        void       (WINE_GLAPI *p_glIndexPointerEXT)(GLenum,GLsizei,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glIndexPointerListIBM)(GLenum,GLint,const GLvoid**,GLint);
+        void       (WINE_GLAPI *p_glInsertComponentEXT)(GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glInstrumentsBufferSGIX)(GLsizei,GLint*);
+        void       (WINE_GLAPI *p_glInterpolatePathsNV)(GLuint,GLuint,GLuint,GLfloat);
+        void       (WINE_GLAPI *p_glInvalidateBufferData)(GLuint);
+        void       (WINE_GLAPI *p_glInvalidateBufferSubData)(GLuint,GLintptr,GLsizeiptr);
+        void       (WINE_GLAPI *p_glInvalidateFramebuffer)(GLenum,GLsizei,const GLenum*);
+        void       (WINE_GLAPI *p_glInvalidateSubFramebuffer)(GLenum,GLsizei,const GLenum*,GLint,GLint,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glInvalidateTexImage)(GLuint,GLint);
+        void       (WINE_GLAPI *p_glInvalidateTexSubImage)(GLuint,GLint,GLint,GLint,GLint,GLsizei,GLsizei,GLsizei);
+        GLboolean  (WINE_GLAPI *p_glIsAsyncMarkerSGIX)(GLuint);
+        GLboolean  (WINE_GLAPI *p_glIsBuffer)(GLuint);
+        GLboolean  (WINE_GLAPI *p_glIsBufferARB)(GLuint);
+        GLboolean  (WINE_GLAPI *p_glIsBufferResidentNV)(GLenum);
+        GLboolean  (WINE_GLAPI *p_glIsEnabledIndexedEXT)(GLenum,GLuint);
+        GLboolean  (WINE_GLAPI *p_glIsEnabledi)(GLenum,GLuint);
+        GLboolean  (WINE_GLAPI *p_glIsFenceAPPLE)(GLuint);
+        GLboolean  (WINE_GLAPI *p_glIsFenceNV)(GLuint);
+        GLboolean  (WINE_GLAPI *p_glIsFramebuffer)(GLuint);
+        GLboolean  (WINE_GLAPI *p_glIsFramebufferEXT)(GLuint);
+        GLboolean  (WINE_GLAPI *p_glIsImageHandleResidentNV)(UINT64);
+        GLboolean  (WINE_GLAPI *p_glIsNameAMD)(GLenum,GLuint);
+        GLboolean  (WINE_GLAPI *p_glIsNamedBufferResidentNV)(GLuint);
+        GLboolean  (WINE_GLAPI *p_glIsNamedStringARB)(GLint,const GLchar*);
+        GLboolean  (WINE_GLAPI *p_glIsObjectBufferATI)(GLuint);
+        GLboolean  (WINE_GLAPI *p_glIsOcclusionQueryNV)(GLuint);
+        GLboolean  (WINE_GLAPI *p_glIsPathNV)(GLuint);
+        GLboolean  (WINE_GLAPI *p_glIsPointInFillPathNV)(GLuint,GLuint,GLfloat,GLfloat);
+        GLboolean  (WINE_GLAPI *p_glIsPointInStrokePathNV)(GLuint,GLfloat,GLfloat);
+        GLboolean  (WINE_GLAPI *p_glIsProgram)(GLuint);
+        GLboolean  (WINE_GLAPI *p_glIsProgramARB)(GLuint);
+        GLboolean  (WINE_GLAPI *p_glIsProgramNV)(GLuint);
+        GLboolean  (WINE_GLAPI *p_glIsProgramPipeline)(GLuint);
+        GLboolean  (WINE_GLAPI *p_glIsQuery)(GLuint);
+        GLboolean  (WINE_GLAPI *p_glIsQueryARB)(GLuint);
+        GLboolean  (WINE_GLAPI *p_glIsRenderbuffer)(GLuint);
+        GLboolean  (WINE_GLAPI *p_glIsRenderbufferEXT)(GLuint);
+        GLboolean  (WINE_GLAPI *p_glIsSampler)(GLuint);
+        GLboolean  (WINE_GLAPI *p_glIsShader)(GLuint);
+        GLboolean  (WINE_GLAPI *p_glIsSync)(GLvoid*);
+        GLboolean  (WINE_GLAPI *p_glIsTextureEXT)(GLuint);
+        GLboolean  (WINE_GLAPI *p_glIsTextureHandleResidentNV)(UINT64);
+        GLboolean  (WINE_GLAPI *p_glIsTransformFeedback)(GLuint);
+        GLboolean  (WINE_GLAPI *p_glIsTransformFeedbackNV)(GLuint);
+        GLboolean  (WINE_GLAPI *p_glIsVariantEnabledEXT)(GLuint,GLenum);
+        GLboolean  (WINE_GLAPI *p_glIsVertexArray)(GLuint);
+        GLboolean  (WINE_GLAPI *p_glIsVertexArrayAPPLE)(GLuint);
+        GLboolean  (WINE_GLAPI *p_glIsVertexAttribEnabledAPPLE)(GLuint,GLenum);
+        void       (WINE_GLAPI *p_glLightEnviSGIX)(GLenum,GLint);
+        void       (WINE_GLAPI *p_glLinkProgram)(GLuint);
+        void       (WINE_GLAPI *p_glLinkProgramARB)(GLhandleARB);
+        void       (WINE_GLAPI *p_glListParameterfSGIX)(GLuint,GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glListParameterfvSGIX)(GLuint,GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glListParameteriSGIX)(GLuint,GLenum,GLint);
+        void       (WINE_GLAPI *p_glListParameterivSGIX)(GLuint,GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glLoadIdentityDeformationMapSGIX)(GLbitfield);
+        void       (WINE_GLAPI *p_glLoadProgramNV)(GLenum,GLuint,GLsizei,const GLubyte*);
+        void       (WINE_GLAPI *p_glLoadTransposeMatrixd)(const GLdouble*);
+        void       (WINE_GLAPI *p_glLoadTransposeMatrixdARB)(const GLdouble*);
+        void       (WINE_GLAPI *p_glLoadTransposeMatrixf)(const GLfloat*);
+        void       (WINE_GLAPI *p_glLoadTransposeMatrixfARB)(const GLfloat*);
+        void       (WINE_GLAPI *p_glLockArraysEXT)(GLint,GLsizei);
+        void       (WINE_GLAPI *p_glMTexCoord2fSGIS)(GLenum,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glMTexCoord2fvSGIS)(GLenum,GLfloat *);
+        void       (WINE_GLAPI *p_glMakeBufferNonResidentNV)(GLenum);
+        void       (WINE_GLAPI *p_glMakeBufferResidentNV)(GLenum,GLenum);
+        void       (WINE_GLAPI *p_glMakeImageHandleNonResidentNV)(UINT64);
+        void       (WINE_GLAPI *p_glMakeImageHandleResidentNV)(UINT64,GLenum);
+        void       (WINE_GLAPI *p_glMakeNamedBufferNonResidentNV)(GLuint);
+        void       (WINE_GLAPI *p_glMakeNamedBufferResidentNV)(GLuint,GLenum);
+        void       (WINE_GLAPI *p_glMakeTextureHandleNonResidentNV)(UINT64);
+        void       (WINE_GLAPI *p_glMakeTextureHandleResidentNV)(UINT64);
+        GLvoid*    (WINE_GLAPI *p_glMapBuffer)(GLenum,GLenum);
+        GLvoid*    (WINE_GLAPI *p_glMapBufferARB)(GLenum,GLenum);
+        GLvoid*    (WINE_GLAPI *p_glMapBufferRange)(GLenum,GLintptr,GLsizeiptr,GLbitfield);
+        void       (WINE_GLAPI *p_glMapControlPointsNV)(GLenum,GLuint,GLenum,GLsizei,GLsizei,GLint,GLint,GLboolean,const GLvoid*);
+        GLvoid*    (WINE_GLAPI *p_glMapNamedBufferEXT)(GLuint,GLenum);
+        GLvoid*    (WINE_GLAPI *p_glMapNamedBufferRangeEXT)(GLuint,GLintptr,GLsizeiptr,GLbitfield);
+        GLvoid*    (WINE_GLAPI *p_glMapObjectBufferATI)(GLuint);
+        void       (WINE_GLAPI *p_glMapParameterfvNV)(GLenum,GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glMapParameterivNV)(GLenum,GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glMapVertexAttrib1dAPPLE)(GLuint,GLuint,GLdouble,GLdouble,GLint,GLint,const GLdouble*);
+        void       (WINE_GLAPI *p_glMapVertexAttrib1fAPPLE)(GLuint,GLuint,GLfloat,GLfloat,GLint,GLint,const GLfloat*);
+        void       (WINE_GLAPI *p_glMapVertexAttrib2dAPPLE)(GLuint,GLuint,GLdouble,GLdouble,GLint,GLint,GLdouble,GLdouble,GLint,GLint,const GLdouble*);
+        void       (WINE_GLAPI *p_glMapVertexAttrib2fAPPLE)(GLuint,GLuint,GLfloat,GLfloat,GLint,GLint,GLfloat,GLfloat,GLint,GLint,const GLfloat*);
+        void       (WINE_GLAPI *p_glMatrixFrustumEXT)(GLenum,GLdouble,GLdouble,GLdouble,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glMatrixIndexPointerARB)(GLint,GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glMatrixIndexubvARB)(GLint,const GLubyte*);
+        void       (WINE_GLAPI *p_glMatrixIndexuivARB)(GLint,const GLuint*);
+        void       (WINE_GLAPI *p_glMatrixIndexusvARB)(GLint,const GLushort*);
+        void       (WINE_GLAPI *p_glMatrixLoadIdentityEXT)(GLenum);
+        void       (WINE_GLAPI *p_glMatrixLoadTransposedEXT)(GLenum,const GLdouble*);
+        void       (WINE_GLAPI *p_glMatrixLoadTransposefEXT)(GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glMatrixLoaddEXT)(GLenum,const GLdouble*);
+        void       (WINE_GLAPI *p_glMatrixLoadfEXT)(GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glMatrixMultTransposedEXT)(GLenum,const GLdouble*);
+        void       (WINE_GLAPI *p_glMatrixMultTransposefEXT)(GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glMatrixMultdEXT)(GLenum,const GLdouble*);
+        void       (WINE_GLAPI *p_glMatrixMultfEXT)(GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glMatrixOrthoEXT)(GLenum,GLdouble,GLdouble,GLdouble,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glMatrixPopEXT)(GLenum);
+        void       (WINE_GLAPI *p_glMatrixPushEXT)(GLenum);
+        void       (WINE_GLAPI *p_glMatrixRotatedEXT)(GLenum,GLdouble,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glMatrixRotatefEXT)(GLenum,GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glMatrixScaledEXT)(GLenum,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glMatrixScalefEXT)(GLenum,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glMatrixTranslatedEXT)(GLenum,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glMatrixTranslatefEXT)(GLenum,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glMemoryBarrier)(GLbitfield);
+        void       (WINE_GLAPI *p_glMemoryBarrierEXT)(GLbitfield);
+        void       (WINE_GLAPI *p_glMinSampleShading)(GLfloat);
+        void       (WINE_GLAPI *p_glMinSampleShadingARB)(GLfloat);
+        void       (WINE_GLAPI *p_glMinmax)(GLenum,GLenum,GLboolean);
+        void       (WINE_GLAPI *p_glMinmaxEXT)(GLenum,GLenum,GLboolean);
+        void       (WINE_GLAPI *p_glMultTransposeMatrixd)(const GLdouble*);
+        void       (WINE_GLAPI *p_glMultTransposeMatrixdARB)(const GLdouble*);
+        void       (WINE_GLAPI *p_glMultTransposeMatrixf)(const GLfloat*);
+        void       (WINE_GLAPI *p_glMultTransposeMatrixfARB)(const GLfloat*);
+        void       (WINE_GLAPI *p_glMultiDrawArrays)(GLenum,const GLint*,const GLsizei*,GLsizei);
+        void       (WINE_GLAPI *p_glMultiDrawArraysEXT)(GLenum,const GLint*,const GLsizei*,GLsizei);
+        void       (WINE_GLAPI *p_glMultiDrawArraysIndirect)(GLenum,const void*,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glMultiDrawArraysIndirectAMD)(GLenum,const GLvoid*,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glMultiDrawElementArrayAPPLE)(GLenum,const GLint*,const GLsizei*,GLsizei);
+        void       (WINE_GLAPI *p_glMultiDrawElements)(GLenum,const GLsizei*,GLenum,const GLvoid* const*,GLsizei);
+        void       (WINE_GLAPI *p_glMultiDrawElementsBaseVertex)(GLenum,const GLsizei*,GLenum,const GLvoid* const*,GLsizei,const GLint*);
+        void       (WINE_GLAPI *p_glMultiDrawElementsEXT)(GLenum,const GLsizei*,GLenum,const GLvoid**,GLsizei);
+        void       (WINE_GLAPI *p_glMultiDrawElementsIndirect)(GLenum,GLenum,const void*,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glMultiDrawElementsIndirectAMD)(GLenum,GLenum,const GLvoid*,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glMultiDrawRangeElementArrayAPPLE)(GLenum,GLuint,GLuint,const GLint*,const GLsizei*,GLsizei);
+        void       (WINE_GLAPI *p_glMultiModeDrawArraysIBM)(const GLenum*,const GLint*,const GLsizei*,GLsizei,GLint);
+        void       (WINE_GLAPI *p_glMultiModeDrawElementsIBM)(const GLenum*,const GLsizei*,GLenum,const GLvoid* const*,GLsizei,GLint);
+        void       (WINE_GLAPI *p_glMultiTexBufferEXT)(GLenum,GLenum,GLenum,GLuint);
+        void       (WINE_GLAPI *p_glMultiTexCoord1d)(GLenum,GLdouble);
+        void       (WINE_GLAPI *p_glMultiTexCoord1dARB)(GLenum,GLdouble);
+        void       (WINE_GLAPI *p_glMultiTexCoord1dSGIS)(GLenum,GLdouble);
+        void       (WINE_GLAPI *p_glMultiTexCoord1dv)(GLenum,const GLdouble*);
+        void       (WINE_GLAPI *p_glMultiTexCoord1dvARB)(GLenum,const GLdouble*);
+        void       (WINE_GLAPI *p_glMultiTexCoord1dvSGIS)(GLenum,GLdouble *);
+        void       (WINE_GLAPI *p_glMultiTexCoord1f)(GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glMultiTexCoord1fARB)(GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glMultiTexCoord1fSGIS)(GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glMultiTexCoord1fv)(GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glMultiTexCoord1fvARB)(GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glMultiTexCoord1fvSGIS)(GLenum,const GLfloat *);
+        void       (WINE_GLAPI *p_glMultiTexCoord1hNV)(GLenum,GLhalfNV);
+        void       (WINE_GLAPI *p_glMultiTexCoord1hvNV)(GLenum,const GLhalfNV*);
+        void       (WINE_GLAPI *p_glMultiTexCoord1i)(GLenum,GLint);
+        void       (WINE_GLAPI *p_glMultiTexCoord1iARB)(GLenum,GLint);
+        void       (WINE_GLAPI *p_glMultiTexCoord1iSGIS)(GLenum,GLint);
+        void       (WINE_GLAPI *p_glMultiTexCoord1iv)(GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glMultiTexCoord1ivARB)(GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glMultiTexCoord1ivSGIS)(GLenum,GLint *);
+        void       (WINE_GLAPI *p_glMultiTexCoord1s)(GLenum,GLshort);
+        void       (WINE_GLAPI *p_glMultiTexCoord1sARB)(GLenum,GLshort);
+        void       (WINE_GLAPI *p_glMultiTexCoord1sSGIS)(GLenum,GLshort);
+        void       (WINE_GLAPI *p_glMultiTexCoord1sv)(GLenum,const GLshort*);
+        void       (WINE_GLAPI *p_glMultiTexCoord1svARB)(GLenum,const GLshort*);
+        void       (WINE_GLAPI *p_glMultiTexCoord1svSGIS)(GLenum,GLshort *);
+        void       (WINE_GLAPI *p_glMultiTexCoord2d)(GLenum,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glMultiTexCoord2dARB)(GLenum,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glMultiTexCoord2dSGIS)(GLenum,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glMultiTexCoord2dv)(GLenum,const GLdouble*);
+        void       (WINE_GLAPI *p_glMultiTexCoord2dvARB)(GLenum,const GLdouble*);
+        void       (WINE_GLAPI *p_glMultiTexCoord2dvSGIS)(GLenum,GLdouble *);
+        void       (WINE_GLAPI *p_glMultiTexCoord2f)(GLenum,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glMultiTexCoord2fARB)(GLenum,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glMultiTexCoord2fSGIS)(GLenum,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glMultiTexCoord2fv)(GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glMultiTexCoord2fvARB)(GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glMultiTexCoord2fvSGIS)(GLenum,GLfloat *);
+        void       (WINE_GLAPI *p_glMultiTexCoord2hNV)(GLenum,GLhalfNV,GLhalfNV);
+        void       (WINE_GLAPI *p_glMultiTexCoord2hvNV)(GLenum,const GLhalfNV*);
+        void       (WINE_GLAPI *p_glMultiTexCoord2i)(GLenum,GLint,GLint);
+        void       (WINE_GLAPI *p_glMultiTexCoord2iARB)(GLenum,GLint,GLint);
+        void       (WINE_GLAPI *p_glMultiTexCoord2iSGIS)(GLenum,GLint,GLint);
+        void       (WINE_GLAPI *p_glMultiTexCoord2iv)(GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glMultiTexCoord2ivARB)(GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glMultiTexCoord2ivSGIS)(GLenum,GLint *);
+        void       (WINE_GLAPI *p_glMultiTexCoord2s)(GLenum,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glMultiTexCoord2sARB)(GLenum,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glMultiTexCoord2sSGIS)(GLenum,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glMultiTexCoord2sv)(GLenum,const GLshort*);
+        void       (WINE_GLAPI *p_glMultiTexCoord2svARB)(GLenum,const GLshort*);
+        void       (WINE_GLAPI *p_glMultiTexCoord2svSGIS)(GLenum,GLshort *);
+        void       (WINE_GLAPI *p_glMultiTexCoord3d)(GLenum,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glMultiTexCoord3dARB)(GLenum,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glMultiTexCoord3dSGIS)(GLenum,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glMultiTexCoord3dv)(GLenum,const GLdouble*);
+        void       (WINE_GLAPI *p_glMultiTexCoord3dvARB)(GLenum,const GLdouble*);
+        void       (WINE_GLAPI *p_glMultiTexCoord3dvSGIS)(GLenum,GLdouble *);
+        void       (WINE_GLAPI *p_glMultiTexCoord3f)(GLenum,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glMultiTexCoord3fARB)(GLenum,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glMultiTexCoord3fSGIS)(GLenum,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glMultiTexCoord3fv)(GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glMultiTexCoord3fvARB)(GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glMultiTexCoord3fvSGIS)(GLenum,GLfloat *);
+        void       (WINE_GLAPI *p_glMultiTexCoord3hNV)(GLenum,GLhalfNV,GLhalfNV,GLhalfNV);
+        void       (WINE_GLAPI *p_glMultiTexCoord3hvNV)(GLenum,const GLhalfNV*);
+        void       (WINE_GLAPI *p_glMultiTexCoord3i)(GLenum,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glMultiTexCoord3iARB)(GLenum,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glMultiTexCoord3iSGIS)(GLenum,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glMultiTexCoord3iv)(GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glMultiTexCoord3ivARB)(GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glMultiTexCoord3ivSGIS)(GLenum,GLint *);
+        void       (WINE_GLAPI *p_glMultiTexCoord3s)(GLenum,GLshort,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glMultiTexCoord3sARB)(GLenum,GLshort,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glMultiTexCoord3sSGIS)(GLenum,GLshort,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glMultiTexCoord3sv)(GLenum,const GLshort*);
+        void       (WINE_GLAPI *p_glMultiTexCoord3svARB)(GLenum,const GLshort*);
+        void       (WINE_GLAPI *p_glMultiTexCoord3svSGIS)(GLenum,GLshort *);
+        void       (WINE_GLAPI *p_glMultiTexCoord4d)(GLenum,GLdouble,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glMultiTexCoord4dARB)(GLenum,GLdouble,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glMultiTexCoord4dSGIS)(GLenum,GLdouble,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glMultiTexCoord4dv)(GLenum,const GLdouble*);
+        void       (WINE_GLAPI *p_glMultiTexCoord4dvARB)(GLenum,const GLdouble*);
+        void       (WINE_GLAPI *p_glMultiTexCoord4dvSGIS)(GLenum,GLdouble *);
+        void       (WINE_GLAPI *p_glMultiTexCoord4f)(GLenum,GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glMultiTexCoord4fARB)(GLenum,GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glMultiTexCoord4fSGIS)(GLenum,GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glMultiTexCoord4fv)(GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glMultiTexCoord4fvARB)(GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glMultiTexCoord4fvSGIS)(GLenum,GLfloat *);
+        void       (WINE_GLAPI *p_glMultiTexCoord4hNV)(GLenum,GLhalfNV,GLhalfNV,GLhalfNV,GLhalfNV);
+        void       (WINE_GLAPI *p_glMultiTexCoord4hvNV)(GLenum,const GLhalfNV*);
+        void       (WINE_GLAPI *p_glMultiTexCoord4i)(GLenum,GLint,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glMultiTexCoord4iARB)(GLenum,GLint,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glMultiTexCoord4iSGIS)(GLenum,GLint,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glMultiTexCoord4iv)(GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glMultiTexCoord4ivARB)(GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glMultiTexCoord4ivSGIS)(GLenum,GLint *);
+        void       (WINE_GLAPI *p_glMultiTexCoord4s)(GLenum,GLshort,GLshort,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glMultiTexCoord4sARB)(GLenum,GLshort,GLshort,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glMultiTexCoord4sSGIS)(GLenum,GLshort,GLshort,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glMultiTexCoord4sv)(GLenum,const GLshort*);
+        void       (WINE_GLAPI *p_glMultiTexCoord4svARB)(GLenum,const GLshort*);
+        void       (WINE_GLAPI *p_glMultiTexCoord4svSGIS)(GLenum,GLshort *);
+        void       (WINE_GLAPI *p_glMultiTexCoordP1ui)(GLenum,GLenum,GLuint);
+        void       (WINE_GLAPI *p_glMultiTexCoordP1uiv)(GLenum,GLenum,const GLuint*);
+        void       (WINE_GLAPI *p_glMultiTexCoordP2ui)(GLenum,GLenum,GLuint);
+        void       (WINE_GLAPI *p_glMultiTexCoordP2uiv)(GLenum,GLenum,const GLuint*);
+        void       (WINE_GLAPI *p_glMultiTexCoordP3ui)(GLenum,GLenum,GLuint);
+        void       (WINE_GLAPI *p_glMultiTexCoordP3uiv)(GLenum,GLenum,const GLuint*);
+        void       (WINE_GLAPI *p_glMultiTexCoordP4ui)(GLenum,GLenum,GLuint);
+        void       (WINE_GLAPI *p_glMultiTexCoordP4uiv)(GLenum,GLenum,const GLuint*);
+        void       (WINE_GLAPI *p_glMultiTexCoordPointerEXT)(GLenum,GLint,GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glMultiTexCoordPointerSGIS)(GLenum,GLint,GLenum,GLsizei,GLvoid *);
+        void       (WINE_GLAPI *p_glMultiTexEnvfEXT)(GLenum,GLenum,GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glMultiTexEnvfvEXT)(GLenum,GLenum,GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glMultiTexEnviEXT)(GLenum,GLenum,GLenum,GLint);
+        void       (WINE_GLAPI *p_glMultiTexEnvivEXT)(GLenum,GLenum,GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glMultiTexGendEXT)(GLenum,GLenum,GLenum,GLdouble);
+        void       (WINE_GLAPI *p_glMultiTexGendvEXT)(GLenum,GLenum,GLenum,const GLdouble*);
+        void       (WINE_GLAPI *p_glMultiTexGenfEXT)(GLenum,GLenum,GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glMultiTexGenfvEXT)(GLenum,GLenum,GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glMultiTexGeniEXT)(GLenum,GLenum,GLenum,GLint);
+        void       (WINE_GLAPI *p_glMultiTexGenivEXT)(GLenum,GLenum,GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glMultiTexImage1DEXT)(GLenum,GLenum,GLint,GLenum,GLsizei,GLint,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glMultiTexImage2DEXT)(GLenum,GLenum,GLint,GLenum,GLsizei,GLsizei,GLint,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glMultiTexImage3DEXT)(GLenum,GLenum,GLint,GLenum,GLsizei,GLsizei,GLsizei,GLint,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glMultiTexParameterIivEXT)(GLenum,GLenum,GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glMultiTexParameterIuivEXT)(GLenum,GLenum,GLenum,const GLuint*);
+        void       (WINE_GLAPI *p_glMultiTexParameterfEXT)(GLenum,GLenum,GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glMultiTexParameterfvEXT)(GLenum,GLenum,GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glMultiTexParameteriEXT)(GLenum,GLenum,GLenum,GLint);
+        void       (WINE_GLAPI *p_glMultiTexParameterivEXT)(GLenum,GLenum,GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glMultiTexRenderbufferEXT)(GLenum,GLenum,GLuint);
+        void       (WINE_GLAPI *p_glMultiTexSubImage1DEXT)(GLenum,GLenum,GLint,GLint,GLsizei,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glMultiTexSubImage2DEXT)(GLenum,GLenum,GLint,GLint,GLint,GLsizei,GLsizei,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glMultiTexSubImage3DEXT)(GLenum,GLenum,GLint,GLint,GLint,GLint,GLsizei,GLsizei,GLsizei,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glNamedBufferDataEXT)(GLuint,GLsizeiptr,const GLvoid*,GLenum);
+        void       (WINE_GLAPI *p_glNamedBufferSubDataEXT)(GLuint,GLintptr,GLsizeiptr,const GLvoid*);
+        void       (WINE_GLAPI *p_glNamedCopyBufferSubDataEXT)(GLuint,GLuint,GLintptr,GLintptr,GLsizeiptr);
+        void       (WINE_GLAPI *p_glNamedFramebufferParameteriEXT)(GLuint,GLenum,GLint);
+        void       (WINE_GLAPI *p_glNamedFramebufferRenderbufferEXT)(GLuint,GLenum,GLenum,GLuint);
+        void       (WINE_GLAPI *p_glNamedFramebufferTexture1DEXT)(GLuint,GLenum,GLenum,GLuint,GLint);
+        void       (WINE_GLAPI *p_glNamedFramebufferTexture2DEXT)(GLuint,GLenum,GLenum,GLuint,GLint);
+        void       (WINE_GLAPI *p_glNamedFramebufferTexture3DEXT)(GLuint,GLenum,GLenum,GLuint,GLint,GLint);
+        void       (WINE_GLAPI *p_glNamedFramebufferTextureEXT)(GLuint,GLenum,GLuint,GLint);
+        void       (WINE_GLAPI *p_glNamedFramebufferTextureFaceEXT)(GLuint,GLenum,GLuint,GLint,GLenum);
+        void       (WINE_GLAPI *p_glNamedFramebufferTextureLayerEXT)(GLuint,GLenum,GLuint,GLint,GLint);
+        void       (WINE_GLAPI *p_glNamedProgramLocalParameter4dEXT)(GLuint,GLenum,GLuint,GLdouble,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glNamedProgramLocalParameter4dvEXT)(GLuint,GLenum,GLuint,const GLdouble*);
+        void       (WINE_GLAPI *p_glNamedProgramLocalParameter4fEXT)(GLuint,GLenum,GLuint,GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glNamedProgramLocalParameter4fvEXT)(GLuint,GLenum,GLuint,const GLfloat*);
+        void       (WINE_GLAPI *p_glNamedProgramLocalParameterI4iEXT)(GLuint,GLenum,GLuint,GLint,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glNamedProgramLocalParameterI4ivEXT)(GLuint,GLenum,GLuint,const GLint*);
+        void       (WINE_GLAPI *p_glNamedProgramLocalParameterI4uiEXT)(GLuint,GLenum,GLuint,GLuint,GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glNamedProgramLocalParameterI4uivEXT)(GLuint,GLenum,GLuint,const GLuint*);
+        void       (WINE_GLAPI *p_glNamedProgramLocalParameters4fvEXT)(GLuint,GLenum,GLuint,GLsizei,const GLfloat*);
+        void       (WINE_GLAPI *p_glNamedProgramLocalParametersI4ivEXT)(GLuint,GLenum,GLuint,GLsizei,const GLint*);
+        void       (WINE_GLAPI *p_glNamedProgramLocalParametersI4uivEXT)(GLuint,GLenum,GLuint,GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glNamedProgramStringEXT)(GLuint,GLenum,GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glNamedRenderbufferStorageEXT)(GLuint,GLenum,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glNamedRenderbufferStorageMultisampleCoverageEXT)(GLuint,GLsizei,GLsizei,GLenum,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glNamedRenderbufferStorageMultisampleEXT)(GLuint,GLsizei,GLenum,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glNamedStringARB)(GLenum,GLint,const GLchar*,GLint,const GLchar*);
+        GLuint     (WINE_GLAPI *p_glNewBufferRegion)(GLenum);
+        GLuint     (WINE_GLAPI *p_glNewObjectBufferATI)(GLsizei,const GLvoid*,GLenum);
+        void       (WINE_GLAPI *p_glNormal3fVertex3fSUN)(GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glNormal3fVertex3fvSUN)(const GLfloat*,const GLfloat*);
+        void       (WINE_GLAPI *p_glNormal3hNV)(GLhalfNV,GLhalfNV,GLhalfNV);
+        void       (WINE_GLAPI *p_glNormal3hvNV)(const GLhalfNV*);
+        void       (WINE_GLAPI *p_glNormalFormatNV)(GLenum,GLsizei);
+        void       (WINE_GLAPI *p_glNormalP3ui)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glNormalP3uiv)(GLenum,const GLuint*);
+        void       (WINE_GLAPI *p_glNormalPointerEXT)(GLenum,GLsizei,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glNormalPointerListIBM)(GLenum,GLint,const GLvoid**,GLint);
+        void       (WINE_GLAPI *p_glNormalPointervINTEL)(GLenum,const GLvoid**);
+        void       (WINE_GLAPI *p_glNormalStream3bATI)(GLenum,GLbyte,GLbyte,GLbyte);
+        void       (WINE_GLAPI *p_glNormalStream3bvATI)(GLenum,const GLbyte*);
+        void       (WINE_GLAPI *p_glNormalStream3dATI)(GLenum,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glNormalStream3dvATI)(GLenum,const GLdouble*);
+        void       (WINE_GLAPI *p_glNormalStream3fATI)(GLenum,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glNormalStream3fvATI)(GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glNormalStream3iATI)(GLenum,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glNormalStream3ivATI)(GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glNormalStream3sATI)(GLenum,GLshort,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glNormalStream3svATI)(GLenum,const GLshort*);
+        void       (WINE_GLAPI *p_glObjectLabel)(GLenum,GLuint,GLsizei,const GLchar*);
+        void       (WINE_GLAPI *p_glObjectPtrLabel)(const void*,GLsizei,const GLchar*);
+        GLenum     (WINE_GLAPI *p_glObjectPurgeableAPPLE)(GLenum,GLuint,GLenum);
+        GLenum     (WINE_GLAPI *p_glObjectUnpurgeableAPPLE)(GLenum,GLuint,GLenum);
+        void       (WINE_GLAPI *p_glPNTrianglesfATI)(GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glPNTrianglesiATI)(GLenum,GLint);
+        void       (WINE_GLAPI *p_glPassTexCoordATI)(GLuint,GLuint,GLenum);
+        void       (WINE_GLAPI *p_glPatchParameterfv)(GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glPatchParameteri)(GLenum,GLint);
+        void       (WINE_GLAPI *p_glPathColorGenNV)(GLenum,GLenum,GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glPathCommandsNV)(GLuint,GLsizei,const GLubyte*,GLsizei,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glPathCoordsNV)(GLuint,GLsizei,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glPathCoverDepthFuncNV)(GLenum);
+        void       (WINE_GLAPI *p_glPathDashArrayNV)(GLuint,GLsizei,const GLfloat*);
+        void       (WINE_GLAPI *p_glPathFogGenNV)(GLenum);
+        void       (WINE_GLAPI *p_glPathGlyphRangeNV)(GLuint,GLenum,const GLvoid*,GLbitfield,GLuint,GLsizei,GLenum,GLuint,GLfloat);
+        void       (WINE_GLAPI *p_glPathGlyphsNV)(GLuint,GLenum,const GLvoid*,GLbitfield,GLsizei,GLenum,const GLvoid*,GLenum,GLuint,GLfloat);
+        void       (WINE_GLAPI *p_glPathParameterfNV)(GLuint,GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glPathParameterfvNV)(GLuint,GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glPathParameteriNV)(GLuint,GLenum,GLint);
+        void       (WINE_GLAPI *p_glPathParameterivNV)(GLuint,GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glPathStencilDepthOffsetNV)(GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glPathStencilFuncNV)(GLenum,GLint,GLuint);
+        void       (WINE_GLAPI *p_glPathStringNV)(GLuint,GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glPathSubCommandsNV)(GLuint,GLsizei,GLsizei,GLsizei,const GLubyte*,GLsizei,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glPathSubCoordsNV)(GLuint,GLsizei,GLsizei,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glPathTexGenNV)(GLenum,GLenum,GLint,const GLfloat*);
+        void       (WINE_GLAPI *p_glPauseTransformFeedback)(void);
+        void       (WINE_GLAPI *p_glPauseTransformFeedbackNV)(void);
+        void       (WINE_GLAPI *p_glPixelDataRangeNV)(GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glPixelTexGenParameterfSGIS)(GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glPixelTexGenParameterfvSGIS)(GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glPixelTexGenParameteriSGIS)(GLenum,GLint);
+        void       (WINE_GLAPI *p_glPixelTexGenParameterivSGIS)(GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glPixelTexGenSGIX)(GLenum);
+        void       (WINE_GLAPI *p_glPixelTransformParameterfEXT)(GLenum,GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glPixelTransformParameterfvEXT)(GLenum,GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glPixelTransformParameteriEXT)(GLenum,GLenum,GLint);
+        void       (WINE_GLAPI *p_glPixelTransformParameterivEXT)(GLenum,GLenum,const GLint*);
+        GLboolean  (WINE_GLAPI *p_glPointAlongPathNV)(GLuint,GLsizei,GLsizei,GLfloat,GLfloat*,GLfloat*,GLfloat*,GLfloat*);
+        void       (WINE_GLAPI *p_glPointParameterf)(GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glPointParameterfARB)(GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glPointParameterfEXT)(GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glPointParameterfSGIS)(GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glPointParameterfv)(GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glPointParameterfvARB)(GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glPointParameterfvEXT)(GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glPointParameterfvSGIS)(GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glPointParameteri)(GLenum,GLint);
+        void       (WINE_GLAPI *p_glPointParameteriNV)(GLenum,GLint);
+        void       (WINE_GLAPI *p_glPointParameteriv)(GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glPointParameterivNV)(GLenum,const GLint*);
+        GLint      (WINE_GLAPI *p_glPollAsyncSGIX)(GLuint*);
+        GLint      (WINE_GLAPI *p_glPollInstrumentsSGIX)(GLint*);
+        void       (WINE_GLAPI *p_glPolygonOffsetEXT)(GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glPopDebugGroup)(void);
+        void       (WINE_GLAPI *p_glPresentFrameDualFillNV)(GLuint,UINT64,GLuint,GLuint,GLenum,GLenum,GLuint,GLenum,GLuint,GLenum,GLuint,GLenum,GLuint);
+        void       (WINE_GLAPI *p_glPresentFrameKeyedNV)(GLuint,UINT64,GLuint,GLuint,GLenum,GLenum,GLuint,GLuint,GLenum,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glPrimitiveRestartIndex)(GLuint);
+        void       (WINE_GLAPI *p_glPrimitiveRestartIndexNV)(GLuint);
+        void       (WINE_GLAPI *p_glPrimitiveRestartNV)(void);
+        void       (WINE_GLAPI *p_glPrioritizeTexturesEXT)(GLsizei,const GLuint*,const GLclampf*);
+        void       (WINE_GLAPI *p_glProgramBinary)(GLuint,GLenum,const GLvoid*,GLsizei);
+        void       (WINE_GLAPI *p_glProgramBufferParametersIivNV)(GLenum,GLuint,GLuint,GLsizei,const GLint*);
+        void       (WINE_GLAPI *p_glProgramBufferParametersIuivNV)(GLenum,GLuint,GLuint,GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glProgramBufferParametersfvNV)(GLenum,GLuint,GLuint,GLsizei,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramEnvParameter4dARB)(GLenum,GLuint,GLdouble,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glProgramEnvParameter4dvARB)(GLenum,GLuint,const GLdouble*);
+        void       (WINE_GLAPI *p_glProgramEnvParameter4fARB)(GLenum,GLuint,GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glProgramEnvParameter4fvARB)(GLenum,GLuint,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramEnvParameterI4iNV)(GLenum,GLuint,GLint,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glProgramEnvParameterI4ivNV)(GLenum,GLuint,const GLint*);
+        void       (WINE_GLAPI *p_glProgramEnvParameterI4uiNV)(GLenum,GLuint,GLuint,GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glProgramEnvParameterI4uivNV)(GLenum,GLuint,const GLuint*);
+        void       (WINE_GLAPI *p_glProgramEnvParameters4fvEXT)(GLenum,GLuint,GLsizei,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramEnvParametersI4ivNV)(GLenum,GLuint,GLsizei,const GLint*);
+        void       (WINE_GLAPI *p_glProgramEnvParametersI4uivNV)(GLenum,GLuint,GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glProgramLocalParameter4dARB)(GLenum,GLuint,GLdouble,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glProgramLocalParameter4dvARB)(GLenum,GLuint,const GLdouble*);
+        void       (WINE_GLAPI *p_glProgramLocalParameter4fARB)(GLenum,GLuint,GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glProgramLocalParameter4fvARB)(GLenum,GLuint,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramLocalParameterI4iNV)(GLenum,GLuint,GLint,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glProgramLocalParameterI4ivNV)(GLenum,GLuint,const GLint*);
+        void       (WINE_GLAPI *p_glProgramLocalParameterI4uiNV)(GLenum,GLuint,GLuint,GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glProgramLocalParameterI4uivNV)(GLenum,GLuint,const GLuint*);
+        void       (WINE_GLAPI *p_glProgramLocalParameters4fvEXT)(GLenum,GLuint,GLsizei,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramLocalParametersI4ivNV)(GLenum,GLuint,GLsizei,const GLint*);
+        void       (WINE_GLAPI *p_glProgramLocalParametersI4uivNV)(GLenum,GLuint,GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glProgramNamedParameter4dNV)(GLuint,GLsizei,const GLubyte*,GLdouble,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glProgramNamedParameter4dvNV)(GLuint,GLsizei,const GLubyte*,const GLdouble*);
+        void       (WINE_GLAPI *p_glProgramNamedParameter4fNV)(GLuint,GLsizei,const GLubyte*,GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glProgramNamedParameter4fvNV)(GLuint,GLsizei,const GLubyte*,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramParameter4dNV)(GLenum,GLuint,GLdouble,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glProgramParameter4dvNV)(GLenum,GLuint,const GLdouble*);
+        void       (WINE_GLAPI *p_glProgramParameter4fNV)(GLenum,GLuint,GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glProgramParameter4fvNV)(GLenum,GLuint,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramParameteri)(GLuint,GLenum,GLint);
+        void       (WINE_GLAPI *p_glProgramParameteriARB)(GLuint,GLenum,GLint);
+        void       (WINE_GLAPI *p_glProgramParameteriEXT)(GLuint,GLenum,GLint);
+        void       (WINE_GLAPI *p_glProgramParameters4dvNV)(GLenum,GLuint,GLsizei,const GLdouble*);
+        void       (WINE_GLAPI *p_glProgramParameters4fvNV)(GLenum,GLuint,GLsizei,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramStringARB)(GLenum,GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glProgramSubroutineParametersuivNV)(GLenum,GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glProgramUniform1d)(GLuint,GLint,GLdouble);
+        void       (WINE_GLAPI *p_glProgramUniform1dEXT)(GLuint,GLint,GLdouble);
+        void       (WINE_GLAPI *p_glProgramUniform1dv)(GLuint,GLint,GLsizei,const GLdouble*);
+        void       (WINE_GLAPI *p_glProgramUniform1dvEXT)(GLuint,GLint,GLsizei,const GLdouble*);
+        void       (WINE_GLAPI *p_glProgramUniform1f)(GLuint,GLint,GLfloat);
+        void       (WINE_GLAPI *p_glProgramUniform1fEXT)(GLuint,GLint,GLfloat);
+        void       (WINE_GLAPI *p_glProgramUniform1fv)(GLuint,GLint,GLsizei,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramUniform1fvEXT)(GLuint,GLint,GLsizei,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramUniform1i)(GLuint,GLint,GLint);
+        void       (WINE_GLAPI *p_glProgramUniform1i64NV)(GLuint,GLint,INT64);
+        void       (WINE_GLAPI *p_glProgramUniform1i64vNV)(GLuint,GLint,GLsizei,const INT64*);
+        void       (WINE_GLAPI *p_glProgramUniform1iEXT)(GLuint,GLint,GLint);
+        void       (WINE_GLAPI *p_glProgramUniform1iv)(GLuint,GLint,GLsizei,const GLint*);
+        void       (WINE_GLAPI *p_glProgramUniform1ivEXT)(GLuint,GLint,GLsizei,const GLint*);
+        void       (WINE_GLAPI *p_glProgramUniform1ui)(GLuint,GLint,GLuint);
+        void       (WINE_GLAPI *p_glProgramUniform1ui64NV)(GLuint,GLint,UINT64);
+        void       (WINE_GLAPI *p_glProgramUniform1ui64vNV)(GLuint,GLint,GLsizei,const UINT64*);
+        void       (WINE_GLAPI *p_glProgramUniform1uiEXT)(GLuint,GLint,GLuint);
+        void       (WINE_GLAPI *p_glProgramUniform1uiv)(GLuint,GLint,GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glProgramUniform1uivEXT)(GLuint,GLint,GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glProgramUniform2d)(GLuint,GLint,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glProgramUniform2dEXT)(GLuint,GLint,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glProgramUniform2dv)(GLuint,GLint,GLsizei,const GLdouble*);
+        void       (WINE_GLAPI *p_glProgramUniform2dvEXT)(GLuint,GLint,GLsizei,const GLdouble*);
+        void       (WINE_GLAPI *p_glProgramUniform2f)(GLuint,GLint,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glProgramUniform2fEXT)(GLuint,GLint,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glProgramUniform2fv)(GLuint,GLint,GLsizei,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramUniform2fvEXT)(GLuint,GLint,GLsizei,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramUniform2i)(GLuint,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glProgramUniform2i64NV)(GLuint,GLint,INT64,INT64);
+        void       (WINE_GLAPI *p_glProgramUniform2i64vNV)(GLuint,GLint,GLsizei,const INT64*);
+        void       (WINE_GLAPI *p_glProgramUniform2iEXT)(GLuint,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glProgramUniform2iv)(GLuint,GLint,GLsizei,const GLint*);
+        void       (WINE_GLAPI *p_glProgramUniform2ivEXT)(GLuint,GLint,GLsizei,const GLint*);
+        void       (WINE_GLAPI *p_glProgramUniform2ui)(GLuint,GLint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glProgramUniform2ui64NV)(GLuint,GLint,UINT64,UINT64);
+        void       (WINE_GLAPI *p_glProgramUniform2ui64vNV)(GLuint,GLint,GLsizei,const UINT64*);
+        void       (WINE_GLAPI *p_glProgramUniform2uiEXT)(GLuint,GLint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glProgramUniform2uiv)(GLuint,GLint,GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glProgramUniform2uivEXT)(GLuint,GLint,GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glProgramUniform3d)(GLuint,GLint,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glProgramUniform3dEXT)(GLuint,GLint,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glProgramUniform3dv)(GLuint,GLint,GLsizei,const GLdouble*);
+        void       (WINE_GLAPI *p_glProgramUniform3dvEXT)(GLuint,GLint,GLsizei,const GLdouble*);
+        void       (WINE_GLAPI *p_glProgramUniform3f)(GLuint,GLint,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glProgramUniform3fEXT)(GLuint,GLint,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glProgramUniform3fv)(GLuint,GLint,GLsizei,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramUniform3fvEXT)(GLuint,GLint,GLsizei,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramUniform3i)(GLuint,GLint,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glProgramUniform3i64NV)(GLuint,GLint,INT64,INT64,INT64);
+        void       (WINE_GLAPI *p_glProgramUniform3i64vNV)(GLuint,GLint,GLsizei,const INT64*);
+        void       (WINE_GLAPI *p_glProgramUniform3iEXT)(GLuint,GLint,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glProgramUniform3iv)(GLuint,GLint,GLsizei,const GLint*);
+        void       (WINE_GLAPI *p_glProgramUniform3ivEXT)(GLuint,GLint,GLsizei,const GLint*);
+        void       (WINE_GLAPI *p_glProgramUniform3ui)(GLuint,GLint,GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glProgramUniform3ui64NV)(GLuint,GLint,UINT64,UINT64,UINT64);
+        void       (WINE_GLAPI *p_glProgramUniform3ui64vNV)(GLuint,GLint,GLsizei,const UINT64*);
+        void       (WINE_GLAPI *p_glProgramUniform3uiEXT)(GLuint,GLint,GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glProgramUniform3uiv)(GLuint,GLint,GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glProgramUniform3uivEXT)(GLuint,GLint,GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glProgramUniform4d)(GLuint,GLint,GLdouble,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glProgramUniform4dEXT)(GLuint,GLint,GLdouble,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glProgramUniform4dv)(GLuint,GLint,GLsizei,const GLdouble*);
+        void       (WINE_GLAPI *p_glProgramUniform4dvEXT)(GLuint,GLint,GLsizei,const GLdouble*);
+        void       (WINE_GLAPI *p_glProgramUniform4f)(GLuint,GLint,GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glProgramUniform4fEXT)(GLuint,GLint,GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glProgramUniform4fv)(GLuint,GLint,GLsizei,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramUniform4fvEXT)(GLuint,GLint,GLsizei,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramUniform4i)(GLuint,GLint,GLint,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glProgramUniform4i64NV)(GLuint,GLint,INT64,INT64,INT64,INT64);
+        void       (WINE_GLAPI *p_glProgramUniform4i64vNV)(GLuint,GLint,GLsizei,const INT64*);
+        void       (WINE_GLAPI *p_glProgramUniform4iEXT)(GLuint,GLint,GLint,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glProgramUniform4iv)(GLuint,GLint,GLsizei,const GLint*);
+        void       (WINE_GLAPI *p_glProgramUniform4ivEXT)(GLuint,GLint,GLsizei,const GLint*);
+        void       (WINE_GLAPI *p_glProgramUniform4ui)(GLuint,GLint,GLuint,GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glProgramUniform4ui64NV)(GLuint,GLint,UINT64,UINT64,UINT64,UINT64);
+        void       (WINE_GLAPI *p_glProgramUniform4ui64vNV)(GLuint,GLint,GLsizei,const UINT64*);
+        void       (WINE_GLAPI *p_glProgramUniform4uiEXT)(GLuint,GLint,GLuint,GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glProgramUniform4uiv)(GLuint,GLint,GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glProgramUniform4uivEXT)(GLuint,GLint,GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glProgramUniformHandleui64NV)(GLuint,GLint,UINT64);
+        void       (WINE_GLAPI *p_glProgramUniformHandleui64vNV)(GLuint,GLint,GLsizei,const UINT64*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix2dv)(GLuint,GLint,GLsizei,GLboolean,const GLdouble*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix2dvEXT)(GLuint,GLint,GLsizei,GLboolean,const GLdouble*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix2fv)(GLuint,GLint,GLsizei,GLboolean,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix2fvEXT)(GLuint,GLint,GLsizei,GLboolean,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix2x3dv)(GLuint,GLint,GLsizei,GLboolean,const GLdouble*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix2x3dvEXT)(GLuint,GLint,GLsizei,GLboolean,const GLdouble*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix2x3fv)(GLuint,GLint,GLsizei,GLboolean,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix2x3fvEXT)(GLuint,GLint,GLsizei,GLboolean,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix2x4dv)(GLuint,GLint,GLsizei,GLboolean,const GLdouble*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix2x4dvEXT)(GLuint,GLint,GLsizei,GLboolean,const GLdouble*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix2x4fv)(GLuint,GLint,GLsizei,GLboolean,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix2x4fvEXT)(GLuint,GLint,GLsizei,GLboolean,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix3dv)(GLuint,GLint,GLsizei,GLboolean,const GLdouble*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix3dvEXT)(GLuint,GLint,GLsizei,GLboolean,const GLdouble*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix3fv)(GLuint,GLint,GLsizei,GLboolean,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix3fvEXT)(GLuint,GLint,GLsizei,GLboolean,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix3x2dv)(GLuint,GLint,GLsizei,GLboolean,const GLdouble*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix3x2dvEXT)(GLuint,GLint,GLsizei,GLboolean,const GLdouble*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix3x2fv)(GLuint,GLint,GLsizei,GLboolean,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix3x2fvEXT)(GLuint,GLint,GLsizei,GLboolean,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix3x4dv)(GLuint,GLint,GLsizei,GLboolean,const GLdouble*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix3x4dvEXT)(GLuint,GLint,GLsizei,GLboolean,const GLdouble*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix3x4fv)(GLuint,GLint,GLsizei,GLboolean,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix3x4fvEXT)(GLuint,GLint,GLsizei,GLboolean,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix4dv)(GLuint,GLint,GLsizei,GLboolean,const GLdouble*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix4dvEXT)(GLuint,GLint,GLsizei,GLboolean,const GLdouble*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix4fv)(GLuint,GLint,GLsizei,GLboolean,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix4fvEXT)(GLuint,GLint,GLsizei,GLboolean,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix4x2dv)(GLuint,GLint,GLsizei,GLboolean,const GLdouble*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix4x2dvEXT)(GLuint,GLint,GLsizei,GLboolean,const GLdouble*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix4x2fv)(GLuint,GLint,GLsizei,GLboolean,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix4x2fvEXT)(GLuint,GLint,GLsizei,GLboolean,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix4x3dv)(GLuint,GLint,GLsizei,GLboolean,const GLdouble*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix4x3dvEXT)(GLuint,GLint,GLsizei,GLboolean,const GLdouble*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix4x3fv)(GLuint,GLint,GLsizei,GLboolean,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramUniformMatrix4x3fvEXT)(GLuint,GLint,GLsizei,GLboolean,const GLfloat*);
+        void       (WINE_GLAPI *p_glProgramUniformui64NV)(GLuint,GLint,UINT64);
+        void       (WINE_GLAPI *p_glProgramUniformui64vNV)(GLuint,GLint,GLsizei,const UINT64*);
+        void       (WINE_GLAPI *p_glProgramVertexLimitNV)(GLenum,GLint);
+        void       (WINE_GLAPI *p_glProvokingVertex)(GLenum);
+        void       (WINE_GLAPI *p_glProvokingVertexEXT)(GLenum);
+        void       (WINE_GLAPI *p_glPushClientAttribDefaultEXT)(GLbitfield);
+        void       (WINE_GLAPI *p_glPushDebugGroup)(GLenum,GLuint,GLsizei,const GLchar*);
+        void       (WINE_GLAPI *p_glQueryCounter)(GLuint,GLenum);
+        void       (WINE_GLAPI *p_glReadBufferRegion)(GLenum,GLint,GLint,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glReadInstrumentsSGIX)(GLint);
+        void       (WINE_GLAPI *p_glReadnPixelsARB)(GLint,GLint,GLsizei,GLsizei,GLenum,GLenum,GLsizei,GLvoid*);
+        void       (WINE_GLAPI *p_glReferencePlaneSGIX)(const GLdouble*);
+        void       (WINE_GLAPI *p_glReleaseShaderCompiler)(void);
+        void       (WINE_GLAPI *p_glRenderbufferStorage)(GLenum,GLenum,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glRenderbufferStorageEXT)(GLenum,GLenum,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glRenderbufferStorageMultisample)(GLenum,GLsizei,GLenum,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glRenderbufferStorageMultisampleCoverageNV)(GLenum,GLsizei,GLsizei,GLenum,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glRenderbufferStorageMultisampleEXT)(GLenum,GLsizei,GLenum,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glReplacementCodePointerSUN)(GLenum,GLsizei,const GLvoid**);
+        void       (WINE_GLAPI *p_glReplacementCodeubSUN)(GLubyte);
+        void       (WINE_GLAPI *p_glReplacementCodeubvSUN)(const GLubyte*);
+        void       (WINE_GLAPI *p_glReplacementCodeuiColor3fVertex3fSUN)(GLuint,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glReplacementCodeuiColor3fVertex3fvSUN)(const GLuint*,const GLfloat*,const GLfloat*);
+        void       (WINE_GLAPI *p_glReplacementCodeuiColor4fNormal3fVertex3fSUN)(GLuint,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glReplacementCodeuiColor4fNormal3fVertex3fvSUN)(const GLuint*,const GLfloat*,const GLfloat*,const GLfloat*);
+        void       (WINE_GLAPI *p_glReplacementCodeuiColor4ubVertex3fSUN)(GLuint,GLubyte,GLubyte,GLubyte,GLubyte,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glReplacementCodeuiColor4ubVertex3fvSUN)(const GLuint*,const GLubyte*,const GLfloat*);
+        void       (WINE_GLAPI *p_glReplacementCodeuiNormal3fVertex3fSUN)(GLuint,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glReplacementCodeuiNormal3fVertex3fvSUN)(const GLuint*,const GLfloat*,const GLfloat*);
+        void       (WINE_GLAPI *p_glReplacementCodeuiSUN)(GLuint);
+        void       (WINE_GLAPI *p_glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN)(GLuint,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN)(const GLuint*,const GLfloat*,const GLfloat*,const GLfloat*,const GLfloat*);
+        void       (WINE_GLAPI *p_glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN)(GLuint,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN)(const GLuint*,const GLfloat*,const GLfloat*,const GLfloat*);
+        void       (WINE_GLAPI *p_glReplacementCodeuiTexCoord2fVertex3fSUN)(GLuint,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glReplacementCodeuiTexCoord2fVertex3fvSUN)(const GLuint*,const GLfloat*,const GLfloat*);
+        void       (WINE_GLAPI *p_glReplacementCodeuiVertex3fSUN)(GLuint,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glReplacementCodeuiVertex3fvSUN)(const GLuint*,const GLfloat*);
+        void       (WINE_GLAPI *p_glReplacementCodeuivSUN)(const GLuint*);
+        void       (WINE_GLAPI *p_glReplacementCodeusSUN)(GLushort);
+        void       (WINE_GLAPI *p_glReplacementCodeusvSUN)(const GLushort*);
+        void       (WINE_GLAPI *p_glRequestResidentProgramsNV)(GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glResetHistogram)(GLenum);
+        void       (WINE_GLAPI *p_glResetHistogramEXT)(GLenum);
+        void       (WINE_GLAPI *p_glResetMinmax)(GLenum);
+        void       (WINE_GLAPI *p_glResetMinmaxEXT)(GLenum);
+        void       (WINE_GLAPI *p_glResizeBuffersMESA)(void);
+        void       (WINE_GLAPI *p_glResumeTransformFeedback)(void);
+        void       (WINE_GLAPI *p_glResumeTransformFeedbackNV)(void);
+        void       (WINE_GLAPI *p_glSampleCoverage)(GLfloat,GLboolean);
+        void       (WINE_GLAPI *p_glSampleCoverageARB)(GLfloat,GLboolean);
+        void       (WINE_GLAPI *p_glSampleMapATI)(GLuint,GLuint,GLenum);
+        void       (WINE_GLAPI *p_glSampleMaskEXT)(GLclampf,GLboolean);
+        void       (WINE_GLAPI *p_glSampleMaskIndexedNV)(GLuint,GLbitfield);
+        void       (WINE_GLAPI *p_glSampleMaskSGIS)(GLclampf,GLboolean);
+        void       (WINE_GLAPI *p_glSampleMaski)(GLuint,GLbitfield);
+        void       (WINE_GLAPI *p_glSamplePatternEXT)(GLenum);
+        void       (WINE_GLAPI *p_glSamplePatternSGIS)(GLenum);
+        void       (WINE_GLAPI *p_glSamplerParameterIiv)(GLuint,GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glSamplerParameterIuiv)(GLuint,GLenum,const GLuint*);
+        void       (WINE_GLAPI *p_glSamplerParameterf)(GLuint,GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glSamplerParameterfv)(GLuint,GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glSamplerParameteri)(GLuint,GLenum,GLint);
+        void       (WINE_GLAPI *p_glSamplerParameteriv)(GLuint,GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glScissorArrayv)(GLuint,GLsizei,const GLint*);
+        void       (WINE_GLAPI *p_glScissorIndexed)(GLuint,GLint,GLint,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glScissorIndexedv)(GLuint,const GLint*);
+        void       (WINE_GLAPI *p_glSecondaryColor3b)(GLbyte,GLbyte,GLbyte);
+        void       (WINE_GLAPI *p_glSecondaryColor3bEXT)(GLbyte,GLbyte,GLbyte);
+        void       (WINE_GLAPI *p_glSecondaryColor3bv)(const GLbyte*);
+        void       (WINE_GLAPI *p_glSecondaryColor3bvEXT)(const GLbyte*);
+        void       (WINE_GLAPI *p_glSecondaryColor3d)(GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glSecondaryColor3dEXT)(GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glSecondaryColor3dv)(const GLdouble*);
+        void       (WINE_GLAPI *p_glSecondaryColor3dvEXT)(const GLdouble*);
+        void       (WINE_GLAPI *p_glSecondaryColor3f)(GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glSecondaryColor3fEXT)(GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glSecondaryColor3fv)(const GLfloat*);
+        void       (WINE_GLAPI *p_glSecondaryColor3fvEXT)(const GLfloat*);
+        void       (WINE_GLAPI *p_glSecondaryColor3hNV)(GLhalfNV,GLhalfNV,GLhalfNV);
+        void       (WINE_GLAPI *p_glSecondaryColor3hvNV)(const GLhalfNV*);
+        void       (WINE_GLAPI *p_glSecondaryColor3i)(GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glSecondaryColor3iEXT)(GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glSecondaryColor3iv)(const GLint*);
+        void       (WINE_GLAPI *p_glSecondaryColor3ivEXT)(const GLint*);
+        void       (WINE_GLAPI *p_glSecondaryColor3s)(GLshort,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glSecondaryColor3sEXT)(GLshort,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glSecondaryColor3sv)(const GLshort*);
+        void       (WINE_GLAPI *p_glSecondaryColor3svEXT)(const GLshort*);
+        void       (WINE_GLAPI *p_glSecondaryColor3ub)(GLubyte,GLubyte,GLubyte);
+        void       (WINE_GLAPI *p_glSecondaryColor3ubEXT)(GLubyte,GLubyte,GLubyte);
+        void       (WINE_GLAPI *p_glSecondaryColor3ubv)(const GLubyte*);
+        void       (WINE_GLAPI *p_glSecondaryColor3ubvEXT)(const GLubyte*);
+        void       (WINE_GLAPI *p_glSecondaryColor3ui)(GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glSecondaryColor3uiEXT)(GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glSecondaryColor3uiv)(const GLuint*);
+        void       (WINE_GLAPI *p_glSecondaryColor3uivEXT)(const GLuint*);
+        void       (WINE_GLAPI *p_glSecondaryColor3us)(GLushort,GLushort,GLushort);
+        void       (WINE_GLAPI *p_glSecondaryColor3usEXT)(GLushort,GLushort,GLushort);
+        void       (WINE_GLAPI *p_glSecondaryColor3usv)(const GLushort*);
+        void       (WINE_GLAPI *p_glSecondaryColor3usvEXT)(const GLushort*);
+        void       (WINE_GLAPI *p_glSecondaryColorFormatNV)(GLint,GLenum,GLsizei);
+        void       (WINE_GLAPI *p_glSecondaryColorP3ui)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glSecondaryColorP3uiv)(GLenum,const GLuint*);
+        void       (WINE_GLAPI *p_glSecondaryColorPointer)(GLint,GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glSecondaryColorPointerEXT)(GLint,GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glSecondaryColorPointerListIBM)(GLint,GLenum,GLint,const GLvoid**,GLint);
+        void       (WINE_GLAPI *p_glSelectPerfMonitorCountersAMD)(GLuint,GLboolean,GLuint,GLint,GLuint*);
+        void       (WINE_GLAPI *p_glSelectTextureCoordSetSGIS)(GLenum);
+        void       (WINE_GLAPI *p_glSelectTextureSGIS)(GLenum);
+        void       (WINE_GLAPI *p_glSeparableFilter2D)(GLenum,GLenum,GLsizei,GLsizei,GLenum,GLenum,const GLvoid*,const GLvoid*);
+        void       (WINE_GLAPI *p_glSeparableFilter2DEXT)(GLenum,GLenum,GLsizei,GLsizei,GLenum,GLenum,const GLvoid*,const GLvoid*);
+        void       (WINE_GLAPI *p_glSetFenceAPPLE)(GLuint);
+        void       (WINE_GLAPI *p_glSetFenceNV)(GLuint,GLenum);
+        void       (WINE_GLAPI *p_glSetFragmentShaderConstantATI)(GLuint,const GLfloat*);
+        void       (WINE_GLAPI *p_glSetInvariantEXT)(GLuint,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glSetLocalConstantEXT)(GLuint,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glSetMultisamplefvAMD)(GLenum,GLuint,const GLfloat*);
+        void       (WINE_GLAPI *p_glShaderBinary)(GLsizei,const GLuint*,GLenum,const GLvoid*,GLsizei);
+        void       (WINE_GLAPI *p_glShaderOp1EXT)(GLenum,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glShaderOp2EXT)(GLenum,GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glShaderOp3EXT)(GLenum,GLuint,GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glShaderSource)(GLuint,GLsizei,const GLchar* const*,const GLint*);
+        void       (WINE_GLAPI *p_glShaderSourceARB)(GLhandleARB,GLsizei,const GLcharARB**,const GLint*);
+        void       (WINE_GLAPI *p_glShaderStorageBlockBinding)(GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glSharpenTexFuncSGIS)(GLenum,GLsizei,const GLfloat*);
+        void       (WINE_GLAPI *p_glSpriteParameterfSGIX)(GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glSpriteParameterfvSGIX)(GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glSpriteParameteriSGIX)(GLenum,GLint);
+        void       (WINE_GLAPI *p_glSpriteParameterivSGIX)(GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glStartInstrumentsSGIX)(void);
+        void       (WINE_GLAPI *p_glStencilClearTagEXT)(GLsizei,GLuint);
+        void       (WINE_GLAPI *p_glStencilFillPathInstancedNV)(GLsizei,GLenum,const GLvoid*,GLuint,GLenum,GLuint,GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glStencilFillPathNV)(GLuint,GLenum,GLuint);
+        void       (WINE_GLAPI *p_glStencilFuncSeparate)(GLenum,GLenum,GLint,GLuint);
+        void       (WINE_GLAPI *p_glStencilFuncSeparateATI)(GLenum,GLenum,GLint,GLuint);
+        void       (WINE_GLAPI *p_glStencilMaskSeparate)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glStencilOpSeparate)(GLenum,GLenum,GLenum,GLenum);
+        void       (WINE_GLAPI *p_glStencilOpSeparateATI)(GLenum,GLenum,GLenum,GLenum);
+        void       (WINE_GLAPI *p_glStencilOpValueAMD)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glStencilStrokePathInstancedNV)(GLsizei,GLenum,const GLvoid*,GLuint,GLint,GLuint,GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glStencilStrokePathNV)(GLuint,GLint,GLuint);
+        void       (WINE_GLAPI *p_glStopInstrumentsSGIX)(GLint);
+        void       (WINE_GLAPI *p_glStringMarkerGREMEDY)(GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glSwizzleEXT)(GLuint,GLuint,GLenum,GLenum,GLenum,GLenum);
+        void       (WINE_GLAPI *p_glTagSampleBufferSGIX)(void);
+        void       (WINE_GLAPI *p_glTangent3bEXT)(GLbyte,GLbyte,GLbyte);
+        void       (WINE_GLAPI *p_glTangent3bvEXT)(const GLbyte*);
+        void       (WINE_GLAPI *p_glTangent3dEXT)(GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glTangent3dvEXT)(const GLdouble*);
+        void       (WINE_GLAPI *p_glTangent3fEXT)(GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glTangent3fvEXT)(const GLfloat*);
+        void       (WINE_GLAPI *p_glTangent3iEXT)(GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glTangent3ivEXT)(const GLint*);
+        void       (WINE_GLAPI *p_glTangent3sEXT)(GLshort,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glTangent3svEXT)(const GLshort*);
+        void       (WINE_GLAPI *p_glTangentPointerEXT)(GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glTbufferMask3DFX)(GLuint);
+        void       (WINE_GLAPI *p_glTessellationFactorAMD)(GLfloat);
+        void       (WINE_GLAPI *p_glTessellationModeAMD)(GLenum);
+        GLboolean  (WINE_GLAPI *p_glTestFenceAPPLE)(GLuint);
+        GLboolean  (WINE_GLAPI *p_glTestFenceNV)(GLuint);
+        GLboolean  (WINE_GLAPI *p_glTestObjectAPPLE)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glTexBuffer)(GLenum,GLenum,GLuint);
+        void       (WINE_GLAPI *p_glTexBufferARB)(GLenum,GLenum,GLuint);
+        void       (WINE_GLAPI *p_glTexBufferEXT)(GLenum,GLenum,GLuint);
+        void       (WINE_GLAPI *p_glTexBufferRange)(GLenum,GLenum,GLuint,GLintptr,GLsizeiptr);
+        void       (WINE_GLAPI *p_glTexBumpParameterfvATI)(GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glTexBumpParameterivATI)(GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glTexCoord1hNV)(GLhalfNV);
+        void       (WINE_GLAPI *p_glTexCoord1hvNV)(const GLhalfNV*);
+        void       (WINE_GLAPI *p_glTexCoord2fColor3fVertex3fSUN)(GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glTexCoord2fColor3fVertex3fvSUN)(const GLfloat*,const GLfloat*,const GLfloat*);
+        void       (WINE_GLAPI *p_glTexCoord2fColor4fNormal3fVertex3fSUN)(GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glTexCoord2fColor4fNormal3fVertex3fvSUN)(const GLfloat*,const GLfloat*,const GLfloat*,const GLfloat*);
+        void       (WINE_GLAPI *p_glTexCoord2fColor4ubVertex3fSUN)(GLfloat,GLfloat,GLubyte,GLubyte,GLubyte,GLubyte,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glTexCoord2fColor4ubVertex3fvSUN)(const GLfloat*,const GLubyte*,const GLfloat*);
+        void       (WINE_GLAPI *p_glTexCoord2fNormal3fVertex3fSUN)(GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glTexCoord2fNormal3fVertex3fvSUN)(const GLfloat*,const GLfloat*,const GLfloat*);
+        void       (WINE_GLAPI *p_glTexCoord2fVertex3fSUN)(GLfloat,GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glTexCoord2fVertex3fvSUN)(const GLfloat*,const GLfloat*);
+        void       (WINE_GLAPI *p_glTexCoord2hNV)(GLhalfNV,GLhalfNV);
+        void       (WINE_GLAPI *p_glTexCoord2hvNV)(const GLhalfNV*);
+        void       (WINE_GLAPI *p_glTexCoord3hNV)(GLhalfNV,GLhalfNV,GLhalfNV);
+        void       (WINE_GLAPI *p_glTexCoord3hvNV)(const GLhalfNV*);
+        void       (WINE_GLAPI *p_glTexCoord4fColor4fNormal3fVertex4fSUN)(GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glTexCoord4fColor4fNormal3fVertex4fvSUN)(const GLfloat*,const GLfloat*,const GLfloat*,const GLfloat*);
+        void       (WINE_GLAPI *p_glTexCoord4fVertex4fSUN)(GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glTexCoord4fVertex4fvSUN)(const GLfloat*,const GLfloat*);
+        void       (WINE_GLAPI *p_glTexCoord4hNV)(GLhalfNV,GLhalfNV,GLhalfNV,GLhalfNV);
+        void       (WINE_GLAPI *p_glTexCoord4hvNV)(const GLhalfNV*);
+        void       (WINE_GLAPI *p_glTexCoordFormatNV)(GLint,GLenum,GLsizei);
+        void       (WINE_GLAPI *p_glTexCoordP1ui)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glTexCoordP1uiv)(GLenum,const GLuint*);
+        void       (WINE_GLAPI *p_glTexCoordP2ui)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glTexCoordP2uiv)(GLenum,const GLuint*);
+        void       (WINE_GLAPI *p_glTexCoordP3ui)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glTexCoordP3uiv)(GLenum,const GLuint*);
+        void       (WINE_GLAPI *p_glTexCoordP4ui)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glTexCoordP4uiv)(GLenum,const GLuint*);
+        void       (WINE_GLAPI *p_glTexCoordPointerEXT)(GLint,GLenum,GLsizei,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glTexCoordPointerListIBM)(GLint,GLenum,GLint,const GLvoid**,GLint);
+        void       (WINE_GLAPI *p_glTexCoordPointervINTEL)(GLint,GLenum,const GLvoid**);
+        void       (WINE_GLAPI *p_glTexFilterFuncSGIS)(GLenum,GLenum,GLsizei,const GLfloat*);
+        void       (WINE_GLAPI *p_glTexImage2DMultisample)(GLenum,GLsizei,GLint,GLsizei,GLsizei,GLboolean);
+        void       (WINE_GLAPI *p_glTexImage2DMultisampleCoverageNV)(GLenum,GLsizei,GLsizei,GLint,GLsizei,GLsizei,GLboolean);
+        void       (WINE_GLAPI *p_glTexImage3D)(GLenum,GLint,GLint,GLsizei,GLsizei,GLsizei,GLint,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glTexImage3DEXT)(GLenum,GLint,GLenum,GLsizei,GLsizei,GLsizei,GLint,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glTexImage3DMultisample)(GLenum,GLsizei,GLint,GLsizei,GLsizei,GLsizei,GLboolean);
+        void       (WINE_GLAPI *p_glTexImage3DMultisampleCoverageNV)(GLenum,GLsizei,GLsizei,GLint,GLsizei,GLsizei,GLsizei,GLboolean);
+        void       (WINE_GLAPI *p_glTexImage4DSGIS)(GLenum,GLint,GLenum,GLsizei,GLsizei,GLsizei,GLsizei,GLint,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glTexParameterIiv)(GLenum,GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glTexParameterIivEXT)(GLenum,GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glTexParameterIuiv)(GLenum,GLenum,const GLuint*);
+        void       (WINE_GLAPI *p_glTexParameterIuivEXT)(GLenum,GLenum,const GLuint*);
+        void       (WINE_GLAPI *p_glTexRenderbufferNV)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glTexStorage1D)(GLenum,GLsizei,GLenum,GLsizei);
+        void       (WINE_GLAPI *p_glTexStorage2D)(GLenum,GLsizei,GLenum,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glTexStorage2DMultisample)(GLenum,GLsizei,GLenum,GLsizei,GLsizei,GLboolean);
+        void       (WINE_GLAPI *p_glTexStorage3D)(GLenum,GLsizei,GLenum,GLsizei,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glTexStorage3DMultisample)(GLenum,GLsizei,GLenum,GLsizei,GLsizei,GLsizei,GLboolean);
+        void       (WINE_GLAPI *p_glTexStorageSparseAMD)(GLenum,GLenum,GLsizei,GLsizei,GLsizei,GLsizei,GLbitfield);
+        void       (WINE_GLAPI *p_glTexSubImage1DEXT)(GLenum,GLint,GLint,GLsizei,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glTexSubImage2DEXT)(GLenum,GLint,GLint,GLint,GLsizei,GLsizei,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glTexSubImage3D)(GLenum,GLint,GLint,GLint,GLint,GLsizei,GLsizei,GLsizei,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glTexSubImage3DEXT)(GLenum,GLint,GLint,GLint,GLint,GLsizei,GLsizei,GLsizei,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glTexSubImage4DSGIS)(GLenum,GLint,GLint,GLint,GLint,GLint,GLsizei,GLsizei,GLsizei,GLsizei,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glTextureBarrierNV)(void);
+        void       (WINE_GLAPI *p_glTextureBufferEXT)(GLuint,GLenum,GLenum,GLuint);
+        void       (WINE_GLAPI *p_glTextureBufferRangeEXT)(GLuint,GLenum,GLenum,GLuint,GLintptr,GLsizeiptr);
+        void       (WINE_GLAPI *p_glTextureColorMaskSGIS)(GLboolean,GLboolean,GLboolean,GLboolean);
+        void       (WINE_GLAPI *p_glTextureImage1DEXT)(GLuint,GLenum,GLint,GLenum,GLsizei,GLint,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glTextureImage2DEXT)(GLuint,GLenum,GLint,GLenum,GLsizei,GLsizei,GLint,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glTextureImage2DMultisampleCoverageNV)(GLuint,GLenum,GLsizei,GLsizei,GLint,GLsizei,GLsizei,GLboolean);
+        void       (WINE_GLAPI *p_glTextureImage2DMultisampleNV)(GLuint,GLenum,GLsizei,GLint,GLsizei,GLsizei,GLboolean);
+        void       (WINE_GLAPI *p_glTextureImage3DEXT)(GLuint,GLenum,GLint,GLenum,GLsizei,GLsizei,GLsizei,GLint,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glTextureImage3DMultisampleCoverageNV)(GLuint,GLenum,GLsizei,GLsizei,GLint,GLsizei,GLsizei,GLsizei,GLboolean);
+        void       (WINE_GLAPI *p_glTextureImage3DMultisampleNV)(GLuint,GLenum,GLsizei,GLint,GLsizei,GLsizei,GLsizei,GLboolean);
+        void       (WINE_GLAPI *p_glTextureLightEXT)(GLenum);
+        void       (WINE_GLAPI *p_glTextureMaterialEXT)(GLenum,GLenum);
+        void       (WINE_GLAPI *p_glTextureNormalEXT)(GLenum);
+        void       (WINE_GLAPI *p_glTextureParameterIivEXT)(GLuint,GLenum,GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glTextureParameterIuivEXT)(GLuint,GLenum,GLenum,const GLuint*);
+        void       (WINE_GLAPI *p_glTextureParameterfEXT)(GLuint,GLenum,GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glTextureParameterfvEXT)(GLuint,GLenum,GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glTextureParameteriEXT)(GLuint,GLenum,GLenum,GLint);
+        void       (WINE_GLAPI *p_glTextureParameterivEXT)(GLuint,GLenum,GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glTextureRangeAPPLE)(GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glTextureRenderbufferEXT)(GLuint,GLenum,GLuint);
+        void       (WINE_GLAPI *p_glTextureStorage1DEXT)(GLuint,GLenum,GLsizei,GLenum,GLsizei);
+        void       (WINE_GLAPI *p_glTextureStorage2DEXT)(GLuint,GLenum,GLsizei,GLenum,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glTextureStorage2DMultisampleEXT)(GLuint,GLenum,GLsizei,GLenum,GLsizei,GLsizei,GLboolean);
+        void       (WINE_GLAPI *p_glTextureStorage3DEXT)(GLuint,GLenum,GLsizei,GLenum,GLsizei,GLsizei,GLsizei);
+        void       (WINE_GLAPI *p_glTextureStorage3DMultisampleEXT)(GLuint,GLenum,GLsizei,GLenum,GLsizei,GLsizei,GLsizei,GLboolean);
+        void       (WINE_GLAPI *p_glTextureStorageSparseAMD)(GLuint,GLenum,GLenum,GLsizei,GLsizei,GLsizei,GLsizei,GLbitfield);
+        void       (WINE_GLAPI *p_glTextureSubImage1DEXT)(GLuint,GLenum,GLint,GLint,GLsizei,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glTextureSubImage2DEXT)(GLuint,GLenum,GLint,GLint,GLint,GLsizei,GLsizei,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glTextureSubImage3DEXT)(GLuint,GLenum,GLint,GLint,GLint,GLint,GLsizei,GLsizei,GLsizei,GLenum,GLenum,const GLvoid*);
+        void       (WINE_GLAPI *p_glTextureView)(GLuint,GLenum,GLuint,GLenum,GLuint,GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glTrackMatrixNV)(GLenum,GLuint,GLenum,GLenum);
+        void       (WINE_GLAPI *p_glTransformFeedbackAttribsNV)(GLuint,const GLint*,GLenum);
+        void       (WINE_GLAPI *p_glTransformFeedbackStreamAttribsNV)(GLsizei,const GLint*,GLsizei,const GLint*,GLenum);
+        void       (WINE_GLAPI *p_glTransformFeedbackVaryings)(GLuint,GLsizei,const GLchar* const*,GLenum);
+        void       (WINE_GLAPI *p_glTransformFeedbackVaryingsEXT)(GLuint,GLsizei,const GLchar**,GLenum);
+        void       (WINE_GLAPI *p_glTransformFeedbackVaryingsNV)(GLuint,GLsizei,const GLint*,GLenum);
+        void       (WINE_GLAPI *p_glTransformPathNV)(GLuint,GLuint,GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glUniform1d)(GLint,GLdouble);
+        void       (WINE_GLAPI *p_glUniform1dv)(GLint,GLsizei,const GLdouble*);
+        void       (WINE_GLAPI *p_glUniform1f)(GLint,GLfloat);
+        void       (WINE_GLAPI *p_glUniform1fARB)(GLint,GLfloat);
+        void       (WINE_GLAPI *p_glUniform1fv)(GLint,GLsizei,const GLfloat*);
+        void       (WINE_GLAPI *p_glUniform1fvARB)(GLint,GLsizei,const GLfloat*);
+        void       (WINE_GLAPI *p_glUniform1i)(GLint,GLint);
+        void       (WINE_GLAPI *p_glUniform1i64NV)(GLint,INT64);
+        void       (WINE_GLAPI *p_glUniform1i64vNV)(GLint,GLsizei,const INT64*);
+        void       (WINE_GLAPI *p_glUniform1iARB)(GLint,GLint);
+        void       (WINE_GLAPI *p_glUniform1iv)(GLint,GLsizei,const GLint*);
+        void       (WINE_GLAPI *p_glUniform1ivARB)(GLint,GLsizei,const GLint*);
+        void       (WINE_GLAPI *p_glUniform1ui)(GLint,GLuint);
+        void       (WINE_GLAPI *p_glUniform1ui64NV)(GLint,UINT64);
+        void       (WINE_GLAPI *p_glUniform1ui64vNV)(GLint,GLsizei,const UINT64*);
+        void       (WINE_GLAPI *p_glUniform1uiEXT)(GLint,GLuint);
+        void       (WINE_GLAPI *p_glUniform1uiv)(GLint,GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glUniform1uivEXT)(GLint,GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glUniform2d)(GLint,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glUniform2dv)(GLint,GLsizei,const GLdouble*);
+        void       (WINE_GLAPI *p_glUniform2f)(GLint,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glUniform2fARB)(GLint,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glUniform2fv)(GLint,GLsizei,const GLfloat*);
+        void       (WINE_GLAPI *p_glUniform2fvARB)(GLint,GLsizei,const GLfloat*);
+        void       (WINE_GLAPI *p_glUniform2i)(GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glUniform2i64NV)(GLint,INT64,INT64);
+        void       (WINE_GLAPI *p_glUniform2i64vNV)(GLint,GLsizei,const INT64*);
+        void       (WINE_GLAPI *p_glUniform2iARB)(GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glUniform2iv)(GLint,GLsizei,const GLint*);
+        void       (WINE_GLAPI *p_glUniform2ivARB)(GLint,GLsizei,const GLint*);
+        void       (WINE_GLAPI *p_glUniform2ui)(GLint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glUniform2ui64NV)(GLint,UINT64,UINT64);
+        void       (WINE_GLAPI *p_glUniform2ui64vNV)(GLint,GLsizei,const UINT64*);
+        void       (WINE_GLAPI *p_glUniform2uiEXT)(GLint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glUniform2uiv)(GLint,GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glUniform2uivEXT)(GLint,GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glUniform3d)(GLint,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glUniform3dv)(GLint,GLsizei,const GLdouble*);
+        void       (WINE_GLAPI *p_glUniform3f)(GLint,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glUniform3fARB)(GLint,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glUniform3fv)(GLint,GLsizei,const GLfloat*);
+        void       (WINE_GLAPI *p_glUniform3fvARB)(GLint,GLsizei,const GLfloat*);
+        void       (WINE_GLAPI *p_glUniform3i)(GLint,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glUniform3i64NV)(GLint,INT64,INT64,INT64);
+        void       (WINE_GLAPI *p_glUniform3i64vNV)(GLint,GLsizei,const INT64*);
+        void       (WINE_GLAPI *p_glUniform3iARB)(GLint,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glUniform3iv)(GLint,GLsizei,const GLint*);
+        void       (WINE_GLAPI *p_glUniform3ivARB)(GLint,GLsizei,const GLint*);
+        void       (WINE_GLAPI *p_glUniform3ui)(GLint,GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glUniform3ui64NV)(GLint,UINT64,UINT64,UINT64);
+        void       (WINE_GLAPI *p_glUniform3ui64vNV)(GLint,GLsizei,const UINT64*);
+        void       (WINE_GLAPI *p_glUniform3uiEXT)(GLint,GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glUniform3uiv)(GLint,GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glUniform3uivEXT)(GLint,GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glUniform4d)(GLint,GLdouble,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glUniform4dv)(GLint,GLsizei,const GLdouble*);
+        void       (WINE_GLAPI *p_glUniform4f)(GLint,GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glUniform4fARB)(GLint,GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glUniform4fv)(GLint,GLsizei,const GLfloat*);
+        void       (WINE_GLAPI *p_glUniform4fvARB)(GLint,GLsizei,const GLfloat*);
+        void       (WINE_GLAPI *p_glUniform4i)(GLint,GLint,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glUniform4i64NV)(GLint,INT64,INT64,INT64,INT64);
+        void       (WINE_GLAPI *p_glUniform4i64vNV)(GLint,GLsizei,const INT64*);
+        void       (WINE_GLAPI *p_glUniform4iARB)(GLint,GLint,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glUniform4iv)(GLint,GLsizei,const GLint*);
+        void       (WINE_GLAPI *p_glUniform4ivARB)(GLint,GLsizei,const GLint*);
+        void       (WINE_GLAPI *p_glUniform4ui)(GLint,GLuint,GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glUniform4ui64NV)(GLint,UINT64,UINT64,UINT64,UINT64);
+        void       (WINE_GLAPI *p_glUniform4ui64vNV)(GLint,GLsizei,const UINT64*);
+        void       (WINE_GLAPI *p_glUniform4uiEXT)(GLint,GLuint,GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glUniform4uiv)(GLint,GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glUniform4uivEXT)(GLint,GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glUniformBlockBinding)(GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glUniformBufferEXT)(GLuint,GLint,GLuint);
+        void       (WINE_GLAPI *p_glUniformHandleui64NV)(GLint,UINT64);
+        void       (WINE_GLAPI *p_glUniformHandleui64vNV)(GLint,GLsizei,const UINT64*);
+        void       (WINE_GLAPI *p_glUniformMatrix2dv)(GLint,GLsizei,GLboolean,const GLdouble*);
+        void       (WINE_GLAPI *p_glUniformMatrix2fv)(GLint,GLsizei,GLboolean,const GLfloat*);
+        void       (WINE_GLAPI *p_glUniformMatrix2fvARB)(GLint,GLsizei,GLboolean,const GLfloat*);
+        void       (WINE_GLAPI *p_glUniformMatrix2x3dv)(GLint,GLsizei,GLboolean,const GLdouble*);
+        void       (WINE_GLAPI *p_glUniformMatrix2x3fv)(GLint,GLsizei,GLboolean,const GLfloat*);
+        void       (WINE_GLAPI *p_glUniformMatrix2x4dv)(GLint,GLsizei,GLboolean,const GLdouble*);
+        void       (WINE_GLAPI *p_glUniformMatrix2x4fv)(GLint,GLsizei,GLboolean,const GLfloat*);
+        void       (WINE_GLAPI *p_glUniformMatrix3dv)(GLint,GLsizei,GLboolean,const GLdouble*);
+        void       (WINE_GLAPI *p_glUniformMatrix3fv)(GLint,GLsizei,GLboolean,const GLfloat*);
+        void       (WINE_GLAPI *p_glUniformMatrix3fvARB)(GLint,GLsizei,GLboolean,const GLfloat*);
+        void       (WINE_GLAPI *p_glUniformMatrix3x2dv)(GLint,GLsizei,GLboolean,const GLdouble*);
+        void       (WINE_GLAPI *p_glUniformMatrix3x2fv)(GLint,GLsizei,GLboolean,const GLfloat*);
+        void       (WINE_GLAPI *p_glUniformMatrix3x4dv)(GLint,GLsizei,GLboolean,const GLdouble*);
+        void       (WINE_GLAPI *p_glUniformMatrix3x4fv)(GLint,GLsizei,GLboolean,const GLfloat*);
+        void       (WINE_GLAPI *p_glUniformMatrix4dv)(GLint,GLsizei,GLboolean,const GLdouble*);
+        void       (WINE_GLAPI *p_glUniformMatrix4fv)(GLint,GLsizei,GLboolean,const GLfloat*);
+        void       (WINE_GLAPI *p_glUniformMatrix4fvARB)(GLint,GLsizei,GLboolean,const GLfloat*);
+        void       (WINE_GLAPI *p_glUniformMatrix4x2dv)(GLint,GLsizei,GLboolean,const GLdouble*);
+        void       (WINE_GLAPI *p_glUniformMatrix4x2fv)(GLint,GLsizei,GLboolean,const GLfloat*);
+        void       (WINE_GLAPI *p_glUniformMatrix4x3dv)(GLint,GLsizei,GLboolean,const GLdouble*);
+        void       (WINE_GLAPI *p_glUniformMatrix4x3fv)(GLint,GLsizei,GLboolean,const GLfloat*);
+        void       (WINE_GLAPI *p_glUniformSubroutinesuiv)(GLenum,GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glUniformui64NV)(GLint,UINT64);
+        void       (WINE_GLAPI *p_glUniformui64vNV)(GLint,GLsizei,const UINT64*);
+        void       (WINE_GLAPI *p_glUnlockArraysEXT)(void);
+        GLboolean  (WINE_GLAPI *p_glUnmapBuffer)(GLenum);
+        GLboolean  (WINE_GLAPI *p_glUnmapBufferARB)(GLenum);
+        GLboolean  (WINE_GLAPI *p_glUnmapNamedBufferEXT)(GLuint);
+        void       (WINE_GLAPI *p_glUnmapObjectBufferATI)(GLuint);
+        void       (WINE_GLAPI *p_glUpdateObjectBufferATI)(GLuint,GLuint,GLsizei,const GLvoid*,GLenum);
+        void       (WINE_GLAPI *p_glUseProgram)(GLuint);
+        void       (WINE_GLAPI *p_glUseProgramObjectARB)(GLhandleARB);
+        void       (WINE_GLAPI *p_glUseProgramStages)(GLuint,GLbitfield,GLuint);
+        void       (WINE_GLAPI *p_glUseShaderProgramEXT)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glVDPAUFiniNV)(void);
+        void       (WINE_GLAPI *p_glVDPAUGetSurfaceivNV)(GLvdpauSurfaceNV,GLenum,GLsizei,GLsizei*,GLint*);
+        void       (WINE_GLAPI *p_glVDPAUInitNV)(const GLvoid*,const GLvoid*);
+        void       (WINE_GLAPI *p_glVDPAUIsSurfaceNV)(GLvdpauSurfaceNV);
+        void       (WINE_GLAPI *p_glVDPAUMapSurfacesNV)(GLsizei,const GLvdpauSurfaceNV*);
+        GLvdpauSurfaceNV (WINE_GLAPI *p_glVDPAURegisterOutputSurfaceNV)(GLvoid*,GLenum,GLsizei,const GLuint*);
+        GLvdpauSurfaceNV (WINE_GLAPI *p_glVDPAURegisterVideoSurfaceNV)(const GLvoid*,GLenum,GLsizei,const GLuint*);
+        void       (WINE_GLAPI *p_glVDPAUSurfaceAccessNV)(GLvdpauSurfaceNV,GLenum);
+        void       (WINE_GLAPI *p_glVDPAUUnmapSurfacesNV)(GLsizei,const GLvdpauSurfaceNV*);
+        void       (WINE_GLAPI *p_glVDPAUUnregisterSurfaceNV)(GLvdpauSurfaceNV);
+        void       (WINE_GLAPI *p_glValidateProgram)(GLuint);
+        void       (WINE_GLAPI *p_glValidateProgramARB)(GLhandleARB);
+        void       (WINE_GLAPI *p_glValidateProgramPipeline)(GLuint);
+        void       (WINE_GLAPI *p_glVariantArrayObjectATI)(GLuint,GLenum,GLsizei,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glVariantPointerEXT)(GLuint,GLenum,GLuint,const GLvoid*);
+        void       (WINE_GLAPI *p_glVariantbvEXT)(GLuint,const GLbyte*);
+        void       (WINE_GLAPI *p_glVariantdvEXT)(GLuint,const GLdouble*);
+        void       (WINE_GLAPI *p_glVariantfvEXT)(GLuint,const GLfloat*);
+        void       (WINE_GLAPI *p_glVariantivEXT)(GLuint,const GLint*);
+        void       (WINE_GLAPI *p_glVariantsvEXT)(GLuint,const GLshort*);
+        void       (WINE_GLAPI *p_glVariantubvEXT)(GLuint,const GLubyte*);
+        void       (WINE_GLAPI *p_glVariantuivEXT)(GLuint,const GLuint*);
+        void       (WINE_GLAPI *p_glVariantusvEXT)(GLuint,const GLushort*);
+        void       (WINE_GLAPI *p_glVertex2hNV)(GLhalfNV,GLhalfNV);
+        void       (WINE_GLAPI *p_glVertex2hvNV)(const GLhalfNV*);
+        void       (WINE_GLAPI *p_glVertex3hNV)(GLhalfNV,GLhalfNV,GLhalfNV);
+        void       (WINE_GLAPI *p_glVertex3hvNV)(const GLhalfNV*);
+        void       (WINE_GLAPI *p_glVertex4hNV)(GLhalfNV,GLhalfNV,GLhalfNV,GLhalfNV);
+        void       (WINE_GLAPI *p_glVertex4hvNV)(const GLhalfNV*);
+        void       (WINE_GLAPI *p_glVertexArrayBindVertexBufferEXT)(GLuint,GLuint,GLuint,GLintptr,GLsizei);
+        void       (WINE_GLAPI *p_glVertexArrayParameteriAPPLE)(GLenum,GLint);
+        void       (WINE_GLAPI *p_glVertexArrayRangeAPPLE)(GLsizei,GLvoid*);
+        void       (WINE_GLAPI *p_glVertexArrayRangeNV)(GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glVertexArrayVertexAttribBindingEXT)(GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glVertexArrayVertexAttribFormatEXT)(GLuint,GLuint,GLint,GLenum,GLboolean,GLuint);
+        void       (WINE_GLAPI *p_glVertexArrayVertexAttribIFormatEXT)(GLuint,GLuint,GLint,GLenum,GLuint);
+        void       (WINE_GLAPI *p_glVertexArrayVertexAttribLFormatEXT)(GLuint,GLuint,GLint,GLenum,GLuint);
+        void       (WINE_GLAPI *p_glVertexArrayVertexAttribLOffsetEXT)(GLuint,GLuint,GLuint,GLint,GLenum,GLsizei,GLintptr);
+        void       (WINE_GLAPI *p_glVertexArrayVertexBindingDivisorEXT)(GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glVertexAttrib1d)(GLuint,GLdouble);
+        void       (WINE_GLAPI *p_glVertexAttrib1dARB)(GLuint,GLdouble);
+        void       (WINE_GLAPI *p_glVertexAttrib1dNV)(GLuint,GLdouble);
+        void       (WINE_GLAPI *p_glVertexAttrib1dv)(GLuint,const GLdouble*);
+        void       (WINE_GLAPI *p_glVertexAttrib1dvARB)(GLuint,const GLdouble*);
+        void       (WINE_GLAPI *p_glVertexAttrib1dvNV)(GLuint,const GLdouble*);
+        void       (WINE_GLAPI *p_glVertexAttrib1f)(GLuint,GLfloat);
+        void       (WINE_GLAPI *p_glVertexAttrib1fARB)(GLuint,GLfloat);
+        void       (WINE_GLAPI *p_glVertexAttrib1fNV)(GLuint,GLfloat);
+        void       (WINE_GLAPI *p_glVertexAttrib1fv)(GLuint,const GLfloat*);
+        void       (WINE_GLAPI *p_glVertexAttrib1fvARB)(GLuint,const GLfloat*);
+        void       (WINE_GLAPI *p_glVertexAttrib1fvNV)(GLuint,const GLfloat*);
+        void       (WINE_GLAPI *p_glVertexAttrib1hNV)(GLuint,GLhalfNV);
+        void       (WINE_GLAPI *p_glVertexAttrib1hvNV)(GLuint,const GLhalfNV*);
+        void       (WINE_GLAPI *p_glVertexAttrib1s)(GLuint,GLshort);
+        void       (WINE_GLAPI *p_glVertexAttrib1sARB)(GLuint,GLshort);
+        void       (WINE_GLAPI *p_glVertexAttrib1sNV)(GLuint,GLshort);
+        void       (WINE_GLAPI *p_glVertexAttrib1sv)(GLuint,const GLshort*);
+        void       (WINE_GLAPI *p_glVertexAttrib1svARB)(GLuint,const GLshort*);
+        void       (WINE_GLAPI *p_glVertexAttrib1svNV)(GLuint,const GLshort*);
+        void       (WINE_GLAPI *p_glVertexAttrib2d)(GLuint,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glVertexAttrib2dARB)(GLuint,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glVertexAttrib2dNV)(GLuint,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glVertexAttrib2dv)(GLuint,const GLdouble*);
+        void       (WINE_GLAPI *p_glVertexAttrib2dvARB)(GLuint,const GLdouble*);
+        void       (WINE_GLAPI *p_glVertexAttrib2dvNV)(GLuint,const GLdouble*);
+        void       (WINE_GLAPI *p_glVertexAttrib2f)(GLuint,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glVertexAttrib2fARB)(GLuint,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glVertexAttrib2fNV)(GLuint,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glVertexAttrib2fv)(GLuint,const GLfloat*);
+        void       (WINE_GLAPI *p_glVertexAttrib2fvARB)(GLuint,const GLfloat*);
+        void       (WINE_GLAPI *p_glVertexAttrib2fvNV)(GLuint,const GLfloat*);
+        void       (WINE_GLAPI *p_glVertexAttrib2hNV)(GLuint,GLhalfNV,GLhalfNV);
+        void       (WINE_GLAPI *p_glVertexAttrib2hvNV)(GLuint,const GLhalfNV*);
+        void       (WINE_GLAPI *p_glVertexAttrib2s)(GLuint,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glVertexAttrib2sARB)(GLuint,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glVertexAttrib2sNV)(GLuint,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glVertexAttrib2sv)(GLuint,const GLshort*);
+        void       (WINE_GLAPI *p_glVertexAttrib2svARB)(GLuint,const GLshort*);
+        void       (WINE_GLAPI *p_glVertexAttrib2svNV)(GLuint,const GLshort*);
+        void       (WINE_GLAPI *p_glVertexAttrib3d)(GLuint,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glVertexAttrib3dARB)(GLuint,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glVertexAttrib3dNV)(GLuint,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glVertexAttrib3dv)(GLuint,const GLdouble*);
+        void       (WINE_GLAPI *p_glVertexAttrib3dvARB)(GLuint,const GLdouble*);
+        void       (WINE_GLAPI *p_glVertexAttrib3dvNV)(GLuint,const GLdouble*);
+        void       (WINE_GLAPI *p_glVertexAttrib3f)(GLuint,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glVertexAttrib3fARB)(GLuint,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glVertexAttrib3fNV)(GLuint,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glVertexAttrib3fv)(GLuint,const GLfloat*);
+        void       (WINE_GLAPI *p_glVertexAttrib3fvARB)(GLuint,const GLfloat*);
+        void       (WINE_GLAPI *p_glVertexAttrib3fvNV)(GLuint,const GLfloat*);
+        void       (WINE_GLAPI *p_glVertexAttrib3hNV)(GLuint,GLhalfNV,GLhalfNV,GLhalfNV);
+        void       (WINE_GLAPI *p_glVertexAttrib3hvNV)(GLuint,const GLhalfNV*);
+        void       (WINE_GLAPI *p_glVertexAttrib3s)(GLuint,GLshort,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glVertexAttrib3sARB)(GLuint,GLshort,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glVertexAttrib3sNV)(GLuint,GLshort,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glVertexAttrib3sv)(GLuint,const GLshort*);
+        void       (WINE_GLAPI *p_glVertexAttrib3svARB)(GLuint,const GLshort*);
+        void       (WINE_GLAPI *p_glVertexAttrib3svNV)(GLuint,const GLshort*);
+        void       (WINE_GLAPI *p_glVertexAttrib4Nbv)(GLuint,const GLbyte*);
+        void       (WINE_GLAPI *p_glVertexAttrib4NbvARB)(GLuint,const GLbyte*);
+        void       (WINE_GLAPI *p_glVertexAttrib4Niv)(GLuint,const GLint*);
+        void       (WINE_GLAPI *p_glVertexAttrib4NivARB)(GLuint,const GLint*);
+        void       (WINE_GLAPI *p_glVertexAttrib4Nsv)(GLuint,const GLshort*);
+        void       (WINE_GLAPI *p_glVertexAttrib4NsvARB)(GLuint,const GLshort*);
+        void       (WINE_GLAPI *p_glVertexAttrib4Nub)(GLuint,GLubyte,GLubyte,GLubyte,GLubyte);
+        void       (WINE_GLAPI *p_glVertexAttrib4NubARB)(GLuint,GLubyte,GLubyte,GLubyte,GLubyte);
+        void       (WINE_GLAPI *p_glVertexAttrib4Nubv)(GLuint,const GLubyte*);
+        void       (WINE_GLAPI *p_glVertexAttrib4NubvARB)(GLuint,const GLubyte*);
+        void       (WINE_GLAPI *p_glVertexAttrib4Nuiv)(GLuint,const GLuint*);
+        void       (WINE_GLAPI *p_glVertexAttrib4NuivARB)(GLuint,const GLuint*);
+        void       (WINE_GLAPI *p_glVertexAttrib4Nusv)(GLuint,const GLushort*);
+        void       (WINE_GLAPI *p_glVertexAttrib4NusvARB)(GLuint,const GLushort*);
+        void       (WINE_GLAPI *p_glVertexAttrib4bv)(GLuint,const GLbyte*);
+        void       (WINE_GLAPI *p_glVertexAttrib4bvARB)(GLuint,const GLbyte*);
+        void       (WINE_GLAPI *p_glVertexAttrib4d)(GLuint,GLdouble,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glVertexAttrib4dARB)(GLuint,GLdouble,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glVertexAttrib4dNV)(GLuint,GLdouble,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glVertexAttrib4dv)(GLuint,const GLdouble*);
+        void       (WINE_GLAPI *p_glVertexAttrib4dvARB)(GLuint,const GLdouble*);
+        void       (WINE_GLAPI *p_glVertexAttrib4dvNV)(GLuint,const GLdouble*);
+        void       (WINE_GLAPI *p_glVertexAttrib4f)(GLuint,GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glVertexAttrib4fARB)(GLuint,GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glVertexAttrib4fNV)(GLuint,GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glVertexAttrib4fv)(GLuint,const GLfloat*);
+        void       (WINE_GLAPI *p_glVertexAttrib4fvARB)(GLuint,const GLfloat*);
+        void       (WINE_GLAPI *p_glVertexAttrib4fvNV)(GLuint,const GLfloat*);
+        void       (WINE_GLAPI *p_glVertexAttrib4hNV)(GLuint,GLhalfNV,GLhalfNV,GLhalfNV,GLhalfNV);
+        void       (WINE_GLAPI *p_glVertexAttrib4hvNV)(GLuint,const GLhalfNV*);
+        void       (WINE_GLAPI *p_glVertexAttrib4iv)(GLuint,const GLint*);
+        void       (WINE_GLAPI *p_glVertexAttrib4ivARB)(GLuint,const GLint*);
+        void       (WINE_GLAPI *p_glVertexAttrib4s)(GLuint,GLshort,GLshort,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glVertexAttrib4sARB)(GLuint,GLshort,GLshort,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glVertexAttrib4sNV)(GLuint,GLshort,GLshort,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glVertexAttrib4sv)(GLuint,const GLshort*);
+        void       (WINE_GLAPI *p_glVertexAttrib4svARB)(GLuint,const GLshort*);
+        void       (WINE_GLAPI *p_glVertexAttrib4svNV)(GLuint,const GLshort*);
+        void       (WINE_GLAPI *p_glVertexAttrib4ubNV)(GLuint,GLubyte,GLubyte,GLubyte,GLubyte);
+        void       (WINE_GLAPI *p_glVertexAttrib4ubv)(GLuint,const GLubyte*);
+        void       (WINE_GLAPI *p_glVertexAttrib4ubvARB)(GLuint,const GLubyte*);
+        void       (WINE_GLAPI *p_glVertexAttrib4ubvNV)(GLuint,const GLubyte*);
+        void       (WINE_GLAPI *p_glVertexAttrib4uiv)(GLuint,const GLuint*);
+        void       (WINE_GLAPI *p_glVertexAttrib4uivARB)(GLuint,const GLuint*);
+        void       (WINE_GLAPI *p_glVertexAttrib4usv)(GLuint,const GLushort*);
+        void       (WINE_GLAPI *p_glVertexAttrib4usvARB)(GLuint,const GLushort*);
+        void       (WINE_GLAPI *p_glVertexAttribArrayObjectATI)(GLuint,GLint,GLenum,GLboolean,GLsizei,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glVertexAttribBinding)(GLuint,GLuint);
+        void       (WINE_GLAPI *p_glVertexAttribDivisor)(GLuint,GLuint);
+        void       (WINE_GLAPI *p_glVertexAttribDivisorARB)(GLuint,GLuint);
+        void       (WINE_GLAPI *p_glVertexAttribFormat)(GLuint,GLint,GLenum,GLboolean,GLuint);
+        void       (WINE_GLAPI *p_glVertexAttribFormatNV)(GLuint,GLint,GLenum,GLboolean,GLsizei);
+        void       (WINE_GLAPI *p_glVertexAttribI1i)(GLuint,GLint);
+        void       (WINE_GLAPI *p_glVertexAttribI1iEXT)(GLuint,GLint);
+        void       (WINE_GLAPI *p_glVertexAttribI1iv)(GLuint,const GLint*);
+        void       (WINE_GLAPI *p_glVertexAttribI1ivEXT)(GLuint,const GLint*);
+        void       (WINE_GLAPI *p_glVertexAttribI1ui)(GLuint,GLuint);
+        void       (WINE_GLAPI *p_glVertexAttribI1uiEXT)(GLuint,GLuint);
+        void       (WINE_GLAPI *p_glVertexAttribI1uiv)(GLuint,const GLuint*);
+        void       (WINE_GLAPI *p_glVertexAttribI1uivEXT)(GLuint,const GLuint*);
+        void       (WINE_GLAPI *p_glVertexAttribI2i)(GLuint,GLint,GLint);
+        void       (WINE_GLAPI *p_glVertexAttribI2iEXT)(GLuint,GLint,GLint);
+        void       (WINE_GLAPI *p_glVertexAttribI2iv)(GLuint,const GLint*);
+        void       (WINE_GLAPI *p_glVertexAttribI2ivEXT)(GLuint,const GLint*);
+        void       (WINE_GLAPI *p_glVertexAttribI2ui)(GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glVertexAttribI2uiEXT)(GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glVertexAttribI2uiv)(GLuint,const GLuint*);
+        void       (WINE_GLAPI *p_glVertexAttribI2uivEXT)(GLuint,const GLuint*);
+        void       (WINE_GLAPI *p_glVertexAttribI3i)(GLuint,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glVertexAttribI3iEXT)(GLuint,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glVertexAttribI3iv)(GLuint,const GLint*);
+        void       (WINE_GLAPI *p_glVertexAttribI3ivEXT)(GLuint,const GLint*);
+        void       (WINE_GLAPI *p_glVertexAttribI3ui)(GLuint,GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glVertexAttribI3uiEXT)(GLuint,GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glVertexAttribI3uiv)(GLuint,const GLuint*);
+        void       (WINE_GLAPI *p_glVertexAttribI3uivEXT)(GLuint,const GLuint*);
+        void       (WINE_GLAPI *p_glVertexAttribI4bv)(GLuint,const GLbyte*);
+        void       (WINE_GLAPI *p_glVertexAttribI4bvEXT)(GLuint,const GLbyte*);
+        void       (WINE_GLAPI *p_glVertexAttribI4i)(GLuint,GLint,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glVertexAttribI4iEXT)(GLuint,GLint,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glVertexAttribI4iv)(GLuint,const GLint*);
+        void       (WINE_GLAPI *p_glVertexAttribI4ivEXT)(GLuint,const GLint*);
+        void       (WINE_GLAPI *p_glVertexAttribI4sv)(GLuint,const GLshort*);
+        void       (WINE_GLAPI *p_glVertexAttribI4svEXT)(GLuint,const GLshort*);
+        void       (WINE_GLAPI *p_glVertexAttribI4ubv)(GLuint,const GLubyte*);
+        void       (WINE_GLAPI *p_glVertexAttribI4ubvEXT)(GLuint,const GLubyte*);
+        void       (WINE_GLAPI *p_glVertexAttribI4ui)(GLuint,GLuint,GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glVertexAttribI4uiEXT)(GLuint,GLuint,GLuint,GLuint,GLuint);
+        void       (WINE_GLAPI *p_glVertexAttribI4uiv)(GLuint,const GLuint*);
+        void       (WINE_GLAPI *p_glVertexAttribI4uivEXT)(GLuint,const GLuint*);
+        void       (WINE_GLAPI *p_glVertexAttribI4usv)(GLuint,const GLushort*);
+        void       (WINE_GLAPI *p_glVertexAttribI4usvEXT)(GLuint,const GLushort*);
+        void       (WINE_GLAPI *p_glVertexAttribIFormat)(GLuint,GLint,GLenum,GLuint);
+        void       (WINE_GLAPI *p_glVertexAttribIFormatNV)(GLuint,GLint,GLenum,GLsizei);
+        void       (WINE_GLAPI *p_glVertexAttribIPointer)(GLuint,GLint,GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glVertexAttribIPointerEXT)(GLuint,GLint,GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glVertexAttribL1d)(GLuint,GLdouble);
+        void       (WINE_GLAPI *p_glVertexAttribL1dEXT)(GLuint,GLdouble);
+        void       (WINE_GLAPI *p_glVertexAttribL1dv)(GLuint,const GLdouble*);
+        void       (WINE_GLAPI *p_glVertexAttribL1dvEXT)(GLuint,const GLdouble*);
+        void       (WINE_GLAPI *p_glVertexAttribL1i64NV)(GLuint,INT64);
+        void       (WINE_GLAPI *p_glVertexAttribL1i64vNV)(GLuint,const INT64*);
+        void       (WINE_GLAPI *p_glVertexAttribL1ui64NV)(GLuint,UINT64);
+        void       (WINE_GLAPI *p_glVertexAttribL1ui64vNV)(GLuint,const UINT64*);
+        void       (WINE_GLAPI *p_glVertexAttribL2d)(GLuint,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glVertexAttribL2dEXT)(GLuint,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glVertexAttribL2dv)(GLuint,const GLdouble*);
+        void       (WINE_GLAPI *p_glVertexAttribL2dvEXT)(GLuint,const GLdouble*);
+        void       (WINE_GLAPI *p_glVertexAttribL2i64NV)(GLuint,INT64,INT64);
+        void       (WINE_GLAPI *p_glVertexAttribL2i64vNV)(GLuint,const INT64*);
+        void       (WINE_GLAPI *p_glVertexAttribL2ui64NV)(GLuint,UINT64,UINT64);
+        void       (WINE_GLAPI *p_glVertexAttribL2ui64vNV)(GLuint,const UINT64*);
+        void       (WINE_GLAPI *p_glVertexAttribL3d)(GLuint,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glVertexAttribL3dEXT)(GLuint,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glVertexAttribL3dv)(GLuint,const GLdouble*);
+        void       (WINE_GLAPI *p_glVertexAttribL3dvEXT)(GLuint,const GLdouble*);
+        void       (WINE_GLAPI *p_glVertexAttribL3i64NV)(GLuint,INT64,INT64,INT64);
+        void       (WINE_GLAPI *p_glVertexAttribL3i64vNV)(GLuint,const INT64*);
+        void       (WINE_GLAPI *p_glVertexAttribL3ui64NV)(GLuint,UINT64,UINT64,UINT64);
+        void       (WINE_GLAPI *p_glVertexAttribL3ui64vNV)(GLuint,const UINT64*);
+        void       (WINE_GLAPI *p_glVertexAttribL4d)(GLuint,GLdouble,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glVertexAttribL4dEXT)(GLuint,GLdouble,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glVertexAttribL4dv)(GLuint,const GLdouble*);
+        void       (WINE_GLAPI *p_glVertexAttribL4dvEXT)(GLuint,const GLdouble*);
+        void       (WINE_GLAPI *p_glVertexAttribL4i64NV)(GLuint,INT64,INT64,INT64,INT64);
+        void       (WINE_GLAPI *p_glVertexAttribL4i64vNV)(GLuint,const INT64*);
+        void       (WINE_GLAPI *p_glVertexAttribL4ui64NV)(GLuint,UINT64,UINT64,UINT64,UINT64);
+        void       (WINE_GLAPI *p_glVertexAttribL4ui64vNV)(GLuint,const UINT64*);
+        void       (WINE_GLAPI *p_glVertexAttribLFormat)(GLuint,GLint,GLenum,GLuint);
+        void       (WINE_GLAPI *p_glVertexAttribLFormatNV)(GLuint,GLint,GLenum,GLsizei);
+        void       (WINE_GLAPI *p_glVertexAttribLPointer)(GLuint,GLint,GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glVertexAttribLPointerEXT)(GLuint,GLint,GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glVertexAttribP1ui)(GLuint,GLenum,GLboolean,GLuint);
+        void       (WINE_GLAPI *p_glVertexAttribP1uiv)(GLuint,GLenum,GLboolean,const GLuint*);
+        void       (WINE_GLAPI *p_glVertexAttribP2ui)(GLuint,GLenum,GLboolean,GLuint);
+        void       (WINE_GLAPI *p_glVertexAttribP2uiv)(GLuint,GLenum,GLboolean,const GLuint*);
+        void       (WINE_GLAPI *p_glVertexAttribP3ui)(GLuint,GLenum,GLboolean,GLuint);
+        void       (WINE_GLAPI *p_glVertexAttribP3uiv)(GLuint,GLenum,GLboolean,const GLuint*);
+        void       (WINE_GLAPI *p_glVertexAttribP4ui)(GLuint,GLenum,GLboolean,GLuint);
+        void       (WINE_GLAPI *p_glVertexAttribP4uiv)(GLuint,GLenum,GLboolean,const GLuint*);
+        void       (WINE_GLAPI *p_glVertexAttribPointer)(GLuint,GLint,GLenum,GLboolean,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glVertexAttribPointerARB)(GLuint,GLint,GLenum,GLboolean,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glVertexAttribPointerNV)(GLuint,GLint,GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glVertexAttribs1dvNV)(GLuint,GLsizei,const GLdouble*);
+        void       (WINE_GLAPI *p_glVertexAttribs1fvNV)(GLuint,GLsizei,const GLfloat*);
+        void       (WINE_GLAPI *p_glVertexAttribs1hvNV)(GLuint,GLsizei,const GLhalfNV*);
+        void       (WINE_GLAPI *p_glVertexAttribs1svNV)(GLuint,GLsizei,const GLshort*);
+        void       (WINE_GLAPI *p_glVertexAttribs2dvNV)(GLuint,GLsizei,const GLdouble*);
+        void       (WINE_GLAPI *p_glVertexAttribs2fvNV)(GLuint,GLsizei,const GLfloat*);
+        void       (WINE_GLAPI *p_glVertexAttribs2hvNV)(GLuint,GLsizei,const GLhalfNV*);
+        void       (WINE_GLAPI *p_glVertexAttribs2svNV)(GLuint,GLsizei,const GLshort*);
+        void       (WINE_GLAPI *p_glVertexAttribs3dvNV)(GLuint,GLsizei,const GLdouble*);
+        void       (WINE_GLAPI *p_glVertexAttribs3fvNV)(GLuint,GLsizei,const GLfloat*);
+        void       (WINE_GLAPI *p_glVertexAttribs3hvNV)(GLuint,GLsizei,const GLhalfNV*);
+        void       (WINE_GLAPI *p_glVertexAttribs3svNV)(GLuint,GLsizei,const GLshort*);
+        void       (WINE_GLAPI *p_glVertexAttribs4dvNV)(GLuint,GLsizei,const GLdouble*);
+        void       (WINE_GLAPI *p_glVertexAttribs4fvNV)(GLuint,GLsizei,const GLfloat*);
+        void       (WINE_GLAPI *p_glVertexAttribs4hvNV)(GLuint,GLsizei,const GLhalfNV*);
+        void       (WINE_GLAPI *p_glVertexAttribs4svNV)(GLuint,GLsizei,const GLshort*);
+        void       (WINE_GLAPI *p_glVertexAttribs4ubvNV)(GLuint,GLsizei,const GLubyte*);
+        void       (WINE_GLAPI *p_glVertexBindingDivisor)(GLuint,GLuint);
+        void       (WINE_GLAPI *p_glVertexBlendARB)(GLint);
+        void       (WINE_GLAPI *p_glVertexBlendEnvfATI)(GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glVertexBlendEnviATI)(GLenum,GLint);
+        void       (WINE_GLAPI *p_glVertexFormatNV)(GLint,GLenum,GLsizei);
+        void       (WINE_GLAPI *p_glVertexP2ui)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glVertexP2uiv)(GLenum,const GLuint*);
+        void       (WINE_GLAPI *p_glVertexP3ui)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glVertexP3uiv)(GLenum,const GLuint*);
+        void       (WINE_GLAPI *p_glVertexP4ui)(GLenum,GLuint);
+        void       (WINE_GLAPI *p_glVertexP4uiv)(GLenum,const GLuint*);
+        void       (WINE_GLAPI *p_glVertexPointerEXT)(GLint,GLenum,GLsizei,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glVertexPointerListIBM)(GLint,GLenum,GLint,const GLvoid**,GLint);
+        void       (WINE_GLAPI *p_glVertexPointervINTEL)(GLint,GLenum,const GLvoid**);
+        void       (WINE_GLAPI *p_glVertexStream1dATI)(GLenum,GLdouble);
+        void       (WINE_GLAPI *p_glVertexStream1dvATI)(GLenum,const GLdouble*);
+        void       (WINE_GLAPI *p_glVertexStream1fATI)(GLenum,GLfloat);
+        void       (WINE_GLAPI *p_glVertexStream1fvATI)(GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glVertexStream1iATI)(GLenum,GLint);
+        void       (WINE_GLAPI *p_glVertexStream1ivATI)(GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glVertexStream1sATI)(GLenum,GLshort);
+        void       (WINE_GLAPI *p_glVertexStream1svATI)(GLenum,const GLshort*);
+        void       (WINE_GLAPI *p_glVertexStream2dATI)(GLenum,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glVertexStream2dvATI)(GLenum,const GLdouble*);
+        void       (WINE_GLAPI *p_glVertexStream2fATI)(GLenum,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glVertexStream2fvATI)(GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glVertexStream2iATI)(GLenum,GLint,GLint);
+        void       (WINE_GLAPI *p_glVertexStream2ivATI)(GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glVertexStream2sATI)(GLenum,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glVertexStream2svATI)(GLenum,const GLshort*);
+        void       (WINE_GLAPI *p_glVertexStream3dATI)(GLenum,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glVertexStream3dvATI)(GLenum,const GLdouble*);
+        void       (WINE_GLAPI *p_glVertexStream3fATI)(GLenum,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glVertexStream3fvATI)(GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glVertexStream3iATI)(GLenum,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glVertexStream3ivATI)(GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glVertexStream3sATI)(GLenum,GLshort,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glVertexStream3svATI)(GLenum,const GLshort*);
+        void       (WINE_GLAPI *p_glVertexStream4dATI)(GLenum,GLdouble,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glVertexStream4dvATI)(GLenum,const GLdouble*);
+        void       (WINE_GLAPI *p_glVertexStream4fATI)(GLenum,GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glVertexStream4fvATI)(GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glVertexStream4iATI)(GLenum,GLint,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glVertexStream4ivATI)(GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glVertexStream4sATI)(GLenum,GLshort,GLshort,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glVertexStream4svATI)(GLenum,const GLshort*);
+        void       (WINE_GLAPI *p_glVertexWeightPointerEXT)(GLint,GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glVertexWeightfEXT)(GLfloat);
+        void       (WINE_GLAPI *p_glVertexWeightfvEXT)(const GLfloat*);
+        void       (WINE_GLAPI *p_glVertexWeighthNV)(GLhalfNV);
+        void       (WINE_GLAPI *p_glVertexWeighthvNV)(const GLhalfNV*);
+        GLenum     (WINE_GLAPI *p_glVideoCaptureNV)(GLuint,GLuint*,UINT64*);
+        void       (WINE_GLAPI *p_glVideoCaptureStreamParameterdvNV)(GLuint,GLuint,GLenum,const GLdouble*);
+        void       (WINE_GLAPI *p_glVideoCaptureStreamParameterfvNV)(GLuint,GLuint,GLenum,const GLfloat*);
+        void       (WINE_GLAPI *p_glVideoCaptureStreamParameterivNV)(GLuint,GLuint,GLenum,const GLint*);
+        void       (WINE_GLAPI *p_glViewportArrayv)(GLuint,GLsizei,const GLfloat*);
+        void       (WINE_GLAPI *p_glViewportIndexedf)(GLuint,GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glViewportIndexedfv)(GLuint,const GLfloat*);
+        void       (WINE_GLAPI *p_glWaitSync)(GLvoid*,GLbitfield,UINT64);
+        void       (WINE_GLAPI *p_glWeightPathsNV)(GLuint,GLsizei,const GLuint*,const GLfloat*);
+        void       (WINE_GLAPI *p_glWeightPointerARB)(GLint,GLenum,GLsizei,const GLvoid*);
+        void       (WINE_GLAPI *p_glWeightbvARB)(GLint,const GLbyte*);
+        void       (WINE_GLAPI *p_glWeightdvARB)(GLint,const GLdouble*);
+        void       (WINE_GLAPI *p_glWeightfvARB)(GLint,const GLfloat*);
+        void       (WINE_GLAPI *p_glWeightivARB)(GLint,const GLint*);
+        void       (WINE_GLAPI *p_glWeightsvARB)(GLint,const GLshort*);
+        void       (WINE_GLAPI *p_glWeightubvARB)(GLint,const GLubyte*);
+        void       (WINE_GLAPI *p_glWeightuivARB)(GLint,const GLuint*);
+        void       (WINE_GLAPI *p_glWeightusvARB)(GLint,const GLushort*);
+        void       (WINE_GLAPI *p_glWindowPos2d)(GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glWindowPos2dARB)(GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glWindowPos2dMESA)(GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glWindowPos2dv)(const GLdouble*);
+        void       (WINE_GLAPI *p_glWindowPos2dvARB)(const GLdouble*);
+        void       (WINE_GLAPI *p_glWindowPos2dvMESA)(const GLdouble*);
+        void       (WINE_GLAPI *p_glWindowPos2f)(GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glWindowPos2fARB)(GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glWindowPos2fMESA)(GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glWindowPos2fv)(const GLfloat*);
+        void       (WINE_GLAPI *p_glWindowPos2fvARB)(const GLfloat*);
+        void       (WINE_GLAPI *p_glWindowPos2fvMESA)(const GLfloat*);
+        void       (WINE_GLAPI *p_glWindowPos2i)(GLint,GLint);
+        void       (WINE_GLAPI *p_glWindowPos2iARB)(GLint,GLint);
+        void       (WINE_GLAPI *p_glWindowPos2iMESA)(GLint,GLint);
+        void       (WINE_GLAPI *p_glWindowPos2iv)(const GLint*);
+        void       (WINE_GLAPI *p_glWindowPos2ivARB)(const GLint*);
+        void       (WINE_GLAPI *p_glWindowPos2ivMESA)(const GLint*);
+        void       (WINE_GLAPI *p_glWindowPos2s)(GLshort,GLshort);
+        void       (WINE_GLAPI *p_glWindowPos2sARB)(GLshort,GLshort);
+        void       (WINE_GLAPI *p_glWindowPos2sMESA)(GLshort,GLshort);
+        void       (WINE_GLAPI *p_glWindowPos2sv)(const GLshort*);
+        void       (WINE_GLAPI *p_glWindowPos2svARB)(const GLshort*);
+        void       (WINE_GLAPI *p_glWindowPos2svMESA)(const GLshort*);
+        void       (WINE_GLAPI *p_glWindowPos3d)(GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glWindowPos3dARB)(GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glWindowPos3dMESA)(GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glWindowPos3dv)(const GLdouble*);
+        void       (WINE_GLAPI *p_glWindowPos3dvARB)(const GLdouble*);
+        void       (WINE_GLAPI *p_glWindowPos3dvMESA)(const GLdouble*);
+        void       (WINE_GLAPI *p_glWindowPos3f)(GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glWindowPos3fARB)(GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glWindowPos3fMESA)(GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glWindowPos3fv)(const GLfloat*);
+        void       (WINE_GLAPI *p_glWindowPos3fvARB)(const GLfloat*);
+        void       (WINE_GLAPI *p_glWindowPos3fvMESA)(const GLfloat*);
+        void       (WINE_GLAPI *p_glWindowPos3i)(GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glWindowPos3iARB)(GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glWindowPos3iMESA)(GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glWindowPos3iv)(const GLint*);
+        void       (WINE_GLAPI *p_glWindowPos3ivARB)(const GLint*);
+        void       (WINE_GLAPI *p_glWindowPos3ivMESA)(const GLint*);
+        void       (WINE_GLAPI *p_glWindowPos3s)(GLshort,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glWindowPos3sARB)(GLshort,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glWindowPos3sMESA)(GLshort,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glWindowPos3sv)(const GLshort*);
+        void       (WINE_GLAPI *p_glWindowPos3svARB)(const GLshort*);
+        void       (WINE_GLAPI *p_glWindowPos3svMESA)(const GLshort*);
+        void       (WINE_GLAPI *p_glWindowPos4dMESA)(GLdouble,GLdouble,GLdouble,GLdouble);
+        void       (WINE_GLAPI *p_glWindowPos4dvMESA)(const GLdouble*);
+        void       (WINE_GLAPI *p_glWindowPos4fMESA)(GLfloat,GLfloat,GLfloat,GLfloat);
+        void       (WINE_GLAPI *p_glWindowPos4fvMESA)(const GLfloat*);
+        void       (WINE_GLAPI *p_glWindowPos4iMESA)(GLint,GLint,GLint,GLint);
+        void       (WINE_GLAPI *p_glWindowPos4ivMESA)(const GLint*);
+        void       (WINE_GLAPI *p_glWindowPos4sMESA)(GLshort,GLshort,GLshort,GLshort);
+        void       (WINE_GLAPI *p_glWindowPos4svMESA)(const GLshort*);
+        void       (WINE_GLAPI *p_glWriteMaskEXT)(GLuint,GLuint,GLenum,GLenum,GLenum,GLenum);
+        GLvoid*    (WINE_GLAPI *p_wglAllocateMemoryNV)(GLsizei,GLfloat,GLfloat,GLfloat);
+        BOOL       (WINE_GLAPI *p_wglBindTexImageARB)(struct wgl_pbuffer *,int);
+        BOOL       (WINE_GLAPI *p_wglChoosePixelFormatARB)(HDC,const int*,const FLOAT*,UINT,int*,UINT*);
+        struct wgl_context * (WINE_GLAPI *p_wglCreateContextAttribsARB)(HDC,struct wgl_context *,const int*);
+        struct wgl_pbuffer * (WINE_GLAPI *p_wglCreatePbufferARB)(HDC,int,int,int,const int*);
+        BOOL       (WINE_GLAPI *p_wglDestroyPbufferARB)(struct wgl_pbuffer *);
+        void       (WINE_GLAPI *p_wglFreeMemoryNV)(void*);
+        HDC        (WINE_GLAPI *p_wglGetCurrentReadDCARB)(void);
+        const GLubyte * (WINE_GLAPI *p_wglGetExtensionsStringARB)(HDC);
+        const GLubyte * (WINE_GLAPI *p_wglGetExtensionsStringEXT)(void);
+        HDC        (WINE_GLAPI *p_wglGetPbufferDCARB)(struct wgl_pbuffer *);
+        BOOL       (WINE_GLAPI *p_wglGetPixelFormatAttribfvARB)(HDC,int,int,UINT,const int*,FLOAT*);
+        BOOL       (WINE_GLAPI *p_wglGetPixelFormatAttribivARB)(HDC,int,int,UINT,const int*,int*);
+        int        (WINE_GLAPI *p_wglGetSwapIntervalEXT)(void);
+        BOOL       (WINE_GLAPI *p_wglMakeContextCurrentARB)(HDC,HDC,struct wgl_context *);
+        BOOL       (WINE_GLAPI *p_wglQueryPbufferARB)(struct wgl_pbuffer *,int,int*);
+        int        (WINE_GLAPI *p_wglReleasePbufferDCARB)(struct wgl_pbuffer *,HDC);
+        BOOL       (WINE_GLAPI *p_wglReleaseTexImageARB)(struct wgl_pbuffer *,int);
+        BOOL       (WINE_GLAPI *p_wglSetPbufferAttribARB)(struct wgl_pbuffer *,const int*);
+        BOOL       (WINE_GLAPI *p_wglSetPixelFormatWINE)(HDC,int);
+        BOOL       (WINE_GLAPI *p_wglSwapIntervalEXT)(int);
+    } ext;
+};
+
+#define ALL_WGL_FUNCS \
+    USE_GL_FUNC(glAccum) \
+    USE_GL_FUNC(glAlphaFunc) \
+    USE_GL_FUNC(glAreTexturesResident) \
+    USE_GL_FUNC(glArrayElement) \
+    USE_GL_FUNC(glBegin) \
+    USE_GL_FUNC(glBindTexture) \
+    USE_GL_FUNC(glBitmap) \
+    USE_GL_FUNC(glBlendFunc) \
+    USE_GL_FUNC(glCallList) \
+    USE_GL_FUNC(glCallLists) \
+    USE_GL_FUNC(glClear) \
+    USE_GL_FUNC(glClearAccum) \
+    USE_GL_FUNC(glClearColor) \
+    USE_GL_FUNC(glClearDepth) \
+    USE_GL_FUNC(glClearIndex) \
+    USE_GL_FUNC(glClearStencil) \
+    USE_GL_FUNC(glClipPlane) \
+    USE_GL_FUNC(glColor3b) \
+    USE_GL_FUNC(glColor3bv) \
+    USE_GL_FUNC(glColor3d) \
+    USE_GL_FUNC(glColor3dv) \
+    USE_GL_FUNC(glColor3f) \
+    USE_GL_FUNC(glColor3fv) \
+    USE_GL_FUNC(glColor3i) \
+    USE_GL_FUNC(glColor3iv) \
+    USE_GL_FUNC(glColor3s) \
+    USE_GL_FUNC(glColor3sv) \
+    USE_GL_FUNC(glColor3ub) \
+    USE_GL_FUNC(glColor3ubv) \
+    USE_GL_FUNC(glColor3ui) \
+    USE_GL_FUNC(glColor3uiv) \
+    USE_GL_FUNC(glColor3us) \
+    USE_GL_FUNC(glColor3usv) \
+    USE_GL_FUNC(glColor4b) \
+    USE_GL_FUNC(glColor4bv) \
+    USE_GL_FUNC(glColor4d) \
+    USE_GL_FUNC(glColor4dv) \
+    USE_GL_FUNC(glColor4f) \
+    USE_GL_FUNC(glColor4fv) \
+    USE_GL_FUNC(glColor4i) \
+    USE_GL_FUNC(glColor4iv) \
+    USE_GL_FUNC(glColor4s) \
+    USE_GL_FUNC(glColor4sv) \
+    USE_GL_FUNC(glColor4ub) \
+    USE_GL_FUNC(glColor4ubv) \
+    USE_GL_FUNC(glColor4ui) \
+    USE_GL_FUNC(glColor4uiv) \
+    USE_GL_FUNC(glColor4us) \
+    USE_GL_FUNC(glColor4usv) \
+    USE_GL_FUNC(glColorMask) \
+    USE_GL_FUNC(glColorMaterial) \
+    USE_GL_FUNC(glColorPointer) \
+    USE_GL_FUNC(glCopyPixels) \
+    USE_GL_FUNC(glCopyTexImage1D) \
+    USE_GL_FUNC(glCopyTexImage2D) \
+    USE_GL_FUNC(glCopyTexSubImage1D) \
+    USE_GL_FUNC(glCopyTexSubImage2D) \
+    USE_GL_FUNC(glCullFace) \
+    USE_GL_FUNC(glDeleteLists) \
+    USE_GL_FUNC(glDeleteTextures) \
+    USE_GL_FUNC(glDepthFunc) \
+    USE_GL_FUNC(glDepthMask) \
+    USE_GL_FUNC(glDepthRange) \
+    USE_GL_FUNC(glDisable) \
+    USE_GL_FUNC(glDisableClientState) \
+    USE_GL_FUNC(glDrawArrays) \
+    USE_GL_FUNC(glDrawBuffer) \
+    USE_GL_FUNC(glDrawElements) \
+    USE_GL_FUNC(glDrawPixels) \
+    USE_GL_FUNC(glEdgeFlag) \
+    USE_GL_FUNC(glEdgeFlagPointer) \
+    USE_GL_FUNC(glEdgeFlagv) \
+    USE_GL_FUNC(glEnable) \
+    USE_GL_FUNC(glEnableClientState) \
+    USE_GL_FUNC(glEnd) \
+    USE_GL_FUNC(glEndList) \
+    USE_GL_FUNC(glEvalCoord1d) \
+    USE_GL_FUNC(glEvalCoord1dv) \
+    USE_GL_FUNC(glEvalCoord1f) \
+    USE_GL_FUNC(glEvalCoord1fv) \
+    USE_GL_FUNC(glEvalCoord2d) \
+    USE_GL_FUNC(glEvalCoord2dv) \
+    USE_GL_FUNC(glEvalCoord2f) \
+    USE_GL_FUNC(glEvalCoord2fv) \
+    USE_GL_FUNC(glEvalMesh1) \
+    USE_GL_FUNC(glEvalMesh2) \
+    USE_GL_FUNC(glEvalPoint1) \
+    USE_GL_FUNC(glEvalPoint2) \
+    USE_GL_FUNC(glFeedbackBuffer) \
+    USE_GL_FUNC(glFinish) \
+    USE_GL_FUNC(glFlush) \
+    USE_GL_FUNC(glFogf) \
+    USE_GL_FUNC(glFogfv) \
+    USE_GL_FUNC(glFogi) \
+    USE_GL_FUNC(glFogiv) \
+    USE_GL_FUNC(glFrontFace) \
+    USE_GL_FUNC(glFrustum) \
+    USE_GL_FUNC(glGenLists) \
+    USE_GL_FUNC(glGenTextures) \
+    USE_GL_FUNC(glGetBooleanv) \
+    USE_GL_FUNC(glGetClipPlane) \
+    USE_GL_FUNC(glGetDoublev) \
+    USE_GL_FUNC(glGetError) \
+    USE_GL_FUNC(glGetFloatv) \
+    USE_GL_FUNC(glGetIntegerv) \
+    USE_GL_FUNC(glGetLightfv) \
+    USE_GL_FUNC(glGetLightiv) \
+    USE_GL_FUNC(glGetMapdv) \
+    USE_GL_FUNC(glGetMapfv) \
+    USE_GL_FUNC(glGetMapiv) \
+    USE_GL_FUNC(glGetMaterialfv) \
+    USE_GL_FUNC(glGetMaterialiv) \
+    USE_GL_FUNC(glGetPixelMapfv) \
+    USE_GL_FUNC(glGetPixelMapuiv) \
+    USE_GL_FUNC(glGetPixelMapusv) \
+    USE_GL_FUNC(glGetPointerv) \
+    USE_GL_FUNC(glGetPolygonStipple) \
+    USE_GL_FUNC(glGetString) \
+    USE_GL_FUNC(glGetTexEnvfv) \
+    USE_GL_FUNC(glGetTexEnviv) \
+    USE_GL_FUNC(glGetTexGendv) \
+    USE_GL_FUNC(glGetTexGenfv) \
+    USE_GL_FUNC(glGetTexGeniv) \
+    USE_GL_FUNC(glGetTexImage) \
+    USE_GL_FUNC(glGetTexLevelParameterfv) \
+    USE_GL_FUNC(glGetTexLevelParameteriv) \
+    USE_GL_FUNC(glGetTexParameterfv) \
+    USE_GL_FUNC(glGetTexParameteriv) \
+    USE_GL_FUNC(glHint) \
+    USE_GL_FUNC(glIndexMask) \
+    USE_GL_FUNC(glIndexPointer) \
+    USE_GL_FUNC(glIndexd) \
+    USE_GL_FUNC(glIndexdv) \
+    USE_GL_FUNC(glIndexf) \
+    USE_GL_FUNC(glIndexfv) \
+    USE_GL_FUNC(glIndexi) \
+    USE_GL_FUNC(glIndexiv) \
+    USE_GL_FUNC(glIndexs) \
+    USE_GL_FUNC(glIndexsv) \
+    USE_GL_FUNC(glIndexub) \
+    USE_GL_FUNC(glIndexubv) \
+    USE_GL_FUNC(glInitNames) \
+    USE_GL_FUNC(glInterleavedArrays) \
+    USE_GL_FUNC(glIsEnabled) \
+    USE_GL_FUNC(glIsList) \
+    USE_GL_FUNC(glIsTexture) \
+    USE_GL_FUNC(glLightModelf) \
+    USE_GL_FUNC(glLightModelfv) \
+    USE_GL_FUNC(glLightModeli) \
+    USE_GL_FUNC(glLightModeliv) \
+    USE_GL_FUNC(glLightf) \
+    USE_GL_FUNC(glLightfv) \
+    USE_GL_FUNC(glLighti) \
+    USE_GL_FUNC(glLightiv) \
+    USE_GL_FUNC(glLineStipple) \
+    USE_GL_FUNC(glLineWidth) \
+    USE_GL_FUNC(glListBase) \
+    USE_GL_FUNC(glLoadIdentity) \
+    USE_GL_FUNC(glLoadMatrixd) \
+    USE_GL_FUNC(glLoadMatrixf) \
+    USE_GL_FUNC(glLoadName) \
+    USE_GL_FUNC(glLogicOp) \
+    USE_GL_FUNC(glMap1d) \
+    USE_GL_FUNC(glMap1f) \
+    USE_GL_FUNC(glMap2d) \
+    USE_GL_FUNC(glMap2f) \
+    USE_GL_FUNC(glMapGrid1d) \
+    USE_GL_FUNC(glMapGrid1f) \
+    USE_GL_FUNC(glMapGrid2d) \
+    USE_GL_FUNC(glMapGrid2f) \
+    USE_GL_FUNC(glMaterialf) \
+    USE_GL_FUNC(glMaterialfv) \
+    USE_GL_FUNC(glMateriali) \
+    USE_GL_FUNC(glMaterialiv) \
+    USE_GL_FUNC(glMatrixMode) \
+    USE_GL_FUNC(glMultMatrixd) \
+    USE_GL_FUNC(glMultMatrixf) \
+    USE_GL_FUNC(glNewList) \
+    USE_GL_FUNC(glNormal3b) \
+    USE_GL_FUNC(glNormal3bv) \
+    USE_GL_FUNC(glNormal3d) \
+    USE_GL_FUNC(glNormal3dv) \
+    USE_GL_FUNC(glNormal3f) \
+    USE_GL_FUNC(glNormal3fv) \
+    USE_GL_FUNC(glNormal3i) \
+    USE_GL_FUNC(glNormal3iv) \
+    USE_GL_FUNC(glNormal3s) \
+    USE_GL_FUNC(glNormal3sv) \
+    USE_GL_FUNC(glNormalPointer) \
+    USE_GL_FUNC(glOrtho) \
+    USE_GL_FUNC(glPassThrough) \
+    USE_GL_FUNC(glPixelMapfv) \
+    USE_GL_FUNC(glPixelMapuiv) \
+    USE_GL_FUNC(glPixelMapusv) \
+    USE_GL_FUNC(glPixelStoref) \
+    USE_GL_FUNC(glPixelStorei) \
+    USE_GL_FUNC(glPixelTransferf) \
+    USE_GL_FUNC(glPixelTransferi) \
+    USE_GL_FUNC(glPixelZoom) \
+    USE_GL_FUNC(glPointSize) \
+    USE_GL_FUNC(glPolygonMode) \
+    USE_GL_FUNC(glPolygonOffset) \
+    USE_GL_FUNC(glPolygonStipple) \
+    USE_GL_FUNC(glPopAttrib) \
+    USE_GL_FUNC(glPopClientAttrib) \
+    USE_GL_FUNC(glPopMatrix) \
+    USE_GL_FUNC(glPopName) \
+    USE_GL_FUNC(glPrioritizeTextures) \
+    USE_GL_FUNC(glPushAttrib) \
+    USE_GL_FUNC(glPushClientAttrib) \
+    USE_GL_FUNC(glPushMatrix) \
+    USE_GL_FUNC(glPushName) \
+    USE_GL_FUNC(glRasterPos2d) \
+    USE_GL_FUNC(glRasterPos2dv) \
+    USE_GL_FUNC(glRasterPos2f) \
+    USE_GL_FUNC(glRasterPos2fv) \
+    USE_GL_FUNC(glRasterPos2i) \
+    USE_GL_FUNC(glRasterPos2iv) \
+    USE_GL_FUNC(glRasterPos2s) \
+    USE_GL_FUNC(glRasterPos2sv) \
+    USE_GL_FUNC(glRasterPos3d) \
+    USE_GL_FUNC(glRasterPos3dv) \
+    USE_GL_FUNC(glRasterPos3f) \
+    USE_GL_FUNC(glRasterPos3fv) \
+    USE_GL_FUNC(glRasterPos3i) \
+    USE_GL_FUNC(glRasterPos3iv) \
+    USE_GL_FUNC(glRasterPos3s) \
+    USE_GL_FUNC(glRasterPos3sv) \
+    USE_GL_FUNC(glRasterPos4d) \
+    USE_GL_FUNC(glRasterPos4dv) \
+    USE_GL_FUNC(glRasterPos4f) \
+    USE_GL_FUNC(glRasterPos4fv) \
+    USE_GL_FUNC(glRasterPos4i) \
+    USE_GL_FUNC(glRasterPos4iv) \
+    USE_GL_FUNC(glRasterPos4s) \
+    USE_GL_FUNC(glRasterPos4sv) \
+    USE_GL_FUNC(glReadBuffer) \
+    USE_GL_FUNC(glReadPixels) \
+    USE_GL_FUNC(glRectd) \
+    USE_GL_FUNC(glRectdv) \
+    USE_GL_FUNC(glRectf) \
+    USE_GL_FUNC(glRectfv) \
+    USE_GL_FUNC(glRecti) \
+    USE_GL_FUNC(glRectiv) \
+    USE_GL_FUNC(glRects) \
+    USE_GL_FUNC(glRectsv) \
+    USE_GL_FUNC(glRenderMode) \
+    USE_GL_FUNC(glRotated) \
+    USE_GL_FUNC(glRotatef) \
+    USE_GL_FUNC(glScaled) \
+    USE_GL_FUNC(glScalef) \
+    USE_GL_FUNC(glScissor) \
+    USE_GL_FUNC(glSelectBuffer) \
+    USE_GL_FUNC(glShadeModel) \
+    USE_GL_FUNC(glStencilFunc) \
+    USE_GL_FUNC(glStencilMask) \
+    USE_GL_FUNC(glStencilOp) \
+    USE_GL_FUNC(glTexCoord1d) \
+    USE_GL_FUNC(glTexCoord1dv) \
+    USE_GL_FUNC(glTexCoord1f) \
+    USE_GL_FUNC(glTexCoord1fv) \
+    USE_GL_FUNC(glTexCoord1i) \
+    USE_GL_FUNC(glTexCoord1iv) \
+    USE_GL_FUNC(glTexCoord1s) \
+    USE_GL_FUNC(glTexCoord1sv) \
+    USE_GL_FUNC(glTexCoord2d) \
+    USE_GL_FUNC(glTexCoord2dv) \
+    USE_GL_FUNC(glTexCoord2f) \
+    USE_GL_FUNC(glTexCoord2fv) \
+    USE_GL_FUNC(glTexCoord2i) \
+    USE_GL_FUNC(glTexCoord2iv) \
+    USE_GL_FUNC(glTexCoord2s) \
+    USE_GL_FUNC(glTexCoord2sv) \
+    USE_GL_FUNC(glTexCoord3d) \
+    USE_GL_FUNC(glTexCoord3dv) \
+    USE_GL_FUNC(glTexCoord3f) \
+    USE_GL_FUNC(glTexCoord3fv) \
+    USE_GL_FUNC(glTexCoord3i) \
+    USE_GL_FUNC(glTexCoord3iv) \
+    USE_GL_FUNC(glTexCoord3s) \
+    USE_GL_FUNC(glTexCoord3sv) \
+    USE_GL_FUNC(glTexCoord4d) \
+    USE_GL_FUNC(glTexCoord4dv) \
+    USE_GL_FUNC(glTexCoord4f) \
+    USE_GL_FUNC(glTexCoord4fv) \
+    USE_GL_FUNC(glTexCoord4i) \
+    USE_GL_FUNC(glTexCoord4iv) \
+    USE_GL_FUNC(glTexCoord4s) \
+    USE_GL_FUNC(glTexCoord4sv) \
+    USE_GL_FUNC(glTexCoordPointer) \
+    USE_GL_FUNC(glTexEnvf) \
+    USE_GL_FUNC(glTexEnvfv) \
+    USE_GL_FUNC(glTexEnvi) \
+    USE_GL_FUNC(glTexEnviv) \
+    USE_GL_FUNC(glTexGend) \
+    USE_GL_FUNC(glTexGendv) \
+    USE_GL_FUNC(glTexGenf) \
+    USE_GL_FUNC(glTexGenfv) \
+    USE_GL_FUNC(glTexGeni) \
+    USE_GL_FUNC(glTexGeniv) \
+    USE_GL_FUNC(glTexImage1D) \
+    USE_GL_FUNC(glTexImage2D) \
+    USE_GL_FUNC(glTexParameterf) \
+    USE_GL_FUNC(glTexParameterfv) \
+    USE_GL_FUNC(glTexParameteri) \
+    USE_GL_FUNC(glTexParameteriv) \
+    USE_GL_FUNC(glTexSubImage1D) \
+    USE_GL_FUNC(glTexSubImage2D) \
+    USE_GL_FUNC(glTranslated) \
+    USE_GL_FUNC(glTranslatef) \
+    USE_GL_FUNC(glVertex2d) \
+    USE_GL_FUNC(glVertex2dv) \
+    USE_GL_FUNC(glVertex2f) \
+    USE_GL_FUNC(glVertex2fv) \
+    USE_GL_FUNC(glVertex2i) \
+    USE_GL_FUNC(glVertex2iv) \
+    USE_GL_FUNC(glVertex2s) \
+    USE_GL_FUNC(glVertex2sv) \
+    USE_GL_FUNC(glVertex3d) \
+    USE_GL_FUNC(glVertex3dv) \
+    USE_GL_FUNC(glVertex3f) \
+    USE_GL_FUNC(glVertex3fv) \
+    USE_GL_FUNC(glVertex3i) \
+    USE_GL_FUNC(glVertex3iv) \
+    USE_GL_FUNC(glVertex3s) \
+    USE_GL_FUNC(glVertex3sv) \
+    USE_GL_FUNC(glVertex4d) \
+    USE_GL_FUNC(glVertex4dv) \
+    USE_GL_FUNC(glVertex4f) \
+    USE_GL_FUNC(glVertex4fv) \
+    USE_GL_FUNC(glVertex4i) \
+    USE_GL_FUNC(glVertex4iv) \
+    USE_GL_FUNC(glVertex4s) \
+    USE_GL_FUNC(glVertex4sv) \
+    USE_GL_FUNC(glVertexPointer) \
+    USE_GL_FUNC(glViewport)
+
+extern struct opengl_funcs * CDECL __wine_get_wgl_driver( HDC hdc, UINT version );
+extern BOOL CDECL __wine_set_pixel_format( HWND hwnd, int format );
+
+#endif /* __WINE_WGL_DRIVER_H */
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/include/wine/wglext.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/include/wine/wglext.h	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/include/wine/wglext.h	(revision 46521)
@@ -0,0 +1,943 @@
+#ifndef __wglext_h_
+#define __wglext_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright (c) 2007-2012 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+/* Function declaration macros - to move into glplatform.h */
+
+#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
+#define WIN32_LEAN_AND_MEAN 1
+#include <windows.h>
+#endif
+
+#ifndef APIENTRY
+#define APIENTRY
+#endif
+#ifndef APIENTRYP
+#define APIENTRYP APIENTRY *
+#endif
+#ifndef GLAPI
+#define GLAPI extern
+#endif
+
+/*************************************************************/
+
+/* Header file version number */
+/* wglext.h last updated 2012/01/04 */
+/* Current version at http://www.opengl.org/registry/ */
+#define WGL_WGLEXT_VERSION 24
+
+#ifndef WGL_ARB_buffer_region
+#define WGL_FRONT_COLOR_BUFFER_BIT_ARB 0x00000001
+#define WGL_BACK_COLOR_BUFFER_BIT_ARB  0x00000002
+#define WGL_DEPTH_BUFFER_BIT_ARB       0x00000004
+#define WGL_STENCIL_BUFFER_BIT_ARB     0x00000008
+#endif
+
+#ifndef WGL_ARB_multisample
+#define WGL_SAMPLE_BUFFERS_ARB         0x2041
+#define WGL_SAMPLES_ARB                0x2042
+#endif
+
+#ifndef WGL_ARB_extensions_string
+#endif
+
+#ifndef WGL_ARB_pixel_format
+#define WGL_NUMBER_PIXEL_FORMATS_ARB   0x2000
+#define WGL_DRAW_TO_WINDOW_ARB         0x2001
+#define WGL_DRAW_TO_BITMAP_ARB         0x2002
+#define WGL_ACCELERATION_ARB           0x2003
+#define WGL_NEED_PALETTE_ARB           0x2004
+#define WGL_NEED_SYSTEM_PALETTE_ARB    0x2005
+#define WGL_SWAP_LAYER_BUFFERS_ARB     0x2006
+#define WGL_SWAP_METHOD_ARB            0x2007
+#define WGL_NUMBER_OVERLAYS_ARB        0x2008
+#define WGL_NUMBER_UNDERLAYS_ARB       0x2009
+#define WGL_TRANSPARENT_ARB            0x200A
+#define WGL_TRANSPARENT_RED_VALUE_ARB  0x2037
+#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038
+#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039
+#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A
+#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B
+#define WGL_SHARE_DEPTH_ARB            0x200C
+#define WGL_SHARE_STENCIL_ARB          0x200D
+#define WGL_SHARE_ACCUM_ARB            0x200E
+#define WGL_SUPPORT_GDI_ARB            0x200F
+#define WGL_SUPPORT_OPENGL_ARB         0x2010
+#define WGL_DOUBLE_BUFFER_ARB          0x2011
+#define WGL_STEREO_ARB                 0x2012
+#define WGL_PIXEL_TYPE_ARB             0x2013
+#define WGL_COLOR_BITS_ARB             0x2014
+#define WGL_RED_BITS_ARB               0x2015
+#define WGL_RED_SHIFT_ARB              0x2016
+#define WGL_GREEN_BITS_ARB             0x2017
+#define WGL_GREEN_SHIFT_ARB            0x2018
+#define WGL_BLUE_BITS_ARB              0x2019
+#define WGL_BLUE_SHIFT_ARB             0x201A
+#define WGL_ALPHA_BITS_ARB             0x201B
+#define WGL_ALPHA_SHIFT_ARB            0x201C
+#define WGL_ACCUM_BITS_ARB             0x201D
+#define WGL_ACCUM_RED_BITS_ARB         0x201E
+#define WGL_ACCUM_GREEN_BITS_ARB       0x201F
+#define WGL_ACCUM_BLUE_BITS_ARB        0x2020
+#define WGL_ACCUM_ALPHA_BITS_ARB       0x2021
+#define WGL_DEPTH_BITS_ARB             0x2022
+#define WGL_STENCIL_BITS_ARB           0x2023
+#define WGL_AUX_BUFFERS_ARB            0x2024
+#define WGL_NO_ACCELERATION_ARB        0x2025
+#define WGL_GENERIC_ACCELERATION_ARB   0x2026
+#define WGL_FULL_ACCELERATION_ARB      0x2027
+#define WGL_SWAP_EXCHANGE_ARB          0x2028
+#define WGL_SWAP_COPY_ARB              0x2029
+#define WGL_SWAP_UNDEFINED_ARB         0x202A
+#define WGL_TYPE_RGBA_ARB              0x202B
+#define WGL_TYPE_COLORINDEX_ARB        0x202C
+#endif
+
+#ifndef WGL_ARB_make_current_read
+#define ERROR_INVALID_PIXEL_TYPE_ARB   0x2043
+#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054
+#endif
+
+#ifndef WGL_ARB_pbuffer
+#define WGL_DRAW_TO_PBUFFER_ARB        0x202D
+#define WGL_MAX_PBUFFER_PIXELS_ARB     0x202E
+#define WGL_MAX_PBUFFER_WIDTH_ARB      0x202F
+#define WGL_MAX_PBUFFER_HEIGHT_ARB     0x2030
+#define WGL_PBUFFER_LARGEST_ARB        0x2033
+#define WGL_PBUFFER_WIDTH_ARB          0x2034
+#define WGL_PBUFFER_HEIGHT_ARB         0x2035
+#define WGL_PBUFFER_LOST_ARB           0x2036
+#endif
+
+#ifndef WGL_ARB_render_texture
+#define WGL_BIND_TO_TEXTURE_RGB_ARB    0x2070
+#define WGL_BIND_TO_TEXTURE_RGBA_ARB   0x2071
+#define WGL_TEXTURE_FORMAT_ARB         0x2072
+#define WGL_TEXTURE_TARGET_ARB         0x2073
+#define WGL_MIPMAP_TEXTURE_ARB         0x2074
+#define WGL_TEXTURE_RGB_ARB            0x2075
+#define WGL_TEXTURE_RGBA_ARB           0x2076
+#define WGL_NO_TEXTURE_ARB             0x2077
+#define WGL_TEXTURE_CUBE_MAP_ARB       0x2078
+#define WGL_TEXTURE_1D_ARB             0x2079
+#define WGL_TEXTURE_2D_ARB             0x207A
+#define WGL_MIPMAP_LEVEL_ARB           0x207B
+#define WGL_CUBE_MAP_FACE_ARB          0x207C
+#define WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D
+#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x207E
+#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x207F
+#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x2080
+#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x2081
+#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x2082
+#define WGL_FRONT_LEFT_ARB             0x2083
+#define WGL_FRONT_RIGHT_ARB            0x2084
+#define WGL_BACK_LEFT_ARB              0x2085
+#define WGL_BACK_RIGHT_ARB             0x2086
+#define WGL_AUX0_ARB                   0x2087
+#define WGL_AUX1_ARB                   0x2088
+#define WGL_AUX2_ARB                   0x2089
+#define WGL_AUX3_ARB                   0x208A
+#define WGL_AUX4_ARB                   0x208B
+#define WGL_AUX5_ARB                   0x208C
+#define WGL_AUX6_ARB                   0x208D
+#define WGL_AUX7_ARB                   0x208E
+#define WGL_AUX8_ARB                   0x208F
+#define WGL_AUX9_ARB                   0x2090
+#endif
+
+#ifndef WGL_ARB_pixel_format_float
+#define WGL_TYPE_RGBA_FLOAT_ARB        0x21A0
+#endif
+
+#ifndef WGL_ARB_framebuffer_sRGB
+#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9
+#endif
+
+#ifndef WGL_ARB_create_context
+#define WGL_CONTEXT_DEBUG_BIT_ARB      0x00000001
+#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
+#define WGL_CONTEXT_MAJOR_VERSION_ARB  0x2091
+#define WGL_CONTEXT_MINOR_VERSION_ARB  0x2092
+#define WGL_CONTEXT_LAYER_PLANE_ARB    0x2093
+#define WGL_CONTEXT_FLAGS_ARB          0x2094
+#define ERROR_INVALID_VERSION_ARB      0x2095
+#endif
+
+#ifndef WGL_ARB_create_context_profile
+#define WGL_CONTEXT_PROFILE_MASK_ARB   0x9126
+#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
+#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+#define ERROR_INVALID_PROFILE_ARB      0x2096
+#endif
+
+#ifndef WGL_ARB_create_context_robustness
+#define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
+#define WGL_LOSE_CONTEXT_ON_RESET_ARB  0x8252
+#define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
+#define WGL_NO_RESET_NOTIFICATION_ARB  0x8261
+#endif
+
+#ifndef WGL_EXT_make_current_read
+#define ERROR_INVALID_PIXEL_TYPE_EXT   0x2043
+#endif
+
+#ifndef WGL_EXT_pixel_format
+#define WGL_NUMBER_PIXEL_FORMATS_EXT   0x2000
+#define WGL_DRAW_TO_WINDOW_EXT         0x2001
+#define WGL_DRAW_TO_BITMAP_EXT         0x2002
+#define WGL_ACCELERATION_EXT           0x2003
+#define WGL_NEED_PALETTE_EXT           0x2004
+#define WGL_NEED_SYSTEM_PALETTE_EXT    0x2005
+#define WGL_SWAP_LAYER_BUFFERS_EXT     0x2006
+#define WGL_SWAP_METHOD_EXT            0x2007
+#define WGL_NUMBER_OVERLAYS_EXT        0x2008
+#define WGL_NUMBER_UNDERLAYS_EXT       0x2009
+#define WGL_TRANSPARENT_EXT            0x200A
+#define WGL_TRANSPARENT_VALUE_EXT      0x200B
+#define WGL_SHARE_DEPTH_EXT            0x200C
+#define WGL_SHARE_STENCIL_EXT          0x200D
+#define WGL_SHARE_ACCUM_EXT            0x200E
+#define WGL_SUPPORT_GDI_EXT            0x200F
+#define WGL_SUPPORT_OPENGL_EXT         0x2010
+#define WGL_DOUBLE_BUFFER_EXT          0x2011
+#define WGL_STEREO_EXT                 0x2012
+#define WGL_PIXEL_TYPE_EXT             0x2013
+#define WGL_COLOR_BITS_EXT             0x2014
+#define WGL_RED_BITS_EXT               0x2015
+#define WGL_RED_SHIFT_EXT              0x2016
+#define WGL_GREEN_BITS_EXT             0x2017
+#define WGL_GREEN_SHIFT_EXT            0x2018
+#define WGL_BLUE_BITS_EXT              0x2019
+#define WGL_BLUE_SHIFT_EXT             0x201A
+#define WGL_ALPHA_BITS_EXT             0x201B
+#define WGL_ALPHA_SHIFT_EXT            0x201C
+#define WGL_ACCUM_BITS_EXT             0x201D
+#define WGL_ACCUM_RED_BITS_EXT         0x201E
+#define WGL_ACCUM_GREEN_BITS_EXT       0x201F
+#define WGL_ACCUM_BLUE_BITS_EXT        0x2020
+#define WGL_ACCUM_ALPHA_BITS_EXT       0x2021
+#define WGL_DEPTH_BITS_EXT             0x2022
+#define WGL_STENCIL_BITS_EXT           0x2023
+#define WGL_AUX_BUFFERS_EXT            0x2024
+#define WGL_NO_ACCELERATION_EXT        0x2025
+#define WGL_GENERIC_ACCELERATION_EXT   0x2026
+#define WGL_FULL_ACCELERATION_EXT      0x2027
+#define WGL_SWAP_EXCHANGE_EXT          0x2028
+#define WGL_SWAP_COPY_EXT              0x2029
+#define WGL_SWAP_UNDEFINED_EXT         0x202A
+#define WGL_TYPE_RGBA_EXT              0x202B
+#define WGL_TYPE_COLORINDEX_EXT        0x202C
+#endif
+
+#ifndef WGL_EXT_pbuffer
+#define WGL_DRAW_TO_PBUFFER_EXT        0x202D
+#define WGL_MAX_PBUFFER_PIXELS_EXT     0x202E
+#define WGL_MAX_PBUFFER_WIDTH_EXT      0x202F
+#define WGL_MAX_PBUFFER_HEIGHT_EXT     0x2030
+#define WGL_OPTIMAL_PBUFFER_WIDTH_EXT  0x2031
+#define WGL_OPTIMAL_PBUFFER_HEIGHT_EXT 0x2032
+#define WGL_PBUFFER_LARGEST_EXT        0x2033
+#define WGL_PBUFFER_WIDTH_EXT          0x2034
+#define WGL_PBUFFER_HEIGHT_EXT         0x2035
+#endif
+
+#ifndef WGL_EXT_depth_float
+#define WGL_DEPTH_FLOAT_EXT            0x2040
+#endif
+
+#ifndef WGL_3DFX_multisample
+#define WGL_SAMPLE_BUFFERS_3DFX        0x2060
+#define WGL_SAMPLES_3DFX               0x2061
+#endif
+
+#ifndef WGL_EXT_multisample
+#define WGL_SAMPLE_BUFFERS_EXT         0x2041
+#define WGL_SAMPLES_EXT                0x2042
+#endif
+
+#ifndef WGL_I3D_digital_video_control
+#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D 0x2050
+#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D 0x2051
+#define WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D 0x2052
+#define WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D 0x2053
+#endif
+
+#ifndef WGL_I3D_gamma
+#define WGL_GAMMA_TABLE_SIZE_I3D       0x204E
+#define WGL_GAMMA_EXCLUDE_DESKTOP_I3D  0x204F
+#endif
+
+#ifndef WGL_I3D_genlock
+#define WGL_GENLOCK_SOURCE_MULTIVIEW_I3D 0x2044
+#define WGL_GENLOCK_SOURCE_EXTENAL_SYNC_I3D 0x2045
+#define WGL_GENLOCK_SOURCE_EXTENAL_FIELD_I3D 0x2046
+#define WGL_GENLOCK_SOURCE_EXTENAL_TTL_I3D 0x2047
+#define WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D 0x2048
+#define WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D 0x2049
+#define WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D 0x204A
+#define WGL_GENLOCK_SOURCE_EDGE_RISING_I3D 0x204B
+#define WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D 0x204C
+#endif
+
+#ifndef WGL_I3D_image_buffer
+#define WGL_IMAGE_BUFFER_MIN_ACCESS_I3D 0x00000001
+#define WGL_IMAGE_BUFFER_LOCK_I3D      0x00000002
+#endif
+
+#ifndef WGL_I3D_swap_frame_lock
+#endif
+
+#ifndef WGL_NV_render_depth_texture
+#define WGL_BIND_TO_TEXTURE_DEPTH_NV   0x20A3
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV 0x20A4
+#define WGL_DEPTH_TEXTURE_FORMAT_NV    0x20A5
+#define WGL_TEXTURE_DEPTH_COMPONENT_NV 0x20A6
+#define WGL_DEPTH_COMPONENT_NV         0x20A7
+#endif
+
+#ifndef WGL_NV_render_texture_rectangle
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV 0x20A0
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV 0x20A1
+#define WGL_TEXTURE_RECTANGLE_NV       0x20A2
+#endif
+
+#ifndef WGL_ATI_pixel_format_float
+#define WGL_TYPE_RGBA_FLOAT_ATI        0x21A0
+#endif
+
+#ifndef WGL_NV_float_buffer
+#define WGL_FLOAT_COMPONENTS_NV        0x20B0
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV 0x20B1
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV 0x20B2
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV 0x20B3
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV 0x20B4
+#define WGL_TEXTURE_FLOAT_R_NV         0x20B5
+#define WGL_TEXTURE_FLOAT_RG_NV        0x20B6
+#define WGL_TEXTURE_FLOAT_RGB_NV       0x20B7
+#define WGL_TEXTURE_FLOAT_RGBA_NV      0x20B8
+#endif
+
+#ifndef WGL_3DL_stereo_control
+#define WGL_STEREO_EMITTER_ENABLE_3DL  0x2055
+#define WGL_STEREO_EMITTER_DISABLE_3DL 0x2056
+#define WGL_STEREO_POLARITY_NORMAL_3DL 0x2057
+#define WGL_STEREO_POLARITY_INVERT_3DL 0x2058
+#endif
+
+#ifndef WGL_EXT_pixel_format_packed_float
+#define WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT 0x20A8
+#endif
+
+#ifndef WGL_EXT_framebuffer_sRGB
+#define WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20A9
+#endif
+
+#ifndef WGL_NV_present_video
+#define WGL_NUM_VIDEO_SLOTS_NV         0x20F0
+#endif
+
+#ifndef WGL_NV_video_out
+#define WGL_BIND_TO_VIDEO_RGB_NV       0x20C0
+#define WGL_BIND_TO_VIDEO_RGBA_NV      0x20C1
+#define WGL_BIND_TO_VIDEO_RGB_AND_DEPTH_NV 0x20C2
+#define WGL_VIDEO_OUT_COLOR_NV         0x20C3
+#define WGL_VIDEO_OUT_ALPHA_NV         0x20C4
+#define WGL_VIDEO_OUT_DEPTH_NV         0x20C5
+#define WGL_VIDEO_OUT_COLOR_AND_ALPHA_NV 0x20C6
+#define WGL_VIDEO_OUT_COLOR_AND_DEPTH_NV 0x20C7
+#define WGL_VIDEO_OUT_FRAME            0x20C8
+#define WGL_VIDEO_OUT_FIELD_1          0x20C9
+#define WGL_VIDEO_OUT_FIELD_2          0x20CA
+#define WGL_VIDEO_OUT_STACKED_FIELDS_1_2 0x20CB
+#define WGL_VIDEO_OUT_STACKED_FIELDS_2_1 0x20CC
+#endif
+
+#ifndef WGL_NV_swap_group
+#endif
+
+#ifndef WGL_NV_gpu_affinity
+#define WGL_ERROR_INCOMPATIBLE_AFFINITY_MASKS_NV 0x20D0
+#define WGL_ERROR_MISSING_AFFINITY_MASK_NV 0x20D1
+#endif
+
+#ifndef WGL_AMD_gpu_association
+#define WGL_GPU_VENDOR_AMD             0x1F00
+#define WGL_GPU_RENDERER_STRING_AMD    0x1F01
+#define WGL_GPU_OPENGL_VERSION_STRING_AMD 0x1F02
+#define WGL_GPU_FASTEST_TARGET_GPUS_AMD 0x21A2
+#define WGL_GPU_RAM_AMD                0x21A3
+#define WGL_GPU_CLOCK_AMD              0x21A4
+#define WGL_GPU_NUM_PIPES_AMD          0x21A5
+#define WGL_GPU_NUM_SIMD_AMD           0x21A6
+#define WGL_GPU_NUM_RB_AMD             0x21A7
+#define WGL_GPU_NUM_SPI_AMD            0x21A8
+#endif
+
+#ifndef WGL_NV_video_capture
+#define WGL_UNIQUE_ID_NV               0x20CE
+#define WGL_NUM_VIDEO_CAPTURE_SLOTS_NV 0x20CF
+#endif
+
+#ifndef WGL_NV_copy_image
+#endif
+
+#ifndef WGL_NV_multisample_coverage
+#define WGL_COVERAGE_SAMPLES_NV        0x2042
+#define WGL_COLOR_SAMPLES_NV           0x20B9
+#endif
+
+#ifndef WGL_EXT_create_context_es2_profile
+#define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
+#endif
+
+#ifndef WGL_NV_DX_interop
+#define WGL_ACCESS_READ_ONLY_NV        0x00000000
+#define WGL_ACCESS_READ_WRITE_NV       0x00000001
+#define WGL_ACCESS_WRITE_DISCARD_NV    0x00000002
+#endif
+
+#ifndef WGL_NV_DX_interop2
+#endif
+
+#ifndef WGL_EXT_swap_control_tear
+#endif
+
+
+/*************************************************************/
+
+#ifndef WGL_ARB_pbuffer
+DECLARE_HANDLE(HPBUFFERARB);
+#endif
+#ifndef WGL_EXT_pbuffer
+DECLARE_HANDLE(HPBUFFEREXT);
+#endif
+#ifndef WGL_NV_present_video
+DECLARE_HANDLE(HVIDEOOUTPUTDEVICENV);
+#endif
+#ifndef WGL_NV_video_output
+DECLARE_HANDLE(HPVIDEODEV);
+#endif
+#ifndef WGL_NV_gpu_affinity
+DECLARE_HANDLE(HPGPUNV);
+DECLARE_HANDLE(HGPUNV);
+
+typedef struct _GPU_DEVICE {
+    DWORD  cb;
+    CHAR   DeviceName[32];
+    CHAR   DeviceString[128];
+    DWORD  Flags;
+    RECT   rcVirtualScreen;
+} GPU_DEVICE, *PGPU_DEVICE;
+#endif
+#ifndef WGL_NV_video_capture
+DECLARE_HANDLE(HVIDEOINPUTDEVICENV);
+#endif
+
+#ifndef WGL_ARB_buffer_region
+#define WGL_ARB_buffer_region 1
+#ifdef WGL_WGLEXT_PROTOTYPES
+extern HANDLE WINAPI wglCreateBufferRegionARB (HDC hDC, int iLayerPlane, UINT uType);
+extern VOID WINAPI wglDeleteBufferRegionARB (HANDLE hRegion);
+extern BOOL WINAPI wglSaveBufferRegionARB (HANDLE hRegion, int x, int y, int width, int height);
+extern BOOL WINAPI wglRestoreBufferRegionARB (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc);
+#endif /* WGL_WGLEXT_PROTOTYPES */
+typedef HANDLE (WINAPI * PFNWGLCREATEBUFFERREGIONARBPROC) (HDC hDC, int iLayerPlane, UINT uType);
+typedef VOID (WINAPI * PFNWGLDELETEBUFFERREGIONARBPROC) (HANDLE hRegion);
+typedef BOOL (WINAPI * PFNWGLSAVEBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height);
+typedef BOOL (WINAPI * PFNWGLRESTOREBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc);
+#endif
+
+#ifndef WGL_ARB_multisample
+#define WGL_ARB_multisample 1
+#endif
+
+#ifndef WGL_ARB_extensions_string
+#define WGL_ARB_extensions_string 1
+#ifdef WGL_WGLEXT_PROTOTYPES
+extern const char * WINAPI wglGetExtensionsStringARB (HDC hdc);
+#endif /* WGL_WGLEXT_PROTOTYPES */
+typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc);
+#endif
+
+#ifndef WGL_ARB_pixel_format
+#define WGL_ARB_pixel_format 1
+#ifdef WGL_WGLEXT_PROTOTYPES
+extern BOOL WINAPI wglGetPixelFormatAttribivARB (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues);
+extern BOOL WINAPI wglGetPixelFormatAttribfvARB (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues);
+extern BOOL WINAPI wglChoosePixelFormatARB (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
+#endif /* WGL_WGLEXT_PROTOTYPES */
+typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues);
+typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues);
+typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
+#endif
+
+#ifndef WGL_ARB_make_current_read
+#define WGL_ARB_make_current_read 1
+#ifdef WGL_WGLEXT_PROTOTYPES
+extern BOOL WINAPI wglMakeContextCurrentARB (HDC hDrawDC, HDC hReadDC, HGLRC hglrc);
+extern HDC WINAPI wglGetCurrentReadDCARB (void);
+#endif /* WGL_WGLEXT_PROTOTYPES */
+typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTARBPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc);
+typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCARBPROC) (void);
+#endif
+
+#ifndef WGL_ARB_pbuffer
+#define WGL_ARB_pbuffer 1
+#ifdef WGL_WGLEXT_PROTOTYPES
+extern HPBUFFERARB WINAPI wglCreatePbufferARB (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList);
+extern HDC WINAPI wglGetPbufferDCARB (HPBUFFERARB hPbuffer);
+extern int WINAPI wglReleasePbufferDCARB (HPBUFFERARB hPbuffer, HDC hDC);
+extern BOOL WINAPI wglDestroyPbufferARB (HPBUFFERARB hPbuffer);
+extern BOOL WINAPI wglQueryPbufferARB (HPBUFFERARB hPbuffer, int iAttribute, int *piValue);
+#endif /* WGL_WGLEXT_PROTOTYPES */
+typedef HPBUFFERARB (WINAPI * PFNWGLCREATEPBUFFERARBPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList);
+typedef HDC (WINAPI * PFNWGLGETPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer);
+typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer, HDC hDC);
+typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFERARBPROC) (HPBUFFERARB hPbuffer);
+typedef BOOL (WINAPI * PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, int iAttribute, int *piValue);
+#endif
+
+#ifndef WGL_ARB_render_texture
+#define WGL_ARB_render_texture 1
+#ifdef WGL_WGLEXT_PROTOTYPES
+extern BOOL WINAPI wglBindTexImageARB (HPBUFFERARB hPbuffer, int iBuffer);
+extern BOOL WINAPI wglReleaseTexImageARB (HPBUFFERARB hPbuffer, int iBuffer);
+extern BOOL WINAPI wglSetPbufferAttribARB (HPBUFFERARB hPbuffer, const int *piAttribList);
+#endif /* WGL_WGLEXT_PROTOTYPES */
+typedef BOOL (WINAPI * PFNWGLBINDTEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer);
+typedef BOOL (WINAPI * PFNWGLRELEASETEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer);
+typedef BOOL (WINAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, const int *piAttribList);
+#endif
+
+#ifndef WGL_ARB_pixel_format_float
+#define WGL_ARB_pixel_format_float 1
+#endif
+
+#ifndef WGL_ARB_framebuffer_sRGB
+#define WGL_ARB_framebuffer_sRGB 1
+#endif
+
+#ifndef WGL_ARB_create_context
+#define WGL_ARB_create_context 1
+#ifdef WGL_WGLEXT_PROTOTYPES
+extern HGLRC WINAPI wglCreateContextAttribsARB (HDC hDC, HGLRC hShareContext, const int *attribList);
+#endif /* WGL_WGLEXT_PROTOTYPES */
+typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int *attribList);
+#endif
+
+#ifndef WGL_ARB_create_context_profile
+#define WGL_ARB_create_context_profile 1
+#endif
+
+#ifndef WGL_ARB_create_context_robustness
+#define WGL_ARB_create_context_robustness 1
+#endif
+
+#ifndef WGL_EXT_display_color_table
+#define WGL_EXT_display_color_table 1
+#ifdef WGL_WGLEXT_PROTOTYPES
+extern GLboolean WINAPI wglCreateDisplayColorTableEXT (GLushort id);
+extern GLboolean WINAPI wglLoadDisplayColorTableEXT (const GLushort *table, GLuint length);
+extern GLboolean WINAPI wglBindDisplayColorTableEXT (GLushort id);
+extern VOID WINAPI wglDestroyDisplayColorTableEXT (GLushort id);
+#endif /* WGL_WGLEXT_PROTOTYPES */
+typedef GLboolean (WINAPI * PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC) (GLushort id);
+typedef GLboolean (WINAPI * PFNWGLLOADDISPLAYCOLORTABLEEXTPROC) (const GLushort *table, GLuint length);
+typedef GLboolean (WINAPI * PFNWGLBINDDISPLAYCOLORTABLEEXTPROC) (GLushort id);
+typedef VOID (WINAPI * PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC) (GLushort id);
+#endif
+
+#ifndef WGL_EXT_extensions_string
+#define WGL_EXT_extensions_string 1
+#ifdef WGL_WGLEXT_PROTOTYPES
+extern const char * WINAPI wglGetExtensionsStringEXT (void);
+#endif /* WGL_WGLEXT_PROTOTYPES */
+typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC) (void);
+#endif
+
+#ifndef WGL_EXT_make_current_read
+#define WGL_EXT_make_current_read 1
+#ifdef WGL_WGLEXT_PROTOTYPES
+extern BOOL WINAPI wglMakeContextCurrentEXT (HDC hDrawDC, HDC hReadDC, HGLRC hglrc);
+extern HDC WINAPI wglGetCurrentReadDCEXT (void);
+#endif /* WGL_WGLEXT_PROTOTYPES */
+typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTEXTPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc);
+typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCEXTPROC) (void);
+#endif
+
+#ifndef WGL_EXT_pbuffer
+#define WGL_EXT_pbuffer 1
+#ifdef WGL_WGLEXT_PROTOTYPES
+extern HPBUFFEREXT WINAPI wglCreatePbufferEXT (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList);
+extern HDC WINAPI wglGetPbufferDCEXT (HPBUFFEREXT hPbuffer);
+extern int WINAPI wglReleasePbufferDCEXT (HPBUFFEREXT hPbuffer, HDC hDC);
+extern BOOL WINAPI wglDestroyPbufferEXT (HPBUFFEREXT hPbuffer);
+extern BOOL WINAPI wglQueryPbufferEXT (HPBUFFEREXT hPbuffer, int iAttribute, int *piValue);
+#endif /* WGL_WGLEXT_PROTOTYPES */
+typedef HPBUFFEREXT (WINAPI * PFNWGLCREATEPBUFFEREXTPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList);
+typedef HDC (WINAPI * PFNWGLGETPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer);
+typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer, HDC hDC);
+typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer);
+typedef BOOL (WINAPI * PFNWGLQUERYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer, int iAttribute, int *piValue);
+#endif
+
+#ifndef WGL_EXT_pixel_format
+#define WGL_EXT_pixel_format 1
+#ifdef WGL_WGLEXT_PROTOTYPES
+extern BOOL WINAPI wglGetPixelFormatAttribivEXT (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, int *piValues);
+extern BOOL WINAPI wglGetPixelFormatAttribfvEXT (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, FLOAT *pfValues);
+extern BOOL WINAPI wglChoosePixelFormatEXT (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
+#endif /* WGL_WGLEXT_PROTOTYPES */
+typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, int *piValues);
+typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, FLOAT *pfValues);
+typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATEXTPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
+#endif
+
+#ifndef WGL_EXT_swap_control
+#define WGL_EXT_swap_control 1
+#ifdef WGL_WGLEXT_PROTOTYPES
+extern BOOL WINAPI wglSwapIntervalEXT (int interval);
+extern int WINAPI wglGetSwapIntervalEXT (void);
+#endif /* WGL_WGLEXT_PROTOTYPES */
+typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval);
+typedef int (WINAPI * PFNWGLGETSWAPINTERVALEXTPROC) (void);
+#endif
+
+#ifndef WGL_EXT_depth_float
+#define WGL_EXT_depth_float 1
+#endif
+
+#ifndef WGL_NV_vertex_array_range
+#define WGL_NV_vertex_array_range 1
+#ifdef WGL_WGLEXT_PROTOTYPES
+extern void* WINAPI wglAllocateMemoryNV (GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority);
+extern void WINAPI wglFreeMemoryNV (void *pointer);
+#endif /* WGL_WGLEXT_PROTOTYPES */
+typedef void* (WINAPI * PFNWGLALLOCATEMEMORYNVPROC) (GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority);
+typedef void (WINAPI * PFNWGLFREEMEMORYNVPROC) (void *pointer);
+#endif
+
+#ifndef WGL_3DFX_multisample
+#define WGL_3DFX_multisample 1
+#endif
+
+#ifndef WGL_EXT_multisample
+#define WGL_EXT_multisample 1
+#endif
+
+#ifndef WGL_OML_sync_control
+#define WGL_OML_sync_control 1
+#ifdef WGL_WGLEXT_PROTOTYPES
+extern BOOL WINAPI wglGetSyncValuesOML (HDC hdc, INT64 *ust, INT64 *msc, INT64 *sbc);
+extern BOOL WINAPI wglGetMscRateOML (HDC hdc, INT32 *numerator, INT32 *denominator);
+extern INT64 WINAPI wglSwapBuffersMscOML (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder);
+extern INT64 WINAPI wglSwapLayerBuffersMscOML (HDC hdc, int fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder);
+extern BOOL WINAPI wglWaitForMscOML (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64 *ust, INT64 *msc, INT64 *sbc);
+extern BOOL WINAPI wglWaitForSbcOML (HDC hdc, INT64 target_sbc, INT64 *ust, INT64 *msc, INT64 *sbc);
+#endif /* WGL_WGLEXT_PROTOTYPES */
+typedef BOOL (WINAPI * PFNWGLGETSYNCVALUESOMLPROC) (HDC hdc, INT64 *ust, INT64 *msc, INT64 *sbc);
+typedef BOOL (WINAPI * PFNWGLGETMSCRATEOMLPROC) (HDC hdc, INT32 *numerator, INT32 *denominator);
+typedef INT64 (WINAPI * PFNWGLSWAPBUFFERSMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder);
+typedef INT64 (WINAPI * PFNWGLSWAPLAYERBUFFERSMSCOMLPROC) (HDC hdc, int fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder);
+typedef BOOL (WINAPI * PFNWGLWAITFORMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64 *ust, INT64 *msc, INT64 *sbc);
+typedef BOOL (WINAPI * PFNWGLWAITFORSBCOMLPROC) (HDC hdc, INT64 target_sbc, INT64 *ust, INT64 *msc, INT64 *sbc);
+#endif
+
+#ifndef WGL_I3D_digital_video_control
+#define WGL_I3D_digital_video_control 1
+#ifdef WGL_WGLEXT_PROTOTYPES
+extern BOOL WINAPI wglGetDigitalVideoParametersI3D (HDC hDC, int iAttribute, int *piValue);
+extern BOOL WINAPI wglSetDigitalVideoParametersI3D (HDC hDC, int iAttribute, const int *piValue);
+#endif /* WGL_WGLEXT_PROTOTYPES */
+typedef BOOL (WINAPI * PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int *piValue);
+typedef BOOL (WINAPI * PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int *piValue);
+#endif
+
+#ifndef WGL_I3D_gamma
+#define WGL_I3D_gamma 1
+#ifdef WGL_WGLEXT_PROTOTYPES
+extern BOOL WINAPI wglGetGammaTableParametersI3D (HDC hDC, int iAttribute, int *piValue);
+extern BOOL WINAPI wglSetGammaTableParametersI3D (HDC hDC, int iAttribute, const int *piValue);
+extern BOOL WINAPI wglGetGammaTableI3D (HDC hDC, int iEntries, USHORT *puRed, USHORT *puGreen, USHORT *puBlue);
+extern BOOL WINAPI wglSetGammaTableI3D (HDC hDC, int iEntries, const USHORT *puRed, const USHORT *puGreen, const USHORT *puBlue);
+#endif /* WGL_WGLEXT_PROTOTYPES */
+typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int *piValue);
+typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int *piValue);
+typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, USHORT *puRed, USHORT *puGreen, USHORT *puBlue);
+typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, const USHORT *puRed, const USHORT *puGreen, const USHORT *puBlue);
+#endif
+
+#ifndef WGL_I3D_genlock
+#define WGL_I3D_genlock 1
+#ifdef WGL_WGLEXT_PROTOTYPES
+extern BOOL WINAPI wglEnableGenlockI3D (HDC hDC);
+extern BOOL WINAPI wglDisableGenlockI3D (HDC hDC);
+extern BOOL WINAPI wglIsEnabledGenlockI3D (HDC hDC, BOOL *pFlag);
+extern BOOL WINAPI wglGenlockSourceI3D (HDC hDC, UINT uSource);
+extern BOOL WINAPI wglGetGenlockSourceI3D (HDC hDC, UINT *uSource);
+extern BOOL WINAPI wglGenlockSourceEdgeI3D (HDC hDC, UINT uEdge);
+extern BOOL WINAPI wglGetGenlockSourceEdgeI3D (HDC hDC, UINT *uEdge);
+extern BOOL WINAPI wglGenlockSampleRateI3D (HDC hDC, UINT uRate);
+extern BOOL WINAPI wglGetGenlockSampleRateI3D (HDC hDC, UINT *uRate);
+extern BOOL WINAPI wglGenlockSourceDelayI3D (HDC hDC, UINT uDelay);
+extern BOOL WINAPI wglGetGenlockSourceDelayI3D (HDC hDC, UINT *uDelay);
+extern BOOL WINAPI wglQueryGenlockMaxSourceDelayI3D (HDC hDC, UINT *uMaxLineDelay, UINT *uMaxPixelDelay);
+#endif /* WGL_WGLEXT_PROTOTYPES */
+typedef BOOL (WINAPI * PFNWGLENABLEGENLOCKI3DPROC) (HDC hDC);
+typedef BOOL (WINAPI * PFNWGLDISABLEGENLOCKI3DPROC) (HDC hDC);
+typedef BOOL (WINAPI * PFNWGLISENABLEDGENLOCKI3DPROC) (HDC hDC, BOOL *pFlag);
+typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEI3DPROC) (HDC hDC, UINT uSource);
+typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEI3DPROC) (HDC hDC, UINT *uSource);
+typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT uEdge);
+typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT *uEdge);
+typedef BOOL (WINAPI * PFNWGLGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT uRate);
+typedef BOOL (WINAPI * PFNWGLGETGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT *uRate);
+typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT uDelay);
+typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT *uDelay);
+typedef BOOL (WINAPI * PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC) (HDC hDC, UINT *uMaxLineDelay, UINT *uMaxPixelDelay);
+#endif
+
+#ifndef WGL_I3D_image_buffer
+#define WGL_I3D_image_buffer 1
+#ifdef WGL_WGLEXT_PROTOTYPES
+extern LPVOID WINAPI wglCreateImageBufferI3D (HDC hDC, DWORD dwSize, UINT uFlags);
+extern BOOL WINAPI wglDestroyImageBufferI3D (HDC hDC, LPVOID pAddress);
+extern BOOL WINAPI wglAssociateImageBufferEventsI3D (HDC hDC, const HANDLE *pEvent, const LPVOID *pAddress, const DWORD *pSize, UINT count);
+extern BOOL WINAPI wglReleaseImageBufferEventsI3D (HDC hDC, const LPVOID *pAddress, UINT count);
+#endif /* WGL_WGLEXT_PROTOTYPES */
+typedef LPVOID (WINAPI * PFNWGLCREATEIMAGEBUFFERI3DPROC) (HDC hDC, DWORD dwSize, UINT uFlags);
+typedef BOOL (WINAPI * PFNWGLDESTROYIMAGEBUFFERI3DPROC) (HDC hDC, LPVOID pAddress);
+typedef BOOL (WINAPI * PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC) (HDC hDC, const HANDLE *pEvent, const LPVOID *pAddress, const DWORD *pSize, UINT count);
+typedef BOOL (WINAPI * PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC) (HDC hDC, const LPVOID *pAddress, UINT count);
+#endif
+
+#ifndef WGL_I3D_swap_frame_lock
+#define WGL_I3D_swap_frame_lock 1
+#ifdef WGL_WGLEXT_PROTOTYPES
+extern BOOL WINAPI wglEnableFrameLockI3D (void);
+extern BOOL WINAPI wglDisableFrameLockI3D (void);
+extern BOOL WINAPI wglIsEnabledFrameLockI3D (BOOL *pFlag);
+extern BOOL WINAPI wglQueryFrameLockMasterI3D (BOOL *pFlag);
+#endif /* WGL_WGLEXT_PROTOTYPES */
+typedef BOOL (WINAPI * PFNWGLENABLEFRAMELOCKI3DPROC) (void);
+typedef BOOL (WINAPI * PFNWGLDISABLEFRAMELOCKI3DPROC) (void);
+typedef BOOL (WINAPI * PFNWGLISENABLEDFRAMELOCKI3DPROC) (BOOL *pFlag);
+typedef BOOL (WINAPI * PFNWGLQUERYFRAMELOCKMASTERI3DPROC) (BOOL *pFlag);
+#endif
+
+#ifndef WGL_I3D_swap_frame_usage
+#define WGL_I3D_swap_frame_usage 1
+#ifdef WGL_WGLEXT_PROTOTYPES
+extern BOOL WINAPI wglGetFrameUsageI3D (float *pUsage);
+extern BOOL WINAPI wglBeginFrameTrackingI3D (void);
+extern BOOL WINAPI wglEndFrameTrackingI3D (void);
+extern BOOL WINAPI wglQueryFrameTrackingI3D (DWORD *pFrameCount, DWORD *pMissedFrames, float *pLastMissedUsage);
+#endif /* WGL_WGLEXT_PROTOTYPES */
+typedef BOOL (WINAPI * PFNWGLGETFRAMEUSAGEI3DPROC) (float *pUsage);
+typedef BOOL (WINAPI * PFNWGLBEGINFRAMETRACKINGI3DPROC) (void);
+typedef BOOL (WINAPI * PFNWGLENDFRAMETRACKINGI3DPROC) (void);
+typedef BOOL (WINAPI * PFNWGLQUERYFRAMETRACKINGI3DPROC) (DWORD *pFrameCount, DWORD *pMissedFrames, float *pLastMissedUsage);
+#endif
+
+#ifndef WGL_ATI_pixel_format_float
+#define WGL_ATI_pixel_format_float 1
+#endif
+
+#ifndef WGL_NV_float_buffer
+#define WGL_NV_float_buffer 1
+#endif
+
+#ifndef WGL_3DL_stereo_control
+#define WGL_3DL_stereo_control 1
+#ifdef WGL_WGLEXT_PROTOTYPES
+extern BOOL WINAPI wglSetStereoEmitterState3DL (HDC hDC, UINT uState);
+#endif /* WGL_WGLEXT_PROTOTYPES */
+typedef BOOL (WINAPI * PFNWGLSETSTEREOEMITTERSTATE3DLPROC) (HDC hDC, UINT uState);
+#endif
+
+#ifndef WGL_EXT_pixel_format_packed_float
+#define WGL_EXT_pixel_format_packed_float 1
+#endif
+
+#ifndef WGL_EXT_framebuffer_sRGB
+#define WGL_EXT_framebuffer_sRGB 1
+#endif
+
+#ifndef WGL_NV_present_video
+#define WGL_NV_present_video 1
+#ifdef WGL_WGLEXT_PROTOTYPES
+extern int WINAPI wglEnumerateVideoDevicesNV (HDC hDC, HVIDEOOUTPUTDEVICENV *phDeviceList);
+extern BOOL WINAPI wglBindVideoDeviceNV (HDC hDC, unsigned int uVideoSlot, HVIDEOOUTPUTDEVICENV hVideoDevice, const int *piAttribList);
+extern BOOL WINAPI wglQueryCurrentContextNV (int iAttribute, int *piValue);
+#endif /* WGL_WGLEXT_PROTOTYPES */
+typedef int (WINAPI * PFNWGLENUMERATEVIDEODEVICESNVPROC) (HDC hDC, HVIDEOOUTPUTDEVICENV *phDeviceList);
+typedef BOOL (WINAPI * PFNWGLBINDVIDEODEVICENVPROC) (HDC hDC, unsigned int uVideoSlot, HVIDEOOUTPUTDEVICENV hVideoDevice, const int *piAttribList);
+typedef BOOL (WINAPI * PFNWGLQUERYCURRENTCONTEXTNVPROC) (int iAttribute, int *piValue);
+#endif
+
+#ifndef WGL_NV_video_output
+#define WGL_NV_video_output 1
+#ifdef WGL_WGLEXT_PROTOTYPES
+extern BOOL WINAPI wglGetVideoDeviceNV (HDC hDC, int numDevices, HPVIDEODEV *hVideoDevice);
+extern BOOL WINAPI wglReleaseVideoDeviceNV (HPVIDEODEV hVideoDevice);
+extern BOOL WINAPI wglBindVideoImageNV (HPVIDEODEV hVideoDevice, HPBUFFERARB hPbuffer, int iVideoBuffer);
+extern BOOL WINAPI wglReleaseVideoImageNV (HPBUFFERARB hPbuffer, int iVideoBuffer);
+extern BOOL WINAPI wglSendPbufferToVideoNV (HPBUFFERARB hPbuffer, int iBufferType, unsigned long *pulCounterPbuffer, BOOL bBlock);
+extern BOOL WINAPI wglGetVideoInfoNV (HPVIDEODEV hpVideoDevice, unsigned long *pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo);
+#endif /* WGL_WGLEXT_PROTOTYPES */
+typedef BOOL (WINAPI * PFNWGLGETVIDEODEVICENVPROC) (HDC hDC, int numDevices, HPVIDEODEV *hVideoDevice);
+typedef BOOL (WINAPI * PFNWGLRELEASEVIDEODEVICENVPROC) (HPVIDEODEV hVideoDevice);
+typedef BOOL (WINAPI * PFNWGLBINDVIDEOIMAGENVPROC) (HPVIDEODEV hVideoDevice, HPBUFFERARB hPbuffer, int iVideoBuffer);
+typedef BOOL (WINAPI * PFNWGLRELEASEVIDEOIMAGENVPROC) (HPBUFFERARB hPbuffer, int iVideoBuffer);
+typedef BOOL (WINAPI * PFNWGLSENDPBUFFERTOVIDEONVPROC) (HPBUFFERARB hPbuffer, int iBufferType, unsigned long *pulCounterPbuffer, BOOL bBlock);
+typedef BOOL (WINAPI * PFNWGLGETVIDEOINFONVPROC) (HPVIDEODEV hpVideoDevice, unsigned long *pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo);
+#endif
+
+#ifndef WGL_NV_swap_group
+#define WGL_NV_swap_group 1
+#ifdef WGL_WGLEXT_PROTOTYPES
+extern BOOL WINAPI wglJoinSwapGroupNV (HDC hDC, GLuint group);
+extern BOOL WINAPI wglBindSwapBarrierNV (GLuint group, GLuint barrier);
+extern BOOL WINAPI wglQuerySwapGroupNV (HDC hDC, GLuint *group, GLuint *barrier);
+extern BOOL WINAPI wglQueryMaxSwapGroupsNV (HDC hDC, GLuint *maxGroups, GLuint *maxBarriers);
+extern BOOL WINAPI wglQueryFrameCountNV (HDC hDC, GLuint *count);
+extern BOOL WINAPI wglResetFrameCountNV (HDC hDC);
+#endif /* WGL_WGLEXT_PROTOTYPES */
+typedef BOOL (WINAPI * PFNWGLJOINSWAPGROUPNVPROC) (HDC hDC, GLuint group);
+typedef BOOL (WINAPI * PFNWGLBINDSWAPBARRIERNVPROC) (GLuint group, GLuint barrier);
+typedef BOOL (WINAPI * PFNWGLQUERYSWAPGROUPNVPROC) (HDC hDC, GLuint *group, GLuint *barrier);
+typedef BOOL (WINAPI * PFNWGLQUERYMAXSWAPGROUPSNVPROC) (HDC hDC, GLuint *maxGroups, GLuint *maxBarriers);
+typedef BOOL (WINAPI * PFNWGLQUERYFRAMECOUNTNVPROC) (HDC hDC, GLuint *count);
+typedef BOOL (WINAPI * PFNWGLRESETFRAMECOUNTNVPROC) (HDC hDC);
+#endif
+
+#ifndef WGL_NV_gpu_affinity
+#define WGL_NV_gpu_affinity 1
+#ifdef WGL_WGLEXT_PROTOTYPES
+extern BOOL WINAPI wglEnumGpusNV (UINT iGpuIndex, HGPUNV *phGpu);
+extern BOOL WINAPI wglEnumGpuDevicesNV (HGPUNV hGpu, UINT iDeviceIndex, PGPU_DEVICE lpGpuDevice);
+extern HDC WINAPI wglCreateAffinityDCNV (const HGPUNV *phGpuList);
+extern BOOL WINAPI wglEnumGpusFromAffinityDCNV (HDC hAffinityDC, UINT iGpuIndex, HGPUNV *hGpu);
+extern BOOL WINAPI wglDeleteDCNV (HDC hdc);
+#endif /* WGL_WGLEXT_PROTOTYPES */
+typedef BOOL (WINAPI * PFNWGLENUMGPUSNVPROC) (UINT iGpuIndex, HGPUNV *phGpu);
+typedef BOOL (WINAPI * PFNWGLENUMGPUDEVICESNVPROC) (HGPUNV hGpu, UINT iDeviceIndex, PGPU_DEVICE lpGpuDevice);
+typedef HDC (WINAPI * PFNWGLCREATEAFFINITYDCNVPROC) (const HGPUNV *phGpuList);
+typedef BOOL (WINAPI * PFNWGLENUMGPUSFROMAFFINITYDCNVPROC) (HDC hAffinityDC, UINT iGpuIndex, HGPUNV *hGpu);
+typedef BOOL (WINAPI * PFNWGLDELETEDCNVPROC) (HDC hdc);
+#endif
+
+#ifndef WGL_AMD_gpu_association
+#define WGL_AMD_gpu_association 1
+#ifdef WGL_WGLEXT_PROTOTYPES
+extern UINT WINAPI wglGetGPUIDsAMD (UINT maxCount, UINT *ids);
+extern INT WINAPI wglGetGPUInfoAMD (UINT id, int property, GLenum dataType, UINT size, void *data);
+extern UINT WINAPI wglGetContextGPUIDAMD (HGLRC hglrc);
+extern HGLRC WINAPI wglCreateAssociatedContextAMD (UINT id);
+extern HGLRC WINAPI wglCreateAssociatedContextAttribsAMD (UINT id, HGLRC hShareContext, const int *attribList);
+extern BOOL WINAPI wglDeleteAssociatedContextAMD (HGLRC hglrc);
+extern BOOL WINAPI wglMakeAssociatedContextCurrentAMD (HGLRC hglrc);
+extern HGLRC WINAPI wglGetCurrentAssociatedContextAMD (void);
+extern VOID WINAPI wglBlitContextFramebufferAMD (HGLRC dstCtx, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#endif /* WGL_WGLEXT_PROTOTYPES */
+typedef UINT (WINAPI * PFNWGLGETGPUIDSAMDPROC) (UINT maxCount, UINT *ids);
+typedef INT (WINAPI * PFNWGLGETGPUINFOAMDPROC) (UINT id, int property, GLenum dataType, UINT size, void *data);
+typedef UINT (WINAPI * PFNWGLGETCONTEXTGPUIDAMDPROC) (HGLRC hglrc);
+typedef HGLRC (WINAPI * PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC) (UINT id);
+typedef HGLRC (WINAPI * PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC) (UINT id, HGLRC hShareContext, const int *attribList);
+typedef BOOL (WINAPI * PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC) (HGLRC hglrc);
+typedef BOOL (WINAPI * PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC) (HGLRC hglrc);
+typedef HGLRC (WINAPI * PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC) (void);
+typedef VOID (WINAPI * PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC) (HGLRC dstCtx, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#endif
+
+#ifndef WGL_NV_video_capture
+#define WGL_NV_video_capture 1
+#ifdef WGL_WGLEXT_PROTOTYPES
+extern BOOL WINAPI wglBindVideoCaptureDeviceNV (UINT uVideoSlot, HVIDEOINPUTDEVICENV hDevice);
+extern UINT WINAPI wglEnumerateVideoCaptureDevicesNV (HDC hDc, HVIDEOINPUTDEVICENV *phDeviceList);
+extern BOOL WINAPI wglLockVideoCaptureDeviceNV (HDC hDc, HVIDEOINPUTDEVICENV hDevice);
+extern BOOL WINAPI wglQueryVideoCaptureDeviceNV (HDC hDc, HVIDEOINPUTDEVICENV hDevice, int iAttribute, int *piValue);
+extern BOOL WINAPI wglReleaseVideoCaptureDeviceNV (HDC hDc, HVIDEOINPUTDEVICENV hDevice);
+#endif /* WGL_WGLEXT_PROTOTYPES */
+typedef BOOL (WINAPI * PFNWGLBINDVIDEOCAPTUREDEVICENVPROC) (UINT uVideoSlot, HVIDEOINPUTDEVICENV hDevice);
+typedef UINT (WINAPI * PFNWGLENUMERATEVIDEOCAPTUREDEVICESNVPROC) (HDC hDc, HVIDEOINPUTDEVICENV *phDeviceList);
+typedef BOOL (WINAPI * PFNWGLLOCKVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice);
+typedef BOOL (WINAPI * PFNWGLQUERYVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice, int iAttribute, int *piValue);
+typedef BOOL (WINAPI * PFNWGLRELEASEVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice);
+#endif
+
+#ifndef WGL_NV_copy_image
+#define WGL_NV_copy_image 1
+#ifdef WGL_WGLEXT_PROTOTYPES
+extern BOOL WINAPI wglCopyImageSubDataNV (HGLRC hSrcRC, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, HGLRC hDstRC, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth);
+#endif /* WGL_WGLEXT_PROTOTYPES */
+typedef BOOL (WINAPI * PFNWGLCOPYIMAGESUBDATANVPROC) (HGLRC hSrcRC, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, HGLRC hDstRC, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth);
+#endif
+
+#ifndef WGL_NV_multisample_coverage
+#define WGL_NV_multisample_coverage 1
+#endif
+
+#ifndef WGL_NV_DX_interop
+#define WGL_NV_DX_interop 1
+#ifdef WGL_WGLEXT_PROTOTYPES
+extern BOOL WINAPI wglDXSetResourceShareHandleNV (void *dxObject, HANDLE shareHandle);
+extern HANDLE WINAPI wglDXOpenDeviceNV (void *dxDevice);
+extern BOOL WINAPI wglDXCloseDeviceNV (HANDLE hDevice);
+extern HANDLE WINAPI wglDXRegisterObjectNV (HANDLE hDevice, void *dxObject, GLuint name, GLenum type, GLenum access);
+extern BOOL WINAPI wglDXUnregisterObjectNV (HANDLE hDevice, HANDLE hObject);
+extern BOOL WINAPI wglDXObjectAccessNV (HANDLE hObject, GLenum access);
+extern BOOL WINAPI wglDXLockObjectsNV (HANDLE hDevice, GLint count, HANDLE *hObjects);
+extern BOOL WINAPI wglDXUnlockObjectsNV (HANDLE hDevice, GLint count, HANDLE *hObjects);
+#endif /* WGL_WGLEXT_PROTOTYPES */
+typedef BOOL (WINAPI * PFNWGLDXSETRESOURCESHAREHANDLENVPROC) (void *dxObject, HANDLE shareHandle);
+typedef HANDLE (WINAPI * PFNWGLDXOPENDEVICENVPROC) (void *dxDevice);
+typedef BOOL (WINAPI * PFNWGLDXCLOSEDEVICENVPROC) (HANDLE hDevice);
+typedef HANDLE (WINAPI * PFNWGLDXREGISTEROBJECTNVPROC) (HANDLE hDevice, void *dxObject, GLuint name, GLenum type, GLenum access);
+typedef BOOL (WINAPI * PFNWGLDXUNREGISTEROBJECTNVPROC) (HANDLE hDevice, HANDLE hObject);
+typedef BOOL (WINAPI * PFNWGLDXOBJECTACCESSNVPROC) (HANDLE hObject, GLenum access);
+typedef BOOL (WINAPI * PFNWGLDXLOCKOBJECTSNVPROC) (HANDLE hDevice, GLint count, HANDLE *hObjects);
+typedef BOOL (WINAPI * PFNWGLDXUNLOCKOBJECTSNVPROC) (HANDLE hDevice, GLint count, HANDLE *hObjects);
+#endif
+
+#ifndef WGL_NV_DX_interop2
+#define WGL_NV_DX_interop2 1
+#endif
+
+#ifndef WGL_EXT_swap_control_tear
+#define WGL_EXT_swap_control_tear 1
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/include/wine/wined3d.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/include/wine/wined3d.h	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/vbox/libWineStub/include/wine/wined3d.h	(revision 46521)
@@ -0,0 +1,2486 @@
+/*
+ * Copyright 2002-2003 The wine-d3d team
+ * Copyright 2002-2003 Jason Edmeades
+ * Copyright 2002-2003 Raphael Junqueira
+ * Copyright 2005 Oliver Stieber
+ * Copyright 2006 Stefan Dösinger
+ * Copyright 2006 Stefan Dösinger for CodeWeavers
+ * Copyright 2007 Henri Verbeet
+ * Copyright 2008 Henri Verbeet for CodeWeavers
+ *
+ * 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_WINED3D_H
+#define __WINE_WINED3D_H
+
+#ifdef VBOX_WITH_WDDM
+#include "../../../vbox/VBoxWineEx.h"
+#endif
+
+#ifdef VBOX
+#define DECLSPEC_HIDDEN
+#endif
+
+#define WINED3D_OK                                              S_OK
+
+#define _FACWINED3D                                             0x876
+#define MAKE_WINED3DSTATUS(code)                                MAKE_HRESULT(0, _FACWINED3D, code)
+#define WINED3DOK_NOAUTOGEN                                     MAKE_WINED3DSTATUS(2159)
+
+#define MAKE_WINED3DHRESULT(code)                               MAKE_HRESULT(1, _FACWINED3D, code)
+#define WINED3DERR_WRONGTEXTUREFORMAT                           MAKE_WINED3DHRESULT(2072)
+#define WINED3DERR_UNSUPPORTEDCOLOROPERATION                    MAKE_WINED3DHRESULT(2073)
+#define WINED3DERR_UNSUPPORTEDCOLORARG                          MAKE_WINED3DHRESULT(2074)
+#define WINED3DERR_UNSUPPORTEDALPHAOPERATION                    MAKE_WINED3DHRESULT(2075)
+#define WINED3DERR_UNSUPPORTEDALPHAARG                          MAKE_WINED3DHRESULT(2076)
+#define WINED3DERR_TOOMANYOPERATIONS                            MAKE_WINED3DHRESULT(2077)
+#define WINED3DERR_CONFLICTINGTEXTUREFILTER                     MAKE_WINED3DHRESULT(2078)
+#define WINED3DERR_UNSUPPORTEDFACTORVALUE                       MAKE_WINED3DHRESULT(2079)
+#define WINED3DERR_CONFLICTINGRENDERSTATE                       MAKE_WINED3DHRESULT(2081)
+#define WINED3DERR_UNSUPPORTEDTEXTUREFILTER                     MAKE_WINED3DHRESULT(2082)
+#define WINED3DERR_CONFLICTINGTEXTUREPALETTE                    MAKE_WINED3DHRESULT(2086)
+#define WINED3DERR_DRIVERINTERNALERROR                          MAKE_WINED3DHRESULT(2087)
+#define WINED3DERR_NOTFOUND                                     MAKE_WINED3DHRESULT(2150)
+#define WINED3DERR_MOREDATA                                     MAKE_WINED3DHRESULT(2151)
+#define WINED3DERR_DEVICELOST                                   MAKE_WINED3DHRESULT(2152)
+#define WINED3DERR_DEVICENOTRESET                               MAKE_WINED3DHRESULT(2153)
+#define WINED3DERR_NOTAVAILABLE                                 MAKE_WINED3DHRESULT(2154)
+#define WINED3DERR_OUTOFVIDEOMEMORY                             MAKE_WINED3DHRESULT(380)
+#define WINED3DERR_INVALIDDEVICE                                MAKE_WINED3DHRESULT(2155)
+#define WINED3DERR_INVALIDCALL                                  MAKE_WINED3DHRESULT(2156)
+#define WINED3DERR_DRIVERINVALIDCALL                            MAKE_WINED3DHRESULT(2157)
+#define WINED3DERR_WASSTILLDRAWING                              MAKE_WINED3DHRESULT(540)
+#define WINEDDERR_NOTAOVERLAYSURFACE                            MAKE_WINED3DHRESULT(580)
+#define WINEDDERR_NOTLOCKED                                     MAKE_WINED3DHRESULT(584)
+#define WINEDDERR_NODC                                          MAKE_WINED3DHRESULT(586)
+#define WINEDDERR_DCALREADYCREATED                              MAKE_WINED3DHRESULT(620)
+#define WINEDDERR_NOTFLIPPABLE                                  MAKE_WINED3DHRESULT(582)
+#define WINEDDERR_SURFACEBUSY                                   MAKE_WINED3DHRESULT(430)
+#define WINEDDERR_INVALIDRECT                                   MAKE_WINED3DHRESULT(150)
+#define WINEDDERR_NOCLIPLIST                                    MAKE_WINED3DHRESULT(205)
+#define WINEDDERR_OVERLAYNOTVISIBLE                             MAKE_WINED3DHRESULT(577)
+
+enum wined3d_light_type
+{
+    WINED3D_LIGHT_POINT                     = 1,
+    WINED3D_LIGHT_SPOT                      = 2,
+    WINED3D_LIGHT_DIRECTIONAL               = 3,
+    WINED3D_LIGHT_PARALLELPOINT             = 4, /* D3D7 */
+    WINED3D_LIGHT_GLSPOT                    = 5, /* D3D7 */
+};
+
+enum wined3d_primitive_type
+{
+    WINED3D_PT_UNDEFINED                    = 0,
+    WINED3D_PT_POINTLIST                    = 1,
+    WINED3D_PT_LINELIST                     = 2,
+    WINED3D_PT_LINESTRIP                    = 3,
+    WINED3D_PT_TRIANGLELIST                 = 4,
+    WINED3D_PT_TRIANGLESTRIP                = 5,
+    WINED3D_PT_TRIANGLEFAN                  = 6,
+    WINED3D_PT_LINELIST_ADJ                 = 10,
+    WINED3D_PT_LINESTRIP_ADJ                = 11,
+    WINED3D_PT_TRIANGLELIST_ADJ             = 12,
+    WINED3D_PT_TRIANGLESTRIP_ADJ            = 13,
+};
+
+enum wined3d_device_type
+{
+    WINED3D_DEVICE_TYPE_HAL                 = 1,
+    WINED3D_DEVICE_TYPE_REF                 = 2,
+    WINED3D_DEVICE_TYPE_SW                  = 3,
+    WINED3D_DEVICE_TYPE_NULLREF             = 4,
+};
+
+enum wined3d_degree_type
+{
+    WINED3D_DEGREE_LINEAR                   = 1,
+    WINED3D_DEGREE_QUADRATIC                = 2,
+    WINED3D_DEGREE_CUBIC                    = 3,
+    WINED3D_DEGREE_QUINTIC                  = 5,
+};
+
+#define WINEMAKEFOURCC(ch0, ch1, ch2, ch3) \
+        ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
+        ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
+
+enum wined3d_format_id
+{
+    WINED3DFMT_UNKNOWN,
+    WINED3DFMT_B8G8R8_UNORM,
+    WINED3DFMT_B5G5R5X1_UNORM,
+    WINED3DFMT_B4G4R4A4_UNORM,
+    WINED3DFMT_B2G3R3_UNORM,
+    WINED3DFMT_B2G3R3A8_UNORM,
+    WINED3DFMT_B4G4R4X4_UNORM,
+    WINED3DFMT_R8G8B8X8_UNORM,
+    WINED3DFMT_B10G10R10A2_UNORM,
+    WINED3DFMT_P8_UINT_A8_UNORM,
+    WINED3DFMT_P8_UINT,
+    WINED3DFMT_L8_UNORM,
+    WINED3DFMT_L8A8_UNORM,
+    WINED3DFMT_L4A4_UNORM,
+    WINED3DFMT_R5G5_SNORM_L6_UNORM,
+    WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
+    WINED3DFMT_R10G11B11_SNORM,
+    WINED3DFMT_R10G10B10_SNORM_A2_UNORM,
+    WINED3DFMT_D16_LOCKABLE,
+    WINED3DFMT_D32_UNORM,
+    WINED3DFMT_S1_UINT_D15_UNORM,
+    WINED3DFMT_X8D24_UNORM,
+    WINED3DFMT_S4X4_UINT_D24_UNORM,
+    WINED3DFMT_L16_UNORM,
+    WINED3DFMT_S8_UINT_D24_FLOAT,
+    WINED3DFMT_VERTEXDATA,
+    WINED3DFMT_R8G8_SNORM_Cx,
+    WINED3DFMT_R32G32B32A32_TYPELESS,
+    WINED3DFMT_R32G32B32A32_FLOAT,
+    WINED3DFMT_R32G32B32A32_UINT,
+    WINED3DFMT_R32G32B32A32_SINT,
+    WINED3DFMT_R32G32B32_TYPELESS,
+    WINED3DFMT_R32G32B32_FLOAT,
+    WINED3DFMT_R32G32B32_UINT,
+    WINED3DFMT_R32G32B32_SINT,
+    WINED3DFMT_R16G16B16A16_TYPELESS,
+    WINED3DFMT_R16G16B16A16_FLOAT,
+    WINED3DFMT_R16G16B16A16_UNORM,
+    WINED3DFMT_R16G16B16A16_UINT,
+    WINED3DFMT_R16G16B16A16_SNORM,
+    WINED3DFMT_R16G16B16A16_SINT,
+    WINED3DFMT_R32G32_TYPELESS,
+    WINED3DFMT_R32G32_FLOAT,
+    WINED3DFMT_R32G32_UINT,
+    WINED3DFMT_R32G32_SINT,
+    WINED3DFMT_R32G8X24_TYPELESS,
+    WINED3DFMT_D32_FLOAT_S8X24_UINT,
+    WINED3DFMT_R32_FLOAT_X8X24_TYPELESS,
+    WINED3DFMT_X32_TYPELESS_G8X24_UINT,
+    WINED3DFMT_R10G10B10A2_TYPELESS,
+    WINED3DFMT_R10G10B10A2_UNORM,
+    WINED3DFMT_R10G10B10A2_UINT,
+    WINED3DFMT_R10G10B10A2_SNORM,
+    WINED3DFMT_R11G11B10_FLOAT,
+    WINED3DFMT_R8G8B8A8_TYPELESS,
+    WINED3DFMT_R8G8B8A8_UNORM,
+    WINED3DFMT_R8G8B8A8_UNORM_SRGB,
+    WINED3DFMT_R8G8B8A8_UINT,
+    WINED3DFMT_R8G8B8A8_SNORM,
+    WINED3DFMT_R8G8B8A8_SINT,
+    WINED3DFMT_R16G16_TYPELESS,
+    WINED3DFMT_R16G16_FLOAT,
+    WINED3DFMT_R16G16_UNORM,
+    WINED3DFMT_R16G16_UINT,
+    WINED3DFMT_R16G16_SNORM,
+    WINED3DFMT_R16G16_SINT,
+    WINED3DFMT_R32_TYPELESS,
+    WINED3DFMT_D32_FLOAT,
+    WINED3DFMT_R32_FLOAT,
+    WINED3DFMT_R32_UINT,
+    WINED3DFMT_R32_SINT,
+    WINED3DFMT_R24G8_TYPELESS,
+    WINED3DFMT_D24_UNORM_S8_UINT,
+    WINED3DFMT_R24_UNORM_X8_TYPELESS,
+    WINED3DFMT_X24_TYPELESS_G8_UINT,
+    WINED3DFMT_R8G8_TYPELESS,
+    WINED3DFMT_R8G8_UNORM,
+    WINED3DFMT_R8G8_UINT,
+    WINED3DFMT_R8G8_SNORM,
+    WINED3DFMT_R8G8_SINT,
+    WINED3DFMT_R16_TYPELESS,
+    WINED3DFMT_R16_FLOAT,
+    WINED3DFMT_D16_UNORM,
+    WINED3DFMT_R16_UNORM,
+    WINED3DFMT_R16_UINT,
+    WINED3DFMT_R16_SNORM,
+    WINED3DFMT_R16_SINT,
+    WINED3DFMT_R8_TYPELESS,
+    WINED3DFMT_R8_UNORM,
+    WINED3DFMT_R8_UINT,
+    WINED3DFMT_R8_SNORM,
+    WINED3DFMT_R8_SINT,
+    WINED3DFMT_A8_UNORM,
+    WINED3DFMT_R1_UNORM,
+    WINED3DFMT_R9G9B9E5_SHAREDEXP,
+    WINED3DFMT_R8G8_B8G8_UNORM,
+    WINED3DFMT_G8R8_G8B8_UNORM,
+    WINED3DFMT_BC1_TYPELESS,
+    WINED3DFMT_BC1_UNORM,
+    WINED3DFMT_BC1_UNORM_SRGB,
+    WINED3DFMT_BC2_TYPELESS,
+    WINED3DFMT_BC2_UNORM,
+    WINED3DFMT_BC2_UNORM_SRGB,
+    WINED3DFMT_BC3_TYPELESS,
+    WINED3DFMT_BC3_UNORM,
+    WINED3DFMT_BC3_UNORM_SRGB,
+    WINED3DFMT_BC4_TYPELESS,
+    WINED3DFMT_BC4_UNORM,
+    WINED3DFMT_BC4_SNORM,
+    WINED3DFMT_BC5_TYPELESS,
+    WINED3DFMT_BC5_UNORM,
+    WINED3DFMT_BC5_SNORM,
+    WINED3DFMT_B5G6R5_UNORM,
+    WINED3DFMT_B5G5R5A1_UNORM,
+    WINED3DFMT_B8G8R8A8_UNORM,
+    WINED3DFMT_B8G8R8X8_UNORM,
+    /* FOURCC formats. */
+    WINED3DFMT_UYVY                         = WINEMAKEFOURCC('U','Y','V','Y'),
+    WINED3DFMT_YUY2                         = WINEMAKEFOURCC('Y','U','Y','2'),
+    WINED3DFMT_YV12                         = WINEMAKEFOURCC('Y','V','1','2'),
+    WINED3DFMT_DXT1                         = WINEMAKEFOURCC('D','X','T','1'),
+    WINED3DFMT_DXT2                         = WINEMAKEFOURCC('D','X','T','2'),
+    WINED3DFMT_DXT3                         = WINEMAKEFOURCC('D','X','T','3'),
+    WINED3DFMT_DXT4                         = WINEMAKEFOURCC('D','X','T','4'),
+    WINED3DFMT_DXT5                         = WINEMAKEFOURCC('D','X','T','5'),
+    WINED3DFMT_MULTI2_ARGB8                 = WINEMAKEFOURCC('M','E','T','1'),
+    WINED3DFMT_G8R8_G8B8                    = WINEMAKEFOURCC('G','R','G','B'),
+    WINED3DFMT_R8G8_B8G8                    = WINEMAKEFOURCC('R','G','B','G'),
+    WINED3DFMT_ATI2N                        = WINEMAKEFOURCC('A','T','I','2'),
+    WINED3DFMT_INST                         = WINEMAKEFOURCC('I','N','S','T'),
+    WINED3DFMT_NVDB                         = WINEMAKEFOURCC('N','V','D','B'),
+    WINED3DFMT_NVHU                         = WINEMAKEFOURCC('N','V','H','U'),
+    WINED3DFMT_NVHS                         = WINEMAKEFOURCC('N','V','H','S'),
+    WINED3DFMT_INTZ                         = WINEMAKEFOURCC('I','N','T','Z'),
+    WINED3DFMT_RESZ                         = WINEMAKEFOURCC('R','E','S','Z'),
+    WINED3DFMT_NULL                         = WINEMAKEFOURCC('N','U','L','L'),
+    WINED3DFMT_R16                          = WINEMAKEFOURCC(' ','R','1','6'),
+    WINED3DFMT_AL16                         = WINEMAKEFOURCC('A','L','1','6'),
+
+    WINED3DFMT_FORCE_DWORD = 0xffffffff
+};
+
+enum wined3d_render_state
+{
+    WINED3D_RS_ANTIALIAS                    = 2, /* d3d7 */
+    WINED3D_RS_TEXTUREPERSPECTIVE           = 4, /* d3d7 */
+    WINED3D_RS_WRAPU                        = 5, /* d3d7 */
+    WINED3D_RS_WRAPV                        = 6, /* d3d7 */
+    WINED3D_RS_ZENABLE                      = 7,
+    WINED3D_RS_FILLMODE                     = 8,
+    WINED3D_RS_SHADEMODE                    = 9,
+    WINED3D_RS_LINEPATTERN                  = 10, /* d3d7, d3d8 */
+    WINED3D_RS_MONOENABLE                   = 11, /* d3d7 */
+    WINED3D_RS_ROP2                         = 12, /* d3d7 */
+    WINED3D_RS_PLANEMASK                    = 13, /* d3d7 */
+    WINED3D_RS_ZWRITEENABLE                 = 14,
+    WINED3D_RS_ALPHATESTENABLE              = 15,
+    WINED3D_RS_LASTPIXEL                    = 16,
+    WINED3D_RS_SRCBLEND                     = 19,
+    WINED3D_RS_DESTBLEND                    = 20,
+    WINED3D_RS_CULLMODE                     = 22,
+    WINED3D_RS_ZFUNC                        = 23,
+    WINED3D_RS_ALPHAREF                     = 24,
+    WINED3D_RS_ALPHAFUNC                    = 25,
+    WINED3D_RS_DITHERENABLE                 = 26,
+    WINED3D_RS_ALPHABLENDENABLE             = 27,
+    WINED3D_RS_FOGENABLE                    = 28,
+    WINED3D_RS_SPECULARENABLE               = 29,
+    WINED3D_RS_ZVISIBLE                     = 30, /* d3d7, d3d8 */
+    WINED3D_RS_SUBPIXEL                     = 31, /* d3d7 */
+    WINED3D_RS_SUBPIXELX                    = 32, /* d3d7 */
+    WINED3D_RS_STIPPLEDALPHA                = 33, /* d3d7 */
+    WINED3D_RS_FOGCOLOR                     = 34,
+    WINED3D_RS_FOGTABLEMODE                 = 35,
+    WINED3D_RS_FOGSTART                     = 36,
+    WINED3D_RS_FOGEND                       = 37,
+    WINED3D_RS_FOGDENSITY                   = 38,
+    WINED3D_RS_STIPPLEENABLE                = 39, /* d3d7 */
+    WINED3D_RS_EDGEANTIALIAS                = 40, /* d3d7, d3d8 */
+    WINED3D_RS_COLORKEYENABLE               = 41, /* d3d7 */
+    WINED3D_RS_MIPMAPLODBIAS                = 46, /* d3d7 */
+    WINED3D_RS_RANGEFOGENABLE               = 48,
+    WINED3D_RS_ANISOTROPY                   = 49, /* d3d7 */
+    WINED3D_RS_FLUSHBATCH                   = 50, /* d3d7 */
+    WINED3D_RS_TRANSLUCENTSORTINDEPENDENT   = 51, /* d3d7 */
+    WINED3D_RS_STENCILENABLE                = 52,
+    WINED3D_RS_STENCILFAIL                  = 53,
+    WINED3D_RS_STENCILZFAIL                 = 54,
+    WINED3D_RS_STENCILPASS                  = 55,
+    WINED3D_RS_STENCILFUNC                  = 56,
+    WINED3D_RS_STENCILREF                   = 57,
+    WINED3D_RS_STENCILMASK                  = 58,
+    WINED3D_RS_STENCILWRITEMASK             = 59,
+    WINED3D_RS_TEXTUREFACTOR                = 60,
+    WINED3D_RS_WRAP0                        = 128,
+    WINED3D_RS_WRAP1                        = 129,
+    WINED3D_RS_WRAP2                        = 130,
+    WINED3D_RS_WRAP3                        = 131,
+    WINED3D_RS_WRAP4                        = 132,
+    WINED3D_RS_WRAP5                        = 133,
+    WINED3D_RS_WRAP6                        = 134,
+    WINED3D_RS_WRAP7                        = 135,
+    WINED3D_RS_CLIPPING                     = 136,
+    WINED3D_RS_LIGHTING                     = 137,
+    WINED3D_RS_EXTENTS                      = 138, /* d3d7 */
+    WINED3D_RS_AMBIENT                      = 139,
+    WINED3D_RS_FOGVERTEXMODE                = 140,
+    WINED3D_RS_COLORVERTEX                  = 141,
+    WINED3D_RS_LOCALVIEWER                  = 142,
+    WINED3D_RS_NORMALIZENORMALS             = 143,
+    WINED3D_RS_COLORKEYBLENDENABLE          = 144, /* d3d7 */
+    WINED3D_RS_DIFFUSEMATERIALSOURCE        = 145,
+    WINED3D_RS_SPECULARMATERIALSOURCE       = 146,
+    WINED3D_RS_AMBIENTMATERIALSOURCE        = 147,
+    WINED3D_RS_EMISSIVEMATERIALSOURCE       = 148,
+    WINED3D_RS_VERTEXBLEND                  = 151,
+    WINED3D_RS_CLIPPLANEENABLE              = 152,
+    WINED3D_RS_SOFTWAREVERTEXPROCESSING     = 153, /* d3d8 */
+    WINED3D_RS_POINTSIZE                    = 154,
+    WINED3D_RS_POINTSIZE_MIN                = 155,
+    WINED3D_RS_POINTSPRITEENABLE            = 156,
+    WINED3D_RS_POINTSCALEENABLE             = 157,
+    WINED3D_RS_POINTSCALE_A                 = 158,
+    WINED3D_RS_POINTSCALE_B                 = 159,
+    WINED3D_RS_POINTSCALE_C                 = 160,
+    WINED3D_RS_MULTISAMPLEANTIALIAS         = 161,
+    WINED3D_RS_MULTISAMPLEMASK              = 162,
+    WINED3D_RS_PATCHEDGESTYLE               = 163,
+    WINED3D_RS_PATCHSEGMENTS                = 164, /* d3d8 */
+    WINED3D_RS_DEBUGMONITORTOKEN            = 165,
+    WINED3D_RS_POINTSIZE_MAX                = 166,
+    WINED3D_RS_INDEXEDVERTEXBLENDENABLE     = 167,
+    WINED3D_RS_COLORWRITEENABLE             = 168,
+    WINED3D_RS_TWEENFACTOR                  = 170,
+    WINED3D_RS_BLENDOP                      = 171,
+    WINED3D_RS_POSITIONDEGREE               = 172,
+    WINED3D_RS_NORMALDEGREE                 = 173,
+    WINED3D_RS_SCISSORTESTENABLE            = 174,
+    WINED3D_RS_SLOPESCALEDEPTHBIAS          = 175,
+    WINED3D_RS_ANTIALIASEDLINEENABLE        = 176,
+    WINED3D_RS_MINTESSELLATIONLEVEL         = 178,
+    WINED3D_RS_MAXTESSELLATIONLEVEL         = 179,
+    WINED3D_RS_ADAPTIVETESS_X               = 180,
+    WINED3D_RS_ADAPTIVETESS_Y               = 181,
+    WINED3D_RS_ADAPTIVETESS_Z               = 182,
+    WINED3D_RS_ADAPTIVETESS_W               = 183,
+    WINED3D_RS_ENABLEADAPTIVETESSELLATION   = 184,
+    WINED3D_RS_TWOSIDEDSTENCILMODE          = 185,
+    WINED3D_RS_CCW_STENCILFAIL              = 186,
+    WINED3D_RS_CCW_STENCILZFAIL             = 187,
+    WINED3D_RS_CCW_STENCILPASS              = 188,
+    WINED3D_RS_CCW_STENCILFUNC              = 189,
+    WINED3D_RS_COLORWRITEENABLE1            = 190,
+    WINED3D_RS_COLORWRITEENABLE2            = 191,
+    WINED3D_RS_COLORWRITEENABLE3            = 192,
+    WINED3D_RS_BLENDFACTOR                  = 193,
+    WINED3D_RS_SRGBWRITEENABLE              = 194,
+    WINED3D_RS_DEPTHBIAS                    = 195,
+    WINED3D_RS_WRAP8                        = 198,
+    WINED3D_RS_WRAP9                        = 199,
+    WINED3D_RS_WRAP10                       = 200,
+    WINED3D_RS_WRAP11                       = 201,
+    WINED3D_RS_WRAP12                       = 202,
+    WINED3D_RS_WRAP13                       = 203,
+    WINED3D_RS_WRAP14                       = 204,
+    WINED3D_RS_WRAP15                       = 205,
+    WINED3D_RS_SEPARATEALPHABLENDENABLE     = 206,
+    WINED3D_RS_SRCBLENDALPHA                = 207,
+    WINED3D_RS_DESTBLENDALPHA               = 208,
+    WINED3D_RS_BLENDOPALPHA                 = 209,
+};
+#define WINEHIGHEST_RENDER_STATE                                WINED3D_RS_BLENDOPALPHA
+
+enum wined3d_blend
+{
+    WINED3D_BLEND_ZERO                      =  1,
+    WINED3D_BLEND_ONE                       =  2,
+    WINED3D_BLEND_SRCCOLOR                  =  3,
+    WINED3D_BLEND_INVSRCCOLOR               =  4,
+    WINED3D_BLEND_SRCALPHA                  =  5,
+    WINED3D_BLEND_INVSRCALPHA               =  6,
+    WINED3D_BLEND_DESTALPHA                 =  7,
+    WINED3D_BLEND_INVDESTALPHA              =  8,
+    WINED3D_BLEND_DESTCOLOR                 =  9,
+    WINED3D_BLEND_INVDESTCOLOR              = 10,
+    WINED3D_BLEND_SRCALPHASAT               = 11,
+    WINED3D_BLEND_BOTHSRCALPHA              = 12,
+    WINED3D_BLEND_BOTHINVSRCALPHA           = 13,
+    WINED3D_BLEND_BLENDFACTOR               = 14,
+    WINED3D_BLEND_INVBLENDFACTOR            = 15,
+};
+
+enum wined3d_blend_op
+{
+    WINED3D_BLEND_OP_ADD                    = 1,
+    WINED3D_BLEND_OP_SUBTRACT               = 2,
+    WINED3D_BLEND_OP_REVSUBTRACT            = 3,
+    WINED3D_BLEND_OP_MIN                    = 4,
+    WINED3D_BLEND_OP_MAX                    = 5,
+};
+
+enum wined3d_vertex_blend_flags
+{
+    WINED3D_VBF_DISABLE                     = 0,
+    WINED3D_VBF_1WEIGHTS                    = 1,
+    WINED3D_VBF_2WEIGHTS                    = 2,
+    WINED3D_VBF_3WEIGHTS                    = 3,
+    WINED3D_VBF_TWEENING                    = 255,
+    WINED3D_VBF_0WEIGHTS                    = 256,
+};
+
+enum wined3d_cmp_func
+{
+    WINED3D_CMP_NEVER                       = 1,
+    WINED3D_CMP_LESS                        = 2,
+    WINED3D_CMP_EQUAL                       = 3,
+    WINED3D_CMP_LESSEQUAL                   = 4,
+    WINED3D_CMP_GREATER                     = 5,
+    WINED3D_CMP_NOTEQUAL                    = 6,
+    WINED3D_CMP_GREATEREQUAL                = 7,
+    WINED3D_CMP_ALWAYS                      = 8,
+};
+
+enum wined3d_depth_buffer_type
+{
+    WINED3D_ZB_FALSE                        = 0,
+    WINED3D_ZB_TRUE                         = 1,
+    WINED3D_ZB_USEW                         = 2,
+};
+
+enum wined3d_fog_mode
+{
+    WINED3D_FOG_NONE                        = 0,
+    WINED3D_FOG_EXP                         = 1,
+    WINED3D_FOG_EXP2                        = 2,
+    WINED3D_FOG_LINEAR                      = 3,
+};
+
+enum wined3d_shade_mode
+{
+    WINED3D_SHADE_FLAT                      = 1,
+    WINED3D_SHADE_GOURAUD                   = 2,
+    WINED3D_SHADE_PHONG                     = 3,
+};
+
+enum wined3d_fill_mode
+{
+    WINED3D_FILL_POINT                      = 1,
+    WINED3D_FILL_WIREFRAME                  = 2,
+    WINED3D_FILL_SOLID                      = 3,
+};
+
+enum wined3d_cull
+{
+    WINED3D_CULL_NONE                       = 1,
+    WINED3D_CULL_CW                         = 2,
+    WINED3D_CULL_CCW                        = 3,
+};
+
+enum wined3d_stencil_op
+{
+    WINED3D_STENCIL_OP_KEEP                 = 1,
+    WINED3D_STENCIL_OP_ZERO                 = 2,
+    WINED3D_STENCIL_OP_REPLACE              = 3,
+    WINED3D_STENCIL_OP_INCR_SAT             = 4,
+    WINED3D_STENCIL_OP_DECR_SAT             = 5,
+    WINED3D_STENCIL_OP_INVERT               = 6,
+    WINED3D_STENCIL_OP_INCR                 = 7,
+    WINED3D_STENCIL_OP_DECR                 = 8,
+};
+
+enum wined3d_material_color_source
+{
+    WINED3D_MCS_MATERIAL                    = 0,
+    WINED3D_MCS_COLOR1                      = 1,
+    WINED3D_MCS_COLOR2                      = 2,
+};
+
+enum wined3d_patch_edge_style
+{
+    WINED3D_PATCH_EDGE_DISCRETE             = 0,
+    WINED3D_PATCH_EDGE_CONTINUOUS           = 1,
+};
+
+enum wined3d_backbuffer_type
+{
+    WINED3D_BACKBUFFER_TYPE_MONO            = 0,
+    WINED3D_BACKBUFFER_TYPE_LEFT            = 1,
+    WINED3D_BACKBUFFER_TYPE_RIGHT           = 2,
+};
+
+enum wined3d_swap_effect
+{
+    WINED3D_SWAP_EFFECT_DISCARD             = 1,
+    WINED3D_SWAP_EFFECT_FLIP                = 2,
+    WINED3D_SWAP_EFFECT_COPY                = 3,
+    WINED3D_SWAP_EFFECT_COPY_VSYNC          = 4,
+};
+
+enum wined3d_sampler_state
+{
+    WINED3D_SAMP_ADDRESS_U                  = 1,
+    WINED3D_SAMP_ADDRESS_V                  = 2,
+    WINED3D_SAMP_ADDRESS_W                  = 3,
+    WINED3D_SAMP_BORDER_COLOR               = 4,
+    WINED3D_SAMP_MAG_FILTER                 = 5,
+    WINED3D_SAMP_MIN_FILTER                 = 6,
+    WINED3D_SAMP_MIP_FILTER                 = 7,
+    WINED3D_SAMP_MIPMAP_LOD_BIAS            = 8,
+    WINED3D_SAMP_MAX_MIP_LEVEL              = 9,
+    WINED3D_SAMP_MAX_ANISOTROPY             = 10,
+    WINED3D_SAMP_SRGB_TEXTURE               = 11,
+    WINED3D_SAMP_ELEMENT_INDEX              = 12,
+    WINED3D_SAMP_DMAP_OFFSET                = 13,
+};
+#define WINED3D_HIGHEST_SAMPLER_STATE                           WINED3D_SAMP_DMAP_OFFSET
+
+enum wined3d_multisample_type
+{
+    WINED3D_MULTISAMPLE_NONE                = 0,
+    WINED3D_MULTISAMPLE_NON_MASKABLE        = 1,
+    WINED3D_MULTISAMPLE_2_SAMPLES           = 2,
+    WINED3D_MULTISAMPLE_3_SAMPLES           = 3,
+    WINED3D_MULTISAMPLE_4_SAMPLES           = 4,
+    WINED3D_MULTISAMPLE_5_SAMPLES           = 5,
+    WINED3D_MULTISAMPLE_6_SAMPLES           = 6,
+    WINED3D_MULTISAMPLE_7_SAMPLES           = 7,
+    WINED3D_MULTISAMPLE_8_SAMPLES           = 8,
+    WINED3D_MULTISAMPLE_9_SAMPLES           = 9,
+    WINED3D_MULTISAMPLE_10_SAMPLES          = 10,
+    WINED3D_MULTISAMPLE_11_SAMPLES          = 11,
+    WINED3D_MULTISAMPLE_12_SAMPLES          = 12,
+    WINED3D_MULTISAMPLE_13_SAMPLES          = 13,
+    WINED3D_MULTISAMPLE_14_SAMPLES          = 14,
+    WINED3D_MULTISAMPLE_15_SAMPLES          = 15,
+    WINED3D_MULTISAMPLE_16_SAMPLES          = 16,
+};
+
+enum wined3d_texture_stage_state
+{
+    WINED3D_TSS_COLOR_OP                    = 0,
+    WINED3D_TSS_COLOR_ARG1                  = 1,
+    WINED3D_TSS_COLOR_ARG2                  = 2,
+    WINED3D_TSS_ALPHA_OP                    = 3,
+    WINED3D_TSS_ALPHA_ARG1                  = 4,
+    WINED3D_TSS_ALPHA_ARG2                  = 5,
+    WINED3D_TSS_BUMPENV_MAT00               = 6,
+    WINED3D_TSS_BUMPENV_MAT01               = 7,
+    WINED3D_TSS_BUMPENV_MAT10               = 8,
+    WINED3D_TSS_BUMPENV_MAT11               = 9,
+    WINED3D_TSS_TEXCOORD_INDEX              = 10,
+    WINED3D_TSS_BUMPENV_LSCALE              = 11,
+    WINED3D_TSS_BUMPENV_LOFFSET             = 12,
+    WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS     = 13,
+    WINED3D_TSS_COLOR_ARG0                  = 14,
+    WINED3D_TSS_ALPHA_ARG0                  = 15,
+    WINED3D_TSS_RESULT_ARG                  = 16,
+    WINED3D_TSS_CONSTANT                    = 17,
+    WINED3D_TSS_INVALID                     = ~0U,
+};
+#define WINED3D_HIGHEST_TEXTURE_STATE                           WINED3D_TSS_CONSTANT
+
+enum wined3d_texture_transform_flags
+{
+    WINED3D_TTFF_DISABLE                    = 0,
+    WINED3D_TTFF_COUNT1                     = 1,
+    WINED3D_TTFF_COUNT2                     = 2,
+    WINED3D_TTFF_COUNT3                     = 3,
+    WINED3D_TTFF_COUNT4                     = 4,
+    WINED3D_TTFF_PROJECTED                  = 256,
+};
+
+enum wined3d_texture_op
+{
+    WINED3D_TOP_DISABLE                     = 1,
+    WINED3D_TOP_SELECT_ARG1                 = 2,
+    WINED3D_TOP_SELECT_ARG2                 = 3,
+    WINED3D_TOP_MODULATE                    = 4,
+    WINED3D_TOP_MODULATE_2X                 = 5,
+    WINED3D_TOP_MODULATE_4X                 = 6,
+    WINED3D_TOP_ADD                         = 7,
+    WINED3D_TOP_ADD_SIGNED                  = 8,
+    WINED3D_TOP_ADD_SIGNED_2X               = 9,
+    WINED3D_TOP_SUBTRACT                    = 10,
+    WINED3D_TOP_ADD_SMOOTH                  = 11,
+    WINED3D_TOP_BLEND_DIFFUSE_ALPHA         = 12,
+    WINED3D_TOP_BLEND_TEXTURE_ALPHA         = 13,
+    WINED3D_TOP_BLEND_FACTOR_ALPHA          = 14,
+    WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM      = 15,
+    WINED3D_TOP_BLEND_CURRENT_ALPHA         = 16,
+    WINED3D_TOP_PREMODULATE                 = 17,
+    WINED3D_TOP_MODULATE_ALPHA_ADD_COLOR    = 18,
+    WINED3D_TOP_MODULATE_COLOR_ADD_ALPHA    = 19,
+    WINED3D_TOP_MODULATE_INVALPHA_ADD_COLOR = 20,
+    WINED3D_TOP_MODULATE_INVCOLOR_ADD_ALPHA = 21,
+    WINED3D_TOP_BUMPENVMAP                  = 22,
+    WINED3D_TOP_BUMPENVMAP_LUMINANCE        = 23,
+    WINED3D_TOP_DOTPRODUCT3                 = 24,
+    WINED3D_TOP_MULTIPLY_ADD                = 25,
+    WINED3D_TOP_LERP                        = 26,
+};
+
+enum wined3d_texture_address
+{
+    WINED3D_TADDRESS_WRAP                   = 1,
+    WINED3D_TADDRESS_MIRROR                 = 2,
+    WINED3D_TADDRESS_CLAMP                  = 3,
+    WINED3D_TADDRESS_BORDER                 = 4,
+    WINED3D_TADDRESS_MIRROR_ONCE            = 5,
+};
+
+enum wined3d_transform_state
+{
+    WINED3D_TS_VIEW                         = 2,
+    WINED3D_TS_PROJECTION                   = 3,
+    WINED3D_TS_TEXTURE0                     = 16,
+    WINED3D_TS_TEXTURE1                     = 17,
+    WINED3D_TS_TEXTURE2                     = 18,
+    WINED3D_TS_TEXTURE3                     = 19,
+    WINED3D_TS_TEXTURE4                     = 20,
+    WINED3D_TS_TEXTURE5                     = 21,
+    WINED3D_TS_TEXTURE6                     = 22,
+    WINED3D_TS_TEXTURE7                     = 23,
+    WINED3D_TS_WORLD                        = 256, /* WINED3D_TS_WORLD_MATRIX(0) */
+    WINED3D_TS_WORLD1                       = 257,
+    WINED3D_TS_WORLD2                       = 258,
+    WINED3D_TS_WORLD3                       = 259,
+};
+
+#define WINED3D_TS_WORLD_MATRIX(index)                          (enum wined3d_transform_state)(index + 256)
+
+enum wined3d_basis_type
+{
+    WINED3D_BASIS_BEZIER                    = 0,
+    WINED3D_BASIS_BSPLINE                   = 1,
+    WINED3D_BASIS_INTERPOLATE               = 2,
+};
+
+enum wined3d_cubemap_face
+{
+    WINED3D_CUBEMAP_FACE_POSITIVE_X         = 0,
+    WINED3D_CUBEMAP_FACE_NEGATIVE_X         = 1,
+    WINED3D_CUBEMAP_FACE_POSITIVE_Y         = 2,
+    WINED3D_CUBEMAP_FACE_NEGATIVE_Y         = 3,
+    WINED3D_CUBEMAP_FACE_POSITIVE_Z         = 4,
+    WINED3D_CUBEMAP_FACE_NEGATIVE_Z         = 5,
+};
+
+enum wined3d_texture_filter_type
+{
+    WINED3D_TEXF_NONE                       = 0,
+    WINED3D_TEXF_POINT                      = 1,
+    WINED3D_TEXF_LINEAR                     = 2,
+    WINED3D_TEXF_ANISOTROPIC                = 3,
+    WINED3D_TEXF_FLAT_CUBIC                 = 4,
+    WINED3D_TEXF_GAUSSIAN_CUBIC             = 5,
+    WINED3D_TEXF_PYRAMIDAL_QUAD             = 6,
+    WINED3D_TEXF_GAUSSIAN_QUAD              = 7,
+};
+
+enum wined3d_resource_type
+{
+    WINED3D_RTYPE_SURFACE                   = 1,
+    WINED3D_RTYPE_VOLUME                    = 2,
+    WINED3D_RTYPE_TEXTURE                   = 3,
+    WINED3D_RTYPE_VOLUME_TEXTURE            = 4,
+    WINED3D_RTYPE_CUBE_TEXTURE              = 5,
+    WINED3D_RTYPE_BUFFER                    = 6,
+};
+
+enum wined3d_pool
+{
+    WINED3D_POOL_DEFAULT                    = 0,
+    WINED3D_POOL_MANAGED                    = 1,
+    WINED3D_POOL_SYSTEM_MEM                 = 2,
+    WINED3D_POOL_SCRATCH                    = 3,
+};
+
+enum wined3d_query_type
+{
+    WINED3D_QUERY_TYPE_VCACHE               = 4,
+    WINED3D_QUERY_TYPE_RESOURCE_MANAGER     = 5,
+    WINED3D_QUERY_TYPE_VERTEX_STATS         = 6,
+    WINED3D_QUERY_TYPE_EVENT                = 8,
+    WINED3D_QUERY_TYPE_OCCLUSION            = 9,
+    WINED3D_QUERY_TYPE_TIMESTAMP            = 10,
+    WINED3D_QUERY_TYPE_TIMESTAMP_DISJOINT   = 11,
+    WINED3D_QUERY_TYPE_TIMESTAMP_FREQ       = 12,
+    WINED3D_QUERY_TYPE_PIPELINE_TIMINGS     = 13,
+    WINED3D_QUERY_TYPE_INTERFACE_TIMINGS    = 14,
+    WINED3D_QUERY_TYPE_VERTEX_TIMINGS       = 15,
+    WINED3D_QUERY_TYPE_PIXEL_TIMINGS        = 16,
+    WINED3D_QUERY_TYPE_BANDWIDTH_TIMINGS    = 17,
+    WINED3D_QUERY_TYPE_CACHE_UTILIZATION    = 18
+};
+
+#define WINED3DISSUE_BEGIN                                      (1 << 1)
+#define WINED3DISSUE_END                                        (1 << 0)
+#define WINED3DGETDATA_FLUSH                                    (1 << 0)
+
+enum wined3d_stateblock_type
+{
+    WINED3D_SBT_INIT                        = 0,
+    WINED3D_SBT_ALL                         = 1,
+    WINED3D_SBT_PIXEL_STATE                 = 2,
+    WINED3D_SBT_VERTEX_STATE                = 3,
+    WINED3D_SBT_RECORDED                    = 4, /* WineD3D private */
+};
+
+enum wined3d_decl_method
+{
+    WINED3D_DECL_METHOD_DEFAULT             = 0,
+    WINED3D_DECL_METHOD_PARTIAL_U           = 1,
+    WINED3D_DECL_METHOD_PARTIAL_V           = 2,
+    WINED3D_DECL_METHOD_CROSS_UV            = 3,
+    WINED3D_DECL_METHOD_UV                  = 4,
+    WINED3D_DECL_METHOD_LOOKUP              = 5,
+    WINED3D_DECL_METHOD_LOOKUP_PRESAMPLED   = 6,
+};
+
+enum wined3d_decl_usage
+{
+    WINED3D_DECL_USAGE_POSITION             = 0,
+    WINED3D_DECL_USAGE_BLEND_WEIGHT         = 1,
+    WINED3D_DECL_USAGE_BLEND_INDICES        = 2,
+    WINED3D_DECL_USAGE_NORMAL               = 3,
+    WINED3D_DECL_USAGE_PSIZE                = 4,
+    WINED3D_DECL_USAGE_TEXCOORD             = 5,
+    WINED3D_DECL_USAGE_TANGENT              = 6,
+    WINED3D_DECL_USAGE_BINORMAL             = 7,
+    WINED3D_DECL_USAGE_TESS_FACTOR          = 8,
+    WINED3D_DECL_USAGE_POSITIONT            = 9,
+    WINED3D_DECL_USAGE_COLOR                = 10,
+    WINED3D_DECL_USAGE_FOG                  = 11,
+    WINED3D_DECL_USAGE_DEPTH                = 12,
+    WINED3D_DECL_USAGE_SAMPLE               = 13
+};
+
+enum wined3d_sysval_semantic
+{
+    WINED3D_SV_DEPTH = 0xffffffff,
+    WINED3D_SV_TARGET0 = 0,
+    WINED3D_SV_TARGET1 = 1,
+    WINED3D_SV_TARGET2 = 2,
+    WINED3D_SV_TARGET3 = 3,
+    WINED3D_SV_TARGET4 = 4,
+    WINED3D_SV_TARGET5 = 5,
+    WINED3D_SV_TARGET6 = 6,
+    WINED3D_SV_TARGET7 = 7,
+};
+
+enum wined3d_scanline_ordering
+{
+    WINED3D_SCANLINE_ORDERING_UNKNOWN       = 0,
+    WINED3D_SCANLINE_ORDERING_PROGRESSIVE   = 1,
+    WINED3D_SCANLINE_ORDERING_INTERLACED    = 2,
+};
+
+enum wined3d_display_rotation
+{
+    WINED3D_DISPLAY_ROTATION_UNSPECIFIED    = 0,
+    WINED3D_DISPLAY_ROTATION_0              = 1,
+    WINED3D_DISPLAY_ROTATION_90             = 2,
+    WINED3D_DISPLAY_ROTATION_180            = 3,
+    WINED3D_DISPLAY_ROTATION_270            = 4,
+};
+
+#define WINED3DCOLORWRITEENABLE_RED                             (1 << 0)
+#define WINED3DCOLORWRITEENABLE_GREEN                           (1 << 1)
+#define WINED3DCOLORWRITEENABLE_BLUE                            (1 << 2)
+#define WINED3DCOLORWRITEENABLE_ALPHA                           (1 << 3)
+
+#define WINED3DADAPTER_DEFAULT                                  0
+#define WINED3DENUM_NO_WHQL_LEVEL                               2
+#define WINED3DPRESENT_BACK_BUFFER_MAX                          3
+
+#define WINED3DTSS_TCI_PASSTHRU                                 0x00000
+#define WINED3DTSS_TCI_CAMERASPACENORMAL                        0x10000
+#define WINED3DTSS_TCI_CAMERASPACEPOSITION                      0x20000
+#define WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR              0x30000
+#define WINED3DTSS_TCI_SPHEREMAP                                0x40000
+
+#define WINED3DTA_SELECTMASK                                    0x0000000f
+#define WINED3DTA_DIFFUSE                                       0x00000000
+#define WINED3DTA_CURRENT                                       0x00000001
+#define WINED3DTA_TEXTURE                                       0x00000002
+#define WINED3DTA_TFACTOR                                       0x00000003
+#define WINED3DTA_SPECULAR                                      0x00000004
+#define WINED3DTA_TEMP                                          0x00000005
+#define WINED3DTA_CONSTANT                                      0x00000006
+#define WINED3DTA_COMPLEMENT                                    0x00000010
+#define WINED3DTA_ALPHAREPLICATE                                0x00000020
+
+#define WINED3DPRESENTFLAG_LOCKABLE_BACKBUFFER                  0x00000001
+#define WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL                 0x00000002
+#define WINED3DPRESENTFLAG_DEVICECLIP                           0x00000004
+#define WINED3DPRESENTFLAG_VIDEO                                0x00000010
+#define WINED3DPRESENTFLAG_NOAUTOROTATE                         0x00000020
+#define WINED3DPRESENTFLAG_UNPRUNEDMODE                         0x00000040
+
+#define WINED3DDP_MAXTEXCOORD                                   8
+
+#define WINED3DUSAGE_RENDERTARGET                               0x00000001
+#define WINED3DUSAGE_DEPTHSTENCIL                               0x00000002
+#define WINED3DUSAGE_WRITEONLY                                  0x00000008
+#define WINED3DUSAGE_SOFTWAREPROCESSING                         0x00000010
+#define WINED3DUSAGE_DONOTCLIP                                  0x00000020
+#define WINED3DUSAGE_POINTS                                     0x00000040
+#define WINED3DUSAGE_RTPATCHES                                  0x00000080
+#define WINED3DUSAGE_NPATCHES                                   0x00000100
+#define WINED3DUSAGE_DYNAMIC                                    0x00000200
+#define WINED3DUSAGE_AUTOGENMIPMAP                              0x00000400
+#define WINED3DUSAGE_DMAP                                       0x00004000
+#define WINED3DUSAGE_MASK                                       0x00004fff
+#define WINED3DUSAGE_OWNDC                                      0x20000000
+#define WINED3DUSAGE_STATICDECL                                 0x40000000
+#define WINED3DUSAGE_OVERLAY                                    0x80000000
+
+#define WINED3DUSAGE_QUERY_LEGACYBUMPMAP                        0x00008000
+#define WINED3DUSAGE_QUERY_FILTER                               0x00020000
+#define WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING             0x00080000
+#define WINED3DUSAGE_QUERY_SRGBREAD                             0x00010000
+#define WINED3DUSAGE_QUERY_SRGBWRITE                            0x00040000
+#define WINED3DUSAGE_QUERY_VERTEXTEXTURE                        0x00100000
+#define WINED3DUSAGE_QUERY_WRAPANDMIP                           0x00200000
+#define WINED3DUSAGE_QUERY_MASK                                 0x003f8000
+
+#define WINED3D_MAP_READONLY                                    0x0010
+#define WINED3D_MAP_NOSYSLOCK                                   0x0800
+#define WINED3D_MAP_NOOVERWRITE                                 0x1000
+#define WINED3D_MAP_DISCARD                                     0x2000
+#define WINED3D_MAP_DONOTWAIT                                   0x4000
+#define WINED3D_MAP_NO_DIRTY_UPDATE                             0x8000
+
+#define WINED3DPRESENT_RATE_DEFAULT                             0x00000000
+
+#define WINED3DPRESENT_INTERVAL_DEFAULT                         0x00000000
+#define WINED3DPRESENT_INTERVAL_ONE                             0x00000001
+#define WINED3DPRESENT_INTERVAL_TWO                             0x00000002
+#define WINED3DPRESENT_INTERVAL_THREE                           0x00000004
+#define WINED3DPRESENT_INTERVAL_FOUR                            0x00000008
+#define WINED3DPRESENT_INTERVAL_IMMEDIATE                       0x80000000
+
+#define WINED3DMAXUSERCLIPPLANES                                32
+#define WINED3DCLIPPLANE0                                       (1 << 0)
+#define WINED3DCLIPPLANE1                                       (1 << 1)
+#define WINED3DCLIPPLANE2                                       (1 << 2)
+#define WINED3DCLIPPLANE3                                       (1 << 3)
+#define WINED3DCLIPPLANE4                                       (1 << 4)
+#define WINED3DCLIPPLANE5                                       (1 << 5)
+
+/* FVF (Flexible Vertex Format) codes */
+#define WINED3DFVF_RESERVED0                                    0x0001
+#define WINED3DFVF_POSITION_MASK                                0x400e
+#define WINED3DFVF_XYZ                                          0x0002
+#define WINED3DFVF_XYZRHW                                       0x0004
+#define WINED3DFVF_XYZB1                                        0x0006
+#define WINED3DFVF_XYZB2                                        0x0008
+#define WINED3DFVF_XYZB3                                        0x000a
+#define WINED3DFVF_XYZB4                                        0x000c
+#define WINED3DFVF_XYZB5                                        0x000e
+#define WINED3DFVF_XYZW                                         0x4002
+#define WINED3DFVF_NORMAL                                       0x0010
+#define WINED3DFVF_PSIZE                                        0x0020
+#define WINED3DFVF_DIFFUSE                                      0x0040
+#define WINED3DFVF_SPECULAR                                     0x0080
+#define WINED3DFVF_TEXCOUNT_MASK                                0x0f00
+#define WINED3DFVF_TEXCOUNT_SHIFT                               8
+#define WINED3DFVF_TEX0                                         0x0000
+#define WINED3DFVF_TEX1                                         0x0100
+#define WINED3DFVF_TEX2                                         0x0200
+#define WINED3DFVF_TEX3                                         0x0300
+#define WINED3DFVF_TEX4                                         0x0400
+#define WINED3DFVF_TEX5                                         0x0500
+#define WINED3DFVF_TEX6                                         0x0600
+#define WINED3DFVF_TEX7                                         0x0700
+#define WINED3DFVF_TEX8                                         0x0800
+#define WINED3DFVF_LASTBETA_UBYTE4                              0x1000
+#define WINED3DFVF_LASTBETA_D3DCOLOR                            0x8000
+#define WINED3DFVF_RESERVED2                                    0x6000
+
+#define WINED3DFVF_TEXTUREFORMAT1                               3
+#define WINED3DFVF_TEXTUREFORMAT2                               0
+#define WINED3DFVF_TEXTUREFORMAT3                               1
+#define WINED3DFVF_TEXTUREFORMAT4                               2
+#define WINED3DFVF_TEXCOORDSIZE1(idx)                           (WINED3DFVF_TEXTUREFORMAT1 << (idx * 2 + 16))
+#define WINED3DFVF_TEXCOORDSIZE2(idx)                           (WINED3DFVF_TEXTUREFORMAT2 << (idx * 2 + 16))
+#define WINED3DFVF_TEXCOORDSIZE3(idx)                           (WINED3DFVF_TEXTUREFORMAT3 << (idx * 2 + 16))
+#define WINED3DFVF_TEXCOORDSIZE4(idx)                           (WINED3DFVF_TEXTUREFORMAT4 << (idx * 2 + 16))
+
+/* Clear flags */
+#define WINED3DCLEAR_TARGET                                     0x00000001
+#define WINED3DCLEAR_ZBUFFER                                    0x00000002
+#define WINED3DCLEAR_STENCIL                                    0x00000004
+
+/* Stream source flags */
+#define WINED3DSTREAMSOURCE_INDEXEDDATA                         (1 << 30)
+#define WINED3DSTREAMSOURCE_INSTANCEDATA                        (2 << 30)
+
+/* SetPrivateData flags */
+#define WINED3DSPD_IUNKNOWN                                     0x00000001
+
+/* IWineD3D::CreateDevice behaviour flags */
+#define WINED3DCREATE_FPU_PRESERVE                              0x00000002
+#define WINED3DCREATE_PUREDEVICE                                0x00000010
+#define WINED3DCREATE_SOFTWARE_VERTEXPROCESSING                 0x00000020
+#define WINED3DCREATE_HARDWARE_VERTEXPROCESSING                 0x00000040
+#define WINED3DCREATE_MIXED_VERTEXPROCESSING                    0x00000080
+#define WINED3DCREATE_DISABLE_DRIVER_MANAGEMENT                 0x00000100
+#define WINED3DCREATE_ADAPTERGROUP_DEVICE                       0x00000200
+
+/* VTF defines */
+#define WINED3DDMAPSAMPLER                                      0x100
+#define WINED3DVERTEXTEXTURESAMPLER0                            (WINED3DDMAPSAMPLER + 1)
+#define WINED3DVERTEXTEXTURESAMPLER1                            (WINED3DDMAPSAMPLER + 2)
+#define WINED3DVERTEXTEXTURESAMPLER2                            (WINED3DDMAPSAMPLER + 3)
+#define WINED3DVERTEXTEXTURESAMPLER3                            (WINED3DDMAPSAMPLER + 4)
+
+#define WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD           0x00000020
+#define WINED3DCAPS3_LINEAR_TO_SRGB_PRESENTATION                0x00000080
+#define WINED3DCAPS3_COPY_TO_VIDMEM                             0x00000100
+#define WINED3DCAPS3_COPY_TO_SYSTEMMEM                          0x00000200
+#define WINED3DCAPS3_RESERVED                                   0x8000001f
+
+#define WINED3DDEVCAPS2_STREAMOFFSET                            0x00000001
+#define WINED3DDEVCAPS2_DMAPNPATCH                              0x00000002
+#define WINED3DDEVCAPS2_ADAPTIVETESSRTPATCH                     0x00000004
+#define WINED3DDEVCAPS2_ADAPTIVETESSNPATCH                      0x00000008
+#define WINED3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES           0x00000010
+#define WINED3DDEVCAPS2_PRESAMPLEDDMAPNPATCH                    0x00000020
+#define WINED3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET      0x00000040
+
+#define WINED3DDTCAPS_UBYTE4                                    0x00000001
+#define WINED3DDTCAPS_UBYTE4N                                   0x00000002
+#define WINED3DDTCAPS_SHORT2N                                   0x00000004
+#define WINED3DDTCAPS_SHORT4N                                   0x00000008
+#define WINED3DDTCAPS_USHORT2N                                  0x00000010
+#define WINED3DDTCAPS_USHORT4N                                  0x00000020
+#define WINED3DDTCAPS_UDEC3                                     0x00000040
+#define WINED3DDTCAPS_DEC3N                                     0x00000080
+#define WINED3DDTCAPS_FLOAT16_2                                 0x00000100
+#define WINED3DDTCAPS_FLOAT16_4                                 0x00000200
+
+#define WINED3DFVFCAPS_TEXCOORDCOUNTMASK                        0x0000ffff
+#define WINED3DFVFCAPS_DONOTSTRIPELEMENTS                       0x00080000
+#define WINED3DFVFCAPS_PSIZE                                    0x00100000
+
+#define WINED3DLINECAPS_TEXTURE                                 0x00000001
+#define WINED3DLINECAPS_ZTEST                                   0x00000002
+#define WINED3DLINECAPS_BLEND                                   0x00000004
+#define WINED3DLINECAPS_ALPHACMP                                0x00000008
+#define WINED3DLINECAPS_FOG                                     0x00000010
+#define WINED3DLINECAPS_ANTIALIAS                               0x00000020
+
+#define WINED3DMAX30SHADERINSTRUCTIONS                          32768
+#define WINED3DMIN30SHADERINSTRUCTIONS                          512
+
+#define WINED3DPBLENDCAPS_ZERO                                  0x00000001
+#define WINED3DPBLENDCAPS_ONE                                   0x00000002
+#define WINED3DPBLENDCAPS_SRCCOLOR                              0x00000004
+#define WINED3DPBLENDCAPS_INVSRCCOLOR                           0x00000008
+#define WINED3DPBLENDCAPS_SRCALPHA                              0x00000010
+#define WINED3DPBLENDCAPS_INVSRCALPHA                           0x00000020
+#define WINED3DPBLENDCAPS_DESTALPHA                             0x00000040
+#define WINED3DPBLENDCAPS_INVDESTALPHA                          0x00000080
+#define WINED3DPBLENDCAPS_DESTCOLOR                             0x00000100
+#define WINED3DPBLENDCAPS_INVDESTCOLOR                          0x00000200
+#define WINED3DPBLENDCAPS_SRCALPHASAT                           0x00000400
+#define WINED3DPBLENDCAPS_BOTHSRCALPHA                          0x00000800
+#define WINED3DPBLENDCAPS_BOTHINVSRCALPHA                       0x00001000
+#define WINED3DPBLENDCAPS_BLENDFACTOR                           0x00002000
+
+#define WINED3DPCMPCAPS_NEVER                                   0x00000001
+#define WINED3DPCMPCAPS_LESS                                    0x00000002
+#define WINED3DPCMPCAPS_EQUAL                                   0x00000004
+#define WINED3DPCMPCAPS_LESSEQUAL                               0x00000008
+#define WINED3DPCMPCAPS_GREATER                                 0x00000010
+#define WINED3DPCMPCAPS_NOTEQUAL                                0x00000020
+#define WINED3DPCMPCAPS_GREATEREQUAL                            0x00000040
+#define WINED3DPCMPCAPS_ALWAYS                                  0x00000080
+
+#define WINED3DPMISCCAPS_MASKZ                                  0x00000002
+#define WINED3DPMISCCAPS_LINEPATTERNREP                         0x00000004
+#define WINED3DPMISCCAPS_CULLNONE                               0x00000010
+#define WINED3DPMISCCAPS_CULLCW                                 0x00000020
+#define WINED3DPMISCCAPS_CULLCCW                                0x00000040
+#define WINED3DPMISCCAPS_COLORWRITEENABLE                       0x00000080
+#define WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS                  0x00000100
+#define WINED3DPMISCCAPS_CLIPTLVERTS                            0x00000200
+#define WINED3DPMISCCAPS_TSSARGTEMP                             0x00000400
+#define WINED3DPMISCCAPS_BLENDOP                                0x00000800
+#define WINED3DPMISCCAPS_NULLREFERENCE                          0x00001000
+#define WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS                  0x00004000
+#define WINED3DPMISCCAPS_PERSTAGECONSTANT                       0x00008000
+#define WINED3DPMISCCAPS_FOGANDSPECULARALPHA                    0x00010000
+#define WINED3DPMISCCAPS_SEPARATEALPHABLEND                     0x00020000
+#define WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS                0x00040000
+#define WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING             0x00080000
+#define WINED3DPMISCCAPS_FOGVERTEXCLAMPED                       0x00100000
+#define WINED3DPMISCCAPS_POSTBLENDSRGBCONVERT                   0x00200000
+
+#define WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH                 24
+#define WINED3DPS20_MIN_DYNAMICFLOWCONTROLDEPTH                 0
+#define WINED3DPS20_MAX_NUMTEMPS                                32
+#define WINED3DPS20_MIN_NUMTEMPS                                12
+#define WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH                  4
+#define WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH                  0
+#define WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS                     512
+#define WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS                     96
+
+#define WINED3DPS20CAPS_ARBITRARYSWIZZLE                        0x00000001
+#define WINED3DPS20CAPS_GRADIENTINSTRUCTIONS                    0x00000002
+#define WINED3DPS20CAPS_PREDICATION                             0x00000004
+#define WINED3DPS20CAPS_NODEPENDENTREADLIMIT                    0x00000008
+#define WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT                   0x00000010
+
+#define WINED3DPTADDRESSCAPS_WRAP                               0x00000001
+#define WINED3DPTADDRESSCAPS_MIRROR                             0x00000002
+#define WINED3DPTADDRESSCAPS_CLAMP                              0x00000004
+#define WINED3DPTADDRESSCAPS_BORDER                             0x00000008
+#define WINED3DPTADDRESSCAPS_INDEPENDENTUV                      0x00000010
+#define WINED3DPTADDRESSCAPS_MIRRORONCE                         0x00000020
+
+#define WINED3DSTENCILCAPS_KEEP                                 0x00000001
+#define WINED3DSTENCILCAPS_ZERO                                 0x00000002
+#define WINED3DSTENCILCAPS_REPLACE                              0x00000004
+#define WINED3DSTENCILCAPS_INCRSAT                              0x00000008
+#define WINED3DSTENCILCAPS_DECRSAT                              0x00000010
+#define WINED3DSTENCILCAPS_INVERT                               0x00000020
+#define WINED3DSTENCILCAPS_INCR                                 0x00000040
+#define WINED3DSTENCILCAPS_DECR                                 0x00000080
+#define WINED3DSTENCILCAPS_TWOSIDED                             0x00000100
+
+#define WINED3DTEXOPCAPS_DISABLE                                0x00000001
+#define WINED3DTEXOPCAPS_SELECTARG1                             0x00000002
+#define WINED3DTEXOPCAPS_SELECTARG2                             0x00000004
+#define WINED3DTEXOPCAPS_MODULATE                               0x00000008
+#define WINED3DTEXOPCAPS_MODULATE2X                             0x00000010
+#define WINED3DTEXOPCAPS_MODULATE4X                             0x00000020
+#define WINED3DTEXOPCAPS_ADD                                    0x00000040
+#define WINED3DTEXOPCAPS_ADDSIGNED                              0x00000080
+#define WINED3DTEXOPCAPS_ADDSIGNED2X                            0x00000100
+#define WINED3DTEXOPCAPS_SUBTRACT                               0x00000200
+#define WINED3DTEXOPCAPS_ADDSMOOTH                              0x00000400
+#define WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA                      0x00000800
+#define WINED3DTEXOPCAPS_BLENDTEXTUREALPHA                      0x00001000
+#define WINED3DTEXOPCAPS_BLENDFACTORALPHA                       0x00002000
+#define WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM                    0x00004000
+#define WINED3DTEXOPCAPS_BLENDCURRENTALPHA                      0x00008000
+#define WINED3DTEXOPCAPS_PREMODULATE                            0x00010000
+#define WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR                 0x00020000
+#define WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA                 0x00040000
+#define WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR              0x00080000
+#define WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA              0x00100000
+#define WINED3DTEXOPCAPS_BUMPENVMAP                             0x00200000
+#define WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE                    0x00400000
+#define WINED3DTEXOPCAPS_DOTPRODUCT3                            0x00800000
+#define WINED3DTEXOPCAPS_MULTIPLYADD                            0x01000000
+#define WINED3DTEXOPCAPS_LERP                                   0x02000000
+
+#define WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH                 24
+#define WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH                 0
+#define WINED3DVS20_MAX_NUMTEMPS                                32
+#define WINED3DVS20_MIN_NUMTEMPS                                12
+#define WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH                  4
+#define WINED3DVS20_MIN_STATICFLOWCONTROLDEPTH                  1
+
+#define WINED3DVS20CAPS_PREDICATION                             0x00000001
+
+#define WINED3DCAPS2_NO2DDURING3DSCENE                          0x00000002
+#define WINED3DCAPS2_FULLSCREENGAMMA                            0x00020000
+#define WINED3DCAPS2_CANRENDERWINDOWED                          0x00080000
+#define WINED3DCAPS2_CANCALIBRATEGAMMA                          0x00100000
+#define WINED3DCAPS2_RESERVED                                   0x02000000
+#define WINED3DCAPS2_CANMANAGERESOURCE                          0x10000000
+#define WINED3DCAPS2_DYNAMICTEXTURES                            0x20000000
+#define WINED3DCAPS2_CANAUTOGENMIPMAP                           0x40000000
+
+#define WINED3DPRASTERCAPS_DITHER                               0x00000001
+#define WINED3DPRASTERCAPS_ROP2                                 0x00000002
+#define WINED3DPRASTERCAPS_XOR                                  0x00000004
+#define WINED3DPRASTERCAPS_PAT                                  0x00000008
+#define WINED3DPRASTERCAPS_ZTEST                                0x00000010
+#define WINED3DPRASTERCAPS_SUBPIXEL                             0x00000020
+#define WINED3DPRASTERCAPS_SUBPIXELX                            0x00000040
+#define WINED3DPRASTERCAPS_FOGVERTEX                            0x00000080
+#define WINED3DPRASTERCAPS_FOGTABLE                             0x00000100
+#define WINED3DPRASTERCAPS_STIPPLE                              0x00000200
+#define WINED3DPRASTERCAPS_ANTIALIASSORTDEPENDENT               0x00000400
+#define WINED3DPRASTERCAPS_ANTIALIASSORTINDEPENDENT             0x00000800
+#define WINED3DPRASTERCAPS_ANTIALIASEDGES                       0x00001000
+#define WINED3DPRASTERCAPS_MIPMAPLODBIAS                        0x00002000
+#define WINED3DPRASTERCAPS_ZBIAS                                0x00004000
+#define WINED3DPRASTERCAPS_ZBUFFERLESSHSR                       0x00008000
+#define WINED3DPRASTERCAPS_FOGRANGE                             0x00010000
+#define WINED3DPRASTERCAPS_ANISOTROPY                           0x00020000
+#define WINED3DPRASTERCAPS_WBUFFER                              0x00040000
+#define WINED3DPRASTERCAPS_TRANSLUCENTSORTINDEPENDENT           0x00080000
+#define WINED3DPRASTERCAPS_WFOG                                 0x00100000
+#define WINED3DPRASTERCAPS_ZFOG                                 0x00200000
+#define WINED3DPRASTERCAPS_COLORPERSPECTIVE                     0x00400000
+#define WINED3DPRASTERCAPS_SCISSORTEST                          0x01000000
+#define WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS                  0x02000000
+#define WINED3DPRASTERCAPS_DEPTHBIAS                            0x04000000
+#define WINED3DPRASTERCAPS_MULTISAMPLE_TOGGLE                   0x08000000
+
+#define WINED3DPSHADECAPS_COLORFLATMONO                         0x00000001
+#define WINED3DPSHADECAPS_COLORFLATRGB                          0x00000002
+#define WINED3DPSHADECAPS_COLORGOURAUDMONO                      0x00000004
+#define WINED3DPSHADECAPS_COLORGOURAUDRGB                       0x00000008
+#define WINED3DPSHADECAPS_COLORPHONGMONO                        0x00000010
+#define WINED3DPSHADECAPS_COLORPHONGRGB                         0x00000020
+#define WINED3DPSHADECAPS_SPECULARFLATMONO                      0x00000040
+#define WINED3DPSHADECAPS_SPECULARFLATRGB                       0x00000080
+#define WINED3DPSHADECAPS_SPECULARGOURAUDMONO                   0x00000100
+#define WINED3DPSHADECAPS_SPECULARGOURAUDRGB                    0x00000200
+#define WINED3DPSHADECAPS_SPECULARPHONGMONO                     0x00000400
+#define WINED3DPSHADECAPS_SPECULARPHONGRGB                      0x00000800
+#define WINED3DPSHADECAPS_ALPHAFLATBLEND                        0x00001000
+#define WINED3DPSHADECAPS_ALPHAFLATSTIPPLED                     0x00002000
+#define WINED3DPSHADECAPS_ALPHAGOURAUDBLEND                     0x00004000
+#define WINED3DPSHADECAPS_ALPHAGOURAUDSTIPPLED                  0x00008000
+#define WINED3DPSHADECAPS_ALPHAPHONGBLEND                       0x00010000
+#define WINED3DPSHADECAPS_ALPHAPHONGSTIPPLED                    0x00020000
+#define WINED3DPSHADECAPS_FOGFLAT                               0x00040000
+#define WINED3DPSHADECAPS_FOGGOURAUD                            0x00080000
+#define WINED3DPSHADECAPS_FOGPHONG                              0x00100000
+
+#define WINED3DPTEXTURECAPS_PERSPECTIVE                         0x00000001
+#define WINED3DPTEXTURECAPS_POW2                                0x00000002
+#define WINED3DPTEXTURECAPS_ALPHA                               0x00000004
+#define WINED3DPTEXTURECAPS_TRANSPARENCY                        0x00000008
+#define WINED3DPTEXTURECAPS_BORDER                              0x00000010
+#define WINED3DPTEXTURECAPS_SQUAREONLY                          0x00000020
+#define WINED3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE            0x00000040
+#define WINED3DPTEXTURECAPS_ALPHAPALETTE                        0x00000080
+#define WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL                  0x00000100
+#define WINED3DPTEXTURECAPS_PROJECTED                           0x00000400
+#define WINED3DPTEXTURECAPS_CUBEMAP                             0x00000800
+#define WINED3DPTEXTURECAPS_COLORKEYBLEND                       0x00001000
+#define WINED3DPTEXTURECAPS_VOLUMEMAP                           0x00002000
+#define WINED3DPTEXTURECAPS_MIPMAP                              0x00004000
+#define WINED3DPTEXTURECAPS_MIPVOLUMEMAP                        0x00008000
+#define WINED3DPTEXTURECAPS_MIPCUBEMAP                          0x00010000
+#define WINED3DPTEXTURECAPS_CUBEMAP_POW2                        0x00020000
+#define WINED3DPTEXTURECAPS_VOLUMEMAP_POW2                      0x00040000
+#define WINED3DPTEXTURECAPS_NOPROJECTEDBUMPENV                  0x00200000
+
+#define WINED3DPTFILTERCAPS_NEAREST                             0x00000001
+#define WINED3DPTFILTERCAPS_LINEAR                              0x00000002
+#define WINED3DPTFILTERCAPS_MIPNEAREST                          0x00000004
+#define WINED3DPTFILTERCAPS_MIPLINEAR                           0x00000008
+#define WINED3DPTFILTERCAPS_LINEARMIPNEAREST                    0x00000010
+#define WINED3DPTFILTERCAPS_LINEARMIPLINEAR                     0x00000020
+#define WINED3DPTFILTERCAPS_MINFPOINT                           0x00000100
+#define WINED3DPTFILTERCAPS_MINFLINEAR                          0x00000200
+#define WINED3DPTFILTERCAPS_MINFANISOTROPIC                     0x00000400
+#define WINED3DPTFILTERCAPS_MIPFPOINT                           0x00010000
+#define WINED3DPTFILTERCAPS_MIPFLINEAR                          0x00020000
+#define WINED3DPTFILTERCAPS_MAGFPOINT                           0x01000000
+#define WINED3DPTFILTERCAPS_MAGFLINEAR                          0x02000000
+#define WINED3DPTFILTERCAPS_MAGFANISOTROPIC                     0x04000000
+#define WINED3DPTFILTERCAPS_MAGFPYRAMIDALQUAD                   0x08000000
+#define WINED3DPTFILTERCAPS_MAGFGAUSSIANQUAD                    0x10000000
+
+#define WINED3DVTXPCAPS_TEXGEN                                  0x00000001
+#define WINED3DVTXPCAPS_MATERIALSOURCE7                         0x00000002
+#define WINED3DVTXPCAPS_VERTEXFOG                               0x00000004
+#define WINED3DVTXPCAPS_DIRECTIONALLIGHTS                       0x00000008
+#define WINED3DVTXPCAPS_POSITIONALLIGHTS                        0x00000010
+#define WINED3DVTXPCAPS_LOCALVIEWER                             0x00000020
+#define WINED3DVTXPCAPS_TWEENING                                0x00000040
+#define WINED3DVTXPCAPS_TEXGEN_SPHEREMAP                        0x00000100
+#define WINED3DVTXPCAPS_NO_TEXGEN_NONLOCALVIEWER                0x00000200
+
+#define WINED3DCURSORCAPS_COLOR                                 0x00000001
+#define WINED3DCURSORCAPS_LOWRES                                0x00000002
+
+#define WINED3DDEVCAPS_FLOATTLVERTEX                            0x00000001
+#define WINED3DDEVCAPS_SORTINCREASINGZ                          0x00000002
+#define WINED3DDEVCAPS_SORTDECREASINGZ                          0X00000004
+#define WINED3DDEVCAPS_SORTEXACT                                0x00000008
+#define WINED3DDEVCAPS_EXECUTESYSTEMMEMORY                      0x00000010
+#define WINED3DDEVCAPS_EXECUTEVIDEOMEMORY                       0x00000020
+#define WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY                     0x00000040
+#define WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY                      0x00000080
+#define WINED3DDEVCAPS_TEXTURESYSTEMMEMORY                      0x00000100
+#define WINED3DDEVCAPS_TEXTUREVIDEOMEMORY                       0x00000200
+#define WINED3DDEVCAPS_DRAWPRIMTLVERTEX                         0x00000400
+#define WINED3DDEVCAPS_CANRENDERAFTERFLIP                       0x00000800
+#define WINED3DDEVCAPS_TEXTURENONLOCALVIDMEM                    0x00001000
+#define WINED3DDEVCAPS_DRAWPRIMITIVES2                          0x00002000
+#define WINED3DDEVCAPS_SEPARATETEXTUREMEMORIES                  0x00004000
+#define WINED3DDEVCAPS_DRAWPRIMITIVES2EX                        0x00008000
+#define WINED3DDEVCAPS_HWTRANSFORMANDLIGHT                      0x00010000
+#define WINED3DDEVCAPS_CANBLTSYSTONONLOCAL                      0x00020000
+#define WINED3DDEVCAPS_HWRASTERIZATION                          0x00080000
+#define WINED3DDEVCAPS_PUREDEVICE                               0x00100000
+#define WINED3DDEVCAPS_QUINTICRTPATCHES                         0x00200000
+#define WINED3DDEVCAPS_RTPATCHES                                0x00400000
+#define WINED3DDEVCAPS_RTPATCHHANDLEZERO                        0x00800000
+#define WINED3DDEVCAPS_NPATCHES                                 0x01000000
+
+#define WINED3D_LEGACY_DEPTH_BIAS                               0x00000001
+#define WINED3D_NO3D                                            0x00000002
+#define WINED3D_VIDMEM_ACCOUNTING                               0x00000004
+
+#define WINED3D_RESZ_CODE                                       0x7fa05000
+
+/* dwDDFX */
+/* arithmetic stretching along y axis */
+#define WINEDDBLTFX_ARITHSTRETCHY                               0x00000001
+/* mirror on y axis */
+#define WINEDDBLTFX_MIRRORLEFTRIGHT                             0x00000002
+/* mirror on x axis */
+#define WINEDDBLTFX_MIRRORUPDOWN                                0x00000004
+/* do not tear */
+#define WINEDDBLTFX_NOTEARING                                   0x00000008
+/* 180 degrees clockwise rotation */
+#define WINEDDBLTFX_ROTATE180                                   0x00000010
+/* 270 degrees clockwise rotation */
+#define WINEDDBLTFX_ROTATE270                                   0x00000020
+/* 90 degrees clockwise rotation */
+#define WINEDDBLTFX_ROTATE90                                    0x00000040
+/* dwZBufferLow and dwZBufferHigh specify limits to the copied Z values */
+#define WINEDDBLTFX_ZBUFFERRANGE                                0x00000080
+/* add dwZBufferBaseDest to every source z value before compare */
+#define WINEDDBLTFX_ZBUFFERBASEDEST                             0x00000100
+
+/* dwFlags for Blt* */
+#define WINEDDBLT_ALPHADEST                                     0x00000001
+#define WINEDDBLT_ALPHADESTCONSTOVERRIDE                        0x00000002
+#define WINEDDBLT_ALPHADESTNEG                                  0x00000004
+#define WINEDDBLT_ALPHADESTSURFACEOVERRIDE                      0x00000008
+#define WINEDDBLT_ALPHAEDGEBLEND                                0x00000010
+#define WINEDDBLT_ALPHASRC                                      0x00000020
+#define WINEDDBLT_ALPHASRCCONSTOVERRIDE                         0x00000040
+#define WINEDDBLT_ALPHASRCNEG                                   0x00000080
+#define WINEDDBLT_ALPHASRCSURFACEOVERRIDE                       0x00000100
+#define WINEDDBLT_ASYNC                                         0x00000200
+#define WINEDDBLT_COLORFILL                                     0x00000400
+#define WINEDDBLT_DDFX                                          0x00000800
+#define WINEDDBLT_DDROPS                                        0x00001000
+#define WINEDDBLT_KEYDEST                                       0x00002000
+#define WINEDDBLT_KEYDESTOVERRIDE                               0x00004000
+#define WINEDDBLT_KEYSRC                                        0x00008000
+#define WINEDDBLT_KEYSRCOVERRIDE                                0x00010000
+#define WINEDDBLT_ROP                                           0x00020000
+#define WINEDDBLT_ROTATIONANGLE                                 0x00040000
+#define WINEDDBLT_ZBUFFER                                       0x00080000
+#define WINEDDBLT_ZBUFFERDESTCONSTOVERRIDE                      0x00100000
+#define WINEDDBLT_ZBUFFERDESTOVERRIDE                           0x00200000
+#define WINEDDBLT_ZBUFFERSRCCONSTOVERRIDE                       0x00400000
+#define WINEDDBLT_ZBUFFERSRCOVERRIDE                            0x00800000
+#define WINEDDBLT_WAIT                                          0x01000000
+#define WINEDDBLT_DEPTHFILL                                     0x02000000
+#define WINEDDBLT_DONOTWAIT                                     0x08000000
+
+/* DDSURFACEDESC.dwFlags */
+#define WINEDDSD_CAPS                                           0x00000001
+#define WINEDDSD_HEIGHT                                         0x00000002
+#define WINEDDSD_WIDTH                                          0x00000004
+#define WINEDDSD_PITCH                                          0x00000008
+#define WINEDDSD_BACKBUFFERCOUNT                                0x00000020
+#define WINEDDSD_ZBUFFERBITDEPTH                                0x00000040
+#define WINEDDSD_ALPHABITDEPTH                                  0x00000080
+#define WINEDDSD_LPSURFACE                                      0x00000800
+#define WINEDDSD_PIXELFORMAT                                    0x00001000
+#define WINEDDSD_CKDESTOVERLAY                                  0x00002000
+#define WINEDDSD_CKDESTBLT                                      0x00004000
+#define WINEDDSD_CKSRCOVERLAY                                   0x00008000
+#define WINEDDSD_CKSRCBLT                                       0x00010000
+#define WINEDDSD_MIPMAPCOUNT                                    0x00020000
+#define WINEDDSD_REFRESHRATE                                    0x00040000
+#define WINEDDSD_LINEARSIZE                                     0x00080000
+#define WINEDDSD_TEXTURESTAGE                                   0x00100000
+#define WINEDDSD_FVF                                            0x00200000
+#define WINEDDSD_SRCVBHANDLE                                    0x00400000
+#define WINEDDSD_ALL                                            0x007ff9ee
+
+/* Set/Get Colour Key Flags */
+#define WINEDDCKEY_COLORSPACE                                   0x00000001 /* Struct is single colour space */
+#define WINEDDCKEY_DESTBLT                                      0x00000002 /* To be used as dest for blt */
+#define WINEDDCKEY_DESTOVERLAY                                  0x00000004 /* To be used as dest for CK overlays */
+#define WINEDDCKEY_SRCBLT                                       0x00000008 /* To be used as src for blt */
+#define WINEDDCKEY_SRCOVERLAY                                   0x00000010 /* To be used as src for CK overlays */
+
+/* dwFlags for GetBltStatus */
+#define WINEDDGBS_CANBLT                                        0x00000001
+#define WINEDDGBS_ISBLTDONE                                     0x00000002
+
+/* dwFlags for GetFlipStatus */
+#define WINEDDGFS_CANFLIP                                       0x00000001
+#define WINEDDGFS_ISFLIPDONE                                    0x00000002
+
+/* dwFlags for Flip */
+#define WINEDDFLIP_WAIT                                         0x00000001
+#define WINEDDFLIP_EVEN                                         0x00000002 /* only valid for overlay */
+#define WINEDDFLIP_ODD                                          0x00000004 /* only valid for overlay */
+#define WINEDDFLIP_NOVSYNC                                      0x00000008
+#define WINEDDFLIP_STEREO                                       0x00000010
+#define WINEDDFLIP_DONOTWAIT                                    0x00000020
+#define WINEDDFLIP_INTERVAL2                                    0x02000000
+#define WINEDDFLIP_INTERVAL3                                    0x03000000
+#define WINEDDFLIP_INTERVAL4                                    0x04000000
+
+#define WINEDDOVER_ALPHADEST                                    0x00000001
+#define WINEDDOVER_ALPHADESTCONSTOVERRIDE                       0x00000002
+#define WINEDDOVER_ALPHADESTNEG                                 0x00000004
+#define WINEDDOVER_ALPHADESTSURFACEOVERRIDE                     0x00000008
+#define WINEDDOVER_ALPHAEDGEBLEND                               0x00000010
+#define WINEDDOVER_ALPHASRC                                     0x00000020
+#define WINEDDOVER_ALPHASRCCONSTOVERRIDE                        0x00000040
+#define WINEDDOVER_ALPHASRCNEG                                  0x00000080
+#define WINEDDOVER_ALPHASRCSURFACEOVERRIDE                      0x00000100
+#define WINEDDOVER_HIDE                                         0x00000200
+#define WINEDDOVER_KEYDEST                                      0x00000400
+#define WINEDDOVER_KEYDESTOVERRIDE                              0x00000800
+#define WINEDDOVER_KEYSRC                                       0x00001000
+#define WINEDDOVER_KEYSRCOVERRIDE                               0x00002000
+#define WINEDDOVER_SHOW                                         0x00004000
+#define WINEDDOVER_ADDDIRTYRECT                                 0x00008000
+#define WINEDDOVER_REFRESHDIRTYRECTS                            0x00010000
+#define WINEDDOVER_REFRESHALL                                   0x00020000
+#define WINEDDOVER_DDFX                                         0x00080000
+#define WINEDDOVER_AUTOFLIP                                     0x00100000
+#define WINEDDOVER_BOB                                          0x00200000
+#define WINEDDOVER_OVERRIDEBOBWEAVE                             0x00400000
+#define WINEDDOVER_INTERLEAVED                                  0x00800000
+
+/* DirectDraw Caps */
+#define WINEDDSCAPS_RESERVED1                                   0x00000001
+#define WINEDDSCAPS_ALPHA                                       0x00000002
+#define WINEDDSCAPS_BACKBUFFER                                  0x00000004
+#define WINEDDSCAPS_COMPLEX                                     0x00000008
+#define WINEDDSCAPS_FLIP                                        0x00000010
+#define WINEDDSCAPS_FRONTBUFFER                                 0x00000020
+#define WINEDDSCAPS_OFFSCREENPLAIN                              0x00000040
+#define WINEDDSCAPS_OVERLAY                                     0x00000080
+#define WINEDDSCAPS_PALETTE                                     0x00000100
+#define WINEDDSCAPS_PRIMARYSURFACE                              0x00000200
+#define WINEDDSCAPS_PRIMARYSURFACELEFT                          0x00000400
+#define WINEDDSCAPS_SYSTEMMEMORY                                0x00000800
+#define WINEDDSCAPS_TEXTURE                                     0x00001000
+#define WINEDDSCAPS_3DDEVICE                                    0x00002000
+#define WINEDDSCAPS_VIDEOMEMORY                                 0x00004000
+#define WINEDDSCAPS_VISIBLE                                     0x00008000
+#define WINEDDSCAPS_WRITEONLY                                   0x00010000
+#define WINEDDSCAPS_ZBUFFER                                     0x00020000
+#define WINEDDSCAPS_OWNDC                                       0x00040000
+#define WINEDDSCAPS_LIVEVIDEO                                   0x00080000
+#define WINEDDSCAPS_HWCODEC                                     0x00100000
+#define WINEDDSCAPS_MODEX                                       0x00200000
+#define WINEDDSCAPS_MIPMAP                                      0x00400000
+#define WINEDDSCAPS_RESERVED2                                   0x00800000
+#define WINEDDSCAPS_ALLOCONLOAD                                 0x04000000
+#define WINEDDSCAPS_VIDEOPORT                                   0x08000000
+#define WINEDDSCAPS_LOCALVIDMEM                                 0x10000000
+#define WINEDDSCAPS_NONLOCALVIDMEM                              0x20000000
+#define WINEDDSCAPS_STANDARDVGAMODE                             0x40000000
+#define WINEDDSCAPS_OPTIMIZED                                   0x80000000
+
+#define WINEDDCKEYCAPS_DESTBLT                                  0x00000001
+#define WINEDDCKEYCAPS_DESTBLTCLRSPACE                          0x00000002
+#define WINEDDCKEYCAPS_DESTBLTCLRSPACEYUV                       0x00000004
+#define WINEDDCKEYCAPS_DESTBLTYUV                               0x00000008
+#define WINEDDCKEYCAPS_DESTOVERLAY                              0x00000010
+#define WINEDDCKEYCAPS_DESTOVERLAYCLRSPACE                      0x00000020
+#define WINEDDCKEYCAPS_DESTOVERLAYCLRSPACEYUV                   0x00000040
+#define WINEDDCKEYCAPS_DESTOVERLAYONEACTIVE                     0x00000080
+#define WINEDDCKEYCAPS_DESTOVERLAYYUV                           0x00000100
+#define WINEDDCKEYCAPS_SRCBLT                                   0x00000200
+#define WINEDDCKEYCAPS_SRCBLTCLRSPACE                           0x00000400
+#define WINEDDCKEYCAPS_SRCBLTCLRSPACEYUV                        0x00000800
+#define WINEDDCKEYCAPS_SRCBLTYUV                                0x00001000
+#define WINEDDCKEYCAPS_SRCOVERLAY                               0x00002000
+#define WINEDDCKEYCAPS_SRCOVERLAYCLRSPACE                       0x00004000
+#define WINEDDCKEYCAPS_SRCOVERLAYCLRSPACEYUV                    0x00008000
+#define WINEDDCKEYCAPS_SRCOVERLAYONEACTIVE                      0x00010000
+#define WINEDDCKEYCAPS_SRCOVERLAYYUV                            0x00020000
+#define WINEDDCKEYCAPS_NOCOSTOVERLAY                            0x00040000
+
+#define WINEDDFXCAPS_BLTALPHA                                   0x00000001
+#define WINEDDFXCAPS_OVERLAYALPHA                               0x00000004
+#define WINEDDFXCAPS_BLTARITHSTRETCHYN                          0x00000010
+#define WINEDDFXCAPS_BLTARITHSTRETCHY                           0x00000020
+#define WINEDDFXCAPS_BLTMIRRORLEFTRIGHT                         0x00000040
+#define WINEDDFXCAPS_BLTMIRRORUPDOWN                            0x00000080
+#define WINEDDFXCAPS_BLTROTATION                                0x00000100
+#define WINEDDFXCAPS_BLTROTATION90                              0x00000200
+#define WINEDDFXCAPS_BLTSHRINKX                                 0x00000400
+#define WINEDDFXCAPS_BLTSHRINKXN                                0x00000800
+#define WINEDDFXCAPS_BLTSHRINKY                                 0x00001000
+#define WINEDDFXCAPS_BLTSHRINKYN                                0x00002000
+#define WINEDDFXCAPS_BLTSTRETCHX                                0x00004000
+#define WINEDDFXCAPS_BLTSTRETCHXN                               0x00008000
+#define WINEDDFXCAPS_BLTSTRETCHY                                0x00010000
+#define WINEDDFXCAPS_BLTSTRETCHYN                               0x00020000
+#define WINEDDFXCAPS_OVERLAYARITHSTRETCHY                       0x00040000
+#define WINEDDFXCAPS_OVERLAYARITHSTRETCHYN                      0x00000008
+#define WINEDDFXCAPS_OVERLAYSHRINKX                             0x00080000
+#define WINEDDFXCAPS_OVERLAYSHRINKXN                            0x00100000
+#define WINEDDFXCAPS_OVERLAYSHRINKY                             0x00200000
+#define WINEDDFXCAPS_OVERLAYSHRINKYN                            0x00400000
+#define WINEDDFXCAPS_OVERLAYSTRETCHX                            0x00800000
+#define WINEDDFXCAPS_OVERLAYSTRETCHXN                           0x01000000
+#define WINEDDFXCAPS_OVERLAYSTRETCHY                            0x02000000
+#define WINEDDFXCAPS_OVERLAYSTRETCHYN                           0x04000000
+#define WINEDDFXCAPS_OVERLAYMIRRORLEFTRIGHT                     0x08000000
+#define WINEDDFXCAPS_OVERLAYMIRRORUPDOWN                        0x10000000
+
+#define WINEDDCAPS_3D                                           0x00000001
+#define WINEDDCAPS_ALIGNBOUNDARYDEST                            0x00000002
+#define WINEDDCAPS_ALIGNSIZEDEST                                0x00000004
+#define WINEDDCAPS_ALIGNBOUNDARYSRC                             0x00000008
+#define WINEDDCAPS_ALIGNSIZESRC                                 0x00000010
+#define WINEDDCAPS_ALIGNSTRIDE                                  0x00000020
+#define WINEDDCAPS_BLT                                          0x00000040
+#define WINEDDCAPS_BLTQUEUE                                     0x00000080
+#define WINEDDCAPS_BLTFOURCC                                    0x00000100
+#define WINEDDCAPS_BLTSTRETCH                                   0x00000200
+#define WINEDDCAPS_GDI                                          0x00000400
+#define WINEDDCAPS_OVERLAY                                      0x00000800
+#define WINEDDCAPS_OVERLAYCANTCLIP                              0x00001000
+#define WINEDDCAPS_OVERLAYFOURCC                                0x00002000
+#define WINEDDCAPS_OVERLAYSTRETCH                               0x00004000
+#define WINEDDCAPS_PALETTE                                      0x00008000
+#define WINEDDCAPS_PALETTEVSYNC                                 0x00010000
+#define WINEDDCAPS_READSCANLINE                                 0x00020000
+#define WINEDDCAPS_STEREOVIEW                                   0x00040000
+#define WINEDDCAPS_VBI                                          0x00080000
+#define WINEDDCAPS_ZBLTS                                        0x00100000
+#define WINEDDCAPS_ZOVERLAYS                                    0x00200000
+#define WINEDDCAPS_COLORKEY                                     0x00400000
+#define WINEDDCAPS_ALPHA                                        0x00800000
+#define WINEDDCAPS_COLORKEYHWASSIST                             0x01000000
+#define WINEDDCAPS_NOHARDWARE                                   0x02000000
+#define WINEDDCAPS_BLTCOLORFILL                                 0x04000000
+#define WINEDDCAPS_BANKSWITCHED                                 0x08000000
+#define WINEDDCAPS_BLTDEPTHFILL                                 0x10000000
+#define WINEDDCAPS_CANCLIP                                      0x20000000
+#define WINEDDCAPS_CANCLIPSTRETCHED                             0x40000000
+#define WINEDDCAPS_CANBLTSYSMEM                                 0x80000000
+
+#define WINEDDCAPS2_CERTIFIED                                   0x00000001
+#define WINEDDCAPS2_NO2DDURING3DSCENE                           0x00000002
+#define WINEDDCAPS2_VIDEOPORT                                   0x00000004
+#define WINEDDCAPS2_AUTOFLIPOVERLAY                             0x00000008
+#define WINEDDCAPS2_CANBOBINTERLEAVED                           0x00000010
+#define WINEDDCAPS2_CANBOBNONINTERLEAVED                        0x00000020
+#define WINEDDCAPS2_COLORCONTROLOVERLAY                         0x00000040
+#define WINEDDCAPS2_COLORCONTROLPRIMARY                         0x00000080
+#define WINEDDCAPS2_CANDROPZ16BIT                               0x00000100
+#define WINEDDCAPS2_NONLOCALVIDMEM                              0x00000200
+#define WINEDDCAPS2_NONLOCALVIDMEMCAPS                          0x00000400
+#define WINEDDCAPS2_NOPAGELOCKREQUIRED                          0x00000800
+#define WINEDDCAPS2_WIDESURFACES                                0x00001000
+#define WINEDDCAPS2_CANFLIPODDEVEN                              0x00002000
+#define WINEDDCAPS2_CANBOBHARDWARE                              0x00004000
+#define WINEDDCAPS2_COPYFOURCC                                  0x00008000
+#define WINEDDCAPS2_PRIMARYGAMMA                                0x00020000
+#define WINEDDCAPS2_CANRENDERWINDOWED                           0x00080000
+#define WINEDDCAPS2_CANCALIBRATEGAMMA                           0x00100000
+#define WINEDDCAPS2_FLIPINTERVAL                                0x00200000
+#define WINEDDCAPS2_FLIPNOVSYNC                                 0x00400000
+#define WINEDDCAPS2_CANMANAGETEXTURE                            0x00800000
+#define WINEDDCAPS2_TEXMANINNONLOCALVIDMEM                      0x01000000
+#define WINEDDCAPS2_STEREO                                      0x02000000
+#define WINEDDCAPS2_SYSTONONLOCAL_AS_SYSTOLOCAL                 0x04000000
+
+/* DDCAPS.d */
+#define WINEDDPCAPS_4BIT                                        0x00000001
+#define WINEDDPCAPS_8BITENTRIES                                 0x00000002
+#define WINEDDPCAPS_8BIT                                        0x00000004
+#define WINEDDPCAPS_INITIALIZE                                  0x00000008
+#define WINEDDPCAPS_PRIMARYSURFACE                              0x00000010
+#define WINEDDPCAPS_PRIMARYSURFACELEFT                          0x00000020
+#define WINEDDPCAPS_ALLOW256                                    0x00000040
+#define WINEDDPCAPS_VSYNC                                       0x00000080
+#define WINEDDPCAPS_1BIT                                        0x00000100
+#define WINEDDPCAPS_2BIT                                        0x00000200
+#define WINEDDPCAPS_ALPHA                                       0x00000400
+
+#define WINED3D_SURFACE_MAPPABLE                                0x00000001
+#define WINED3D_SURFACE_DISCARD                                 0x00000002
+#define WINED3D_SURFACE_PIN_SYSMEM                              0x00000004
+
+struct wined3d_display_mode
+{
+    UINT width;
+    UINT height;
+    UINT refresh_rate;
+    enum wined3d_format_id format_id;
+    enum wined3d_scanline_ordering scanline_ordering;
+};
+
+struct wined3d_color
+{
+    float r;
+    float g;
+    float b;
+    float a;
+};
+
+struct wined3d_vec3
+{
+    float x;
+    float y;
+    float z;
+};
+
+struct wined3d_vec4
+{
+    float x;
+    float y;
+    float z;
+    float w;
+};
+
+struct wined3d_matrix
+{
+    union
+    {
+        struct
+        {
+            float _11, _12, _13, _14;
+            float _21, _22, _23, _24;
+            float _31, _32, _33, _34;
+            float _41, _42, _43, _44;
+        } DUMMYSTRUCTNAME;
+        float m[4][4];
+    } DUMMYUNIONNAME;
+};
+
+struct wined3d_light
+{
+    enum wined3d_light_type type;
+    struct wined3d_color diffuse;
+    struct wined3d_color specular;
+    struct wined3d_color ambient;
+    struct wined3d_vec3 position;
+    struct wined3d_vec3 direction;
+    float range;
+    float falloff;
+    float attenuation0;
+    float attenuation1;
+    float attenuation2;
+    float theta;
+    float phi;
+};
+
+struct wined3d_material
+{
+    struct wined3d_color diffuse;
+    struct wined3d_color ambient;
+    struct wined3d_color specular;
+    struct wined3d_color emissive;
+    float power;
+};
+
+struct wined3d_viewport
+{
+    UINT x;
+    UINT y;
+    UINT width;
+    UINT height;
+    float min_z;
+    float max_z;
+};
+
+struct wined3d_gamma_ramp
+{
+    WORD red[256];
+    WORD green[256];
+    WORD blue[256];
+};
+
+struct wined3d_line_pattern
+{
+    WORD repeat_factor;
+    WORD line_pattern;
+};
+
+struct wined3d_rect_patch_info
+{
+    UINT start_vertex_offset_width;
+    UINT start_vertex_offset_height;
+    UINT width;
+    UINT height;
+    UINT stride;
+    enum wined3d_basis_type basis;
+    enum wined3d_degree_type degree;
+};
+
+struct wined3d_tri_patch_info
+{
+    UINT start_vertex_offset;
+    UINT vertex_count;
+    enum wined3d_basis_type basis;
+    enum wined3d_degree_type degree;
+};
+
+struct wined3d_adapter_identifier
+{
+    char *driver;
+    UINT driver_size;
+    char *description;
+    UINT description_size;
+    char *device_name;
+    UINT device_name_size;
+    LARGE_INTEGER driver_version;
+    DWORD vendor_id;
+    DWORD device_id;
+    DWORD subsystem_id;
+    DWORD revision;
+    GUID device_identifier;
+    DWORD whql_level;
+    LUID adapter_luid;
+    SIZE_T video_memory;
+};
+
+struct wined3d_swapchain_desc
+{
+    UINT backbuffer_width;
+    UINT backbuffer_height;
+    enum wined3d_format_id backbuffer_format;
+    UINT backbuffer_count;
+    enum wined3d_multisample_type multisample_type;
+    DWORD multisample_quality;
+    enum wined3d_swap_effect swap_effect;
+    HWND device_window;
+    BOOL windowed;
+    BOOL enable_auto_depth_stencil;
+    enum wined3d_format_id auto_depth_stencil_format;
+    DWORD flags;
+    UINT refresh_rate;
+    UINT swap_interval;
+    BOOL auto_restore_display_mode;
+#ifdef VBOX_WITH_WDDM
+    struct VBOXUHGSMI *pHgsmi;
+#endif
+};
+
+struct wined3d_resource_desc
+{
+    enum wined3d_resource_type resource_type;
+    enum wined3d_format_id format;
+    enum wined3d_multisample_type multisample_type;
+    UINT multisample_quality;
+    DWORD usage;
+    enum wined3d_pool pool;
+    UINT width;
+    UINT height;
+    UINT depth;
+    UINT size;
+};
+
+struct wined3d_clip_status
+{
+   DWORD clip_union;
+   DWORD clip_intersection;
+};
+
+struct wined3d_vertex_element
+{
+    enum wined3d_format_id format;
+    WORD input_slot;
+    WORD offset;
+    UINT output_slot; /* D3D 8 & 10 */
+    BYTE method;
+    BYTE usage;
+    BYTE usage_idx;
+};
+
+struct wined3d_device_creation_parameters
+{
+    UINT adapter_idx;
+    enum wined3d_device_type device_type;
+    HWND focus_window;
+    DWORD flags;
+};
+
+struct wined3d_raster_status
+{
+    BOOL in_vblank;
+    UINT scan_line;
+};
+
+struct wined3d_map_desc
+{
+    UINT row_pitch;
+    UINT slice_pitch;
+    void *data;
+};
+
+struct wined3d_box
+{
+    UINT left;
+    UINT top;
+    UINT right;
+    UINT bottom;
+    UINT front;
+    UINT back;
+};
+
+struct wined3d_vertex_shader_caps
+{
+    DWORD caps;
+    INT dynamic_flow_control_depth;
+    INT temp_count;
+    INT static_flow_control_depth;
+};
+
+struct wined3d_pixel_shader_caps
+{
+    DWORD caps;
+    INT dynamic_flow_control_depth;
+    INT temp_count;
+    INT static_flow_control_depth;
+    INT instruction_slot_count;
+};
+
+struct wined3d_ddraw_caps
+{
+    DWORD caps;
+    DWORD caps2;
+    DWORD color_key_caps;
+    DWORD fx_caps;
+    DWORD fx_alpha_caps;
+    DWORD pal_caps;
+    DWORD sv_caps;
+    DWORD svb_caps;
+    DWORD svb_color_key_caps;
+    DWORD svb_fx_caps;
+    DWORD vsb_caps;
+    DWORD vsb_color_key_caps;
+    DWORD vsb_fx_caps;
+    DWORD ssb_caps;
+    DWORD ssb_color_key_caps;
+    DWORD ssb_fx_caps;
+    DWORD dds_caps;
+    DWORD stride_align;
+};
+
+typedef struct _WINED3DCAPS
+{
+    enum wined3d_device_type DeviceType;
+    UINT AdapterOrdinal;
+
+    DWORD Caps;
+    DWORD Caps2;
+    DWORD Caps3;
+    DWORD PresentationIntervals;
+
+    DWORD CursorCaps;
+    DWORD DevCaps;
+    DWORD PrimitiveMiscCaps;
+    DWORD RasterCaps;
+    DWORD ZCmpCaps;
+    DWORD SrcBlendCaps;
+    DWORD DestBlendCaps;
+    DWORD AlphaCmpCaps;
+    DWORD ShadeCaps;
+    DWORD TextureCaps;
+    DWORD TextureFilterCaps;
+    DWORD CubeTextureFilterCaps;
+    DWORD VolumeTextureFilterCaps;
+    DWORD TextureAddressCaps;
+    DWORD VolumeTextureAddressCaps;
+    DWORD LineCaps;
+
+    DWORD MaxTextureWidth;
+    DWORD MaxTextureHeight;
+    DWORD MaxVolumeExtent;
+    DWORD MaxTextureRepeat;
+    DWORD MaxTextureAspectRatio;
+    DWORD MaxAnisotropy;
+    float MaxVertexW;
+
+    float GuardBandLeft;
+    float GuardBandTop;
+    float GuardBandRight;
+    float GuardBandBottom;
+
+    float ExtentsAdjust;
+    DWORD StencilCaps;
+
+    DWORD FVFCaps;
+    DWORD TextureOpCaps;
+    DWORD MaxTextureBlendStages;
+    DWORD MaxSimultaneousTextures;
+
+    DWORD VertexProcessingCaps;
+    DWORD MaxActiveLights;
+    DWORD MaxUserClipPlanes;
+    DWORD MaxVertexBlendMatrices;
+    DWORD MaxVertexBlendMatrixIndex;
+
+    float MaxPointSize;
+
+    DWORD MaxPrimitiveCount;
+    DWORD MaxVertexIndex;
+    DWORD MaxStreams;
+    DWORD MaxStreamStride;
+
+    DWORD VertexShaderVersion;
+    DWORD MaxVertexShaderConst;
+
+    DWORD PixelShaderVersion;
+    float PixelShader1xMaxValue;
+
+    /* DX 9 */
+    DWORD DevCaps2;
+
+    float MaxNpatchTessellationLevel;
+    DWORD Reserved5; /* undocumented */
+
+    UINT MasterAdapterOrdinal;
+    UINT AdapterOrdinalInGroup;
+    UINT NumberOfAdaptersInGroup;
+    DWORD DeclTypes;
+    DWORD NumSimultaneousRTs;
+    DWORD StretchRectFilterCaps;
+    struct wined3d_vertex_shader_caps VS20Caps;
+    struct wined3d_pixel_shader_caps PS20Caps;
+    DWORD VertexTextureFilterCaps;
+    DWORD MaxVShaderInstructionsExecuted;
+    DWORD MaxPShaderInstructionsExecuted;
+    DWORD MaxVertexShader30InstructionSlots;
+    DWORD MaxPixelShader30InstructionSlots;
+    DWORD Reserved2; /* Not in the microsoft headers but documented */
+    DWORD Reserved3;
+
+    struct wined3d_ddraw_caps ddraw_caps;
+} WINED3DCAPS;
+
+struct wined3d_color_key
+{
+    DWORD color_space_low_value;    /* low boundary of color space that is to
+                                     * be treated as Color Key, inclusive */
+    DWORD color_space_high_value;   /* high boundary of color space that is
+                                     * to be treated as Color Key, inclusive */
+};
+
+typedef struct _WINEDDBLTFX
+{
+    DWORD dwSize;                                   /* size of structure */
+    DWORD dwDDFX;                                   /* FX operations */
+    DWORD dwROP;                                    /* Win32 raster operations */
+    DWORD dwDDROP;                                  /* Raster operations new for DirectDraw */
+    DWORD dwRotationAngle;                          /* Rotation angle for blt */
+    DWORD dwZBufferOpCode;                          /* ZBuffer compares */
+    DWORD dwZBufferLow;                             /* Low limit of Z buffer */
+    DWORD dwZBufferHigh;                            /* High limit of Z buffer */
+    DWORD dwZBufferBaseDest;                        /* Destination base value */
+    DWORD dwZDestConstBitDepth;                     /* Bit depth used to specify Z constant for destination */
+    union
+    {
+        DWORD dwZDestConst;                         /* Constant to use as Z buffer for dest */
+        struct wined3d_surface *lpDDSZBufferDest;   /* Surface to use as Z buffer for dest */
+    } DUMMYUNIONNAME1;
+    DWORD dwZSrcConstBitDepth;                      /* Bit depth used to specify Z constant for source */
+    union
+    {
+        DWORD dwZSrcConst;                          /* Constant to use as Z buffer for src */
+        struct wined3d_surface *lpDDSZBufferSrc;    /* Surface to use as Z buffer for src */
+    } DUMMYUNIONNAME2;
+    DWORD dwAlphaEdgeBlendBitDepth;                 /* Bit depth used to specify constant for alpha edge blend */
+    DWORD dwAlphaEdgeBlend;                         /* Alpha for edge blending */
+    DWORD dwReserved;
+    DWORD dwAlphaDestConstBitDepth;                 /* Bit depth used to specify alpha constant for destination */
+    union
+    {
+        DWORD dwAlphaDestConst;                     /* Constant to use as Alpha Channel */
+        struct wined3d_surface *lpDDSAlphaDest;     /* Surface to use as Alpha Channel */
+    } DUMMYUNIONNAME3;
+    DWORD dwAlphaSrcConstBitDepth;                  /* Bit depth used to specify alpha constant for source */
+    union
+    {
+        DWORD dwAlphaSrcConst;                      /* Constant to use as Alpha Channel */
+        struct wined3d_surface *lpDDSAlphaSrc;      /* Surface to use as Alpha Channel */
+    } DUMMYUNIONNAME4;
+    union
+    {
+        DWORD dwFillColor;                          /* color in RGB or Palettized */
+        DWORD dwFillDepth;                          /* depth value for z-buffer */
+        DWORD dwFillPixel;                          /* pixel val for RGBA or RGBZ */
+        struct wined3d_surface *lpDDSPattern;       /* Surface to use as pattern */
+    } DUMMYUNIONNAME5;
+    struct wined3d_color_key ddckDestColorkey;      /* DestColorkey override */
+    struct wined3d_color_key ddckSrcColorkey;       /* SrcColorkey override */
+} WINEDDBLTFX,*LPWINEDDBLTFX;
+
+typedef struct _WINEDDOVERLAYFX
+{
+    DWORD dwSize;                                   /* size of structure */
+    DWORD dwAlphaEdgeBlendBitDepth;                 /* Bit depth used to specify constant for alpha edge blend */
+    DWORD dwAlphaEdgeBlend;                         /* Constant to use as alpha for edge blend */
+    DWORD dwReserved;
+    DWORD dwAlphaDestConstBitDepth;                 /* Bit depth used to specify alpha constant for destination */
+    union
+    {
+        DWORD dwAlphaDestConst;                     /* Constant to use as alpha channel for dest */
+        struct wined3d_surface *lpDDSAlphaDest;     /* Surface to use as alpha channel for dest */
+    } DUMMYUNIONNAME1;
+    DWORD dwAlphaSrcConstBitDepth;                  /* Bit depth used to specify alpha constant for source */
+    union
+    {
+        DWORD dwAlphaSrcConst;                      /* Constant to use as alpha channel for src */
+        struct wined3d_surface *lpDDSAlphaSrc;      /* Surface to use as alpha channel for src */
+    } DUMMYUNIONNAME2;
+    struct wined3d_color_key dckDestColorkey;       /* DestColorkey override */
+    struct wined3d_color_key dckSrcColorkey;        /* SrcColorkey override */
+    DWORD dwDDFX;                                   /* Overlay FX */
+    DWORD dwFlags;                                  /* flags */
+} WINEDDOVERLAYFX;
+
+struct wined3d_buffer_desc
+{
+    UINT byte_width;
+    DWORD usage;
+    UINT bind_flags;
+    UINT cpu_access_flags;
+    UINT misc_flags;
+};
+
+struct wined3d_shader_signature_element
+{
+    const char *semantic_name;
+    UINT semantic_idx;
+    enum wined3d_sysval_semantic sysval_semantic;
+    DWORD component_type;
+    UINT register_idx;
+    DWORD mask;
+};
+
+struct wined3d_shader_signature
+{
+    UINT element_count;
+    struct wined3d_shader_signature_element *elements;
+    char *string_data;
+};
+
+struct wined3d_parent_ops
+{
+    void (__stdcall *wined3d_object_destroyed)(void *parent);
+};
+
+struct wined3d;
+struct wined3d_buffer;
+struct wined3d_device;
+struct wined3d_palette;
+struct wined3d_query;
+struct wined3d_rendertarget_view;
+struct wined3d_resource;
+struct wined3d_sampler;
+struct wined3d_shader;
+struct wined3d_stateblock;
+struct wined3d_surface;
+struct wined3d_swapchain;
+struct wined3d_texture;
+struct wined3d_vertex_declaration;
+struct wined3d_volume;
+
+struct wined3d_device_parent
+{
+    const struct wined3d_device_parent_ops *ops;
+};
+
+struct wined3d_device_parent_ops
+{
+    void (__cdecl *wined3d_device_created)(struct wined3d_device_parent *device_parent, struct wined3d_device *device);
+    void (__cdecl *mode_changed)(struct wined3d_device_parent *device_parent);
+    HRESULT (__cdecl *create_swapchain_surface)(struct wined3d_device_parent *device_parent, void *container_parent,
+            const struct wined3d_resource_desc *desc, struct wined3d_surface **surface);
+    HRESULT (__cdecl *create_texture_surface)(struct wined3d_device_parent *device_parent, void *container_parent,
+            const struct wined3d_resource_desc *desc, UINT sub_resource_idx, DWORD flags,
+            struct wined3d_surface **surface
+#ifdef VBOX_WITH_WDDM
+            , HANDLE *shared_handle
+            , void *pvClientMem
+#endif
+            );
+    HRESULT (__cdecl *create_volume)(struct wined3d_device_parent *device_parent, void *container_parent,
+            UINT width, UINT height, UINT depth, enum wined3d_format_id format_id, enum wined3d_pool pool, DWORD usage,
+            struct wined3d_volume **volume
+#ifdef VBOX_WITH_WDDM
+            , HANDLE *shared_handle
+            , void *pvClientMem
+#endif
+            );
+    HRESULT (__cdecl *create_swapchain)(struct wined3d_device_parent *device_parent,
+            struct wined3d_swapchain_desc *desc, struct wined3d_swapchain **swapchain);
+};
+
+typedef HRESULT (CDECL *wined3d_device_reset_cb)(struct wined3d_resource *resource);
+#ifndef VBOX_WITH_WDDM
+void __stdcall wined3d_mutex_lock(void);
+void __stdcall wined3d_mutex_unlock(void);
+#else
+#define wined3d_mutex_lock() do {} while (0)
+#define wined3d_mutex_unlock() do {} while (0)
+#endif
+
+HRESULT __cdecl wined3d_check_depth_stencil_match(const struct wined3d *wined3d, UINT adapter_idx,
+        enum wined3d_device_type device_type, enum wined3d_format_id adapter_format_id,
+        enum wined3d_format_id render_target_format_id, enum wined3d_format_id depth_stencil_format_id);
+HRESULT __cdecl wined3d_check_device_format(const struct wined3d *wined3d, UINT adaper_idx,
+        enum wined3d_device_type device_type, enum wined3d_format_id adapter_format_id, DWORD usage,
+        enum wined3d_resource_type resource_type, enum wined3d_format_id check_format_id);
+HRESULT __cdecl wined3d_check_device_format_conversion(const struct wined3d *wined3d, UINT adapter_idx,
+        enum wined3d_device_type device_type, enum wined3d_format_id source_format_id,
+        enum wined3d_format_id target_format_id);
+HRESULT __cdecl wined3d_check_device_multisample_type(const struct wined3d *wined3d, UINT adapter_idx,
+        enum wined3d_device_type device_type, enum wined3d_format_id surface_format_id, BOOL windowed,
+        enum wined3d_multisample_type multisample_type, DWORD *quality_levels);
+HRESULT __cdecl wined3d_check_device_type(const struct wined3d *wined3d, UINT adapter_idx,
+        enum wined3d_device_type device_type, enum wined3d_format_id display_format_id,
+        enum wined3d_format_id backbuffer_format_id, BOOL windowed);
+struct wined3d * __cdecl wined3d_create(UINT version, DWORD flags);
+ULONG __cdecl wined3d_decref(struct wined3d *wined3d);
+HRESULT __cdecl wined3d_enum_adapter_modes(const struct wined3d *wined3d, UINT adapter_idx,
+        enum wined3d_format_id format_id, enum wined3d_scanline_ordering scanline_ordering,
+        UINT mode_idx, struct wined3d_display_mode *mode);
+UINT __cdecl wined3d_get_adapter_count(const struct wined3d *wined3d);
+HRESULT __cdecl wined3d_get_adapter_display_mode(const struct wined3d *wined3d, UINT adapter_idx,
+        struct wined3d_display_mode *mode, enum wined3d_display_rotation *rotation);
+HRESULT __cdecl wined3d_get_adapter_identifier(const struct wined3d *wined3d, UINT adapter_idx,
+        DWORD flags, struct wined3d_adapter_identifier *identifier);
+UINT __cdecl wined3d_get_adapter_mode_count(const struct wined3d *wined3d, UINT adapter_idx,
+        enum wined3d_format_id format_id, enum wined3d_scanline_ordering scanline_ordering);
+HMONITOR __cdecl wined3d_get_adapter_monitor(const struct wined3d *wined3d, UINT adapter_idx);
+HRESULT __cdecl wined3d_get_adapter_raster_status(const struct wined3d *wined3d, UINT adapter_idx,
+        struct wined3d_raster_status *raster_status);
+HRESULT __cdecl wined3d_get_device_caps(const struct wined3d *wined3d, UINT adapter_idx,
+        enum wined3d_device_type device_type, WINED3DCAPS *caps);
+ULONG __cdecl wined3d_incref(struct wined3d *wined3d);
+HRESULT __cdecl wined3d_register_software_device(struct wined3d *wined3d, void *init_function);
+HRESULT __cdecl wined3d_set_adapter_display_mode(struct wined3d *wined3d,
+        UINT adapter_idx, const struct wined3d_display_mode *mode);
+
+HRESULT __cdecl wined3d_buffer_create(struct wined3d_device *device, struct wined3d_buffer_desc *desc,
+        const void *data, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_buffer **buffer);
+HRESULT __cdecl wined3d_buffer_create_ib(struct wined3d_device *device, UINT length, DWORD usage,
+        enum wined3d_pool pool, void *parent, const struct wined3d_parent_ops *parent_ops,
+        struct wined3d_buffer **buffer);
+HRESULT __cdecl wined3d_buffer_create_vb(struct wined3d_device *device, UINT length, DWORD usage,
+        enum wined3d_pool pool, void *parent, const struct wined3d_parent_ops *parent_ops,
+        struct wined3d_buffer **buffer);
+ULONG __cdecl wined3d_buffer_decref(struct wined3d_buffer *buffer);
+void * __cdecl wined3d_buffer_get_parent(const struct wined3d_buffer *buffer);
+DWORD __cdecl wined3d_buffer_get_priority(const struct wined3d_buffer *buffer);
+struct wined3d_resource * __cdecl wined3d_buffer_get_resource(struct wined3d_buffer *buffer);
+ULONG __cdecl wined3d_buffer_incref(struct wined3d_buffer *buffer);
+HRESULT __cdecl wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UINT size, BYTE **data, DWORD flags);
+void  __cdecl wined3d_buffer_preload(struct wined3d_buffer *buffer);
+DWORD __cdecl wined3d_buffer_set_priority(struct wined3d_buffer *buffer, DWORD new_priority);
+void __cdecl wined3d_buffer_unmap(struct wined3d_buffer *buffer);
+
+HRESULT __cdecl wined3d_device_acquire_focus_window(struct wined3d_device *device, HWND window);
+HRESULT __cdecl wined3d_device_begin_scene(struct wined3d_device *device);
+HRESULT __cdecl wined3d_device_begin_stateblock(struct wined3d_device *device);
+HRESULT __cdecl wined3d_device_clear(struct wined3d_device *device, DWORD rect_count, const RECT *rects, DWORD flags,
+        const struct wined3d_color *color, float z, DWORD stencil);
+void __cdecl wined3d_device_clear_rendertarget_view(struct wined3d_device *device,
+        struct wined3d_rendertarget_view *rendertarget_view, const struct wined3d_color *color);
+HRESULT __cdecl wined3d_device_color_fill(struct wined3d_device *device, struct wined3d_surface *surface,
+        const RECT *rect, const struct wined3d_color *color);
+HRESULT __cdecl wined3d_device_create(struct wined3d *wined3d, UINT adapter_idx,
+        enum wined3d_device_type device_type, HWND focus_window, DWORD behaviour_flags, BYTE surface_alignment,
+        struct wined3d_device_parent *device_parent, struct wined3d_device **device);
+ULONG __cdecl wined3d_device_decref(struct wined3d_device *device);
+HRESULT __cdecl wined3d_device_draw_indexed_primitive(struct wined3d_device *device, UINT start_idx, UINT index_count);
+void __cdecl wined3d_device_draw_indexed_primitive_instanced(struct wined3d_device *device,
+        UINT start_idx, UINT index_count, UINT start_instance, UINT instance_count);
+HRESULT __cdecl wined3d_device_draw_primitive(struct wined3d_device *device, UINT start_vertex, UINT vertex_count);
+HRESULT __cdecl wined3d_device_end_scene(struct wined3d_device *device);
+HRESULT __cdecl wined3d_device_end_stateblock(struct wined3d_device *device, struct wined3d_stateblock **stateblock);
+void __cdecl wined3d_device_evict_managed_resources(struct wined3d_device *device);
+UINT __cdecl wined3d_device_get_available_texture_mem(const struct wined3d_device *device);
+HRESULT __cdecl wined3d_device_get_back_buffer(const struct wined3d_device *device, UINT swapchain_idx,
+        UINT backbuffer_idx, enum wined3d_backbuffer_type backbuffer_type, struct wined3d_surface **backbuffer);
+INT __cdecl wined3d_device_get_base_vertex_index(const struct wined3d_device *device);
+HRESULT __cdecl wined3d_device_get_clip_plane(const struct wined3d_device *device,
+        UINT plane_idx, struct wined3d_vec4 *plane);
+HRESULT __cdecl wined3d_device_get_clip_status(const struct wined3d_device *device,
+        struct wined3d_clip_status *clip_status);
+void __cdecl wined3d_device_get_creation_parameters(const struct wined3d_device *device,
+        struct wined3d_device_creation_parameters *creation_parameters);
+struct wined3d_surface * __cdecl wined3d_device_get_depth_stencil(const struct wined3d_device *device);
+HRESULT __cdecl wined3d_device_get_device_caps(const struct wined3d_device *device, WINED3DCAPS *caps);
+HRESULT __cdecl wined3d_device_get_display_mode(const struct wined3d_device *device, UINT swapchain_idx,
+        struct wined3d_display_mode *mode, enum wined3d_display_rotation *rotation);
+HRESULT __cdecl wined3d_device_get_front_buffer_data(const struct wined3d_device *device,
+        UINT swapchain_idx, struct wined3d_surface *dst_surface);
+void __cdecl wined3d_device_get_gamma_ramp(const struct wined3d_device *device,
+        UINT swapchain_idx, struct wined3d_gamma_ramp *ramp);
+struct wined3d_shader * __cdecl wined3d_device_get_geometry_shader(const struct wined3d_device *device);
+struct wined3d_buffer * __cdecl wined3d_device_get_gs_cb(const struct wined3d_device *device, UINT idx);
+struct wined3d_sampler * __cdecl wined3d_device_get_gs_sampler(const struct wined3d_device *device, UINT idx);
+struct wined3d_buffer * __cdecl wined3d_device_get_index_buffer(const struct wined3d_device *device,
+        enum wined3d_format_id *format);
+HRESULT __cdecl wined3d_device_get_light(const struct wined3d_device *device,
+        UINT light_idx, struct wined3d_light *light);
+HRESULT __cdecl wined3d_device_get_light_enable(const struct wined3d_device *device, UINT light_idx, BOOL *enable);
+void __cdecl wined3d_device_get_material(const struct wined3d_device *device, struct wined3d_material *material);
+float __cdecl wined3d_device_get_npatch_mode(const struct wined3d_device *device);
+struct wined3d_shader * __cdecl wined3d_device_get_pixel_shader(const struct wined3d_device *device);
+void __cdecl wined3d_device_get_primitive_type(const struct wined3d_device *device,
+        enum wined3d_primitive_type *primitive_topology);
+struct wined3d_buffer * __cdecl wined3d_device_get_ps_cb(const struct wined3d_device *device, UINT idx);
+HRESULT __cdecl wined3d_device_get_ps_consts_b(const struct wined3d_device *device,
+        UINT start_register, BOOL *constants, UINT bool_count);
+HRESULT __cdecl wined3d_device_get_ps_consts_f(const struct wined3d_device *device,
+        UINT start_register, float *constants, UINT vector4f_count);
+HRESULT __cdecl wined3d_device_get_ps_consts_i(const struct wined3d_device *device,
+        UINT start_register, int *constants, UINT vector4i_count);
+struct wined3d_sampler * __cdecl wined3d_device_get_ps_sampler(const struct wined3d_device *device, UINT idx);
+HRESULT __cdecl wined3d_device_get_raster_status(const struct wined3d_device *device,
+        UINT swapchain_idx, struct wined3d_raster_status *raster_status);
+DWORD __cdecl wined3d_device_get_render_state(const struct wined3d_device *device, enum wined3d_render_state state);
+struct wined3d_surface * __cdecl wined3d_device_get_render_target(const struct wined3d_device *device,
+        UINT render_target_idx);
+DWORD __cdecl wined3d_device_get_sampler_state(const struct wined3d_device *device,
+        UINT sampler_idx, enum wined3d_sampler_state state);
+void __cdecl wined3d_device_get_scissor_rect(const struct wined3d_device *device, RECT *rect);
+BOOL __cdecl wined3d_device_get_software_vertex_processing(const struct wined3d_device *device);
+struct wined3d_buffer * __cdecl wined3d_device_get_stream_output(struct wined3d_device *device,
+        UINT idx, UINT *offset);
+HRESULT __cdecl wined3d_device_get_stream_source(const struct wined3d_device *device,
+        UINT stream_idx, struct wined3d_buffer **buffer, UINT *offset, UINT *stride);
+HRESULT __cdecl wined3d_device_get_stream_source_freq(const struct wined3d_device *device,
+        UINT stream_idx, UINT *divider);
+struct wined3d_surface * __cdecl wined3d_device_get_surface_from_dc(const struct wined3d_device *device, HDC dc);
+struct wined3d_swapchain * __cdecl wined3d_device_get_swapchain(const struct wined3d_device *device,
+        UINT swapchain_idx);
+UINT __cdecl wined3d_device_get_swapchain_count(const struct wined3d_device *device);
+struct wined3d_texture * __cdecl wined3d_device_get_texture(const struct wined3d_device *device, UINT stage);
+DWORD __cdecl wined3d_device_get_texture_stage_state(const struct wined3d_device *device,
+        UINT stage, enum wined3d_texture_stage_state state);
+void __cdecl wined3d_device_get_transform(const struct wined3d_device *device,
+        enum wined3d_transform_state state, struct wined3d_matrix *matrix);
+struct wined3d_vertex_declaration * __cdecl wined3d_device_get_vertex_declaration(const struct wined3d_device *device);
+struct wined3d_shader * __cdecl wined3d_device_get_vertex_shader(const struct wined3d_device *device);
+void __cdecl wined3d_device_get_viewport(const struct wined3d_device *device, struct wined3d_viewport *viewport);
+struct wined3d_buffer * __cdecl wined3d_device_get_vs_cb(const struct wined3d_device *device, UINT idx);
+HRESULT __cdecl wined3d_device_get_vs_consts_b(const struct wined3d_device *device,
+        UINT start_register, BOOL *constants, UINT bool_count);
+HRESULT __cdecl wined3d_device_get_vs_consts_f(const struct wined3d_device *device,
+        UINT start_register, float *constants, UINT vector4f_count);
+HRESULT __cdecl wined3d_device_get_vs_consts_i(const struct wined3d_device *device,
+        UINT start_register, int *constants, UINT vector4i_count);
+struct wined3d_sampler * __cdecl wined3d_device_get_vs_sampler(const struct wined3d_device *device, UINT idx);
+ULONG __cdecl wined3d_device_incref(struct wined3d_device *device);
+HRESULT __cdecl wined3d_device_init_3d(struct wined3d_device *device, struct wined3d_swapchain_desc *swapchain_desc);
+HRESULT __cdecl wined3d_device_init_gdi(struct wined3d_device *device, struct wined3d_swapchain_desc *swapchain_desc);
+void __cdecl wined3d_device_multiply_transform(struct wined3d_device *device,
+        enum wined3d_transform_state state, const struct wined3d_matrix *matrix);
+HRESULT __cdecl wined3d_device_present(const struct wined3d_device *device, const RECT *src_rect,
+        const RECT *dst_rect, HWND dst_window_override, const RGNDATA *dirty_region, DWORD flags);
+HRESULT __cdecl wined3d_device_process_vertices(struct wined3d_device *device,
+        UINT src_start_idx, UINT dst_idx, UINT vertex_count, struct wined3d_buffer *dst_buffer,
+        const struct wined3d_vertex_declaration *declaration, DWORD flags, DWORD dst_fvf);
+void __cdecl wined3d_device_release_focus_window(struct wined3d_device *device);
+HRESULT __cdecl wined3d_device_reset(struct wined3d_device *device,
+        const struct wined3d_swapchain_desc *swapchain_desc, const struct wined3d_display_mode *mode,
+        wined3d_device_reset_cb callback, BOOL reset_state);
+void __cdecl wined3d_device_restore_fullscreen_window(struct wined3d_device *device, HWND window);
+void __cdecl wined3d_device_set_base_vertex_index(struct wined3d_device *device, INT base_index);
+HRESULT __cdecl wined3d_device_set_clip_plane(struct wined3d_device *device,
+        UINT plane_idx, const struct wined3d_vec4 *plane);
+HRESULT __cdecl wined3d_device_set_clip_status(struct wined3d_device *device,
+        const struct wined3d_clip_status *clip_status);
+void __cdecl wined3d_device_set_cursor_position(struct wined3d_device *device,
+        int x_screen_space, int y_screen_space, DWORD flags);
+HRESULT __cdecl wined3d_device_set_cursor_properties(struct wined3d_device *device,
+        UINT x_hotspot, UINT y_hotspot, struct wined3d_surface *cursor_surface);
+void __cdecl wined3d_device_set_depth_stencil(struct wined3d_device *device, struct wined3d_surface *depth_stencil);
+HRESULT __cdecl wined3d_device_set_dialog_box_mode(struct wined3d_device *device, BOOL enable_dialogs);
+void __cdecl wined3d_device_set_gamma_ramp(const struct wined3d_device *device,
+        UINT swapchain_idx, DWORD flags, const struct wined3d_gamma_ramp *ramp);
+void __cdecl wined3d_device_set_geometry_shader(struct wined3d_device *device, struct wined3d_shader *shader);
+void __cdecl wined3d_device_set_gs_cb(struct wined3d_device *device, UINT idx, struct wined3d_buffer *buffer);
+void __cdecl wined3d_device_set_gs_sampler(struct wined3d_device *device, UINT idx, struct wined3d_sampler *sampler);
+void __cdecl wined3d_device_set_index_buffer(struct wined3d_device *device,
+        struct wined3d_buffer *index_buffer, enum wined3d_format_id format_id);
+HRESULT __cdecl wined3d_device_set_light(struct wined3d_device *device,
+        UINT light_idx, const struct wined3d_light *light);
+HRESULT __cdecl wined3d_device_set_light_enable(struct wined3d_device *device, UINT light_idx, BOOL enable);
+void __cdecl wined3d_device_set_material(struct wined3d_device *device, const struct wined3d_material *material);
+void __cdecl wined3d_device_set_multithreaded(struct wined3d_device *device);
+HRESULT __cdecl wined3d_device_set_npatch_mode(struct wined3d_device *device, float segments);
+void __cdecl wined3d_device_set_pixel_shader(struct wined3d_device *device, struct wined3d_shader *shader);
+void __cdecl wined3d_device_set_primitive_type(struct wined3d_device *device,
+        enum wined3d_primitive_type primitive_topology);
+void __cdecl wined3d_device_set_ps_cb(struct wined3d_device *device, UINT idx, struct wined3d_buffer *buffer);
+HRESULT __cdecl wined3d_device_set_ps_consts_b(struct wined3d_device *device,
+        UINT start_register, const BOOL *constants, UINT bool_count);
+HRESULT __cdecl wined3d_device_set_ps_consts_f(struct wined3d_device *device,
+        UINT start_register, const float *constants, UINT vector4f_count);
+HRESULT __cdecl wined3d_device_set_ps_consts_i(struct wined3d_device *device,
+        UINT start_register, const int *constants, UINT vector4i_count);
+void __cdecl wined3d_device_set_ps_sampler(struct wined3d_device *device, UINT idx, struct wined3d_sampler *sampler);
+void __cdecl wined3d_device_set_render_state(struct wined3d_device *device,
+        enum wined3d_render_state state, DWORD value);
+HRESULT __cdecl wined3d_device_set_render_target(struct wined3d_device *device,
+        UINT render_target_idx, struct wined3d_surface *render_target, BOOL set_viewport);
+void __cdecl wined3d_device_set_sampler_state(struct wined3d_device *device,
+        UINT sampler_idx, enum wined3d_sampler_state state, DWORD value);
+void __cdecl wined3d_device_set_scissor_rect(struct wined3d_device *device, const RECT *rect);
+void __cdecl wined3d_device_set_software_vertex_processing(struct wined3d_device *device, BOOL software);
+void __cdecl wined3d_device_set_stream_output(struct wined3d_device *device, UINT idx,
+        struct wined3d_buffer *buffer, UINT offset);
+HRESULT __cdecl wined3d_device_set_stream_source(struct wined3d_device *device,
+        UINT stream_idx, struct wined3d_buffer *buffer, UINT offset, UINT stride);
+HRESULT __cdecl wined3d_device_set_stream_source_freq(struct wined3d_device *device, UINT stream_idx, UINT divider);
+HRESULT __cdecl wined3d_device_set_texture(struct wined3d_device *device, UINT stage, struct wined3d_texture *texture);
+void __cdecl wined3d_device_set_texture_stage_state(struct wined3d_device *device,
+        UINT stage, enum wined3d_texture_stage_state state, DWORD value);
+void __cdecl wined3d_device_set_transform(struct wined3d_device *device,
+        enum wined3d_transform_state state, const struct wined3d_matrix *matrix);
+void __cdecl wined3d_device_set_vertex_declaration(struct wined3d_device *device,
+        struct wined3d_vertex_declaration *declaration);
+void __cdecl wined3d_device_set_vertex_shader(struct wined3d_device *device, struct wined3d_shader *shader);
+void __cdecl wined3d_device_set_viewport(struct wined3d_device *device, const struct wined3d_viewport *viewport);
+void __cdecl wined3d_device_set_vs_cb(struct wined3d_device *device, UINT idx, struct wined3d_buffer *buffer);
+HRESULT __cdecl wined3d_device_set_vs_consts_b(struct wined3d_device *device,
+        UINT start_register, const BOOL *constants, UINT bool_count);
+HRESULT __cdecl wined3d_device_set_vs_consts_f(struct wined3d_device *device,
+        UINT start_register, const float *constants, UINT vector4f_count);
+HRESULT __cdecl wined3d_device_set_vs_consts_i(struct wined3d_device *device,
+        UINT start_register, const int *constants, UINT vector4i_count);
+void __cdecl wined3d_device_set_vs_sampler(struct wined3d_device *device, UINT idx, struct wined3d_sampler *sampler);
+void __cdecl wined3d_device_setup_fullscreen_window(struct wined3d_device *device, HWND window, UINT w, UINT h);
+BOOL __cdecl wined3d_device_show_cursor(struct wined3d_device *device, BOOL show);
+HRESULT __cdecl wined3d_device_uninit_3d(struct wined3d_device *device);
+HRESULT __cdecl wined3d_device_uninit_gdi(struct wined3d_device *device);
+HRESULT __cdecl wined3d_device_update_surface(struct wined3d_device *device, struct wined3d_surface *src_surface,
+        const RECT *src_rect, struct wined3d_surface *dst_surface, const POINT *dst_point);
+HRESULT __cdecl wined3d_device_update_texture(struct wined3d_device *device,
+        struct wined3d_texture *src_texture, struct wined3d_texture *dst_texture);
+HRESULT __cdecl wined3d_device_validate_device(const struct wined3d_device *device, DWORD *num_passes);
+
+HRESULT __cdecl wined3d_palette_create(struct wined3d_device *device, DWORD flags,
+        const PALETTEENTRY *entries, void *parent, struct wined3d_palette **palette);
+ULONG __cdecl wined3d_palette_decref(struct wined3d_palette *palette);
+HRESULT __cdecl wined3d_palette_get_entries(const struct wined3d_palette *palette,
+        DWORD flags, DWORD start, DWORD count, PALETTEENTRY *entries);
+DWORD __cdecl wined3d_palette_get_flags(const struct wined3d_palette *palette);
+void * __cdecl wined3d_palette_get_parent(const struct wined3d_palette *palette);
+ULONG __cdecl wined3d_palette_incref(struct wined3d_palette *palette);
+HRESULT __cdecl wined3d_palette_set_entries(struct wined3d_palette *palette,
+        DWORD flags, DWORD start, DWORD count, const PALETTEENTRY *entries);
+
+HRESULT __cdecl wined3d_query_create(struct wined3d_device *device,
+        enum wined3d_query_type type, struct wined3d_query **query);
+ULONG __cdecl wined3d_query_decref(struct wined3d_query *query);
+HRESULT __cdecl wined3d_query_get_data(struct wined3d_query *query, void *data, UINT data_size, DWORD flags);
+UINT __cdecl wined3d_query_get_data_size(const struct wined3d_query *query);
+enum wined3d_query_type __cdecl wined3d_query_get_type(const struct wined3d_query *query);
+ULONG __cdecl wined3d_query_incref(struct wined3d_query *query);
+HRESULT __cdecl wined3d_query_issue(struct wined3d_query *query, DWORD flags);
+
+HRESULT __cdecl wined3d_resource_free_private_data(struct wined3d_resource *resource, REFGUID guid);
+void __cdecl wined3d_resource_get_desc(const struct wined3d_resource *resource,
+        struct wined3d_resource_desc *desc);
+void * __cdecl wined3d_resource_get_parent(const struct wined3d_resource *resource);
+HRESULT __cdecl wined3d_resource_get_private_data(const struct wined3d_resource *resource,
+        REFGUID guid, void *data, DWORD *data_size);
+HRESULT __cdecl wined3d_resource_set_private_data(struct wined3d_resource *resource,
+        REFGUID guid, const void *data, DWORD data_size, DWORD flags);
+
+HRESULT __cdecl wined3d_rendertarget_view_create(struct wined3d_resource *resource,
+        void *parent, struct wined3d_rendertarget_view **rendertarget_view);
+ULONG __cdecl wined3d_rendertarget_view_decref(struct wined3d_rendertarget_view *view);
+void * __cdecl wined3d_rendertarget_view_get_parent(const struct wined3d_rendertarget_view *view);
+struct wined3d_resource * __cdecl wined3d_rendertarget_view_get_resource(const struct wined3d_rendertarget_view *view);
+ULONG __cdecl wined3d_rendertarget_view_incref(struct wined3d_rendertarget_view *view);
+
+HRESULT __cdecl wined3d_sampler_create(void *parent, struct wined3d_sampler **sampler);
+ULONG __cdecl wined3d_sampler_decref(struct wined3d_sampler *sampler);
+void * __cdecl wined3d_sampler_get_parent(const struct wined3d_sampler *sampler);
+ULONG __cdecl wined3d_sampler_incref(struct wined3d_sampler *sampler);
+
+HRESULT __cdecl wined3d_shader_create_gs(struct wined3d_device *device, const DWORD *byte_code,
+        const struct wined3d_shader_signature *output_signature, void *parent,
+        const struct wined3d_parent_ops *parent_ops, struct wined3d_shader **shader, unsigned int max_version);
+HRESULT __cdecl wined3d_shader_create_ps(struct wined3d_device *device, const DWORD *byte_code,
+        const struct wined3d_shader_signature *output_signature, void *parent,
+        const struct wined3d_parent_ops *parent_ops, struct wined3d_shader **shader, unsigned int max_version);
+HRESULT __cdecl wined3d_shader_create_vs(struct wined3d_device *device, const DWORD *byte_code,
+        const struct wined3d_shader_signature *output_signature, void *parent,
+        const struct wined3d_parent_ops *parent_ops, struct wined3d_shader **shader, unsigned int max_version);
+ULONG __cdecl wined3d_shader_decref(struct wined3d_shader *shader);
+HRESULT __cdecl wined3d_shader_get_byte_code(const struct wined3d_shader *shader,
+        void *byte_code, UINT *byte_code_size);
+void * __cdecl wined3d_shader_get_parent(const struct wined3d_shader *shader);
+ULONG __cdecl wined3d_shader_incref(struct wined3d_shader *shader);
+HRESULT __cdecl wined3d_shader_set_local_constants_float(struct wined3d_shader *shader,
+        UINT start_idx, const float *src_data, UINT vector4f_count);
+
+void __cdecl wined3d_stateblock_apply(const struct wined3d_stateblock *stateblock);
+void __cdecl wined3d_stateblock_capture(struct wined3d_stateblock *stateblock);
+HRESULT __cdecl wined3d_stateblock_create(struct wined3d_device *device,
+        enum wined3d_stateblock_type type, struct wined3d_stateblock **stateblock);
+ULONG __cdecl wined3d_stateblock_decref(struct wined3d_stateblock *stateblock);
+ULONG __cdecl wined3d_stateblock_incref(struct wined3d_stateblock *stateblock);
+
+HRESULT __cdecl wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst_rect,
+        struct wined3d_surface *src_surface, const RECT *src_rect, DWORD flags,
+        const WINEDDBLTFX *blt_fx, enum wined3d_texture_filter_type filter);
+HRESULT __cdecl wined3d_surface_create(struct wined3d_device *device, UINT width, UINT height,
+        enum wined3d_format_id format_id, DWORD usage, enum wined3d_pool pool,
+        enum wined3d_multisample_type multisample_type, DWORD multisample_quality, DWORD flags,
+        void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_surface **surface
+#ifdef VBOX_WITH_WDDM
+        , HANDLE *shared_handle
+        , void *pvClientMem
+#endif
+        );
+ULONG __cdecl wined3d_surface_decref(struct wined3d_surface *surface);
+HRESULT __cdecl wined3d_surface_flip(struct wined3d_surface *surface, struct wined3d_surface *override, DWORD flags);
+struct wined3d_surface * __cdecl wined3d_surface_from_resource(struct wined3d_resource *resource);
+HRESULT __cdecl wined3d_surface_get_blt_status(const struct wined3d_surface *surface, DWORD flags);
+HRESULT __cdecl wined3d_surface_get_flip_status(const struct wined3d_surface *surface, DWORD flags);
+HRESULT __cdecl wined3d_surface_get_overlay_position(const struct wined3d_surface *surface, LONG *x, LONG *y);
+struct wined3d_palette * __cdecl wined3d_surface_get_palette(const struct wined3d_surface *surface);
+void * __cdecl wined3d_surface_get_parent(const struct wined3d_surface *surface);
+DWORD __cdecl wined3d_surface_get_pitch(const struct wined3d_surface *surface);
+DWORD __cdecl wined3d_surface_get_priority(const struct wined3d_surface *surface);
+HRESULT __cdecl wined3d_surface_get_render_target_data(struct wined3d_surface *surface,
+        struct wined3d_surface *render_target);
+struct wined3d_resource * __cdecl wined3d_surface_get_resource(struct wined3d_surface *surface);
+HRESULT __cdecl wined3d_surface_getdc(struct wined3d_surface *surface, HDC *dc);
+ULONG __cdecl wined3d_surface_incref(struct wined3d_surface *surface);
+HRESULT __cdecl wined3d_surface_is_lost(const struct wined3d_surface *surface);
+HRESULT __cdecl wined3d_surface_map(struct wined3d_surface *surface,
+        struct wined3d_map_desc *map_desc, const RECT *rect, DWORD flags);
+void __cdecl wined3d_surface_preload(struct wined3d_surface *surface);
+HRESULT __cdecl wined3d_surface_releasedc(struct wined3d_surface *surface, HDC dc);
+HRESULT __cdecl wined3d_surface_restore(struct wined3d_surface *surface);
+HRESULT __cdecl wined3d_surface_set_color_key(struct wined3d_surface *surface,
+        DWORD flags, const struct wined3d_color_key *color_key);
+HRESULT __cdecl wined3d_surface_set_mem(struct wined3d_surface *surface, void *mem);
+HRESULT __cdecl wined3d_surface_set_overlay_position(struct wined3d_surface *surface, LONG x, LONG y);
+void __cdecl wined3d_surface_set_palette(struct wined3d_surface *surface, struct wined3d_palette *palette);
+DWORD __cdecl wined3d_surface_set_priority(struct wined3d_surface *surface, DWORD new_priority);
+HRESULT __cdecl wined3d_surface_unmap(struct wined3d_surface *surface);
+HRESULT __cdecl wined3d_surface_update_desc(struct wined3d_surface *surface,
+        UINT width, UINT height, enum wined3d_format_id format_id,
+        enum wined3d_multisample_type multisample_type, UINT multisample_quality);
+HRESULT __cdecl wined3d_surface_update_overlay(struct wined3d_surface *surface, const RECT *src_rect,
+        struct wined3d_surface *dst_surface, const RECT *dst_rect, DWORD flags, const WINEDDOVERLAYFX *fx);
+HRESULT __cdecl wined3d_surface_update_overlay_z_order(struct wined3d_surface *surface,
+        DWORD flags, struct wined3d_surface *ref);
+
+HRESULT __cdecl wined3d_swapchain_create(struct wined3d_device *device, struct wined3d_swapchain_desc *desc,
+        void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_swapchain **swapchain);
+ULONG __cdecl wined3d_swapchain_decref(struct wined3d_swapchain *swapchain);
+struct wined3d_surface * __cdecl wined3d_swapchain_get_back_buffer(const struct wined3d_swapchain *swapchain,
+        UINT backbuffer_idx, enum wined3d_backbuffer_type backbuffer_type);
+struct wined3d_device * __cdecl wined3d_swapchain_get_device(const struct wined3d_swapchain *swapchain);
+HRESULT __cdecl wined3d_swapchain_get_display_mode(const struct wined3d_swapchain *swapchain,
+        struct wined3d_display_mode *mode, enum wined3d_display_rotation *rotation);
+HRESULT __cdecl wined3d_swapchain_get_front_buffer_data(const struct wined3d_swapchain *swapchain,
+        struct wined3d_surface *dst_surface);
+HRESULT __cdecl wined3d_swapchain_get_gamma_ramp(const struct wined3d_swapchain *swapchain,
+        struct wined3d_gamma_ramp *ramp);
+void * __cdecl wined3d_swapchain_get_parent(const struct wined3d_swapchain *swapchain);
+void __cdecl wined3d_swapchain_get_desc(const struct wined3d_swapchain *swapchain,
+        struct wined3d_swapchain_desc *desc);
+HRESULT __cdecl wined3d_swapchain_get_raster_status(const struct wined3d_swapchain *swapchain,
+        struct wined3d_raster_status *raster_status);
+ULONG __cdecl wined3d_swapchain_incref(struct wined3d_swapchain *swapchain);
+HRESULT __cdecl wined3d_swapchain_present(struct wined3d_swapchain *swapchain,
+        const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override,
+        const RGNDATA *dirty_region, DWORD flags);
+HRESULT __cdecl wined3d_swapchain_set_gamma_ramp(const struct wined3d_swapchain *swapchain,
+        DWORD flags, const struct wined3d_gamma_ramp *ramp);
+void __cdecl wined3d_swapchain_set_window(struct wined3d_swapchain *swapchain, HWND window);
+
+HRESULT __cdecl wined3d_texture_add_dirty_region(struct wined3d_texture *texture,
+        UINT layer, const struct wined3d_box *dirty_region);
+HRESULT __cdecl wined3d_texture_create_2d(struct wined3d_device *device, const struct wined3d_resource_desc *desc,
+        UINT level_count, DWORD surface_flags, void *parent, const struct wined3d_parent_ops *parent_ops,
+        struct wined3d_texture **texture
+#ifdef VBOX_WITH_WDDM
+        , HANDLE *shared_handle
+        , void **pavClientMem
+#endif
+        );
+HRESULT __cdecl wined3d_texture_create_3d(struct wined3d_device *device, const struct wined3d_resource_desc *desc,
+        UINT level_count, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture
+#ifdef VBOX_WITH_WDDM
+        , HANDLE *shared_handle
+        , void **pavClientMem
+#endif
+        );
+HRESULT __cdecl wined3d_texture_create_cube(struct wined3d_device *device, const struct wined3d_resource_desc *desc,
+        UINT level_count, DWORD surface_flags, void *parent, const struct wined3d_parent_ops *parent_ops,
+        struct wined3d_texture **texture
+#ifdef VBOX_WITH_WDDM
+        , HANDLE *shared_handle
+        , void **pavClientMem
+#endif
+        );
+ULONG __cdecl wined3d_texture_decref(struct wined3d_texture *texture);
+void __cdecl wined3d_texture_generate_mipmaps(struct wined3d_texture *texture);
+enum wined3d_texture_filter_type __cdecl wined3d_texture_get_autogen_filter_type(const struct wined3d_texture *texture);
+DWORD __cdecl wined3d_texture_get_level_count(const struct wined3d_texture *texture);
+DWORD __cdecl wined3d_texture_get_lod(const struct wined3d_texture *texture);
+void * __cdecl wined3d_texture_get_parent(const struct wined3d_texture *texture);
+DWORD __cdecl wined3d_texture_get_priority(const struct wined3d_texture *texture);
+struct wined3d_resource * __cdecl wined3d_texture_get_resource(struct wined3d_texture *texture);
+struct wined3d_resource * __cdecl wined3d_texture_get_sub_resource(struct wined3d_texture *texture,
+        UINT sub_resource_idx);
+ULONG __cdecl wined3d_texture_incref(struct wined3d_texture *texture);
+void __cdecl wined3d_texture_preload(struct wined3d_texture *texture);
+HRESULT __cdecl wined3d_texture_set_autogen_filter_type(struct wined3d_texture *texture,
+        enum wined3d_texture_filter_type filter_type);
+DWORD __cdecl wined3d_texture_set_lod(struct wined3d_texture *texture, DWORD lod);
+DWORD __cdecl wined3d_texture_set_priority(struct wined3d_texture *texture, DWORD priority);
+
+HRESULT __cdecl wined3d_vertex_declaration_create(struct wined3d_device *device,
+        const struct wined3d_vertex_element *elements, UINT element_count, void *parent,
+        const struct wined3d_parent_ops *parent_ops, struct wined3d_vertex_declaration **declaration);
+HRESULT __cdecl wined3d_vertex_declaration_create_from_fvf(struct wined3d_device *device,
+        DWORD fvf, void *parent, const struct wined3d_parent_ops *parent_ops,
+        struct wined3d_vertex_declaration **declaration);
+ULONG __cdecl wined3d_vertex_declaration_decref(struct wined3d_vertex_declaration *declaration);
+void * __cdecl wined3d_vertex_declaration_get_parent(const struct wined3d_vertex_declaration *declaration);
+ULONG __cdecl wined3d_vertex_declaration_incref(struct wined3d_vertex_declaration *declaration);
+
+HRESULT __cdecl wined3d_volume_create(struct wined3d_device *device, UINT width, UINT height, UINT depth,
+        DWORD usage, enum wined3d_format_id format_id, enum wined3d_pool pool, void *parent,
+        const struct wined3d_parent_ops *parent_ops, struct wined3d_volume **volume
+#ifdef VBOX_WITH_WDDM
+        , HANDLE *shared_handle
+        , void *pvClientMem
+#endif
+        );
+ULONG __cdecl wined3d_volume_decref(struct wined3d_volume *volume);
+struct wined3d_volume * __cdecl wined3d_volume_from_resource(struct wined3d_resource *resource);
+void * __cdecl wined3d_volume_get_parent(const struct wined3d_volume *volume);
+DWORD __cdecl wined3d_volume_get_priority(const struct wined3d_volume *volume);
+struct wined3d_resource * __cdecl wined3d_volume_get_resource(struct wined3d_volume *volume);
+ULONG __cdecl wined3d_volume_incref(struct wined3d_volume *volume);
+HRESULT __cdecl wined3d_volume_map(struct wined3d_volume *volume,
+        struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags);
+void __cdecl wined3d_volume_preload(struct wined3d_volume *volume);
+DWORD __cdecl wined3d_volume_set_priority(struct wined3d_volume *volume, DWORD new_priority);
+HRESULT __cdecl wined3d_volume_unmap(struct wined3d_volume *volume);
+
+#ifdef VBOX_WITH_WDDM
+HRESULT __cdecl wined3d_device_flush(struct wined3d_device *device);
+HRESULT __cdecl wined3d_device_flush_to_host(struct wined3d_device *device);
+HRESULT __cdecl wined3d_device_finish(struct wined3d_device *device);
+HRESULT __cdecl wined3d_device_blt_vol(struct wined3d_device *device, struct wined3d_volume *src, struct wined3d_volume *dst, const struct wined3d_box *pSrcBoxArg, const struct VBOXPOINT3D *pDstPoin3D);
+HRESULT __cdecl wined3d_device_blt_voltex(struct wined3d_device *device, struct wined3d_texture *src, struct wined3d_texture *dst, const struct wined3d_box *pSrcBoxArg, const struct VBOXPOINT3D *pDstPoin3D);
+
+HRESULT __cdecl wined3d_swapchain_present_rt(struct wined3d_swapchain *swapchain, struct wined3d_surface *rt);
+
+#endif
+
+#endif /* __WINE_WINED3D_H */
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/arb_program_shader.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/arb_program_shader.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/arb_program_shader.c	(revision 46521)
@@ -0,0 +1,7469 @@
+/*
+ * Pixel and vertex shaders implementation using ARB_vertex_program
+ * and ARB_fragment_program GL extensions.
+ *
+ * Copyright 2002-2003 Jason Edmeades
+ * Copyright 2002-2003 Raphael Junqueira
+ * Copyright 2004 Christian Costa
+ * Copyright 2005 Oliver Stieber
+ * Copyright 2006 Ivan Gyurdiev
+ * Copyright 2006 Jason Green
+ * Copyright 2006 Henri Verbeet
+ * Copyright 2007-2011, 2013 Stefan Dösinger for CodeWeavers
+ * Copyright 2009 Henri Verbeet for CodeWeavers
+ *
+ * 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 <math.h>
+#include <stdio.h>
+
+#include "wined3d_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
+WINE_DECLARE_DEBUG_CHANNEL(d3d_constants);
+WINE_DECLARE_DEBUG_CHANNEL(d3d);
+
+static BOOL shader_is_pshader_version(enum wined3d_shader_type type)
+{
+    return type == WINED3D_SHADER_TYPE_PIXEL;
+}
+
+static BOOL shader_is_vshader_version(enum wined3d_shader_type type)
+{
+    return type == WINED3D_SHADER_TYPE_VERTEX;
+}
+
+/* Extract a line. Note that this modifies the source string. */
+static char *get_line(char **ptr)
+{
+    char *p, *q;
+
+    p = *ptr;
+    if (!(q = strstr(p, "\n")))
+    {
+        if (!*p) return NULL;
+        *ptr += strlen(p);
+        return p;
+    }
+    *q = '\0';
+    *ptr = q + 1;
+
+    return p;
+}
+
+static void shader_arb_dump_program_source(const char *source)
+{
+    ULONG source_size;
+    char *ptr, *line, *tmp;
+
+    source_size = strlen(source) + 1;
+    tmp = HeapAlloc(GetProcessHeap(), 0, source_size);
+    if (!tmp)
+    {
+        ERR("Failed to allocate %u bytes for shader source.\n", source_size);
+        return;
+    }
+    memcpy(tmp, source, source_size);
+
+    ptr = tmp;
+    while ((line = get_line(&ptr))) FIXME("    %s\n", line);
+    FIXME("\n");
+
+    HeapFree(GetProcessHeap(), 0, tmp);
+}
+
+enum arb_helper_value
+{
+    ARB_ZERO,
+    ARB_ONE,
+    ARB_TWO,
+    ARB_0001,
+    ARB_EPS,
+
+    ARB_VS_REL_OFFSET
+};
+
+static const char *arb_get_helper_value(enum wined3d_shader_type shader, enum arb_helper_value value)
+{
+    if (shader == WINED3D_SHADER_TYPE_GEOMETRY)
+    {
+        ERR("Geometry shaders are unsupported\n");
+        return "bad";
+    }
+
+    if (shader == WINED3D_SHADER_TYPE_PIXEL)
+    {
+        switch (value)
+        {
+            case ARB_ZERO: return "ps_helper_const.x";
+            case ARB_ONE: return "ps_helper_const.y";
+            case ARB_TWO: return "coefmul.x";
+            case ARB_0001: return "ps_helper_const.xxxy";
+            case ARB_EPS: return "ps_helper_const.z";
+            default: break;
+        }
+    }
+    else
+    {
+        switch (value)
+        {
+            case ARB_ZERO: return "helper_const.x";
+            case ARB_ONE: return "helper_const.y";
+            case ARB_TWO: return "helper_const.z";
+            case ARB_EPS: return "helper_const.w";
+            case ARB_0001: return "helper_const.xxxy";
+            case ARB_VS_REL_OFFSET: return "rel_addr_const.y";
+        }
+    }
+    FIXME("Unmanaged %s shader helper constant requested: %u\n",
+          shader == WINED3D_SHADER_TYPE_PIXEL ? "pixel" : "vertex", value);
+    switch (value)
+    {
+        case ARB_ZERO: return "0.0";
+        case ARB_ONE: return "1.0";
+        case ARB_TWO: return "2.0";
+        case ARB_0001: return "{0.0, 0.0, 0.0, 1.0}";
+        case ARB_EPS: return "1e-8";
+        default: return "bad";
+    }
+}
+
+static inline BOOL ffp_clip_emul(const struct wined3d_state *state)
+{
+    return state->lowest_disabled_stage < 7;
+}
+
+/* ARB_program_shader private data */
+
+struct control_frame
+{
+    struct                          list entry;
+    enum
+    {
+        IF,
+        IFC,
+        LOOP,
+        REP
+    } type;
+    BOOL                            muting;
+    BOOL                            outer_loop;
+    union
+    {
+        unsigned int                loop;
+        unsigned int                ifc;
+    } no;
+    struct wined3d_shader_loop_control loop_control;
+    BOOL                            had_else;
+};
+
+struct arb_ps_np2fixup_info
+{
+    struct ps_np2fixup_info         super;
+    /* For ARB we need a offset value:
+     * With both GLSL and ARB mode the NP2 fixup information (the texture dimensions) are stored in a
+     * consecutive way (GLSL uses a uniform array). Since ARB doesn't know the notion of a "standalone"
+     * array we need an offset to the index inside the program local parameter array. */
+    UINT                            offset;
+};
+
+struct arb_ps_compile_args
+{
+    struct ps_compile_args          super;
+    WORD                            bools;
+    WORD                            clip;  /* only a boolean, use a WORD for alignment */
+    unsigned char                   loop_ctrl[MAX_CONST_I][3];
+};
+
+struct stb_const_desc
+{
+    unsigned char           texunit;
+    UINT                    const_num;
+};
+
+struct arb_ps_compiled_shader
+{
+    struct arb_ps_compile_args      args;
+    struct arb_ps_np2fixup_info     np2fixup_info;
+    struct stb_const_desc           bumpenvmatconst[MAX_TEXTURES];
+    struct stb_const_desc           luminanceconst[MAX_TEXTURES];
+    UINT                            int_consts[MAX_CONST_I];
+    GLuint                          prgId;
+    UINT                            ycorrection;
+    unsigned char                   numbumpenvmatconsts;
+    char                            num_int_consts;
+};
+
+struct arb_vs_compile_args
+{
+    struct vs_compile_args          super;
+    union
+    {
+        struct
+        {
+            WORD                    bools;
+            unsigned char           clip_texcoord;
+            unsigned char           clipplane_mask;
+        }                           boolclip;
+        DWORD                       boolclip_compare;
+    } clip;
+    DWORD                           ps_signature;
+    union
+    {
+        unsigned char               samplers[4];
+        DWORD                       samplers_compare;
+    } vertex;
+    unsigned char                   loop_ctrl[MAX_CONST_I][3];
+};
+
+struct arb_vs_compiled_shader
+{
+    struct arb_vs_compile_args      args;
+    GLuint                          prgId;
+    UINT                            int_consts[MAX_CONST_I];
+    char                            num_int_consts;
+    char                            need_color_unclamp;
+    UINT                            pos_fixup;
+};
+
+struct recorded_instruction
+{
+    struct wined3d_shader_instruction ins;
+    struct list entry;
+};
+
+struct shader_arb_ctx_priv
+{
+    char addr_reg[20];
+    enum
+    {
+        /* plain GL_ARB_vertex_program or GL_ARB_fragment_program */
+        ARB,
+        /* GL_NV_vertex_progam2_option or GL_NV_fragment_program_option */
+        NV2,
+        /* GL_NV_vertex_program3 or GL_NV_fragment_program2 */
+        NV3
+    } target_version;
+
+    const struct arb_vs_compile_args    *cur_vs_args;
+    const struct arb_ps_compile_args    *cur_ps_args;
+    const struct arb_ps_compiled_shader *compiled_fprog;
+    const struct arb_vs_compiled_shader *compiled_vprog;
+    struct arb_ps_np2fixup_info         *cur_np2fixup_info;
+    struct list                         control_frames;
+    struct list                         record;
+    BOOL                                recording;
+    BOOL                                muted;
+    unsigned int                        num_loops, loop_depth, num_ifcs;
+    int                                 aL;
+
+    unsigned int                        vs_clipplanes;
+    BOOL                                footer_written;
+    BOOL                                in_main_func;
+
+    /* For 3.0 vertex shaders */
+    const char                          *vs_output[MAX_REG_OUTPUT];
+    /* For 2.x and earlier vertex shaders */
+    const char                          *texcrd_output[8], *color_output[2], *fog_output;
+
+    /* 3.0 pshader input for compatibility with fixed function */
+    const char                          *ps_input[MAX_REG_INPUT];
+};
+
+struct ps_signature
+{
+    struct wined3d_shader_signature_element *sig;
+    DWORD                               idx;
+    struct wine_rb_entry                entry;
+};
+
+struct arb_pshader_private {
+    struct arb_ps_compiled_shader   *gl_shaders;
+    UINT                            num_gl_shaders, shader_array_size;
+    DWORD                           input_signature_idx;
+    DWORD                           clipplane_emulation;
+    BOOL                            clamp_consts;
+};
+
+struct arb_vshader_private {
+    struct arb_vs_compiled_shader   *gl_shaders;
+    UINT                            num_gl_shaders, shader_array_size;
+    UINT rel_offset;
+};
+
+struct shader_arb_priv
+{
+    GLuint                  current_vprogram_id;
+    GLuint                  current_fprogram_id;
+    const struct arb_ps_compiled_shader *compiled_fprog;
+    const struct arb_vs_compiled_shader *compiled_vprog;
+    GLuint                  depth_blt_vprogram_id;
+    GLuint                  depth_blt_fprogram_id_full[tex_type_count];
+    GLuint                  depth_blt_fprogram_id_masked[tex_type_count];
+    BOOL                    use_arbfp_fixed_func;
+    struct wine_rb_tree     fragment_shaders;
+    BOOL                    last_ps_const_clamped;
+    BOOL                    last_vs_color_unclamp;
+
+    struct wine_rb_tree     signature_tree;
+    DWORD ps_sig_number;
+
+    unsigned int highest_dirty_ps_const, highest_dirty_vs_const;
+    char *vshader_const_dirty, *pshader_const_dirty;
+    const struct wined3d_context *last_context;
+
+    const struct wined3d_vertex_pipe_ops *vertex_pipe;
+    const struct fragment_pipeline *fragment_pipe;
+    BOOL ffp_proj_control;
+};
+
+/* Context activation for state handlers is done by the caller. */
+
+static BOOL need_rel_addr_const(const struct arb_vshader_private *shader_data,
+        const struct wined3d_shader_reg_maps *reg_maps, const struct wined3d_gl_info *gl_info)
+{
+    if (shader_data->rel_offset) return TRUE;
+    if (!reg_maps->usesmova) return FALSE;
+    return !gl_info->supported[NV_VERTEX_PROGRAM2_OPTION];
+}
+
+/* Returns TRUE if result.clip from GL_NV_vertex_program2 should be used and FALSE otherwise */
+static inline BOOL use_nv_clip(const struct wined3d_gl_info *gl_info)
+{
+    return gl_info->supported[NV_VERTEX_PROGRAM2_OPTION]
+            && !(gl_info->quirks & WINED3D_QUIRK_NV_CLIP_BROKEN);
+}
+
+static BOOL need_helper_const(const struct arb_vshader_private *shader_data,
+        const struct wined3d_shader_reg_maps *reg_maps, const struct wined3d_gl_info *gl_info)
+{
+    if (need_rel_addr_const(shader_data, reg_maps, gl_info)) return TRUE;
+    if (!gl_info->supported[NV_VERTEX_PROGRAM]) return TRUE; /* Need to init colors. */
+    if (gl_info->quirks & WINED3D_QUIRK_ARB_VS_OFFSET_LIMIT) return TRUE; /* Load the immval offset. */
+    if (gl_info->quirks & WINED3D_QUIRK_SET_TEXCOORD_W) return TRUE; /* Have to init texcoords. */
+    if (!use_nv_clip(gl_info)) return TRUE; /* Init the clip texcoord */
+    if (reg_maps->usesnrm) return TRUE; /* 0.0 */
+    if (reg_maps->usespow) return TRUE; /* EPS, 0.0 and 1.0 */
+    if (reg_maps->fog) return TRUE; /* Clamping fog coord, 0.0 and 1.0 */
+    return FALSE;
+}
+
+static unsigned int reserved_vs_const(const struct arb_vshader_private *shader_data,
+        const struct wined3d_shader_reg_maps *reg_maps, const struct wined3d_gl_info *gl_info)
+{
+    unsigned int ret = 1;
+    /* We use one PARAM for the pos fixup, and in some cases one to load
+     * some immediate values into the shader. */
+    if (need_helper_const(shader_data, reg_maps, gl_info)) ++ret;
+    if (need_rel_addr_const(shader_data, reg_maps, gl_info)) ++ret;
+    return ret;
+}
+
+/* Loads floating point constants into the currently set ARB_vertex/fragment_program.
+ * When constant_list == NULL, it will load all the constants.
+ *
+ * @target_type should be either GL_VERTEX_PROGRAM_ARB (for vertex shaders)
+ *  or GL_FRAGMENT_PROGRAM_ARB (for pixel shaders)
+ */
+/* Context activation is done by the caller. */
+static unsigned int shader_arb_load_constantsF(const struct wined3d_shader *shader,
+        const struct wined3d_gl_info *gl_info, GLuint target_type, unsigned int max_constants,
+        const float *constants, char *dirty_consts)
+{
+    struct wined3d_shader_lconst *lconst;
+    DWORD i, j;
+    unsigned int ret;
+
+    if (TRACE_ON(d3d_constants))
+    {
+        for(i = 0; i < max_constants; i++) {
+            if(!dirty_consts[i]) continue;
+            TRACE_(d3d_constants)("Loading constants %i: %f, %f, %f, %f\n", i,
+                        constants[i * 4 + 0], constants[i * 4 + 1],
+                        constants[i * 4 + 2], constants[i * 4 + 3]);
+        }
+    }
+
+    i = 0;
+
+    /* In 1.X pixel shaders constants are implicitly clamped in the range [-1;1] */
+    if (target_type == GL_FRAGMENT_PROGRAM_ARB && shader->reg_maps.shader_version.major == 1)
+    {
+        float lcl_const[4];
+        /* ps 1.x supports only 8 constants, clamp only those. When switching between 1.x and higher
+         * shaders, the first 8 constants are marked dirty for reload
+         */
+        for(; i < min(8, max_constants); i++) {
+            if(!dirty_consts[i]) continue;
+            dirty_consts[i] = 0;
+
+            j = 4 * i;
+            if (constants[j + 0] > 1.0f) lcl_const[0] = 1.0f;
+            else if (constants[j + 0] < -1.0f) lcl_const[0] = -1.0f;
+            else lcl_const[0] = constants[j + 0];
+
+            if (constants[j + 1] > 1.0f) lcl_const[1] = 1.0f;
+            else if (constants[j + 1] < -1.0f) lcl_const[1] = -1.0f;
+            else lcl_const[1] = constants[j + 1];
+
+            if (constants[j + 2] > 1.0f) lcl_const[2] = 1.0f;
+            else if (constants[j + 2] < -1.0f) lcl_const[2] = -1.0f;
+            else lcl_const[2] = constants[j + 2];
+
+            if (constants[j + 3] > 1.0f) lcl_const[3] = 1.0f;
+            else if (constants[j + 3] < -1.0f) lcl_const[3] = -1.0f;
+            else lcl_const[3] = constants[j + 3];
+
+            GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, i, lcl_const));
+        }
+
+        /* If further constants are dirty, reload them without clamping.
+         *
+         * The alternative is not to touch them, but then we cannot reset the dirty constant count
+         * to zero. That's bad for apps that only use PS 1.x shaders, because in that case the code
+         * above would always re-check the first 8 constants since max_constant remains at the init
+         * value
+         */
+    }
+
+    if (gl_info->supported[EXT_GPU_PROGRAM_PARAMETERS])
+    {
+        /* TODO: Benchmark if we're better of with finding the dirty constants ourselves,
+         * or just reloading *all* constants at once
+         *
+        GL_EXTCALL(glProgramEnvParameters4fvEXT(target_type, i, max_constants, constants + (i * 4)));
+         */
+        for(; i < max_constants; i++) {
+            if(!dirty_consts[i]) continue;
+
+            /* Find the next block of dirty constants */
+            dirty_consts[i] = 0;
+            j = i;
+            for(i++; (i < max_constants) && dirty_consts[i]; i++) {
+                dirty_consts[i] = 0;
+            }
+
+            GL_EXTCALL(glProgramEnvParameters4fvEXT(target_type, j, i - j, constants + (j * 4)));
+        }
+    } else {
+        for(; i < max_constants; i++) {
+            if(dirty_consts[i]) {
+                dirty_consts[i] = 0;
+                GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, i, constants + (i * 4)));
+            }
+        }
+    }
+    checkGLcall("glProgramEnvParameter4fvARB()");
+
+    /* Load immediate constants */
+    if (shader->load_local_constsF)
+    {
+        if (TRACE_ON(d3d_shader))
+        {
+            LIST_FOR_EACH_ENTRY(lconst, &shader->constantsF, struct wined3d_shader_lconst, entry)
+            {
+                GLfloat* values = (GLfloat*)lconst->value;
+                TRACE_(d3d_constants)("Loading local constants %i: %f, %f, %f, %f\n", lconst->idx,
+                        values[0], values[1], values[2], values[3]);
+            }
+        }
+        /* Immediate constants are clamped for 1.X shaders at loading times */
+        ret = 0;
+        LIST_FOR_EACH_ENTRY(lconst, &shader->constantsF, struct wined3d_shader_lconst, entry)
+        {
+            dirty_consts[lconst->idx] = 1; /* Dirtify so the non-immediate constant overwrites it next time */
+            ret = max(ret, lconst->idx + 1);
+            GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, lconst->idx, (GLfloat*)lconst->value));
+        }
+        checkGLcall("glProgramEnvParameter4fvARB()");
+        return ret; /* The loaded immediate constants need reloading for the next shader */
+    } else {
+        return 0; /* No constants are dirty now */
+    }
+}
+
+/**
+ * Loads the texture dimensions for NP2 fixup into the currently set ARB_[vertex/fragment]_programs.
+ */
+static void shader_arb_load_np2fixup_constants(void *shader_priv,
+        const struct wined3d_gl_info *gl_info, const struct wined3d_state *state)
+{
+    const struct shader_arb_priv * priv = shader_priv;
+
+    /* NP2 texcoord fixup is (currently) only done for pixelshaders. */
+    if (!use_ps(state)) return;
+
+    if (priv->compiled_fprog && priv->compiled_fprog->np2fixup_info.super.active) {
+        const struct arb_ps_np2fixup_info* const fixup = &priv->compiled_fprog->np2fixup_info;
+        UINT i;
+        WORD active = fixup->super.active;
+        GLfloat np2fixup_constants[4 * MAX_FRAGMENT_SAMPLERS];
+
+        for (i = 0; active; active >>= 1, ++i)
+        {
+            const struct wined3d_texture *tex = state->textures[i];
+            const unsigned char idx = fixup->super.idx[i];
+            GLfloat *tex_dim = &np2fixup_constants[(idx >> 1) * 4];
+
+            if (!(active & 1)) continue;
+
+            if (!tex) {
+                FIXME("Nonexistent texture is flagged for NP2 texcoord fixup\n");
+                continue;
+            }
+
+            if (idx % 2)
+            {
+                tex_dim[2] = tex->pow2_matrix[0];
+                tex_dim[3] = tex->pow2_matrix[5];
+            }
+            else
+            {
+                tex_dim[0] = tex->pow2_matrix[0];
+                tex_dim[1] = tex->pow2_matrix[5];
+            }
+        }
+
+        for (i = 0; i < fixup->super.num_consts; ++i) {
+            GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB,
+                                                   fixup->offset + i, &np2fixup_constants[i * 4]));
+        }
+    }
+}
+
+/* Context activation is done by the caller. */
+static void shader_arb_ps_local_constants(const struct arb_ps_compiled_shader *gl_shader,
+        const struct wined3d_context *context, const struct wined3d_state *state, UINT rt_height)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    unsigned char i;
+
+    for(i = 0; i < gl_shader->numbumpenvmatconsts; i++)
+    {
+        int texunit = gl_shader->bumpenvmatconst[i].texunit;
+
+        /* The state manager takes care that this function is always called if the bump env matrix changes */
+        const float *data = (const float *)&state->texture_states[texunit][WINED3D_TSS_BUMPENV_MAT00];
+        GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB,
+                gl_shader->bumpenvmatconst[i].const_num, data));
+
+        if (gl_shader->luminanceconst[i].const_num != WINED3D_CONST_NUM_UNUSED)
+        {
+            /* WINED3D_TSS_BUMPENVLSCALE and WINED3D_TSS_BUMPENVLOFFSET are next to each other.
+             * point gl to the scale, and load 4 floats. x = scale, y = offset, z and w are junk, we
+             * don't care about them. The pointers are valid for sure because the stateblock is bigger.
+             * (they're WINED3D_TSS_TEXTURETRANSFORMFLAGS and WINED3D_TSS_ADDRESSW, so most likely 0 or NaN
+            */
+            const float *scale = (const float *)&state->texture_states[texunit][WINED3D_TSS_BUMPENV_LSCALE];
+            GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB,
+                    gl_shader->luminanceconst[i].const_num, scale));
+        }
+    }
+    checkGLcall("Load bumpmap consts");
+
+    if(gl_shader->ycorrection != WINED3D_CONST_NUM_UNUSED)
+    {
+        /* ycorrection.x: Backbuffer height(onscreen) or 0(offscreen).
+        * ycorrection.y: -1.0(onscreen), 1.0(offscreen)
+        * ycorrection.z: 1.0
+        * ycorrection.w: 0.0
+        */
+        float val[4];
+        val[0] = context->render_offscreen ? 0.0f : (float) rt_height;
+        val[1] = context->render_offscreen ? 1.0f : -1.0f;
+        val[2] = 1.0f;
+        val[3] = 0.0f;
+        GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, gl_shader->ycorrection, val));
+        checkGLcall("y correction loading");
+    }
+
+    if (!gl_shader->num_int_consts) return;
+
+    for(i = 0; i < MAX_CONST_I; i++)
+    {
+        if(gl_shader->int_consts[i] != WINED3D_CONST_NUM_UNUSED)
+        {
+            float val[4];
+            val[0] = (float)state->ps_consts_i[4 * i];
+            val[1] = (float)state->ps_consts_i[4 * i + 1];
+            val[2] = (float)state->ps_consts_i[4 * i + 2];
+            val[3] = -1.0f;
+
+            GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, gl_shader->int_consts[i], val));
+        }
+    }
+    checkGLcall("Load ps int consts");
+}
+
+/* Context activation is done by the caller. */
+static void shader_arb_vs_local_constants(const struct arb_vs_compiled_shader *gl_shader,
+        const struct wined3d_context *context, const struct wined3d_state *state)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    float position_fixup[4];
+    unsigned char i;
+
+    /* Upload the position fixup */
+    shader_get_position_fixup(context, state, position_fixup);
+    GL_EXTCALL(glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, gl_shader->pos_fixup, position_fixup));
+
+    if (!gl_shader->num_int_consts) return;
+
+    for(i = 0; i < MAX_CONST_I; i++)
+    {
+        if(gl_shader->int_consts[i] != WINED3D_CONST_NUM_UNUSED)
+        {
+            float val[4];
+            val[0] = (float)state->vs_consts_i[4 * i];
+            val[1] = (float)state->vs_consts_i[4 * i + 1];
+            val[2] = (float)state->vs_consts_i[4 * i + 2];
+            val[3] = -1.0f;
+
+            GL_EXTCALL(glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, gl_shader->int_consts[i], val));
+        }
+    }
+    checkGLcall("Load vs int consts");
+}
+
+static void shader_arb_select(void *shader_priv, const struct wined3d_context *context,
+        const struct wined3d_state *state);
+
+/**
+ * Loads the app-supplied constants into the currently set ARB_[vertex/fragment]_programs.
+ *
+ * We only support float constants in ARB at the moment, so don't
+ * worry about the Integers or Booleans
+ */
+/* Context activation is done by the caller (state handler). */
+static void shader_arb_load_constants_internal(struct shader_arb_priv *priv,
+        const struct wined3d_context *context, const struct wined3d_state *state,
+        BOOL usePixelShader, BOOL useVertexShader, BOOL from_shader_select)
+{
+    const struct wined3d_d3d_info *d3d_info = context->d3d_info;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    if (!from_shader_select)
+    {
+        const struct wined3d_shader *vshader = state->vertex_shader, *pshader = state->pixel_shader;
+        if (vshader
+                && (vshader->reg_maps.boolean_constants
+                || (!gl_info->supported[NV_VERTEX_PROGRAM2_OPTION]
+                && (vshader->reg_maps.integer_constants & ~vshader->reg_maps.local_int_consts))))
+        {
+            TRACE("bool/integer vertex shader constants potentially modified, forcing shader reselection.\n");
+            shader_arb_select(priv, context, state);
+        }
+        else if (pshader
+                && (pshader->reg_maps.boolean_constants
+                || (!gl_info->supported[NV_FRAGMENT_PROGRAM_OPTION]
+                && (pshader->reg_maps.integer_constants & ~pshader->reg_maps.local_int_consts))))
+        {
+            TRACE("bool/integer pixel shader constants potentially modified, forcing shader reselection.\n");
+            shader_arb_select(priv, context, state);
+        }
+    }
+
+    if (context != priv->last_context)
+    {
+        memset(priv->vshader_const_dirty, 1,
+                sizeof(*priv->vshader_const_dirty) * d3d_info->limits.vs_uniform_count);
+        priv->highest_dirty_vs_const = d3d_info->limits.vs_uniform_count;
+
+        memset(priv->pshader_const_dirty, 1,
+                sizeof(*priv->pshader_const_dirty) * d3d_info->limits.ps_uniform_count);
+        priv->highest_dirty_ps_const = d3d_info->limits.ps_uniform_count;
+
+        priv->last_context = context;
+    }
+
+    if (useVertexShader)
+    {
+        struct wined3d_shader *vshader = state->vertex_shader;
+        const struct arb_vs_compiled_shader *gl_shader = priv->compiled_vprog;
+
+        /* Load DirectX 9 float constants for vertex shader */
+        priv->highest_dirty_vs_const = shader_arb_load_constantsF(vshader, gl_info, GL_VERTEX_PROGRAM_ARB,
+                priv->highest_dirty_vs_const, state->vs_consts_f, priv->vshader_const_dirty);
+        shader_arb_vs_local_constants(gl_shader, context, state);
+    }
+
+    if (usePixelShader)
+    {
+        struct wined3d_shader *pshader = state->pixel_shader;
+        const struct arb_ps_compiled_shader *gl_shader = priv->compiled_fprog;
+        UINT rt_height = state->fb->render_targets[0]->resource.height;
+
+        /* Load DirectX 9 float constants for pixel shader */
+        priv->highest_dirty_ps_const = shader_arb_load_constantsF(pshader, gl_info, GL_FRAGMENT_PROGRAM_ARB,
+                priv->highest_dirty_ps_const, state->ps_consts_f, priv->pshader_const_dirty);
+        shader_arb_ps_local_constants(gl_shader, context, state, rt_height);
+    }
+}
+
+static void shader_arb_load_constants(void *shader_priv, const struct wined3d_context *context,
+        const struct wined3d_state *state)
+{
+    BOOL vs = use_vs(state);
+    BOOL ps = use_ps(state);
+
+    shader_arb_load_constants_internal(shader_priv, context, state, ps, vs, FALSE);
+}
+
+static void shader_arb_update_float_vertex_constants(struct wined3d_device *device, UINT start, UINT count)
+{
+    struct wined3d_context *context = context_get_current();
+    struct shader_arb_priv *priv = device->shader_priv;
+
+    /* We don't want shader constant dirtification to be an O(contexts), so just dirtify the active
+     * context. On a context switch the old context will be fully dirtified */
+    if (!context || context->swapchain->device != device) return;
+
+    memset(priv->vshader_const_dirty + start, 1, sizeof(*priv->vshader_const_dirty) * count);
+    priv->highest_dirty_vs_const = max(priv->highest_dirty_vs_const, start + count);
+}
+
+static void shader_arb_update_float_pixel_constants(struct wined3d_device *device, UINT start, UINT count)
+{
+    struct wined3d_context *context = context_get_current();
+    struct shader_arb_priv *priv = device->shader_priv;
+
+    /* We don't want shader constant dirtification to be an O(contexts), so just dirtify the active
+     * context. On a context switch the old context will be fully dirtified */
+    if (!context || context->swapchain->device != device) return;
+
+    memset(priv->pshader_const_dirty + start, 1, sizeof(*priv->pshader_const_dirty) * count);
+    priv->highest_dirty_ps_const = max(priv->highest_dirty_ps_const, start + count);
+}
+
+/* Generate the variable & register declarations for the ARB_vertex_program output target */
+static void shader_generate_arb_declarations(const struct wined3d_shader *shader,
+        const struct wined3d_shader_reg_maps *reg_maps, struct wined3d_shader_buffer *buffer,
+        const struct wined3d_gl_info *gl_info, DWORD *num_clipplanes,
+        const struct shader_arb_ctx_priv *ctx)
+{
+    DWORD i;
+    char pshader = shader_is_pshader_version(reg_maps->shader_version.type);
+    const struct wined3d_shader_lconst *lconst;
+    unsigned max_constantsF;
+    DWORD map;
+
+    /* In pixel shaders, all private constants are program local, we don't need anything
+     * from program.env. Thus we can advertise the full set of constants in pixel shaders.
+     * If we need a private constant the GL implementation will squeeze it in somewhere
+     *
+     * With vertex shaders we need the posFixup and on some GL implementations 4 helper
+     * immediate values. The posFixup is loaded using program.env for now, so always
+     * subtract one from the number of constants. If the shader uses indirect addressing,
+     * account for the helper const too because we have to declare all available d3d constants
+     * and don't know which are actually used.
+     */
+    if (pshader)
+    {
+        max_constantsF = gl_info->limits.arb_ps_native_constants;
+        /* 24 is the minimum MAX_PROGRAM_ENV_PARAMETERS_ARB value. */
+        if (max_constantsF < 24)
+            max_constantsF = gl_info->limits.arb_ps_float_constants;
+    }
+    else
+    {
+        const struct arb_vshader_private *shader_data = shader->backend_data;
+        max_constantsF = gl_info->limits.arb_vs_native_constants;
+        /* 96 is the minimum MAX_PROGRAM_ENV_PARAMETERS_ARB value.
+         * Also prevents max_constantsF from becoming less than 0 and
+         * wrapping . */
+        if (max_constantsF < 96)
+            max_constantsF = gl_info->limits.arb_vs_float_constants;
+
+        if (reg_maps->usesrelconstF)
+        {
+            DWORD highest_constf = 0, clip_limit;
+
+            max_constantsF -= reserved_vs_const(shader_data, reg_maps, gl_info);
+            max_constantsF -= count_bits(reg_maps->integer_constants);
+            max_constantsF -= gl_info->reserved_arb_constants;
+
+            for (i = 0; i < shader->limits.constant_float; ++i)
+            {
+                DWORD idx = i >> 5;
+                DWORD shift = i & 0x1f;
+                if(reg_maps->constf[idx] & (1 << shift)) highest_constf = i;
+            }
+
+            if(use_nv_clip(gl_info) && ctx->target_version >= NV2)
+            {
+                if(ctx->cur_vs_args->super.clip_enabled)
+                    clip_limit = gl_info->limits.clipplanes;
+                else
+                    clip_limit = 0;
+            }
+            else
+            {
+                unsigned int mask = ctx->cur_vs_args->clip.boolclip.clipplane_mask;
+                clip_limit = min(count_bits(mask), 4);
+            }
+            *num_clipplanes = min(clip_limit, max_constantsF - highest_constf - 1);
+            max_constantsF -= *num_clipplanes;
+            if(*num_clipplanes < clip_limit)
+            {
+                WARN("Only %u clipplanes out of %u enabled\n", *num_clipplanes, gl_info->limits.clipplanes);
+            }
+        }
+        else
+        {
+            if (ctx->target_version >= NV2) *num_clipplanes = gl_info->limits.clipplanes;
+            else *num_clipplanes = min(gl_info->limits.clipplanes, 4);
+        }
+    }
+
+    for (i = 0, map = reg_maps->temporary; map; map >>= 1, ++i)
+    {
+        if (map & 1) shader_addline(buffer, "TEMP R%u;\n", i);
+    }
+
+    for (i = 0, map = reg_maps->address; map; map >>= 1, ++i)
+    {
+        if (map & 1) shader_addline(buffer, "ADDRESS A%u;\n", i);
+    }
+
+    if (pshader && reg_maps->shader_version.major == 1 && reg_maps->shader_version.minor <= 3)
+    {
+        for (i = 0, map = reg_maps->texcoord; map; map >>= 1, ++i)
+        {
+            if (map & 1) shader_addline(buffer, "TEMP T%u;\n", i);
+        }
+    }
+
+    if (!shader->load_local_constsF)
+    {
+        LIST_FOR_EACH_ENTRY(lconst, &shader->constantsF, struct wined3d_shader_lconst, entry)
+        {
+            const float *value;
+            value = (const float *)lconst->value;
+            shader_addline(buffer, "PARAM C%u = {%.8e, %.8e, %.8e, %.8e};\n", lconst->idx,
+                           value[0], value[1], value[2], value[3]);
+        }
+    }
+
+    /* After subtracting privately used constants from the hardware limit(they are loaded as
+     * local constants), make sure the shader doesn't violate the env constant limit
+     */
+    if(pshader)
+    {
+        max_constantsF = min(max_constantsF, gl_info->limits.arb_ps_float_constants);
+    }
+    else
+    {
+        max_constantsF = min(max_constantsF, gl_info->limits.arb_vs_float_constants);
+    }
+
+    /* Avoid declaring more constants than needed */
+    max_constantsF = min(max_constantsF, shader->limits.constant_float);
+
+    /* we use the array-based constants array if the local constants are marked for loading,
+     * because then we use indirect addressing, or when the local constant list is empty,
+     * because then we don't know if we're using indirect addressing or not. If we're hardcoding
+     * local constants do not declare the loaded constants as an array because ARB compilers usually
+     * do not optimize unused constants away
+     */
+    if (reg_maps->usesrelconstF)
+    {
+        /* Need to PARAM the environment parameters (constants) so we can use relative addressing */
+        shader_addline(buffer, "PARAM C[%d] = { program.env[0..%d] };\n",
+                    max_constantsF, max_constantsF - 1);
+    } else {
+        for(i = 0; i < max_constantsF; i++) {
+            DWORD idx, mask;
+            idx = i >> 5;
+            mask = 1 << (i & 0x1f);
+            if (!shader_constant_is_local(shader, i) && (reg_maps->constf[idx] & mask))
+            {
+                shader_addline(buffer, "PARAM C%d = program.env[%d];\n",i, i);
+            }
+        }
+    }
+}
+
+static const char * const shift_tab[] = {
+    "dummy",     /*  0 (none) */
+    "coefmul.x", /*  1 (x2)   */
+    "coefmul.y", /*  2 (x4)   */
+    "coefmul.z", /*  3 (x8)   */
+    "coefmul.w", /*  4 (x16)  */
+    "dummy",     /*  5 (x32)  */
+    "dummy",     /*  6 (x64)  */
+    "dummy",     /*  7 (x128) */
+    "dummy",     /*  8 (d256) */
+    "dummy",     /*  9 (d128) */
+    "dummy",     /* 10 (d64)  */
+    "dummy",     /* 11 (d32)  */
+    "coefdiv.w", /* 12 (d16)  */
+    "coefdiv.z", /* 13 (d8)   */
+    "coefdiv.y", /* 14 (d4)   */
+    "coefdiv.x"  /* 15 (d2)   */
+};
+
+static void shader_arb_get_write_mask(const struct wined3d_shader_instruction *ins,
+        const struct wined3d_shader_dst_param *dst, char *write_mask)
+{
+    char *ptr = write_mask;
+
+    if (dst->write_mask != WINED3DSP_WRITEMASK_ALL)
+    {
+        *ptr++ = '.';
+        if (dst->write_mask & WINED3DSP_WRITEMASK_0) *ptr++ = 'x';
+        if (dst->write_mask & WINED3DSP_WRITEMASK_1) *ptr++ = 'y';
+        if (dst->write_mask & WINED3DSP_WRITEMASK_2) *ptr++ = 'z';
+        if (dst->write_mask & WINED3DSP_WRITEMASK_3) *ptr++ = 'w';
+    }
+
+    *ptr = '\0';
+}
+
+static void shader_arb_get_swizzle(const struct wined3d_shader_src_param *param, BOOL fixup, char *swizzle_str)
+{
+    /* For registers of type WINED3DDECLTYPE_D3DCOLOR, data is stored as "bgra",
+     * but addressed as "rgba". To fix this we need to swap the register's x
+     * and z components. */
+    const char *swizzle_chars = fixup ? "zyxw" : "xyzw";
+    char *ptr = swizzle_str;
+
+    /* swizzle bits fields: wwzzyyxx */
+    DWORD swizzle = param->swizzle;
+    DWORD swizzle_x = swizzle & 0x03;
+    DWORD swizzle_y = (swizzle >> 2) & 0x03;
+    DWORD swizzle_z = (swizzle >> 4) & 0x03;
+    DWORD swizzle_w = (swizzle >> 6) & 0x03;
+
+    /* If the swizzle is the default swizzle (ie, "xyzw"), we don't need to
+     * generate a swizzle string. Unless we need to our own swizzling. */
+    if (swizzle != WINED3DSP_NOSWIZZLE || fixup)
+    {
+        *ptr++ = '.';
+        if (swizzle_x == swizzle_y && swizzle_x == swizzle_z && swizzle_x == swizzle_w) {
+            *ptr++ = swizzle_chars[swizzle_x];
+        } else {
+            *ptr++ = swizzle_chars[swizzle_x];
+            *ptr++ = swizzle_chars[swizzle_y];
+            *ptr++ = swizzle_chars[swizzle_z];
+            *ptr++ = swizzle_chars[swizzle_w];
+        }
+    }
+
+    *ptr = '\0';
+}
+
+static void shader_arb_request_a0(const struct wined3d_shader_instruction *ins, const char *src)
+{
+    struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+
+    if (!strcmp(priv->addr_reg, src)) return;
+
+    strcpy(priv->addr_reg, src);
+    shader_addline(buffer, "ARL A0.x, %s;\n", src);
+}
+
+static void shader_arb_get_src_param(const struct wined3d_shader_instruction *ins,
+        const struct wined3d_shader_src_param *src, unsigned int tmpreg, char *outregstr);
+
+static void shader_arb_get_register_name(const struct wined3d_shader_instruction *ins,
+        const struct wined3d_shader_register *reg, char *register_name, BOOL *is_color)
+{
+    /* oPos, oFog and oPts in D3D */
+    static const char * const rastout_reg_names[] = {"TMP_OUT", "TMP_FOGCOORD", "result.pointsize"};
+    const struct wined3d_shader *shader = ins->ctx->shader;
+    const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps;
+    BOOL pshader = shader_is_pshader_version(reg_maps->shader_version.type);
+    struct shader_arb_ctx_priv *ctx = ins->ctx->backend_data;
+
+    *is_color = FALSE;
+
+    switch (reg->type)
+    {
+        case WINED3DSPR_TEMP:
+            sprintf(register_name, "R%u", reg->idx[0].offset);
+            break;
+
+        case WINED3DSPR_INPUT:
+            if (pshader)
+            {
+                if (reg_maps->shader_version.major < 3)
+                {
+                    if (!reg->idx[0].offset)
+                        strcpy(register_name, "fragment.color.primary");
+                    else
+                        strcpy(register_name, "fragment.color.secondary");
+                }
+                else
+                {
+                    if (reg->idx[0].rel_addr)
+                    {
+                        char rel_reg[50];
+                        shader_arb_get_src_param(ins, reg->idx[0].rel_addr, 0, rel_reg);
+
+                        if (!strcmp(rel_reg, "**aL_emul**"))
+                        {
+                            DWORD idx = ctx->aL + reg->idx[0].offset;
+                            if(idx < MAX_REG_INPUT)
+                            {
+                                strcpy(register_name, ctx->ps_input[idx]);
+                            }
+                            else
+                            {
+                                ERR("Pixel shader input register out of bounds: %u\n", idx);
+                                sprintf(register_name, "out_of_bounds_%u", idx);
+                            }
+                        }
+                        else if (reg_maps->input_registers & 0x0300)
+                        {
+                            /* There are two ways basically:
+                             *
+                             * 1) Use the unrolling code that is used for loop emulation and unroll the loop.
+                             *    That means trouble if the loop also contains a breakc or if the control values
+                             *    aren't local constants.
+                             * 2) Generate an if block that checks if aL.y < 8, == 8 or == 9 and selects the
+                             *    source dynamically. The trouble is that we cannot simply read aL.y because it
+                             *    is an ADDRESS register. We could however push it, load .zw with a value and use
+                             *    ADAC to load the condition code register and pop it again afterwards
+                             */
+                            FIXME("Relative input register addressing with more than 8 registers\n");
+
+                            /* This is better than nothing for now */
+                            sprintf(register_name, "fragment.texcoord[%s + %u]", rel_reg, reg->idx[0].offset);
+                        }
+                        else if(ctx->cur_ps_args->super.vp_mode != vertexshader)
+                        {
+                            /* This is problematic because we'd have to consult the ctx->ps_input strings
+                             * for where to find the varying. Some may be "0.0", others can be texcoords or
+                             * colors. This needs either a pipeline replacement to make the vertex shader feed
+                             * proper varyings, or loop unrolling
+                             *
+                             * For now use the texcoords and hope for the best
+                             */
+                            FIXME("Non-vertex shader varying input with indirect addressing\n");
+                            sprintf(register_name, "fragment.texcoord[%s + %u]", rel_reg, reg->idx[0].offset);
+                        }
+                        else
+                        {
+                            /* D3D supports indirect addressing only with aL in loop registers. The loop instruction
+                             * pulls GL_NV_fragment_program2 in
+                             */
+                            sprintf(register_name, "fragment.texcoord[%s + %u]", rel_reg, reg->idx[0].offset);
+                        }
+                    }
+                    else
+                    {
+                        if (reg->idx[0].offset < MAX_REG_INPUT)
+                        {
+                            strcpy(register_name, ctx->ps_input[reg->idx[0].offset]);
+                        }
+                        else
+                        {
+                            ERR("Pixel shader input register out of bounds: %u\n", reg->idx[0].offset);
+                            sprintf(register_name, "out_of_bounds_%u", reg->idx[0].offset);
+                        }
+                    }
+                }
+            }
+            else
+            {
+                if (ctx->cur_vs_args->super.swizzle_map & (1 << reg->idx[0].offset))
+                    *is_color = TRUE;
+                sprintf(register_name, "vertex.attrib[%u]", reg->idx[0].offset);
+            }
+            break;
+
+        case WINED3DSPR_CONST:
+            if (!pshader && reg->idx[0].rel_addr)
+            {
+                const struct arb_vshader_private *shader_data = shader->backend_data;
+                UINT rel_offset = shader_data->rel_offset;
+                BOOL aL = FALSE;
+                char rel_reg[50];
+                if (reg_maps->shader_version.major < 2)
+                {
+                    sprintf(rel_reg, "A0.x");
+                }
+                else
+                {
+                    shader_arb_get_src_param(ins, reg->idx[0].rel_addr, 0, rel_reg);
+                    if (ctx->target_version == ARB)
+                    {
+                        if (!strcmp(rel_reg, "**aL_emul**"))
+                        {
+                            aL = TRUE;
+                        } else {
+                            shader_arb_request_a0(ins, rel_reg);
+                            sprintf(rel_reg, "A0.x");
+                        }
+                    }
+                }
+                if (aL)
+                    sprintf(register_name, "C[%u]", ctx->aL + reg->idx[0].offset);
+                else if (reg->idx[0].offset >= rel_offset)
+                    sprintf(register_name, "C[%s + %u]", rel_reg, reg->idx[0].offset - rel_offset);
+                else
+                    sprintf(register_name, "C[%s - %u]", rel_reg, rel_offset - reg->idx[0].offset);
+            }
+            else
+            {
+                if (reg_maps->usesrelconstF)
+                    sprintf(register_name, "C[%u]", reg->idx[0].offset);
+                else
+                    sprintf(register_name, "C%u", reg->idx[0].offset);
+            }
+            break;
+
+        case WINED3DSPR_TEXTURE: /* case WINED3DSPR_ADDR: */
+            if (pshader)
+            {
+                if (reg_maps->shader_version.major == 1
+                        && reg_maps->shader_version.minor <= 3)
+                    /* In ps <= 1.3, Tx is a temporary register as destination
+                     * to all instructions, and as source to most instructions.
+                     * For some instructions it is the texcoord input. Those
+                     * instructions know about the special use. */
+                    sprintf(register_name, "T%u", reg->idx[0].offset);
+                else
+                    /* In ps 1.4 and 2.x Tx is always a (read-only) varying. */
+                    sprintf(register_name, "fragment.texcoord[%u]", reg->idx[0].offset);
+            }
+            else
+            {
+                if (reg_maps->shader_version.major == 1 || ctx->target_version >= NV2)
+                    sprintf(register_name, "A%u", reg->idx[0].offset);
+                else
+                    sprintf(register_name, "A%u_SHADOW", reg->idx[0].offset);
+            }
+            break;
+
+        case WINED3DSPR_COLOROUT:
+            if (ctx->cur_ps_args->super.srgb_correction && !reg->idx[0].offset)
+            {
+                strcpy(register_name, "TMP_COLOR");
+            }
+            else
+            {
+                if (ctx->cur_ps_args->super.srgb_correction)
+                    FIXME("sRGB correction on higher render targets.\n");
+                if (reg_maps->rt_mask > 1)
+                    sprintf(register_name, "result.color[%u]", reg->idx[0].offset);
+                else
+                    strcpy(register_name, "result.color");
+                }
+            break;
+
+        case WINED3DSPR_RASTOUT:
+            if (reg->idx[0].offset == 1)
+                sprintf(register_name, "%s", ctx->fog_output);
+            else
+                sprintf(register_name, "%s", rastout_reg_names[reg->idx[0].offset]);
+            break;
+
+        case WINED3DSPR_DEPTHOUT:
+            strcpy(register_name, "result.depth");
+            break;
+
+        case WINED3DSPR_ATTROUT:
+        /* case WINED3DSPR_OUTPUT: */
+            if (pshader)
+                sprintf(register_name, "oD[%u]", reg->idx[0].offset);
+            else
+                strcpy(register_name, ctx->color_output[reg->idx[0].offset]);
+            break;
+
+        case WINED3DSPR_TEXCRDOUT:
+            if (pshader)
+                sprintf(register_name, "oT[%u]", reg->idx[0].offset);
+            else if (reg_maps->shader_version.major < 3)
+                strcpy(register_name, ctx->texcrd_output[reg->idx[0].offset]);
+                else
+                strcpy(register_name, ctx->vs_output[reg->idx[0].offset]);
+            break;
+
+        case WINED3DSPR_LOOP:
+            if(ctx->target_version >= NV2)
+            {
+                /* Pshader has an implicitly declared loop index counter A0.x that cannot be renamed */
+                if(pshader) sprintf(register_name, "A0.x");
+                else sprintf(register_name, "aL.y");
+            }
+            else
+            {
+                /* Unfortunately this code cannot return the value of ctx->aL here. An immediate value
+                 * would be valid, but if aL is used for indexing(its only use), there's likely an offset,
+                 * thus the result would be something like C[15 + 30], which is not valid in the ARB program
+                 * grammar. So return a marker for the emulated aL and intercept it in constant and varying
+                 * indexing
+                 */
+                sprintf(register_name, "**aL_emul**");
+            }
+
+            break;
+
+        case WINED3DSPR_CONSTINT:
+            sprintf(register_name, "I%u", reg->idx[0].offset);
+            break;
+
+        case WINED3DSPR_MISCTYPE:
+            if (!reg->idx[0].offset)
+                sprintf(register_name, "vpos");
+            else if (reg->idx[0].offset == 1)
+                sprintf(register_name, "fragment.facing.x");
+            else
+                FIXME("Unknown MISCTYPE register index %u.\n", reg->idx[0].offset);
+            break;
+
+        default:
+            FIXME("Unhandled register type %#x[%u].\n", reg->type, reg->idx[0].offset);
+            sprintf(register_name, "unrecognized_register[%u]", reg->idx[0].offset);
+            break;
+    }
+}
+
+static void shader_arb_get_dst_param(const struct wined3d_shader_instruction *ins,
+        const struct wined3d_shader_dst_param *wined3d_dst, char *str)
+{
+    char register_name[255];
+    char write_mask[6];
+    BOOL is_color;
+
+    shader_arb_get_register_name(ins, &wined3d_dst->reg, register_name, &is_color);
+    strcpy(str, register_name);
+
+    shader_arb_get_write_mask(ins, wined3d_dst, write_mask);
+    strcat(str, write_mask);
+}
+
+static const char *shader_arb_get_fixup_swizzle(enum fixup_channel_source channel_source)
+{
+    switch(channel_source)
+    {
+        case CHANNEL_SOURCE_ZERO: return "0";
+        case CHANNEL_SOURCE_ONE: return "1";
+        case CHANNEL_SOURCE_X: return "x";
+        case CHANNEL_SOURCE_Y: return "y";
+        case CHANNEL_SOURCE_Z: return "z";
+        case CHANNEL_SOURCE_W: return "w";
+        default:
+            FIXME("Unhandled channel source %#x\n", channel_source);
+            return "undefined";
+    }
+}
+
+static void gen_color_correction(struct wined3d_shader_buffer *buffer, const char *reg,
+        DWORD dst_mask, const char *one, const char *two, struct color_fixup_desc fixup)
+{
+    DWORD mask;
+
+    if (is_complex_fixup(fixup))
+    {
+        enum complex_fixup complex_fixup = get_complex_fixup(fixup);
+        FIXME("Complex fixup (%#x) not supported\n", complex_fixup);
+        return;
+    }
+
+    mask = 0;
+    if (fixup.x_source != CHANNEL_SOURCE_X) mask |= WINED3DSP_WRITEMASK_0;
+    if (fixup.y_source != CHANNEL_SOURCE_Y) mask |= WINED3DSP_WRITEMASK_1;
+    if (fixup.z_source != CHANNEL_SOURCE_Z) mask |= WINED3DSP_WRITEMASK_2;
+    if (fixup.w_source != CHANNEL_SOURCE_W) mask |= WINED3DSP_WRITEMASK_3;
+    mask &= dst_mask;
+
+    if (mask)
+    {
+        shader_addline(buffer, "SWZ %s, %s, %s, %s, %s, %s;\n", reg, reg,
+                shader_arb_get_fixup_swizzle(fixup.x_source), shader_arb_get_fixup_swizzle(fixup.y_source),
+                shader_arb_get_fixup_swizzle(fixup.z_source), shader_arb_get_fixup_swizzle(fixup.w_source));
+    }
+
+    mask = 0;
+    if (fixup.x_sign_fixup) mask |= WINED3DSP_WRITEMASK_0;
+    if (fixup.y_sign_fixup) mask |= WINED3DSP_WRITEMASK_1;
+    if (fixup.z_sign_fixup) mask |= WINED3DSP_WRITEMASK_2;
+    if (fixup.w_sign_fixup) mask |= WINED3DSP_WRITEMASK_3;
+    mask &= dst_mask;
+
+    if (mask)
+    {
+        char reg_mask[6];
+        char *ptr = reg_mask;
+
+        if (mask != WINED3DSP_WRITEMASK_ALL)
+        {
+            *ptr++ = '.';
+            if (mask & WINED3DSP_WRITEMASK_0) *ptr++ = 'x';
+            if (mask & WINED3DSP_WRITEMASK_1) *ptr++ = 'y';
+            if (mask & WINED3DSP_WRITEMASK_2) *ptr++ = 'z';
+            if (mask & WINED3DSP_WRITEMASK_3) *ptr++ = 'w';
+        }
+        *ptr = '\0';
+
+        shader_addline(buffer, "MAD %s%s, %s, %s, -%s;\n", reg, reg_mask, reg, two, one);
+    }
+}
+
+static const char *shader_arb_get_modifier(const struct wined3d_shader_instruction *ins)
+{
+    DWORD mod;
+    struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
+    if (!ins->dst_count) return "";
+
+    mod = ins->dst[0].modifiers;
+
+    /* Silently ignore PARTIALPRECISION if its not supported */
+    if(priv->target_version == ARB) mod &= ~WINED3DSPDM_PARTIALPRECISION;
+
+    if(mod & WINED3DSPDM_MSAMPCENTROID)
+    {
+        FIXME("Unhandled modifier WINED3DSPDM_MSAMPCENTROID\n");
+        mod &= ~WINED3DSPDM_MSAMPCENTROID;
+    }
+
+    switch(mod)
+    {
+        case WINED3DSPDM_SATURATE | WINED3DSPDM_PARTIALPRECISION:
+            return "H_SAT";
+
+        case WINED3DSPDM_SATURATE:
+            return "_SAT";
+
+        case WINED3DSPDM_PARTIALPRECISION:
+            return "H";
+
+        case 0:
+            return "";
+
+        default:
+            FIXME("Unknown modifiers 0x%08x\n", mod);
+            return "";
+    }
+}
+
+#define TEX_PROJ        0x1
+#define TEX_BIAS        0x2
+#define TEX_LOD         0x4
+#define TEX_DERIV       0x10
+
+static void shader_hw_sample(const struct wined3d_shader_instruction *ins, DWORD sampler_idx,
+        const char *dst_str, const char *coord_reg, WORD flags, const char *dsx, const char *dsy)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    DWORD sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx];
+    const char *tex_type;
+    BOOL np2_fixup = FALSE;
+    struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
+    const char *mod;
+    BOOL pshader = shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type);
+    const struct wined3d_shader *shader;
+    const struct wined3d_device *device;
+    const struct wined3d_gl_info *gl_info;
+
+    /* D3D vertex shader sampler IDs are vertex samplers(0-3), not global d3d samplers */
+    if(!pshader) sampler_idx += MAX_FRAGMENT_SAMPLERS;
+
+    switch(sampler_type) {
+        case WINED3DSTT_1D:
+            tex_type = "1D";
+            break;
+
+        case WINED3DSTT_2D:
+            shader = ins->ctx->shader;
+            device = shader->device;
+            gl_info = &device->adapter->gl_info;
+
+            if (pshader && priv->cur_ps_args->super.np2_fixup & (1 << sampler_idx)
+                    && gl_info->supported[ARB_TEXTURE_RECTANGLE])
+                tex_type = "RECT";
+            else
+                tex_type = "2D";
+            if (shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type))
+            {
+                if (priv->cur_np2fixup_info->super.active & (1 << sampler_idx))
+                {
+                    if (flags) FIXME("Only ordinary sampling from NP2 textures is supported.\n");
+                    else np2_fixup = TRUE;
+                }
+            }
+            break;
+
+        case WINED3DSTT_VOLUME:
+            tex_type = "3D";
+            break;
+
+        case WINED3DSTT_CUBE:
+            tex_type = "CUBE";
+            break;
+
+        default:
+            ERR("Unexpected texture type %d\n", sampler_type);
+            tex_type = "";
+    }
+
+    /* TEX, TXL, TXD and TXP do not support the "H" modifier,
+     * so don't use shader_arb_get_modifier
+     */
+    if(ins->dst[0].modifiers & WINED3DSPDM_SATURATE) mod = "_SAT";
+    else mod = "";
+
+    /* Fragment samplers always have indentity mapping */
+    if(sampler_idx >= MAX_FRAGMENT_SAMPLERS)
+    {
+        sampler_idx = priv->cur_vs_args->vertex.samplers[sampler_idx - MAX_FRAGMENT_SAMPLERS];
+    }
+
+    if (flags & TEX_DERIV)
+    {
+        if(flags & TEX_PROJ) FIXME("Projected texture sampling with custom derivatives\n");
+        if(flags & TEX_BIAS) FIXME("Biased texture sampling with custom derivatives\n");
+        shader_addline(buffer, "TXD%s %s, %s, %s, %s, texture[%u], %s;\n", mod, dst_str, coord_reg,
+                       dsx, dsy,sampler_idx, tex_type);
+    }
+    else if(flags & TEX_LOD)
+    {
+        if(flags & TEX_PROJ) FIXME("Projected texture sampling with explicit lod\n");
+        if(flags & TEX_BIAS) FIXME("Biased texture sampling with explicit lod\n");
+        shader_addline(buffer, "TXL%s %s, %s, texture[%u], %s;\n", mod, dst_str, coord_reg,
+                       sampler_idx, tex_type);
+    }
+    else if (flags & TEX_BIAS)
+    {
+        /* Shouldn't be possible, but let's check for it */
+        if(flags & TEX_PROJ) FIXME("Biased and Projected texture sampling\n");
+        /* TXB takes the 4th component of the source vector automatically, as d3d. Nothing more to do */
+        shader_addline(buffer, "TXB%s %s, %s, texture[%u], %s;\n", mod, dst_str, coord_reg, sampler_idx, tex_type);
+    }
+    else if (flags & TEX_PROJ)
+    {
+        shader_addline(buffer, "TXP%s %s, %s, texture[%u], %s;\n", mod, dst_str, coord_reg, sampler_idx, tex_type);
+    }
+    else
+    {
+        if (np2_fixup)
+        {
+            const unsigned char idx = priv->cur_np2fixup_info->super.idx[sampler_idx];
+            shader_addline(buffer, "MUL TA, np2fixup[%u].%s, %s;\n", idx >> 1,
+                           (idx % 2) ? "zwxy" : "xyzw", coord_reg);
+
+            shader_addline(buffer, "TEX%s %s, TA, texture[%u], %s;\n", mod, dst_str, sampler_idx, tex_type);
+        }
+        else
+            shader_addline(buffer, "TEX%s %s, %s, texture[%u], %s;\n", mod, dst_str, coord_reg, sampler_idx, tex_type);
+    }
+
+    if (pshader)
+    {
+        gen_color_correction(buffer, dst_str, ins->dst[0].write_mask,
+                arb_get_helper_value(WINED3D_SHADER_TYPE_PIXEL, ARB_ONE),
+                arb_get_helper_value(WINED3D_SHADER_TYPE_PIXEL, ARB_TWO),
+                priv->cur_ps_args->super.color_fixup[sampler_idx]);
+    }
+}
+
+static void shader_arb_get_src_param(const struct wined3d_shader_instruction *ins,
+        const struct wined3d_shader_src_param *src, unsigned int tmpreg, char *outregstr)
+{
+    /* Generate a line that does the input modifier computation and return the input register to use */
+    BOOL is_color = FALSE;
+    char regstr[256];
+    char swzstr[20];
+    int insert_line;
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    struct shader_arb_ctx_priv *ctx = ins->ctx->backend_data;
+    const char *one = arb_get_helper_value(ins->ctx->reg_maps->shader_version.type, ARB_ONE);
+    const char *two = arb_get_helper_value(ins->ctx->reg_maps->shader_version.type, ARB_TWO);
+
+    /* Assume a new line will be added */
+    insert_line = 1;
+
+    /* Get register name */
+    shader_arb_get_register_name(ins, &src->reg, regstr, &is_color);
+    shader_arb_get_swizzle(src, is_color, swzstr);
+
+    switch (src->modifiers)
+    {
+    case WINED3DSPSM_NONE:
+        sprintf(outregstr, "%s%s", regstr, swzstr);
+        insert_line = 0;
+        break;
+    case WINED3DSPSM_NEG:
+        sprintf(outregstr, "-%s%s", regstr, swzstr);
+        insert_line = 0;
+        break;
+    case WINED3DSPSM_BIAS:
+        shader_addline(buffer, "ADD T%c, %s, -coefdiv.x;\n", 'A' + tmpreg, regstr);
+        break;
+    case WINED3DSPSM_BIASNEG:
+        shader_addline(buffer, "ADD T%c, -%s, coefdiv.x;\n", 'A' + tmpreg, regstr);
+        break;
+    case WINED3DSPSM_SIGN:
+        shader_addline(buffer, "MAD T%c, %s, %s, -%s;\n", 'A' + tmpreg, regstr, two, one);
+        break;
+    case WINED3DSPSM_SIGNNEG:
+        shader_addline(buffer, "MAD T%c, %s, -%s, %s;\n", 'A' + tmpreg, regstr, two, one);
+        break;
+    case WINED3DSPSM_COMP:
+        shader_addline(buffer, "SUB T%c, %s, %s;\n", 'A' + tmpreg, one, regstr);
+        break;
+    case WINED3DSPSM_X2:
+        shader_addline(buffer, "ADD T%c, %s, %s;\n", 'A' + tmpreg, regstr, regstr);
+        break;
+    case WINED3DSPSM_X2NEG:
+        shader_addline(buffer, "ADD T%c, -%s, -%s;\n", 'A' + tmpreg, regstr, regstr);
+        break;
+    case WINED3DSPSM_DZ:
+        shader_addline(buffer, "RCP T%c, %s.z;\n", 'A' + tmpreg, regstr);
+        shader_addline(buffer, "MUL T%c, %s, T%c;\n", 'A' + tmpreg, regstr, 'A' + tmpreg);
+        break;
+    case WINED3DSPSM_DW:
+        shader_addline(buffer, "RCP T%c, %s.w;\n", 'A' + tmpreg, regstr);
+        shader_addline(buffer, "MUL T%c, %s, T%c;\n", 'A' + tmpreg, regstr, 'A' + tmpreg);
+        break;
+    case WINED3DSPSM_ABS:
+        if(ctx->target_version >= NV2) {
+            sprintf(outregstr, "|%s%s|", regstr, swzstr);
+            insert_line = 0;
+        } else {
+            shader_addline(buffer, "ABS T%c, %s;\n", 'A' + tmpreg, regstr);
+        }
+        break;
+    case WINED3DSPSM_ABSNEG:
+        if(ctx->target_version >= NV2) {
+            sprintf(outregstr, "-|%s%s|", regstr, swzstr);
+        } else {
+            shader_addline(buffer, "ABS T%c, %s;\n", 'A' + tmpreg, regstr);
+            sprintf(outregstr, "-T%c%s", 'A' + tmpreg, swzstr);
+        }
+        insert_line = 0;
+        break;
+    default:
+        sprintf(outregstr, "%s%s", regstr, swzstr);
+        insert_line = 0;
+    }
+
+    /* Return modified or original register, with swizzle */
+    if (insert_line)
+        sprintf(outregstr, "T%c%s", 'A' + tmpreg, swzstr);
+}
+
+static void pshader_hw_bem(const struct wined3d_shader_instruction *ins)
+{
+    const struct wined3d_shader_dst_param *dst = &ins->dst[0];
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    DWORD sampler_code = dst->reg.idx[0].offset;
+    char dst_name[50];
+    char src_name[2][50];
+
+    shader_arb_get_dst_param(ins, dst, dst_name);
+
+    /* Sampling the perturbation map in Tsrc was done already, including the signedness correction if needed
+     *
+     * Keep in mind that src_name[1] can be "TB" and src_name[0] can be "TA" because modifiers like _x2 are valid
+     * with bem. So delay loading the first parameter until after the perturbation calculation which needs two
+     * temps is done.
+     */
+    shader_arb_get_src_param(ins, &ins->src[1], 1, src_name[1]);
+    shader_addline(buffer, "SWZ TA, bumpenvmat%d, x, z, 0, 0;\n", sampler_code);
+    shader_addline(buffer, "DP3 TC.r, TA, %s;\n", src_name[1]);
+    shader_addline(buffer, "SWZ TA, bumpenvmat%d, y, w, 0, 0;\n", sampler_code);
+    shader_addline(buffer, "DP3 TC.g, TA, %s;\n", src_name[1]);
+
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src_name[0]);
+    shader_addline(buffer, "ADD %s, %s, TC;\n", dst_name, src_name[0]);
+}
+
+static DWORD negate_modifiers(DWORD mod, char *extra_char)
+{
+    *extra_char = ' ';
+    switch(mod)
+    {
+        case WINED3DSPSM_NONE:      return WINED3DSPSM_NEG;
+        case WINED3DSPSM_NEG:       return WINED3DSPSM_NONE;
+        case WINED3DSPSM_BIAS:      return WINED3DSPSM_BIASNEG;
+        case WINED3DSPSM_BIASNEG:   return WINED3DSPSM_BIAS;
+        case WINED3DSPSM_SIGN:      return WINED3DSPSM_SIGNNEG;
+        case WINED3DSPSM_SIGNNEG:   return WINED3DSPSM_SIGN;
+        case WINED3DSPSM_COMP:      *extra_char = '-'; return WINED3DSPSM_COMP;
+        case WINED3DSPSM_X2:        return WINED3DSPSM_X2NEG;
+        case WINED3DSPSM_X2NEG:     return WINED3DSPSM_X2;
+        case WINED3DSPSM_DZ:        *extra_char = '-'; return WINED3DSPSM_DZ;
+        case WINED3DSPSM_DW:        *extra_char = '-'; return WINED3DSPSM_DW;
+        case WINED3DSPSM_ABS:       return WINED3DSPSM_ABSNEG;
+        case WINED3DSPSM_ABSNEG:    return WINED3DSPSM_ABS;
+    }
+    FIXME("Unknown modifier %u\n", mod);
+    return mod;
+}
+
+static void pshader_hw_cnd(const struct wined3d_shader_instruction *ins)
+{
+    const struct wined3d_shader_dst_param *dst = &ins->dst[0];
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    char dst_name[50];
+    char src_name[3][50];
+    DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major,
+            ins->ctx->reg_maps->shader_version.minor);
+
+    shader_arb_get_dst_param(ins, dst, dst_name);
+    shader_arb_get_src_param(ins, &ins->src[1], 1, src_name[1]);
+
+    /* The coissue flag changes the semantic of the cnd instruction in <= 1.3 shaders */
+    if (shader_version <= WINED3D_SHADER_VERSION(1, 3) && ins->coissue)
+    {
+        shader_addline(buffer, "MOV%s %s, %s;\n", shader_arb_get_modifier(ins), dst_name, src_name[1]);
+    }
+    else
+    {
+        struct wined3d_shader_src_param src0_copy = ins->src[0];
+        char extra_neg;
+
+        /* src0 may have a negate srcmod set, so we can't blindly add "-" to the name */
+        src0_copy.modifiers = negate_modifiers(src0_copy.modifiers, &extra_neg);
+
+        shader_arb_get_src_param(ins, &src0_copy, 0, src_name[0]);
+        shader_arb_get_src_param(ins, &ins->src[2], 2, src_name[2]);
+        shader_addline(buffer, "ADD TA, %c%s, coefdiv.x;\n", extra_neg, src_name[0]);
+        shader_addline(buffer, "CMP%s %s, TA, %s, %s;\n", shader_arb_get_modifier(ins),
+                dst_name, src_name[1], src_name[2]);
+    }
+}
+
+static void pshader_hw_cmp(const struct wined3d_shader_instruction *ins)
+{
+    const struct wined3d_shader_dst_param *dst = &ins->dst[0];
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    char dst_name[50];
+    char src_name[3][50];
+
+    shader_arb_get_dst_param(ins, dst, dst_name);
+
+    /* Generate input register names (with modifiers) */
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src_name[0]);
+    shader_arb_get_src_param(ins, &ins->src[1], 1, src_name[1]);
+    shader_arb_get_src_param(ins, &ins->src[2], 2, src_name[2]);
+
+    shader_addline(buffer, "CMP%s %s, %s, %s, %s;\n", shader_arb_get_modifier(ins),
+            dst_name, src_name[0], src_name[2], src_name[1]);
+}
+
+/** Process the WINED3DSIO_DP2ADD instruction in ARB.
+ * dst = dot2(src0, src1) + src2 */
+static void pshader_hw_dp2add(const struct wined3d_shader_instruction *ins)
+{
+    const struct wined3d_shader_dst_param *dst = &ins->dst[0];
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    char dst_name[50];
+    char src_name[3][50];
+    struct shader_arb_ctx_priv *ctx = ins->ctx->backend_data;
+
+    shader_arb_get_dst_param(ins, dst, dst_name);
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src_name[0]);
+    shader_arb_get_src_param(ins, &ins->src[2], 2, src_name[2]);
+
+    if(ctx->target_version >= NV3)
+    {
+        /* GL_NV_fragment_program2 has a 1:1 matching instruction */
+        shader_arb_get_src_param(ins, &ins->src[1], 1, src_name[1]);
+        shader_addline(buffer, "DP2A%s %s, %s, %s, %s;\n", shader_arb_get_modifier(ins),
+                       dst_name, src_name[0], src_name[1], src_name[2]);
+    }
+    else if(ctx->target_version >= NV2)
+    {
+        /* dst.x = src2.?, src0.x, src1.x + src0.y * src1.y
+         * dst.y = src2.?, src0.x, src1.z + src0.y * src1.w
+         * dst.z = src2.?, src0.x, src1.x + src0.y * src1.y
+         * dst.z = src2.?, src0.x, src1.z + src0.y * src1.w
+         *
+         * Make sure that src1.zw = src1.xy, then we get a classic dp2add
+         *
+         * .xyxy and other swizzles that we could get with this are not valid in
+         * plain ARBfp, but luckily the NV extension grammar lifts this limitation.
+         */
+        struct wined3d_shader_src_param tmp_param = ins->src[1];
+        DWORD swizzle = tmp_param.swizzle & 0xf; /* Selects .xy */
+        tmp_param.swizzle = swizzle | (swizzle << 4); /* Creates .xyxy */
+
+        shader_arb_get_src_param(ins, &tmp_param, 1, src_name[1]);
+
+        shader_addline(buffer, "X2D%s %s, %s, %s, %s;\n", shader_arb_get_modifier(ins),
+                       dst_name, src_name[2], src_name[0], src_name[1]);
+    }
+    else
+    {
+        shader_arb_get_src_param(ins, &ins->src[1], 1, src_name[1]);
+        /* Emulate a DP2 with a DP3 and 0.0. Don't use the dest as temp register, it could be src[1] or src[2]
+        * src_name[0] can be TA, but TA is a private temp for modifiers, so it is save to overwrite
+        */
+        shader_addline(buffer, "MOV TA, %s;\n", src_name[0]);
+        shader_addline(buffer, "MOV TA.z, 0.0;\n");
+        shader_addline(buffer, "DP3 TA, TA, %s;\n", src_name[1]);
+        shader_addline(buffer, "ADD%s %s, TA, %s;\n", shader_arb_get_modifier(ins), dst_name, src_name[2]);
+    }
+}
+
+/* Map the opcode 1-to-1 to the GL code */
+static void shader_hw_map2gl(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    const char *instruction;
+    char arguments[256], dst_str[50];
+    unsigned int i;
+    const struct wined3d_shader_dst_param *dst = &ins->dst[0];
+
+    switch (ins->handler_idx)
+    {
+        case WINED3DSIH_ABS: instruction = "ABS"; break;
+        case WINED3DSIH_ADD: instruction = "ADD"; break;
+        case WINED3DSIH_CRS: instruction = "XPD"; break;
+        case WINED3DSIH_DP3: instruction = "DP3"; break;
+        case WINED3DSIH_DP4: instruction = "DP4"; break;
+        case WINED3DSIH_DST: instruction = "DST"; break;
+        case WINED3DSIH_FRC: instruction = "FRC"; break;
+        case WINED3DSIH_LIT: instruction = "LIT"; break;
+        case WINED3DSIH_LRP: instruction = "LRP"; break;
+        case WINED3DSIH_MAD: instruction = "MAD"; break;
+        case WINED3DSIH_MAX: instruction = "MAX"; break;
+        case WINED3DSIH_MIN: instruction = "MIN"; break;
+        case WINED3DSIH_MOV: instruction = "MOV"; break;
+        case WINED3DSIH_MUL: instruction = "MUL"; break;
+        case WINED3DSIH_SGE: instruction = "SGE"; break;
+        case WINED3DSIH_SLT: instruction = "SLT"; break;
+        case WINED3DSIH_SUB: instruction = "SUB"; break;
+        case WINED3DSIH_MOVA:instruction = "ARR"; break;
+        case WINED3DSIH_DSX: instruction = "DDX"; break;
+        default: instruction = "";
+            FIXME("Unhandled opcode %#x\n", ins->handler_idx);
+            break;
+    }
+
+    /* Note that shader_arb_add_dst_param() adds spaces. */
+    arguments[0] = '\0';
+    shader_arb_get_dst_param(ins, dst, dst_str);
+    for (i = 0; i < ins->src_count; ++i)
+    {
+        char operand[100];
+        strcat(arguments, ", ");
+        shader_arb_get_src_param(ins, &ins->src[i], i, operand);
+        strcat(arguments, operand);
+    }
+    shader_addline(buffer, "%s%s %s%s;\n", instruction, shader_arb_get_modifier(ins), dst_str, arguments);
+}
+
+static void shader_hw_nop(const struct wined3d_shader_instruction *ins) {}
+
+static void shader_hw_mov(const struct wined3d_shader_instruction *ins)
+{
+    const struct wined3d_shader *shader = ins->ctx->shader;
+    const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps;
+    BOOL pshader = shader_is_pshader_version(reg_maps->shader_version.type);
+    struct shader_arb_ctx_priv *ctx = ins->ctx->backend_data;
+    const char *zero = arb_get_helper_value(reg_maps->shader_version.type, ARB_ZERO);
+    const char *one = arb_get_helper_value(reg_maps->shader_version.type, ARB_ONE);
+    const char *two = arb_get_helper_value(reg_maps->shader_version.type, ARB_TWO);
+
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    char src0_param[256];
+
+    if (ins->handler_idx == WINED3DSIH_MOVA)
+    {
+        const struct arb_vshader_private *shader_data = shader->backend_data;
+        char write_mask[6];
+        const char *offset = arb_get_helper_value(WINED3D_SHADER_TYPE_VERTEX, ARB_VS_REL_OFFSET);
+
+        if(ctx->target_version >= NV2) {
+            shader_hw_map2gl(ins);
+            return;
+        }
+        shader_arb_get_src_param(ins, &ins->src[0], 0, src0_param);
+        shader_arb_get_write_mask(ins, &ins->dst[0], write_mask);
+
+        /* This implements the mova formula used in GLSL. The first two instructions
+         * prepare the sign() part. Note that it is fine to have my_sign(0.0) = 1.0
+         * in this case:
+         * mova A0.x, 0.0
+         *
+         * A0.x = arl(floor(abs(0.0) + 0.5) * 1.0) = floor(0.5) = 0.0 since arl does a floor
+         *
+         * The ARL is performed when A0 is used - the requested component is read from A0_SHADOW into
+         * A0.x. We can use the overwritten component of A0_shadow as temporary storage for the sign.
+         */
+        shader_addline(buffer, "SGE A0_SHADOW%s, %s, %s;\n", write_mask, src0_param, zero);
+        shader_addline(buffer, "MAD A0_SHADOW%s, A0_SHADOW, %s, -%s;\n", write_mask, two, one);
+
+        shader_addline(buffer, "ABS TA%s, %s;\n", write_mask, src0_param);
+        shader_addline(buffer, "ADD TA%s, TA, rel_addr_const.x;\n", write_mask);
+        shader_addline(buffer, "FLR TA%s, TA;\n", write_mask);
+        if (shader_data->rel_offset)
+        {
+            shader_addline(buffer, "ADD TA%s, TA, %s;\n", write_mask, offset);
+        }
+        shader_addline(buffer, "MUL A0_SHADOW%s, TA, A0_SHADOW;\n", write_mask);
+
+        ((struct shader_arb_ctx_priv *)ins->ctx->backend_data)->addr_reg[0] = '\0';
+    }
+    else if (reg_maps->shader_version.major == 1
+          && !shader_is_pshader_version(reg_maps->shader_version.type)
+          && ins->dst[0].reg.type == WINED3DSPR_ADDR)
+    {
+        const struct arb_vshader_private *shader_data = shader->backend_data;
+        src0_param[0] = '\0';
+
+        if (shader_data->rel_offset)
+        {
+            const char *offset = arb_get_helper_value(WINED3D_SHADER_TYPE_VERTEX, ARB_VS_REL_OFFSET);
+            shader_arb_get_src_param(ins, &ins->src[0], 0, src0_param);
+            shader_addline(buffer, "ADD TA.x, %s, %s;\n", src0_param, offset);
+            shader_addline(buffer, "ARL A0.x, TA.x;\n");
+        }
+        else
+        {
+            /* Apple's ARB_vertex_program implementation does not accept an ARL source argument
+             * with more than one component. Thus replicate the first source argument over all
+             * 4 components. For example, .xyzw -> .x (or better: .xxxx), .zwxy -> .z, etc) */
+            struct wined3d_shader_src_param tmp_src = ins->src[0];
+            tmp_src.swizzle = (tmp_src.swizzle & 0x3) * 0x55;
+            shader_arb_get_src_param(ins, &tmp_src, 0, src0_param);
+            shader_addline(buffer, "ARL A0.x, %s;\n", src0_param);
+        }
+    }
+    else if (ins->dst[0].reg.type == WINED3DSPR_COLOROUT && !ins->dst[0].reg.idx[0].offset && pshader)
+    {
+        if (ctx->cur_ps_args->super.srgb_correction && shader->u.ps.color0_mov)
+        {
+            shader_addline(buffer, "#mov handled in srgb write code\n");
+            return;
+        }
+        shader_hw_map2gl(ins);
+    }
+    else
+    {
+        shader_hw_map2gl(ins);
+    }
+}
+
+static void pshader_hw_texkill(const struct wined3d_shader_instruction *ins)
+{
+    const struct wined3d_shader_dst_param *dst = &ins->dst[0];
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    char reg_dest[40];
+
+    /* No swizzles are allowed in d3d's texkill. PS 1.x ignores the 4th component as documented,
+     * but >= 2.0 honors it (undocumented, but tested by the d3d9 testsuite)
+     */
+    shader_arb_get_dst_param(ins, dst, reg_dest);
+
+    if (ins->ctx->reg_maps->shader_version.major >= 2)
+    {
+        const char *kilsrc = "TA";
+        BOOL is_color;
+
+        shader_arb_get_register_name(ins, &dst->reg, reg_dest, &is_color);
+        if(dst->write_mask == WINED3DSP_WRITEMASK_ALL)
+        {
+            kilsrc = reg_dest;
+        }
+        else
+        {
+            /* Sigh. KIL doesn't support swizzles/writemasks. KIL passes a writemask, but ".xy" for example
+             * is not valid as a swizzle in ARB (needs ".xyyy"). Use SWZ to load the register properly, and set
+             * masked out components to 0(won't kill)
+             */
+            char x = '0', y = '0', z = '0', w = '0';
+            if(dst->write_mask & WINED3DSP_WRITEMASK_0) x = 'x';
+            if(dst->write_mask & WINED3DSP_WRITEMASK_1) y = 'y';
+            if(dst->write_mask & WINED3DSP_WRITEMASK_2) z = 'z';
+            if(dst->write_mask & WINED3DSP_WRITEMASK_3) w = 'w';
+            shader_addline(buffer, "SWZ TA, %s, %c, %c, %c, %c;\n", reg_dest, x, y, z, w);
+        }
+        shader_addline(buffer, "KIL %s;\n", kilsrc);
+    }
+    else
+    {
+        /* ARB fp doesn't like swizzles on the parameter of the KIL instruction. To mask the 4th component,
+         * copy the register into our general purpose TMP variable, overwrite .w and pass TMP to KIL
+         *
+         * ps_1_3 shaders use the texcoord incarnation of the Tx register. ps_1_4 shaders can use the same,
+         * or pass in any temporary register(in shader phase 2)
+         */
+        if (ins->ctx->reg_maps->shader_version.minor <= 3)
+            sprintf(reg_dest, "fragment.texcoord[%u]", dst->reg.idx[0].offset);
+        else
+            shader_arb_get_dst_param(ins, dst, reg_dest);
+        shader_addline(buffer, "SWZ TA, %s, x, y, z, 1;\n", reg_dest);
+        shader_addline(buffer, "KIL TA;\n");
+    }
+}
+
+static void pshader_hw_tex(const struct wined3d_shader_instruction *ins)
+{
+    struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
+    const struct wined3d_shader_dst_param *dst = &ins->dst[0];
+    DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major,
+            ins->ctx->reg_maps->shader_version.minor);
+    struct wined3d_shader_src_param src;
+
+    char reg_dest[40];
+    char reg_coord[40];
+    DWORD reg_sampler_code;
+    WORD myflags = 0;
+    BOOL swizzle_coord = FALSE;
+
+    /* All versions have a destination register */
+    shader_arb_get_dst_param(ins, dst, reg_dest);
+
+    /* 1.0-1.4: Use destination register number as texture code.
+       2.0+: Use provided sampler number as texure code. */
+    if (shader_version < WINED3D_SHADER_VERSION(2,0))
+        reg_sampler_code = dst->reg.idx[0].offset;
+    else
+        reg_sampler_code = ins->src[1].reg.idx[0].offset;
+
+    /* 1.0-1.3: Use the texcoord varying.
+       1.4+: Use provided coordinate source register. */
+    if (shader_version < WINED3D_SHADER_VERSION(1,4))
+        sprintf(reg_coord, "fragment.texcoord[%u]", reg_sampler_code);
+    else {
+        /* TEX is the only instruction that can handle DW and DZ natively */
+        src = ins->src[0];
+        if(src.modifiers == WINED3DSPSM_DW) src.modifiers = WINED3DSPSM_NONE;
+        if(src.modifiers == WINED3DSPSM_DZ) src.modifiers = WINED3DSPSM_NONE;
+        shader_arb_get_src_param(ins, &src, 0, reg_coord);
+    }
+
+    /* projection flag:
+     * 1.1, 1.2, 1.3: Use WINED3D_TSS_TEXTURETRANSFORMFLAGS
+     * 1.4: Use WINED3DSPSM_DZ or WINED3DSPSM_DW on src[0]
+     * 2.0+: Use WINED3DSI_TEXLD_PROJECT on the opcode
+     */
+    if (shader_version < WINED3D_SHADER_VERSION(1,4))
+    {
+        DWORD flags = 0;
+        if (reg_sampler_code < MAX_TEXTURES)
+            flags = priv->cur_ps_args->super.tex_transform >> reg_sampler_code * WINED3D_PSARGS_TEXTRANSFORM_SHIFT;
+        if (flags & WINED3D_PSARGS_PROJECTED)
+        {
+            myflags |= TEX_PROJ;
+            if ((flags & ~WINED3D_PSARGS_PROJECTED) == WINED3D_TTFF_COUNT3)
+                swizzle_coord = TRUE;
+        }
+    }
+    else if (shader_version < WINED3D_SHADER_VERSION(2,0))
+    {
+        enum wined3d_shader_src_modifier src_mod = ins->src[0].modifiers;
+        if (src_mod == WINED3DSPSM_DZ)
+        {
+            swizzle_coord = TRUE;
+            myflags |= TEX_PROJ;
+        } else if(src_mod == WINED3DSPSM_DW) {
+            myflags |= TEX_PROJ;
+        }
+    } else {
+        if (ins->flags & WINED3DSI_TEXLD_PROJECT) myflags |= TEX_PROJ;
+        if (ins->flags & WINED3DSI_TEXLD_BIAS) myflags |= TEX_BIAS;
+    }
+
+    if (swizzle_coord)
+    {
+        /* TXP cannot handle DZ natively, so move the z coordinate to .w.
+         * reg_coord is a read-only varying register, so we need a temp reg */
+        shader_addline(ins->ctx->buffer, "SWZ TA, %s, x, y, z, z;\n", reg_coord);
+        strcpy(reg_coord, "TA");
+    }
+
+    shader_hw_sample(ins, reg_sampler_code, reg_dest, reg_coord, myflags, NULL, NULL);
+}
+
+static void pshader_hw_texcoord(const struct wined3d_shader_instruction *ins)
+{
+    const struct wined3d_shader_dst_param *dst = &ins->dst[0];
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major,
+            ins->ctx->reg_maps->shader_version.minor);
+    char dst_str[50];
+
+    if (shader_version < WINED3D_SHADER_VERSION(1,4))
+    {
+        DWORD reg = dst->reg.idx[0].offset;
+
+        shader_arb_get_dst_param(ins, &ins->dst[0], dst_str);
+        shader_addline(buffer, "MOV_SAT %s, fragment.texcoord[%u];\n", dst_str, reg);
+    } else {
+        char reg_src[40];
+
+        shader_arb_get_src_param(ins, &ins->src[0], 0, reg_src);
+        shader_arb_get_dst_param(ins, &ins->dst[0], dst_str);
+        shader_addline(buffer, "MOV %s, %s;\n", dst_str, reg_src);
+   }
+}
+
+static void pshader_hw_texreg2ar(const struct wined3d_shader_instruction *ins)
+{
+     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+     DWORD flags = 0;
+
+     DWORD reg1 = ins->dst[0].reg.idx[0].offset;
+     char dst_str[50];
+     char src_str[50];
+
+     /* Note that texreg2ar treats Tx as a temporary register, not as a varying */
+     shader_arb_get_dst_param(ins, &ins->dst[0], dst_str);
+     shader_arb_get_src_param(ins, &ins->src[0], 0, src_str);
+     /* Move .x first in case src_str is "TA" */
+     shader_addline(buffer, "MOV TA.y, %s.x;\n", src_str);
+     shader_addline(buffer, "MOV TA.x, %s.w;\n", src_str);
+     if (reg1 < MAX_TEXTURES)
+     {
+         struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
+         flags = priv->cur_ps_args->super.tex_transform >> reg1 * WINED3D_PSARGS_TEXTRANSFORM_SHIFT;
+     }
+     shader_hw_sample(ins, reg1, dst_str, "TA", flags & WINED3D_PSARGS_PROJECTED ? TEX_PROJ : 0, NULL, NULL);
+}
+
+static void pshader_hw_texreg2gb(const struct wined3d_shader_instruction *ins)
+{
+     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+
+     DWORD reg1 = ins->dst[0].reg.idx[0].offset;
+     char dst_str[50];
+     char src_str[50];
+
+     /* Note that texreg2gb treats Tx as a temporary register, not as a varying */
+     shader_arb_get_dst_param(ins, &ins->dst[0], dst_str);
+     shader_arb_get_src_param(ins, &ins->src[0], 0, src_str);
+     shader_addline(buffer, "MOV TA.x, %s.y;\n", src_str);
+     shader_addline(buffer, "MOV TA.y, %s.z;\n", src_str);
+     shader_hw_sample(ins, reg1, dst_str, "TA", 0, NULL, NULL);
+}
+
+static void pshader_hw_texreg2rgb(const struct wined3d_shader_instruction *ins)
+{
+    DWORD reg1 = ins->dst[0].reg.idx[0].offset;
+    char dst_str[50];
+    char src_str[50];
+
+    /* Note that texreg2rg treats Tx as a temporary register, not as a varying */
+    shader_arb_get_dst_param(ins, &ins->dst[0], dst_str);
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src_str);
+    shader_hw_sample(ins, reg1, dst_str, src_str, 0, NULL, NULL);
+}
+
+static void pshader_hw_texbem(const struct wined3d_shader_instruction *ins)
+{
+    struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
+    const struct wined3d_shader_dst_param *dst = &ins->dst[0];
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    char reg_coord[40], dst_reg[50], src_reg[50];
+    DWORD reg_dest_code;
+
+    /* All versions have a destination register. The Tx where the texture coordinates come
+     * from is the varying incarnation of the texture register
+     */
+    reg_dest_code = dst->reg.idx[0].offset;
+    shader_arb_get_dst_param(ins, &ins->dst[0], dst_reg);
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src_reg);
+    sprintf(reg_coord, "fragment.texcoord[%u]", reg_dest_code);
+
+    /* Sampling the perturbation map in Tsrc was done already, including the signedness correction if needed
+     * The Tx in which the perturbation map is stored is the tempreg incarnation of the texture register
+     *
+     * GL_NV_fragment_program_option could handle this in one instruction via X2D:
+     * X2D TA.xy, fragment.texcoord, T%u, bumpenvmat%u.xzyw
+     *
+     * However, the NV extensions are never enabled for <= 2.0 shaders because of the performance penalty that
+     * comes with it, and texbem is an 1.x only instruction. No 1.x instruction forces us to enable the NV
+     * extension.
+     */
+    shader_addline(buffer, "SWZ TB, bumpenvmat%d, x, z, 0, 0;\n", reg_dest_code);
+    shader_addline(buffer, "DP3 TA.x, TB, %s;\n", src_reg);
+    shader_addline(buffer, "SWZ TB, bumpenvmat%d, y, w, 0, 0;\n", reg_dest_code);
+    shader_addline(buffer, "DP3 TA.y, TB, %s;\n", src_reg);
+
+    /* with projective textures, texbem only divides the static texture coord, not the displacement,
+     * so we can't let the GL handle this.
+     */
+    if ((priv->cur_ps_args->super.tex_transform >> reg_dest_code * WINED3D_PSARGS_TEXTRANSFORM_SHIFT)
+            & WINED3D_PSARGS_PROJECTED)
+    {
+        shader_addline(buffer, "RCP TB.w, %s.w;\n", reg_coord);
+        shader_addline(buffer, "MUL TB.xy, %s, TB.w;\n", reg_coord);
+        shader_addline(buffer, "ADD TA.xy, TA, TB;\n");
+    } else {
+        shader_addline(buffer, "ADD TA.xy, TA, %s;\n", reg_coord);
+    }
+
+    shader_hw_sample(ins, reg_dest_code, dst_reg, "TA", 0, NULL, NULL);
+
+    if (ins->handler_idx == WINED3DSIH_TEXBEML)
+    {
+        /* No src swizzles are allowed, so this is ok */
+        shader_addline(buffer, "MAD TA, %s.z, luminance%d.x, luminance%d.y;\n",
+                       src_reg, reg_dest_code, reg_dest_code);
+        shader_addline(buffer, "MUL %s, %s, TA;\n", dst_reg, dst_reg);
+    }
+}
+
+static void pshader_hw_texm3x2pad(const struct wined3d_shader_instruction *ins)
+{
+    DWORD reg = ins->dst[0].reg.idx[0].offset;
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    char src0_name[50], dst_name[50];
+    BOOL is_color;
+    struct wined3d_shader_register tmp_reg = ins->dst[0].reg;
+
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src0_name);
+    /* The next instruction will be a texm3x2tex or texm3x2depth that writes to the uninitialized
+     * T<reg+1> register. Use this register to store the calculated vector
+     */
+    tmp_reg.idx[0].offset = reg + 1;
+    shader_arb_get_register_name(ins, &tmp_reg, dst_name, &is_color);
+    shader_addline(buffer, "DP3 %s.x, fragment.texcoord[%u], %s;\n", dst_name, reg, src0_name);
+}
+
+static void pshader_hw_texm3x2tex(const struct wined3d_shader_instruction *ins)
+{
+    struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
+    DWORD flags;
+    DWORD reg = ins->dst[0].reg.idx[0].offset;
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    char dst_str[50];
+    char src0_name[50];
+    char dst_reg[50];
+    BOOL is_color;
+
+    /* We know that we're writing to the uninitialized T<reg> register, so use it for temporary storage */
+    shader_arb_get_register_name(ins, &ins->dst[0].reg, dst_reg, &is_color);
+
+    shader_arb_get_dst_param(ins, &ins->dst[0], dst_str);
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src0_name);
+    shader_addline(buffer, "DP3 %s.y, fragment.texcoord[%u], %s;\n", dst_reg, reg, src0_name);
+    flags = reg < MAX_TEXTURES ? priv->cur_ps_args->super.tex_transform >> reg * WINED3D_PSARGS_TEXTRANSFORM_SHIFT : 0;
+    shader_hw_sample(ins, reg, dst_str, dst_reg, flags & WINED3D_PSARGS_PROJECTED ? TEX_PROJ : 0, NULL, NULL);
+}
+
+static void pshader_hw_texm3x3pad(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_tex_mx *tex_mx = ins->ctx->tex_mx;
+    DWORD reg = ins->dst[0].reg.idx[0].offset;
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    char src0_name[50], dst_name[50];
+    struct wined3d_shader_register tmp_reg = ins->dst[0].reg;
+    BOOL is_color;
+
+    /* There are always 2 texm3x3pad instructions followed by one texm3x3[tex,vspec, ...] instruction, with
+     * incrementing ins->dst[0].register_idx numbers. So the pad instruction already knows the final destination
+     * register, and this register is uninitialized(otherwise the assembler complains that it is 'redeclared')
+     */
+    tmp_reg.idx[0].offset = reg + 2 - tex_mx->current_row;
+    shader_arb_get_register_name(ins, &tmp_reg, dst_name, &is_color);
+
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src0_name);
+    shader_addline(buffer, "DP3 %s.%c, fragment.texcoord[%u], %s;\n",
+                   dst_name, 'x' + tex_mx->current_row, reg, src0_name);
+    tex_mx->texcoord_w[tex_mx->current_row++] = reg;
+}
+
+static void pshader_hw_texm3x3tex(const struct wined3d_shader_instruction *ins)
+{
+    struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
+    struct wined3d_shader_tex_mx *tex_mx = ins->ctx->tex_mx;
+    DWORD flags;
+    DWORD reg = ins->dst[0].reg.idx[0].offset;
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    char dst_str[50];
+    char src0_name[50], dst_name[50];
+    BOOL is_color;
+
+    shader_arb_get_register_name(ins, &ins->dst[0].reg, dst_name, &is_color);
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src0_name);
+    shader_addline(buffer, "DP3 %s.z, fragment.texcoord[%u], %s;\n", dst_name, reg, src0_name);
+
+    /* Sample the texture using the calculated coordinates */
+    shader_arb_get_dst_param(ins, &ins->dst[0], dst_str);
+    flags = reg < MAX_TEXTURES ? priv->cur_ps_args->super.tex_transform >> reg * WINED3D_PSARGS_TEXTRANSFORM_SHIFT : 0;
+    shader_hw_sample(ins, reg, dst_str, dst_name, flags & WINED3D_PSARGS_PROJECTED ? TEX_PROJ : 0, NULL, NULL);
+    tex_mx->current_row = 0;
+}
+
+static void pshader_hw_texm3x3vspec(const struct wined3d_shader_instruction *ins)
+{
+    struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
+    struct wined3d_shader_tex_mx *tex_mx = ins->ctx->tex_mx;
+    DWORD flags;
+    DWORD reg = ins->dst[0].reg.idx[0].offset;
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    char dst_str[50];
+    char src0_name[50];
+    char dst_reg[50];
+    BOOL is_color;
+
+    /* Get the dst reg without writemask strings. We know this register is uninitialized, so we can use all
+     * components for temporary data storage
+     */
+    shader_arb_get_register_name(ins, &ins->dst[0].reg, dst_reg, &is_color);
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src0_name);
+    shader_addline(buffer, "DP3 %s.z, fragment.texcoord[%u], %s;\n", dst_reg, reg, src0_name);
+
+    /* Construct the eye-ray vector from w coordinates */
+    shader_addline(buffer, "MOV TB.x, fragment.texcoord[%u].w;\n", tex_mx->texcoord_w[0]);
+    shader_addline(buffer, "MOV TB.y, fragment.texcoord[%u].w;\n", tex_mx->texcoord_w[1]);
+    shader_addline(buffer, "MOV TB.z, fragment.texcoord[%u].w;\n", reg);
+
+    /* Calculate reflection vector
+     */
+    shader_addline(buffer, "DP3 %s.w, %s, TB;\n", dst_reg, dst_reg);
+    /* The .w is ignored when sampling, so I can use TB.w to calculate dot(N, N) */
+    shader_addline(buffer, "DP3 TB.w, %s, %s;\n", dst_reg, dst_reg);
+    shader_addline(buffer, "RCP TB.w, TB.w;\n");
+    shader_addline(buffer, "MUL %s.w, %s.w, TB.w;\n", dst_reg, dst_reg);
+    shader_addline(buffer, "MUL %s, %s.w, %s;\n", dst_reg, dst_reg, dst_reg);
+    shader_addline(buffer, "MAD %s, coefmul.x, %s, -TB;\n", dst_reg, dst_reg);
+
+    /* Sample the texture using the calculated coordinates */
+    shader_arb_get_dst_param(ins, &ins->dst[0], dst_str);
+    flags = reg < MAX_TEXTURES ? priv->cur_ps_args->super.tex_transform >> reg * WINED3D_PSARGS_TEXTRANSFORM_SHIFT : 0;
+    shader_hw_sample(ins, reg, dst_str, dst_reg, flags & WINED3D_PSARGS_PROJECTED ? TEX_PROJ : 0, NULL, NULL);
+    tex_mx->current_row = 0;
+}
+
+static void pshader_hw_texm3x3spec(const struct wined3d_shader_instruction *ins)
+{
+    struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
+    struct wined3d_shader_tex_mx *tex_mx = ins->ctx->tex_mx;
+    DWORD flags;
+    DWORD reg = ins->dst[0].reg.idx[0].offset;
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    char dst_str[50];
+    char src0_name[50];
+    char src1_name[50];
+    char dst_reg[50];
+    BOOL is_color;
+
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src0_name);
+    shader_arb_get_src_param(ins, &ins->src[0], 1, src1_name);
+    shader_arb_get_register_name(ins, &ins->dst[0].reg, dst_reg, &is_color);
+    /* Note: dst_reg.xy is input here, generated by two texm3x3pad instructions */
+    shader_addline(buffer, "DP3 %s.z, fragment.texcoord[%u], %s;\n", dst_reg, reg, src0_name);
+
+    /* Calculate reflection vector.
+     *
+     *                   dot(N, E)
+     * dst_reg.xyz = 2 * --------- * N - E
+     *                   dot(N, N)
+     *
+     * Which normalizes the normal vector
+     */
+    shader_addline(buffer, "DP3 %s.w, %s, %s;\n", dst_reg, dst_reg, src1_name);
+    shader_addline(buffer, "DP3 TC.w, %s, %s;\n", dst_reg, dst_reg);
+    shader_addline(buffer, "RCP TC.w, TC.w;\n");
+    shader_addline(buffer, "MUL %s.w, %s.w, TC.w;\n", dst_reg, dst_reg);
+    shader_addline(buffer, "MUL %s, %s.w, %s;\n", dst_reg, dst_reg, dst_reg);
+    shader_addline(buffer, "MAD %s, coefmul.x, %s, -%s;\n", dst_reg, dst_reg, src1_name);
+
+    /* Sample the texture using the calculated coordinates */
+    shader_arb_get_dst_param(ins, &ins->dst[0], dst_str);
+    flags = reg < MAX_TEXTURES ? priv->cur_ps_args->super.tex_transform >> reg * WINED3D_PSARGS_TEXTRANSFORM_SHIFT : 0;
+    shader_hw_sample(ins, reg, dst_str, dst_reg, flags & WINED3D_PSARGS_PROJECTED ? TEX_PROJ : 0, NULL, NULL);
+    tex_mx->current_row = 0;
+}
+
+static void pshader_hw_texdepth(const struct wined3d_shader_instruction *ins)
+{
+    const struct wined3d_shader_dst_param *dst = &ins->dst[0];
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    char dst_name[50];
+    const char *zero = arb_get_helper_value(ins->ctx->reg_maps->shader_version.type, ARB_ZERO);
+    const char *one = arb_get_helper_value(ins->ctx->reg_maps->shader_version.type, ARB_ONE);
+
+    /* texdepth has an implicit destination, the fragment depth value. It's only parameter,
+     * which is essentially an input, is the destination register because it is the first
+     * parameter. According to the msdn, this must be register r5, but let's keep it more flexible
+     * here(writemasks/swizzles are not valid on texdepth)
+     */
+    shader_arb_get_dst_param(ins, dst, dst_name);
+
+    /* According to the msdn, the source register(must be r5) is unusable after
+     * the texdepth instruction, so we're free to modify it
+     */
+    shader_addline(buffer, "MIN %s.y, %s.y, %s;\n", dst_name, dst_name, one);
+
+    /* How to deal with the special case dst_name.g == 0? if r != 0, then
+     * the r * (1 / 0) will give infinity, which is clamped to 1.0, the correct
+     * result. But if r = 0.0, then 0 * inf = 0, which is incorrect.
+     */
+    shader_addline(buffer, "RCP %s.y, %s.y;\n", dst_name, dst_name);
+    shader_addline(buffer, "MUL TA.x, %s.x, %s.y;\n", dst_name, dst_name);
+    shader_addline(buffer, "MIN TA.x, TA.x, %s;\n", one);
+    shader_addline(buffer, "MAX result.depth, TA.x, %s;\n", zero);
+}
+
+/** Process the WINED3DSIO_TEXDP3TEX instruction in ARB:
+ * Take a 3-component dot product of the TexCoord[dstreg] and src,
+ * then perform a 1D texture lookup from stage dstregnum, place into dst. */
+static void pshader_hw_texdp3tex(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    DWORD sampler_idx = ins->dst[0].reg.idx[0].offset;
+    char src0[50];
+    char dst_str[50];
+
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src0);
+    shader_addline(buffer, "MOV TB, 0.0;\n");
+    shader_addline(buffer, "DP3 TB.x, fragment.texcoord[%u], %s;\n", sampler_idx, src0);
+
+    shader_arb_get_dst_param(ins, &ins->dst[0], dst_str);
+    shader_hw_sample(ins, sampler_idx, dst_str, "TB", 0 /* Only one coord, can't be projected */, NULL, NULL);
+}
+
+/** Process the WINED3DSIO_TEXDP3 instruction in ARB:
+ * Take a 3-component dot product of the TexCoord[dstreg] and src. */
+static void pshader_hw_texdp3(const struct wined3d_shader_instruction *ins)
+{
+    const struct wined3d_shader_dst_param *dst = &ins->dst[0];
+    char src0[50];
+    char dst_str[50];
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+
+    /* Handle output register */
+    shader_arb_get_dst_param(ins, dst, dst_str);
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src0);
+    shader_addline(buffer, "DP3 %s, fragment.texcoord[%u], %s;\n", dst_str, dst->reg.idx[0].offset, src0);
+}
+
+/** Process the WINED3DSIO_TEXM3X3 instruction in ARB
+ * Perform the 3rd row of a 3x3 matrix multiply */
+static void pshader_hw_texm3x3(const struct wined3d_shader_instruction *ins)
+{
+    const struct wined3d_shader_dst_param *dst = &ins->dst[0];
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    char dst_str[50], dst_name[50];
+    char src0[50];
+    BOOL is_color;
+
+    shader_arb_get_dst_param(ins, dst, dst_str);
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src0);
+    shader_arb_get_register_name(ins, &ins->dst[0].reg, dst_name, &is_color);
+    shader_addline(buffer, "DP3 %s.z, fragment.texcoord[%u], %s;\n", dst_name, dst->reg.idx[0].offset, src0);
+    shader_addline(buffer, "MOV %s, %s;\n", dst_str, dst_name);
+}
+
+/** Process the WINED3DSIO_TEXM3X2DEPTH instruction in ARB:
+ * Last row of a 3x2 matrix multiply, use the result to calculate the depth:
+ * Calculate tmp0.y = TexCoord[dstreg] . src.xyz;  (tmp0.x has already been calculated)
+ * depth = (tmp0.y == 0.0) ? 1.0 : tmp0.x / tmp0.y
+ */
+static void pshader_hw_texm3x2depth(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    const struct wined3d_shader_dst_param *dst = &ins->dst[0];
+    char src0[50], dst_name[50];
+    BOOL is_color;
+    const char *zero = arb_get_helper_value(ins->ctx->reg_maps->shader_version.type, ARB_ZERO);
+    const char *one = arb_get_helper_value(ins->ctx->reg_maps->shader_version.type, ARB_ONE);
+
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src0);
+    shader_arb_get_register_name(ins, &ins->dst[0].reg, dst_name, &is_color);
+    shader_addline(buffer, "DP3 %s.y, fragment.texcoord[%u], %s;\n", dst_name, dst->reg.idx[0].offset, src0);
+
+    /* How to deal with the special case dst_name.g == 0? if r != 0, then
+     * the r * (1 / 0) will give infinity, which is clamped to 1.0, the correct
+     * result. But if r = 0.0, then 0 * inf = 0, which is incorrect.
+     */
+    shader_addline(buffer, "RCP %s.y, %s.y;\n", dst_name, dst_name);
+    shader_addline(buffer, "MUL %s.x, %s.x, %s.y;\n", dst_name, dst_name, dst_name);
+    shader_addline(buffer, "MIN %s.x, %s.x, %s;\n", dst_name, dst_name, one);
+    shader_addline(buffer, "MAX result.depth, %s.x, %s;\n", dst_name, zero);
+}
+
+/** Handles transforming all WINED3DSIO_M?x? opcodes for
+    Vertex/Pixel shaders to ARB_vertex_program codes */
+static void shader_hw_mnxn(const struct wined3d_shader_instruction *ins)
+{
+    int i;
+    int nComponents = 0;
+    struct wined3d_shader_dst_param tmp_dst = {{0}};
+    struct wined3d_shader_src_param tmp_src[2] = {{{0}}};
+    struct wined3d_shader_instruction tmp_ins;
+
+    memset(&tmp_ins, 0, sizeof(tmp_ins));
+
+    /* Set constants for the temporary argument */
+    tmp_ins.ctx = ins->ctx;
+    tmp_ins.dst_count = 1;
+    tmp_ins.dst = &tmp_dst;
+    tmp_ins.src_count = 2;
+    tmp_ins.src = tmp_src;
+
+    switch(ins->handler_idx)
+    {
+        case WINED3DSIH_M4x4:
+            nComponents = 4;
+            tmp_ins.handler_idx = WINED3DSIH_DP4;
+            break;
+        case WINED3DSIH_M4x3:
+            nComponents = 3;
+            tmp_ins.handler_idx = WINED3DSIH_DP4;
+            break;
+        case WINED3DSIH_M3x4:
+            nComponents = 4;
+            tmp_ins.handler_idx = WINED3DSIH_DP3;
+            break;
+        case WINED3DSIH_M3x3:
+            nComponents = 3;
+            tmp_ins.handler_idx = WINED3DSIH_DP3;
+            break;
+        case WINED3DSIH_M3x2:
+            nComponents = 2;
+            tmp_ins.handler_idx = WINED3DSIH_DP3;
+            break;
+        default:
+            FIXME("Unhandled opcode %#x\n", ins->handler_idx);
+            break;
+    }
+
+    tmp_dst = ins->dst[0];
+    tmp_src[0] = ins->src[0];
+    tmp_src[1] = ins->src[1];
+    for (i = 0; i < nComponents; ++i)
+    {
+        tmp_dst.write_mask = WINED3DSP_WRITEMASK_0 << i;
+        shader_hw_map2gl(&tmp_ins);
+        ++tmp_src[1].reg.idx[0].offset;
+    }
+}
+
+static void shader_hw_rcp(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+
+    char dst[50];
+    char src[50];
+
+    shader_arb_get_dst_param(ins, &ins->dst[0], dst); /* Destination */
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src);
+    if (ins->src[0].swizzle == WINED3DSP_NOSWIZZLE)
+    {
+        /* Dx sdk says .x is used if no swizzle is given, but our test shows that
+         * .w is used
+         */
+        strcat(src, ".w");
+    }
+
+    shader_addline(buffer, "RCP%s %s, %s;\n", shader_arb_get_modifier(ins), dst, src);
+}
+
+static void shader_hw_scalar_op(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    const char *instruction;
+
+    char dst[50];
+    char src[50];
+
+    switch(ins->handler_idx)
+    {
+        case WINED3DSIH_RSQ:  instruction = "RSQ"; break;
+        case WINED3DSIH_RCP:  instruction = "RCP"; break;
+        case WINED3DSIH_EXP:  instruction = "EX2"; break;
+        case WINED3DSIH_EXPP: instruction = "EXP"; break;
+        default: instruction = "";
+            FIXME("Unhandled opcode %#x\n", ins->handler_idx);
+            break;
+    }
+
+    shader_arb_get_dst_param(ins, &ins->dst[0], dst); /* Destination */
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src);
+    if (ins->src[0].swizzle == WINED3DSP_NOSWIZZLE)
+    {
+        /* Dx sdk says .x is used if no swizzle is given, but our test shows that
+         * .w is used
+         */
+        strcat(src, ".w");
+    }
+
+    shader_addline(buffer, "%s%s %s, %s;\n", instruction, shader_arb_get_modifier(ins), dst, src);
+}
+
+static void shader_hw_nrm(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    char dst_name[50];
+    char src_name[50];
+    struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
+    BOOL pshader = shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type);
+    const char *zero = arb_get_helper_value(ins->ctx->reg_maps->shader_version.type, ARB_ZERO);
+
+    shader_arb_get_dst_param(ins, &ins->dst[0], dst_name);
+    shader_arb_get_src_param(ins, &ins->src[0], 1 /* Use TB */, src_name);
+
+    /* In D3D, NRM of a vector with length zero returns zero. Catch this situation, as
+     * otherwise NRM or RSQ would return NaN */
+    if(pshader && priv->target_version >= NV3)
+    {
+        /* GL_NV_fragment_program2's NRM needs protection against length zero vectors too
+         *
+         * TODO: Find out if DP3+NRM+MOV is really faster than DP3+RSQ+MUL
+         */
+        shader_addline(buffer, "DP3C TA, %s, %s;\n", src_name, src_name);
+        shader_addline(buffer, "NRM%s %s, %s;\n", shader_arb_get_modifier(ins), dst_name, src_name);
+        shader_addline(buffer, "MOV %s (EQ), %s;\n", dst_name, zero);
+    }
+    else if(priv->target_version >= NV2)
+    {
+        shader_addline(buffer, "DP3C TA.x, %s, %s;\n", src_name, src_name);
+        shader_addline(buffer, "RSQ TA.x (NE), TA.x;\n");
+        shader_addline(buffer, "MUL%s %s, %s, TA.x;\n", shader_arb_get_modifier(ins), dst_name,
+                       src_name);
+    }
+    else
+    {
+        const char *one = arb_get_helper_value(ins->ctx->reg_maps->shader_version.type, ARB_ONE);
+
+        shader_addline(buffer, "DP3 TA.x, %s, %s;\n", src_name, src_name);
+        /* Pass any non-zero value to RSQ if the input vector has a length of zero. The
+         * RSQ result doesn't matter, as long as multiplying it by 0 returns 0.
+         */
+        shader_addline(buffer, "SGE TA.y, -TA.x, %s;\n", zero);
+        shader_addline(buffer, "MAD TA.x, %s, TA.y, TA.x;\n", one);
+
+        shader_addline(buffer, "RSQ TA.x, TA.x;\n");
+        /* dst.w = src[0].w * 1 / (src.x^2 + src.y^2 + src.z^2)^(1/2) according to msdn*/
+        shader_addline(buffer, "MUL%s %s, %s, TA.x;\n", shader_arb_get_modifier(ins), dst_name,
+                    src_name);
+    }
+}
+
+static void shader_hw_lrp(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    char dst_name[50];
+    char src_name[3][50];
+
+    /* ARB_fragment_program has a convenient LRP instruction */
+    if(shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type)) {
+        shader_hw_map2gl(ins);
+        return;
+    }
+
+    shader_arb_get_dst_param(ins, &ins->dst[0], dst_name);
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src_name[0]);
+    shader_arb_get_src_param(ins, &ins->src[1], 1, src_name[1]);
+    shader_arb_get_src_param(ins, &ins->src[2], 2, src_name[2]);
+
+    shader_addline(buffer, "SUB TA, %s, %s;\n", src_name[1], src_name[2]);
+    shader_addline(buffer, "MAD%s %s, %s, TA, %s;\n", shader_arb_get_modifier(ins),
+                   dst_name, src_name[0], src_name[2]);
+}
+
+static void shader_hw_sincos(const struct wined3d_shader_instruction *ins)
+{
+    /* This instruction exists in ARB, but the d3d instruction takes two extra parameters which
+     * must contain fixed constants. So we need a separate function to filter those constants and
+     * can't use map2gl
+     */
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
+    const struct wined3d_shader_dst_param *dst = &ins->dst[0];
+    char dst_name[50];
+    char src_name0[50], src_name1[50], src_name2[50];
+    BOOL is_color;
+
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src_name0);
+    if(shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type)) {
+        shader_arb_get_dst_param(ins, &ins->dst[0], dst_name);
+        /* No modifiers are supported on SCS */
+        shader_addline(buffer, "SCS %s, %s;\n", dst_name, src_name0);
+
+        if(ins->dst[0].modifiers & WINED3DSPDM_SATURATE)
+        {
+            shader_arb_get_register_name(ins, &dst->reg, src_name0, &is_color);
+            shader_addline(buffer, "MOV_SAT %s, %s;\n", dst_name, src_name0);
+        }
+    } else if(priv->target_version >= NV2) {
+        shader_arb_get_register_name(ins, &dst->reg, dst_name, &is_color);
+
+        /* Sincos writemask must be .x, .y or .xy */
+        if(dst->write_mask & WINED3DSP_WRITEMASK_0)
+            shader_addline(buffer, "COS%s %s.x, %s;\n", shader_arb_get_modifier(ins), dst_name, src_name0);
+        if(dst->write_mask & WINED3DSP_WRITEMASK_1)
+            shader_addline(buffer, "SIN%s %s.y, %s;\n", shader_arb_get_modifier(ins), dst_name, src_name0);
+    } else {
+        /* Approximate sine and cosine with a taylor series, as per math textbook. The application passes 8
+         * helper constants(D3DSINCOSCONST1 and D3DSINCOSCONST2) in src1 and src2.
+         *
+         * sin(x) = x - x^3/3! + x^5/5! - x^7/7! + ...
+         * cos(x) = 1 - x^2/2! + x^4/4! - x^6/6! + ...
+         *
+         * The constants we get are:
+         *
+         *  +1   +1,     -1     -1     +1      +1      -1       -1
+         *      ---- ,  ---- , ---- , ----- , ----- , ----- , ------
+         *      1!*2    2!*4   3!*8   4!*16   5!*32   6!*64   7!*128
+         *
+         * If used with x^2, x^3, x^4 etc they calculate sin(x/2) and cos(x/2):
+         *
+         * (x/2)^2 = x^2 / 4
+         * (x/2)^3 = x^3 / 8
+         * (x/2)^4 = x^4 / 16
+         * (x/2)^5 = x^5 / 32
+         * etc
+         *
+         * To get the final result:
+         * sin(x) = 2 * sin(x/2) * cos(x/2)
+         * cos(x) = cos(x/2)^2 - sin(x/2)^2
+         * (from sin(x+y) and cos(x+y) rules)
+         *
+         * As per MSDN, dst.z is undefined after the operation, and so is
+         * dst.x and dst.y if they're masked out by the writemask. Ie
+         * sincos dst.y, src1, c0, c1
+         * returns the sine in dst.y. dst.x and dst.z are undefined, dst.w is not touched. The assembler
+         * vsa.exe also stops with an error if the dest register is the same register as the source
+         * register. This means we can use dest.xyz as temporary storage. The assembler vsa.exe output also
+         * indicates that sincos consumes 8 instruction slots in vs_2_0(and, strangely, in vs_3_0).
+         */
+        shader_arb_get_src_param(ins, &ins->src[1], 1, src_name1);
+        shader_arb_get_src_param(ins, &ins->src[2], 2, src_name2);
+        shader_arb_get_register_name(ins, &dst->reg, dst_name, &is_color);
+
+        shader_addline(buffer, "MUL %s.x, %s, %s;\n", dst_name, src_name0, src_name0);  /* x ^ 2 */
+        shader_addline(buffer, "MUL TA.y, %s.x, %s;\n", dst_name, src_name0);           /* x ^ 3 */
+        shader_addline(buffer, "MUL %s.y, TA.y, %s;\n", dst_name, src_name0);           /* x ^ 4 */
+        shader_addline(buffer, "MUL TA.z, %s.y, %s;\n", dst_name, src_name0);           /* x ^ 5 */
+        shader_addline(buffer, "MUL %s.z, TA.z, %s;\n", dst_name, src_name0);           /* x ^ 6 */
+        shader_addline(buffer, "MUL TA.w, %s.z, %s;\n", dst_name, src_name0);           /* x ^ 7 */
+
+        /* sin(x/2)
+         *
+         * Unfortunately we don't get the constants in a DP4-capable form. Is there a way to
+         * properly merge that with MULs in the code above?
+         * The swizzles .yz and xw however fit into the .yzxw swizzle added to ps_2_0. Maybe
+         * we can merge the sine and cosine MAD rows to calculate them together.
+         */
+        shader_addline(buffer, "MUL TA.x, %s, %s.w;\n", src_name0, src_name2); /* x^1, +1/(1!*2) */
+        shader_addline(buffer, "MAD TA.x, TA.y, %s.x, TA.x;\n", src_name2); /* -1/(3!*8) */
+        shader_addline(buffer, "MAD TA.x, TA.z, %s.w, TA.x;\n", src_name1); /* +1/(5!*32) */
+        shader_addline(buffer, "MAD TA.x, TA.w, %s.x, TA.x;\n", src_name1); /* -1/(7!*128) */
+
+        /* cos(x/2) */
+        shader_addline(buffer, "MAD TA.y, %s.x, %s.y, %s.z;\n", dst_name, src_name2, src_name2); /* -1/(2!*4), +1.0 */
+        shader_addline(buffer, "MAD TA.y, %s.y, %s.z, TA.y;\n", dst_name, src_name1); /* +1/(4!*16) */
+        shader_addline(buffer, "MAD TA.y, %s.z, %s.y, TA.y;\n", dst_name, src_name1); /* -1/(6!*64) */
+
+        if(dst->write_mask & WINED3DSP_WRITEMASK_0) {
+            /* cos x */
+            shader_addline(buffer, "MUL TA.z, TA.y, TA.y;\n");
+            shader_addline(buffer, "MAD %s.x, -TA.x, TA.x, TA.z;\n", dst_name);
+        }
+        if(dst->write_mask & WINED3DSP_WRITEMASK_1) {
+            /* sin x */
+            shader_addline(buffer, "MUL %s.y, TA.x, TA.y;\n", dst_name);
+            shader_addline(buffer, "ADD %s.y, %s.y, %s.y;\n", dst_name, dst_name, dst_name);
+        }
+    }
+}
+
+static void shader_hw_sgn(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    char dst_name[50];
+    char src_name[50];
+    struct shader_arb_ctx_priv *ctx = ins->ctx->backend_data;
+
+    shader_arb_get_dst_param(ins, &ins->dst[0], dst_name);
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src_name);
+
+    /* SGN is only valid in vertex shaders */
+    if(ctx->target_version >= NV2) {
+        shader_addline(buffer, "SSG%s %s, %s;\n", shader_arb_get_modifier(ins), dst_name, src_name);
+        return;
+    }
+
+    /* If SRC > 0.0, -SRC < SRC = TRUE, otherwise false.
+     * if SRC < 0.0,  SRC < -SRC = TRUE. If neither is true, src = 0.0
+     */
+    if(ins->dst[0].modifiers & WINED3DSPDM_SATURATE) {
+        shader_addline(buffer, "SLT %s, -%s, %s;\n", dst_name, src_name, src_name);
+    } else {
+        /* src contains TA? Write to the dest first. This won't overwrite our destination.
+         * Then use TA, and calculate the final result
+         *
+         * Not reading from TA? Store the first result in TA to avoid overwriting the
+         * destination if src reg = dst reg
+         */
+        if(strstr(src_name, "TA"))
+        {
+            shader_addline(buffer, "SLT %s,  %s, -%s;\n", dst_name, src_name, src_name);
+            shader_addline(buffer, "SLT TA, -%s, %s;\n", src_name, src_name);
+            shader_addline(buffer, "ADD %s, %s, -TA;\n", dst_name, dst_name);
+        }
+        else
+        {
+            shader_addline(buffer, "SLT TA, -%s, %s;\n", src_name, src_name);
+            shader_addline(buffer, "SLT %s,  %s, -%s;\n", dst_name, src_name, src_name);
+            shader_addline(buffer, "ADD %s, TA, -%s;\n", dst_name, dst_name);
+        }
+    }
+}
+
+static void shader_hw_dsy(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    char src[50];
+    char dst[50];
+    char dst_name[50];
+    BOOL is_color;
+
+    shader_arb_get_dst_param(ins, &ins->dst[0], dst);
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src);
+    shader_arb_get_register_name(ins, &ins->dst[0].reg, dst_name, &is_color);
+
+    shader_addline(buffer, "DDY %s, %s;\n", dst, src);
+    shader_addline(buffer, "MUL%s %s, %s, ycorrection.y;\n", shader_arb_get_modifier(ins), dst, dst_name);
+}
+
+static DWORD abs_modifier(DWORD mod, BOOL *need_abs)
+{
+    *need_abs = FALSE;
+
+    switch(mod)
+    {
+        case WINED3DSPSM_NONE:      return WINED3DSPSM_ABS;
+        case WINED3DSPSM_NEG:       return WINED3DSPSM_ABS;
+        case WINED3DSPSM_BIAS:      *need_abs = TRUE; return WINED3DSPSM_BIAS;
+        case WINED3DSPSM_BIASNEG:   *need_abs = TRUE; return WINED3DSPSM_BIASNEG;
+        case WINED3DSPSM_SIGN:      *need_abs = TRUE; return WINED3DSPSM_SIGN;
+        case WINED3DSPSM_SIGNNEG:   *need_abs = TRUE; return WINED3DSPSM_SIGNNEG;
+        case WINED3DSPSM_COMP:      *need_abs = TRUE; return WINED3DSPSM_COMP;
+        case WINED3DSPSM_X2:        *need_abs = TRUE; return WINED3DSPSM_X2;
+        case WINED3DSPSM_X2NEG:     *need_abs = TRUE; return WINED3DSPSM_X2NEG;
+        case WINED3DSPSM_DZ:        *need_abs = TRUE; return WINED3DSPSM_DZ;
+        case WINED3DSPSM_DW:        *need_abs = TRUE; return WINED3DSPSM_DW;
+        case WINED3DSPSM_ABS:       return WINED3DSPSM_ABS;
+        case WINED3DSPSM_ABSNEG:    return WINED3DSPSM_ABS;
+    }
+    FIXME("Unknown modifier %u\n", mod);
+    return mod;
+}
+
+static void shader_hw_log(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    char src0[50], dst[50];
+    struct wined3d_shader_src_param src0_copy = ins->src[0];
+    BOOL need_abs = FALSE;
+    const char *instr;
+
+    switch(ins->handler_idx)
+    {
+        case WINED3DSIH_LOG:  instr = "LG2"; break;
+        case WINED3DSIH_LOGP: instr = "LOG"; break;
+        default:
+            ERR("Unexpected instruction %d\n", ins->handler_idx);
+            return;
+    }
+
+    /* LOG and LOGP operate on the absolute value of the input */
+    src0_copy.modifiers = abs_modifier(src0_copy.modifiers, &need_abs);
+
+    shader_arb_get_dst_param(ins, &ins->dst[0], dst);
+    shader_arb_get_src_param(ins, &src0_copy, 0, src0);
+
+    if(need_abs)
+    {
+        shader_addline(buffer, "ABS TA, %s;\n", src0);
+        shader_addline(buffer, "%s%s %s, TA;\n", instr, shader_arb_get_modifier(ins), dst);
+    }
+    else
+    {
+        shader_addline(buffer, "%s%s %s, %s;\n", instr, shader_arb_get_modifier(ins), dst, src0);
+    }
+}
+
+static void shader_hw_pow(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    char src0[50], src1[50], dst[50];
+    struct wined3d_shader_src_param src0_copy = ins->src[0];
+    BOOL need_abs = FALSE;
+    struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
+    const char *one = arb_get_helper_value(ins->ctx->reg_maps->shader_version.type, ARB_ONE);
+
+    /* POW operates on the absolute value of the input */
+    src0_copy.modifiers = abs_modifier(src0_copy.modifiers, &need_abs);
+
+    shader_arb_get_dst_param(ins, &ins->dst[0], dst);
+    shader_arb_get_src_param(ins, &src0_copy, 0, src0);
+    shader_arb_get_src_param(ins, &ins->src[1], 1, src1);
+
+    if (need_abs)
+        shader_addline(buffer, "ABS TA.x, %s;\n", src0);
+    else
+        shader_addline(buffer, "MOV TA.x, %s;\n", src0);
+
+    if (priv->target_version >= NV2)
+    {
+        shader_addline(buffer, "MOVC TA.y, %s;\n", src1);
+        shader_addline(buffer, "POW%s %s, TA.x, TA.y;\n", shader_arb_get_modifier(ins), dst);
+        shader_addline(buffer, "MOV %s (EQ.y), %s;\n", dst, one);
+    }
+    else
+    {
+        const char *zero = arb_get_helper_value(ins->ctx->reg_maps->shader_version.type, ARB_ZERO);
+        const char *flt_eps = arb_get_helper_value(ins->ctx->reg_maps->shader_version.type, ARB_EPS);
+
+        shader_addline(buffer, "ABS TA.y, %s;\n", src1);
+        shader_addline(buffer, "SGE TA.y, -TA.y, %s;\n", zero);
+        /* Possibly add flt_eps to avoid getting float special values */
+        shader_addline(buffer, "MAD TA.z, TA.y, %s, %s;\n", flt_eps, src1);
+        shader_addline(buffer, "POW%s TA.x, TA.x, TA.z;\n", shader_arb_get_modifier(ins));
+        shader_addline(buffer, "MAD TA.x, -TA.x, TA.y, TA.x;\n");
+        shader_addline(buffer, "MAD %s, TA.y, %s, TA.x;\n", dst, one);
+    }
+}
+
+static void shader_hw_loop(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    char src_name[50];
+    BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type);
+
+    /* src0 is aL */
+    shader_arb_get_src_param(ins, &ins->src[1], 0, src_name);
+
+    if(vshader)
+    {
+        struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
+        struct list *e = list_head(&priv->control_frames);
+        struct control_frame *control_frame = LIST_ENTRY(e, struct control_frame, entry);
+
+        if(priv->loop_depth > 1) shader_addline(buffer, "PUSHA aL;\n");
+        /* The constant loader makes sure to load -1 into iX.w */
+        shader_addline(buffer, "ARLC aL, %s.xywz;\n", src_name);
+        shader_addline(buffer, "BRA loop_%u_end (LE.x);\n", control_frame->no.loop);
+        shader_addline(buffer, "loop_%u_start:\n", control_frame->no.loop);
+    }
+    else
+    {
+        shader_addline(buffer, "LOOP %s;\n", src_name);
+    }
+}
+
+static void shader_hw_rep(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    char src_name[50];
+    BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type);
+
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src_name);
+
+    /* The constant loader makes sure to load -1 into iX.w */
+    if(vshader)
+    {
+        struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
+        struct list *e = list_head(&priv->control_frames);
+        struct control_frame *control_frame = LIST_ENTRY(e, struct control_frame, entry);
+
+        if(priv->loop_depth > 1) shader_addline(buffer, "PUSHA aL;\n");
+
+        shader_addline(buffer, "ARLC aL, %s.xywz;\n", src_name);
+        shader_addline(buffer, "BRA loop_%u_end (LE.x);\n", control_frame->no.loop);
+        shader_addline(buffer, "loop_%u_start:\n", control_frame->no.loop);
+    }
+    else
+    {
+        shader_addline(buffer, "REP %s;\n", src_name);
+    }
+}
+
+static void shader_hw_endloop(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type);
+
+    if(vshader)
+    {
+        struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
+        struct list *e = list_head(&priv->control_frames);
+        struct control_frame *control_frame = LIST_ENTRY(e, struct control_frame, entry);
+
+        shader_addline(buffer, "ARAC aL.xy, aL;\n");
+        shader_addline(buffer, "BRA loop_%u_start (GT.x);\n", control_frame->no.loop);
+        shader_addline(buffer, "loop_%u_end:\n", control_frame->no.loop);
+
+        if(priv->loop_depth > 1) shader_addline(buffer, "POPA aL;\n");
+    }
+    else
+    {
+        shader_addline(buffer, "ENDLOOP;\n");
+    }
+}
+
+static void shader_hw_endrep(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type);
+
+    if(vshader)
+    {
+        struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
+        struct list *e = list_head(&priv->control_frames);
+        struct control_frame *control_frame = LIST_ENTRY(e, struct control_frame, entry);
+
+        shader_addline(buffer, "ARAC aL.xy, aL;\n");
+        shader_addline(buffer, "BRA loop_%u_start (GT.x);\n", control_frame->no.loop);
+        shader_addline(buffer, "loop_%u_end:\n", control_frame->no.loop);
+
+        if(priv->loop_depth > 1) shader_addline(buffer, "POPA aL;\n");
+    }
+    else
+    {
+        shader_addline(buffer, "ENDREP;\n");
+    }
+}
+
+static const struct control_frame *find_last_loop(const struct shader_arb_ctx_priv *priv)
+{
+    struct control_frame *control_frame;
+
+    LIST_FOR_EACH_ENTRY(control_frame, &priv->control_frames, struct control_frame, entry)
+    {
+        if(control_frame->type == LOOP || control_frame->type == REP) return control_frame;
+    }
+    ERR("Could not find loop for break\n");
+    return NULL;
+}
+
+static void shader_hw_break(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    const struct control_frame *control_frame = find_last_loop(ins->ctx->backend_data);
+    BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type);
+
+    if(vshader)
+    {
+        shader_addline(buffer, "BRA loop_%u_end;\n", control_frame->no.loop);
+    }
+    else
+    {
+        shader_addline(buffer, "BRK;\n");
+    }
+}
+
+static const char *get_compare(enum wined3d_shader_rel_op op)
+{
+    switch (op)
+    {
+        case WINED3D_SHADER_REL_OP_GT: return "GT";
+        case WINED3D_SHADER_REL_OP_EQ: return "EQ";
+        case WINED3D_SHADER_REL_OP_GE: return "GE";
+        case WINED3D_SHADER_REL_OP_LT: return "LT";
+        case WINED3D_SHADER_REL_OP_NE: return "NE";
+        case WINED3D_SHADER_REL_OP_LE: return "LE";
+        default:
+            FIXME("Unrecognized operator %#x.\n", op);
+            return "(\?\?)";
+    }
+}
+
+static enum wined3d_shader_rel_op invert_compare(enum wined3d_shader_rel_op op)
+{
+    switch (op)
+    {
+        case WINED3D_SHADER_REL_OP_GT: return WINED3D_SHADER_REL_OP_LE;
+        case WINED3D_SHADER_REL_OP_EQ: return WINED3D_SHADER_REL_OP_NE;
+        case WINED3D_SHADER_REL_OP_GE: return WINED3D_SHADER_REL_OP_LT;
+        case WINED3D_SHADER_REL_OP_LT: return WINED3D_SHADER_REL_OP_GE;
+        case WINED3D_SHADER_REL_OP_NE: return WINED3D_SHADER_REL_OP_EQ;
+        case WINED3D_SHADER_REL_OP_LE: return WINED3D_SHADER_REL_OP_GT;
+        default:
+            FIXME("Unrecognized operator %#x.\n", op);
+            return -1;
+    }
+}
+
+static void shader_hw_breakc(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type);
+    const struct control_frame *control_frame = find_last_loop(ins->ctx->backend_data);
+    char src_name0[50];
+    char src_name1[50];
+    const char *comp = get_compare(ins->flags);
+
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src_name0);
+    shader_arb_get_src_param(ins, &ins->src[1], 1, src_name1);
+
+    if(vshader)
+    {
+        /* SUBC CC, src0, src1" works only in pixel shaders, so use TA to throw
+         * away the subtraction result
+         */
+        shader_addline(buffer, "SUBC TA, %s, %s;\n", src_name0, src_name1);
+        shader_addline(buffer, "BRA loop_%u_end (%s.x);\n", control_frame->no.loop, comp);
+    }
+    else
+    {
+        shader_addline(buffer, "SUBC TA, %s, %s;\n", src_name0, src_name1);
+        shader_addline(buffer, "BRK (%s.x);\n", comp);
+    }
+}
+
+static void shader_hw_ifc(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
+    struct list *e = list_head(&priv->control_frames);
+    struct control_frame *control_frame = LIST_ENTRY(e, struct control_frame, entry);
+    const char *comp;
+    char src_name0[50];
+    char src_name1[50];
+    BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type);
+
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src_name0);
+    shader_arb_get_src_param(ins, &ins->src[1], 1, src_name1);
+
+    if(vshader)
+    {
+        /* Invert the flag. We jump to the else label if the condition is NOT true */
+        comp = get_compare(invert_compare(ins->flags));
+        shader_addline(buffer, "SUBC TA, %s, %s;\n", src_name0, src_name1);
+        shader_addline(buffer, "BRA ifc_%u_else (%s.x);\n", control_frame->no.ifc, comp);
+    }
+    else
+    {
+        comp = get_compare(ins->flags);
+        shader_addline(buffer, "SUBC TA, %s, %s;\n", src_name0, src_name1);
+        shader_addline(buffer, "IF %s.x;\n", comp);
+    }
+}
+
+static void shader_hw_else(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
+    struct list *e = list_head(&priv->control_frames);
+    struct control_frame *control_frame = LIST_ENTRY(e, struct control_frame, entry);
+    BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type);
+
+    if(vshader)
+    {
+        shader_addline(buffer, "BRA ifc_%u_endif;\n", control_frame->no.ifc);
+        shader_addline(buffer, "ifc_%u_else:\n", control_frame->no.ifc);
+        control_frame->had_else = TRUE;
+    }
+    else
+    {
+        shader_addline(buffer, "ELSE;\n");
+    }
+}
+
+static void shader_hw_endif(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
+    struct list *e = list_head(&priv->control_frames);
+    struct control_frame *control_frame = LIST_ENTRY(e, struct control_frame, entry);
+    BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type);
+
+    if(vshader)
+    {
+        if(control_frame->had_else)
+        {
+            shader_addline(buffer, "ifc_%u_endif:\n", control_frame->no.ifc);
+        }
+        else
+        {
+            shader_addline(buffer, "#No else branch. else is endif\n");
+            shader_addline(buffer, "ifc_%u_else:\n", control_frame->no.ifc);
+        }
+    }
+    else
+    {
+        shader_addline(buffer, "ENDIF;\n");
+    }
+}
+
+static void shader_hw_texldd(const struct wined3d_shader_instruction *ins)
+{
+    DWORD sampler_idx = ins->src[1].reg.idx[0].offset;
+    char reg_dest[40];
+    char reg_src[3][40];
+    WORD flags = TEX_DERIV;
+
+    shader_arb_get_dst_param(ins, &ins->dst[0], reg_dest);
+    shader_arb_get_src_param(ins, &ins->src[0], 0, reg_src[0]);
+    shader_arb_get_src_param(ins, &ins->src[2], 1, reg_src[1]);
+    shader_arb_get_src_param(ins, &ins->src[3], 2, reg_src[2]);
+
+    if (ins->flags & WINED3DSI_TEXLD_PROJECT) flags |= TEX_PROJ;
+    if (ins->flags & WINED3DSI_TEXLD_BIAS) flags |= TEX_BIAS;
+
+    shader_hw_sample(ins, sampler_idx, reg_dest, reg_src[0], flags, reg_src[1], reg_src[2]);
+}
+
+static void shader_hw_texldl(const struct wined3d_shader_instruction *ins)
+{
+    DWORD sampler_idx = ins->src[1].reg.idx[0].offset;
+    char reg_dest[40];
+    char reg_coord[40];
+    WORD flags = TEX_LOD;
+
+    shader_arb_get_dst_param(ins, &ins->dst[0], reg_dest);
+    shader_arb_get_src_param(ins, &ins->src[0], 0, reg_coord);
+
+    if (ins->flags & WINED3DSI_TEXLD_PROJECT) flags |= TEX_PROJ;
+    if (ins->flags & WINED3DSI_TEXLD_BIAS) flags |= TEX_BIAS;
+
+    shader_hw_sample(ins, sampler_idx, reg_dest, reg_coord, flags, NULL, NULL);
+}
+
+static void shader_hw_label(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
+
+    priv->in_main_func = FALSE;
+    /* Call instructions activate the NV extensions, not labels and rets. If there is an uncalled
+     * subroutine, don't generate a label that will make GL complain
+     */
+    if(priv->target_version == ARB) return;
+
+    shader_addline(buffer, "l%u:\n", ins->src[0].reg.idx[0].offset);
+}
+
+static void vshader_add_footer(struct shader_arb_ctx_priv *priv_ctx,
+        const struct arb_vshader_private *shader_data, const struct arb_vs_compile_args *args,
+        const struct wined3d_shader_reg_maps *reg_maps, const struct wined3d_gl_info *gl_info,
+        struct wined3d_shader_buffer *buffer)
+{
+    unsigned int i;
+
+    /* The D3DRS_FOGTABLEMODE render state defines if the shader-generated fog coord is used
+     * or if the fragment depth is used. If the fragment depth is used(FOGTABLEMODE != NONE),
+     * the fog frag coord is thrown away. If the fog frag coord is used, but not written by
+     * the shader, it is set to 0.0(fully fogged, since start = 1.0, end = 0.0)
+     */
+    if (args->super.fog_src == VS_FOG_Z)
+    {
+        shader_addline(buffer, "MOV result.fogcoord, TMP_OUT.z;\n");
+    }
+    else
+    {
+        if (!reg_maps->fog)
+        {
+            /* posFixup.x is always 1.0, so we can safely use it */
+            shader_addline(buffer, "ADD result.fogcoord, posFixup.x, -posFixup.x;\n");
+        }
+        else
+        {
+            /* Clamp fogcoord */
+            const char *zero = arb_get_helper_value(reg_maps->shader_version.type, ARB_ZERO);
+            const char *one = arb_get_helper_value(reg_maps->shader_version.type, ARB_ONE);
+
+            shader_addline(buffer, "MIN TMP_FOGCOORD.x, TMP_FOGCOORD.x, %s;\n", one);
+            shader_addline(buffer, "MAX result.fogcoord.x, TMP_FOGCOORD.x, %s;\n", zero);
+        }
+    }
+
+    /* Clipplanes are always stored without y inversion */
+    if (use_nv_clip(gl_info) && priv_ctx->target_version >= NV2)
+    {
+        if (args->super.clip_enabled)
+        {
+            for (i = 0; i < priv_ctx->vs_clipplanes; i++)
+            {
+                shader_addline(buffer, "DP4 result.clip[%u].x, TMP_OUT, state.clip[%u].plane;\n", i, i);
+            }
+        }
+    }
+    else if (args->clip.boolclip.clip_texcoord)
+    {
+        unsigned int cur_clip = 0;
+        char component[4] = {'x', 'y', 'z', 'w'};
+        const char *zero = arb_get_helper_value(WINED3D_SHADER_TYPE_VERTEX, ARB_ZERO);
+
+        for (i = 0; i < gl_info->limits.clipplanes; ++i)
+        {
+            if (args->clip.boolclip.clipplane_mask & (1 << i))
+            {
+                shader_addline(buffer, "DP4 TA.%c, TMP_OUT, state.clip[%u].plane;\n",
+                               component[cur_clip++], i);
+            }
+        }
+        switch (cur_clip)
+        {
+            case 0:
+                shader_addline(buffer, "MOV TA, %s;\n", zero);
+                break;
+            case 1:
+                shader_addline(buffer, "MOV TA.yzw, %s;\n", zero);
+                break;
+            case 2:
+                shader_addline(buffer, "MOV TA.zw, %s;\n", zero);
+                break;
+            case 3:
+                shader_addline(buffer, "MOV TA.w, %s;\n", zero);
+                break;
+        }
+        shader_addline(buffer, "MOV result.texcoord[%u], TA;\n",
+                       args->clip.boolclip.clip_texcoord - 1);
+    }
+
+    /* Write the final position.
+     *
+     * OpenGL coordinates specify the center of the pixel while d3d coords specify
+     * the corner. The offsets are stored in z and w in posFixup. posFixup.y contains
+     * 1.0 or -1.0 to turn the rendering upside down for offscreen rendering. PosFixup.x
+     * contains 1.0 to allow a mad, but arb vs swizzles are too restricted for that.
+     */
+    shader_addline(buffer, "MUL TA, posFixup, TMP_OUT.w;\n");
+    shader_addline(buffer, "ADD TMP_OUT.x, TMP_OUT.x, TA.z;\n");
+    shader_addline(buffer, "MAD TMP_OUT.y, TMP_OUT.y, posFixup.y, TA.w;\n");
+
+    /* Z coord [0;1]->[-1;1] mapping, see comment in transform_projection in state.c
+     * and the glsl equivalent
+     */
+    if (need_helper_const(shader_data, reg_maps, gl_info))
+    {
+        const char *two = arb_get_helper_value(WINED3D_SHADER_TYPE_VERTEX, ARB_TWO);
+        shader_addline(buffer, "MAD TMP_OUT.z, TMP_OUT.z, %s, -TMP_OUT.w;\n", two);
+    }
+    else
+    {
+        shader_addline(buffer, "ADD TMP_OUT.z, TMP_OUT.z, TMP_OUT.z;\n");
+        shader_addline(buffer, "ADD TMP_OUT.z, TMP_OUT.z, -TMP_OUT.w;\n");
+    }
+
+    shader_addline(buffer, "MOV result.position, TMP_OUT;\n");
+
+    priv_ctx->footer_written = TRUE;
+}
+
+static void shader_hw_ret(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
+    const struct wined3d_shader *shader = ins->ctx->shader;
+    BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type);
+
+    if(priv->target_version == ARB) return;
+
+    if(vshader)
+    {
+        if (priv->in_main_func) vshader_add_footer(priv, shader->backend_data,
+                priv->cur_vs_args, ins->ctx->reg_maps, ins->ctx->gl_info, buffer);
+    }
+
+    shader_addline(buffer, "RET;\n");
+}
+
+static void shader_hw_call(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    shader_addline(buffer, "CAL l%u;\n", ins->src[0].reg.idx[0].offset);
+}
+
+/* Context activation is done by the caller. */
+static GLuint create_arb_blt_vertex_program(const struct wined3d_gl_info *gl_info)
+{
+    GLuint program_id = 0;
+    GLint pos;
+
+    const char *blt_vprogram =
+        "!!ARBvp1.0\n"
+        "PARAM c[1] = { { 1, 0.5 } };\n"
+        "MOV result.position, vertex.position;\n"
+        "MOV result.color, c[0].x;\n"
+        "MOV result.texcoord[0], vertex.texcoord[0];\n"
+        "END\n";
+
+    GL_EXTCALL(glGenProgramsARB(1, &program_id));
+    GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, program_id));
+    GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
+            strlen(blt_vprogram), blt_vprogram));
+    checkGLcall("glProgramStringARB()");
+
+    gl_info->gl_ops.gl.p_glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos);
+    if (pos != -1)
+    {
+        FIXME("Vertex program error at position %d: %s\n\n", pos,
+            debugstr_a((const char *)gl_info->gl_ops.gl.p_glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
+        shader_arb_dump_program_source(blt_vprogram);
+    }
+    else
+    {
+        GLint native;
+
+        GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &native));
+        checkGLcall("glGetProgramivARB()");
+        if (!native) WARN("Program exceeds native resource limits.\n");
+    }
+
+    return program_id;
+}
+
+/* Context activation is done by the caller. */
+static GLuint create_arb_blt_fragment_program(const struct wined3d_gl_info *gl_info,
+        enum tex_types tex_type, BOOL masked)
+{
+    GLuint program_id = 0;
+    const char *fprogram;
+    GLint pos;
+
+    static const char * const blt_fprograms_full[tex_type_count] =
+    {
+        /* tex_1d */
+        NULL,
+        /* tex_2d */
+        "!!ARBfp1.0\n"
+        "TEMP R0;\n"
+        "TEX R0.x, fragment.texcoord[0], texture[0], 2D;\n"
+        "MOV result.depth.z, R0.x;\n"
+        "END\n",
+        /* tex_3d */
+        NULL,
+        /* tex_cube */
+        "!!ARBfp1.0\n"
+        "TEMP R0;\n"
+        "TEX R0.x, fragment.texcoord[0], texture[0], CUBE;\n"
+        "MOV result.depth.z, R0.x;\n"
+        "END\n",
+        /* tex_rect */
+        "!!ARBfp1.0\n"
+        "TEMP R0;\n"
+        "TEX R0.x, fragment.texcoord[0], texture[0], RECT;\n"
+        "MOV result.depth.z, R0.x;\n"
+        "END\n",
+    };
+
+    static const char * const blt_fprograms_masked[tex_type_count] =
+    {
+        /* tex_1d */
+        NULL,
+        /* tex_2d */
+        "!!ARBfp1.0\n"
+        "PARAM mask = program.local[0];\n"
+        "TEMP R0;\n"
+        "SLT R0.xy, fragment.position, mask.zwzw;\n"
+        "MUL R0.x, R0.x, R0.y;\n"
+        "KIL -R0.x;\n"
+        "TEX R0.x, fragment.texcoord[0], texture[0], 2D;\n"
+        "MOV result.depth.z, R0.x;\n"
+        "END\n",
+        /* tex_3d */
+        NULL,
+        /* tex_cube */
+        "!!ARBfp1.0\n"
+        "PARAM mask = program.local[0];\n"
+        "TEMP R0;\n"
+        "SLT R0.xy, fragment.position, mask.zwzw;\n"
+        "MUL R0.x, R0.x, R0.y;\n"
+        "KIL -R0.x;\n"
+        "TEX R0.x, fragment.texcoord[0], texture[0], CUBE;\n"
+        "MOV result.depth.z, R0.x;\n"
+        "END\n",
+        /* tex_rect */
+        "!!ARBfp1.0\n"
+        "PARAM mask = program.local[0];\n"
+        "TEMP R0;\n"
+        "SLT R0.xy, fragment.position, mask.zwzw;\n"
+        "MUL R0.x, R0.x, R0.y;\n"
+        "KIL -R0.x;\n"
+        "TEX R0.x, fragment.texcoord[0], texture[0], RECT;\n"
+        "MOV result.depth.z, R0.x;\n"
+        "END\n",
+    };
+
+    fprogram = masked ? blt_fprograms_masked[tex_type] : blt_fprograms_full[tex_type];
+    if (!fprogram)
+    {
+        FIXME("tex_type %#x not supported, falling back to tex_2d\n", tex_type);
+        tex_type = tex_2d;
+        fprogram = masked ? blt_fprograms_masked[tex_type] : blt_fprograms_full[tex_type];
+    }
+
+    GL_EXTCALL(glGenProgramsARB(1, &program_id));
+    GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, program_id));
+    GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(fprogram), fprogram));
+    checkGLcall("glProgramStringARB()");
+
+    gl_info->gl_ops.gl.p_glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos);
+    if (pos != -1)
+    {
+        FIXME("Fragment program error at position %d: %s\n\n", pos,
+            debugstr_a((const char *)gl_info->gl_ops.gl.p_glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
+        shader_arb_dump_program_source(fprogram);
+    }
+    else
+    {
+        GLint native;
+
+        GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &native));
+        checkGLcall("glGetProgramivARB()");
+        if (!native) WARN("Program exceeds native resource limits.\n");
+    }
+
+    return program_id;
+}
+
+static void arbfp_add_sRGB_correction(struct wined3d_shader_buffer *buffer, const char *fragcolor,
+        const char *tmp1, const char *tmp2, const char *tmp3, const char *tmp4, BOOL condcode)
+{
+    /* Perform sRGB write correction. See GLX_EXT_framebuffer_sRGB */
+
+    if(condcode)
+    {
+        /* Sigh. MOVC CC doesn't work, so use one of the temps as dummy dest */
+        shader_addline(buffer, "SUBC %s, %s.x, srgb_consts1.y;\n", tmp1, fragcolor);
+        /* Calculate the > 0.0031308 case */
+        shader_addline(buffer, "POW %s.x (GE), %s.x, srgb_consts1.z;\n", fragcolor, fragcolor);
+        shader_addline(buffer, "POW %s.y (GE), %s.y, srgb_consts1.z;\n", fragcolor, fragcolor);
+        shader_addline(buffer, "POW %s.z (GE), %s.z, srgb_consts1.z;\n", fragcolor, fragcolor);
+        shader_addline(buffer, "MUL %s.xyz (GE), %s, srgb_consts1.w;\n", fragcolor, fragcolor);
+        shader_addline(buffer, "SUB %s.xyz (GE), %s, srgb_consts2.x;\n", fragcolor, fragcolor);
+        /* Calculate the < case */
+        shader_addline(buffer, "MUL %s.xyz (LT), srgb_consts1.x, %s;\n", fragcolor, fragcolor);
+    }
+    else
+    {
+        /* Calculate the > 0.0031308 case */
+        shader_addline(buffer, "POW %s.x, %s.x, srgb_consts1.z;\n", tmp1, fragcolor);
+        shader_addline(buffer, "POW %s.y, %s.y, srgb_consts1.z;\n", tmp1, fragcolor);
+        shader_addline(buffer, "POW %s.z, %s.z, srgb_consts1.z;\n", tmp1, fragcolor);
+        shader_addline(buffer, "MUL %s, %s, srgb_consts1.w;\n", tmp1, tmp1);
+        shader_addline(buffer, "SUB %s, %s, srgb_consts2.x;\n", tmp1, tmp1);
+        /* Calculate the < case */
+        shader_addline(buffer, "MUL %s, srgb_consts1.x, %s;\n", tmp2, fragcolor);
+        /* Get 1.0 / 0.0 masks for > 0.0031308 and < 0.0031308 */
+        shader_addline(buffer, "SLT %s, srgb_consts1.y, %s;\n", tmp3, fragcolor);
+        shader_addline(buffer, "SGE %s, srgb_consts1.y, %s;\n", tmp4, fragcolor);
+        /* Store the components > 0.0031308 in the destination */
+        shader_addline(buffer, "MUL %s.xyz, %s, %s;\n", fragcolor, tmp1, tmp3);
+        /* Add the components that are < 0.0031308 */
+        shader_addline(buffer, "MAD %s.xyz, %s, %s, %s;\n", fragcolor, tmp2, tmp4, fragcolor);
+        /* Move everything into result.color at once. Nvidia hardware cannot handle partial
+        * result.color writes(.rgb first, then .a), or handle overwriting already written
+        * components. The assembler uses a temporary register in this case, which is usually
+        * not allocated from one of our registers that were used earlier.
+        */
+    }
+    /* [0.0;1.0] clamping. Not needed, this is done implicitly */
+}
+
+static const DWORD *find_loop_control_values(const struct wined3d_shader *shader, DWORD idx)
+{
+    const struct wined3d_shader_lconst *constant;
+
+    LIST_FOR_EACH_ENTRY(constant, &shader->constantsI, struct wined3d_shader_lconst, entry)
+    {
+        if (constant->idx == idx)
+        {
+            return constant->value;
+        }
+    }
+    return NULL;
+}
+
+static void init_ps_input(const struct wined3d_shader *shader,
+        const struct arb_ps_compile_args *args, struct shader_arb_ctx_priv *priv)
+{
+    static const char * const texcoords[8] =
+    {
+        "fragment.texcoord[0]", "fragment.texcoord[1]", "fragment.texcoord[2]", "fragment.texcoord[3]",
+        "fragment.texcoord[4]", "fragment.texcoord[5]", "fragment.texcoord[6]", "fragment.texcoord[7]"
+    };
+    unsigned int i;
+    const struct wined3d_shader_signature_element *sig = shader->input_signature;
+    const char *semantic_name;
+    DWORD semantic_idx;
+
+    switch(args->super.vp_mode)
+    {
+        case pretransformed:
+        case fixedfunction:
+            /* The pixelshader has to collect the varyings on its own. In any case properly load
+             * color0 and color1. In the case of pretransformed vertices also load texcoords. Set
+             * other attribs to 0.0.
+             *
+             * For fixedfunction this behavior is correct, according to the tests. For pretransformed
+             * we'd either need a replacement shader that can load other attribs like BINORMAL, or
+             * load the texcoord attrib pointers to match the pixel shader signature
+             */
+            for(i = 0; i < MAX_REG_INPUT; i++)
+            {
+                semantic_name = sig[i].semantic_name;
+                semantic_idx = sig[i].semantic_idx;
+                if (!semantic_name) continue;
+
+                if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_COLOR))
+                {
+                    if (!semantic_idx) priv->ps_input[i] = "fragment.color.primary";
+                    else if(semantic_idx == 1) priv->ps_input[i] = "fragment.color.secondary";
+                    else priv->ps_input[i] = "0.0";
+                }
+                else if(args->super.vp_mode == fixedfunction)
+                {
+                    priv->ps_input[i] = "0.0";
+                }
+                else if(shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_TEXCOORD))
+                {
+                    if(semantic_idx < 8) priv->ps_input[i] = texcoords[semantic_idx];
+                    else priv->ps_input[i] = "0.0";
+                }
+                else if(shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_FOG))
+                {
+                    if (!semantic_idx) priv->ps_input[i] = "fragment.fogcoord";
+                    else priv->ps_input[i] = "0.0";
+                }
+                else
+                {
+                    priv->ps_input[i] = "0.0";
+                }
+
+                TRACE("v%u, semantic %s%u is %s\n", i, semantic_name, semantic_idx, priv->ps_input[i]);
+            }
+            break;
+
+        case vertexshader:
+            /* That one is easy. The vertex shaders provide v0-v7 in fragment.texcoord and v8 and v9 in
+             * fragment.color
+             */
+            for(i = 0; i < 8; i++)
+            {
+                priv->ps_input[i] = texcoords[i];
+            }
+            priv->ps_input[8] = "fragment.color.primary";
+            priv->ps_input[9] = "fragment.color.secondary";
+            break;
+    }
+}
+
+/* Context activation is done by the caller. */
+static GLuint shader_arb_generate_pshader(const struct wined3d_shader *shader,
+        const struct wined3d_gl_info *gl_info, struct wined3d_shader_buffer *buffer,
+        const struct arb_ps_compile_args *args, struct arb_ps_compiled_shader *compiled)
+{
+    const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
+    const DWORD *function = shader->function;
+    GLuint retval;
+    char fragcolor[16];
+    DWORD next_local = 0;
+    struct shader_arb_ctx_priv priv_ctx;
+    BOOL dcl_td = FALSE;
+    BOOL want_nv_prog = FALSE;
+    struct arb_pshader_private *shader_priv = shader->backend_data;
+    GLint errPos;
+    DWORD map;
+
+    char srgbtmp[4][4];
+    unsigned int i, found = 0;
+
+    for (i = 0, map = reg_maps->temporary; map; map >>= 1, ++i)
+    {
+        if (!(map & 1)
+                || (shader->u.ps.color0_mov && i == shader->u.ps.color0_reg)
+                || (reg_maps->shader_version.major < 2 && !i))
+            continue;
+
+        sprintf(srgbtmp[found], "R%u", i);
+        ++found;
+        if (found == 4) break;
+    }
+
+    switch(found) {
+        case 0:
+            sprintf(srgbtmp[0], "TA");
+            sprintf(srgbtmp[1], "TB");
+            sprintf(srgbtmp[2], "TC");
+            sprintf(srgbtmp[3], "TD");
+            dcl_td = TRUE;
+            break;
+        case 1:
+            sprintf(srgbtmp[1], "TA");
+            sprintf(srgbtmp[2], "TB");
+            sprintf(srgbtmp[3], "TC");
+            break;
+        case 2:
+            sprintf(srgbtmp[2], "TA");
+            sprintf(srgbtmp[3], "TB");
+            break;
+        case 3:
+            sprintf(srgbtmp[3], "TA");
+            break;
+        case 4:
+            break;
+    }
+
+    /*  Create the hw ARB shader */
+    memset(&priv_ctx, 0, sizeof(priv_ctx));
+    priv_ctx.cur_ps_args = args;
+    priv_ctx.compiled_fprog = compiled;
+    priv_ctx.cur_np2fixup_info = &compiled->np2fixup_info;
+    init_ps_input(shader, args, &priv_ctx);
+    list_init(&priv_ctx.control_frames);
+
+    /* Avoid enabling NV_fragment_program* if we do not need it.
+     *
+     * Enabling GL_NV_fragment_program_option causes the driver to occupy a temporary register,
+     * and it slows down the shader execution noticeably(about 5%). Usually our instruction emulation
+     * is faster than what we gain from using higher native instructions. There are some things though
+     * that cannot be emulated. In that case enable the extensions.
+     * If the extension is enabled, instruction handlers that support both ways will use it.
+     *
+     * Testing shows no performance difference between OPTION NV_fragment_program2 and NV_fragment_program.
+     * So enable the best we can get.
+     */
+    if(reg_maps->usesdsx || reg_maps->usesdsy || reg_maps->loop_depth > 0 || reg_maps->usestexldd ||
+       reg_maps->usestexldl || reg_maps->usesfacing || reg_maps->usesifc || reg_maps->usescall)
+    {
+        want_nv_prog = TRUE;
+    }
+
+    shader_addline(buffer, "!!ARBfp1.0\n");
+    if (want_nv_prog && gl_info->supported[NV_FRAGMENT_PROGRAM2])
+    {
+        shader_addline(buffer, "OPTION NV_fragment_program2;\n");
+        priv_ctx.target_version = NV3;
+    }
+    else if (want_nv_prog && gl_info->supported[NV_FRAGMENT_PROGRAM_OPTION])
+    {
+        shader_addline(buffer, "OPTION NV_fragment_program;\n");
+        priv_ctx.target_version = NV2;
+    } else {
+        if(want_nv_prog)
+        {
+            /* This is an error - either we're advertising the wrong shader version, or aren't enforcing some
+             * limits properly
+             */
+            ERR("The shader requires instructions that are not available in plain GL_ARB_fragment_program\n");
+            ERR("Try GLSL\n");
+        }
+        priv_ctx.target_version = ARB;
+    }
+
+    if (reg_maps->rt_mask > 1)
+    {
+        shader_addline(buffer, "OPTION ARB_draw_buffers;\n");
+    }
+
+    if (reg_maps->shader_version.major < 3)
+    {
+        switch (args->super.fog)
+        {
+            case WINED3D_FFP_PS_FOG_OFF:
+                break;
+            case WINED3D_FFP_PS_FOG_LINEAR:
+                shader_addline(buffer, "OPTION ARB_fog_linear;\n");
+                break;
+            case WINED3D_FFP_PS_FOG_EXP:
+                shader_addline(buffer, "OPTION ARB_fog_exp;\n");
+                break;
+            case WINED3D_FFP_PS_FOG_EXP2:
+                shader_addline(buffer, "OPTION ARB_fog_exp2;\n");
+                break;
+        }
+    }
+
+    /* For now always declare the temps. At least the Nvidia assembler optimizes completely
+     * unused temps away(but occupies them for the whole shader if they're used once). Always
+     * declaring them avoids tricky bookkeeping work
+     */
+    shader_addline(buffer, "TEMP TA;\n");      /* Used for modifiers */
+    shader_addline(buffer, "TEMP TB;\n");      /* Used for modifiers */
+    shader_addline(buffer, "TEMP TC;\n");      /* Used for modifiers */
+    if(dcl_td) shader_addline(buffer, "TEMP TD;\n"); /* Used for sRGB writing */
+    shader_addline(buffer, "PARAM coefdiv = { 0.5, 0.25, 0.125, 0.0625 };\n");
+    shader_addline(buffer, "PARAM coefmul = { 2, 4, 8, 16 };\n");
+    shader_addline(buffer, "PARAM ps_helper_const = { 0.0, 1.0, %1.10f, 0.0 };\n", eps);
+
+    if (reg_maps->shader_version.major < 2)
+    {
+        strcpy(fragcolor, "R0");
+    }
+    else
+    {
+        if (args->super.srgb_correction)
+        {
+            if (shader->u.ps.color0_mov)
+            {
+                sprintf(fragcolor, "R%u", shader->u.ps.color0_reg);
+            }
+            else
+            {
+                shader_addline(buffer, "TEMP TMP_COLOR;\n");
+                strcpy(fragcolor, "TMP_COLOR");
+            }
+        } else {
+            strcpy(fragcolor, "result.color");
+        }
+    }
+
+    if(args->super.srgb_correction) {
+        shader_addline(buffer, "PARAM srgb_consts1 = {%f, %f, %f, %f};\n",
+                       srgb_mul_low, srgb_cmp, srgb_pow, srgb_mul_high);
+        shader_addline(buffer, "PARAM srgb_consts2 = {%f, %f, %f, %f};\n",
+                       srgb_sub_high, 0.0, 0.0, 0.0);
+    }
+
+    /* Base Declarations */
+    shader_generate_arb_declarations(shader, reg_maps, buffer, gl_info, NULL, &priv_ctx);
+
+    for (i = 0, map = reg_maps->bumpmat; map; map >>= 1, ++i)
+    {
+        unsigned char bump_const;
+
+        if (!(map & 1)) continue;
+
+        bump_const = compiled->numbumpenvmatconsts;
+        compiled->bumpenvmatconst[bump_const].const_num = WINED3D_CONST_NUM_UNUSED;
+        compiled->bumpenvmatconst[bump_const].texunit = i;
+        compiled->luminanceconst[bump_const].const_num = WINED3D_CONST_NUM_UNUSED;
+        compiled->luminanceconst[bump_const].texunit = i;
+
+        /* We can fit the constants into the constant limit for sure because texbem, texbeml, bem and beml are only supported
+         * in 1.x shaders, and GL_ARB_fragment_program has a constant limit of 24 constants. So in the worst case we're loading
+         * 8 shader constants, 8 bump matrices and 8 luminance parameters and are perfectly fine. (No NP2 fixup on bumpmapped
+         * textures due to conditional NP2 restrictions)
+         *
+         * Use local constants to load the bump env parameters, not program.env. This avoids collisions with d3d constants of
+         * shaders in newer shader models. Since the bump env parameters have to share their space with NP2 fixup constants,
+         * their location is shader dependent anyway and they cannot be loaded globally.
+         */
+        compiled->bumpenvmatconst[bump_const].const_num = next_local++;
+        shader_addline(buffer, "PARAM bumpenvmat%d = program.local[%d];\n",
+                       i, compiled->bumpenvmatconst[bump_const].const_num);
+        compiled->numbumpenvmatconsts = bump_const + 1;
+
+        if (!(reg_maps->luminanceparams & (1 << i))) continue;
+
+        compiled->luminanceconst[bump_const].const_num = next_local++;
+        shader_addline(buffer, "PARAM luminance%d = program.local[%d];\n",
+                       i, compiled->luminanceconst[bump_const].const_num);
+    }
+
+    for(i = 0; i < MAX_CONST_I; i++)
+    {
+        compiled->int_consts[i] = WINED3D_CONST_NUM_UNUSED;
+        if (reg_maps->integer_constants & (1 << i) && priv_ctx.target_version >= NV2)
+        {
+            const DWORD *control_values = find_loop_control_values(shader, i);
+
+            if(control_values)
+            {
+                shader_addline(buffer, "PARAM I%u = {%u, %u, %u, -1};\n", i,
+                                control_values[0], control_values[1], control_values[2]);
+            }
+            else
+            {
+                compiled->int_consts[i] = next_local;
+                compiled->num_int_consts++;
+                shader_addline(buffer, "PARAM I%u = program.local[%u];\n", i, next_local++);
+            }
+        }
+    }
+
+    if(reg_maps->vpos || reg_maps->usesdsy)
+    {
+        compiled->ycorrection = next_local;
+        shader_addline(buffer, "PARAM ycorrection = program.local[%u];\n", next_local++);
+
+        if(reg_maps->vpos)
+        {
+            shader_addline(buffer, "TEMP vpos;\n");
+            /* ycorrection.x: Backbuffer height(onscreen) or 0(offscreen).
+             * ycorrection.y: -1.0(onscreen), 1.0(offscreen)
+             * ycorrection.z: 1.0
+             * ycorrection.w: 0.0
+             */
+            shader_addline(buffer, "MAD vpos, fragment.position, ycorrection.zyww, ycorrection.wxww;\n");
+            shader_addline(buffer, "FLR vpos.xy, vpos;\n");
+        }
+    }
+    else
+    {
+        compiled->ycorrection = WINED3D_CONST_NUM_UNUSED;
+    }
+
+    /* Load constants to fixup NP2 texcoords if there are still free constants left:
+     * Constants (texture dimensions) for the NP2 fixup are loaded as local program parameters. This will consume
+     * at most 8 (MAX_FRAGMENT_SAMPLERS / 2) parameters, which is highly unlikely, since the application had to
+     * use 16 NP2 textures at the same time. In case that we run out of constants the fixup is simply not
+     * applied / activated. This will probably result in wrong rendering of the texture, but will save us from
+     * shader compilation errors and the subsequent errors when drawing with this shader. */
+    if (priv_ctx.cur_ps_args->super.np2_fixup) {
+        unsigned char cur_fixup_sampler = 0;
+
+        struct arb_ps_np2fixup_info* const fixup = priv_ctx.cur_np2fixup_info;
+        const WORD map = priv_ctx.cur_ps_args->super.np2_fixup;
+        const UINT max_lconsts = gl_info->limits.arb_ps_local_constants;
+
+        fixup->offset = next_local;
+        fixup->super.active = 0;
+
+        for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i) {
+            if (!(map & (1 << i))) continue;
+
+            if (fixup->offset + (cur_fixup_sampler >> 1) < max_lconsts) {
+                fixup->super.active |= (1 << i);
+                fixup->super.idx[i] = cur_fixup_sampler++;
+            } else {
+                FIXME("No free constant found to load NP2 fixup data into shader. "
+                      "Sampling from this texture will probably look wrong.\n");
+                break;
+            }
+        }
+
+        fixup->super.num_consts = (cur_fixup_sampler + 1) >> 1;
+        if (fixup->super.num_consts) {
+            shader_addline(buffer, "PARAM np2fixup[%u] = { program.env[%u..%u] };\n",
+                           fixup->super.num_consts, fixup->offset, fixup->super.num_consts + fixup->offset - 1);
+        }
+    }
+
+    if (shader_priv->clipplane_emulation != ~0U && args->clip)
+    {
+        shader_addline(buffer, "KIL fragment.texcoord[%u];\n", shader_priv->clipplane_emulation);
+    }
+
+    /* Base Shader Body */
+    shader_generate_main(shader, buffer, reg_maps, function, &priv_ctx);
+
+    if(args->super.srgb_correction) {
+        arbfp_add_sRGB_correction(buffer, fragcolor, srgbtmp[0], srgbtmp[1], srgbtmp[2], srgbtmp[3],
+                                  priv_ctx.target_version >= NV2);
+    }
+
+    if(strcmp(fragcolor, "result.color")) {
+        shader_addline(buffer, "MOV result.color, %s;\n", fragcolor);
+    }
+    shader_addline(buffer, "END\n");
+
+    /* TODO: change to resource.glObjectHandle or something like that */
+    GL_EXTCALL(glGenProgramsARB(1, &retval));
+
+    TRACE("Creating a hw pixel shader, prg=%d\n", retval);
+    GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, retval));
+
+    TRACE("Created hw pixel shader, prg=%d\n", retval);
+    /* Create the program and check for errors */
+    GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
+               buffer->content_size, buffer->buffer));
+    checkGLcall("glProgramStringARB()");
+
+    gl_info->gl_ops.gl.p_glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
+    if (errPos != -1)
+    {
+        FIXME("HW PixelShader Error at position %d: %s\n\n",
+              errPos, debugstr_a((const char *)gl_info->gl_ops.gl.p_glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
+        shader_arb_dump_program_source(buffer->buffer);
+        retval = 0;
+    }
+    else
+    {
+        GLint native;
+
+        GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &native));
+        checkGLcall("glGetProgramivARB()");
+        if (!native) WARN("Program exceeds native resource limits.\n");
+    }
+
+    return retval;
+}
+
+static int compare_sig(const struct wined3d_shader_signature_element *sig1, const struct wined3d_shader_signature_element *sig2)
+{
+    unsigned int i;
+    int ret;
+
+    for(i = 0; i < MAX_REG_INPUT; i++)
+    {
+        if (!sig1[i].semantic_name || !sig2[i].semantic_name)
+        {
+            /* Compare pointers, not contents. One string is NULL(element does not exist), the other one is not NULL */
+            if(sig1[i].semantic_name != sig2[i].semantic_name) return sig1[i].semantic_name < sig2[i].semantic_name ? -1 : 1;
+            continue;
+        }
+
+        if ((ret = strcmp(sig1[i].semantic_name, sig2[i].semantic_name))) return ret;
+        if(sig1[i].semantic_idx    != sig2[i].semantic_idx)    return sig1[i].semantic_idx    < sig2[i].semantic_idx    ? -1 : 1;
+        if(sig1[i].sysval_semantic != sig2[i].sysval_semantic) return sig1[i].sysval_semantic < sig2[i].sysval_semantic ? -1 : 1;
+        if(sig1[i].component_type  != sig2[i].component_type)  return sig1[i].component_type  < sig2[i].component_type  ? -1 : 1;
+        if(sig1[i].register_idx    != sig2[i].register_idx)    return sig1[i].register_idx    < sig2[i].register_idx    ? -1 : 1;
+        if(sig1[i].mask            != sig2[i].mask)            return sig1[i].mask            < sig2[i].mask            ? -1 : 1;
+    }
+    return 0;
+}
+
+static struct wined3d_shader_signature_element *clone_sig(const struct wined3d_shader_signature_element *sig)
+{
+    struct wined3d_shader_signature_element *new;
+    int i;
+    char *name;
+
+    new = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*new) * MAX_REG_INPUT);
+    for(i = 0; i < MAX_REG_INPUT; i++)
+    {
+        if (!sig[i].semantic_name) continue;
+
+        new[i] = sig[i];
+        /* Clone the semantic string */
+        name = HeapAlloc(GetProcessHeap(), 0, strlen(sig[i].semantic_name) + 1);
+        strcpy(name, sig[i].semantic_name);
+        new[i].semantic_name = name;
+    }
+    return new;
+}
+
+static DWORD find_input_signature(struct shader_arb_priv *priv, const struct wined3d_shader_signature_element *sig)
+{
+    struct wine_rb_entry *entry = wine_rb_get(&priv->signature_tree, sig);
+    struct ps_signature *found_sig;
+
+    if (entry)
+    {
+        found_sig = WINE_RB_ENTRY_VALUE(entry, struct ps_signature, entry);
+        TRACE("Found existing signature %u\n", found_sig->idx);
+        return found_sig->idx;
+    }
+    found_sig = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*sig));
+    found_sig->sig = clone_sig(sig);
+    found_sig->idx = priv->ps_sig_number++;
+    TRACE("New signature stored and assigned number %u\n", found_sig->idx);
+    if(wine_rb_put(&priv->signature_tree, sig, &found_sig->entry) == -1)
+    {
+        ERR("Failed to insert program entry.\n");
+    }
+    return found_sig->idx;
+}
+
+static void init_output_registers(const struct wined3d_shader *shader,
+        const struct wined3d_shader_signature_element *ps_input_sig,
+        struct shader_arb_ctx_priv *priv_ctx, struct arb_vs_compiled_shader *compiled)
+{
+    unsigned int i, j;
+    static const char * const texcoords[8] =
+    {
+        "result.texcoord[0]", "result.texcoord[1]", "result.texcoord[2]", "result.texcoord[3]",
+        "result.texcoord[4]", "result.texcoord[5]", "result.texcoord[6]", "result.texcoord[7]"
+    };
+    const char *semantic_name;
+    DWORD semantic_idx, reg_idx;
+
+    /* Write generic input varyings 0 to 7 to result.texcoord[], varying 8 to result.color.primary
+     * and varying 9 to result.color.secondary
+     */
+    static const char * const decl_idx_to_string[MAX_REG_INPUT] =
+    {
+        "result.texcoord[0]", "result.texcoord[1]", "result.texcoord[2]", "result.texcoord[3]",
+        "result.texcoord[4]", "result.texcoord[5]", "result.texcoord[6]", "result.texcoord[7]",
+        "result.color.primary", "result.color.secondary"
+    };
+
+    if (!ps_input_sig)
+    {
+        TRACE("Pixel shader uses builtin varyings\n");
+        /* Map builtins to builtins */
+        for(i = 0; i < 8; i++)
+        {
+            priv_ctx->texcrd_output[i] = texcoords[i];
+        }
+        priv_ctx->color_output[0] = "result.color.primary";
+        priv_ctx->color_output[1] = "result.color.secondary";
+        priv_ctx->fog_output = "TMP_FOGCOORD";
+
+        /* Map declared regs to builtins. Use "TA" to /dev/null unread output */
+        for (i = 0; i < (sizeof(shader->output_signature) / sizeof(*shader->output_signature)); ++i)
+        {
+            semantic_name = shader->output_signature[i].semantic_name;
+            if (!semantic_name) continue;
+
+            if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_POSITION))
+            {
+                TRACE("o%u is TMP_OUT\n", i);
+                if (!shader->output_signature[i].semantic_idx) priv_ctx->vs_output[i] = "TMP_OUT";
+                else priv_ctx->vs_output[i] = "TA";
+            }
+            else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_PSIZE))
+            {
+                TRACE("o%u is result.pointsize\n", i);
+                if (!shader->output_signature[i].semantic_idx) priv_ctx->vs_output[i] = "result.pointsize";
+                else priv_ctx->vs_output[i] = "TA";
+            }
+            else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_COLOR))
+            {
+                TRACE("o%u is result.color.?, idx %u\n", i, shader->output_signature[i].semantic_idx);
+                if (!shader->output_signature[i].semantic_idx)
+                    priv_ctx->vs_output[i] = "result.color.primary";
+                else if (shader->output_signature[i].semantic_idx == 1)
+                    priv_ctx->vs_output[i] = "result.color.secondary";
+                else priv_ctx->vs_output[i] = "TA";
+            }
+            else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_TEXCOORD))
+            {
+                TRACE("o%u is %s\n", i, texcoords[shader->output_signature[i].semantic_idx]);
+                if (shader->output_signature[i].semantic_idx >= 8) priv_ctx->vs_output[i] = "TA";
+                else priv_ctx->vs_output[i] = texcoords[shader->output_signature[i].semantic_idx];
+            }
+            else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_FOG))
+            {
+                TRACE("o%u is result.fogcoord\n", i);
+                if (shader->output_signature[i].semantic_idx > 0) priv_ctx->vs_output[i] = "TA";
+                else priv_ctx->vs_output[i] = "result.fogcoord";
+            }
+            else
+            {
+                priv_ctx->vs_output[i] = "TA";
+            }
+        }
+        return;
+    }
+
+    TRACE("Pixel shader uses declared varyings\n");
+
+    /* Map builtin to declared. /dev/null the results by default to the TA temp reg */
+    for(i = 0; i < 8; i++)
+    {
+        priv_ctx->texcrd_output[i] = "TA";
+    }
+    priv_ctx->color_output[0] = "TA";
+    priv_ctx->color_output[1] = "TA";
+    priv_ctx->fog_output = "TA";
+
+    for(i = 0; i < MAX_REG_INPUT; i++)
+    {
+        semantic_name = ps_input_sig[i].semantic_name;
+        semantic_idx = ps_input_sig[i].semantic_idx;
+        reg_idx = ps_input_sig[i].register_idx;
+        if (!semantic_name) continue;
+
+        /* If a declared input register is not written by builtin arguments, don't write to it.
+         * GL_NV_vertex_program makes sure the input defaults to 0.0, which is correct with D3D
+         *
+         * Don't care about POSITION and PSIZE here - this is a builtin vertex shader, position goes
+         * to TMP_OUT in any case
+         */
+        if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_TEXCOORD))
+        {
+            if (semantic_idx < 8)
+                priv_ctx->texcrd_output[semantic_idx] = decl_idx_to_string[reg_idx];
+        }
+        else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_COLOR))
+        {
+            if (semantic_idx < 2)
+                priv_ctx->color_output[semantic_idx] = decl_idx_to_string[reg_idx];
+        }
+        else if(shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_FOG))
+        {
+            if (!semantic_idx)
+                priv_ctx->fog_output = decl_idx_to_string[reg_idx];
+        }
+        else
+        {
+            continue;
+        }
+
+        if (!strcmp(decl_idx_to_string[reg_idx], "result.color.primary")
+                || !strcmp(decl_idx_to_string[reg_idx], "result.color.secondary"))
+        {
+            compiled->need_color_unclamp = TRUE;
+        }
+    }
+
+    /* Map declared to declared */
+    for (i = 0; i < (sizeof(shader->output_signature) / sizeof(*shader->output_signature)); ++i)
+    {
+        /* Write unread output to TA to throw them away */
+        priv_ctx->vs_output[i] = "TA";
+        semantic_name = shader->output_signature[i].semantic_name;
+        if (!semantic_name) continue;
+
+        if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_POSITION)
+                && !shader->output_signature[i].semantic_idx)
+        {
+            priv_ctx->vs_output[i] = "TMP_OUT";
+            continue;
+        }
+        else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_PSIZE)
+                && !shader->output_signature[i].semantic_idx)
+        {
+            priv_ctx->vs_output[i] = "result.pointsize";
+            continue;
+        }
+
+        for(j = 0; j < MAX_REG_INPUT; j++)
+        {
+            if (!ps_input_sig[j].semantic_name) continue;
+
+            if (!strcmp(ps_input_sig[j].semantic_name, semantic_name)
+                    && ps_input_sig[j].semantic_idx == shader->output_signature[i].semantic_idx)
+            {
+                priv_ctx->vs_output[i] = decl_idx_to_string[ps_input_sig[j].register_idx];
+
+                if (!strcmp(priv_ctx->vs_output[i], "result.color.primary")
+                        || !strcmp(priv_ctx->vs_output[i], "result.color.secondary"))
+                {
+                    compiled->need_color_unclamp = TRUE;
+                }
+            }
+        }
+    }
+}
+
+/* Context activation is done by the caller. */
+static GLuint shader_arb_generate_vshader(const struct wined3d_shader *shader,
+        const struct wined3d_gl_info *gl_info, struct wined3d_shader_buffer *buffer,
+        const struct arb_vs_compile_args *args, struct arb_vs_compiled_shader *compiled,
+        const struct wined3d_shader_signature_element *ps_input_sig)
+{
+    const struct arb_vshader_private *shader_data = shader->backend_data;
+    const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
+    struct shader_arb_priv *priv = shader->device->shader_priv;
+    const DWORD *function = shader->function;
+    GLuint ret;
+    DWORD next_local = 0;
+    struct shader_arb_ctx_priv priv_ctx;
+    unsigned int i;
+    GLint errPos;
+
+    memset(&priv_ctx, 0, sizeof(priv_ctx));
+    priv_ctx.cur_vs_args = args;
+    list_init(&priv_ctx.control_frames);
+    init_output_registers(shader, ps_input_sig, &priv_ctx, compiled);
+
+    /*  Create the hw ARB shader */
+    shader_addline(buffer, "!!ARBvp1.0\n");
+
+    /* Always enable the NV extension if available. Unlike fragment shaders, there is no
+     * mesurable performance penalty, and we can always make use of it for clipplanes.
+     */
+    if (gl_info->supported[NV_VERTEX_PROGRAM3])
+    {
+        shader_addline(buffer, "OPTION NV_vertex_program3;\n");
+        priv_ctx.target_version = NV3;
+        shader_addline(buffer, "ADDRESS aL;\n");
+    }
+    else if (gl_info->supported[NV_VERTEX_PROGRAM2_OPTION])
+    {
+        shader_addline(buffer, "OPTION NV_vertex_program2;\n");
+        priv_ctx.target_version = NV2;
+        shader_addline(buffer, "ADDRESS aL;\n");
+    } else {
+        priv_ctx.target_version = ARB;
+    }
+
+    shader_addline(buffer, "TEMP TMP_OUT;\n");
+    if (reg_maps->fog)
+        shader_addline(buffer, "TEMP TMP_FOGCOORD;\n");
+    if (need_helper_const(shader_data, reg_maps, gl_info))
+    {
+        shader_addline(buffer, "PARAM helper_const = { 0.0, 1.0, 2.0, %1.10f};\n", eps);
+    }
+    if (need_rel_addr_const(shader_data, reg_maps, gl_info))
+    {
+        shader_addline(buffer, "PARAM rel_addr_const = { 0.5, %d.0, 0.0, 0.0 };\n", shader_data->rel_offset);
+        shader_addline(buffer, "TEMP A0_SHADOW;\n");
+    }
+
+    shader_addline(buffer, "TEMP TA;\n");
+    shader_addline(buffer, "TEMP TB;\n");
+
+    /* Base Declarations */
+    shader_generate_arb_declarations(shader, reg_maps, buffer, gl_info,
+            &priv_ctx.vs_clipplanes, &priv_ctx);
+
+    for(i = 0; i < MAX_CONST_I; i++)
+    {
+        compiled->int_consts[i] = WINED3D_CONST_NUM_UNUSED;
+        if(reg_maps->integer_constants & (1 << i) && priv_ctx.target_version >= NV2)
+        {
+            const DWORD *control_values = find_loop_control_values(shader, i);
+
+            if(control_values)
+            {
+                shader_addline(buffer, "PARAM I%u = {%u, %u, %u, -1};\n", i,
+                                control_values[0], control_values[1], control_values[2]);
+            }
+            else
+            {
+                compiled->int_consts[i] = next_local;
+                compiled->num_int_consts++;
+                shader_addline(buffer, "PARAM I%u = program.local[%u];\n", i, next_local++);
+            }
+        }
+    }
+
+    /* We need a constant to fixup the final position */
+    shader_addline(buffer, "PARAM posFixup = program.local[%u];\n", next_local);
+    compiled->pos_fixup = next_local++;
+
+    /* Initialize output parameters. GL_ARB_vertex_program does not require special initialization values
+     * for output parameters. D3D in theory does not do that either, but some applications depend on a
+     * proper initialization of the secondary color, and programs using the fixed function pipeline without
+     * a replacement shader depend on the texcoord.w being set properly.
+     *
+     * GL_NV_vertex_program defines that all output values are initialized to {0.0, 0.0, 0.0, 1.0}. This
+     * assertion is in effect even when using GL_ARB_vertex_program without any NV specific additions. So
+     * skip this if NV_vertex_program is supported. Otherwise, initialize the secondary color. For the tex-
+     * coords, we have a flag in the opengl caps. Many cards do not require the texcoord being set, and
+     * this can eat a number of instructions, so skip it unless this cap is set as well
+     */
+    if (!gl_info->supported[NV_VERTEX_PROGRAM])
+    {
+        const char *color_init = arb_get_helper_value(WINED3D_SHADER_TYPE_VERTEX, ARB_0001);
+        shader_addline(buffer, "MOV result.color.secondary, %s;\n", color_init);
+
+        if (gl_info->quirks & WINED3D_QUIRK_SET_TEXCOORD_W && !priv->ffp_proj_control)
+        {
+            int i;
+            const char *one = arb_get_helper_value(WINED3D_SHADER_TYPE_VERTEX, ARB_ONE);
+            for(i = 0; i < min(8, MAX_REG_TEXCRD); i++)
+            {
+                if (reg_maps->texcoord_mask[i] && reg_maps->texcoord_mask[i] != WINED3DSP_WRITEMASK_ALL)
+                    shader_addline(buffer, "MOV result.texcoord[%u].w, %s\n", i, one);
+            }
+        }
+    }
+
+    /* The shader starts with the main function */
+    priv_ctx.in_main_func = TRUE;
+    /* Base Shader Body */
+    shader_generate_main(shader, buffer, reg_maps, function, &priv_ctx);
+
+    if (!priv_ctx.footer_written) vshader_add_footer(&priv_ctx,
+            shader_data, args, reg_maps, gl_info, buffer);
+
+    shader_addline(buffer, "END\n");
+
+    /* TODO: change to resource.glObjectHandle or something like that */
+    GL_EXTCALL(glGenProgramsARB(1, &ret));
+
+    TRACE("Creating a hw vertex shader, prg=%d\n", ret);
+    GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, ret));
+
+    TRACE("Created hw vertex shader, prg=%d\n", ret);
+    /* Create the program and check for errors */
+    GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
+               buffer->content_size, buffer->buffer));
+    checkGLcall("glProgramStringARB()");
+
+    gl_info->gl_ops.gl.p_glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
+    if (errPos != -1)
+    {
+        FIXME("HW VertexShader Error at position %d: %s\n\n",
+              errPos, debugstr_a((const char *)gl_info->gl_ops.gl.p_glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
+        shader_arb_dump_program_source(buffer->buffer);
+        ret = -1;
+    }
+    else
+    {
+        GLint native;
+
+        GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &native));
+        checkGLcall("glGetProgramivARB()");
+        if (!native) WARN("Program exceeds native resource limits.\n");
+        }
+
+    return ret;
+}
+
+/* Context activation is done by the caller. */
+static struct arb_ps_compiled_shader *find_arb_pshader(struct wined3d_shader *shader,
+        const struct arb_ps_compile_args *args)
+{
+    struct wined3d_device *device = shader->device;
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
+    UINT i;
+    DWORD new_size;
+    struct arb_ps_compiled_shader *new_array;
+    struct wined3d_shader_buffer buffer;
+    struct arb_pshader_private *shader_data;
+    GLuint ret;
+
+    if (!shader->backend_data)
+    {
+        struct shader_arb_priv *priv = device->shader_priv;
+
+        shader->backend_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*shader_data));
+        shader_data = shader->backend_data;
+        shader_data->clamp_consts = shader->reg_maps.shader_version.major == 1;
+
+        if (shader->reg_maps.shader_version.major < 3)
+            shader_data->input_signature_idx = ~0U;
+        else
+            shader_data->input_signature_idx = find_input_signature(priv, shader->input_signature);
+
+        TRACE("Shader got assigned input signature index %u\n", shader_data->input_signature_idx);
+
+        if (!d3d_info->vs_clipping)
+            shader_data->clipplane_emulation = shader_find_free_input_register(&shader->reg_maps,
+                    d3d_info->limits.ffp_blend_stages - 1);
+        else
+            shader_data->clipplane_emulation = ~0U;
+    }
+    shader_data = shader->backend_data;
+
+    /* Usually we have very few GL shaders for each d3d shader(just 1 or maybe 2),
+     * so a linear search is more performant than a hashmap or a binary search
+     * (cache coherency etc)
+     */
+    for (i = 0; i < shader_data->num_gl_shaders; ++i)
+    {
+        if (!memcmp(&shader_data->gl_shaders[i].args, args, sizeof(*args)))
+            return &shader_data->gl_shaders[i];
+    }
+
+    TRACE("No matching GL shader found, compiling a new shader\n");
+    if(shader_data->shader_array_size == shader_data->num_gl_shaders) {
+        if (shader_data->num_gl_shaders)
+        {
+            new_size = shader_data->shader_array_size + max(1, shader_data->shader_array_size / 2);
+            new_array = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, shader_data->gl_shaders,
+                                    new_size * sizeof(*shader_data->gl_shaders));
+        } else {
+            new_array = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*shader_data->gl_shaders));
+            new_size = 1;
+        }
+
+        if(!new_array) {
+            ERR("Out of memory\n");
+            return 0;
+        }
+        shader_data->gl_shaders = new_array;
+        shader_data->shader_array_size = new_size;
+    }
+
+    shader_data->gl_shaders[shader_data->num_gl_shaders].args = *args;
+
+    pixelshader_update_samplers(shader, args->super.tex_types);
+
+    if (!shader_buffer_init(&buffer))
+    {
+        ERR("Failed to initialize shader buffer.\n");
+        return 0;
+    }
+
+    ret = shader_arb_generate_pshader(shader, gl_info, &buffer, args,
+            &shader_data->gl_shaders[shader_data->num_gl_shaders]);
+    shader_buffer_free(&buffer);
+    shader_data->gl_shaders[shader_data->num_gl_shaders].prgId = ret;
+
+    return &shader_data->gl_shaders[shader_data->num_gl_shaders++];
+}
+
+static inline BOOL vs_args_equal(const struct arb_vs_compile_args *stored, const struct arb_vs_compile_args *new,
+                                 const DWORD use_map, BOOL skip_int) {
+    if((stored->super.swizzle_map & use_map) != new->super.swizzle_map) return FALSE;
+    if(stored->super.clip_enabled != new->super.clip_enabled) return FALSE;
+    if(stored->super.fog_src != new->super.fog_src) return FALSE;
+    if(stored->clip.boolclip_compare != new->clip.boolclip_compare) return FALSE;
+    if(stored->ps_signature != new->ps_signature) return FALSE;
+    if(stored->vertex.samplers_compare != new->vertex.samplers_compare) return FALSE;
+    if(skip_int) return TRUE;
+
+    return !memcmp(stored->loop_ctrl, new->loop_ctrl, sizeof(stored->loop_ctrl));
+}
+
+static struct arb_vs_compiled_shader *find_arb_vshader(struct wined3d_shader *shader,
+        const struct arb_vs_compile_args *args,
+        const struct wined3d_shader_signature_element *ps_input_sig)
+{
+    struct wined3d_device *device = shader->device;
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    DWORD use_map = device->stream_info.use_map;
+    UINT i;
+    DWORD new_size;
+    struct arb_vs_compiled_shader *new_array;
+    struct wined3d_shader_buffer buffer;
+    struct arb_vshader_private *shader_data;
+    GLuint ret;
+
+    if (!shader->backend_data)
+    {
+        const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
+
+        shader->backend_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*shader_data));
+        shader_data = shader->backend_data;
+
+        if ((gl_info->quirks & WINED3D_QUIRK_ARB_VS_OFFSET_LIMIT)
+                && reg_maps->min_rel_offset <= reg_maps->max_rel_offset)
+        {
+            if (reg_maps->max_rel_offset - reg_maps->min_rel_offset > 127)
+            {
+                FIXME("The difference between the minimum and maximum relative offset is > 127.\n");
+                FIXME("Which this OpenGL implementation does not support. Try using GLSL.\n");
+                FIXME("Min: %u, Max: %u.\n", reg_maps->min_rel_offset, reg_maps->max_rel_offset);
+            }
+            else if (reg_maps->max_rel_offset - reg_maps->min_rel_offset > 63)
+                shader_data->rel_offset = reg_maps->min_rel_offset + 63;
+            else if (reg_maps->max_rel_offset > 63)
+                shader_data->rel_offset = reg_maps->min_rel_offset;
+        }
+    }
+    shader_data = shader->backend_data;
+
+    /* Usually we have very few GL shaders for each d3d shader(just 1 or maybe 2),
+     * so a linear search is more performant than a hashmap or a binary search
+     * (cache coherency etc)
+     */
+    for(i = 0; i < shader_data->num_gl_shaders; i++) {
+        if (vs_args_equal(&shader_data->gl_shaders[i].args, args,
+                use_map, gl_info->supported[NV_VERTEX_PROGRAM2_OPTION]))
+        {
+            return &shader_data->gl_shaders[i];
+        }
+    }
+
+    TRACE("No matching GL shader found, compiling a new shader\n");
+
+    if(shader_data->shader_array_size == shader_data->num_gl_shaders) {
+        if (shader_data->num_gl_shaders)
+        {
+            new_size = shader_data->shader_array_size + max(1, shader_data->shader_array_size / 2);
+            new_array = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, shader_data->gl_shaders,
+                                    new_size * sizeof(*shader_data->gl_shaders));
+        } else {
+            new_array = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*shader_data->gl_shaders));
+            new_size = 1;
+        }
+
+        if(!new_array) {
+            ERR("Out of memory\n");
+            return 0;
+        }
+        shader_data->gl_shaders = new_array;
+        shader_data->shader_array_size = new_size;
+    }
+
+    shader_data->gl_shaders[shader_data->num_gl_shaders].args = *args;
+
+    if (!shader_buffer_init(&buffer))
+    {
+        ERR("Failed to initialize shader buffer.\n");
+        return 0;
+    }
+
+    ret = shader_arb_generate_vshader(shader, gl_info, &buffer, args,
+            &shader_data->gl_shaders[shader_data->num_gl_shaders],
+            ps_input_sig);
+    shader_buffer_free(&buffer);
+    shader_data->gl_shaders[shader_data->num_gl_shaders].prgId = ret;
+
+    return &shader_data->gl_shaders[shader_data->num_gl_shaders++];
+}
+
+static void find_arb_ps_compile_args(const struct wined3d_state *state,
+        const struct wined3d_context *context, const struct wined3d_shader *shader,
+        struct arb_ps_compile_args *args)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    const struct wined3d_d3d_info *d3d_info = context->d3d_info;
+    int i;
+    WORD int_skip;
+
+    find_ps_compile_args(state, shader, &args->super);
+
+    /* This forces all local boolean constants to 1 to make them stateblock independent */
+    args->bools = shader->reg_maps.local_bool_consts;
+
+    for(i = 0; i < MAX_CONST_B; i++)
+    {
+        if (state->ps_consts_b[i])
+            args->bools |= ( 1 << i);
+    }
+
+    /* Only enable the clip plane emulation KIL if at least one clipplane is enabled. The KIL instruction
+     * is quite expensive because it forces the driver to disable early Z discards. It is cheaper to
+     * duplicate the shader than have a no-op KIL instruction in every shader
+     */
+    if (!d3d_info->vs_clipping && use_vs(state)
+            && state->render_states[WINED3D_RS_CLIPPING]
+            && state->render_states[WINED3D_RS_CLIPPLANEENABLE])
+        args->clip = 1;
+    else
+        args->clip = 0;
+
+    /* Skip if unused or local, or supported natively */
+    int_skip = ~shader->reg_maps.integer_constants | shader->reg_maps.local_int_consts;
+    if (int_skip == 0xffff || gl_info->supported[NV_FRAGMENT_PROGRAM_OPTION])
+    {
+        memset(args->loop_ctrl, 0, sizeof(args->loop_ctrl));
+        return;
+    }
+
+    for(i = 0; i < MAX_CONST_I; i++)
+    {
+        if(int_skip & (1 << i))
+        {
+            args->loop_ctrl[i][0] = 0;
+            args->loop_ctrl[i][1] = 0;
+            args->loop_ctrl[i][2] = 0;
+        }
+        else
+        {
+            args->loop_ctrl[i][0] = state->ps_consts_i[i * 4];
+            args->loop_ctrl[i][1] = state->ps_consts_i[i * 4 + 1];
+            args->loop_ctrl[i][2] = state->ps_consts_i[i * 4 + 2];
+        }
+    }
+}
+
+static void find_arb_vs_compile_args(const struct wined3d_state *state,
+        const struct wined3d_context *context, const struct wined3d_shader *shader,
+        struct arb_vs_compile_args *args)
+{
+    struct wined3d_device *device = shader->device;
+    const struct wined3d_adapter *adapter = device->adapter;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    const struct wined3d_d3d_info *d3d_info = context->d3d_info;
+    int i;
+    WORD int_skip;
+
+    find_vs_compile_args(state, shader, &args->super);
+
+    args->clip.boolclip_compare = 0;
+    if (use_ps(state))
+    {
+        const struct wined3d_shader *ps = state->pixel_shader;
+        const struct arb_pshader_private *shader_priv = ps->backend_data;
+        args->ps_signature = shader_priv->input_signature_idx;
+
+        args->clip.boolclip.clip_texcoord = shader_priv->clipplane_emulation + 1;
+    }
+    else
+    {
+        args->ps_signature = ~0;
+        if (!d3d_info->vs_clipping && adapter->fragment_pipe == &arbfp_fragment_pipeline)
+        {
+            args->clip.boolclip.clip_texcoord = ffp_clip_emul(state) ? d3d_info->limits.ffp_blend_stages : 0;
+        }
+        /* Otherwise: Setting boolclip_compare set clip_texcoord to 0 */
+    }
+
+    if (args->clip.boolclip.clip_texcoord)
+    {
+        if (state->render_states[WINED3D_RS_CLIPPING])
+            args->clip.boolclip.clipplane_mask = (unsigned char)state->render_states[WINED3D_RS_CLIPPLANEENABLE];
+        /* clipplane_mask was set to 0 by setting boolclip_compare to 0 */
+    }
+
+    /* This forces all local boolean constants to 1 to make them stateblock independent */
+    args->clip.boolclip.bools = shader->reg_maps.local_bool_consts;
+    /* TODO: Figure out if it would be better to store bool constants as bitmasks in the stateblock */
+    for(i = 0; i < MAX_CONST_B; i++)
+    {
+        if (state->vs_consts_b[i])
+            args->clip.boolclip.bools |= ( 1 << i);
+    }
+
+    args->vertex.samplers[0] = device->texUnitMap[MAX_FRAGMENT_SAMPLERS + 0];
+    args->vertex.samplers[1] = device->texUnitMap[MAX_FRAGMENT_SAMPLERS + 1];
+    args->vertex.samplers[2] = device->texUnitMap[MAX_FRAGMENT_SAMPLERS + 2];
+    args->vertex.samplers[3] = 0;
+
+    /* Skip if unused or local */
+    int_skip = ~shader->reg_maps.integer_constants | shader->reg_maps.local_int_consts;
+    /* This is about flow control, not clipping. */
+    if (int_skip == 0xffff || gl_info->supported[NV_VERTEX_PROGRAM2_OPTION])
+    {
+        memset(args->loop_ctrl, 0, sizeof(args->loop_ctrl));
+        return;
+    }
+
+    for(i = 0; i < MAX_CONST_I; i++)
+    {
+        if(int_skip & (1 << i))
+        {
+            args->loop_ctrl[i][0] = 0;
+            args->loop_ctrl[i][1] = 0;
+            args->loop_ctrl[i][2] = 0;
+        }
+        else
+        {
+            args->loop_ctrl[i][0] = state->vs_consts_i[i * 4];
+            args->loop_ctrl[i][1] = state->vs_consts_i[i * 4 + 1];
+            args->loop_ctrl[i][2] = state->vs_consts_i[i * 4 + 2];
+        }
+    }
+}
+
+/* Context activation is done by the caller. */
+static void shader_arb_select(void *shader_priv, const struct wined3d_context *context,
+        const struct wined3d_state *state)
+{
+    struct shader_arb_priv *priv = shader_priv;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    int i;
+
+    /* Deal with pixel shaders first so the vertex shader arg function has the input signature ready */
+    if (use_ps(state))
+    {
+        struct wined3d_shader *ps = state->pixel_shader;
+        struct arb_ps_compile_args compile_args;
+        struct arb_ps_compiled_shader *compiled;
+
+        TRACE("Using pixel shader %p.\n", ps);
+        find_arb_ps_compile_args(state, context, ps, &compile_args);
+        compiled = find_arb_pshader(ps, &compile_args);
+        priv->current_fprogram_id = compiled->prgId;
+        priv->compiled_fprog = compiled;
+
+        /* Bind the fragment program */
+        GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, priv->current_fprogram_id));
+        checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, priv->current_fprogram_id);");
+
+        if (!priv->use_arbfp_fixed_func)
+            priv->fragment_pipe->enable_extension(gl_info, FALSE);
+
+        /* Enable OpenGL fragment programs. */
+        gl_info->gl_ops.gl.p_glEnable(GL_FRAGMENT_PROGRAM_ARB);
+        checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
+
+        TRACE("Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n", priv->current_fprogram_id);
+
+        /* Pixel Shader 1.x constants are clamped to [-1;1], Pixel Shader 2.0 constants are not. If switching between
+         * a 1.x and newer shader, reload the first 8 constants
+         */
+        if (priv->last_ps_const_clamped != ((struct arb_pshader_private *)ps->backend_data)->clamp_consts)
+        {
+            priv->last_ps_const_clamped = ((struct arb_pshader_private *)ps->backend_data)->clamp_consts;
+            priv->highest_dirty_ps_const = max(priv->highest_dirty_ps_const, 8);
+            for(i = 0; i < 8; i++)
+            {
+                priv->pshader_const_dirty[i] = 1;
+            }
+            /* Also takes care of loading local constants */
+            shader_arb_load_constants_internal(shader_priv, context, state, TRUE, FALSE, TRUE);
+        }
+        else
+        {
+            UINT rt_height = state->fb->render_targets[0]->resource.height;
+            shader_arb_ps_local_constants(compiled, context, state, rt_height);
+        }
+
+        /* Force constant reloading for the NP2 fixup (see comment in shader_glsl_select for more info) */
+        if (compiled->np2fixup_info.super.active)
+            shader_arb_load_np2fixup_constants(priv, gl_info, state);
+    }
+    else
+    {
+        if (gl_info->supported[ARB_FRAGMENT_PROGRAM] && !priv->use_arbfp_fixed_func)
+        {
+            /* Disable only if we're not using arbfp fixed function fragment
+             * processing. If this is used, keep GL_FRAGMENT_PROGRAM_ARB
+             * enabled, and the fixed function pipeline will bind the fixed
+             * function replacement shader. */
+            gl_info->gl_ops.gl.p_glDisable(GL_FRAGMENT_PROGRAM_ARB);
+            checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)");
+            priv->current_fprogram_id = 0;
+        }
+        priv->fragment_pipe->enable_extension(gl_info, TRUE);
+    }
+
+    if (use_vs(state))
+    {
+        struct wined3d_shader *vs = state->vertex_shader;
+        struct arb_vs_compile_args compile_args;
+        struct arb_vs_compiled_shader *compiled;
+        const struct wined3d_shader_signature_element *ps_input_sig;
+
+        TRACE("Using vertex shader %p\n", vs);
+        find_arb_vs_compile_args(state, context, vs, &compile_args);
+
+        /* Instead of searching for the signature in the signature list, read the one from the
+         * current pixel shader. It's maybe not the shader where the signature came from, but it
+         * is the same signature and faster to find. */
+        if (compile_args.ps_signature == ~0U)
+            ps_input_sig = NULL;
+        else
+            ps_input_sig = state->pixel_shader->input_signature;
+
+        compiled = find_arb_vshader(vs, &compile_args, ps_input_sig);
+        priv->current_vprogram_id = compiled->prgId;
+        priv->compiled_vprog = compiled;
+
+        /* Bind the vertex program */
+        GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id));
+        checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id);");
+
+        priv->vertex_pipe->vp_enable(gl_info, FALSE);
+
+        /* Enable OpenGL vertex programs */
+        gl_info->gl_ops.gl.p_glEnable(GL_VERTEX_PROGRAM_ARB);
+        checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
+        TRACE("Bound vertex program %u and enabled GL_VERTEX_PROGRAM_ARB\n", priv->current_vprogram_id);
+        shader_arb_vs_local_constants(compiled, context, state);
+
+        if(priv->last_vs_color_unclamp != compiled->need_color_unclamp) {
+            priv->last_vs_color_unclamp = compiled->need_color_unclamp;
+
+            if (gl_info->supported[ARB_COLOR_BUFFER_FLOAT])
+            {
+                GL_EXTCALL(glClampColorARB(GL_CLAMP_VERTEX_COLOR_ARB, !compiled->need_color_unclamp));
+                checkGLcall("glClampColorARB");
+            } else {
+                FIXME("vertex color clamp needs to be changed, but extension not supported.\n");
+            }
+        }
+    }
+    else
+    {
+        if (gl_info->supported[ARB_VERTEX_PROGRAM])
+    {
+        priv->current_vprogram_id = 0;
+        gl_info->gl_ops.gl.p_glDisable(GL_VERTEX_PROGRAM_ARB);
+        checkGLcall("glDisable(GL_VERTEX_PROGRAM_ARB)");
+    }
+        priv->vertex_pipe->vp_enable(gl_info, TRUE);
+    }
+}
+
+
+/* Context activation is done by the caller. */
+static void shader_arb_disable(void *shader_priv, const struct wined3d_context *context)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    struct shader_arb_priv *priv = shader_priv;
+
+    if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_FRAGMENT_PROGRAM_ARB);
+        checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)");
+        priv->current_fprogram_id = 0;
+    }
+    priv->fragment_pipe->enable_extension(gl_info, FALSE);
+
+    if (gl_info->supported[ARB_VERTEX_PROGRAM])
+    {
+        priv->current_vprogram_id = 0;
+        gl_info->gl_ops.gl.p_glDisable(GL_VERTEX_PROGRAM_ARB);
+        checkGLcall("glDisable(GL_VERTEX_PROGRAM_ARB)");
+    }
+    priv->vertex_pipe->vp_enable(gl_info, FALSE);
+
+    if (gl_info->supported[ARB_COLOR_BUFFER_FLOAT] && priv->last_vs_color_unclamp)
+    {
+        GL_EXTCALL(glClampColorARB(GL_CLAMP_VERTEX_COLOR_ARB, GL_FIXED_ONLY_ARB));
+        checkGLcall("glClampColorARB");
+        priv->last_vs_color_unclamp = FALSE;
+    }
+}
+
+/* Context activation is done by the caller. */
+static void shader_arb_select_depth_blt(void *shader_priv, const struct wined3d_gl_info *gl_info,
+        enum tex_types tex_type, const SIZE *ds_mask_size)
+{
+    const float mask[] = {0.0f, 0.0f, (float)ds_mask_size->cx, (float)ds_mask_size->cy};
+    BOOL masked = ds_mask_size->cx && ds_mask_size->cy;
+    struct shader_arb_priv *priv = shader_priv;
+    GLuint *blt_fprogram;
+
+    if (!priv->depth_blt_vprogram_id) priv->depth_blt_vprogram_id = create_arb_blt_vertex_program(gl_info);
+    GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->depth_blt_vprogram_id));
+    gl_info->gl_ops.gl.p_glEnable(GL_VERTEX_PROGRAM_ARB);
+
+    blt_fprogram = masked ? &priv->depth_blt_fprogram_id_masked[tex_type] : &priv->depth_blt_fprogram_id_full[tex_type];
+    if (!*blt_fprogram) *blt_fprogram = create_arb_blt_fragment_program(gl_info, tex_type, masked);
+    GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, *blt_fprogram));
+    if (masked) GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 0, mask));
+    gl_info->gl_ops.gl.p_glEnable(GL_FRAGMENT_PROGRAM_ARB);
+}
+
+/* Context activation is done by the caller. */
+static void shader_arb_deselect_depth_blt(void *shader_priv, const struct wined3d_gl_info *gl_info)
+{
+    struct shader_arb_priv *priv = shader_priv;
+
+    if (priv->current_vprogram_id) {
+        GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id));
+        checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertexShader->prgId);");
+
+        TRACE("Bound vertex program %u and enabled GL_VERTEX_PROGRAM_ARB.\n", priv->current_vprogram_id);
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_VERTEX_PROGRAM_ARB);
+        checkGLcall("glDisable(GL_VERTEX_PROGRAM_ARB)");
+    }
+
+    if (priv->current_fprogram_id) {
+        GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, priv->current_fprogram_id));
+        checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixelShader->prgId);");
+
+        TRACE("Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB.\n", priv->current_fprogram_id);
+    }
+    else if(!priv->use_arbfp_fixed_func)
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_FRAGMENT_PROGRAM_ARB);
+        checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)");
+    }
+}
+
+static void shader_arb_destroy(struct wined3d_shader *shader)
+{
+    struct wined3d_device *device = shader->device;
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+
+    if (shader_is_pshader_version(shader->reg_maps.shader_version.type))
+    {
+        struct arb_pshader_private *shader_data = shader->backend_data;
+        UINT i;
+
+        if(!shader_data) return; /* This can happen if a shader was never compiled */
+
+        if (shader_data->num_gl_shaders)
+        {
+            struct wined3d_context *context = context_acquire(device, NULL);
+
+            for (i = 0; i < shader_data->num_gl_shaders; ++i)
+            {
+                GL_EXTCALL(glDeleteProgramsARB(1, &shader_data->gl_shaders[i].prgId));
+                checkGLcall("GL_EXTCALL(glDeleteProgramsARB(1, &shader_data->gl_shaders[i].prgId))");
+            }
+
+            context_release(context);
+        }
+
+        HeapFree(GetProcessHeap(), 0, shader_data->gl_shaders);
+        HeapFree(GetProcessHeap(), 0, shader_data);
+        shader->backend_data = NULL;
+    }
+    else
+    {
+        struct arb_vshader_private *shader_data = shader->backend_data;
+        UINT i;
+
+        if(!shader_data) return; /* This can happen if a shader was never compiled */
+
+        if (shader_data->num_gl_shaders)
+        {
+            struct wined3d_context *context = context_acquire(device, NULL);
+
+            for (i = 0; i < shader_data->num_gl_shaders; ++i)
+            {
+                GL_EXTCALL(glDeleteProgramsARB(1, &shader_data->gl_shaders[i].prgId));
+                checkGLcall("GL_EXTCALL(glDeleteProgramsARB(1, &shader_data->gl_shaders[i].prgId))");
+            }
+
+            context_release(context);
+        }
+
+        HeapFree(GetProcessHeap(), 0, shader_data->gl_shaders);
+        HeapFree(GetProcessHeap(), 0, shader_data);
+        shader->backend_data = NULL;
+    }
+}
+
+static int sig_tree_compare(const void *key, const struct wine_rb_entry *entry)
+{
+    struct ps_signature *e = WINE_RB_ENTRY_VALUE(entry, struct ps_signature, entry);
+    return compare_sig(key, e->sig);
+}
+
+static const struct wine_rb_functions sig_tree_functions =
+{
+    wined3d_rb_alloc,
+    wined3d_rb_realloc,
+    wined3d_rb_free,
+    sig_tree_compare
+};
+
+static HRESULT shader_arb_alloc(struct wined3d_device *device, const struct wined3d_vertex_pipe_ops *vertex_pipe,
+        const struct fragment_pipeline *fragment_pipe)
+{
+    struct shader_arb_priv *priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*priv));
+    struct fragment_caps fragment_caps;
+    void *vertex_priv, *fragment_priv;
+    const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
+
+    if (!(vertex_priv = vertex_pipe->vp_alloc(&arb_program_shader_backend, priv)))
+    {
+        ERR("Failed to initialize vertex pipe.\n");
+        HeapFree(GetProcessHeap(), 0, priv);
+        return E_FAIL;
+    }
+
+    if (!(fragment_priv = fragment_pipe->alloc_private(&arb_program_shader_backend, priv)))
+    {
+        ERR("Failed to initialize fragment pipe.\n");
+        vertex_pipe->vp_free(device);
+        HeapFree(GetProcessHeap(), 0, priv);
+        return E_FAIL;
+    }
+
+    priv->vshader_const_dirty = HeapAlloc(GetProcessHeap(), 0,
+            sizeof(*priv->vshader_const_dirty) * d3d_info->limits.vs_uniform_count);
+    if (!priv->vshader_const_dirty)
+        goto fail;
+    memset(priv->vshader_const_dirty, 1,
+           sizeof(*priv->vshader_const_dirty) * d3d_info->limits.vs_uniform_count);
+
+    priv->pshader_const_dirty = HeapAlloc(GetProcessHeap(), 0,
+            sizeof(*priv->pshader_const_dirty) * d3d_info->limits.ps_uniform_count);
+    if (!priv->pshader_const_dirty)
+        goto fail;
+    memset(priv->pshader_const_dirty, 1,
+            sizeof(*priv->pshader_const_dirty) * d3d_info->limits.ps_uniform_count);
+
+    if(wine_rb_init(&priv->signature_tree, &sig_tree_functions) == -1)
+    {
+        ERR("RB tree init failed\n");
+        goto fail;
+    }
+
+    priv->vertex_pipe = vertex_pipe;
+    priv->fragment_pipe = fragment_pipe;
+    fragment_pipe->get_caps(&device->adapter->gl_info, &fragment_caps);
+    priv->ffp_proj_control = fragment_caps.wined3d_caps & WINED3D_FRAGMENT_CAP_PROJ_CONTROL;
+
+    device->vertex_priv = vertex_priv;
+    device->fragment_priv = fragment_priv;
+    device->shader_priv = priv;
+
+    return WINED3D_OK;
+
+fail:
+    HeapFree(GetProcessHeap(), 0, priv->pshader_const_dirty);
+    HeapFree(GetProcessHeap(), 0, priv->vshader_const_dirty);
+    fragment_pipe->free_private(device);
+    vertex_pipe->vp_free(device);
+    HeapFree(GetProcessHeap(), 0, priv);
+    return E_OUTOFMEMORY;
+}
+
+static void release_signature(struct wine_rb_entry *entry, void *context)
+{
+    struct ps_signature *sig = WINE_RB_ENTRY_VALUE(entry, struct ps_signature, entry);
+    int i;
+    for(i = 0; i < MAX_REG_INPUT; i++)
+    {
+        HeapFree(GetProcessHeap(), 0, (char *) sig->sig[i].semantic_name);
+    }
+    HeapFree(GetProcessHeap(), 0, sig->sig);
+    HeapFree(GetProcessHeap(), 0, sig);
+}
+
+/* Context activation is done by the caller. */
+static void shader_arb_free(struct wined3d_device *device)
+{
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    struct shader_arb_priv *priv = device->shader_priv;
+    int i;
+
+    if (priv->depth_blt_vprogram_id)
+        GL_EXTCALL(glDeleteProgramsARB(1, &priv->depth_blt_vprogram_id));
+
+    for (i = 0; i < tex_type_count; ++i)
+    {
+        if (priv->depth_blt_fprogram_id_full[i])
+        {
+            GL_EXTCALL(glDeleteProgramsARB(1, &priv->depth_blt_fprogram_id_full[i]));
+        }
+        if (priv->depth_blt_fprogram_id_masked[i])
+        {
+            GL_EXTCALL(glDeleteProgramsARB(1, &priv->depth_blt_fprogram_id_masked[i]));
+        }
+    }
+
+    wine_rb_destroy(&priv->signature_tree, release_signature, NULL);
+    HeapFree(GetProcessHeap(), 0, priv->pshader_const_dirty);
+    HeapFree(GetProcessHeap(), 0, priv->vshader_const_dirty);
+    priv->fragment_pipe->free_private(device);
+    priv->vertex_pipe->vp_free(device);
+    HeapFree(GetProcessHeap(), 0, device->shader_priv);
+}
+
+static void shader_arb_context_destroyed(void *shader_priv, const struct wined3d_context *context)
+{
+    struct shader_arb_priv *priv = shader_priv;
+
+    if (priv->last_context == context)
+        priv->last_context = NULL;
+}
+
+static void shader_arb_get_caps(const struct wined3d_gl_info *gl_info, struct shader_caps *caps)
+{
+    if (gl_info->supported[ARB_VERTEX_PROGRAM])
+    {
+        DWORD vs_consts;
+        UINT vs_version;
+
+        /* 96 is the minimum allowed value of MAX_PROGRAM_ENV_PARAMETERS_ARB
+         * for vertex programs. If the native limit is less than that it's
+         * not very useful, and e.g. Mesa swrast returns 0, probably to
+         * indicate it's a software implementation. */
+        if (gl_info->limits.arb_vs_native_constants < 96)
+            vs_consts = gl_info->limits.arb_vs_float_constants;
+        else
+            vs_consts = min(gl_info->limits.arb_vs_float_constants, gl_info->limits.arb_vs_native_constants);
+
+        if (gl_info->supported[NV_VERTEX_PROGRAM3])
+        {
+            vs_version = 3;
+            TRACE("Hardware vertex shader version 3.0 enabled (NV_VERTEX_PROGRAM3)\n");
+        }
+        else if (vs_consts >= 256)
+        {
+            /* Shader Model 2.0 requires at least 256 vertex shader constants */
+            vs_version = 2;
+            TRACE("Hardware vertex shader version 2.0 enabled (ARB_PROGRAM)\n");
+        }
+        else
+        {
+            vs_version = 1;
+            TRACE("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
+        }
+        caps->vs_version = min(wined3d_settings.max_sm_vs, vs_version);
+        caps->vs_uniform_count = vs_consts;
+    }
+    else
+    {
+        caps->vs_version = 0;
+        caps->vs_uniform_count = 0;
+    }
+
+    caps->gs_version = 0;
+
+    if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
+    {
+        DWORD ps_consts;
+        UINT ps_version;
+
+        /* Similar as above for vertex programs, but the minimum for fragment
+         * programs is 24. */
+        if (gl_info->limits.arb_ps_native_constants < 24)
+            ps_consts = gl_info->limits.arb_ps_float_constants;
+        else
+            ps_consts = min(gl_info->limits.arb_ps_float_constants, gl_info->limits.arb_ps_native_constants);
+
+        if (gl_info->supported[NV_FRAGMENT_PROGRAM2])
+        {
+            ps_version = 3;
+            TRACE("Hardware pixel shader version 3.0 enabled (NV_FRAGMENT_PROGRAM2)\n");
+        }
+        else if (ps_consts >= 32)
+        {
+            /* Shader Model 2.0 requires at least 32 pixel shader constants */
+            ps_version = 2;
+            TRACE("Hardware pixel shader version 2.0 enabled (ARB_PROGRAM)\n");
+        }
+        else
+        {
+            ps_version = 1;
+            TRACE("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
+        }
+        caps->ps_version = min(wined3d_settings.max_sm_ps, ps_version);
+        caps->ps_uniform_count = ps_consts;
+        caps->ps_1x_max_value = 8.0f;
+    }
+    else
+    {
+        caps->ps_version = 0;
+        caps->ps_uniform_count = 0;
+        caps->ps_1x_max_value = 0.0f;
+    }
+
+    caps->wined3d_caps = WINED3D_SHADER_CAP_SRGB_WRITE;
+    if (use_nv_clip(gl_info))
+        caps->wined3d_caps |= WINED3D_SHADER_CAP_VS_CLIPPING;
+}
+
+static BOOL shader_arb_color_fixup_supported(struct color_fixup_desc fixup)
+{
+    if (TRACE_ON(d3d_shader) && TRACE_ON(d3d))
+    {
+        TRACE("Checking support for color_fixup:\n");
+        dump_color_fixup_desc(fixup);
+    }
+
+    /* We support everything except complex conversions. */
+    if (!is_complex_fixup(fixup))
+    {
+        TRACE("[OK]\n");
+        return TRUE;
+    }
+
+    TRACE("[FAILED]\n");
+    return FALSE;
+}
+
+static void shader_arb_add_instruction_modifiers(const struct wined3d_shader_instruction *ins) {
+    DWORD shift;
+    char write_mask[20], regstr[50];
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    BOOL is_color = FALSE;
+    const struct wined3d_shader_dst_param *dst;
+
+    if (!ins->dst_count) return;
+
+    dst = &ins->dst[0];
+    shift = dst->shift;
+    if (!shift) return; /* Saturate alone is handled by the instructions */
+
+    shader_arb_get_write_mask(ins, dst, write_mask);
+    shader_arb_get_register_name(ins, &dst->reg, regstr, &is_color);
+
+    /* Generate a line that does the output modifier computation
+     * FIXME: _SAT vs shift? _SAT alone is already handled in the instructions, if this
+     * maps problems in e.g. _d4_sat modify shader_arb_get_modifier
+     */
+    shader_addline(buffer, "MUL%s %s%s, %s, %s;\n", shader_arb_get_modifier(ins),
+                   regstr, write_mask, regstr, shift_tab[shift]);
+}
+
+static const SHADER_HANDLER shader_arb_instruction_handler_table[WINED3DSIH_TABLE_SIZE] =
+{
+    /* WINED3DSIH_ABS                   */ shader_hw_map2gl,
+    /* WINED3DSIH_ADD                   */ shader_hw_map2gl,
+    /* WINED3DSIH_AND                   */ NULL,
+    /* WINED3DSIH_BEM                   */ pshader_hw_bem,
+    /* WINED3DSIH_BREAK                 */ shader_hw_break,
+    /* WINED3DSIH_BREAKC                */ shader_hw_breakc,
+    /* WINED3DSIH_BREAKP                */ NULL,
+    /* WINED3DSIH_CALL                  */ shader_hw_call,
+    /* WINED3DSIH_CALLNZ                */ NULL,
+    /* WINED3DSIH_CMP                   */ pshader_hw_cmp,
+    /* WINED3DSIH_CND                   */ pshader_hw_cnd,
+    /* WINED3DSIH_CRS                   */ shader_hw_map2gl,
+    /* WINED3DSIH_CUT                   */ NULL,
+    /* WINED3DSIH_DCL                   */ shader_hw_nop,
+    /* WINED3DSIH_DCL_CONSTANT_BUFFER   */ shader_hw_nop,
+    /* WINED3DSIH_DCL_INPUT_PRIMITIVE   */ shader_hw_nop,
+    /* WINED3DSIH_DCL_OUTPUT_TOPOLOGY   */ shader_hw_nop,
+    /* WINED3DSIH_DCL_VERTICES_OUT      */ shader_hw_nop,
+    /* WINED3DSIH_DEF                   */ shader_hw_nop,
+    /* WINED3DSIH_DEFB                  */ shader_hw_nop,
+    /* WINED3DSIH_DEFI                  */ shader_hw_nop,
+    /* WINED3DSIH_DIV                   */ NULL,
+    /* WINED3DSIH_DP2ADD                */ pshader_hw_dp2add,
+    /* WINED3DSIH_DP3                   */ shader_hw_map2gl,
+    /* WINED3DSIH_DP4                   */ shader_hw_map2gl,
+    /* WINED3DSIH_DST                   */ shader_hw_map2gl,
+    /* WINED3DSIH_DSX                   */ shader_hw_map2gl,
+    /* WINED3DSIH_DSY                   */ shader_hw_dsy,
+    /* WINED3DSIH_ELSE                  */ shader_hw_else,
+    /* WINED3DSIH_EMIT                  */ NULL,
+    /* WINED3DSIH_ENDIF                 */ shader_hw_endif,
+    /* WINED3DSIH_ENDLOOP               */ shader_hw_endloop,
+    /* WINED3DSIH_ENDREP                */ shader_hw_endrep,
+    /* WINED3DSIH_EQ                    */ NULL,
+    /* WINED3DSIH_EXP                   */ shader_hw_scalar_op,
+    /* WINED3DSIH_EXPP                  */ shader_hw_scalar_op,
+    /* WINED3DSIH_FRC                   */ shader_hw_map2gl,
+    /* WINED3DSIH_FTOI                  */ NULL,
+    /* WINED3DSIH_GE                    */ NULL,
+    /* WINED3DSIH_IADD                  */ NULL,
+    /* WINED3DSIH_IEQ                   */ NULL,
+    /* WINED3DSIH_IF                    */ NULL /* Hardcoded into the shader */,
+    /* WINED3DSIH_IFC                   */ shader_hw_ifc,
+    /* WINED3DSIH_IGE                   */ NULL,
+    /* WINED3DSIH_IMUL                  */ NULL,
+    /* WINED3DSIH_ITOF                  */ NULL,
+    /* WINED3DSIH_LABEL                 */ shader_hw_label,
+    /* WINED3DSIH_LD                    */ NULL,
+    /* WINED3DSIH_LIT                   */ shader_hw_map2gl,
+    /* WINED3DSIH_LOG                   */ shader_hw_log,
+    /* WINED3DSIH_LOGP                  */ shader_hw_log,
+    /* WINED3DSIH_LOOP                  */ shader_hw_loop,
+    /* WINED3DSIH_LRP                   */ shader_hw_lrp,
+    /* WINED3DSIH_LT                    */ NULL,
+    /* WINED3DSIH_M3x2                  */ shader_hw_mnxn,
+    /* WINED3DSIH_M3x3                  */ shader_hw_mnxn,
+    /* WINED3DSIH_M3x4                  */ shader_hw_mnxn,
+    /* WINED3DSIH_M4x3                  */ shader_hw_mnxn,
+    /* WINED3DSIH_M4x4                  */ shader_hw_mnxn,
+    /* WINED3DSIH_MAD                   */ shader_hw_map2gl,
+    /* WINED3DSIH_MAX                   */ shader_hw_map2gl,
+    /* WINED3DSIH_MIN                   */ shader_hw_map2gl,
+    /* WINED3DSIH_MOV                   */ shader_hw_mov,
+    /* WINED3DSIH_MOVA                  */ shader_hw_mov,
+    /* WINED3DSIH_MOVC                  */ NULL,
+    /* WINED3DSIH_MUL                   */ shader_hw_map2gl,
+    /* WINED3DSIH_NOP                   */ shader_hw_nop,
+    /* WINED3DSIH_NRM                   */ shader_hw_nrm,
+    /* WINED3DSIH_PHASE                 */ shader_hw_nop,
+    /* WINED3DSIH_POW                   */ shader_hw_pow,
+    /* WINED3DSIH_RCP                   */ shader_hw_rcp,
+    /* WINED3DSIH_REP                   */ shader_hw_rep,
+    /* WINED3DSIH_RET                   */ shader_hw_ret,
+    /* WINED3DSIH_ROUND_NI              */ NULL,
+    /* WINED3DSIH_RSQ                   */ shader_hw_scalar_op,
+    /* WINED3DSIH_SAMPLE                */ NULL,
+    /* WINED3DSIH_SAMPLE_GRAD           */ NULL,
+    /* WINED3DSIH_SAMPLE_LOD            */ NULL,
+    /* WINED3DSIH_SETP                  */ NULL,
+    /* WINED3DSIH_SGE                   */ shader_hw_map2gl,
+    /* WINED3DSIH_SGN                   */ shader_hw_sgn,
+    /* WINED3DSIH_SINCOS                */ shader_hw_sincos,
+    /* WINED3DSIH_SLT                   */ shader_hw_map2gl,
+    /* WINED3DSIH_SQRT                  */ NULL,
+    /* WINED3DSIH_SUB                   */ shader_hw_map2gl,
+    /* WINED3DSIH_TEX                   */ pshader_hw_tex,
+    /* WINED3DSIH_TEXBEM                */ pshader_hw_texbem,
+    /* WINED3DSIH_TEXBEML               */ pshader_hw_texbem,
+    /* WINED3DSIH_TEXCOORD              */ pshader_hw_texcoord,
+    /* WINED3DSIH_TEXDEPTH              */ pshader_hw_texdepth,
+    /* WINED3DSIH_TEXDP3                */ pshader_hw_texdp3,
+    /* WINED3DSIH_TEXDP3TEX             */ pshader_hw_texdp3tex,
+    /* WINED3DSIH_TEXKILL               */ pshader_hw_texkill,
+    /* WINED3DSIH_TEXLDD                */ shader_hw_texldd,
+    /* WINED3DSIH_TEXLDL                */ shader_hw_texldl,
+    /* WINED3DSIH_TEXM3x2DEPTH          */ pshader_hw_texm3x2depth,
+    /* WINED3DSIH_TEXM3x2PAD            */ pshader_hw_texm3x2pad,
+    /* WINED3DSIH_TEXM3x2TEX            */ pshader_hw_texm3x2tex,
+    /* WINED3DSIH_TEXM3x3               */ pshader_hw_texm3x3,
+    /* WINED3DSIH_TEXM3x3DIFF           */ NULL,
+    /* WINED3DSIH_TEXM3x3PAD            */ pshader_hw_texm3x3pad,
+    /* WINED3DSIH_TEXM3x3SPEC           */ pshader_hw_texm3x3spec,
+    /* WINED3DSIH_TEXM3x3TEX            */ pshader_hw_texm3x3tex,
+    /* WINED3DSIH_TEXM3x3VSPEC          */ pshader_hw_texm3x3vspec,
+    /* WINED3DSIH_TEXREG2AR             */ pshader_hw_texreg2ar,
+    /* WINED3DSIH_TEXREG2GB             */ pshader_hw_texreg2gb,
+    /* WINED3DSIH_TEXREG2RGB            */ pshader_hw_texreg2rgb,
+    /* WINED3DSIH_UDIV                  */ NULL,
+    /* WINED3DSIH_USHR                  */ NULL,
+    /* WINED3DSIH_UTOF                  */ NULL,
+    /* WINED3DSIH_XOR                   */ NULL,
+};
+
+static BOOL get_bool_const(const struct wined3d_shader_instruction *ins,
+        const struct wined3d_shader *shader, DWORD idx)
+{
+    const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps;
+    BOOL vshader = shader_is_vshader_version(reg_maps->shader_version.type);
+    const struct wined3d_shader_lconst *constant;
+    WORD bools = 0;
+    WORD flag = (1 << idx);
+    struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
+
+    if (reg_maps->local_bool_consts & flag)
+    {
+        /* What good is a if(bool) with a hardcoded local constant? I don't know, but handle it */
+        LIST_FOR_EACH_ENTRY(constant, &shader->constantsB, struct wined3d_shader_lconst, entry)
+        {
+            if (constant->idx == idx)
+            {
+                return constant->value[0];
+            }
+        }
+        ERR("Local constant not found\n");
+        return FALSE;
+    }
+    else
+    {
+        if(vshader) bools = priv->cur_vs_args->clip.boolclip.bools;
+        else bools = priv->cur_ps_args->bools;
+        return bools & flag;
+    }
+}
+
+static void get_loop_control_const(const struct wined3d_shader_instruction *ins,
+        const struct wined3d_shader *shader, UINT idx, struct wined3d_shader_loop_control *loop_control)
+{
+    const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps;
+    struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
+
+    /* Integer constants can either be a local constant, or they can be stored in the shader
+     * type specific compile args. */
+    if (reg_maps->local_int_consts & (1 << idx))
+    {
+        const struct wined3d_shader_lconst *constant;
+
+        LIST_FOR_EACH_ENTRY(constant, &shader->constantsI, struct wined3d_shader_lconst, entry)
+        {
+            if (constant->idx == idx)
+            {
+                loop_control->count = constant->value[0];
+                loop_control->start = constant->value[1];
+                /* Step is signed. */
+                loop_control->step = (int)constant->value[2];
+                return;
+            }
+        }
+        /* If this happens the flag was set incorrectly */
+        ERR("Local constant not found\n");
+        loop_control->count = 0;
+        loop_control->start = 0;
+        loop_control->step = 0;
+        return;
+    }
+
+    switch (reg_maps->shader_version.type)
+    {
+        case WINED3D_SHADER_TYPE_VERTEX:
+            /* Count and aL start value are unsigned */
+            loop_control->count = priv->cur_vs_args->loop_ctrl[idx][0];
+            loop_control->start = priv->cur_vs_args->loop_ctrl[idx][1];
+            /* Step is signed. */
+            loop_control->step = ((char)priv->cur_vs_args->loop_ctrl[idx][2]);
+            break;
+
+        case WINED3D_SHADER_TYPE_PIXEL:
+            loop_control->count = priv->cur_ps_args->loop_ctrl[idx][0];
+            loop_control->start = priv->cur_ps_args->loop_ctrl[idx][1];
+            loop_control->step = ((char)priv->cur_ps_args->loop_ctrl[idx][2]);
+            break;
+
+        default:
+            FIXME("Unhandled shader type %#x.\n", reg_maps->shader_version.type);
+            break;
+    }
+}
+
+static void record_instruction(struct list *list, const struct wined3d_shader_instruction *ins)
+{
+    unsigned int i;
+    struct wined3d_shader_dst_param *dst_param = NULL;
+    struct wined3d_shader_src_param *src_param = NULL, *rel_addr = NULL;
+    struct recorded_instruction *rec = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*rec));
+    if(!rec)
+    {
+        ERR("Out of memory\n");
+        return;
+    }
+
+    rec->ins = *ins;
+    dst_param = HeapAlloc(GetProcessHeap(), 0, sizeof(*dst_param));
+    if(!dst_param) goto free;
+    *dst_param = *ins->dst;
+    if (ins->dst->reg.idx[0].rel_addr)
+    {
+        rel_addr = HeapAlloc(GetProcessHeap(), 0, sizeof(*rel_addr));
+        if (!rel_addr)
+            goto free;
+        *rel_addr = *ins->dst->reg.idx[0].rel_addr;
+        dst_param->reg.idx[0].rel_addr = rel_addr;
+    }
+    rec->ins.dst = dst_param;
+
+    src_param = HeapAlloc(GetProcessHeap(), 0, sizeof(*src_param) * ins->src_count);
+    if (!src_param)
+        goto free;
+    for (i = 0; i < ins->src_count; ++i)
+    {
+        src_param[i] = ins->src[i];
+        if (ins->src[i].reg.idx[0].rel_addr)
+        {
+            rel_addr = HeapAlloc(GetProcessHeap(), 0, sizeof(*rel_addr));
+            if (!rel_addr)
+                goto free;
+            *rel_addr = *ins->src[i].reg.idx[0].rel_addr;
+            src_param[i].reg.idx[0].rel_addr = rel_addr;
+        }
+    }
+    rec->ins.src = src_param;
+    list_add_tail(list, &rec->entry);
+    return;
+
+free:
+    ERR("Out of memory\n");
+    if(dst_param)
+    {
+        HeapFree(GetProcessHeap(), 0, (void *)dst_param->reg.idx[0].rel_addr);
+        HeapFree(GetProcessHeap(), 0, dst_param);
+    }
+    if(src_param)
+    {
+        for(i = 0; i < ins->src_count; i++)
+        {
+            HeapFree(GetProcessHeap(), 0, (void *)src_param[i].reg.idx[0].rel_addr);
+        }
+        HeapFree(GetProcessHeap(), 0, src_param);
+    }
+    HeapFree(GetProcessHeap(), 0, rec);
+}
+
+static void free_recorded_instruction(struct list *list)
+{
+    struct recorded_instruction *rec_ins, *entry2;
+    unsigned int i;
+
+    LIST_FOR_EACH_ENTRY_SAFE(rec_ins, entry2, list, struct recorded_instruction, entry)
+    {
+        list_remove(&rec_ins->entry);
+        if (rec_ins->ins.dst)
+        {
+            HeapFree(GetProcessHeap(), 0, (void *)rec_ins->ins.dst->reg.idx[0].rel_addr);
+            HeapFree(GetProcessHeap(), 0, (void *)rec_ins->ins.dst);
+        }
+        if (rec_ins->ins.src)
+        {
+            for (i = 0; i < rec_ins->ins.src_count; ++i)
+            {
+                HeapFree(GetProcessHeap(), 0, (void *)rec_ins->ins.src[i].reg.idx[0].rel_addr);
+            }
+            HeapFree(GetProcessHeap(), 0, (void *)rec_ins->ins.src);
+        }
+        HeapFree(GetProcessHeap(), 0, rec_ins);
+    }
+}
+
+static void pop_control_frame(const struct wined3d_shader_instruction *ins)
+{
+    struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
+    struct control_frame *control_frame;
+
+    if (ins->handler_idx == WINED3DSIH_ENDLOOP || ins->handler_idx == WINED3DSIH_ENDREP)
+    {
+        struct list *e = list_head(&priv->control_frames);
+        control_frame = LIST_ENTRY(e, struct control_frame, entry);
+        list_remove(&control_frame->entry);
+        HeapFree(GetProcessHeap(), 0, control_frame);
+        priv->loop_depth--;
+    }
+    else if (ins->handler_idx == WINED3DSIH_ENDIF)
+    {
+        /* Non-ifc ENDIFs were already handled previously. */
+        struct list *e = list_head(&priv->control_frames);
+        control_frame = LIST_ENTRY(e, struct control_frame, entry);
+        list_remove(&control_frame->entry);
+        HeapFree(GetProcessHeap(), 0, control_frame);
+    }
+}
+
+static void shader_arb_handle_instruction(const struct wined3d_shader_instruction *ins) {
+    SHADER_HANDLER hw_fct;
+    struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
+    const struct wined3d_shader *shader = ins->ctx->shader;
+    struct control_frame *control_frame;
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    BOOL bool_const;
+
+    if(ins->handler_idx == WINED3DSIH_LOOP || ins->handler_idx == WINED3DSIH_REP)
+    {
+        control_frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*control_frame));
+        list_add_head(&priv->control_frames, &control_frame->entry);
+
+        if(ins->handler_idx == WINED3DSIH_LOOP) control_frame->type = LOOP;
+        if(ins->handler_idx == WINED3DSIH_REP) control_frame->type = REP;
+
+        if(priv->target_version >= NV2)
+        {
+            control_frame->no.loop = priv->num_loops++;
+            priv->loop_depth++;
+        }
+        else
+        {
+            /* Don't bother recording when we're in a not used if branch */
+            if(priv->muted)
+            {
+                return;
+            }
+
+            if(!priv->recording)
+            {
+                list_init(&priv->record);
+                priv->recording = TRUE;
+                control_frame->outer_loop = TRUE;
+                get_loop_control_const(ins, shader, ins->src[0].reg.idx[0].offset, &control_frame->loop_control);
+                return; /* Instruction is handled */
+            }
+            /* Record this loop in the outer loop's recording */
+        }
+    }
+    else if(ins->handler_idx == WINED3DSIH_ENDLOOP || ins->handler_idx == WINED3DSIH_ENDREP)
+    {
+        if(priv->target_version >= NV2)
+        {
+            /* Nothing to do. The control frame is popped after the HW instr handler */
+        }
+        else
+        {
+            struct list *e = list_head(&priv->control_frames);
+            control_frame = LIST_ENTRY(e, struct control_frame, entry);
+            list_remove(&control_frame->entry);
+
+            if(control_frame->outer_loop)
+            {
+                unsigned int iteration;
+                int aL = 0;
+                struct list copy;
+
+                /* Turn off recording before playback */
+                priv->recording = FALSE;
+
+                /* Move the recorded instructions to a separate list and get them out of the private data
+                 * structure. If there are nested loops, the shader_arb_handle_instruction below will
+                 * be recorded again, thus priv->record might be overwritten
+                 */
+                list_init(&copy);
+                list_move_tail(&copy, &priv->record);
+                list_init(&priv->record);
+
+                if(ins->handler_idx == WINED3DSIH_ENDLOOP)
+                {
+                    shader_addline(buffer, "#unrolling loop: %u iterations, aL=%u, inc %d\n",
+                                   control_frame->loop_control.count, control_frame->loop_control.start,
+                                   control_frame->loop_control.step);
+                    aL = control_frame->loop_control.start;
+                }
+                else
+                {
+                    shader_addline(buffer, "#unrolling rep: %u iterations\n", control_frame->loop_control.count);
+                }
+
+                for (iteration = 0; iteration < control_frame->loop_control.count; ++iteration)
+                {
+                    struct recorded_instruction *rec_ins;
+                    if(ins->handler_idx == WINED3DSIH_ENDLOOP)
+                    {
+                        priv->aL = aL;
+                        shader_addline(buffer, "#Iteration %u, aL=%d\n", iteration, aL);
+                    }
+                    else
+                    {
+                        shader_addline(buffer, "#Iteration %u\n", iteration);
+                    }
+
+                    LIST_FOR_EACH_ENTRY(rec_ins, &copy, struct recorded_instruction, entry)
+                    {
+                        shader_arb_handle_instruction(&rec_ins->ins);
+                    }
+
+                    if(ins->handler_idx == WINED3DSIH_ENDLOOP)
+                    {
+                        aL += control_frame->loop_control.step;
+                    }
+                }
+                shader_addline(buffer, "#end loop/rep\n");
+
+                free_recorded_instruction(&copy);
+                HeapFree(GetProcessHeap(), 0, control_frame);
+                return; /* Instruction is handled */
+            }
+            else
+            {
+                /* This is a nested loop. Proceed to the normal recording function */
+                HeapFree(GetProcessHeap(), 0, control_frame);
+            }
+        }
+    }
+
+    if(priv->recording)
+    {
+        record_instruction(&priv->record, ins);
+        return;
+    }
+
+    /* boolean if */
+    if(ins->handler_idx == WINED3DSIH_IF)
+    {
+        control_frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*control_frame));
+        list_add_head(&priv->control_frames, &control_frame->entry);
+        control_frame->type = IF;
+
+        bool_const = get_bool_const(ins, shader, ins->src[0].reg.idx[0].offset);
+        if (ins->src[0].modifiers == WINED3DSPSM_NOT)
+            bool_const = !bool_const;
+        if (!priv->muted && !bool_const)
+        {
+            shader_addline(buffer, "#if(FALSE){\n");
+            priv->muted = TRUE;
+            control_frame->muting = TRUE;
+        }
+        else shader_addline(buffer, "#if(TRUE) {\n");
+
+        return; /* Instruction is handled */
+    }
+    else if(ins->handler_idx == WINED3DSIH_IFC)
+    {
+        /* IF(bool) and if_cond(a, b) use the same ELSE and ENDIF tokens */
+        control_frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*control_frame));
+        control_frame->type = IFC;
+        control_frame->no.ifc = priv->num_ifcs++;
+        list_add_head(&priv->control_frames, &control_frame->entry);
+    }
+    else if(ins->handler_idx == WINED3DSIH_ELSE)
+    {
+        struct list *e = list_head(&priv->control_frames);
+        control_frame = LIST_ENTRY(e, struct control_frame, entry);
+
+        if(control_frame->type == IF)
+        {
+            shader_addline(buffer, "#} else {\n");
+            if(!priv->muted && !control_frame->muting)
+            {
+                priv->muted = TRUE;
+                control_frame->muting = TRUE;
+            }
+            else if(control_frame->muting) priv->muted = FALSE;
+            return; /* Instruction is handled. */
+        }
+        /* In case of an ifc, generate a HW shader instruction */
+        if (control_frame->type != IFC)
+            ERR("Control frame does not match.\n");
+    }
+    else if(ins->handler_idx == WINED3DSIH_ENDIF)
+    {
+        struct list *e = list_head(&priv->control_frames);
+        control_frame = LIST_ENTRY(e, struct control_frame, entry);
+
+        if(control_frame->type == IF)
+        {
+            shader_addline(buffer, "#} endif\n");
+            if(control_frame->muting) priv->muted = FALSE;
+            list_remove(&control_frame->entry);
+            HeapFree(GetProcessHeap(), 0, control_frame);
+            return; /* Instruction is handled */
+        }
+        /* In case of an ifc, generate a HW shader instruction */
+        if (control_frame->type != IFC)
+            ERR("Control frame does not match.\n");
+    }
+
+    if(priv->muted)
+    {
+        pop_control_frame(ins);
+        return;
+    }
+
+    /* Select handler */
+    hw_fct = shader_arb_instruction_handler_table[ins->handler_idx];
+
+    /* Unhandled opcode */
+    if (!hw_fct)
+    {
+        FIXME("Backend can't handle opcode %#x\n", ins->handler_idx);
+        return;
+    }
+    hw_fct(ins);
+
+    pop_control_frame(ins);
+
+    shader_arb_add_instruction_modifiers(ins);
+}
+
+static BOOL shader_arb_has_ffp_proj_control(void *shader_priv)
+{
+    struct shader_arb_priv *priv = shader_priv;
+
+    return priv->ffp_proj_control;
+}
+
+const struct wined3d_shader_backend_ops arb_program_shader_backend =
+{
+    shader_arb_handle_instruction,
+    shader_arb_select,
+    shader_arb_disable,
+    shader_arb_select_depth_blt,
+    shader_arb_deselect_depth_blt,
+    shader_arb_update_float_vertex_constants,
+    shader_arb_update_float_pixel_constants,
+    shader_arb_load_constants,
+    shader_arb_load_np2fixup_constants,
+    shader_arb_destroy,
+    shader_arb_alloc,
+    shader_arb_free,
+    shader_arb_context_destroyed,
+    shader_arb_get_caps,
+    shader_arb_color_fixup_supported,
+    shader_arb_has_ffp_proj_control,
+};
+
+/* ARB_fragment_program fixed function pipeline replacement definitions */
+#define ARB_FFP_CONST_TFACTOR           0
+#define ARB_FFP_CONST_SPECULAR_ENABLE   ((ARB_FFP_CONST_TFACTOR) + 1)
+#define ARB_FFP_CONST_CONSTANT(i)       ((ARB_FFP_CONST_SPECULAR_ENABLE) + 1 + i)
+#define ARB_FFP_CONST_BUMPMAT(i)        ((ARB_FFP_CONST_CONSTANT(7)) + 1 + i)
+#define ARB_FFP_CONST_LUMINANCE(i)      ((ARB_FFP_CONST_BUMPMAT(7)) + 1 + i)
+
+struct arbfp_ffp_desc
+{
+    struct ffp_frag_desc parent;
+    GLuint shader;
+};
+
+/* Context activation is done by the caller. */
+static void arbfp_enable(const struct wined3d_gl_info *gl_info, BOOL enable)
+{
+    if (enable)
+    {
+        gl_info->gl_ops.gl.p_glEnable(GL_FRAGMENT_PROGRAM_ARB);
+        checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB)");
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_FRAGMENT_PROGRAM_ARB);
+        checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)");
+    }
+}
+
+static void *arbfp_alloc(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv)
+{
+    struct shader_arb_priv *priv;
+
+    /* Share private data between the shader backend and the pipeline
+     * replacement, if both are the arb implementation. This is needed to
+     * figure out whether ARBfp should be disabled if no pixel shader is bound
+     * or not. */
+    if (shader_backend == &arb_program_shader_backend)
+        priv = shader_priv;
+    else if (!(priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*priv))))
+        return NULL;
+
+    if (wine_rb_init(&priv->fragment_shaders, &wined3d_ffp_frag_program_rb_functions) == -1)
+    {
+        ERR("Failed to initialize rbtree.\n");
+        if (priv != shader_priv)
+            HeapFree(GetProcessHeap(), 0, priv);
+        return NULL;
+    }
+    priv->use_arbfp_fixed_func = TRUE;
+
+    return priv;
+}
+
+/* Context activation is done by the caller. */
+static void arbfp_free_ffpshader(struct wine_rb_entry *entry, void *context)
+{
+    const struct wined3d_gl_info *gl_info = context;
+    struct arbfp_ffp_desc *entry_arb = WINE_RB_ENTRY_VALUE(entry, struct arbfp_ffp_desc, parent.entry);
+
+    GL_EXTCALL(glDeleteProgramsARB(1, &entry_arb->shader));
+    checkGLcall("glDeleteProgramsARB(1, &entry_arb->shader)");
+    HeapFree(GetProcessHeap(), 0, entry_arb);
+}
+
+/* Context activation is done by the caller. */
+static void arbfp_free(struct wined3d_device *device)
+{
+    struct shader_arb_priv *priv = device->fragment_priv;
+
+    wine_rb_destroy(&priv->fragment_shaders, arbfp_free_ffpshader, &device->adapter->gl_info);
+    priv->use_arbfp_fixed_func = FALSE;
+
+    if (device->shader_backend != &arb_program_shader_backend)
+    {
+        HeapFree(GetProcessHeap(), 0, device->fragment_priv);
+    }
+}
+
+static void arbfp_get_caps(const struct wined3d_gl_info *gl_info, struct fragment_caps *caps)
+{
+    caps->wined3d_caps = WINED3D_FRAGMENT_CAP_PROJ_CONTROL
+            | WINED3D_FRAGMENT_CAP_SRGB_WRITE;
+    caps->PrimitiveMiscCaps = WINED3DPMISCCAPS_TSSARGTEMP;
+    caps->TextureOpCaps =  WINED3DTEXOPCAPS_DISABLE                     |
+                           WINED3DTEXOPCAPS_SELECTARG1                  |
+                           WINED3DTEXOPCAPS_SELECTARG2                  |
+                           WINED3DTEXOPCAPS_MODULATE4X                  |
+                           WINED3DTEXOPCAPS_MODULATE2X                  |
+                           WINED3DTEXOPCAPS_MODULATE                    |
+                           WINED3DTEXOPCAPS_ADDSIGNED2X                 |
+                           WINED3DTEXOPCAPS_ADDSIGNED                   |
+                           WINED3DTEXOPCAPS_ADD                         |
+                           WINED3DTEXOPCAPS_SUBTRACT                    |
+                           WINED3DTEXOPCAPS_ADDSMOOTH                   |
+                           WINED3DTEXOPCAPS_BLENDCURRENTALPHA           |
+                           WINED3DTEXOPCAPS_BLENDFACTORALPHA            |
+                           WINED3DTEXOPCAPS_BLENDTEXTUREALPHA           |
+                           WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA           |
+                           WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM         |
+                           WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR      |
+                           WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA      |
+                           WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA   |
+                           WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR   |
+                           WINED3DTEXOPCAPS_DOTPRODUCT3                 |
+                           WINED3DTEXOPCAPS_MULTIPLYADD                 |
+                           WINED3DTEXOPCAPS_LERP                        |
+                           WINED3DTEXOPCAPS_BUMPENVMAP                  |
+                           WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE;
+
+    /* TODO: Implement WINED3DTEXOPCAPS_PREMODULATE */
+
+    caps->MaxTextureBlendStages   = 8;
+    caps->MaxSimultaneousTextures = min(gl_info->limits.fragment_samplers, 8);
+}
+
+static void state_texfactor_arbfp(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id)
+{
+    struct wined3d_device *device = context->swapchain->device;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    float col[4];
+
+    /* Don't load the parameter if we're using an arbfp pixel shader,
+     * otherwise we'll overwrite application provided constants. */
+    if (device->shader_backend == &arb_program_shader_backend)
+    {
+        struct shader_arb_priv *priv;
+
+        if (use_ps(state)) return;
+
+        priv = device->shader_priv;
+        priv->pshader_const_dirty[ARB_FFP_CONST_TFACTOR] = 1;
+        priv->highest_dirty_ps_const = max(priv->highest_dirty_ps_const, ARB_FFP_CONST_TFACTOR + 1);
+    }
+
+    D3DCOLORTOGLFLOAT4(state->render_states[WINED3D_RS_TEXTUREFACTOR], col);
+    GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_TFACTOR, col));
+    checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_TFACTOR, col)");
+}
+
+static void state_arb_specularenable(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id)
+{
+    struct wined3d_device *device = context->swapchain->device;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    float col[4];
+
+    /* Don't load the parameter if we're using an arbfp pixel shader, otherwise we'll overwrite
+     * application provided constants
+     */
+    if (device->shader_backend == &arb_program_shader_backend)
+    {
+        struct shader_arb_priv *priv;
+
+        if (use_ps(state)) return;
+
+        priv = device->shader_priv;
+        priv->pshader_const_dirty[ARB_FFP_CONST_SPECULAR_ENABLE] = 1;
+        priv->highest_dirty_ps_const = max(priv->highest_dirty_ps_const, ARB_FFP_CONST_SPECULAR_ENABLE + 1);
+    }
+
+    if (state->render_states[WINED3D_RS_SPECULARENABLE])
+    {
+        /* The specular color has no alpha */
+        col[0] = 1.0f; col[1] = 1.0f;
+        col[2] = 1.0f; col[3] = 0.0f;
+    } else {
+        col[0] = 0.0f; col[1] = 0.0f;
+        col[2] = 0.0f; col[3] = 0.0f;
+    }
+    GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_SPECULAR_ENABLE, col));
+    checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_SPECULAR_ENABLE, col)");
+}
+
+static void set_bumpmat_arbfp(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
+    struct wined3d_device *device = context->swapchain->device;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    float mat[2][2];
+
+    if (use_ps(state))
+    {
+        /* The pixel shader has to know the bump env matrix. Do a constants
+         * update. */
+        if (stage && (state->pixel_shader->reg_maps.bumpmat & (1 << stage)))
+            context->load_constants = 1;
+
+        if(device->shader_backend == &arb_program_shader_backend) {
+            /* Exit now, don't set the bumpmat below, otherwise we may overwrite pixel shader constants */
+            return;
+        }
+    }
+    else if (device->shader_backend == &arb_program_shader_backend)
+    {
+        struct shader_arb_priv *priv = device->shader_priv;
+        priv->pshader_const_dirty[ARB_FFP_CONST_BUMPMAT(stage)] = 1;
+        priv->highest_dirty_ps_const = max(priv->highest_dirty_ps_const, ARB_FFP_CONST_BUMPMAT(stage) + 1);
+    }
+
+    mat[0][0] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_MAT00]);
+    mat[0][1] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_MAT01]);
+    mat[1][0] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_MAT10]);
+    mat[1][1] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_MAT11]);
+
+    GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_BUMPMAT(stage), &mat[0][0]));
+    checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_BUMPMAT(stage), &mat[0][0])");
+}
+
+static void tex_bumpenvlum_arbfp(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id)
+{
+    DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
+    struct wined3d_device *device = context->swapchain->device;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    float param[4];
+
+    if (use_ps(state))
+    {
+        /* The pixel shader has to know the luminance offset. Do a constants
+         * update. */
+        if (stage && (state->pixel_shader->reg_maps.luminanceparams & (1 << stage)))
+            context->load_constants = 1;
+
+        if(device->shader_backend == &arb_program_shader_backend) {
+            /* Exit now, don't set the bumpmat below, otherwise we may overwrite pixel shader constants */
+            return;
+        }
+    }
+    else if (device->shader_backend == &arb_program_shader_backend)
+    {
+        struct shader_arb_priv *priv = device->shader_priv;
+        priv->pshader_const_dirty[ARB_FFP_CONST_LUMINANCE(stage)] = 1;
+        priv->highest_dirty_ps_const = max(priv->highest_dirty_ps_const, ARB_FFP_CONST_LUMINANCE(stage) + 1);
+    }
+
+    param[0] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_LSCALE]);
+    param[1] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_LOFFSET]);
+    param[2] = 0.0f;
+    param[3] = 0.0f;
+
+    GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_LUMINANCE(stage), param));
+    checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_LUMINANCE(stage), param)");
+}
+
+static const char *get_argreg(struct wined3d_shader_buffer *buffer, DWORD argnum, unsigned int stage, DWORD arg)
+{
+    const char *ret;
+
+    if(arg == ARG_UNUSED) return "unused"; /* This is the marker for unused registers */
+
+    switch(arg & WINED3DTA_SELECTMASK) {
+        case WINED3DTA_DIFFUSE:
+            ret = "fragment.color.primary"; break;
+
+        case WINED3DTA_CURRENT:
+            if (!stage) ret = "fragment.color.primary";
+            else ret = "ret";
+            break;
+
+        case WINED3DTA_TEXTURE:
+            switch(stage) {
+                case 0: ret = "tex0"; break;
+                case 1: ret = "tex1"; break;
+                case 2: ret = "tex2"; break;
+                case 3: ret = "tex3"; break;
+                case 4: ret = "tex4"; break;
+                case 5: ret = "tex5"; break;
+                case 6: ret = "tex6"; break;
+                case 7: ret = "tex7"; break;
+                default: ret = "unknown texture";
+            }
+            break;
+
+        case WINED3DTA_TFACTOR:
+            ret = "tfactor"; break;
+
+        case WINED3DTA_SPECULAR:
+            ret = "fragment.color.secondary"; break;
+
+        case WINED3DTA_TEMP:
+            ret = "tempreg"; break;
+
+        case WINED3DTA_CONSTANT:
+            FIXME("Implement perstage constants\n");
+            switch(stage) {
+                case 0: ret = "const0"; break;
+                case 1: ret = "const1"; break;
+                case 2: ret = "const2"; break;
+                case 3: ret = "const3"; break;
+                case 4: ret = "const4"; break;
+                case 5: ret = "const5"; break;
+                case 6: ret = "const6"; break;
+                case 7: ret = "const7"; break;
+                default: ret = "unknown constant";
+            }
+            break;
+
+        default:
+            return "unknown";
+    }
+
+    if(arg & WINED3DTA_COMPLEMENT) {
+        shader_addline(buffer, "SUB arg%u, const.x, %s;\n", argnum, ret);
+        if(argnum == 0) ret = "arg0";
+        if(argnum == 1) ret = "arg1";
+        if(argnum == 2) ret = "arg2";
+    }
+    if(arg & WINED3DTA_ALPHAREPLICATE) {
+        shader_addline(buffer, "MOV arg%u, %s.w;\n", argnum, ret);
+        if(argnum == 0) ret = "arg0";
+        if(argnum == 1) ret = "arg1";
+        if(argnum == 2) ret = "arg2";
+    }
+    return ret;
+}
+
+static void gen_ffp_instr(struct wined3d_shader_buffer *buffer, unsigned int stage, BOOL color,
+        BOOL alpha, DWORD dst, DWORD op, DWORD dw_arg0, DWORD dw_arg1, DWORD dw_arg2)
+{
+    const char *dstmask, *dstreg, *arg0, *arg1, *arg2;
+    unsigned int mul = 1;
+
+    if(color && alpha) dstmask = "";
+    else if(color) dstmask = ".xyz";
+    else dstmask = ".w";
+
+    if(dst == tempreg) dstreg = "tempreg";
+    else dstreg = "ret";
+
+    arg0 = get_argreg(buffer, 0, stage, dw_arg0);
+    arg1 = get_argreg(buffer, 1, stage, dw_arg1);
+    arg2 = get_argreg(buffer, 2, stage, dw_arg2);
+
+    switch (op)
+    {
+        case WINED3D_TOP_DISABLE:
+            if (!stage)
+                shader_addline(buffer, "MOV %s%s, fragment.color.primary;\n", dstreg, dstmask);
+            break;
+
+        case WINED3D_TOP_SELECT_ARG2:
+            arg1 = arg2;
+            /* FALLTHROUGH */
+        case WINED3D_TOP_SELECT_ARG1:
+            shader_addline(buffer, "MOV %s%s, %s;\n", dstreg, dstmask, arg1);
+            break;
+
+        case WINED3D_TOP_MODULATE_4X:
+            mul = 2;
+            /* FALLTHROUGH */
+        case WINED3D_TOP_MODULATE_2X:
+            mul *= 2;
+            /* FALLTHROUGH */
+        case WINED3D_TOP_MODULATE:
+            shader_addline(buffer, "MUL %s%s, %s, %s;\n", dstreg, dstmask, arg1, arg2);
+            break;
+
+        case WINED3D_TOP_ADD_SIGNED_2X:
+            mul = 2;
+            /* FALLTHROUGH */
+        case WINED3D_TOP_ADD_SIGNED:
+            shader_addline(buffer, "SUB arg2, %s, const.w;\n", arg2);
+            arg2 = "arg2";
+            /* FALLTHROUGH */
+        case WINED3D_TOP_ADD:
+            shader_addline(buffer, "ADD_SAT %s%s, %s, %s;\n", dstreg, dstmask, arg1, arg2);
+            break;
+
+        case WINED3D_TOP_SUBTRACT:
+            shader_addline(buffer, "SUB_SAT %s%s, %s, %s;\n", dstreg, dstmask, arg1, arg2);
+            break;
+
+        case WINED3D_TOP_ADD_SMOOTH:
+            shader_addline(buffer, "SUB arg1, const.x, %s;\n", arg1);
+            shader_addline(buffer, "MAD_SAT %s%s, arg1, %s, %s;\n", dstreg, dstmask, arg2, arg1);
+            break;
+
+        case WINED3D_TOP_BLEND_CURRENT_ALPHA:
+            arg0 = get_argreg(buffer, 0, stage, WINED3DTA_CURRENT);
+            shader_addline(buffer, "LRP %s%s, %s.w, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
+            break;
+        case WINED3D_TOP_BLEND_FACTOR_ALPHA:
+            arg0 = get_argreg(buffer, 0, stage, WINED3DTA_TFACTOR);
+            shader_addline(buffer, "LRP %s%s, %s.w, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
+            break;
+        case WINED3D_TOP_BLEND_TEXTURE_ALPHA:
+            arg0 = get_argreg(buffer, 0, stage, WINED3DTA_TEXTURE);
+            shader_addline(buffer, "LRP %s%s, %s.w, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
+            break;
+        case WINED3D_TOP_BLEND_DIFFUSE_ALPHA:
+            arg0 = get_argreg(buffer, 0, stage, WINED3DTA_DIFFUSE);
+            shader_addline(buffer, "LRP %s%s, %s.w, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
+            break;
+
+        case WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM:
+            arg0 = get_argreg(buffer, 0, stage, WINED3DTA_TEXTURE);
+            shader_addline(buffer, "SUB arg0.w, const.x, %s.w;\n", arg0);
+            shader_addline(buffer, "MAD_SAT %s%s, %s, arg0.w, %s;\n", dstreg, dstmask, arg2, arg1);
+            break;
+
+        /* D3DTOP_PREMODULATE ???? */
+
+        case WINED3D_TOP_MODULATE_INVALPHA_ADD_COLOR:
+            shader_addline(buffer, "SUB arg0.w, const.x, %s;\n", arg1);
+            shader_addline(buffer, "MAD_SAT %s%s, arg0.w, %s, %s;\n", dstreg, dstmask, arg2, arg1);
+            break;
+        case WINED3D_TOP_MODULATE_ALPHA_ADD_COLOR:
+            shader_addline(buffer, "MAD_SAT %s%s, %s.w, %s, %s;\n", dstreg, dstmask, arg1, arg2, arg1);
+            break;
+        case WINED3D_TOP_MODULATE_INVCOLOR_ADD_ALPHA:
+            shader_addline(buffer, "SUB arg0, const.x, %s;\n", arg1);
+            shader_addline(buffer, "MAD_SAT %s%s, arg0, %s, %s.w;\n", dstreg, dstmask, arg2, arg1);
+            break;
+        case WINED3D_TOP_MODULATE_COLOR_ADD_ALPHA:
+            shader_addline(buffer, "MAD_SAT %s%s, %s, %s, %s.w;\n", dstreg, dstmask, arg1, arg2, arg1);
+            break;
+
+        case WINED3D_TOP_DOTPRODUCT3:
+            mul = 4;
+            shader_addline(buffer, "SUB arg1, %s, const.w;\n", arg1);
+            shader_addline(buffer, "SUB arg2, %s, const.w;\n", arg2);
+            shader_addline(buffer, "DP3_SAT %s%s, arg1, arg2;\n", dstreg, dstmask);
+            break;
+
+        case WINED3D_TOP_MULTIPLY_ADD:
+            shader_addline(buffer, "MAD_SAT %s%s, %s, %s, %s;\n", dstreg, dstmask, arg1, arg2, arg0);
+            break;
+
+        case WINED3D_TOP_LERP:
+            /* The msdn is not quite right here */
+            shader_addline(buffer, "LRP %s%s, %s, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
+            break;
+
+        case WINED3D_TOP_BUMPENVMAP:
+        case WINED3D_TOP_BUMPENVMAP_LUMINANCE:
+            /* Those are handled in the first pass of the shader(generation pass 1 and 2) already */
+            break;
+
+        default:
+            FIXME("Unhandled texture op %08x\n", op);
+    }
+
+    if (mul == 2)
+        shader_addline(buffer, "MUL_SAT %s%s, %s, const.y;\n", dstreg, dstmask, dstreg);
+    else if (mul == 4)
+        shader_addline(buffer, "MUL_SAT %s%s, %s, const.z;\n", dstreg, dstmask, dstreg);
+}
+
+static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, const struct wined3d_gl_info *gl_info)
+{
+    unsigned int stage;
+    struct wined3d_shader_buffer buffer;
+    BOOL tex_read[MAX_TEXTURES] = {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE};
+    BOOL bump_used[MAX_TEXTURES] = {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE};
+    BOOL luminance_used[MAX_TEXTURES] = {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE};
+    UINT lowest_disabled_stage;
+    const char *textype;
+    const char *instr, *sat;
+    char colorcor_dst[8];
+    GLuint ret;
+    DWORD arg0, arg1, arg2;
+    BOOL tempreg_used = FALSE, tfactor_used = FALSE;
+    BOOL op_equal;
+    const char *final_combiner_src = "ret";
+    GLint pos;
+
+    /* Find out which textures are read */
+    for (stage = 0; stage < MAX_TEXTURES; ++stage)
+    {
+        if (settings->op[stage].cop == WINED3D_TOP_DISABLE)
+            break;
+        arg0 = settings->op[stage].carg0 & WINED3DTA_SELECTMASK;
+        arg1 = settings->op[stage].carg1 & WINED3DTA_SELECTMASK;
+        arg2 = settings->op[stage].carg2 & WINED3DTA_SELECTMASK;
+        if(arg0 == WINED3DTA_TEXTURE) tex_read[stage] = TRUE;
+        if(arg1 == WINED3DTA_TEXTURE) tex_read[stage] = TRUE;
+        if(arg2 == WINED3DTA_TEXTURE) tex_read[stage] = TRUE;
+
+        if (settings->op[stage].cop == WINED3D_TOP_BLEND_TEXTURE_ALPHA)
+            tex_read[stage] = TRUE;
+        if (settings->op[stage].cop == WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM)
+            tex_read[stage] = TRUE;
+        if (settings->op[stage].cop == WINED3D_TOP_BUMPENVMAP)
+        {
+            bump_used[stage] = TRUE;
+            tex_read[stage] = TRUE;
+        }
+        if (settings->op[stage].cop == WINED3D_TOP_BUMPENVMAP_LUMINANCE)
+        {
+            bump_used[stage] = TRUE;
+            tex_read[stage] = TRUE;
+            luminance_used[stage] = TRUE;
+        }
+        else if (settings->op[stage].cop == WINED3D_TOP_BLEND_FACTOR_ALPHA)
+        {
+            tfactor_used = TRUE;
+        }
+
+        if(arg0 == WINED3DTA_TFACTOR || arg1 == WINED3DTA_TFACTOR || arg2 == WINED3DTA_TFACTOR) {
+            tfactor_used = TRUE;
+        }
+
+        if(settings->op[stage].dst == tempreg) tempreg_used = TRUE;
+        if(arg0 == WINED3DTA_TEMP || arg1 == WINED3DTA_TEMP || arg2 == WINED3DTA_TEMP) {
+            tempreg_used = TRUE;
+        }
+
+        if (settings->op[stage].aop == WINED3D_TOP_DISABLE)
+            continue;
+        arg0 = settings->op[stage].aarg0 & WINED3DTA_SELECTMASK;
+        arg1 = settings->op[stage].aarg1 & WINED3DTA_SELECTMASK;
+        arg2 = settings->op[stage].aarg2 & WINED3DTA_SELECTMASK;
+        if(arg0 == WINED3DTA_TEXTURE) tex_read[stage] = TRUE;
+        if(arg1 == WINED3DTA_TEXTURE) tex_read[stage] = TRUE;
+        if(arg2 == WINED3DTA_TEXTURE) tex_read[stage] = TRUE;
+
+        if(arg0 == WINED3DTA_TEMP || arg1 == WINED3DTA_TEMP || arg2 == WINED3DTA_TEMP) {
+            tempreg_used = TRUE;
+        }
+        if(arg0 == WINED3DTA_TFACTOR || arg1 == WINED3DTA_TFACTOR || arg2 == WINED3DTA_TFACTOR) {
+            tfactor_used = TRUE;
+        }
+    }
+    lowest_disabled_stage = stage;
+
+    /* Shader header */
+    if (!shader_buffer_init(&buffer))
+    {
+        ERR("Failed to initialize shader buffer.\n");
+        return 0;
+    }
+
+    shader_addline(&buffer, "!!ARBfp1.0\n");
+
+    switch (settings->fog)
+    {
+        case WINED3D_FFP_PS_FOG_OFF:                                                         break;
+        case WINED3D_FFP_PS_FOG_LINEAR: shader_addline(&buffer, "OPTION ARB_fog_linear;\n"); break;
+        case WINED3D_FFP_PS_FOG_EXP:    shader_addline(&buffer, "OPTION ARB_fog_exp;\n");    break;
+        case WINED3D_FFP_PS_FOG_EXP2:   shader_addline(&buffer, "OPTION ARB_fog_exp2;\n");   break;
+        default: FIXME("Unexpected fog setting %d\n", settings->fog);
+    }
+
+    shader_addline(&buffer, "PARAM const = {1, 2, 4, 0.5};\n");
+    shader_addline(&buffer, "TEMP TMP;\n");
+    shader_addline(&buffer, "TEMP ret;\n");
+    if(tempreg_used || settings->sRGB_write) shader_addline(&buffer, "TEMP tempreg;\n");
+    shader_addline(&buffer, "TEMP arg0;\n");
+    shader_addline(&buffer, "TEMP arg1;\n");
+    shader_addline(&buffer, "TEMP arg2;\n");
+    for(stage = 0; stage < MAX_TEXTURES; stage++) {
+        if(!tex_read[stage]) continue;
+        shader_addline(&buffer, "TEMP tex%u;\n", stage);
+        if(!bump_used[stage]) continue;
+        shader_addline(&buffer, "PARAM bumpmat%u = program.env[%u];\n", stage, ARB_FFP_CONST_BUMPMAT(stage));
+        if(!luminance_used[stage]) continue;
+        shader_addline(&buffer, "PARAM luminance%u = program.env[%u];\n", stage, ARB_FFP_CONST_LUMINANCE(stage));
+    }
+    if(tfactor_used) {
+        shader_addline(&buffer, "PARAM tfactor = program.env[%u];\n", ARB_FFP_CONST_TFACTOR);
+    }
+        shader_addline(&buffer, "PARAM specular_enable = program.env[%u];\n", ARB_FFP_CONST_SPECULAR_ENABLE);
+
+    if(settings->sRGB_write) {
+        shader_addline(&buffer, "PARAM srgb_consts1 = {%f, %f, %f, %f};\n",
+                       srgb_mul_low, srgb_cmp, srgb_pow, srgb_mul_high);
+        shader_addline(&buffer, "PARAM srgb_consts2 = {%f, %f, %f, %f};\n",
+                       srgb_sub_high, 0.0, 0.0, 0.0);
+    }
+
+    if (lowest_disabled_stage < 7 && settings->emul_clipplanes)
+        shader_addline(&buffer, "KIL fragment.texcoord[7];\n");
+
+    /* Generate texture sampling instructions) */
+    for (stage = 0; stage < MAX_TEXTURES && settings->op[stage].cop != WINED3D_TOP_DISABLE; ++stage)
+    {
+        if (!tex_read[stage])
+            continue;
+
+        switch(settings->op[stage].tex_type) {
+            case tex_1d:                    textype = "1D";     break;
+            case tex_2d:                    textype = "2D";     break;
+            case tex_3d:                    textype = "3D";     break;
+            case tex_cube:                  textype = "CUBE";   break;
+            case tex_rect:                  textype = "RECT";   break;
+            default: textype = "unexpected_textype";   break;
+        }
+
+        if (settings->op[stage].cop == WINED3D_TOP_BUMPENVMAP
+                || settings->op[stage].cop == WINED3D_TOP_BUMPENVMAP_LUMINANCE)
+            sat = "";
+        else
+            sat = "_SAT";
+
+        if(settings->op[stage].projected == proj_none) {
+            instr = "TEX";
+        } else if(settings->op[stage].projected == proj_count4 ||
+                  settings->op[stage].projected == proj_count3) {
+            instr = "TXP";
+        } else {
+            FIXME("Unexpected projection mode %d\n", settings->op[stage].projected);
+            instr = "TXP";
+        }
+
+        if (stage > 0
+                && (settings->op[stage - 1].cop == WINED3D_TOP_BUMPENVMAP
+                || settings->op[stage - 1].cop == WINED3D_TOP_BUMPENVMAP_LUMINANCE))
+        {
+            shader_addline(&buffer, "SWZ arg1, bumpmat%u, x, z, 0, 0;\n", stage - 1);
+            shader_addline(&buffer, "DP3 ret.x, arg1, tex%u;\n", stage - 1);
+            shader_addline(&buffer, "SWZ arg1, bumpmat%u, y, w, 0, 0;\n", stage - 1);
+            shader_addline(&buffer, "DP3 ret.y, arg1, tex%u;\n", stage - 1);
+
+            /* with projective textures, texbem only divides the static texture coord, not the displacement,
+             * so multiply the displacement with the dividing parameter before passing it to TXP
+             */
+            if (settings->op[stage].projected != proj_none) {
+                if(settings->op[stage].projected == proj_count4) {
+                    shader_addline(&buffer, "MOV ret.w, fragment.texcoord[%u].w;\n", stage);
+                    shader_addline(&buffer, "MUL ret.xyz, ret, fragment.texcoord[%u].w, fragment.texcoord[%u];\n", stage, stage);
+                } else {
+                    shader_addline(&buffer, "MOV ret.w, fragment.texcoord[%u].z;\n", stage);
+                    shader_addline(&buffer, "MAD ret.xyz, ret, fragment.texcoord[%u].z, fragment.texcoord[%u];\n", stage, stage);
+                }
+            } else {
+                shader_addline(&buffer, "ADD ret, ret, fragment.texcoord[%u];\n", stage);
+            }
+
+            shader_addline(&buffer, "%s%s tex%u, ret, texture[%u], %s;\n",
+                    instr, sat, stage, stage, textype);
+            if (settings->op[stage - 1].cop == WINED3D_TOP_BUMPENVMAP_LUMINANCE)
+            {
+                shader_addline(&buffer, "MAD_SAT ret.x, tex%u.z, luminance%u.x, luminance%u.y;\n",
+                               stage - 1, stage - 1, stage - 1);
+                shader_addline(&buffer, "MUL tex%u, tex%u, ret.x;\n", stage, stage);
+            }
+        } else if(settings->op[stage].projected == proj_count3) {
+            shader_addline(&buffer, "MOV ret, fragment.texcoord[%u];\n", stage);
+            shader_addline(&buffer, "MOV ret.w, ret.z;\n");
+            shader_addline(&buffer, "%s%s tex%u, ret, texture[%u], %s;\n",
+                            instr, sat, stage, stage, textype);
+        } else {
+            shader_addline(&buffer, "%s%s tex%u, fragment.texcoord[%u], texture[%u], %s;\n",
+                            instr, sat, stage, stage, stage, textype);
+        }
+
+        sprintf(colorcor_dst, "tex%u", stage);
+        gen_color_correction(&buffer, colorcor_dst, WINED3DSP_WRITEMASK_ALL, "const.x", "const.y",
+                settings->op[stage].color_fixup);
+    }
+
+    /* Generate the main shader */
+    for (stage = 0; stage < MAX_TEXTURES; ++stage)
+    {
+        if (settings->op[stage].cop == WINED3D_TOP_DISABLE)
+        {
+            if (!stage)
+                final_combiner_src = "fragment.color.primary";
+            break;
+        }
+
+        if (settings->op[stage].cop == WINED3D_TOP_SELECT_ARG1
+                && settings->op[stage].aop == WINED3D_TOP_SELECT_ARG1)
+            op_equal = settings->op[stage].carg1 == settings->op[stage].aarg1;
+        else if (settings->op[stage].cop == WINED3D_TOP_SELECT_ARG1
+                && settings->op[stage].aop == WINED3D_TOP_SELECT_ARG2)
+            op_equal = settings->op[stage].carg1 == settings->op[stage].aarg2;
+        else if (settings->op[stage].cop == WINED3D_TOP_SELECT_ARG2
+                && settings->op[stage].aop == WINED3D_TOP_SELECT_ARG1)
+            op_equal = settings->op[stage].carg2 == settings->op[stage].aarg1;
+        else if (settings->op[stage].cop == WINED3D_TOP_SELECT_ARG2
+                && settings->op[stage].aop == WINED3D_TOP_SELECT_ARG2)
+            op_equal = settings->op[stage].carg2 == settings->op[stage].aarg2;
+        else
+            op_equal = settings->op[stage].aop   == settings->op[stage].cop
+                    && settings->op[stage].carg0 == settings->op[stage].aarg0
+                    && settings->op[stage].carg1 == settings->op[stage].aarg1
+                    && settings->op[stage].carg2 == settings->op[stage].aarg2;
+
+        if (settings->op[stage].aop == WINED3D_TOP_DISABLE)
+        {
+            gen_ffp_instr(&buffer, stage, TRUE, FALSE, settings->op[stage].dst,
+                          settings->op[stage].cop, settings->op[stage].carg0,
+                          settings->op[stage].carg1, settings->op[stage].carg2);
+            if (!stage)
+                shader_addline(&buffer, "MOV ret.w, fragment.color.primary.w;\n");
+        }
+        else if (op_equal)
+        {
+            gen_ffp_instr(&buffer, stage, TRUE, TRUE, settings->op[stage].dst,
+                          settings->op[stage].cop, settings->op[stage].carg0,
+                          settings->op[stage].carg1, settings->op[stage].carg2);
+        } else {
+            gen_ffp_instr(&buffer, stage, TRUE, FALSE, settings->op[stage].dst,
+                          settings->op[stage].cop, settings->op[stage].carg0,
+                          settings->op[stage].carg1, settings->op[stage].carg2);
+            gen_ffp_instr(&buffer, stage, FALSE, TRUE, settings->op[stage].dst,
+                          settings->op[stage].aop, settings->op[stage].aarg0,
+                          settings->op[stage].aarg1, settings->op[stage].aarg2);
+        }
+    }
+
+    if(settings->sRGB_write) {
+        shader_addline(&buffer, "MAD ret, fragment.color.secondary, specular_enable, %s;\n", final_combiner_src);
+        arbfp_add_sRGB_correction(&buffer, "ret", "arg0", "arg1", "arg2", "tempreg", FALSE);
+        shader_addline(&buffer, "MOV result.color, ret;\n");
+    } else {
+        shader_addline(&buffer, "MAD result.color, fragment.color.secondary, specular_enable, %s;\n", final_combiner_src);
+    }
+
+    /* Footer */
+    shader_addline(&buffer, "END\n");
+
+    /* Generate the shader */
+    GL_EXTCALL(glGenProgramsARB(1, &ret));
+    GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, ret));
+    GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
+            strlen(buffer.buffer), buffer.buffer));
+    checkGLcall("glProgramStringARB()");
+
+    gl_info->gl_ops.gl.p_glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos);
+    if (pos != -1)
+    {
+        FIXME("Fragment program error at position %d: %s\n\n", pos,
+              debugstr_a((const char *)gl_info->gl_ops.gl.p_glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
+        shader_arb_dump_program_source(buffer.buffer);
+    }
+    else
+    {
+        GLint native;
+
+        GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &native));
+        checkGLcall("glGetProgramivARB()");
+        if (!native) WARN("Program exceeds native resource limits.\n");
+    }
+
+    shader_buffer_free(&buffer);
+    return ret;
+}
+
+static void fragment_prog_arbfp(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_device *device = context->swapchain->device;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    struct shader_arb_priv *priv = device->fragment_priv;
+    BOOL use_pshader = use_ps(state);
+    struct ffp_frag_settings settings;
+    const struct arbfp_ffp_desc *desc;
+    unsigned int i;
+
+    TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);
+
+    if (isStateDirty(context, STATE_RENDER(WINED3D_RS_FOGENABLE)))
+    {
+        if (!use_pshader && device->shader_backend == &arb_program_shader_backend && context->last_was_pshader)
+        {
+            /* Reload fixed function constants since they collide with the
+             * pixel shader constants. */
+            for (i = 0; i < MAX_TEXTURES; ++i)
+            {
+                set_bumpmat_arbfp(context, state, STATE_TEXTURESTAGE(i, WINED3D_TSS_BUMPENV_MAT00));
+            }
+            state_texfactor_arbfp(context, state, STATE_RENDER(WINED3D_RS_TEXTUREFACTOR));
+            state_arb_specularenable(context, state, STATE_RENDER(WINED3D_RS_SPECULARENABLE));
+        }
+        else if (use_pshader)
+        {
+            context->select_shader = 1;
+        }
+        return;
+    }
+
+    if (!use_pshader)
+    {
+        /* Find or create a shader implementing the fixed function pipeline
+         * settings, then activate it. */
+        gen_ffp_frag_op(context, state, &settings, FALSE);
+        desc = (const struct arbfp_ffp_desc *)find_ffp_frag_shader(&priv->fragment_shaders, &settings);
+        if(!desc) {
+            struct arbfp_ffp_desc *new_desc = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_desc));
+            if (!new_desc)
+            {
+                ERR("Out of memory\n");
+                return;
+            }
+
+            new_desc->parent.settings = settings;
+            new_desc->shader = gen_arbfp_ffp_shader(&settings, gl_info);
+            add_ffp_frag_shader(&priv->fragment_shaders, &new_desc->parent);
+            TRACE("Allocated fixed function replacement shader descriptor %p\n", new_desc);
+            desc = new_desc;
+        }
+
+        /* Now activate the replacement program. GL_FRAGMENT_PROGRAM_ARB is already active (however, note the
+         * comment above the shader_select call below). If e.g. GLSL is active, the shader_select call will
+         * deactivate it.
+         */
+        GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, desc->shader));
+        checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, desc->shader)");
+        priv->current_fprogram_id = desc->shader;
+
+        if (device->shader_backend == &arb_program_shader_backend && context->last_was_pshader)
+        {
+            /* Reload fixed function constants since they collide with the
+             * pixel shader constants. */
+            for (i = 0; i < MAX_TEXTURES; ++i)
+            {
+                set_bumpmat_arbfp(context, state, STATE_TEXTURESTAGE(i, WINED3D_TSS_BUMPENV_MAT00));
+            }
+            state_texfactor_arbfp(context, state, STATE_RENDER(WINED3D_RS_TEXTUREFACTOR));
+            state_arb_specularenable(context, state, STATE_RENDER(WINED3D_RS_SPECULARENABLE));
+        }
+        context->last_was_pshader = FALSE;
+    } else {
+        context->last_was_pshader = TRUE;
+    }
+
+    context->select_shader = 1;
+    context->load_constants = 1;
+}
+
+/* We can't link the fog states to the fragment state directly since the
+ * vertex pipeline links them to FOGENABLE. A different linking in different
+ * pipeline parts can't be expressed in the combined state table, so we need
+ * to handle that with a forwarding function. The other invisible side effect
+ * is that changing the fog start and fog end (which links to FOGENABLE in
+ * vertex) results in the fragment_prog_arbfp function being called because
+ * FOGENABLE is dirty, which calls this function here. */
+static void state_arbfp_fog(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    enum fogsource new_source;
+
+    TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);
+
+    if (!isStateDirty(context, STATE_PIXELSHADER))
+        fragment_prog_arbfp(context, state, state_id);
+
+    if (!state->render_states[WINED3D_RS_FOGENABLE])
+        return;
+
+    if (state->render_states[WINED3D_RS_FOGTABLEMODE] == WINED3D_FOG_NONE)
+    {
+        if (use_vs(state))
+        {
+            new_source = FOGSOURCE_VS;
+        }
+        else
+        {
+            if (state->render_states[WINED3D_RS_FOGVERTEXMODE] == WINED3D_FOG_NONE || context->last_was_rhw)
+                new_source = FOGSOURCE_COORD;
+            else
+                new_source = FOGSOURCE_FFP;
+        }
+    }
+    else
+    {
+        new_source = FOGSOURCE_FFP;
+    }
+
+    if (new_source != context->fog_source)
+    {
+        context->fog_source = new_source;
+        state_fogstartend(context, state, STATE_RENDER(WINED3D_RS_FOGSTART));
+    }
+}
+
+static void textransform(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    if (!isStateDirty(context, STATE_PIXELSHADER))
+        fragment_prog_arbfp(context, state, state_id);
+}
+
+static const struct StateEntryTemplate arbfp_fragmentstate_template[] =
+{
+    {STATE_RENDER(WINED3D_RS_TEXTUREFACTOR),              { STATE_RENDER(WINED3D_RS_TEXTUREFACTOR),             state_texfactor_arbfp   }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG1),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG2),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG0),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_OP),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG1),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG2),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG0),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_RESULT_ARG),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   set_bumpmat_arbfp       }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT01),    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT10),    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT11),    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE),   { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE),  tex_bumpenvlum_arbfp    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LOFFSET),  { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE),  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_OP),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG1),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG2),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG0),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_OP),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG1),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG2),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG0),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_RESULT_ARG),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   set_bumpmat_arbfp       }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT01),    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT10),    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT11),    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE),   { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE),  tex_bumpenvlum_arbfp    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LOFFSET),  { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE),  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_OP),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG1),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG2),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG0),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_OP),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG1),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG2),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG0),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_RESULT_ARG),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   set_bumpmat_arbfp       }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT01),    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT10),    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT11),    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE),   { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE),  tex_bumpenvlum_arbfp    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LOFFSET),  { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE),  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_OP),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG1),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG2),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG0),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_OP),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG1),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG2),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG0),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_RESULT_ARG),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   set_bumpmat_arbfp       }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT01),    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT10),    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT11),    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE),   { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE),  tex_bumpenvlum_arbfp    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LOFFSET),  { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE),  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_OP),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG1),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG2),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG0),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_OP),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG1),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG2),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG0),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_RESULT_ARG),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   set_bumpmat_arbfp       }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT01),    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT10),    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT11),    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE),   { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE),  tex_bumpenvlum_arbfp    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LOFFSET),  { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE),  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_OP),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG1),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG2),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG0),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_OP),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG1),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG2),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG0),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_RESULT_ARG),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   set_bumpmat_arbfp       }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT01),    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT10),    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT11),    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE),   { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE),  tex_bumpenvlum_arbfp    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LOFFSET),  { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE),  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_OP),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG1),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG2),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG0),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_OP),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG1),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG2),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG0),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_RESULT_ARG),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   set_bumpmat_arbfp       }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT01),    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT10),    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT11),    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE),   { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE),  tex_bumpenvlum_arbfp    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LOFFSET),  { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE),  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_OP),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG1),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG2),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG0),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_OP),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG1),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG2),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG0),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_RESULT_ARG),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   set_bumpmat_arbfp       }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT01),    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT10),    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT11),    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE),   { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE),  tex_bumpenvlum_arbfp    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LOFFSET),  { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE),  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_PIXELSHADER,                                   { STATE_PIXELSHADER,                                  fragment_prog_arbfp     }, WINED3D_GL_EXT_NONE             },
+    {STATE_RENDER(WINED3D_RS_FOGENABLE),                  { STATE_RENDER(WINED3D_RS_FOGENABLE),                 state_arbfp_fog         }, WINED3D_GL_EXT_NONE             },
+    {STATE_RENDER(WINED3D_RS_FOGTABLEMODE),               { STATE_RENDER(WINED3D_RS_FOGENABLE),                 NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_RENDER(WINED3D_RS_FOGVERTEXMODE),              { STATE_RENDER(WINED3D_RS_FOGENABLE),                 NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_RENDER(WINED3D_RS_FOGSTART),                   { STATE_RENDER(WINED3D_RS_FOGSTART),                  state_fogstartend       }, WINED3D_GL_EXT_NONE             },
+    {STATE_RENDER(WINED3D_RS_FOGEND),                     { STATE_RENDER(WINED3D_RS_FOGSTART),                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE),            { STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE),           state_srgbwrite         }, ARB_FRAMEBUFFER_SRGB            },
+    {STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE),            { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_RENDER(WINED3D_RS_FOGCOLOR),                   { STATE_RENDER(WINED3D_RS_FOGCOLOR),                  state_fogcolor          }, WINED3D_GL_EXT_NONE             },
+    {STATE_RENDER(WINED3D_RS_FOGDENSITY),                 { STATE_RENDER(WINED3D_RS_FOGDENSITY),                state_fogdensity        }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
+    {STATE_RENDER(WINED3D_RS_SPECULARENABLE),             { STATE_RENDER(WINED3D_RS_SPECULARENABLE),            state_arb_specularenable}, WINED3D_GL_EXT_NONE             },
+    {0 /* Terminate */,                                   { 0,                                                  0                       }, WINED3D_GL_EXT_NONE             },
+};
+
+const struct fragment_pipeline arbfp_fragment_pipeline = {
+    arbfp_enable,
+    arbfp_get_caps,
+    arbfp_alloc,
+    arbfp_free,
+    shader_arb_color_fixup_supported,
+    arbfp_fragmentstate_template,
+};
+
+struct arbfp_blit_priv {
+    GLenum yuy2_rect_shader, yuy2_2d_shader;
+    GLenum uyvy_rect_shader, uyvy_2d_shader;
+    GLenum yv12_rect_shader, yv12_2d_shader;
+    GLenum p8_rect_shader, p8_2d_shader;
+    GLuint palette_texture;
+};
+
+static HRESULT arbfp_blit_alloc(struct wined3d_device *device)
+{
+    device->blit_priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct arbfp_blit_priv));
+    if(!device->blit_priv) {
+        ERR("Out of memory\n");
+        return E_OUTOFMEMORY;
+    }
+    return WINED3D_OK;
+}
+
+/* Context activation is done by the caller. */
+static void arbfp_blit_free(struct wined3d_device *device)
+{
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    struct arbfp_blit_priv *priv = device->blit_priv;
+
+    GL_EXTCALL(glDeleteProgramsARB(1, &priv->yuy2_rect_shader));
+    GL_EXTCALL(glDeleteProgramsARB(1, &priv->yuy2_2d_shader));
+    GL_EXTCALL(glDeleteProgramsARB(1, &priv->uyvy_rect_shader));
+    GL_EXTCALL(glDeleteProgramsARB(1, &priv->uyvy_2d_shader));
+    GL_EXTCALL(glDeleteProgramsARB(1, &priv->yv12_rect_shader));
+    GL_EXTCALL(glDeleteProgramsARB(1, &priv->yv12_2d_shader));
+    GL_EXTCALL(glDeleteProgramsARB(1, &priv->p8_rect_shader));
+    GL_EXTCALL(glDeleteProgramsARB(1, &priv->p8_2d_shader));
+    checkGLcall("Delete yuv and p8 programs");
+
+    if (priv->palette_texture)
+        gl_info->gl_ops.gl.p_glDeleteTextures(1, &priv->palette_texture);
+
+    HeapFree(GetProcessHeap(), 0, device->blit_priv);
+    device->blit_priv = NULL;
+}
+
+static BOOL gen_planar_yuv_read(struct wined3d_shader_buffer *buffer, enum complex_fixup fixup,
+        GLenum textype, char *luminance)
+{
+    char chroma;
+    const char *tex, *texinstr;
+
+    if (fixup == COMPLEX_FIXUP_UYVY) {
+        chroma = 'x';
+        *luminance = 'w';
+    } else {
+        chroma = 'w';
+        *luminance = 'x';
+    }
+    switch(textype) {
+        case GL_TEXTURE_2D:             tex = "2D";     texinstr = "TXP"; break;
+        case GL_TEXTURE_RECTANGLE_ARB:  tex = "RECT";   texinstr = "TEX"; break;
+        default:
+            /* This is more tricky than just replacing the texture type - we have to navigate
+             * properly in the texture to find the correct chroma values
+             */
+            FIXME("Implement yuv correction for non-2d, non-rect textures\n");
+            return FALSE;
+    }
+
+    /* First we have to read the chroma values. This means we need at least two pixels(no filtering),
+     * or 4 pixels(with filtering). To get the unmodified chromas, we have to rid ourselves of the
+     * filtering when we sample the texture.
+     *
+     * These are the rules for reading the chroma:
+     *
+     * Even pixel: Cr
+     * Even pixel: U
+     * Odd pixel: V
+     *
+     * So we have to get the sampling x position in non-normalized coordinates in integers
+     */
+    if(textype != GL_TEXTURE_RECTANGLE_ARB) {
+        shader_addline(buffer, "MUL texcrd.xy, fragment.texcoord[0], size.x;\n");
+        shader_addline(buffer, "MOV texcrd.w, size.x;\n");
+    } else {
+        shader_addline(buffer, "MOV texcrd, fragment.texcoord[0];\n");
+    }
+    /* We must not allow filtering between pixel x and x+1, this would mix U and V
+     * Vertical filtering is ok. However, bear in mind that the pixel center is at
+     * 0.5, so add 0.5.
+     */
+    shader_addline(buffer, "FLR texcrd.x, texcrd.x;\n");
+    shader_addline(buffer, "ADD texcrd.x, texcrd.x, coef.y;\n");
+
+    /* Divide the x coordinate by 0.5 and get the fraction. This gives 0.25 and 0.75 for the
+     * even and odd pixels respectively
+     */
+    shader_addline(buffer, "MUL texcrd2, texcrd, coef.y;\n");
+    shader_addline(buffer, "FRC texcrd2, texcrd2;\n");
+
+    /* Sample Pixel 1 */
+    shader_addline(buffer, "%s luminance, texcrd, texture[0], %s;\n", texinstr, tex);
+
+    /* Put the value into either of the chroma values */
+    shader_addline(buffer, "SGE temp.x, texcrd2.x, coef.y;\n");
+    shader_addline(buffer, "MUL chroma.x, luminance.%c, temp.x;\n", chroma);
+    shader_addline(buffer, "SLT temp.x, texcrd2.x, coef.y;\n");
+    shader_addline(buffer, "MUL chroma.y, luminance.%c, temp.x;\n", chroma);
+
+    /* Sample pixel 2. If we read an even pixel(SLT above returned 1), sample
+     * the pixel right to the current one. Otherwise, sample the left pixel.
+     * Bias and scale the SLT result to -1;1 and add it to the texcrd.x.
+     */
+    shader_addline(buffer, "MAD temp.x, temp.x, coef.z, -coef.x;\n");
+    shader_addline(buffer, "ADD texcrd.x, texcrd, temp.x;\n");
+    shader_addline(buffer, "%s luminance, texcrd, texture[0], %s;\n", texinstr, tex);
+
+    /* Put the value into the other chroma */
+    shader_addline(buffer, "SGE temp.x, texcrd2.x, coef.y;\n");
+    shader_addline(buffer, "MAD chroma.y, luminance.%c, temp.x, chroma.y;\n", chroma);
+    shader_addline(buffer, "SLT temp.x, texcrd2.x, coef.y;\n");
+    shader_addline(buffer, "MAD chroma.x, luminance.%c, temp.x, chroma.x;\n", chroma);
+
+    /* TODO: If filtering is enabled, sample a 2nd pair of pixels left or right of
+     * the current one and lerp the two U and V values
+     */
+
+    /* This gives the correctly filtered luminance value */
+    shader_addline(buffer, "TEX luminance, fragment.texcoord[0], texture[0], %s;\n", tex);
+
+    return TRUE;
+}
+
+static BOOL gen_yv12_read(struct wined3d_shader_buffer *buffer, GLenum textype, char *luminance)
+{
+    const char *tex;
+
+    switch(textype) {
+        case GL_TEXTURE_2D:             tex = "2D";     break;
+        case GL_TEXTURE_RECTANGLE_ARB:  tex = "RECT";   break;
+        default:
+            FIXME("Implement yv12 correction for non-2d, non-rect textures\n");
+            return FALSE;
+    }
+
+    /* YV12 surfaces contain a WxH sized luminance plane, followed by a (W/2)x(H/2)
+     * V and a (W/2)x(H/2) U plane, each with 8 bit per pixel. So the effective
+     * bitdepth is 12 bits per pixel. Since the U and V planes have only half the
+     * pitch of the luminance plane, the packing into the gl texture is a bit
+     * unfortunate. If the whole texture is interpreted as luminance data it looks
+     * approximately like this:
+     *
+     *        +----------------------------------+----
+     *        |                                  |
+     *        |                                  |
+     *        |                                  |
+     *        |                                  |
+     *        |                                  |   2
+     *        |            LUMINANCE             |   -
+     *        |                                  |   3
+     *        |                                  |
+     *        |                                  |
+     *        |                                  |
+     *        |                                  |
+     *        +----------------+-----------------+----
+     *        |                |                 |
+     *        |  U even rows   |  U odd rows     |
+     *        |                |                 |   1
+     *        +----------------+------------------   -
+     *        |                |                 |   3
+     *        |  V even rows   |  V odd rows     |
+     *        |                |                 |
+     *        +----------------+-----------------+----
+     *        |                |                 |
+     *        |     0.5        |       0.5       |
+     *
+     * So it appears as if there are 4 chroma images, but in fact the odd rows
+     * in the chroma images are in the same row as the even ones. So its is
+     * kinda tricky to read
+     *
+     * When reading from rectangle textures, keep in mind that the input y coordinates
+     * go from 0 to d3d_height, whereas the opengl texture height is 1.5 * d3d_height
+     */
+    shader_addline(buffer, "PARAM yv12_coef = {%f, %f, %f, %f};\n",
+            2.0f / 3.0f, 1.0f / 6.0f, (2.0f / 3.0f) + (1.0f / 6.0f), 1.0f / 3.0f);
+
+    shader_addline(buffer, "MOV texcrd, fragment.texcoord[0];\n");
+    /* the chroma planes have only half the width */
+    shader_addline(buffer, "MUL texcrd.x, texcrd.x, coef.y;\n");
+
+    /* The first value is between 2/3 and 5/6th of the texture's height, so scale+bias
+     * the coordinate. Also read the right side of the image when reading odd lines
+     *
+     * Don't forget to clamp the y values in into the range, otherwise we'll get filtering
+     * bleeding
+     */
+    if(textype == GL_TEXTURE_2D) {
+
+        shader_addline(buffer, "RCP chroma.w, size.y;\n");
+
+        shader_addline(buffer, "MUL texcrd2.y, texcrd.y, size.y;\n");
+
+        shader_addline(buffer, "FLR texcrd2.y, texcrd2.y;\n");
+        shader_addline(buffer, "MAD texcrd.y, texcrd.y, yv12_coef.y, yv12_coef.x;\n");
+
+        /* Read odd lines from the right side(add size * 0.5 to the x coordinate */
+        shader_addline(buffer, "ADD texcrd2.x, texcrd2.y, yv12_coef.y;\n"); /* To avoid 0.5 == 0.5 comparisons */
+        shader_addline(buffer, "FRC texcrd2.x, texcrd2.x;\n");
+        shader_addline(buffer, "SGE texcrd2.x, texcrd2.x, coef.y;\n");
+        shader_addline(buffer, "MAD texcrd.x, texcrd2.x, coef.y, texcrd.x;\n");
+
+        /* clamp, keep the half pixel origin in mind */
+        shader_addline(buffer, "MAD temp.y, coef.y, chroma.w, yv12_coef.x;\n");
+        shader_addline(buffer, "MAX texcrd.y, temp.y, texcrd.y;\n");
+        shader_addline(buffer, "MAD temp.y, -coef.y, chroma.w, yv12_coef.z;\n");
+        shader_addline(buffer, "MIN texcrd.y, temp.y, texcrd.y;\n");
+    } else {
+        /* Read from [size - size+size/4] */
+        shader_addline(buffer, "FLR texcrd.y, texcrd.y;\n");
+        shader_addline(buffer, "MAD texcrd.y, texcrd.y, coef.w, size.y;\n");
+
+        /* Read odd lines from the right side(add size * 0.5 to the x coordinate */
+        shader_addline(buffer, "ADD texcrd2.x, texcrd.y, yv12_coef.y;\n"); /* To avoid 0.5 == 0.5 comparisons */
+        shader_addline(buffer, "FRC texcrd2.x, texcrd2.x;\n");
+        shader_addline(buffer, "SGE texcrd2.x, texcrd2.x, coef.y;\n");
+        shader_addline(buffer, "MUL texcrd2.x, texcrd2.x, size.x;\n");
+        shader_addline(buffer, "MAD texcrd.x, texcrd2.x, coef.y, texcrd.x;\n");
+
+        /* Make sure to read exactly from the pixel center */
+        shader_addline(buffer, "FLR texcrd.y, texcrd.y;\n");
+        shader_addline(buffer, "ADD texcrd.y, texcrd.y, coef.y;\n");
+
+        /* Clamp */
+        shader_addline(buffer, "MAD temp.y, size.y, coef.w, size.y;\n");
+        shader_addline(buffer, "ADD temp.y, temp.y, -coef.y;\n");
+        shader_addline(buffer, "MIN texcrd.y, temp.y, texcrd.y;\n");
+        shader_addline(buffer, "ADD temp.y, size.y, -coef.y;\n");
+        shader_addline(buffer, "MAX texcrd.y, temp.y, texcrd.y;\n");
+    }
+    /* Read the texture, put the result into the output register */
+    shader_addline(buffer, "TEX temp, texcrd, texture[0], %s;\n", tex);
+    shader_addline(buffer, "MOV chroma.x, temp.w;\n");
+
+    /* The other chroma value is 1/6th of the texture lower, from 5/6th to 6/6th
+     * No need to clamp because we're just reusing the already clamped value from above
+     */
+    if(textype == GL_TEXTURE_2D) {
+        shader_addline(buffer, "ADD texcrd.y, texcrd.y, yv12_coef.y;\n");
+    } else {
+        shader_addline(buffer, "MAD texcrd.y, size.y, coef.w, texcrd.y;\n");
+    }
+    shader_addline(buffer, "TEX temp, texcrd, texture[0], %s;\n", tex);
+    shader_addline(buffer, "MOV chroma.y, temp.w;\n");
+
+    /* Sample the luminance value. It is in the top 2/3rd of the texture, so scale the y coordinate.
+     * Clamp the y coordinate to prevent the chroma values from bleeding into the sampled luminance
+     * values due to filtering
+     */
+    shader_addline(buffer, "MOV texcrd, fragment.texcoord[0];\n");
+    if(textype == GL_TEXTURE_2D) {
+        /* Multiply the y coordinate by 2/3 and clamp it */
+        shader_addline(buffer, "MUL texcrd.y, texcrd.y, yv12_coef.x;\n");
+        shader_addline(buffer, "MAD temp.y, -coef.y, chroma.w, yv12_coef.x;\n");
+        shader_addline(buffer, "MIN texcrd.y, temp.y, texcrd.y;\n");
+        shader_addline(buffer, "TEX luminance, texcrd, texture[0], %s;\n", tex);
+    } else {
+        /* Reading from texture_rectangles is pretty straightforward, just use the unmodified
+         * texture coordinate. It is still a good idea to clamp it though, since the opengl texture
+         * is bigger
+         */
+        shader_addline(buffer, "ADD temp.x, size.y, -coef.y;\n");
+        shader_addline(buffer, "MIN texcrd.y, texcrd.y, size.x;\n");
+        shader_addline(buffer, "TEX luminance, texcrd, texture[0], %s;\n", tex);
+    }
+    *luminance = 'a';
+
+    return TRUE;
+}
+
+static GLuint gen_p8_shader(struct arbfp_blit_priv *priv,
+        const struct wined3d_gl_info *gl_info, GLenum textype)
+{
+    GLenum shader;
+    struct wined3d_shader_buffer buffer;
+    GLint pos;
+
+    /* Shader header */
+    if (!shader_buffer_init(&buffer))
+    {
+        ERR("Failed to initialize shader buffer.\n");
+        return 0;
+    }
+
+    GL_EXTCALL(glGenProgramsARB(1, &shader));
+    GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, shader));
+    if (!shader)
+    {
+        shader_buffer_free(&buffer);
+        return 0;
+    }
+
+    shader_addline(&buffer, "!!ARBfp1.0\n");
+    shader_addline(&buffer, "TEMP index;\n");
+
+    /* { 255/256, 0.5/255*255/256, 0, 0 } */
+    shader_addline(&buffer, "PARAM constants = { 0.996, 0.00195, 0, 0 };\n");
+
+    /* The alpha-component contains the palette index */
+    if(textype == GL_TEXTURE_RECTANGLE_ARB)
+        shader_addline(&buffer, "TXP index, fragment.texcoord[0], texture[0], RECT;\n");
+    else
+        shader_addline(&buffer, "TEX index, fragment.texcoord[0], texture[0], 2D;\n");
+
+    /* Scale the index by 255/256 and add a bias of '0.5' in order to sample in the middle */
+    shader_addline(&buffer, "MAD index.a, index.a, constants.x, constants.y;\n");
+
+    /* Use the alpha-component as an index in the palette to get the final color */
+    shader_addline(&buffer, "TEX result.color, index.a, texture[1], 1D;\n");
+    shader_addline(&buffer, "END\n");
+
+    GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
+            strlen(buffer.buffer), buffer.buffer));
+    checkGLcall("glProgramStringARB()");
+
+    gl_info->gl_ops.gl.p_glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos);
+    if (pos != -1)
+    {
+        FIXME("Fragment program error at position %d: %s\n\n", pos,
+              debugstr_a((const char *)gl_info->gl_ops.gl.p_glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
+        shader_arb_dump_program_source(buffer.buffer);
+    }
+
+    if (textype == GL_TEXTURE_RECTANGLE_ARB)
+        priv->p8_rect_shader = shader;
+    else
+        priv->p8_2d_shader = shader;
+
+    shader_buffer_free(&buffer);
+
+    return shader;
+}
+
+/* Context activation is done by the caller. */
+static void upload_palette(const struct wined3d_surface *surface, struct wined3d_context *context)
+{
+    BYTE table[256][4];
+    struct wined3d_device *device = surface->resource.device;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    struct arbfp_blit_priv *priv = device->blit_priv;
+    BOOL colorkey = (surface->CKeyFlags & WINEDDSD_CKSRCBLT) != 0;
+
+    d3dfmt_p8_init_palette(surface, table, colorkey);
+
+    if (gl_info->supported[APPLE_CLIENT_STORAGE])
+    {
+        gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
+        checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
+    }
+
+    if (!priv->palette_texture)
+        gl_info->gl_ops.gl.p_glGenTextures(1, &priv->palette_texture);
+
+    GL_EXTCALL(glActiveTextureARB(GL_TEXTURE1));
+    gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_1D, priv->palette_texture);
+
+    gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    /* Make sure we have discrete color levels. */
+    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    /* Upload the palette */
+    /* TODO: avoid unneeded uploads in the future by adding some SFLAG_PALETTE_DIRTY mechanism */
+    gl_info->gl_ops.gl.p_glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, table);
+
+    if (gl_info->supported[APPLE_CLIENT_STORAGE])
+    {
+        gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
+        checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
+    }
+
+    /* Switch back to unit 0 in which the 2D texture will be stored. */
+    context_active_texture(context, gl_info, 0);
+}
+
+/* Context activation is done by the caller. */
+static GLuint gen_yuv_shader(struct arbfp_blit_priv *priv, const struct wined3d_gl_info *gl_info,
+        enum complex_fixup yuv_fixup, GLenum textype)
+{
+    GLenum shader;
+    struct wined3d_shader_buffer buffer;
+    char luminance_component;
+    GLint pos;
+
+    /* Shader header */
+    if (!shader_buffer_init(&buffer))
+    {
+        ERR("Failed to initialize shader buffer.\n");
+        return 0;
+    }
+
+    GL_EXTCALL(glGenProgramsARB(1, &shader));
+    checkGLcall("GL_EXTCALL(glGenProgramsARB(1, &shader))");
+    GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, shader));
+    checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, shader)");
+    if (!shader)
+    {
+        shader_buffer_free(&buffer);
+        return 0;
+    }
+
+    /* The YUY2 and UYVY formats contain two pixels packed into a 32 bit macropixel,
+     * giving effectively 16 bit per pixel. The color consists of a luminance(Y) and
+     * two chroma(U and V) values. Each macropixel has two luminance values, one for
+     * each single pixel it contains, and one U and one V value shared between both
+     * pixels.
+     *
+     * The data is loaded into an A8L8 texture. With YUY2, the luminance component
+     * contains the luminance and alpha the chroma. With UYVY it is vice versa. Thus
+     * take the format into account when generating the read swizzles
+     *
+     * Reading the Y value is straightforward - just sample the texture. The hardware
+     * takes care of filtering in the horizontal and vertical direction.
+     *
+     * Reading the U and V values is harder. We have to avoid filtering horizontally,
+     * because that would mix the U and V values of one pixel or two adjacent pixels.
+     * Thus floor the texture coordinate and add 0.5 to get an unfiltered read,
+     * regardless of the filtering setting. Vertical filtering works automatically
+     * though - the U and V values of two rows are mixed nicely.
+     *
+     * Apart of avoiding filtering issues, the code has to know which value it just
+     * read, and where it can find the other one. To determine this, it checks if
+     * it sampled an even or odd pixel, and shifts the 2nd read accordingly.
+     *
+     * Handling horizontal filtering of U and V values requires reading a 2nd pair
+     * of pixels, extracting U and V and mixing them. This is not implemented yet.
+     *
+     * An alternative implementation idea is to load the texture as A8R8G8B8 texture,
+     * with width / 2. This way one read gives all 3 values, finding U and V is easy
+     * in an unfiltered situation. Finding the luminance on the other hand requires
+     * finding out if it is an odd or even pixel. The real drawback of this approach
+     * is filtering. This would have to be emulated completely in the shader, reading
+     * up two 2 packed pixels in up to 2 rows and interpolating both horizontally and
+     * vertically. Beyond that it would require adjustments to the texture handling
+     * code to deal with the width scaling
+     */
+    shader_addline(&buffer, "!!ARBfp1.0\n");
+    shader_addline(&buffer, "TEMP luminance;\n");
+    shader_addline(&buffer, "TEMP temp;\n");
+    shader_addline(&buffer, "TEMP chroma;\n");
+    shader_addline(&buffer, "TEMP texcrd;\n");
+    shader_addline(&buffer, "TEMP texcrd2;\n");
+    shader_addline(&buffer, "PARAM coef = {1.0, 0.5, 2.0, 0.25};\n");
+    shader_addline(&buffer, "PARAM yuv_coef = {1.403, 0.344, 0.714, 1.770};\n");
+    shader_addline(&buffer, "PARAM size = program.local[0];\n");
+
+    switch (yuv_fixup)
+    {
+        case COMPLEX_FIXUP_UYVY:
+        case COMPLEX_FIXUP_YUY2:
+            if (!gen_planar_yuv_read(&buffer, yuv_fixup, textype, &luminance_component))
+            {
+                shader_buffer_free(&buffer);
+                return 0;
+            }
+            break;
+
+        case COMPLEX_FIXUP_YV12:
+            if (!gen_yv12_read(&buffer, textype, &luminance_component))
+            {
+                shader_buffer_free(&buffer);
+                return 0;
+            }
+            break;
+
+        default:
+            FIXME("Unsupported YUV fixup %#x\n", yuv_fixup);
+            shader_buffer_free(&buffer);
+            return 0;
+    }
+
+    /* Calculate the final result. Formula is taken from
+     * http://www.fourcc.org/fccyvrgb.php. Note that the chroma
+     * ranges from -0.5 to 0.5
+     */
+    shader_addline(&buffer, "SUB chroma.xy, chroma, coef.y;\n");
+
+    shader_addline(&buffer, "MAD result.color.x, chroma.x, yuv_coef.x, luminance.%c;\n", luminance_component);
+    shader_addline(&buffer, "MAD temp.x, -chroma.y, yuv_coef.y, luminance.%c;\n", luminance_component);
+    shader_addline(&buffer, "MAD result.color.y, -chroma.x, yuv_coef.z, temp.x;\n");
+    shader_addline(&buffer, "MAD result.color.z, chroma.y, yuv_coef.w, luminance.%c;\n", luminance_component);
+    shader_addline(&buffer, "END\n");
+
+    GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
+            strlen(buffer.buffer), buffer.buffer));
+    checkGLcall("glProgramStringARB()");
+
+    gl_info->gl_ops.gl.p_glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos);
+    if (pos != -1)
+    {
+        FIXME("Fragment program error at position %d: %s\n\n", pos,
+              debugstr_a((const char *)gl_info->gl_ops.gl.p_glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
+        shader_arb_dump_program_source(buffer.buffer);
+    }
+    else
+    {
+        GLint native;
+
+        GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &native));
+        checkGLcall("glGetProgramivARB()");
+        if (!native) WARN("Program exceeds native resource limits.\n");
+    }
+
+    shader_buffer_free(&buffer);
+
+    switch (yuv_fixup)
+    {
+        case COMPLEX_FIXUP_YUY2:
+            if (textype == GL_TEXTURE_RECTANGLE_ARB) priv->yuy2_rect_shader = shader;
+            else priv->yuy2_2d_shader = shader;
+            break;
+
+        case COMPLEX_FIXUP_UYVY:
+            if (textype == GL_TEXTURE_RECTANGLE_ARB) priv->uyvy_rect_shader = shader;
+            else priv->uyvy_2d_shader = shader;
+            break;
+
+        case COMPLEX_FIXUP_YV12:
+            if (textype == GL_TEXTURE_RECTANGLE_ARB) priv->yv12_rect_shader = shader;
+            else priv->yv12_2d_shader = shader;
+            break;
+        default:
+            ERR("Unsupported complex fixup: %d\n", yuv_fixup);
+    }
+
+    return shader;
+}
+
+/* Context activation is done by the caller. */
+static HRESULT arbfp_blit_set(void *blit_priv, struct wined3d_context *context, const struct wined3d_surface *surface)
+{
+    GLenum shader;
+    float size[4] = {(float) surface->pow2Width, (float) surface->pow2Height, 1.0f, 1.0f};
+    struct arbfp_blit_priv *priv = blit_priv;
+    enum complex_fixup fixup;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    GLenum textype;
+
+    if (surface->container)
+        textype = surface->container->target;
+    else
+        textype = surface->texture_target;
+
+    if (surface->flags & SFLAG_CONVERTED)
+    {
+        gl_info->gl_ops.gl.p_glEnable(textype);
+        checkGLcall("glEnable(textype)");
+        return WINED3D_OK;
+    }
+
+    if (!is_complex_fixup(surface->resource.format->color_fixup))
+    {
+        TRACE("Fixup:\n");
+        dump_color_fixup_desc(surface->resource.format->color_fixup);
+        /* Don't bother setting up a shader for unconverted formats */
+        gl_info->gl_ops.gl.p_glEnable(textype);
+        checkGLcall("glEnable(textype)");
+        return WINED3D_OK;
+    }
+
+    fixup = get_complex_fixup(surface->resource.format->color_fixup);
+
+    switch(fixup)
+    {
+        case COMPLEX_FIXUP_YUY2:
+            shader = textype == GL_TEXTURE_RECTANGLE_ARB ? priv->yuy2_rect_shader : priv->yuy2_2d_shader;
+            break;
+
+        case COMPLEX_FIXUP_UYVY:
+            shader = textype == GL_TEXTURE_RECTANGLE_ARB ? priv->uyvy_rect_shader : priv->uyvy_2d_shader;
+            break;
+
+        case COMPLEX_FIXUP_YV12:
+            shader = textype == GL_TEXTURE_RECTANGLE_ARB ? priv->yv12_rect_shader : priv->yv12_2d_shader;
+            break;
+
+        case COMPLEX_FIXUP_P8:
+            shader = textype == GL_TEXTURE_RECTANGLE_ARB ? priv->p8_rect_shader : priv->p8_2d_shader;
+            if (!shader) shader = gen_p8_shader(priv, gl_info, textype);
+
+            upload_palette(surface, context);
+            break;
+
+        default:
+            FIXME("Unsupported complex fixup %#x, not setting a shader\n", fixup);
+            gl_info->gl_ops.gl.p_glEnable(textype);
+            checkGLcall("glEnable(textype)");
+            return E_NOTIMPL;
+    }
+
+    if (!shader) shader = gen_yuv_shader(priv, gl_info, fixup, textype);
+
+    gl_info->gl_ops.gl.p_glEnable(GL_FRAGMENT_PROGRAM_ARB);
+    checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB)");
+    GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, shader));
+    checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, shader)");
+    GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 0, size));
+    checkGLcall("glProgramLocalParameter4fvARB");
+
+    return WINED3D_OK;
+}
+
+/* Context activation is done by the caller. */
+static void arbfp_blit_unset(const struct wined3d_gl_info *gl_info)
+{
+    gl_info->gl_ops.gl.p_glDisable(GL_FRAGMENT_PROGRAM_ARB);
+    checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)");
+    gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
+    checkGLcall("glDisable(GL_TEXTURE_2D)");
+    if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB);
+        checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
+    }
+    if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB);
+        checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
+    }
+}
+
+static BOOL arbfp_blit_supported(const struct wined3d_gl_info *gl_info, enum wined3d_blit_op blit_op,
+        const RECT *src_rect, DWORD src_usage, enum wined3d_pool src_pool, const struct wined3d_format *src_format,
+        const RECT *dst_rect, DWORD dst_usage, enum wined3d_pool dst_pool, const struct wined3d_format *dst_format)
+{
+    enum complex_fixup src_fixup;
+
+    if (!gl_info->supported[ARB_FRAGMENT_PROGRAM])
+        return FALSE;
+
+    if (blit_op != WINED3D_BLIT_OP_COLOR_BLIT)
+    {
+        TRACE("Unsupported blit_op=%d\n", blit_op);
+        return FALSE;
+    }
+
+    if (src_pool == WINED3D_POOL_SYSTEM_MEM || dst_pool == WINED3D_POOL_SYSTEM_MEM)
+        return FALSE;
+
+    src_fixup = get_complex_fixup(src_format->color_fixup);
+    if (TRACE_ON(d3d_shader) && TRACE_ON(d3d))
+    {
+        TRACE("Checking support for fixup:\n");
+        dump_color_fixup_desc(src_format->color_fixup);
+    }
+
+    if (!is_identity_fixup(dst_format->color_fixup))
+    {
+        TRACE("Destination fixups are not supported\n");
+        return FALSE;
+    }
+
+    if (is_identity_fixup(src_format->color_fixup))
+    {
+        TRACE("[OK]\n");
+        return TRUE;
+    }
+
+     /* We only support YUV conversions. */
+    if (!is_complex_fixup(src_format->color_fixup))
+    {
+        TRACE("[FAILED]\n");
+        return FALSE;
+    }
+
+    switch(src_fixup)
+    {
+        case COMPLEX_FIXUP_YUY2:
+        case COMPLEX_FIXUP_UYVY:
+        case COMPLEX_FIXUP_YV12:
+        case COMPLEX_FIXUP_P8:
+            TRACE("[OK]\n");
+            return TRUE;
+
+        default:
+            FIXME("Unsupported YUV fixup %#x\n", src_fixup);
+            TRACE("[FAILED]\n");
+            return FALSE;
+    }
+}
+
+HRESULT arbfp_blit_surface(struct wined3d_device *device, DWORD filter,
+        struct wined3d_surface *src_surface, const RECT *src_rect_in,
+        struct wined3d_surface *dst_surface, const RECT *dst_rect_in)
+{
+    struct wined3d_context *context;
+    RECT src_rect = *src_rect_in;
+    RECT dst_rect = *dst_rect_in;
+
+    /* Now load the surface */
+    if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
+            && (src_surface->flags & (SFLAG_INTEXTURE | SFLAG_INDRAWABLE)) == SFLAG_INDRAWABLE)
+    {
+        /* Without FBO blits transferring from the drawable to the texture is
+         * expensive, because we have to flip the data in sysmem. Since we can
+         * flip in the blitter, we don't actually need that flip anyway. So we
+         * use the surface's texture as scratch texture, and flip the source
+         * rectangle instead. */
+        surface_load_fb_texture(src_surface, FALSE);
+
+        src_rect.top = src_surface->resource.height - src_rect.top;
+        src_rect.bottom = src_surface->resource.height - src_rect.bottom;
+    }
+    else
+        surface_internal_preload(src_surface, SRGB_RGB);
+
+    /* Activate the destination context, set it up for blitting */
+    context = context_acquire(device, dst_surface);
+    context_apply_blit_state(context, device);
+
+    if (!surface_is_offscreen(dst_surface))
+#ifndef VBOX_WINE_WITH_SINGLE_CONTEXT
+        surface_translate_drawable_coords(dst_surface, context->win_handle, &dst_rect);
+#else
+        surface_translate_drawable_coords(dst_surface, context->swapchain->win_handle, &dst_rect);
+#endif
+
+    arbfp_blit_set(device->blit_priv, context, src_surface);
+
+    /* Draw a textured quad */
+    draw_textured_quad(src_surface, context, &src_rect, &dst_rect, filter);
+
+    /* Leave the opengl state valid for blitting */
+    arbfp_blit_unset(context->gl_info);
+
+    if (wined3d_settings.strict_draw_ordering
+            || (dst_surface->swapchain && (dst_surface->swapchain->front_buffer == dst_surface)))
+        context->gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */
+
+    context_release(context);
+
+    surface_modify_location(dst_surface, dst_surface->draw_binding, TRUE);
+    return WINED3D_OK;
+}
+
+/* Do not call while under the GL lock. */
+static HRESULT arbfp_blit_color_fill(struct wined3d_device *device, struct wined3d_surface *dst_surface,
+        const RECT *dst_rect, const struct wined3d_color *color)
+{
+    FIXME("Color filling not implemented by arbfp_blit\n");
+    return WINED3DERR_INVALIDCALL;
+}
+
+/* Do not call while under the GL lock. */
+static HRESULT arbfp_blit_depth_fill(struct wined3d_device *device,
+        struct wined3d_surface *surface, const RECT *rect, float depth)
+{
+    FIXME("Depth filling not implemented by arbfp_blit.\n");
+    return WINED3DERR_INVALIDCALL;
+}
+
+const struct blit_shader arbfp_blit = {
+    arbfp_blit_alloc,
+    arbfp_blit_free,
+    arbfp_blit_set,
+    arbfp_blit_unset,
+    arbfp_blit_supported,
+    arbfp_blit_color_fill,
+    arbfp_blit_depth_fill,
+};
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/ati_fragment_shader.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/ati_fragment_shader.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/ati_fragment_shader.c	(revision 46521)
@@ -0,0 +1,1219 @@
+/*
+ * Fixed function pipeline replacement using GL_ATI_fragment_shader
+ *
+ * Copyright 2008 Stefan Dösinger(for CodeWeavers)
+ *
+ * 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 <math.h>
+#include <stdio.h>
+
+#include "wined3d_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
+WINE_DECLARE_DEBUG_CHANNEL(d3d);
+
+/* Context activation for state handlers is done by the caller. */
+
+/* Some private defines, Constant associations, etc.
+ * Env bump matrix and per stage constant should be independent,
+ * a stage that bump maps can't read the per state constant
+ */
+#define ATI_FFP_CONST_BUMPMAT(i) (GL_CON_0_ATI + i)
+#define ATI_FFP_CONST_CONSTANT0 GL_CON_0_ATI
+#define ATI_FFP_CONST_CONSTANT1 GL_CON_1_ATI
+#define ATI_FFP_CONST_CONSTANT2 GL_CON_2_ATI
+#define ATI_FFP_CONST_CONSTANT3 GL_CON_3_ATI
+#define ATI_FFP_CONST_CONSTANT4 GL_CON_4_ATI
+#define ATI_FFP_CONST_CONSTANT5 GL_CON_5_ATI
+#define ATI_FFP_CONST_TFACTOR   GL_CON_6_ATI
+
+/* GL_ATI_fragment_shader specific fixed function pipeline description. "Inherits" from the common one */
+struct atifs_ffp_desc
+{
+    struct ffp_frag_desc parent;
+    GLuint shader;
+    unsigned int num_textures_used;
+};
+
+struct atifs_private_data
+{
+    struct wine_rb_tree fragment_shaders; /* A rb-tree to track fragment pipeline replacement shaders */
+};
+
+static const char *debug_dstmod(GLuint mod) {
+    switch(mod) {
+        case GL_NONE:               return "GL_NONE";
+        case GL_2X_BIT_ATI:         return "GL_2X_BIT_ATI";
+        case GL_4X_BIT_ATI:         return "GL_4X_BIT_ATI";
+        case GL_8X_BIT_ATI:         return "GL_8X_BIT_ATI";
+        case GL_HALF_BIT_ATI:       return "GL_HALF_BIT_ATI";
+        case GL_QUARTER_BIT_ATI:    return "GL_QUARTER_BIT_ATI";
+        case GL_EIGHTH_BIT_ATI:     return "GL_EIGHTH_BIT_ATI";
+        case GL_SATURATE_BIT_ATI:   return "GL_SATURATE_BIT_ATI";
+        default:                    return "Unexpected modifier\n";
+    }
+}
+
+static const char *debug_argmod(GLuint mod) {
+    switch(mod) {
+        case GL_NONE:
+            return "GL_NONE";
+
+        case GL_2X_BIT_ATI:
+            return "GL_2X_BIT_ATI";
+        case GL_COMP_BIT_ATI:
+            return "GL_COMP_BIT_ATI";
+        case GL_NEGATE_BIT_ATI:
+            return "GL_NEGATE_BIT_ATI";
+        case GL_BIAS_BIT_ATI:
+            return "GL_BIAS_BIT_ATI";
+
+        case GL_2X_BIT_ATI | GL_COMP_BIT_ATI:
+            return "GL_2X_BIT_ATI | GL_COMP_BIT_ATI";
+        case GL_2X_BIT_ATI | GL_NEGATE_BIT_ATI:
+            return "GL_2X_BIT_ATI | GL_NEGATE_BIT_ATI";
+        case GL_2X_BIT_ATI | GL_BIAS_BIT_ATI:
+            return "GL_2X_BIT_ATI | GL_BIAS_BIT_ATI";
+        case GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI:
+            return "GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI";
+        case GL_COMP_BIT_ATI | GL_BIAS_BIT_ATI:
+            return "GL_COMP_BIT_ATI | GL_BIAS_BIT_ATI";
+        case GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI:
+            return "GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI";
+
+        case GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI:
+            return "GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI";
+        case GL_2X_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI:
+            return "GL_2X_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI";
+        case GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_BIAS_BIT_ATI:
+            return "GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_BIAS_BIT_ATI";
+        case GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI:
+            return "GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI";
+
+        case GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI:
+            return "GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI";
+
+        default:
+            return "Unexpected argmod combination\n";
+    }
+}
+static const char *debug_register(GLuint reg) {
+    switch(reg) {
+        case GL_REG_0_ATI:                  return "GL_REG_0_ATI";
+        case GL_REG_1_ATI:                  return "GL_REG_1_ATI";
+        case GL_REG_2_ATI:                  return "GL_REG_2_ATI";
+        case GL_REG_3_ATI:                  return "GL_REG_3_ATI";
+        case GL_REG_4_ATI:                  return "GL_REG_4_ATI";
+        case GL_REG_5_ATI:                  return "GL_REG_5_ATI";
+
+        case GL_CON_0_ATI:                  return "GL_CON_0_ATI";
+        case GL_CON_1_ATI:                  return "GL_CON_1_ATI";
+        case GL_CON_2_ATI:                  return "GL_CON_2_ATI";
+        case GL_CON_3_ATI:                  return "GL_CON_3_ATI";
+        case GL_CON_4_ATI:                  return "GL_CON_4_ATI";
+        case GL_CON_5_ATI:                  return "GL_CON_5_ATI";
+        case GL_CON_6_ATI:                  return "GL_CON_6_ATI";
+        case GL_CON_7_ATI:                  return "GL_CON_7_ATI";
+
+        case GL_ZERO:                       return "GL_ZERO";
+        case GL_ONE:                        return "GL_ONE";
+        case GL_PRIMARY_COLOR:              return "GL_PRIMARY_COLOR";
+        case GL_SECONDARY_INTERPOLATOR_ATI: return "GL_SECONDARY_INTERPOLATOR_ATI";
+
+        default:                            return "Unknown register\n";
+    }
+}
+
+static const char *debug_swizzle(GLuint swizzle) {
+    switch(swizzle) {
+        case GL_SWIZZLE_STR_ATI:        return "GL_SWIZZLE_STR_ATI";
+        case GL_SWIZZLE_STQ_ATI:        return "GL_SWIZZLE_STQ_ATI";
+        case GL_SWIZZLE_STR_DR_ATI:     return "GL_SWIZZLE_STR_DR_ATI";
+        case GL_SWIZZLE_STQ_DQ_ATI:     return "GL_SWIZZLE_STQ_DQ_ATI";
+        default:                        return "unknown swizzle";
+    }
+}
+
+static const char *debug_rep(GLuint rep) {
+    switch(rep) {
+        case GL_NONE:                   return "GL_NONE";
+        case GL_RED:                    return "GL_RED";
+        case GL_GREEN:                  return "GL_GREEN";
+        case GL_BLUE:                   return "GL_BLUE";
+        case GL_ALPHA:                  return "GL_ALPHA";
+        default:                        return "unknown argrep";
+    }
+}
+
+static const char *debug_op(GLuint op) {
+    switch(op) {
+        case GL_MOV_ATI:                return "GL_MOV_ATI";
+        case GL_ADD_ATI:                return "GL_ADD_ATI";
+        case GL_MUL_ATI:                return "GL_MUL_ATI";
+        case GL_SUB_ATI:                return "GL_SUB_ATI";
+        case GL_DOT3_ATI:               return "GL_DOT3_ATI";
+        case GL_DOT4_ATI:               return "GL_DOT4_ATI";
+        case GL_MAD_ATI:                return "GL_MAD_ATI";
+        case GL_LERP_ATI:               return "GL_LERP_ATI";
+        case GL_CND_ATI:                return "GL_CND_ATI";
+        case GL_CND0_ATI:               return "GL_CND0_ATI";
+        case GL_DOT2_ADD_ATI:           return "GL_DOT2_ADD_ATI";
+        default:                        return "unexpected op";
+    }
+}
+
+static const char *debug_mask(GLuint mask) {
+    switch(mask) {
+        case GL_NONE:                           return "GL_NONE";
+        case GL_RED_BIT_ATI:                    return "GL_RED_BIT_ATI";
+        case GL_GREEN_BIT_ATI:                  return "GL_GREEN_BIT_ATI";
+        case GL_BLUE_BIT_ATI:                   return "GL_BLUE_BIT_ATI";
+        case GL_RED_BIT_ATI | GL_GREEN_BIT_ATI: return "GL_RED_BIT_ATI | GL_GREEN_BIT_ATI";
+        case GL_RED_BIT_ATI | GL_BLUE_BIT_ATI:  return "GL_RED_BIT_ATI | GL_BLUE_BIT_ATI";
+        case GL_GREEN_BIT_ATI | GL_BLUE_BIT_ATI:return "GL_GREEN_BIT_ATI | GL_BLUE_BIT_ATI";
+        case GL_RED_BIT_ATI | GL_GREEN_BIT_ATI | GL_BLUE_BIT_ATI:return "GL_RED_BIT_ATI | GL_GREEN_BIT_ATI | GL_BLUE_BIT_ATI";
+        default:                                return "Unexpected writemask";
+    }
+}
+
+static void wrap_op1(const struct wined3d_gl_info *gl_info, GLuint op, GLuint dst, GLuint dstMask, GLuint dstMod,
+        GLuint arg1, GLuint arg1Rep, GLuint arg1Mod)
+{
+    if(dstMask == GL_ALPHA) {
+        TRACE("glAlphaFragmentOp1ATI(%s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst), debug_dstmod(dstMod),
+              debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod));
+        GL_EXTCALL(glAlphaFragmentOp1ATI(op, dst, dstMod, arg1, arg1Rep, arg1Mod));
+    } else {
+        TRACE("glColorFragmentOp1ATI(%s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst),
+              debug_mask(dstMask), debug_dstmod(dstMod),
+              debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod));
+        GL_EXTCALL(glColorFragmentOp1ATI(op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod));
+    }
+}
+
+static void wrap_op2(const struct wined3d_gl_info *gl_info, GLuint op, GLuint dst, GLuint dstMask, GLuint dstMod,
+        GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod)
+{
+    if(dstMask == GL_ALPHA) {
+        TRACE("glAlphaFragmentOp2ATI(%s, %s, %s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst), debug_dstmod(dstMod),
+              debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod),
+              debug_register(arg2), debug_rep(arg2Rep), debug_argmod(arg2Mod));
+        GL_EXTCALL(glAlphaFragmentOp2ATI(op, dst, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod));
+    } else {
+        TRACE("glColorFragmentOp2ATI(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst),
+              debug_mask(dstMask), debug_dstmod(dstMod),
+              debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod),
+              debug_register(arg2), debug_rep(arg2Rep), debug_argmod(arg2Mod));
+        GL_EXTCALL(glColorFragmentOp2ATI(op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod));
+    }
+}
+
+static void wrap_op3(const struct wined3d_gl_info *gl_info, GLuint op, GLuint dst, GLuint dstMask, GLuint dstMod,
+        GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod,
+        GLuint arg3, GLuint arg3Rep, GLuint arg3Mod)
+{
+    if(dstMask == GL_ALPHA) {
+        /* Leave some free space to fit "GL_NONE, " in to align most alpha and color op lines */
+        TRACE("glAlphaFragmentOp3ATI(%s, %s,          %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst), debug_dstmod(dstMod),
+              debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod),
+              debug_register(arg2), debug_rep(arg2Rep), debug_argmod(arg2Mod),
+              debug_register(arg3), debug_rep(arg3Rep), debug_argmod(arg3Mod));
+        GL_EXTCALL(glAlphaFragmentOp3ATI(op, dst, dstMod,
+                                         arg1, arg1Rep, arg1Mod,
+                                         arg2, arg2Rep, arg2Mod,
+                                         arg3, arg3Rep, arg3Mod));
+    } else {
+        TRACE("glColorFragmentOp3ATI(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst),
+              debug_mask(dstMask), debug_dstmod(dstMod),
+              debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod),
+              debug_register(arg2), debug_rep(arg2Rep), debug_argmod(arg2Mod),
+              debug_register(arg3), debug_rep(arg3Rep), debug_argmod(arg3Mod));
+        GL_EXTCALL(glColorFragmentOp3ATI(op, dst, dstMask, dstMod,
+                                         arg1, arg1Rep, arg1Mod,
+                                         arg2, arg2Rep, arg2Mod,
+                                         arg3, arg3Rep, arg3Mod));
+    }
+}
+
+static GLuint register_for_arg(DWORD arg, const struct wined3d_gl_info *gl_info,
+        unsigned int stage, GLuint *mod, GLuint *rep, GLuint tmparg)
+{
+    GLenum ret;
+
+    if(mod) *mod = GL_NONE;
+    if(arg == ARG_UNUSED)
+    {
+        if (rep) *rep = GL_NONE;
+        return -1; /* This is the marker for unused registers */
+    }
+
+    switch(arg & WINED3DTA_SELECTMASK) {
+        case WINED3DTA_DIFFUSE:
+            ret = GL_PRIMARY_COLOR;
+            break;
+
+        case WINED3DTA_CURRENT:
+            /* Note that using GL_REG_0_ATI for the passed on register is safe because
+             * texture0 is read at stage0, so in the worst case it is read in the
+             * instruction writing to reg0. Afterwards texture0 is not used any longer.
+             * If we're reading from current
+             */
+            ret = stage ? GL_REG_0_ATI : GL_PRIMARY_COLOR;
+            break;
+
+        case WINED3DTA_TEXTURE:
+            ret = GL_REG_0_ATI + stage;
+            break;
+
+        case WINED3DTA_TFACTOR:
+            ret = ATI_FFP_CONST_TFACTOR;
+            break;
+
+        case WINED3DTA_SPECULAR:
+            ret = GL_SECONDARY_INTERPOLATOR_ATI;
+            break;
+
+        case WINED3DTA_TEMP:
+            ret = tmparg;
+            break;
+
+        case WINED3DTA_CONSTANT:
+            FIXME("Unhandled source argument WINED3DTA_TEMP\n");
+            ret = GL_CON_0_ATI;
+            break;
+
+        default:
+            FIXME("Unknown source argument %d\n", arg);
+            ret = GL_ZERO;
+    }
+
+    if(arg & WINED3DTA_COMPLEMENT) {
+        if(mod) *mod |= GL_COMP_BIT_ATI;
+    }
+    if(arg & WINED3DTA_ALPHAREPLICATE) {
+        if(rep) *rep = GL_ALPHA;
+    } else {
+        if(rep) *rep = GL_NONE;
+    }
+    return ret;
+}
+
+static GLuint find_tmpreg(const struct texture_stage_op op[MAX_TEXTURES])
+{
+    int lowest_read = -1;
+    int lowest_write = -1;
+    int i;
+    BOOL tex_used[MAX_TEXTURES];
+
+    memset(tex_used, 0, sizeof(tex_used));
+    for (i = 0; i < MAX_TEXTURES; ++i)
+    {
+        if (op[i].cop == WINED3D_TOP_DISABLE)
+            break;
+
+        if(lowest_read == -1 &&
+          (op[i].carg1 == WINED3DTA_TEMP || op[i].carg2 == WINED3DTA_TEMP || op[i].carg0 == WINED3DTA_TEMP ||
+           op[i].aarg1 == WINED3DTA_TEMP || op[i].aarg2 == WINED3DTA_TEMP || op[i].aarg0 == WINED3DTA_TEMP)) {
+            lowest_read = i;
+        }
+
+        if(lowest_write == -1 && op[i].dst == tempreg) {
+            lowest_write = i;
+        }
+
+        if(op[i].carg1 == WINED3DTA_TEXTURE || op[i].carg2 == WINED3DTA_TEXTURE || op[i].carg0 == WINED3DTA_TEXTURE ||
+           op[i].aarg1 == WINED3DTA_TEXTURE || op[i].aarg2 == WINED3DTA_TEXTURE || op[i].aarg0 == WINED3DTA_TEXTURE) {
+            tex_used[i] = TRUE;
+        }
+    }
+
+    /* Temp reg not read? We don't need it, return GL_NONE */
+    if(lowest_read == -1) return GL_NONE;
+
+    if(lowest_write >= lowest_read) {
+        FIXME("Temp register read before being written\n");
+    }
+
+    if(lowest_write == -1) {
+        /* This needs a test. Maybe we are supposed to return 0.0/0.0/0.0/0.0, or fail drawprim, or whatever */
+        FIXME("Temp register read without being written\n");
+        return GL_REG_1_ATI;
+    } else if(lowest_write >= 1) {
+        /* If we're writing to the temp reg at earliest in stage 1, we can use register 1 for the temp result.
+         * there may be texture data stored in reg 1, but we do not need it any longer since stage 1 already
+         * read it
+         */
+        return GL_REG_1_ATI;
+    } else {
+        /* Search for a free texture register. We have 6 registers available. GL_REG_0_ATI is already used
+         * for the regular result
+         */
+        for(i = 1; i < 6; i++) {
+            if(!tex_used[i]) {
+                return GL_REG_0_ATI + i;
+            }
+        }
+        /* What to do here? Report it in ValidateDevice? */
+        FIXME("Could not find a register for the temporary register\n");
+        return 0;
+    }
+}
+
+static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], const struct wined3d_gl_info *gl_info)
+{
+    GLuint ret = GL_EXTCALL(glGenFragmentShadersATI(1));
+    unsigned int stage;
+    GLuint arg0, arg1, arg2, extrarg;
+    GLuint dstmod, argmod0, argmod1, argmod2, argmodextra;
+    GLuint rep0, rep1, rep2;
+    GLuint swizzle;
+    GLuint tmparg = find_tmpreg(op);
+    GLuint dstreg;
+
+    if(!ret) {
+        ERR("Failed to generate a GL_ATI_fragment_shader shader id\n");
+        return 0;
+    }
+    GL_EXTCALL(glBindFragmentShaderATI(ret));
+    checkGLcall("GL_EXTCALL(glBindFragmentShaderATI(ret))");
+
+    TRACE("glBeginFragmentShaderATI()\n");
+    GL_EXTCALL(glBeginFragmentShaderATI());
+    checkGLcall("GL_EXTCALL(glBeginFragmentShaderATI())");
+
+    /* Pass 1: Generate sampling instructions for perturbation maps */
+    for (stage = 0; stage < gl_info->limits.textures; ++stage)
+    {
+        if (op[stage].cop == WINED3D_TOP_DISABLE)
+            break;
+        if (op[stage].cop != WINED3D_TOP_BUMPENVMAP
+                && op[stage].cop != WINED3D_TOP_BUMPENVMAP_LUMINANCE)
+            continue;
+
+        TRACE("glSampleMapATI(GL_REG_%d_ATI, GL_TEXTURE_%d_ARB, GL_SWIZZLE_STR_ATI)\n",
+              stage, stage);
+        GL_EXTCALL(glSampleMapATI(GL_REG_0_ATI + stage,
+                   GL_TEXTURE0_ARB + stage,
+                   GL_SWIZZLE_STR_ATI));
+        if(op[stage + 1].projected == proj_none) {
+            swizzle = GL_SWIZZLE_STR_ATI;
+        } else if(op[stage + 1].projected == proj_count4) {
+            swizzle = GL_SWIZZLE_STQ_DQ_ATI;
+        } else {
+            swizzle = GL_SWIZZLE_STR_DR_ATI;
+        }
+        TRACE("glPassTexCoordATI(GL_REG_%d_ATI, GL_TEXTURE_%d_ARB, %s)\n",
+              stage + 1, stage + 1, debug_swizzle(swizzle));
+        GL_EXTCALL(glPassTexCoordATI(GL_REG_0_ATI + stage + 1,
+                   GL_TEXTURE0_ARB + stage + 1,
+                   swizzle));
+    }
+
+    /* Pass 2: Generate perturbation calculations */
+    for (stage = 0; stage < gl_info->limits.textures; ++stage)
+    {
+        GLuint argmodextra_x, argmodextra_y;
+        struct color_fixup_desc fixup;
+
+        if (op[stage].cop == WINED3D_TOP_DISABLE)
+            break;
+        if (op[stage].cop != WINED3D_TOP_BUMPENVMAP
+                && op[stage].cop != WINED3D_TOP_BUMPENVMAP_LUMINANCE)
+            continue;
+
+        fixup = op[stage].color_fixup;
+        if (fixup.x_source != CHANNEL_SOURCE_X || fixup.y_source != CHANNEL_SOURCE_Y)
+        {
+            FIXME("Swizzles not implemented\n");
+            argmodextra_x = GL_NONE;
+            argmodextra_y = GL_NONE;
+        }
+        else
+        {
+            /* Nice thing, we get the color correction for free :-) */
+            argmodextra_x = fixup.x_sign_fixup ? GL_2X_BIT_ATI | GL_BIAS_BIT_ATI : GL_NONE;
+            argmodextra_y = fixup.y_sign_fixup ? GL_2X_BIT_ATI | GL_BIAS_BIT_ATI : GL_NONE;
+        }
+
+        wrap_op3(gl_info, GL_DOT2_ADD_ATI, GL_REG_0_ATI + stage + 1, GL_RED_BIT_ATI, GL_NONE,
+                 GL_REG_0_ATI + stage, GL_NONE, argmodextra_x,
+                 ATI_FFP_CONST_BUMPMAT(stage), GL_NONE, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI,
+                 GL_REG_0_ATI + stage + 1, GL_RED, GL_NONE);
+
+        /* Don't use GL_DOT2_ADD_ATI here because we cannot configure it to read the blue and alpha
+         * component of the bump matrix. Instead do this with two MADs:
+         *
+         * coord.a = tex.r * bump.b + coord.g
+         * coord.g = tex.g * bump.a + coord.a
+         *
+         * The first instruction writes to alpha so it can be coissued with the above DOT2_ADD.
+         * coord.a is unused. If the perturbed texture is projected, this was already handled
+         * in the glPassTexCoordATI above.
+         */
+        wrap_op3(gl_info, GL_MAD_ATI, GL_REG_0_ATI + stage + 1, GL_ALPHA, GL_NONE,
+                 GL_REG_0_ATI + stage, GL_RED, argmodextra_y,
+                 ATI_FFP_CONST_BUMPMAT(stage), GL_BLUE, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI,
+                 GL_REG_0_ATI + stage + 1, GL_GREEN, GL_NONE);
+        wrap_op3(gl_info, GL_MAD_ATI, GL_REG_0_ATI + stage + 1, GL_GREEN_BIT_ATI, GL_NONE,
+                 GL_REG_0_ATI + stage, GL_GREEN, argmodextra_y,
+                 ATI_FFP_CONST_BUMPMAT(stage), GL_ALPHA, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI,
+                 GL_REG_0_ATI + stage + 1, GL_ALPHA, GL_NONE);
+    }
+
+    /* Pass 3: Generate sampling instructions for regular textures */
+    for (stage = 0; stage < gl_info->limits.textures; ++stage)
+    {
+        if (op[stage].cop == WINED3D_TOP_DISABLE)
+            break;
+
+        if(op[stage].projected == proj_none) {
+            swizzle = GL_SWIZZLE_STR_ATI;
+        } else if(op[stage].projected == proj_count3) {
+            swizzle = GL_SWIZZLE_STR_DR_ATI;
+        } else {
+            swizzle = GL_SWIZZLE_STQ_DQ_ATI;
+        }
+
+        if ((op[stage].carg0 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
+                || (op[stage].carg1 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
+                || (op[stage].carg2 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
+                || (op[stage].aarg0 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
+                || (op[stage].aarg1 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
+                || (op[stage].aarg2 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
+                || op[stage].cop == WINED3D_TOP_BLEND_TEXTURE_ALPHA)
+        {
+            if (stage > 0
+                    && (op[stage - 1].cop == WINED3D_TOP_BUMPENVMAP
+                    || op[stage - 1].cop == WINED3D_TOP_BUMPENVMAP_LUMINANCE))
+            {
+                TRACE("glSampleMapATI(GL_REG_%d_ATI, GL_REG_%d_ATI, GL_SWIZZLE_STR_ATI)\n",
+                      stage, stage);
+                GL_EXTCALL(glSampleMapATI(GL_REG_0_ATI + stage,
+                           GL_REG_0_ATI + stage,
+                           GL_SWIZZLE_STR_ATI));
+            } else {
+                TRACE("glSampleMapATI(GL_REG_%d_ATI, GL_TEXTURE_%d_ARB, %s)\n",
+                    stage, stage, debug_swizzle(swizzle));
+                GL_EXTCALL(glSampleMapATI(GL_REG_0_ATI + stage,
+                                        GL_TEXTURE0_ARB + stage,
+                                        swizzle));
+            }
+        }
+    }
+
+    /* Pass 4: Generate the arithmetic instructions */
+    for (stage = 0; stage < MAX_TEXTURES; ++stage)
+    {
+        if (op[stage].cop == WINED3D_TOP_DISABLE)
+        {
+            if (!stage)
+            {
+                /* Handle complete texture disabling gracefully */
+                wrap_op1(gl_info, GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
+                         GL_PRIMARY_COLOR, GL_NONE, GL_NONE);
+                wrap_op1(gl_info, GL_MOV_ATI, GL_REG_0_ATI, GL_ALPHA, GL_NONE,
+                         GL_PRIMARY_COLOR, GL_NONE, GL_NONE);
+            }
+            break;
+        }
+
+        if(op[stage].dst == tempreg) {
+            /* If we're writing to D3DTA_TEMP, but never reading from it we don't have to write there in the first place.
+             * skip the entire stage, this saves some GPU time
+             */
+            if(tmparg == GL_NONE) continue;
+
+            dstreg = tmparg;
+        } else {
+            dstreg = GL_REG_0_ATI;
+        }
+
+        arg0 = register_for_arg(op[stage].carg0, gl_info, stage, &argmod0, &rep0, tmparg);
+        arg1 = register_for_arg(op[stage].carg1, gl_info, stage, &argmod1, &rep1, tmparg);
+        arg2 = register_for_arg(op[stage].carg2, gl_info, stage, &argmod2, &rep2, tmparg);
+        dstmod = GL_NONE;
+        argmodextra = GL_NONE;
+        extrarg = GL_NONE;
+
+        switch (op[stage].cop)
+        {
+            case WINED3D_TOP_SELECT_ARG2:
+                arg1 = arg2;
+                argmod1 = argmod2;
+                rep1 = rep2;
+                /* fall through */
+            case WINED3D_TOP_SELECT_ARG1:
+                wrap_op1(gl_info, GL_MOV_ATI, dstreg, GL_NONE, GL_NONE,
+                         arg1, rep1, argmod1);
+                break;
+
+            case WINED3D_TOP_MODULATE_4X:
+                if(dstmod == GL_NONE) dstmod = GL_4X_BIT_ATI;
+                /* fall through */
+            case WINED3D_TOP_MODULATE_2X:
+                if(dstmod == GL_NONE) dstmod = GL_2X_BIT_ATI;
+                dstmod |= GL_SATURATE_BIT_ATI;
+                /* fall through */
+            case WINED3D_TOP_MODULATE:
+                wrap_op2(gl_info, GL_MUL_ATI, dstreg, GL_NONE, dstmod,
+                         arg1, rep1, argmod1,
+                         arg2, rep2, argmod2);
+                break;
+
+            case WINED3D_TOP_ADD_SIGNED_2X:
+                dstmod = GL_2X_BIT_ATI;
+                /* fall through */
+            case WINED3D_TOP_ADD_SIGNED:
+                argmodextra = GL_BIAS_BIT_ATI;
+                /* fall through */
+            case WINED3D_TOP_ADD:
+                dstmod |= GL_SATURATE_BIT_ATI;
+                wrap_op2(gl_info, GL_ADD_ATI, GL_REG_0_ATI, GL_NONE, dstmod,
+                         arg1, rep1, argmod1,
+                         arg2, rep2, argmodextra | argmod2);
+                break;
+
+            case WINED3D_TOP_SUBTRACT:
+                dstmod |= GL_SATURATE_BIT_ATI;
+                wrap_op2(gl_info, GL_SUB_ATI, dstreg, GL_NONE, dstmod,
+                         arg1, rep1, argmod1,
+                         arg2, rep2, argmod2);
+                break;
+
+            case WINED3D_TOP_ADD_SMOOTH:
+                argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
+                /* Dst = arg1 + * arg2(1 -arg 1)
+                 *     = arg2 * (1 - arg1) + arg1
+                 */
+                wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
+                         arg2, rep2, argmod2,
+                         arg1, rep1, argmodextra,
+                         arg1, rep1, argmod1);
+                break;
+
+            case WINED3D_TOP_BLEND_CURRENT_ALPHA:
+                if (extrarg == GL_NONE)
+                    extrarg = register_for_arg(WINED3DTA_CURRENT, gl_info, stage, NULL, NULL, -1);
+                /* fall through */
+            case WINED3D_TOP_BLEND_FACTOR_ALPHA:
+                if (extrarg == GL_NONE)
+                    extrarg = register_for_arg(WINED3DTA_TFACTOR, gl_info, stage, NULL, NULL, -1);
+                /* fall through */
+            case WINED3D_TOP_BLEND_TEXTURE_ALPHA:
+                if (extrarg == GL_NONE)
+                    extrarg = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1);
+                /* fall through */
+            case WINED3D_TOP_BLEND_DIFFUSE_ALPHA:
+                if (extrarg == GL_NONE)
+                    extrarg = register_for_arg(WINED3DTA_DIFFUSE, gl_info, stage, NULL, NULL, -1);
+                wrap_op3(gl_info, GL_LERP_ATI, dstreg, GL_NONE, GL_NONE,
+                         extrarg, GL_ALPHA, GL_NONE,
+                         arg1, rep1, argmod1,
+                         arg2, rep2, argmod2);
+                break;
+
+            case WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM:
+                arg0 = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1);
+                wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_NONE,
+                         arg2, rep2,  argmod2,
+                         arg0, GL_ALPHA, GL_COMP_BIT_ATI,
+                         arg1, rep1,  argmod1);
+                break;
+
+            /* D3DTOP_PREMODULATE ???? */
+
+            case WINED3D_TOP_MODULATE_INVALPHA_ADD_COLOR:
+                argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
+                /* fall through */
+            case WINED3D_TOP_MODULATE_ALPHA_ADD_COLOR:
+                if (!argmodextra)
+                    argmodextra = argmod1;
+                wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
+                         arg2, rep2,  argmod2,
+                         arg1, GL_ALPHA, argmodextra,
+                         arg1, rep1,  argmod1);
+                break;
+
+            case WINED3D_TOP_MODULATE_INVCOLOR_ADD_ALPHA:
+                argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
+                /* fall through */
+            case WINED3D_TOP_MODULATE_COLOR_ADD_ALPHA:
+                if (!argmodextra)
+                    argmodextra = argmod1;
+                wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
+                         arg2, rep2,  argmod2,
+                         arg1, rep1,  argmodextra,
+                         arg1, GL_ALPHA, argmod1);
+                break;
+
+            case WINED3D_TOP_DOTPRODUCT3:
+                wrap_op2(gl_info, GL_DOT3_ATI, dstreg, GL_NONE, GL_4X_BIT_ATI | GL_SATURATE_BIT_ATI,
+                         arg1, rep1, argmod1 | GL_BIAS_BIT_ATI,
+                         arg2, rep2, argmod2 | GL_BIAS_BIT_ATI);
+                break;
+
+            case WINED3D_TOP_MULTIPLY_ADD:
+                wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
+                         arg1, rep1, argmod1,
+                         arg2, rep2, argmod2,
+                         arg0, rep0, argmod0);
+                break;
+
+            case WINED3D_TOP_LERP:
+                wrap_op3(gl_info, GL_LERP_ATI, dstreg, GL_NONE, GL_NONE,
+                         arg0, rep0, argmod0,
+                         arg1, rep1, argmod1,
+                         arg2, rep2, argmod2);
+                break;
+
+            case WINED3D_TOP_BUMPENVMAP:
+            case WINED3D_TOP_BUMPENVMAP_LUMINANCE:
+                /* Those are handled in the first pass of the shader(generation pass 1 and 2) already */
+                break;
+
+            default: FIXME("Unhandled color operation %d on stage %d\n", op[stage].cop, stage);
+        }
+
+        arg0 = register_for_arg(op[stage].aarg0, gl_info, stage, &argmod0, NULL, tmparg);
+        arg1 = register_for_arg(op[stage].aarg1, gl_info, stage, &argmod1, NULL, tmparg);
+        arg2 = register_for_arg(op[stage].aarg2, gl_info, stage, &argmod2, NULL, tmparg);
+        dstmod = GL_NONE;
+        argmodextra = GL_NONE;
+        extrarg = GL_NONE;
+
+        switch (op[stage].aop)
+        {
+            case WINED3D_TOP_DISABLE:
+                /* Get the primary color to the output if on stage 0, otherwise leave register 0 untouched */
+                if (!stage)
+                {
+                    wrap_op1(gl_info, GL_MOV_ATI, GL_REG_0_ATI, GL_ALPHA, GL_NONE,
+                             GL_PRIMARY_COLOR, GL_NONE, GL_NONE);
+                }
+                break;
+
+            case WINED3D_TOP_SELECT_ARG2:
+                arg1 = arg2;
+                argmod1 = argmod2;
+                /* fall through */
+            case WINED3D_TOP_SELECT_ARG1:
+                wrap_op1(gl_info, GL_MOV_ATI, dstreg, GL_ALPHA, GL_NONE,
+                         arg1, GL_NONE, argmod1);
+                break;
+
+            case WINED3D_TOP_MODULATE_4X:
+                if (dstmod == GL_NONE)
+                    dstmod = GL_4X_BIT_ATI;
+                /* fall through */
+            case WINED3D_TOP_MODULATE_2X:
+                if (dstmod == GL_NONE)
+                    dstmod = GL_2X_BIT_ATI;
+                dstmod |= GL_SATURATE_BIT_ATI;
+                /* fall through */
+            case WINED3D_TOP_MODULATE:
+                wrap_op2(gl_info, GL_MUL_ATI, dstreg, GL_ALPHA, dstmod,
+                         arg1, GL_NONE, argmod1,
+                         arg2, GL_NONE, argmod2);
+                break;
+
+            case WINED3D_TOP_ADD_SIGNED_2X:
+                dstmod = GL_2X_BIT_ATI;
+                /* fall through */
+            case WINED3D_TOP_ADD_SIGNED:
+                argmodextra = GL_BIAS_BIT_ATI;
+                /* fall through */
+            case WINED3D_TOP_ADD:
+                dstmod |= GL_SATURATE_BIT_ATI;
+                wrap_op2(gl_info, GL_ADD_ATI, dstreg, GL_ALPHA, dstmod,
+                         arg1, GL_NONE, argmod1,
+                         arg2, GL_NONE, argmodextra | argmod2);
+                break;
+
+            case WINED3D_TOP_SUBTRACT:
+                dstmod |= GL_SATURATE_BIT_ATI;
+                wrap_op2(gl_info, GL_SUB_ATI, dstreg, GL_ALPHA, dstmod,
+                         arg1, GL_NONE, argmod1,
+                         arg2, GL_NONE, argmod2);
+                break;
+
+            case WINED3D_TOP_ADD_SMOOTH:
+                argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
+                /* Dst = arg1 + * arg2(1 -arg 1)
+                 *     = arg2 * (1 - arg1) + arg1
+                 */
+                wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_ALPHA, GL_SATURATE_BIT_ATI,
+                         arg2, GL_NONE, argmod2,
+                         arg1, GL_NONE, argmodextra,
+                         arg1, GL_NONE, argmod1);
+                break;
+
+            case WINED3D_TOP_BLEND_CURRENT_ALPHA:
+                if (extrarg == GL_NONE)
+                    extrarg = register_for_arg(WINED3DTA_CURRENT, gl_info, stage, NULL, NULL, -1);
+                /* fall through */
+            case WINED3D_TOP_BLEND_FACTOR_ALPHA:
+                if (extrarg == GL_NONE)
+                    extrarg = register_for_arg(WINED3DTA_TFACTOR, gl_info, stage, NULL, NULL, -1);
+                /* fall through */
+            case WINED3D_TOP_BLEND_TEXTURE_ALPHA:
+                if (extrarg == GL_NONE)
+                    extrarg = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1);
+                /* fall through */
+            case WINED3D_TOP_BLEND_DIFFUSE_ALPHA:
+                if (extrarg == GL_NONE)
+                    extrarg = register_for_arg(WINED3DTA_DIFFUSE, gl_info, stage, NULL, NULL, -1);
+                wrap_op3(gl_info, GL_LERP_ATI, dstreg, GL_ALPHA, GL_NONE,
+                         extrarg, GL_ALPHA, GL_NONE,
+                         arg1, GL_NONE, argmod1,
+                         arg2, GL_NONE, argmod2);
+                break;
+
+            case WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM:
+                arg0 = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1);
+                wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_ALPHA, GL_NONE,
+                         arg2, GL_NONE,  argmod2,
+                         arg0, GL_ALPHA, GL_COMP_BIT_ATI,
+                         arg1, GL_NONE,  argmod1);
+                break;
+
+            /* D3DTOP_PREMODULATE ???? */
+
+            case WINED3D_TOP_DOTPRODUCT3:
+                wrap_op2(gl_info, GL_DOT3_ATI, dstreg, GL_ALPHA, GL_4X_BIT_ATI | GL_SATURATE_BIT_ATI,
+                         arg1, GL_NONE, argmod1 | GL_BIAS_BIT_ATI,
+                         arg2, GL_NONE, argmod2 | GL_BIAS_BIT_ATI);
+                break;
+
+            case WINED3D_TOP_MULTIPLY_ADD:
+                wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_ALPHA, GL_SATURATE_BIT_ATI,
+                         arg1, GL_NONE, argmod1,
+                         arg2, GL_NONE, argmod2,
+                         arg0, GL_NONE, argmod0);
+                break;
+
+            case WINED3D_TOP_LERP:
+                wrap_op3(gl_info, GL_LERP_ATI, dstreg, GL_ALPHA, GL_SATURATE_BIT_ATI,
+                         arg1, GL_NONE, argmod1,
+                         arg2, GL_NONE, argmod2,
+                         arg0, GL_NONE, argmod0);
+                break;
+
+            case WINED3D_TOP_MODULATE_INVALPHA_ADD_COLOR:
+            case WINED3D_TOP_MODULATE_ALPHA_ADD_COLOR:
+            case WINED3D_TOP_MODULATE_COLOR_ADD_ALPHA:
+            case WINED3D_TOP_MODULATE_INVCOLOR_ADD_ALPHA:
+            case WINED3D_TOP_BUMPENVMAP:
+            case WINED3D_TOP_BUMPENVMAP_LUMINANCE:
+                ERR("Application uses an invalid alpha operation\n");
+                break;
+
+            default: FIXME("Unhandled alpha operation %d on stage %d\n", op[stage].aop, stage);
+        }
+    }
+
+    TRACE("glEndFragmentShaderATI()\n");
+    GL_EXTCALL(glEndFragmentShaderATI());
+    checkGLcall("GL_EXTCALL(glEndFragmentShaderATI())");
+    return ret;
+}
+
+static void set_tex_op_atifs(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_device *device = context->swapchain->device;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    const struct wined3d_d3d_info *d3d_info = context->d3d_info;
+    const struct atifs_ffp_desc *desc;
+    struct ffp_frag_settings settings;
+    struct atifs_private_data *priv = device->fragment_priv;
+    DWORD mapped_stage;
+    unsigned int i;
+
+    gen_ffp_frag_op(context, state, &settings, TRUE);
+    desc = (const struct atifs_ffp_desc *)find_ffp_frag_shader(&priv->fragment_shaders, &settings);
+    if(!desc) {
+        struct atifs_ffp_desc *new_desc = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_desc));
+        if (!new_desc)
+        {
+            ERR("Out of memory\n");
+            return;
+        }
+        new_desc->num_textures_used = 0;
+        for (i = 0; i < d3d_info->limits.ffp_blend_stages; ++i)
+        {
+            if (settings.op[i].cop == WINED3D_TOP_DISABLE)
+                break;
+            new_desc->num_textures_used = i + 1;
+        }
+
+        new_desc->parent.settings = settings;
+        new_desc->shader = gen_ati_shader(settings.op, gl_info);
+        add_ffp_frag_shader(&priv->fragment_shaders, &new_desc->parent);
+        TRACE("Allocated fixed function replacement shader descriptor %p\n", new_desc);
+        desc = new_desc;
+    }
+
+    /* GL_ATI_fragment_shader depends on the GL_TEXTURE_xD enable settings. Update the texture stages
+     * used by this shader
+     */
+    for (i = 0; i < desc->num_textures_used; ++i)
+    {
+        mapped_stage = device->texUnitMap[i];
+        if (mapped_stage != WINED3D_UNMAPPED_STAGE)
+        {
+            context_active_texture(context, gl_info, mapped_stage);
+            texture_activate_dimensions(state->textures[i], gl_info);
+        }
+    }
+
+    GL_EXTCALL(glBindFragmentShaderATI(desc->shader));
+}
+
+static void state_texfactor_atifs(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    float col[4];
+
+    D3DCOLORTOGLFLOAT4(state->render_states[WINED3D_RS_TEXTUREFACTOR], col);
+    GL_EXTCALL(glSetFragmentShaderConstantATI(ATI_FFP_CONST_TFACTOR, col));
+    checkGLcall("glSetFragmentShaderConstantATI(ATI_FFP_CONST_TFACTOR, col)");
+}
+
+static void set_bumpmat(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    float mat[2][2];
+
+    mat[0][0] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_MAT00]);
+    mat[1][0] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_MAT01]);
+    mat[0][1] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_MAT10]);
+    mat[1][1] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_MAT11]);
+    /* GL_ATI_fragment_shader allows only constants from 0.0 to 1.0, but the bumpmat
+     * constants can be in any range. While they should stay between [-1.0 and 1.0] because
+     * Shader Model 1.x pixel shaders are clamped to that range negative values are used occasionally,
+     * for example by our d3d9 test. So to get negative values scale -1;1 to 0;1 and undo that in the
+     * shader(it is free). This might potentially reduce precision. However, if the hardware does
+     * support proper floats it shouldn't, and if it doesn't we can't get anything better anyway
+     */
+    mat[0][0] = (mat[0][0] + 1.0f) * 0.5f;
+    mat[1][0] = (mat[1][0] + 1.0f) * 0.5f;
+    mat[0][1] = (mat[0][1] + 1.0f) * 0.5f;
+    mat[1][1] = (mat[1][1] + 1.0f) * 0.5f;
+    GL_EXTCALL(glSetFragmentShaderConstantATI(ATI_FFP_CONST_BUMPMAT(stage), (float *) mat));
+    checkGLcall("glSetFragmentShaderConstantATI(ATI_FFP_CONST_BUMPMAT(stage), mat)");
+}
+
+static void textransform(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    if (!isStateDirty(context, STATE_PIXELSHADER))
+        set_tex_op_atifs(context, state, state_id);
+}
+
+static void atifs_apply_pixelshader(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    context->last_was_pshader = use_ps(state);
+    /* The ATIFS code does not support pixel shaders currently, but we have to
+     * provide a state handler to call shader_select to select a vertex shader
+     * if one is applied because the vertex shader state may defer calling the
+     * shader backend if the pshader state is dirty.
+     *
+     * In theory the application should not be able to mark the pixel shader
+     * dirty because it cannot create a shader, and thus has no way to set the
+     * state to something != NULL. However, a different pipeline part may link
+     * a different state to its pixelshader handler, thus a pshader state
+     * exists and can be dirtified. Also the pshader is always dirtified at
+     * startup, and blitting disables all shaders and dirtifies all shader
+     * states. If atifs can deal with this it keeps the rest of the code
+     * simpler. */
+    context->select_shader = 1;
+    context->load_constants = 1;
+}
+
+static void atifs_srgbwriteenable(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    if (state->render_states[WINED3D_RS_SRGBWRITEENABLE])
+        WARN("sRGB writes are not supported by this fragment pipe.\n");
+}
+
+static const struct StateEntryTemplate atifs_fragmentstate_template[] = {
+    {STATE_RENDER(WINED3D_RS_TEXTUREFACTOR),              { STATE_RENDER(WINED3D_RS_TEXTUREFACTOR),             state_texfactor_atifs   }, WINED3D_GL_EXT_NONE             },
+    {STATE_RENDER(WINED3D_RS_FOGCOLOR),                   { STATE_RENDER(WINED3D_RS_FOGCOLOR),                  state_fogcolor          }, WINED3D_GL_EXT_NONE             },
+    {STATE_RENDER(WINED3D_RS_FOGDENSITY),                 { STATE_RENDER(WINED3D_RS_FOGDENSITY),                state_fogdensity        }, WINED3D_GL_EXT_NONE             },
+    {STATE_RENDER(WINED3D_RS_FOGENABLE),                  { STATE_RENDER(WINED3D_RS_FOGENABLE),                 state_fog_fragpart      }, WINED3D_GL_EXT_NONE             },
+    {STATE_RENDER(WINED3D_RS_FOGTABLEMODE),               { STATE_RENDER(WINED3D_RS_FOGENABLE),                 NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_RENDER(WINED3D_RS_FOGVERTEXMODE),              { STATE_RENDER(WINED3D_RS_FOGENABLE),                 NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_RENDER(WINED3D_RS_FOGSTART),                   { STATE_RENDER(WINED3D_RS_FOGSTART),                  state_fogstartend       }, WINED3D_GL_EXT_NONE             },
+    {STATE_RENDER(WINED3D_RS_FOGEND),                     { STATE_RENDER(WINED3D_RS_FOGSTART),                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE),            { STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE),           atifs_srgbwriteenable   }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),         { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        set_tex_op_atifs        }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG1),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG2),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG0),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_OP),         { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG1),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG2),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG0),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_RESULT_ARG),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   set_bumpmat             }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT01),    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT10),    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT11),    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_OP),         { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG1),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG2),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG0),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_OP),         { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG1),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG2),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG0),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_RESULT_ARG),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   set_bumpmat             }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT01),    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT10),    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT11),    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_OP),         { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG1),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG2),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG0),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_OP),         { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG1),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG2),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG0),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_RESULT_ARG),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   set_bumpmat             }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT01),    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT10),    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT11),    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_OP),         { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG1),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG2),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG0),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_OP),         { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG1),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG2),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG0),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_RESULT_ARG),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   set_bumpmat             }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT01),    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT10),    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT11),    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_OP),         { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG1),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG2),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG0),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_OP),         { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG1),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG2),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG0),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_RESULT_ARG),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   set_bumpmat             }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT01),    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT10),    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT11),    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_OP),         { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG1),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG2),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG0),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_OP),         { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG1),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG2),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG0),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_RESULT_ARG),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   set_bumpmat             }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT01),    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT10),    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT11),    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_OP),         { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG1),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG2),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG0),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_OP),         { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG1),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG2),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG0),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_RESULT_ARG),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   set_bumpmat             }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT01),    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT10),    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT11),    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_OP),         { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG1),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG2),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG0),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_OP),         { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG1),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG2),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG0),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_RESULT_ARG),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   set_bumpmat             }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT01),    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT10),    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT11),    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(0),                                   { STATE_SAMPLER(0),                                   sampler_texdim          }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(1),                                   { STATE_SAMPLER(1),                                   sampler_texdim          }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(2),                                   { STATE_SAMPLER(2),                                   sampler_texdim          }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(3),                                   { STATE_SAMPLER(3),                                   sampler_texdim          }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(4),                                   { STATE_SAMPLER(4),                                   sampler_texdim          }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(5),                                   { STATE_SAMPLER(5),                                   sampler_texdim          }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(6),                                   { STATE_SAMPLER(6),                                   sampler_texdim          }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(7),                                   { STATE_SAMPLER(7),                                   sampler_texdim          }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
+    {STATE_PIXELSHADER,                                   { STATE_PIXELSHADER,                                  atifs_apply_pixelshader }, WINED3D_GL_EXT_NONE             },
+    {0 /* Terminate */,                                   { 0,                                                  0                       }, WINED3D_GL_EXT_NONE             },
+};
+
+/* Context activation is done by the caller. */
+static void atifs_enable(const struct wined3d_gl_info *gl_info, BOOL enable)
+{
+    if (enable)
+    {
+        gl_info->gl_ops.gl.p_glEnable(GL_FRAGMENT_SHADER_ATI);
+        checkGLcall("glEnable(GL_FRAGMENT_SHADER_ATI)");
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_FRAGMENT_SHADER_ATI);
+        checkGLcall("glDisable(GL_FRAGMENT_SHADER_ATI)");
+    }
+}
+
+static void atifs_get_caps(const struct wined3d_gl_info *gl_info, struct fragment_caps *caps)
+{
+    caps->wined3d_caps = WINED3D_FRAGMENT_CAP_PROJ_CONTROL;
+    caps->PrimitiveMiscCaps = WINED3DPMISCCAPS_TSSARGTEMP;
+    caps->TextureOpCaps =  WINED3DTEXOPCAPS_DISABLE                     |
+                           WINED3DTEXOPCAPS_SELECTARG1                  |
+                           WINED3DTEXOPCAPS_SELECTARG2                  |
+                           WINED3DTEXOPCAPS_MODULATE4X                  |
+                           WINED3DTEXOPCAPS_MODULATE2X                  |
+                           WINED3DTEXOPCAPS_MODULATE                    |
+                           WINED3DTEXOPCAPS_ADDSIGNED2X                 |
+                           WINED3DTEXOPCAPS_ADDSIGNED                   |
+                           WINED3DTEXOPCAPS_ADD                         |
+                           WINED3DTEXOPCAPS_SUBTRACT                    |
+                           WINED3DTEXOPCAPS_ADDSMOOTH                   |
+                           WINED3DTEXOPCAPS_BLENDCURRENTALPHA           |
+                           WINED3DTEXOPCAPS_BLENDFACTORALPHA            |
+                           WINED3DTEXOPCAPS_BLENDTEXTUREALPHA           |
+                           WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA           |
+                           WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM         |
+                           WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR      |
+                           WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA      |
+                           WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA   |
+                           WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR   |
+                           WINED3DTEXOPCAPS_DOTPRODUCT3                 |
+                           WINED3DTEXOPCAPS_MULTIPLYADD                 |
+                           WINED3DTEXOPCAPS_LERP                        |
+                           WINED3DTEXOPCAPS_BUMPENVMAP;
+
+    /* TODO: Implement WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
+    and WINED3DTEXOPCAPS_PREMODULATE */
+
+    /* GL_ATI_fragment_shader always supports 6 textures, which was the limit on r200 cards
+     * which this extension is exclusively focused on(later cards have GL_ARB_fragment_program).
+     * If the current card has more than 8 fixed function textures in OpenGL's regular fixed
+     * function pipeline then the ATI_fragment_shader backend imposes a stricter limit. This
+     * shouldn't be too hard since Nvidia cards have a limit of 4 textures with the default ffp
+     * pipeline, and almost all games are happy with that. We can however support up to 8
+     * texture stages because we have a 2nd pass limit of 8 instructions, and per stage we use
+     * only 1 instruction.
+     *
+     * The proper fix for this is not to use GL_ATI_fragment_shader on cards newer than the
+     * r200 series and use an ARB or GLSL shader instead
+     */
+    caps->MaxTextureBlendStages   = 8;
+    caps->MaxSimultaneousTextures = 6;
+}
+
+static void *atifs_alloc(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv)
+{
+    struct atifs_private_data *priv;
+
+    if (!(priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*priv))))
+        return NULL;
+
+    if (wine_rb_init(&priv->fragment_shaders, &wined3d_ffp_frag_program_rb_functions) == -1)
+    {
+        ERR("Failed to initialize rbtree.\n");
+        HeapFree(GetProcessHeap(), 0, priv);
+        return NULL;
+    }
+
+    return priv;
+}
+
+/* Context activation is done by the caller. */
+static void atifs_free_ffpshader(struct wine_rb_entry *entry, void *cb_ctx)
+{
+    const struct wined3d_gl_info *gl_info = cb_ctx;
+    struct atifs_ffp_desc *entry_ati = WINE_RB_ENTRY_VALUE(entry, struct atifs_ffp_desc, parent.entry);
+
+    GL_EXTCALL(glDeleteFragmentShaderATI(entry_ati->shader));
+    checkGLcall("glDeleteFragmentShaderATI(entry->shader)");
+    HeapFree(GetProcessHeap(), 0, entry_ati);
+}
+
+/* Context activation is done by the caller. */
+static void atifs_free(struct wined3d_device *device)
+{
+    struct atifs_private_data *priv = device->fragment_priv;
+
+    wine_rb_destroy(&priv->fragment_shaders, atifs_free_ffpshader, &device->adapter->gl_info);
+
+    HeapFree(GetProcessHeap(), 0, priv);
+    device->fragment_priv = NULL;
+}
+
+static BOOL atifs_color_fixup_supported(struct color_fixup_desc fixup)
+{
+    if (TRACE_ON(d3d_shader) && TRACE_ON(d3d))
+    {
+        TRACE("Checking support for fixup:\n");
+        dump_color_fixup_desc(fixup);
+    }
+
+    /* We only support sign fixup of the first two channels. */
+    if (fixup.x_source == CHANNEL_SOURCE_X && fixup.y_source == CHANNEL_SOURCE_Y
+            && fixup.z_source == CHANNEL_SOURCE_Z && fixup.w_source == CHANNEL_SOURCE_W
+            && !fixup.z_sign_fixup && !fixup.w_sign_fixup)
+    {
+        TRACE("[OK]\n");
+        return TRUE;
+    }
+
+    TRACE("[FAILED]\n");
+    return FALSE;
+}
+
+const struct fragment_pipeline atifs_fragment_pipeline = {
+    atifs_enable,
+    atifs_get_caps,
+    atifs_alloc,
+    atifs_free,
+    atifs_color_fixup_supported,
+    atifs_fragmentstate_template,
+};
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/buffer.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/buffer.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/buffer.c	(revision 46521)
@@ -0,0 +1,1547 @@
+/*
+ * Copyright 2002-2005 Jason Edmeades
+ * Copyright 2002-2005 Raphael Junqueira
+ * Copyright 2004 Christian Costa
+ * Copyright 2005 Oliver Stieber
+ * Copyright 2007-2010 Stefan Dösinger for CodeWeavers
+ * Copyright 2009-2010 Henri Verbeet for CodeWeavers
+ *
+ * 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 "wined3d_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d);
+
+#define VB_MAXDECLCHANGES     100     /* After that number of decl changes we stop converting */
+#define VB_RESETDECLCHANGE    1000    /* Reset the decl changecount after that number of draws */
+#define VB_MAXFULLCONVERSIONS 5       /* Number of full conversions before we stop converting */
+#define VB_RESETFULLCONVS     20      /* Reset full conversion counts after that number of draws */
+
+static inline BOOL buffer_add_dirty_area(struct wined3d_buffer *This, UINT offset, UINT size)
+{
+    if (!This->buffer_object) return TRUE;
+
+    if (This->maps_size <= This->modified_areas)
+    {
+        void *new = HeapReAlloc(GetProcessHeap(), 0, This->maps,
+                                This->maps_size * 2 * sizeof(*This->maps));
+        if (!new)
+        {
+            ERR("Out of memory\n");
+            return FALSE;
+        }
+        else
+        {
+            This->maps = new;
+            This->maps_size *= 2;
+        }
+    }
+
+    if(offset > This->resource.size || offset + size > This->resource.size)
+    {
+        WARN("Invalid range dirtified, marking entire buffer dirty\n");
+        offset = 0;
+        size = This->resource.size;
+    }
+    else if(!offset && !size)
+    {
+        size = This->resource.size;
+    }
+
+    This->maps[This->modified_areas].offset = offset;
+    This->maps[This->modified_areas].size = size;
+    This->modified_areas++;
+    return TRUE;
+}
+
+static inline void buffer_clear_dirty_areas(struct wined3d_buffer *This)
+{
+    This->modified_areas = 0;
+}
+
+static BOOL buffer_is_dirty(const struct wined3d_buffer *buffer)
+{
+    return !!buffer->modified_areas;
+}
+
+static BOOL buffer_is_fully_dirty(const struct wined3d_buffer *buffer)
+{
+    unsigned int i;
+
+    for (i = 0; i < buffer->modified_areas; ++i)
+    {
+        if (!buffer->maps[i].offset && buffer->maps[i].size == buffer->resource.size)
+            return TRUE;
+    }
+    return FALSE;
+}
+
+/* Context activation is done by the caller */
+static void delete_gl_buffer(struct wined3d_buffer *This, const struct wined3d_gl_info *gl_info)
+{
+    if(!This->buffer_object) return;
+
+    GL_EXTCALL(glDeleteBuffersARB(1, &This->buffer_object));
+    checkGLcall("glDeleteBuffersARB");
+    This->buffer_object = 0;
+
+    if(This->query)
+    {
+        wined3d_event_query_destroy(This->query);
+        This->query = NULL;
+    }
+    This->flags &= ~WINED3D_BUFFER_APPLESYNC;
+}
+
+/* Context activation is done by the caller. */
+static void buffer_create_buffer_object(struct wined3d_buffer *This, const struct wined3d_gl_info *gl_info)
+{
+    GLenum gl_usage = GL_STATIC_DRAW_ARB;
+    GLenum error;
+
+    TRACE("Creating an OpenGL vertex buffer object for wined3d_buffer %p with usage %s.\n",
+            This, debug_d3dusage(This->resource.usage));
+
+    /* Make sure that the gl error is cleared. Do not use checkGLcall
+    * here because checkGLcall just prints a fixme and continues. However,
+    * if an error during VBO creation occurs we can fall back to non-vbo operation
+    * with full functionality(but performance loss)
+    */
+    while (gl_info->gl_ops.gl.p_glGetError() != GL_NO_ERROR);
+
+    /* Basically the FVF parameter passed to CreateVertexBuffer is no good.
+     * The vertex declaration from the device determines how the data in the
+     * buffer is interpreted. This means that on each draw call the buffer has
+     * to be verified to check if the rhw and color values are in the correct
+     * format. */
+
+    GL_EXTCALL(glGenBuffersARB(1, &This->buffer_object));
+    error = gl_info->gl_ops.gl.p_glGetError();
+    if (!This->buffer_object || error != GL_NO_ERROR)
+    {
+        ERR("Failed to create a VBO with error %s (%#x)\n", debug_glerror(error), error);
+        goto fail;
+    }
+
+    if (This->buffer_type_hint == GL_ELEMENT_ARRAY_BUFFER_ARB)
+        device_invalidate_state(This->resource.device, STATE_INDEXBUFFER);
+    GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object));
+    error = gl_info->gl_ops.gl.p_glGetError();
+    if (error != GL_NO_ERROR)
+    {
+        ERR("Failed to bind the VBO with error %s (%#x)\n", debug_glerror(error), error);
+        goto fail;
+    }
+
+    if (This->resource.usage & WINED3DUSAGE_DYNAMIC)
+    {
+        TRACE("Buffer has WINED3DUSAGE_DYNAMIC set.\n");
+        gl_usage = GL_STREAM_DRAW_ARB;
+
+        if(gl_info->supported[APPLE_FLUSH_BUFFER_RANGE])
+        {
+            GL_EXTCALL(glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE));
+            checkGLcall("glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE)");
+            This->flags |= WINED3D_BUFFER_FLUSH;
+
+            GL_EXTCALL(glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE));
+            checkGLcall("glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE)");
+            This->flags |= WINED3D_BUFFER_APPLESYNC;
+        }
+        /* No setup is needed here for GL_ARB_map_buffer_range */
+    }
+
+    /* Reserve memory for the buffer. The amount of data won't change
+     * so we are safe with calling glBufferData once and
+     * calling glBufferSubData on updates. Upload the actual data in case
+     * we're not double buffering, so we can release the heap mem afterwards
+     */
+    GL_EXTCALL(glBufferDataARB(This->buffer_type_hint, This->resource.size, This->resource.allocatedMemory, gl_usage));
+    error = gl_info->gl_ops.gl.p_glGetError();
+    if (error != GL_NO_ERROR)
+    {
+        ERR("glBufferDataARB failed with error %s (%#x)\n", debug_glerror(error), error);
+        goto fail;
+    }
+
+    This->buffer_object_size = This->resource.size;
+    This->buffer_object_usage = gl_usage;
+
+    if(This->flags & WINED3D_BUFFER_DOUBLEBUFFER)
+    {
+        if(!buffer_add_dirty_area(This, 0, 0))
+        {
+            ERR("buffer_add_dirty_area failed, this is not expected\n");
+            goto fail;
+        }
+    }
+    else
+    {
+        HeapFree(GetProcessHeap(), 0, This->resource.heapMemory);
+        This->resource.allocatedMemory = NULL;
+        This->resource.heapMemory = NULL;
+    }
+
+    return;
+
+fail:
+    /* Clean up all vbo init, but continue because we can work without a vbo :-) */
+    ERR("Failed to create a vertex buffer object. Continuing, but performance issues may occur\n");
+    delete_gl_buffer(This, gl_info);
+    buffer_clear_dirty_areas(This);
+}
+
+static BOOL buffer_process_converted_attribute(struct wined3d_buffer *This,
+        const enum wined3d_buffer_conversion_type conversion_type,
+        const struct wined3d_stream_info_element *attrib, DWORD *stride_this_run
+#ifdef VBOX_WITH_WINE_FIX_BUFOFFSET
+        , DWORD *offset_this_run
+#endif
+        )
+{
+    DWORD attrib_size;
+    BOOL ret = FALSE;
+    unsigned int i;
+#ifndef VBOX_WITH_WINE_FIX_BUFOFFSET
+    DWORD_PTR data;
+#else
+    UINT stream_offset = (UINT)(attrib->data.addr - attrib->offset);
+#endif
+
+    /* Check for some valid situations which cause us pain. One is if the buffer is used for
+     * constant attributes(stride = 0), the other one is if the buffer is used on two streams
+     * with different strides. In the 2nd case we might have to drop conversion entirely,
+     * it is possible that the same bytes are once read as FLOAT2 and once as UBYTE4N.
+     */
+    if (!attrib->stride)
+    {
+        FIXME("%s used with stride 0, let's hope we get the vertex stride from somewhere else\n",
+                debug_d3dformat(attrib->format->id));
+    }
+#ifndef VBOX_WITH_WINE_FIX_BUFOFFSET
+    else if(attrib->stride != *stride_this_run && *stride_this_run)
+    {
+        FIXME("Got two concurrent strides, %d and %d\n", attrib->stride, *stride_this_run);
+    }
+#else
+    else if((attrib->stride != *stride_this_run && *stride_this_run)
+            || (stream_offset != *offset_this_run && *offset_this_run))
+    {
+        ERR("Got two concurrent strides, %d and %d\n", attrib->stride, *stride_this_run);
+    }
+#endif
+    else
+    {
+        *stride_this_run = attrib->stride;
+#ifdef VBOX_WITH_WINE_FIX_BUFOFFSET
+        *offset_this_run = stream_offset;
+        if (This->stride != *stride_this_run
+                || This->offset != *offset_this_run)
+#else
+        if (This->stride != *stride_this_run)
+#endif
+        {
+            /* We rely that this happens only on the first converted attribute that is found,
+             * if at all. See above check
+             */
+            TRACE("Reconverting because converted attributes occur, and the stride changed\n");
+            This->stride = *stride_this_run;
+#ifdef VBOX_WITH_WINE_FIX_BUFOFFSET
+            This->offset = *offset_this_run;
+#endif
+            HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, This->conversion_map);
+            This->conversion_map = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+                    sizeof(*This->conversion_map) * This->stride);
+            ret = TRUE;
+        }
+    }
+
+#ifndef VBOX_WITH_WINE_FIX_BUFOFFSET
+    data = ((DWORD_PTR)attrib->data.addr) % This->stride;
+#endif
+    attrib_size = attrib->format->component_count * attrib->format->component_size;
+    for (i = 0; i < attrib_size; ++i)
+    {
+#ifndef VBOX_WITH_WINE_FIX_BUFOFFSET
+        DWORD_PTR idx = (data + i) % This->stride;
+#else
+        DWORD_PTR idx = attrib->offset;
+#endif
+        if (This->conversion_map[idx] != conversion_type)
+        {
+            TRACE("Byte %ld in vertex changed\n", idx);
+            TRACE("It was type %d, is %d now\n", This->conversion_map[idx], conversion_type);
+            ret = TRUE;
+            This->conversion_map[idx] = conversion_type;
+        }
+    }
+
+    return ret;
+}
+
+static BOOL buffer_check_attribute(struct wined3d_buffer *This, const struct wined3d_stream_info *si,
+        UINT attrib_idx, const BOOL check_d3dcolor, const BOOL is_ffp_position, const BOOL is_ffp_color,
+        DWORD *stride_this_run
+#ifdef VBOX_WITH_WINE_FIX_BUFOFFSET
+        , DWORD *offset_this_run
+#endif
+        )
+{
+    const struct wined3d_stream_info_element *attrib = &si->elements[attrib_idx];
+    enum wined3d_format_id format;
+    BOOL ret = FALSE;
+
+    /* Ignore attributes that do not have our vbo. After that check we can be sure that the attribute is
+     * there, on nonexistent attribs the vbo is 0.
+     */
+    if (!(si->use_map & (1 << attrib_idx))
+            || attrib->data.buffer_object != This->buffer_object)
+        return FALSE;
+
+    format = attrib->format->id;
+    /* Look for newly appeared conversion */
+    if (check_d3dcolor && format == WINED3DFMT_B8G8R8A8_UNORM)
+    {
+        ret = buffer_process_converted_attribute(This, CONV_D3DCOLOR, attrib, stride_this_run
+#ifdef VBOX_WITH_WINE_FIX_BUFOFFSET
+                , offset_this_run
+#endif
+                );
+
+        if (!is_ffp_color) FIXME("Test for non-color fixed function WINED3DFMT_B8G8R8A8_UNORM format\n");
+    }
+    else if (is_ffp_position && si->position_transformed)
+    {
+        if (format != WINED3DFMT_R32G32B32A32_FLOAT)
+        {
+            FIXME("Unexpected format %s for transformed position.\n", debug_d3dformat(format));
+            return FALSE;
+        }
+
+        ret = buffer_process_converted_attribute(This, CONV_POSITIONT, attrib, stride_this_run
+#ifdef VBOX_WITH_WINE_FIX_BUFOFFSET
+                , offset_this_run
+#endif
+                );
+    }
+    else if (This->conversion_map)
+    {
+        ret = buffer_process_converted_attribute(This, CONV_NONE, attrib, stride_this_run
+#ifdef VBOX_WITH_WINE_FIX_BUFOFFSET
+                , offset_this_run
+#endif
+                );
+    }
+
+    return ret;
+}
+
+static BOOL buffer_find_decl(struct wined3d_buffer *This)
+{
+    struct wined3d_device *device = This->resource.device;
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    const struct wined3d_stream_info *si = &device->stream_info;
+    const struct wined3d_state *state = &device->stateBlock->state;
+    UINT stride_this_run = 0;
+#ifdef VBOX_WITH_WINE_FIX_BUFOFFSET
+    UINT offset_this_run = 0;
+#endif
+    BOOL ret = FALSE;
+    BOOL support_d3dcolor = gl_info->supported[ARB_VERTEX_ARRAY_BGRA];
+
+    /* In d3d7 the vertex buffer declaration NEVER changes because it is stored in the d3d7 vertex buffer.
+     * Once we have our declaration there is no need to look it up again. Index buffers also never need
+     * conversion, so once the (empty) conversion structure is created don't bother checking again
+     */
+    if (This->flags & WINED3D_BUFFER_HASDESC)
+    {
+        if(This->resource.usage & WINED3DUSAGE_STATICDECL) return FALSE;
+    }
+
+    if (use_vs(state))
+    {
+        TRACE("Vertex shaders used, no VBO conversion is needed\n");
+        if(This->conversion_map)
+        {
+            HeapFree(GetProcessHeap(), 0, This->conversion_map);
+            This->conversion_map = NULL;
+            This->stride = 0;
+            return TRUE;
+        }
+
+        return FALSE;
+    }
+
+    TRACE("Finding vertex buffer conversion information\n");
+    /* Certain declaration types need some fixups before we can pass them to
+     * opengl. This means D3DCOLOR attributes with fixed function vertex
+     * processing, FLOAT4 POSITIONT with fixed function, and FLOAT16 if
+     * GL_ARB_half_float_vertex is not supported.
+     *
+     * Note for d3d8 and d3d9:
+     * The vertex buffer FVF doesn't help with finding them, we have to use
+     * the decoded vertex declaration and pick the things that concern the
+     * current buffer. A problem with this is that this can change between
+     * draws, so we have to validate the information and reprocess the buffer
+     * if it changes, and avoid false positives for performance reasons.
+     * WineD3D doesn't even know the vertex buffer any more, it is managed
+     * by the client libraries and passed to SetStreamSource and ProcessVertices
+     * as needed.
+     *
+     * We have to distinguish between vertex shaders and fixed function to
+     * pick the way we access the strided vertex information.
+     *
+     * This code sets up a per-byte array with the size of the detected
+     * stride of the arrays in the buffer. For each byte we have a field
+     * that marks the conversion needed on this byte. For example, the
+     * following declaration with fixed function vertex processing:
+     *
+     *      POSITIONT, FLOAT4
+     *      NORMAL, FLOAT3
+     *      DIFFUSE, FLOAT16_4
+     *      SPECULAR, D3DCOLOR
+     *
+     * Will result in
+     * {                 POSITIONT                    }{             NORMAL                }{    DIFFUSE          }{SPECULAR }
+     * [P][P][P][P][P][P][P][P][P][P][P][P][P][P][P][P][0][0][0][0][0][0][0][0][0][0][0][0][F][F][F][F][F][F][F][F][C][C][C][C]
+     *
+     * Where in this example map P means 4 component position conversion, 0
+     * means no conversion, F means FLOAT16_2 conversion and C means D3DCOLOR
+     * conversion (red / blue swizzle).
+     *
+     * If we're doing conversion and the stride changes we have to reconvert
+     * the whole buffer. Note that we do not mind if the semantic changes,
+     * we only care for the conversion type. So if the NORMAL is replaced
+     * with a TEXCOORD, nothing has to be done, or if the DIFFUSE is replaced
+     * with a D3DCOLOR BLENDWEIGHT we can happily dismiss the change. Some
+     * conversion types depend on the semantic as well, for example a FLOAT4
+     * texcoord needs no conversion while a FLOAT4 positiont needs one
+     */
+
+    ret = buffer_check_attribute(This, si, WINED3D_FFP_POSITION,
+            TRUE, TRUE,  FALSE, &stride_this_run
+#ifdef VBOX_WITH_WINE_FIX_BUFOFFSET
+                , &offset_this_run
+#endif
+            ) || ret;
+    ret = buffer_check_attribute(This, si, WINED3D_FFP_NORMAL,
+            TRUE, FALSE, FALSE, &stride_this_run
+#ifdef VBOX_WITH_WINE_FIX_BUFOFFSET
+                , &offset_this_run
+#endif
+            ) || ret;
+    ret = buffer_check_attribute(This, si, WINED3D_FFP_DIFFUSE,
+            !support_d3dcolor, FALSE, TRUE,  &stride_this_run
+#ifdef VBOX_WITH_WINE_FIX_BUFOFFSET
+                , &offset_this_run
+#endif
+            ) || ret;
+    ret = buffer_check_attribute(This, si, WINED3D_FFP_SPECULAR,
+            !support_d3dcolor, FALSE, TRUE,  &stride_this_run
+#ifdef VBOX_WITH_WINE_FIX_BUFOFFSET
+                , &offset_this_run
+#endif
+            ) || ret;
+    ret = buffer_check_attribute(This, si, WINED3D_FFP_TEXCOORD0,
+            TRUE, FALSE, FALSE, &stride_this_run
+#ifdef VBOX_WITH_WINE_FIX_BUFOFFSET
+                , &offset_this_run
+#endif
+            ) || ret;
+    ret = buffer_check_attribute(This, si, WINED3D_FFP_TEXCOORD1,
+            TRUE, FALSE, FALSE, &stride_this_run
+#ifdef VBOX_WITH_WINE_FIX_BUFOFFSET
+                , &offset_this_run
+#endif
+            ) || ret;
+    ret = buffer_check_attribute(This, si, WINED3D_FFP_TEXCOORD2,
+            TRUE, FALSE, FALSE, &stride_this_run
+#ifdef VBOX_WITH_WINE_FIX_BUFOFFSET
+                , &offset_this_run
+#endif
+            ) || ret;
+    ret = buffer_check_attribute(This, si, WINED3D_FFP_TEXCOORD3,
+            TRUE, FALSE, FALSE, &stride_this_run
+#ifdef VBOX_WITH_WINE_FIX_BUFOFFSET
+                , &offset_this_run
+#endif
+            ) || ret;
+    ret = buffer_check_attribute(This, si, WINED3D_FFP_TEXCOORD4,
+            TRUE, FALSE, FALSE, &stride_this_run
+#ifdef VBOX_WITH_WINE_FIX_BUFOFFSET
+                , &offset_this_run
+#endif
+            ) || ret;
+    ret = buffer_check_attribute(This, si, WINED3D_FFP_TEXCOORD5,
+            TRUE, FALSE, FALSE, &stride_this_run
+#ifdef VBOX_WITH_WINE_FIX_BUFOFFSET
+                , &offset_this_run
+#endif
+            ) || ret;
+    ret = buffer_check_attribute(This, si, WINED3D_FFP_TEXCOORD6,
+            TRUE, FALSE, FALSE, &stride_this_run
+#ifdef VBOX_WITH_WINE_FIX_BUFOFFSET
+                , &offset_this_run
+#endif
+            ) || ret;
+    ret = buffer_check_attribute(This, si, WINED3D_FFP_TEXCOORD7,
+            TRUE, FALSE, FALSE, &stride_this_run
+#ifdef VBOX_WITH_WINE_FIX_BUFOFFSET
+                , &offset_this_run
+#endif
+            ) || ret;
+
+    if (!stride_this_run && This->conversion_map)
+    {
+        /* Sanity test */
+        if (!ret) ERR("no converted attributes found, old conversion map exists, and no declaration change?\n");
+        HeapFree(GetProcessHeap(), 0, This->conversion_map);
+        This->conversion_map = NULL;
+        This->stride = 0;
+    }
+
+    if (ret) TRACE("Conversion information changed\n");
+
+    return ret;
+}
+
+static inline void fixup_d3dcolor(DWORD *dst_color)
+{
+    DWORD src_color = *dst_color;
+
+    /* Color conversion like in drawStridedSlow. watch out for little endianity
+     * If we want that stuff to work on big endian machines too we have to consider more things
+     *
+     * 0xff000000: Alpha mask
+     * 0x00ff0000: Blue mask
+     * 0x0000ff00: Green mask
+     * 0x000000ff: Red mask
+     */
+    *dst_color = 0;
+    *dst_color |= (src_color & 0xff00ff00);         /* Alpha Green */
+    *dst_color |= (src_color & 0x00ff0000) >> 16;   /* Red */
+    *dst_color |= (src_color & 0x000000ff) << 16;   /* Blue */
+}
+
+static inline void fixup_transformed_pos(float *p)
+{
+    /* rhw conversion like in position_float4(). */
+    if (p[3] != 1.0f && p[3] != 0.0f)
+    {
+        float w = 1.0f / p[3];
+        p[0] *= w;
+        p[1] *= w;
+        p[2] *= w;
+        p[3] = w;
+    }
+}
+
+/* Context activation is done by the caller. */
+void buffer_get_memory(struct wined3d_buffer *buffer, const struct wined3d_gl_info *gl_info,
+        struct wined3d_bo_address *data)
+{
+    data->buffer_object = buffer->buffer_object;
+    if (!buffer->buffer_object)
+    {
+        if ((buffer->flags & WINED3D_BUFFER_CREATEBO) && !buffer->resource.map_count)
+        {
+            buffer_create_buffer_object(buffer, gl_info);
+            buffer->flags &= ~WINED3D_BUFFER_CREATEBO;
+            if (buffer->buffer_object)
+            {
+                data->buffer_object = buffer->buffer_object;
+                data->addr = NULL;
+                return;
+            }
+        }
+        data->addr = buffer->resource.allocatedMemory;
+    }
+    else
+    {
+        data->addr = NULL;
+    }
+}
+
+ULONG CDECL wined3d_buffer_incref(struct wined3d_buffer *buffer)
+{
+    ULONG refcount = InterlockedIncrement(&buffer->resource.ref);
+
+    TRACE("%p increasing refcount to %u.\n", buffer, refcount);
+
+    return refcount;
+}
+
+/* Context activation is done by the caller. */
+BYTE *buffer_get_sysmem(struct wined3d_buffer *This, const struct wined3d_gl_info *gl_info)
+{
+    /* AllocatedMemory exists if the buffer is double buffered or has no buffer object at all */
+    if(This->resource.allocatedMemory) return This->resource.allocatedMemory;
+
+    This->resource.heapMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->resource.size + RESOURCE_ALIGNMENT);
+    This->resource.allocatedMemory = (BYTE *)(((ULONG_PTR)This->resource.heapMemory + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1));
+
+    if (This->buffer_type_hint == GL_ELEMENT_ARRAY_BUFFER_ARB)
+        device_invalidate_state(This->resource.device, STATE_INDEXBUFFER);
+
+    GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object));
+    GL_EXTCALL(glGetBufferSubDataARB(This->buffer_type_hint, 0, This->resource.size, This->resource.allocatedMemory));
+    This->flags |= WINED3D_BUFFER_DOUBLEBUFFER;
+
+    return This->resource.allocatedMemory;
+}
+
+/* Do not call while under the GL lock. */
+static void buffer_unload(struct wined3d_resource *resource)
+{
+    struct wined3d_buffer *buffer = buffer_from_resource(resource);
+
+    TRACE("buffer %p.\n", buffer);
+
+    if (buffer->buffer_object)
+    {
+        struct wined3d_device *device = resource->device;
+        struct wined3d_context *context;
+
+        context = context_acquire(device, NULL);
+
+        /* Download the buffer, but don't permanently enable double buffering */
+        if (!(buffer->flags & WINED3D_BUFFER_DOUBLEBUFFER))
+        {
+            buffer_get_sysmem(buffer, context->gl_info);
+            buffer->flags &= ~WINED3D_BUFFER_DOUBLEBUFFER;
+        }
+
+        delete_gl_buffer(buffer, context->gl_info);
+        buffer->flags |= WINED3D_BUFFER_CREATEBO; /* Recreate the buffer object next load */
+        buffer_clear_dirty_areas(buffer);
+
+        context_release(context);
+
+        HeapFree(GetProcessHeap(), 0, buffer->conversion_map);
+        buffer->conversion_map = NULL;
+        buffer->stride = 0;
+        buffer->conversion_stride = 0;
+        buffer->flags &= ~WINED3D_BUFFER_HASDESC;
+    }
+
+    resource_unload(resource);
+}
+
+/* Do not call while under the GL lock. */
+ULONG CDECL wined3d_buffer_decref(struct wined3d_buffer *buffer)
+{
+    ULONG refcount = InterlockedDecrement(&buffer->resource.ref);
+
+    TRACE("%p decreasing refcount to %u.\n", buffer, refcount);
+
+    if (!refcount)
+    {
+        buffer_unload(&buffer->resource);
+        resource_cleanup(&buffer->resource);
+        buffer->resource.parent_ops->wined3d_object_destroyed(buffer->resource.parent);
+        HeapFree(GetProcessHeap(), 0, buffer->maps);
+        HeapFree(GetProcessHeap(), 0, buffer);
+    }
+
+    return refcount;
+}
+
+void * CDECL wined3d_buffer_get_parent(const struct wined3d_buffer *buffer)
+{
+    TRACE("buffer %p.\n", buffer);
+
+    return buffer->resource.parent;
+}
+
+DWORD CDECL wined3d_buffer_set_priority(struct wined3d_buffer *buffer, DWORD priority)
+{
+    return resource_set_priority(&buffer->resource, priority);
+}
+
+DWORD CDECL wined3d_buffer_get_priority(const struct wined3d_buffer *buffer)
+{
+    return resource_get_priority(&buffer->resource);
+}
+
+/* The caller provides a context and binds the buffer */
+static void buffer_sync_apple(struct wined3d_buffer *This, DWORD flags, const struct wined3d_gl_info *gl_info)
+{
+    enum wined3d_event_query_result ret;
+
+    /* No fencing needs to be done if the app promises not to overwrite
+     * existing data. */
+    if (flags & WINED3D_MAP_NOOVERWRITE)
+        return;
+
+    if (flags & WINED3D_MAP_DISCARD)
+    {
+        GL_EXTCALL(glBufferDataARB(This->buffer_type_hint, This->resource.size, NULL, This->buffer_object_usage));
+        checkGLcall("glBufferDataARB\n");
+        return;
+    }
+
+    if(!This->query)
+    {
+        TRACE("Creating event query for buffer %p\n", This);
+
+        if (!wined3d_event_query_supported(gl_info))
+        {
+            FIXME("Event queries not supported, dropping async buffer locks.\n");
+            goto drop_query;
+        }
+
+        This->query = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->query));
+        if (!This->query)
+        {
+            ERR("Failed to allocate event query memory, dropping async buffer locks.\n");
+            goto drop_query;
+        }
+
+        /* Since we don't know about old draws a glFinish is needed once */
+        gl_info->gl_ops.gl.p_glFinish();
+        return;
+    }
+    TRACE("Synchronizing buffer %p\n", This);
+    ret = wined3d_event_query_finish(This->query, This->resource.device);
+    switch(ret)
+    {
+        case WINED3D_EVENT_QUERY_NOT_STARTED:
+        case WINED3D_EVENT_QUERY_OK:
+            /* All done */
+            return;
+
+        case WINED3D_EVENT_QUERY_WRONG_THREAD:
+            WARN("Cannot synchronize buffer lock due to a thread conflict\n");
+            goto drop_query;
+
+        default:
+            ERR("wined3d_event_query_finish returned %u, dropping async buffer locks\n", ret);
+            goto drop_query;
+    }
+
+drop_query:
+    if(This->query)
+    {
+        wined3d_event_query_destroy(This->query);
+        This->query = NULL;
+    }
+
+    gl_info->gl_ops.gl.p_glFinish();
+    GL_EXTCALL(glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_TRUE));
+    checkGLcall("glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_TRUE)");
+    This->flags &= ~WINED3D_BUFFER_APPLESYNC;
+}
+
+/* The caller provides a GL context */
+static void buffer_direct_upload(struct wined3d_buffer *This, const struct wined3d_gl_info *gl_info, DWORD flags)
+{
+    BYTE *map;
+    UINT start = 0, len = 0;
+
+    /* This potentially invalidates the element array buffer binding, but the
+     * caller always takes care of this. */
+    GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object));
+    checkGLcall("glBindBufferARB");
+    if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
+    {
+        GLbitfield mapflags;
+        mapflags = GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT;
+        if (flags & WINED3D_BUFFER_DISCARD)
+            mapflags |= GL_MAP_INVALIDATE_BUFFER_BIT;
+        if (flags & WINED3D_BUFFER_NOSYNC)
+            mapflags |= GL_MAP_UNSYNCHRONIZED_BIT;
+        map = GL_EXTCALL(glMapBufferRange(This->buffer_type_hint, 0,
+                    This->resource.size, mapflags));
+        checkGLcall("glMapBufferRange");
+    }
+    else
+    {
+        if (This->flags & WINED3D_BUFFER_APPLESYNC)
+        {
+            DWORD syncflags = 0;
+            if (flags & WINED3D_BUFFER_DISCARD)
+                syncflags |= WINED3D_MAP_DISCARD;
+            if (flags & WINED3D_BUFFER_NOSYNC)
+                syncflags |= WINED3D_MAP_NOOVERWRITE;
+            buffer_sync_apple(This, syncflags, gl_info);
+        }
+        map = GL_EXTCALL(glMapBufferARB(This->buffer_type_hint, GL_WRITE_ONLY_ARB));
+        checkGLcall("glMapBufferARB");
+    }
+    if (!map)
+    {
+        ERR("Failed to map opengl buffer\n");
+        return;
+    }
+
+    while (This->modified_areas)
+    {
+        This->modified_areas--;
+        start = This->maps[This->modified_areas].offset;
+        len = This->maps[This->modified_areas].size;
+
+        memcpy(map + start, This->resource.allocatedMemory + start, len);
+
+        if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
+        {
+            GL_EXTCALL(glFlushMappedBufferRange(This->buffer_type_hint, start, len));
+            checkGLcall("glFlushMappedBufferRange");
+        }
+        else if (This->flags & WINED3D_BUFFER_FLUSH)
+        {
+            GL_EXTCALL(glFlushMappedBufferRangeAPPLE(This->buffer_type_hint, start, len));
+            checkGLcall("glFlushMappedBufferRangeAPPLE");
+        }
+    }
+    GL_EXTCALL(glUnmapBufferARB(This->buffer_type_hint));
+    checkGLcall("glUnmapBufferARB");
+}
+
+#ifdef VBOX_WITH_WINE_FIX_BUFOFFSET
+static UINT wined3d_buffer_stream_offset_left(UINT x, UINT offset, UINT stride)
+{
+    UINT off = ((UINT)(RT_ABS((INT)(x - offset))) % stride);
+    if (!off)
+        return x;
+    if (x > offset)
+        return x - off;
+
+    /* x < offset */
+    return x  - stride + off;
+}
+
+static UINT wined3d_buffer_stream_offset_right(UINT x, UINT offset, UINT stride)
+{
+    UINT left = wined3d_buffer_stream_offset_left(x, offset, stride);
+
+    if (left == x)
+        return x;
+    return left + stride;
+}
+#endif
+
+/* Do not call while under the GL lock. */
+void CDECL wined3d_buffer_preload(struct wined3d_buffer *buffer)
+{
+    DWORD flags = buffer->flags & (WINED3D_BUFFER_NOSYNC | WINED3D_BUFFER_DISCARD);
+    struct wined3d_device *device = buffer->resource.device;
+    UINT start = 0, end = 0, len = 0, vertices;
+    const struct wined3d_gl_info *gl_info;
+    struct wined3d_context *context;
+    BOOL decl_changed = FALSE;
+    unsigned int i, j;
+    BYTE *data;
+#ifdef VBOX_WITH_WINE_FIX_BUFOFFSET
+    BYTE *cur_ptr;
+    UINT conv_start, conv_end;
+#endif
+
+    TRACE("buffer %p.\n", buffer);
+
+    if (buffer->resource.map_count)
+    {
+        WARN("Buffer is mapped, skipping preload.\n");
+        return;
+    }
+
+    buffer->flags &= ~(WINED3D_BUFFER_NOSYNC | WINED3D_BUFFER_DISCARD);
+
+    if (!buffer->buffer_object)
+    {
+        /* TODO: Make converting independent from VBOs */
+        if (buffer->flags & WINED3D_BUFFER_CREATEBO)
+        {
+            context = context_acquire(device, NULL);
+            buffer_create_buffer_object(buffer, context->gl_info);
+            context_release(context);
+            buffer->flags &= ~WINED3D_BUFFER_CREATEBO;
+        }
+        else
+        {
+            /* Not doing any conversion */
+            return;
+        }
+    }
+
+    /* Reading the declaration makes only sense if the stateblock is finalized and the buffer bound to a stream */
+    if (device->isInDraw && buffer->resource.bind_count > 0)
+    {
+        decl_changed = buffer_find_decl(buffer);
+        buffer->flags |= WINED3D_BUFFER_HASDESC;
+    }
+
+    if (!decl_changed && !(buffer->flags & WINED3D_BUFFER_HASDESC && buffer_is_dirty(buffer)))
+    {
+        ++buffer->draw_count;
+        if (buffer->draw_count > VB_RESETDECLCHANGE)
+            buffer->decl_change_count = 0;
+        if (buffer->draw_count > VB_RESETFULLCONVS)
+            buffer->full_conversion_count = 0;
+        return;
+    }
+
+    /* If applications change the declaration over and over, reconverting all the time is a huge
+     * performance hit. So count the declaration changes and release the VBO if there are too many
+     * of them (and thus stop converting)
+     */
+    if (decl_changed)
+    {
+        ++buffer->decl_change_count;
+        buffer->draw_count = 0;
+
+        if (buffer->decl_change_count > VB_MAXDECLCHANGES
+                || (buffer->conversion_map && (buffer->resource.usage & WINED3DUSAGE_DYNAMIC)))
+        {
+            FIXME("Too many declaration changes or converting dynamic buffer, stopping converting\n");
+
+            buffer_unload(&buffer->resource);
+            buffer->flags &= ~WINED3D_BUFFER_CREATEBO;
+
+            /* The stream source state handler might have read the memory of
+             * the vertex buffer already and got the memory in the vbo which
+             * is not valid any longer. Dirtify the stream source to force a
+             * reload. This happens only once per changed vertexbuffer and
+             * should occur rather rarely. */
+            device_invalidate_state(device, STATE_STREAMSRC);
+            return;
+        }
+
+        /* The declaration changed, reload the whole buffer */
+        WARN("Reloading buffer because of decl change\n");
+        buffer_clear_dirty_areas(buffer);
+        if (!buffer_add_dirty_area(buffer, 0, 0))
+        {
+            ERR("buffer_add_dirty_area failed, this is not expected\n");
+            return;
+        }
+        /* Avoid unfenced updates, we might overwrite more areas of the buffer than the application
+         * cleared for unsynchronized updates
+         */
+        flags = 0;
+    }
+    else
+    {
+        /* However, it is perfectly fine to change the declaration every now and then. We don't want a game that
+         * changes it every minute drop the VBO after VB_MAX_DECL_CHANGES minutes. So count draws without
+         * decl changes and reset the decl change count after a specific number of them
+         */
+        if (buffer->conversion_map && buffer_is_fully_dirty(buffer))
+        {
+            ++buffer->full_conversion_count;
+            if (buffer->full_conversion_count > VB_MAXFULLCONVERSIONS)
+            {
+                FIXME("Too many full buffer conversions, stopping converting.\n");
+                buffer_unload(&buffer->resource);
+                buffer->flags &= ~WINED3D_BUFFER_CREATEBO;
+                if (buffer->resource.bind_count)
+                    device_invalidate_state(device, STATE_STREAMSRC);
+                return;
+            }
+        }
+        else
+        {
+            ++buffer->draw_count;
+            if (buffer->draw_count > VB_RESETDECLCHANGE)
+                buffer->decl_change_count = 0;
+            if (buffer->draw_count > VB_RESETFULLCONVS)
+                buffer->full_conversion_count = 0;
+        }
+    }
+
+    if (buffer->buffer_type_hint == GL_ELEMENT_ARRAY_BUFFER_ARB)
+        device_invalidate_state(device, STATE_INDEXBUFFER);
+
+    if (!buffer->conversion_map)
+    {
+        /* That means that there is nothing to fixup. Just upload from
+         * buffer->resource.allocatedMemory directly into the vbo. Do not
+         * free the system memory copy because drawPrimitive may need it if
+         * the stride is 0, for instancing emulation, vertex blending
+         * emulation or shader emulation. */
+        TRACE("No conversion needed.\n");
+
+        /* Nothing to do because we locked directly into the vbo */
+        if (!(buffer->flags & WINED3D_BUFFER_DOUBLEBUFFER))
+        {
+            return;
+        }
+
+        context = context_acquire(device, NULL);
+        buffer_direct_upload(buffer, context->gl_info, flags);
+
+        context_release(context);
+        return;
+    }
+
+    context = context_acquire(device, NULL);
+    gl_info = context->gl_info;
+
+    if(!(buffer->flags & WINED3D_BUFFER_DOUBLEBUFFER))
+    {
+        buffer_get_sysmem(buffer, gl_info);
+    }
+
+    /* Now for each vertex in the buffer that needs conversion */
+    vertices = buffer->resource.size / buffer->stride;
+
+    data = HeapAlloc(GetProcessHeap(), 0, buffer->resource.size);
+
+    while(buffer->modified_areas)
+    {
+        buffer->modified_areas--;
+        start = buffer->maps[buffer->modified_areas].offset;
+        len = buffer->maps[buffer->modified_areas].size;
+        end = start + len;
+
+#ifdef VBOX_WITH_WINE_FIX_BUFOFFSET
+        if (buffer->offset > UINT32_MAX)
+        {
+            ERR("negative offset, unexpected!");
+        }
+
+        conv_start = wined3d_buffer_stream_offset_left(start, buffer->offset, buffer->stride);
+        if (conv_start <= start)
+        {
+            start = conv_start;
+        }
+        else
+        {
+            /* <- < 0, add stride */
+            conv_start += buffer->stride;
+        }
+
+        Assert(conv_start < UINT32_MAX/3);
+
+        conv_end =  wined3d_buffer_stream_offset_right(end, buffer->offset, buffer->stride);
+        if (conv_end > end)
+        {
+            if (conv_end <= buffer->resource.size)
+                end = conv_end;
+            else
+                conv_end -= buffer->stride;
+        }
+        else if (conv_end < end)
+        {
+            ERR("unexpected!");
+        }
+        else
+        {
+            end = conv_end;
+        }
+#endif
+        memcpy(data + start, buffer->resource.allocatedMemory + start, end - start);
+
+#ifdef VBOX_WITH_WINE_FIX_BUFOFFSET
+        for (cur_ptr = data + conv_start; cur_ptr < data + conv_end; cur_ptr += buffer->stride)
+#else
+        for (i = start / buffer->stride; i < min((end / buffer->stride) + 1, vertices); ++i)
+#endif
+        {
+            for (j = 0; j < buffer->stride; ++j)
+            {
+                switch (buffer->conversion_map[j])
+                {
+                    case CONV_NONE:
+                        /* Done already */
+                        j += 3;
+                        break;
+                    case CONV_D3DCOLOR:
+#ifdef VBOX_WITH_WINE_FIX_BUFOFFSET
+                        fixup_d3dcolor((DWORD *) (cur_ptr + j));
+#else
+                        fixup_d3dcolor((DWORD *) (data + i * buffer->stride + j));
+#endif
+                        j += 3;
+                        break;
+
+                    case CONV_POSITIONT:
+#ifdef VBOX_WITH_WINE_FIX_BUFOFFSET
+                        fixup_transformed_pos((float *) (cur_ptr + j));
+#else
+                        fixup_transformed_pos((float *) (data + i * buffer->stride + j));
+#endif
+                        j += 15;
+                        break;
+                    default:
+                        FIXME("Unimplemented conversion %d in shifted conversion\n", buffer->conversion_map[j]);
+                }
+            }
+        }
+
+        GL_EXTCALL(glBindBufferARB(buffer->buffer_type_hint, buffer->buffer_object));
+        checkGLcall("glBindBufferARB");
+        GL_EXTCALL(glBufferSubDataARB(buffer->buffer_type_hint, start, len, data + start));
+        checkGLcall("glBufferSubDataARB");
+    }
+
+    HeapFree(GetProcessHeap(), 0, data);
+    context_release(context);
+}
+
+static DWORD buffer_sanitize_flags(const struct wined3d_buffer *buffer, DWORD flags)
+{
+    /* Not all flags make sense together, but Windows never returns an error.
+     * Catch the cases that could cause issues. */
+    if (flags & WINED3D_MAP_READONLY)
+    {
+        if (flags & WINED3D_MAP_DISCARD)
+        {
+            WARN("WINED3D_MAP_READONLY combined with WINED3D_MAP_DISCARD, ignoring flags.\n");
+            return 0;
+        }
+        if (flags & WINED3D_MAP_NOOVERWRITE)
+        {
+            WARN("WINED3D_MAP_READONLY combined with WINED3D_MAP_NOOVERWRITE, ignoring flags.\n");
+            return 0;
+        }
+    }
+    else if ((flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE))
+            == (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE))
+    {
+        WARN("WINED3D_MAP_DISCARD and WINED3D_MAP_NOOVERWRITE used together, ignoring.\n");
+        return 0;
+    }
+    else if (flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE)
+            && !(buffer->resource.usage & WINED3DUSAGE_DYNAMIC))
+    {
+        WARN("DISCARD or NOOVERWRITE map on non-dynamic buffer, ignoring.\n");
+        return 0;
+    }
+
+    return flags;
+}
+
+static GLbitfield buffer_gl_map_flags(DWORD d3d_flags)
+{
+    GLbitfield ret = 0;
+
+    if (!(d3d_flags & WINED3D_MAP_READONLY))
+        ret |= GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT;
+    if (!(d3d_flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE)))
+        ret |= GL_MAP_READ_BIT;
+
+    if (d3d_flags & WINED3D_MAP_DISCARD)
+        ret |= GL_MAP_INVALIDATE_BUFFER_BIT;
+    if (d3d_flags & WINED3D_MAP_NOOVERWRITE)
+        ret |= GL_MAP_UNSYNCHRONIZED_BIT;
+
+    return ret;
+}
+
+struct wined3d_resource * CDECL wined3d_buffer_get_resource(struct wined3d_buffer *buffer)
+{
+    TRACE("buffer %p.\n", buffer);
+
+    return &buffer->resource;
+}
+
+HRESULT CDECL wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UINT size, BYTE **data, DWORD flags)
+{
+    BOOL dirty = buffer_is_dirty(buffer);
+    LONG count;
+
+    TRACE("buffer %p, offset %u, size %u, data %p, flags %#x\n", buffer, offset, size, data, flags);
+
+    flags = buffer_sanitize_flags(buffer, flags);
+        if (flags & WINED3D_MAP_DISCARD)
+        {
+        /* DISCARD invalidates the entire buffer, regardless of the specified
+         * offset and size. Some applications also depend on the entire buffer
+         * being uploaded in that case. Two such applications are Port Royale
+         * and Darkstar One. */
+            if (!buffer_add_dirty_area(buffer, 0, 0))
+                return E_OUTOFMEMORY;
+        }
+    else if (!(flags & WINED3D_MAP_READONLY))
+        {
+            if (!buffer_add_dirty_area(buffer, offset, size))
+                return E_OUTOFMEMORY;
+        }
+
+    count = ++buffer->resource.map_count;
+
+    if (buffer->buffer_object)
+    {
+        if (!(buffer->flags & WINED3D_BUFFER_DOUBLEBUFFER))
+        {
+            if (count == 1)
+            {
+                struct wined3d_device *device = buffer->resource.device;
+                struct wined3d_context *context;
+                const struct wined3d_gl_info *gl_info;
+
+                context = context_acquire(device, NULL);
+                gl_info = context->gl_info;
+
+                if (buffer->buffer_type_hint == GL_ELEMENT_ARRAY_BUFFER_ARB)
+                    context_invalidate_state(context, STATE_INDEXBUFFER);
+                GL_EXTCALL(glBindBufferARB(buffer->buffer_type_hint, buffer->buffer_object));
+
+                if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
+                {
+                    GLbitfield mapflags = buffer_gl_map_flags(flags);
+                    buffer->resource.allocatedMemory = GL_EXTCALL(glMapBufferRange(buffer->buffer_type_hint,
+                            0, buffer->resource.size, mapflags));
+                    checkGLcall("glMapBufferRange");
+                }
+                else
+                {
+                    if (buffer->flags & WINED3D_BUFFER_APPLESYNC)
+                        buffer_sync_apple(buffer, flags, gl_info);
+                    buffer->resource.allocatedMemory = GL_EXTCALL(glMapBufferARB(buffer->buffer_type_hint,
+                            GL_READ_WRITE_ARB));
+                    checkGLcall("glMapBufferARB");
+                }
+
+                if (((DWORD_PTR)buffer->resource.allocatedMemory) & (RESOURCE_ALIGNMENT - 1))
+                {
+                    WARN("Pointer %p is not %u byte aligned.\n", buffer->resource.allocatedMemory, RESOURCE_ALIGNMENT);
+
+                    GL_EXTCALL(glUnmapBufferARB(buffer->buffer_type_hint));
+                    checkGLcall("glUnmapBufferARB");
+                    buffer->resource.allocatedMemory = NULL;
+
+                    if (buffer->resource.usage & WINED3DUSAGE_DYNAMIC)
+                    {
+                        /* The extra copy is more expensive than not using VBOs at
+                         * all on the Nvidia Linux driver, which is the only driver
+                         * that returns unaligned pointers
+                         */
+                        TRACE("Dynamic buffer, dropping VBO\n");
+                        buffer_unload(&buffer->resource);
+                        buffer->flags &= ~WINED3D_BUFFER_CREATEBO;
+                        if (buffer->resource.bind_count)
+                            device_invalidate_state(device, STATE_STREAMSRC);
+                    }
+                    else
+                    {
+                        TRACE("Falling back to doublebuffered operation\n");
+                        buffer_get_sysmem(buffer, gl_info);
+                    }
+                    TRACE("New pointer is %p.\n", buffer->resource.allocatedMemory);
+                }
+                context_release(context);
+            }
+        }
+        else
+        {
+            if (dirty)
+            {
+                if (buffer->flags & WINED3D_BUFFER_NOSYNC && !(flags & WINED3D_MAP_NOOVERWRITE))
+                {
+                    buffer->flags &= ~WINED3D_BUFFER_NOSYNC;
+                }
+            }
+            else if(flags & WINED3D_MAP_NOOVERWRITE)
+            {
+                buffer->flags |= WINED3D_BUFFER_NOSYNC;
+            }
+
+            if (flags & WINED3D_MAP_DISCARD)
+            {
+                buffer->flags |= WINED3D_BUFFER_DISCARD;
+            }
+        }
+    }
+
+    *data = buffer->resource.allocatedMemory + offset;
+
+    TRACE("Returning memory at %p (base %p, offset %u).\n", *data, buffer->resource.allocatedMemory, offset);
+    /* TODO: check Flags compatibility with buffer->currentDesc.Usage (see MSDN) */
+
+    return WINED3D_OK;
+}
+
+void CDECL wined3d_buffer_unmap(struct wined3d_buffer *buffer)
+{
+    ULONG i;
+
+    TRACE("buffer %p.\n", buffer);
+
+    /* In the case that the number of Unmap calls > the
+     * number of Map calls, d3d returns always D3D_OK.
+     * This is also needed to prevent Map from returning garbage on
+     * the next call (this will happen if the lock_count is < 0). */
+    if (!buffer->resource.map_count)
+    {
+        WARN("Unmap called without a previous map call.\n");
+        return;
+    }
+
+    if (--buffer->resource.map_count)
+    {
+        /* Delay loading the buffer until everything is unlocked */
+        TRACE("Ignoring unmap.\n");
+        return;
+    }
+
+    if (!(buffer->flags & WINED3D_BUFFER_DOUBLEBUFFER) && buffer->buffer_object)
+    {
+        struct wined3d_device *device = buffer->resource.device;
+        const struct wined3d_gl_info *gl_info;
+        struct wined3d_context *context;
+
+        context = context_acquire(device, NULL);
+        gl_info = context->gl_info;
+
+        if (buffer->buffer_type_hint == GL_ELEMENT_ARRAY_BUFFER_ARB)
+            context_invalidate_state(context, STATE_INDEXBUFFER);
+        GL_EXTCALL(glBindBufferARB(buffer->buffer_type_hint, buffer->buffer_object));
+
+        if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
+        {
+            for (i = 0; i < buffer->modified_areas; ++i)
+            {
+                GL_EXTCALL(glFlushMappedBufferRange(buffer->buffer_type_hint,
+                        buffer->maps[i].offset, buffer->maps[i].size));
+                checkGLcall("glFlushMappedBufferRange");
+            }
+        }
+        else if (buffer->flags & WINED3D_BUFFER_FLUSH)
+        {
+            for (i = 0; i < buffer->modified_areas; ++i)
+            {
+                GL_EXTCALL(glFlushMappedBufferRangeAPPLE(buffer->buffer_type_hint,
+                        buffer->maps[i].offset, buffer->maps[i].size));
+                checkGLcall("glFlushMappedBufferRangeAPPLE");
+            }
+        }
+
+        GL_EXTCALL(glUnmapBufferARB(buffer->buffer_type_hint));
+        if (wined3d_settings.strict_draw_ordering)
+            gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */
+        context_release(context);
+
+        buffer->resource.allocatedMemory = NULL;
+        buffer_clear_dirty_areas(buffer);
+    }
+    else if (buffer->flags & WINED3D_BUFFER_HASDESC)
+    {
+        wined3d_buffer_preload(buffer);
+    }
+}
+
+static const struct wined3d_resource_ops buffer_resource_ops =
+{
+    buffer_unload,
+};
+
+static HRESULT buffer_init(struct wined3d_buffer *buffer, struct wined3d_device *device,
+        UINT size, DWORD usage, enum wined3d_format_id format_id, enum wined3d_pool pool, GLenum bind_hint,
+        const char *data, void *parent, const struct wined3d_parent_ops *parent_ops)
+{
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    const struct wined3d_format *format = wined3d_get_format(gl_info, format_id);
+    HRESULT hr;
+    BOOL dynamic_buffer_ok;
+
+    if (!size)
+    {
+        WARN("Size 0 requested, returning WINED3DERR_INVALIDCALL\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    hr = resource_init(&buffer->resource, device, WINED3D_RTYPE_BUFFER, format,
+            WINED3D_MULTISAMPLE_NONE, 0, usage, pool, size, 1, 1, size,
+            parent, parent_ops, &buffer_resource_ops
+#ifdef VBOX_WITH_WDDM
+            , NULL, NULL /* <- no need this info here so far */
+#endif
+            );
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize resource, hr %#x\n", hr);
+        return hr;
+    }
+    buffer->buffer_type_hint = bind_hint;
+
+    TRACE("size %#x, usage %#x, format %s, memory @ %p, iface @ %p.\n", buffer->resource.size, buffer->resource.usage,
+            debug_d3dformat(buffer->resource.format->id), buffer->resource.allocatedMemory, buffer);
+
+    if (device->create_parms.flags & WINED3DCREATE_SOFTWARE_VERTEXPROCESSING)
+    {
+        /* SWvp always returns the same pointer in buffer maps and retains data in DISCARD maps.
+         * Keep a system memory copy of the buffer to provide the same behavior to the application.
+         * Still use a VBO to support OpenGL 3 core contexts. */
+        TRACE("Using doublebuffer mode because of software vertex processing\n");
+        buffer->flags |= WINED3D_BUFFER_DOUBLEBUFFER;
+    }
+
+    dynamic_buffer_ok = gl_info->supported[APPLE_FLUSH_BUFFER_RANGE] || gl_info->supported[ARB_MAP_BUFFER_RANGE];
+
+    /* Observations show that drawStridedSlow is faster on dynamic VBs than converting +
+     * drawStridedFast (half-life 2 and others).
+     *
+     * Basically converting the vertices in the buffer is quite expensive, and observations
+     * show that drawStridedSlow is faster than converting + uploading + drawStridedFast.
+     * Therefore do not create a VBO for WINED3DUSAGE_DYNAMIC buffers.
+     */
+    if (!gl_info->supported[ARB_VERTEX_BUFFER_OBJECT])
+    {
+        TRACE("Not creating a vbo because GL_ARB_vertex_buffer is not supported\n");
+    }
+#ifndef VBOX_WITH_WDDM /* @todo: extend this to VBOX in general */
+    else if(buffer->resource.pool == WINED3D_POOL_SYSTEM_MEM)
+    {
+        TRACE("Not creating a vbo because the vertex buffer is in system memory\n");
+    }
+    else if(!dynamic_buffer_ok && (buffer->resource.usage & WINED3DUSAGE_DYNAMIC))
+    {
+        TRACE("Not creating a vbo because the buffer has dynamic usage and no GL support\n");
+    }
+#endif
+    else
+    {
+        buffer->flags |= WINED3D_BUFFER_CREATEBO;
+    }
+
+    if (data)
+    {
+        BYTE *ptr;
+
+        hr = wined3d_buffer_map(buffer, 0, size, &ptr, 0);
+        if (FAILED(hr))
+        {
+            ERR("Failed to map buffer, hr %#x\n", hr);
+            buffer_unload(&buffer->resource);
+            resource_cleanup(&buffer->resource);
+            return hr;
+        }
+
+        memcpy(ptr, data, size);
+
+        wined3d_buffer_unmap(buffer);
+    }
+
+    buffer->maps = HeapAlloc(GetProcessHeap(), 0, sizeof(*buffer->maps));
+    if (!buffer->maps)
+    {
+        ERR("Out of memory\n");
+        buffer_unload(&buffer->resource);
+        resource_cleanup(&buffer->resource);
+        return E_OUTOFMEMORY;
+    }
+    buffer->maps_size = 1;
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_buffer_create(struct wined3d_device *device, struct wined3d_buffer_desc *desc, const void *data,
+        void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_buffer **buffer)
+{
+    struct wined3d_buffer *object;
+    HRESULT hr;
+
+    TRACE("device %p, desc %p, data %p, parent %p, buffer %p\n", device, desc, data, parent, buffer);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return E_OUTOFMEMORY;
+
+    FIXME("Ignoring access flags (pool)\n");
+
+    hr = buffer_init(object, device, desc->byte_width, desc->usage, WINED3DFMT_UNKNOWN,
+            WINED3D_POOL_MANAGED, GL_ARRAY_BUFFER_ARB, data, parent, parent_ops);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize buffer, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+    object->desc = *desc;
+
+    TRACE("Created buffer %p.\n", object);
+
+    *buffer = object;
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_buffer_create_vb(struct wined3d_device *device, UINT size, DWORD usage, enum wined3d_pool pool,
+        void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_buffer **buffer)
+{
+    struct wined3d_buffer *object;
+    HRESULT hr;
+
+    TRACE("device %p, size %u, usage %#x, pool %#x, parent %p, parent_ops %p, buffer %p.\n",
+            device, size, usage, pool, parent, parent_ops, buffer);
+
+    if (pool == WINED3D_POOL_SCRATCH)
+    {
+        /* The d3d9 tests shows that this is not allowed. It doesn't make much
+         * sense anyway, SCRATCH buffers wouldn't be usable anywhere. */
+        WARN("Vertex buffer in WINED3D_POOL_SCRATCH requested, returning WINED3DERR_INVALIDCALL.\n");
+        *buffer = NULL;
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+    {
+        *buffer = NULL;
+        return WINED3DERR_OUTOFVIDEOMEMORY;
+    }
+
+    hr = buffer_init(object, device, size, usage, WINED3DFMT_VERTEXDATA,
+            pool, GL_ARRAY_BUFFER_ARB, NULL, parent, parent_ops);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize buffer, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created buffer %p.\n", object);
+    *buffer = object;
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_buffer_create_ib(struct wined3d_device *device, UINT size, DWORD usage, enum wined3d_pool pool,
+        void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_buffer **buffer)
+{
+    struct wined3d_buffer *object;
+    HRESULT hr;
+
+    TRACE("device %p, size %u, usage %#x, pool %#x, parent %p, parent_ops %p, buffer %p.\n",
+            device, size, usage, pool, parent, parent_ops, buffer);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+    {
+        *buffer = NULL;
+        return WINED3DERR_OUTOFVIDEOMEMORY;
+    }
+
+    hr = buffer_init(object, device, size, usage | WINED3DUSAGE_STATICDECL,
+            WINED3DFMT_UNKNOWN, pool, GL_ELEMENT_ARRAY_BUFFER_ARB, NULL,
+            parent, parent_ops);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize buffer, hr %#x\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created buffer %p.\n", object);
+    *buffer = object;
+
+    return WINED3D_OK;
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/context.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/context.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/context.c	(revision 46521)
@@ -0,0 +1,2972 @@
+/*
+ * Context and render target management in wined3d
+ *
+ * Copyright 2007-2011, 2013 Stefan Dösinger for CodeWeavers
+ * Copyright 2009-2011 Henri Verbeet for CodeWeavers
+ *
+ * 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 <stdio.h>
+#ifdef HAVE_FLOAT_H
+# include <float.h>
+#endif
+
+#include "wined3d_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d);
+WINE_DECLARE_DEBUG_CHANNEL(d3d_perf);
+WINE_DECLARE_DEBUG_CHANNEL(d3d_synchronous);
+
+static DWORD wined3d_context_tls_idx;
+
+#if defined(VBOX_WINE_WITH_SINGLE_CONTEXT) || defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
+# define vboxGetCurrentContext() VBoxTlsRefGetCurrent(struct wined3d_context, wined3d_context_tls_idx)
+# define vboxSetCurrentContext(_ctx) VBoxTlsRefSetCurrent(struct wined3d_context, wined3d_context_tls_idx, (_ctx))
+#endif
+
+/* FBO helper functions */
+
+/* Context activation is done by the caller. */
+static void context_bind_fbo(struct wined3d_context *context, GLenum target, GLuint fbo)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    switch (target)
+    {
+        case GL_READ_FRAMEBUFFER:
+            if (context->fbo_read_binding == fbo) return;
+            context->fbo_read_binding = fbo;
+            break;
+
+        case GL_DRAW_FRAMEBUFFER:
+            if (context->fbo_draw_binding == fbo) return;
+            context->fbo_draw_binding = fbo;
+            break;
+
+        case GL_FRAMEBUFFER:
+            if (context->fbo_read_binding == fbo
+                    && context->fbo_draw_binding == fbo) return;
+            context->fbo_read_binding = fbo;
+            context->fbo_draw_binding = fbo;
+            break;
+
+        default:
+            FIXME("Unhandled target %#x.\n", target);
+            break;
+    }
+
+    gl_info->fbo_ops.glBindFramebuffer(target, fbo);
+    checkGLcall("glBindFramebuffer()");
+}
+
+/* Context activation is done by the caller. */
+static void context_clean_fbo_attachments(const struct wined3d_gl_info *gl_info, GLenum target)
+{
+    unsigned int i;
+
+    for (i = 0; i < gl_info->limits.buffers; ++i)
+    {
+        gl_info->fbo_ops.glFramebufferTexture2D(target, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, 0, 0);
+        checkGLcall("glFramebufferTexture2D()");
+    }
+    gl_info->fbo_ops.glFramebufferTexture2D(target, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
+    checkGLcall("glFramebufferTexture2D()");
+
+    gl_info->fbo_ops.glFramebufferTexture2D(target, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
+    checkGLcall("glFramebufferTexture2D()");
+}
+
+/* Context activation is done by the caller. */
+static void context_destroy_fbo(struct wined3d_context *context, GLuint fbo)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    context_bind_fbo(context, GL_FRAMEBUFFER, fbo);
+    context_clean_fbo_attachments(gl_info, GL_FRAMEBUFFER);
+    context_bind_fbo(context, GL_FRAMEBUFFER, 0);
+
+    gl_info->fbo_ops.glDeleteFramebuffers(1, &fbo);
+    checkGLcall("glDeleteFramebuffers()");
+}
+
+static void context_attach_depth_stencil_rb(const struct wined3d_gl_info *gl_info,
+        GLenum fbo_target, DWORD format_flags, GLuint rb)
+{
+    if (format_flags & WINED3DFMT_FLAG_DEPTH)
+    {
+        gl_info->fbo_ops.glFramebufferRenderbuffer(fbo_target, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rb);
+        checkGLcall("glFramebufferRenderbuffer()");
+    }
+
+    if (format_flags & WINED3DFMT_FLAG_STENCIL)
+    {
+        gl_info->fbo_ops.glFramebufferRenderbuffer(fbo_target, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rb);
+        checkGLcall("glFramebufferRenderbuffer()");
+    }
+}
+
+/* Context activation is done by the caller. */
+static void context_attach_depth_stencil_fbo(struct wined3d_context *context,
+        GLenum fbo_target, struct wined3d_surface *depth_stencil, DWORD location)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    TRACE("Attach depth stencil %p\n", depth_stencil);
+
+    if (depth_stencil)
+    {
+        DWORD format_flags = depth_stencil->resource.format->flags;
+
+        if (depth_stencil->current_renderbuffer)
+        {
+            context_attach_depth_stencil_rb(gl_info, fbo_target,
+                    format_flags, depth_stencil->current_renderbuffer->id);
+        }
+        else
+        {
+            switch (location)
+            {
+                case SFLAG_INTEXTURE:
+                case SFLAG_INSRGBTEX:
+                    surface_prepare_texture(depth_stencil, context, FALSE);
+
+                    if (format_flags & WINED3DFMT_FLAG_DEPTH)
+                    {
+                        gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_DEPTH_ATTACHMENT,
+                                depth_stencil->texture_target, depth_stencil->texture_name,
+                                depth_stencil->texture_level);
+                        checkGLcall("glFramebufferTexture2D()");
+                    }
+
+                    if (format_flags & WINED3DFMT_FLAG_STENCIL)
+                    {
+                        gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_STENCIL_ATTACHMENT,
+                                depth_stencil->texture_target, depth_stencil->texture_name,
+                                depth_stencil->texture_level);
+                        checkGLcall("glFramebufferTexture2D()");
+                    }
+                    break;
+
+                case SFLAG_INRB_MULTISAMPLE:
+                    surface_prepare_rb(depth_stencil, gl_info, TRUE);
+                    context_attach_depth_stencil_rb(gl_info, fbo_target,
+                            format_flags, depth_stencil->rb_multisample);
+                    break;
+
+                case SFLAG_INRB_RESOLVED:
+                    surface_prepare_rb(depth_stencil, gl_info, FALSE);
+                    context_attach_depth_stencil_rb(gl_info, fbo_target,
+                            format_flags, depth_stencil->rb_resolved);
+                    break;
+
+                default:
+                    ERR("Unsupported location %s (%#x).\n", debug_surflocation(location), location);
+                    break;
+            }
+        }
+
+        if (!(format_flags & WINED3DFMT_FLAG_DEPTH))
+        {
+            gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
+            checkGLcall("glFramebufferTexture2D()");
+        }
+
+        if (!(format_flags & WINED3DFMT_FLAG_STENCIL))
+        {
+            gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
+            checkGLcall("glFramebufferTexture2D()");
+        }
+    }
+    else
+    {
+        gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
+        checkGLcall("glFramebufferTexture2D()");
+
+        gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
+        checkGLcall("glFramebufferTexture2D()");
+    }
+}
+
+/* Context activation is done by the caller. */
+static void context_attach_surface_fbo(struct wined3d_context *context,
+        GLenum fbo_target, DWORD idx, struct wined3d_surface *surface, DWORD location)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    TRACE("Attach surface %p to %u\n", surface, idx);
+
+    if (surface && surface->resource.format->id != WINED3DFMT_NULL)
+    {
+        BOOL srgb;
+
+        switch (location)
+        {
+            case SFLAG_INTEXTURE:
+            case SFLAG_INSRGBTEX:
+                srgb = location == SFLAG_INSRGBTEX;
+                surface_prepare_texture(surface, context, srgb);
+                gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_COLOR_ATTACHMENT0 + idx,
+                        surface->texture_target, surface_get_texture_name(surface, gl_info, srgb),
+                        surface->texture_level);
+                checkGLcall("glFramebufferTexture2D()");
+                break;
+
+            case SFLAG_INRB_MULTISAMPLE:
+                surface_prepare_rb(surface, gl_info, TRUE);
+                gl_info->fbo_ops.glFramebufferRenderbuffer(fbo_target, GL_COLOR_ATTACHMENT0 + idx,
+                        GL_RENDERBUFFER, surface->rb_multisample);
+                checkGLcall("glFramebufferRenderbuffer()");
+                break;
+
+            case SFLAG_INRB_RESOLVED:
+                surface_prepare_rb(surface, gl_info, FALSE);
+                gl_info->fbo_ops.glFramebufferRenderbuffer(fbo_target, GL_COLOR_ATTACHMENT0 + idx,
+                        GL_RENDERBUFFER, surface->rb_resolved);
+                checkGLcall("glFramebufferRenderbuffer()");
+                break;
+
+            default:
+                ERR("Unsupported location %s (%#x).\n", debug_surflocation(location), location);
+                break;
+        }
+    }
+    else
+    {
+        gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_COLOR_ATTACHMENT0 + idx, GL_TEXTURE_2D, 0, 0);
+        checkGLcall("glFramebufferTexture2D()");
+    }
+}
+
+/* Context activation is done by the caller. */
+void context_check_fbo_status(const struct wined3d_context *context, GLenum target)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    GLenum status;
+
+    if (!FIXME_ON(d3d)) return;
+
+    status = gl_info->fbo_ops.glCheckFramebufferStatus(target);
+    if (status == GL_FRAMEBUFFER_COMPLETE)
+    {
+        TRACE("FBO complete\n");
+    }
+    else
+    {
+        const struct wined3d_surface *attachment;
+        unsigned int i;
+
+        FIXME("FBO status %s (%#x)\n", debug_fbostatus(status), status);
+
+        if (!context->current_fbo)
+        {
+            ERR("FBO 0 is incomplete, driver bug?\n");
+            return;
+        }
+
+        FIXME("\tLocation %s (%#x).\n", debug_surflocation(context->current_fbo->location),
+                context->current_fbo->location);
+
+        /* Dump the FBO attachments */
+        for (i = 0; i < gl_info->limits.buffers; ++i)
+        {
+            attachment = context->current_fbo->render_targets[i];
+            if (attachment)
+            {
+                FIXME("\tColor attachment %d: (%p) %s %ux%u %u samples.\n",
+                        i, attachment, debug_d3dformat(attachment->resource.format->id),
+                        attachment->pow2Width, attachment->pow2Height, attachment->resource.multisample_type);
+            }
+        }
+        attachment = context->current_fbo->depth_stencil;
+        if (attachment)
+        {
+            FIXME("\tDepth attachment: (%p) %s %ux%u %u samples.\n",
+                    attachment, debug_d3dformat(attachment->resource.format->id),
+                    attachment->pow2Width, attachment->pow2Height, attachment->resource.multisample_type);
+        }
+    }
+}
+
+static inline DWORD context_generate_rt_mask(GLenum buffer)
+{
+    /* Should take care of all the GL_FRONT/GL_BACK/GL_AUXi/GL_NONE... cases */
+    return buffer ? (1 << 31) | buffer : 0;
+}
+
+static inline DWORD context_generate_rt_mask_from_surface(const struct wined3d_surface *target)
+{
+    return (1 << 31) | surface_get_gl_buffer(target);
+}
+
+static struct fbo_entry *context_create_fbo_entry(const struct wined3d_context *context,
+        struct wined3d_surface **render_targets, struct wined3d_surface *depth_stencil, DWORD location)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    struct fbo_entry *entry;
+
+    entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*entry));
+    entry->render_targets = HeapAlloc(GetProcessHeap(), 0, gl_info->limits.buffers * sizeof(*entry->render_targets));
+    memcpy(entry->render_targets, render_targets, gl_info->limits.buffers * sizeof(*entry->render_targets));
+    entry->depth_stencil = depth_stencil;
+    entry->location = location;
+    entry->rt_mask = context_generate_rt_mask(GL_COLOR_ATTACHMENT0);
+    entry->attached = FALSE;
+    gl_info->fbo_ops.glGenFramebuffers(1, &entry->id);
+    checkGLcall("glGenFramebuffers()");
+    TRACE("Created FBO %u.\n", entry->id);
+
+    return entry;
+}
+
+/* Context activation is done by the caller. */
+static void context_reuse_fbo_entry(struct wined3d_context *context, GLenum target,
+        struct wined3d_surface **render_targets, struct wined3d_surface *depth_stencil,
+        DWORD location, struct fbo_entry *entry)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    context_bind_fbo(context, target, entry->id);
+    context_clean_fbo_attachments(gl_info, target);
+
+    memcpy(entry->render_targets, render_targets, gl_info->limits.buffers * sizeof(*entry->render_targets));
+    entry->depth_stencil = depth_stencil;
+    entry->location = location;
+    entry->attached = FALSE;
+}
+
+/* Context activation is done by the caller. */
+static void context_destroy_fbo_entry(struct wined3d_context *context, struct fbo_entry *entry)
+{
+    if (entry->id)
+    {
+        TRACE("Destroy FBO %u.\n", entry->id);
+        context_destroy_fbo(context, entry->id);
+    }
+    --context->fbo_entry_count;
+    list_remove(&entry->entry);
+    HeapFree(GetProcessHeap(), 0, entry->render_targets);
+    HeapFree(GetProcessHeap(), 0, entry);
+}
+
+
+/* Context activation is done by the caller. */
+static struct fbo_entry *context_find_fbo_entry(struct wined3d_context *context, GLenum target,
+        struct wined3d_surface **render_targets, struct wined3d_surface *depth_stencil, DWORD location)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    struct fbo_entry *entry;
+
+    if (depth_stencil && render_targets && render_targets[0])
+    {
+        if (depth_stencil->resource.width < render_targets[0]->resource.width ||
+            depth_stencil->resource.height < render_targets[0]->resource.height)
+        {
+            WARN("Depth stencil is smaller than the primary color buffer, disabling\n");
+            depth_stencil = NULL;
+        }
+    }
+
+    LIST_FOR_EACH_ENTRY(entry, &context->fbo_list, struct fbo_entry, entry)
+    {
+        if (!memcmp(entry->render_targets,
+                render_targets, gl_info->limits.buffers * sizeof(*entry->render_targets))
+                && entry->depth_stencil == depth_stencil && entry->location == location)
+        {
+            list_remove(&entry->entry);
+            list_add_head(&context->fbo_list, &entry->entry);
+            return entry;
+        }
+    }
+
+    if (context->fbo_entry_count < WINED3D_MAX_FBO_ENTRIES)
+    {
+        entry = context_create_fbo_entry(context, render_targets, depth_stencil, location);
+        list_add_head(&context->fbo_list, &entry->entry);
+        ++context->fbo_entry_count;
+    }
+    else
+    {
+        entry = LIST_ENTRY(list_tail(&context->fbo_list), struct fbo_entry, entry);
+        context_reuse_fbo_entry(context, target, render_targets, depth_stencil, location, entry);
+        list_remove(&entry->entry);
+        list_add_head(&context->fbo_list, &entry->entry);
+    }
+
+    return entry;
+}
+
+/* Context activation is done by the caller. */
+static void context_apply_fbo_entry(struct wined3d_context *context, GLenum target, struct fbo_entry *entry)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    unsigned int i;
+    GLuint read_binding, draw_binding;
+
+    if (entry->attached)
+    {
+        context_bind_fbo(context, target, entry->id);
+        return;
+    }
+
+    read_binding = context->fbo_read_binding;
+    draw_binding = context->fbo_draw_binding;
+    context_bind_fbo(context, GL_FRAMEBUFFER, entry->id);
+
+    /* Apply render targets */
+    for (i = 0; i < gl_info->limits.buffers; ++i)
+    {
+        context_attach_surface_fbo(context, target, i, entry->render_targets[i], entry->location);
+    }
+
+    /* Apply depth targets */
+    if (entry->depth_stencil)
+        surface_set_compatible_renderbuffer(entry->depth_stencil, entry->render_targets[0]);
+    context_attach_depth_stencil_fbo(context, target, entry->depth_stencil, entry->location);
+
+    /* Set valid read and draw buffer bindings to satisfy pedantic pre-ES2_compatibility
+     * GL contexts requirements. */
+    glReadBuffer(GL_NONE);
+    context_set_draw_buffer(context, GL_NONE);
+    if (target != GL_FRAMEBUFFER)
+    {
+        if (target == GL_READ_FRAMEBUFFER)
+            context_bind_fbo(context, GL_DRAW_FRAMEBUFFER, draw_binding);
+        else
+            context_bind_fbo(context, GL_READ_FRAMEBUFFER, read_binding);
+    }
+
+    entry->attached = TRUE;
+}
+
+/* Context activation is done by the caller. */
+static void context_apply_fbo_state(struct wined3d_context *context, GLenum target,
+        struct wined3d_surface **render_targets, struct wined3d_surface *depth_stencil, DWORD location)
+{
+    struct fbo_entry *entry, *entry2;
+
+    LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &context->fbo_destroy_list, struct fbo_entry, entry)
+    {
+        context_destroy_fbo_entry(context, entry);
+    }
+
+    if (context->rebind_fbo)
+    {
+        context_bind_fbo(context, GL_FRAMEBUFFER, 0);
+        context->rebind_fbo = FALSE;
+    }
+
+    if (location == SFLAG_INDRAWABLE)
+    {
+        context->current_fbo = NULL;
+        context_bind_fbo(context, target, 0);
+    }
+    else
+    {
+        context->current_fbo = context_find_fbo_entry(context, target, render_targets, depth_stencil, location);
+        context_apply_fbo_entry(context, target, context->current_fbo);
+    }
+}
+
+/* Context activation is done by the caller. */
+void context_apply_fbo_state_blit(struct wined3d_context *context, GLenum target,
+        struct wined3d_surface *render_target, struct wined3d_surface *depth_stencil, DWORD location)
+{
+    UINT clear_size = (context->gl_info->limits.buffers - 1) * sizeof(*context->blit_targets);
+
+    context->blit_targets[0] = render_target;
+    if (clear_size)
+        memset(&context->blit_targets[1], 0, clear_size);
+    context_apply_fbo_state(context, target, context->blit_targets, depth_stencil, location);
+}
+
+/* Context activation is done by the caller. */
+void context_alloc_occlusion_query(struct wined3d_context *context, struct wined3d_occlusion_query *query)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    if (context->free_occlusion_query_count)
+    {
+        query->id = context->free_occlusion_queries[--context->free_occlusion_query_count];
+    }
+    else
+    {
+        if (gl_info->supported[ARB_OCCLUSION_QUERY])
+        {
+            GL_EXTCALL(glGenQueriesARB(1, &query->id));
+            checkGLcall("glGenQueriesARB");
+
+            TRACE("Allocated occlusion query %u in context %p.\n", query->id, context);
+        }
+        else
+        {
+            WARN("Occlusion queries not supported, not allocating query id.\n");
+            query->id = 0;
+        }
+    }
+
+    query->context = context;
+    list_add_head(&context->occlusion_queries, &query->entry);
+}
+
+void context_free_occlusion_query(struct wined3d_occlusion_query *query)
+{
+    struct wined3d_context *context = query->context;
+
+    list_remove(&query->entry);
+    query->context = NULL;
+
+    if (context->free_occlusion_query_count >= context->free_occlusion_query_size - 1)
+    {
+        UINT new_size = context->free_occlusion_query_size << 1;
+        GLuint *new_data = HeapReAlloc(GetProcessHeap(), 0, context->free_occlusion_queries,
+                new_size * sizeof(*context->free_occlusion_queries));
+
+        if (!new_data)
+        {
+            ERR("Failed to grow free list, leaking query %u in context %p.\n", query->id, context);
+            return;
+        }
+
+        context->free_occlusion_query_size = new_size;
+        context->free_occlusion_queries = new_data;
+    }
+
+    context->free_occlusion_queries[context->free_occlusion_query_count++] = query->id;
+}
+
+/* Context activation is done by the caller. */
+void context_alloc_event_query(struct wined3d_context *context, struct wined3d_event_query *query)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    if (context->free_event_query_count)
+    {
+        query->object = context->free_event_queries[--context->free_event_query_count];
+    }
+    else
+    {
+        if (gl_info->supported[ARB_SYNC])
+        {
+            /* Using ARB_sync, not much to do here. */
+            query->object.sync = NULL;
+            TRACE("Allocated event query %p in context %p.\n", query->object.sync, context);
+        }
+        else if (gl_info->supported[APPLE_FENCE])
+        {
+            GL_EXTCALL(glGenFencesAPPLE(1, &query->object.id));
+            checkGLcall("glGenFencesAPPLE");
+
+            TRACE("Allocated event query %u in context %p.\n", query->object.id, context);
+        }
+        else if(gl_info->supported[NV_FENCE])
+        {
+            GL_EXTCALL(glGenFencesNV(1, &query->object.id));
+            checkGLcall("glGenFencesNV");
+
+            TRACE("Allocated event query %u in context %p.\n", query->object.id, context);
+        }
+        else
+        {
+            WARN("Event queries not supported, not allocating query id.\n");
+            query->object.id = 0;
+        }
+    }
+
+    query->context = context;
+    list_add_head(&context->event_queries, &query->entry);
+}
+
+void context_free_event_query(struct wined3d_event_query *query)
+{
+    struct wined3d_context *context = query->context;
+
+    list_remove(&query->entry);
+    query->context = NULL;
+
+    if (context->free_event_query_count >= context->free_event_query_size - 1)
+    {
+        UINT new_size = context->free_event_query_size << 1;
+        union wined3d_gl_query_object *new_data = HeapReAlloc(GetProcessHeap(), 0, context->free_event_queries,
+                new_size * sizeof(*context->free_event_queries));
+
+        if (!new_data)
+        {
+            ERR("Failed to grow free list, leaking query %u in context %p.\n", query->object.id, context);
+            return;
+        }
+
+        context->free_event_query_size = new_size;
+        context->free_event_queries = new_data;
+    }
+
+    context->free_event_queries[context->free_event_query_count++] = query->object;
+}
+
+typedef void (context_fbo_entry_func_t)(struct wined3d_context *context, struct fbo_entry *entry);
+
+static void context_enum_surface_fbo_entries(const struct wined3d_device *device,
+        const struct wined3d_surface *surface, context_fbo_entry_func_t *callback)
+{
+    UINT i;
+
+    for (i = 0; i < device->context_count; ++i)
+    {
+        struct wined3d_context *context = device->contexts[i];
+        const struct wined3d_gl_info *gl_info = context->gl_info;
+        struct fbo_entry *entry, *entry2;
+
+        if (context->current_rt == surface) context->current_rt = NULL;
+
+        LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &context->fbo_list, struct fbo_entry, entry)
+        {
+            UINT j;
+
+            if (entry->depth_stencil == surface)
+            {
+                callback(context, entry);
+                continue;
+            }
+
+            for (j = 0; j < gl_info->limits.buffers; ++j)
+            {
+                if (entry->render_targets[j] == surface)
+                {
+                    callback(context, entry);
+                    break;
+                }
+            }
+        }
+    }
+}
+
+static void context_queue_fbo_entry_destruction(struct wined3d_context *context, struct fbo_entry *entry)
+{
+    list_remove(&entry->entry);
+    list_add_head(&context->fbo_destroy_list, &entry->entry);
+}
+
+void context_resource_released(const struct wined3d_device *device,
+        struct wined3d_resource *resource, enum wined3d_resource_type type)
+{
+    if (!device->d3d_initialized) return;
+
+    switch (type)
+    {
+        case WINED3D_RTYPE_SURFACE:
+            context_enum_surface_fbo_entries(device, surface_from_resource(resource),
+                    context_queue_fbo_entry_destruction);
+            break;
+
+        default:
+            break;
+    }
+}
+
+static void context_detach_fbo_entry(struct wined3d_context *context, struct fbo_entry *entry)
+{
+    entry->attached = FALSE;
+}
+
+void context_resource_unloaded(const struct wined3d_device *device,
+        struct wined3d_resource *resource, enum wined3d_resource_type type)
+{
+    switch (type)
+    {
+        case WINED3D_RTYPE_SURFACE:
+            context_enum_surface_fbo_entries(device, surface_from_resource(resource),
+                    context_detach_fbo_entry);
+            break;
+
+        default:
+            break;
+    }
+}
+
+void context_surface_update(struct wined3d_context *context, const struct wined3d_surface *surface)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    struct fbo_entry *entry = context->current_fbo;
+    unsigned int i;
+
+    if (!entry || context->rebind_fbo) return;
+
+    for (i = 0; i < gl_info->limits.buffers; ++i)
+    {
+        if (surface == entry->render_targets[i])
+        {
+            TRACE("Updated surface %p is bound as color attachment %u to the current FBO.\n", surface, i);
+            context->rebind_fbo = TRUE;
+            return;
+        }
+    }
+
+    if (surface == entry->depth_stencil)
+    {
+        TRACE("Updated surface %p is bound as depth attachment to the current FBO.\n", surface);
+        context->rebind_fbo = TRUE;
+    }
+}
+
+#ifndef VBOX
+static BOOL context_set_pixel_format(const struct wined3d_gl_info *gl_info, HDC dc, int format)
+{
+    int current = GetPixelFormat(dc);
+
+    if (current == format) return TRUE;
+
+    if (!current)
+    {
+        if (!SetPixelFormat(dc, format, NULL))
+        {
+            /* This may also happen if the dc belongs to a destroyed window. */
+            WARN("Failed to set pixel format %d on device context %p, last error %#x.\n",
+                    format, dc, GetLastError());
+            return FALSE;
+        }
+        return TRUE;
+    }
+
+    /* By default WGL doesn't allow pixel format adjustments but we need it
+     * here. For this reason there's a Wine specific wglSetPixelFormat()
+     * which allows us to set the pixel format multiple times. Only use it
+     * when really needed. */
+    if (gl_info->supported[WGL_WINE_PIXEL_FORMAT_PASSTHROUGH])
+    {
+        if (!GL_EXTCALL(wglSetPixelFormatWINE(dc, format)))
+        {
+            ERR("wglSetPixelFormatWINE failed to set pixel format %d on device context %p.\n",
+                    format, dc);
+            return FALSE;
+        }
+        return TRUE;
+    }
+
+    /* OpenGL doesn't allow pixel format adjustments. Print an error and
+     * continue using the old format. There's a big chance that the old
+     * format works although with a performance hit and perhaps rendering
+     * errors. */
+    ERR("Unable to set pixel format %d on device context %p. Already using format %d.\n",
+            format, dc, current);
+    return TRUE;
+}
+#endif
+
+static BOOL context_set_gl_context(struct wined3d_context *ctx)
+{
+    struct wined3d_swapchain *swapchain = ctx->swapchain;
+#ifndef VBOX
+    BOOL backup = FALSE;
+
+    if (!context_set_pixel_format(ctx->gl_info, ctx->hdc, ctx->pixel_format))
+    {
+        WARN("Failed to set pixel format %d on device context %p.\n",
+                ctx->pixel_format, ctx->hdc);
+        backup = TRUE;
+    }
+
+    if (backup || !wglMakeCurrent(ctx->hdc, ctx->glCtx))
+#else
+    if (!wglMakeCurrent(ctx->swapchain->hDC, ctx->glCtx))
+#endif
+    {
+#ifndef VBOX_WITH_WDDM
+        HDC dc;
+#endif
+
+#ifndef VBOX
+        WARN("Failed to make GL context %p current on device context %p, last error %#x.\n",
+                ctx->glCtx, ctx->hdc, GetLastError());
+#else
+        WARN("Failed to make GL context %p current on device context %p, last error %#x.\n",
+                ctx->glCtx, ctx->swapchain->hDC, GetLastError());
+#endif
+        ctx->valid = 0;
+        WARN("Trying fallback to the backup window.\n");
+#if !defined(VBOX_WINE_WITH_SINGLE_CONTEXT) && !defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
+        /* FIXME: If the context is destroyed it's no longer associated with
+         * a swapchain, so we can't use the swapchain to get a backup dc. To
+         * make this work windowless contexts would need to be handled by the
+         * device. */
+        if (ctx->destroyed)
+        {
+            FIXME("Unable to get backup dc for destroyed context %p.\n", ctx);
+            context_set_current(NULL);
+            return FALSE;
+        }
+#endif
+#ifndef VBOX_WITH_WDDM
+        if (!(dc = swapchain_get_backup_dc(swapchain)))
+        {
+            context_set_current(NULL);
+            return FALSE;
+        }
+#ifndef VBOX
+        if (!context_set_pixel_format(ctx->gl_info, dc, ctx->pixel_format))
+        {
+            ERR("Failed to set pixel format %d on device context %p.\n",
+                    ctx->pixel_format, dc);
+            context_set_current(NULL);
+            return FALSE;
+        }
+#endif
+        if (!wglMakeCurrent(dc, ctx->glCtx))
+        {
+            ERR("Fallback to backup window (dc %p) failed too, last error %#x.\n",
+                    dc, GetLastError());
+            context_set_current(NULL);
+            return FALSE;
+        }
+#else
+        return FALSE;
+#endif
+    }
+    return TRUE;
+}
+
+static void context_restore_gl_context(const struct wined3d_gl_info *gl_info, HDC dc, HGLRC gl_ctx, int pf)
+{
+#ifndef VBOX
+    if (!context_set_pixel_format(gl_info, dc, pf))
+    {
+        ERR("Failed to restore pixel format %d on device context %p.\n", pf, dc);
+        context_set_current(NULL);
+        return;
+    }
+#endif
+    if (!wglMakeCurrent(dc, gl_ctx))
+    {
+        ERR("Failed to restore GL context %p on device context %p, last error %#x.\n",
+                gl_ctx, dc, GetLastError());
+        context_set_current(NULL);
+    }
+#ifdef VBOX
+    else
+    {
+        /* success branch */
+        /* sync back our tls with gl settings  */
+        const struct wined3d_context *current_context = context_get_current();
+        if (current_context && current_context->glCtx != gl_ctx)
+        {
+            UINT i = 0;
+            struct wined3d_device *device = current_context->swapchain->device;
+            for (; i < device->context_count; ++i)
+            {
+                struct wined3d_context *ctx = device->contexts[i];
+                if (ctx->glCtx == gl_ctx)
+                {
+                    context_set_current(ctx);
+                    break;
+                }
+            }
+
+            if (i == device->context_count)
+            {
+                context_set_current(NULL);
+            }
+        }
+    }
+#endif
+}
+
+#ifdef VBOX_WINE_WITH_SINGLE_CONTEXT
+static BOOL swapchain_validate(const struct wined3d_swapchain *swapchain)
+{
+    if (!swapchain->hDC)
+    {
+        ERR("NULL hDC");
+        return FALSE;
+    }
+
+#if defined(DEBUG) || !defined(VBOX_WITH_WDDM)
+    {
+        HWND hWnd = WindowFromDC(swapchain->hDC);
+        if (hWnd != swapchain->win_handle)
+        {
+# if defined(VBOX_WITH_WDDM)
+            ERR("Unexpected swapchain for dc %p window expected %p, but was %p.\n", swapchain->hDC, swapchain->win_handle, hWnd);
+# else
+            ERR("Swapchain for dc %p window expected %p, but was %p.\n", swapchain->hDC, swapchain->win_handle, hWnd);
+            return FALSE;
+# endif
+        }
+    }
+#endif
+    return TRUE;
+}
+
+static struct wined3d_swapchain* swapchain_find_valid(const struct wined3d_device *device)
+{
+    int i;
+    struct wined3d_context * context = device->contexts[0];
+    struct wined3d_swapchain* swapchain = NULL;
+    if (context)
+    {
+        swapchain = context->swapchain;
+        if (swapchain && swapchain_validate(swapchain))
+        {
+            return swapchain;
+        }
+    }
+    for (i = device->swapchain_count - 1; i >= 0 ; --i)
+    {
+        Assert(device->swapchains[i]);
+        if (swapchain != device->swapchains[i] /* the current context swapchain is known to be invalid */
+              && swapchain_validate(device->swapchains[i]))
+        {
+            return device->swapchains[i];
+        }
+    }
+
+    return NULL;
+}
+
+static struct wined3d_swapchain* swapchain_find_valid_or_any(const struct wined3d_device *device)
+{
+    struct wined3d_swapchain* swapchain = swapchain_find_valid(device);
+    if (swapchain)
+        return swapchain;
+
+    ERR("no valid swapchain found!");
+    swapchain = device->swapchains[0];
+    Assert(swapchain);
+    return swapchain;
+}
+
+struct wined3d_context *context_find_create(struct wined3d_device *device,
+        struct wined3d_swapchain *swapchain,
+        const struct wined3d_format *ds_format)
+{
+    struct wined3d_context *context;
+    struct wined3d_surface *target = swapchain->back_buffers ? swapchain->back_buffers[0] : swapchain->front_buffer;
+    if (!device->context_count)
+    {
+        Assert(!device->swapchain_count);
+        context = context_create(swapchain, target, ds_format
+#ifdef VBOX_WITH_WDDM
+                , device->pHgsmi
+#endif
+                );
+        if(!context)
+        {
+            ERR("Failed to create the context.\n");
+        }
+        else
+        {
+            Assert(context->valid);
+        }
+    }
+    else
+    {
+        context = context_acquire(device, target);
+        if(!context)
+        {
+            ERR("Failed to acquire the context.\n");
+        }
+        else
+        {
+            Assert(context->valid);
+        }
+    }
+
+    return context;
+}
+
+#endif
+
+static void context_update_window(struct wined3d_context *context
+#ifdef VBOX_WINE_WITH_SINGLE_CONTEXT
+        , struct wined3d_swapchain *swapchain
+#endif
+        )
+{
+#ifdef VBOX_WINE_WITH_SINGLE_CONTEXT
+    TRACE("Updating context %p swapchain from %p to %p.\n",
+            context, context->swapchain, swapchain);
+
+    if (context->swapchain == swapchain)
+        return;
+
+    if (!swapchain_validate(swapchain))
+    {
+        ERR("invalid swapchain %p\n", swapchain);
+        goto err;
+    }
+    context->swapchain = swapchain;
+
+    context->valid = 1;
+
+    context_set_gl_context(context);
+#else
+    if (context->win_handle == context->swapchain->win_handle)
+        return;
+
+    TRACE("Updating context %p window from %p to %p.\n",
+            context, context->win_handle, context->swapchain->win_handle);
+
+    if (context->valid)
+    {
+        /* You'd figure ReleaseDC() would fail if the DC doesn't match the
+         * window. However, that's not what actually happens, and there are
+         * user32 tests that confirm ReleaseDC() with the wrong window is
+         * supposed to succeed. So explicitly check that the DC belongs to
+         * the window, since we want to avoid releasing a DC that belongs to
+         * some other window if the original window was already destroyed. */
+        if (WindowFromDC(context->hdc) != context->win_handle)
+        {
+            WARN("DC %p does not belong to window %p.\n",
+                    context->hdc, context->win_handle);
+        }
+#ifndef VBOX
+        else if (!ReleaseDC(context->win_handle, context->hdc))
+#else
+        else if (!VBoxExtReleaseDC(context->win_handle, context->hdc))
+#endif
+        {
+            ERR("Failed to release device context %p, last error %#x.\n",
+                    context->hdc, GetLastError());
+        }
+    }
+    else context->valid = 1;
+
+    context->win_handle = context->swapchain->win_handle;
+
+#ifndef VBOX
+    if (!(context->hdc = GetDC(context->win_handle)))
+#else
+    if (!(context->hdc = VBoxExtGetDC(context->win_handle)))
+#endif
+    {
+        ERR("Failed to get a device context for window %p.\n", context->win_handle);
+        goto err;
+    }
+#ifndef VBOX
+    if (!context_set_pixel_format(context->gl_info, context->hdc, context->pixel_format))
+    {
+        ERR("Failed to set pixel format %d on device context %p.\n",
+                context->pixel_format, context->hdc);
+        goto err;
+    }
+#endif
+    context_set_gl_context(context);
+#endif
+    return;
+
+err:
+    context->valid = 0;
+}
+
+#ifdef VBOX_WINE_WITH_SINGLE_CONTEXT
+static void context_adjust_any_valid(struct wined3d_context *context)
+{
+    struct wined3d_swapchain* swapchain = context->swapchain;
+
+    if (context->valid && swapchain && swapchain_validate(swapchain))
+        return;
+
+    swapchain = swapchain_find_valid(context->device);
+    if (!swapchain)
+    {
+        ERR("no valid swapchain found");
+        Assert(!context->valid);
+        return;
+    }
+
+    context_update_window(context, swapchain);
+}
+#endif
+
+/* Do not call while under the GL lock. */
+static void context_destroy_gl_resources(struct wined3d_context *context)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    struct wined3d_occlusion_query *occlusion_query;
+    struct wined3d_event_query *event_query;
+    struct fbo_entry *entry, *entry2;
+    HGLRC restore_ctx;
+    HDC restore_dc;
+    unsigned int i;
+    int restore_pf;
+
+    restore_ctx = wglGetCurrentContext();
+    restore_dc = wglGetCurrentDC();
+    restore_pf = GetPixelFormat(restore_dc);
+
+#ifndef VBOX_WINE_WITH_SINGLE_CONTEXT
+    if (context->valid && restore_ctx != context->glCtx)
+        context_set_gl_context(context);
+#else
+    if (restore_ctx != context->glCtx)
+        context_adjust_any_valid(context);
+#endif
+    else
+        restore_ctx = NULL;
+
+
+    LIST_FOR_EACH_ENTRY(occlusion_query, &context->occlusion_queries, struct wined3d_occlusion_query, entry)
+    {
+        if (context->valid && gl_info->supported[ARB_OCCLUSION_QUERY])
+            GL_EXTCALL(glDeleteQueriesARB(1, &occlusion_query->id));
+        occlusion_query->context = NULL;
+    }
+
+    LIST_FOR_EACH_ENTRY(event_query, &context->event_queries, struct wined3d_event_query, entry)
+    {
+        if (context->valid)
+        {
+            if (gl_info->supported[ARB_SYNC])
+            {
+                if (event_query->object.sync) GL_EXTCALL(glDeleteSync(event_query->object.sync));
+            }
+            else if (gl_info->supported[APPLE_FENCE]) GL_EXTCALL(glDeleteFencesAPPLE(1, &event_query->object.id));
+            else if (gl_info->supported[NV_FENCE]) GL_EXTCALL(glDeleteFencesNV(1, &event_query->object.id));
+        }
+        event_query->context = NULL;
+    }
+
+    LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &context->fbo_destroy_list, struct fbo_entry, entry)
+    {
+        if (!context->valid) entry->id = 0;
+        context_destroy_fbo_entry(context, entry);
+    }
+
+    LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &context->fbo_list, struct fbo_entry, entry)
+    {
+        if (!context->valid) entry->id = 0;
+        context_destroy_fbo_entry(context, entry);
+    }
+
+    if (context->valid)
+    {
+        if (context->dummy_arbfp_prog)
+        {
+            GL_EXTCALL(glDeleteProgramsARB(1, &context->dummy_arbfp_prog));
+        }
+
+        if (gl_info->supported[ARB_OCCLUSION_QUERY])
+            GL_EXTCALL(glDeleteQueriesARB(context->free_occlusion_query_count, context->free_occlusion_queries));
+
+        if (gl_info->supported[ARB_SYNC])
+        {
+            for (i = 0; i < context->free_event_query_count; ++i)
+            {
+                GL_EXTCALL(glDeleteSync(context->free_event_queries[i].sync));
+            }
+        }
+        else if (gl_info->supported[APPLE_FENCE])
+        {
+            for (i = 0; i < context->free_event_query_count; ++i)
+            {
+                GL_EXTCALL(glDeleteFencesAPPLE(1, &context->free_event_queries[i].id));
+            }
+        }
+        else if (gl_info->supported[NV_FENCE])
+        {
+            for (i = 0; i < context->free_event_query_count; ++i)
+            {
+                GL_EXTCALL(glDeleteFencesNV(1, &context->free_event_queries[i].id));
+            }
+        }
+
+        checkGLcall("context cleanup");
+    }
+
+    HeapFree(GetProcessHeap(), 0, context->free_occlusion_queries);
+    HeapFree(GetProcessHeap(), 0, context->free_event_queries);
+
+    if (restore_ctx)
+    {
+        context_restore_gl_context(gl_info, restore_dc, restore_ctx, restore_pf);
+    }
+    else if (wglGetCurrentContext() && !wglMakeCurrent(NULL, NULL))
+    {
+        ERR("Failed to disable GL context.\n");
+    }
+
+#ifndef VBOX_WITH_WDDM
+# ifndef VBOX_WINE_WITH_SINGLE_CONTEXT
+#  ifndef VBOX
+    ReleaseDC(context->win_handle, context->hdc);
+#  else
+    VBoxExtReleaseDC(context->win_handle, context->hdc);
+#  endif
+# endif
+#endif
+
+    if (!wglDeleteContext(context->glCtx))
+    {
+        DWORD err = GetLastError();
+        ERR("wglDeleteContext(%p) failed, last error %#x.\n", context->glCtx, err);
+    }
+}
+
+DWORD context_get_tls_idx(void)
+{
+    return wined3d_context_tls_idx;
+}
+
+void context_set_tls_idx(DWORD idx)
+{
+    wined3d_context_tls_idx = idx;
+}
+
+#if defined(VBOX_WINE_WITH_SINGLE_CONTEXT) || defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
+static struct wined3d_context *context_get_current_ex(DWORD adjustTid)
+{
+    struct wined3d_context *ctx = vboxGetCurrentContext();
+    if (ctx && !VBoxTlsRefIsFunctional(ctx))
+    {
+        /* this is a destroyed context left in the tls of the current thread */
+        /* 1. this releases the context and clears the tls */
+        vboxSetCurrentContext(NULL);
+        /* return there is no context current */
+        return NULL;
+    }
+    if (!adjustTid)
+        return ctx;
+    if (!ctx || ctx->tid == adjustTid)
+        return ctx;
+    /* the context may have cleared swapchain (if swapchain was destroyed), ensure it has some valid swapchain set */
+    if (context_set_current(ctx))
+    {
+        Assert(ctx->tid == adjustTid);
+        return ctx;
+    }
+    ERR("context_set_current failed\n");
+    return NULL;
+}
+#endif
+
+struct wined3d_context *context_get_current(void)
+{
+#if !defined(VBOX_WINE_WITH_SINGLE_CONTEXT) && !defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
+    return TlsGetValue(wined3d_context_tls_idx);
+#else
+    DWORD tid = GetCurrentThreadId();
+    return context_get_current_ex(tid);
+#endif
+}
+
+/* Do not call while under the GL lock. */
+BOOL context_set_current(struct wined3d_context *ctx)
+{
+#if defined(VBOX_WINE_WITH_SINGLE_CONTEXT) || defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
+    struct wined3d_context *old = context_get_current_ex(0);
+    DWORD tid = GetCurrentThreadId();
+#else
+    struct wined3d_context *old = context_get_current();
+#endif
+
+    if (old == ctx)
+    {
+#if defined(VBOX_WINE_WITH_SINGLE_CONTEXT) || defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
+        if (ctx && ctx->tid != tid)
+        {
+            old = NULL;
+        }
+        else
+#endif
+        {
+        TRACE("Already using D3D context %p.\n", ctx);
+        return TRUE;
+        }
+    }
+
+    if (old)
+    {
+#if defined(VBOX_WINE_WITH_SINGLE_CONTEXT) || defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
+        old->tid = 0;
+        old->current = 0;
+#else
+        if (old->destroyed)
+        {
+            TRACE("Switching away from destroyed context %p.\n", old);
+            context_destroy_gl_resources(old);
+            HeapFree(GetProcessHeap(), 0, (void *)old->gl_info);
+            HeapFree(GetProcessHeap(), 0, old);
+        }
+        else
+        {
+            old->current = 0;
+        }
+#endif
+    }
+
+    if (ctx)
+    {
+        if (!ctx->valid)
+        {
+            ERR("Trying to make invalid context %p current\n", ctx);
+            return FALSE;
+        }
+
+#ifndef VBOX_WINE_WITH_SINGLE_CONTEXT
+        TRACE("Switching to D3D context %p, GL context %p, device context %p.\n", ctx, ctx->glCtx, ctx->hdc);
+#else
+        TRACE("Switching to D3D context %p, GL context %p, device context %p.\n", ctx, ctx->glCtx, ctx->swapchain->hDC);
+#endif
+        if (!context_set_gl_context(ctx))
+            return FALSE;
+        ctx->current = 1;
+    }
+    else if(wglGetCurrentContext())
+    {
+        TRACE("Clearing current D3D context.\n");
+        if (!wglMakeCurrent(NULL, NULL))
+        {
+            DWORD err = GetLastError();
+            ERR("Failed to clear current GL context, last error %#x.\n", err);
+#if defined(VBOX_WINE_WITH_SINGLE_CONTEXT) || defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
+            vboxSetCurrentContext(NULL);
+#else
+            TlsSetValue(wined3d_context_tls_idx, NULL);
+#endif
+            return FALSE;
+        }
+    }
+#if defined(VBOX_WINE_WITH_SINGLE_CONTEXT) || defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
+    vboxSetCurrentContext(ctx);
+    if (ctx)
+        ctx->tid = tid;
+    return TRUE;
+#else
+    return TlsSetValue(wined3d_context_tls_idx, ctx);
+#endif
+}
+
+#if defined(VBOX_WINE_WITH_SINGLE_CONTEXT) || defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
+void context_clear_on_thread_detach()
+{
+    /* In theory, we should do context_set_current(NULL) here,
+     * but since it may result in calling a context dtor, it should be done under wined3d lock.
+     * We can not acquire a wined3d lock here since this routine is called in a DllMain context
+     * and this would result in a lock order violation, which may result in a deadlock.
+     * In other words, wined3d may internally call Win32 API functions which result in
+     * a DLL lock acquisition while holding wined3d lock.
+     * So lock order should always be "wined3d lock" -> "dll lock".
+     *
+     * This is why we do the following:
+     * */
+
+    /* 1. get the current context w/o adjusting its thread id, etc. */
+    struct wined3d_context *old = context_get_current_ex(0);
+    if (!old)
+        return;
+
+//    /* there is a currently assigned context,
+//     * 2. now increase its ref count to ensure its dtor routine is not called while making set_current(NULL).
+//     * This is needed since dtor can only be run with a wined3d lock held */
+//    VBoxTlsRefAddRef(old);
+
+    /* context_tls_dtor now does only memfree, so just call it right away */
+
+    /* 3. now we can call context_set_current(NULL) */
+    context_set_current(NULL);
+
+//    /* 4. to avoid possible deadlocks we make an asynchronous call to a worker thread to make
+//     * wined3d lock - context release - wined3d unlock from there. */
+//    VBoxExtReleaseContextAsync(old);
+}
+#endif
+
+void context_release(struct wined3d_context *context)
+{
+    TRACE("Releasing context %p, level %u.\n", context, context->level);
+
+    if (WARN_ON(d3d))
+    {
+        if (!context->level)
+            WARN("Context %p is not active.\n", context);
+        else if (context != context_get_current())
+            WARN("Context %p is not the current context.\n", context);
+    }
+
+    if (!--context->level && context->restore_ctx)
+    {
+        TRACE("Restoring GL context %p on device context %p.\n", context->restore_ctx, context->restore_dc);
+        context_restore_gl_context(context->gl_info, context->restore_dc, context->restore_ctx, context->restore_pf);
+        context->restore_ctx = NULL;
+        context->restore_dc = NULL;
+    }
+}
+
+static void context_enter(struct wined3d_context *context)
+{
+    TRACE("Entering context %p, level %u.\n", context, context->level + 1);
+
+    if (!context->level++)
+    {
+        const struct wined3d_context *current_context = context_get_current();
+        HGLRC current_gl = wglGetCurrentContext();
+
+        if (current_gl && (!current_context || current_context->glCtx != current_gl))
+        {
+            TRACE("Another GL context (%p on device context %p) is already current.\n",
+                    current_gl, wglGetCurrentDC());
+            context->restore_ctx = current_gl;
+            context->restore_dc = wglGetCurrentDC();
+            context->restore_pf = GetPixelFormat(context->restore_dc);
+        }
+    }
+}
+
+void context_invalidate_state(struct wined3d_context *context, DWORD state)
+{
+    DWORD rep = context->state_table[state].representative;
+    DWORD idx;
+    BYTE shift;
+
+    if (isStateDirty(context, rep)) return;
+
+    context->dirtyArray[context->numDirtyEntries++] = rep;
+    idx = rep / (sizeof(*context->isStateDirty) * CHAR_BIT);
+    shift = rep & ((sizeof(*context->isStateDirty) * CHAR_BIT) - 1);
+    context->isStateDirty[idx] |= (1 << shift);
+}
+
+/* This function takes care of wined3d pixel format selection. */
+static int context_choose_pixel_format(const struct wined3d_device *device, HDC hdc,
+        const struct wined3d_format *color_format, const struct wined3d_format *ds_format,
+        BOOL auxBuffers, BOOL findCompatible)
+{
+    int iPixelFormat=0;
+    BYTE redBits, greenBits, blueBits, alphaBits, colorBits;
+    BYTE depthBits=0, stencilBits=0;
+    unsigned int current_value;
+    unsigned int cfg_count = device->adapter->cfg_count;
+    unsigned int i;
+
+    TRACE("device %p, dc %p, color_format %s, ds_format %s, aux_buffers %#x, find_compatible %#x.\n",
+            device, hdc, debug_d3dformat(color_format->id), debug_d3dformat(ds_format->id),
+            auxBuffers, findCompatible);
+
+    if (!getColorBits(color_format, &redBits, &greenBits, &blueBits, &alphaBits, &colorBits))
+    {
+        ERR("Unable to get color bits for format %s (%#x)!\n",
+                debug_d3dformat(color_format->id), color_format->id);
+        return 0;
+    }
+
+    getDepthStencilBits(ds_format, &depthBits, &stencilBits);
+
+    current_value = 0;
+    for (i = 0; i < cfg_count; ++i)
+    {
+        const struct wined3d_pixel_format *cfg = &device->adapter->cfgs[i];
+        unsigned int value;
+
+        /* For now only accept RGBA formats. Perhaps some day we will
+         * allow floating point formats for pbuffers. */
+        if (cfg->iPixelType != WGL_TYPE_RGBA_ARB)
+            continue;
+        /* In window mode we need a window drawable format and double buffering. */
+        if (!(cfg->windowDrawable && cfg->doubleBuffer))
+            continue;
+        if (cfg->redSize < redBits)
+            continue;
+        if (cfg->greenSize < greenBits)
+            continue;
+        if (cfg->blueSize < blueBits)
+            continue;
+        if (cfg->alphaSize < alphaBits)
+            continue;
+        if (cfg->depthSize < depthBits)
+            continue;
+        if (stencilBits && cfg->stencilSize != stencilBits)
+            continue;
+        /* Check multisampling support. */
+        if (cfg->numSamples)
+            continue;
+
+        value = 1;
+        /* We try to locate a format which matches our requirements exactly. In case of
+         * depth it is no problem to emulate 16-bit using e.g. 24-bit, so accept that. */
+        if (cfg->depthSize == depthBits)
+            value += 1;
+        if (cfg->stencilSize == stencilBits)
+            value += 2;
+        if (cfg->alphaSize == alphaBits)
+            value += 4;
+        /* We like to have aux buffers in backbuffer mode */
+        if (auxBuffers && cfg->auxBuffers)
+            value += 8;
+        if (cfg->redSize == redBits
+                && cfg->greenSize == greenBits
+                && cfg->blueSize == blueBits)
+            value += 16;
+
+        if (value > current_value)
+        {
+            iPixelFormat = cfg->iPixelFormat;
+            current_value = value;
+        }
+    }
+
+    /* When findCompatible is set and no suitable format was found, let ChoosePixelFormat choose a pixel format in order not to crash. */
+    if(!iPixelFormat && !findCompatible) {
+        ERR("Can't find a suitable iPixelFormat\n");
+        return FALSE;
+    } else if(!iPixelFormat) {
+        PIXELFORMATDESCRIPTOR pfd;
+
+        TRACE("Falling back to ChoosePixelFormat as we weren't able to find an exactly matching pixel format\n");
+        /* PixelFormat selection */
+        ZeroMemory(&pfd, sizeof(pfd));
+        pfd.nSize      = sizeof(pfd);
+        pfd.nVersion   = 1;
+        pfd.dwFlags    = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;/*PFD_GENERIC_ACCELERATED*/
+        pfd.iPixelType = PFD_TYPE_RGBA;
+        pfd.cAlphaBits = alphaBits;
+        pfd.cColorBits = colorBits;
+        pfd.cDepthBits = depthBits;
+        pfd.cStencilBits = stencilBits;
+        pfd.iLayerType = PFD_MAIN_PLANE;
+
+        iPixelFormat = ChoosePixelFormat(hdc, &pfd);
+        if(!iPixelFormat) {
+            /* If this happens something is very wrong as ChoosePixelFormat barely fails */
+            ERR("Can't find a suitable iPixelFormat\n");
+            return FALSE;
+        }
+    }
+
+    TRACE("Found iPixelFormat=%d for ColorFormat=%s, DepthStencilFormat=%s\n",
+            iPixelFormat, debug_d3dformat(color_format->id), debug_d3dformat(ds_format->id));
+    return iPixelFormat;
+}
+
+/* Context activation is done by the caller. */
+static void bind_dummy_textures(const struct wined3d_device *device, const struct wined3d_context *context)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    unsigned int i, count = min(MAX_COMBINED_SAMPLERS, gl_info->limits.combined_samplers);
+
+    for (i = 0; i < count; ++i)
+    {
+        GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
+        checkGLcall("glActiveTextureARB");
+
+        gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, device->dummy_texture_2d[i]);
+        checkGLcall("glBindTexture");
+
+        if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
+        {
+            gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_RECTANGLE_ARB, device->dummy_texture_rect[i]);
+            checkGLcall("glBindTexture");
+        }
+
+        if (gl_info->supported[EXT_TEXTURE3D])
+        {
+            gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_3D, device->dummy_texture_3d[i]);
+            checkGLcall("glBindTexture");
+        }
+
+        if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
+        {
+            gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_CUBE_MAP, device->dummy_texture_cube[i]);
+            checkGLcall("glBindTexture");
+        }
+    }
+}
+
+#if defined(VBOX_WINE_WITH_SINGLE_CONTEXT) || defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
+static DECLCALLBACK(void) context_tls_dtor(void* pvCtx)
+{
+    struct wined3d_context * context = (struct wined3d_context *)pvCtx;
+    HeapFree(GetProcessHeap(), 0, context);
+}
+#endif
+
+BOOL context_debug_output_enabled(const struct wined3d_gl_info *gl_info)
+{
+    return gl_info->supported[ARB_DEBUG_OUTPUT]
+            && (ERR_ON(d3d) || FIXME_ON(d3d) || WARN_ON(d3d_perf));
+}
+
+static void WINE_GLAPI wined3d_debug_callback(GLenum source, GLenum type, GLuint id,
+        GLenum severity, GLsizei length, const char *message, void *ctx)
+{
+    switch (type)
+    {
+        case GL_DEBUG_TYPE_ERROR_ARB:
+            ERR("%p: %s.\n", ctx, debugstr_an(message, length));
+            break;
+
+        case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB:
+        case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB:
+        case GL_DEBUG_TYPE_PORTABILITY_ARB:
+            FIXME("%p: %s.\n", ctx, debugstr_an(message, length));
+            break;
+
+        case GL_DEBUG_TYPE_PERFORMANCE_ARB:
+            WARN_(d3d_perf)("%p: %s.\n", ctx, debugstr_an(message, length));
+            break;
+
+        default:
+            FIXME("ctx %p, type %#x: %s.\n", ctx, type, debugstr_an(message, length));
+            break;
+    }
+}
+
+/* Do not call while under the GL lock. */
+struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
+        struct wined3d_surface *target, const struct wined3d_format *ds_format
+#ifdef VBOX_WITH_WDDM
+        , struct VBOXUHGSMI *pHgsmi
+#endif
+        )
+{
+    struct wined3d_device *device = swapchain->device;
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    const struct wined3d_format *color_format;
+    struct wined3d_context *ret;
+    BOOL auxBuffers = FALSE;
+    HGLRC ctx, share_ctx;
+    int pixel_format;
+    unsigned int s;
+    int swap_interval;
+    DWORD state;
+    HDC hdc;
+
+    TRACE("swapchain %p, target %p, window %p.\n", swapchain, target, swapchain->win_handle);
+
+#ifdef VBOX_WITH_WDDM
+    if (!pHgsmi)
+    {
+        ERR("HGSMI should be specified!");
+        return NULL;
+    }
+#endif
+
+    ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ret));
+    if (!ret)
+        return NULL;
+
+    ret->blit_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+            gl_info->limits.buffers * sizeof(*ret->blit_targets));
+    if (!ret->blit_targets)
+        goto out;
+
+    ret->draw_buffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+            gl_info->limits.buffers * sizeof(*ret->draw_buffers));
+    if (!ret->draw_buffers)
+        goto out;
+
+    ret->free_occlusion_query_size = 4;
+    ret->free_occlusion_queries = HeapAlloc(GetProcessHeap(), 0,
+            ret->free_occlusion_query_size * sizeof(*ret->free_occlusion_queries));
+    if (!ret->free_occlusion_queries)
+        goto out;
+
+    list_init(&ret->occlusion_queries);
+
+    ret->free_event_query_size = 4;
+    ret->free_event_queries = HeapAlloc(GetProcessHeap(), 0,
+            ret->free_event_query_size * sizeof(*ret->free_event_queries));
+    if (!ret->free_event_queries)
+        goto out;
+
+    list_init(&ret->event_queries);
+    list_init(&ret->fbo_list);
+    list_init(&ret->fbo_destroy_list);
+
+#if defined(VBOX_WINE_WITH_SINGLE_CONTEXT) || defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
+    VBoxTlsRefInit(ret, context_tls_dtor);
+#endif
+
+#ifdef VBOX_WINE_WITH_SINGLE_CONTEXT
+    ret->device = device;
+    if (!swapchain->hDC)
+    {
+        ERR("Swapchain hDC is null");
+        goto out;
+    }
+    hdc = swapchain->hDC;
+#else
+    if (!(hdc = GetDC(swapchain->win_handle)))
+    {
+        WARN("Failed to retireve device context, trying swapchain backup.\n");
+        if (!(hdc = swapchain_get_backup_dc(swapchain)))
+        {
+            ERR("Failed to retrieve a device context.\n");
+            goto out;
+        }
+    }
+#endif
+
+    color_format = target->resource.format;
+
+    /* In case of ORM_BACKBUFFER, make sure to request an alpha component for
+     * X4R4G4B4/X8R8G8B8 as we might need it for the backbuffer. */
+    if (wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER)
+    {
+        auxBuffers = TRUE;
+
+        if (color_format->id == WINED3DFMT_B4G4R4X4_UNORM)
+            color_format = wined3d_get_format(gl_info, WINED3DFMT_B4G4R4A4_UNORM);
+        else if (color_format->id == WINED3DFMT_B8G8R8X8_UNORM)
+            color_format = wined3d_get_format(gl_info, WINED3DFMT_B8G8R8A8_UNORM);
+    }
+
+    /* DirectDraw supports 8bit paletted render targets and these are used by
+     * old games like StarCraft and C&C. Most modern hardware doesn't support
+     * 8bit natively so we perform some form of 8bit -> 32bit conversion. The
+     * conversion (ab)uses the alpha component for storing the palette index.
+     * For this reason we require a format with 8bit alpha, so request
+     * A8R8G8B8. */
+    if (color_format->id == WINED3DFMT_P8_UINT)
+        color_format = wined3d_get_format(gl_info, WINED3DFMT_B8G8R8A8_UNORM);
+
+    /* Try to find a pixel format which matches our requirements. */
+    pixel_format = context_choose_pixel_format(device, hdc, color_format, ds_format, auxBuffers, FALSE);
+
+    /* Try to locate a compatible format if we weren't able to find anything. */
+    if (!pixel_format)
+    {
+        TRACE("Trying to locate a compatible pixel format because an exact match failed.\n");
+        pixel_format = context_choose_pixel_format(device, hdc, color_format, ds_format, auxBuffers, TRUE);
+    }
+
+    /* If we still don't have a pixel format, something is very wrong as ChoosePixelFormat barely fails */
+    if (!pixel_format)
+    {
+        ERR("Can't find a suitable pixel format.\n");
+        goto out;
+    }
+
+    context_enter(ret);
+#ifndef VBOX
+    if (!context_set_pixel_format(gl_info, hdc, pixel_format))
+    {
+        ERR("Failed to set pixel format %d on device context %p.\n", pixel_format, hdc);
+        context_release(ret);
+        goto out;
+    }
+
+    share_ctx = device->context_count ? device->contexts[0]->glCtx : NULL;
+    if (gl_info->p_wglCreateContextAttribsARB)
+    {
+        unsigned int ctx_attrib_idx = 0;
+        GLint ctx_attribs[3];
+
+        if (context_debug_output_enabled(gl_info))
+        {
+            ctx_attribs[ctx_attrib_idx++] = WGL_CONTEXT_FLAGS_ARB;
+            ctx_attribs[ctx_attrib_idx++] = WGL_CONTEXT_DEBUG_BIT_ARB;
+        }
+        ctx_attribs[ctx_attrib_idx] = 0;
+
+        if (!(ctx = gl_info->p_wglCreateContextAttribsARB(hdc, share_ctx, ctx_attribs)))
+        {
+            ERR("Failed to create a WGL context.\n");
+            context_release(ret);
+            goto out;
+        }
+    }
+    else
+    {
+        if (!(ctx = wglCreateContext(hdc)))
+#else
+            ctx = pVBoxCreateContext(hdc
+#ifdef VBOX_WITH_WDDM
+                    , pHgsmi
+#else
+                    , NULL
+#endif
+                    );
+        if (!ctx)
+#endif
+        {
+            ERR("Failed to create a WGL context.\n");
+            context_release(ret);
+            goto out;
+        }
+
+#ifndef VBOX
+        if (share_ctx && !wglShareLists(share_ctx, ctx))
+        {
+            ERR("wglShareLists(%p, %p) failed, last error %#x.\n", share_ctx, ctx, GetLastError());
+            context_release(ret);
+            if (!wglDeleteContext(ctx))
+                ERR("wglDeleteContext(%p) failed, last error %#x.\n", ctx, GetLastError());
+            goto out;
+        }
+    }
+#endif
+
+    if (!device_context_add(device, ret))
+    {
+        ERR("Failed to add the newly created context to the context list\n");
+        context_release(ret);
+        if (!wglDeleteContext(ctx))
+            ERR("wglDeleteContext(%p) failed, last error %#x.\n", ctx, GetLastError());
+        goto out;
+    }
+
+    ret->gl_info = gl_info;
+    ret->d3d_info = &device->adapter->d3d_info;
+    ret->state_table = device->StateTable;
+
+    /* Mark all states dirty to force a proper initialization of the states
+     * on the first use of the context. */
+    for (state = 0; state <= STATE_HIGHEST; ++state)
+    {
+        if (ret->state_table[state].representative)
+            context_invalidate_state(ret, state);
+    }
+
+    ret->swapchain = swapchain;
+    ret->current_rt = target;
+#if !defined(VBOX_WINE_WITH_SINGLE_CONTEXT) && !defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
+    ret->tid = GetCurrentThreadId();
+#else
+    ret->tid = 0;
+#endif
+
+    ret->render_offscreen = surface_is_offscreen(target);
+    ret->draw_buffers_mask = context_generate_rt_mask(GL_BACK);
+    ret->valid = 1;
+
+    ret->glCtx = ctx;
+#if !defined(VBOX_WINE_WITH_SINGLE_CONTEXT) && !defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
+    ret->win_handle = swapchain->win_handle;
+    ret->hdc = hdc;
+#endif
+    ret->pixel_format = pixel_format;
+
+    /* Set up the context defaults */
+    if (!context_set_current(ret))
+    {
+        ERR("Cannot activate context to set up defaults.\n");
+        device_context_remove(device, ret);
+        context_release(ret);
+        if (!wglDeleteContext(ctx))
+            ERR("wglDeleteContext(%p) failed, last error %#x.\n", ctx, GetLastError());
+        goto out;
+    }
+
+    if (context_debug_output_enabled(gl_info))
+    {
+        GL_EXTCALL(glDebugMessageCallbackARB(wined3d_debug_callback, ret));
+        if (TRACE_ON(d3d_synchronous))
+            gl_info->gl_ops.gl.p_glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
+        GL_EXTCALL(glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_FALSE));
+        if (ERR_ON(d3d))
+        {
+            GL_EXTCALL(glDebugMessageControlARB(GL_DONT_CARE, GL_DEBUG_TYPE_ERROR_ARB,
+                    GL_DONT_CARE, 0, NULL, GL_TRUE));
+        }
+        if (FIXME_ON(d3d))
+        {
+            GL_EXTCALL(glDebugMessageControlARB(GL_DONT_CARE, GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB,
+                    GL_DONT_CARE, 0, NULL, GL_TRUE));
+            GL_EXTCALL(glDebugMessageControlARB(GL_DONT_CARE, GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB,
+                    GL_DONT_CARE, 0, NULL, GL_TRUE));
+            GL_EXTCALL(glDebugMessageControlARB(GL_DONT_CARE, GL_DEBUG_TYPE_PORTABILITY_ARB,
+                    GL_DONT_CARE, 0, NULL, GL_TRUE));
+        }
+        if (WARN_ON(d3d_perf))
+        {
+            GL_EXTCALL(glDebugMessageControlARB(GL_DONT_CARE, GL_DEBUG_TYPE_PERFORMANCE_ARB,
+                    GL_DONT_CARE, 0, NULL, GL_TRUE));
+        }
+    }
+
+    switch (swapchain->desc.swap_interval)
+    {
+        case WINED3DPRESENT_INTERVAL_IMMEDIATE:
+            swap_interval = 0;
+            break;
+        case WINED3DPRESENT_INTERVAL_DEFAULT:
+        case WINED3DPRESENT_INTERVAL_ONE:
+            swap_interval = 1;
+            break;
+        case WINED3DPRESENT_INTERVAL_TWO:
+            swap_interval = 2;
+            break;
+        case WINED3DPRESENT_INTERVAL_THREE:
+            swap_interval = 3;
+            break;
+        case WINED3DPRESENT_INTERVAL_FOUR:
+            swap_interval = 4;
+            break;
+        default:
+            FIXME("Unknown swap interval %#x.\n", swapchain->desc.swap_interval);
+            swap_interval = 1;
+    }
+
+    if (gl_info->supported[WGL_EXT_SWAP_CONTROL])
+    {
+        if (!GL_EXTCALL(wglSwapIntervalEXT(swap_interval)))
+            ERR("wglSwapIntervalEXT failed to set swap interval %d for context %p, last error %#x\n",
+                swap_interval, ret, GetLastError());
+    }
+
+#ifdef VBOX
+    /* for WDDM case this is used for shared resource handling
+     *
+     * for XPDM this is needed to at least support texture sharing between device contexts.
+     * this is a kinda hack, but it is needed since our ogl driver currently does not support ShareLists */
+    pglChromiumParameteriCR(GL_SHARE_CONTEXT_RESOURCES_CR, GL_TRUE);
+# if defined(VBOX_WINE_WITH_SINGLE_CONTEXT) || defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
+    pglChromiumParameteriCR(GL_FLUSH_ON_THREAD_SWITCH_CR,  GL_TRUE);
+# endif
+# if defined(VBOX_WITH_WDDM)
+    pglChromiumParameteriCR(GL_HOST_WND_CREATED_HIDDEN,  GL_TRUE);
+# endif
+#endif
+
+    gl_info->gl_ops.gl.p_glGetIntegerv(GL_AUX_BUFFERS, &ret->aux_buffers);
+
+    TRACE("Setting up the screen\n");
+
+    gl_info->gl_ops.gl.p_glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
+    checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
+
+    gl_info->gl_ops.gl.p_glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
+    checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
+
+    gl_info->gl_ops.gl.p_glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
+    checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
+
+    gl_info->gl_ops.gl.p_glPixelStorei(GL_PACK_ALIGNMENT, device->surface_alignment);
+    checkGLcall("glPixelStorei(GL_PACK_ALIGNMENT, device->surface_alignment);");
+    gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_ALIGNMENT, device->surface_alignment);
+    checkGLcall("glPixelStorei(GL_UNPACK_ALIGNMENT, device->surface_alignment);");
+
+    if (gl_info->supported[APPLE_CLIENT_STORAGE])
+    {
+        /* Most textures will use client storage if supported. Exceptions are
+         * non-native power of 2 textures and textures in DIB sections. */
+        gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
+        checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
+    }
+    if (gl_info->supported[ARB_VERTEX_BLEND])
+    {
+        /* Direct3D always uses n-1 weights for n world matrices and uses
+         * 1 - sum for the last one this is equal to GL_WEIGHT_SUM_UNITY_ARB.
+         * Enabling it doesn't do anything unless GL_VERTEX_BLEND_ARB isn't
+         * enabled as well. */
+        gl_info->gl_ops.gl.p_glEnable(GL_WEIGHT_SUM_UNITY_ARB);
+        checkGLcall("glEnable(GL_WEIGHT_SUM_UNITY_ARB)");
+    }
+    if (gl_info->supported[NV_TEXTURE_SHADER2])
+    {
+        /* Set up the previous texture input for all shader units. This applies to bump mapping, and in d3d
+         * the previous texture where to source the offset from is always unit - 1.
+         */
+        for (s = 1; s < gl_info->limits.textures; ++s)
+        {
+            context_active_texture(ret, gl_info, s);
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_SHADER_NV,
+                    GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB + s - 1);
+            checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, ...");
+        }
+    }
+    if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
+    {
+        /* MacOS(radeon X1600 at least, but most likely others too) refuses to draw if GLSL and ARBFP are
+         * enabled, but the currently bound arbfp program is 0. Enabling ARBFP with prog 0 is invalid, but
+         * GLSL should bypass this. This causes problems in programs that never use the fixed function pipeline,
+         * because the ARBFP extension is enabled by the ARBFP pipeline at context creation, but no program
+         * is ever assigned.
+         *
+         * So make sure a program is assigned to each context. The first real ARBFP use will set a different
+         * program and the dummy program is destroyed when the context is destroyed.
+         */
+        const char *dummy_program =
+                "!!ARBfp1.0\n"
+                "MOV result.color, fragment.color.primary;\n"
+                "END\n";
+        GL_EXTCALL(glGenProgramsARB(1, &ret->dummy_arbfp_prog));
+        GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, ret->dummy_arbfp_prog));
+        GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(dummy_program), dummy_program));
+    }
+
+    if (gl_info->supported[ARB_POINT_SPRITE])
+    {
+        for (s = 0; s < gl_info->limits.textures; ++s)
+        {
+            context_active_texture(ret, gl_info, s);
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
+            checkGLcall("glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)");
+        }
+    }
+
+    if (gl_info->supported[ARB_PROVOKING_VERTEX])
+    {
+        GL_EXTCALL(glProvokingVertex(GL_FIRST_VERTEX_CONVENTION));
+    }
+    else if (gl_info->supported[EXT_PROVOKING_VERTEX])
+    {
+        GL_EXTCALL(glProvokingVertexEXT(GL_FIRST_VERTEX_CONVENTION_EXT));
+    }
+    ret->select_shader = 1;
+
+    /* If this happens to be the first context for the device, dummy textures
+     * are not created yet. In that case, they will be created (and bound) by
+     * create_dummy_textures right after this context is initialized. */
+    if (device->dummy_texture_2d[0])
+        bind_dummy_textures(device, ret);
+
+    TRACE("Created context %p.\n", ret);
+
+    return ret;
+
+out:
+    HeapFree(GetProcessHeap(), 0, ret->free_event_queries);
+    HeapFree(GetProcessHeap(), 0, ret->free_occlusion_queries);
+    HeapFree(GetProcessHeap(), 0, ret->draw_buffers);
+    HeapFree(GetProcessHeap(), 0, ret->blit_targets);
+    HeapFree(GetProcessHeap(), 0, ret);
+    return NULL;
+}
+
+/* Do not call while under the GL lock. */
+void context_destroy(struct wined3d_device *device, struct wined3d_context *context)
+{
+#if !defined(VBOX_WINE_WITH_SINGLE_CONTEXT) && !defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
+    BOOL destroy;
+#endif
+
+    TRACE("Destroying ctx %p\n", context);
+
+#if !defined(VBOX_WINE_WITH_SINGLE_CONTEXT) && !defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
+    if (context->tid == GetCurrentThreadId() || !context->current)
+    {
+        context_destroy_gl_resources(context);
+        TlsSetValue(wined3d_context_tls_idx, NULL);
+        destroy = TRUE;
+    }
+    else
+    {
+        /* Make a copy of gl_info for context_destroy_gl_resources use, the one
+           in wined3d_adapter may go away in the meantime */
+        struct wined3d_gl_info *gl_info = HeapAlloc(GetProcessHeap(), 0, sizeof(*gl_info));
+        *gl_info = *context->gl_info;
+        context->gl_info = gl_info;
+        context->destroyed = 1;
+        destroy = FALSE;
+    }
+#else
+    context_destroy_gl_resources(context);
+#endif
+
+    HeapFree(GetProcessHeap(), 0, context->draw_buffers);
+    HeapFree(GetProcessHeap(), 0, context->blit_targets);
+    device_context_remove(device, context);
+#if !defined(VBOX_WINE_WITH_SINGLE_CONTEXT) && !defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
+    if (destroy) HeapFree(GetProcessHeap(), 0, context);
+#else
+    context->swapchain = NULL;
+
+    VBoxTlsRefMarkDestroy(context);
+    VBoxTlsRefRelease(context);
+#endif
+}
+
+/* Context activation is done by the caller. */
+static void set_blit_dimension(const struct wined3d_gl_info *gl_info, UINT width, UINT height)
+{
+    const GLdouble projection[] =
+    {
+        2.0 / width,          0.0,  0.0, 0.0,
+                0.0, 2.0 / height,  0.0, 0.0,
+                0.0,          0.0,  2.0, 0.0,
+               -1.0,         -1.0, -1.0, 1.0,
+    };
+
+    gl_info->gl_ops.gl.p_glMatrixMode(GL_PROJECTION);
+    checkGLcall("glMatrixMode(GL_PROJECTION)");
+    gl_info->gl_ops.gl.p_glLoadMatrixd(projection);
+    checkGLcall("glLoadMatrixd");
+    gl_info->gl_ops.gl.p_glViewport(0, 0, width, height);
+    checkGLcall("glViewport");
+}
+
+static void context_get_rt_size(const struct wined3d_context *context, SIZE *size)
+{
+    const struct wined3d_surface *rt = context->current_rt;
+
+    if (rt->swapchain && rt->swapchain->front_buffer == rt)
+    {
+        RECT window_size;
+#ifdef VBOX_WINE_WITH_SINGLE_CONTEXT
+        ERR("not tested!");
+        GetClientRect(rt->swapchain->win_handle, &window_size);
+#else
+        GetClientRect(context->win_handle, &window_size);
+#endif
+#ifdef DEBUG_misha
+        Assert(window_size.right - window_size.left == rt->resource.width);
+        Assert(window_size.bottom - window_size.top == rt->resource.height);
+#endif
+        size->cx = window_size.right - window_size.left;
+        size->cy = window_size.bottom - window_size.top;
+
+        return;
+    }
+    size->cx = rt->resource.width;
+    size->cy = rt->resource.height;
+}
+
+/*****************************************************************************
+ * SetupForBlit
+ *
+ * Sets up a context for DirectDraw blitting.
+ * All texture units are disabled, texture unit 0 is set as current unit
+ * fog, lighting, blending, alpha test, z test, scissor test, culling disabled
+ * color writing enabled for all channels
+ * register combiners disabled, shaders disabled
+ * world matrix is set to identity, texture matrix 0 too
+ * projection matrix is setup for drawing screen coordinates
+ *
+ * Params:
+ *  This: Device to activate the context for
+ *  context: Context to setup
+ *
+ *****************************************************************************/
+/* Context activation is done by the caller. */
+static void SetupForBlit(const struct wined3d_device *device, struct wined3d_context *context)
+{
+    int i;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    DWORD sampler;
+    SIZE rt_size;
+
+    TRACE("Setting up context %p for blitting\n", context);
+
+    context_get_rt_size(context, &rt_size);
+
+    if (context->last_was_blit)
+    {
+        if (context->blit_w != rt_size.cx || context->blit_h != rt_size.cy)
+        {
+            set_blit_dimension(gl_info, rt_size.cx, rt_size.cy);
+            context->blit_w = rt_size.cx;
+            context->blit_h = rt_size.cy;
+            /* No need to dirtify here, the states are still dirtified because
+             * they weren't applied since the last SetupForBlit() call. */
+        }
+        TRACE("Context is already set up for blitting, nothing to do\n");
+        return;
+    }
+    context->last_was_blit = TRUE;
+
+    /* Disable all textures. The caller can then bind a texture it wants to blit
+     * from
+     *
+     * The blitting code uses (for now) the fixed function pipeline, so make sure to reset all fixed
+     * function texture unit. No need to care for higher samplers
+     */
+    for (i = gl_info->limits.textures - 1; i > 0 ; --i)
+    {
+        sampler = device->rev_tex_unit_map[i];
+        context_active_texture(context, gl_info, i);
+
+        if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
+        {
+            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB);
+            checkGLcall("glDisable GL_TEXTURE_CUBE_MAP_ARB");
+        }
+        gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
+        checkGLcall("glDisable GL_TEXTURE_3D");
+        if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
+        {
+            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB);
+            checkGLcall("glDisable GL_TEXTURE_RECTANGLE_ARB");
+        }
+        gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
+        checkGLcall("glDisable GL_TEXTURE_2D");
+
+        gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+        checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);");
+
+        if (sampler != WINED3D_UNMAPPED_STAGE)
+        {
+            if (sampler < MAX_TEXTURES)
+                context_invalidate_state(context, STATE_TEXTURESTAGE(sampler, WINED3D_TSS_COLOR_OP));
+            context_invalidate_state(context, STATE_SAMPLER(sampler));
+        }
+    }
+    context_active_texture(context, gl_info, 0);
+
+    sampler = device->rev_tex_unit_map[0];
+
+    if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB);
+        checkGLcall("glDisable GL_TEXTURE_CUBE_MAP_ARB");
+    }
+    gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
+    checkGLcall("glDisable GL_TEXTURE_3D");
+    if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB);
+        checkGLcall("glDisable GL_TEXTURE_RECTANGLE_ARB");
+    }
+    gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
+    checkGLcall("glDisable GL_TEXTURE_2D");
+
+    gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+    gl_info->gl_ops.gl.p_glMatrixMode(GL_TEXTURE);
+    checkGLcall("glMatrixMode(GL_TEXTURE)");
+    gl_info->gl_ops.gl.p_glLoadIdentity();
+    checkGLcall("glLoadIdentity()");
+
+    if (gl_info->supported[EXT_TEXTURE_LOD_BIAS])
+    {
+        gl_info->gl_ops.gl.p_glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
+                GL_TEXTURE_LOD_BIAS_EXT, 0.0f);
+        checkGLcall("glTexEnvf GL_TEXTURE_LOD_BIAS_EXT ...");
+    }
+
+    if (sampler != WINED3D_UNMAPPED_STAGE)
+    {
+        if (sampler < MAX_TEXTURES)
+        {
+            context_invalidate_state(context, STATE_TRANSFORM(WINED3D_TS_TEXTURE0 + sampler));
+            context_invalidate_state(context, STATE_TEXTURESTAGE(sampler, WINED3D_TSS_COLOR_OP));
+        }
+        context_invalidate_state(context, STATE_SAMPLER(sampler));
+    }
+
+    /* Other misc states */
+    gl_info->gl_ops.gl.p_glDisable(GL_ALPHA_TEST);
+    checkGLcall("glDisable(GL_ALPHA_TEST)");
+    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ALPHATESTENABLE));
+    gl_info->gl_ops.gl.p_glDisable(GL_LIGHTING);
+    checkGLcall("glDisable GL_LIGHTING");
+    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_LIGHTING));
+    gl_info->gl_ops.gl.p_glDisable(GL_DEPTH_TEST);
+    checkGLcall("glDisable GL_DEPTH_TEST");
+    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ZENABLE));
+    glDisableWINE(GL_FOG);
+    checkGLcall("glDisable GL_FOG");
+    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_FOGENABLE));
+    gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
+    checkGLcall("glDisable GL_BLEND");
+    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE));
+    gl_info->gl_ops.gl.p_glDisable(GL_CULL_FACE);
+    checkGLcall("glDisable GL_CULL_FACE");
+    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_CULLMODE));
+    gl_info->gl_ops.gl.p_glDisable(GL_STENCIL_TEST);
+    checkGLcall("glDisable GL_STENCIL_TEST");
+    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_STENCILENABLE));
+    gl_info->gl_ops.gl.p_glDisable(GL_SCISSOR_TEST);
+    checkGLcall("glDisable GL_SCISSOR_TEST");
+    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_SCISSORTESTENABLE));
+    if (gl_info->supported[ARB_POINT_SPRITE])
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_POINT_SPRITE_ARB);
+        checkGLcall("glDisable GL_POINT_SPRITE_ARB");
+        context_invalidate_state(context, STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE));
+    }
+    gl_info->gl_ops.gl.p_glColorMask(GL_TRUE, GL_TRUE,GL_TRUE,GL_TRUE);
+    checkGLcall("glColorMask");
+    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE));
+    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE1));
+    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE2));
+    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE3));
+    if (gl_info->supported[EXT_SECONDARY_COLOR])
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_COLOR_SUM_EXT);
+        context_invalidate_state(context, STATE_RENDER(WINED3D_RS_SPECULARENABLE));
+        checkGLcall("glDisable(GL_COLOR_SUM_EXT)");
+    }
+
+    /* Setup transforms */
+    gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
+    checkGLcall("glMatrixMode(GL_MODELVIEW)");
+    gl_info->gl_ops.gl.p_glLoadIdentity();
+    checkGLcall("glLoadIdentity()");
+    context_invalidate_state(context, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)));
+
+    context->last_was_rhw = TRUE;
+    context_invalidate_state(context, STATE_VDECL); /* because of last_was_rhw = TRUE */
+
+    gl_info->gl_ops.gl.p_glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)");
+    gl_info->gl_ops.gl.p_glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)");
+    gl_info->gl_ops.gl.p_glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)");
+    gl_info->gl_ops.gl.p_glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)");
+    gl_info->gl_ops.gl.p_glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)");
+    gl_info->gl_ops.gl.p_glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)");
+    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_CLIPPING));
+
+    set_blit_dimension(gl_info, rt_size.cx, rt_size.cy);
+
+    /* Disable shaders */
+    device->shader_backend->shader_disable(device->shader_priv, context);
+    context->select_shader = 1;
+    context->load_constants = 1;
+
+    context->blit_w = rt_size.cx;
+    context->blit_h = rt_size.cy;
+    context_invalidate_state(context, STATE_VIEWPORT);
+    context_invalidate_state(context, STATE_TRANSFORM(WINED3D_TS_PROJECTION));
+}
+
+static inline BOOL is_rt_mask_onscreen(DWORD rt_mask)
+{
+    return rt_mask & (1 << 31);
+}
+
+static inline GLenum draw_buffer_from_rt_mask(DWORD rt_mask)
+{
+    return rt_mask & ~(1 << 31);
+}
+
+/* Context activation is done by the caller. */
+static void context_apply_draw_buffers(struct wined3d_context *context, DWORD rt_mask)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    if (!rt_mask)
+    {
+        gl_info->gl_ops.gl.p_glDrawBuffer(GL_NONE);
+        checkGLcall("glDrawBuffer()");
+    }
+    else if (is_rt_mask_onscreen(rt_mask))
+    {
+        gl_info->gl_ops.gl.p_glDrawBuffer(draw_buffer_from_rt_mask(rt_mask));
+        checkGLcall("glDrawBuffer()");
+    }
+    else
+    {
+        if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
+        {
+            unsigned int i = 0;
+
+            while (rt_mask)
+            {
+                if (rt_mask & 1)
+                    context->draw_buffers[i] = GL_COLOR_ATTACHMENT0 + i;
+                else
+                    context->draw_buffers[i] = GL_NONE;
+
+                rt_mask >>= 1;
+                ++i;
+            }
+
+            if (gl_info->supported[ARB_DRAW_BUFFERS])
+            {
+                GL_EXTCALL(glDrawBuffersARB(i, context->draw_buffers));
+                checkGLcall("glDrawBuffers()");
+            }
+            else
+            {
+                gl_info->gl_ops.gl.p_glDrawBuffer(context->draw_buffers[0]);
+                checkGLcall("glDrawBuffer()");
+            }
+        }
+        else
+        {
+            ERR("Unexpected draw buffers mask with backbuffer ORM.\n");
+        }
+    }
+}
+
+/* Context activation is done by the caller. */
+void context_set_draw_buffer(struct wined3d_context *context, GLenum buffer)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    DWORD *current_mask = context->current_fbo ? &context->current_fbo->rt_mask : &context->draw_buffers_mask;
+    DWORD new_mask = context_generate_rt_mask(buffer);
+
+    if (new_mask == *current_mask)
+        return;
+
+    gl_info->gl_ops.gl.p_glDrawBuffer(buffer);
+    checkGLcall("glDrawBuffer()");
+
+    *current_mask = new_mask;
+}
+
+/* Context activation is done by the caller. */
+void context_active_texture(struct wined3d_context *context, const struct wined3d_gl_info *gl_info, unsigned int unit)
+{
+    GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0 + unit));
+    checkGLcall("glActiveTextureARB");
+    context->active_texture = unit;
+}
+
+void context_bind_texture(struct wined3d_context *context, GLenum target, GLuint name)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    DWORD unit = context->active_texture;
+    DWORD old_texture_type = context->texture_type[unit];
+
+    if (name)
+    {
+        gl_info->gl_ops.gl.p_glBindTexture(target, name);
+        checkGLcall("glBindTexture");
+    }
+    else
+    {
+        target = GL_NONE;
+    }
+
+    if (old_texture_type != target)
+    {
+        const struct wined3d_device *device = context->swapchain->device;
+
+        switch (old_texture_type)
+        {
+            case GL_NONE:
+                /* nothing to do */
+                break;
+            case GL_TEXTURE_2D:
+                gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, device->dummy_texture_2d[unit]);
+                checkGLcall("glBindTexture");
+                break;
+            case GL_TEXTURE_RECTANGLE_ARB:
+                gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_RECTANGLE_ARB, device->dummy_texture_rect[unit]);
+                checkGLcall("glBindTexture");
+                break;
+            case GL_TEXTURE_CUBE_MAP:
+                gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_CUBE_MAP, device->dummy_texture_cube[unit]);
+                checkGLcall("glBindTexture");
+                break;
+            case GL_TEXTURE_3D:
+                gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_3D, device->dummy_texture_3d[unit]);
+                checkGLcall("glBindTexture");
+                break;
+            default:
+                ERR("Unexpected texture target %#x\n", old_texture_type);
+        }
+
+        context->texture_type[unit] = target;
+    }
+}
+
+static void context_set_render_offscreen(struct wined3d_context *context, BOOL offscreen)
+{
+    if (context->render_offscreen == offscreen) return;
+
+    context_invalidate_state(context, STATE_POINTSPRITECOORDORIGIN);
+    context_invalidate_state(context, STATE_TRANSFORM(WINED3D_TS_PROJECTION));
+    context_invalidate_state(context, STATE_VIEWPORT);
+    context_invalidate_state(context, STATE_SCISSORRECT);
+    context_invalidate_state(context, STATE_FRONTFACE);
+    context->render_offscreen = offscreen;
+}
+
+static BOOL match_depth_stencil_format(const struct wined3d_format *existing,
+        const struct wined3d_format *required)
+{
+    BYTE existing_depth, existing_stencil, required_depth, required_stencil;
+
+    if (existing == required) return TRUE;
+    if ((existing->flags & WINED3DFMT_FLAG_FLOAT) != (required->flags & WINED3DFMT_FLAG_FLOAT)) return FALSE;
+
+    getDepthStencilBits(existing, &existing_depth, &existing_stencil);
+    getDepthStencilBits(required, &required_depth, &required_stencil);
+
+    if(existing_depth < required_depth) return FALSE;
+    /* If stencil bits are used the exact amount is required - otherwise wrapping
+     * won't work correctly */
+    if(required_stencil && required_stencil != existing_stencil) return FALSE;
+    return TRUE;
+}
+
+/* The caller provides a context */
+static void context_validate_onscreen_formats(struct wined3d_context *context,
+        const struct wined3d_surface *depth_stencil)
+{
+    /* Onscreen surfaces are always in a swapchain */
+    struct wined3d_swapchain *swapchain = context->current_rt->swapchain;
+
+    if (context->render_offscreen || !depth_stencil) return;
+    if (match_depth_stencil_format(swapchain->ds_format, depth_stencil->resource.format)) return;
+
+    /* TODO: If the requested format would satisfy the needs of the existing one(reverse match),
+     * or no onscreen depth buffer was created, the OpenGL drawable could be changed to the new
+     * format. */
+    WARN("Depth stencil format is not supported by WGL, rendering the backbuffer in an FBO\n");
+
+    /* The currently active context is the necessary context to access the swapchain's onscreen buffers */
+    surface_load_location(context->current_rt, SFLAG_INTEXTURE, NULL);
+    swapchain->render_to_fbo = TRUE;
+    swapchain_update_draw_bindings(swapchain);
+    context_set_render_offscreen(context, TRUE);
+}
+
+static DWORD context_generate_rt_mask_no_fbo(const struct wined3d_device *device, const struct wined3d_surface *rt)
+{
+    if (!rt || rt->resource.format->id == WINED3DFMT_NULL)
+        return 0;
+    else if (rt->swapchain)
+        return context_generate_rt_mask_from_surface(rt);
+    else
+        return context_generate_rt_mask(device->offscreenBuffer);
+}
+
+/* Context activation is done by the caller. */
+void context_apply_blit_state(struct wined3d_context *context, const struct wined3d_device *device)
+{
+    struct wined3d_surface *rt = context->current_rt;
+    DWORD rt_mask, *cur_mask;
+
+    if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
+    {
+        context_validate_onscreen_formats(context, NULL);
+
+        if (context->render_offscreen)
+        {
+            surface_internal_preload(rt, SRGB_RGB);
+
+            context_apply_fbo_state_blit(context, GL_FRAMEBUFFER, rt, NULL, rt->draw_binding);
+            if (rt->resource.format->id != WINED3DFMT_NULL)
+                rt_mask = 1;
+            else
+                rt_mask = 0;
+        }
+        else
+        {
+            context->current_fbo = NULL;
+            context_bind_fbo(context, GL_FRAMEBUFFER, 0);
+            rt_mask = context_generate_rt_mask_from_surface(rt);
+        }
+    }
+    else
+    {
+        rt_mask = context_generate_rt_mask_no_fbo(device, rt);
+    }
+
+    cur_mask = context->current_fbo ? &context->current_fbo->rt_mask : &context->draw_buffers_mask;
+
+    if (rt_mask != *cur_mask)
+    {
+        context_apply_draw_buffers(context, rt_mask);
+        *cur_mask = rt_mask;
+    }
+
+    if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
+    {
+        context_check_fbo_status(context, GL_FRAMEBUFFER);
+    }
+
+    SetupForBlit(device, context);
+    context_invalidate_state(context, STATE_FRAMEBUFFER);
+}
+
+static BOOL context_validate_rt_config(UINT rt_count,
+        struct wined3d_surface * const *rts, const struct wined3d_surface *ds)
+{
+    unsigned int i;
+
+    if (ds) return TRUE;
+
+    for (i = 0; i < rt_count; ++i)
+    {
+        if (rts[i] && rts[i]->resource.format->id != WINED3DFMT_NULL)
+            return TRUE;
+    }
+
+    WARN("Invalid render target config, need at least one attachment.\n");
+    return FALSE;
+}
+
+/* Context activation is done by the caller. */
+BOOL context_apply_clear_state(struct wined3d_context *context, const struct wined3d_device *device,
+        UINT rt_count, const struct wined3d_fb_state *fb)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    DWORD rt_mask = 0, *cur_mask;
+    UINT i;
+    struct wined3d_surface **rts = fb->render_targets;
+
+    if (isStateDirty(context, STATE_FRAMEBUFFER) || fb != &device->fb
+            || rt_count != context->gl_info->limits.buffers)
+    {
+        if (!context_validate_rt_config(rt_count, rts, fb->depth_stencil))
+            return FALSE;
+
+        if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
+        {
+            context_validate_onscreen_formats(context, fb->depth_stencil);
+
+            if (!rt_count || surface_is_offscreen(rts[0]))
+            {
+                for (i = 0; i < rt_count; ++i)
+                {
+                    context->blit_targets[i] = rts[i];
+                    if (rts[i] && rts[i]->resource.format->id != WINED3DFMT_NULL)
+                        rt_mask |= (1 << i);
+                }
+                while (i < context->gl_info->limits.buffers)
+                {
+                    context->blit_targets[i] = NULL;
+                    ++i;
+                }
+                context_apply_fbo_state(context, GL_FRAMEBUFFER, context->blit_targets, fb->depth_stencil,
+                        rt_count ? rts[0]->draw_binding : SFLAG_INTEXTURE);
+            }
+            else
+            {
+                context_apply_fbo_state(context, GL_FRAMEBUFFER, NULL, NULL, SFLAG_INDRAWABLE);
+                rt_mask = context_generate_rt_mask_from_surface(rts[0]);
+            }
+
+            /* If the framebuffer is not the device's fb the device's fb has to be reapplied
+             * next draw. Otherwise we could mark the framebuffer state clean here, once the
+             * state management allows this */
+            context_invalidate_state(context, STATE_FRAMEBUFFER);
+        }
+        else
+        {
+            rt_mask = context_generate_rt_mask_no_fbo(device, rt_count ? rts[0] : NULL);
+        }
+    }
+    else if (wined3d_settings.offscreen_rendering_mode == ORM_FBO
+            && (!rt_count || surface_is_offscreen(rts[0])))
+    {
+        for (i = 0; i < rt_count; ++i)
+        {
+            if (rts[i] && rts[i]->resource.format->id != WINED3DFMT_NULL) rt_mask |= (1 << i);
+        }
+    }
+    else
+    {
+        rt_mask = context_generate_rt_mask_no_fbo(device, rt_count ? rts[0] : NULL);
+    }
+
+    cur_mask = context->current_fbo ? &context->current_fbo->rt_mask : &context->draw_buffers_mask;
+
+    if (rt_mask != *cur_mask)
+    {
+        context_apply_draw_buffers(context, rt_mask);
+        *cur_mask = rt_mask;
+        context_invalidate_state(context, STATE_FRAMEBUFFER);
+    }
+
+    if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
+    {
+        context_check_fbo_status(context, GL_FRAMEBUFFER);
+    }
+
+    if (context->last_was_blit)
+        context->last_was_blit = FALSE;
+
+    /* Blending and clearing should be orthogonal, but tests on the nvidia
+     * driver show that disabling blending when clearing improves the clearing
+     * performance incredibly. */
+    gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
+    gl_info->gl_ops.gl.p_glEnable(GL_SCISSOR_TEST);
+    checkGLcall("glEnable GL_SCISSOR_TEST");
+
+    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE));
+    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_SCISSORTESTENABLE));
+    context_invalidate_state(context, STATE_SCISSORRECT);
+
+    return TRUE;
+}
+
+static DWORD find_draw_buffers_mask(const struct wined3d_context *context, const struct wined3d_device *device)
+{
+    const struct wined3d_state *state = &device->stateBlock->state;
+    struct wined3d_surface **rts = state->fb->render_targets;
+    struct wined3d_shader *ps = state->pixel_shader;
+    DWORD rt_mask, rt_mask_bits;
+    unsigned int i;
+
+    if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) return context_generate_rt_mask_no_fbo(device, rts[0]);
+    else if (!context->render_offscreen) return context_generate_rt_mask_from_surface(rts[0]);
+
+    rt_mask = ps ? ps->reg_maps.rt_mask : 1;
+    rt_mask &= context->d3d_info->valid_rt_mask;
+    rt_mask_bits = rt_mask;
+    i = 0;
+    while (rt_mask_bits)
+    {
+        rt_mask_bits &= ~(1 << i);
+        if (!rts[i] || rts[i]->resource.format->id == WINED3DFMT_NULL)
+            rt_mask &= ~(1 << i);
+
+        i++;
+    }
+
+    return rt_mask;
+}
+
+/* Context activation is done by the caller. */
+void context_state_fb(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_device *device = context->swapchain->device;
+    const struct wined3d_fb_state *fb = state->fb;
+    DWORD rt_mask = find_draw_buffers_mask(context, device);
+    DWORD *cur_mask;
+
+    if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
+    {
+        if (!context->render_offscreen)
+        {
+            context_apply_fbo_state(context, GL_FRAMEBUFFER, NULL, NULL, SFLAG_INDRAWABLE);
+        }
+        else
+        {
+            context_apply_fbo_state(context, GL_FRAMEBUFFER, fb->render_targets, fb->depth_stencil,
+                    fb->render_targets[0]->draw_binding);
+        }
+    }
+
+    cur_mask = context->current_fbo ? &context->current_fbo->rt_mask : &context->draw_buffers_mask;
+    if (rt_mask != *cur_mask)
+    {
+        context_apply_draw_buffers(context, rt_mask);
+        *cur_mask = rt_mask;
+    }
+}
+
+/* Context activation is done by the caller. */
+void context_state_drawbuf(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_device *device = context->swapchain->device;
+    DWORD rt_mask, *cur_mask;
+
+    if (isStateDirty(context, STATE_FRAMEBUFFER)) return;
+
+    cur_mask = context->current_fbo ? &context->current_fbo->rt_mask : &context->draw_buffers_mask;
+    rt_mask = find_draw_buffers_mask(context, device);
+    if (rt_mask != *cur_mask)
+    {
+        context_apply_draw_buffers(context, rt_mask);
+        *cur_mask = rt_mask;
+    }
+}
+
+/* Context activation is done by the caller. */
+BOOL context_apply_draw_state(struct wined3d_context *context, struct wined3d_device *device)
+{
+    const struct wined3d_state *state = &device->stateBlock->state;
+    const struct StateEntry *state_table = context->state_table;
+    const struct wined3d_fb_state *fb = state->fb;
+    unsigned int i;
+
+    if (!context_validate_rt_config(context->gl_info->limits.buffers,
+            fb->render_targets, fb->depth_stencil))
+        return FALSE;
+
+    if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && isStateDirty(context, STATE_FRAMEBUFFER))
+    {
+        context_validate_onscreen_formats(context, fb->depth_stencil);
+    }
+
+    /* Preload resources before FBO setup. Texture preload in particular may
+     * result in changes to the current FBO, due to using e.g. FBO blits for
+     * updating a resource location. */
+    device_update_tex_unit_map(device);
+    device_preload_textures(device);
+    if (isStateDirty(context, STATE_VDECL) || isStateDirty(context, STATE_STREAMSRC))
+        device_update_stream_info(device, context->gl_info);
+    if (state->index_buffer)
+    {
+        if (device->stream_info.all_vbo)
+            wined3d_buffer_preload(state->index_buffer);
+        else
+            buffer_get_sysmem(state->index_buffer, context->gl_info);
+    }
+
+    for (i = 0; i < context->numDirtyEntries; ++i)
+    {
+        DWORD rep = context->dirtyArray[i];
+        DWORD idx = rep / (sizeof(*context->isStateDirty) * CHAR_BIT);
+        BYTE shift = rep & ((sizeof(*context->isStateDirty) * CHAR_BIT) - 1);
+        context->isStateDirty[idx] &= ~(1 << shift);
+        state_table[rep].apply(context, state, rep);
+    }
+
+    if (context->select_shader)
+    {
+        device->shader_backend->shader_select(device->shader_priv, context, state);
+        context->select_shader = 0;
+    }
+
+    if (context->load_constants)
+    {
+        device->shader_backend->shader_load_constants(device->shader_priv,
+                context, state);
+        context->load_constants = 0;
+    }
+
+    if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
+    {
+        context_check_fbo_status(context, GL_FRAMEBUFFER);
+    }
+
+    context->numDirtyEntries = 0; /* This makes the whole list clean */
+    context->last_was_blit = FALSE;
+
+    return TRUE;
+}
+
+static void context_setup_target(struct wined3d_context *context, struct wined3d_surface *target)
+{
+    BOOL old_render_offscreen = context->render_offscreen, render_offscreen;
+
+    render_offscreen = surface_is_offscreen(target);
+    if (context->current_rt == target && render_offscreen == old_render_offscreen) return;
+
+    /* To compensate the lack of format switching with some offscreen rendering methods and on onscreen buffers
+     * the alpha blend state changes with different render target formats. */
+    if (!context->current_rt)
+    {
+        context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE));
+    }
+    else
+    {
+        const struct wined3d_format *old = context->current_rt->resource.format;
+        const struct wined3d_format *new = target->resource.format;
+
+        if (old->id != new->id)
+        {
+            /* Disable blending when the alpha mask has changed and when a format doesn't support blending. */
+            if ((old->alpha_size && !new->alpha_size) || (!old->alpha_size && new->alpha_size)
+                    || !(new->flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING))
+                context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE));
+
+            /* Update sRGB writing when switching between formats that do/do not support sRGB writing */
+            if ((old->flags & WINED3DFMT_FLAG_SRGB_WRITE) != (new->flags & WINED3DFMT_FLAG_SRGB_WRITE))
+                context_invalidate_state(context, STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE));
+        }
+
+        /* When switching away from an offscreen render target, and we're not
+         * using FBOs, we have to read the drawable into the texture. This is
+         * done via PreLoad (and SFLAG_INDRAWABLE set on the surface). There
+         * are some things that need care though. PreLoad needs a GL context,
+         * and FindContext is called before the context is activated. It also
+         * has to be called with the old rendertarget active, otherwise a
+         * wrong drawable is read. */
+        if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
+                && old_render_offscreen && context->current_rt != target)
+        {
+            /* Read the back buffer of the old drawable into the destination texture. */
+            if (context->current_rt->texture_name_srgb)
+                surface_internal_preload(context->current_rt, SRGB_SRGB);
+            surface_internal_preload(context->current_rt, SRGB_RGB);
+            surface_modify_location(context->current_rt, SFLAG_INDRAWABLE, FALSE);
+        }
+    }
+
+    context->current_rt = target;
+    context_set_render_offscreen(context, render_offscreen);
+}
+
+/* Do not call while under the GL lock. */
+struct wined3d_context *context_acquire(const struct wined3d_device *device, struct wined3d_surface *target)
+{
+    struct wined3d_context *current_context = context_get_current();
+    struct wined3d_context *context;
+#ifdef VBOX_WINE_WITH_SINGLE_CONTEXT
+    struct wined3d_swapchain *swapchain = NULL;
+#endif
+
+    TRACE("device %p, target %p.\n", device, target);
+
+#if !defined(VBOX_WINE_WITH_SINGLE_CONTEXT) && !defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
+    if (current_context && current_context->destroyed)
+        current_context = NULL;
+#endif
+
+    if (!target)
+    {
+        if (current_context
+                && current_context->current_rt
+#ifndef VBOX_WINE_WITH_SINGLE_CONTEXT
+                && current_context->swapchain->device == device
+#else
+                && current_context->device == device
+#endif
+                )
+        {
+            target = current_context->current_rt;
+        }
+        else
+        {
+#ifndef VBOX_WINE_WITH_SINGLE_CONTEXT
+            struct wined3d_swapchain *swapchain = device->swapchains[0];
+#else
+            swapchain = swapchain_find_valid_or_any(device);
+            if (!swapchain)
+            {
+                ERR("no valid swapchain found!");
+                swapchain = device->swapchains[0];
+                Assert(swapchain);
+            }
+#endif
+            if (swapchain->back_buffers)
+                target = swapchain->back_buffers[0];
+            else
+                target = swapchain->front_buffer;
+        }
+    }
+
+#ifdef VBOX_WITH_WINE_DBG
+    Assert(target);
+#endif
+
+    if (current_context && current_context->current_rt == target)
+    {
+        context = current_context;
+    }
+    else if (target->swapchain)
+    {
+        TRACE("Rendering onscreen.\n");
+
+        context = swapchain_get_context(target->swapchain);
+#ifdef VBOX_WINE_WITH_SINGLE_CONTEXT
+        swapchain = target->swapchain;
+        Assert(swapchain);
+#endif
+    }
+    else
+    {
+        TRACE("Rendering offscreen.\n");
+
+        /* Stay with the current context if possible. Otherwise use the
+         * context for the primary swapchain. */
+        if (current_context && current_context->swapchain->device == device)
+            context = current_context;
+        else
+            context = swapchain_get_context(device->swapchains[0]);
+    }
+
+#ifndef VBOX_WINE_WITH_SINGLE_CONTEXT
+    context_update_window(context);
+#else
+    if (!swapchain)
+        swapchain = swapchain_find_valid_or_any(device);
+    context_update_window(context, swapchain);
+#endif
+    context_setup_target(context, target);
+    context_enter(context);
+    if (!context->valid) return context;
+
+    if (context != current_context)
+    {
+        if (!context_set_current(context))
+            ERR("Failed to activate the new context.\n");
+    }
+    else if (context->restore_ctx)
+    {
+        context_set_gl_context(context);
+    }
+
+    return context;
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/device.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/device.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/device.c	(revision 46521)
@@ -0,0 +1,5686 @@
+/*
+ * Copyright 2002 Lionel Ulmer
+ * Copyright 2002-2005 Jason Edmeades
+ * Copyright 2003-2004 Raphael Junqueira
+ * Copyright 2004 Christian Costa
+ * Copyright 2005 Oliver Stieber
+ * Copyright 2006-2008 Stefan Dösinger for CodeWeavers
+ * Copyright 2006-2008 Henri Verbeet
+ * Copyright 2007 Andrew Riedi
+ * Copyright 2009-2011 Henri Verbeet for CodeWeavers
+ *
+ * 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 <stdio.h>
+#ifdef HAVE_FLOAT_H
+# include <float.h>
+#endif
+
+#include "wined3d_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d);
+WINE_DECLARE_DEBUG_CHANNEL(d3d_perf);
+
+/* Define the default light parameters as specified by MSDN. */
+const struct wined3d_light WINED3D_default_light =
+{
+    WINED3D_LIGHT_DIRECTIONAL,  /* Type */
+    { 1.0f, 1.0f, 1.0f, 0.0f }, /* Diffuse r,g,b,a */
+    { 0.0f, 0.0f, 0.0f, 0.0f }, /* Specular r,g,b,a */
+    { 0.0f, 0.0f, 0.0f, 0.0f }, /* Ambient r,g,b,a, */
+    { 0.0f, 0.0f, 0.0f },       /* Position x,y,z */
+    { 0.0f, 0.0f, 1.0f },       /* Direction x,y,z */
+    0.0f,                       /* Range */
+    0.0f,                       /* Falloff */
+    0.0f, 0.0f, 0.0f,           /* Attenuation 0,1,2 */
+    0.0f,                       /* Theta */
+    0.0f                        /* Phi */
+};
+
+/* Note that except for WINED3DPT_POINTLIST and WINED3DPT_LINELIST these
+ * actually have the same values in GL and D3D. */
+GLenum gl_primitive_type_from_d3d(enum wined3d_primitive_type primitive_type)
+{
+    switch(primitive_type)
+    {
+        case WINED3D_PT_POINTLIST:
+            return GL_POINTS;
+
+        case WINED3D_PT_LINELIST:
+            return GL_LINES;
+
+        case WINED3D_PT_LINESTRIP:
+            return GL_LINE_STRIP;
+
+        case WINED3D_PT_TRIANGLELIST:
+            return GL_TRIANGLES;
+
+        case WINED3D_PT_TRIANGLESTRIP:
+            return GL_TRIANGLE_STRIP;
+
+        case WINED3D_PT_TRIANGLEFAN:
+            return GL_TRIANGLE_FAN;
+
+        case WINED3D_PT_LINELIST_ADJ:
+            return GL_LINES_ADJACENCY_ARB;
+
+        case WINED3D_PT_LINESTRIP_ADJ:
+            return GL_LINE_STRIP_ADJACENCY_ARB;
+
+        case WINED3D_PT_TRIANGLELIST_ADJ:
+            return GL_TRIANGLES_ADJACENCY_ARB;
+
+        case WINED3D_PT_TRIANGLESTRIP_ADJ:
+            return GL_TRIANGLE_STRIP_ADJACENCY_ARB;
+
+        default:
+            FIXME("Unhandled primitive type %s\n", debug_d3dprimitivetype(primitive_type));
+            return GL_NONE;
+    }
+}
+
+static enum wined3d_primitive_type d3d_primitive_type_from_gl(GLenum primitive_type)
+{
+    switch(primitive_type)
+    {
+        case GL_POINTS:
+            return WINED3D_PT_POINTLIST;
+
+        case GL_LINES:
+            return WINED3D_PT_LINELIST;
+
+        case GL_LINE_STRIP:
+            return WINED3D_PT_LINESTRIP;
+
+        case GL_TRIANGLES:
+            return WINED3D_PT_TRIANGLELIST;
+
+        case GL_TRIANGLE_STRIP:
+            return WINED3D_PT_TRIANGLESTRIP;
+
+        case GL_TRIANGLE_FAN:
+            return WINED3D_PT_TRIANGLEFAN;
+
+        case GL_LINES_ADJACENCY_ARB:
+            return WINED3D_PT_LINELIST_ADJ;
+
+        case GL_LINE_STRIP_ADJACENCY_ARB:
+            return WINED3D_PT_LINESTRIP_ADJ;
+
+        case GL_TRIANGLES_ADJACENCY_ARB:
+            return WINED3D_PT_TRIANGLELIST_ADJ;
+
+        case GL_TRIANGLE_STRIP_ADJACENCY_ARB:
+            return WINED3D_PT_TRIANGLESTRIP_ADJ;
+
+        default:
+            FIXME("Unhandled primitive type %s\n", debug_d3dprimitivetype(primitive_type));
+            return WINED3D_PT_UNDEFINED;
+    }
+}
+
+static BOOL fixed_get_input(BYTE usage, BYTE usage_idx, unsigned int *regnum)
+{
+    if ((usage == WINED3D_DECL_USAGE_POSITION || usage == WINED3D_DECL_USAGE_POSITIONT) && !usage_idx)
+        *regnum = WINED3D_FFP_POSITION;
+    else if (usage == WINED3D_DECL_USAGE_BLEND_WEIGHT && !usage_idx)
+        *regnum = WINED3D_FFP_BLENDWEIGHT;
+    else if (usage == WINED3D_DECL_USAGE_BLEND_INDICES && !usage_idx)
+        *regnum = WINED3D_FFP_BLENDINDICES;
+    else if (usage == WINED3D_DECL_USAGE_NORMAL && !usage_idx)
+        *regnum = WINED3D_FFP_NORMAL;
+    else if (usage == WINED3D_DECL_USAGE_PSIZE && !usage_idx)
+        *regnum = WINED3D_FFP_PSIZE;
+    else if (usage == WINED3D_DECL_USAGE_COLOR && !usage_idx)
+        *regnum = WINED3D_FFP_DIFFUSE;
+    else if (usage == WINED3D_DECL_USAGE_COLOR && usage_idx == 1)
+        *regnum = WINED3D_FFP_SPECULAR;
+    else if (usage == WINED3D_DECL_USAGE_TEXCOORD && usage_idx < WINED3DDP_MAXTEXCOORD)
+        *regnum = WINED3D_FFP_TEXCOORD0 + usage_idx;
+    else
+    {
+        FIXME("Unsupported input stream [usage=%s, usage_idx=%u]\n", debug_d3ddeclusage(usage), usage_idx);
+        *regnum = ~0U;
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+/* Context activation is done by the caller. */
+static void device_stream_info_from_declaration(struct wined3d_device *device, struct wined3d_stream_info *stream_info)
+{
+    const struct wined3d_state *state = &device->stateBlock->state;
+    /* We need to deal with frequency data! */
+    struct wined3d_vertex_declaration *declaration = state->vertex_declaration;
+    BOOL use_vshader;
+    unsigned int i;
+    WORD map;
+
+    stream_info->use_map = 0;
+    stream_info->swizzle_map = 0;
+    stream_info->all_vbo = 1;
+
+    /* Check for transformed vertices, disable vertex shader if present. */
+    stream_info->position_transformed = declaration->position_transformed;
+    use_vshader = state->vertex_shader && !declaration->position_transformed;
+
+    /* Translate the declaration into strided data. */
+    for (i = 0; i < declaration->element_count; ++i)
+    {
+        const struct wined3d_vertex_declaration_element *element = &declaration->elements[i];
+        const struct wined3d_stream_state *stream = &state->streams[element->input_slot];
+        struct wined3d_buffer *buffer = stream->buffer;
+        struct wined3d_bo_address data;
+        BOOL stride_used;
+        unsigned int idx;
+        DWORD stride;
+
+        TRACE("%p Element %p (%u of %u)\n", declaration->elements,
+                element, i + 1, declaration->element_count);
+
+        if (!buffer) continue;
+
+        stride = stream->stride;
+
+        TRACE("Stream %u, buffer %p.\n", element->input_slot, buffer);
+        buffer_get_memory(buffer, &device->adapter->gl_info, &data);
+
+        /* We can't use VBOs if the base vertex index is negative. OpenGL
+         * doesn't accept negative offsets (or rather offsets bigger than the
+         * VBO, because the pointer is unsigned), so use system memory
+         * sources. In most sane cases the pointer - offset will still be > 0,
+         * otherwise it will wrap around to some big value. Hope that with the
+         * indices, the driver wraps it back internally. If not,
+         * drawStridedSlow() is needed, including a vertex buffer path. */
+
+        if (state->load_base_vertex_index < 0)
+        {
+            WARN_(d3d_perf)("load_base_vertex_index is < 0 (%d), not using VBOs.\n", state->load_base_vertex_index);
+            data.buffer_object = 0;
+            data.addr = buffer_get_sysmem(buffer, &device->adapter->gl_info);
+            if ((UINT_PTR)data.addr < -state->load_base_vertex_index * stride)
+                FIXME("System memory vertex data load offset is negative!\n");
+        }
+        data.addr += element->offset;
+
+        TRACE("offset %u input_slot %u usage_idx %d\n", element->offset, element->input_slot, element->usage_idx);
+
+        if (use_vshader)
+        {
+            if (element->output_slot == ~0U)
+            {
+                /* TODO: Assuming vertexdeclarations are usually used with the
+                 * same or a similar shader, it might be worth it to store the
+                 * last used output slot and try that one first. */
+                stride_used = vshader_get_input(state->vertex_shader,
+                        element->usage, element->usage_idx, &idx);
+            }
+            else
+            {
+                idx = element->output_slot;
+                stride_used = TRUE;
+            }
+        }
+        else
+        {
+            if (!element->ffp_valid)
+            {
+                WARN("Skipping unsupported fixed function element of format %s and usage %s\n",
+                        debug_d3dformat(element->format->id), debug_d3ddeclusage(element->usage));
+                stride_used = FALSE;
+            }
+            else
+            {
+                stride_used = fixed_get_input(element->usage, element->usage_idx, &idx);
+            }
+        }
+
+        if (stride_used)
+        {
+            TRACE("Load %s array %u [usage %s, usage_idx %u, "
+                    "input_slot %u, offset %u, stride %u, format %s, buffer_object %u]\n",
+                    use_vshader ? "shader": "fixed function", idx,
+                    debug_d3ddeclusage(element->usage), element->usage_idx, element->input_slot,
+                    element->offset, stride, debug_d3dformat(element->format->id), data.buffer_object);
+
+            data.addr += stream->offset;
+
+            stream_info->elements[idx].format = element->format;
+            stream_info->elements[idx].data = data;
+#ifdef VBOX_WITH_WINE_FIX_BUFOFFSET
+            stream_info->elements[idx].offset = element->offset;
+#endif
+            stream_info->elements[idx].stride = stride;
+            stream_info->elements[idx].stream_idx = element->input_slot;
+
+            if (!device->adapter->gl_info.supported[ARB_VERTEX_ARRAY_BGRA]
+                    && element->format->id == WINED3DFMT_B8G8R8A8_UNORM)
+            {
+                stream_info->swizzle_map |= 1 << idx;
+            }
+            stream_info->use_map |= 1 << idx;
+        }
+    }
+
+    /* Preload the vertex buffers. */
+    device->num_buffer_queries = 0;
+    for (i = 0, map = stream_info->use_map; map; map >>= 1, ++i)
+    {
+        struct wined3d_stream_info_element *element;
+        struct wined3d_buffer *buffer;
+
+        if (!(map & 1))
+            continue;
+
+        element = &stream_info->elements[i];
+        buffer = state->streams[element->stream_idx].buffer;
+        wined3d_buffer_preload(buffer);
+
+        /* If the preload dropped the buffer object, update the stream info. */
+        if (buffer->buffer_object != element->data.buffer_object)
+        {
+            element->data.buffer_object = 0;
+            element->data.addr = buffer_get_sysmem(buffer, &device->adapter->gl_info) + (ptrdiff_t)element->data.addr;
+        }
+
+        if (!buffer->buffer_object)
+            stream_info->all_vbo = 0;
+
+        if (buffer->query)
+            device->buffer_queries[device->num_buffer_queries++] = buffer->query;
+    }
+}
+
+/* Context activation is done by the caller. */
+void device_update_stream_info(struct wined3d_device *device, const struct wined3d_gl_info *gl_info)
+{
+    struct wined3d_stream_info *stream_info = &device->stream_info;
+    const struct wined3d_state *state = &device->stateBlock->state;
+    DWORD prev_all_vbo = stream_info->all_vbo;
+
+    TRACE("============================= Vertex Declaration =============================\n");
+    device_stream_info_from_declaration(device, stream_info);
+
+    if (state->vertex_shader && !stream_info->position_transformed)
+    {
+        if (state->vertex_declaration->half_float_conv_needed && !stream_info->all_vbo)
+        {
+            TRACE("Using drawStridedSlow with vertex shaders for FLOAT16 conversion.\n");
+            device->useDrawStridedSlow = TRUE;
+        }
+        else
+        {
+            device->useDrawStridedSlow = FALSE;
+        }
+    }
+    else
+    {
+        WORD slow_mask = (1 << WINED3D_FFP_PSIZE);
+        slow_mask |= -!gl_info->supported[ARB_VERTEX_ARRAY_BGRA]
+                & ((1 << WINED3D_FFP_DIFFUSE) | (1 << WINED3D_FFP_SPECULAR));
+
+        if ((stream_info->position_transformed || (stream_info->use_map & slow_mask)) && !stream_info->all_vbo)
+        {
+            device->useDrawStridedSlow = TRUE;
+        }
+        else
+        {
+            device->useDrawStridedSlow = FALSE;
+        }
+    }
+
+    if (prev_all_vbo != stream_info->all_vbo)
+        device_invalidate_state(device, STATE_INDEXBUFFER);
+}
+
+static void device_preload_texture(const struct wined3d_state *state, unsigned int idx)
+{
+    struct wined3d_texture *texture;
+    enum WINED3DSRGB srgb;
+
+    if (!(texture = state->textures[idx])) return;
+    srgb = state->sampler_states[idx][WINED3D_SAMP_SRGB_TEXTURE] ? SRGB_SRGB : SRGB_RGB;
+    texture->texture_ops->texture_preload(texture, srgb);
+}
+
+void device_preload_textures(const struct wined3d_device *device)
+{
+    const struct wined3d_state *state = &device->stateBlock->state;
+    unsigned int i;
+
+    if (use_vs(state))
+    {
+        for (i = 0; i < MAX_VERTEX_SAMPLERS; ++i)
+        {
+            if (state->vertex_shader->reg_maps.sampler_type[i])
+                device_preload_texture(state, MAX_FRAGMENT_SAMPLERS + i);
+        }
+    }
+
+    if (use_ps(state))
+    {
+        for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i)
+        {
+            if (state->pixel_shader->reg_maps.sampler_type[i])
+                device_preload_texture(state, i);
+        }
+    }
+    else
+    {
+        WORD ffu_map = device->fixed_function_usage_map;
+
+        for (i = 0; ffu_map; ffu_map >>= 1, ++i)
+        {
+            if (ffu_map & 1)
+                device_preload_texture(state, i);
+        }
+    }
+}
+
+BOOL device_context_add(struct wined3d_device *device, struct wined3d_context *context)
+{
+    struct wined3d_context **new_array;
+
+    TRACE("Adding context %p.\n", context);
+
+    if (!device->contexts) new_array = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_array));
+    else new_array = HeapReAlloc(GetProcessHeap(), 0, device->contexts,
+            sizeof(*new_array) * (device->context_count + 1));
+
+    if (!new_array)
+    {
+        ERR("Failed to grow the context array.\n");
+        return FALSE;
+    }
+
+    new_array[device->context_count++] = context;
+    device->contexts = new_array;
+    return TRUE;
+}
+
+void device_context_remove(struct wined3d_device *device, struct wined3d_context *context)
+{
+    struct wined3d_context **new_array;
+    BOOL found = FALSE;
+    UINT i;
+
+    TRACE("Removing context %p.\n", context);
+
+    for (i = 0; i < device->context_count; ++i)
+    {
+        if (device->contexts[i] == context)
+        {
+            found = TRUE;
+            break;
+        }
+    }
+
+    if (!found)
+    {
+        ERR("Context %p doesn't exist in context array.\n", context);
+        return;
+    }
+
+    if (!--device->context_count)
+    {
+        HeapFree(GetProcessHeap(), 0, device->contexts);
+        device->contexts = NULL;
+        return;
+    }
+
+    memmove(&device->contexts[i], &device->contexts[i + 1], (device->context_count - i) * sizeof(*device->contexts));
+    new_array = HeapReAlloc(GetProcessHeap(), 0, device->contexts, device->context_count * sizeof(*device->contexts));
+    if (!new_array)
+    {
+        ERR("Failed to shrink context array. Oh well.\n");
+        return;
+    }
+
+    device->contexts = new_array;
+}
+
+/* Do not call while under the GL lock. */
+void device_switch_onscreen_ds(struct wined3d_device *device,
+        struct wined3d_context *context, struct wined3d_surface *depth_stencil)
+{
+    if (device->onscreen_depth_stencil)
+    {
+        surface_load_ds_location(device->onscreen_depth_stencil, context, SFLAG_INTEXTURE);
+
+        surface_modify_ds_location(device->onscreen_depth_stencil, SFLAG_INTEXTURE,
+                device->onscreen_depth_stencil->ds_current_size.cx,
+                device->onscreen_depth_stencil->ds_current_size.cy);
+        wined3d_surface_decref(device->onscreen_depth_stencil);
+    }
+    device->onscreen_depth_stencil = depth_stencil;
+    wined3d_surface_incref(device->onscreen_depth_stencil);
+}
+
+static BOOL is_full_clear(const struct wined3d_surface *target, const RECT *draw_rect, const RECT *clear_rect)
+{
+    /* partial draw rect */
+    if (draw_rect->left || draw_rect->top
+            || draw_rect->right < target->resource.width
+            || draw_rect->bottom < target->resource.height)
+        return FALSE;
+
+    /* partial clear rect */
+    if (clear_rect && (clear_rect->left > 0 || clear_rect->top > 0
+            || clear_rect->right < target->resource.width
+            || clear_rect->bottom < target->resource.height))
+        return FALSE;
+
+    return TRUE;
+}
+
+static void prepare_ds_clear(struct wined3d_surface *ds, struct wined3d_context *context,
+        DWORD location, const RECT *draw_rect, UINT rect_count, const RECT *clear_rect, RECT *out_rect)
+{
+    RECT current_rect, r;
+
+    if (ds->flags & SFLAG_DISCARDED)
+    {
+        /* Depth buffer was discarded, make it entirely current in its new location since
+         * there is no other place where we would get data anyway. */
+        SetRect(out_rect, 0, 0, ds->resource.width, ds->resource.height);
+        return;
+    }
+
+    if (ds->flags & location)
+        SetRect(&current_rect, 0, 0,
+                ds->ds_current_size.cx,
+                ds->ds_current_size.cy);
+    else
+        SetRectEmpty(&current_rect);
+
+    IntersectRect(&r, draw_rect, &current_rect);
+    if (EqualRect(&r, draw_rect))
+    {
+        /* current_rect ⊇ draw_rect, modify only. */
+        SetRect(out_rect, 0, 0, ds->ds_current_size.cx, ds->ds_current_size.cy);
+        return;
+    }
+
+    if (EqualRect(&r, &current_rect))
+    {
+        /* draw_rect ⊇ current_rect, test if we're doing a full clear. */
+
+        if (!clear_rect)
+        {
+            /* Full clear, modify only. */
+            *out_rect = *draw_rect;
+            return;
+        }
+
+        IntersectRect(&r, draw_rect, clear_rect);
+        if (EqualRect(&r, draw_rect))
+        {
+            /* clear_rect ⊇ draw_rect, modify only. */
+            *out_rect = *draw_rect;
+            return;
+        }
+    }
+
+    /* Full load. */
+    surface_load_ds_location(ds, context, location);
+    SetRect(out_rect, 0, 0, ds->ds_current_size.cx, ds->ds_current_size.cy);
+}
+
+/* Do not call while under the GL lock. */
+void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, const struct wined3d_fb_state *fb,
+        UINT rect_count, const RECT *rects, const RECT *draw_rect, DWORD flags, const struct wined3d_color *color,
+        float depth, DWORD stencil)
+{
+    const RECT *clear_rect = (rect_count > 0 && rects) ? (const RECT *)rects : NULL;
+    struct wined3d_surface *target = rt_count ? fb->render_targets[0] : NULL;
+    const struct wined3d_gl_info *gl_info;
+    UINT drawable_width, drawable_height;
+    struct wined3d_context *context;
+    GLbitfield clear_mask = 0;
+    BOOL render_offscreen;
+    unsigned int i;
+    RECT ds_rect;
+
+    /* When we're clearing parts of the drawable, make sure that the target surface is well up to date in the
+     * drawable. After the clear we'll mark the drawable up to date, so we have to make sure that this is true
+     * for the cleared parts, and the untouched parts.
+     *
+     * If we're clearing the whole target there is no need to copy it into the drawable, it will be overwritten
+     * anyway. If we're not clearing the color buffer we don't have to copy either since we're not going to set
+     * the drawable up to date. We have to check all settings that limit the clear area though. Do not bother
+     * checking all this if the dest surface is in the drawable anyway. */
+    if (flags & WINED3DCLEAR_TARGET && !is_full_clear(target, draw_rect, clear_rect))
+    {
+        for (i = 0; i < rt_count; ++i)
+        {
+            struct wined3d_surface *rt = fb->render_targets[i];
+            if (rt)
+                surface_load_location(rt, rt->draw_binding, NULL);
+        }
+    }
+
+    context = context_acquire(device, target);
+    if (!context->valid)
+    {
+        context_release(context);
+        WARN("Invalid context, skipping clear.\n");
+        return;
+    }
+    gl_info = context->gl_info;
+
+    if (target)
+    {
+        render_offscreen = context->render_offscreen;
+        target->get_drawable_size(context, &drawable_width, &drawable_height);
+    }
+    else
+    {
+        render_offscreen = TRUE;
+        drawable_width = fb->depth_stencil->pow2Width;
+        drawable_height = fb->depth_stencil->pow2Height;
+    }
+
+    if (flags & WINED3DCLEAR_ZBUFFER)
+    {
+        DWORD location = render_offscreen ? fb->depth_stencil->draw_binding : SFLAG_INDRAWABLE;
+
+        if (!render_offscreen && fb->depth_stencil != device->onscreen_depth_stencil)
+            device_switch_onscreen_ds(device, context, fb->depth_stencil);
+        prepare_ds_clear(fb->depth_stencil, context, location,
+                draw_rect, rect_count, clear_rect, &ds_rect);
+    }
+
+    if (!context_apply_clear_state(context, device, rt_count, fb))
+    {
+        context_release(context);
+        WARN("Failed to apply clear state, skipping clear.\n");
+        return;
+    }
+
+    /* Only set the values up once, as they are not changing. */
+    if (flags & WINED3DCLEAR_STENCIL)
+    {
+        if (gl_info->supported[EXT_STENCIL_TWO_SIDE])
+        {
+            gl_info->gl_ops.gl.p_glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
+            context_invalidate_state(context, STATE_RENDER(WINED3D_RS_TWOSIDEDSTENCILMODE));
+        }
+        gl_info->gl_ops.gl.p_glStencilMask(~0U);
+        context_invalidate_state(context, STATE_RENDER(WINED3D_RS_STENCILWRITEMASK));
+        gl_info->gl_ops.gl.p_glClearStencil(stencil);
+        checkGLcall("glClearStencil");
+        clear_mask = clear_mask | GL_STENCIL_BUFFER_BIT;
+    }
+
+    if (flags & WINED3DCLEAR_ZBUFFER)
+    {
+        DWORD location = render_offscreen ? fb->depth_stencil->draw_binding : SFLAG_INDRAWABLE;
+
+        surface_modify_ds_location(fb->depth_stencil, location, ds_rect.right, ds_rect.bottom);
+
+        gl_info->gl_ops.gl.p_glDepthMask(GL_TRUE);
+        context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ZWRITEENABLE));
+        gl_info->gl_ops.gl.p_glClearDepth(depth);
+        checkGLcall("glClearDepth");
+        clear_mask = clear_mask | GL_DEPTH_BUFFER_BIT;
+    }
+
+    if (flags & WINED3DCLEAR_TARGET)
+    {
+        for (i = 0; i < rt_count; ++i)
+        {
+            struct wined3d_surface *rt = fb->render_targets[i];
+
+            if (rt)
+                surface_modify_location(rt, rt->draw_binding, TRUE);
+        }
+
+        gl_info->gl_ops.gl.p_glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+        context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE));
+        context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE1));
+        context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE2));
+        context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE3));
+        gl_info->gl_ops.gl.p_glClearColor(color->r, color->g, color->b, color->a);
+        checkGLcall("glClearColor");
+        clear_mask = clear_mask | GL_COLOR_BUFFER_BIT;
+    }
+
+    if (!clear_rect)
+    {
+        if (render_offscreen)
+        {
+            gl_info->gl_ops.gl.p_glScissor(draw_rect->left, draw_rect->top,
+                    draw_rect->right - draw_rect->left, draw_rect->bottom - draw_rect->top);
+        }
+        else
+        {
+            gl_info->gl_ops.gl.p_glScissor(draw_rect->left, drawable_height - draw_rect->bottom,
+                        draw_rect->right - draw_rect->left, draw_rect->bottom - draw_rect->top);
+        }
+        checkGLcall("glScissor");
+        gl_info->gl_ops.gl.p_glClear(clear_mask);
+        checkGLcall("glClear");
+    }
+    else
+    {
+        RECT current_rect;
+
+        /* Now process each rect in turn. */
+        for (i = 0; i < rect_count; ++i)
+        {
+            /* Note that GL uses lower left, width/height. */
+            IntersectRect(&current_rect, draw_rect, &clear_rect[i]);
+
+            TRACE("clear_rect[%u] %s, current_rect %s.\n", i,
+                    wine_dbgstr_rect(&clear_rect[i]),
+                    wine_dbgstr_rect(&current_rect));
+
+            /* Tests show that rectangles where x1 > x2 or y1 > y2 are ignored silently.
+             * The rectangle is not cleared, no error is returned, but further rectangles are
+             * still cleared if they are valid. */
+            if (current_rect.left > current_rect.right || current_rect.top > current_rect.bottom)
+            {
+                TRACE("Rectangle with negative dimensions, ignoring.\n");
+                continue;
+            }
+
+            if (render_offscreen)
+            {
+                gl_info->gl_ops.gl.p_glScissor(current_rect.left, current_rect.top,
+                        current_rect.right - current_rect.left, current_rect.bottom - current_rect.top);
+            }
+            else
+            {
+                gl_info->gl_ops.gl.p_glScissor(current_rect.left, drawable_height - current_rect.bottom,
+                          current_rect.right - current_rect.left, current_rect.bottom - current_rect.top);
+            }
+            checkGLcall("glScissor");
+
+            gl_info->gl_ops.gl.p_glClear(clear_mask);
+            checkGLcall("glClear");
+        }
+    }
+
+    if (wined3d_settings.strict_draw_ordering || (flags & WINED3DCLEAR_TARGET
+            && target->swapchain && target->swapchain->front_buffer == target))
+        gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */
+
+    context_release(context);
+}
+
+ULONG CDECL wined3d_device_incref(struct wined3d_device *device)
+{
+    ULONG refcount = InterlockedIncrement(&device->ref);
+
+    TRACE("%p increasing refcount to %u.\n", device, refcount);
+
+    return refcount;
+}
+
+ULONG CDECL wined3d_device_decref(struct wined3d_device *device)
+{
+    ULONG refcount = InterlockedDecrement(&device->ref);
+
+    TRACE("%p decreasing refcount to %u.\n", device, refcount);
+
+    if (!refcount)
+    {
+        struct wined3d_stateblock *stateblock;
+        UINT i;
+
+        if (wined3d_stateblock_decref(device->updateStateBlock)
+                && device->updateStateBlock != device->stateBlock)
+            FIXME("Something's still holding the update stateblock.\n");
+        device->updateStateBlock = NULL;
+
+        stateblock = device->stateBlock;
+        device->stateBlock = NULL;
+        if (wined3d_stateblock_decref(stateblock))
+            FIXME("Something's still holding the stateblock.\n");
+
+        for (i = 0; i < sizeof(device->multistate_funcs) / sizeof(device->multistate_funcs[0]); ++i)
+        {
+            HeapFree(GetProcessHeap(), 0, device->multistate_funcs[i]);
+            device->multistate_funcs[i] = NULL;
+        }
+
+        if (!list_empty(&device->resources))
+        {
+            struct wined3d_resource *resource;
+
+            FIXME("Device released with resources still bound, acceptable but unexpected.\n");
+
+            LIST_FOR_EACH_ENTRY(resource, &device->resources, struct wined3d_resource, resource_list_entry)
+            {
+                FIXME("Leftover resource %p with type %s (%#x).\n",
+                        resource, debug_d3dresourcetype(resource->type), resource->type);
+            }
+        }
+
+        if (device->contexts)
+            ERR("Context array not freed!\n");
+        if (device->hardwareCursor)
+            DestroyCursor(device->hardwareCursor);
+        device->hardwareCursor = 0;
+
+        wined3d_decref(device->wined3d);
+        device->wined3d = NULL;
+        HeapFree(GetProcessHeap(), 0, device);
+        TRACE("Freed device %p.\n", device);
+    }
+
+    return refcount;
+}
+
+UINT CDECL wined3d_device_get_swapchain_count(const struct wined3d_device *device)
+{
+    TRACE("device %p.\n", device);
+
+    return device->swapchain_count;
+}
+
+struct wined3d_swapchain * CDECL wined3d_device_get_swapchain(const struct wined3d_device *device, UINT swapchain_idx)
+{
+    TRACE("device %p, swapchain_idx %u.\n", device, swapchain_idx);
+
+    if (swapchain_idx >= device->swapchain_count)
+    {
+        WARN("swapchain_idx %u >= swapchain_count %u.\n",
+                swapchain_idx, device->swapchain_count);
+        return NULL;
+    }
+
+    return device->swapchains[swapchain_idx];
+}
+
+#ifndef VBOX
+static void device_load_logo(struct wined3d_device *device, const char *filename)
+{
+    struct wined3d_color_key color_key;
+    HBITMAP hbm;
+    BITMAP bm;
+    HRESULT hr;
+    HDC dcb = NULL, dcs = NULL;
+
+    hbm = LoadImageA(NULL, filename, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
+    if(hbm)
+    {
+        GetObjectA(hbm, sizeof(BITMAP), &bm);
+        dcb = CreateCompatibleDC(NULL);
+        if(!dcb) goto out;
+        SelectObject(dcb, hbm);
+    }
+    else
+    {
+        /* Create a 32x32 white surface to indicate that wined3d is used, but the specified image
+         * couldn't be loaded
+         */
+        memset(&bm, 0, sizeof(bm));
+        bm.bmWidth = 32;
+        bm.bmHeight = 32;
+    }
+
+    hr = wined3d_surface_create(device, bm.bmWidth, bm.bmHeight, WINED3DFMT_B5G6R5_UNORM, 0,
+            WINED3D_POOL_SYSTEM_MEM, WINED3D_MULTISAMPLE_NONE, 0, WINED3D_SURFACE_MAPPABLE,
+            NULL, &wined3d_null_parent_ops, &device->logo_surface);
+    if (FAILED(hr))
+    {
+        ERR("Wine logo requested, but failed to create surface, hr %#x.\n", hr);
+        goto out;
+    }
+
+    if (dcb)
+    {
+        if (FAILED(hr = wined3d_surface_getdc(device->logo_surface, &dcs)))
+            goto out;
+        BitBlt(dcs, 0, 0, bm.bmWidth, bm.bmHeight, dcb, 0, 0, SRCCOPY);
+        wined3d_surface_releasedc(device->logo_surface, dcs);
+
+        color_key.color_space_low_value = 0;
+        color_key.color_space_high_value = 0;
+        wined3d_surface_set_color_key(device->logo_surface, WINEDDCKEY_SRCBLT, &color_key);
+    }
+    else
+    {
+        const struct wined3d_color c = {1.0f, 1.0f, 1.0f, 1.0f};
+        /* Fill the surface with a white color to show that wined3d is there */
+        wined3d_device_color_fill(device, device->logo_surface, NULL, &c);
+    }
+
+out:
+    if (dcb) DeleteDC(dcb);
+    if (hbm) DeleteObject(hbm);
+}
+#endif
+
+/* Context activation is done by the caller. */
+static void create_dummy_textures(struct wined3d_device *device, struct wined3d_context *context)
+{
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    unsigned int i, j, count;
+    /* Under DirectX you can sample even if no texture is bound, whereas
+     * OpenGL will only allow that when a valid texture is bound.
+     * We emulate this by creating dummy textures and binding them
+     * to each texture stage when the currently set D3D texture is NULL. */
+
+    if (gl_info->supported[APPLE_CLIENT_STORAGE])
+    {
+        /* The dummy texture does not have client storage backing */
+        gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
+        checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
+    }
+
+    count = min(MAX_COMBINED_SAMPLERS, gl_info->limits.combined_samplers);
+    for (i = 0; i < count; ++i)
+    {
+        DWORD color = 0x000000ff;
+
+        /* Make appropriate texture active */
+        context_active_texture(context, gl_info, i);
+
+        gl_info->gl_ops.gl.p_glGenTextures(1, &device->dummy_texture_2d[i]);
+        checkGLcall("glGenTextures");
+        TRACE("Dummy 2D texture %u given name %u.\n", i, device->dummy_texture_2d[i]);
+
+        gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, device->dummy_texture_2d[i]);
+        checkGLcall("glBindTexture");
+
+        gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0,
+                GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &color);
+        checkGLcall("glTexImage2D");
+
+        if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
+        {
+            gl_info->gl_ops.gl.p_glGenTextures(1, &device->dummy_texture_rect[i]);
+            checkGLcall("glGenTextures");
+            TRACE("Dummy rectangle texture %u given name %u.\n", i, device->dummy_texture_rect[i]);
+
+            gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_RECTANGLE_ARB, device->dummy_texture_rect[i]);
+            checkGLcall("glBindTexture");
+
+            gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, 1, 1, 0,
+                    GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &color);
+            checkGLcall("glTexImage2D");
+        }
+
+        if (gl_info->supported[EXT_TEXTURE3D])
+        {
+            gl_info->gl_ops.gl.p_glGenTextures(1, &device->dummy_texture_3d[i]);
+            checkGLcall("glGenTextures");
+            TRACE("Dummy 3D texture %u given name %u.\n", i, device->dummy_texture_3d[i]);
+
+            gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_3D, device->dummy_texture_3d[i]);
+            checkGLcall("glBindTexture");
+
+            GL_EXTCALL(glTexImage3DEXT(GL_TEXTURE_3D, 0, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &color));
+            checkGLcall("glTexImage3D");
+        }
+
+        if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
+        {
+            gl_info->gl_ops.gl.p_glGenTextures(1, &device->dummy_texture_cube[i]);
+            checkGLcall("glGenTextures");
+            TRACE("Dummy cube texture %u given name %u.\n", i, device->dummy_texture_cube[i]);
+
+            gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_CUBE_MAP, device->dummy_texture_cube[i]);
+            checkGLcall("glBindTexture");
+
+            for (j = GL_TEXTURE_CUBE_MAP_POSITIVE_X; j <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; ++j)
+            {
+                gl_info->gl_ops.gl.p_glTexImage2D(j, 0, GL_RGBA8, 1, 1, 0,
+                        GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &color);
+                checkGLcall("glTexImage2D");
+            }
+        }
+    }
+
+    if (gl_info->supported[APPLE_CLIENT_STORAGE])
+    {
+        /* Re-enable because if supported it is enabled by default */
+        gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
+        checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
+    }
+}
+
+/* Context activation is done by the caller. */
+static void destroy_dummy_textures(struct wined3d_device *device, const struct wined3d_gl_info *gl_info)
+{
+    unsigned int count = min(MAX_COMBINED_SAMPLERS, gl_info->limits.combined_samplers);
+
+    if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
+    {
+        gl_info->gl_ops.gl.p_glDeleteTextures(count, device->dummy_texture_cube);
+        checkGLcall("glDeleteTextures(count, device->dummy_texture_cube)");
+    }
+
+    if (gl_info->supported[EXT_TEXTURE3D])
+    {
+        gl_info->gl_ops.gl.p_glDeleteTextures(count, device->dummy_texture_3d);
+        checkGLcall("glDeleteTextures(count, device->dummy_texture_3d)");
+    }
+
+    if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
+    {
+        gl_info->gl_ops.gl.p_glDeleteTextures(count, device->dummy_texture_rect);
+        checkGLcall("glDeleteTextures(count, device->dummy_texture_rect)");
+    }
+
+    gl_info->gl_ops.gl.p_glDeleteTextures(count, device->dummy_texture_2d);
+    checkGLcall("glDeleteTextures(count, device->dummy_texture_2d)");
+
+    memset(device->dummy_texture_cube, 0, count * sizeof(*device->dummy_texture_cube));
+    memset(device->dummy_texture_3d, 0, count * sizeof(*device->dummy_texture_3d));
+    memset(device->dummy_texture_rect, 0, count * sizeof(*device->dummy_texture_rect));
+    memset(device->dummy_texture_2d, 0, count * sizeof(*device->dummy_texture_2d));
+}
+
+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;
+}
+
+void CDECL wined3d_device_setup_fullscreen_window(struct wined3d_device *device, HWND window, UINT w, UINT h)
+{
+    BOOL filter_messages;
+    LONG style, exstyle;
+
+    TRACE("Setting up window %p for fullscreen mode.\n", window);
+
+    if (device->style || device->exStyle)
+    {
+        ERR("Changing the window style for window %p, but another style (%08x, %08x) is already stored.\n",
+                window, device->style, device->exStyle);
+    }
+
+    device->style = GetWindowLongW(window, GWL_STYLE);
+    device->exStyle = GetWindowLongW(window, GWL_EXSTYLE);
+
+    style = fullscreen_style(device->style);
+    exstyle = fullscreen_exstyle(device->exStyle);
+
+    TRACE("Old style was %08x, %08x, setting to %08x, %08x.\n",
+            device->style, device->exStyle, style, exstyle);
+
+    filter_messages = device->filter_messages;
+    device->filter_messages = TRUE;
+
+    SetWindowLongW(window, GWL_STYLE, style);
+    SetWindowLongW(window, GWL_EXSTYLE, exstyle);
+    SetWindowPos(window, HWND_TOPMOST, 0, 0, w, h, SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOACTIVATE);
+
+    device->filter_messages = filter_messages;
+}
+
+void CDECL wined3d_device_restore_fullscreen_window(struct wined3d_device *device, HWND window)
+{
+    BOOL filter_messages;
+    LONG style, exstyle;
+
+    if (!device->style && !device->exStyle) return;
+
+    style = GetWindowLongW(window, GWL_STYLE);
+    exstyle = GetWindowLongW(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. */
+    device->style ^= (device->style ^ style) & WS_VISIBLE;
+    device->exStyle ^= (device->exStyle ^ exstyle) & WS_EX_TOPMOST;
+
+    TRACE("Restoring window style of window %p to %08x, %08x.\n",
+            window, device->style, device->exStyle);
+
+    filter_messages = device->filter_messages;
+    device->filter_messages = TRUE;
+
+    /* 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). */
+    if (style == fullscreen_style(device->style) && exstyle == fullscreen_exstyle(device->exStyle))
+    {
+        SetWindowLongW(window, GWL_STYLE, device->style);
+        SetWindowLongW(window, GWL_EXSTYLE, device->exStyle);
+    }
+    SetWindowPos(window, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
+
+    device->filter_messages = filter_messages;
+
+    /* Delete the old values. */
+    device->style = 0;
+    device->exStyle = 0;
+}
+
+HRESULT CDECL wined3d_device_acquire_focus_window(struct wined3d_device *device, HWND window)
+{
+#ifndef VBOX_WITH_WDDM
+    TRACE("device %p, window %p.\n", device, window);
+
+    if (!wined3d_register_window(window, device))
+    {
+        ERR("Failed to register window %p.\n", window);
+        return E_FAIL;
+    }
+
+    InterlockedExchangePointer((void **)&device->focus_window, window);
+    SetWindowPos(window, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
+
+    return WINED3D_OK;
+#else
+    ERR("unsupported!");
+    return E_FAIL;
+#endif
+}
+
+void CDECL wined3d_device_release_focus_window(struct wined3d_device *device)
+{
+#ifndef VBOX_WITH_WDDM
+    TRACE("device %p.\n", device);
+
+    if (device->focus_window) wined3d_unregister_window(device->focus_window);
+    InterlockedExchangePointer((void **)&device->focus_window, NULL);
+#else
+    ERR("unsupported!");
+#endif
+}
+
+HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device,
+        struct wined3d_swapchain_desc *swapchain_desc)
+{
+    static const struct wined3d_color black = {0.0f, 0.0f, 0.0f, 0.0f};
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    struct wined3d_swapchain *swapchain = NULL;
+    struct wined3d_context *context;
+    HRESULT hr;
+    DWORD state;
+
+    TRACE("device %p, swapchain_desc %p.\n", device, swapchain_desc);
+
+    if (device->d3d_initialized)
+        return WINED3DERR_INVALIDCALL;
+    if (device->wined3d->flags & WINED3D_NO3D)
+        return WINED3DERR_INVALIDCALL;
+
+#ifdef VBOX_WITH_WDDM
+    if (!swapchain_desc->pHgsmi)
+    {
+        ERR("hgsmi not specified!");
+        return WINED3DERR_INVALIDCALL;
+    }
+    device->pHgsmi = swapchain_desc->pHgsmi;
+#endif
+
+    device->fb.render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+            sizeof(*device->fb.render_targets) * gl_info->limits.buffers);
+
+    /* Initialize the texture unit mapping to a 1:1 mapping */
+    for (state = 0; state < MAX_COMBINED_SAMPLERS; ++state)
+    {
+        if (state < gl_info->limits.fragment_samplers)
+        {
+            device->texUnitMap[state] = state;
+            device->rev_tex_unit_map[state] = state;
+        }
+        else
+        {
+            device->texUnitMap[state] = WINED3D_UNMAPPED_STAGE;
+            device->rev_tex_unit_map[state] = WINED3D_UNMAPPED_STAGE;
+        }
+    }
+
+    if (FAILED(hr = device->shader_backend->shader_alloc_private(device,
+            device->adapter->vertex_pipe, device->adapter->fragment_pipe)))
+    {
+        TRACE("Shader private data couldn't be allocated\n");
+        goto err_out;
+    }
+    if (FAILED(hr = device->blitter->alloc_private(device)))
+    {
+        TRACE("Blitter private data couldn't be allocated\n");
+        goto err_out;
+    }
+
+    /* Setup the implicit swapchain. This also initializes a context. */
+    TRACE("Creating implicit swapchain\n");
+    hr = device->device_parent->ops->create_swapchain(device->device_parent,
+            swapchain_desc, &swapchain);
+    if (FAILED(hr))
+    {
+        WARN("Failed to create implicit swapchain\n");
+        goto err_out;
+    }
+
+    device->swapchain_count = 1;
+    device->swapchains = HeapAlloc(GetProcessHeap(), 0, device->swapchain_count * sizeof(*device->swapchains));
+    if (!device->swapchains)
+    {
+        ERR("Out of memory!\n");
+        goto err_out;
+    }
+    device->swapchains[0] = swapchain;
+
+    if (swapchain->back_buffers && swapchain->back_buffers[0])
+    {
+        TRACE("Setting rendertarget to %p.\n", swapchain->back_buffers);
+        device->fb.render_targets[0] = swapchain->back_buffers[0];
+    }
+    else
+    {
+        TRACE("Setting rendertarget to %p.\n", swapchain->front_buffer);
+        device->fb.render_targets[0] = swapchain->front_buffer;
+    }
+    wined3d_surface_incref(device->fb.render_targets[0]);
+
+    /* Depth Stencil support */
+    device->fb.depth_stencil = device->auto_depth_stencil;
+    if (device->fb.depth_stencil)
+        wined3d_surface_incref(device->fb.depth_stencil);
+
+    /* Set up some starting GL setup */
+
+    /* Setup all the devices defaults */
+    stateblock_init_default_state(device->stateBlock);
+
+    context = context_acquire(device, swapchain->front_buffer);
+
+    create_dummy_textures(device, context);
+
+    device->contexts[0]->last_was_rhw = 0;
+
+    switch (wined3d_settings.offscreen_rendering_mode)
+    {
+        case ORM_FBO:
+            device->offscreenBuffer = GL_COLOR_ATTACHMENT0;
+            break;
+
+        case ORM_BACKBUFFER:
+        {
+            if (context_get_current()->aux_buffers > 0)
+            {
+                TRACE("Using auxiliary buffer for offscreen rendering\n");
+                device->offscreenBuffer = GL_AUX0;
+            }
+            else
+            {
+                TRACE("Using back buffer for offscreen rendering\n");
+                device->offscreenBuffer = GL_BACK;
+            }
+        }
+    }
+
+    TRACE("All defaults now set up, leaving 3D init.\n");
+
+    context_release(context);
+
+    /* Clear the screen */
+    wined3d_device_clear(device, 0, NULL, WINED3DCLEAR_TARGET
+            | (swapchain_desc->enable_auto_depth_stencil ? WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL : 0),
+            &black, 1.0f, 0);
+
+    device->d3d_initialized = TRUE;
+
+#ifndef VBOX
+    if (wined3d_settings.logo)
+        device_load_logo(device, wined3d_settings.logo);
+#endif
+    return WINED3D_OK;
+
+err_out:
+    HeapFree(GetProcessHeap(), 0, device->fb.render_targets);
+    HeapFree(GetProcessHeap(), 0, device->swapchains);
+    device->swapchain_count = 0;
+    if (swapchain)
+        wined3d_swapchain_decref(swapchain);
+    if (device->blit_priv)
+        device->blitter->free_private(device);
+    if (device->shader_priv)
+        device->shader_backend->shader_free_private(device);
+
+    return hr;
+}
+
+HRESULT CDECL wined3d_device_init_gdi(struct wined3d_device *device,
+        struct wined3d_swapchain_desc *swapchain_desc)
+{
+    struct wined3d_swapchain *swapchain = NULL;
+    HRESULT hr;
+
+    TRACE("device %p, swapchain_desc %p.\n", device, swapchain_desc);
+
+    /* Setup the implicit swapchain */
+    TRACE("Creating implicit swapchain\n");
+    hr = device->device_parent->ops->create_swapchain(device->device_parent,
+            swapchain_desc, &swapchain);
+    if (FAILED(hr))
+    {
+        WARN("Failed to create implicit swapchain\n");
+        goto err_out;
+    }
+
+    device->swapchain_count = 1;
+    device->swapchains = HeapAlloc(GetProcessHeap(), 0, device->swapchain_count * sizeof(*device->swapchains));
+    if (!device->swapchains)
+    {
+        ERR("Out of memory!\n");
+        goto err_out;
+    }
+    device->swapchains[0] = swapchain;
+    return WINED3D_OK;
+
+err_out:
+    wined3d_swapchain_decref(swapchain);
+    return hr;
+}
+
+HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device)
+{
+    struct wined3d_resource *resource, *cursor;
+    const struct wined3d_gl_info *gl_info;
+    struct wined3d_context *context;
+    struct wined3d_surface *surface;
+    UINT i;
+
+    TRACE("device %p.\n", device);
+
+    if (!device->d3d_initialized)
+        return WINED3DERR_INVALIDCALL;
+
+#ifdef VBOX_WINE_WITH_PROFILE
+    VBOXWINEPROFILE_DRAWPRIM_TERM(&device->DrawPrimProfile);
+#endif
+
+    /* Force making the context current again, to verify it is still valid
+     * (workaround for broken drivers) */
+    context_set_current(NULL);
+    /* I don't think that the interface guarantees that the device is destroyed from the same thread
+     * it was created. Thus make sure a context is active for the glDelete* calls
+     */
+    context = context_acquire(device, NULL);
+    gl_info = context->gl_info;
+
+    if (device->logo_surface)
+        wined3d_surface_decref(device->logo_surface);
+
+    stateblock_unbind_resources(device->stateBlock);
+
+    /* Unload resources */
+    LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &device->resources, struct wined3d_resource, resource_list_entry)
+    {
+        TRACE("Unloading resource %p.\n", resource);
+
+        resource->resource_ops->resource_unload(resource);
+    }
+
+    /* Delete the mouse cursor texture */
+    if (device->cursorTexture)
+    {
+        gl_info->gl_ops.gl.p_glDeleteTextures(1, &device->cursorTexture);
+        device->cursorTexture = 0;
+    }
+
+    /* Destroy the depth blt resources, they will be invalid after the reset. Also free shader
+     * private data, it might contain opengl pointers
+     */
+    if (device->depth_blt_texture)
+    {
+        gl_info->gl_ops.gl.p_glDeleteTextures(1, &device->depth_blt_texture);
+        device->depth_blt_texture = 0;
+    }
+
+#ifdef VBOX_WINE_WITH_SHADER_CACHE
+    shader_chaches_term(device);
+#endif
+
+    /* Destroy the shader backend. Note that this has to happen after all shaders are destroyed. */
+    device->blitter->free_private(device);
+    device->shader_backend->shader_free_private(device);
+
+    /* Release the buffers (with sanity checks)*/
+    if (device->onscreen_depth_stencil)
+    {
+        surface = device->onscreen_depth_stencil;
+        device->onscreen_depth_stencil = NULL;
+        wined3d_surface_decref(surface);
+    }
+
+    if (device->fb.depth_stencil)
+    {
+        surface = device->fb.depth_stencil;
+
+        TRACE("Releasing depth/stencil buffer %p.\n", surface);
+
+        device->fb.depth_stencil = NULL;
+        wined3d_surface_decref(surface);
+    }
+
+    if (device->auto_depth_stencil)
+    {
+        surface = device->auto_depth_stencil;
+        device->auto_depth_stencil = NULL;
+        if (wined3d_surface_decref(surface))
+            FIXME("Something's still holding the auto depth stencil buffer (%p).\n", surface);
+    }
+
+    for (i = 1; i < gl_info->limits.buffers; ++i)
+    {
+        wined3d_device_set_render_target(device, i, NULL, FALSE);
+    }
+
+    surface = device->fb.render_targets[0];
+    TRACE("Setting rendertarget 0 to NULL\n");
+    device->fb.render_targets[0] = NULL;
+    TRACE("Releasing the render target at %p\n", surface);
+    wined3d_surface_decref(surface);
+
+    context_release(context);
+
+    for (i = 0; i < device->swapchain_count; ++i)
+    {
+        TRACE("Releasing the implicit swapchain %u.\n", i);
+        if (wined3d_swapchain_decref(device->swapchains[i]))
+            FIXME("Something's still holding the implicit swapchain.\n");
+    }
+
+#ifdef VBOX_WINE_WITH_SINGLE_CONTEXT
+    while (device->context_count)
+    {
+        context_destroy(device, device->contexts[0]);
+    }
+#endif
+
+    HeapFree(GetProcessHeap(), 0, device->swapchains);
+    device->swapchains = NULL;
+    device->swapchain_count = 0;
+
+    HeapFree(GetProcessHeap(), 0, device->fb.render_targets);
+    device->fb.render_targets = NULL;
+
+    device->d3d_initialized = FALSE;
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_device_uninit_gdi(struct wined3d_device *device)
+{
+    unsigned int i;
+
+    for (i = 0; i < device->swapchain_count; ++i)
+    {
+        TRACE("Releasing the implicit swapchain %u.\n", i);
+        if (wined3d_swapchain_decref(device->swapchains[i]))
+            FIXME("Something's still holding the implicit swapchain.\n");
+    }
+
+    HeapFree(GetProcessHeap(), 0, device->swapchains);
+    device->swapchains = NULL;
+    device->swapchain_count = 0;
+    return WINED3D_OK;
+}
+
+/* Enables thread safety in the wined3d device and its resources. Called by DirectDraw
+ * from SetCooperativeLevel if DDSCL_MULTITHREADED is specified, and by d3d8/9 from
+ * CreateDevice if D3DCREATE_MULTITHREADED is passed.
+ *
+ * There is no way to deactivate thread safety once it is enabled.
+ */
+void CDECL wined3d_device_set_multithreaded(struct wined3d_device *device)
+{
+    TRACE("device %p.\n", device);
+
+    /* For now just store the flag (needed in case of ddraw). */
+    device->create_parms.flags |= WINED3DCREATE_MULTITHREADED;
+}
+
+
+UINT CDECL wined3d_device_get_available_texture_mem(const struct wined3d_device *device)
+{
+#ifndef VBOX_WITH_WDDM
+    TRACE("device %p.\n", device);
+
+    TRACE("Emulating %d MB, returning %d MB left.\n",
+            device->adapter->TextureRam / (1024 * 1024),
+            (device->adapter->TextureRam - device->adapter->UsedTextureRam) / (1024 * 1024));
+
+    return device->adapter->TextureRam - device->adapter->UsedTextureRam;
+#else
+    ERR("unsupported!");
+    return ~0UL;
+#endif
+}
+
+void CDECL wined3d_device_set_stream_output(struct wined3d_device *device, UINT idx,
+        struct wined3d_buffer *buffer, UINT offset)
+{
+    struct wined3d_buffer *prev_buffer;
+
+    TRACE("device %p, idx %u, buffer %p, offset %u.\n", device, idx, buffer, offset);
+
+    if (idx >= MAX_STREAM_OUT)
+    {
+        WARN("Invalid stream output %u.\n", idx);
+        return;
+    }
+
+    prev_buffer = device->updateStateBlock->state.stream_output[idx].buffer;
+    device->updateStateBlock->state.stream_output[idx].buffer = buffer;
+    device->updateStateBlock->state.stream_output[idx].offset = offset;
+
+    if (device->isRecordingState)
+    {
+        if (buffer)
+            wined3d_buffer_incref(buffer);
+        if (prev_buffer)
+            wined3d_buffer_decref(prev_buffer);
+        return;
+    }
+
+    if (prev_buffer != buffer)
+    {
+        if (buffer)
+        {
+            InterlockedIncrement(&buffer->resource.bind_count);
+            wined3d_buffer_incref(buffer);
+        }
+        if (prev_buffer)
+        {
+            InterlockedDecrement(&prev_buffer->resource.bind_count);
+            wined3d_buffer_decref(prev_buffer);
+        }
+    }
+}
+
+struct wined3d_buffer * CDECL wined3d_device_get_stream_output(struct wined3d_device *device,
+        UINT idx, UINT *offset)
+{
+    TRACE("device %p, idx %u, offset %p.\n", device, idx, offset);
+
+    if (idx >= MAX_STREAM_OUT)
+    {
+        WARN("Invalid stream output %u.\n", idx);
+        return NULL;
+    }
+
+    *offset = device->stateBlock->state.stream_output[idx].offset;
+    return device->stateBlock->state.stream_output[idx].buffer;
+}
+
+HRESULT CDECL wined3d_device_set_stream_source(struct wined3d_device *device, UINT stream_idx,
+        struct wined3d_buffer *buffer, UINT offset, UINT stride)
+{
+    struct wined3d_stream_state *stream;
+    struct wined3d_buffer *prev_buffer;
+
+    TRACE("device %p, stream_idx %u, buffer %p, offset %u, stride %u.\n",
+            device, stream_idx, buffer, offset, stride);
+
+    if (stream_idx >= MAX_STREAMS)
+    {
+        WARN("Stream index %u out of range.\n", stream_idx);
+        return WINED3DERR_INVALIDCALL;
+    }
+    else if (offset & 0x3)
+    {
+        WARN("Offset %u is not 4 byte aligned.\n", offset);
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    stream = &device->updateStateBlock->state.streams[stream_idx];
+    prev_buffer = stream->buffer;
+
+    device->updateStateBlock->changed.streamSource |= 1 << stream_idx;
+
+    if (prev_buffer == buffer
+            && stream->stride == stride
+            && stream->offset == offset)
+    {
+       TRACE("Application is setting the old values over, nothing to do.\n");
+       return WINED3D_OK;
+    }
+
+    stream->buffer = buffer;
+    if (buffer)
+    {
+        stream->stride = stride;
+        stream->offset = offset;
+    }
+
+    /* Handle recording of state blocks. */
+    if (device->isRecordingState)
+    {
+        TRACE("Recording... not performing anything.\n");
+        if (buffer)
+            wined3d_buffer_incref(buffer);
+        if (prev_buffer)
+            wined3d_buffer_decref(prev_buffer);
+        return WINED3D_OK;
+    }
+
+    if (buffer)
+    {
+        InterlockedIncrement(&buffer->resource.bind_count);
+        wined3d_buffer_incref(buffer);
+    }
+    if (prev_buffer)
+    {
+        InterlockedDecrement(&prev_buffer->resource.bind_count);
+        wined3d_buffer_decref(prev_buffer);
+    }
+
+    device_invalidate_state(device, STATE_STREAMSRC);
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_device_get_stream_source(const struct wined3d_device *device,
+        UINT stream_idx, struct wined3d_buffer **buffer, UINT *offset, UINT *stride)
+{
+    struct wined3d_stream_state *stream;
+
+    TRACE("device %p, stream_idx %u, buffer %p, offset %p, stride %p.\n",
+            device, stream_idx, buffer, offset, stride);
+
+    if (stream_idx >= MAX_STREAMS)
+    {
+        WARN("Stream index %u out of range.\n", stream_idx);
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    stream = &device->stateBlock->state.streams[stream_idx];
+    *buffer = stream->buffer;
+    if (*buffer)
+        wined3d_buffer_incref(*buffer);
+    if (offset)
+        *offset = stream->offset;
+    *stride = stream->stride;
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_device_set_stream_source_freq(struct wined3d_device *device, UINT stream_idx, UINT divider)
+{
+    struct wined3d_stream_state *stream;
+    UINT old_flags, old_freq;
+
+    TRACE("device %p, stream_idx %u, divider %#x.\n", device, stream_idx, divider);
+
+    /* Verify input. At least in d3d9 this is invalid. */
+    if ((divider & WINED3DSTREAMSOURCE_INSTANCEDATA) && (divider & WINED3DSTREAMSOURCE_INDEXEDDATA))
+    {
+        WARN("INSTANCEDATA and INDEXEDDATA were set, returning D3DERR_INVALIDCALL.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+    if ((divider & WINED3DSTREAMSOURCE_INSTANCEDATA) && !stream_idx)
+    {
+        WARN("INSTANCEDATA used on stream 0, returning D3DERR_INVALIDCALL.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+    if (!divider)
+    {
+        WARN("Divider is 0, returning D3DERR_INVALIDCALL.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    stream = &device->updateStateBlock->state.streams[stream_idx];
+    old_flags = stream->flags;
+    old_freq = stream->frequency;
+
+    stream->flags = divider & (WINED3DSTREAMSOURCE_INSTANCEDATA | WINED3DSTREAMSOURCE_INDEXEDDATA);
+    stream->frequency = divider & 0x7fffff;
+
+    device->updateStateBlock->changed.streamFreq |= 1 << stream_idx;
+
+    if (stream->frequency != old_freq || stream->flags != old_flags)
+        device_invalidate_state(device, STATE_STREAMSRC);
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_device_get_stream_source_freq(const struct wined3d_device *device,
+        UINT stream_idx, UINT *divider)
+{
+    struct wined3d_stream_state *stream;
+
+    TRACE("device %p, stream_idx %u, divider %p.\n", device, stream_idx, divider);
+
+    stream = &device->updateStateBlock->state.streams[stream_idx];
+    *divider = stream->flags | stream->frequency;
+
+    TRACE("Returning %#x.\n", *divider);
+
+    return WINED3D_OK;
+}
+
+void CDECL wined3d_device_set_transform(struct wined3d_device *device,
+        enum wined3d_transform_state d3dts, const struct wined3d_matrix *matrix)
+{
+    TRACE("device %p, state %s, matrix %p.\n",
+            device, debug_d3dtstype(d3dts), matrix);
+    TRACE("%.8e %.8e %.8e %.8e\n", matrix->u.s._11, matrix->u.s._12, matrix->u.s._13, matrix->u.s._14);
+    TRACE("%.8e %.8e %.8e %.8e\n", matrix->u.s._21, matrix->u.s._22, matrix->u.s._23, matrix->u.s._24);
+    TRACE("%.8e %.8e %.8e %.8e\n", matrix->u.s._31, matrix->u.s._32, matrix->u.s._33, matrix->u.s._34);
+    TRACE("%.8e %.8e %.8e %.8e\n", matrix->u.s._41, matrix->u.s._42, matrix->u.s._43, matrix->u.s._44);
+
+    /* Handle recording of state blocks. */
+    if (device->isRecordingState)
+    {
+        TRACE("Recording... not performing anything.\n");
+        device->updateStateBlock->changed.transform[d3dts >> 5] |= 1 << (d3dts & 0x1f);
+        device->updateStateBlock->state.transforms[d3dts] = *matrix;
+        return;
+    }
+
+    /* If the new matrix is the same as the current one,
+     * we cut off any further processing. this seems to be a reasonable
+     * optimization because as was noticed, some apps (warcraft3 for example)
+     * tend towards setting the same matrix repeatedly for some reason.
+     *
+     * From here on we assume that the new matrix is different, wherever it matters. */
+    if (!memcmp(&device->stateBlock->state.transforms[d3dts].u.m[0][0], matrix, sizeof(*matrix)))
+    {
+        TRACE("The application is setting the same matrix over again.\n");
+        return;
+    }
+
+    device->stateBlock->state.transforms[d3dts] = *matrix;
+
+    if (d3dts < WINED3D_TS_WORLD_MATRIX(device->adapter->gl_info.limits.blends))
+        device_invalidate_state(device, STATE_TRANSFORM(d3dts));
+}
+
+void CDECL wined3d_device_get_transform(const struct wined3d_device *device,
+        enum wined3d_transform_state state, struct wined3d_matrix *matrix)
+{
+    TRACE("device %p, state %s, matrix %p.\n", device, debug_d3dtstype(state), matrix);
+
+    *matrix = device->stateBlock->state.transforms[state];
+}
+
+void CDECL wined3d_device_multiply_transform(struct wined3d_device *device,
+        enum wined3d_transform_state state, const struct wined3d_matrix *matrix)
+{
+    const struct wined3d_matrix *mat;
+    struct wined3d_matrix temp;
+
+    TRACE("device %p, state %s, matrix %p.\n", device, debug_d3dtstype(state), matrix);
+
+    /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
+     * below means it will be recorded in a state block change, but it
+     * works regardless where it is recorded.
+     * If this is found to be wrong, change to StateBlock. */
+    if (state > HIGHEST_TRANSFORMSTATE)
+    {
+        WARN("Unhandled transform state %#x.\n", state);
+        return;
+    }
+
+    mat = &device->updateStateBlock->state.transforms[state];
+    multiply_matrix(&temp, mat, matrix);
+
+    /* Apply change via set transform - will reapply to eg. lights this way. */
+    wined3d_device_set_transform(device, state, &temp);
+}
+
+/* Note lights are real special cases. Although the device caps state only
+ * e.g. 8 are supported, you can reference any indexes you want as long as
+ * that number max are enabled at any one point in time. Therefore since the
+ * indices can be anything, we need a hashmap of them. However, this causes
+ * stateblock problems. When capturing the state block, I duplicate the
+ * hashmap, but when recording, just build a chain pretty much of commands to
+ * be replayed. */
+HRESULT CDECL wined3d_device_set_light(struct wined3d_device *device,
+        UINT light_idx, const struct wined3d_light *light)
+{
+    UINT hash_idx = LIGHTMAP_HASHFUNC(light_idx);
+    struct wined3d_light_info *object = NULL;
+    struct list *e;
+    float rho;
+
+    TRACE("device %p, light_idx %u, light %p.\n", device, light_idx, light);
+
+    /* Check the parameter range. Need for speed most wanted sets junk lights
+     * which confuse the GL driver. */
+    if (!light)
+        return WINED3DERR_INVALIDCALL;
+
+    switch (light->type)
+    {
+        case WINED3D_LIGHT_POINT:
+        case WINED3D_LIGHT_SPOT:
+        case WINED3D_LIGHT_PARALLELPOINT:
+        case WINED3D_LIGHT_GLSPOT:
+            /* Incorrect attenuation values can cause the gl driver to crash.
+             * Happens with Need for speed most wanted. */
+            if (light->attenuation0 < 0.0f || light->attenuation1 < 0.0f || light->attenuation2 < 0.0f)
+            {
+                WARN("Attenuation is negative, returning WINED3DERR_INVALIDCALL.\n");
+                return WINED3DERR_INVALIDCALL;
+            }
+            break;
+
+        case WINED3D_LIGHT_DIRECTIONAL:
+            /* Ignores attenuation */
+            break;
+
+        default:
+        WARN("Light type out of range, returning WINED3DERR_INVALIDCALL\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    LIST_FOR_EACH(e, &device->updateStateBlock->state.light_map[hash_idx])
+    {
+        object = LIST_ENTRY(e, struct wined3d_light_info, entry);
+        if (object->OriginalIndex == light_idx)
+            break;
+        object = NULL;
+    }
+
+    if (!object)
+    {
+        TRACE("Adding new light\n");
+        object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+        if (!object)
+            return E_OUTOFMEMORY;
+
+        list_add_head(&device->updateStateBlock->state.light_map[hash_idx], &object->entry);
+        object->glIndex = -1;
+        object->OriginalIndex = light_idx;
+    }
+
+    /* Initialize the object. */
+    TRACE("Light %d setting to type %d, Diffuse(%f,%f,%f,%f), Specular(%f,%f,%f,%f), Ambient(%f,%f,%f,%f)\n",
+            light_idx, light->type,
+            light->diffuse.r, light->diffuse.g, light->diffuse.b, light->diffuse.a,
+            light->specular.r, light->specular.g, light->specular.b, light->specular.a,
+            light->ambient.r, light->ambient.g, light->ambient.b, light->ambient.a);
+    TRACE("... Pos(%f,%f,%f), Dir(%f,%f,%f)\n", light->position.x, light->position.y, light->position.z,
+            light->direction.x, light->direction.y, light->direction.z);
+    TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n",
+            light->range, light->falloff, light->theta, light->phi);
+
+    /* Update the live definitions if the light is currently assigned a glIndex. */
+    if (object->glIndex != -1 && !device->isRecordingState)
+    {
+        if (object->OriginalParms.type != light->type)
+            device_invalidate_state(device, STATE_LIGHT_TYPE);
+        device_invalidate_state(device, STATE_ACTIVELIGHT(object->glIndex));
+    }
+
+    /* Save away the information. */
+    object->OriginalParms = *light;
+
+    switch (light->type)
+    {
+        case WINED3D_LIGHT_POINT:
+            /* Position */
+            object->lightPosn[0] = light->position.x;
+            object->lightPosn[1] = light->position.y;
+            object->lightPosn[2] = light->position.z;
+            object->lightPosn[3] = 1.0f;
+            object->cutoff = 180.0f;
+            /* FIXME: Range */
+            break;
+
+        case WINED3D_LIGHT_DIRECTIONAL:
+            /* Direction */
+            object->lightPosn[0] = -light->direction.x;
+            object->lightPosn[1] = -light->direction.y;
+            object->lightPosn[2] = -light->direction.z;
+            object->lightPosn[3] = 0.0f;
+            object->exponent = 0.0f;
+            object->cutoff = 180.0f;
+            break;
+
+        case WINED3D_LIGHT_SPOT:
+            /* Position */
+            object->lightPosn[0] = light->position.x;
+            object->lightPosn[1] = light->position.y;
+            object->lightPosn[2] = light->position.z;
+            object->lightPosn[3] = 1.0f;
+
+            /* Direction */
+            object->lightDirn[0] = light->direction.x;
+            object->lightDirn[1] = light->direction.y;
+            object->lightDirn[2] = light->direction.z;
+            object->lightDirn[3] = 1.0f;
+
+            /* opengl-ish and d3d-ish spot lights use too different models
+             * for the light "intensity" as a function of the angle towards
+             * the main light direction, so we only can approximate very
+             * roughly. However, spot lights are rather rarely used in games
+             * (if ever used at all). Furthermore if still used, probably
+             * nobody pays attention to such details. */
+            if (!light->falloff)
+            {
+                /* Falloff = 0 is easy, because d3d's and opengl's spot light
+                 * equations have the falloff resp. exponent parameter as an
+                 * exponent, so the spot light lighting will always be 1.0 for
+                 * both of them, and we don't have to care for the rest of the
+                 * rather complex calculation. */
+                object->exponent = 0.0f;
+            }
+            else
+            {
+                rho = light->theta + (light->phi - light->theta) / (2 * light->falloff);
+                if (rho < 0.0001f)
+                    rho = 0.0001f;
+#ifdef VBOX_WITH_WINE_FIXES
+                object->exponent = -0.3f / log(cos(rho / 2));
+#else
+                object->exponent = -0.3f / logf(cosf(rho / 2));
+#endif
+            }
+
+            if (object->exponent > 128.0f)
+                object->exponent = 128.0f;
+
+            object->cutoff = (float)(light->phi * 90 / M_PI);
+            /* FIXME: Range */
+            break;
+
+        default:
+            FIXME("Unrecognized light type %#x.\n", light->type);
+    }
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_device_get_light(const struct wined3d_device *device,
+        UINT light_idx, struct wined3d_light *light)
+{
+    UINT hash_idx = LIGHTMAP_HASHFUNC(light_idx);
+    struct wined3d_light_info *light_info = NULL;
+    struct list *e;
+
+    TRACE("device %p, light_idx %u, light %p.\n", device, light_idx, light);
+
+    LIST_FOR_EACH(e, &device->stateBlock->state.light_map[hash_idx])
+    {
+        light_info = LIST_ENTRY(e, struct wined3d_light_info, entry);
+        if (light_info->OriginalIndex == light_idx)
+            break;
+        light_info = NULL;
+    }
+
+    if (!light_info)
+    {
+        TRACE("Light information requested but light not defined\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    *light = light_info->OriginalParms;
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_device_set_light_enable(struct wined3d_device *device, UINT light_idx, BOOL enable)
+{
+    UINT hash_idx = LIGHTMAP_HASHFUNC(light_idx);
+    struct wined3d_light_info *light_info = NULL;
+    struct list *e;
+
+    TRACE("device %p, light_idx %u, enable %#x.\n", device, light_idx, enable);
+
+    LIST_FOR_EACH(e, &device->updateStateBlock->state.light_map[hash_idx])
+    {
+        light_info = LIST_ENTRY(e, struct wined3d_light_info, entry);
+        if (light_info->OriginalIndex == light_idx)
+            break;
+        light_info = NULL;
+    }
+    TRACE("Found light %p.\n", light_info);
+
+    /* Special case - enabling an undefined light creates one with a strict set of parameters. */
+    if (!light_info)
+    {
+        TRACE("Light enabled requested but light not defined, so defining one!\n");
+        wined3d_device_set_light(device, light_idx, &WINED3D_default_light);
+
+        /* Search for it again! Should be fairly quick as near head of list. */
+        LIST_FOR_EACH(e, &device->updateStateBlock->state.light_map[hash_idx])
+        {
+            light_info = LIST_ENTRY(e, struct wined3d_light_info, entry);
+            if (light_info->OriginalIndex == light_idx)
+                break;
+            light_info = NULL;
+        }
+        if (!light_info)
+        {
+            FIXME("Adding default lights has failed dismally\n");
+            return WINED3DERR_INVALIDCALL;
+        }
+    }
+
+    if (!enable)
+    {
+        if (light_info->glIndex != -1)
+        {
+            if (!device->isRecordingState)
+            {
+                device_invalidate_state(device, STATE_LIGHT_TYPE);
+                device_invalidate_state(device, STATE_ACTIVELIGHT(light_info->glIndex));
+            }
+
+            device->updateStateBlock->state.lights[light_info->glIndex] = NULL;
+            light_info->glIndex = -1;
+        }
+        else
+        {
+            TRACE("Light already disabled, nothing to do\n");
+        }
+        light_info->enabled = FALSE;
+    }
+    else
+    {
+        light_info->enabled = TRUE;
+        if (light_info->glIndex != -1)
+        {
+            TRACE("Nothing to do as light was enabled\n");
+        }
+        else
+        {
+            unsigned int i;
+            const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+            /* Find a free GL light. */
+            for (i = 0; i < gl_info->limits.lights; ++i)
+            {
+                if (!device->updateStateBlock->state.lights[i])
+                {
+                    device->updateStateBlock->state.lights[i] = light_info;
+                    light_info->glIndex = i;
+                    break;
+                }
+            }
+            if (light_info->glIndex == -1)
+            {
+                /* Our tests show that Windows returns D3D_OK in this situation, even with
+                 * D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE devices. This
+                 * is consistent among ddraw, d3d8 and d3d9. GetLightEnable returns TRUE
+                 * as well for those lights.
+                 *
+                 * TODO: Test how this affects rendering. */
+                WARN("Too many concurrently active lights\n");
+                return WINED3D_OK;
+            }
+
+            /* i == light_info->glIndex */
+            if (!device->isRecordingState)
+            {
+                device_invalidate_state(device, STATE_LIGHT_TYPE);
+                device_invalidate_state(device, STATE_ACTIVELIGHT(i));
+        }
+    }
+    }
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_device_get_light_enable(const struct wined3d_device *device, UINT light_idx, BOOL *enable)
+{
+    UINT hash_idx = LIGHTMAP_HASHFUNC(light_idx);
+    struct wined3d_light_info *light_info = NULL;
+    struct list *e;
+
+    TRACE("device %p, light_idx %u, enable %p.\n", device, light_idx, enable);
+
+    LIST_FOR_EACH(e, &device->stateBlock->state.light_map[hash_idx])
+    {
+        light_info = LIST_ENTRY(e, struct wined3d_light_info, entry);
+        if (light_info->OriginalIndex == light_idx)
+            break;
+        light_info = NULL;
+    }
+
+    if (!light_info)
+    {
+        TRACE("Light enabled state requested but light not defined.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+    /* true is 128 according to SetLightEnable */
+    *enable = light_info->enabled ? 128 : 0;
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_device_set_clip_plane(struct wined3d_device *device,
+        UINT plane_idx, const struct wined3d_vec4 *plane)
+{
+    TRACE("device %p, plane_idx %u, plane %p.\n", device, plane_idx, plane);
+
+    /* Validate plane_idx. */
+    if (plane_idx >= device->adapter->gl_info.limits.clipplanes)
+    {
+        TRACE("Application has requested clipplane this device doesn't support.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    device->updateStateBlock->changed.clipplane |= 1 << plane_idx;
+
+    if (!memcmp(&device->updateStateBlock->state.clip_planes[plane_idx], plane, sizeof(*plane)))
+    {
+        TRACE("Application is setting old values over, nothing to do.\n");
+        return WINED3D_OK;
+    }
+
+    device->updateStateBlock->state.clip_planes[plane_idx] = *plane;
+
+    /* Handle recording of state blocks. */
+    if (device->isRecordingState)
+    {
+        TRACE("Recording... not performing anything.\n");
+        return WINED3D_OK;
+    }
+
+    device_invalidate_state(device, STATE_CLIPPLANE(plane_idx));
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_device_get_clip_plane(const struct wined3d_device *device,
+        UINT plane_idx, struct wined3d_vec4 *plane)
+{
+    TRACE("device %p, plane_idx %u, plane %p.\n", device, plane_idx, plane);
+
+    /* Validate plane_idx. */
+    if (plane_idx >= device->adapter->gl_info.limits.clipplanes)
+    {
+        TRACE("Application has requested clipplane this device doesn't support.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    *plane = device->stateBlock->state.clip_planes[plane_idx];
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_device_set_clip_status(struct wined3d_device *device,
+        const struct wined3d_clip_status *clip_status)
+{
+    FIXME("device %p, clip_status %p stub!\n", device, clip_status);
+
+    if (!clip_status)
+        return WINED3DERR_INVALIDCALL;
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_device_get_clip_status(const struct wined3d_device *device,
+        struct wined3d_clip_status *clip_status)
+{
+    FIXME("device %p, clip_status %p stub!\n", device, clip_status);
+
+    if (!clip_status)
+        return WINED3DERR_INVALIDCALL;
+
+    return WINED3D_OK;
+}
+
+void CDECL wined3d_device_set_material(struct wined3d_device *device, const struct wined3d_material *material)
+{
+    TRACE("device %p, material %p.\n", device, material);
+
+    device->updateStateBlock->changed.material = TRUE;
+    device->updateStateBlock->state.material = *material;
+
+    /* Handle recording of state blocks */
+    if (device->isRecordingState)
+    {
+        TRACE("Recording... not performing anything.\n");
+        return;
+    }
+
+    device_invalidate_state(device, STATE_MATERIAL);
+}
+
+void CDECL wined3d_device_get_material(const struct wined3d_device *device, struct wined3d_material *material)
+{
+    TRACE("device %p, material %p.\n", device, material);
+
+    *material = device->updateStateBlock->state.material;
+
+    TRACE("diffuse {%.8e, %.8e, %.8e, %.8e}\n",
+            material->diffuse.r, material->diffuse.g,
+            material->diffuse.b, material->diffuse.a);
+    TRACE("ambient {%.8e, %.8e, %.8e, %.8e}\n",
+            material->ambient.r, material->ambient.g,
+            material->ambient.b, material->ambient.a);
+    TRACE("specular {%.8e, %.8e, %.8e, %.8e}\n",
+            material->specular.r, material->specular.g,
+            material->specular.b, material->specular.a);
+    TRACE("emissive {%.8e, %.8e, %.8e, %.8e}\n",
+            material->emissive.r, material->emissive.g,
+            material->emissive.b, material->emissive.a);
+    TRACE("power %.8e.\n", material->power);
+}
+
+void CDECL wined3d_device_set_index_buffer(struct wined3d_device *device,
+        struct wined3d_buffer *buffer, enum wined3d_format_id format_id)
+{
+    struct wined3d_buffer *prev_buffer;
+
+    TRACE("device %p, buffer %p, format %s.\n",
+            device, buffer, debug_d3dformat(format_id));
+
+    prev_buffer = device->updateStateBlock->state.index_buffer;
+
+    device->updateStateBlock->changed.indices = TRUE;
+    device->updateStateBlock->state.index_buffer = buffer;
+    device->updateStateBlock->state.index_format = format_id;
+
+    /* Handle recording of state blocks. */
+    if (device->isRecordingState)
+    {
+        TRACE("Recording... not performing anything.\n");
+        if (buffer)
+            wined3d_buffer_incref(buffer);
+        if (prev_buffer)
+            wined3d_buffer_decref(prev_buffer);
+        return;
+    }
+
+    if (prev_buffer != buffer)
+    {
+        device_invalidate_state(device, STATE_INDEXBUFFER);
+        if (buffer)
+        {
+            InterlockedIncrement(&buffer->resource.bind_count);
+            wined3d_buffer_incref(buffer);
+        }
+        if (prev_buffer)
+        {
+            InterlockedDecrement(&prev_buffer->resource.bind_count);
+            wined3d_buffer_decref(prev_buffer);
+        }
+    }
+}
+
+struct wined3d_buffer * CDECL wined3d_device_get_index_buffer(const struct wined3d_device *device,
+        enum wined3d_format_id *format)
+{
+    TRACE("device %p, format %p.\n", device, format);
+
+    *format = device->stateBlock->state.index_format;
+    return device->stateBlock->state.index_buffer;
+}
+
+void CDECL wined3d_device_set_base_vertex_index(struct wined3d_device *device, INT base_index)
+{
+    TRACE("device %p, base_index %d.\n", device, base_index);
+
+    device->updateStateBlock->state.base_vertex_index = base_index;
+}
+
+INT CDECL wined3d_device_get_base_vertex_index(const struct wined3d_device *device)
+{
+    TRACE("device %p.\n", device);
+
+    return device->stateBlock->state.base_vertex_index;
+}
+
+void CDECL wined3d_device_set_viewport(struct wined3d_device *device, const struct wined3d_viewport *viewport)
+{
+    TRACE("device %p, viewport %p.\n", device, viewport);
+    TRACE("x %u, y %u, w %u, h %u, min_z %.8e, max_z %.8e.\n",
+          viewport->x, viewport->y, viewport->width, viewport->height, viewport->min_z, viewport->max_z);
+
+    device->updateStateBlock->changed.viewport = TRUE;
+    device->updateStateBlock->state.viewport = *viewport;
+
+    /* Handle recording of state blocks */
+    if (device->isRecordingState)
+    {
+        TRACE("Recording... not performing anything\n");
+        return;
+    }
+
+    device_invalidate_state(device, STATE_VIEWPORT);
+}
+
+void CDECL wined3d_device_get_viewport(const struct wined3d_device *device, struct wined3d_viewport *viewport)
+{
+    TRACE("device %p, viewport %p.\n", device, viewport);
+
+    *viewport = device->stateBlock->state.viewport;
+}
+
+static void resolve_depth_buffer(struct wined3d_state *state)
+{
+    struct wined3d_texture *texture = state->textures[0];
+    struct wined3d_surface *depth_stencil, *surface;
+
+    if (!texture || texture->resource.type != WINED3D_RTYPE_TEXTURE
+            || !(texture->resource.format->flags & WINED3DFMT_FLAG_DEPTH))
+        return;
+    surface = surface_from_resource(texture->sub_resources[0]);
+    depth_stencil = state->fb->depth_stencil;
+    if (!depth_stencil)
+        return;
+
+    wined3d_surface_blt(surface, NULL, depth_stencil, NULL, 0, NULL, WINED3D_TEXF_POINT);
+}
+
+void CDECL wined3d_device_set_render_state(struct wined3d_device *device,
+        enum wined3d_render_state state, DWORD value)
+{
+    DWORD old_value = device->stateBlock->state.render_states[state];
+
+    TRACE("device %p, state %s (%#x), value %#x.\n", device, debug_d3drenderstate(state), state, value);
+
+    device->updateStateBlock->changed.renderState[state >> 5] |= 1 << (state & 0x1f);
+    device->updateStateBlock->state.render_states[state] = value;
+
+    /* Handle recording of state blocks. */
+    if (device->isRecordingState)
+    {
+        TRACE("Recording... not performing anything.\n");
+        return;
+    }
+
+    /* Compared here and not before the assignment to allow proper stateblock recording. */
+    if (value == old_value)
+        TRACE("Application is setting the old value over, nothing to do.\n");
+    else
+        device_invalidate_state(device, STATE_RENDER(state));
+
+    if (state == WINED3D_RS_POINTSIZE && value == WINED3D_RESZ_CODE)
+    {
+        TRACE("RESZ multisampled depth buffer resolve triggered.\n");
+        resolve_depth_buffer(&device->stateBlock->state);
+    }
+}
+
+DWORD CDECL wined3d_device_get_render_state(const struct wined3d_device *device, enum wined3d_render_state state)
+{
+    TRACE("device %p, state %s (%#x).\n", device, debug_d3drenderstate(state), state);
+
+    return device->stateBlock->state.render_states[state];
+}
+
+void CDECL wined3d_device_set_sampler_state(struct wined3d_device *device,
+        UINT sampler_idx, enum wined3d_sampler_state state, DWORD value)
+{
+    DWORD old_value;
+
+    TRACE("device %p, sampler_idx %u, state %s, value %#x.\n",
+            device, sampler_idx, debug_d3dsamplerstate(state), value);
+
+    if (sampler_idx >= WINED3DVERTEXTEXTURESAMPLER0 && sampler_idx <= WINED3DVERTEXTEXTURESAMPLER3)
+        sampler_idx -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS);
+
+    if (sampler_idx >= sizeof(device->stateBlock->state.sampler_states)
+            / sizeof(*device->stateBlock->state.sampler_states))
+    {
+        WARN("Invalid sampler %u.\n", sampler_idx);
+        return; /* Windows accepts overflowing this array ... we do not. */
+    }
+
+    old_value = device->stateBlock->state.sampler_states[sampler_idx][state];
+    device->updateStateBlock->state.sampler_states[sampler_idx][state] = value;
+    device->updateStateBlock->changed.samplerState[sampler_idx] |= 1 << state;
+
+    /* Handle recording of state blocks. */
+    if (device->isRecordingState)
+    {
+        TRACE("Recording... not performing anything.\n");
+        return;
+    }
+
+    if (old_value == value)
+    {
+        TRACE("Application is setting the old value over, nothing to do.\n");
+        return;
+    }
+
+    device_invalidate_state(device, STATE_SAMPLER(sampler_idx));
+}
+
+DWORD CDECL wined3d_device_get_sampler_state(const struct wined3d_device *device,
+        UINT sampler_idx, enum wined3d_sampler_state state)
+{
+    TRACE("device %p, sampler_idx %u, state %s.\n",
+            device, sampler_idx, debug_d3dsamplerstate(state));
+
+    if (sampler_idx >= WINED3DVERTEXTEXTURESAMPLER0 && sampler_idx <= WINED3DVERTEXTEXTURESAMPLER3)
+        sampler_idx -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS);
+
+    if (sampler_idx >= sizeof(device->stateBlock->state.sampler_states)
+            / sizeof(*device->stateBlock->state.sampler_states))
+    {
+        WARN("Invalid sampler %u.\n", sampler_idx);
+        return 0; /* Windows accepts overflowing this array ... we do not. */
+    }
+
+    return device->stateBlock->state.sampler_states[sampler_idx][state];
+}
+
+void CDECL wined3d_device_set_scissor_rect(struct wined3d_device *device, const RECT *rect)
+{
+    TRACE("device %p, rect %s.\n", device, wine_dbgstr_rect(rect));
+
+    device->updateStateBlock->changed.scissorRect = TRUE;
+    if (EqualRect(&device->updateStateBlock->state.scissor_rect, rect))
+    {
+        TRACE("App is setting the old scissor rectangle over, nothing to do.\n");
+        return;
+    }
+    CopyRect(&device->updateStateBlock->state.scissor_rect, rect);
+
+    if (device->isRecordingState)
+    {
+        TRACE("Recording... not performing anything.\n");
+        return;
+    }
+
+    device_invalidate_state(device, STATE_SCISSORRECT);
+}
+
+void CDECL wined3d_device_get_scissor_rect(const struct wined3d_device *device, RECT *rect)
+{
+    TRACE("device %p, rect %p.\n", device, rect);
+
+    *rect = device->updateStateBlock->state.scissor_rect;
+    TRACE("Returning rect %s.\n", wine_dbgstr_rect(rect));
+}
+
+void CDECL wined3d_device_set_vertex_declaration(struct wined3d_device *device,
+        struct wined3d_vertex_declaration *declaration)
+{
+    struct wined3d_vertex_declaration *prev = device->updateStateBlock->state.vertex_declaration;
+
+    TRACE("device %p, declaration %p.\n", device, declaration);
+
+    if (declaration)
+        wined3d_vertex_declaration_incref(declaration);
+    if (prev)
+        wined3d_vertex_declaration_decref(prev);
+
+    device->updateStateBlock->state.vertex_declaration = declaration;
+    device->updateStateBlock->changed.vertexDecl = TRUE;
+
+    if (device->isRecordingState)
+    {
+        TRACE("Recording... not performing anything.\n");
+        return;
+    }
+
+    if (declaration == prev)
+    {
+        /* Checked after the assignment to allow proper stateblock recording. */
+        TRACE("Application is setting the old declaration over, nothing to do.\n");
+        return;
+    }
+
+    device_invalidate_state(device, STATE_VDECL);
+}
+
+struct wined3d_vertex_declaration * CDECL wined3d_device_get_vertex_declaration(const struct wined3d_device *device)
+{
+    TRACE("device %p.\n", device);
+
+    return device->stateBlock->state.vertex_declaration;
+}
+
+void CDECL wined3d_device_set_vertex_shader(struct wined3d_device *device, struct wined3d_shader *shader)
+{
+    struct wined3d_shader *prev = device->updateStateBlock->state.vertex_shader;
+
+    TRACE("device %p, shader %p.\n", device, shader);
+
+    if (shader)
+        wined3d_shader_incref(shader);
+    if (prev)
+        wined3d_shader_decref(prev);
+
+    device->updateStateBlock->state.vertex_shader = shader;
+    device->updateStateBlock->changed.vertexShader = TRUE;
+
+    if (device->isRecordingState)
+    {
+        TRACE("Recording... not performing anything.\n");
+        return;
+    }
+
+    if (shader == prev)
+    {
+        TRACE("Application is setting the old shader over, nothing to do.\n");
+        return;
+    }
+
+    device_invalidate_state(device, STATE_VSHADER);
+}
+
+struct wined3d_shader * CDECL wined3d_device_get_vertex_shader(const struct wined3d_device *device)
+{
+    TRACE("device %p.\n", device);
+
+    return device->stateBlock->state.vertex_shader;
+}
+
+void CDECL wined3d_device_set_vs_cb(struct wined3d_device *device, UINT idx, struct wined3d_buffer *buffer)
+{
+    struct wined3d_buffer *prev;
+
+    TRACE("device %p, idx %u, buffer %p.\n", device, idx, buffer);
+
+    if (idx >= MAX_CONSTANT_BUFFERS)
+    {
+        WARN("Invalid constant buffer index %u.\n", idx);
+        return;
+    }
+
+    prev = device->updateStateBlock->state.vs_cb[idx];
+    device->updateStateBlock->state.vs_cb[idx] = buffer;
+
+    if (device->isRecordingState)
+    {
+        if (buffer)
+            wined3d_buffer_incref(buffer);
+        if (prev)
+            wined3d_buffer_decref(prev);
+        return;
+    }
+
+    if (prev != buffer)
+    {
+        if (buffer)
+        {
+            InterlockedIncrement(&buffer->resource.bind_count);
+            wined3d_buffer_incref(buffer);
+        }
+        if (prev)
+        {
+            InterlockedDecrement(&prev->resource.bind_count);
+            wined3d_buffer_decref(prev);
+        }
+    }
+}
+
+struct wined3d_buffer * CDECL wined3d_device_get_vs_cb(const struct wined3d_device *device, UINT idx)
+{
+    TRACE("device %p, idx %u.\n", device, idx);
+
+    if (idx >= MAX_CONSTANT_BUFFERS)
+    {
+        WARN("Invalid constant buffer index %u.\n", idx);
+        return NULL;
+    }
+
+    return device->stateBlock->state.vs_cb[idx];
+}
+
+void CDECL wined3d_device_set_vs_sampler(struct wined3d_device *device, UINT idx, struct wined3d_sampler *sampler)
+{
+    struct wined3d_sampler *prev;
+
+    TRACE("device %p, idx %u, sampler %p.\n", device, idx, sampler);
+
+    if (idx >= MAX_SAMPLER_OBJECTS)
+    {
+        WARN("Invalid sampler index %u.\n", idx);
+        return;
+    }
+
+    prev = device->updateStateBlock->state.vs_sampler[idx];
+    device->updateStateBlock->state.vs_sampler[idx] = sampler;
+
+    if (sampler)
+        wined3d_sampler_incref(sampler);
+    if (prev)
+        wined3d_sampler_decref(prev);
+}
+
+struct wined3d_sampler * CDECL wined3d_device_get_vs_sampler(const struct wined3d_device *device, UINT idx)
+{
+    TRACE("device %p, idx %u.\n", device, idx);
+
+    if (idx >= MAX_SAMPLER_OBJECTS)
+    {
+        WARN("Invalid sampler index %u.\n", idx);
+        return NULL;
+    }
+
+    return device->stateBlock->state.vs_sampler[idx];
+}
+
+HRESULT CDECL wined3d_device_set_vs_consts_b(struct wined3d_device *device,
+        UINT start_register, const BOOL *constants, UINT bool_count)
+{
+    UINT count = min(bool_count, MAX_CONST_B - start_register);
+    UINT i;
+
+    TRACE("device %p, start_register %u, constants %p, bool_count %u.\n",
+            device, start_register, constants, bool_count);
+
+    if (!constants || start_register >= MAX_CONST_B)
+        return WINED3DERR_INVALIDCALL;
+
+    memcpy(&device->updateStateBlock->state.vs_consts_b[start_register], constants, count * sizeof(BOOL));
+    for (i = 0; i < count; ++i)
+        TRACE("Set BOOL constant %u to %s.\n", start_register + i, constants[i] ? "true" : "false");
+
+    for (i = start_register; i < count + start_register; ++i)
+        device->updateStateBlock->changed.vertexShaderConstantsB |= (1 << i);
+
+    if (!device->isRecordingState)
+        device_invalidate_state(device, STATE_VERTEXSHADERCONSTANT);
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_device_get_vs_consts_b(const struct wined3d_device *device,
+        UINT start_register, BOOL *constants, UINT bool_count)
+{
+    UINT count = min(bool_count, MAX_CONST_B - start_register);
+
+    TRACE("device %p, start_register %u, constants %p, bool_count %u.\n",
+            device, start_register, constants, bool_count);
+
+    if (!constants || start_register >= MAX_CONST_B)
+        return WINED3DERR_INVALIDCALL;
+
+    memcpy(constants, &device->stateBlock->state.vs_consts_b[start_register], count * sizeof(BOOL));
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_device_set_vs_consts_i(struct wined3d_device *device,
+        UINT start_register, const int *constants, UINT vector4i_count)
+{
+    UINT count = min(vector4i_count, MAX_CONST_I - start_register);
+    UINT i;
+
+    TRACE("device %p, start_register %u, constants %p, vector4i_count %u.\n",
+            device, start_register, constants, vector4i_count);
+
+    if (!constants || start_register >= MAX_CONST_I)
+        return WINED3DERR_INVALIDCALL;
+
+    memcpy(&device->updateStateBlock->state.vs_consts_i[start_register * 4], constants, count * sizeof(int) * 4);
+    for (i = 0; i < count; ++i)
+        TRACE("Set INT constant %u to {%d, %d, %d, %d}.\n", start_register + i,
+                constants[i * 4], constants[i * 4 + 1],
+                constants[i * 4 + 2], constants[i * 4 + 3]);
+
+    for (i = start_register; i < count + start_register; ++i)
+        device->updateStateBlock->changed.vertexShaderConstantsI |= (1 << i);
+
+    if (!device->isRecordingState)
+        device_invalidate_state(device, STATE_VERTEXSHADERCONSTANT);
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_device_get_vs_consts_i(const struct wined3d_device *device,
+        UINT start_register, int *constants, UINT vector4i_count)
+{
+    UINT count = min(vector4i_count, MAX_CONST_I - start_register);
+
+    TRACE("device %p, start_register %u, constants %p, vector4i_count %u.\n",
+            device, start_register, constants, vector4i_count);
+
+    if (!constants || start_register >= MAX_CONST_I)
+        return WINED3DERR_INVALIDCALL;
+
+    memcpy(constants, &device->stateBlock->state.vs_consts_i[start_register * 4], count * sizeof(int) * 4);
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_device_set_vs_consts_f(struct wined3d_device *device,
+        UINT start_register, const float *constants, UINT vector4f_count)
+{
+    UINT i;
+    const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
+
+    TRACE("device %p, start_register %u, constants %p, vector4f_count %u.\n",
+            device, start_register, constants, vector4f_count);
+
+    /* Specifically test start_register > limit to catch MAX_UINT overflows
+     * when adding start_register + vector4f_count. */
+    if (!constants
+            || start_register + vector4f_count > d3d_info->limits.vs_uniform_count
+            || start_register > d3d_info->limits.vs_uniform_count)
+        return WINED3DERR_INVALIDCALL;
+
+    memcpy(&device->updateStateBlock->state.vs_consts_f[start_register * 4],
+            constants, vector4f_count * sizeof(float) * 4);
+    if (TRACE_ON(d3d))
+    {
+        for (i = 0; i < vector4f_count; ++i)
+            TRACE("Set FLOAT constant %u to {%.8e, %.8e, %.8e, %.8e}.\n", start_register + i,
+                    constants[i * 4], constants[i * 4 + 1],
+                    constants[i * 4 + 2], constants[i * 4 + 3]);
+    }
+
+    if (!device->isRecordingState)
+    {
+        device->shader_backend->shader_update_float_vertex_constants(device, start_register, vector4f_count);
+        device_invalidate_state(device, STATE_VERTEXSHADERCONSTANT);
+    }
+
+    memset(device->updateStateBlock->changed.vertexShaderConstantsF + start_register, 1,
+            sizeof(*device->updateStateBlock->changed.vertexShaderConstantsF) * vector4f_count);
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_device_get_vs_consts_f(const struct wined3d_device *device,
+        UINT start_register, float *constants, UINT vector4f_count)
+{
+    const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
+    int count = min(vector4f_count, d3d_info->limits.vs_uniform_count - start_register);
+
+    TRACE("device %p, start_register %u, constants %p, vector4f_count %u.\n",
+            device, start_register, constants, vector4f_count);
+
+    if (!constants || count < 0)
+        return WINED3DERR_INVALIDCALL;
+
+    memcpy(constants, &device->stateBlock->state.vs_consts_f[start_register * 4], count * sizeof(float) * 4);
+
+    return WINED3D_OK;
+}
+
+static void device_invalidate_texture_stage(const struct wined3d_device *device, DWORD stage)
+{
+    DWORD i;
+
+    for (i = 0; i <= WINED3D_HIGHEST_TEXTURE_STATE; ++i)
+    {
+        device_invalidate_state(device, STATE_TEXTURESTAGE(stage, i));
+    }
+}
+
+static void device_map_stage(struct wined3d_device *device, DWORD stage, DWORD unit)
+{
+    DWORD i = device->rev_tex_unit_map[unit];
+    DWORD j = device->texUnitMap[stage];
+
+    device->texUnitMap[stage] = unit;
+    if (i != WINED3D_UNMAPPED_STAGE && i != stage)
+        device->texUnitMap[i] = WINED3D_UNMAPPED_STAGE;
+
+    device->rev_tex_unit_map[unit] = stage;
+    if (j != WINED3D_UNMAPPED_STAGE && j != unit)
+        device->rev_tex_unit_map[j] = WINED3D_UNMAPPED_STAGE;
+}
+
+static void device_update_fixed_function_usage_map(struct wined3d_device *device)
+{
+    UINT i;
+
+    device->fixed_function_usage_map = 0;
+    for (i = 0; i < MAX_TEXTURES; ++i)
+    {
+        const struct wined3d_state *state = &device->stateBlock->state;
+        enum wined3d_texture_op color_op = state->texture_states[i][WINED3D_TSS_COLOR_OP];
+        enum wined3d_texture_op alpha_op = state->texture_states[i][WINED3D_TSS_ALPHA_OP];
+        DWORD color_arg1 = state->texture_states[i][WINED3D_TSS_COLOR_ARG1] & WINED3DTA_SELECTMASK;
+        DWORD color_arg2 = state->texture_states[i][WINED3D_TSS_COLOR_ARG2] & WINED3DTA_SELECTMASK;
+        DWORD color_arg3 = state->texture_states[i][WINED3D_TSS_COLOR_ARG0] & WINED3DTA_SELECTMASK;
+        DWORD alpha_arg1 = state->texture_states[i][WINED3D_TSS_ALPHA_ARG1] & WINED3DTA_SELECTMASK;
+        DWORD alpha_arg2 = state->texture_states[i][WINED3D_TSS_ALPHA_ARG2] & WINED3DTA_SELECTMASK;
+        DWORD alpha_arg3 = state->texture_states[i][WINED3D_TSS_ALPHA_ARG0] & WINED3DTA_SELECTMASK;
+
+        /* Not used, and disable higher stages. */
+        if (color_op == WINED3D_TOP_DISABLE)
+            break;
+
+        if (((color_arg1 == WINED3DTA_TEXTURE) && color_op != WINED3D_TOP_SELECT_ARG2)
+                || ((color_arg2 == WINED3DTA_TEXTURE) && color_op != WINED3D_TOP_SELECT_ARG1)
+                || ((color_arg3 == WINED3DTA_TEXTURE)
+                    && (color_op == WINED3D_TOP_MULTIPLY_ADD || color_op == WINED3D_TOP_LERP))
+                || ((alpha_arg1 == WINED3DTA_TEXTURE) && alpha_op != WINED3D_TOP_SELECT_ARG2)
+                || ((alpha_arg2 == WINED3DTA_TEXTURE) && alpha_op != WINED3D_TOP_SELECT_ARG1)
+                || ((alpha_arg3 == WINED3DTA_TEXTURE)
+                    && (alpha_op == WINED3D_TOP_MULTIPLY_ADD || alpha_op == WINED3D_TOP_LERP)))
+            device->fixed_function_usage_map |= (1 << i);
+
+        if ((color_op == WINED3D_TOP_BUMPENVMAP || color_op == WINED3D_TOP_BUMPENVMAP_LUMINANCE)
+                && i < MAX_TEXTURES - 1)
+            device->fixed_function_usage_map |= (1 << (i + 1));
+    }
+}
+
+static void device_map_fixed_function_samplers(struct wined3d_device *device, const struct wined3d_d3d_info *d3d_info)
+{
+    unsigned int i, tex;
+    WORD ffu_map;
+
+    device_update_fixed_function_usage_map(device);
+    ffu_map = device->fixed_function_usage_map;
+
+    if (d3d_info->limits.ffp_textures == d3d_info->limits.ffp_blend_stages
+            || device->stateBlock->state.lowest_disabled_stage <= d3d_info->limits.ffp_textures)
+    {
+        for (i = 0; ffu_map; ffu_map >>= 1, ++i)
+        {
+            if (!(ffu_map & 1)) continue;
+
+            if (device->texUnitMap[i] != i)
+            {
+                device_map_stage(device, i, i);
+                device_invalidate_state(device, STATE_SAMPLER(i));
+                device_invalidate_texture_stage(device, i);
+            }
+        }
+        return;
+    }
+
+    /* Now work out the mapping */
+    tex = 0;
+    for (i = 0; ffu_map; ffu_map >>= 1, ++i)
+    {
+        if (!(ffu_map & 1)) continue;
+
+        if (device->texUnitMap[i] != tex)
+        {
+            device_map_stage(device, i, tex);
+            device_invalidate_state(device, STATE_SAMPLER(i));
+            device_invalidate_texture_stage(device, i);
+        }
+
+        ++tex;
+    }
+}
+
+static void device_map_psamplers(struct wined3d_device *device, const struct wined3d_d3d_info *d3d_info)
+{
+    const enum wined3d_sampler_texture_type *sampler_type =
+            device->stateBlock->state.pixel_shader->reg_maps.sampler_type;
+    unsigned int i;
+
+    for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i)
+    {
+        if (sampler_type[i] && device->texUnitMap[i] != i)
+        {
+            device_map_stage(device, i, i);
+            device_invalidate_state(device, STATE_SAMPLER(i));
+            if (i < d3d_info->limits.ffp_blend_stages)
+                device_invalidate_texture_stage(device, i);
+        }
+    }
+}
+
+static BOOL device_unit_free_for_vs(const struct wined3d_device *device,
+        const enum wined3d_sampler_texture_type *pshader_sampler_tokens,
+        const enum wined3d_sampler_texture_type *vshader_sampler_tokens, DWORD unit)
+{
+    DWORD current_mapping = device->rev_tex_unit_map[unit];
+
+    /* Not currently used */
+    if (current_mapping == WINED3D_UNMAPPED_STAGE) return TRUE;
+
+    if (current_mapping < MAX_FRAGMENT_SAMPLERS) {
+        /* Used by a fragment sampler */
+
+        if (!pshader_sampler_tokens) {
+            /* No pixel shader, check fixed function */
+            return current_mapping >= MAX_TEXTURES || !(device->fixed_function_usage_map & (1 << current_mapping));
+        }
+
+        /* Pixel shader, check the shader's sampler map */
+        return !pshader_sampler_tokens[current_mapping];
+    }
+
+    /* Used by a vertex sampler */
+    return !vshader_sampler_tokens[current_mapping - MAX_FRAGMENT_SAMPLERS];
+}
+
+static void device_map_vsamplers(struct wined3d_device *device, BOOL ps, const struct wined3d_gl_info *gl_info)
+{
+    const enum wined3d_sampler_texture_type *vshader_sampler_type =
+            device->stateBlock->state.vertex_shader->reg_maps.sampler_type;
+    const enum wined3d_sampler_texture_type *pshader_sampler_type = NULL;
+    int start = min(MAX_COMBINED_SAMPLERS, gl_info->limits.combined_samplers) - 1;
+    int i;
+
+    if (ps)
+    {
+        /* Note that we only care if a sampler is sampled or not, not the sampler's specific type.
+         * Otherwise we'd need to call shader_update_samplers() here for 1.x pixelshaders. */
+        pshader_sampler_type = device->stateBlock->state.pixel_shader->reg_maps.sampler_type;
+    }
+
+    for (i = 0; i < MAX_VERTEX_SAMPLERS; ++i) {
+        DWORD vsampler_idx = i + MAX_FRAGMENT_SAMPLERS;
+        if (vshader_sampler_type[i])
+        {
+            if (device->texUnitMap[vsampler_idx] != WINED3D_UNMAPPED_STAGE)
+            {
+                /* Already mapped somewhere */
+                continue;
+            }
+
+            while (start >= 0)
+            {
+                if (device_unit_free_for_vs(device, pshader_sampler_type, vshader_sampler_type, start))
+                {
+                    device_map_stage(device, vsampler_idx, start);
+                    device_invalidate_state(device, STATE_SAMPLER(vsampler_idx));
+
+                    --start;
+                    break;
+                }
+
+                --start;
+            }
+        }
+    }
+}
+
+void device_update_tex_unit_map(struct wined3d_device *device)
+{
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
+    const struct wined3d_state *state = &device->stateBlock->state;
+    BOOL vs = use_vs(state);
+    BOOL ps = use_ps(state);
+    /*
+     * Rules are:
+     * -> Pixel shaders need a 1:1 map. In theory the shader input could be mapped too, but
+     * that would be really messy and require shader recompilation
+     * -> When the mapping of a stage is changed, sampler and ALL texture stage states have
+     * to be reset. Because of that try to work with a 1:1 mapping as much as possible
+     */
+    if (ps)
+        device_map_psamplers(device, d3d_info);
+    else
+        device_map_fixed_function_samplers(device, d3d_info);
+
+    if (vs)
+        device_map_vsamplers(device, ps, gl_info);
+}
+
+void CDECL wined3d_device_set_pixel_shader(struct wined3d_device *device, struct wined3d_shader *shader)
+{
+    struct wined3d_shader *prev = device->updateStateBlock->state.pixel_shader;
+
+    TRACE("device %p, shader %p.\n", device, shader);
+
+    if (shader)
+        wined3d_shader_incref(shader);
+    if (prev)
+        wined3d_shader_decref(prev);
+
+    device->updateStateBlock->state.pixel_shader = shader;
+    device->updateStateBlock->changed.pixelShader = TRUE;
+
+    if (device->isRecordingState)
+    {
+        TRACE("Recording... not performing anything.\n");
+        return;
+    }
+
+    if (shader == prev)
+    {
+        TRACE("Application is setting the old shader over, nothing to do.\n");
+        return;
+    }
+
+    device_invalidate_state(device, STATE_PIXELSHADER);
+}
+
+struct wined3d_shader * CDECL wined3d_device_get_pixel_shader(const struct wined3d_device *device)
+{
+    TRACE("device %p.\n", device);
+
+    return device->stateBlock->state.pixel_shader;
+}
+
+void CDECL wined3d_device_set_ps_cb(struct wined3d_device *device, UINT idx, struct wined3d_buffer *buffer)
+{
+    struct wined3d_buffer *prev;
+
+    TRACE("device %p, idx %u, buffer %p.\n", device, idx, buffer);
+
+    if (idx >= MAX_CONSTANT_BUFFERS)
+    {
+        WARN("Invalid constant buffer index %u.\n", idx);
+        return;
+    }
+
+    prev = device->updateStateBlock->state.ps_cb[idx];
+    device->updateStateBlock->state.ps_cb[idx] = buffer;
+
+    if (device->isRecordingState)
+    {
+        if (buffer)
+            wined3d_buffer_incref(buffer);
+        if (prev)
+            wined3d_buffer_decref(prev);
+        return;
+    }
+
+    if (prev != buffer)
+    {
+        if (buffer)
+        {
+            InterlockedIncrement(&buffer->resource.bind_count);
+            wined3d_buffer_incref(buffer);
+        }
+        if (prev)
+        {
+            InterlockedDecrement(&prev->resource.bind_count);
+            wined3d_buffer_decref(prev);
+        }
+    }
+}
+
+struct wined3d_buffer * CDECL wined3d_device_get_ps_cb(const struct wined3d_device *device, UINT idx)
+{
+    TRACE("device %p, idx %u.\n", device, idx);
+
+    if (idx >= MAX_CONSTANT_BUFFERS)
+    {
+        WARN("Invalid constant buffer index %u.\n", idx);
+        return NULL;
+    }
+
+    return device->stateBlock->state.ps_cb[idx];
+}
+
+void CDECL wined3d_device_set_ps_sampler(struct wined3d_device *device, UINT idx, struct wined3d_sampler *sampler)
+{
+    struct wined3d_sampler *prev;
+
+    TRACE("device %p, idx %u, sampler %p.\n", device, idx, sampler);
+
+    if (idx >= MAX_SAMPLER_OBJECTS)
+    {
+        WARN("Invalid sampler index %u.\n", idx);
+        return;
+    }
+
+    prev = device->updateStateBlock->state.ps_sampler[idx];
+    device->updateStateBlock->state.ps_sampler[idx] = sampler;
+
+    if (sampler)
+        wined3d_sampler_incref(sampler);
+    if (prev)
+        wined3d_sampler_decref(prev);
+}
+
+struct wined3d_sampler * CDECL wined3d_device_get_ps_sampler(const struct wined3d_device *device, UINT idx)
+{
+    TRACE("device %p, idx %u.\n", device, idx);
+
+    if (idx >= MAX_SAMPLER_OBJECTS)
+    {
+        WARN("Invalid sampler index %u.\n", idx);
+        return NULL;
+    }
+
+    return device->stateBlock->state.ps_sampler[idx];
+}
+
+HRESULT CDECL wined3d_device_set_ps_consts_b(struct wined3d_device *device,
+        UINT start_register, const BOOL *constants, UINT bool_count)
+{
+    UINT count = min(bool_count, MAX_CONST_B - start_register);
+    UINT i;
+
+    TRACE("device %p, start_register %u, constants %p, bool_count %u.\n",
+            device, start_register, constants, bool_count);
+
+    if (!constants || start_register >= MAX_CONST_B)
+        return WINED3DERR_INVALIDCALL;
+
+    memcpy(&device->updateStateBlock->state.ps_consts_b[start_register], constants, count * sizeof(BOOL));
+    for (i = 0; i < count; ++i)
+        TRACE("Set BOOL constant %u to %s.\n", start_register + i, constants[i] ? "true" : "false");
+
+    for (i = start_register; i < count + start_register; ++i)
+        device->updateStateBlock->changed.pixelShaderConstantsB |= (1 << i);
+
+    if (!device->isRecordingState)
+        device_invalidate_state(device, STATE_PIXELSHADERCONSTANT);
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_device_get_ps_consts_b(const struct wined3d_device *device,
+        UINT start_register, BOOL *constants, UINT bool_count)
+{
+    UINT count = min(bool_count, MAX_CONST_B - start_register);
+
+    TRACE("device %p, start_register %u, constants %p, bool_count %u.\n",
+            device, start_register, constants, bool_count);
+
+    if (!constants || start_register >= MAX_CONST_B)
+        return WINED3DERR_INVALIDCALL;
+
+    memcpy(constants, &device->stateBlock->state.ps_consts_b[start_register], count * sizeof(BOOL));
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_device_set_ps_consts_i(struct wined3d_device *device,
+        UINT start_register, const int *constants, UINT vector4i_count)
+{
+    UINT count = min(vector4i_count, MAX_CONST_I - start_register);
+    UINT i;
+
+    TRACE("device %p, start_register %u, constants %p, vector4i_count %u.\n",
+            device, start_register, constants, vector4i_count);
+
+    if (!constants || start_register >= MAX_CONST_I)
+        return WINED3DERR_INVALIDCALL;
+
+    memcpy(&device->updateStateBlock->state.ps_consts_i[start_register * 4], constants, count * sizeof(int) * 4);
+    for (i = 0; i < count; ++i)
+        TRACE("Set INT constant %u to {%d, %d, %d, %d}.\n", start_register + i,
+                constants[i * 4], constants[i * 4 + 1],
+                constants[i * 4 + 2], constants[i * 4 + 3]);
+
+    for (i = start_register; i < count + start_register; ++i)
+        device->updateStateBlock->changed.pixelShaderConstantsI |= (1 << i);
+
+    if (!device->isRecordingState)
+        device_invalidate_state(device, STATE_PIXELSHADERCONSTANT);
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_device_get_ps_consts_i(const struct wined3d_device *device,
+        UINT start_register, int *constants, UINT vector4i_count)
+{
+    UINT count = min(vector4i_count, MAX_CONST_I - start_register);
+
+    TRACE("device %p, start_register %u, constants %p, vector4i_count %u.\n",
+            device, start_register, constants, vector4i_count);
+
+    if (!constants || start_register >= MAX_CONST_I)
+        return WINED3DERR_INVALIDCALL;
+
+    memcpy(constants, &device->stateBlock->state.ps_consts_i[start_register * 4], count * sizeof(int) * 4);
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_device_set_ps_consts_f(struct wined3d_device *device,
+        UINT start_register, const float *constants, UINT vector4f_count)
+{
+    UINT i;
+    const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
+
+    TRACE("device %p, start_register %u, constants %p, vector4f_count %u.\n",
+            device, start_register, constants, vector4f_count);
+
+    /* Specifically test start_register > limit to catch MAX_UINT overflows
+     * when adding start_register + vector4f_count. */
+    if (!constants
+            || start_register + vector4f_count > d3d_info->limits.ps_uniform_count
+            || start_register > d3d_info->limits.ps_uniform_count)
+        return WINED3DERR_INVALIDCALL;
+
+    memcpy(&device->updateStateBlock->state.ps_consts_f[start_register * 4],
+            constants, vector4f_count * sizeof(float) * 4);
+    if (TRACE_ON(d3d))
+    {
+        for (i = 0; i < vector4f_count; ++i)
+            TRACE("Set FLOAT constant %u to {%.8e, %.8e, %.8e, %.8e}.\n", start_register + i,
+                    constants[i * 4], constants[i * 4 + 1],
+                    constants[i * 4 + 2], constants[i * 4 + 3]);
+    }
+
+    if (!device->isRecordingState)
+    {
+        device->shader_backend->shader_update_float_pixel_constants(device, start_register, vector4f_count);
+        device_invalidate_state(device, STATE_PIXELSHADERCONSTANT);
+    }
+
+    memset(device->updateStateBlock->changed.pixelShaderConstantsF + start_register, 1,
+            sizeof(*device->updateStateBlock->changed.pixelShaderConstantsF) * vector4f_count);
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_device_get_ps_consts_f(const struct wined3d_device *device,
+        UINT start_register, float *constants, UINT vector4f_count)
+{
+    const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
+    int count = min(vector4f_count, d3d_info->limits.ps_uniform_count - start_register);
+
+    TRACE("device %p, start_register %u, constants %p, vector4f_count %u.\n",
+            device, start_register, constants, vector4f_count);
+
+    if (!constants || count < 0)
+        return WINED3DERR_INVALIDCALL;
+
+    memcpy(constants, &device->stateBlock->state.ps_consts_f[start_register * 4], count * sizeof(float) * 4);
+
+    return WINED3D_OK;
+}
+
+void CDECL wined3d_device_set_geometry_shader(struct wined3d_device *device, struct wined3d_shader *shader)
+{
+    struct wined3d_shader *prev = device->updateStateBlock->state.geometry_shader;
+
+    TRACE("device %p, shader %p.\n", device, shader);
+
+    if (shader)
+        wined3d_shader_incref(shader);
+    if (prev)
+        wined3d_shader_decref(prev);
+
+    device->updateStateBlock->state.geometry_shader = shader;
+
+    if (device->isRecordingState || shader == prev)
+        return;
+
+    device_invalidate_state(device, STATE_GEOMETRY_SHADER);
+}
+
+struct wined3d_shader * CDECL wined3d_device_get_geometry_shader(const struct wined3d_device *device)
+{
+    TRACE("device %p.\n", device);
+
+    return device->stateBlock->state.geometry_shader;
+}
+
+void CDECL wined3d_device_set_gs_cb(struct wined3d_device *device, UINT idx, struct wined3d_buffer *buffer)
+{
+    struct wined3d_buffer *prev;
+
+    TRACE("device %p, idx %u, buffer %p.\n", device, idx, buffer);
+
+    if (idx >= MAX_CONSTANT_BUFFERS)
+    {
+        WARN("Invalid constant buffer index %u.\n", idx);
+        return;
+    }
+
+    prev = device->updateStateBlock->state.gs_cb[idx];
+    device->updateStateBlock->state.gs_cb[idx] = buffer;
+
+    if (device->isRecordingState)
+    {
+        if (buffer)
+            wined3d_buffer_incref(buffer);
+        if (prev)
+            wined3d_buffer_decref(prev);
+        return;
+    }
+
+    if (prev != buffer)
+    {
+        if (buffer)
+        {
+            InterlockedIncrement(&buffer->resource.bind_count);
+            wined3d_buffer_incref(buffer);
+        }
+        if (prev)
+        {
+            InterlockedDecrement(&prev->resource.bind_count);
+            wined3d_buffer_decref(prev);
+        }
+    }
+}
+
+struct wined3d_buffer * CDECL wined3d_device_get_gs_cb(const struct wined3d_device *device, UINT idx)
+{
+    TRACE("device %p, idx %u.\n", device, idx);
+
+    if (idx >= MAX_CONSTANT_BUFFERS)
+    {
+        WARN("Invalid constant buffer index %u.\n", idx);
+        return NULL;
+    }
+
+    return device->stateBlock->state.gs_cb[idx];
+}
+
+void CDECL wined3d_device_set_gs_sampler(struct wined3d_device *device, UINT idx, struct wined3d_sampler *sampler)
+{
+    struct wined3d_sampler *prev;
+
+    TRACE("device %p, idx %u, sampler %p.\n", device, idx, sampler);
+
+    if (idx >= MAX_SAMPLER_OBJECTS)
+    {
+        WARN("Invalid sampler index %u.\n", idx);
+        return;
+    }
+
+    prev = device->updateStateBlock->state.gs_sampler[idx];
+    device->updateStateBlock->state.gs_sampler[idx] = sampler;
+
+    if (sampler)
+        wined3d_sampler_incref(sampler);
+    if (prev)
+        wined3d_sampler_decref(prev);
+}
+
+struct wined3d_sampler * CDECL wined3d_device_get_gs_sampler(const struct wined3d_device *device, UINT idx)
+{
+    TRACE("device %p, idx %u.\n", device, idx);
+
+    if (idx >= MAX_SAMPLER_OBJECTS)
+    {
+        WARN("Invalid sampler index %u.\n", idx);
+        return NULL;
+    }
+
+    return device->stateBlock->state.gs_sampler[idx];
+}
+
+/* Context activation is done by the caller. */
+/* Do not call while under the GL lock. */
+#define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
+static HRESULT process_vertices_strided(const struct wined3d_device *device, DWORD dwDestIndex, DWORD dwCount,
+        const struct wined3d_stream_info *stream_info, struct wined3d_buffer *dest, DWORD flags,
+        DWORD DestFVF)
+{
+    struct wined3d_matrix mat, proj_mat, view_mat, world_mat;
+    struct wined3d_viewport vp;
+    UINT vertex_size;
+    unsigned int i;
+    BYTE *dest_ptr;
+    BOOL doClip;
+    DWORD numTextures;
+    HRESULT hr;
+
+    if (stream_info->use_map & (1 << WINED3D_FFP_NORMAL))
+    {
+        WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
+    }
+
+    if (!(stream_info->use_map & (1 << WINED3D_FFP_POSITION)))
+    {
+        ERR("Source has no position mask\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    if (device->stateBlock->state.render_states[WINED3D_RS_CLIPPING])
+    {
+        static BOOL warned = FALSE;
+        /*
+         * The clipping code is not quite correct. Some things need
+         * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
+         * so disable clipping for now.
+         * (The graphics in Half-Life are broken, and my processvertices
+         *  test crashes with IDirect3DDevice3)
+        doClip = TRUE;
+         */
+        doClip = FALSE;
+        if(!warned) {
+           warned = TRUE;
+           FIXME("Clipping is broken and disabled for now\n");
+        }
+    }
+    else
+        doClip = FALSE;
+
+    vertex_size = get_flexible_vertex_size(DestFVF);
+    if (FAILED(hr = wined3d_buffer_map(dest, dwDestIndex * vertex_size, dwCount * vertex_size, &dest_ptr, 0)))
+    {
+        WARN("Failed to map buffer, hr %#x.\n", hr);
+        return hr;
+    }
+
+    wined3d_device_get_transform(device, WINED3D_TS_VIEW, &view_mat);
+    wined3d_device_get_transform(device, WINED3D_TS_PROJECTION, &proj_mat);
+    wined3d_device_get_transform(device, WINED3D_TS_WORLD_MATRIX(0), &world_mat);
+
+    TRACE("View mat:\n");
+    TRACE("%f %f %f %f\n", view_mat.u.s._11, view_mat.u.s._12, view_mat.u.s._13, view_mat.u.s._14);
+    TRACE("%f %f %f %f\n", view_mat.u.s._21, view_mat.u.s._22, view_mat.u.s._23, view_mat.u.s._24);
+    TRACE("%f %f %f %f\n", view_mat.u.s._31, view_mat.u.s._32, view_mat.u.s._33, view_mat.u.s._34);
+    TRACE("%f %f %f %f\n", view_mat.u.s._41, view_mat.u.s._42, view_mat.u.s._43, view_mat.u.s._44);
+
+    TRACE("Proj mat:\n");
+    TRACE("%f %f %f %f\n", proj_mat.u.s._11, proj_mat.u.s._12, proj_mat.u.s._13, proj_mat.u.s._14);
+    TRACE("%f %f %f %f\n", proj_mat.u.s._21, proj_mat.u.s._22, proj_mat.u.s._23, proj_mat.u.s._24);
+    TRACE("%f %f %f %f\n", proj_mat.u.s._31, proj_mat.u.s._32, proj_mat.u.s._33, proj_mat.u.s._34);
+    TRACE("%f %f %f %f\n", proj_mat.u.s._41, proj_mat.u.s._42, proj_mat.u.s._43, proj_mat.u.s._44);
+
+    TRACE("World mat:\n");
+    TRACE("%f %f %f %f\n", world_mat.u.s._11, world_mat.u.s._12, world_mat.u.s._13, world_mat.u.s._14);
+    TRACE("%f %f %f %f\n", world_mat.u.s._21, world_mat.u.s._22, world_mat.u.s._23, world_mat.u.s._24);
+    TRACE("%f %f %f %f\n", world_mat.u.s._31, world_mat.u.s._32, world_mat.u.s._33, world_mat.u.s._34);
+    TRACE("%f %f %f %f\n", world_mat.u.s._41, world_mat.u.s._42, world_mat.u.s._43, world_mat.u.s._44);
+
+    /* Get the viewport */
+    wined3d_device_get_viewport(device, &vp);
+    TRACE("viewport  x %u, y %u, width %u, height %u, min_z %.8e, max_z %.8e.\n",
+          vp.x, vp.y, vp.width, vp.height, vp.min_z, vp.max_z);
+
+    multiply_matrix(&mat,&view_mat,&world_mat);
+    multiply_matrix(&mat,&proj_mat,&mat);
+
+    numTextures = (DestFVF & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
+
+    for (i = 0; i < dwCount; i+= 1) {
+        unsigned int tex_index;
+
+        if ( ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZ ) ||
+             ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) ) {
+            /* The position first */
+            const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_POSITION];
+            const float *p = (const float *)(element->data.addr + i * element->stride);
+            float x, y, z, rhw;
+            TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
+
+            /* Multiplication with world, view and projection matrix */
+            x =   (p[0] * mat.u.s._11) + (p[1] * mat.u.s._21) + (p[2] * mat.u.s._31) + (1.0f * mat.u.s._41);
+            y =   (p[0] * mat.u.s._12) + (p[1] * mat.u.s._22) + (p[2] * mat.u.s._32) + (1.0f * mat.u.s._42);
+            z =   (p[0] * mat.u.s._13) + (p[1] * mat.u.s._23) + (p[2] * mat.u.s._33) + (1.0f * mat.u.s._43);
+            rhw = (p[0] * mat.u.s._14) + (p[1] * mat.u.s._24) + (p[2] * mat.u.s._34) + (1.0f * mat.u.s._44);
+
+            TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
+
+            /* WARNING: The following things are taken from d3d7 and were not yet checked
+             * against d3d8 or d3d9!
+             */
+
+            /* Clipping conditions: From msdn
+             *
+             * A vertex is clipped if it does not match the following requirements
+             * -rhw < x <= rhw
+             * -rhw < y <= rhw
+             *    0 < z <= rhw
+             *    0 < rhw ( Not in d3d7, but tested in d3d7)
+             *
+             * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
+             * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
+             *
+             */
+
+            if( !doClip ||
+                ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
+                  (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) &&
+                  ( rhw > eps ) ) ) {
+
+                /* "Normal" viewport transformation (not clipped)
+                 * 1) The values are divided by rhw
+                 * 2) The y axis is negative, so multiply it with -1
+                 * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
+                 *    -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
+                 * 4) Multiply x with Width/2 and add Width/2
+                 * 5) The same for the height
+                 * 6) Add the viewpoint X and Y to the 2D coordinates and
+                 *    The minimum Z value to z
+                 * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
+                 *
+                 * Well, basically it's simply a linear transformation into viewport
+                 * coordinates
+                 */
+
+                x /= rhw;
+                y /= rhw;
+                z /= rhw;
+
+                y *= -1;
+
+                x *= vp.width / 2;
+                y *= vp.height / 2;
+                z *= vp.max_z - vp.min_z;
+
+                x += vp.width / 2 + vp.x;
+                y += vp.height / 2 + vp.y;
+                z += vp.min_z;
+
+                rhw = 1 / rhw;
+            } else {
+                /* That vertex got clipped
+                 * Contrary to OpenGL it is not dropped completely, it just
+                 * undergoes a different calculation.
+                 */
+                TRACE("Vertex got clipped\n");
+                x += rhw;
+                y += rhw;
+
+                x  /= 2;
+                y  /= 2;
+
+                /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
+                 * outside of the main vertex buffer memory. That needs some more
+                 * investigation...
+                 */
+            }
+
+            TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
+
+
+            ( (float *) dest_ptr)[0] = x;
+            ( (float *) dest_ptr)[1] = y;
+            ( (float *) dest_ptr)[2] = z;
+            ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
+
+            dest_ptr += 3 * sizeof(float);
+
+            if ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW)
+                dest_ptr += sizeof(float);
+        }
+
+        if (DestFVF & WINED3DFVF_PSIZE)
+            dest_ptr += sizeof(DWORD);
+
+        if (DestFVF & WINED3DFVF_NORMAL)
+        {
+            const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_NORMAL];
+            const float *normal = (const float *)(element->data.addr + i * element->stride);
+            /* AFAIK this should go into the lighting information */
+            FIXME("Didn't expect the destination to have a normal\n");
+            copy_and_next(dest_ptr, normal, 3 * sizeof(float));
+        }
+
+        if (DestFVF & WINED3DFVF_DIFFUSE)
+        {
+            const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_DIFFUSE];
+            const DWORD *color_d = (const DWORD *)(element->data.addr + i * element->stride);
+            if (!(stream_info->use_map & (1 << WINED3D_FFP_DIFFUSE)))
+            {
+                static BOOL warned = FALSE;
+
+                if(!warned) {
+                    ERR("No diffuse color in source, but destination has one\n");
+                    warned = TRUE;
+                }
+
+                *( (DWORD *) dest_ptr) = 0xffffffff;
+                dest_ptr += sizeof(DWORD);
+            }
+            else
+            {
+                copy_and_next(dest_ptr, color_d, sizeof(DWORD));
+            }
+        }
+
+        if (DestFVF & WINED3DFVF_SPECULAR)
+        {
+            /* What's the color value in the feedback buffer? */
+            const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_SPECULAR];
+            const DWORD *color_s = (const DWORD *)(element->data.addr + i * element->stride);
+            if (!(stream_info->use_map & (1 << WINED3D_FFP_SPECULAR)))
+            {
+                static BOOL warned = FALSE;
+
+                if(!warned) {
+                    ERR("No specular color in source, but destination has one\n");
+                    warned = TRUE;
+                }
+
+                *(DWORD *)dest_ptr = 0xff000000;
+                dest_ptr += sizeof(DWORD);
+            }
+            else
+            {
+                copy_and_next(dest_ptr, color_s, sizeof(DWORD));
+            }
+        }
+
+        for (tex_index = 0; tex_index < numTextures; ++tex_index)
+        {
+            const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_TEXCOORD0 + tex_index];
+            const float *tex_coord = (const float *)(element->data.addr + i * element->stride);
+            if (!(stream_info->use_map & (1 << (WINED3D_FFP_TEXCOORD0 + tex_index))))
+            {
+                ERR("No source texture, but destination requests one\n");
+                dest_ptr += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
+            }
+            else
+            {
+                copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
+            }
+        }
+    }
+
+    wined3d_buffer_unmap(dest);
+
+    return WINED3D_OK;
+}
+#undef copy_and_next
+
+/* Do not call while under the GL lock. */
+HRESULT CDECL wined3d_device_process_vertices(struct wined3d_device *device,
+        UINT src_start_idx, UINT dst_idx, UINT vertex_count, struct wined3d_buffer *dst_buffer,
+        const struct wined3d_vertex_declaration *declaration, DWORD flags, DWORD dst_fvf)
+{
+    struct wined3d_state *state = &device->stateBlock->state;
+    struct wined3d_stream_info stream_info;
+    const struct wined3d_gl_info *gl_info;
+    struct wined3d_context *context;
+    struct wined3d_shader *vs;
+    unsigned int i;
+    HRESULT hr;
+
+    TRACE("device %p, src_start_idx %u, dst_idx %u, vertex_count %u, "
+            "dst_buffer %p, declaration %p, flags %#x, dst_fvf %#x.\n",
+            device, src_start_idx, dst_idx, vertex_count,
+            dst_buffer, declaration, flags, dst_fvf);
+
+    if (declaration)
+        FIXME("Output vertex declaration not implemented yet.\n");
+
+    /* Need any context to write to the vbo. */
+    context = context_acquire(device, NULL);
+    gl_info = context->gl_info;
+
+    vs = state->vertex_shader;
+    state->vertex_shader = NULL;
+    device_stream_info_from_declaration(device, &stream_info);
+    state->vertex_shader = vs;
+
+    /* We can't convert FROM a VBO, and vertex buffers used to source into
+     * process_vertices() are unlikely to ever be used for drawing. Release
+     * VBOs in those buffers and fix up the stream_info structure.
+     *
+     * Also apply the start index. */
+    for (i = 0; i < (sizeof(stream_info.elements) / sizeof(*stream_info.elements)); ++i)
+    {
+        struct wined3d_stream_info_element *e;
+
+        if (!(stream_info.use_map & (1 << i)))
+            continue;
+
+        e = &stream_info.elements[i];
+        if (e->data.buffer_object)
+        {
+            struct wined3d_buffer *vb = state->streams[e->stream_idx].buffer;
+            e->data.buffer_object = 0;
+            e->data.addr = (BYTE *)((ULONG_PTR)e->data.addr + (ULONG_PTR)buffer_get_sysmem(vb, gl_info));
+            GL_EXTCALL(glDeleteBuffersARB(1, &vb->buffer_object));
+            vb->buffer_object = 0;
+        }
+        if (e->data.addr)
+            e->data.addr += e->stride * src_start_idx;
+    }
+
+    hr = process_vertices_strided(device, dst_idx, vertex_count,
+            &stream_info, dst_buffer, flags, dst_fvf);
+
+    context_release(context);
+
+    return hr;
+}
+
+void CDECL wined3d_device_set_texture_stage_state(struct wined3d_device *device,
+        UINT stage, enum wined3d_texture_stage_state state, DWORD value)
+{
+    const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
+    DWORD old_value;
+
+    TRACE("device %p, stage %u, state %s, value %#x.\n",
+            device, stage, debug_d3dtexturestate(state), value);
+
+    if (state > WINED3D_HIGHEST_TEXTURE_STATE)
+    {
+        WARN("Invalid state %#x passed.\n", state);
+        return;
+    }
+
+    if (stage >= d3d_info->limits.ffp_blend_stages)
+    {
+        WARN("Attempting to set stage %u which is higher than the max stage %u, ignoring.\n",
+                stage, d3d_info->limits.ffp_blend_stages - 1);
+        return;
+    }
+
+    old_value = device->updateStateBlock->state.texture_states[stage][state];
+    device->updateStateBlock->changed.textureState[stage] |= 1 << state;
+    device->updateStateBlock->state.texture_states[stage][state] = value;
+
+    if (device->isRecordingState)
+    {
+        TRACE("Recording... not performing anything.\n");
+        return;
+    }
+
+    /* Checked after the assignments to allow proper stateblock recording. */
+    if (old_value == value)
+    {
+        TRACE("Application is setting the old value over, nothing to do.\n");
+        return;
+    }
+
+    if (stage > device->stateBlock->state.lowest_disabled_stage
+            && device->StateTable[STATE_TEXTURESTAGE(0, state)].representative
+            == STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP))
+    {
+        /* Colorop change above lowest disabled stage? That won't change
+         * anything in the GL setup. Changes in other states are important on
+         * disabled stages too. */
+        return;
+    }
+
+    if (state == WINED3D_TSS_COLOR_OP)
+    {
+        unsigned int i;
+
+        if (value == WINED3D_TOP_DISABLE && old_value != WINED3D_TOP_DISABLE)
+        {
+            /* Previously enabled stage disabled now. Make sure to dirtify
+             * all enabled stages above stage, they have to be disabled.
+             *
+             * The current stage is dirtified below. */
+            for (i = stage + 1; i < device->stateBlock->state.lowest_disabled_stage; ++i)
+            {
+                TRACE("Additionally dirtifying stage %u.\n", i);
+                device_invalidate_state(device, STATE_TEXTURESTAGE(i, WINED3D_TSS_COLOR_OP));
+            }
+            device->stateBlock->state.lowest_disabled_stage = stage;
+            TRACE("New lowest disabled: %u.\n", stage);
+        }
+        else if (value != WINED3D_TOP_DISABLE && old_value == WINED3D_TOP_DISABLE)
+        {
+            /* Previously disabled stage enabled. Stages above it may need
+             * enabling. Stage must be lowest_disabled_stage here, if it's
+             * bigger success is returned above, and stages below the lowest
+             * disabled stage can't be enabled (because they are enabled
+             * already).
+             *
+             * Again stage stage doesn't need to be dirtified here, it is
+             * handled below. */
+            for (i = stage + 1; i < d3d_info->limits.ffp_blend_stages; ++i)
+            {
+                if (device->updateStateBlock->state.texture_states[i][WINED3D_TSS_COLOR_OP] == WINED3D_TOP_DISABLE)
+                    break;
+                TRACE("Additionally dirtifying stage %u due to enable.\n", i);
+                device_invalidate_state(device, STATE_TEXTURESTAGE(i, WINED3D_TSS_COLOR_OP));
+            }
+            device->stateBlock->state.lowest_disabled_stage = i;
+            TRACE("New lowest disabled: %u.\n", i);
+        }
+    }
+
+    device_invalidate_state(device, STATE_TEXTURESTAGE(stage, state));
+}
+
+DWORD CDECL wined3d_device_get_texture_stage_state(const struct wined3d_device *device,
+        UINT stage, enum wined3d_texture_stage_state state)
+{
+    TRACE("device %p, stage %u, state %s.\n",
+            device, stage, debug_d3dtexturestate(state));
+
+    if (state > WINED3D_HIGHEST_TEXTURE_STATE)
+    {
+        WARN("Invalid state %#x passed.\n", state);
+        return 0;
+    }
+
+    return device->updateStateBlock->state.texture_states[stage][state];
+}
+
+HRESULT CDECL wined3d_device_set_texture(struct wined3d_device *device,
+        UINT stage, struct wined3d_texture *texture)
+{
+    const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
+    struct wined3d_texture *prev;
+
+    TRACE("device %p, stage %u, texture %p.\n", device, stage, texture);
+
+    if (stage >= WINED3DVERTEXTEXTURESAMPLER0 && stage <= WINED3DVERTEXTEXTURESAMPLER3)
+        stage -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS);
+
+    /* Windows accepts overflowing this array... we do not. */
+    if (stage >= sizeof(device->stateBlock->state.textures) / sizeof(*device->stateBlock->state.textures))
+    {
+        WARN("Ignoring invalid stage %u.\n", stage);
+        return WINED3D_OK;
+    }
+
+    if (texture && texture->resource.pool == WINED3D_POOL_SCRATCH)
+    {
+        WARN("Rejecting attempt to set scratch texture.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    device->updateStateBlock->changed.textures |= 1 << stage;
+
+    prev = device->updateStateBlock->state.textures[stage];
+    TRACE("Previous texture %p.\n", prev);
+
+    if (texture == prev)
+    {
+        TRACE("App is setting the same texture again, nothing to do.\n");
+        return WINED3D_OK;
+    }
+
+    TRACE("Setting new texture to %p.\n", texture);
+    device->updateStateBlock->state.textures[stage] = texture;
+
+    if (device->isRecordingState)
+    {
+        TRACE("Recording... not performing anything\n");
+
+        if (texture) wined3d_texture_incref(texture);
+        if (prev) wined3d_texture_decref(prev);
+
+        return WINED3D_OK;
+    }
+
+    if (texture)
+    {
+        LONG bind_count = InterlockedIncrement(&texture->resource.bind_count);
+
+        wined3d_texture_incref(texture);
+
+        if (!prev || texture->target != prev->target)
+            device_invalidate_state(device, STATE_PIXELSHADER);
+
+        if (!prev && stage < d3d_info->limits.ffp_blend_stages)
+        {
+            /* The source arguments for color and alpha ops have different
+             * meanings when a NULL texture is bound, so the COLOR_OP and
+             * ALPHA_OP have to be dirtified. */
+            device_invalidate_state(device, STATE_TEXTURESTAGE(stage, WINED3D_TSS_COLOR_OP));
+            device_invalidate_state(device, STATE_TEXTURESTAGE(stage, WINED3D_TSS_ALPHA_OP));
+        }
+
+        if (bind_count == 1)
+            texture->sampler = stage;
+    }
+
+    if (prev)
+    {
+        LONG bind_count = InterlockedDecrement(&prev->resource.bind_count);
+
+        if (!texture && stage < d3d_info->limits.ffp_blend_stages)
+        {
+            device_invalidate_state(device, STATE_TEXTURESTAGE(stage, WINED3D_TSS_COLOR_OP));
+            device_invalidate_state(device, STATE_TEXTURESTAGE(stage, WINED3D_TSS_ALPHA_OP));
+        }
+
+        if (bind_count && prev->sampler == stage)
+        {
+            unsigned int i;
+
+            /* Search for other stages the texture is bound to. Shouldn't
+             * happen if applications bind textures to a single stage only. */
+            TRACE("Searching for other stages the texture is bound to.\n");
+            for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
+            {
+                if (device->updateStateBlock->state.textures[i] == prev)
+                {
+                    TRACE("Texture is also bound to stage %u.\n", i);
+                    prev->sampler = i;
+                    break;
+                }
+            }
+        }
+
+        wined3d_texture_decref(prev);
+    }
+
+    device_invalidate_state(device, STATE_SAMPLER(stage));
+
+    return WINED3D_OK;
+}
+
+struct wined3d_texture * CDECL wined3d_device_get_texture(const struct wined3d_device *device, UINT stage)
+{
+    TRACE("device %p, stage %u.\n", device, stage);
+
+    if (stage >= WINED3DVERTEXTEXTURESAMPLER0 && stage <= WINED3DVERTEXTEXTURESAMPLER3)
+        stage -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS);
+
+    if (stage >= sizeof(device->stateBlock->state.textures) / sizeof(*device->stateBlock->state.textures))
+    {
+        WARN("Ignoring invalid stage %u.\n", stage);
+        return NULL; /* Windows accepts overflowing this array ... we do not. */
+    }
+
+    return device->stateBlock->state.textures[stage];
+}
+
+HRESULT CDECL wined3d_device_get_back_buffer(const struct wined3d_device *device, UINT swapchain_idx,
+        UINT backbuffer_idx, enum wined3d_backbuffer_type backbuffer_type, struct wined3d_surface **backbuffer)
+{
+    struct wined3d_swapchain *swapchain;
+
+    TRACE("device %p, swapchain_idx %u, backbuffer_idx %u, backbuffer_type %#x, backbuffer %p.\n",
+            device, swapchain_idx, backbuffer_idx, backbuffer_type, backbuffer);
+
+    if (!(swapchain = wined3d_device_get_swapchain(device, swapchain_idx)))
+        return WINED3DERR_INVALIDCALL;
+
+    if (!(*backbuffer = wined3d_swapchain_get_back_buffer(swapchain, backbuffer_idx, backbuffer_type)))
+        return WINED3DERR_INVALIDCALL;
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_device_get_device_caps(const struct wined3d_device *device, WINED3DCAPS *caps)
+{
+    TRACE("device %p, caps %p.\n", device, caps);
+
+    return wined3d_get_device_caps(device->wined3d, device->adapter->ordinal,
+            device->create_parms.device_type, caps);
+}
+
+HRESULT CDECL wined3d_device_get_display_mode(const struct wined3d_device *device, UINT swapchain_idx,
+        struct wined3d_display_mode *mode, enum wined3d_display_rotation *rotation)
+{
+    struct wined3d_swapchain *swapchain;
+
+    TRACE("device %p, swapchain_idx %u, mode %p, rotation %p.\n",
+            device, swapchain_idx, mode, rotation);
+
+    if (!(swapchain = wined3d_device_get_swapchain(device, swapchain_idx)))
+        return WINED3DERR_INVALIDCALL;
+
+    return wined3d_swapchain_get_display_mode(swapchain, mode, rotation);
+}
+
+HRESULT CDECL wined3d_device_begin_stateblock(struct wined3d_device *device)
+{
+    struct wined3d_stateblock *stateblock;
+    HRESULT hr;
+
+    TRACE("device %p.\n", device);
+
+    if (device->isRecordingState)
+        return WINED3DERR_INVALIDCALL;
+
+    hr = wined3d_stateblock_create(device, WINED3D_SBT_RECORDED, &stateblock);
+    if (FAILED(hr))
+        return hr;
+
+    wined3d_stateblock_decref(device->updateStateBlock);
+    device->updateStateBlock = stateblock;
+    device->isRecordingState = TRUE;
+
+    TRACE("Recording stateblock %p.\n", stateblock);
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_device_end_stateblock(struct wined3d_device *device,
+        struct wined3d_stateblock **stateblock)
+{
+    struct wined3d_stateblock *object = device->updateStateBlock;
+
+    TRACE("device %p, stateblock %p.\n", device, stateblock);
+
+    if (!device->isRecordingState)
+    {
+        WARN("Not recording.\n");
+        *stateblock = NULL;
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    stateblock_init_contained_states(object);
+
+    *stateblock = object;
+    device->isRecordingState = FALSE;
+    device->updateStateBlock = device->stateBlock;
+    wined3d_stateblock_incref(device->updateStateBlock);
+
+    TRACE("Returning stateblock %p.\n", *stateblock);
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_device_begin_scene(struct wined3d_device *device)
+{
+    /* At the moment we have no need for any functionality at the beginning
+     * of a scene. */
+    TRACE("device %p.\n", device);
+
+    if (device->inScene)
+    {
+        WARN("Already in scene, returning WINED3DERR_INVALIDCALL.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+    device->inScene = TRUE;
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_device_end_scene(struct wined3d_device *device)
+{
+    struct wined3d_context *context;
+
+    TRACE("device %p.\n", device);
+
+    if (!device->inScene)
+    {
+        WARN("Not in scene, returning WINED3DERR_INVALIDCALL.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    context = context_acquire(device, NULL);
+    /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
+    context->gl_info->gl_ops.gl.p_glFlush();
+    /* No checkGLcall here to avoid locking the lock just for checking a call that hardly ever
+     * fails. */
+    context_release(context);
+
+    device->inScene = FALSE;
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_device_present(const struct wined3d_device *device, const RECT *src_rect,
+        const RECT *dst_rect, HWND dst_window_override, const RGNDATA *dirty_region, DWORD flags)
+{
+    UINT i;
+
+    TRACE("device %p, src_rect %s, dst_rect %s, dst_window_override %p, dirty_region %p, flags %#x.\n",
+            device, wine_dbgstr_rect(src_rect), wine_dbgstr_rect(dst_rect),
+            dst_window_override, dirty_region, flags);
+
+    for (i = 0; i < device->swapchain_count; ++i)
+    {
+        wined3d_swapchain_present(device->swapchains[i], src_rect,
+                dst_rect, dst_window_override, dirty_region, flags);
+    }
+
+    return WINED3D_OK;
+}
+
+/* Do not call while under the GL lock. */
+HRESULT CDECL wined3d_device_clear(struct wined3d_device *device, DWORD rect_count,
+        const RECT *rects, DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil)
+{
+    RECT draw_rect;
+
+    TRACE("device %p, rect_count %u, rects %p, flags %#x, color {%.8e, %.8e, %.8e, %.8e}, depth %.8e, stencil %u.\n",
+            device, rect_count, rects, flags, color->r, color->g, color->b, color->a, depth, stencil);
+
+    if (!rect_count && rects)
+    {
+        WARN("Rects is %p, but rect_count is 0, ignoring clear\n", rects);
+        return WINED3D_OK;
+    }
+
+    if (flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL))
+    {
+        struct wined3d_surface *ds = device->fb.depth_stencil;
+        if (!ds)
+        {
+            WARN("Clearing depth and/or stencil without a depth stencil buffer attached, returning WINED3DERR_INVALIDCALL\n");
+            /* TODO: What about depth stencil buffers without stencil bits? */
+            return WINED3DERR_INVALIDCALL;
+        }
+        else if (flags & WINED3DCLEAR_TARGET)
+        {
+            if (ds->resource.width < device->fb.render_targets[0]->resource.width
+                    || ds->resource.height < device->fb.render_targets[0]->resource.height)
+            {
+                WARN("Silently ignoring depth and target clear with mismatching sizes\n");
+                return WINED3D_OK;
+            }
+        }
+    }
+
+    wined3d_get_draw_rect(&device->stateBlock->state, &draw_rect);
+    device_clear_render_targets(device, device->adapter->gl_info.limits.buffers,
+            &device->fb, rect_count, rects, &draw_rect, flags, color, depth, stencil);
+
+    return WINED3D_OK;
+}
+
+void CDECL wined3d_device_set_primitive_type(struct wined3d_device *device,
+        enum wined3d_primitive_type primitive_type)
+{
+    GLenum gl_primitive_type, prev;
+
+    TRACE("device %p, primitive_type %s\n", device, debug_d3dprimitivetype(primitive_type));
+
+    device->updateStateBlock->changed.primitive_type = TRUE;
+    gl_primitive_type = gl_primitive_type_from_d3d(primitive_type);
+    prev = device->updateStateBlock->state.gl_primitive_type;
+    device->updateStateBlock->state.gl_primitive_type = gl_primitive_type;
+    if (!device->isRecordingState && gl_primitive_type != prev
+            && (gl_primitive_type == GL_POINTS || prev == GL_POINTS))
+        device_invalidate_state(device, STATE_POINT_SIZE_ENABLE);
+}
+
+void CDECL wined3d_device_get_primitive_type(const struct wined3d_device *device,
+        enum wined3d_primitive_type *primitive_type)
+{
+    TRACE("device %p, primitive_type %p\n", device, primitive_type);
+
+    *primitive_type = d3d_primitive_type_from_gl(device->stateBlock->state.gl_primitive_type);
+
+    TRACE("Returning %s\n", debug_d3dprimitivetype(*primitive_type));
+}
+
+HRESULT CDECL wined3d_device_draw_primitive(struct wined3d_device *device, UINT start_vertex, UINT vertex_count)
+{
+    TRACE("device %p, start_vertex %u, vertex_count %u.\n", device, start_vertex, vertex_count);
+
+    if (!device->stateBlock->state.vertex_declaration)
+    {
+        WARN("Called without a valid vertex declaration set.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    if (device->stateBlock->state.load_base_vertex_index)
+    {
+        device->stateBlock->state.load_base_vertex_index = 0;
+        device_invalidate_state(device, STATE_BASEVERTEXINDEX);
+    }
+
+    /* Account for the loading offset due to index buffers. Instead of
+     * reloading all sources correct it with the startvertex parameter. */
+    draw_primitive(device, start_vertex, vertex_count, 0, 0, FALSE);
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_device_draw_indexed_primitive(struct wined3d_device *device, UINT start_idx, UINT index_count)
+{
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+
+    TRACE("device %p, start_idx %u, index_count %u.\n", device, start_idx, index_count);
+
+    if (!device->stateBlock->state.index_buffer)
+    {
+        /* D3D9 returns D3DERR_INVALIDCALL when DrawIndexedPrimitive is called
+         * without an index buffer set. (The first time at least...)
+         * D3D8 simply dies, but I doubt it can do much harm to return
+         * D3DERR_INVALIDCALL there as well. */
+        WARN("Called without a valid index buffer set, returning WINED3DERR_INVALIDCALL.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    if (!device->stateBlock->state.vertex_declaration)
+    {
+        WARN("Called without a valid vertex declaration set.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    if (!gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX] &&
+        device->stateBlock->state.load_base_vertex_index != device->stateBlock->state.base_vertex_index)
+    {
+        device->stateBlock->state.load_base_vertex_index = device->stateBlock->state.base_vertex_index;
+        device_invalidate_state(device, STATE_BASEVERTEXINDEX);
+    }
+
+    draw_primitive(device, start_idx, index_count, 0, 0, TRUE);
+
+    return WINED3D_OK;
+}
+
+void CDECL wined3d_device_draw_indexed_primitive_instanced(struct wined3d_device *device,
+        UINT start_idx, UINT index_count, UINT start_instance, UINT instance_count)
+{
+    TRACE("device %p, start_idx %u, index_count %u.\n", device, start_idx, index_count);
+
+    draw_primitive(device, start_idx, index_count, start_instance, instance_count, TRUE);
+}
+
+/* This is a helper function for UpdateTexture, there is no UpdateVolume method in D3D. */
+static HRESULT device_update_volume(struct wined3d_device *device,
+        struct wined3d_volume *src_volume, struct wined3d_volume *dst_volume)
+{
+    struct wined3d_map_desc src;
+    struct wined3d_map_desc dst;
+    HRESULT hr;
+
+    TRACE("device %p, src_volume %p, dst_volume %p.\n",
+            device, src_volume, dst_volume);
+
+    /* TODO: Implement direct loading into the gl volume instead of using
+     * memcpy and dirtification to improve loading performance. */
+    if (FAILED(hr = wined3d_volume_map(src_volume, &src, NULL, WINED3D_MAP_READONLY)))
+        return hr;
+    if (FAILED(hr = wined3d_volume_map(dst_volume, &dst, NULL, WINED3D_MAP_DISCARD)))
+    {
+        wined3d_volume_unmap(src_volume);
+        return hr;
+    }
+
+    memcpy(dst.data, src.data, dst_volume->resource.size);
+
+    hr = wined3d_volume_unmap(dst_volume);
+    if (FAILED(hr))
+        wined3d_volume_unmap(src_volume);
+    else
+        hr = wined3d_volume_unmap(src_volume);
+
+    return hr;
+}
+
+HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device,
+        struct wined3d_texture *src_texture, struct wined3d_texture *dst_texture)
+{
+    enum wined3d_resource_type type;
+    unsigned int level_count, i;
+    HRESULT hr;
+
+    TRACE("device %p, src_texture %p, dst_texture %p.\n", device, src_texture, dst_texture);
+
+    /* Verify that the source and destination textures are non-NULL. */
+    if (!src_texture || !dst_texture)
+    {
+        WARN("Source and destination textures must be non-NULL, returning WINED3DERR_INVALIDCALL.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    if (src_texture == dst_texture)
+    {
+        WARN("Source and destination are the same object, returning WINED3DERR_INVALIDCALL.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    /* Verify that the source and destination textures are the same type. */
+    type = src_texture->resource.type;
+    if (dst_texture->resource.type != type)
+    {
+        WARN("Source and destination have different types, returning WINED3DERR_INVALIDCALL.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    /* Check that both textures have the identical numbers of levels. */
+    level_count = wined3d_texture_get_level_count(src_texture);
+    if (wined3d_texture_get_level_count(dst_texture) != level_count)
+    {
+        WARN("Source and destination have different level counts, returning WINED3DERR_INVALIDCALL.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    /* Make sure that the destination texture is loaded. */
+    dst_texture->texture_ops->texture_preload(dst_texture, SRGB_RGB);
+
+    /* Update every surface level of the texture. */
+    switch (type)
+    {
+        case WINED3D_RTYPE_TEXTURE:
+        {
+            struct wined3d_surface *src_surface;
+            struct wined3d_surface *dst_surface;
+
+            for (i = 0; i < level_count; ++i)
+            {
+                src_surface = surface_from_resource(wined3d_texture_get_sub_resource(src_texture, i));
+                dst_surface = surface_from_resource(wined3d_texture_get_sub_resource(dst_texture, i));
+                hr = wined3d_device_update_surface(device, src_surface, NULL, dst_surface, NULL);
+                if (FAILED(hr))
+                {
+                    WARN("Failed to update surface, hr %#x.\n", hr);
+                    return hr;
+                }
+            }
+            break;
+        }
+
+        case WINED3D_RTYPE_CUBE_TEXTURE:
+        {
+            struct wined3d_surface *src_surface;
+            struct wined3d_surface *dst_surface;
+
+            for (i = 0; i < level_count * 6; ++i)
+            {
+                src_surface = surface_from_resource(wined3d_texture_get_sub_resource(src_texture, i));
+                dst_surface = surface_from_resource(wined3d_texture_get_sub_resource(dst_texture, i));
+                hr = wined3d_device_update_surface(device, src_surface, NULL, dst_surface, NULL);
+                if (FAILED(hr))
+                {
+                    WARN("Failed to update surface, hr %#x.\n", hr);
+                    return hr;
+                }
+            }
+            break;
+        }
+
+        case WINED3D_RTYPE_VOLUME_TEXTURE:
+        {
+            for (i = 0; i < level_count; ++i)
+            {
+                hr = device_update_volume(device,
+                        volume_from_resource(wined3d_texture_get_sub_resource(src_texture, i)),
+                        volume_from_resource(wined3d_texture_get_sub_resource(dst_texture, i)));
+                if (FAILED(hr))
+                {
+                    WARN("Failed to update volume, hr %#x.\n", hr);
+                    return hr;
+                }
+            }
+            break;
+        }
+
+        default:
+            FIXME("Unsupported texture type %#x.\n", type);
+            return WINED3DERR_INVALIDCALL;
+    }
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_device_get_front_buffer_data(const struct wined3d_device *device,
+        UINT swapchain_idx, struct wined3d_surface *dst_surface)
+{
+    struct wined3d_swapchain *swapchain;
+
+    TRACE("device %p, swapchain_idx %u, dst_surface %p.\n", device, swapchain_idx, dst_surface);
+
+    if (!(swapchain = wined3d_device_get_swapchain(device, swapchain_idx)))
+        return WINED3DERR_INVALIDCALL;
+
+    return wined3d_swapchain_get_front_buffer_data(swapchain, dst_surface);
+}
+
+HRESULT CDECL wined3d_device_validate_device(const struct wined3d_device *device, DWORD *num_passes)
+{
+    const struct wined3d_state *state = &device->stateBlock->state;
+    struct wined3d_texture *texture;
+    DWORD i;
+
+    TRACE("device %p, num_passes %p.\n", device, num_passes);
+
+    for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
+    {
+        if (state->sampler_states[i][WINED3D_SAMP_MIN_FILTER] == WINED3D_TEXF_NONE)
+        {
+            WARN("Sampler state %u has minfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i);
+            return WINED3DERR_UNSUPPORTEDTEXTUREFILTER;
+        }
+        if (state->sampler_states[i][WINED3D_SAMP_MAG_FILTER] == WINED3D_TEXF_NONE)
+        {
+            WARN("Sampler state %u has magfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i);
+            return WINED3DERR_UNSUPPORTEDTEXTUREFILTER;
+        }
+
+        texture = state->textures[i];
+        if (!texture || texture->resource.format->flags & WINED3DFMT_FLAG_FILTERING) continue;
+
+        if (state->sampler_states[i][WINED3D_SAMP_MAG_FILTER] != WINED3D_TEXF_POINT)
+        {
+            WARN("Non-filterable texture and mag filter enabled on samper %u, returning E_FAIL\n", i);
+            return E_FAIL;
+        }
+        if (state->sampler_states[i][WINED3D_SAMP_MIN_FILTER] != WINED3D_TEXF_POINT)
+        {
+            WARN("Non-filterable texture and min filter enabled on samper %u, returning E_FAIL\n", i);
+            return E_FAIL;
+        }
+        if (state->sampler_states[i][WINED3D_SAMP_MIP_FILTER] != WINED3D_TEXF_NONE
+                && state->sampler_states[i][WINED3D_SAMP_MIP_FILTER] != WINED3D_TEXF_POINT)
+        {
+            WARN("Non-filterable texture and mip filter enabled on samper %u, returning E_FAIL\n", i);
+            return E_FAIL;
+        }
+    }
+
+    if (state->render_states[WINED3D_RS_ZENABLE] || state->render_states[WINED3D_RS_ZWRITEENABLE]
+            || state->render_states[WINED3D_RS_STENCILENABLE])
+    {
+        struct wined3d_surface *ds = device->fb.depth_stencil;
+        struct wined3d_surface *target = device->fb.render_targets[0];
+
+        if(ds && target
+                && (ds->resource.width < target->resource.width || ds->resource.height < target->resource.height))
+        {
+            WARN("Depth stencil is smaller than the color buffer, returning D3DERR_CONFLICTINGRENDERSTATE\n");
+            return WINED3DERR_CONFLICTINGRENDERSTATE;
+        }
+    }
+
+    /* return a sensible default */
+    *num_passes = 1;
+
+    TRACE("returning D3D_OK\n");
+    return WINED3D_OK;
+}
+
+void CDECL wined3d_device_set_software_vertex_processing(struct wined3d_device *device, BOOL software)
+{
+    static BOOL warned;
+
+    TRACE("device %p, software %#x.\n", device, software);
+
+    if (!warned)
+    {
+        FIXME("device %p, software %#x stub!\n", device, software);
+        warned = TRUE;
+    }
+
+    device->softwareVertexProcessing = software;
+}
+
+BOOL CDECL wined3d_device_get_software_vertex_processing(const struct wined3d_device *device)
+{
+    static BOOL warned;
+
+    TRACE("device %p.\n", device);
+
+    if (!warned)
+    {
+        TRACE("device %p stub!\n", device);
+        warned = TRUE;
+    }
+
+    return device->softwareVertexProcessing;
+}
+
+HRESULT CDECL wined3d_device_get_raster_status(const struct wined3d_device *device,
+        UINT swapchain_idx, struct wined3d_raster_status *raster_status)
+{
+    struct wined3d_swapchain *swapchain;
+
+    TRACE("device %p, swapchain_idx %u, raster_status %p.\n",
+            device, swapchain_idx, raster_status);
+
+    if (!(swapchain = wined3d_device_get_swapchain(device, swapchain_idx)))
+        return WINED3DERR_INVALIDCALL;
+
+    return wined3d_swapchain_get_raster_status(swapchain, raster_status);
+}
+
+HRESULT CDECL wined3d_device_set_npatch_mode(struct wined3d_device *device, float segments)
+{
+    static BOOL warned;
+
+    TRACE("device %p, segments %.8e.\n", device, segments);
+
+    if (segments != 0.0f)
+    {
+        if (!warned)
+        {
+            FIXME("device %p, segments %.8e stub!\n", device, segments);
+            warned = TRUE;
+        }
+    }
+
+    return WINED3D_OK;
+}
+
+float CDECL wined3d_device_get_npatch_mode(const struct wined3d_device *device)
+{
+    static BOOL warned;
+
+    TRACE("device %p.\n", device);
+
+    if (!warned)
+    {
+        FIXME("device %p stub!\n", device);
+        warned = TRUE;
+    }
+
+    return 0.0f;
+}
+
+HRESULT CDECL wined3d_device_update_surface(struct wined3d_device *device,
+        struct wined3d_surface *src_surface, const RECT *src_rect,
+        struct wined3d_surface *dst_surface, const POINT *dst_point)
+{
+    TRACE("device %p, src_surface %p, src_rect %s, dst_surface %p, dst_point %s.\n",
+            device, src_surface, wine_dbgstr_rect(src_rect),
+            dst_surface, wine_dbgstr_point(dst_point));
+
+    if (src_surface->resource.pool != WINED3D_POOL_SYSTEM_MEM || dst_surface->resource.pool != WINED3D_POOL_DEFAULT)
+    {
+        WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n",
+                src_surface, dst_surface);
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    return surface_upload_from_surface(dst_surface, dst_point, src_surface, src_rect);
+}
+
+/* Do not call while under the GL lock. */
+HRESULT CDECL wined3d_device_color_fill(struct wined3d_device *device,
+        struct wined3d_surface *surface, const RECT *rect, const struct wined3d_color *color)
+{
+    RECT r;
+
+    TRACE("device %p, surface %p, rect %s, color {%.8e, %.8e, %.8e, %.8e}.\n",
+            device, surface, wine_dbgstr_rect(rect),
+            color->r, color->g, color->b, color->a);
+
+    if (surface->resource.pool != WINED3D_POOL_DEFAULT && surface->resource.pool != WINED3D_POOL_SYSTEM_MEM)
+    {
+        WARN("Color-fill not allowed on %s surfaces.\n", debug_d3dpool(surface->resource.pool));
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    if (!rect)
+    {
+        SetRect(&r, 0, 0, surface->resource.width, surface->resource.height);
+        rect = &r;
+    }
+
+    return surface_color_fill(surface, rect, color);
+}
+
+/* Do not call while under the GL lock. */
+void CDECL wined3d_device_clear_rendertarget_view(struct wined3d_device *device,
+        struct wined3d_rendertarget_view *rendertarget_view, const struct wined3d_color *color)
+{
+    struct wined3d_resource *resource;
+    HRESULT hr;
+    RECT rect;
+
+    resource = rendertarget_view->resource;
+    if (resource->type != WINED3D_RTYPE_SURFACE)
+    {
+        FIXME("Only supported on surface resources\n");
+        return;
+    }
+
+    SetRect(&rect, 0, 0, resource->width, resource->height);
+    hr = surface_color_fill(surface_from_resource(resource), &rect, color);
+    if (FAILED(hr)) ERR("Color fill failed, hr %#x.\n", hr);
+}
+
+struct wined3d_surface * CDECL wined3d_device_get_render_target(const struct wined3d_device *device,
+        UINT render_target_idx)
+{
+    TRACE("device %p, render_target_idx %u.\n", device, render_target_idx);
+
+    if (render_target_idx >= device->adapter->gl_info.limits.buffers)
+    {
+        WARN("Only %u render targets are supported.\n", device->adapter->gl_info.limits.buffers);
+        return NULL;
+    }
+
+    return device->fb.render_targets[render_target_idx];
+}
+
+struct wined3d_surface * CDECL wined3d_device_get_depth_stencil(const struct wined3d_device *device)
+{
+    TRACE("device %p.\n", device);
+
+    return device->fb.depth_stencil;
+}
+
+HRESULT CDECL wined3d_device_set_render_target(struct wined3d_device *device,
+        UINT render_target_idx, struct wined3d_surface *render_target, BOOL set_viewport)
+{
+    struct wined3d_surface *prev;
+
+    TRACE("device %p, render_target_idx %u, render_target %p, set_viewport %#x.\n",
+            device, render_target_idx, render_target, set_viewport);
+
+    if (render_target_idx >= device->adapter->gl_info.limits.buffers)
+    {
+        WARN("Only %u render targets are supported.\n", device->adapter->gl_info.limits.buffers);
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    /* Render target 0 can't be set to NULL. */
+    if (!render_target && !render_target_idx)
+    {
+        WARN("Trying to set render target 0 to NULL.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    if (render_target && !(render_target->resource.usage & WINED3DUSAGE_RENDERTARGET))
+    {
+        FIXME("Surface %p doesn't have render target usage.\n", render_target);
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    /* Set the viewport and scissor rectangles, if requested. Tests show that
+     * stateblock recording is ignored, the change goes directly into the
+     * primary stateblock. */
+    if (!render_target_idx && set_viewport)
+    {
+        struct wined3d_state *state = &device->stateBlock->state;
+
+        state->viewport.x = 0;
+        state->viewport.y = 0;
+        state->viewport.width = render_target->resource.width;
+        state->viewport.height = render_target->resource.height;
+        state->viewport.min_z = 0.0f;
+        state->viewport.max_z = 1.0f;
+        device_invalidate_state(device, STATE_VIEWPORT);
+
+        state->scissor_rect.top = 0;
+        state->scissor_rect.left = 0;
+        state->scissor_rect.right = render_target->resource.width;
+        state->scissor_rect.bottom = render_target->resource.height;
+        device_invalidate_state(device, STATE_SCISSORRECT);
+    }
+
+
+    prev = device->fb.render_targets[render_target_idx];
+    if (render_target == prev)
+        return WINED3D_OK;
+
+    if (render_target)
+        wined3d_surface_incref(render_target);
+    device->fb.render_targets[render_target_idx] = render_target;
+    /* Release after the assignment, to prevent device_resource_released()
+     * from seeing the surface as still in use. */
+    if (prev)
+        wined3d_surface_decref(prev);
+
+    device_invalidate_state(device, STATE_FRAMEBUFFER);
+
+    return WINED3D_OK;
+}
+
+void CDECL wined3d_device_set_depth_stencil(struct wined3d_device *device, struct wined3d_surface *depth_stencil)
+{
+    struct wined3d_surface *prev = device->fb.depth_stencil;
+
+    TRACE("device %p, depth_stencil %p, old depth_stencil %p.\n",
+            device, depth_stencil, prev);
+
+    if (prev == depth_stencil)
+    {
+        TRACE("Trying to do a NOP SetRenderTarget operation.\n");
+        return;
+    }
+
+    if (prev)
+    {
+        if (device->swapchains[0]->desc.flags & WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL
+                || prev->flags & SFLAG_DISCARD)
+        {
+            surface_modify_ds_location(prev, SFLAG_DISCARDED,
+                    prev->resource.width, prev->resource.height);
+            if (prev == device->onscreen_depth_stencil)
+            {
+                wined3d_surface_decref(device->onscreen_depth_stencil);
+                device->onscreen_depth_stencil = NULL;
+            }
+        }
+    }
+
+    device->fb.depth_stencil = depth_stencil;
+    if (depth_stencil)
+        wined3d_surface_incref(depth_stencil);
+
+    if (!prev != !depth_stencil)
+    {
+        /* Swapping NULL / non NULL depth stencil affects the depth and tests */
+        device_invalidate_state(device, STATE_RENDER(WINED3D_RS_ZENABLE));
+        device_invalidate_state(device, STATE_RENDER(WINED3D_RS_STENCILENABLE));
+        device_invalidate_state(device, STATE_RENDER(WINED3D_RS_STENCILWRITEMASK));
+        device_invalidate_state(device, STATE_RENDER(WINED3D_RS_DEPTHBIAS));
+    }
+    else if (prev && prev->resource.format->depth_size != depth_stencil->resource.format->depth_size)
+    {
+        device_invalidate_state(device, STATE_RENDER(WINED3D_RS_DEPTHBIAS));
+    }
+    if (prev)
+        wined3d_surface_decref(prev);
+
+    device_invalidate_state(device, STATE_FRAMEBUFFER);
+
+    return;
+}
+
+HRESULT CDECL wined3d_device_set_cursor_properties(struct wined3d_device *device,
+        UINT x_hotspot, UINT y_hotspot, struct wined3d_surface *cursor_image)
+{
+    TRACE("device %p, x_hotspot %u, y_hotspot %u, cursor_image %p.\n",
+            device, x_hotspot, y_hotspot, cursor_image);
+
+    /* some basic validation checks */
+    if (device->cursorTexture)
+    {
+        struct wined3d_context *context = context_acquire(device, NULL);
+        context->gl_info->gl_ops.gl.p_glDeleteTextures(1, &device->cursorTexture);
+        context_release(context);
+        device->cursorTexture = 0;
+    }
+
+    if (cursor_image)
+    {
+        struct wined3d_display_mode mode;
+        struct wined3d_map_desc map_desc;
+        HRESULT hr;
+
+        /* MSDN: Cursor must be A8R8G8B8 */
+        if (cursor_image->resource.format->id != WINED3DFMT_B8G8R8A8_UNORM)
+        {
+            WARN("surface %p has an invalid format.\n", cursor_image);
+            return WINED3DERR_INVALIDCALL;
+        }
+
+        if (FAILED(hr = wined3d_get_adapter_display_mode(device->wined3d, device->adapter->ordinal, &mode, NULL)))
+        {
+            ERR("Failed to get display mode, hr %#x.\n", hr);
+            return WINED3DERR_INVALIDCALL;
+        }
+
+        /* MSDN: Cursor must be smaller than the display mode */
+        if (cursor_image->resource.width > mode.width || cursor_image->resource.height > mode.height)
+        {
+            WARN("Surface %p dimensions are %ux%u, but screen dimensions are %ux%u.\n",
+                    cursor_image, cursor_image->resource.width, cursor_image->resource.height,
+                    mode.width, mode.height);
+            return WINED3DERR_INVALIDCALL;
+        }
+
+        /* TODO: MSDN: Cursor sizes must be a power of 2 */
+
+        /* Do not store the surface's pointer because the application may
+         * release it after setting the cursor image. Windows doesn't
+         * addref the set surface, so we can't do this either without
+         * creating circular refcount dependencies. Copy out the gl texture
+         * instead. */
+        device->cursorWidth = cursor_image->resource.width;
+        device->cursorHeight = cursor_image->resource.height;
+        if (SUCCEEDED(wined3d_surface_map(cursor_image, &map_desc, NULL, WINED3D_MAP_READONLY)))
+        {
+            const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+            const struct wined3d_format *format = wined3d_get_format(gl_info, WINED3DFMT_B8G8R8A8_UNORM);
+            struct wined3d_context *context;
+            char *mem, *bits = map_desc.data;
+            GLint intfmt = format->glInternal;
+            GLint gl_format = format->glFormat;
+            GLint type = format->glType;
+            INT height = device->cursorHeight;
+            INT width = device->cursorWidth;
+            INT bpp = format->byte_count;
+            INT i;
+
+            /* Reformat the texture memory (pitch and width can be
+             * different) */
+            mem = HeapAlloc(GetProcessHeap(), 0, width * height * bpp);
+            for (i = 0; i < height; ++i)
+                memcpy(&mem[width * bpp * i], &bits[map_desc.row_pitch * i], width * bpp);
+            wined3d_surface_unmap(cursor_image);
+
+            context = context_acquire(device, NULL);
+
+            if (gl_info->supported[APPLE_CLIENT_STORAGE])
+            {
+                gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
+                checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
+            }
+
+            invalidate_active_texture(device, context);
+            /* Create a new cursor texture */
+            gl_info->gl_ops.gl.p_glGenTextures(1, &device->cursorTexture);
+            checkGLcall("glGenTextures");
+            context_bind_texture(context, GL_TEXTURE_2D, device->cursorTexture);
+            /* Copy the bitmap memory into the cursor texture */
+            gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, intfmt, width, height, 0, gl_format, type, mem);
+            checkGLcall("glTexImage2D");
+            HeapFree(GetProcessHeap(), 0, mem);
+
+            if (gl_info->supported[APPLE_CLIENT_STORAGE])
+            {
+                gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
+                checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
+            }
+
+            context_release(context);
+        }
+        else
+        {
+            FIXME("A cursor texture was not returned.\n");
+            device->cursorTexture = 0;
+        }
+
+        if (cursor_image->resource.width == 32 && cursor_image->resource.height == 32)
+        {
+            UINT mask_size = cursor_image->resource.width * cursor_image->resource.height / 8;
+            ICONINFO cursorInfo;
+            DWORD *maskBits;
+            HCURSOR cursor;
+
+            /* 32-bit user32 cursors ignore the alpha channel if it's all
+             * zeroes, and use the mask instead. Fill the mask with all ones
+             * to ensure we still get a fully transparent cursor. */
+            maskBits = HeapAlloc(GetProcessHeap(), 0, mask_size);
+            memset(maskBits, 0xff, mask_size);
+            wined3d_surface_map(cursor_image, &map_desc, NULL,
+                    WINED3D_MAP_NO_DIRTY_UPDATE | WINED3D_MAP_READONLY);
+            TRACE("width: %u height: %u.\n", cursor_image->resource.width, cursor_image->resource.height);
+
+            cursorInfo.fIcon = FALSE;
+            cursorInfo.xHotspot = x_hotspot;
+            cursorInfo.yHotspot = y_hotspot;
+            cursorInfo.hbmMask = CreateBitmap(cursor_image->resource.width, cursor_image->resource.height,
+                    1, 1, maskBits);
+            cursorInfo.hbmColor = CreateBitmap(cursor_image->resource.width, cursor_image->resource.height,
+                    1, 32, map_desc.data);
+            wined3d_surface_unmap(cursor_image);
+            /* Create our cursor and clean up. */
+            cursor = CreateIconIndirect(&cursorInfo);
+            if (cursorInfo.hbmMask) DeleteObject(cursorInfo.hbmMask);
+            if (cursorInfo.hbmColor) DeleteObject(cursorInfo.hbmColor);
+            if (device->hardwareCursor) DestroyCursor(device->hardwareCursor);
+            device->hardwareCursor = cursor;
+            if (device->bCursorVisible) SetCursor( cursor );
+            HeapFree(GetProcessHeap(), 0, maskBits);
+        }
+    }
+
+    device->xHotSpot = x_hotspot;
+    device->yHotSpot = y_hotspot;
+    return WINED3D_OK;
+}
+
+void CDECL wined3d_device_set_cursor_position(struct wined3d_device *device,
+        int x_screen_space, int y_screen_space, DWORD flags)
+{
+    TRACE("device %p, x %d, y %d, flags %#x.\n",
+            device, x_screen_space, y_screen_space, flags);
+
+    device->xScreenSpace = x_screen_space;
+    device->yScreenSpace = y_screen_space;
+
+    if (device->hardwareCursor)
+    {
+        POINT pt;
+
+        GetCursorPos( &pt );
+        if (x_screen_space == pt.x && y_screen_space == pt.y)
+            return;
+        SetCursorPos( x_screen_space, y_screen_space );
+
+        /* Switch to the software cursor if position diverges from the hardware one. */
+        GetCursorPos( &pt );
+        if (x_screen_space != pt.x || y_screen_space != pt.y)
+        {
+            if (device->bCursorVisible) SetCursor( NULL );
+            DestroyCursor( device->hardwareCursor );
+            device->hardwareCursor = 0;
+        }
+    }
+}
+
+BOOL CDECL wined3d_device_show_cursor(struct wined3d_device *device, BOOL show)
+{
+    BOOL oldVisible = device->bCursorVisible;
+
+    TRACE("device %p, show %#x.\n", device, show);
+
+    /*
+     * When ShowCursor is first called it should make the cursor appear at the OS's last
+     * known cursor position.
+     */
+    if (show && !oldVisible)
+    {
+        POINT pt;
+        GetCursorPos(&pt);
+        device->xScreenSpace = pt.x;
+        device->yScreenSpace = pt.y;
+    }
+
+    if (device->hardwareCursor)
+    {
+        device->bCursorVisible = show;
+        if (show)
+            SetCursor(device->hardwareCursor);
+        else
+            SetCursor(NULL);
+    }
+    else
+    {
+        if (device->cursorTexture)
+            device->bCursorVisible = show;
+    }
+
+    return oldVisible;
+}
+
+void CDECL wined3d_device_evict_managed_resources(struct wined3d_device *device)
+{
+    struct wined3d_resource *resource, *cursor;
+
+    TRACE("device %p.\n", device);
+
+    LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &device->resources, struct wined3d_resource, resource_list_entry)
+    {
+        TRACE("Checking resource %p for eviction.\n", resource);
+
+        if (resource->pool == WINED3D_POOL_MANAGED && !resource->map_count)
+        {
+            TRACE("Evicting %p.\n", resource);
+            resource->resource_ops->resource_unload(resource);
+        }
+    }
+
+    /* Invalidate stream sources, the buffer(s) may have been evicted. */
+    device_invalidate_state(device, STATE_STREAMSRC);
+}
+
+#ifndef VBOX_WITH_WDDM
+/* Do not call while under the GL lock. */
+static void delete_opengl_contexts(struct wined3d_device *device, struct wined3d_swapchain *swapchain)
+{
+    struct wined3d_resource *resource, *cursor;
+    const struct wined3d_gl_info *gl_info;
+    struct wined3d_context *context;
+    struct wined3d_shader *shader;
+
+    context = context_acquire(device, NULL);
+    gl_info = context->gl_info;
+
+    LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &device->resources, struct wined3d_resource, resource_list_entry)
+    {
+        TRACE("Unloading resource %p.\n", resource);
+
+        resource->resource_ops->resource_unload(resource);
+    }
+
+    LIST_FOR_EACH_ENTRY(shader, &device->shaders, struct wined3d_shader, shader_list_entry)
+    {
+        device->shader_backend->shader_destroy(shader);
+    }
+
+    if (device->depth_blt_texture)
+    {
+        gl_info->gl_ops.gl.p_glDeleteTextures(1, &device->depth_blt_texture);
+        device->depth_blt_texture = 0;
+    }
+    if (device->cursorTexture)
+    {
+        gl_info->gl_ops.gl.p_glDeleteTextures(1, &device->cursorTexture);
+        device->cursorTexture = 0;
+    }
+
+    device->blitter->free_private(device);
+    device->shader_backend->shader_free_private(device);
+    destroy_dummy_textures(device, gl_info);
+
+    context_release(context);
+
+    while (device->context_count)
+    {
+#ifndef VBOX_WINE_WITH_SINGLE_CONTEXT
+        swapchain_destroy_contexts(device->contexts[0]->swapchain);
+#else
+        context_destroy(device, device->contexts[0]);
+#endif
+    }
+
+#ifndef VBOX_WINE_WITH_SINGLE_CONTEXT
+    HeapFree(GetProcessHeap(), 0, swapchain->context);
+    swapchain->context = NULL;
+#else
+#endif
+}
+
+/* Do not call while under the GL lock. */
+static HRESULT create_primary_opengl_context(struct wined3d_device *device, struct wined3d_swapchain *swapchain)
+{
+    struct wined3d_context *context;
+    struct wined3d_surface *target;
+    HRESULT hr;
+
+    if (FAILED(hr = device->shader_backend->shader_alloc_private(device,
+            device->adapter->vertex_pipe, device->adapter->fragment_pipe)))
+    {
+        ERR("Failed to allocate shader private data, hr %#x.\n", hr);
+        return hr;
+    }
+
+    if (FAILED(hr = device->blitter->alloc_private(device)))
+    {
+        ERR("Failed to allocate blitter private data, hr %#x.\n", hr);
+        device->shader_backend->shader_free_private(device);
+        return hr;
+    }
+
+    /* Recreate the primary swapchain's context */
+#ifndef VBOX_WINE_WITH_SINGLE_CONTEXT
+    swapchain->context = HeapAlloc(GetProcessHeap(), 0, sizeof(*swapchain->context));
+    if (!swapchain->context)
+#else
+    device->contexts = HeapAlloc(GetProcessHeap(), 0, sizeof(*device->contexts));
+    if (!device->contexts)
+#endif
+    {
+        ERR("Failed to allocate memory for swapchain context array.\n");
+        device->blitter->free_private(device);
+        device->shader_backend->shader_free_private(device);
+        return E_OUTOFMEMORY;
+    }
+
+    target = swapchain->back_buffers ? swapchain->back_buffers[0] : swapchain->front_buffer;
+    if (!(context = context_create(swapchain, target, swapchain->ds_format)))
+    {
+        WARN("Failed to create context.\n");
+        device->blitter->free_private(device);
+        device->shader_backend->shader_free_private(device);
+#ifndef VBOX_WINE_WITH_SINGLE_CONTEXT
+        HeapFree(GetProcessHeap(), 0, swapchain->context);
+#else
+        HeapFree(GetProcessHeap(), 0, device->contexts);
+#endif
+        return E_FAIL;
+    }
+
+#ifndef VBOX_WINE_WITH_SINGLE_CONTEXT
+    swapchain->context[0] = context;
+    swapchain->num_contexts = 1;
+#endif
+    create_dummy_textures(device, context);
+    context_release(context);
+
+    return WINED3D_OK;
+}
+#endif
+/* Do not call while under the GL lock. */
+HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
+        const struct wined3d_swapchain_desc *swapchain_desc, const struct wined3d_display_mode *mode,
+        wined3d_device_reset_cb callback, BOOL reset_state)
+{
+#ifndef VBOX_WITH_WDDM
+    struct wined3d_resource *resource, *cursor;
+    struct wined3d_swapchain *swapchain;
+    struct wined3d_display_mode m;
+    BOOL DisplayModeChanged = FALSE;
+    BOOL update_desc = FALSE;
+    UINT backbuffer_width = swapchain_desc->backbuffer_width;
+    UINT backbuffer_height = swapchain_desc->backbuffer_height;
+    HRESULT hr = WINED3D_OK;
+    unsigned int i;
+
+    TRACE("device %p, swapchain_desc %p, mode %p, callback %p.\n", device, swapchain_desc, mode, callback);
+
+    if (!(swapchain = wined3d_device_get_swapchain(device, 0)))
+    {
+        ERR("Failed to get the first implicit swapchain.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    if (reset_state)
+        stateblock_unbind_resources(device->stateBlock);
+
+    if (device->fb.render_targets)
+    {
+        if (swapchain->back_buffers && swapchain->back_buffers[0])
+            wined3d_device_set_render_target(device, 0, swapchain->back_buffers[0], FALSE);
+        else
+            wined3d_device_set_render_target(device, 0, swapchain->front_buffer, FALSE);
+        for (i = 1; i < device->adapter->gl_info.limits.buffers; ++i)
+        {
+            wined3d_device_set_render_target(device, i, NULL, FALSE);
+        }
+    }
+    wined3d_device_set_depth_stencil(device, NULL);
+
+    if (device->onscreen_depth_stencil)
+    {
+        wined3d_surface_decref(device->onscreen_depth_stencil);
+        device->onscreen_depth_stencil = NULL;
+    }
+
+    if (reset_state)
+    {
+        LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &device->resources, struct wined3d_resource, resource_list_entry)
+        {
+            TRACE("Enumerating resource %p.\n", resource);
+            if (FAILED(hr = callback(resource)))
+                return hr;
+        }
+    }
+
+    /* Is it necessary to recreate the gl context? Actually every setting can be changed
+     * on an existing gl context, so there's no real need for recreation.
+     *
+     * TODO: Figure out how Reset influences resources in D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
+     *
+     * TODO: Figure out what happens to explicit swapchains, or if we have more than one implicit swapchain
+     */
+    TRACE("New params:\n");
+    TRACE("backbuffer_width %u\n", swapchain_desc->backbuffer_width);
+    TRACE("backbuffer_height %u\n", swapchain_desc->backbuffer_height);
+    TRACE("backbuffer_format %s\n", debug_d3dformat(swapchain_desc->backbuffer_format));
+    TRACE("backbuffer_count %u\n", swapchain_desc->backbuffer_count);
+    TRACE("multisample_type %#x\n", swapchain_desc->multisample_type);
+    TRACE("multisample_quality %u\n", swapchain_desc->multisample_quality);
+    TRACE("swap_effect %#x\n", swapchain_desc->swap_effect);
+    TRACE("device_window %p\n", swapchain_desc->device_window);
+    TRACE("windowed %#x\n", swapchain_desc->windowed);
+    TRACE("enable_auto_depth_stencil %#x\n", swapchain_desc->enable_auto_depth_stencil);
+    if (swapchain_desc->enable_auto_depth_stencil)
+        TRACE("auto_depth_stencil_format %s\n", debug_d3dformat(swapchain_desc->auto_depth_stencil_format));
+    TRACE("flags %#x\n", swapchain_desc->flags);
+    TRACE("refresh_rate %u\n", swapchain_desc->refresh_rate);
+    TRACE("swap_interval %u\n", swapchain_desc->swap_interval);
+    TRACE("auto_restore_display_mode %#x\n", swapchain_desc->auto_restore_display_mode);
+
+    /* No special treatment of these parameters. Just store them */
+    swapchain->desc.swap_effect = swapchain_desc->swap_effect;
+    swapchain->desc.flags = swapchain_desc->flags;
+    swapchain->desc.swap_interval = swapchain_desc->swap_interval;
+    swapchain->desc.refresh_rate = swapchain_desc->refresh_rate;
+
+    /* What to do about these? */
+    if (swapchain_desc->backbuffer_count
+            && swapchain_desc->backbuffer_count != swapchain->desc.backbuffer_count)
+        FIXME("Cannot change the back buffer count yet.\n");
+
+    if (swapchain_desc->device_window
+            && swapchain_desc->device_window != swapchain->desc.device_window)
+    {
+        TRACE("Changing the device window from %p to %p.\n",
+                swapchain->desc.device_window, swapchain_desc->device_window);
+        swapchain->desc.device_window = swapchain_desc->device_window;
+        swapchain->device_window = swapchain_desc->device_window;
+        wined3d_swapchain_set_window(swapchain, NULL);
+    }
+
+    if (swapchain_desc->enable_auto_depth_stencil && !device->auto_depth_stencil)
+    {
+        struct wined3d_resource_desc surface_desc;
+
+        TRACE("Creating the depth stencil buffer\n");
+
+        surface_desc.resource_type = WINED3D_RTYPE_SURFACE;
+        surface_desc.format = swapchain_desc->auto_depth_stencil_format;
+        surface_desc.multisample_type = swapchain_desc->multisample_type;
+        surface_desc.multisample_quality = swapchain_desc->multisample_quality;
+        surface_desc.usage = WINED3DUSAGE_DEPTHSTENCIL;
+        surface_desc.pool = WINED3D_POOL_DEFAULT;
+        surface_desc.width = swapchain_desc->backbuffer_width;
+        surface_desc.height = swapchain_desc->backbuffer_height;
+        surface_desc.depth = 1;
+        surface_desc.size = 0;
+
+        if (FAILED(hr = device->device_parent->ops->create_swapchain_surface(device->device_parent,
+                device->device_parent, &surface_desc, &device->auto_depth_stencil)))
+        {
+            ERR("Failed to create the depth stencil buffer, hr %#x.\n", hr);
+            return WINED3DERR_INVALIDCALL;
+        }
+    }
+
+    /* Reset the depth stencil */
+    if (swapchain_desc->enable_auto_depth_stencil)
+        wined3d_device_set_depth_stencil(device, device->auto_depth_stencil);
+
+    if (mode)
+    {
+        DisplayModeChanged = TRUE;
+        m = *mode;
+    }
+    else if (swapchain_desc->windowed)
+    {
+        m.width = swapchain->orig_width;
+        m.height = swapchain->orig_height;
+        m.refresh_rate = 0;
+        m.format_id = swapchain->desc.backbuffer_format;
+        m.scanline_ordering = WINED3D_SCANLINE_ORDERING_UNKNOWN;
+    }
+    else
+    {
+        m.width = swapchain_desc->backbuffer_width;
+        m.height = swapchain_desc->backbuffer_height;
+        m.refresh_rate = swapchain_desc->refresh_rate;
+        m.format_id = swapchain_desc->backbuffer_format;
+        m.scanline_ordering = WINED3D_SCANLINE_ORDERING_UNKNOWN;
+    }
+
+    if (!backbuffer_width || !backbuffer_height)
+    {
+        /* The application is requesting that either the swapchain width or
+         * height be set to the corresponding dimension in the window's
+         * client rect. */
+
+        RECT client_rect;
+
+        if (!swapchain_desc->windowed)
+            return WINED3DERR_INVALIDCALL;
+
+        if (!GetClientRect(swapchain->device_window, &client_rect))
+        {
+            ERR("Failed to get client rect, last error %#x.\n", GetLastError());
+            return WINED3DERR_INVALIDCALL;
+        }
+
+        if (!backbuffer_width)
+            backbuffer_width = client_rect.right;
+
+        if (!backbuffer_height)
+            backbuffer_height = client_rect.bottom;
+    }
+
+    if (backbuffer_width != swapchain->desc.backbuffer_width
+            || backbuffer_height != swapchain->desc.backbuffer_height)
+    {
+        if (!swapchain_desc->windowed)
+            DisplayModeChanged = TRUE;
+
+        swapchain->desc.backbuffer_width = backbuffer_width;
+        swapchain->desc.backbuffer_height = backbuffer_height;
+        update_desc = TRUE;
+    }
+
+    if (swapchain_desc->backbuffer_format != WINED3DFMT_UNKNOWN
+            && swapchain_desc->backbuffer_format != swapchain->desc.backbuffer_format)
+    {
+        swapchain->desc.backbuffer_format = swapchain_desc->backbuffer_format;
+        update_desc = TRUE;
+    }
+
+    if (swapchain_desc->multisample_type != swapchain->desc.multisample_type
+            || swapchain_desc->multisample_quality != swapchain->desc.multisample_quality)
+    {
+        swapchain->desc.multisample_type = swapchain_desc->multisample_type;
+        swapchain->desc.multisample_quality = swapchain_desc->multisample_quality;
+        update_desc = TRUE;
+    }
+
+    if (update_desc)
+    {
+        UINT i;
+
+        if (FAILED(hr = wined3d_surface_update_desc(swapchain->front_buffer, swapchain->desc.backbuffer_width,
+                swapchain->desc.backbuffer_height, swapchain->desc.backbuffer_format,
+                swapchain->desc.multisample_type, swapchain->desc.multisample_quality)))
+            return hr;
+
+        for (i = 0; i < swapchain->desc.backbuffer_count; ++i)
+        {
+            if (FAILED(hr = wined3d_surface_update_desc(swapchain->back_buffers[i], swapchain->desc.backbuffer_width,
+                    swapchain->desc.backbuffer_height, swapchain->desc.backbuffer_format,
+                    swapchain->desc.multisample_type, swapchain->desc.multisample_quality)))
+                return hr;
+        }
+        if (device->auto_depth_stencil)
+        {
+            if (FAILED(hr = wined3d_surface_update_desc(device->auto_depth_stencil, swapchain->desc.backbuffer_width,
+                    swapchain->desc.backbuffer_height, device->auto_depth_stencil->resource.format->id,
+                    swapchain->desc.multisample_type, swapchain->desc.multisample_quality)))
+                return hr;
+        }
+    }
+
+    if (!swapchain_desc->windowed != !swapchain->desc.windowed
+            || DisplayModeChanged)
+    {
+        if (FAILED(hr = wined3d_set_adapter_display_mode(device->wined3d, device->adapter->ordinal, &m)))
+        {
+            WARN("Failed to set display mode, hr %#x.\n", hr);
+            return WINED3DERR_INVALIDCALL;
+        }
+
+        if (!swapchain_desc->windowed)
+        {
+            if (swapchain->desc.windowed)
+            {
+                HWND focus_window = device->create_parms.focus_window;
+                if (!focus_window)
+                    focus_window = swapchain_desc->device_window;
+                if (FAILED(hr = wined3d_device_acquire_focus_window(device, focus_window)))
+                {
+                    ERR("Failed to acquire focus window, hr %#x.\n", hr);
+                    return hr;
+                }
+
+                /* switch from windowed to fs */
+                wined3d_device_setup_fullscreen_window(device, swapchain->device_window,
+                        swapchain_desc->backbuffer_width,
+                        swapchain_desc->backbuffer_height);
+            }
+            else
+            {
+                /* Fullscreen -> fullscreen mode change */
+                MoveWindow(swapchain->device_window, 0, 0,
+                        swapchain_desc->backbuffer_width,
+                        swapchain_desc->backbuffer_height,
+                        TRUE);
+            }
+        }
+        else if (!swapchain->desc.windowed)
+        {
+            /* Fullscreen -> windowed switch */
+            wined3d_device_restore_fullscreen_window(device, swapchain->device_window);
+            wined3d_device_release_focus_window(device);
+        }
+        swapchain->desc.windowed = swapchain_desc->windowed;
+    }
+    else if (!swapchain_desc->windowed)
+    {
+        DWORD style = device->style;
+        DWORD exStyle = device->exStyle;
+        /* If we're in fullscreen, and the mode wasn't changed, we have to get the window back into
+         * the right position. Some applications(Battlefield 2, Guild Wars) move it and then call
+         * Reset to clear up their mess. Guild Wars also loses the device during that.
+         */
+        device->style = 0;
+        device->exStyle = 0;
+        wined3d_device_setup_fullscreen_window(device, swapchain->device_window,
+                swapchain_desc->backbuffer_width,
+                swapchain_desc->backbuffer_height);
+        device->style = style;
+        device->exStyle = exStyle;
+    }
+
+    if (reset_state)
+    {
+        TRACE("Resetting stateblock.\n");
+        wined3d_stateblock_decref(device->updateStateBlock);
+        wined3d_stateblock_decref(device->stateBlock);
+
+        if (device->d3d_initialized)
+            delete_opengl_contexts(device, swapchain);
+
+        /* Note: No parent needed for initial internal stateblock */
+        hr = wined3d_stateblock_create(device, WINED3D_SBT_INIT, &device->stateBlock);
+        if (FAILED(hr))
+            ERR("Resetting the stateblock failed with error %#x.\n", hr);
+        else
+            TRACE("Created stateblock %p.\n", device->stateBlock);
+        device->updateStateBlock = device->stateBlock;
+        wined3d_stateblock_incref(device->updateStateBlock);
+
+        stateblock_init_default_state(device->stateBlock);
+    }
+    else
+    {
+        struct wined3d_surface *rt = device->fb.render_targets[0];
+        struct wined3d_state *state = &device->stateBlock->state;
+
+        /* Note the min_z / max_z is not reset. */
+        state->viewport.x = 0;
+        state->viewport.y = 0;
+        state->viewport.width = rt->resource.width;
+        state->viewport.height = rt->resource.height;
+        device_invalidate_state(device, STATE_VIEWPORT);
+
+        state->scissor_rect.top = 0;
+        state->scissor_rect.left = 0;
+        state->scissor_rect.right = rt->resource.width;
+        state->scissor_rect.bottom = rt->resource.height;
+        device_invalidate_state(device, STATE_SCISSORRECT);
+    }
+
+    swapchain_update_render_to_fbo(swapchain);
+    swapchain_update_draw_bindings(swapchain);
+
+    if (reset_state && device->d3d_initialized)
+        hr = create_primary_opengl_context(device, swapchain);
+
+    /* All done. There is no need to reload resources or shaders, this will happen automatically on the
+     * first use
+     */
+    return hr;
+#else
+    ERR("not supported!");
+    return E_FAIL;
+#endif
+}
+
+HRESULT CDECL wined3d_device_set_dialog_box_mode(struct wined3d_device *device, BOOL enable_dialogs)
+{
+    TRACE("device %p, enable_dialogs %#x.\n", device, enable_dialogs);
+
+    if (!enable_dialogs) FIXME("Dialogs cannot be disabled yet.\n");
+
+    return WINED3D_OK;
+}
+
+
+void CDECL wined3d_device_get_creation_parameters(const struct wined3d_device *device,
+        struct wined3d_device_creation_parameters *parameters)
+{
+    TRACE("device %p, parameters %p.\n", device, parameters);
+
+    *parameters = device->create_parms;
+}
+
+void CDECL wined3d_device_set_gamma_ramp(const struct wined3d_device *device,
+        UINT swapchain_idx, DWORD flags, const struct wined3d_gamma_ramp *ramp)
+{
+    struct wined3d_swapchain *swapchain;
+
+    TRACE("device %p, swapchain_idx %u, flags %#x, ramp %p.\n",
+            device, swapchain_idx, flags, ramp);
+
+    if ((swapchain = wined3d_device_get_swapchain(device, swapchain_idx)))
+        wined3d_swapchain_set_gamma_ramp(swapchain, flags, ramp);
+}
+
+void CDECL wined3d_device_get_gamma_ramp(const struct wined3d_device *device,
+        UINT swapchain_idx, struct wined3d_gamma_ramp *ramp)
+{
+    struct wined3d_swapchain *swapchain;
+
+    TRACE("device %p, swapchain_idx %u, ramp %p.\n",
+            device, swapchain_idx, ramp);
+
+    if ((swapchain = wined3d_device_get_swapchain(device, swapchain_idx)))
+        wined3d_swapchain_get_gamma_ramp(swapchain, ramp);
+}
+
+void device_resource_add(struct wined3d_device *device, struct wined3d_resource *resource)
+{
+    TRACE("device %p, resource %p.\n", device, resource);
+
+    list_add_head(&device->resources, &resource->resource_list_entry);
+}
+
+static void device_resource_remove(struct wined3d_device *device, struct wined3d_resource *resource)
+{
+    TRACE("device %p, resource %p.\n", device, resource);
+
+    list_remove(&resource->resource_list_entry);
+}
+
+void device_resource_released(struct wined3d_device *device, struct wined3d_resource *resource)
+{
+    enum wined3d_resource_type type = resource->type;
+    unsigned int i;
+
+    TRACE("device %p, resource %p, type %s.\n", device, resource, debug_d3dresourcetype(type));
+
+    context_resource_released(device, resource, type);
+
+    switch (type)
+    {
+        case WINED3D_RTYPE_SURFACE:
+            {
+                struct wined3d_surface *surface = surface_from_resource(resource);
+
+                if (!device->d3d_initialized) break;
+
+                for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i)
+                {
+                    if (device->fb.render_targets[i] == surface)
+                    {
+                        ERR("Surface %p is still in use as render target %u.\n", surface, i);
+                        device->fb.render_targets[i] = NULL;
+                    }
+                }
+
+                if (device->fb.depth_stencil == surface)
+                {
+                    ERR("Surface %p is still in use as depth/stencil buffer.\n", surface);
+                    device->fb.depth_stencil = NULL;
+                }
+            }
+            break;
+
+        case WINED3D_RTYPE_TEXTURE:
+        case WINED3D_RTYPE_CUBE_TEXTURE:
+        case WINED3D_RTYPE_VOLUME_TEXTURE:
+            for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
+            {
+                struct wined3d_texture *texture = wined3d_texture_from_resource(resource);
+
+                if (device->stateBlock && device->stateBlock->state.textures[i] == texture)
+                {
+                    ERR("Texture %p is still in use by stateblock %p, stage %u.\n",
+                            texture, device->stateBlock, i);
+                    device->stateBlock->state.textures[i] = NULL;
+                }
+
+                if (device->updateStateBlock != device->stateBlock
+                        && device->updateStateBlock->state.textures[i] == texture)
+                {
+                    ERR("Texture %p is still in use by stateblock %p, stage %u.\n",
+                            texture, device->updateStateBlock, i);
+                    device->updateStateBlock->state.textures[i] = NULL;
+                }
+            }
+            break;
+
+        case WINED3D_RTYPE_BUFFER:
+            {
+                struct wined3d_buffer *buffer = buffer_from_resource(resource);
+
+                for (i = 0; i < MAX_STREAMS; ++i)
+                {
+                    if (device->stateBlock && device->stateBlock->state.streams[i].buffer == buffer)
+                    {
+                        ERR("Buffer %p is still in use by stateblock %p, stream %u.\n",
+                                buffer, device->stateBlock, i);
+                        device->stateBlock->state.streams[i].buffer = NULL;
+                    }
+
+                    if (device->updateStateBlock != device->stateBlock
+                            && device->updateStateBlock->state.streams[i].buffer == buffer)
+                    {
+                        ERR("Buffer %p is still in use by stateblock %p, stream %u.\n",
+                                buffer, device->updateStateBlock, i);
+                        device->updateStateBlock->state.streams[i].buffer = NULL;
+                    }
+
+                }
+
+                if (device->stateBlock && device->stateBlock->state.index_buffer == buffer)
+                {
+                    ERR("Buffer %p is still in use by stateblock %p as index buffer.\n",
+                            buffer, device->stateBlock);
+                    device->stateBlock->state.index_buffer =  NULL;
+                }
+
+                if (device->updateStateBlock != device->stateBlock
+                        && device->updateStateBlock->state.index_buffer == buffer)
+                {
+                    ERR("Buffer %p is still in use by stateblock %p as index buffer.\n",
+                            buffer, device->updateStateBlock);
+                    device->updateStateBlock->state.index_buffer =  NULL;
+                }
+            }
+            break;
+
+        default:
+            break;
+    }
+
+    /* Remove the resource from the resourceStore */
+    device_resource_remove(device, resource);
+
+    TRACE("Resource released.\n");
+}
+
+struct wined3d_surface * CDECL wined3d_device_get_surface_from_dc(const struct wined3d_device *device, HDC dc)
+{
+    struct wined3d_resource *resource;
+
+    TRACE("device %p, dc %p.\n", device, dc);
+
+    if (!dc)
+        return NULL;
+
+    LIST_FOR_EACH_ENTRY(resource, &device->resources, struct wined3d_resource, resource_list_entry)
+    {
+        if (resource->type == WINED3D_RTYPE_SURFACE)
+        {
+            struct wined3d_surface *s = surface_from_resource(resource);
+
+            if (s->hDC == dc)
+            {
+                TRACE("Found surface %p for dc %p.\n", s, dc);
+                return s;
+            }
+        }
+    }
+
+    return NULL;
+}
+
+HRESULT device_init(struct wined3d_device *device, struct wined3d *wined3d,
+        UINT adapter_idx, enum wined3d_device_type device_type, HWND focus_window, DWORD flags,
+        BYTE surface_alignment, struct wined3d_device_parent *device_parent)
+{
+    struct wined3d_adapter *adapter = &wined3d->adapters[adapter_idx];
+    const struct fragment_pipeline *fragment_pipeline;
+    const struct wined3d_vertex_pipe_ops *vertex_pipeline;
+    unsigned int i;
+    HRESULT hr;
+
+    device->ref = 1;
+    device->wined3d = wined3d;
+    wined3d_incref(device->wined3d);
+    device->adapter = wined3d->adapter_count ? adapter : NULL;
+    device->device_parent = device_parent;
+    list_init(&device->resources);
+    list_init(&device->shaders);
+    device->surface_alignment = surface_alignment;
+
+    /* Save the creation parameters. */
+    device->create_parms.adapter_idx = adapter_idx;
+    device->create_parms.device_type = device_type;
+    device->create_parms.focus_window = focus_window;
+    device->create_parms.flags = flags;
+
+#ifdef VBOX_WINE_WITH_PROFILE
+    VBOXWINEPROFILE_DRAWPRIM_INIT(&device->DrawPrimProfile);
+#endif
+
+    device->shader_backend = adapter->shader_backend;
+
+    vertex_pipeline = adapter->vertex_pipe;
+
+    fragment_pipeline = adapter->fragment_pipe;
+
+    if (vertex_pipeline->vp_states && fragment_pipeline->states
+            && FAILED(hr = compile_state_table(device->StateTable, device->multistate_funcs,
+            &adapter->gl_info, &adapter->d3d_info, vertex_pipeline,
+            fragment_pipeline, misc_state_template)))
+    {
+        ERR("Failed to compile state table, hr %#x.\n", hr);
+        wined3d_decref(device->wined3d);
+        return hr;
+    }
+
+    device->blitter = adapter->blitter;
+
+    hr = wined3d_stateblock_create(device, WINED3D_SBT_INIT, &device->stateBlock);
+    if (FAILED(hr))
+    {
+        WARN("Failed to create stateblock.\n");
+        for (i = 0; i < sizeof(device->multistate_funcs) / sizeof(device->multistate_funcs[0]); ++i)
+        {
+            HeapFree(GetProcessHeap(), 0, device->multistate_funcs[i]);
+        }
+        wined3d_decref(device->wined3d);
+        return hr;
+    }
+
+    TRACE("Created stateblock %p.\n", device->stateBlock);
+    device->updateStateBlock = device->stateBlock;
+    wined3d_stateblock_incref(device->updateStateBlock);
+
+#ifdef VBOX_WINE_WITH_SHADER_CACHE
+    shader_chaches_init(device);
+#endif
+
+    return WINED3D_OK;
+}
+
+
+void device_invalidate_state(const struct wined3d_device *device, DWORD state)
+{
+    DWORD rep = device->StateTable[state].representative;
+    struct wined3d_context *context;
+    DWORD idx;
+    BYTE shift;
+    UINT i;
+
+    for (i = 0; i < device->context_count; ++i)
+    {
+        context = device->contexts[i];
+        if(isStateDirty(context, rep)) continue;
+
+        context->dirtyArray[context->numDirtyEntries++] = rep;
+        idx = rep / (sizeof(*context->isStateDirty) * CHAR_BIT);
+        shift = rep & ((sizeof(*context->isStateDirty) * CHAR_BIT) - 1);
+        context->isStateDirty[idx] |= (1 << shift);
+    }
+}
+
+void get_drawable_size_fbo(const struct wined3d_context *context, UINT *width, UINT *height)
+{
+    /* The drawable size of a fbo target is the opengl texture size, which is the power of two size. */
+    *width = context->current_rt->pow2Width;
+    *height = context->current_rt->pow2Height;
+}
+
+void get_drawable_size_backbuffer(const struct wined3d_context *context, UINT *width, UINT *height)
+{
+    const struct wined3d_swapchain *swapchain = context->swapchain;
+    /* The drawable size of a backbuffer / aux buffer offscreen target is the size of the
+     * current context's drawable, which is the size of the back buffer of the swapchain
+     * the active context belongs to. */
+    *width = swapchain->desc.backbuffer_width;
+    *height = swapchain->desc.backbuffer_height;
+}
+
+#ifndef VBOX_WITH_WDDM
+LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL unicode,
+        UINT message, WPARAM wparam, LPARAM lparam, WNDPROC proc)
+{
+    if (device->filter_messages)
+    {
+        TRACE("Filtering message: window %p, message %#x, wparam %#lx, lparam %#lx.\n",
+                window, message, wparam, lparam);
+        if (unicode)
+            return DefWindowProcW(window, message, wparam, lparam);
+        else
+            return DefWindowProcA(window, message, wparam, lparam);
+    }
+
+    if (message == WM_DESTROY)
+    {
+        TRACE("unregister window %p.\n", window);
+        wined3d_unregister_window(window);
+
+        if (InterlockedCompareExchangePointer((void **)&device->focus_window, NULL, window) != window)
+            ERR("Window %p is not the focus window for device %p.\n", window, device);
+    }
+    else if (message == WM_DISPLAYCHANGE)
+    {
+        device->device_parent->ops->mode_changed(device->device_parent);
+    }
+
+    if (unicode)
+        return CallWindowProcW(proc, window, message, wparam, lparam);
+    else
+        return CallWindowProcA(proc, window, message, wparam, lparam);
+}
+
+#else
+HRESULT CDECL wined3d_device_flush(struct wined3d_device *device)
+{
+    /* we use only one context, so just acquiring it here should do the job,
+     * @todo: perhaps we should introduce the mechanism similar to the one used in flush_to_host
+     * to avoid context acquisition */
+    struct wined3d_context *context = context_acquire(device, NULL);
+    Assert(context->valid);
+    context->gl_info->gl_ops.gl.p_glFlush();
+    context_release(context);
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_device_flush_to_host(struct wined3d_device *device)
+{
+    struct wined3d_context *context;
+    int i;
+
+    /* no context acquisition is needed */
+    for (i = 0; i < device->context_count; ++i)
+    {
+        context = device->contexts[i];
+        pVBoxFlushToHost(context->glCtx);
+    }
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_device_finish(struct wined3d_device *device)
+{
+    /* we use only one context, so just acquiring it here should do the job,
+     * @todo: perhaps we should introduce the mechanism similar to the one used in flush_to_host
+     * to avoid context acquisition */
+    struct wined3d_context *context = context_acquire(device, NULL);
+    Assert(context->valid);
+    context->gl_info->gl_ops.gl.p_glFinish();
+    context_release(context);
+    return WINED3D_OK;
+
+}
+#endif
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/directx.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/directx.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/directx.c	(revision 46521)
@@ -0,0 +1,5352 @@
+/*
+ * Copyright 2002-2004 Jason Edmeades
+ * Copyright 2003-2004 Raphael Junqueira
+ * Copyright 2004 Christian Costa
+ * Copyright 2005 Oliver Stieber
+ * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
+ * Copyright 2009-2011 Henri Verbeet for CodeWeavers
+ *
+ * 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 <stdio.h>
+
+#include "wined3d_private.h"
+#include "winternl.h"
+#ifdef VBOX_WITH_WDDM
+#include <VBox/VBoxCrHgsmi.h>
+#endif
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d);
+WINE_DECLARE_DEBUG_CHANNEL(d3d_perf);
+
+#define WINE_DEFAULT_VIDMEM (64 * 1024 * 1024)
+
+/* The driver names reflect the lowest GPU supported
+ * by a certain driver, so DRIVER_AMD_R300 supports
+ * R3xx, R4xx and R5xx GPUs. */
+enum wined3d_display_driver
+{
+    DRIVER_AMD_RAGE_128PRO,
+    DRIVER_AMD_R100,
+    DRIVER_AMD_R300,
+    DRIVER_AMD_R600,
+    DRIVER_INTEL_GMA800,
+    DRIVER_INTEL_GMA900,
+    DRIVER_INTEL_GMA950,
+    DRIVER_INTEL_GMA3000,
+    DRIVER_NVIDIA_TNT,
+    DRIVER_NVIDIA_GEFORCE2MX,
+    DRIVER_NVIDIA_GEFORCEFX,
+    DRIVER_NVIDIA_GEFORCE6,
+    DRIVER_UNKNOWN
+};
+
+enum wined3d_driver_model
+{
+    DRIVER_MODEL_WIN9X,
+    DRIVER_MODEL_NT40,
+    DRIVER_MODEL_NT5X,
+    DRIVER_MODEL_NT6X
+};
+
+enum wined3d_gl_vendor
+{
+    GL_VENDOR_UNKNOWN,
+    GL_VENDOR_APPLE,
+    GL_VENDOR_FGLRX,
+    GL_VENDOR_INTEL,
+    GL_VENDOR_MESA,
+    GL_VENDOR_NVIDIA,
+};
+
+/* The d3d device ID */
+static const GUID IID_D3DDEVICE_D3DUID = { 0xaeb2cdd4, 0x6e41, 0x43ea, { 0x94,0x1c,0x83,0x61,0xcc,0x76,0x07,0x81 } };
+
+/* Extension detection */
+struct wined3d_extension_map
+{
+    const char *extension_string;
+    enum wined3d_gl_extension extension;
+};
+
+static const struct wined3d_extension_map gl_extension_map[] =
+{
+    /* APPLE */
+    {"GL_APPLE_client_storage",             APPLE_CLIENT_STORAGE          },
+    {"GL_APPLE_fence",                      APPLE_FENCE                   },
+    {"GL_APPLE_float_pixels",               APPLE_FLOAT_PIXELS            },
+    {"GL_APPLE_flush_buffer_range",         APPLE_FLUSH_BUFFER_RANGE      },
+    {"GL_APPLE_ycbcr_422",                  APPLE_YCBCR_422               },
+
+    /* ARB */
+    {"GL_ARB_color_buffer_float",           ARB_COLOR_BUFFER_FLOAT        },
+    {"GL_ARB_debug_output",                 ARB_DEBUG_OUTPUT              },
+    {"GL_ARB_depth_buffer_float",           ARB_DEPTH_BUFFER_FLOAT        },
+    {"GL_ARB_depth_clamp",                  ARB_DEPTH_CLAMP               },
+    {"GL_ARB_depth_texture",                ARB_DEPTH_TEXTURE             },
+    {"GL_ARB_draw_buffers",                 ARB_DRAW_BUFFERS              },
+    {"GL_ARB_draw_elements_base_vertex",    ARB_DRAW_ELEMENTS_BASE_VERTEX },
+    {"GL_ARB_draw_instanced",               ARB_DRAW_INSTANCED            },
+    {"GL_ARB_fragment_program",             ARB_FRAGMENT_PROGRAM          },
+    {"GL_ARB_fragment_shader",              ARB_FRAGMENT_SHADER           },
+    {"GL_ARB_framebuffer_object",           ARB_FRAMEBUFFER_OBJECT        },
+    {"GL_ARB_framebuffer_sRGB",             ARB_FRAMEBUFFER_SRGB          },
+    {"GL_ARB_geometry_shader4",             ARB_GEOMETRY_SHADER4          },
+    {"GL_ARB_half_float_pixel",             ARB_HALF_FLOAT_PIXEL          },
+    {"GL_ARB_half_float_vertex",            ARB_HALF_FLOAT_VERTEX         },
+    {"GL_ARB_instanced_arrays",             ARB_INSTANCED_ARRAYS,         },
+    {"GL_ARB_internalformat_query2",        ARB_INTERNALFORMAT_QUERY2,    },
+    {"GL_ARB_map_buffer_alignment",         ARB_MAP_BUFFER_ALIGNMENT      },
+    {"GL_ARB_map_buffer_range",             ARB_MAP_BUFFER_RANGE          },
+    {"GL_ARB_multisample",                  ARB_MULTISAMPLE               }, /* needs GLX_ARB_MULTISAMPLE as well */
+    {"GL_ARB_multitexture",                 ARB_MULTITEXTURE              },
+    {"GL_ARB_occlusion_query",              ARB_OCCLUSION_QUERY           },
+    {"GL_ARB_pixel_buffer_object",          ARB_PIXEL_BUFFER_OBJECT       },
+    {"GL_ARB_point_parameters",             ARB_POINT_PARAMETERS          },
+    {"GL_ARB_point_sprite",                 ARB_POINT_SPRITE              },
+    {"GL_ARB_provoking_vertex",             ARB_PROVOKING_VERTEX          },
+    {"GL_ARB_shader_bit_encoding",          ARB_SHADER_BIT_ENCODING       },
+    {"GL_ARB_shader_objects",               ARB_SHADER_OBJECTS            },
+    {"GL_ARB_shader_texture_lod",           ARB_SHADER_TEXTURE_LOD        },
+    {"GL_ARB_shading_language_100",         ARB_SHADING_LANGUAGE_100      },
+    {"GL_ARB_shadow",                       ARB_SHADOW                    },
+    {"GL_ARB_sync",                         ARB_SYNC                      },
+    {"GL_ARB_texture_border_clamp",         ARB_TEXTURE_BORDER_CLAMP      },
+    {"GL_ARB_texture_compression",          ARB_TEXTURE_COMPRESSION       },
+    {"GL_ARB_texture_compression_rgtc",     ARB_TEXTURE_COMPRESSION_RGTC  },
+    {"GL_ARB_texture_cube_map",             ARB_TEXTURE_CUBE_MAP          },
+    {"GL_ARB_texture_env_add",              ARB_TEXTURE_ENV_ADD           },
+    {"GL_ARB_texture_env_combine",          ARB_TEXTURE_ENV_COMBINE       },
+    {"GL_ARB_texture_env_dot3",             ARB_TEXTURE_ENV_DOT3          },
+    {"GL_ARB_texture_float",                ARB_TEXTURE_FLOAT             },
+    {"GL_ARB_texture_mirrored_repeat",      ARB_TEXTURE_MIRRORED_REPEAT   },
+#ifdef VBOX_WITH_WINE_FIX_IBMTMR
+    {"GL_IBM_texture_mirrored_repeat",      ARB_TEXTURE_MIRRORED_REPEAT   },
+#endif
+    {"GL_ARB_texture_non_power_of_two",     ARB_TEXTURE_NON_POWER_OF_TWO  },
+    {"GL_ARB_texture_rectangle",            ARB_TEXTURE_RECTANGLE         },
+    {"GL_ARB_texture_rg",                   ARB_TEXTURE_RG                },
+    {"GL_ARB_vertex_array_bgra",            ARB_VERTEX_ARRAY_BGRA         },
+    {"GL_ARB_vertex_blend",                 ARB_VERTEX_BLEND              },
+    {"GL_ARB_vertex_buffer_object",         ARB_VERTEX_BUFFER_OBJECT      },
+    {"GL_ARB_vertex_program",               ARB_VERTEX_PROGRAM            },
+    {"GL_ARB_vertex_shader",                ARB_VERTEX_SHADER             },
+
+    /* ATI */
+    {"GL_ATI_fragment_shader",              ATI_FRAGMENT_SHADER           },
+    {"GL_ATI_separate_stencil",             ATI_SEPARATE_STENCIL          },
+    {"GL_ATI_texture_compression_3dc",      ATI_TEXTURE_COMPRESSION_3DC   },
+    {"GL_ATI_texture_env_combine3",         ATI_TEXTURE_ENV_COMBINE3      },
+    {"GL_ATI_texture_mirror_once",          ATI_TEXTURE_MIRROR_ONCE       },
+
+    /* EXT */
+    {"GL_EXT_blend_color",                  EXT_BLEND_COLOR               },
+    {"GL_EXT_blend_equation_separate",      EXT_BLEND_EQUATION_SEPARATE   },
+    {"GL_EXT_blend_func_separate",          EXT_BLEND_FUNC_SEPARATE       },
+    {"GL_EXT_blend_minmax",                 EXT_BLEND_MINMAX              },
+    {"GL_EXT_blend_subtract",               EXT_BLEND_SUBTRACT            },
+    {"GL_EXT_depth_bounds_test",            EXT_DEPTH_BOUNDS_TEST         },
+    {"GL_EXT_draw_buffers2",                EXT_DRAW_BUFFERS2             },
+    {"GL_EXT_fog_coord",                    EXT_FOG_COORD                 },
+    {"GL_EXT_framebuffer_blit",             EXT_FRAMEBUFFER_BLIT          },
+    {"GL_EXT_framebuffer_multisample",      EXT_FRAMEBUFFER_MULTISAMPLE   },
+    {"GL_EXT_framebuffer_object",           EXT_FRAMEBUFFER_OBJECT        },
+    {"GL_EXT_gpu_program_parameters",       EXT_GPU_PROGRAM_PARAMETERS    },
+    {"GL_EXT_gpu_shader4",                  EXT_GPU_SHADER4               },
+    {"GL_EXT_packed_depth_stencil",         EXT_PACKED_DEPTH_STENCIL      },
+    {"GL_EXT_paletted_texture",             EXT_PALETTED_TEXTURE          },
+    {"GL_EXT_point_parameters",             EXT_POINT_PARAMETERS          },
+    {"GL_EXT_provoking_vertex",             EXT_PROVOKING_VERTEX          },
+    {"GL_EXT_secondary_color",              EXT_SECONDARY_COLOR           },
+    {"GL_EXT_stencil_two_side",             EXT_STENCIL_TWO_SIDE          },
+    {"GL_EXT_stencil_wrap",                 EXT_STENCIL_WRAP              },
+    {"GL_EXT_texture3D",                    EXT_TEXTURE3D                 },
+    {"GL_EXT_texture_compression_rgtc",     EXT_TEXTURE_COMPRESSION_RGTC  },
+    {"GL_EXT_texture_compression_s3tc",     EXT_TEXTURE_COMPRESSION_S3TC  },
+    {"GL_EXT_texture_env_add",              EXT_TEXTURE_ENV_ADD           },
+    {"GL_EXT_texture_env_combine",          EXT_TEXTURE_ENV_COMBINE       },
+    {"GL_EXT_texture_env_dot3",             EXT_TEXTURE_ENV_DOT3          },
+    {"GL_EXT_texture_filter_anisotropic",   EXT_TEXTURE_FILTER_ANISOTROPIC},
+    {"GL_EXT_texture_lod_bias",             EXT_TEXTURE_LOD_BIAS          },
+    {"GL_EXT_texture_sRGB",                 EXT_TEXTURE_SRGB              },
+    {"GL_EXT_texture_sRGB_decode",          EXT_TEXTURE_SRGB_DECODE       },
+    {"GL_EXT_vertex_array_bgra",            EXT_VERTEX_ARRAY_BGRA         },
+
+    /* NV */
+    {"GL_NV_depth_clamp",                   NV_DEPTH_CLAMP                },
+    {"GL_NV_fence",                         NV_FENCE                      },
+    {"GL_NV_fog_distance",                  NV_FOG_DISTANCE               },
+    {"GL_NV_fragment_program",              NV_FRAGMENT_PROGRAM           },
+    {"GL_NV_fragment_program2",             NV_FRAGMENT_PROGRAM2          },
+    {"GL_NV_fragment_program_option",       NV_FRAGMENT_PROGRAM_OPTION    },
+    {"GL_NV_half_float",                    NV_HALF_FLOAT                 },
+    {"GL_NV_light_max_exponent",            NV_LIGHT_MAX_EXPONENT         },
+    {"GL_NV_point_sprite",                  NV_POINT_SPRITE               },
+    {"GL_NV_register_combiners",            NV_REGISTER_COMBINERS         },
+    {"GL_NV_register_combiners2",           NV_REGISTER_COMBINERS2        },
+    {"GL_NV_texgen_reflection",             NV_TEXGEN_REFLECTION          },
+    {"GL_NV_texture_env_combine4",          NV_TEXTURE_ENV_COMBINE4       },
+    {"GL_NV_texture_shader",                NV_TEXTURE_SHADER             },
+    {"GL_NV_texture_shader2",               NV_TEXTURE_SHADER2            },
+    {"GL_NV_vertex_program",                NV_VERTEX_PROGRAM             },
+    {"GL_NV_vertex_program1_1",             NV_VERTEX_PROGRAM1_1          },
+    {"GL_NV_vertex_program2",               NV_VERTEX_PROGRAM2            },
+    {"GL_NV_vertex_program2_option",        NV_VERTEX_PROGRAM2_OPTION     },
+    {"GL_NV_vertex_program3",               NV_VERTEX_PROGRAM3            },
+
+    /* SGI */
+    {"GL_SGIS_generate_mipmap",             SGIS_GENERATE_MIPMAP          },
+};
+
+static const struct wined3d_extension_map wgl_extension_map[] =
+{
+    {"WGL_ARB_pixel_format",                WGL_ARB_PIXEL_FORMAT             },
+    {"WGL_EXT_swap_control",                WGL_EXT_SWAP_CONTROL             },
+    {"WGL_WINE_pixel_format_passthrough",   WGL_WINE_PIXEL_FORMAT_PASSTHROUGH},
+};
+
+/**********************************************************
+ * Utility functions follow
+ **********************************************************/
+
+const struct min_lookup minMipLookup[] =
+{
+    /* NONE         POINT                       LINEAR */
+    {{GL_NEAREST,   GL_NEAREST,                 GL_NEAREST}},               /* NONE */
+    {{GL_NEAREST,   GL_NEAREST_MIPMAP_NEAREST,  GL_NEAREST_MIPMAP_LINEAR}}, /* POINT*/
+    {{GL_LINEAR,    GL_LINEAR_MIPMAP_NEAREST,   GL_LINEAR_MIPMAP_LINEAR}},  /* LINEAR */
+};
+
+const struct min_lookup minMipLookup_noFilter[] =
+{
+    /* NONE         POINT                       LINEAR */
+    {{GL_NEAREST,   GL_NEAREST,                 GL_NEAREST}},               /* NONE */
+    {{GL_NEAREST,   GL_NEAREST,                 GL_NEAREST}},               /* POINT */
+    {{GL_NEAREST,   GL_NEAREST,                 GL_NEAREST}},               /* LINEAR */
+};
+
+const struct min_lookup minMipLookup_noMip[] =
+{
+    /* NONE         POINT                       LINEAR */
+    {{GL_NEAREST,   GL_NEAREST,                 GL_NEAREST}},               /* NONE */
+    {{GL_NEAREST,   GL_NEAREST,                 GL_NEAREST}},               /* POINT */
+    {{GL_LINEAR,    GL_LINEAR,                  GL_LINEAR }},               /* LINEAR */
+};
+
+const GLenum magLookup[] =
+{
+    /* NONE     POINT       LINEAR */
+    GL_NEAREST, GL_NEAREST, GL_LINEAR,
+};
+
+const GLenum magLookup_noFilter[] =
+{
+    /* NONE     POINT       LINEAR */
+    GL_NEAREST, GL_NEAREST, GL_NEAREST,
+};
+
+/* drawStridedSlow attributes */
+glAttribFunc position_funcs[WINED3D_FFP_EMIT_COUNT];
+glAttribFunc diffuse_funcs[WINED3D_FFP_EMIT_COUNT];
+glAttribFunc specular_func_3ubv;
+glAttribFunc specular_funcs[WINED3D_FFP_EMIT_COUNT];
+glAttribFunc normal_funcs[WINED3D_FFP_EMIT_COUNT];
+glMultiTexCoordFunc multi_texcoord_funcs[WINED3D_FFP_EMIT_COUNT];
+
+/**
+ * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created,
+ * i.e., there is no GL Context - Get a default rendering context to enable the
+ * function query some info from GL.
+ */
+
+struct wined3d_fake_gl_ctx
+{
+    HDC dc;
+    HWND wnd;
+    HGLRC gl_ctx;
+    HDC restore_dc;
+    HGLRC restore_gl_ctx;
+};
+
+static void WineD3D_ReleaseFakeGLContext(const struct wined3d_fake_gl_ctx *ctx)
+{
+    TRACE("Destroying fake GL context.\n");
+
+    if (!wglMakeCurrent(NULL, NULL))
+        ERR("Failed to disable fake GL context.\n");
+
+    if (!wglDeleteContext(ctx->gl_ctx))
+    {
+        DWORD err = GetLastError();
+        ERR("wglDeleteContext(%p) failed, last error %#x.\n", ctx->gl_ctx, err);
+    }
+
+    ReleaseDC(ctx->wnd, ctx->dc);
+    DestroyWindow(ctx->wnd);
+
+    if (ctx->restore_gl_ctx && !wglMakeCurrent(ctx->restore_dc, ctx->restore_gl_ctx))
+        ERR("Failed to restore previous GL context.\n");
+}
+
+static void wined3d_create_fake_gl_context_attribs(struct wined3d_fake_gl_ctx *fake_gl_ctx,
+        struct wined3d_gl_info *gl_info, const GLint *ctx_attribs)
+{
+    HGLRC new_ctx;
+
+    if (!(gl_info->p_wglCreateContextAttribsARB = (void *)wglGetProcAddress("wglCreateContextAttribsARB")))
+        return;
+
+    if (!(new_ctx = gl_info->p_wglCreateContextAttribsARB(fake_gl_ctx->dc, NULL, ctx_attribs)))
+    {
+        ERR("Failed to create a context using wglCreateContextAttribsARB(), last error %#x.\n", GetLastError());
+        gl_info->p_wglCreateContextAttribsARB = NULL;
+        return;
+    }
+
+    if (!wglMakeCurrent(fake_gl_ctx->dc, new_ctx))
+    {
+        ERR("Failed to make new context current, last error %#x.\n", GetLastError());
+        if (!wglDeleteContext(new_ctx))
+            ERR("Failed to delete new context, last error %#x.\n", GetLastError());
+        gl_info->p_wglCreateContextAttribsARB = NULL;
+        return;
+    }
+
+    if (!wglDeleteContext(fake_gl_ctx->gl_ctx))
+        ERR("Failed to delete old context, last error %#x.\n", GetLastError());
+    fake_gl_ctx->gl_ctx = new_ctx;
+}
+
+/* Do not call while under the GL lock. */
+#ifdef VBOX
+static BOOL WineD3D_CreateFakeGLContext(struct wined3d_fake_gl_ctx *ctx, struct VBOXUHGSMI *pHgsmi)
+#else
+static BOOL WineD3D_CreateFakeGLContext(struct wined3d_fake_gl_ctx *ctx)
+#endif
+{
+    PIXELFORMATDESCRIPTOR pfd;
+    int iPixelFormat;
+
+    TRACE("getting context...\n");
+
+    ctx->restore_dc = wglGetCurrentDC();
+    ctx->restore_gl_ctx = wglGetCurrentContext();
+
+    /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes. */
+    ctx->wnd = CreateWindowA(WINED3D_OPENGL_WINDOW_CLASS_NAME, "WineD3D fake window",
+            WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
+    if (!ctx->wnd)
+    {
+        ERR("Failed to create a window.\n");
+        goto fail;
+    }
+
+    ctx->dc = GetDC(ctx->wnd);
+    if (!ctx->dc)
+    {
+        ERR("Failed to get a DC.\n");
+        goto fail;
+    }
+
+    /* PixelFormat selection */
+    ZeroMemory(&pfd, sizeof(pfd));
+    pfd.nSize = sizeof(pfd);
+    pfd.nVersion = 1;
+    pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW; /* PFD_GENERIC_ACCELERATED */
+    pfd.iPixelType = PFD_TYPE_RGBA;
+    pfd.cColorBits = 32;
+    pfd.iLayerType = PFD_MAIN_PLANE;
+
+    if (!(iPixelFormat = ChoosePixelFormat(ctx->dc, &pfd)))
+    {
+        /* If this happens something is very wrong as ChoosePixelFormat barely fails. */
+        ERR("Failed to find a suitable pixel format.\n");
+        goto fail;
+    }
+    DescribePixelFormat(ctx->dc, iPixelFormat, sizeof(pfd), &pfd);
+    SetPixelFormat(ctx->dc, iPixelFormat, &pfd);
+
+    /* Create a GL context. */
+#ifdef VBOX
+    if (!(ctx->gl_ctx = pVBoxCreateContext(ctx->dc, pHgsmi)))
+#else
+    if (!(ctx->gl_ctx = wglCreateContext(ctx->dc)))
+#endif
+    {
+        WARN("Failed to create default context for capabilities initialization.\n");
+        goto fail;
+    }
+
+    /* Make it the current GL context. */
+    if (!wglMakeCurrent(ctx->dc, ctx->gl_ctx))
+    {
+        ERR("Failed to make fake GL context current.\n");
+        goto fail;
+    }
+
+    return TRUE;
+
+fail:
+    if (ctx->gl_ctx) wglDeleteContext(ctx->gl_ctx);
+    ctx->gl_ctx = NULL;
+    if (ctx->dc) ReleaseDC(ctx->wnd, ctx->dc);
+    ctx->dc = NULL;
+    if (ctx->wnd) DestroyWindow(ctx->wnd);
+    ctx->wnd = NULL;
+    if (ctx->restore_gl_ctx && !wglMakeCurrent(ctx->restore_dc, ctx->restore_gl_ctx))
+        ERR("Failed to restore previous GL context.\n");
+
+    return FALSE;
+}
+
+/* Adjust the amount of used texture memory */
+#ifndef VBOX_WITH_WDDM
+unsigned int adapter_adjust_memory(struct wined3d_adapter *adapter, int amount)
+{
+    adapter->UsedTextureRam += amount;
+    TRACE("Adjusted adapter memory by %d to %d.\n", amount, adapter->UsedTextureRam);
+    return adapter->UsedTextureRam;
+}
+#endif
+
+static void wined3d_adapter_cleanup(struct wined3d_adapter *adapter)
+{
+    HeapFree(GetProcessHeap(), 0, adapter->gl_info.formats);
+    HeapFree(GetProcessHeap(), 0, adapter->cfgs);
+}
+
+ULONG CDECL wined3d_incref(struct wined3d *wined3d)
+{
+    ULONG refcount = InterlockedIncrement(&wined3d->ref);
+
+    TRACE("%p increasing refcount to %u.\n", wined3d, refcount);
+
+    return refcount;
+}
+
+ULONG CDECL wined3d_decref(struct wined3d *wined3d)
+{
+    ULONG refcount = InterlockedDecrement(&wined3d->ref);
+
+    TRACE("%p decreasing refcount to %u.\n", wined3d, refcount);
+
+    if (!refcount)
+    {
+        unsigned int i;
+
+        for (i = 0; i < wined3d->adapter_count; ++i)
+        {
+            wined3d_adapter_cleanup(&wined3d->adapters[i]);
+        }
+        HeapFree(GetProcessHeap(), 0, wined3d);
+
+#ifdef VBOX_WITH_WDDM
+        VBoxExtCheckTerm();
+#endif
+    }
+
+    return refcount;
+}
+
+/* Context activation is done by the caller. */
+static BOOL test_arb_vs_offset_limit(const struct wined3d_gl_info *gl_info)
+{
+    GLuint prog;
+    BOOL ret = FALSE;
+    const char *testcode =
+        "!!ARBvp1.0\n"
+        "PARAM C[66] = { program.env[0..65] };\n"
+        "ADDRESS A0;"
+        "PARAM zero = {0.0, 0.0, 0.0, 0.0};\n"
+        "ARL A0.x, zero.x;\n"
+        "MOV result.position, C[A0.x + 65];\n"
+        "END\n";
+
+    while (gl_info->gl_ops.gl.p_glGetError());
+    GL_EXTCALL(glGenProgramsARB(1, &prog));
+    if(!prog) {
+        ERR("Failed to create an ARB offset limit test program\n");
+    }
+    GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
+    GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
+                                  strlen(testcode), testcode));
+    if (gl_info->gl_ops.gl.p_glGetError())
+    {
+        TRACE("OpenGL implementation does not allow indirect addressing offsets > 63\n");
+        TRACE("error: %s\n", debugstr_a((const char *)gl_info->gl_ops.gl.p_glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
+        ret = TRUE;
+    } else TRACE("OpenGL implementation allows offsets > 63\n");
+
+    GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
+    GL_EXTCALL(glDeleteProgramsARB(1, &prog));
+    checkGLcall("ARB vp offset limit test cleanup");
+
+    return ret;
+}
+
+static BOOL match_amd_r300_to_500(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
+        enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
+{
+    if (card_vendor != HW_VENDOR_AMD) return FALSE;
+    if (device == CARD_AMD_RADEON_9500) return TRUE;
+    if (device == CARD_AMD_RADEON_X700) return TRUE;
+    if (device == CARD_AMD_RADEON_X1600) return TRUE;
+    return FALSE;
+}
+
+static BOOL match_geforce5(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
+        enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
+{
+    if (card_vendor == HW_VENDOR_NVIDIA)
+    {
+        if (device == CARD_NVIDIA_GEFORCEFX_5200 ||
+            device == CARD_NVIDIA_GEFORCEFX_5600 ||
+            device == CARD_NVIDIA_GEFORCEFX_5800)
+        {
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+static BOOL match_apple(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
+        enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
+{
+    /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
+     * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
+     * detect the Apple OpenGL implementation to apply some extension fixups afterwards.
+     *
+     * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks
+     * aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
+     * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
+     * like client storage might be supported on other implementations too, but GL_APPLE_flush_render
+     * is specific to the Mac OS X window management, and GL_APPLE_ycbcr_422 is QuickTime specific. So
+     * the chance that other implementations support them is rather small since Win32 QuickTime uses
+     * DirectDraw, not OpenGL.
+     *
+     * This test has been moved into wined3d_guess_gl_vendor()
+     */
+    if (gl_vendor == GL_VENDOR_APPLE)
+    {
+        return TRUE;
+    }
+    return FALSE;
+}
+
+/* Context activation is done by the caller. */
+static void test_pbo_functionality(struct wined3d_gl_info *gl_info)
+{
+    /* Some OpenGL implementations, namely Apple's Geforce 8 driver, advertises PBOs,
+     * but glTexSubImage from a PBO fails miserably, with the first line repeated over
+     * all the texture. This function detects this bug by its symptom and disables PBOs
+     * if the test fails.
+     *
+     * The test uploads a 4x4 texture via the PBO in the "native" format GL_BGRA,
+     * GL_UNSIGNED_INT_8_8_8_8_REV. This format triggers the bug, and it is what we use
+     * for D3DFMT_A8R8G8B8. Then the texture is read back without any PBO and the data
+     * read back is compared to the original. If they are equal PBOs are assumed to work,
+     * otherwise the PBO extension is disabled. */
+    GLuint texture, pbo;
+    static const unsigned int pattern[] =
+    {
+        0x00000000, 0x000000ff, 0x0000ff00, 0x40ff0000,
+        0x80ffffff, 0x40ffff00, 0x00ff00ff, 0x0000ffff,
+        0x00ffff00, 0x00ff00ff, 0x0000ffff, 0x000000ff,
+        0x80ff00ff, 0x0000ffff, 0x00ff00ff, 0x40ff00ff
+    };
+    unsigned int check[sizeof(pattern) / sizeof(pattern[0])];
+
+    /* No PBO -> No point in testing them. */
+    if (!gl_info->supported[ARB_PIXEL_BUFFER_OBJECT]) return;
+
+    while (gl_info->gl_ops.gl.p_glGetError());
+    gl_info->gl_ops.gl.p_glGenTextures(1, &texture);
+    gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, texture);
+
+    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
+    gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
+    checkGLcall("Specifying the PBO test texture");
+
+    GL_EXTCALL(glGenBuffersARB(1, &pbo));
+    GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo));
+    GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, sizeof(pattern), pattern, GL_STREAM_DRAW_ARB));
+    checkGLcall("Specifying the PBO test pbo");
+
+    gl_info->gl_ops.gl.p_glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
+    checkGLcall("Loading the PBO test texture");
+
+    GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
+
+    gl_info->gl_ops.gl.p_glFinish(); /* just to be sure */
+
+    memset(check, 0, sizeof(check));
+
+    gl_info->gl_ops.gl.p_glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, check);
+    checkGLcall("Reading back the PBO test texture");
+
+    gl_info->gl_ops.gl.p_glDeleteTextures(1, &texture);
+    GL_EXTCALL(glDeleteBuffersARB(1, &pbo));
+    checkGLcall("PBO test cleanup");
+
+    if (memcmp(check, pattern, sizeof(check)))
+    {
+        WARN_(d3d_perf)("PBO test failed, read back data doesn't match original.\n"
+                "Disabling PBOs. This may result in slower performance.\n");
+        gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = FALSE;
+    }
+    else
+    {
+        TRACE("PBO test successful.\n");
+    }
+}
+
+static BOOL match_apple_intel(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
+        enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
+{
+    return (card_vendor == HW_VENDOR_INTEL) && (gl_vendor == GL_VENDOR_APPLE);
+}
+
+static BOOL match_apple_nonr500ati(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
+        enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
+{
+    if (gl_vendor != GL_VENDOR_APPLE) return FALSE;
+    if (card_vendor != HW_VENDOR_AMD) return FALSE;
+    if (device == CARD_AMD_RADEON_X1600) return FALSE;
+    return TRUE;
+}
+
+static BOOL match_dx10_capable(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
+        enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
+{
+    /* DX9 cards support 40 single float varyings in hardware, most drivers report 32. ATI misreports
+     * 44 varyings. So assume that if we have more than 44 varyings we have a dx10 card.
+     * This detection is for the gl_ClipPos varying quirk. If a d3d9 card really supports more than 44
+     * varyings and we subtract one in dx9 shaders its not going to hurt us because the dx9 limit is
+     * hardcoded
+     *
+     * dx10 cards usually have 64 varyings */
+    return gl_info->limits.glsl_varyings > 44;
+}
+
+static BOOL match_not_dx10_capable(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
+        enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
+{
+    return !match_dx10_capable(gl_info, gl_renderer, gl_vendor, card_vendor, device);
+}
+
+/* A GL context is provided by the caller */
+static BOOL match_allows_spec_alpha(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
+        enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
+{
+    GLenum error;
+    DWORD data[16];
+
+    if (!gl_info->supported[EXT_SECONDARY_COLOR])
+        return FALSE;
+
+    while (gl_info->gl_ops.gl.p_glGetError());
+    GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE, 4, data);
+    error = gl_info->gl_ops.gl.p_glGetError();
+
+    if (error == GL_NO_ERROR)
+    {
+        TRACE("GL Implementation accepts 4 component specular color pointers\n");
+        return TRUE;
+    }
+    else
+    {
+        TRACE("GL implementation does not accept 4 component specular colors, error %s\n",
+              debug_glerror(error));
+        return FALSE;
+    }
+}
+
+/* A GL context is provided by the caller */
+static BOOL match_broken_nv_clip(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
+        enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
+{
+    GLuint prog;
+    BOOL ret = FALSE;
+    GLint pos;
+    const char *testcode =
+        "!!ARBvp1.0\n"
+        "OPTION NV_vertex_program2;\n"
+        "MOV result.clip[0], 0.0;\n"
+        "MOV result.position, 0.0;\n"
+        "END\n";
+
+    if (!gl_info->supported[NV_VERTEX_PROGRAM2_OPTION]) return FALSE;
+
+    while (gl_info->gl_ops.gl.p_glGetError());
+
+    GL_EXTCALL(glGenProgramsARB(1, &prog));
+    if(!prog)
+    {
+        ERR("Failed to create the NVvp clip test program\n");
+        return FALSE;
+    }
+    GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
+    GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
+                                  strlen(testcode), testcode));
+    gl_info->gl_ops.gl.p_glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos);
+    if(pos != -1)
+    {
+        WARN("GL_NV_vertex_program2_option result.clip[] test failed\n");
+        TRACE("error: %s\n", debugstr_a((const char *)gl_info->gl_ops.gl.p_glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
+        ret = TRUE;
+        while (gl_info->gl_ops.gl.p_glGetError());
+    }
+    else TRACE("GL_NV_vertex_program2_option result.clip[] test passed\n");
+
+    GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
+    GL_EXTCALL(glDeleteProgramsARB(1, &prog));
+    checkGLcall("GL_NV_vertex_program2_option result.clip[] test cleanup");
+
+    return ret;
+}
+
+/* Context activation is done by the caller. */
+static BOOL match_fbo_tex_update(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
+        enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
+{
+    char data[4 * 4 * 4];
+    GLuint tex, fbo;
+    GLenum status;
+
+    if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) return FALSE;
+
+    memset(data, 0xcc, sizeof(data));
+
+    gl_info->gl_ops.gl.p_glGenTextures(1, &tex);
+    gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, tex);
+    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
+    checkGLcall("glTexImage2D");
+
+    gl_info->fbo_ops.glGenFramebuffers(1, &fbo);
+    gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+    gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
+    checkGLcall("glFramebufferTexture2D");
+
+    status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER);
+    if (status != GL_FRAMEBUFFER_COMPLETE) ERR("FBO status %#x\n", status);
+    checkGLcall("glCheckFramebufferStatus");
+
+    memset(data, 0x11, sizeof(data));
+    gl_info->gl_ops.gl.p_glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data);
+    checkGLcall("glTexSubImage2D");
+
+    gl_info->gl_ops.gl.p_glClearColor(0.996f, 0.729f, 0.745f, 0.792f);
+    gl_info->gl_ops.gl.p_glClear(GL_COLOR_BUFFER_BIT);
+    checkGLcall("glClear");
+
+    gl_info->gl_ops.gl.p_glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data);
+    checkGLcall("glGetTexImage");
+
+    gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
+    gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, 0);
+    gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, 0);
+    checkGLcall("glBindTexture");
+
+    gl_info->fbo_ops.glDeleteFramebuffers(1, &fbo);
+    gl_info->gl_ops.gl.p_glDeleteTextures(1, &tex);
+    checkGLcall("glDeleteTextures");
+
+    return *(DWORD *)data == 0x11111111;
+}
+
+/* Context activation is done by the caller. */
+static BOOL match_broken_rgba16(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
+        enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
+{
+    /* GL_RGBA16 uses GL_RGBA8 internally on Geforce 7 and older cards.
+     * This leads to graphical bugs in Half Life 2 and Unreal engine games. */
+    GLuint tex;
+    GLint size;
+
+    gl_info->gl_ops.gl.p_glGenTextures(1, &tex);
+    gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, tex);
+    gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, 4, 4, 0, GL_RGBA, GL_UNSIGNED_SHORT, NULL);
+    checkGLcall("glTexImage2D");
+
+    gl_info->gl_ops.gl.p_glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_RED_SIZE, &size);
+    checkGLcall("glGetTexLevelParameteriv");
+    TRACE("Real color depth is %d\n", size);
+
+    gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, 0);
+    checkGLcall("glBindTexture");
+    gl_info->gl_ops.gl.p_glDeleteTextures(1, &tex);
+    checkGLcall("glDeleteTextures");
+
+    return size < 16;
+}
+
+static BOOL match_fglrx(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
+        enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
+{
+    return gl_vendor == GL_VENDOR_FGLRX;
+}
+
+static BOOL match_r200(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
+        enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
+{
+    if (card_vendor != HW_VENDOR_AMD) return FALSE;
+    if (device == CARD_AMD_RADEON_8500) return TRUE;
+    return FALSE;
+}
+
+static void quirk_apple_glsl_constants(struct wined3d_gl_info *gl_info)
+{
+    /* MacOS needs uniforms for relative addressing offsets. This can accumulate to quite a few uniforms.
+     * Beyond that the general uniform isn't optimal, so reserve a number of uniforms. 12 vec4's should
+     * allow 48 different offsets or other helper immediate values. */
+    TRACE("Reserving 12 GLSL constants for compiler private use.\n");
+    gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 12);
+}
+
+static void quirk_amd_dx9(struct wined3d_gl_info *gl_info)
+{
+    /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although
+     * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL).
+     * If real NP2 textures are used, the driver falls back to software. We could just remove the
+     * extension and use GL_ARB_texture_rectangle instead, but texture_rectangle is inconvenient
+     * due to the non-normalized texture coordinates. Thus set an internal extension flag,
+     * GL_WINE_normalized_texrect, which signals the code that it can use non power of two textures
+     * as per GL_ARB_texture_non_power_of_two, but has to stick to the texture_rectangle limits.
+     *
+     * fglrx doesn't advertise GL_ARB_texture_non_power_of_two, but it advertises opengl 2.0 which
+     * has this extension promoted to core. The extension loading code sets this extension supported
+     * due to that, so this code works on fglrx as well. */
+    if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
+    {
+        TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing.\n");
+        gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
+        gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT] = TRUE;
+    }
+}
+
+static void quirk_no_np2(struct wined3d_gl_info *gl_info)
+{
+    /*  The nVidia GeForceFX series reports OpenGL 2.0 capabilities with the latest drivers versions, but
+     *  doesn't explicitly advertise the ARB_tex_npot extension in the GL extension string.
+     *  This usually means that ARB_tex_npot is supported in hardware as long as the application is staying
+     *  within the limits enforced by the ARB_texture_rectangle extension. This however is not true for the
+     *  FX series, which instantly falls back to a slower software path as soon as ARB_tex_npot is used.
+     *  We therefore completely remove ARB_tex_npot from the list of supported extensions.
+     *
+     *  Note that wine_normalized_texrect can't be used in this case because internally it uses ARB_tex_npot,
+     *  triggering the software fallback. There is not much we can do here apart from disabling the
+     *  software-emulated extension and re-enable ARB_tex_rect (which was previously disabled
+     *  in wined3d_adapter_init_gl_caps).
+     *  This fixup removes performance problems on both the FX 5900 and FX 5700 (e.g. for framebuffer
+     *  post-processing effects in the game "Max Payne 2").
+     *  The behaviour can be verified through a simple test app attached in bugreport #14724. */
+    TRACE("GL_ARB_texture_non_power_of_two advertised through OpenGL 2.0 on NV FX card, removing.\n");
+    gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
+    gl_info->supported[ARB_TEXTURE_RECTANGLE] = TRUE;
+}
+
+static void quirk_texcoord_w(struct wined3d_gl_info *gl_info)
+{
+    /* The Intel GPUs on MacOS set the .w register of texcoords to 0.0 by default, which causes problems
+     * with fixed function fragment processing. Ideally this flag should be detected with a test shader
+     * and OpenGL feedback mode, but some GL implementations (MacOS ATI at least, probably all MacOS ones)
+     * do not like vertex shaders in feedback mode and return an error, even though it should be valid
+     * according to the spec.
+     *
+     * We don't want to enable this on all cards, as it adds an extra instruction per texcoord used. This
+     * makes the shader slower and eats instruction slots which should be available to the d3d app.
+     *
+     * ATI Radeon HD 2xxx cards on MacOS have the issue. Instead of checking for the buggy cards, blacklist
+     * all radeon cards on Macs and whitelist the good ones. That way we're prepared for the future. If
+     * this workaround is activated on cards that do not need it, it won't break things, just affect
+     * performance negatively. */
+    TRACE("Enabling vertex texture coord fixes in vertex shaders.\n");
+    gl_info->quirks |= WINED3D_QUIRK_SET_TEXCOORD_W;
+}
+
+static void quirk_clip_varying(struct wined3d_gl_info *gl_info)
+{
+    gl_info->quirks |= WINED3D_QUIRK_GLSL_CLIP_VARYING;
+}
+
+static void quirk_allows_specular_alpha(struct wined3d_gl_info *gl_info)
+{
+    gl_info->quirks |= WINED3D_QUIRK_ALLOWS_SPECULAR_ALPHA;
+}
+
+static void quirk_disable_nvvp_clip(struct wined3d_gl_info *gl_info)
+{
+    gl_info->quirks |= WINED3D_QUIRK_NV_CLIP_BROKEN;
+}
+
+static void quirk_fbo_tex_update(struct wined3d_gl_info *gl_info)
+{
+    gl_info->quirks |= WINED3D_QUIRK_FBO_TEX_UPDATE;
+}
+
+static void quirk_broken_rgba16(struct wined3d_gl_info *gl_info)
+{
+    gl_info->quirks |= WINED3D_QUIRK_BROKEN_RGBA16;
+}
+
+static void quirk_infolog_spam(struct wined3d_gl_info *gl_info)
+{
+    gl_info->quirks |= WINED3D_QUIRK_INFO_LOG_SPAM;
+}
+
+static void quirk_limited_tex_filtering(struct wined3d_gl_info *gl_info)
+{
+    /* Nvidia GeForce 6xxx and 7xxx support accelerated VTF only on a few
+       selected texture formats. They are apparently the only DX9 class GPUs
+       supporting VTF.
+       Also, DX9-era GPUs are somewhat limited with float textures
+       filtering and blending. */
+    gl_info->quirks |= WINED3D_QUIRK_LIMITED_TEX_FILTERING;
+}
+
+static void quirk_r200_constants(struct wined3d_gl_info *gl_info)
+{
+    /* The Mesa r200 driver (and there is no other driver for this GPU Wine would run on)
+     * loads some fog parameters (start, end, exponent, but not the color) into the
+     * program.
+     *
+     * Apparently the fog hardware is only able to handle linear fog with a range of 0.0;1.0,
+     * and it is the responsibility of the vertex pipeline to handle non-linear fog and
+     * linear fog with start and end other than 0.0 and 1.0. */
+    TRACE("Reserving 1 ARB constant for compiler private use.\n");
+    gl_info->reserved_arb_constants = max(gl_info->reserved_arb_constants, 1);
+}
+
+#ifdef VBOX_WITH_WINE_FIX_QUIRKS
+static BOOL match_ati_hd4800(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
+        enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
+{
+    if (card_vendor != HW_VENDOR_AMD) return FALSE;
+    if (device == CARD_AMD_RADEON_HD4800) return TRUE;
+    return FALSE;
+}
+
+static void quirk_fullsize_blit(struct wined3d_gl_info *gl_info)
+{
+    gl_info->quirks |= WINED3D_QUIRK_FULLSIZE_BLIT;
+}
+
+#ifdef VBOX_WITH_WDDM
+# if 0
+static BOOL match_mesa_nvidia(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
+        enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
+{
+    if (card_vendor != HW_VENDOR_NVIDIA) return FALSE;
+    if (gl_vendor != GL_VENDOR_MESA) return FALSE;
+    return TRUE;
+}
+
+static void quirk_no_shader_3(struct wined3d_gl_info *gl_info)
+{
+    int vs_selected_mode, ps_selected_mode;
+    select_shader_mode(gl_info, &ps_selected_mode, &vs_selected_mode);
+    if (vs_selected_mode != SHADER_GLSL && ps_selected_mode != SHADER_GLSL)
+        return;
+
+    gl_info->quirks |= WINED3D_QUIRK_NO_SHADER_V3;
+}
+# endif
+#endif
+
+static BOOL match_intel(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
+        enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
+{
+    if (card_vendor == HW_VENDOR_INTEL) return TRUE;
+    if (gl_vendor == HW_VENDOR_INTEL) return TRUE;
+    return FALSE;
+}
+
+static void quirk_force_blit(struct wined3d_gl_info *gl_info)
+{
+    gl_info->quirks |= WINED3D_QUIRK_FORCE_BLIT;
+}
+#endif
+
+struct driver_quirk
+{
+    BOOL (*match)(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
+            enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device);
+    void (*apply)(struct wined3d_gl_info *gl_info);
+    const char *description;
+};
+
+static const struct driver_quirk quirk_table[] =
+{
+    {
+        match_amd_r300_to_500,
+        quirk_amd_dx9,
+        "AMD normalized texrect quirk"
+    },
+    {
+        match_apple,
+        quirk_apple_glsl_constants,
+        "Apple GLSL uniform override"
+    },
+    {
+        match_geforce5,
+        quirk_no_np2,
+        "Geforce 5 NP2 disable"
+    },
+    {
+        match_apple_intel,
+        quirk_texcoord_w,
+        "Init texcoord .w for Apple Intel GPU driver"
+    },
+    {
+        match_apple_nonr500ati,
+        quirk_texcoord_w,
+        "Init texcoord .w for Apple ATI >= r600 GPU driver"
+    },
+    {
+        match_dx10_capable,
+        quirk_clip_varying,
+        "Reserved varying for gl_ClipPos"
+    },
+    {
+        /* GL_EXT_secondary_color does not allow 4 component secondary colors, but most
+         * GL implementations accept it. The Mac GL is the only implementation known to
+         * reject it.
+         *
+         * If we can pass 4 component specular colors, do it, because (a) we don't have
+         * to screw around with the data, and (b) the D3D fixed function vertex pipeline
+         * passes specular alpha to the pixel shader if any is used. Otherwise the
+         * specular alpha is used to pass the fog coordinate, which we pass to opengl
+         * via GL_EXT_fog_coord.
+         */
+        match_allows_spec_alpha,
+        quirk_allows_specular_alpha,
+        "Allow specular alpha quirk"
+    },
+    {
+        match_broken_nv_clip,
+        quirk_disable_nvvp_clip,
+        "Apple NV_vertex_program clip bug quirk"
+    },
+    {
+        match_fbo_tex_update,
+        quirk_fbo_tex_update,
+        "FBO rebind for attachment updates"
+    },
+    {
+        match_broken_rgba16,
+        quirk_broken_rgba16,
+        "True RGBA16 is not available"
+    },
+    {
+        match_fglrx,
+        quirk_infolog_spam,
+        "Not printing GLSL infolog"
+    },
+    {
+        match_not_dx10_capable,
+        quirk_limited_tex_filtering,
+        "Texture filtering, blending and VTF support is limited"
+    },
+    {
+        match_r200,
+        quirk_r200_constants,
+        "r200 vertex shader constants"
+    },
+#ifdef VBOX_WITH_WINE_FIX_QUIRKS
+    {
+        match_ati_hd4800,
+        quirk_fullsize_blit,
+        "Fullsize blit"
+    },
+#if 0 //def VBOX_WITH_WDDM
+    {
+        match_mesa_nvidia,
+        quirk_no_shader_3,
+        "disable shader 3 support"
+    },
+#endif
+    {
+        match_intel,
+        quirk_force_blit,
+        "force framebuffer blit when possible"
+    }
+#endif
+};
+
+/* Certain applications (Steam) complain if we report an outdated driver version. In general,
+ * reporting a driver version is moot because we are not the Windows driver, and we have different
+ * bugs, features, etc.
+ *
+ * The driver version has the form "x.y.z.w".
+ *
+ * "x" is the Windows version the driver is meant for:
+ * 4 -> 95/98/NT4
+ * 5 -> 2000
+ * 6 -> 2000/XP
+ * 7 -> Vista
+ * 8 -> Win 7
+ *
+ * "y" is the maximum Direct3D version the driver supports.
+ * y  -> d3d version mapping:
+ * 11 -> d3d6
+ * 12 -> d3d7
+ * 13 -> d3d8
+ * 14 -> d3d9
+ * 15 -> d3d10
+ * 16 -> d3d10.1
+ * 17 -> d3d11
+ *
+ * "z" is the subversion number.
+ *
+ * "w" is the vendor specific driver build number.
+ */
+
+struct driver_version_information
+{
+    enum wined3d_display_driver driver;
+    enum wined3d_driver_model driver_model;
+    const char *driver_name;            /* name of Windows driver */
+    WORD version;                       /* version word ('y'), contained in low word of DriverVersion.HighPart */
+    WORD subversion;                    /* subversion word ('z'), contained in high word of DriverVersion.LowPart */
+    WORD build;                         /* build number ('w'), contained in low word of DriverVersion.LowPart */
+};
+
+/* The driver version table contains driver information for different devices on several OS versions. */
+static const struct driver_version_information driver_version_table[] =
+{
+    /* AMD
+     * - Radeon HD2x00 (R600) and up supported by current drivers.
+     * - Radeon 9500 (R300) - X1*00 (R5xx) supported up to Catalyst 9.3 (Linux) and 10.2 (XP/Vista/Win7)
+     * - Radeon 7xxx (R100) - 9250 (RV250) supported up to Catalyst 6.11 (XP)
+     * - Rage 128 supported up to XP, latest official build 6.13.3279 dated October 2001 */
+    {DRIVER_AMD_RAGE_128PRO,    DRIVER_MODEL_NT5X,  "ati2dvaa.dll", 13, 3279,  0},
+    {DRIVER_AMD_R100,           DRIVER_MODEL_NT5X,  "ati2dvag.dll", 14, 10, 6614},
+    {DRIVER_AMD_R300,           DRIVER_MODEL_NT5X,  "ati2dvag.dll", 14, 10, 6764},
+    {DRIVER_AMD_R600,           DRIVER_MODEL_NT5X,  "ati2dvag.dll", 14, 10, 8681},
+    {DRIVER_AMD_R300,           DRIVER_MODEL_NT6X,  "atiumdag.dll", 14, 10, 741 },
+    {DRIVER_AMD_R600,           DRIVER_MODEL_NT6X,  "atiumdag.dll", 14, 10, 741 },
+
+    /* Intel
+     * The drivers are unified but not all versions support all GPUs. At some point the 2k/xp
+     * drivers used ialmrnt5.dll for GMA800/GMA900 but at some point the file was renamed to
+     * igxprd32.dll but the GMA800 driver was never updated. */
+    {DRIVER_INTEL_GMA800,       DRIVER_MODEL_NT5X,  "ialmrnt5.dll", 14, 10, 3889},
+    {DRIVER_INTEL_GMA900,       DRIVER_MODEL_NT5X,  "igxprd32.dll", 14, 10, 4764},
+    {DRIVER_INTEL_GMA950,       DRIVER_MODEL_NT5X,  "igxprd32.dll", 14, 10, 4926},
+    {DRIVER_INTEL_GMA3000,      DRIVER_MODEL_NT5X,  "igxprd32.dll", 14, 10, 5218},
+    {DRIVER_INTEL_GMA950,       DRIVER_MODEL_NT6X,  "igdumd32.dll", 14, 10, 1504},
+    {DRIVER_INTEL_GMA3000,      DRIVER_MODEL_NT6X,  "igdumd32.dll", 15, 10, 1666},
+
+    /* Nvidia
+     * - Geforce6 and newer cards are supported by the current driver (197.x) on XP-Win7
+     * - GeforceFX support is up to 173.x on <= XP
+     * - Geforce2MX/3/4 up to 96.x on <= XP
+     * - TNT/Geforce1/2 up to 71.x on <= XP
+     * All version numbers used below are from the Linux nvidia drivers. */
+    {DRIVER_NVIDIA_TNT,         DRIVER_MODEL_NT5X,  "nv4_disp.dll", 14, 10, 7186},
+    {DRIVER_NVIDIA_GEFORCE2MX,  DRIVER_MODEL_NT5X,  "nv4_disp.dll", 14, 10, 9371},
+    {DRIVER_NVIDIA_GEFORCEFX,   DRIVER_MODEL_NT5X,  "nv4_disp.dll", 14, 11, 7516},
+    {DRIVER_NVIDIA_GEFORCE6,    DRIVER_MODEL_NT5X,  "nv4_disp.dll", 15, 12, 6658},
+    {DRIVER_NVIDIA_GEFORCE6,    DRIVER_MODEL_NT6X,  "nvd3dum.dll",  15, 12, 6658},
+};
+
+struct gpu_description
+{
+    WORD vendor;                    /* reported PCI card vendor ID  */
+    WORD card;                      /* reported PCI card device ID  */
+    const char *description;        /* Description of the card e.g. NVIDIA RIVA TNT */
+    enum wined3d_display_driver driver;
+    unsigned int vidmem;
+};
+
+/* The amount of video memory stored in the gpu description table is the minimum amount of video memory
+ * found on a board containing a specific GPU. */
+static const struct gpu_description gpu_description_table[] =
+{
+    /* Nvidia cards */
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_RIVA_TNT,           "NVIDIA RIVA TNT",                  DRIVER_NVIDIA_TNT,       16  },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_RIVA_TNT2,          "NVIDIA RIVA TNT2/TNT2 Pro",        DRIVER_NVIDIA_TNT,       32  },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE,            "NVIDIA GeForce 256",               DRIVER_NVIDIA_TNT,       32  },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE2,           "NVIDIA GeForce2 GTS/GeForce2 Pro", DRIVER_NVIDIA_TNT,       32  },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE2_MX,        "NVIDIA GeForce2 MX/MX 400",        DRIVER_NVIDIA_GEFORCE2MX,32  },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE3,           "NVIDIA GeForce3",                  DRIVER_NVIDIA_GEFORCE2MX,64  },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE4_MX,        "NVIDIA GeForce4 MX 460",           DRIVER_NVIDIA_GEFORCE2MX,64  },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE4_TI4200,    "NVIDIA GeForce4 Ti 4200",          DRIVER_NVIDIA_GEFORCE2MX,64, },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCEFX_5200,     "NVIDIA GeForce FX 5200",           DRIVER_NVIDIA_GEFORCEFX, 64  },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCEFX_5600,     "NVIDIA GeForce FX 5600",           DRIVER_NVIDIA_GEFORCEFX, 128 },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCEFX_5800,     "NVIDIA GeForce FX 5800",           DRIVER_NVIDIA_GEFORCEFX, 256 },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_6200,       "NVIDIA GeForce 6200",              DRIVER_NVIDIA_GEFORCE6,  64  },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_6600GT,     "NVIDIA GeForce 6600 GT",           DRIVER_NVIDIA_GEFORCE6,  128 },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_6800,       "NVIDIA GeForce 6800",              DRIVER_NVIDIA_GEFORCE6,  128 },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_7300,       "NVIDIA GeForce Go 7300",           DRIVER_NVIDIA_GEFORCE6,  256 },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_7400,       "NVIDIA GeForce Go 7400",           DRIVER_NVIDIA_GEFORCE6,  256 },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_7600,       "NVIDIA GeForce 7600 GT",           DRIVER_NVIDIA_GEFORCE6,  256 },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_7800GT,     "NVIDIA GeForce 7800 GT",           DRIVER_NVIDIA_GEFORCE6,  256 },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_8300GS,     "NVIDIA GeForce 8300 GS",           DRIVER_NVIDIA_GEFORCE6,  128 },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_8400GS,     "NVIDIA GeForce 8400 GS",           DRIVER_NVIDIA_GEFORCE6,  128 },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_8600GT,     "NVIDIA GeForce 8600 GT",           DRIVER_NVIDIA_GEFORCE6,  256 },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_8600MGT,    "NVIDIA GeForce 8600M GT",          DRIVER_NVIDIA_GEFORCE6,  512 },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_8800GTS,    "NVIDIA GeForce 8800 GTS",          DRIVER_NVIDIA_GEFORCE6,  320 },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_8800GTX,    "NVIDIA GeForce 8800 GTX",          DRIVER_NVIDIA_GEFORCE6,  768 },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_9200,       "NVIDIA GeForce 9200",              DRIVER_NVIDIA_GEFORCE6,  256 },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_9300,       "NVIDIA GeForce 9300",              DRIVER_NVIDIA_GEFORCE6,  256 },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_9400M,      "NVIDIA GeForce 9400M",             DRIVER_NVIDIA_GEFORCE6,  256 },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_9400GT,     "NVIDIA GeForce 9400 GT",           DRIVER_NVIDIA_GEFORCE6,  256 },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_9500GT,     "NVIDIA GeForce 9500 GT",           DRIVER_NVIDIA_GEFORCE6,  256 },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_9600GT,     "NVIDIA GeForce 9600 GT",           DRIVER_NVIDIA_GEFORCE6,  384 },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_9800GT,     "NVIDIA GeForce 9800 GT",           DRIVER_NVIDIA_GEFORCE6,  512 },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_210,        "NVIDIA GeForce 210",               DRIVER_NVIDIA_GEFORCE6,  512 },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT220,      "NVIDIA GeForce GT 220",            DRIVER_NVIDIA_GEFORCE6,  512 },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT240,      "NVIDIA GeForce GT 240",            DRIVER_NVIDIA_GEFORCE6,  512 },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX260,     "NVIDIA GeForce GTX 260",           DRIVER_NVIDIA_GEFORCE6,  1024},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX275,     "NVIDIA GeForce GTX 275",           DRIVER_NVIDIA_GEFORCE6,  896 },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX280,     "NVIDIA GeForce GTX 280",           DRIVER_NVIDIA_GEFORCE6,  1024},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_315M,       "NVIDIA GeForce 315M",              DRIVER_NVIDIA_GEFORCE6,  512 },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_320M,       "NVIDIA GeForce 320M",              DRIVER_NVIDIA_GEFORCE6,  256},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_410M,       "NVIDIA GeForce 410M",              DRIVER_NVIDIA_GEFORCE6,  512},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT320M,     "NVIDIA GeForce GT 320M",           DRIVER_NVIDIA_GEFORCE6,  1024},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT325M,     "NVIDIA GeForce GT 325M",           DRIVER_NVIDIA_GEFORCE6,  1024},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT330,      "NVIDIA GeForce GT 330",            DRIVER_NVIDIA_GEFORCE6,  1024},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTS350M,    "NVIDIA GeForce GTS 350M",          DRIVER_NVIDIA_GEFORCE6,  1024},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT420,      "NVIDIA GeForce GT 420",            DRIVER_NVIDIA_GEFORCE6,  2048},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT430,      "NVIDIA GeForce GT 430",            DRIVER_NVIDIA_GEFORCE6,  1024},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT440,      "NVIDIA GeForce GT 440",            DRIVER_NVIDIA_GEFORCE6,  1024},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTS450,     "NVIDIA GeForce GTS 450",           DRIVER_NVIDIA_GEFORCE6,  1024},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX460,     "NVIDIA GeForce GTX 460",           DRIVER_NVIDIA_GEFORCE6,  768 },
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX460M,    "NVIDIA GeForce GTX 460M",          DRIVER_NVIDIA_GEFORCE6,  1536},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX465,     "NVIDIA GeForce GTX 465",           DRIVER_NVIDIA_GEFORCE6,  1024},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX470,     "NVIDIA GeForce GTX 470",           DRIVER_NVIDIA_GEFORCE6,  1280},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX480,     "NVIDIA GeForce GTX 480",           DRIVER_NVIDIA_GEFORCE6,  1536},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT520,      "NVIDIA GeForce GT 520",            DRIVER_NVIDIA_GEFORCE6,  1024},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT540M,     "NVIDIA GeForce GT 540M",           DRIVER_NVIDIA_GEFORCE6,  1024},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX550,     "NVIDIA GeForce GTX 550 Ti",        DRIVER_NVIDIA_GEFORCE6,  1024},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT555M,     "NVIDIA GeForce GT 555M",           DRIVER_NVIDIA_GEFORCE6,  1024},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX560TI,   "NVIDIA GeForce GTX 560 Ti",        DRIVER_NVIDIA_GEFORCE6,  1024},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX560,     "NVIDIA GeForce GTX 560",           DRIVER_NVIDIA_GEFORCE6,  1024},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX570,     "NVIDIA GeForce GTX 570",           DRIVER_NVIDIA_GEFORCE6,  1280},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX580,     "NVIDIA GeForce GTX 580",           DRIVER_NVIDIA_GEFORCE6,  1536},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT610,      "NVIDIA GeForce GT 610",            DRIVER_NVIDIA_GEFORCE6,  1024},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT630,      "NVIDIA GeForce GT 630",            DRIVER_NVIDIA_GEFORCE6,  1024},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT630M,     "NVIDIA GeForce GT 630M",           DRIVER_NVIDIA_GEFORCE6,  1024},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT640M,     "NVIDIA GeForce GT 640M",           DRIVER_NVIDIA_GEFORCE6,  1024},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT650M,     "NVIDIA GeForce GT 650M",           DRIVER_NVIDIA_GEFORCE6,  2048},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX650,     "NVIDIA GeForce GTX 650",           DRIVER_NVIDIA_GEFORCE6,  1024},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX650TI,   "NVIDIA GeForce GTX 650 Ti",        DRIVER_NVIDIA_GEFORCE6,  1024},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX660,     "NVIDIA GeForce GTX 660",           DRIVER_NVIDIA_GEFORCE6,  2048},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX660TI,   "NVIDIA GeForce GTX 660 Ti",        DRIVER_NVIDIA_GEFORCE6,  2048},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX670,     "NVIDIA GeForce GTX 670",           DRIVER_NVIDIA_GEFORCE6,  2048},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX680,     "NVIDIA GeForce GTX 680",           DRIVER_NVIDIA_GEFORCE6,  2048},
+
+    /* AMD cards */
+    {HW_VENDOR_AMD,        CARD_AMD_RAGE_128PRO,           "ATI Rage Fury",                    DRIVER_AMD_RAGE_128PRO,  16  },
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_7200,           "ATI RADEON 7200 SERIES",           DRIVER_AMD_R100,         32  },
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_8500,           "ATI RADEON 8500 SERIES",           DRIVER_AMD_R100,         64  },
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_9500,           "ATI Radeon 9500",                  DRIVER_AMD_R300,         64  },
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_XPRESS_200M,    "ATI RADEON XPRESS 200M Series",    DRIVER_AMD_R300,         64  },
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_X700,           "ATI Radeon X700 SE",               DRIVER_AMD_R300,         128 },
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_X1600,          "ATI Radeon X1600 Series",          DRIVER_AMD_R300,         128 },
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD2350,         "ATI Mobility Radeon HD 2350",      DRIVER_AMD_R600,         256 },
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD2600,         "ATI Mobility Radeon HD 2600",      DRIVER_AMD_R600,         256 },
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD2900,         "ATI Radeon HD 2900 XT",            DRIVER_AMD_R600,         512 },
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD3200,         "ATI Radeon HD 3200 Graphics",      DRIVER_AMD_R600,         128 },
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD4200M,        "ATI Mobility Radeon HD 4200",      DRIVER_AMD_R600,         256 },
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD4350,         "ATI Radeon HD 4350",               DRIVER_AMD_R600,         256 },
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD4600,         "ATI Radeon HD 4600 Series",        DRIVER_AMD_R600,         512 },
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD4700,         "ATI Radeon HD 4700 Series",        DRIVER_AMD_R600,         512 },
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD4800,         "ATI Radeon HD 4800 Series",        DRIVER_AMD_R600,         512 },
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD5400,         "ATI Radeon HD 5400 Series",        DRIVER_AMD_R600,         512 },
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD5600,         "ATI Radeon HD 5600 Series",        DRIVER_AMD_R600,         512 },
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD5700,         "ATI Radeon HD 5700 Series",        DRIVER_AMD_R600,         512 },
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD5800,         "ATI Radeon HD 5800 Series",        DRIVER_AMD_R600,         1024},
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD5900,         "ATI Radeon HD 5900 Series",        DRIVER_AMD_R600,         1024},
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD6300,         "AMD Radeon HD 6300 series Graphics", DRIVER_AMD_R600,       1024},
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD6400,         "AMD Radeon HD 6400 Series",        DRIVER_AMD_R600,         1024},
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD6410D,        "AMD Radeon HD 6410D",              DRIVER_AMD_R600,         1024},
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD6550D,        "AMD Radeon HD 6550D",              DRIVER_AMD_R600,         1024},
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD6600,         "AMD Radeon HD 6600 Series",        DRIVER_AMD_R600,         1024},
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD6600M,        "AMD Radeon HD 6600M Series",       DRIVER_AMD_R600,         512 },
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD6700,         "AMD Radeon HD 6700 Series",        DRIVER_AMD_R600,         1024},
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD6800,         "AMD Radeon HD 6800 Series",        DRIVER_AMD_R600,         1024},
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD6900,         "AMD Radeon HD 6900 Series",        DRIVER_AMD_R600,         2048},
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD7700,         "AMD Radeon HD 7700 Series",        DRIVER_AMD_R600,         1024},
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD7800,         "AMD Radeon HD 7800 Series",        DRIVER_AMD_R600,         2048},
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD7900,         "AMD Radeon HD 7900 Series",        DRIVER_AMD_R600,         2048},
+    /* Intel cards */
+    {HW_VENDOR_INTEL,      CARD_INTEL_830M,                "Intel(R) 82830M Graphics Controller",                       DRIVER_INTEL_GMA800,  32 },
+    {HW_VENDOR_INTEL,      CARD_INTEL_855GM,               "Intel(R) 82852/82855 GM/GME Graphics Controller",           DRIVER_INTEL_GMA800,  32 },
+    {HW_VENDOR_INTEL,      CARD_INTEL_845G,                "Intel(R) 845G",                                             DRIVER_INTEL_GMA800,  32 },
+    {HW_VENDOR_INTEL,      CARD_INTEL_865G,                "Intel(R) 82865G Graphics Controller",                       DRIVER_INTEL_GMA800,  32 },
+    {HW_VENDOR_INTEL,      CARD_INTEL_915G,                "Intel(R) 82915G/GV/910GL Express Chipset Family",           DRIVER_INTEL_GMA900,  64 },
+    {HW_VENDOR_INTEL,      CARD_INTEL_E7221G,              "Intel(R) E7221G",                                           DRIVER_INTEL_GMA900,  64 },
+    {HW_VENDOR_INTEL,      CARD_INTEL_915GM,               "Mobile Intel(R) 915GM/GMS,910GML Express Chipset Family",   DRIVER_INTEL_GMA900,  64 },
+    {HW_VENDOR_INTEL,      CARD_INTEL_945G,                "Intel(R) 945G",                                             DRIVER_INTEL_GMA950,  64 },
+    {HW_VENDOR_INTEL,      CARD_INTEL_945GM,               "Mobile Intel(R) 945GM Express Chipset Family",              DRIVER_INTEL_GMA950,  64 },
+    {HW_VENDOR_INTEL,      CARD_INTEL_945GME,              "Intel(R) 945GME",                                           DRIVER_INTEL_GMA950,  64 },
+    {HW_VENDOR_INTEL,      CARD_INTEL_Q35,                 "Intel(R) Q35",                                              DRIVER_INTEL_GMA950,  64 },
+    {HW_VENDOR_INTEL,      CARD_INTEL_G33,                 "Intel(R) G33",                                              DRIVER_INTEL_GMA950,  64 },
+    {HW_VENDOR_INTEL,      CARD_INTEL_Q33,                 "Intel(R) Q33",                                              DRIVER_INTEL_GMA950,  64 },
+    {HW_VENDOR_INTEL,      CARD_INTEL_PNVG,                "Intel(R) IGD",                                              DRIVER_INTEL_GMA950,  64 },
+    {HW_VENDOR_INTEL,      CARD_INTEL_PNVM,                "Intel(R) IGD",                                              DRIVER_INTEL_GMA950,  64 },
+    {HW_VENDOR_INTEL,      CARD_INTEL_965Q,                "Intel(R) 965Q",                                             DRIVER_INTEL_GMA3000, 128},
+    {HW_VENDOR_INTEL,      CARD_INTEL_965G,                "Intel(R) 965G",                                             DRIVER_INTEL_GMA3000, 128},
+    {HW_VENDOR_INTEL,      CARD_INTEL_946GZ,               "Intel(R) 946GZ",                                            DRIVER_INTEL_GMA3000, 128},
+    {HW_VENDOR_INTEL,      CARD_INTEL_965GM,               "Mobile Intel(R) 965 Express Chipset Family",                DRIVER_INTEL_GMA3000, 128},
+    {HW_VENDOR_INTEL,      CARD_INTEL_965GME,              "Intel(R) 965GME",                                           DRIVER_INTEL_GMA3000, 128},
+    {HW_VENDOR_INTEL,      CARD_INTEL_GM45,                "Mobile Intel(R) GM45 Express Chipset Family",               DRIVER_INTEL_GMA3000, 512},
+    {HW_VENDOR_INTEL,      CARD_INTEL_IGD,                 "Intel(R) Integrated Graphics Device",                       DRIVER_INTEL_GMA3000, 512},
+    {HW_VENDOR_INTEL,      CARD_INTEL_G45,                 "Intel(R) G45/G43",                                          DRIVER_INTEL_GMA3000, 512},
+    {HW_VENDOR_INTEL,      CARD_INTEL_Q45,                 "Intel(R) Q45/Q43",                                          DRIVER_INTEL_GMA3000, 512},
+    {HW_VENDOR_INTEL,      CARD_INTEL_G41,                 "Intel(R) G41",                                              DRIVER_INTEL_GMA3000, 512},
+    {HW_VENDOR_INTEL,      CARD_INTEL_B43,                 "Intel(R) B43",                                              DRIVER_INTEL_GMA3000, 512},
+    {HW_VENDOR_INTEL,      CARD_INTEL_ILKD,                "Intel(R) Ironlake Desktop",                                 DRIVER_INTEL_GMA3000, 1024},
+    {HW_VENDOR_INTEL,      CARD_INTEL_ILKM,                "Intel(R) Ironlake Mobile",                                  DRIVER_INTEL_GMA3000, 1024},
+    {HW_VENDOR_INTEL,      CARD_INTEL_SNBD,                "Intel(R) Sandybridge Desktop",                              DRIVER_INTEL_GMA3000, 1024},
+    {HW_VENDOR_INTEL,      CARD_INTEL_SNBM,                "Intel(R) Sandybridge Mobile",                               DRIVER_INTEL_GMA3000, 1024},
+    {HW_VENDOR_INTEL,      CARD_INTEL_SNBS,                "Intel(R) Sandybridge Server",                               DRIVER_INTEL_GMA3000, 1024},
+    {HW_VENDOR_INTEL,      CARD_INTEL_IVBD,                "Intel(R) Ivybridge Desktop",                                DRIVER_INTEL_GMA3000, 1024},
+    {HW_VENDOR_INTEL,      CARD_INTEL_IVBM,                "Intel(R) Ivybridge Mobile",                                 DRIVER_INTEL_GMA3000, 1024},
+    {HW_VENDOR_INTEL,      CARD_INTEL_IVBS,                "Intel(R) Ivybridge Server",                                 DRIVER_INTEL_GMA3000, 1024},
+};
+
+static const struct driver_version_information *get_driver_version_info(enum wined3d_display_driver driver,
+        enum wined3d_driver_model driver_model)
+{
+    unsigned int i;
+
+    TRACE("Looking up version info for driver=%d driver_model=%d\n", driver, driver_model);
+    for (i = 0; i < (sizeof(driver_version_table) / sizeof(driver_version_table[0])); i++)
+    {
+        const struct driver_version_information *entry = &driver_version_table[i];
+
+        if (entry->driver == driver && entry->driver_model == driver_model)
+        {
+            TRACE("Found driver \"%s\", version %u, subversion %u, build %u.\n",
+                    entry->driver_name, entry->version, entry->subversion, entry->build);
+            return entry;
+        }
+    }
+    return NULL;
+}
+
+static void init_driver_info(struct wined3d_driver_info *driver_info,
+        enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
+{
+    OSVERSIONINFOW os_version;
+    WORD driver_os_version;
+    unsigned int i;
+    enum wined3d_display_driver driver = DRIVER_UNKNOWN;
+    enum wined3d_driver_model driver_model;
+    const struct driver_version_information *version_info;
+
+    if (wined3d_settings.pci_vendor_id != PCI_VENDOR_NONE)
+    {
+        TRACE("Overriding PCI vendor ID with 0x%04x.\n", wined3d_settings.pci_vendor_id);
+        vendor = wined3d_settings.pci_vendor_id;
+    }
+    driver_info->vendor = vendor;
+
+    if (wined3d_settings.pci_device_id != PCI_DEVICE_NONE)
+    {
+        TRACE("Overriding PCI device ID with 0x%04x.\n", wined3d_settings.pci_device_id);
+        device = wined3d_settings.pci_device_id;
+    }
+    driver_info->device = device;
+
+    /* Set a default amount of video memory (64MB). In general this code isn't used unless the user
+     * overrides the pci ids to a card which is not in our database. */
+    driver_info->vidmem = WINE_DEFAULT_VIDMEM;
+
+    memset(&os_version, 0, sizeof(os_version));
+    os_version.dwOSVersionInfoSize = sizeof(os_version);
+    if (!GetVersionExW(&os_version))
+    {
+        ERR("Failed to get OS version, reporting 2000/XP.\n");
+        driver_os_version = 6;
+        driver_model = DRIVER_MODEL_NT5X;
+    }
+    else
+    {
+        TRACE("OS version %u.%u.\n", os_version.dwMajorVersion, os_version.dwMinorVersion);
+        switch (os_version.dwMajorVersion)
+        {
+            case 4:
+                /* If needed we could distinguish between 9x and NT4, but this code won't make
+                 * sense for NT4 since it had no way to obtain this info through DirectDraw 3.0.
+                 */
+                driver_os_version = 4;
+                driver_model = DRIVER_MODEL_WIN9X;
+                break;
+
+            case 5:
+                driver_os_version = 6;
+                driver_model = DRIVER_MODEL_NT5X;
+                break;
+
+            case 6:
+                if (os_version.dwMinorVersion == 0)
+                {
+                    driver_os_version = 7;
+                    driver_model = DRIVER_MODEL_NT6X;
+                }
+                else if (os_version.dwMinorVersion == 1)
+                {
+                    driver_os_version = 8;
+                    driver_model = DRIVER_MODEL_NT6X;
+                }
+                else
+                {
+                    if (os_version.dwMinorVersion > 2)
+                    {
+                        FIXME("Unhandled OS version %u.%u, reporting Win 8.\n",
+                                os_version.dwMajorVersion, os_version.dwMinorVersion);
+                    }
+                    driver_os_version = 9;
+                    driver_model = DRIVER_MODEL_NT6X;
+                }
+                break;
+
+            default:
+                FIXME("Unhandled OS version %u.%u, reporting 2000/XP.\n",
+                        os_version.dwMajorVersion, os_version.dwMinorVersion);
+                driver_os_version = 6;
+                driver_model = DRIVER_MODEL_NT5X;
+                break;
+        }
+    }
+
+    /* When we reach this stage we always have a vendor or device id (it can be a default one).
+     * This means that unless the ids are overridden, we will always find a GPU description. */
+    for (i = 0; i < (sizeof(gpu_description_table) / sizeof(gpu_description_table[0])); i++)
+    {
+        if (vendor == gpu_description_table[i].vendor && device == gpu_description_table[i].card)
+        {
+            TRACE("Found card %04x:%04x in driver DB.\n", vendor, device);
+
+            driver_info->description = gpu_description_table[i].description;
+            driver_info->vidmem = gpu_description_table[i].vidmem * 1024*1024;
+            driver = gpu_description_table[i].driver;
+            break;
+        }
+    }
+
+    if (wined3d_settings.emulated_textureram)
+    {
+        TRACE("Overriding amount of video memory with %u bytes.\n", wined3d_settings.emulated_textureram);
+        driver_info->vidmem = wined3d_settings.emulated_textureram;
+    }
+
+    /* Try to obtain driver version information for the current Windows version. This fails in
+     * some cases:
+     * - the gpu is not available on the currently selected OS version:
+     *   - Geforce GTX480 on Win98. When running applications in compatibility mode on Windows,
+     *     version information for the current Windows version is returned instead of faked info.
+     *     We do the same and assume the default Windows version to emulate is WinXP.
+     *
+     *   - Videocard is a Riva TNT but winver is set to win7 (there are no drivers for this beast)
+     *     For now return the XP driver info. Perhaps later on we should return VESA.
+     *
+     * - the gpu is not in our database (can happen when the user overrides the vendor_id / device_id)
+     *   This could be an indication that our database is not up to date, so this should be fixed.
+     */
+    version_info = get_driver_version_info(driver, driver_model);
+    if (version_info)
+    {
+        driver_info->name = version_info->driver_name;
+        driver_info->version_high = MAKEDWORD_VERSION(driver_os_version, version_info->version);
+        driver_info->version_low = MAKEDWORD_VERSION(version_info->subversion, version_info->build);
+    }
+    else
+    {
+        version_info = get_driver_version_info(driver, DRIVER_MODEL_NT5X);
+        if (version_info)
+        {
+            driver_info->name = version_info->driver_name;
+            driver_info->version_high = MAKEDWORD_VERSION(driver_os_version, version_info->version);
+            driver_info->version_low = MAKEDWORD_VERSION(version_info->subversion, version_info->build);
+        }
+        else
+        {
+            driver_info->description = "Direct3D HAL";
+            driver_info->name = "Display";
+            driver_info->version_high = MAKEDWORD_VERSION(driver_os_version, 15);
+            driver_info->version_low = MAKEDWORD_VERSION(8, 6); /* Nvidia RIVA TNT, arbitrary */
+
+            FIXME("Unable to find a driver/device info for vendor_id=%#x device_id=%#x for driver_model=%d\n",
+                    vendor, device, driver_model);
+        }
+    }
+
+    TRACE("Reporting (fake) driver version 0x%08x-0x%08x.\n",
+            driver_info->version_high, driver_info->version_low);
+}
+
+/* Context activation is done by the caller. */
+static void fixup_extensions(struct wined3d_gl_info *gl_info, const char *gl_renderer,
+        enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
+{
+    unsigned int i;
+
+    for (i = 0; i < (sizeof(quirk_table) / sizeof(*quirk_table)); ++i)
+    {
+        if (!quirk_table[i].match(gl_info, gl_renderer, gl_vendor, card_vendor, device)) continue;
+        TRACE("Applying driver quirk \"%s\".\n", quirk_table[i].description);
+        quirk_table[i].apply(gl_info);
+    }
+
+    /* Find out if PBOs work as they are supposed to. */
+    test_pbo_functionality(gl_info);
+}
+
+static DWORD wined3d_parse_gl_version(const char *gl_version)
+{
+    const char *ptr = gl_version;
+    int major, minor;
+
+    major = atoi(ptr);
+    if (major <= 0)
+        ERR("Invalid OpenGL major version %d.\n", major);
+
+    while (isdigit(*ptr)) ++ptr;
+    if (*ptr++ != '.')
+        ERR("Invalid OpenGL version string %s.\n", debugstr_a(gl_version));
+
+    minor = atoi(ptr);
+
+    TRACE("Found OpenGL version %d.%d.\n", major, minor);
+
+    return MAKEDWORD_VERSION(major, minor);
+}
+
+static enum wined3d_gl_vendor wined3d_guess_gl_vendor(const struct wined3d_gl_info *gl_info,
+        const char *gl_vendor_string, const char *gl_renderer)
+{
+
+    /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
+     * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
+     * detect the Apple OpenGL implementation to apply some extension fixups afterwards.
+     *
+     * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks
+     * aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
+     * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
+     * like client storage might be supported on other implementations too, but GL_APPLE_flush_render
+     * is specific to the Mac OS X window management, and GL_APPLE_ycbcr_422 is QuickTime specific. So
+     * the chance that other implementations support them is rather small since Win32 QuickTime uses
+     * DirectDraw, not OpenGL. */
+    if (gl_info->supported[APPLE_FENCE]
+            && gl_info->supported[APPLE_CLIENT_STORAGE]
+            && gl_info->supported[APPLE_YCBCR_422])
+        return GL_VENDOR_APPLE;
+
+    if (strstr(gl_vendor_string, "NVIDIA"))
+        return GL_VENDOR_NVIDIA;
+
+    if (strstr(gl_vendor_string, "ATI"))
+        return GL_VENDOR_FGLRX;
+
+    if (strstr(gl_vendor_string, "Intel(R)")
+            /* Intel switched from Intel(R) to Intel® recently, so just match Intel. */
+            || strstr(gl_renderer, "Intel")
+            || strstr(gl_vendor_string, "Intel Inc."))
+    {
+#if 0//def VBOX_WITH_WINE_FIX_QUIRKS /* check if we still need this: device detection was improved significantly with wine */
+        if (strstr(gl_renderer, "Mesa"))
+            return GL_VENDOR_MESA;
+#endif
+        return GL_VENDOR_INTEL;
+    }
+
+    if (strstr(gl_vendor_string, "Mesa")
+            || strstr(gl_vendor_string, "X.Org")
+            || strstr(gl_vendor_string, "Advanced Micro Devices, Inc.")
+            || strstr(gl_vendor_string, "DRI R300 Project")
+            || strstr(gl_vendor_string, "Tungsten Graphics, Inc")
+            || strstr(gl_vendor_string, "VMware, Inc.")
+            || strstr(gl_renderer, "Mesa")
+            || strstr(gl_renderer, "Gallium"))
+        return GL_VENDOR_MESA;
+
+    FIXME("Received unrecognized GL_VENDOR %s. Returning GL_VENDOR_UNKNOWN.\n",
+            debugstr_a(gl_vendor_string));
+
+    return GL_VENDOR_UNKNOWN;
+}
+
+static enum wined3d_pci_vendor wined3d_guess_card_vendor(const char *gl_vendor_string, const char *gl_renderer)
+{
+    if (strstr(gl_vendor_string, "NVIDIA")
+            || strstr(gl_vendor_string, "Nouveau")
+            || strstr(gl_vendor_string, "nouveau"))
+        return HW_VENDOR_NVIDIA;
+
+    if (strstr(gl_vendor_string, "ATI")
+            || strstr(gl_vendor_string, "Advanced Micro Devices, Inc.")
+            || strstr(gl_vendor_string, "X.Org R300 Project")
+            || strstr(gl_renderer, "AMD")
+            || strstr(gl_renderer, "R100")
+            || strstr(gl_renderer, "R200")
+            || strstr(gl_renderer, "R300")
+            || strstr(gl_renderer, "R600")
+            || strstr(gl_renderer, "R700"))
+        return HW_VENDOR_AMD;
+
+    if (strstr(gl_vendor_string, "Intel(R)")
+            /* Intel switched from Intel(R) to Intel® recently, so just match Intel. */
+            || strstr(gl_renderer, "Intel")
+            || strstr(gl_renderer, "i915")
+            || strstr(gl_vendor_string, "Intel Inc."))
+        return HW_VENDOR_INTEL;
+
+    if (strstr(gl_vendor_string, "Mesa")
+            || strstr(gl_vendor_string, "Brian Paul")
+            || strstr(gl_vendor_string, "Tungsten Graphics, Inc")
+            || strstr(gl_vendor_string, "VMware, Inc."))
+        return HW_VENDOR_SOFTWARE;
+
+    FIXME("Received unrecognized GL_VENDOR %s. Returning HW_VENDOR_NVIDIA.\n", debugstr_a(gl_vendor_string));
+
+    return HW_VENDOR_NVIDIA;
+}
+
+static UINT d3d_level_from_gl_info(const struct wined3d_gl_info *gl_info)
+{
+    UINT level = 0;
+
+    if (gl_info->supported[ARB_MULTITEXTURE])
+        level = 6;
+    if (gl_info->supported[ARB_TEXTURE_COMPRESSION]
+            && gl_info->supported[ARB_TEXTURE_CUBE_MAP]
+            && gl_info->supported[ARB_TEXTURE_ENV_DOT3])
+        level = 7;
+    if (level == 7 && gl_info->supported[ARB_MULTISAMPLE]
+            && gl_info->supported[ARB_TEXTURE_BORDER_CLAMP])
+        level = 8;
+    if (level == 8 && gl_info->supported[ARB_FRAGMENT_PROGRAM]
+            && gl_info->supported[ARB_VERTEX_SHADER])
+        level = 9;
+    if (level == 9 && gl_info->supported[EXT_GPU_SHADER4])
+        level = 10;
+
+    return level;
+}
+
+static enum wined3d_pci_device select_card_nvidia_binary(const struct wined3d_gl_info *gl_info,
+        const char *gl_renderer)
+{
+    UINT d3d_level = d3d_level_from_gl_info(gl_info);
+    unsigned int i;
+
+#ifndef VBOX_WITH_WDDM
+    if (d3d_level >= 10)
+#endif
+    {
+        static const struct
+        {
+            const char *renderer;
+            enum wined3d_pci_device id;
+        }
+        cards[] =
+        {
+            {"GTX 680",     CARD_NVIDIA_GEFORCE_GTX680},    /* Geforce 600 - highend */
+            {"GTX 670",     CARD_NVIDIA_GEFORCE_GTX670},    /* Geforce 600 - midend high */
+            {"GTX 660 Ti",  CARD_NVIDIA_GEFORCE_GTX660TI},  /* Geforce 600 - midend high */
+            {"GTX 660",     CARD_NVIDIA_GEFORCE_GTX660},    /* Geforce 600 - midend high */
+            {"GTX 650 Ti",  CARD_NVIDIA_GEFORCE_GTX650TI},  /* Geforce 600 - lowend */
+            {"GTX 650",     CARD_NVIDIA_GEFORCE_GTX650},    /* Geforce 600 - lowend */
+            {"GT 650M",     CARD_NVIDIA_GEFORCE_GT650M},    /* Geforce 600 - midend mobile */
+            {"GT 640M",     CARD_NVIDIA_GEFORCE_GT640M},    /* Geforce 600 - midend mobile */
+            {"GT 630M",     CARD_NVIDIA_GEFORCE_GT630M},    /* Geforce 600 - midend mobile */
+            {"GT 630",      CARD_NVIDIA_GEFORCE_GT630},     /* Geforce 600 - lowend */
+            {"GT 610",      CARD_NVIDIA_GEFORCE_GT610},     /* Geforce 600 - lowend */
+            {"GTX 580",     CARD_NVIDIA_GEFORCE_GTX580},    /* Geforce 500 - highend */
+            {"GTX 570",     CARD_NVIDIA_GEFORCE_GTX570},    /* Geforce 500 - midend high */
+            {"GTX 560 Ti",  CARD_NVIDIA_GEFORCE_GTX560TI},  /* Geforce 500 - midend */
+            {"GTX 560",     CARD_NVIDIA_GEFORCE_GTX560},    /* Geforce 500 - midend */
+            {"GT 555M",     CARD_NVIDIA_GEFORCE_GT555M},    /* Geforce 500 - midend mobile */
+            {"GTX 550 Ti",  CARD_NVIDIA_GEFORCE_GTX550},    /* Geforce 500 - midend */
+            {"GT 540M",     CARD_NVIDIA_GEFORCE_GT540M},    /* Geforce 500 - midend mobile */
+            {"GT 520",      CARD_NVIDIA_GEFORCE_GT520},     /* Geforce 500 - lowend */
+            {"GTX 480",     CARD_NVIDIA_GEFORCE_GTX480},    /* Geforce 400 - highend */
+            {"GTX 470",     CARD_NVIDIA_GEFORCE_GTX470},    /* Geforce 400 - midend high */
+            {"GTX 465",     CARD_NVIDIA_GEFORCE_GTX465},    /* Geforce 400 - midend */
+            {"GTX 460M",    CARD_NVIDIA_GEFORCE_GTX460M},   /* Geforce 400 - highend mobile */
+            {"GTX 460",     CARD_NVIDIA_GEFORCE_GTX460},    /* Geforce 400 - midend */
+            {"GTS 450",     CARD_NVIDIA_GEFORCE_GTS450},    /* Geforce 400 - midend low */
+            {"GT 440",      CARD_NVIDIA_GEFORCE_GT440},     /* Geforce 400 - lowend */
+            {"GT 430",      CARD_NVIDIA_GEFORCE_GT430},     /* Geforce 400 - lowend */
+            {"GT 420",      CARD_NVIDIA_GEFORCE_GT420},     /* Geforce 400 - lowend */
+            {"410M",        CARD_NVIDIA_GEFORCE_410M},      /* Geforce 400 - lowend mobile */
+            {"GT 330",      CARD_NVIDIA_GEFORCE_GT330},     /* Geforce 300 - highend */
+            {"GTS 360M",    CARD_NVIDIA_GEFORCE_GTS350M},   /* Geforce 300 - highend mobile */
+            {"GTS 350M",    CARD_NVIDIA_GEFORCE_GTS350M},   /* Geforce 300 - highend mobile */
+            {"GT 330M",     CARD_NVIDIA_GEFORCE_GT325M},    /* Geforce 300 - midend mobile */
+            {"GT 325M",     CARD_NVIDIA_GEFORCE_GT325M},    /* Geforce 300 - midend mobile */
+            {"GT 320M",     CARD_NVIDIA_GEFORCE_GT320M},    /* Geforce 300 - midend mobile */
+            {"320M",        CARD_NVIDIA_GEFORCE_320M},      /* Geforce 300 - midend mobile */
+            {"315M",        CARD_NVIDIA_GEFORCE_315M},      /* Geforce 300 - midend mobile */
+            {"GTX 295",     CARD_NVIDIA_GEFORCE_GTX280},    /* Geforce 200 - highend */
+            {"GTX 285",     CARD_NVIDIA_GEFORCE_GTX280},    /* Geforce 200 - highend */
+            {"GTX 280",     CARD_NVIDIA_GEFORCE_GTX280},    /* Geforce 200 - highend */
+            {"GTX 275",     CARD_NVIDIA_GEFORCE_GTX275},    /* Geforce 200 - midend high */
+            {"GTX 260",     CARD_NVIDIA_GEFORCE_GTX260},    /* Geforce 200 - midend */
+            {"GT 240",      CARD_NVIDIA_GEFORCE_GT240},     /* Geforce 200 - midend */
+            {"GT 220",      CARD_NVIDIA_GEFORCE_GT220},     /* Geforce 200 - lowend */
+            {"Geforce 310", CARD_NVIDIA_GEFORCE_210},       /* Geforce 200 - lowend */
+            {"Geforce 305", CARD_NVIDIA_GEFORCE_210},       /* Geforce 200 - lowend */
+            {"Geforce 210", CARD_NVIDIA_GEFORCE_210},       /* Geforce 200 - lowend */
+            {"G 210",       CARD_NVIDIA_GEFORCE_210},       /* Geforce 200 - lowend */
+            {"GTS 250",     CARD_NVIDIA_GEFORCE_9800GT},    /* Geforce 9 - highend / Geforce 200 - midend */
+            {"GTS 150",     CARD_NVIDIA_GEFORCE_9800GT},    /* Geforce 9 - highend / Geforce 200 - midend */
+            {"9800",        CARD_NVIDIA_GEFORCE_9800GT},    /* Geforce 9 - highend / Geforce 200 - midend */
+            {"GT 140",      CARD_NVIDIA_GEFORCE_9600GT},    /* Geforce 9 - midend */
+            {"9600",        CARD_NVIDIA_GEFORCE_9600GT},    /* Geforce 9 - midend */
+            {"GT 130",      CARD_NVIDIA_GEFORCE_9500GT},    /* Geforce 9 - midend low / Geforce 200 - low */
+            {"GT 120",      CARD_NVIDIA_GEFORCE_9500GT},    /* Geforce 9 - midend low / Geforce 200 - low */
+            {"9500",        CARD_NVIDIA_GEFORCE_9500GT},    /* Geforce 9 - midend low / Geforce 200 - low */
+            {"9400M",       CARD_NVIDIA_GEFORCE_9400M},     /* Geforce 9 - lowend */
+            {"9400",        CARD_NVIDIA_GEFORCE_9400GT},    /* Geforce 9 - lowend */
+            {"9300",        CARD_NVIDIA_GEFORCE_9300},      /* Geforce 9 - lowend low */
+            {"9200",        CARD_NVIDIA_GEFORCE_9200},      /* Geforce 9 - lowend low */
+            {"9100",        CARD_NVIDIA_GEFORCE_9200},      /* Geforce 9 - lowend low */
+            {"G 100",       CARD_NVIDIA_GEFORCE_9200},      /* Geforce 9 - lowend low */
+            {"8800 GTX",    CARD_NVIDIA_GEFORCE_8800GTX},   /* Geforce 8 - highend high */
+            {"8800",        CARD_NVIDIA_GEFORCE_8800GTS},   /* Geforce 8 - highend */
+            {"8600M",       CARD_NVIDIA_GEFORCE_8600MGT},   /* Geforce 8 - midend mobile */
+            {"8600 M",      CARD_NVIDIA_GEFORCE_8600MGT},   /* Geforce 8 - midend mobile */
+            {"8700",        CARD_NVIDIA_GEFORCE_8600GT},    /* Geforce 8 - midend */
+            {"8600",        CARD_NVIDIA_GEFORCE_8600GT},    /* Geforce 8 - midend */
+            {"8500",        CARD_NVIDIA_GEFORCE_8400GS},    /* Geforce 8 - mid-lowend */
+            {"8400",        CARD_NVIDIA_GEFORCE_8400GS},    /* Geforce 8 - mid-lowend */
+            {"8300",        CARD_NVIDIA_GEFORCE_8300GS},    /* Geforce 8 - lowend */
+            {"8200",        CARD_NVIDIA_GEFORCE_8300GS},    /* Geforce 8 - lowend */
+            {"8100",        CARD_NVIDIA_GEFORCE_8300GS},    /* Geforce 8 - lowend */
+        };
+
+        for (i = 0; i < sizeof(cards) / sizeof(*cards); ++i)
+        {
+            if (strstr(gl_renderer, cards[i].renderer))
+                return cards[i].id;
+        }
+
+        return PCI_DEVICE_NONE;
+    }
+
+    /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
+     * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
+     */
+    if (d3d_level >= 9 && gl_info->supported[NV_VERTEX_PROGRAM3])
+    {
+        static const struct
+        {
+            const char *renderer;
+            enum wined3d_pci_device id;
+        }
+        cards[] =
+        {
+            {"Quadro FX 5", CARD_NVIDIA_GEFORCE_7800GT},    /* Geforce 7 - highend */
+            {"Quadro FX 4", CARD_NVIDIA_GEFORCE_7800GT},    /* Geforce 7 - highend */
+            {"7950",        CARD_NVIDIA_GEFORCE_7800GT},    /* Geforce 7 - highend */
+            {"7900",        CARD_NVIDIA_GEFORCE_7800GT},    /* Geforce 7 - highend */
+            {"7800",        CARD_NVIDIA_GEFORCE_7800GT},    /* Geforce 7 - highend */
+            {"7700",        CARD_NVIDIA_GEFORCE_7600},      /* Geforce 7 - midend */
+            {"7600",        CARD_NVIDIA_GEFORCE_7600},      /* Geforce 7 - midend */
+            {"7400",        CARD_NVIDIA_GEFORCE_7400},      /* Geforce 7 - lower medium */
+            {"7300",        CARD_NVIDIA_GEFORCE_7300},      /* Geforce 7 - lowend */
+            {"6800",        CARD_NVIDIA_GEFORCE_6800},      /* Geforce 6 - highend */
+            {"6700",        CARD_NVIDIA_GEFORCE_6600GT},    /* Geforce 6 - midend */
+            {"6610",        CARD_NVIDIA_GEFORCE_6600GT},    /* Geforce 6 - midend */
+            {"6600",        CARD_NVIDIA_GEFORCE_6600GT},    /* Geforce 6 - midend */
+        };
+
+        for (i = 0; i < sizeof(cards) / sizeof(*cards); ++i)
+        {
+            if (strstr(gl_renderer, cards[i].renderer))
+                return cards[i].id;
+        }
+
+        return PCI_DEVICE_NONE;
+    }
+
+    if (d3d_level >= 9)
+    {
+        /* GeforceFX - highend */
+        if (strstr(gl_renderer, "5800")
+                || strstr(gl_renderer, "5900")
+                || strstr(gl_renderer, "5950")
+                || strstr(gl_renderer, "Quadro FX"))
+        {
+            return CARD_NVIDIA_GEFORCEFX_5800;
+        }
+
+        /* GeforceFX - midend */
+        if (strstr(gl_renderer, "5600")
+                || strstr(gl_renderer, "5650")
+                || strstr(gl_renderer, "5700")
+                || strstr(gl_renderer, "5750"))
+        {
+            return CARD_NVIDIA_GEFORCEFX_5600;
+        }
+
+        /* GeforceFX - lowend */
+        return CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
+    }
+
+    if (d3d_level >= 8)
+    {
+        if (strstr(gl_renderer, "GeForce4 Ti") || strstr(gl_renderer, "Quadro4"))
+        {
+            return CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
+        }
+
+        return CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
+    }
+
+    if (d3d_level >= 7)
+    {
+        if (strstr(gl_renderer, "GeForce4 MX"))
+        {
+            return CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
+        }
+
+        if (strstr(gl_renderer, "GeForce2 MX") || strstr(gl_renderer, "Quadro2 MXR"))
+        {
+            return CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
+        }
+
+        if (strstr(gl_renderer, "GeForce2") || strstr(gl_renderer, "Quadro2"))
+        {
+            return CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
+        }
+
+        return CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
+    }
+
+    if (strstr(gl_renderer, "TNT2"))
+    {
+        return CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
+    }
+
+    return CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
+}
+
+static enum wined3d_pci_device select_card_amd_binary(const struct wined3d_gl_info *gl_info,
+        const char *gl_renderer)
+{
+    UINT d3d_level = d3d_level_from_gl_info(gl_info);
+
+    /* See http://developer.amd.com/drivers/pc_vendor_id/Pages/default.aspx
+     *
+     * Beware: renderer string do not match exact card model,
+     * eg HD 4800 is returned for multiple cards, even for RV790 based ones. */
+#ifndef VBOX_WITH_WDDM
+    if (d3d_level >= 10)
+#endif
+    {
+        unsigned int i;
+
+        static const struct
+        {
+            const char *renderer;
+            enum wined3d_pci_device id;
+        }
+        cards[] =
+        {
+            /* Southern Islands */
+            {"HD 7900", CARD_AMD_RADEON_HD7900},
+            {"HD 7800", CARD_AMD_RADEON_HD7800},
+            {"HD 7700", CARD_AMD_RADEON_HD7700},
+            /* Northern Islands */
+            {"HD 6970", CARD_AMD_RADEON_HD6900},
+            {"HD 6900", CARD_AMD_RADEON_HD6900},
+            {"HD 6800", CARD_AMD_RADEON_HD6800},
+            {"HD 6770M",CARD_AMD_RADEON_HD6600M},
+            {"HD 6750M",CARD_AMD_RADEON_HD6600M},
+            {"HD 6700", CARD_AMD_RADEON_HD6700},
+            {"HD 6670", CARD_AMD_RADEON_HD6600},
+            {"HD 6630M",CARD_AMD_RADEON_HD6600M},
+            {"HD 6600M",CARD_AMD_RADEON_HD6600M},
+            {"HD 6600", CARD_AMD_RADEON_HD6600},
+            {"HD 6570", CARD_AMD_RADEON_HD6600},
+            {"HD 6500M",CARD_AMD_RADEON_HD6600M},
+            {"HD 6500", CARD_AMD_RADEON_HD6600},
+            {"HD 6400", CARD_AMD_RADEON_HD6400},
+            {"HD 6300", CARD_AMD_RADEON_HD6300},
+            {"HD 6200", CARD_AMD_RADEON_HD6300},
+            /* Evergreen */
+            {"HD 5870", CARD_AMD_RADEON_HD5800},    /* Radeon EG CYPRESS PRO */
+            {"HD 5850", CARD_AMD_RADEON_HD5800},    /* Radeon EG CYPRESS XT */
+            {"HD 5800", CARD_AMD_RADEON_HD5800},    /* Radeon EG CYPRESS HD58xx generic renderer string */
+            {"HD 5770", CARD_AMD_RADEON_HD5700},    /* Radeon EG JUNIPER XT */
+            {"HD 5750", CARD_AMD_RADEON_HD5700},    /* Radeon EG JUNIPER LE */
+            {"HD 5700", CARD_AMD_RADEON_HD5700},    /* Radeon EG JUNIPER HD57xx generic renderer string */
+            {"HD 5670", CARD_AMD_RADEON_HD5600},    /* Radeon EG REDWOOD XT */
+            {"HD 5570", CARD_AMD_RADEON_HD5600},    /* Radeon EG REDWOOD PRO mapped to HD5600 series */
+            {"HD 5550", CARD_AMD_RADEON_HD5600},    /* Radeon EG REDWOOD LE mapped to HD5600 series */
+            {"HD 5450", CARD_AMD_RADEON_HD5400},    /* Radeon EG CEDAR PRO */
+            {"HD 5000", CARD_AMD_RADEON_HD5600},    /* Defaulting to HD 5600 */
+            /* R700 */
+            {"HD 4890", CARD_AMD_RADEON_HD4800},    /* Radeon RV790 */
+            {"HD 4870", CARD_AMD_RADEON_HD4800},    /* Radeon RV770 */
+            {"HD 4850", CARD_AMD_RADEON_HD4800},    /* Radeon RV770 */
+            {"HD 4830", CARD_AMD_RADEON_HD4800},    /* Radeon RV770 */
+            {"HD 4800", CARD_AMD_RADEON_HD4800},    /* Radeon RV7xx HD48xx generic renderer string */
+            {"HD 4770", CARD_AMD_RADEON_HD4700},    /* Radeon RV740 */
+            {"HD 4700", CARD_AMD_RADEON_HD4700},    /* Radeon RV7xx HD47xx generic renderer string */
+            {"HD 4670", CARD_AMD_RADEON_HD4600},    /* Radeon RV730 */
+            {"HD 4650", CARD_AMD_RADEON_HD4600},    /* Radeon RV730 */
+            {"HD 4600", CARD_AMD_RADEON_HD4600},    /* Radeon RV730 */
+            {"HD 4550", CARD_AMD_RADEON_HD4350},    /* Radeon RV710 */
+            {"HD 4350", CARD_AMD_RADEON_HD4350},    /* Radeon RV710 */
+            /* R600/R700 integrated */
+            {"HD 4200M", CARD_AMD_RADEON_HD4200M},
+            {"HD 3300", CARD_AMD_RADEON_HD3200},
+            {"HD 3200", CARD_AMD_RADEON_HD3200},
+            {"HD 3100", CARD_AMD_RADEON_HD3200},
+            /* R600 */
+            {"HD 3870", CARD_AMD_RADEON_HD2900},    /* HD2900/HD3800 - highend */
+            {"HD 3850", CARD_AMD_RADEON_HD2900},    /* HD2900/HD3800 - highend */
+            {"HD 2900", CARD_AMD_RADEON_HD2900},    /* HD2900/HD3800 - highend */
+            {"HD 3830", CARD_AMD_RADEON_HD2600},    /* China-only midend */
+            {"HD 3690", CARD_AMD_RADEON_HD2600},    /* HD2600/HD3600 - midend */
+            {"HD 3650", CARD_AMD_RADEON_HD2600},    /* HD2600/HD3600 - midend */
+            {"HD 2600", CARD_AMD_RADEON_HD2600},    /* HD2600/HD3600 - midend */
+            {"HD 3470", CARD_AMD_RADEON_HD2350},    /* HD2350/HD2400/HD3400 - lowend */
+            {"HD 3450", CARD_AMD_RADEON_HD2350},    /* HD2350/HD2400/HD3400 - lowend */
+            {"HD 3430", CARD_AMD_RADEON_HD2350},    /* HD2350/HD2400/HD3400 - lowend */
+            {"HD 3400", CARD_AMD_RADEON_HD2350},    /* HD2350/HD2400/HD3400 - lowend */
+            {"HD 2400", CARD_AMD_RADEON_HD2350},    /* HD2350/HD2400/HD3400 - lowend */
+            {"HD 2350", CARD_AMD_RADEON_HD2350},    /* HD2350/HD2400/HD3400 - lowend */
+        };
+
+        for (i = 0; i < sizeof(cards) / sizeof(*cards); ++i)
+        {
+            if (strstr(gl_renderer, cards[i].renderer))
+                return cards[i].id;
+        }
+
+        return PCI_DEVICE_NONE;
+    }
+
+    if (d3d_level >= 9)
+    {
+        /* Radeon R5xx */
+        if (strstr(gl_renderer, "X1600")
+                || strstr(gl_renderer, "X1650")
+                || strstr(gl_renderer, "X1800")
+                || strstr(gl_renderer, "X1900")
+                || strstr(gl_renderer, "X1950"))
+        {
+            return CARD_AMD_RADEON_X1600;
+        }
+
+        /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300/X2500/HD2300 (lowend R5xx)
+         * Note X2300/X2500/HD2300 are R5xx GPUs with a 2xxx naming but they are still DX9-only */
+        if (strstr(gl_renderer, "X700")
+                || strstr(gl_renderer, "X800")
+                || strstr(gl_renderer, "X850")
+                || strstr(gl_renderer, "X1300")
+                || strstr(gl_renderer, "X1400")
+                || strstr(gl_renderer, "X1450")
+                || strstr(gl_renderer, "X1550")
+                || strstr(gl_renderer, "X2300")
+                || strstr(gl_renderer, "X2500")
+                || strstr(gl_renderer, "HD 2300")
+                )
+        {
+            return CARD_AMD_RADEON_X700;
+        }
+
+        /* Radeon Xpress Series - onboard, DX9b, Shader 2.0, 300-400MHz */
+        if (strstr(gl_renderer, "Radeon Xpress"))
+        {
+            return CARD_AMD_RADEON_XPRESS_200M;
+        }
+    }
+
+    return PCI_DEVICE_NONE;
+}
+
+static enum wined3d_pci_device select_card_intel(const struct wined3d_gl_info *gl_info,
+        const char *gl_renderer)
+{
+    unsigned int i;
+
+    static const struct
+    {
+        const char *renderer;
+        enum wined3d_pci_device id;
+    }
+    cards[] =
+    {
+        /* Ivybridge */
+        {"Ivybridge Server",            CARD_INTEL_IVBS},
+        {"Ivybridge Mobile",            CARD_INTEL_IVBM},
+        {"Ivybridge Desktop",           CARD_INTEL_IVBD},
+        /* Sandybridge */
+        {"Sandybridge Server",          CARD_INTEL_SNBS},
+        {"Sandybridge Mobile",          CARD_INTEL_SNBM},
+        {"Sandybridge Desktop",         CARD_INTEL_SNBD},
+        /* Ironlake */
+        {"Ironlake Mobile",             CARD_INTEL_ILKM},
+        {"Ironlake Desktop",            CARD_INTEL_ILKD},
+        /* G4x */
+        {"B43",                         CARD_INTEL_B43},
+        {"G41",                         CARD_INTEL_G41},
+        {"G45",                         CARD_INTEL_G45},
+        {"Q45",                         CARD_INTEL_Q45},
+        {"Integrated Graphics Device",  CARD_INTEL_IGD},
+        {"GM45",                        CARD_INTEL_GM45},
+        /* i965 */
+        {"965GME",                      CARD_INTEL_965GME},
+        {"965GM",                       CARD_INTEL_965GM},
+        {"X3100",                       CARD_INTEL_965GM},  /* MacOS */
+        {"946GZ",                       CARD_INTEL_946GZ},
+        {"965G",                        CARD_INTEL_965G},
+        {"965Q",                        CARD_INTEL_965Q},
+        /* i945 */
+        {"Pineview M",                  CARD_INTEL_PNVM},
+        {"Pineview G",                  CARD_INTEL_PNVG},
+        {"IGD",                         CARD_INTEL_PNVG},
+        {"Q33",                         CARD_INTEL_Q33},
+        {"G33",                         CARD_INTEL_G33},
+        {"Q35",                         CARD_INTEL_Q35},
+        {"945GME",                      CARD_INTEL_945GME},
+        {"945GM",                       CARD_INTEL_945GM},
+        {"GMA 950",                     CARD_INTEL_945GM},  /* MacOS */
+        {"945G",                        CARD_INTEL_945G},
+        /* i915 */
+        {"915GM",                       CARD_INTEL_915GM},
+        {"E7221G",                      CARD_INTEL_E7221G},
+        {"915G",                        CARD_INTEL_915G},
+        /* i8xx */
+        {"865G",                        CARD_INTEL_865G},
+        {"845G",                        CARD_INTEL_845G},
+        {"855GM",                       CARD_INTEL_855GM},
+        {"830M",                        CARD_INTEL_830M},
+#ifdef VBOX_WITH_WINE_FIX_QUIRKS
+        {"HD Graphics",                 CARD_INTEL_SNBM},
+#endif
+    };
+
+    for (i = 0; i < sizeof(cards) / sizeof(*cards); ++i)
+    {
+        if (strstr(gl_renderer, cards[i].renderer))
+            return cards[i].id;
+    }
+
+    return PCI_DEVICE_NONE;
+}
+
+static enum wined3d_pci_device select_card_amd_mesa(const struct wined3d_gl_info *gl_info,
+        const char *gl_renderer)
+{
+    unsigned int i;
+
+    /* 20101109 - These are never returned by current Gallium radeon
+     * drivers: R700, RV790, R680, RV535, RV516, R410, RS485, RV360, RV351.
+     *
+     * These are returned but not handled: RC410, RV380. */
+    static const struct
+    {
+        const char *renderer;
+        enum wined3d_pci_device id;
+    }
+    cards[] =
+    {
+        /* Southern Islands */
+        {"TAHITI",     CARD_AMD_RADEON_HD7900},
+        {"PITCAIRN",   CARD_AMD_RADEON_HD7800},
+        {"CAPE VERDE", CARD_AMD_RADEON_HD7700},
+        /* Northern Islands */
+        {"CAYMAN",  CARD_AMD_RADEON_HD6900},
+        {"BARTS",   CARD_AMD_RADEON_HD6800},
+        {"TURKS",   CARD_AMD_RADEON_HD6600},
+        {"SUMO2",   CARD_AMD_RADEON_HD6410D},   /* SUMO2 first, because we do a strstr(). */
+        {"SUMO",    CARD_AMD_RADEON_HD6550D},
+        {"CAICOS",  CARD_AMD_RADEON_HD6400},
+        {"PALM",    CARD_AMD_RADEON_HD6300},
+        /* Evergreen */
+        {"HEMLOCK", CARD_AMD_RADEON_HD5900},
+        {"CYPRESS", CARD_AMD_RADEON_HD5800},
+        {"JUNIPER", CARD_AMD_RADEON_HD5700},
+        {"REDWOOD", CARD_AMD_RADEON_HD5600},
+        {"CEDAR",   CARD_AMD_RADEON_HD5400},
+        /* R700 */
+        {"R700",        CARD_AMD_RADEON_HD4800},
+        {"RV790",   CARD_AMD_RADEON_HD4800},
+        {"RV770",   CARD_AMD_RADEON_HD4800},
+        {"RV740",       CARD_AMD_RADEON_HD4700},
+        {"RV730",       CARD_AMD_RADEON_HD4600},
+        {"RV710",       CARD_AMD_RADEON_HD4350},
+        /* R600/R700 integrated */
+        {"RS880",       CARD_AMD_RADEON_HD4200M},
+        {"RS780",   CARD_AMD_RADEON_HD3200},
+        /* R600 */
+        {"R680",        CARD_AMD_RADEON_HD2900},
+        {"R600",    CARD_AMD_RADEON_HD2900},
+        {"RV670",   CARD_AMD_RADEON_HD2900},
+        {"RV635",       CARD_AMD_RADEON_HD2600},
+        {"RV630",   CARD_AMD_RADEON_HD2600},
+        {"RV620",       CARD_AMD_RADEON_HD2350},
+        {"RV610",   CARD_AMD_RADEON_HD2350},
+        /* R500 */
+        {"R580",    CARD_AMD_RADEON_X1600},
+        {"R520",    CARD_AMD_RADEON_X1600},
+        {"RV570",   CARD_AMD_RADEON_X1600},
+        {"RV560",   CARD_AMD_RADEON_X1600},
+        {"RV535",   CARD_AMD_RADEON_X1600},
+        {"RV530",   CARD_AMD_RADEON_X1600},
+        {"RV516",       CARD_AMD_RADEON_X700},
+        {"RV515",   CARD_AMD_RADEON_X700},
+        /* R400 */
+        {"R481",    CARD_AMD_RADEON_X700},
+        {"R480",    CARD_AMD_RADEON_X700},
+        {"R430",    CARD_AMD_RADEON_X700},
+        {"R423",    CARD_AMD_RADEON_X700},
+        {"R420",    CARD_AMD_RADEON_X700},
+        {"R410",    CARD_AMD_RADEON_X700},
+        {"RV410",   CARD_AMD_RADEON_X700},
+        /* Radeon Xpress - onboard, DX9b, Shader 2.0, 300-400MHz */
+        {"RS740",   CARD_AMD_RADEON_XPRESS_200M},
+        {"RS690",   CARD_AMD_RADEON_XPRESS_200M},
+        {"RS600",   CARD_AMD_RADEON_XPRESS_200M},
+        {"RS485",   CARD_AMD_RADEON_XPRESS_200M},
+        {"RS482",   CARD_AMD_RADEON_XPRESS_200M},
+        {"RS480",   CARD_AMD_RADEON_XPRESS_200M},
+        {"RS400",   CARD_AMD_RADEON_XPRESS_200M},
+        /* R300 */
+        {"R360",    CARD_AMD_RADEON_9500},
+        {"R350",    CARD_AMD_RADEON_9500},
+        {"R300",    CARD_AMD_RADEON_9500},
+        {"RV370",   CARD_AMD_RADEON_9500},
+        {"RV360",   CARD_AMD_RADEON_9500},
+        {"RV351",   CARD_AMD_RADEON_9500},
+        {"RV350",   CARD_AMD_RADEON_9500},
+    };
+
+    for (i = 0; i < sizeof(cards) / sizeof(*cards); ++i)
+    {
+        if (strstr(gl_renderer, cards[i].renderer))
+            return cards[i].id;
+    }
+
+    return PCI_DEVICE_NONE;
+}
+
+static enum wined3d_pci_device select_card_nvidia_mesa(const struct wined3d_gl_info *gl_info,
+        const char *gl_renderer)
+{
+    unsigned int i;
+
+    static const struct
+    {
+        const char *renderer;
+        enum wined3d_pci_device id;
+    }
+    cards[] =
+    {
+        /* Kepler */
+        {"NVE4",    CARD_NVIDIA_GEFORCE_GTX680},
+        /* Fermi */
+        {"NVD9",    CARD_NVIDIA_GEFORCE_GT520},
+        {"NVCF",    CARD_NVIDIA_GEFORCE_GTX550},
+        {"NVCE",    CARD_NVIDIA_GEFORCE_GTX560},
+        {"NVC8",    CARD_NVIDIA_GEFORCE_GTX570},
+        {"NVC4",    CARD_NVIDIA_GEFORCE_GTX460},
+        {"NVC3",    CARD_NVIDIA_GEFORCE_GT440},
+        {"NVC1",    CARD_NVIDIA_GEFORCE_GT420},
+        {"NVC0",    CARD_NVIDIA_GEFORCE_GTX480},
+        /* Tesla */
+        {"NVAF",    CARD_NVIDIA_GEFORCE_GT320M},
+        {"NVAC",    CARD_NVIDIA_GEFORCE_8200},
+        {"NVAA",    CARD_NVIDIA_GEFORCE_8200},
+        {"NVA8",    CARD_NVIDIA_GEFORCE_210},
+        {"NVA5",    CARD_NVIDIA_GEFORCE_GT220},
+        {"NVA3",    CARD_NVIDIA_GEFORCE_GT240},
+        {"NVA0",    CARD_NVIDIA_GEFORCE_GTX280},
+        {"NV98",    CARD_NVIDIA_GEFORCE_9200},
+        {"NV96",    CARD_NVIDIA_GEFORCE_9400GT},
+        {"NV94",    CARD_NVIDIA_GEFORCE_9600GT},
+        {"NV92",    CARD_NVIDIA_GEFORCE_9800GT},
+        {"NV86",    CARD_NVIDIA_GEFORCE_8500GT},
+        {"NV84",    CARD_NVIDIA_GEFORCE_8600GT},
+        {"NV50",    CARD_NVIDIA_GEFORCE_8800GTX},
+        /* Curie */
+        {"NV68",    CARD_NVIDIA_GEFORCE_6200},      /* 7050 */
+        {"NV67",    CARD_NVIDIA_GEFORCE_6200},      /* 7000M */
+        {"NV63",    CARD_NVIDIA_GEFORCE_6200},      /* 7100 */
+        {"NV4E",    CARD_NVIDIA_GEFORCE_6200},      /* 6100 Go / 6150 Go */
+        {"NV4C",    CARD_NVIDIA_GEFORCE_6200},      /* 6150SE */
+        {"NV4B",    CARD_NVIDIA_GEFORCE_7600},
+        {"NV4A",    CARD_NVIDIA_GEFORCE_6200},
+        {"NV49",    CARD_NVIDIA_GEFORCE_7800GT},    /* 7900 */
+        {"NV47",    CARD_NVIDIA_GEFORCE_7800GT},
+        {"NV46",    CARD_NVIDIA_GEFORCE_7400},
+        {"NV45",    CARD_NVIDIA_GEFORCE_6800},
+        {"NV44",    CARD_NVIDIA_GEFORCE_6200},
+        {"NV43",    CARD_NVIDIA_GEFORCE_6600GT},
+        {"NV42",    CARD_NVIDIA_GEFORCE_6800},
+        {"NV41",    CARD_NVIDIA_GEFORCE_6800},
+        {"NV40",    CARD_NVIDIA_GEFORCE_6800},
+        /* Rankine */
+        {"NV38",    CARD_NVIDIA_GEFORCEFX_5800},    /* FX 5950 Ultra */
+        {"NV36",    CARD_NVIDIA_GEFORCEFX_5800},    /* FX 5700/5750 */
+        {"NV35",    CARD_NVIDIA_GEFORCEFX_5800},    /* FX 5900 */
+        {"NV34",    CARD_NVIDIA_GEFORCEFX_5200},
+        {"NV31",    CARD_NVIDIA_GEFORCEFX_5600},
+        {"NV30",    CARD_NVIDIA_GEFORCEFX_5800},
+        /* Kelvin */
+        {"nv28",    CARD_NVIDIA_GEFORCE4_TI4200},
+        {"nv25",    CARD_NVIDIA_GEFORCE4_TI4200},
+        {"nv20",    CARD_NVIDIA_GEFORCE3},
+        /* Celsius */
+        {"nv1F",    CARD_NVIDIA_GEFORCE4_MX},       /* GF4 MX IGP */
+        {"nv1A",    CARD_NVIDIA_GEFORCE2},          /* GF2 IGP */
+        {"nv18",    CARD_NVIDIA_GEFORCE4_MX},
+        {"nv17",    CARD_NVIDIA_GEFORCE4_MX},
+        {"nv16",    CARD_NVIDIA_GEFORCE2},
+        {"nv15",    CARD_NVIDIA_GEFORCE2},
+        {"nv11",    CARD_NVIDIA_GEFORCE2_MX},
+        {"nv10",    CARD_NVIDIA_GEFORCE},
+        /* Fahrenheit */
+        {"nv05",    CARD_NVIDIA_RIVA_TNT2},
+        {"nv04",    CARD_NVIDIA_RIVA_TNT},
+        {"nv03",    CARD_NVIDIA_RIVA_128},
+    };
+
+    for (i = 0; i < sizeof(cards) / sizeof(*cards); ++i)
+    {
+        if (strstr(gl_renderer, cards[i].renderer))
+            return cards[i].id;
+    }
+
+    return PCI_DEVICE_NONE;
+}
+
+static const struct gl_vendor_selection
+{
+    enum wined3d_gl_vendor gl_vendor;
+    const char *description;        /* Description of the card selector i.e. Apple OS/X Intel */
+    enum wined3d_pci_device (*select_card)(const struct wined3d_gl_info *gl_info, const char *gl_renderer);
+}
+nvidia_gl_vendor_table[] =
+{
+    {GL_VENDOR_NVIDIA, "Nvidia binary driver", select_card_nvidia_binary},
+    {GL_VENDOR_APPLE, "Apple OSX NVidia binary driver", select_card_nvidia_binary},
+    {GL_VENDOR_MESA, "Mesa Nouveau driver", select_card_nvidia_mesa},
+},
+amd_gl_vendor_table[] =
+{
+    {GL_VENDOR_APPLE, "Apple OSX AMD/ATI binary driver", select_card_amd_binary},
+    {GL_VENDOR_FGLRX, "AMD/ATI binary driver", select_card_amd_binary},
+    {GL_VENDOR_MESA, "Mesa AMD/ATI driver", select_card_amd_mesa},
+},
+intel_gl_vendor_table[] =
+{
+    {GL_VENDOR_APPLE, "Apple OSX Intel binary driver", select_card_intel},
+    {GL_VENDOR_INTEL, "Mesa Intel driver", select_card_intel},
+    {GL_VENDOR_MESA, "Mesa Intel driver", select_card_intel},
+};
+
+static enum wined3d_pci_device select_card_fallback_nvidia(const struct wined3d_gl_info *gl_info)
+{
+    UINT d3d_level = d3d_level_from_gl_info(gl_info);
+    if (d3d_level >= 10)
+        return CARD_NVIDIA_GEFORCE_8800GTX;
+    if (d3d_level >= 9 && gl_info->supported[NV_VERTEX_PROGRAM3])
+        return CARD_NVIDIA_GEFORCE_6800;
+    if (d3d_level >= 9)
+#ifndef VBOX_WITH_WDDM
+        return CARD_NVIDIA_GEFORCEFX_5800;
+#else
+        return CARD_NVIDIA_GEFORCE_6200;
+#endif
+    if (d3d_level >= 8)
+        return CARD_NVIDIA_GEFORCE3;
+    if (d3d_level >= 7)
+        return CARD_NVIDIA_GEFORCE;
+    if (d3d_level >= 6)
+        return CARD_NVIDIA_RIVA_TNT;
+    return CARD_NVIDIA_RIVA_128;
+}
+
+static enum wined3d_pci_device select_card_fallback_amd(const struct wined3d_gl_info *gl_info)
+{
+    UINT d3d_level = d3d_level_from_gl_info(gl_info);
+    if (d3d_level >= 10)
+        return CARD_AMD_RADEON_HD2900;
+    if (d3d_level >= 9)
+        return CARD_AMD_RADEON_9500;
+    if (d3d_level >= 8)
+        return CARD_AMD_RADEON_8500;
+    if (d3d_level >= 7)
+        return CARD_AMD_RADEON_7200;
+    return CARD_AMD_RAGE_128PRO;
+}
+
+static enum wined3d_pci_device select_card_fallback_intel(const struct wined3d_gl_info *gl_info)
+{
+    UINT d3d_level = d3d_level_from_gl_info(gl_info);
+    if (d3d_level >= 10)
+        return CARD_INTEL_G45;
+    return CARD_INTEL_915G;
+}
+
+static enum wined3d_pci_device select_card_handler(const struct gl_vendor_selection *table,
+        unsigned int table_size, enum wined3d_gl_vendor gl_vendor,
+        const struct wined3d_gl_info *gl_info, const char *gl_renderer)
+{
+    unsigned int i;
+
+    for (i = 0; i < table_size; ++i)
+    {
+        if (table[i].gl_vendor != gl_vendor)
+            continue;
+
+        TRACE("Applying card selector \"%s\".\n", table[i].description);
+        return table[i].select_card(gl_info, gl_renderer);
+    }
+    FIXME("Couldn't find a suitable card selector for GL vendor %04x (using GL_RENDERER %s)\n",
+            gl_vendor, debugstr_a(gl_renderer));
+
+    return PCI_DEVICE_NONE;
+}
+
+static const struct
+{
+    enum wined3d_pci_vendor card_vendor;
+    const char *description;        /* Description of the card selector i.e. Apple OS/X Intel */
+    const struct gl_vendor_selection *gl_vendor_selection;
+    unsigned int gl_vendor_count;
+    enum wined3d_pci_device (*select_card_fallback)(const struct wined3d_gl_info *gl_info);
+}
+card_vendor_table[] =
+{
+    {HW_VENDOR_NVIDIA,  "Nvidia",  nvidia_gl_vendor_table,
+            sizeof(nvidia_gl_vendor_table) / sizeof(nvidia_gl_vendor_table[0]),
+            select_card_fallback_nvidia},
+    {HW_VENDOR_AMD,     "AMD",     amd_gl_vendor_table,
+            sizeof(amd_gl_vendor_table) / sizeof(amd_gl_vendor_table[0]),
+            select_card_fallback_amd},
+    {HW_VENDOR_INTEL,   "Intel",   intel_gl_vendor_table,
+            sizeof(intel_gl_vendor_table) / sizeof(intel_gl_vendor_table[0]),
+            select_card_fallback_intel},
+};
+
+
+static enum wined3d_pci_device wined3d_guess_card(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
+        enum wined3d_gl_vendor *gl_vendor, enum wined3d_pci_vendor *card_vendor)
+{
+    /* A Direct3D device object contains the PCI id (vendor + device) of the
+     * videocard which is used for rendering. Various applications use this
+     * information to get a rough estimation of the features of the card and
+     * some might use it for enabling 3d effects only on certain types of
+     * videocards. In some cases games might even use it to work around bugs
+     * which happen on certain videocards/driver combinations. The problem is
+     * that OpenGL only exposes a rendering string containing the name of the
+     * videocard and not the PCI id.
+     *
+     * Various games depend on the PCI id, so somehow we need to provide one.
+     * A simple option is to parse the renderer string and translate this to
+     * the right PCI id. This is a lot of work because there are more than 200
+     * GPUs just for Nvidia. Various cards share the same renderer string, so
+     * the amount of code might be 'small' but there are quite a number of
+     * exceptions which would make this a pain to maintain. Another way would
+     * be to query the PCI id from the operating system (assuming this is the
+     * videocard which is used for rendering which is not always the case).
+     * This would work but it is not very portable. Second it would not work
+     * well in, let's say, a remote X situation in which the amount of 3d
+     * features which can be used is limited.
+     *
+     * As said most games only use the PCI id to get an indication of the
+     * capabilities of the card. It doesn't really matter if the given id is
+     * the correct one if we return the id of a card with similar 3d features.
+     *
+     * The code below checks the OpenGL capabilities of a videocard and matches
+     * that to a certain level of Direct3D functionality. Once a card passes
+     * the Direct3D9 check, we know that the card (in case of Nvidia) is at
+     * least a GeforceFX. To give a better estimate we do a basic check on the
+     * renderer string but if that won't pass we return a default card. This
+     * way is better than maintaining a full card database as even without a
+     * full database we can return a card with similar features. Second the
+     * size of the database can be made quite small because when you know what
+     * type of 3d functionality a card has, you know to which GPU family the
+     * GPU must belong. Because of this you only have to check a small part of
+     * the renderer string to distinguishes between different models from that
+     * family.
+     *
+     * The code also selects a default amount of video memory which we will
+     * use for an estimation of the amount of free texture memory. In case of
+     * real D3D the amount of texture memory includes video memory and system
+     * memory (to be specific AGP memory or in case of PCIE TurboCache /
+     * HyperMemory). We don't know how much system memory can be addressed by
+     * the system but we can make a reasonable estimation about the amount of
+     * video memory. If the value is slightly wrong it doesn't matter as we
+     * didn't include AGP-like memory which makes the amount of addressable
+     * memory higher and second OpenGL isn't that critical it moves to system
+     * memory behind our backs if really needed. Note that the amount of video
+     * memory can be overruled using a registry setting. */
+
+    unsigned int i;
+    enum wined3d_pci_device device;
+
+    for (i = 0; i < (sizeof(card_vendor_table) / sizeof(*card_vendor_table)); ++i)
+    {
+        if (card_vendor_table[i].card_vendor != *card_vendor)
+            continue;
+
+        TRACE("Applying card selector \"%s\".\n", card_vendor_table[i].description);
+        device = select_card_handler(card_vendor_table[i].gl_vendor_selection,
+                card_vendor_table[i].gl_vendor_count, *gl_vendor, gl_info, gl_renderer);
+        if (device != PCI_DEVICE_NONE)
+            return device;
+
+        TRACE("Unrecognized renderer %s, falling back to default.\n", debugstr_a(gl_renderer));
+        return card_vendor_table[i].select_card_fallback(gl_info);
+    }
+
+    FIXME("No card selector available for card vendor %04x (using GL_RENDERER %s).\n",
+            *card_vendor, debugstr_a(gl_renderer));
+
+    /* Default to generic Nvidia hardware based on the supported OpenGL extensions. */
+    *card_vendor = HW_VENDOR_NVIDIA;
+    return select_card_fallback_nvidia(gl_info);
+}
+
+static const struct wined3d_vertex_pipe_ops *select_vertex_implementation(const struct wined3d_gl_info *gl_info,
+        const struct wined3d_shader_backend_ops *shader_backend_ops)
+{
+    if (shader_backend_ops == &glsl_shader_backend)
+        return &glsl_vertex_pipe;
+    return &ffp_vertex_pipe;
+}
+
+static const struct fragment_pipeline *select_fragment_implementation(const struct wined3d_gl_info *gl_info,
+        const struct wined3d_shader_backend_ops *shader_backend_ops)
+{
+    if (shader_backend_ops == &glsl_shader_backend)
+        return &glsl_fragment_pipe;
+    if (shader_backend_ops == &arb_program_shader_backend && gl_info->supported[ARB_FRAGMENT_PROGRAM])
+        return &arbfp_fragment_pipeline;
+    if (gl_info->supported[ATI_FRAGMENT_SHADER])
+        return &atifs_fragment_pipeline;
+    if (gl_info->supported[NV_REGISTER_COMBINERS] && gl_info->supported[NV_TEXTURE_SHADER2])
+        return &nvts_fragment_pipeline;
+    if (gl_info->supported[NV_REGISTER_COMBINERS])
+        return &nvrc_fragment_pipeline;
+    return &ffp_fragment_pipeline;
+}
+
+static const struct wined3d_shader_backend_ops *select_shader_backend(const struct wined3d_gl_info *gl_info)
+{
+    BOOL glsl = wined3d_settings.glslRequested && gl_info->glsl_version >= MAKEDWORD_VERSION(1, 20);
+
+    if (glsl && gl_info->supported[ARB_FRAGMENT_SHADER])
+        return &glsl_shader_backend;
+    if (glsl && gl_info->supported[ARB_VERTEX_SHADER])
+    {
+        /* Geforce4 cards support GLSL but for vertex shaders only. Further
+         * its reported GLSL caps are wrong. This combined with the fact that
+         * GLSL won't offer more features or performance, use ARB shaders only
+         * on this card. */
+        if (gl_info->supported[NV_VERTEX_PROGRAM] && !gl_info->supported[NV_VERTEX_PROGRAM2])
+            return &arb_program_shader_backend;
+        return &glsl_shader_backend;
+    }
+    if (gl_info->supported[ARB_VERTEX_PROGRAM] || gl_info->supported[ARB_FRAGMENT_PROGRAM])
+        return &arb_program_shader_backend;
+    return &none_shader_backend;
+}
+
+static const struct blit_shader *select_blit_implementation(const struct wined3d_gl_info *gl_info,
+        const struct wined3d_shader_backend_ops *shader_backend_ops)
+{
+    if ((shader_backend_ops == &glsl_shader_backend
+            || shader_backend_ops == &arb_program_shader_backend)
+            && gl_info->supported[ARB_FRAGMENT_PROGRAM])
+        return &arbfp_blit;
+    return &ffp_blit;
+}
+
+static void parse_extension_string(struct wined3d_gl_info *gl_info, const char *extensions,
+        const struct wined3d_extension_map *map, UINT entry_count)
+{
+    while (*extensions)
+    {
+        const char *start;
+        size_t len;
+        UINT i;
+
+        while (isspace(*extensions))
+            ++extensions;
+        start = extensions;
+        while (!isspace(*extensions) && *extensions)
+            ++extensions;
+
+        len = extensions - start;
+        if (!len)
+            continue;
+
+        TRACE("- %s.\n", debugstr_an(start, len));
+
+        for (i = 0; i < entry_count; ++i)
+        {
+            if (len == strlen(map[i].extension_string)
+                    && !memcmp(start, map[i].extension_string, len))
+            {
+                TRACE(" FOUND: %s support.\n", map[i].extension_string);
+                gl_info->supported[map[i].extension] = TRUE;
+                break;
+            }
+        }
+    }
+}
+
+static void load_gl_funcs(struct wined3d_gl_info *gl_info)
+{
+#define USE_GL_FUNC(pfn) gl_info->gl_ops.ext.p_##pfn = (void *)wglGetProcAddress(#pfn);
+    GL_EXT_FUNCS_GEN;
+#undef USE_GL_FUNC
+
+#ifndef USE_WIN32_OPENGL
+    /* hack: use the functions directly from the TEB table to bypass the thunks */
+    /* note that we still need the above wglGetProcAddress calls to initialize the table */
+    gl_info->gl_ops.ext = ((struct opengl_funcs *)NtCurrentTeb()->glTable)->ext;
+#endif
+}
+
+static void wined3d_adapter_init_limits(struct wined3d_gl_info *gl_info)
+{
+    GLfloat gl_floatv[2];
+    GLint gl_max;
+
+    gl_info->limits.blends = 1;
+    gl_info->limits.buffers = 1;
+    gl_info->limits.textures = 1;
+    gl_info->limits.texture_coords = 1;
+    gl_info->limits.fragment_samplers = 1;
+    gl_info->limits.vertex_samplers = 0;
+    gl_info->limits.combined_samplers = gl_info->limits.fragment_samplers + gl_info->limits.vertex_samplers;
+    gl_info->limits.vertex_attribs = 16;
+    gl_info->limits.glsl_vs_float_constants = 0;
+    gl_info->limits.glsl_ps_float_constants = 0;
+    gl_info->limits.arb_vs_float_constants = 0;
+    gl_info->limits.arb_vs_native_constants = 0;
+    gl_info->limits.arb_vs_instructions = 0;
+    gl_info->limits.arb_vs_temps = 0;
+    gl_info->limits.arb_ps_float_constants = 0;
+    gl_info->limits.arb_ps_local_constants = 0;
+    gl_info->limits.arb_ps_instructions = 0;
+    gl_info->limits.arb_ps_temps = 0;
+
+    gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
+    gl_info->limits.clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
+    TRACE("Clip plane support - max planes %d.\n", gl_max);
+
+    gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
+    gl_info->limits.lights = gl_max;
+    TRACE("Light support - max lights %d.\n", gl_max);
+
+    gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
+    gl_info->limits.texture_size = gl_max;
+    TRACE("Maximum texture size support - max texture size %d.\n", gl_max);
+
+    gl_info->gl_ops.gl.p_glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, gl_floatv);
+    gl_info->limits.pointsize_min = gl_floatv[0];
+    gl_info->limits.pointsize_max = gl_floatv[1];
+    TRACE("Maximum point size support - max point size %f.\n", gl_floatv[1]);
+
+    if (gl_info->supported[ARB_MAP_BUFFER_ALIGNMENT])
+    {
+        gl_info->gl_ops.gl.p_glGetIntegerv(GL_MIN_MAP_BUFFER_ALIGNMENT, &gl_max);
+        TRACE("Minimum buffer map alignment: %d.\n", gl_max);
+    }
+    else
+    {
+        WARN_(d3d_perf)("Driver doesn't guarantee a minimum buffer map alignment.\n");
+    }
+    if (gl_info->supported[NV_REGISTER_COMBINERS])
+    {
+        gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &gl_max);
+        gl_info->limits.general_combiners = gl_max;
+        TRACE("Max general combiners: %d.\n", gl_max);
+    }
+    if (gl_info->supported[ARB_DRAW_BUFFERS] && wined3d_settings.offscreen_rendering_mode == ORM_FBO)
+    {
+        gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
+        gl_info->limits.buffers = gl_max;
+        TRACE("Max draw buffers: %u.\n", gl_max);
+    }
+    if (gl_info->supported[ARB_MULTITEXTURE])
+    {
+        gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
+        gl_info->limits.textures = min(MAX_TEXTURES, gl_max);
+        TRACE("Max textures: %d.\n", gl_info->limits.textures);
+
+        if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
+        {
+            GLint tmp;
+            gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_TEXTURE_COORDS_ARB, &gl_max);
+            gl_info->limits.texture_coords = min(MAX_TEXTURES, gl_max);
+            gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
+            gl_info->limits.fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
+        }
+        else
+        {
+            gl_info->limits.texture_coords = max(gl_info->limits.texture_coords, gl_max);
+            gl_info->limits.fragment_samplers = max(gl_info->limits.fragment_samplers, gl_max);
+        }
+        TRACE("Max texture coords: %d.\n", gl_info->limits.texture_coords);
+        TRACE("Max fragment samplers: %d.\n", gl_info->limits.fragment_samplers);
+
+        if (gl_info->supported[ARB_VERTEX_SHADER])
+        {
+            GLint tmp;
+            gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
+            gl_info->limits.vertex_samplers = tmp;
+            gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
+            gl_info->limits.combined_samplers = tmp;
+            gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &tmp);
+            gl_info->limits.vertex_attribs = tmp;
+
+            /* Loading GLSL sampler uniforms is much simpler if we can assume that the sampler setup
+             * is known at shader link time. In a vertex shader + pixel shader combination this isn't
+             * an issue because then the sampler setup only depends on the two shaders. If a pixel
+             * shader is used with fixed function vertex processing we're fine too because fixed function
+             * vertex processing doesn't use any samplers. If fixed function fragment processing is
+             * used we have to make sure that all vertex sampler setups are valid together with all
+             * possible fixed function fragment processing setups. This is true if vsamplers + MAX_TEXTURES
+             * <= max_samplers. This is true on all d3d9 cards that support vtf(gf 6 and gf7 cards).
+             * dx9 radeon cards do not support vertex texture fetch. DX10 cards have 128 samplers, and
+             * dx9 is limited to 8 fixed function texture stages and 4 vertex samplers. DX10 does not have
+             * a fixed function pipeline anymore.
+             *
+             * So this is just a check to check that our assumption holds true. If not, write a warning
+             * and reduce the number of vertex samplers or probably disable vertex texture fetch. */
+            if (gl_info->limits.vertex_samplers && gl_info->limits.combined_samplers < 12
+                    && MAX_TEXTURES + gl_info->limits.vertex_samplers > gl_info->limits.combined_samplers)
+            {
+                FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers.\n",
+                        gl_info->limits.vertex_samplers, gl_info->limits.combined_samplers);
+                FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers.\n");
+                if (gl_info->limits.combined_samplers > MAX_TEXTURES)
+                    gl_info->limits.vertex_samplers = gl_info->limits.combined_samplers - MAX_TEXTURES;
+                else
+                    gl_info->limits.vertex_samplers = 0;
+            }
+        }
+        else
+        {
+            gl_info->limits.combined_samplers = gl_info->limits.fragment_samplers;
+        }
+        TRACE("Max vertex samplers: %u.\n", gl_info->limits.vertex_samplers);
+        TRACE("Max combined samplers: %u.\n", gl_info->limits.combined_samplers);
+    }
+    if (gl_info->supported[ARB_VERTEX_BLEND])
+    {
+        gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
+        gl_info->limits.blends = gl_max;
+        TRACE("Max blends: %u.\n", gl_info->limits.blends);
+    }
+    if (gl_info->supported[EXT_TEXTURE3D])
+    {
+        gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
+        gl_info->limits.texture3d_size = gl_max;
+        TRACE("Max texture3D size: %d.\n", gl_info->limits.texture3d_size);
+    }
+    if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
+    {
+        gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
+        gl_info->limits.anisotropy = gl_max;
+        TRACE("Max anisotropy: %d.\n", gl_info->limits.anisotropy);
+    }
+    if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
+    {
+        GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
+        gl_info->limits.arb_ps_float_constants = gl_max;
+        TRACE("Max ARB_FRAGMENT_PROGRAM float constants: %d.\n", gl_info->limits.arb_ps_float_constants);
+        GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB, &gl_max));
+        gl_info->limits.arb_ps_native_constants = gl_max;
+        TRACE("Max ARB_FRAGMENT_PROGRAM native float constants: %d.\n",
+                gl_info->limits.arb_ps_native_constants);
+        GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
+        gl_info->limits.arb_ps_temps = gl_max;
+        TRACE("Max ARB_FRAGMENT_PROGRAM native temporaries: %d.\n", gl_info->limits.arb_ps_temps);
+        GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
+        gl_info->limits.arb_ps_instructions = gl_max;
+        TRACE("Max ARB_FRAGMENT_PROGRAM native instructions: %d.\n", gl_info->limits.arb_ps_instructions);
+        GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, &gl_max));
+        gl_info->limits.arb_ps_local_constants = gl_max;
+        TRACE("Max ARB_FRAGMENT_PROGRAM local parameters: %d.\n", gl_info->limits.arb_ps_instructions);
+    }
+    if (gl_info->supported[ARB_VERTEX_PROGRAM])
+    {
+        GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
+        gl_info->limits.arb_vs_float_constants = gl_max;
+        TRACE("Max ARB_VERTEX_PROGRAM float constants: %d.\n", gl_info->limits.arb_vs_float_constants);
+        GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB, &gl_max));
+        gl_info->limits.arb_vs_native_constants = gl_max;
+        TRACE("Max ARB_VERTEX_PROGRAM native float constants: %d.\n",
+                gl_info->limits.arb_vs_native_constants);
+        GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
+        gl_info->limits.arb_vs_temps = gl_max;
+        TRACE("Max ARB_VERTEX_PROGRAM native temporaries: %d.\n", gl_info->limits.arb_vs_temps);
+        GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
+        gl_info->limits.arb_vs_instructions = gl_max;
+        TRACE("Max ARB_VERTEX_PROGRAM native instructions: %d.\n", gl_info->limits.arb_vs_instructions);
+    }
+    if (gl_info->supported[ARB_VERTEX_SHADER])
+    {
+        gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
+        gl_info->limits.glsl_vs_float_constants = gl_max / 4;
+        TRACE("Max ARB_VERTEX_SHADER float constants: %u.\n", gl_info->limits.glsl_vs_float_constants);
+#ifdef VBOX_WITH_WDDM
+        /* AFAICT the " / 4" here comes from that we're going to use the glsl_vs/ps_float_constants to create vec4 arrays,
+         * thus each array element has 4 components, so the actual number of vec4 arrays is GL_MAX_VERTEX/FRAGMENT_UNIFORM_COMPONENTS_ARB / 4
+         * win8 Aero won't properly work with this constant < 256 in any way,
+         * while Intel drivers I've encountered this problem with supports vec4 arrays of size >  GL_MAX_VERTEX/FRAGMENT_UNIFORM_COMPONENTS_ARB / 4
+         * so use it here.
+         * @todo: add logging
+         * @todo: perhaps should be movet to quirks?
+         * */
+        if (gl_info->limits.glsl_vs_float_constants < 256 && gl_max >= 256)
+        {
+            DWORD dwVersion = GetVersion();
+            DWORD dwMajor = (DWORD)(LOBYTE(LOWORD(dwVersion)));
+            DWORD dwMinor = (DWORD)(HIBYTE(LOWORD(dwVersion)));
+            /* tmp workaround Win8 Aero requirement for 256 */
+            if (dwMajor > 6 || dwMinor > 1)
+            {
+                gl_info->limits.glsl_vs_float_constants = 256;
+            }
+        }
+#endif
+    }
+    if (gl_info->supported[ARB_FRAGMENT_SHADER])
+    {
+        gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
+        gl_info->limits.glsl_ps_float_constants = gl_max / 4;
+        TRACE("Max ARB_FRAGMENT_SHADER float constants: %u.\n", gl_info->limits.glsl_ps_float_constants);
+#ifdef VBOX_WITH_WDDM
+        /* AFAICT the " / 4" here comes from that we're going to use the glsl_vs/ps_float_constants to create vec4 arrays,
+         * thus each array element has 4 components, so the actual number of vec4 arrays is GL_MAX_VERTEX/FRAGMENT_UNIFORM_COMPONENTS_ARB / 4
+         * win8 Aero won't properly work with this constant < 256 in any way,
+         * while Intel drivers I've encountered this problem with supports vec4 arrays of size >  GL_MAX_VERTEX/FRAGMENT_UNIFORM_COMPONENTS_ARB / 4
+         * so use it here.
+         * @todo: add logging
+         * @todo: perhaps should be movet to quirks?
+         * */
+        if (gl_info->limits.glsl_ps_float_constants < 256 && gl_max >= 256)
+        {
+            DWORD dwVersion = GetVersion();
+            DWORD dwMajor = (DWORD)(LOBYTE(LOWORD(dwVersion)));
+            DWORD dwMinor = (DWORD)(HIBYTE(LOWORD(dwVersion)));
+            /* tmp workaround Win8 Aero requirement for 256 */
+            if (dwMajor > 6 || dwMinor > 1)
+            {
+                gl_info->limits.glsl_ps_float_constants = 256;
+            }
+        }
+#endif
+        gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max);
+        gl_info->limits.glsl_varyings = gl_max;
+        TRACE("Max GLSL varyings: %u (%u 4 component varyings).\n", gl_max, gl_max / 4);
+    }
+
+    if (gl_info->supported[NV_LIGHT_MAX_EXPONENT])
+        gl_info->gl_ops.gl.p_glGetFloatv(GL_MAX_SHININESS_NV, &gl_info->limits.shininess);
+    else
+        gl_info->limits.shininess = 128.0f;
+
+    if ((gl_info->supported[ARB_FRAMEBUFFER_OBJECT] || gl_info->supported[EXT_FRAMEBUFFER_MULTISAMPLE])
+            && wined3d_settings.allow_multisampling)
+    {
+        gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_SAMPLES, &gl_max);
+        gl_info->limits.samples = gl_max;
+    }
+}
+
+/* Context activation is done by the caller. */
+static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter)
+{
+    struct wined3d_driver_info *driver_info = &adapter->driver_info;
+    const char *gl_vendor_str, *gl_renderer_str, *gl_version_str;
+    struct wined3d_gl_info *gl_info = &adapter->gl_info;
+    enum wined3d_pci_vendor card_vendor;
+    struct fragment_caps fragment_caps;
+    struct shader_caps shader_caps;
+    const char *WGL_Extensions = NULL;
+    const char *GL_Extensions = NULL;
+    enum wined3d_gl_vendor gl_vendor;
+    enum wined3d_pci_device device;
+    DWORD gl_version;
+    HDC hdc;
+    unsigned int i;
+
+    TRACE("adapter %p.\n", adapter);
+
+    gl_renderer_str = (const char *)gl_info->gl_ops.gl.p_glGetString(GL_RENDERER);
+    TRACE("GL_RENDERER: %s.\n", debugstr_a(gl_renderer_str));
+    if (!gl_renderer_str)
+    {
+        ERR("Received a NULL GL_RENDERER.\n");
+        return FALSE;
+    }
+
+    gl_vendor_str = (const char *)gl_info->gl_ops.gl.p_glGetString(GL_VENDOR);
+    TRACE("GL_VENDOR: %s.\n", debugstr_a(gl_vendor_str));
+    if (!gl_vendor_str)
+    {
+        ERR("Received a NULL GL_VENDOR.\n");
+        return FALSE;
+    }
+
+    /* Parse the GL_VERSION field into major and minor information */
+    gl_version_str = (const char *)gl_info->gl_ops.gl.p_glGetString(GL_VERSION);
+    TRACE("GL_VERSION: %s.\n", debugstr_a(gl_version_str));
+    if (!gl_version_str)
+    {
+        ERR("Received a NULL GL_VERSION.\n");
+        return FALSE;
+    }
+    gl_version = wined3d_parse_gl_version(gl_version_str);
+
+    /* Parse the gl supported features, in theory enabling parts of our code appropriately. */
+    GL_Extensions = (const char *)gl_info->gl_ops.gl.p_glGetString(GL_EXTENSIONS);
+    if (!GL_Extensions)
+    {
+        ERR("Received a NULL GL_EXTENSIONS.\n");
+        return FALSE;
+    }
+
+    memset(gl_info->supported, 0, sizeof(gl_info->supported));
+    gl_info->supported[WINED3D_GL_EXT_NONE] = TRUE;
+
+    TRACE("GL extensions reported:\n");
+    parse_extension_string(gl_info, GL_Extensions, gl_extension_map,
+            sizeof(gl_extension_map) / sizeof(*gl_extension_map));
+
+    /* Now work out what GL support this card really has. */
+    load_gl_funcs( gl_info );
+
+    hdc = wglGetCurrentDC();
+    /* Not all GL drivers might offer WGL extensions e.g. VirtualBox. */
+    if (GL_EXTCALL(wglGetExtensionsStringARB))
+        WGL_Extensions = (const char *)GL_EXTCALL(wglGetExtensionsStringARB(hdc));
+    if (!WGL_Extensions)
+        WARN("WGL extensions not supported.\n");
+    else
+        parse_extension_string(gl_info, WGL_Extensions, wgl_extension_map,
+                sizeof(wgl_extension_map) / sizeof(*wgl_extension_map));
+
+    if (!gl_info->supported[EXT_TEXTURE3D] && gl_version >= MAKEDWORD_VERSION(1, 2))
+    {
+        TRACE("GL CORE: GL_EXT_texture3D support.\n");
+        gl_info->gl_ops.ext.p_glTexImage3DEXT = (void *)gl_info->gl_ops.ext.p_glTexImage3D;
+        gl_info->gl_ops.ext.p_glTexSubImage3DEXT = gl_info->gl_ops.ext.p_glTexSubImage3D;
+        gl_info->supported[EXT_TEXTURE3D] = TRUE;
+    }
+
+    if (!gl_info->supported[NV_POINT_SPRITE] && gl_version >= MAKEDWORD_VERSION(1, 4))
+    {
+        TRACE("GL CORE: GL_NV_point_sprite support.\n");
+        gl_info->gl_ops.ext.p_glPointParameterivNV = gl_info->gl_ops.ext.p_glPointParameteriv;
+        gl_info->gl_ops.ext.p_glPointParameteriNV = gl_info->gl_ops.ext.p_glPointParameteri;
+        gl_info->supported[NV_POINT_SPRITE] = TRUE;
+    }
+
+    if (!gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] && gl_version >= MAKEDWORD_VERSION(2, 0))
+    {
+        TRACE("GL CORE: GL_ARB_texture_non_power_of_two support.\n");
+        gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = TRUE;
+    }
+
+    if (gl_version >= MAKEDWORD_VERSION(2, 0)) gl_info->supported[WINED3D_GL_VERSION_2_0] = TRUE;
+
+    if (gl_info->supported[APPLE_FENCE])
+    {
+        /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
+         * The apple extension interacts with some other apple exts. Disable the NV
+         * extension if the apple one is support to prevent confusion in other parts
+         * of the code. */
+        gl_info->supported[NV_FENCE] = FALSE;
+    }
+    if (gl_info->supported[APPLE_FLOAT_PIXELS])
+    {
+        /* GL_APPLE_float_pixels == GL_ARB_texture_float + GL_ARB_half_float_pixel
+         *
+         * The enums are the same:
+         * GL_RGBA16F_ARB     = GL_RGBA_FLOAT16_APPLE = 0x881a
+         * GL_RGB16F_ARB      = GL_RGB_FLOAT16_APPLE  = 0x881b
+         * GL_RGBA32F_ARB     = GL_RGBA_FLOAT32_APPLE = 0x8814
+         * GL_RGB32F_ARB      = GL_RGB_FLOAT32_APPLE  = 0x8815
+         * GL_HALF_FLOAT_ARB  = GL_HALF_APPLE         = 0x140b
+         */
+        if (!gl_info->supported[ARB_TEXTURE_FLOAT])
+        {
+            TRACE(" IMPLIED: GL_ARB_texture_float support (by GL_APPLE_float_pixels).\n");
+            gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE;
+        }
+        if (!gl_info->supported[ARB_HALF_FLOAT_PIXEL])
+        {
+            TRACE(" IMPLIED: GL_ARB_half_float_pixel support (by GL_APPLE_float_pixels).\n");
+            gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE;
+        }
+    }
+    if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
+    {
+        /* GL_ARB_map_buffer_range and GL_APPLE_flush_buffer_range provide the same
+         * functionality. Prefer the ARB extension */
+        gl_info->supported[APPLE_FLUSH_BUFFER_RANGE] = FALSE;
+    }
+    if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
+    {
+        TRACE(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support.\n");
+        gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
+    }
+    if (!gl_info->supported[ARB_DEPTH_CLAMP] && gl_info->supported[NV_DEPTH_CLAMP])
+    {
+        TRACE(" IMPLIED: ARB_depth_clamp support (by NV_depth_clamp).\n");
+        gl_info->supported[ARB_DEPTH_CLAMP] = TRUE;
+    }
+    if (!gl_info->supported[ARB_VERTEX_ARRAY_BGRA] && gl_info->supported[EXT_VERTEX_ARRAY_BGRA])
+    {
+        TRACE(" IMPLIED: ARB_vertex_array_bgra support (by EXT_vertex_array_bgra).\n");
+        gl_info->supported[ARB_VERTEX_ARRAY_BGRA] = TRUE;
+    }
+    if (!gl_info->supported[ARB_TEXTURE_COMPRESSION_RGTC] && gl_info->supported[EXT_TEXTURE_COMPRESSION_RGTC])
+    {
+        TRACE(" IMPLIED: ARB_texture_compression_rgtc support (by EXT_texture_compression_rgtc).\n");
+        gl_info->supported[ARB_TEXTURE_COMPRESSION_RGTC] = TRUE;
+    }
+    if (gl_info->supported[NV_TEXTURE_SHADER2])
+    {
+        if (gl_info->supported[NV_REGISTER_COMBINERS])
+        {
+            /* Also disable ATI_FRAGMENT_SHADER if register combiners and texture_shader2
+             * are supported. The nv extensions provide the same functionality as the
+             * ATI one, and a bit more(signed pixelformats). */
+            gl_info->supported[ATI_FRAGMENT_SHADER] = FALSE;
+        }
+    }
+    if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
+    {
+        /* If we have full NP2 texture support, disable
+         * GL_ARB_texture_rectangle because we will never use it.
+         * This saves a few redundant glDisable calls. */
+        gl_info->supported[ARB_TEXTURE_RECTANGLE] = FALSE;
+    }
+    if (gl_info->supported[ATI_FRAGMENT_SHADER])
+    {
+        /* Disable NV_register_combiners and fragment shader if this is supported.
+         * generally the NV extensions are preferred over the ATI ones, and this
+         * extension is disabled if register_combiners and texture_shader2 are both
+         * supported. So we reach this place only if we have incomplete NV dxlevel 8
+         * fragment processing support. */
+        gl_info->supported[NV_REGISTER_COMBINERS] = FALSE;
+        gl_info->supported[NV_REGISTER_COMBINERS2] = FALSE;
+        gl_info->supported[NV_TEXTURE_SHADER] = FALSE;
+        gl_info->supported[NV_TEXTURE_SHADER2] = FALSE;
+    }
+    if (gl_info->supported[NV_HALF_FLOAT])
+    {
+        /* GL_ARB_half_float_vertex is a subset of GL_NV_half_float. */
+        gl_info->supported[ARB_HALF_FLOAT_VERTEX] = TRUE;
+    }
+    if (gl_info->supported[ARB_FRAMEBUFFER_SRGB] && !gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
+    {
+        /* Current wined3d sRGB infrastructure requires EXT_texture_sRGB_decode
+         * for GL_ARB_framebuffer_sRGB support (without EXT_texture_sRGB_decode
+         * we never render to sRGB surfaces). */
+        gl_info->supported[ARB_FRAMEBUFFER_SRGB] = FALSE;
+    }
+    if (gl_info->supported[ARB_OCCLUSION_QUERY])
+    {
+        GLint counter_bits;
+
+        GL_EXTCALL(glGetQueryivARB(GL_SAMPLES_PASSED_ARB, GL_QUERY_COUNTER_BITS_ARB, &counter_bits));
+        TRACE("Occlusion query counter has %d bits.\n", counter_bits);
+        if (!counter_bits)
+            gl_info->supported[ARB_OCCLUSION_QUERY] = FALSE;
+    }
+
+    wined3d_adapter_init_limits(gl_info);
+
+    if (gl_info->supported[ARB_VERTEX_PROGRAM] && test_arb_vs_offset_limit(gl_info))
+        gl_info->quirks |= WINED3D_QUIRK_ARB_VS_OFFSET_LIMIT;
+
+    if (gl_info->supported[ARB_SHADING_LANGUAGE_100])
+    {
+        const char *str = (const char *)gl_info->gl_ops.gl.p_glGetString(GL_SHADING_LANGUAGE_VERSION_ARB);
+        unsigned int major, minor;
+
+        TRACE("GLSL version string: %s.\n", debugstr_a(str));
+
+        /* The format of the GLSL version string is "major.minor[.release] [vendor info]". */
+        sscanf(str, "%u.%u", &major, &minor);
+        gl_info->glsl_version = MAKEDWORD_VERSION(major, minor);
+    }
+
+    checkGLcall("extension detection");
+
+    adapter->shader_backend = select_shader_backend(gl_info);
+    adapter->vertex_pipe = select_vertex_implementation(gl_info, adapter->shader_backend);
+    adapter->fragment_pipe = select_fragment_implementation(gl_info, adapter->shader_backend);
+    adapter->blitter = select_blit_implementation(gl_info, adapter->shader_backend);
+
+    adapter->shader_backend->shader_get_caps(&adapter->gl_info, &shader_caps);
+    adapter->d3d_info.vs_clipping = shader_caps.wined3d_caps & WINED3D_SHADER_CAP_VS_CLIPPING;
+    adapter->d3d_info.limits.vs_version = shader_caps.vs_version;
+    adapter->d3d_info.limits.gs_version = shader_caps.gs_version;
+    adapter->d3d_info.limits.ps_version = shader_caps.ps_version;
+    adapter->d3d_info.limits.vs_uniform_count = shader_caps.vs_uniform_count;
+    adapter->d3d_info.limits.ps_uniform_count = shader_caps.ps_uniform_count;
+
+    adapter->fragment_pipe->get_caps(gl_info, &fragment_caps);
+    adapter->d3d_info.limits.ffp_blend_stages = fragment_caps.MaxTextureBlendStages;
+    adapter->d3d_info.limits.ffp_textures = fragment_caps.MaxSimultaneousTextures;
+    TRACE("Max texture stages: %u.\n", adapter->d3d_info.limits.ffp_blend_stages);
+
+    if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT])
+    {
+        gl_info->fbo_ops.glIsRenderbuffer = gl_info->gl_ops.ext.p_glIsRenderbuffer;
+        gl_info->fbo_ops.glBindRenderbuffer = gl_info->gl_ops.ext.p_glBindRenderbuffer;
+        gl_info->fbo_ops.glDeleteRenderbuffers = gl_info->gl_ops.ext.p_glDeleteRenderbuffers;
+        gl_info->fbo_ops.glGenRenderbuffers = gl_info->gl_ops.ext.p_glGenRenderbuffers;
+        gl_info->fbo_ops.glRenderbufferStorage = gl_info->gl_ops.ext.p_glRenderbufferStorage;
+        gl_info->fbo_ops.glRenderbufferStorageMultisample = gl_info->gl_ops.ext.p_glRenderbufferStorageMultisample;
+        gl_info->fbo_ops.glGetRenderbufferParameteriv = gl_info->gl_ops.ext.p_glGetRenderbufferParameteriv;
+        gl_info->fbo_ops.glIsFramebuffer = gl_info->gl_ops.ext.p_glIsFramebuffer;
+        gl_info->fbo_ops.glBindFramebuffer = gl_info->gl_ops.ext.p_glBindFramebuffer;
+        gl_info->fbo_ops.glDeleteFramebuffers = gl_info->gl_ops.ext.p_glDeleteFramebuffers;
+        gl_info->fbo_ops.glGenFramebuffers = gl_info->gl_ops.ext.p_glGenFramebuffers;
+        gl_info->fbo_ops.glCheckFramebufferStatus = gl_info->gl_ops.ext.p_glCheckFramebufferStatus;
+        gl_info->fbo_ops.glFramebufferTexture1D = gl_info->gl_ops.ext.p_glFramebufferTexture1D;
+        gl_info->fbo_ops.glFramebufferTexture2D = gl_info->gl_ops.ext.p_glFramebufferTexture2D;
+        gl_info->fbo_ops.glFramebufferTexture3D = gl_info->gl_ops.ext.p_glFramebufferTexture3D;
+        gl_info->fbo_ops.glFramebufferRenderbuffer = gl_info->gl_ops.ext.p_glFramebufferRenderbuffer;
+        gl_info->fbo_ops.glGetFramebufferAttachmentParameteriv
+                = gl_info->gl_ops.ext.p_glGetFramebufferAttachmentParameteriv;
+        gl_info->fbo_ops.glBlitFramebuffer = gl_info->gl_ops.ext.p_glBlitFramebuffer;
+        gl_info->fbo_ops.glGenerateMipmap = gl_info->gl_ops.ext.p_glGenerateMipmap;
+    }
+    else
+    {
+        if (gl_info->supported[EXT_FRAMEBUFFER_OBJECT])
+        {
+            gl_info->fbo_ops.glIsRenderbuffer = gl_info->gl_ops.ext.p_glIsRenderbufferEXT;
+            gl_info->fbo_ops.glBindRenderbuffer = gl_info->gl_ops.ext.p_glBindRenderbufferEXT;
+            gl_info->fbo_ops.glDeleteRenderbuffers = gl_info->gl_ops.ext.p_glDeleteRenderbuffersEXT;
+            gl_info->fbo_ops.glGenRenderbuffers = gl_info->gl_ops.ext.p_glGenRenderbuffersEXT;
+            gl_info->fbo_ops.glRenderbufferStorage = gl_info->gl_ops.ext.p_glRenderbufferStorageEXT;
+            gl_info->fbo_ops.glGetRenderbufferParameteriv = gl_info->gl_ops.ext.p_glGetRenderbufferParameterivEXT;
+            gl_info->fbo_ops.glIsFramebuffer = gl_info->gl_ops.ext.p_glIsFramebufferEXT;
+            gl_info->fbo_ops.glBindFramebuffer = gl_info->gl_ops.ext.p_glBindFramebufferEXT;
+            gl_info->fbo_ops.glDeleteFramebuffers = gl_info->gl_ops.ext.p_glDeleteFramebuffersEXT;
+            gl_info->fbo_ops.glGenFramebuffers = gl_info->gl_ops.ext.p_glGenFramebuffersEXT;
+            gl_info->fbo_ops.glCheckFramebufferStatus = gl_info->gl_ops.ext.p_glCheckFramebufferStatusEXT;
+            gl_info->fbo_ops.glFramebufferTexture1D = gl_info->gl_ops.ext.p_glFramebufferTexture1DEXT;
+            gl_info->fbo_ops.glFramebufferTexture2D = gl_info->gl_ops.ext.p_glFramebufferTexture2DEXT;
+            gl_info->fbo_ops.glFramebufferTexture3D = gl_info->gl_ops.ext.p_glFramebufferTexture3DEXT;
+            gl_info->fbo_ops.glFramebufferRenderbuffer = gl_info->gl_ops.ext.p_glFramebufferRenderbufferEXT;
+            gl_info->fbo_ops.glGetFramebufferAttachmentParameteriv
+                    = gl_info->gl_ops.ext.p_glGetFramebufferAttachmentParameterivEXT;
+            gl_info->fbo_ops.glGenerateMipmap = gl_info->gl_ops.ext.p_glGenerateMipmapEXT;
+        }
+        else if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
+        {
+            WARN_(d3d_perf)("Framebuffer objects not supported, falling back to backbuffer offscreen rendering mode.\n");
+            wined3d_settings.offscreen_rendering_mode = ORM_BACKBUFFER;
+        }
+        if (gl_info->supported[EXT_FRAMEBUFFER_BLIT])
+        {
+            gl_info->fbo_ops.glBlitFramebuffer = gl_info->gl_ops.ext.p_glBlitFramebufferEXT;
+        }
+        if (gl_info->supported[EXT_FRAMEBUFFER_MULTISAMPLE])
+        {
+            gl_info->fbo_ops.glRenderbufferStorageMultisample
+                    = gl_info->gl_ops.ext.p_glRenderbufferStorageMultisampleEXT;
+        }
+    }
+
+    gl_vendor = wined3d_guess_gl_vendor(gl_info, gl_vendor_str, gl_renderer_str);
+    card_vendor = wined3d_guess_card_vendor(gl_vendor_str, gl_renderer_str);
+    TRACE("Found GL_VENDOR (%s)->(0x%04x/0x%04x).\n", debugstr_a(gl_vendor_str), gl_vendor, card_vendor);
+
+    device = wined3d_guess_card(gl_info, gl_renderer_str, &gl_vendor, &card_vendor);
+    TRACE("Found (fake) card: 0x%x (vendor id), 0x%x (device id).\n", card_vendor, device);
+
+    gl_info->wrap_lookup[WINED3D_TADDRESS_WRAP - WINED3D_TADDRESS_WRAP] = GL_REPEAT;
+    gl_info->wrap_lookup[WINED3D_TADDRESS_MIRROR - WINED3D_TADDRESS_WRAP] =
+            gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
+    gl_info->wrap_lookup[WINED3D_TADDRESS_CLAMP - WINED3D_TADDRESS_WRAP] = GL_CLAMP_TO_EDGE;
+    gl_info->wrap_lookup[WINED3D_TADDRESS_BORDER - WINED3D_TADDRESS_WRAP] =
+            gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
+    gl_info->wrap_lookup[WINED3D_TADDRESS_MIRROR_ONCE - WINED3D_TADDRESS_WRAP] =
+            gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
+
+    adapter->d3d_info.valid_rt_mask = 0;
+    for (i = 0; i < gl_info->limits.buffers; ++i)
+        adapter->d3d_info.valid_rt_mask |= (1 << i);
+
+    fixup_extensions(gl_info, gl_renderer_str, gl_vendor, card_vendor, device);
+    init_driver_info(driver_info, card_vendor, device);
+    add_gl_compat_wrappers(gl_info);
+
+    return TRUE;
+}
+
+UINT CDECL wined3d_get_adapter_count(const struct wined3d *wined3d)
+{
+    TRACE("wined3d %p, reporting %u adapters.\n",
+            wined3d, wined3d->adapter_count);
+
+    return wined3d->adapter_count;
+}
+
+HRESULT CDECL wined3d_register_software_device(struct wined3d *wined3d, void *init_function)
+{
+    FIXME("wined3d %p, init_function %p stub!\n", wined3d, init_function);
+
+    return WINED3D_OK;
+}
+
+HMONITOR CDECL wined3d_get_adapter_monitor(const struct wined3d *wined3d, UINT adapter_idx)
+{
+    TRACE("wined3d %p, adapter_idx %u.\n", wined3d, adapter_idx);
+
+    if (adapter_idx >= wined3d->adapter_count)
+        return NULL;
+
+    return MonitorFromPoint(wined3d->adapters[adapter_idx].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
+}
+
+/* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
+     of the same bpp but different resolutions                                  */
+
+/* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
+UINT CDECL wined3d_get_adapter_mode_count(const struct wined3d *wined3d, UINT adapter_idx,
+        enum wined3d_format_id format_id, enum wined3d_scanline_ordering scanline_ordering)
+{
+    const struct wined3d_adapter *adapter;
+    const struct wined3d_format *format;
+    unsigned int i = 0;
+    unsigned int j = 0;
+    UINT format_bits;
+    DEVMODEW mode;
+
+    TRACE("wined3d %p, adapter_idx %u, format %s, scanline_ordering %#x.\n",
+            wined3d, adapter_idx, debug_d3dformat(format_id), scanline_ordering);
+
+    if (adapter_idx >= wined3d->adapter_count)
+        return 0;
+
+    adapter = &wined3d->adapters[adapter_idx];
+    format = wined3d_get_format(&adapter->gl_info, format_id);
+    format_bits = format->byte_count * CHAR_BIT;
+
+    memset(&mode, 0, sizeof(mode));
+    mode.dmSize = sizeof(mode);
+
+    while (EnumDisplaySettingsExW(adapter->DeviceName, j++, &mode, 0))
+    {
+        if (mode.dmFields & DM_DISPLAYFLAGS)
+        {
+            if (scanline_ordering == WINED3D_SCANLINE_ORDERING_PROGRESSIVE
+#ifndef VBOX_WINE_WITHOUT_LIBWINE
+                    && (mode.u2.dmDisplayFlags & DM_INTERLACED))
+#else
+                    && (mode.dmDisplayFlags & DM_INTERLACED))
+#endif
+                continue;
+
+            if (scanline_ordering == WINED3D_SCANLINE_ORDERING_INTERLACED
+#ifndef VBOX_WINE_WITHOUT_LIBWINE
+                    && !(mode.u2.dmDisplayFlags & DM_INTERLACED))
+#else
+                    && !(mode.dmDisplayFlags & DM_INTERLACED))
+#endif
+                continue;
+        }
+
+        if (format_id == WINED3DFMT_UNKNOWN)
+        {
+            /* This is for d3d8, do not enumerate P8 here. */
+            if (mode.dmBitsPerPel == 32 || mode.dmBitsPerPel == 16) ++i;
+        }
+        else if (mode.dmBitsPerPel == format_bits)
+        {
+            ++i;
+        }
+    }
+
+    TRACE("Returning %u matching modes (out of %u total) for adapter %u.\n", i, j, adapter_idx);
+
+    return i;
+}
+
+/* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
+HRESULT CDECL wined3d_enum_adapter_modes(const struct wined3d *wined3d, UINT adapter_idx,
+        enum wined3d_format_id format_id, enum wined3d_scanline_ordering scanline_ordering,
+        UINT mode_idx, struct wined3d_display_mode *mode)
+{
+    const struct wined3d_adapter *adapter;
+    const struct wined3d_format *format;
+    UINT format_bits;
+    DEVMODEW m;
+    UINT i = 0;
+    int j = 0;
+
+    TRACE("wined3d %p, adapter_idx %u, format %s, scanline_ordering %#x, mode_idx %u, mode %p.\n",
+            wined3d, adapter_idx, debug_d3dformat(format_id), scanline_ordering, mode_idx, mode);
+
+    if (!mode || adapter_idx >= wined3d->adapter_count)
+        return WINED3DERR_INVALIDCALL;
+
+    adapter = &wined3d->adapters[adapter_idx];
+    format = wined3d_get_format(&adapter->gl_info, format_id);
+    format_bits = format->byte_count * CHAR_BIT;
+
+    memset(&m, 0, sizeof(m));
+    m.dmSize = sizeof(m);
+
+    while (i <= mode_idx)
+    {
+        if (!EnumDisplaySettingsExW(adapter->DeviceName, j++, &m, 0))
+        {
+            WARN("Invalid mode_idx %u.\n", mode_idx);
+            return WINED3DERR_INVALIDCALL;
+        }
+
+        if (m.dmFields & DM_DISPLAYFLAGS)
+        {
+            if (scanline_ordering == WINED3D_SCANLINE_ORDERING_PROGRESSIVE
+#ifndef VBOX_WINE_WITHOUT_LIBWINE
+                    && (m.u2.dmDisplayFlags & DM_INTERLACED))
+#else
+                    && (m.dmDisplayFlags & DM_INTERLACED))
+#endif
+                continue;
+
+            if (scanline_ordering == WINED3D_SCANLINE_ORDERING_INTERLACED
+#ifndef VBOX_WINE_WITHOUT_LIBWINE
+                    && !(m.u2.dmDisplayFlags & DM_INTERLACED))
+#else
+                    && !(m.dmDisplayFlags & DM_INTERLACED))
+#endif
+                continue;
+        }
+
+        if (format_id == WINED3DFMT_UNKNOWN)
+        {
+            /* This is for d3d8, do not enumerate P8 here. */
+            if (m.dmBitsPerPel == 32 || m.dmBitsPerPel == 16) ++i;
+        }
+        else if (m.dmBitsPerPel == format_bits)
+        {
+            ++i;
+        }
+    }
+
+    mode->width = m.dmPelsWidth;
+    mode->height = m.dmPelsHeight;
+    mode->refresh_rate = DEFAULT_REFRESH_RATE;
+    if (m.dmFields & DM_DISPLAYFREQUENCY)
+        mode->refresh_rate = m.dmDisplayFrequency;
+
+    if (format_id == WINED3DFMT_UNKNOWN)
+        mode->format_id = pixelformat_for_depth(m.dmBitsPerPel);
+    else
+        mode->format_id = format_id;
+
+    if (!(m.dmFields & DM_DISPLAYFLAGS))
+        mode->scanline_ordering = WINED3D_SCANLINE_ORDERING_UNKNOWN;
+#ifndef VBOX_WINE_WITHOUT_LIBWINE
+    else if (m.u2.dmDisplayFlags & DM_INTERLACED)
+#else
+    else if (m.dmDisplayFlags & DM_INTERLACED)
+#endif
+        mode->scanline_ordering = WINED3D_SCANLINE_ORDERING_INTERLACED;
+    else
+        mode->scanline_ordering = WINED3D_SCANLINE_ORDERING_PROGRESSIVE;
+
+    TRACE("%ux%u@%u %u bpp, %s %#x.\n", mode->width, mode->height, mode->refresh_rate,
+            m.dmBitsPerPel, debug_d3dformat(mode->format_id), mode->scanline_ordering);
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_get_adapter_display_mode(const struct wined3d *wined3d, UINT adapter_idx,
+        struct wined3d_display_mode *mode, enum wined3d_display_rotation *rotation)
+{
+    const struct wined3d_adapter *adapter;
+    DEVMODEW m;
+
+    TRACE("wined3d %p, adapter_idx %u, display_mode %p, rotation %p.\n",
+            wined3d, adapter_idx, mode, rotation);
+
+    if (!mode || adapter_idx >= wined3d->adapter_count)
+        return WINED3DERR_INVALIDCALL;
+
+    adapter = &wined3d->adapters[adapter_idx];
+
+    memset(&m, 0, sizeof(m));
+    m.dmSize = sizeof(m);
+
+    EnumDisplaySettingsExW(adapter->DeviceName, ENUM_CURRENT_SETTINGS, &m, 0);
+    mode->width = m.dmPelsWidth;
+    mode->height = m.dmPelsHeight;
+    mode->refresh_rate = DEFAULT_REFRESH_RATE;
+    if (m.dmFields & DM_DISPLAYFREQUENCY)
+        mode->refresh_rate = m.dmDisplayFrequency;
+    mode->format_id = pixelformat_for_depth(m.dmBitsPerPel);
+
+    /* Lie about the format. X11 can't change the color depth, and some apps
+     * are pretty angry if they SetDisplayMode from 24 to 16 bpp and find out
+     * that GetDisplayMode still returns 24 bpp. This should probably be
+     * handled in winex11 instead. */
+    if (adapter->screen_format && adapter->screen_format != mode->format_id)
+    {
+        WARN("Overriding format %s with stored format %s.\n",
+                debug_d3dformat(mode->format_id),
+                debug_d3dformat(adapter->screen_format));
+        mode->format_id = adapter->screen_format;
+    }
+
+    if (!(m.dmFields & DM_DISPLAYFLAGS))
+        mode->scanline_ordering = WINED3D_SCANLINE_ORDERING_UNKNOWN;
+#ifndef VBOX_WINE_WITHOUT_LIBWINE
+    else if (m.u2.dmDisplayFlags & DM_INTERLACED)
+#else
+    else if (m.dmDisplayFlags & DM_INTERLACED)
+#endif
+        mode->scanline_ordering = WINED3D_SCANLINE_ORDERING_INTERLACED;
+    else
+        mode->scanline_ordering = WINED3D_SCANLINE_ORDERING_PROGRESSIVE;
+
+    if (rotation)
+    {
+#ifndef VBOX_WINE_WITHOUT_LIBWINE
+        switch (m.u1.s2.dmDisplayOrientation)
+#else
+        switch (m.dmDisplayOrientation)
+#endif
+        {
+            case DMDO_DEFAULT:
+                *rotation = WINED3D_DISPLAY_ROTATION_0;
+                break;
+            case DMDO_90:
+                *rotation = WINED3D_DISPLAY_ROTATION_90;
+                break;
+            case DMDO_180:
+                *rotation = WINED3D_DISPLAY_ROTATION_180;
+                break;
+            case DMDO_270:
+                *rotation = WINED3D_DISPLAY_ROTATION_270;
+                break;
+            default:
+#ifndef VBOX_WINE_WITHOUT_LIBWINE
+                FIXME("Unhandled display rotation %#x.\n", m.u1.s2.dmDisplayOrientation);
+#else
+                FIXME("Unhandled display rotation %#x.\n", m.dmDisplayOrientation);
+#endif
+                *rotation = WINED3D_DISPLAY_ROTATION_UNSPECIFIED;
+                break;
+        }
+    }
+
+    TRACE("Returning %ux%u@%u %s %#x.\n", mode->width, mode->height,
+            mode->refresh_rate, debug_d3dformat(mode->format_id),
+            mode->scanline_ordering);
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_set_adapter_display_mode(struct wined3d *wined3d,
+        UINT adapter_idx, const struct wined3d_display_mode *mode)
+{
+    struct wined3d_display_mode current_mode;
+    const struct wined3d_format *format;
+    struct wined3d_adapter *adapter;
+    DEVMODEW devmode;
+    RECT clip_rc;
+    HRESULT hr;
+    LONG ret;
+
+    TRACE("wined3d %p, adapter_idx %u, mode %p (%ux%u@%u %s %#x).\n", wined3d, adapter_idx, mode,
+            mode->width, mode->height, mode->refresh_rate, debug_d3dformat(mode->format_id),
+            mode->scanline_ordering);
+
+    if (adapter_idx >= wined3d->adapter_count)
+        return WINED3DERR_INVALIDCALL;
+
+    adapter = &wined3d->adapters[adapter_idx];
+    format = wined3d_get_format(&adapter->gl_info, mode->format_id);
+
+    memset(&devmode, 0, sizeof(devmode));
+    devmode.dmSize = sizeof(devmode);
+    devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
+    devmode.dmBitsPerPel = format->byte_count * CHAR_BIT;
+    devmode.dmPelsWidth = mode->width;
+    devmode.dmPelsHeight = mode->height;
+
+    devmode.dmDisplayFrequency = mode->refresh_rate;
+    if (mode->refresh_rate)
+        devmode.dmFields |= DM_DISPLAYFREQUENCY;
+
+    if (mode->scanline_ordering != WINED3D_SCANLINE_ORDERING_UNKNOWN)
+    {
+        devmode.dmFields |= DM_DISPLAYFLAGS;
+        if (mode->scanline_ordering == WINED3D_SCANLINE_ORDERING_INTERLACED)
+#ifndef VBOX_WINE_WITHOUT_LIBWINE
+            devmode.u2.dmDisplayFlags |= DM_INTERLACED;
+#else
+            devmode.dmDisplayFlags |= DM_INTERLACED;
+#endif
+    }
+
+    /* Only change the mode if necessary. */
+    if (FAILED(hr = wined3d_get_adapter_display_mode(wined3d, adapter_idx, &current_mode, NULL)))
+    {
+        ERR("Failed to get current display mode, hr %#x.\n", hr);
+    }
+    else if (current_mode.width == mode->width
+            && current_mode.height == mode->height
+            && current_mode.format_id == mode->format_id
+            && (current_mode.refresh_rate == mode->refresh_rate
+            || !mode->refresh_rate)
+            && (current_mode.scanline_ordering == mode->scanline_ordering
+            || mode->scanline_ordering == WINED3D_SCANLINE_ORDERING_UNKNOWN))
+    {
+        TRACE("Skipping redundant mode setting call.\n");
+        return WINED3D_OK;
+    }
+
+    ret = ChangeDisplaySettingsExW(adapter->DeviceName, &devmode, NULL, CDS_FULLSCREEN, NULL);
+    if (ret != DISP_CHANGE_SUCCESSFUL)
+    {
+        if (devmode.dmDisplayFrequency)
+        {
+            WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate.\n");
+            devmode.dmFields &= ~DM_DISPLAYFREQUENCY;
+            devmode.dmDisplayFrequency = 0;
+            ret = ChangeDisplaySettingsExW(adapter->DeviceName, &devmode, NULL, CDS_FULLSCREEN, NULL);
+        }
+        if (ret != DISP_CHANGE_SUCCESSFUL)
+            return WINED3DERR_NOTAVAILABLE;
+    }
+
+    /* Store the new values. */
+    adapter->screen_format = mode->format_id;
+
+    /* And finally clip mouse to our screen. */
+    SetRect(&clip_rc, 0, 0, mode->width, mode->height);
+    ClipCursor(&clip_rc);
+
+    return WINED3D_OK;
+}
+
+/* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
+   and fields being inserted in the middle, a new structure is used in place    */
+HRESULT CDECL wined3d_get_adapter_identifier(const struct wined3d *wined3d,
+        UINT adapter_idx, DWORD flags, struct wined3d_adapter_identifier *identifier)
+{
+#ifndef VBOX_WITH_WDDM
+    const struct wined3d_adapter *adapter;
+    size_t len;
+
+    TRACE("wined3d %p, adapter_idx %u, flags %#x, identifier %p.\n",
+            wined3d, adapter_idx, flags, identifier);
+
+    if (adapter_idx >= wined3d->adapter_count)
+        return WINED3DERR_INVALIDCALL;
+
+    adapter = &wined3d->adapters[adapter_idx];
+
+    if (identifier->driver_size)
+    {
+        const char *name = adapter->driver_info.name;
+        len = min(strlen(name), identifier->driver_size - 1);
+        memcpy(identifier->driver, name, len);
+        identifier->driver[len] = '\0';
+    }
+
+    if (identifier->description_size)
+    {
+        const char *description = adapter->driver_info.description;
+        len = min(strlen(description), identifier->description_size - 1);
+        memcpy(identifier->description, description, len);
+        identifier->description[len] = '\0';
+    }
+
+    /* Note that d3d8 doesn't supply a device name. */
+    if (identifier->device_name_size)
+    {
+        if (!WideCharToMultiByte(CP_ACP, 0, adapter->DeviceName, -1, identifier->device_name,
+                identifier->device_name_size, NULL, NULL))
+        {
+            ERR("Failed to convert device name, last error %#x.\n", GetLastError());
+            return WINED3DERR_INVALIDCALL;
+        }
+    }
+
+    identifier->driver_version.u.HighPart = adapter->driver_info.version_high;
+    identifier->driver_version.u.LowPart = adapter->driver_info.version_low;
+    identifier->vendor_id = adapter->driver_info.vendor;
+    identifier->device_id = adapter->driver_info.device;
+    identifier->subsystem_id = 0;
+    identifier->revision = 0;
+    memcpy(&identifier->device_identifier, &IID_D3DDEVICE_D3DUID, sizeof(identifier->device_identifier));
+    identifier->whql_level = (flags & WINED3DENUM_NO_WHQL_LEVEL) ? 0 : 1;
+    memcpy(&identifier->adapter_luid, &adapter->luid, sizeof(identifier->adapter_luid));
+    identifier->video_memory = adapter->TextureRam;
+
+    return WINED3D_OK;
+#else
+    ERR("not supported!");
+    return E_FAIL;
+#endif
+}
+
+HRESULT CDECL wined3d_get_adapter_raster_status(const struct wined3d *wined3d, UINT adapter_idx,
+        struct wined3d_raster_status *raster_status)
+{
+    LONGLONG freq_per_frame, freq_per_line;
+    LARGE_INTEGER counter, freq_per_sec;
+    struct wined3d_display_mode mode;
+    static UINT once;
+
+    if (!once++)
+        FIXME("wined3d %p, adapter_idx %u, raster_status %p semi-stub!\n",
+                wined3d, adapter_idx, raster_status);
+    else
+        WARN("wined3d %p, adapter_idx %u, raster_status %p semi-stub!\n",
+                wined3d, adapter_idx, raster_status);
+
+    /* Obtaining the raster status is a widely implemented but optional
+     * feature. When this method returns OK StarCraft 2 expects the
+     * raster_status->InVBlank value to actually change over time.
+     * And Endless Alice Crysis doesn't care even if this method fails.
+     * Thus this method returns OK and fakes raster_status by
+     * QueryPerformanceCounter. */
+
+    if (!QueryPerformanceCounter(&counter) || !QueryPerformanceFrequency(&freq_per_sec))
+        return WINED3DERR_INVALIDCALL;
+    if (FAILED(wined3d_get_adapter_display_mode(wined3d, adapter_idx, &mode, NULL)))
+        return WINED3DERR_INVALIDCALL;
+    if (mode.refresh_rate == DEFAULT_REFRESH_RATE)
+        mode.refresh_rate = 60;
+
+    freq_per_frame = freq_per_sec.QuadPart / mode.refresh_rate;
+    /* Assume 20 scan lines in the vertical blank. */
+    freq_per_line = freq_per_frame / (mode.height + 20);
+    raster_status->scan_line = (counter.QuadPart % freq_per_frame) / freq_per_line;
+    if (raster_status->scan_line < mode.height)
+        raster_status->in_vblank = FALSE;
+    else
+    {
+        raster_status->scan_line = 0;
+        raster_status->in_vblank = TRUE;
+    }
+
+    TRACE("Returning fake value, in_vblank %u, scan_line %u.\n",
+            raster_status->in_vblank, raster_status->scan_line);
+
+    return WINED3D_OK;
+}
+
+static BOOL wined3d_check_pixel_format_color(const struct wined3d_gl_info *gl_info,
+        const struct wined3d_pixel_format *cfg, const struct wined3d_format *format)
+{
+    BYTE redSize, greenSize, blueSize, alphaSize, colorBits;
+
+    /* Float formats need FBOs. If FBOs are used this function isn't called */
+    if (format->flags & WINED3DFMT_FLAG_FLOAT) return FALSE;
+
+    if(cfg->iPixelType == WGL_TYPE_RGBA_ARB) { /* Integer RGBA formats */
+        if (!getColorBits(format, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
+        {
+            ERR("Unable to check compatibility for format %s.\n", debug_d3dformat(format->id));
+            return FALSE;
+        }
+
+        if(cfg->redSize < redSize)
+            return FALSE;
+
+        if(cfg->greenSize < greenSize)
+            return FALSE;
+
+        if(cfg->blueSize < blueSize)
+            return FALSE;
+
+        if(cfg->alphaSize < alphaSize)
+            return FALSE;
+
+        return TRUE;
+    }
+
+    /* Probably a RGBA_float or color index mode */
+    return FALSE;
+}
+
+static BOOL wined3d_check_pixel_format_depth(const struct wined3d_gl_info *gl_info,
+        const struct wined3d_pixel_format *cfg, const struct wined3d_format *format)
+{
+    BYTE depthSize, stencilSize;
+    BOOL lockable = FALSE;
+
+    if (!getDepthStencilBits(format, &depthSize, &stencilSize))
+    {
+        ERR("Unable to check compatibility for format %s.\n", debug_d3dformat(format->id));
+        return FALSE;
+    }
+
+    /* Float formats need FBOs. If FBOs are used this function isn't called */
+    if (format->flags & WINED3DFMT_FLAG_FLOAT) return FALSE;
+
+    if ((format->id == WINED3DFMT_D16_LOCKABLE) || (format->id == WINED3DFMT_D32_FLOAT))
+        lockable = TRUE;
+
+    /* On some modern cards like the Geforce8/9 GLX doesn't offer some dephthstencil formats which D3D9 reports.
+     * We can safely report 'compatible' formats (e.g. D24 can be used for D16) as long as we aren't dealing with
+     * a lockable format. This also helps D3D <= 7 as they expect D16 which isn't offered without this on Geforce8 cards. */
+    if(!(cfg->depthSize == depthSize || (!lockable && cfg->depthSize > depthSize)))
+        return FALSE;
+
+    /* Some cards like Intel i915 ones only offer D24S8 but lots of games also need a format without stencil, so
+     * allow more stencil bits than requested. */
+    if(cfg->stencilSize < stencilSize)
+        return FALSE;
+
+    return TRUE;
+}
+
+HRESULT CDECL wined3d_check_depth_stencil_match(const struct wined3d *wined3d,
+        UINT adapter_idx, enum wined3d_device_type device_type, enum wined3d_format_id adapter_format_id,
+        enum wined3d_format_id render_target_format_id, enum wined3d_format_id depth_stencil_format_id)
+{
+    const struct wined3d_format *rt_format;
+    const struct wined3d_format *ds_format;
+    const struct wined3d_adapter *adapter;
+
+    TRACE("wined3d %p, adapter_idx %u, device_type %s,\n"
+            "adapter_format %s, render_target_format %s, depth_stencil_format %s.\n",
+            wined3d, adapter_idx, debug_d3ddevicetype(device_type), debug_d3dformat(adapter_format_id),
+            debug_d3dformat(render_target_format_id), debug_d3dformat(depth_stencil_format_id));
+
+    if (adapter_idx >= wined3d->adapter_count)
+        return WINED3DERR_INVALIDCALL;
+
+    adapter = &wined3d->adapters[adapter_idx];
+    rt_format = wined3d_get_format(&adapter->gl_info, render_target_format_id);
+    ds_format = wined3d_get_format(&adapter->gl_info, depth_stencil_format_id);
+    if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
+    {
+        if ((rt_format->flags & WINED3DFMT_FLAG_RENDERTARGET)
+                && (ds_format->flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)))
+        {
+            TRACE("Formats match.\n");
+            return WINED3D_OK;
+        }
+    }
+    else
+    {
+        const struct wined3d_pixel_format *cfgs;
+        unsigned int cfg_count;
+        unsigned int i;
+
+        cfgs = adapter->cfgs;
+        cfg_count = adapter->cfg_count;
+        for (i = 0; i < cfg_count; ++i)
+        {
+            if (wined3d_check_pixel_format_color(&adapter->gl_info, &cfgs[i], rt_format)
+                    && wined3d_check_pixel_format_depth(&adapter->gl_info, &cfgs[i], ds_format))
+            {
+                TRACE("Formats match.\n");
+                return WINED3D_OK;
+            }
+        }
+    }
+
+    TRACE("Unsupported format pair: %s and %s.\n",
+            debug_d3dformat(render_target_format_id),
+            debug_d3dformat(depth_stencil_format_id));
+
+    return WINED3DERR_NOTAVAILABLE;
+}
+
+HRESULT CDECL wined3d_check_device_multisample_type(const struct wined3d *wined3d, UINT adapter_idx,
+        enum wined3d_device_type device_type, enum wined3d_format_id surface_format_id, BOOL windowed,
+        enum wined3d_multisample_type multisample_type, DWORD *quality_levels)
+{
+    const struct wined3d_gl_info *gl_info;
+
+    TRACE("wined3d %p, adapter_idx %u, device_type %s, surface_format %s,\n"
+            "windowed %#x, multisample_type %#x, quality_levels %p.\n",
+            wined3d, adapter_idx, debug_d3ddevicetype(device_type), debug_d3dformat(surface_format_id),
+            windowed, multisample_type, quality_levels);
+
+    if (adapter_idx >= wined3d->adapter_count)
+        return WINED3DERR_INVALIDCALL;
+
+    gl_info = &wined3d->adapters[adapter_idx].gl_info;
+
+    if (multisample_type > gl_info->limits.samples)
+    {
+        TRACE("Returning not supported.\n");
+        if (quality_levels)
+            *quality_levels = 0;
+
+        return WINED3DERR_NOTAVAILABLE;
+    }
+
+    if (quality_levels)
+    {
+        if (multisample_type == WINED3D_MULTISAMPLE_NON_MASKABLE)
+            /* FIXME: This is probably wrong. */
+            *quality_levels = gl_info->limits.samples;
+        else
+            *quality_levels = 1;
+    }
+
+    return WINED3D_OK;
+}
+
+/* Check if the given DisplayFormat + DepthStencilFormat combination is valid for the Adapter */
+static BOOL CheckDepthStencilCapability(const struct wined3d_adapter *adapter,
+        const struct wined3d_format *display_format, const struct wined3d_format *ds_format)
+{
+    /* Only allow depth/stencil formats */
+    if (!(ds_format->depth_size || ds_format->stencil_size)) return FALSE;
+
+    /* Blacklist formats not supported on Windows */
+    switch (ds_format->id)
+    {
+        case WINED3DFMT_S1_UINT_D15_UNORM: /* Breaks the shadowvol2 dx7 sdk sample */
+        case WINED3DFMT_S4X4_UINT_D24_UNORM:
+            TRACE("[FAILED] - not supported on windows.\n");
+            return FALSE;
+
+        default:
+            break;
+    }
+
+    if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
+    {
+        /* With FBOs WGL limitations do not apply, but the format needs to be FBO attachable */
+        if (ds_format->flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) return TRUE;
+    }
+    else
+    {
+        unsigned int i;
+
+        /* Walk through all WGL pixel formats to find a match */
+        for (i = 0; i < adapter->cfg_count; ++i)
+        {
+            const struct wined3d_pixel_format *cfg = &adapter->cfgs[i];
+            if (wined3d_check_pixel_format_color(&adapter->gl_info, cfg, display_format)
+                    && wined3d_check_pixel_format_depth(&adapter->gl_info, cfg, ds_format))
+                return TRUE;
+        }
+    }
+
+    return FALSE;
+}
+
+/* Check the render target capabilities of a format */
+static BOOL CheckRenderTargetCapability(const struct wined3d_adapter *adapter,
+        const struct wined3d_format *adapter_format, const struct wined3d_format *check_format)
+{
+    /* Filter out non-RT formats */
+    if (!(check_format->flags & WINED3DFMT_FLAG_RENDERTARGET)) return FALSE;
+    if (wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER)
+    {
+        BYTE AdapterRed, AdapterGreen, AdapterBlue, AdapterAlpha, AdapterTotalSize;
+        BYTE CheckRed, CheckGreen, CheckBlue, CheckAlpha, CheckTotalSize;
+        const struct wined3d_pixel_format *cfgs = adapter->cfgs;
+        unsigned int i;
+
+        getColorBits(adapter_format, &AdapterRed, &AdapterGreen, &AdapterBlue, &AdapterAlpha, &AdapterTotalSize);
+        getColorBits(check_format, &CheckRed, &CheckGreen, &CheckBlue, &CheckAlpha, &CheckTotalSize);
+
+        /* In backbuffer mode the front and backbuffer share the same WGL pixelformat.
+         * The format must match in RGB, alpha is allowed to be different. (Only the backbuffer can have alpha) */
+        if (!((AdapterRed == CheckRed) && (AdapterGreen == CheckGreen) && (AdapterBlue == CheckBlue)))
+        {
+            TRACE("[FAILED]\n");
+            return FALSE;
+        }
+
+        /* Check if there is a WGL pixel format matching the requirements, the format should also be window
+         * drawable (not offscreen; e.g. Nvidia offers R5G6B5 for pbuffers even when X is running at 24bit) */
+        for (i = 0; i < adapter->cfg_count; ++i)
+        {
+            if (cfgs[i].windowDrawable
+                    && wined3d_check_pixel_format_color(&adapter->gl_info, &cfgs[i], check_format))
+            {
+                TRACE("Pixel format %d is compatible with format %s.\n",
+                        cfgs[i].iPixelFormat, debug_d3dformat(check_format->id));
+                return TRUE;
+            }
+        }
+    }
+    else if(wined3d_settings.offscreen_rendering_mode == ORM_FBO)
+    {
+        /* For now return TRUE for FBOs until we have some proper checks.
+         * Note that this function will only be called when the format is around for texturing. */
+        return TRUE;
+    }
+    return FALSE;
+}
+
+static BOOL CheckSurfaceCapability(const struct wined3d_adapter *adapter,
+        const struct wined3d_format *adapter_format,
+        const struct wined3d_format *check_format, BOOL no3d)
+{
+    if (no3d)
+    {
+        switch (check_format->id)
+        {
+            case WINED3DFMT_B8G8R8_UNORM:
+                TRACE("[FAILED] - Not enumerated on Windows.\n");
+                return FALSE;
+            case WINED3DFMT_B8G8R8A8_UNORM:
+            case WINED3DFMT_B8G8R8X8_UNORM:
+            case WINED3DFMT_B5G6R5_UNORM:
+            case WINED3DFMT_B5G5R5X1_UNORM:
+            case WINED3DFMT_B5G5R5A1_UNORM:
+            case WINED3DFMT_B4G4R4A4_UNORM:
+            case WINED3DFMT_B2G3R3_UNORM:
+            case WINED3DFMT_A8_UNORM:
+            case WINED3DFMT_B2G3R3A8_UNORM:
+            case WINED3DFMT_B4G4R4X4_UNORM:
+            case WINED3DFMT_R10G10B10A2_UNORM:
+            case WINED3DFMT_R8G8B8A8_UNORM:
+            case WINED3DFMT_R8G8B8X8_UNORM:
+            case WINED3DFMT_R16G16_UNORM:
+            case WINED3DFMT_B10G10R10A2_UNORM:
+            case WINED3DFMT_R16G16B16A16_UNORM:
+            case WINED3DFMT_P8_UINT:
+                TRACE("[OK]\n");
+                return TRUE;
+            default:
+                TRACE("[FAILED] - Not available on GDI surfaces.\n");
+                return FALSE;
+        }
+    }
+
+    /* All formats that are supported for textures are supported for surfaces
+     * as well. */
+    if (check_format->flags & WINED3DFMT_FLAG_TEXTURE)
+        return TRUE;
+
+    /* All depth stencil formats are supported on surfaces */
+    if (CheckDepthStencilCapability(adapter, adapter_format, check_format)) return TRUE;
+
+    /* If opengl can't process the format natively, the blitter may be able to convert it */
+    if (adapter->blitter->blit_supported(&adapter->gl_info, WINED3D_BLIT_OP_COLOR_BLIT,
+            NULL, WINED3D_POOL_DEFAULT, 0, check_format,
+            NULL, WINED3D_POOL_DEFAULT, 0, adapter_format))
+    {
+        TRACE("[OK]\n");
+        return TRUE;
+    }
+
+    /* Reject other formats */
+    TRACE("[FAILED]\n");
+    return FALSE;
+}
+
+/* OpenGL supports mipmapping on all formats. Wrapping is unsupported, but we
+ * have to report mipmapping so we cannot reject WRAPANDMIP. Tests show that
+ * Windows reports WRAPANDMIP on unfilterable surfaces as well, apparently to
+ * show that wrapping is supported. The lack of filtering will sort out the
+ * mipmapping capability anyway.
+ *
+ * For now lets report this on all formats, but in the future we may want to
+ * restrict it to some should applications need that. */
+HRESULT CDECL wined3d_check_device_format(const struct wined3d *wined3d, UINT adapter_idx,
+        enum wined3d_device_type device_type, enum wined3d_format_id adapter_format_id, DWORD usage,
+        enum wined3d_resource_type resource_type, enum wined3d_format_id check_format_id)
+{
+    const struct wined3d_adapter *adapter = &wined3d->adapters[adapter_idx];
+    const struct wined3d_gl_info *gl_info = &adapter->gl_info;
+    const struct wined3d_format *adapter_format = wined3d_get_format(gl_info, adapter_format_id);
+    const struct wined3d_format *format = wined3d_get_format(gl_info, check_format_id);
+    DWORD format_flags = 0;
+    DWORD allowed_usage;
+
+    TRACE("wined3d %p, adapter_idx %u, device_type %s, adapter_format %s, usage %s, %s,\n"
+            "resource_type %s, check_format %s.\n",
+            wined3d, adapter_idx, debug_d3ddevicetype(device_type), debug_d3dformat(adapter_format_id),
+            debug_d3dusage(usage), debug_d3dusagequery(usage), debug_d3dresourcetype(resource_type),
+            debug_d3dformat(check_format_id));
+
+    if (adapter_idx >= wined3d->adapter_count)
+        return WINED3DERR_INVALIDCALL;
+
+    switch (resource_type)
+    {
+        case WINED3D_RTYPE_CUBE_TEXTURE:
+            if (!gl_info->supported[ARB_TEXTURE_CUBE_MAP])
+            {
+                TRACE("[FAILED] - No cube texture support.\n");
+                return WINED3DERR_NOTAVAILABLE;
+            }
+
+            format_flags |= WINED3DFMT_FLAG_TEXTURE;
+            allowed_usage = WINED3DUSAGE_AUTOGENMIPMAP
+                    | WINED3DUSAGE_DYNAMIC
+                    | WINED3DUSAGE_RENDERTARGET
+                    | WINED3DUSAGE_SOFTWAREPROCESSING
+                    | WINED3DUSAGE_QUERY_FILTER
+                    | WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING
+                    | WINED3DUSAGE_QUERY_SRGBREAD
+                    | WINED3DUSAGE_QUERY_SRGBWRITE
+                    | WINED3DUSAGE_QUERY_VERTEXTEXTURE
+                    | WINED3DUSAGE_QUERY_WRAPANDMIP;
+            break;
+
+        case WINED3D_RTYPE_SURFACE:
+            if (!CheckSurfaceCapability(adapter, adapter_format, format, wined3d->flags & WINED3D_NO3D))
+            {
+                TRACE("[FAILED] - Not supported for plain surfaces.\n");
+                return WINED3DERR_NOTAVAILABLE;
+            }
+
+            allowed_usage = WINED3DUSAGE_DEPTHSTENCIL
+                    | WINED3DUSAGE_RENDERTARGET
+                    | WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
+            break;
+
+        case WINED3D_RTYPE_TEXTURE:
+            if ((usage & WINED3DUSAGE_DEPTHSTENCIL) && (format->flags & WINED3DFMT_FLAG_SHADOW)
+                    && !gl_info->supported[ARB_SHADOW])
+            {
+                TRACE("[FAILED] - No shadow sampler support.\n");
+                return WINED3DERR_NOTAVAILABLE;
+            }
+
+            format_flags |= WINED3DFMT_FLAG_TEXTURE;
+            allowed_usage = WINED3DUSAGE_AUTOGENMIPMAP
+                    | WINED3DUSAGE_DEPTHSTENCIL
+                    | WINED3DUSAGE_DYNAMIC
+                    | WINED3DUSAGE_RENDERTARGET
+                    | WINED3DUSAGE_SOFTWAREPROCESSING
+                    | WINED3DUSAGE_QUERY_FILTER
+                    | WINED3DUSAGE_QUERY_LEGACYBUMPMAP
+                    | WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING
+                    | WINED3DUSAGE_QUERY_SRGBREAD
+                    | WINED3DUSAGE_QUERY_SRGBWRITE
+                    | WINED3DUSAGE_QUERY_VERTEXTEXTURE
+                    | WINED3DUSAGE_QUERY_WRAPANDMIP;
+            break;
+
+        case WINED3D_RTYPE_VOLUME_TEXTURE:
+        case WINED3D_RTYPE_VOLUME:
+            /* Volume is to VolumeTexture what Surface is to Texture, but its
+             * usage caps are not documented. Most driver seem to offer
+             * (nearly) the same on Volume and VolumeTexture, so do that too. */
+            if (!gl_info->supported[EXT_TEXTURE3D])
+            {
+                TRACE("[FAILED] - No volume texture support.\n");
+                return WINED3DERR_NOTAVAILABLE;
+            }
+
+            /* Filter formats that need conversion; For one part, this
+             * conversion is unimplemented, and volume textures are huge, so
+             * it would be a big performance hit. Unless we hit an application
+             * needing one of those formats, don't advertize them to avoid
+             * leading applications into temptation. The windows drivers don't
+             * support most of those formats on volumes anyway. */
+            if (format->convert)
+            {
+                TRACE("[FAILED] - No converted formats on volumes.\n");
+                return WINED3DERR_NOTAVAILABLE;
+            }
+
+            /* The GL_EXT_texture_compression_s3tc spec requires that loading
+             * an s3tc compressed texture results in an error. While the D3D
+             * refrast does support s3tc volumes, at least the nvidia Windows
+             * driver does not, so we're free not to support this format. */
+            switch (check_format_id)
+            {
+                case WINED3DFMT_DXT1:
+                case WINED3DFMT_DXT2:
+                case WINED3DFMT_DXT3:
+                case WINED3DFMT_DXT4:
+                case WINED3DFMT_DXT5:
+                    TRACE("[FAILED] - DXTn does not support 3D textures.\n");
+                    return WINED3DERR_NOTAVAILABLE;
+
+                default:
+                    /* Do nothing, continue with checking the format below */
+                    break;
+            }
+
+            format_flags |= WINED3DFMT_FLAG_TEXTURE;
+            allowed_usage = WINED3DUSAGE_DYNAMIC
+                    | WINED3DUSAGE_SOFTWAREPROCESSING
+                    | WINED3DUSAGE_QUERY_FILTER
+                    | WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING
+                    | WINED3DUSAGE_QUERY_SRGBREAD
+                    | WINED3DUSAGE_QUERY_SRGBWRITE
+                    | WINED3DUSAGE_QUERY_VERTEXTEXTURE
+                    | WINED3DUSAGE_QUERY_WRAPANDMIP;
+            break;
+
+        default:
+            FIXME("Unhandled resource type %s.\n", debug_d3dresourcetype(resource_type));
+                    return WINED3DERR_NOTAVAILABLE;
+                }
+
+    if ((usage & allowed_usage) != usage)
+                {
+        TRACE("Requested usage %#x, but resource type %s only allows %#x.\n",
+                usage, debug_d3dresourcetype(resource_type), allowed_usage);
+                    return WINED3DERR_NOTAVAILABLE;
+                }
+
+    if (usage & WINED3DUSAGE_QUERY_FILTER)
+        format_flags |= WINED3DFMT_FLAG_FILTERING;
+    if (usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING)
+        format_flags |= WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING;
+            if (usage & WINED3DUSAGE_QUERY_SRGBREAD)
+        format_flags |= WINED3DFMT_FLAG_SRGB_READ;
+    if (usage & WINED3DUSAGE_QUERY_SRGBWRITE)
+        format_flags |= WINED3DFMT_FLAG_SRGB_WRITE;
+    if (usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE)
+        format_flags |= WINED3DFMT_FLAG_VTF;
+    if (usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP)
+        format_flags |= WINED3DFMT_FLAG_BUMPMAP;
+
+    if ((format->flags & format_flags) != format_flags)
+            {
+        TRACE("Requested format flags %#x, but format %s only has %#x.\n",
+                format_flags, debug_d3dformat(check_format_id), format->flags);
+                    return WINED3DERR_NOTAVAILABLE;
+                }
+
+    if ((format_flags & WINED3DFMT_FLAG_TEXTURE) && (wined3d->flags & WINED3D_NO3D))
+                {
+        TRACE("Requested texturing support, but wined3d was created with WINED3D_NO3D.\n");
+                    return WINED3DERR_NOTAVAILABLE;
+                }
+
+    if ((usage & WINED3DUSAGE_DEPTHSTENCIL)
+            && !CheckDepthStencilCapability(adapter, adapter_format, format))
+                {
+        TRACE("Requested WINED3DUSAGE_DEPTHSTENCIL, but format %s is not supported for depth / stencil buffers.\n",
+                debug_d3dformat(check_format_id));
+                    return WINED3DERR_NOTAVAILABLE;
+                }
+
+    if ((usage & WINED3DUSAGE_RENDERTARGET)
+            && !CheckRenderTargetCapability(adapter, adapter_format, format))
+    {
+        TRACE("Requested WINED3DUSAGE_RENDERTARGET, but format %s is not supported for render targets.\n",
+                debug_d3dformat(check_format_id));
+            return WINED3DERR_NOTAVAILABLE;
+    }
+
+    if ((usage & WINED3DUSAGE_AUTOGENMIPMAP) && !gl_info->supported[SGIS_GENERATE_MIPMAP])
+    {
+        TRACE("No WINED3DUSAGE_AUTOGENMIPMAP support, returning WINED3DOK_NOAUTOGEN.\n");
+        return WINED3DOK_NOAUTOGEN;
+    }
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_check_device_format_conversion(const struct wined3d *wined3d, UINT adapter_idx,
+        enum wined3d_device_type device_type, enum wined3d_format_id src_format, enum wined3d_format_id dst_format)
+{
+    FIXME("wined3d %p, adapter_idx %u, device_type %s, src_format %s, dst_format %s stub!\n",
+            wined3d, adapter_idx, debug_d3ddevicetype(device_type), debug_d3dformat(src_format),
+            debug_d3dformat(dst_format));
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_check_device_type(const struct wined3d *wined3d, UINT adapter_idx,
+        enum wined3d_device_type device_type, enum wined3d_format_id display_format,
+        enum wined3d_format_id backbuffer_format, BOOL windowed)
+{
+    UINT mode_count;
+    HRESULT hr;
+
+    TRACE("wined3d %p, adapter_idx %u, device_type %s, display_format %s, backbuffer_format %s, windowed %#x.\n",
+            wined3d, adapter_idx, debug_d3ddevicetype(device_type), debug_d3dformat(display_format),
+            debug_d3dformat(backbuffer_format), windowed);
+
+    if (adapter_idx >= wined3d->adapter_count)
+        return WINED3DERR_INVALIDCALL;
+
+    /* The task of this function is to check whether a certain display / backbuffer format
+     * combination is available on the given adapter. In fullscreen mode microsoft specified
+     * that the display format shouldn't provide alpha and that ignoring alpha the backbuffer
+     * and display format should match exactly.
+     * In windowed mode format conversion can occur and this depends on the driver. When format
+     * conversion is done, this function should nevertheless fail and applications need to use
+     * CheckDeviceFormatConversion.
+     * At the moment we assume that fullscreen and windowed have the same capabilities. */
+
+    /* There are only 4 display formats. */
+    if (!(display_format == WINED3DFMT_B5G6R5_UNORM
+            || display_format == WINED3DFMT_B5G5R5X1_UNORM
+            || display_format == WINED3DFMT_B8G8R8X8_UNORM
+            || display_format == WINED3DFMT_B10G10R10A2_UNORM))
+    {
+        TRACE("Format %s is not supported as display format.\n", debug_d3dformat(display_format));
+        return WINED3DERR_NOTAVAILABLE;
+    }
+
+    /* If the requested display format is not available, don't continue. */
+    mode_count = wined3d_get_adapter_mode_count(wined3d, adapter_idx,
+            display_format, WINED3D_SCANLINE_ORDERING_UNKNOWN);
+    if (!mode_count)
+    {
+        TRACE("No available modes for display format %s.\n", debug_d3dformat(display_format));
+        return WINED3DERR_NOTAVAILABLE;
+    }
+
+    /* Windowed mode allows you to specify WINED3DFMT_UNKNOWN for the backbuffer format,
+     * it means 'reuse' the display format for the backbuffer. */
+    if (!windowed && backbuffer_format == WINED3DFMT_UNKNOWN)
+    {
+        TRACE("backbuffer_format WINED3FMT_UNKNOWN only available in windowed mode.\n");
+        return WINED3DERR_NOTAVAILABLE;
+    }
+
+    /* In FULLSCREEN mode WINED3DFMT_B5G6R5_UNORM can only be mixed with
+     * backbuffer format WINED3DFMT_B5G6R5_UNORM. */
+    if (display_format == WINED3DFMT_B5G6R5_UNORM && backbuffer_format != WINED3DFMT_B5G6R5_UNORM)
+    {
+        TRACE("Unsupported display/backbuffer format combination %s / %s.\n",
+                debug_d3dformat(display_format), debug_d3dformat(backbuffer_format));
+        return WINED3DERR_NOTAVAILABLE;
+    }
+
+    /* In FULLSCREEN mode WINED3DFMT_B5G5R5X1_UNORM can only be mixed with
+     * backbuffer formats WINED3DFMT_B5G5R5X1_UNORM and
+     * WINED3DFMT_B5G5R5A1_UNORM. */
+    if (display_format == WINED3DFMT_B5G5R5X1_UNORM
+            && !(backbuffer_format == WINED3DFMT_B5G5R5X1_UNORM || backbuffer_format == WINED3DFMT_B5G5R5A1_UNORM))
+    {
+        TRACE("Unsupported display/backbuffer format combination %s / %s.\n",
+                debug_d3dformat(display_format), debug_d3dformat(backbuffer_format));
+        return WINED3DERR_NOTAVAILABLE;
+    }
+
+    /* In FULLSCREEN mode WINED3DFMT_B8G8R8X8_UNORM can only be mixed with
+     * backbuffer formats WINED3DFMT_B8G8R8X8_UNORM and
+     * WINED3DFMT_B8G8R8A8_UNORM. */
+    if (display_format == WINED3DFMT_B8G8R8X8_UNORM
+            && !(backbuffer_format == WINED3DFMT_B8G8R8X8_UNORM || backbuffer_format == WINED3DFMT_B8G8R8A8_UNORM))
+    {
+        TRACE("Unsupported display/backbuffer format combination %s / %s.\n",
+                debug_d3dformat(display_format), debug_d3dformat(backbuffer_format));
+        return WINED3DERR_NOTAVAILABLE;
+    }
+
+    /* WINED3DFMT_B10G10R10A2_UNORM is only allowed in fullscreen mode and it
+     * can only be mixed with backbuffer format WINED3DFMT_B10G10R10A2_UNORM. */
+    if (display_format == WINED3DFMT_B10G10R10A2_UNORM
+            && (backbuffer_format != WINED3DFMT_B10G10R10A2_UNORM || windowed))
+    {
+        TRACE("Unsupported display/backbuffer format combination %s / %s.\n",
+                debug_d3dformat(display_format), debug_d3dformat(backbuffer_format));
+        return WINED3DERR_NOTAVAILABLE;
+    }
+
+    /* Use CheckDeviceFormat to see if the backbuffer_format is usable with the given display_format */
+    hr = wined3d_check_device_format(wined3d, adapter_idx, device_type, display_format,
+            WINED3DUSAGE_RENDERTARGET, WINED3D_RTYPE_SURFACE, backbuffer_format);
+    if (FAILED(hr))
+        TRACE("Unsupported display/backbuffer format combination %s / %s.\n",
+                debug_d3dformat(display_format), debug_d3dformat(backbuffer_format));
+
+    return hr;
+}
+
+HRESULT CDECL wined3d_get_device_caps(const struct wined3d *wined3d, UINT adapter_idx,
+        enum wined3d_device_type device_type, WINED3DCAPS *caps)
+{
+    const struct wined3d_adapter *adapter = &wined3d->adapters[adapter_idx];
+    const struct wined3d_gl_info *gl_info = &adapter->gl_info;
+    struct shader_caps shader_caps;
+    struct fragment_caps fragment_caps;
+    struct wined3d_vertex_caps vertex_caps;
+    DWORD ckey_caps, blit_caps, fx_caps, pal_caps;
+
+    TRACE("wined3d %p, adapter_idx %u, device_type %s, caps %p.\n",
+            wined3d, adapter_idx, debug_d3ddevicetype(device_type), caps);
+
+    if (adapter_idx >= wined3d->adapter_count)
+        return WINED3DERR_INVALIDCALL;
+
+    caps->DeviceType = (device_type == WINED3D_DEVICE_TYPE_HAL) ? WINED3D_DEVICE_TYPE_HAL : WINED3D_DEVICE_TYPE_REF;
+    caps->AdapterOrdinal           = adapter_idx;
+
+    caps->Caps                     = 0;
+    caps->Caps2                    = WINED3DCAPS2_CANRENDERWINDOWED |
+                                     WINED3DCAPS2_FULLSCREENGAMMA |
+                                     WINED3DCAPS2_DYNAMICTEXTURES;
+    if (gl_info->supported[SGIS_GENERATE_MIPMAP])
+        caps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP;
+
+    caps->Caps3                    = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD |
+                                     WINED3DCAPS3_COPY_TO_VIDMEM                   |
+                                     WINED3DCAPS3_COPY_TO_SYSTEMMEM;
+
+    caps->PresentationIntervals    = WINED3DPRESENT_INTERVAL_IMMEDIATE  |
+                                     WINED3DPRESENT_INTERVAL_ONE;
+
+    caps->CursorCaps               = WINED3DCURSORCAPS_COLOR            |
+                                     WINED3DCURSORCAPS_LOWRES;
+
+    caps->DevCaps                  = WINED3DDEVCAPS_FLOATTLVERTEX       |
+                                     WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
+                                     WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
+                                     WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
+                                     WINED3DDEVCAPS_DRAWPRIMTLVERTEX    |
+                                     WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
+                                     WINED3DDEVCAPS_EXECUTEVIDEOMEMORY  |
+                                     WINED3DDEVCAPS_PUREDEVICE          |
+                                     WINED3DDEVCAPS_HWRASTERIZATION     |
+                                     WINED3DDEVCAPS_TEXTUREVIDEOMEMORY  |
+                                     WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
+                                     WINED3DDEVCAPS_CANRENDERAFTERFLIP  |
+                                     WINED3DDEVCAPS_DRAWPRIMITIVES2     |
+                                     WINED3DDEVCAPS_DRAWPRIMITIVES2EX;
+
+    caps->PrimitiveMiscCaps        = WINED3DPMISCCAPS_CULLNONE              |
+                                     WINED3DPMISCCAPS_CULLCCW               |
+                                     WINED3DPMISCCAPS_CULLCW                |
+                                     WINED3DPMISCCAPS_COLORWRITEENABLE      |
+                                     WINED3DPMISCCAPS_CLIPTLVERTS           |
+                                     WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
+                                     WINED3DPMISCCAPS_MASKZ                 |
+                                     WINED3DPMISCCAPS_BLENDOP               |
+                                     WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING;
+                                    /* TODO:
+                                        WINED3DPMISCCAPS_NULLREFERENCE
+                                        WINED3DPMISCCAPS_FOGANDSPECULARALPHA
+                                        WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
+                                        WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
+
+    if (gl_info->supported[EXT_BLEND_EQUATION_SEPARATE] && gl_info->supported[EXT_BLEND_FUNC_SEPARATE])
+        caps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_SEPARATEALPHABLEND;
+    if (gl_info->supported[EXT_DRAW_BUFFERS2])
+        caps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS;
+    if (gl_info->supported[ARB_FRAMEBUFFER_SRGB])
+        caps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_POSTBLENDSRGBCONVERT;
+
+    caps->RasterCaps               = WINED3DPRASTERCAPS_DITHER    |
+                                     WINED3DPRASTERCAPS_PAT       |
+                                     WINED3DPRASTERCAPS_WFOG      |
+                                     WINED3DPRASTERCAPS_ZFOG      |
+                                     WINED3DPRASTERCAPS_FOGVERTEX |
+                                     WINED3DPRASTERCAPS_FOGTABLE  |
+                                     WINED3DPRASTERCAPS_STIPPLE   |
+                                     WINED3DPRASTERCAPS_SUBPIXEL  |
+                                     WINED3DPRASTERCAPS_ZTEST     |
+                                     WINED3DPRASTERCAPS_SCISSORTEST   |
+                                     WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
+                                     WINED3DPRASTERCAPS_DEPTHBIAS;
+
+    if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
+    {
+        caps->RasterCaps  |= WINED3DPRASTERCAPS_ANISOTROPY    |
+                             WINED3DPRASTERCAPS_ZBIAS         |
+                             WINED3DPRASTERCAPS_MIPMAPLODBIAS;
+    }
+
+    caps->ZCmpCaps =  WINED3DPCMPCAPS_ALWAYS       |
+                      WINED3DPCMPCAPS_EQUAL        |
+                      WINED3DPCMPCAPS_GREATER      |
+                      WINED3DPCMPCAPS_GREATEREQUAL |
+                      WINED3DPCMPCAPS_LESS         |
+                      WINED3DPCMPCAPS_LESSEQUAL    |
+                      WINED3DPCMPCAPS_NEVER        |
+                      WINED3DPCMPCAPS_NOTEQUAL;
+
+    caps->SrcBlendCaps  =  WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
+                           WINED3DPBLENDCAPS_BOTHSRCALPHA    |
+                           WINED3DPBLENDCAPS_DESTALPHA       |
+                           WINED3DPBLENDCAPS_DESTCOLOR       |
+                           WINED3DPBLENDCAPS_INVDESTALPHA    |
+                           WINED3DPBLENDCAPS_INVDESTCOLOR    |
+                           WINED3DPBLENDCAPS_INVSRCALPHA     |
+                           WINED3DPBLENDCAPS_INVSRCCOLOR     |
+                           WINED3DPBLENDCAPS_ONE             |
+                           WINED3DPBLENDCAPS_SRCALPHA        |
+                           WINED3DPBLENDCAPS_SRCALPHASAT     |
+                           WINED3DPBLENDCAPS_SRCCOLOR        |
+                           WINED3DPBLENDCAPS_ZERO;
+
+    caps->DestBlendCaps =  WINED3DPBLENDCAPS_DESTALPHA       |
+                           WINED3DPBLENDCAPS_DESTCOLOR       |
+                           WINED3DPBLENDCAPS_INVDESTALPHA    |
+                           WINED3DPBLENDCAPS_INVDESTCOLOR    |
+                           WINED3DPBLENDCAPS_INVSRCALPHA     |
+                           WINED3DPBLENDCAPS_INVSRCCOLOR     |
+                           WINED3DPBLENDCAPS_ONE             |
+                           WINED3DPBLENDCAPS_SRCALPHA        |
+                           WINED3DPBLENDCAPS_SRCCOLOR        |
+                           WINED3DPBLENDCAPS_ZERO;
+    /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
+     * according to the glBlendFunc manpage
+     *
+     * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
+     * legacy settings for srcblend only
+     */
+
+    if (gl_info->supported[EXT_BLEND_COLOR])
+    {
+        caps->SrcBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
+        caps->DestBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
+    }
+
+
+    caps->AlphaCmpCaps  = WINED3DPCMPCAPS_ALWAYS       |
+                          WINED3DPCMPCAPS_EQUAL        |
+                          WINED3DPCMPCAPS_GREATER      |
+                          WINED3DPCMPCAPS_GREATEREQUAL |
+                          WINED3DPCMPCAPS_LESS         |
+                          WINED3DPCMPCAPS_LESSEQUAL    |
+                          WINED3DPCMPCAPS_NEVER        |
+                          WINED3DPCMPCAPS_NOTEQUAL;
+
+    caps->ShadeCaps      = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
+                           WINED3DPSHADECAPS_COLORGOURAUDRGB    |
+                           WINED3DPSHADECAPS_ALPHAFLATBLEND     |
+                           WINED3DPSHADECAPS_ALPHAGOURAUDBLEND  |
+                           WINED3DPSHADECAPS_COLORFLATRGB       |
+                           WINED3DPSHADECAPS_FOGFLAT            |
+                           WINED3DPSHADECAPS_FOGGOURAUD         |
+                           WINED3DPSHADECAPS_SPECULARFLATRGB;
+
+    caps->TextureCaps   = WINED3DPTEXTURECAPS_ALPHA              |
+                          WINED3DPTEXTURECAPS_ALPHAPALETTE       |
+                          WINED3DPTEXTURECAPS_TRANSPARENCY       |
+                          WINED3DPTEXTURECAPS_BORDER             |
+                          WINED3DPTEXTURECAPS_MIPMAP             |
+                          WINED3DPTEXTURECAPS_PROJECTED          |
+                          WINED3DPTEXTURECAPS_PERSPECTIVE;
+
+    if (!gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
+    {
+        caps->TextureCaps  |= WINED3DPTEXTURECAPS_POW2 |
+                              WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
+    }
+
+    if (gl_info->supported[EXT_TEXTURE3D])
+    {
+        caps->TextureCaps  |=  WINED3DPTEXTURECAPS_VOLUMEMAP      |
+                               WINED3DPTEXTURECAPS_MIPVOLUMEMAP;
+        if (!gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
+        {
+            caps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
+        }
+    }
+
+    if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
+    {
+        caps->TextureCaps  |= WINED3DPTEXTURECAPS_CUBEMAP     |
+                              WINED3DPTEXTURECAPS_MIPCUBEMAP;
+        if (!gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
+        {
+            caps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP_POW2;
+        }
+    }
+
+    caps->TextureFilterCaps =  WINED3DPTFILTERCAPS_MAGFLINEAR       |
+                               WINED3DPTFILTERCAPS_MAGFPOINT        |
+                               WINED3DPTFILTERCAPS_MINFLINEAR       |
+                               WINED3DPTFILTERCAPS_MINFPOINT        |
+                               WINED3DPTFILTERCAPS_MIPFLINEAR       |
+                               WINED3DPTFILTERCAPS_MIPFPOINT        |
+                               WINED3DPTFILTERCAPS_LINEAR           |
+                               WINED3DPTFILTERCAPS_LINEARMIPLINEAR  |
+                               WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
+                               WINED3DPTFILTERCAPS_MIPLINEAR        |
+                               WINED3DPTFILTERCAPS_MIPNEAREST       |
+                               WINED3DPTFILTERCAPS_NEAREST;
+
+    if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
+    {
+        caps->TextureFilterCaps  |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
+                                    WINED3DPTFILTERCAPS_MINFANISOTROPIC;
+    }
+
+    if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
+    {
+        caps->CubeTextureFilterCaps =  WINED3DPTFILTERCAPS_MAGFLINEAR       |
+                                       WINED3DPTFILTERCAPS_MAGFPOINT        |
+                                       WINED3DPTFILTERCAPS_MINFLINEAR       |
+                                       WINED3DPTFILTERCAPS_MINFPOINT        |
+                                       WINED3DPTFILTERCAPS_MIPFLINEAR       |
+                                       WINED3DPTFILTERCAPS_MIPFPOINT        |
+                                       WINED3DPTFILTERCAPS_LINEAR           |
+                                       WINED3DPTFILTERCAPS_LINEARMIPLINEAR  |
+                                       WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
+                                       WINED3DPTFILTERCAPS_MIPLINEAR        |
+                                       WINED3DPTFILTERCAPS_MIPNEAREST       |
+                                       WINED3DPTFILTERCAPS_NEAREST;
+
+        if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
+        {
+            caps->CubeTextureFilterCaps  |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
+                                            WINED3DPTFILTERCAPS_MINFANISOTROPIC;
+        }
+    }
+    else
+    {
+        caps->CubeTextureFilterCaps = 0;
+    }
+
+    if (gl_info->supported[EXT_TEXTURE3D])
+    {
+        caps->VolumeTextureFilterCaps  = WINED3DPTFILTERCAPS_MAGFLINEAR       |
+                                         WINED3DPTFILTERCAPS_MAGFPOINT        |
+                                         WINED3DPTFILTERCAPS_MINFLINEAR       |
+                                         WINED3DPTFILTERCAPS_MINFPOINT        |
+                                         WINED3DPTFILTERCAPS_MIPFLINEAR       |
+                                         WINED3DPTFILTERCAPS_MIPFPOINT        |
+                                         WINED3DPTFILTERCAPS_LINEAR           |
+                                         WINED3DPTFILTERCAPS_LINEARMIPLINEAR  |
+                                         WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
+                                         WINED3DPTFILTERCAPS_MIPLINEAR        |
+                                         WINED3DPTFILTERCAPS_MIPNEAREST       |
+                                         WINED3DPTFILTERCAPS_NEAREST;
+    }
+    else
+    {
+        caps->VolumeTextureFilterCaps = 0;
+    }
+
+    caps->TextureAddressCaps  =  WINED3DPTADDRESSCAPS_INDEPENDENTUV |
+                                 WINED3DPTADDRESSCAPS_CLAMP  |
+                                 WINED3DPTADDRESSCAPS_WRAP;
+
+    if (gl_info->supported[ARB_TEXTURE_BORDER_CLAMP])
+    {
+        caps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
+    }
+    if (gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT])
+    {
+        caps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
+    }
+    if (gl_info->supported[ATI_TEXTURE_MIRROR_ONCE])
+    {
+        caps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
+    }
+
+    if (gl_info->supported[EXT_TEXTURE3D])
+    {
+        caps->VolumeTextureAddressCaps =   WINED3DPTADDRESSCAPS_INDEPENDENTUV |
+                                           WINED3DPTADDRESSCAPS_CLAMP  |
+                                           WINED3DPTADDRESSCAPS_WRAP;
+        if (gl_info->supported[ARB_TEXTURE_BORDER_CLAMP])
+        {
+            caps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
+        }
+        if (gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT])
+        {
+            caps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
+        }
+        if (gl_info->supported[ATI_TEXTURE_MIRROR_ONCE])
+        {
+            caps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
+        }
+    }
+    else
+    {
+        caps->VolumeTextureAddressCaps = 0;
+    }
+
+    caps->LineCaps  = WINED3DLINECAPS_TEXTURE       |
+                      WINED3DLINECAPS_ZTEST         |
+                      WINED3DLINECAPS_BLEND         |
+                      WINED3DLINECAPS_ALPHACMP      |
+                      WINED3DLINECAPS_FOG;
+    /* WINED3DLINECAPS_ANTIALIAS is not supported on Windows, and dx and gl seem to have a different
+     * idea how generating the smoothing alpha values works; the result is different
+     */
+
+    caps->MaxTextureWidth = gl_info->limits.texture_size;
+    caps->MaxTextureHeight = gl_info->limits.texture_size;
+
+    if (gl_info->supported[EXT_TEXTURE3D])
+        caps->MaxVolumeExtent = gl_info->limits.texture3d_size;
+    else
+        caps->MaxVolumeExtent = 0;
+
+    caps->MaxTextureRepeat = 32768;
+    caps->MaxTextureAspectRatio = gl_info->limits.texture_size;
+    caps->MaxVertexW = 1.0f;
+
+    caps->GuardBandLeft = 0.0f;
+    caps->GuardBandTop = 0.0f;
+    caps->GuardBandRight = 0.0f;
+    caps->GuardBandBottom = 0.0f;
+
+    caps->ExtentsAdjust = 0.0f;
+
+    caps->StencilCaps   = WINED3DSTENCILCAPS_DECRSAT |
+                          WINED3DSTENCILCAPS_INCRSAT |
+                          WINED3DSTENCILCAPS_INVERT  |
+                          WINED3DSTENCILCAPS_KEEP    |
+                          WINED3DSTENCILCAPS_REPLACE |
+                          WINED3DSTENCILCAPS_ZERO;
+    if (gl_info->supported[EXT_STENCIL_WRAP])
+    {
+        caps->StencilCaps |= WINED3DSTENCILCAPS_DECR  |
+                              WINED3DSTENCILCAPS_INCR;
+    }
+    if (gl_info->supported[EXT_STENCIL_TWO_SIDE] || gl_info->supported[ATI_SEPARATE_STENCIL])
+    {
+        caps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
+    }
+
+    caps->MaxAnisotropy = gl_info->limits.anisotropy;
+    caps->MaxPointSize = gl_info->limits.pointsize_max;
+
+    caps->MaxPrimitiveCount   = 0xfffff; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
+    caps->MaxVertexIndex      = 0xfffff;
+    caps->MaxStreams          = MAX_STREAMS;
+    caps->MaxStreamStride     = 1024;
+
+    /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
+    caps->DevCaps2                          = WINED3DDEVCAPS2_STREAMOFFSET |
+                                              WINED3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET;
+    caps->MaxNpatchTessellationLevel        = 0;
+    caps->MasterAdapterOrdinal              = 0;
+    caps->AdapterOrdinalInGroup             = 0;
+    caps->NumberOfAdaptersInGroup           = 1;
+
+    caps->NumSimultaneousRTs = gl_info->limits.buffers;
+
+    caps->StretchRectFilterCaps               = WINED3DPTFILTERCAPS_MINFPOINT  |
+                                                WINED3DPTFILTERCAPS_MAGFPOINT  |
+                                                WINED3DPTFILTERCAPS_MINFLINEAR |
+                                                WINED3DPTFILTERCAPS_MAGFLINEAR;
+    caps->VertexTextureFilterCaps             = 0;
+
+    adapter->shader_backend->shader_get_caps(&adapter->gl_info, &shader_caps);
+    adapter->fragment_pipe->get_caps(&adapter->gl_info, &fragment_caps);
+    adapter->vertex_pipe->vp_get_caps(&adapter->gl_info, &vertex_caps);
+
+    /* Add shader misc caps. Only some of them belong to the shader parts of the pipeline */
+    caps->PrimitiveMiscCaps |= fragment_caps.PrimitiveMiscCaps;
+
+    caps->VertexShaderVersion = shader_caps.vs_version;
+    caps->MaxVertexShaderConst = shader_caps.vs_uniform_count;
+
+    caps->PixelShaderVersion = shader_caps.ps_version;
+    caps->PixelShader1xMaxValue = shader_caps.ps_1x_max_value;
+
+    caps->TextureOpCaps                    = fragment_caps.TextureOpCaps;
+    caps->MaxTextureBlendStages            = fragment_caps.MaxTextureBlendStages;
+    caps->MaxSimultaneousTextures          = fragment_caps.MaxSimultaneousTextures;
+
+    caps->MaxUserClipPlanes                = vertex_caps.max_user_clip_planes;
+    caps->MaxActiveLights                  = vertex_caps.max_active_lights;
+    caps->MaxVertexBlendMatrices           = vertex_caps.max_vertex_blend_matrices;
+    caps->MaxVertexBlendMatrixIndex        = vertex_caps.max_vertex_blend_matrix_index;
+    caps->VertexProcessingCaps             = vertex_caps.vertex_processing_caps;
+    caps->FVFCaps                          = vertex_caps.fvf_caps;
+    caps->RasterCaps                      |= vertex_caps.raster_caps;
+
+    /* The following caps are shader specific, but they are things we cannot detect, or which
+     * are the same among all shader models. So to avoid code duplication set the shader version
+     * specific, but otherwise constant caps here
+     */
+    if (caps->VertexShaderVersion >= 3)
+    {
+        /* Where possible set the caps based on OpenGL extensions and if they
+         * aren't set (in case of software rendering) use the VS 3.0 from
+         * MSDN or else if there's OpenGL spec use a hardcoded value minimum
+         * VS3.0 value. */
+        caps->VS20Caps.caps = WINED3DVS20CAPS_PREDICATION;
+        /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
+        caps->VS20Caps.dynamic_flow_control_depth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH;
+        caps->VS20Caps.temp_count = max(32, adapter->gl_info.limits.arb_vs_temps);
+        /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
+        caps->VS20Caps.static_flow_control_depth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH;
+
+        caps->MaxVShaderInstructionsExecuted    = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
+        caps->MaxVertexShader30InstructionSlots = max(512, adapter->gl_info.limits.arb_vs_instructions);
+    }
+    else if (caps->VertexShaderVersion == 2)
+    {
+        caps->VS20Caps.caps = 0;
+        caps->VS20Caps.dynamic_flow_control_depth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
+        caps->VS20Caps.temp_count = max(12, adapter->gl_info.limits.arb_vs_temps);
+        caps->VS20Caps.static_flow_control_depth = 1;
+
+        caps->MaxVShaderInstructionsExecuted    = 65535;
+        caps->MaxVertexShader30InstructionSlots = 0;
+    }
+    else
+    { /* VS 1.x */
+        caps->VS20Caps.caps = 0;
+        caps->VS20Caps.dynamic_flow_control_depth = 0;
+        caps->VS20Caps.temp_count = 0;
+        caps->VS20Caps.static_flow_control_depth = 0;
+
+        caps->MaxVShaderInstructionsExecuted    = 0;
+        caps->MaxVertexShader30InstructionSlots = 0;
+    }
+
+    if (caps->PixelShaderVersion >= 3)
+    {
+        /* Where possible set the caps based on OpenGL extensions and if they
+         * aren't set (in case of software rendering) use the PS 3.0 from
+         * MSDN or else if there's OpenGL spec use a hardcoded value minimum
+         * PS 3.0 value. */
+
+        /* Caps is more or less undocumented on MSDN but it appears to be
+         * used for PS20Caps based on results from R9600/FX5900/Geforce6800
+         * cards from Windows */
+        caps->PS20Caps.caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
+                WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
+                WINED3DPS20CAPS_PREDICATION          |
+                WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
+                WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
+        /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
+        caps->PS20Caps.dynamic_flow_control_depth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH;
+        caps->PS20Caps.temp_count = max(32, adapter->gl_info.limits.arb_ps_temps);
+        /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
+        caps->PS20Caps.static_flow_control_depth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH;
+        /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
+        caps->PS20Caps.instruction_slot_count = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS;
+
+        caps->MaxPShaderInstructionsExecuted = 65535;
+        caps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS,
+                adapter->gl_info.limits.arb_ps_instructions);
+    }
+    else if(caps->PixelShaderVersion == 2)
+    {
+        /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
+        caps->PS20Caps.caps = 0;
+        caps->PS20Caps.dynamic_flow_control_depth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
+        caps->PS20Caps.temp_count = max(12, adapter->gl_info.limits.arb_ps_temps);
+        caps->PS20Caps.static_flow_control_depth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minimum: 1 */
+        /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
+        caps->PS20Caps.instruction_slot_count = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS;
+
+        caps->MaxPShaderInstructionsExecuted    = 512; /* Minimum value, a GeforceFX uses 1024 */
+        caps->MaxPixelShader30InstructionSlots  = 0;
+    }
+    else /* PS 1.x */
+    {
+        caps->PS20Caps.caps = 0;
+        caps->PS20Caps.dynamic_flow_control_depth = 0;
+        caps->PS20Caps.temp_count = 0;
+        caps->PS20Caps.static_flow_control_depth = 0;
+        caps->PS20Caps.instruction_slot_count = 0;
+
+        caps->MaxPShaderInstructionsExecuted    = 0;
+        caps->MaxPixelShader30InstructionSlots  = 0;
+    }
+
+    if (caps->VertexShaderVersion >= 2)
+    {
+        /* OpenGL supports all the formats below, perhaps not always
+         * without conversion, but it supports them.
+         * Further GLSL doesn't seem to have an official unsigned type so
+         * don't advertise it yet as I'm not sure how we handle it.
+         * We might need to add some clamping in the shader engine to
+         * support it.
+         * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
+        caps->DeclTypes = WINED3DDTCAPS_UBYTE4    |
+                          WINED3DDTCAPS_UBYTE4N   |
+                          WINED3DDTCAPS_SHORT2N   |
+                          WINED3DDTCAPS_SHORT4N;
+        if (gl_info->supported[ARB_HALF_FLOAT_VERTEX])
+        {
+            caps->DeclTypes |= WINED3DDTCAPS_FLOAT16_2 |
+                               WINED3DDTCAPS_FLOAT16_4;
+        }
+    }
+    else
+    {
+        caps->DeclTypes = 0;
+    }
+
+    /* Set DirectDraw helper Caps */
+    ckey_caps =                         WINEDDCKEYCAPS_DESTBLT              |
+                                        WINEDDCKEYCAPS_SRCBLT;
+    fx_caps =                           WINEDDFXCAPS_BLTALPHA               |
+                                        WINEDDFXCAPS_BLTMIRRORLEFTRIGHT     |
+                                        WINEDDFXCAPS_BLTMIRRORUPDOWN        |
+                                        WINEDDFXCAPS_BLTROTATION90          |
+                                        WINEDDFXCAPS_BLTSHRINKX             |
+                                        WINEDDFXCAPS_BLTSHRINKXN            |
+                                        WINEDDFXCAPS_BLTSHRINKY             |
+                                        WINEDDFXCAPS_BLTSHRINKXN            |
+                                        WINEDDFXCAPS_BLTSTRETCHX            |
+                                        WINEDDFXCAPS_BLTSTRETCHXN           |
+                                        WINEDDFXCAPS_BLTSTRETCHY            |
+                                        WINEDDFXCAPS_BLTSTRETCHYN;
+    blit_caps =                         WINEDDCAPS_BLT                      |
+                                        WINEDDCAPS_BLTCOLORFILL             |
+                                        WINEDDCAPS_BLTDEPTHFILL             |
+                                        WINEDDCAPS_BLTSTRETCH               |
+                                        WINEDDCAPS_CANBLTSYSMEM             |
+                                        WINEDDCAPS_CANCLIP                  |
+                                        WINEDDCAPS_CANCLIPSTRETCHED         |
+                                        WINEDDCAPS_COLORKEY                 |
+                                        WINEDDCAPS_COLORKEYHWASSIST         |
+                                        WINEDDCAPS_ALIGNBOUNDARYSRC;
+    pal_caps =                          WINEDDPCAPS_8BIT                    |
+                                        WINEDDPCAPS_PRIMARYSURFACE;
+
+    /* Fill the ddraw caps structure */
+    caps->ddraw_caps.caps =             WINEDDCAPS_GDI                      |
+                                        WINEDDCAPS_PALETTE                  |
+                                        blit_caps;
+    caps->ddraw_caps.caps2 =            WINEDDCAPS2_CERTIFIED               |
+                                        WINEDDCAPS2_NOPAGELOCKREQUIRED      |
+                                        WINEDDCAPS2_PRIMARYGAMMA            |
+                                        WINEDDCAPS2_WIDESURFACES            |
+                                        WINEDDCAPS2_CANRENDERWINDOWED;
+    caps->ddraw_caps.color_key_caps = ckey_caps;
+    caps->ddraw_caps.fx_caps = fx_caps;
+    caps->ddraw_caps.pal_caps = pal_caps;
+    caps->ddraw_caps.svb_caps = blit_caps;
+    caps->ddraw_caps.svb_color_key_caps = ckey_caps;
+    caps->ddraw_caps.svb_fx_caps = fx_caps;
+    caps->ddraw_caps.vsb_caps = blit_caps;
+    caps->ddraw_caps.vsb_color_key_caps = ckey_caps;
+    caps->ddraw_caps.vsb_fx_caps = fx_caps;
+    caps->ddraw_caps.ssb_caps = blit_caps;
+    caps->ddraw_caps.ssb_color_key_caps = ckey_caps;
+    caps->ddraw_caps.ssb_fx_caps = fx_caps;
+
+    caps->ddraw_caps.dds_caps =         WINEDDSCAPS_ALPHA                   |
+                                        WINEDDSCAPS_BACKBUFFER              |
+                                        WINEDDSCAPS_FLIP                    |
+                                        WINEDDSCAPS_FRONTBUFFER             |
+                                        WINEDDSCAPS_OFFSCREENPLAIN          |
+                                        WINEDDSCAPS_PALETTE                 |
+                                        WINEDDSCAPS_PRIMARYSURFACE          |
+                                        WINEDDSCAPS_SYSTEMMEMORY            |
+                                        WINEDDSCAPS_VIDEOMEMORY             |
+                                        WINEDDSCAPS_VISIBLE;
+    caps->ddraw_caps.stride_align = DDRAW_PITCH_ALIGNMENT;
+
+    if (!(wined3d->flags & WINED3D_NO3D))
+    {
+        caps->ddraw_caps.dds_caps |=    WINEDDSCAPS_3DDEVICE                |
+                                        WINEDDSCAPS_MIPMAP                  |
+                                        WINEDDSCAPS_TEXTURE                 |
+                                        WINEDDSCAPS_ZBUFFER;
+        caps->ddraw_caps.caps |=        WINEDDCAPS_3D;
+    }
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_device_create(struct wined3d *wined3d, UINT adapter_idx, enum wined3d_device_type device_type,
+        HWND focus_window, DWORD flags, BYTE surface_alignment, struct wined3d_device_parent *device_parent,
+        struct wined3d_device **device)
+{
+    struct wined3d_device *object;
+    HRESULT hr;
+
+    TRACE("wined3d %p, adapter_idx %u, device_type %#x, focus_window %p, flags %#x, device_parent %p, device %p.\n",
+            wined3d, adapter_idx, device_type, focus_window, flags, device_parent, device);
+
+    /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
+     * number and create a device without a 3D adapter for 2D only operation. */
+    if (wined3d->adapter_count && adapter_idx >= wined3d->adapter_count)
+        return WINED3DERR_INVALIDCALL;
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return E_OUTOFMEMORY;
+
+    hr = device_init(object, wined3d, adapter_idx, device_type,
+            focus_window, flags, surface_alignment, device_parent);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize device, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created device %p.\n", object);
+    *device = object;
+
+    device_parent->ops->wined3d_device_created(device_parent, *device);
+
+    return WINED3D_OK;
+}
+
+static void WINE_GLAPI invalid_func(const void *data)
+{
+    ERR("Invalid vertex attribute function called\n");
+    DebugBreak();
+}
+
+static void WINE_GLAPI invalid_texcoord_func(GLenum unit, const void *data)
+{
+    ERR("Invalid texcoord function called\n");
+    DebugBreak();
+}
+
+/* Helper functions for providing vertex data to opengl. The arrays are initialized based on
+ * the extension detection and are used in drawStridedSlow
+ */
+static void WINE_GLAPI position_d3dcolor(const void *data)
+{
+    DWORD pos = *((const DWORD *)data);
+
+    FIXME("Add a test for fixed function position from d3dcolor type\n");
+    context_get_current()->gl_info->gl_ops.gl.p_glVertex4s(D3DCOLOR_B_R(pos),
+            D3DCOLOR_B_G(pos),
+            D3DCOLOR_B_B(pos),
+            D3DCOLOR_B_A(pos));
+}
+
+static void WINE_GLAPI position_float4(const void *data)
+{
+    const GLfloat *pos = data;
+
+    if (pos[3] != 0.0f && pos[3] != 1.0f)
+    {
+        float w = 1.0f / pos[3];
+
+        context_get_current()->gl_info->gl_ops.gl.p_glVertex4f(pos[0] * w, pos[1] * w, pos[2] * w, w);
+    }
+    else
+    {
+        context_get_current()->gl_info->gl_ops.gl.p_glVertex3fv(pos);
+    }
+}
+
+static void WINE_GLAPI diffuse_d3dcolor(const void *data)
+{
+    DWORD diffuseColor = *((const DWORD *)data);
+
+    context_get_current()->gl_info->gl_ops.gl.p_glColor4ub(D3DCOLOR_B_R(diffuseColor),
+            D3DCOLOR_B_G(diffuseColor),
+            D3DCOLOR_B_B(diffuseColor),
+            D3DCOLOR_B_A(diffuseColor));
+}
+
+static void WINE_GLAPI specular_d3dcolor(const void *data)
+{
+    DWORD specularColor = *((const DWORD *)data);
+    GLbyte d[] = {D3DCOLOR_B_R(specularColor),
+            D3DCOLOR_B_G(specularColor),
+            D3DCOLOR_B_B(specularColor)};
+
+    specular_func_3ubv(d);
+}
+
+static void WINE_GLAPI warn_no_specular_func(const void *data)
+{
+    WARN("GL_EXT_secondary_color not supported\n");
+}
+
+static void fillGLAttribFuncs(const struct wined3d_gl_info *gl_info)
+{
+    position_funcs[WINED3D_FFP_EMIT_FLOAT1]      = invalid_func;
+    position_funcs[WINED3D_FFP_EMIT_FLOAT2]      = invalid_func;
+    position_funcs[WINED3D_FFP_EMIT_FLOAT3]      = (glAttribFunc)gl_info->gl_ops.gl.p_glVertex3fv;
+    position_funcs[WINED3D_FFP_EMIT_FLOAT4]      = position_float4;
+    position_funcs[WINED3D_FFP_EMIT_D3DCOLOR]    = position_d3dcolor;
+    position_funcs[WINED3D_FFP_EMIT_UBYTE4]      = invalid_func;
+    position_funcs[WINED3D_FFP_EMIT_SHORT2]      = invalid_func;
+    position_funcs[WINED3D_FFP_EMIT_SHORT4]      = (glAttribFunc)gl_info->gl_ops.gl.p_glVertex2sv;
+    position_funcs[WINED3D_FFP_EMIT_UBYTE4N]     = invalid_func;
+    position_funcs[WINED3D_FFP_EMIT_SHORT2N]     = invalid_func;
+    position_funcs[WINED3D_FFP_EMIT_SHORT4N]     = invalid_func;
+    position_funcs[WINED3D_FFP_EMIT_USHORT2N]    = invalid_func;
+    position_funcs[WINED3D_FFP_EMIT_USHORT4N]    = invalid_func;
+    position_funcs[WINED3D_FFP_EMIT_UDEC3]       = invalid_func;
+    position_funcs[WINED3D_FFP_EMIT_DEC3N]       = invalid_func;
+    position_funcs[WINED3D_FFP_EMIT_FLOAT16_2]   = invalid_func;
+    position_funcs[WINED3D_FFP_EMIT_FLOAT16_4]   = invalid_func;
+    position_funcs[WINED3D_FFP_EMIT_INVALID]     = invalid_func;
+
+    diffuse_funcs[WINED3D_FFP_EMIT_FLOAT1]       = invalid_func;
+    diffuse_funcs[WINED3D_FFP_EMIT_FLOAT2]       = invalid_func;
+    diffuse_funcs[WINED3D_FFP_EMIT_FLOAT3]       = (glAttribFunc)gl_info->gl_ops.gl.p_glColor3fv;
+    diffuse_funcs[WINED3D_FFP_EMIT_FLOAT4]       = (glAttribFunc)gl_info->gl_ops.gl.p_glColor4fv;
+    diffuse_funcs[WINED3D_FFP_EMIT_D3DCOLOR]     = diffuse_d3dcolor;
+    diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4]       = invalid_func;
+    diffuse_funcs[WINED3D_FFP_EMIT_SHORT2]       = invalid_func;
+    diffuse_funcs[WINED3D_FFP_EMIT_SHORT4]       = invalid_func;
+    diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4N]      = (glAttribFunc)gl_info->gl_ops.gl.p_glColor4ubv;
+    diffuse_funcs[WINED3D_FFP_EMIT_SHORT2N]      = invalid_func;
+    diffuse_funcs[WINED3D_FFP_EMIT_SHORT4N]      = (glAttribFunc)gl_info->gl_ops.gl.p_glColor4sv;
+    diffuse_funcs[WINED3D_FFP_EMIT_USHORT2N]     = invalid_func;
+    diffuse_funcs[WINED3D_FFP_EMIT_USHORT4N]     = (glAttribFunc)gl_info->gl_ops.gl.p_glColor4usv;
+    diffuse_funcs[WINED3D_FFP_EMIT_UDEC3]        = invalid_func;
+    diffuse_funcs[WINED3D_FFP_EMIT_DEC3N]        = invalid_func;
+    diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_2]    = invalid_func;
+    diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_4]    = invalid_func;
+    diffuse_funcs[WINED3D_FFP_EMIT_INVALID]      = invalid_func;
+
+    /* No 4 component entry points here */
+    specular_funcs[WINED3D_FFP_EMIT_FLOAT1]      = invalid_func;
+    specular_funcs[WINED3D_FFP_EMIT_FLOAT2]      = invalid_func;
+    if (gl_info->supported[EXT_SECONDARY_COLOR])
+    {
+        specular_funcs[WINED3D_FFP_EMIT_FLOAT3]  = (glAttribFunc)GL_EXTCALL(glSecondaryColor3fvEXT);
+    }
+    else
+    {
+        specular_funcs[WINED3D_FFP_EMIT_FLOAT3]  = warn_no_specular_func;
+    }
+    specular_funcs[WINED3D_FFP_EMIT_FLOAT4]      = invalid_func;
+    if (gl_info->supported[EXT_SECONDARY_COLOR])
+    {
+        specular_func_3ubv = (glAttribFunc)GL_EXTCALL(glSecondaryColor3ubvEXT);
+        specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = specular_d3dcolor;
+    }
+    else
+    {
+        specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = warn_no_specular_func;
+    }
+    specular_funcs[WINED3D_FFP_EMIT_UBYTE4]      = invalid_func;
+    specular_funcs[WINED3D_FFP_EMIT_SHORT2]      = invalid_func;
+    specular_funcs[WINED3D_FFP_EMIT_SHORT4]      = invalid_func;
+    specular_funcs[WINED3D_FFP_EMIT_UBYTE4N]     = invalid_func;
+    specular_funcs[WINED3D_FFP_EMIT_SHORT2N]     = invalid_func;
+    specular_funcs[WINED3D_FFP_EMIT_SHORT4N]     = invalid_func;
+    specular_funcs[WINED3D_FFP_EMIT_USHORT2N]    = invalid_func;
+    specular_funcs[WINED3D_FFP_EMIT_USHORT4N]    = invalid_func;
+    specular_funcs[WINED3D_FFP_EMIT_UDEC3]       = invalid_func;
+    specular_funcs[WINED3D_FFP_EMIT_DEC3N]       = invalid_func;
+    specular_funcs[WINED3D_FFP_EMIT_FLOAT16_2]   = invalid_func;
+    specular_funcs[WINED3D_FFP_EMIT_FLOAT16_4]   = invalid_func;
+    specular_funcs[WINED3D_FFP_EMIT_INVALID]     = invalid_func;
+
+    /* Only 3 component entry points here. Test how others behave. Float4 normals are used
+     * by one of our tests, trying to pass it to the pixel shader, which fails on Windows.
+     */
+    normal_funcs[WINED3D_FFP_EMIT_FLOAT1]         = invalid_func;
+    normal_funcs[WINED3D_FFP_EMIT_FLOAT2]         = invalid_func;
+    normal_funcs[WINED3D_FFP_EMIT_FLOAT3]         = (glAttribFunc)gl_info->gl_ops.gl.p_glNormal3fv;
+    normal_funcs[WINED3D_FFP_EMIT_FLOAT4]         = (glAttribFunc)gl_info->gl_ops.gl.p_glNormal3fv; /* Just ignore the 4th value */
+    normal_funcs[WINED3D_FFP_EMIT_D3DCOLOR]       = invalid_func;
+    normal_funcs[WINED3D_FFP_EMIT_UBYTE4]         = invalid_func;
+    normal_funcs[WINED3D_FFP_EMIT_SHORT2]         = invalid_func;
+    normal_funcs[WINED3D_FFP_EMIT_SHORT4]         = invalid_func;
+    normal_funcs[WINED3D_FFP_EMIT_UBYTE4N]        = invalid_func;
+    normal_funcs[WINED3D_FFP_EMIT_SHORT2N]        = invalid_func;
+    normal_funcs[WINED3D_FFP_EMIT_SHORT4N]        = invalid_func;
+    normal_funcs[WINED3D_FFP_EMIT_USHORT2N]       = invalid_func;
+    normal_funcs[WINED3D_FFP_EMIT_USHORT4N]       = invalid_func;
+    normal_funcs[WINED3D_FFP_EMIT_UDEC3]          = invalid_func;
+    normal_funcs[WINED3D_FFP_EMIT_DEC3N]          = invalid_func;
+    normal_funcs[WINED3D_FFP_EMIT_FLOAT16_2]      = invalid_func;
+    normal_funcs[WINED3D_FFP_EMIT_FLOAT16_4]      = invalid_func;
+    normal_funcs[WINED3D_FFP_EMIT_INVALID]        = invalid_func;
+
+    multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT1]    = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord1fvARB);
+    multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT2]    = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2fvARB);
+    multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT3]    = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord3fvARB);
+    multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT4]    = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4fvARB);
+    multi_texcoord_funcs[WINED3D_FFP_EMIT_D3DCOLOR]  = invalid_texcoord_func;
+    multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4]    = invalid_texcoord_func;
+    multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2]    = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2svARB);
+    multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4]    = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4svARB);
+    multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4N]   = invalid_texcoord_func;
+    multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2N]   = invalid_texcoord_func;
+    multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4N]   = invalid_texcoord_func;
+    multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT2N]  = invalid_texcoord_func;
+    multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT4N]  = invalid_texcoord_func;
+    multi_texcoord_funcs[WINED3D_FFP_EMIT_UDEC3]     = invalid_texcoord_func;
+    multi_texcoord_funcs[WINED3D_FFP_EMIT_DEC3N]     = invalid_texcoord_func;
+    if (gl_info->supported[NV_HALF_FLOAT])
+    {
+        /* Not supported by ARB_HALF_FLOAT_VERTEX, so check for NV_HALF_FLOAT */
+        multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2hvNV);
+        multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4hvNV);
+    } else {
+        multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_texcoord_func;
+        multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_texcoord_func;
+    }
+    multi_texcoord_funcs[WINED3D_FFP_EMIT_INVALID]   = invalid_texcoord_func;
+}
+
+static void wined3d_adapter_init_fb_cfgs(struct wined3d_adapter *adapter, HDC dc)
+{
+    const struct wined3d_gl_info *gl_info = &adapter->gl_info;
+    int i;
+
+    if (gl_info->supported[WGL_ARB_PIXEL_FORMAT])
+    {
+        UINT attrib_count = 0;
+        GLint cfg_count;
+        int attribs[11];
+        int values[11];
+        int attribute;
+
+        attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
+        GL_EXTCALL(wglGetPixelFormatAttribivARB(dc, 0, 0, 1, &attribute, &cfg_count));
+
+        adapter->cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cfg_count * sizeof(*adapter->cfgs));
+        attribs[attrib_count++] = WGL_RED_BITS_ARB;
+        attribs[attrib_count++] = WGL_GREEN_BITS_ARB;
+        attribs[attrib_count++] = WGL_BLUE_BITS_ARB;
+        attribs[attrib_count++] = WGL_ALPHA_BITS_ARB;
+        attribs[attrib_count++] = WGL_COLOR_BITS_ARB;
+        attribs[attrib_count++] = WGL_DEPTH_BITS_ARB;
+        attribs[attrib_count++] = WGL_STENCIL_BITS_ARB;
+        attribs[attrib_count++] = WGL_DRAW_TO_WINDOW_ARB;
+        attribs[attrib_count++] = WGL_PIXEL_TYPE_ARB;
+        attribs[attrib_count++] = WGL_DOUBLE_BUFFER_ARB;
+        attribs[attrib_count++] = WGL_AUX_BUFFERS_ARB;
+
+        for (i = 0, adapter->cfg_count = 0; i < cfg_count; ++i)
+        {
+            struct wined3d_pixel_format *cfg = &adapter->cfgs[adapter->cfg_count];
+            int format_id = i + 1;
+
+            if (!GL_EXTCALL(wglGetPixelFormatAttribivARB(dc, format_id, 0, attrib_count, attribs, values)))
+                continue;
+
+            cfg->iPixelFormat = format_id;
+            cfg->redSize = values[0];
+            cfg->greenSize = values[1];
+            cfg->blueSize = values[2];
+            cfg->alphaSize = values[3];
+            cfg->colorSize = values[4];
+            cfg->depthSize = values[5];
+            cfg->stencilSize = values[6];
+            cfg->windowDrawable = values[7];
+            cfg->iPixelType = values[8];
+            cfg->doubleBuffer = values[9];
+            cfg->auxBuffers = values[10];
+
+            cfg->numSamples = 0;
+            /* Check multisample support. */
+            if (gl_info->supported[ARB_MULTISAMPLE])
+            {
+                int attribs[2] = {WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB};
+                int values[2];
+
+                if (GL_EXTCALL(wglGetPixelFormatAttribivARB(dc, format_id, 0, 2, attribs, values)))
+                {
+                    /* values[0] = WGL_SAMPLE_BUFFERS_ARB which tells whether
+                     * multisampling is supported. values[1] = number of
+                     * multisample buffers. */
+                    if (values[0])
+                        cfg->numSamples = values[1];
+                }
+            }
+
+            TRACE("iPixelFormat=%d, iPixelType=%#x, doubleBuffer=%d, RGBA=%d/%d/%d/%d, "
+                    "depth=%d, stencil=%d, samples=%d, windowDrawable=%d\n",
+                    cfg->iPixelFormat, cfg->iPixelType, cfg->doubleBuffer,
+                    cfg->redSize, cfg->greenSize, cfg->blueSize, cfg->alphaSize,
+                    cfg->depthSize, cfg->stencilSize, cfg->numSamples, cfg->windowDrawable);
+
+            ++adapter->cfg_count;
+        }
+    }
+    else
+    {
+        int cfg_count;
+
+        cfg_count = DescribePixelFormat(dc, 0, 0, 0);
+        adapter->cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cfg_count * sizeof(*adapter->cfgs));
+
+        for (i = 0, adapter->cfg_count = 0; i < cfg_count; ++i)
+        {
+            struct wined3d_pixel_format *cfg = &adapter->cfgs[adapter->cfg_count];
+            PIXELFORMATDESCRIPTOR pfd;
+            int format_id = i + 1;
+
+            if (!DescribePixelFormat(dc, format_id, sizeof(pfd), &pfd))
+                continue;
+
+            /* We only want HW acceleration using an OpenGL ICD driver.
+             * PFD_GENERIC_FORMAT = slow opengl 1.1 gdi software rendering.
+             * PFD_GENERIC_ACCELERATED = partial hw acceleration using a MCD
+             * driver (e.g. 3dfx minigl). */
+            if (pfd.dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED))
+            {
+                TRACE("Skipping format %d because it isn't ICD accelerated.\n", format_id);
+                continue;
+            }
+
+            cfg->iPixelFormat = format_id;
+            cfg->redSize = pfd.cRedBits;
+            cfg->greenSize = pfd.cGreenBits;
+            cfg->blueSize = pfd.cBlueBits;
+            cfg->alphaSize = pfd.cAlphaBits;
+            cfg->colorSize = pfd.cColorBits;
+            cfg->depthSize = pfd.cDepthBits;
+            cfg->stencilSize = pfd.cStencilBits;
+            cfg->windowDrawable = (pfd.dwFlags & PFD_DRAW_TO_WINDOW) ? 1 : 0;
+            cfg->iPixelType = (pfd.iPixelType == PFD_TYPE_RGBA) ? WGL_TYPE_RGBA_ARB : WGL_TYPE_COLORINDEX_ARB;
+            cfg->doubleBuffer = (pfd.dwFlags & PFD_DOUBLEBUFFER) ? 1 : 0;
+            cfg->auxBuffers = pfd.cAuxBuffers;
+            cfg->numSamples = 0;
+
+            TRACE("iPixelFormat=%d, iPixelType=%#x, doubleBuffer=%d, RGBA=%d/%d/%d/%d, "
+                    "depth=%d, stencil=%d, windowDrawable=%d\n",
+                    cfg->iPixelFormat, cfg->iPixelType, cfg->doubleBuffer,
+                    cfg->redSize, cfg->greenSize, cfg->blueSize, cfg->alphaSize,
+                    cfg->depthSize, cfg->stencilSize, cfg->windowDrawable);
+
+            ++adapter->cfg_count;
+        }
+    }
+}
+
+/* Do not call while under the GL lock. */
+static BOOL wined3d_adapter_init(struct wined3d_adapter *adapter, UINT ordinal)
+{
+    struct wined3d_gl_info *gl_info = &adapter->gl_info;
+    struct wined3d_fake_gl_ctx fake_gl_ctx = {0};
+    unsigned int ctx_attrib_idx = 0;
+    DISPLAY_DEVICEW display_device;
+    GLint ctx_attribs[3];
+#ifdef VBOX
+    struct VBOXUHGSMI *pHgsmi = NULL;
+#endif
+
+    TRACE("adapter %p, ordinal %u.\n", adapter, ordinal);
+
+    adapter->ordinal = ordinal;
+    adapter->monitorPoint.x = -1;
+    adapter->monitorPoint.y = -1;
+
+/* Dynamically load all GL core functions */
+#ifdef USE_WIN32_OPENGL
+    {
+#ifndef VBOX
+        HMODULE mod_gl = GetModuleHandleA("opengl32.dll");
+#else
+        BOOL (APIENTRY *pDrvValidateVersion)(DWORD) DECLSPEC_HIDDEN;
+# ifdef VBOX_WDDM_WOW64
+        HMODULE mod_gl = LoadLibraryA("VBoxOGL-x86.dll");
+# else
+        HMODULE mod_gl = LoadLibraryA("VBoxOGL.dll");
+# endif
+        if (!mod_gl)
+        {
+            ERR("Can't load VBoxOGL.dll!\n");
+            return FALSE;
+        }
+
+        pDrvValidateVersion = (void*)GetProcAddress(mod_gl, "DrvValidateVersion");
+        if(!pDrvValidateVersion) {
+            ERR("Can't get DrvValidateVersion\n");
+            FreeLibrary(mod_gl);
+            return FALSE;
+        }
+        if(!pDrvValidateVersion(1)) {
+            ERR("DrvValidateVersion FAILED\n");
+            FreeLibrary(mod_gl);
+            return FALSE;
+        }
+
+# define VBOX_USE_FUNC(f) p##f = (void *)GetProcAddress(mod_gl, #f);
+        VBOX_GL_FUNCS_GEN
+# undef VBOX_USE_FUNC
+#endif
+#define USE_GL_FUNC(f) gl_info->gl_ops.gl.p_##f = (void *)GetProcAddress(mod_gl, #f);
+        ALL_WGL_FUNCS
+#undef USE_GL_FUNC
+        gl_info->gl_ops.wgl.p_wglSwapBuffers = (void *)GetProcAddress(mod_gl, "wglSwapBuffers");
+    }
+#else
+    /* To bypass the opengl32 thunks retrieve functions from the WGL driver instead of opengl32 */
+    {
+        HDC hdc = GetDC( 0 );
+        const struct opengl_funcs *wgl_driver = __wine_get_wgl_driver( hdc, WINE_WGL_DRIVER_VERSION );
+        ReleaseDC( 0, hdc );
+        if (!wgl_driver || wgl_driver == (void *)-1) return FALSE;
+        gl_info->gl_ops.wgl = wgl_driver->wgl;
+        gl_info->gl_ops.gl = wgl_driver->gl;
+    }
+#endif
+
+    glEnableWINE = gl_info->gl_ops.gl.p_glEnable;
+    glDisableWINE = gl_info->gl_ops.gl.p_glDisable;
+
+#ifdef VBOX_WITH_WDDM
+    pHgsmi = VBoxCrHgsmiCreate();
+    if (!pHgsmi)
+    {
+        ERR("VBoxCrHgsmiCreate failed");
+        return FALSE;
+    }
+#endif
+
+    if (!AllocateLocallyUniqueId(&adapter->luid))
+    {
+        ERR("Failed to set adapter LUID (%#x).\n", GetLastError());
+        return FALSE;
+    }
+    TRACE("Allocated LUID %08x:%08x for adapter %p.\n",
+            adapter->luid.HighPart, adapter->luid.LowPart, adapter);
+
+    if (!WineD3D_CreateFakeGLContext(&fake_gl_ctx
+#ifdef VBOX
+            , pHgsmi
+#endif
+            ))
+    {
+        ERR("Failed to get a GL context for adapter %p.\n", adapter);
+#ifdef VBOX_WITH_WDDM
+        VBoxCrHgsmiDestroy(pHgsmi);
+#endif
+        return FALSE;
+    }
+
+    if (context_debug_output_enabled(gl_info))
+    {
+        ctx_attribs[ctx_attrib_idx++] = WGL_CONTEXT_FLAGS_ARB;
+        ctx_attribs[ctx_attrib_idx++] = WGL_CONTEXT_DEBUG_BIT_ARB;
+    }
+    ctx_attribs[ctx_attrib_idx] = 0;
+    wined3d_create_fake_gl_context_attribs(&fake_gl_ctx, gl_info, ctx_attribs);
+
+    if (!wined3d_adapter_init_gl_caps(adapter))
+    {
+        ERR("Failed to initialize GL caps for adapter %p.\n", adapter);
+        WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
+#ifdef VBOX_WITH_WDDM
+        VBoxCrHgsmiDestroy(pHgsmi);
+#endif
+        return FALSE;
+    }
+
+    wined3d_adapter_init_fb_cfgs(adapter, fake_gl_ctx.dc);
+    /* We haven't found any suitable formats. This should only happen in
+     * case of GDI software rendering, which is pretty useless anyway. */
+    if (!adapter->cfg_count)
+    {
+        WARN("No suitable pixel formats found.\n");
+        WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
+        HeapFree(GetProcessHeap(), 0, adapter->cfgs);
+#ifdef VBOX_WITH_WDDM
+        VBoxCrHgsmiDestroy(pHgsmi);
+#endif
+        return FALSE;
+    }
+
+    if (!wined3d_adapter_init_format_info(adapter))
+    {
+        ERR("Failed to initialize GL format info.\n");
+        WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
+        HeapFree(GetProcessHeap(), 0, adapter->cfgs);
+#ifdef VBOX_WITH_WDDM
+        VBoxCrHgsmiDestroy(pHgsmi);
+#endif
+        return FALSE;
+    }
+
+#ifndef VBOX_WITH_WDDM
+    adapter->TextureRam = adapter->driver_info.vidmem;
+    adapter->UsedTextureRam = 0;
+    TRACE("Emulating %u MB of texture ram.\n", adapter->TextureRam / (1024 * 1024));
+#endif
+
+    display_device.cb = sizeof(display_device);
+    EnumDisplayDevicesW(NULL, ordinal, &display_device, 0);
+    TRACE("DeviceName: %s\n", debugstr_w(display_device.DeviceName));
+    strcpyW(adapter->DeviceName, display_device.DeviceName);
+
+    WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
+
+    fillGLAttribFuncs(&adapter->gl_info);
+
+#ifdef VBOX_WITH_WDDM
+    VBoxCrHgsmiDestroy(pHgsmi);
+#endif
+
+    return TRUE;
+}
+
+static void wined3d_adapter_init_nogl(struct wined3d_adapter *adapter, UINT ordinal)
+{
+    DISPLAY_DEVICEW display_device;
+
+    memset(adapter, 0, sizeof(*adapter));
+    adapter->ordinal = ordinal;
+    adapter->monitorPoint.x = -1;
+    adapter->monitorPoint.y = -1;
+
+    adapter->driver_info.name = "Display";
+    adapter->driver_info.description = "WineD3D DirectDraw Emulation";
+#ifndef VBOX_WITH_WDDM
+    if (wined3d_settings.emulated_textureram)
+        adapter->TextureRam = wined3d_settings.emulated_textureram;
+    else
+        adapter->TextureRam = 128 * 1024 * 1024;
+#endif
+
+    initPixelFormatsNoGL(&adapter->gl_info);
+
+    adapter->vertex_pipe = &none_vertex_pipe;
+    adapter->fragment_pipe = &none_fragment_pipe;
+    adapter->shader_backend = &none_shader_backend;
+    adapter->blitter = &cpu_blit;
+
+    display_device.cb = sizeof(display_device);
+    EnumDisplayDevicesW(NULL, ordinal, &display_device, 0);
+    TRACE("DeviceName: %s\n", debugstr_w(display_device.DeviceName));
+    strcpyW(adapter->DeviceName, display_device.DeviceName);
+}
+
+static void STDMETHODCALLTYPE wined3d_null_wined3d_object_destroyed(void *parent) {}
+
+const struct wined3d_parent_ops wined3d_null_parent_ops =
+{
+    wined3d_null_wined3d_object_destroyed,
+};
+
+/* Do not call while under the GL lock. */
+HRESULT wined3d_init(struct wined3d *wined3d, UINT version, DWORD flags)
+{
+    wined3d->dxVersion = version;
+    wined3d->ref = 1;
+    wined3d->flags = flags;
+
+    TRACE("Initializing adapters.\n");
+
+    if (flags & WINED3D_NO3D)
+    {
+        wined3d_adapter_init_nogl(&wined3d->adapters[0], 0);
+        wined3d->adapter_count = 1;
+        return WINED3D_OK;
+    }
+
+    if (!wined3d_adapter_init(&wined3d->adapters[0], 0))
+    {
+        WARN("Failed to initialize adapter.\n");
+        return E_FAIL;
+    }
+    wined3d->adapter_count = 1;
+
+    return WINED3D_OK;
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/drawprim.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/drawprim.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/drawprim.c	(revision 46521)
@@ -0,0 +1,793 @@
+/*
+ * WINED3D draw functions
+ *
+ * Copyright 2002-2004 Jason Edmeades
+ * Copyright 2002-2004 Raphael Junqueira
+ * Copyright 2004 Christian Costa
+ * Copyright 2005 Oliver Stieber
+ * Copyright 2006, 2008 Henri Verbeet
+ * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
+ * Copyright 2009 Henri Verbeet for CodeWeavers
+ *
+ * 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 "wined3d_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d_draw);
+WINE_DECLARE_DEBUG_CHANNEL(d3d_perf);
+
+#include <stdio.h>
+#include <math.h>
+
+#ifdef DEBUG_misha
+#include "../VBox/VBoxDbgGl.h"
+#endif
+
+#ifdef VBOX_WITH_WINE_FIXES
+# define ceilf ceil
+#endif
+
+/* Context activation is done by the caller. */
+static void drawStridedFast(const struct wined3d_gl_info *gl_info, GLenum primitive_type, UINT count, UINT idx_size,
+        const void *idx_data, UINT start_idx, INT base_vertex_index, UINT start_instance, UINT instance_count)
+{
+    if (idx_size)
+    {
+        GLenum idxtype = idx_size == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
+        if (instance_count)
+        {
+            if (!gl_info->supported[ARB_DRAW_INSTANCED])
+            {
+                FIXME("Instanced drawing not supported.\n");
+            }
+            else
+            {
+                if (start_instance)
+                    FIXME("Start instance (%u) not supported.\n", start_instance);
+                GL_EXTCALL(glDrawElementsInstancedBaseVertex(primitive_type, count, idxtype,
+                        (const char *)idx_data + (idx_size * start_idx), instance_count, base_vertex_index));
+                checkGLcall("glDrawElementsInstancedBaseVertex");
+            }
+        }
+        else if (gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX])
+        {
+            GL_EXTCALL(glDrawElementsBaseVertex(primitive_type, count, idxtype,
+                    (const char *)idx_data + (idx_size * start_idx), base_vertex_index));
+            checkGLcall("glDrawElementsBaseVertex");
+        }
+        else
+        {
+            gl_info->gl_ops.gl.p_glDrawElements(primitive_type, count,
+                    idxtype, (const char *)idx_data + (idx_size * start_idx));
+            checkGLcall("glDrawElements");
+        }
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glDrawArrays(primitive_type, start_idx, count);
+        checkGLcall("glDrawArrays");
+    }
+}
+
+/*
+ * Actually draw using the supplied information.
+ * Slower GL version which extracts info about each vertex in turn
+ */
+
+/* Context activation is done by the caller. */
+static void drawStridedSlow(const struct wined3d_device *device, const struct wined3d_context *context,
+        const struct wined3d_stream_info *si, UINT NumVertexes, GLenum glPrimType,
+        const void *idxData, UINT idxSize, UINT startIdx)
+{
+    unsigned int               textureNo    = 0;
+    const WORD                *pIdxBufS     = NULL;
+    const DWORD               *pIdxBufL     = NULL;
+    UINT vx_index;
+    const struct wined3d_state *state = &device->stateBlock->state;
+    LONG SkipnStrides = startIdx;
+    BOOL pixelShader = use_ps(state);
+    BOOL specular_fog = FALSE;
+    const BYTE *texCoords[WINED3DDP_MAXTEXCOORD];
+    const BYTE *diffuse = NULL, *specular = NULL, *normal = NULL, *position = NULL;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    const struct wined3d_d3d_info *d3d_info = context->d3d_info;
+    UINT texture_stages = d3d_info->limits.ffp_blend_stages;
+    const struct wined3d_stream_info_element *element;
+    UINT num_untracked_materials;
+    DWORD tex_mask = 0;
+
+    TRACE_(d3d_perf)("Using slow vertex array code\n");
+
+    /* Variable Initialization */
+    if (idxSize)
+    {
+        /* Immediate mode drawing can't make use of indices in a vbo - get the
+         * data from the index buffer. If the index buffer has no vbo (not
+         * supported or other reason), or with user pointer drawing idxData
+         * will be non-NULL. */
+        if (!idxData)
+            idxData = buffer_get_sysmem(state->index_buffer, gl_info);
+
+        if (idxSize == 2) pIdxBufS = idxData;
+        else pIdxBufL = idxData;
+    } else if (idxData) {
+        ERR("non-NULL idxData with 0 idxSize, this should never happen\n");
+        return;
+    }
+
+    /* Start drawing in GL */
+    gl_info->gl_ops.gl.p_glBegin(glPrimType);
+
+    if (si->use_map & (1 << WINED3D_FFP_POSITION))
+    {
+        element = &si->elements[WINED3D_FFP_POSITION];
+        position = element->data.addr;
+    }
+
+    if (si->use_map & (1 << WINED3D_FFP_NORMAL))
+    {
+        element = &si->elements[WINED3D_FFP_NORMAL];
+        normal = element->data.addr;
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glNormal3f(0, 0, 0);
+    }
+
+    num_untracked_materials = context->num_untracked_materials;
+    if (si->use_map & (1 << WINED3D_FFP_DIFFUSE))
+    {
+        element = &si->elements[WINED3D_FFP_DIFFUSE];
+        diffuse = element->data.addr;
+
+        if (num_untracked_materials && element->format->id != WINED3DFMT_B8G8R8A8_UNORM)
+            FIXME("Implement diffuse color tracking from %s\n", debug_d3dformat(element->format->id));
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+    }
+
+    if (si->use_map & (1 << WINED3D_FFP_SPECULAR))
+    {
+        element = &si->elements[WINED3D_FFP_SPECULAR];
+        specular = element->data.addr;
+
+        /* special case where the fog density is stored in the specular alpha channel */
+        if (state->render_states[WINED3D_RS_FOGENABLE]
+                && (state->render_states[WINED3D_RS_FOGVERTEXMODE] == WINED3D_FOG_NONE
+                    || si->elements[WINED3D_FFP_POSITION].format->id == WINED3DFMT_R32G32B32A32_FLOAT)
+                && state->render_states[WINED3D_RS_FOGTABLEMODE] == WINED3D_FOG_NONE)
+        {
+            if (gl_info->supported[EXT_FOG_COORD])
+            {
+                if (element->format->id == WINED3DFMT_B8G8R8A8_UNORM) specular_fog = TRUE;
+                else FIXME("Implement fog coordinates from %s\n", debug_d3dformat(element->format->id));
+            }
+            else
+            {
+                static BOOL warned;
+
+                if (!warned)
+                {
+                    /* TODO: Use the fog table code from old ddraw */
+                    FIXME("Implement fog for transformed vertices in software\n");
+                    warned = TRUE;
+                }
+            }
+        }
+    }
+    else if (gl_info->supported[EXT_SECONDARY_COLOR])
+    {
+        GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
+    }
+
+    for (textureNo = 0; textureNo < texture_stages; ++textureNo)
+    {
+        int coordIdx = state->texture_states[textureNo][WINED3D_TSS_TEXCOORD_INDEX];
+        DWORD texture_idx = device->texUnitMap[textureNo];
+
+        if (!gl_info->supported[ARB_MULTITEXTURE] && textureNo > 0)
+        {
+            FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
+            continue;
+        }
+
+        if (!pixelShader && !state->textures[textureNo]) continue;
+
+        if (texture_idx == WINED3D_UNMAPPED_STAGE) continue;
+
+        if (coordIdx > 7)
+        {
+            TRACE("tex: %d - Skip tex coords, as being system generated\n", textureNo);
+            continue;
+        }
+        else if (coordIdx < 0)
+        {
+            FIXME("tex: %d - Coord index %d is less than zero, expect a crash.\n", textureNo, coordIdx);
+            continue;
+        }
+
+        if (si->use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coordIdx)))
+        {
+            element = &si->elements[WINED3D_FFP_TEXCOORD0 + coordIdx];
+            texCoords[coordIdx] = element->data.addr;
+            tex_mask |= (1 << textureNo);
+        }
+        else
+        {
+            TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
+            if (gl_info->supported[ARB_MULTITEXTURE])
+                GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + texture_idx, 0, 0, 0, 1));
+            else
+                gl_info->gl_ops.gl.p_glTexCoord4f(0, 0, 0, 1);
+        }
+    }
+
+    /* We shouldn't start this function if any VBO is involved. Should I put a safety check here?
+     * Guess it's not necessary(we crash then anyway) and would only eat CPU time
+     */
+
+    /* For each primitive */
+    for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
+        UINT texture, tmp_tex_mask;
+        /* Blending data and Point sizes are not supported by this function. They are not supported by the fixed
+         * function pipeline at all. A Fixme for them is printed after decoding the vertex declaration
+         */
+
+        /* For indexed data, we need to go a few more strides in */
+        if (idxData)
+        {
+            /* Indexed so work out the number of strides to skip */
+            if (idxSize == 2)
+                SkipnStrides = pIdxBufS[startIdx + vx_index] + state->base_vertex_index;
+            else
+                SkipnStrides = pIdxBufL[startIdx + vx_index] + state->base_vertex_index;
+        }
+
+        tmp_tex_mask = tex_mask;
+        for (texture = 0; tmp_tex_mask; tmp_tex_mask >>= 1, ++texture)
+        {
+            int coord_idx;
+            const void *ptr;
+            DWORD texture_idx;
+
+            if (!(tmp_tex_mask & 1)) continue;
+
+            coord_idx = state->texture_states[texture][WINED3D_TSS_TEXCOORD_INDEX];
+            ptr = texCoords[coord_idx] + (SkipnStrides * si->elements[WINED3D_FFP_TEXCOORD0 + coord_idx].stride);
+
+            texture_idx = device->texUnitMap[texture];
+            multi_texcoord_funcs[si->elements[WINED3D_FFP_TEXCOORD0 + coord_idx].format->emit_idx](
+                    GL_TEXTURE0_ARB + texture_idx, ptr);
+        }
+
+        /* Diffuse -------------------------------- */
+        if (diffuse) {
+            const void *ptrToCoords = diffuse + SkipnStrides * si->elements[WINED3D_FFP_DIFFUSE].stride;
+
+            diffuse_funcs[si->elements[WINED3D_FFP_DIFFUSE].format->emit_idx](ptrToCoords);
+            if (num_untracked_materials)
+            {
+                DWORD diffuseColor = ((const DWORD *)ptrToCoords)[0];
+                unsigned char i;
+                float color[4];
+
+                color[0] = D3DCOLOR_B_R(diffuseColor) / 255.0f;
+                color[1] = D3DCOLOR_B_G(diffuseColor) / 255.0f;
+                color[2] = D3DCOLOR_B_B(diffuseColor) / 255.0f;
+                color[3] = D3DCOLOR_B_A(diffuseColor) / 255.0f;
+
+                for (i = 0; i < num_untracked_materials; ++i)
+                {
+                    gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, context->untracked_materials[i], color);
+                }
+            }
+        }
+
+        /* Specular ------------------------------- */
+        if (specular) {
+            const void *ptrToCoords = specular + SkipnStrides * si->elements[WINED3D_FFP_SPECULAR].stride;
+
+            specular_funcs[si->elements[WINED3D_FFP_SPECULAR].format->emit_idx](ptrToCoords);
+
+            if (specular_fog)
+            {
+                DWORD specularColor = *(const DWORD *)ptrToCoords;
+                GL_EXTCALL(glFogCoordfEXT((float) (specularColor >> 24)));
+            }
+        }
+
+        /* Normal -------------------------------- */
+        if (normal)
+        {
+            const void *ptrToCoords = normal + SkipnStrides * si->elements[WINED3D_FFP_NORMAL].stride;
+            normal_funcs[si->elements[WINED3D_FFP_NORMAL].format->emit_idx](ptrToCoords);
+        }
+
+        /* Position -------------------------------- */
+        if (position) {
+            const void *ptrToCoords = position + SkipnStrides * si->elements[WINED3D_FFP_POSITION].stride;
+            position_funcs[si->elements[WINED3D_FFP_POSITION].format->emit_idx](ptrToCoords);
+        }
+
+        /* For non indexed mode, step onto next parts */
+        if (!idxData) ++SkipnStrides;
+    }
+
+    gl_info->gl_ops.gl.p_glEnd();
+    checkGLcall("glEnd and previous calls");
+}
+
+/* Context activation is done by the caller. */
+static inline void send_attribute(const struct wined3d_gl_info *gl_info,
+        enum wined3d_format_id format, const UINT index, const void *ptr)
+{
+    switch(format)
+    {
+        case WINED3DFMT_R32_FLOAT:
+            GL_EXTCALL(glVertexAttrib1fvARB(index, ptr));
+            break;
+        case WINED3DFMT_R32G32_FLOAT:
+            GL_EXTCALL(glVertexAttrib2fvARB(index, ptr));
+            break;
+        case WINED3DFMT_R32G32B32_FLOAT:
+            GL_EXTCALL(glVertexAttrib3fvARB(index, ptr));
+            break;
+        case WINED3DFMT_R32G32B32A32_FLOAT:
+            GL_EXTCALL(glVertexAttrib4fvARB(index, ptr));
+            break;
+
+        case WINED3DFMT_R8G8B8A8_UINT:
+            GL_EXTCALL(glVertexAttrib4ubvARB(index, ptr));
+            break;
+        case WINED3DFMT_B8G8R8A8_UNORM:
+            if (gl_info->supported[ARB_VERTEX_ARRAY_BGRA])
+            {
+                const DWORD *src = ptr;
+                DWORD c = *src & 0xff00ff00;
+                c |= (*src & 0xff0000) >> 16;
+                c |= (*src & 0xff) << 16;
+                GL_EXTCALL(glVertexAttrib4NubvARB(index, (GLubyte *)&c));
+                break;
+            }
+            /* else fallthrough */
+        case WINED3DFMT_R8G8B8A8_UNORM:
+            GL_EXTCALL(glVertexAttrib4NubvARB(index, ptr));
+            break;
+
+        case WINED3DFMT_R16G16_SINT:
+            GL_EXTCALL(glVertexAttrib4svARB(index, ptr));
+            break;
+        case WINED3DFMT_R16G16B16A16_SINT:
+            GL_EXTCALL(glVertexAttrib4svARB(index, ptr));
+            break;
+
+        case WINED3DFMT_R16G16_SNORM:
+        {
+            GLshort s[4] = {((const GLshort *)ptr)[0], ((const GLshort *)ptr)[1], 0, 1};
+            GL_EXTCALL(glVertexAttrib4NsvARB(index, s));
+            break;
+        }
+        case WINED3DFMT_R16G16_UNORM:
+        {
+            GLushort s[4] = {((const GLushort *)ptr)[0], ((const GLushort *)ptr)[1], 0, 1};
+            GL_EXTCALL(glVertexAttrib4NusvARB(index, s));
+            break;
+        }
+        case WINED3DFMT_R16G16B16A16_SNORM:
+            GL_EXTCALL(glVertexAttrib4NsvARB(index, ptr));
+            break;
+        case WINED3DFMT_R16G16B16A16_UNORM:
+            GL_EXTCALL(glVertexAttrib4NusvARB(index, ptr));
+            break;
+
+        case WINED3DFMT_R10G10B10A2_UINT:
+            FIXME("Unsure about WINED3DDECLTYPE_UDEC3\n");
+            /*glVertexAttrib3usvARB(instancedData[j], (GLushort *) ptr); Does not exist */
+            break;
+        case WINED3DFMT_R10G10B10A2_SNORM:
+            FIXME("Unsure about WINED3DDECLTYPE_DEC3N\n");
+            /*glVertexAttrib3NusvARB(instancedData[j], (GLushort *) ptr); Does not exist */
+            break;
+
+        case WINED3DFMT_R16G16_FLOAT:
+            /* Are those 16 bit floats. C doesn't have a 16 bit float type. I could read the single bits and calculate a 4
+             * byte float according to the IEEE standard
+             */
+            if (gl_info->supported[NV_HALF_FLOAT] && gl_info->supported[NV_VERTEX_PROGRAM])
+            {
+                /* Not supported by GL_ARB_half_float_vertex */
+                GL_EXTCALL(glVertexAttrib2hvNV(index, ptr));
+            }
+            else
+            {
+                float x = float_16_to_32(((const unsigned short *)ptr) + 0);
+                float y = float_16_to_32(((const unsigned short *)ptr) + 1);
+                GL_EXTCALL(glVertexAttrib2fARB(index, x, y));
+            }
+            break;
+        case WINED3DFMT_R16G16B16A16_FLOAT:
+            if (gl_info->supported[NV_HALF_FLOAT] && gl_info->supported[NV_VERTEX_PROGRAM])
+            {
+                /* Not supported by GL_ARB_half_float_vertex */
+                GL_EXTCALL(glVertexAttrib4hvNV(index, ptr));
+            }
+            else
+            {
+                float x = float_16_to_32(((const unsigned short *)ptr) + 0);
+                float y = float_16_to_32(((const unsigned short *)ptr) + 1);
+                float z = float_16_to_32(((const unsigned short *)ptr) + 2);
+                float w = float_16_to_32(((const unsigned short *)ptr) + 3);
+                GL_EXTCALL(glVertexAttrib4fARB(index, x, y, z, w));
+            }
+            break;
+
+        default:
+            ERR("Unexpected attribute format: %s\n", debug_d3dformat(format));
+            break;
+    }
+}
+
+/* Context activation is done by the caller. */
+static void drawStridedSlowVs(const struct wined3d_gl_info *gl_info, const struct wined3d_state *state,
+        const struct wined3d_stream_info *si, UINT numberOfVertices, GLenum glPrimitiveType,
+        const void *idxData, UINT idxSize, UINT startIdx)
+{
+    LONG SkipnStrides = startIdx + state->load_base_vertex_index;
+    const DWORD *pIdxBufL = NULL;
+    const WORD *pIdxBufS = NULL;
+    UINT vx_index;
+    int i;
+    const BYTE *ptr;
+
+    if (idxSize)
+    {
+        /* Immediate mode drawing can't make use of indices in a vbo - get the
+         * data from the index buffer. If the index buffer has no vbo (not
+         * supported or other reason), or with user pointer drawing idxData
+         * will be non-NULL. */
+        if (!idxData)
+            idxData = buffer_get_sysmem(state->index_buffer, gl_info);
+
+        if (idxSize == 2) pIdxBufS = idxData;
+        else pIdxBufL = idxData;
+    } else if (idxData) {
+        ERR("non-NULL idxData with 0 idxSize, this should never happen\n");
+        return;
+    }
+
+    /* Start drawing in GL */
+    gl_info->gl_ops.gl.p_glBegin(glPrimitiveType);
+
+    for (vx_index = 0; vx_index < numberOfVertices; ++vx_index)
+    {
+        if (idxData)
+        {
+            /* Indexed so work out the number of strides to skip */
+            if (idxSize == 2)
+                SkipnStrides = pIdxBufS[startIdx + vx_index] + state->load_base_vertex_index;
+            else
+                SkipnStrides = pIdxBufL[startIdx + vx_index] + state->load_base_vertex_index;
+        }
+
+        for (i = MAX_ATTRIBS - 1; i >= 0; i--)
+        {
+            if (!(si->use_map & (1 << i))) continue;
+
+            ptr = si->elements[i].data.addr + si->elements[i].stride * SkipnStrides;
+
+            send_attribute(gl_info, si->elements[i].format->id, i, ptr);
+        }
+        SkipnStrides++;
+    }
+
+    gl_info->gl_ops.gl.p_glEnd();
+}
+
+/* Context activation is done by the caller. */
+static void drawStridedInstanced(const struct wined3d_gl_info *gl_info, const struct wined3d_state *state,
+        const struct wined3d_stream_info *si, UINT numberOfVertices, GLenum glPrimitiveType,
+        const void *idxData, UINT idxSize, UINT startIdx, UINT base_vertex_index, UINT instance_count)
+{
+    int numInstancedAttribs = 0, j;
+    UINT instancedData[sizeof(si->elements) / sizeof(*si->elements) /* 16 */];
+    GLenum idxtype = idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
+    UINT i;
+
+    if (!idxSize)
+    {
+        /* This is a nasty thing. MSDN says no hardware supports that and apps have to use software vertex processing.
+         * We don't support this for now
+         *
+         * Shouldn't be too hard to support with opengl, in theory just call glDrawArrays instead of drawElements.
+         * But the StreamSourceFreq value has a different meaning in that situation.
+         */
+        FIXME("Non-indexed instanced drawing is not supported\n");
+        return;
+    }
+
+    for (i = 0; i < sizeof(si->elements) / sizeof(*si->elements); ++i)
+    {
+        if (!(si->use_map & (1 << i))) continue;
+
+        if (state->streams[si->elements[i].stream_idx].flags & WINED3DSTREAMSOURCE_INSTANCEDATA)
+        {
+            instancedData[numInstancedAttribs] = i;
+            numInstancedAttribs++;
+        }
+    }
+
+    for (i = 0; i < instance_count; ++i)
+    {
+        /* Specify the instanced attributes using immediate mode calls */
+        for(j = 0; j < numInstancedAttribs; j++) {
+            const BYTE *ptr = si->elements[instancedData[j]].data.addr
+                    + si->elements[instancedData[j]].stride * i;
+            if (si->elements[instancedData[j]].data.buffer_object)
+            {
+                struct wined3d_buffer *vb = state->streams[si->elements[instancedData[j]].stream_idx].buffer;
+                ptr += (ULONG_PTR)buffer_get_sysmem(vb, gl_info);
+            }
+
+            send_attribute(gl_info, si->elements[instancedData[j]].format->id, instancedData[j], ptr);
+        }
+
+        if (gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX])
+        {
+            GL_EXTCALL(glDrawElementsBaseVertex(glPrimitiveType, numberOfVertices, idxtype,
+                        (const char *)idxData+(idxSize * startIdx), base_vertex_index));
+            checkGLcall("glDrawElementsBaseVertex");
+        }
+        else
+        {
+            gl_info->gl_ops.gl.p_glDrawElements(glPrimitiveType, numberOfVertices, idxtype,
+                        (const char *)idxData + (idxSize * startIdx));
+            checkGLcall("glDrawElements");
+        }
+    }
+}
+
+static void remove_vbos(const struct wined3d_gl_info *gl_info,
+        const struct wined3d_state *state, struct wined3d_stream_info *s)
+{
+    unsigned int i;
+
+    for (i = 0; i < (sizeof(s->elements) / sizeof(*s->elements)); ++i)
+    {
+        struct wined3d_stream_info_element *e;
+
+        if (!(s->use_map & (1 << i))) continue;
+
+        e = &s->elements[i];
+        if (e->data.buffer_object)
+        {
+            struct wined3d_buffer *vb = state->streams[e->stream_idx].buffer;
+            e->data.buffer_object = 0;
+            e->data.addr = (BYTE *)((ULONG_PTR)e->data.addr + (ULONG_PTR)buffer_get_sysmem(vb, gl_info));
+        }
+    }
+}
+
+/* Routine common to the draw primitive and draw indexed primitive routines */
+void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_count,
+        UINT start_instance, UINT instance_count, BOOL indexed)
+{
+    const struct wined3d_state *state = &device->stateBlock->state;
+    const struct wined3d_stream_info *stream_info;
+    struct wined3d_event_query *ib_query = NULL;
+    struct wined3d_stream_info si_emulated;
+    const struct wined3d_gl_info *gl_info;
+    struct wined3d_context *context;
+    BOOL emulation = FALSE;
+    const void *idx_data = NULL;
+    UINT idx_size = 0;
+    unsigned int i;
+
+    if (!index_count) return;
+
+    if (state->render_states[WINED3D_RS_COLORWRITEENABLE])
+    {
+        /* Invalidate the back buffer memory so LockRect will read it the next time */
+        for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i)
+        {
+            struct wined3d_surface *target = device->fb.render_targets[i];
+            if (target)
+            {
+                surface_load_location(target, target->draw_binding, NULL);
+                surface_modify_location(target, target->draw_binding, TRUE);
+            }
+        }
+    }
+
+    /* Signals other modules that a drawing is in progress and the stateblock finalized */
+    device->isInDraw = TRUE;
+
+    context = context_acquire(device, device->fb.render_targets[0]);
+    if (!context->valid)
+    {
+        context_release(context);
+        WARN("Invalid context, skipping draw.\n");
+        return;
+    }
+    gl_info = context->gl_info;
+
+    if (device->fb.depth_stencil)
+    {
+        /* Note that this depends on the context_acquire() call above to set
+         * context->render_offscreen properly. We don't currently take the
+         * Z-compare function into account, but we could skip loading the
+         * depthstencil for D3DCMP_NEVER and D3DCMP_ALWAYS as well. Also note
+         * that we never copy the stencil data.*/
+        DWORD location = context->render_offscreen ? device->fb.depth_stencil->draw_binding : SFLAG_INDRAWABLE;
+        if (state->render_states[WINED3D_RS_ZWRITEENABLE] || state->render_states[WINED3D_RS_ZENABLE])
+        {
+            struct wined3d_surface *ds = device->fb.depth_stencil;
+            RECT current_rect, draw_rect, r;
+
+            if (!context->render_offscreen && ds != device->onscreen_depth_stencil)
+                device_switch_onscreen_ds(device, context, ds);
+
+            if (ds->flags & location)
+                SetRect(&current_rect, 0, 0, ds->ds_current_size.cx, ds->ds_current_size.cy);
+            else
+                SetRectEmpty(&current_rect);
+
+            wined3d_get_draw_rect(state, &draw_rect);
+
+            IntersectRect(&r, &draw_rect, &current_rect);
+            if (!EqualRect(&r, &draw_rect))
+                surface_load_ds_location(ds, context, location);
+        }
+    }
+
+    if (!context_apply_draw_state(context, device))
+    {
+        context_release(context);
+        WARN("Unable to apply draw state, skipping draw.\n");
+        return;
+    }
+
+#ifdef DEBUG_misha
+    DBGL_CHECK_DRAWPRIM(context->gl_info, device);
+#endif
+
+    if (device->fb.depth_stencil && state->render_states[WINED3D_RS_ZWRITEENABLE])
+    {
+        struct wined3d_surface *ds = device->fb.depth_stencil;
+        DWORD location = context->render_offscreen ? ds->draw_binding : SFLAG_INDRAWABLE;
+
+        surface_modify_ds_location(ds, location, ds->ds_current_size.cx, ds->ds_current_size.cy);
+    }
+
+    if ((!gl_info->supported[WINED3D_GL_VERSION_2_0]
+            || !gl_info->supported[NV_POINT_SPRITE])
+            && context->render_offscreen
+            && state->render_states[WINED3D_RS_POINTSPRITEENABLE]
+            && state->gl_primitive_type == GL_POINTS)
+    {
+        FIXME("Point sprite coordinate origin switching not supported.\n");
+    }
+
+    stream_info = &device->stream_info;
+    if (device->instance_count)
+        instance_count = device->instance_count;
+
+        if (indexed)
+        {
+                struct wined3d_buffer *index_buffer = state->index_buffer;
+                if (!index_buffer->buffer_object || !stream_info->all_vbo)
+            idx_data = index_buffer->resource.allocatedMemory;
+                else
+                {
+                    ib_query = index_buffer->query;
+            idx_data = NULL;
+            }
+
+            if (state->index_format == WINED3DFMT_R16_UINT)
+                idx_size = 2;
+            else
+                idx_size = 4;
+        }
+
+        if (!use_vs(state))
+        {
+            if (!stream_info->position_transformed && context->num_untracked_materials
+                    && state->render_states[WINED3D_RS_LIGHTING])
+            {
+                static BOOL warned;
+
+                if (!warned++)
+                    FIXME("Using software emulation because not all material properties could be tracked.\n");
+                else
+                    WARN_(d3d_perf)("Using software emulation because not all material properties could be tracked.\n");
+                emulation = TRUE;
+            }
+            else if (context->fog_coord && state->render_states[WINED3D_RS_FOGENABLE])
+            {
+                static BOOL warned;
+
+            /* Either write a pipeline replacement shader or convert the
+             * specular alpha from unsigned byte to a float in the vertex
+             * buffer. */
+            if (!warned++)
+                FIXME("Using software emulation because manual fog coordinates are provided.\n");
+            else
+                WARN_(d3d_perf)("Using software emulation because manual fog coordinates are provided.\n");
+            emulation = TRUE;
+        }
+
+        if (emulation)
+        {
+            si_emulated = device->stream_info;
+            remove_vbos(gl_info, state, &si_emulated);
+            stream_info = &si_emulated;
+            }
+        }
+
+        if (device->useDrawStridedSlow || emulation)
+        {
+        /* Immediate mode drawing. */
+            if (use_vs(state))
+            {
+                static BOOL warned;
+
+            if (!warned++)
+                FIXME("Using immediate mode with vertex shaders for half float emulation.\n");
+            else
+                WARN_(d3d_perf)("Using immediate mode with vertex shaders for half float emulation.\n");
+
+            drawStridedSlowVs(gl_info, state, stream_info, index_count,
+                    state->gl_primitive_type, idx_data, idx_size, start_idx);
+            }
+            else
+            {
+                drawStridedSlow(device, context, stream_info, index_count,
+                    state->gl_primitive_type, idx_data, idx_size, start_idx);
+            }
+        }
+    else if (!gl_info->supported[ARB_INSTANCED_ARRAYS] && instance_count)
+        {
+        /* Instancing emulation by mixing immediate mode and arrays. */
+        drawStridedInstanced(gl_info, state, stream_info, index_count, state->gl_primitive_type,
+                idx_data, idx_size, start_idx, state->base_vertex_index, instance_count);
+        }
+        else
+        {
+        drawStridedFast(gl_info, state->gl_primitive_type, index_count, idx_size, idx_data,
+                start_idx, state->base_vertex_index, start_instance, instance_count);
+    }
+
+    if (ib_query)
+        wined3d_event_query_issue(ib_query, device);
+    for (i = 0; i < device->num_buffer_queries; ++i)
+    {
+        wined3d_event_query_issue(device->buffer_queries[i], device);
+    }
+
+    if (wined3d_settings.strict_draw_ordering)
+        gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */
+
+    context_release(context);
+
+    TRACE("Done all gl drawing\n");
+
+    /* Control goes back to the device, stateblock values may change again */
+    device->isInDraw = FALSE;
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/gl_compat.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/gl_compat.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/gl_compat.c	(revision 46521)
@@ -0,0 +1,543 @@
+/*
+ * Compatibility functions for older GL implementations
+ *
+ * Copyright 2008 Stefan Dösinger for CodeWeavers
+ *
+ * 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 <stdio.h>
+#ifdef HAVE_FLOAT_H
+# include <float.h>
+#endif
+
+#include "wined3d_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(gl_compat);
+WINE_DECLARE_DEBUG_CHANNEL(d3d_perf);
+
+/* Start GL_ARB_multitexture emulation */
+static void WINE_GLAPI wine_glMultiTexCoord1fARB(GLenum target, GLfloat s) {
+    if(target != GL_TEXTURE0) {
+        ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+        return;
+    }
+    context_get_current()->gl_info->gl_ops.gl.p_glTexCoord1f(s);
+}
+
+static void WINE_GLAPI wine_glMultiTexCoord1fvARB(GLenum target, const GLfloat *v) {
+    if(target != GL_TEXTURE0) {
+        ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+        return;
+    }
+    context_get_current()->gl_info->gl_ops.gl.p_glTexCoord1fv(v);
+}
+
+static void WINE_GLAPI wine_glMultiTexCoord2fARB(GLenum target, GLfloat s, GLfloat t) {
+    if(target != GL_TEXTURE0) {
+        ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+        return;
+    }
+    context_get_current()->gl_info->gl_ops.gl.p_glTexCoord2f(s, t);
+}
+
+static void WINE_GLAPI wine_glMultiTexCoord2fvARB(GLenum target, const GLfloat *v) {
+    if(target != GL_TEXTURE0) {
+        ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+        return;
+    }
+    context_get_current()->gl_info->gl_ops.gl.p_glTexCoord2fv(v);
+}
+
+static void WINE_GLAPI wine_glMultiTexCoord3fARB(GLenum target, GLfloat s, GLfloat t, GLfloat r) {
+    if(target != GL_TEXTURE0) {
+        ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+        return;
+    }
+    context_get_current()->gl_info->gl_ops.gl.p_glTexCoord3f(s, t, r);
+}
+
+static void WINE_GLAPI wine_glMultiTexCoord3fvARB(GLenum target, const GLfloat *v) {
+    if(target != GL_TEXTURE0) {
+        ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+        return;
+    }
+    context_get_current()->gl_info->gl_ops.gl.p_glTexCoord3fv(v);
+}
+
+static void WINE_GLAPI wine_glMultiTexCoord4fARB(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) {
+    if(target != GL_TEXTURE0) {
+        ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+        return;
+    }
+    context_get_current()->gl_info->gl_ops.gl.p_glTexCoord4f(s, t, r, q);
+}
+
+static void WINE_GLAPI wine_glMultiTexCoord4fvARB(GLenum target, const GLfloat *v) {
+    if(target != GL_TEXTURE0) {
+        ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+        return;
+    }
+    context_get_current()->gl_info->gl_ops.gl.p_glTexCoord4fv(v);
+}
+
+static void WINE_GLAPI wine_glMultiTexCoord2svARB(GLenum target, const GLshort *v) {
+    if(target != GL_TEXTURE0) {
+        ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+        return;
+    }
+    context_get_current()->gl_info->gl_ops.gl.p_glTexCoord2sv(v);
+}
+
+static void WINE_GLAPI wine_glMultiTexCoord4svARB(GLenum target, const GLshort *v) {
+    if(target != GL_TEXTURE0) {
+        ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+        return;
+    }
+    context_get_current()->gl_info->gl_ops.gl.p_glTexCoord4sv(v);
+}
+
+static void WINE_GLAPI wine_glActiveTextureARB(GLenum texture) {
+    if(texture != GL_TEXTURE0) {
+        ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+        return;
+    }
+}
+
+static void WINE_GLAPI wine_glClientActiveTextureARB(GLenum texture) {
+    if(texture != GL_TEXTURE0) {
+        ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
+        return;
+    }
+}
+
+static void (WINE_GLAPI *old_multitex_glGetIntegerv) (GLenum pname, GLint* params) = NULL;
+static void WINE_GLAPI wine_glGetIntegerv(GLenum pname, GLint* params) {
+    switch(pname) {
+        case GL_ACTIVE_TEXTURE:         *params = 0;    break;
+        case GL_MAX_TEXTURE_UNITS_ARB:  *params = 1;    break;
+        default: old_multitex_glGetIntegerv(pname, params);
+    }
+}
+
+static void (WINE_GLAPI *old_multitex_glGetFloatv) (GLenum pname, GLfloat* params) = NULL;
+static void WINE_GLAPI wine_glGetFloatv(GLenum pname, GLfloat* params) {
+    if (pname == GL_ACTIVE_TEXTURE) *params = 0.0f;
+    else old_multitex_glGetFloatv(pname, params);
+}
+
+static void (WINE_GLAPI *old_multitex_glGetDoublev) (GLenum pname, GLdouble* params) = NULL;
+static void WINE_GLAPI wine_glGetDoublev(GLenum pname, GLdouble* params) {
+    if(pname == GL_ACTIVE_TEXTURE) *params = 0.0;
+    else old_multitex_glGetDoublev(pname, params);
+}
+
+/* Start GL_EXT_fogcoord emulation */
+static void (WINE_GLAPI *old_fogcoord_glEnable) (GLenum cap) = NULL;
+static void WINE_GLAPI wine_glEnable(GLenum cap) {
+    if(cap == GL_FOG) {
+        struct wined3d_context *ctx = context_get_current();
+        ctx->fog_enabled = 1;
+        if(ctx->gl_fog_source != GL_FRAGMENT_DEPTH_EXT) return;
+    }
+    old_fogcoord_glEnable(cap);
+}
+
+static void (WINE_GLAPI *old_fogcoord_glDisable) (GLenum cap) = NULL;
+static void WINE_GLAPI wine_glDisable(GLenum cap) {
+    if(cap == GL_FOG) {
+        struct wined3d_context *ctx = context_get_current();
+        ctx->fog_enabled = 0;
+        if(ctx->gl_fog_source != GL_FRAGMENT_DEPTH_EXT) return;
+    }
+    old_fogcoord_glDisable(cap);
+}
+
+static void (WINE_GLAPI *old_fogcoord_glFogi) (GLenum pname, GLint param) = NULL;
+static void WINE_GLAPI wine_glFogi(GLenum pname, GLint param) {
+    struct wined3d_context *ctx = context_get_current();
+
+    if(pname == GL_FOG_COORDINATE_SOURCE_EXT) {
+        ctx->gl_fog_source = param;
+        if(param == GL_FRAGMENT_DEPTH_EXT) {
+            if(ctx->fog_enabled) old_fogcoord_glEnable(GL_FOG);
+        } else {
+            WARN_(d3d_perf)("Fog coords activated, but not supported. Using slow emulation\n");
+            old_fogcoord_glDisable(GL_FOG);
+        }
+    } else {
+        if(pname == GL_FOG_START) {
+            ctx->fogstart = (float) param;
+        } else if(pname == GL_FOG_END) {
+            ctx->fogend = (float) param;
+        }
+        old_fogcoord_glFogi(pname, param);
+    }
+}
+
+static void (WINE_GLAPI *old_fogcoord_glFogiv) (GLenum pname, const GLint *param) = NULL;
+static void WINE_GLAPI wine_glFogiv(GLenum pname, const GLint *param) {
+    struct wined3d_context *ctx = context_get_current();
+    if(pname == GL_FOG_COORDINATE_SOURCE_EXT) {
+        ctx->gl_fog_source = *param;
+        if(*param == GL_FRAGMENT_DEPTH_EXT) {
+            if(ctx->fog_enabled) old_fogcoord_glEnable(GL_FOG);
+        } else {
+            WARN_(d3d_perf)("Fog coords activated, but not supported. Using slow emulation\n");
+            old_fogcoord_glDisable(GL_FOG);
+        }
+    } else {
+        if(pname == GL_FOG_START) {
+            ctx->fogstart = (float) *param;
+        } else if(pname == GL_FOG_END) {
+            ctx->fogend = (float) *param;
+        }
+        old_fogcoord_glFogiv(pname, param);
+    }
+}
+
+static void (WINE_GLAPI *old_fogcoord_glFogf) (GLenum pname, GLfloat param) = NULL;
+static void WINE_GLAPI wine_glFogf(GLenum pname, GLfloat param) {
+    struct wined3d_context *ctx = context_get_current();
+    if(pname == GL_FOG_COORDINATE_SOURCE_EXT) {
+        ctx->gl_fog_source = (GLint) param;
+        if(param == GL_FRAGMENT_DEPTH_EXT) {
+            if(ctx->fog_enabled) old_fogcoord_glEnable(GL_FOG);
+        } else {
+            WARN_(d3d_perf)("Fog coords activated, but not supported. Using slow emulation\n");
+            old_fogcoord_glDisable(GL_FOG);
+        }
+    } else {
+        if(pname == GL_FOG_START) {
+            ctx->fogstart = param;
+        } else if(pname == GL_FOG_END) {
+            ctx->fogend = param;
+        }
+        old_fogcoord_glFogf(pname, param);
+    }
+}
+
+static void (WINE_GLAPI *old_fogcoord_glFogfv) (GLenum pname, const GLfloat *param) = NULL;
+static void WINE_GLAPI wine_glFogfv(GLenum pname, const GLfloat *param) {
+    struct wined3d_context *ctx = context_get_current();
+    if(pname == GL_FOG_COORDINATE_SOURCE_EXT) {
+        ctx->gl_fog_source = (GLint) *param;
+        if(*param == GL_FRAGMENT_DEPTH_EXT) {
+            if(ctx->fog_enabled) old_fogcoord_glEnable(GL_FOG);
+        } else {
+            WARN_(d3d_perf)("Fog coords activated, but not supported. Using slow emulation\n");
+            old_fogcoord_glDisable(GL_FOG);
+        }
+    } else {
+        if(pname == GL_FOG_COLOR) {
+            ctx->fogcolor[0] = param[0];
+            ctx->fogcolor[1] = param[1];
+            ctx->fogcolor[2] = param[2];
+            ctx->fogcolor[3] = param[3];
+        } else if(pname == GL_FOG_START) {
+            ctx->fogstart = *param;
+        } else if(pname == GL_FOG_END) {
+            ctx->fogend = *param;
+        }
+        old_fogcoord_glFogfv(pname, param);
+    }
+}
+
+static void (WINE_GLAPI *old_fogcoord_glVertex4f) (GLfloat x, GLfloat y, GLfloat z, GLfloat w) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glVertex4fv) (const GLfloat *pos) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glVertex3f) (GLfloat x, GLfloat y, GLfloat z) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glVertex3fv) (const GLfloat *pos) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glColor4f) (GLfloat r, GLfloat g, GLfloat b, GLfloat a) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glColor4fv) (const GLfloat *color) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glColor3f) (GLfloat r, GLfloat g, GLfloat b) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glColor3fv) (const GLfloat *color) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glColor4ub) (GLubyte r, GLubyte g, GLubyte b, GLubyte a) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glFogCoordfEXT) (GLfloat f) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glFogCoorddEXT) (GLdouble f) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glFogCoordfvEXT) (const GLfloat *f) = NULL;
+static void (WINE_GLAPI *old_fogcoord_glFogCoorddvEXT) (const GLdouble *f) = NULL;
+
+static void WINE_GLAPI wine_glVertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
+    struct wined3d_context *ctx = context_get_current();
+    if(ctx->gl_fog_source == GL_FOG_COORDINATE_EXT && ctx->fog_enabled) {
+        GLfloat c[4] = {ctx->color[0], ctx->color[1], ctx->color[2], ctx->color[3]};
+        GLfloat i;
+
+        i = (ctx->fogend - ctx->fog_coord_value) / (ctx->fogend - ctx->fogstart);
+        c[0] = i * c[0] + (1.0f - i) * ctx->fogcolor[0];
+        c[1] = i * c[1] + (1.0f - i) * ctx->fogcolor[1];
+        c[2] = i * c[2] + (1.0f - i) * ctx->fogcolor[2];
+
+        old_fogcoord_glColor4f(c[0], c[1], c[2], c[3]);
+        old_fogcoord_glVertex4f(x, y, z, w);
+    } else {
+        old_fogcoord_glVertex4f(x, y, z, w);
+    }
+}
+
+static void WINE_GLAPI wine_glVertex4fv(const GLfloat *pos) {
+    wine_glVertex4f(pos[0], pos[1], pos[2], pos[3]);
+}
+
+static void WINE_GLAPI wine_glVertex3f(GLfloat x, GLfloat y, GLfloat z) {
+    wine_glVertex4f(x, y, z, 1.0f);
+}
+
+static void WINE_GLAPI wine_glVertex3fv(const GLfloat *pos) {
+    wine_glVertex4f(pos[0], pos[1], pos[2], 1.0f);
+}
+
+static void WINE_GLAPI wine_glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
+    struct wined3d_context *ctx = context_get_current();
+    ctx->color[0] = r;
+    ctx->color[1] = g;
+    ctx->color[2] = b;
+    ctx->color[3] = a;
+    old_fogcoord_glColor4f(r, g, b, a);
+}
+
+static void WINE_GLAPI wine_glColor4fv(const GLfloat *c) {
+    wine_glColor4f(c[0], c[1], c[2], c[3]);
+}
+
+static void WINE_GLAPI wine_glColor3f(GLfloat r, GLfloat g, GLfloat b) {
+    wine_glColor4f(r, g, b, 1.0f);
+}
+
+static void WINE_GLAPI wine_glColor3fv(const GLfloat *c) {
+    wine_glColor4f(c[0], c[1], c[2], 1.0f);
+}
+
+static void WINE_GLAPI wine_glColor4ub(GLubyte r, GLubyte g, GLubyte b, GLubyte a) {
+    wine_glColor4f(r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f);
+}
+
+/* In D3D the fog coord is a UBYTE, so there's no problem with using the single
+ * precision function
+ */
+static void WINE_GLAPI wine_glFogCoordfEXT(GLfloat f) {
+    struct wined3d_context *ctx = context_get_current();
+    ctx->fog_coord_value = f;
+}
+static void WINE_GLAPI wine_glFogCoorddEXT(GLdouble f) {
+    wine_glFogCoordfEXT((GLfloat) f);
+}
+static void WINE_GLAPI wine_glFogCoordfvEXT(const GLfloat *f) {
+    wine_glFogCoordfEXT(*f);
+}
+static void WINE_GLAPI wine_glFogCoorddvEXT(const GLdouble *f) {
+    wine_glFogCoordfEXT((GLfloat) *f);
+}
+
+/* End GL_EXT_fog_coord emulation */
+
+void add_gl_compat_wrappers(struct wined3d_gl_info *gl_info)
+{
+    if (!gl_info->supported[ARB_MULTITEXTURE])
+    {
+        TRACE("Applying GL_ARB_multitexture emulation hooks\n");
+        gl_info->gl_ops.ext.p_glActiveTextureARB        = wine_glActiveTextureARB;
+        gl_info->gl_ops.ext.p_glClientActiveTextureARB  = wine_glClientActiveTextureARB;
+        gl_info->gl_ops.ext.p_glMultiTexCoord1fARB      = wine_glMultiTexCoord1fARB;
+        gl_info->gl_ops.ext.p_glMultiTexCoord1fvARB     = wine_glMultiTexCoord1fvARB;
+        gl_info->gl_ops.ext.p_glMultiTexCoord2fARB      = wine_glMultiTexCoord2fARB;
+        gl_info->gl_ops.ext.p_glMultiTexCoord2fvARB     = wine_glMultiTexCoord2fvARB;
+        gl_info->gl_ops.ext.p_glMultiTexCoord3fARB      = wine_glMultiTexCoord3fARB;
+        gl_info->gl_ops.ext.p_glMultiTexCoord3fvARB     = wine_glMultiTexCoord3fvARB;
+        gl_info->gl_ops.ext.p_glMultiTexCoord4fARB      = wine_glMultiTexCoord4fARB;
+        gl_info->gl_ops.ext.p_glMultiTexCoord4fvARB     = wine_glMultiTexCoord4fvARB;
+        gl_info->gl_ops.ext.p_glMultiTexCoord2svARB     = wine_glMultiTexCoord2svARB;
+        gl_info->gl_ops.ext.p_glMultiTexCoord4svARB     = wine_glMultiTexCoord4svARB;
+        if(old_multitex_glGetIntegerv) {
+            FIXME("GL_ARB_multitexture glGetIntegerv hook already applied\n");
+        } else {
+            old_multitex_glGetIntegerv = gl_info->gl_ops.gl.p_glGetIntegerv;
+            gl_info->gl_ops.gl.p_glGetIntegerv = wine_glGetIntegerv;
+        }
+        if(old_multitex_glGetFloatv) {
+            FIXME("GL_ARB_multitexture glGetGloatv hook already applied\n");
+        } else {
+            old_multitex_glGetFloatv = gl_info->gl_ops.gl.p_glGetFloatv;
+            gl_info->gl_ops.gl.p_glGetFloatv = wine_glGetFloatv;
+        }
+        if(old_multitex_glGetDoublev) {
+            FIXME("GL_ARB_multitexture glGetDoublev hook already applied\n");
+        } else {
+            old_multitex_glGetDoublev = gl_info->gl_ops.gl.p_glGetDoublev;
+            gl_info->gl_ops.gl.p_glGetDoublev = wine_glGetDoublev;
+        }
+        gl_info->supported[ARB_MULTITEXTURE] = TRUE;
+    }
+
+    if (!gl_info->supported[EXT_FOG_COORD])
+    {
+        /* This emulation isn't perfect. There are a number of potential problems, but they should
+         * not matter in practise:
+         *
+         * Fog vs fragment shader: If we are using GL_ARB_fragment_program with the fog option, the
+         * glDisable(GL_FOG) here won't matter. However, if we have GL_ARB_fragment_program, it is pretty
+         * unlikely that we don't have GL_EXT_fog_coord. Besides, we probably have GL_ARB_vertex_program
+         * too, which would allow fog coord emulation in a fixed function vertex pipeline replacement.
+         *
+         * Fog vs texture: We apply the fog in the vertex color. An app could set up texturing settings which
+         * ignore the vertex color, thus effectively disabling our fog. However, in D3D this type of fog is
+         * a per-vertex fog too, so the apps shouldn't do that.
+         *
+         * Fog vs lighting: The app could in theory use D3DFOG_NONE table and D3DFOG_NONE vertex fog with
+         * untransformed vertices. That enables lighting and fog coords at the same time, and the lighting
+         * calculations could affect the already blended in fog color. There's nothing we can do against that,
+         * but most apps using fog color do their own lighting too and often even use RHW vertices. So live
+         * with it.
+         */
+        TRACE("Applying GL_ARB_fog_coord emulation hooks\n");
+
+        /* This probably means that the implementation doesn't advertise the extension, but implicitly supports
+         * it via the GL core version, or someone messed around in the extension table in directx.c. Add version-
+         * dependent loading for this extension if we ever hit this situation
+         */
+        if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
+        {
+            FIXME("GL implementation supports GL_ARB_fragment_program but not GL_EXT_fog_coord\n");
+            FIXME("The fog coord emulation will most likely fail\n");
+        }
+        else if (gl_info->supported[ARB_FRAGMENT_SHADER])
+        {
+            FIXME("GL implementation supports GL_ARB_fragment_shader but not GL_EXT_fog_coord\n");
+            FIXME("The fog coord emulation will most likely fail\n");
+        }
+
+        if(old_fogcoord_glFogi) {
+            FIXME("GL_EXT_fogcoord glFogi hook already applied\n");
+        } else {
+            old_fogcoord_glFogi = gl_info->gl_ops.gl.p_glFogi;
+            gl_info->gl_ops.gl.p_glFogi = wine_glFogi;
+        }
+        if(old_fogcoord_glFogiv) {
+            FIXME("GL_EXT_fogcoord glFogiv hook already applied\n");
+        } else {
+            old_fogcoord_glFogiv = gl_info->gl_ops.gl.p_glFogiv;
+            gl_info->gl_ops.gl.p_glFogiv = wine_glFogiv;
+        }
+        if(old_fogcoord_glFogf) {
+            FIXME("GL_EXT_fogcoord glFogf hook already applied\n");
+        } else {
+            old_fogcoord_glFogf = gl_info->gl_ops.gl.p_glFogf;
+            gl_info->gl_ops.gl.p_glFogf = wine_glFogf;
+        }
+        if(old_fogcoord_glFogfv) {
+            FIXME("GL_EXT_fogcoord glFogfv hook already applied\n");
+        } else {
+            old_fogcoord_glFogfv = gl_info->gl_ops.gl.p_glFogfv;
+            gl_info->gl_ops.gl.p_glFogfv = wine_glFogfv;
+        }
+        if(old_fogcoord_glEnable) {
+            FIXME("GL_EXT_fogcoord glEnable hook already applied\n");
+        } else {
+            old_fogcoord_glEnable = glEnableWINE;
+            glEnableWINE = wine_glEnable;
+        }
+        if(old_fogcoord_glDisable) {
+            FIXME("GL_EXT_fogcoord glDisable hook already applied\n");
+        } else {
+            old_fogcoord_glDisable = glDisableWINE;
+            glDisableWINE = wine_glDisable;
+        }
+
+        if(old_fogcoord_glVertex4f) {
+            FIXME("GL_EXT_fogcoord glVertex4f hook already applied\n");
+        } else {
+            old_fogcoord_glVertex4f = gl_info->gl_ops.gl.p_glVertex4f;
+            gl_info->gl_ops.gl.p_glVertex4f = wine_glVertex4f;
+        }
+        if(old_fogcoord_glVertex4fv) {
+            FIXME("GL_EXT_fogcoord glVertex4fv hook already applied\n");
+        } else {
+            old_fogcoord_glVertex4fv = gl_info->gl_ops.gl.p_glVertex4fv;
+            gl_info->gl_ops.gl.p_glVertex4fv = wine_glVertex4fv;
+        }
+        if(old_fogcoord_glVertex3f) {
+            FIXME("GL_EXT_fogcoord glVertex3f hook already applied\n");
+        } else {
+            old_fogcoord_glVertex3f = gl_info->gl_ops.gl.p_glVertex3f;
+            gl_info->gl_ops.gl.p_glVertex3f = wine_glVertex3f;
+        }
+        if(old_fogcoord_glVertex3fv) {
+            FIXME("GL_EXT_fogcoord glVertex3fv hook already applied\n");
+        } else {
+            old_fogcoord_glVertex3fv = gl_info->gl_ops.gl.p_glVertex3fv;
+            gl_info->gl_ops.gl.p_glVertex3fv = wine_glVertex3fv;
+        }
+
+        if(old_fogcoord_glColor4f) {
+            FIXME("GL_EXT_fogcoord glColor4f hook already applied\n");
+        } else {
+            old_fogcoord_glColor4f = gl_info->gl_ops.gl.p_glColor4f;
+            gl_info->gl_ops.gl.p_glColor4f = wine_glColor4f;
+        }
+        if(old_fogcoord_glColor4fv) {
+            FIXME("GL_EXT_fogcoord glColor4fv hook already applied\n");
+        } else {
+            old_fogcoord_glColor4fv = gl_info->gl_ops.gl.p_glColor4fv;
+            gl_info->gl_ops.gl.p_glColor4fv = wine_glColor4fv;
+        }
+        if(old_fogcoord_glColor3f) {
+            FIXME("GL_EXT_fogcoord glColor3f hook already applied\n");
+        } else {
+            old_fogcoord_glColor3f = gl_info->gl_ops.gl.p_glColor3f;
+            gl_info->gl_ops.gl.p_glColor3f = wine_glColor3f;
+        }
+        if(old_fogcoord_glColor3fv) {
+            FIXME("GL_EXT_fogcoord glColor3fv hook already applied\n");
+        } else {
+            old_fogcoord_glColor3fv = gl_info->gl_ops.gl.p_glColor3fv;
+            gl_info->gl_ops.gl.p_glColor3fv = wine_glColor3fv;
+        }
+        if(old_fogcoord_glColor4ub) {
+            FIXME("GL_EXT_fogcoord glColor4ub hook already applied\n");
+        } else {
+            old_fogcoord_glColor4ub = gl_info->gl_ops.gl.p_glColor4ub;
+            gl_info->gl_ops.gl.p_glColor4ub = wine_glColor4ub;
+        }
+
+        if(old_fogcoord_glFogCoordfEXT) {
+            FIXME("GL_EXT_fogcoord glFogCoordfEXT hook already applied\n");
+        } else {
+            old_fogcoord_glFogCoordfEXT = gl_info->gl_ops.ext.p_glFogCoordfEXT;
+            gl_info->gl_ops.ext.p_glFogCoordfEXT = wine_glFogCoordfEXT;
+        }
+        if(old_fogcoord_glFogCoordfvEXT) {
+            FIXME("GL_EXT_fogcoord glFogCoordfvEXT hook already applied\n");
+        } else {
+            old_fogcoord_glFogCoordfvEXT = gl_info->gl_ops.ext.p_glFogCoordfvEXT;
+            gl_info->gl_ops.ext.p_glFogCoordfvEXT = wine_glFogCoordfvEXT;
+        }
+        if(old_fogcoord_glFogCoorddEXT) {
+            FIXME("GL_EXT_fogcoord glFogCoorddEXT hook already applied\n");
+        } else {
+            old_fogcoord_glFogCoorddEXT = gl_info->gl_ops.ext.p_glFogCoorddEXT;
+            gl_info->gl_ops.ext.p_glFogCoorddEXT = wine_glFogCoorddEXT;
+        }
+        if(old_fogcoord_glFogCoorddvEXT) {
+            FIXME("GL_EXT_fogcoord glFogCoorddvEXT hook already applied\n");
+        } else {
+            old_fogcoord_glFogCoorddvEXT = gl_info->gl_ops.ext.p_glFogCoorddvEXT;
+            gl_info->gl_ops.ext.p_glFogCoorddvEXT = wine_glFogCoorddvEXT;
+        }
+        gl_info->supported[EXT_FOG_COORD] = TRUE;
+    }
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/glsl_shader.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/glsl_shader.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/glsl_shader.c	(revision 46521)
@@ -0,0 +1,7197 @@
+/*
+ * GLSL pixel and vertex shader implementation
+ *
+ * Copyright 2006 Jason Green
+ * Copyright 2006-2007 Henri Verbeet
+ * Copyright 2007-2009, 2013 Stefan Dösinger for CodeWeavers
+ * Copyright 2009-2011 Henri Verbeet for CodeWeavers
+ *
+ * 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
+ */
+
+/*
+ * D3D shader asm has swizzles on source parameters, and write masks for
+ * destination parameters. GLSL uses swizzles for both. The result of this is
+ * that for example "mov dst.xw, src.zyxw" becomes "dst.xw = src.zw" in GLSL.
+ * Ie, to generate a proper GLSL source swizzle, we need to take the D3D write
+ * mask for the destination parameter into account.
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <limits.h>
+#include <stdio.h>
+
+#include "wined3d_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
+WINE_DECLARE_DEBUG_CHANNEL(d3d_constants);
+WINE_DECLARE_DEBUG_CHANNEL(d3d);
+WINE_DECLARE_DEBUG_CHANNEL(winediag);
+
+#define WINED3D_GLSL_SAMPLE_PROJECTED   0x1
+#define WINED3D_GLSL_SAMPLE_NPOT        0x2
+#define WINED3D_GLSL_SAMPLE_LOD         0x4
+#define WINED3D_GLSL_SAMPLE_GRAD        0x8
+
+struct glsl_dst_param
+{
+    char reg_name[150];
+    char mask_str[6];
+};
+
+struct glsl_src_param
+{
+    char reg_name[150];
+    char param_str[200];
+};
+
+struct glsl_sample_function
+{
+    const char *name;
+    DWORD coord_mask;
+};
+
+enum heap_node_op
+{
+    HEAP_NODE_TRAVERSE_LEFT,
+    HEAP_NODE_TRAVERSE_RIGHT,
+    HEAP_NODE_POP,
+};
+
+struct constant_entry
+{
+    unsigned int idx;
+    unsigned int version;
+};
+
+struct constant_heap
+{
+    struct constant_entry *entries;
+    unsigned int *positions;
+    unsigned int size;
+};
+
+/* GLSL shader private data */
+struct shader_glsl_priv {
+    struct wined3d_shader_buffer shader_buffer;
+    struct wine_rb_tree program_lookup;
+    struct glsl_shader_prog_link *glsl_program;
+    struct constant_heap vconst_heap;
+    struct constant_heap pconst_heap;
+    unsigned char *stack;
+    GLhandleARB depth_blt_program_full[tex_type_count];
+    GLhandleARB depth_blt_program_masked[tex_type_count];
+    UINT next_constant_version;
+
+    const struct wined3d_vertex_pipe_ops *vertex_pipe;
+    const struct fragment_pipeline *fragment_pipe;
+    struct wine_rb_tree ffp_vertex_shaders;
+    struct wine_rb_tree ffp_fragment_shaders;
+    BOOL ffp_proj_control;
+};
+
+struct glsl_vs_program
+{
+    struct list shader_entry;
+    GLhandleARB id;
+    GLenum vertex_color_clamp;
+    GLint *uniform_f_locations;
+    GLint uniform_i_locations[MAX_CONST_I];
+    GLint pos_fixup_location;
+};
+
+struct glsl_gs_program
+{
+    struct list shader_entry;
+    GLhandleARB id;
+};
+
+struct glsl_ps_program
+{
+    struct list shader_entry;
+    GLhandleARB id;
+    GLint *uniform_f_locations;
+    GLint uniform_i_locations[MAX_CONST_I];
+    GLint bumpenv_mat_location[MAX_TEXTURES];
+    GLint bumpenv_lum_scale_location[MAX_TEXTURES];
+    GLint bumpenv_lum_offset_location[MAX_TEXTURES];
+    GLint tex_factor_location;
+    GLint specular_enable_location;
+    GLint ycorrection_location;
+    GLint np2_fixup_location;
+    const struct ps_np2fixup_info *np2_fixup_info;
+};
+
+/* Struct to maintain data about a linked GLSL program */
+struct glsl_shader_prog_link
+{
+    struct wine_rb_entry program_lookup_entry;
+    struct glsl_vs_program vs;
+    struct glsl_gs_program gs;
+    struct glsl_ps_program ps;
+    GLhandleARB programId;
+    UINT constant_version;
+};
+
+struct glsl_program_key
+{
+    GLhandleARB vs_id;
+    GLhandleARB gs_id;
+    GLhandleARB ps_id;
+};
+
+struct shader_glsl_ctx_priv {
+    const struct vs_compile_args    *cur_vs_args;
+    const struct ps_compile_args    *cur_ps_args;
+    struct ps_np2fixup_info         *cur_np2fixup_info;
+};
+
+struct glsl_ps_compiled_shader
+{
+    struct ps_compile_args          args;
+    struct ps_np2fixup_info         np2fixup;
+    GLhandleARB                     prgId;
+};
+
+struct glsl_vs_compiled_shader
+{
+    struct vs_compile_args          args;
+    GLhandleARB                     prgId;
+};
+
+struct glsl_gs_compiled_shader
+{
+    GLhandleARB id;
+};
+
+struct glsl_shader_private
+{
+    union
+    {
+        struct glsl_vs_compiled_shader *vs;
+        struct glsl_gs_compiled_shader *gs;
+        struct glsl_ps_compiled_shader *ps;
+    } gl_shaders;
+    UINT num_gl_shaders, shader_array_size;
+};
+
+struct glsl_ffp_vertex_shader
+{
+    struct wined3d_ffp_vs_desc desc;
+    GLhandleARB id;
+    struct list linked_programs;
+};
+
+struct glsl_ffp_fragment_shader
+{
+    struct ffp_frag_desc entry;
+    GLhandleARB id;
+    struct list linked_programs;
+};
+
+struct glsl_ffp_destroy_ctx
+{
+    struct shader_glsl_priv *priv;
+    const struct wined3d_gl_info *gl_info;
+};
+
+static const char *debug_gl_shader_type(GLenum type)
+{
+    switch (type)
+    {
+#define WINED3D_TO_STR(u) case u: return #u
+        WINED3D_TO_STR(GL_VERTEX_SHADER_ARB);
+        WINED3D_TO_STR(GL_GEOMETRY_SHADER_ARB);
+        WINED3D_TO_STR(GL_FRAGMENT_SHADER_ARB);
+#undef WINED3D_TO_STR
+        default:
+            return wine_dbg_sprintf("UNKNOWN(%#x)", type);
+    }
+}
+
+static const char *shader_glsl_get_prefix(enum wined3d_shader_type type)
+{
+    switch (type)
+    {
+        case WINED3D_SHADER_TYPE_VERTEX:
+            return "vs";
+
+        case WINED3D_SHADER_TYPE_GEOMETRY:
+            return "gs";
+
+        case WINED3D_SHADER_TYPE_PIXEL:
+            return "ps";
+
+        default:
+            FIXME("Unhandled shader type %#x.\n", type);
+            return "unknown";
+    }
+}
+
+/* Extract a line from the info log.
+ * Note that this modifies the source string. */
+static char *get_info_log_line(char **ptr)
+{
+    char *p, *q;
+
+    p = *ptr;
+    if (!(q = strstr(p, "\n")))
+    {
+        if (!*p) return NULL;
+        *ptr += strlen(p);
+        return p;
+    }
+    *q = '\0';
+    *ptr = q + 1;
+
+    return p;
+}
+
+/* Context activation is done by the caller. */
+static void print_glsl_info_log(const struct wined3d_gl_info *gl_info, GLhandleARB obj)
+{
+    int infologLength = 0;
+    char *infoLog;
+
+    if (!WARN_ON(d3d_shader) && !FIXME_ON(d3d_shader))
+        return;
+
+    GL_EXTCALL(glGetObjectParameterivARB(obj,
+               GL_OBJECT_INFO_LOG_LENGTH_ARB,
+               &infologLength));
+
+    /* A size of 1 is just a null-terminated string, so the log should be bigger than
+     * that if there are errors. */
+    if (infologLength > 1)
+    {
+        char *ptr, *line;
+
+        infoLog = HeapAlloc(GetProcessHeap(), 0, infologLength);
+        /* The info log is supposed to be zero-terminated, but at least some
+         * versions of fglrx don't terminate the string properly. The reported
+         * length does include the terminator, so explicitly set it to zero
+         * here. */
+        infoLog[infologLength - 1] = 0;
+        GL_EXTCALL(glGetInfoLogARB(obj, infologLength, NULL, infoLog));
+
+        ptr = infoLog;
+        if (gl_info->quirks & WINED3D_QUIRK_INFO_LOG_SPAM)
+        {
+            WARN("Info log received from GLSL shader #%u:\n", obj);
+            while ((line = get_info_log_line(&ptr))) WARN("    %s\n", line);
+        }
+        else
+        {
+            FIXME("Info log received from GLSL shader #%u:\n", obj);
+            while ((line = get_info_log_line(&ptr))) FIXME("    %s\n", line);
+        }
+        HeapFree(GetProcessHeap(), 0, infoLog);
+    }
+}
+
+/* Context activation is done by the caller. */
+static void shader_glsl_compile(const struct wined3d_gl_info *gl_info, GLhandleARB shader, const char *src)
+{
+    TRACE("Compiling shader object %u.\n", shader);
+    GL_EXTCALL(glShaderSourceARB(shader, 1, &src, NULL));
+    checkGLcall("glShaderSourceARB");
+    GL_EXTCALL(glCompileShaderARB(shader));
+    checkGLcall("glCompileShaderARB");
+    print_glsl_info_log(gl_info, shader);
+}
+
+/* Context activation is done by the caller. */
+static void shader_glsl_dump_program_source(const struct wined3d_gl_info *gl_info, GLhandleARB program)
+{
+    GLint i, object_count, source_size = -1;
+    GLhandleARB *objects;
+    char *source = NULL;
+
+    GL_EXTCALL(glGetObjectParameterivARB(program, GL_OBJECT_ATTACHED_OBJECTS_ARB, &object_count));
+    objects = HeapAlloc(GetProcessHeap(), 0, object_count * sizeof(*objects));
+    if (!objects)
+    {
+        ERR("Failed to allocate object array memory.\n");
+        return;
+    }
+
+    GL_EXTCALL(glGetAttachedObjectsARB(program, object_count, NULL, objects));
+    for (i = 0; i < object_count; ++i)
+    {
+        char *ptr, *line;
+        GLint tmp;
+
+        GL_EXTCALL(glGetObjectParameterivARB(objects[i], GL_OBJECT_SHADER_SOURCE_LENGTH_ARB, &tmp));
+
+        if (source_size < tmp)
+        {
+            HeapFree(GetProcessHeap(), 0, source);
+
+            source = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, tmp);
+            if (!source)
+            {
+                ERR("Failed to allocate %d bytes for shader source.\n", tmp);
+                HeapFree(GetProcessHeap(), 0, objects);
+                return;
+            }
+            source_size = tmp;
+        }
+
+        FIXME("Object %u:\n", objects[i]);
+        GL_EXTCALL(glGetObjectParameterivARB(objects[i], GL_OBJECT_SUBTYPE_ARB, &tmp));
+        FIXME("    GL_OBJECT_SUBTYPE_ARB: %s.\n", debug_gl_shader_type(tmp));
+        GL_EXTCALL(glGetObjectParameterivARB(objects[i], GL_OBJECT_COMPILE_STATUS_ARB, &tmp));
+        FIXME("    GL_OBJECT_COMPILE_STATUS_ARB: %d.\n", tmp);
+        FIXME("\n");
+
+        ptr = source;
+        GL_EXTCALL(glGetShaderSourceARB(objects[i], source_size, NULL, source));
+        while ((line = get_info_log_line(&ptr))) FIXME("    %s\n", line);
+        FIXME("\n");
+    }
+
+    HeapFree(GetProcessHeap(), 0, source);
+    HeapFree(GetProcessHeap(), 0, objects);
+}
+
+/* Context activation is done by the caller. */
+static void shader_glsl_validate_link(const struct wined3d_gl_info *gl_info, GLhandleARB program)
+{
+    GLint tmp;
+
+    if (!TRACE_ON(d3d_shader) && !FIXME_ON(d3d_shader)) return;
+
+    GL_EXTCALL(glGetObjectParameterivARB(program, GL_OBJECT_TYPE_ARB, &tmp));
+    if (tmp == GL_PROGRAM_OBJECT_ARB)
+    {
+        GL_EXTCALL(glGetObjectParameterivARB(program, GL_OBJECT_LINK_STATUS_ARB, &tmp));
+        if (!tmp)
+        {
+            FIXME("Program %u link status invalid.\n", program);
+            shader_glsl_dump_program_source(gl_info, program);
+        }
+    }
+
+    print_glsl_info_log(gl_info, program);
+}
+
+/* Context activation is done by the caller. */
+static void shader_glsl_load_psamplers(const struct wined3d_gl_info *gl_info,
+        const DWORD *tex_unit_map, GLhandleARB programId)
+{
+    GLint name_loc;
+    char sampler_name[20];
+    unsigned int i;
+
+    for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i)
+    {
+        snprintf(sampler_name, sizeof(sampler_name), "ps_sampler%u", i);
+        name_loc = GL_EXTCALL(glGetUniformLocationARB(programId, sampler_name));
+        if (name_loc != -1) {
+            DWORD mapped_unit = tex_unit_map[i];
+            if (mapped_unit != WINED3D_UNMAPPED_STAGE && mapped_unit < gl_info->limits.fragment_samplers)
+            {
+                TRACE("Loading %s for texture %d\n", sampler_name, mapped_unit);
+                GL_EXTCALL(glUniform1iARB(name_loc, mapped_unit));
+                checkGLcall("glUniform1iARB");
+            } else {
+                ERR("Trying to load sampler %s on unsupported unit %d\n", sampler_name, mapped_unit);
+            }
+        }
+    }
+}
+
+/* Context activation is done by the caller. */
+static void shader_glsl_load_vsamplers(const struct wined3d_gl_info *gl_info,
+        const DWORD *tex_unit_map, GLhandleARB programId)
+{
+    GLint name_loc;
+    char sampler_name[20];
+    unsigned int i;
+
+    for (i = 0; i < MAX_VERTEX_SAMPLERS; ++i)
+    {
+        snprintf(sampler_name, sizeof(sampler_name), "vs_sampler%u", i);
+        name_loc = GL_EXTCALL(glGetUniformLocationARB(programId, sampler_name));
+        if (name_loc != -1) {
+            DWORD mapped_unit = tex_unit_map[MAX_FRAGMENT_SAMPLERS + i];
+            if (mapped_unit != WINED3D_UNMAPPED_STAGE && mapped_unit < gl_info->limits.combined_samplers)
+            {
+                TRACE("Loading %s for texture %d\n", sampler_name, mapped_unit);
+                GL_EXTCALL(glUniform1iARB(name_loc, mapped_unit));
+                checkGLcall("glUniform1iARB");
+            } else {
+                ERR("Trying to load sampler %s on unsupported unit %d\n", sampler_name, mapped_unit);
+            }
+        }
+    }
+}
+
+/* Context activation is done by the caller. */
+static inline void walk_constant_heap(const struct wined3d_gl_info *gl_info, const float *constants,
+        const GLint *constant_locations, const struct constant_heap *heap, unsigned char *stack, DWORD version)
+{
+    int stack_idx = 0;
+    unsigned int heap_idx = 1;
+    unsigned int idx;
+
+    if (heap->entries[heap_idx].version <= version) return;
+
+    idx = heap->entries[heap_idx].idx;
+    if (constant_locations[idx] != -1) GL_EXTCALL(glUniform4fvARB(constant_locations[idx], 1, &constants[idx * 4]));
+    stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
+
+    while (stack_idx >= 0)
+    {
+        /* Note that we fall through to the next case statement. */
+        switch(stack[stack_idx])
+        {
+            case HEAP_NODE_TRAVERSE_LEFT:
+            {
+                unsigned int left_idx = heap_idx << 1;
+                if (left_idx < heap->size && heap->entries[left_idx].version > version)
+                {
+                    heap_idx = left_idx;
+                    idx = heap->entries[heap_idx].idx;
+                    if (constant_locations[idx] != -1)
+                        GL_EXTCALL(glUniform4fvARB(constant_locations[idx], 1, &constants[idx * 4]));
+
+                    stack[stack_idx++] = HEAP_NODE_TRAVERSE_RIGHT;
+                    stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
+                    break;
+                }
+            }
+
+            case HEAP_NODE_TRAVERSE_RIGHT:
+            {
+                unsigned int right_idx = (heap_idx << 1) + 1;
+                if (right_idx < heap->size && heap->entries[right_idx].version > version)
+                {
+                    heap_idx = right_idx;
+                    idx = heap->entries[heap_idx].idx;
+                    if (constant_locations[idx] != -1)
+                        GL_EXTCALL(glUniform4fvARB(constant_locations[idx], 1, &constants[idx * 4]));
+
+                    stack[stack_idx++] = HEAP_NODE_POP;
+                    stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
+                    break;
+                }
+            }
+
+            case HEAP_NODE_POP:
+                heap_idx >>= 1;
+                --stack_idx;
+                break;
+        }
+    }
+    checkGLcall("walk_constant_heap()");
+}
+
+/* Context activation is done by the caller. */
+static inline void apply_clamped_constant(const struct wined3d_gl_info *gl_info, GLint location, const GLfloat *data)
+{
+    GLfloat clamped_constant[4];
+
+    if (location == -1) return;
+
+    clamped_constant[0] = data[0] < -1.0f ? -1.0f : data[0] > 1.0f ? 1.0f : data[0];
+    clamped_constant[1] = data[1] < -1.0f ? -1.0f : data[1] > 1.0f ? 1.0f : data[1];
+    clamped_constant[2] = data[2] < -1.0f ? -1.0f : data[2] > 1.0f ? 1.0f : data[2];
+    clamped_constant[3] = data[3] < -1.0f ? -1.0f : data[3] > 1.0f ? 1.0f : data[3];
+
+    GL_EXTCALL(glUniform4fvARB(location, 1, clamped_constant));
+}
+
+/* Context activation is done by the caller. */
+static inline void walk_constant_heap_clamped(const struct wined3d_gl_info *gl_info, const float *constants,
+        const GLint *constant_locations, const struct constant_heap *heap, unsigned char *stack, DWORD version)
+{
+    int stack_idx = 0;
+    unsigned int heap_idx = 1;
+    unsigned int idx;
+
+    if (heap->entries[heap_idx].version <= version) return;
+
+    idx = heap->entries[heap_idx].idx;
+    apply_clamped_constant(gl_info, constant_locations[idx], &constants[idx * 4]);
+    stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
+
+    while (stack_idx >= 0)
+    {
+        /* Note that we fall through to the next case statement. */
+        switch(stack[stack_idx])
+        {
+            case HEAP_NODE_TRAVERSE_LEFT:
+            {
+                unsigned int left_idx = heap_idx << 1;
+                if (left_idx < heap->size && heap->entries[left_idx].version > version)
+                {
+                    heap_idx = left_idx;
+                    idx = heap->entries[heap_idx].idx;
+                    apply_clamped_constant(gl_info, constant_locations[idx], &constants[idx * 4]);
+
+                    stack[stack_idx++] = HEAP_NODE_TRAVERSE_RIGHT;
+                    stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
+                    break;
+                }
+            }
+
+            case HEAP_NODE_TRAVERSE_RIGHT:
+            {
+                unsigned int right_idx = (heap_idx << 1) + 1;
+                if (right_idx < heap->size && heap->entries[right_idx].version > version)
+                {
+                    heap_idx = right_idx;
+                    idx = heap->entries[heap_idx].idx;
+                    apply_clamped_constant(gl_info, constant_locations[idx], &constants[idx * 4]);
+
+                    stack[stack_idx++] = HEAP_NODE_POP;
+                    stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
+                    break;
+                }
+            }
+
+            case HEAP_NODE_POP:
+                heap_idx >>= 1;
+                --stack_idx;
+                break;
+        }
+    }
+    checkGLcall("walk_constant_heap_clamped()");
+}
+
+/* Context activation is done by the caller. */
+static void shader_glsl_load_constantsF(const struct wined3d_shader *shader, const struct wined3d_gl_info *gl_info,
+        const float *constants, const GLint *constant_locations, const struct constant_heap *heap,
+        unsigned char *stack, UINT version)
+{
+    const struct wined3d_shader_lconst *lconst;
+
+    /* 1.X pshaders have the constants clamped to [-1;1] implicitly. */
+    if (shader->reg_maps.shader_version.major == 1
+            && shader->reg_maps.shader_version.type == WINED3D_SHADER_TYPE_PIXEL)
+        walk_constant_heap_clamped(gl_info, constants, constant_locations, heap, stack, version);
+    else
+        walk_constant_heap(gl_info, constants, constant_locations, heap, stack, version);
+
+    if (!shader->load_local_constsF)
+    {
+        TRACE("No need to load local float constants for this shader\n");
+        return;
+    }
+
+    /* Immediate constants are clamped to [-1;1] at shader creation time if needed */
+    LIST_FOR_EACH_ENTRY(lconst, &shader->constantsF, struct wined3d_shader_lconst, entry)
+    {
+        GL_EXTCALL(glUniform4fvARB(constant_locations[lconst->idx], 1, (const GLfloat *)lconst->value));
+    }
+    checkGLcall("glUniform4fvARB()");
+}
+
+/* Context activation is done by the caller. */
+static void shader_glsl_load_constantsI(const struct wined3d_shader *shader, const struct wined3d_gl_info *gl_info,
+        const GLint locations[MAX_CONST_I], const int *constants, WORD constants_set)
+{
+    unsigned int i;
+    struct list* ptr;
+
+    for (i = 0; constants_set; constants_set >>= 1, ++i)
+    {
+        if (!(constants_set & 1)) continue;
+
+        TRACE_(d3d_constants)("Loading constants %u: %i, %i, %i, %i\n",
+                i, constants[i*4], constants[i*4+1], constants[i*4+2], constants[i*4+3]);
+
+        /* We found this uniform name in the program - go ahead and send the data */
+        GL_EXTCALL(glUniform4ivARB(locations[i], 1, &constants[i*4]));
+        checkGLcall("glUniform4ivARB");
+    }
+
+    /* Load immediate constants */
+    ptr = list_head(&shader->constantsI);
+    while (ptr)
+    {
+        const struct wined3d_shader_lconst *lconst = LIST_ENTRY(ptr, const struct wined3d_shader_lconst, entry);
+        unsigned int idx = lconst->idx;
+        const GLint *values = (const GLint *)lconst->value;
+
+        TRACE_(d3d_constants)("Loading local constants %i: %i, %i, %i, %i\n", idx,
+            values[0], values[1], values[2], values[3]);
+
+        /* We found this uniform name in the program - go ahead and send the data */
+        GL_EXTCALL(glUniform4ivARB(locations[idx], 1, values));
+        checkGLcall("glUniform4ivARB");
+        ptr = list_next(&shader->constantsI, ptr);
+    }
+}
+
+/* Context activation is done by the caller. */
+static void shader_glsl_load_constantsB(const struct wined3d_shader *shader, const struct wined3d_gl_info *gl_info,
+        GLhandleARB programId, const BOOL *constants, WORD constants_set)
+{
+    GLint tmp_loc;
+    unsigned int i;
+    char tmp_name[10];
+    const char *prefix;
+    struct list* ptr;
+
+    prefix = shader_glsl_get_prefix(shader->reg_maps.shader_version.type);
+
+    /* TODO: Benchmark and see if it would be beneficial to store the
+     * locations of the constants to avoid looking up each time */
+    for (i = 0; constants_set; constants_set >>= 1, ++i)
+    {
+        if (!(constants_set & 1)) continue;
+
+        TRACE_(d3d_constants)("Loading constants %i: %i;\n", i, constants[i]);
+
+        /* TODO: Benchmark and see if it would be beneficial to store the
+         * locations of the constants to avoid looking up each time */
+        snprintf(tmp_name, sizeof(tmp_name), "%s_b[%i]", prefix, i);
+        tmp_loc = GL_EXTCALL(glGetUniformLocationARB(programId, tmp_name));
+            GL_EXTCALL(glUniform1ivARB(tmp_loc, 1, &constants[i]));
+    }
+
+    /* Load immediate constants */
+    ptr = list_head(&shader->constantsB);
+    while (ptr)
+    {
+        const struct wined3d_shader_lconst *lconst = LIST_ENTRY(ptr, const struct wined3d_shader_lconst, entry);
+        unsigned int idx = lconst->idx;
+        const GLint *values = (const GLint *)lconst->value;
+
+        TRACE_(d3d_constants)("Loading local constants %i: %i\n", idx, values[0]);
+
+        snprintf(tmp_name, sizeof(tmp_name), "%s_b[%i]", prefix, idx);
+        tmp_loc = GL_EXTCALL(glGetUniformLocationARB(programId, tmp_name));
+            GL_EXTCALL(glUniform1ivARB(tmp_loc, 1, values));
+        ptr = list_next(&shader->constantsB, ptr);
+    }
+
+    checkGLcall("shader_glsl_load_constantsB()");
+}
+
+static void reset_program_constant_version(struct wine_rb_entry *entry, void *context)
+{
+    WINE_RB_ENTRY_VALUE(entry, struct glsl_shader_prog_link, program_lookup_entry)->constant_version = 0;
+}
+
+/* Context activation is done by the caller (state handler). */
+static void shader_glsl_load_np2fixup_constants(void *shader_priv,
+        const struct wined3d_gl_info *gl_info, const struct wined3d_state *state)
+{
+    struct shader_glsl_priv *glsl_priv = shader_priv;
+    const struct glsl_shader_prog_link *prog = glsl_priv->glsl_program;
+
+    /* No GLSL program set - nothing to do. */
+    if (!prog) return;
+
+    /* NP2 texcoord fixup is (currently) only done for pixelshaders. */
+    if (!use_ps(state)) return;
+
+    if (prog->ps.np2_fixup_info && prog->ps.np2_fixup_location != -1)
+    {
+        UINT i;
+        UINT fixup = prog->ps.np2_fixup_info->active;
+        GLfloat np2fixup_constants[4 * MAX_FRAGMENT_SAMPLERS];
+
+        for (i = 0; fixup; fixup >>= 1, ++i)
+        {
+            const struct wined3d_texture *tex = state->textures[i];
+            const unsigned char idx = prog->ps.np2_fixup_info->idx[i];
+            GLfloat *tex_dim = &np2fixup_constants[(idx >> 1) * 4];
+
+            if (!tex)
+            {
+                ERR("Nonexistent texture is flagged for NP2 texcoord fixup.\n");
+                continue;
+            }
+
+            if (idx % 2)
+            {
+                tex_dim[2] = tex->pow2_matrix[0];
+                tex_dim[3] = tex->pow2_matrix[5];
+            }
+            else
+            {
+                tex_dim[0] = tex->pow2_matrix[0];
+                tex_dim[1] = tex->pow2_matrix[5];
+            }
+        }
+
+        GL_EXTCALL(glUniform4fvARB(prog->ps.np2_fixup_location,
+                prog->ps.np2_fixup_info->num_consts, np2fixup_constants));
+    }
+}
+
+/* Context activation is done by the caller (state handler). */
+static void shader_glsl_load_constants(void *shader_priv, const struct wined3d_context *context,
+        const struct wined3d_state *state)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    struct shader_glsl_priv *priv = shader_priv;
+    float position_fixup[4];
+
+    GLhandleARB programId;
+    struct glsl_shader_prog_link *prog = priv->glsl_program;
+    UINT constant_version;
+    int i;
+
+    if (!prog) {
+        /* No GLSL program set - nothing to do. */
+        return;
+    }
+    programId = prog->programId;
+    constant_version = prog->constant_version;
+
+    if (use_vs(state))
+    {
+        const struct wined3d_shader *vshader = state->vertex_shader;
+
+        /* Load DirectX 9 float constants/uniforms for vertex shader */
+        shader_glsl_load_constantsF(vshader, gl_info, state->vs_consts_f,
+                prog->vs.uniform_f_locations, &priv->vconst_heap, priv->stack, constant_version);
+
+        /* Load DirectX 9 integer constants/uniforms for vertex shader */
+        shader_glsl_load_constantsI(vshader, gl_info, prog->vs.uniform_i_locations, state->vs_consts_i,
+                vshader->reg_maps.integer_constants);
+
+        /* Load DirectX 9 boolean constants/uniforms for vertex shader */
+        shader_glsl_load_constantsB(vshader, gl_info, programId, state->vs_consts_b,
+                vshader->reg_maps.boolean_constants);
+
+        /* Upload the position fixup params */
+        shader_get_position_fixup(context, state, position_fixup);
+        GL_EXTCALL(glUniform4fvARB(prog->vs.pos_fixup_location, 1, position_fixup));
+        checkGLcall("glUniform4fvARB");
+    }
+
+    if (use_ps(state))
+    {
+        const struct wined3d_shader *pshader = state->pixel_shader;
+
+        /* Load DirectX 9 float constants/uniforms for pixel shader */
+        shader_glsl_load_constantsF(pshader, gl_info, state->ps_consts_f,
+                prog->ps.uniform_f_locations, &priv->pconst_heap, priv->stack, constant_version);
+
+        /* Load DirectX 9 integer constants/uniforms for pixel shader */
+        shader_glsl_load_constantsI(pshader, gl_info, prog->ps.uniform_i_locations, state->ps_consts_i,
+                pshader->reg_maps.integer_constants);
+
+        /* Load DirectX 9 boolean constants/uniforms for pixel shader */
+        shader_glsl_load_constantsB(pshader, gl_info, programId, state->ps_consts_b,
+                pshader->reg_maps.boolean_constants);
+
+        /* Upload the environment bump map matrix if needed. The needsbumpmat
+         * member specifies the texture stage to load the matrix from. It
+         * can't be 0 for a valid texbem instruction. */
+        for (i = 0; i < MAX_TEXTURES; ++i)
+        {
+            const float *data;
+
+            if (prog->ps.bumpenv_mat_location[i] == -1)
+                continue;
+
+            data = (const float *)&state->texture_states[i][WINED3D_TSS_BUMPENV_MAT00];
+            GL_EXTCALL(glUniformMatrix2fvARB(prog->ps.bumpenv_mat_location[i], 1, 0, data));
+            checkGLcall("glUniformMatrix2fvARB");
+
+            /* texbeml needs the luminance scale and offset too. If texbeml
+             * is used, needsbumpmat is set too, so we can check that in the
+             * needsbumpmat check. */
+            if (prog->ps.bumpenv_lum_scale_location[i] != -1)
+            {
+                const GLfloat *scale = (const GLfloat *)&state->texture_states[i][WINED3D_TSS_BUMPENV_LSCALE];
+                const GLfloat *offset = (const GLfloat *)&state->texture_states[i][WINED3D_TSS_BUMPENV_LOFFSET];
+
+                GL_EXTCALL(glUniform1fvARB(prog->ps.bumpenv_lum_scale_location[i], 1, scale));
+                checkGLcall("glUniform1fvARB");
+                GL_EXTCALL(glUniform1fvARB(prog->ps.bumpenv_lum_offset_location[i], 1, offset));
+                checkGLcall("glUniform1fvARB");
+            }
+        }
+
+        if (prog->ps.ycorrection_location != -1)
+        {
+            float correction_params[4];
+
+            if (context->render_offscreen)
+            {
+                correction_params[0] = 0.0f;
+                correction_params[1] = 1.0f;
+            } else {
+                /* position is window relative, not viewport relative */
+                correction_params[0] = (float) context->current_rt->resource.height;
+                correction_params[1] = -1.0f;
+            }
+            GL_EXTCALL(glUniform4fvARB(prog->ps.ycorrection_location, 1, correction_params));
+        }
+    }
+    else if (priv->fragment_pipe == &glsl_fragment_pipe)
+    {
+        float col[4];
+
+        for (i = 0; i < MAX_TEXTURES; ++i)
+        {
+            GL_EXTCALL(glUniformMatrix2fvARB(prog->ps.bumpenv_mat_location[i], 1, 0,
+                        (const float *)&state->texture_states[i][WINED3D_TSS_BUMPENV_MAT00]));
+            GL_EXTCALL(glUniform1fARB(prog->ps.bumpenv_lum_scale_location[i],
+                        *(const float *)&state->texture_states[i][WINED3D_TSS_BUMPENV_LSCALE]));
+            GL_EXTCALL(glUniform1fARB(prog->ps.bumpenv_lum_offset_location[i],
+                        *(const float *)&state->texture_states[i][WINED3D_TSS_BUMPENV_LOFFSET]));
+        }
+
+        D3DCOLORTOGLFLOAT4(state->render_states[WINED3D_RS_TEXTUREFACTOR], col);
+        GL_EXTCALL(glUniform4fARB(prog->ps.tex_factor_location, col[0], col[1], col[2], col[3]));
+
+        if (state->render_states[WINED3D_RS_SPECULARENABLE])
+            GL_EXTCALL(glUniform4fARB(prog->ps.specular_enable_location, 1.0f, 1.0f, 1.0f, 0.0f));
+        else
+            GL_EXTCALL(glUniform4fARB(prog->ps.specular_enable_location, 0.0f, 0.0f, 0.0f, 0.0f));
+
+        checkGLcall("fixed function uniforms");
+    }
+
+    if (priv->next_constant_version == UINT_MAX)
+    {
+        TRACE("Max constant version reached, resetting to 0.\n");
+        wine_rb_for_each_entry(&priv->program_lookup, reset_program_constant_version, NULL);
+        priv->next_constant_version = 1;
+    }
+    else
+    {
+        prog->constant_version = priv->next_constant_version++;
+    }
+}
+
+static void update_heap_entry(const struct constant_heap *heap, unsigned int idx,
+        unsigned int heap_idx, DWORD new_version)
+{
+    struct constant_entry *entries = heap->entries;
+    unsigned int *positions = heap->positions;
+    unsigned int parent_idx;
+
+    while (heap_idx > 1)
+    {
+        parent_idx = heap_idx >> 1;
+
+        if (new_version <= entries[parent_idx].version) break;
+
+        entries[heap_idx] = entries[parent_idx];
+        positions[entries[parent_idx].idx] = heap_idx;
+        heap_idx = parent_idx;
+    }
+
+    entries[heap_idx].version = new_version;
+    entries[heap_idx].idx = idx;
+    positions[idx] = heap_idx;
+}
+
+static void shader_glsl_update_float_vertex_constants(struct wined3d_device *device, UINT start, UINT count)
+{
+    struct shader_glsl_priv *priv = device->shader_priv;
+    struct constant_heap *heap = &priv->vconst_heap;
+    UINT i;
+
+    for (i = start; i < count + start; ++i)
+    {
+        if (!device->stateBlock->changed.vertexShaderConstantsF[i])
+            update_heap_entry(heap, i, heap->size++, priv->next_constant_version);
+        else
+            update_heap_entry(heap, i, heap->positions[i], priv->next_constant_version);
+    }
+}
+
+static void shader_glsl_update_float_pixel_constants(struct wined3d_device *device, UINT start, UINT count)
+{
+    struct shader_glsl_priv *priv = device->shader_priv;
+    struct constant_heap *heap = &priv->pconst_heap;
+    UINT i;
+
+    for (i = start; i < count + start; ++i)
+    {
+        if (!device->stateBlock->changed.pixelShaderConstantsF[i])
+            update_heap_entry(heap, i, heap->size++, priv->next_constant_version);
+        else
+            update_heap_entry(heap, i, heap->positions[i], priv->next_constant_version);
+    }
+}
+
+static unsigned int vec4_varyings(DWORD shader_major, const struct wined3d_gl_info *gl_info)
+{
+    unsigned int ret = gl_info->limits.glsl_varyings / 4;
+    /* 4.0 shaders do not write clip coords because d3d10 does not support user clipplanes */
+    if(shader_major > 3) return ret;
+
+    /* 3.0 shaders may need an extra varying for the clip coord on some cards(mostly dx10 ones) */
+    if (gl_info->quirks & WINED3D_QUIRK_GLSL_CLIP_VARYING) ret -= 1;
+    return ret;
+}
+
+/** Generate the variable & register declarations for the GLSL output target */
+static void shader_generate_glsl_declarations(const struct wined3d_context *context,
+        struct wined3d_shader_buffer *buffer, const struct wined3d_shader *shader,
+        const struct wined3d_shader_reg_maps *reg_maps, const struct shader_glsl_ctx_priv *ctx_priv)
+{
+    const struct wined3d_shader_version *version = &reg_maps->shader_version;
+    const struct wined3d_state *state = &shader->device->stateBlock->state;
+    const struct ps_compile_args *ps_args = ctx_priv->cur_ps_args;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    const struct wined3d_fb_state *fb = &shader->device->fb;
+    unsigned int i, extra_constants_needed = 0;
+    const struct wined3d_shader_lconst *lconst;
+    const char *prefix;
+    DWORD map;
+
+    prefix = shader_glsl_get_prefix(version->type);
+
+    /* Prototype the subroutines */
+    for (i = 0, map = reg_maps->labels; map; map >>= 1, ++i)
+    {
+        if (map & 1) shader_addline(buffer, "void subroutine%u();\n", i);
+    }
+
+    /* Declare the constants (aka uniforms) */
+    if (shader->limits.constant_float > 0)
+    {
+        unsigned max_constantsF;
+
+        /* Unless the shader uses indirect addressing, always declare the
+         * maximum array size and ignore that we need some uniforms privately.
+         * E.g. if GL supports 256 uniforms, and we need 2 for the pos fixup
+         * and immediate values, still declare VC[256]. If the shader needs
+         * more uniforms than we have it won't work in any case. If it uses
+         * less, the compiler will figure out which uniforms are really used
+         * and strip them out. This allows a shader to use c255 on a dx9 card,
+         * as long as it doesn't also use all the other constants.
+         *
+         * If the shader uses indirect addressing the compiler must assume
+         * that all declared uniforms are used. In this case, declare only the
+         * amount that we're assured to have.
+         *
+         * Thus we run into problems in these two cases:
+         * 1) The shader really uses more uniforms than supported.
+         * 2) The shader uses indirect addressing, less constants than
+         *    supported, but uses a constant index > #supported consts. */
+        if (version->type == WINED3D_SHADER_TYPE_PIXEL)
+        {
+            /* No indirect addressing here. */
+            max_constantsF = gl_info->limits.glsl_ps_float_constants;
+        }
+        else
+        {
+            if (reg_maps->usesrelconstF)
+            {
+                /* Subtract the other potential uniforms from the max
+                 * available (bools, ints, and 1 row of projection matrix).
+                 * Subtract another uniform for immediate values, which have
+                 * to be loaded via uniform by the driver as well. The shader
+                 * code only uses 0.5, 2.0, 1.0, 128 and -128 in vertex
+                 * shader code, so one vec4 should be enough. (Unfortunately
+                 * the Nvidia driver doesn't store 128 and -128 in one float).
+                 *
+                 * Writing gl_ClipVertex requires one uniform for each
+                 * clipplane as well. */
+                max_constantsF = gl_info->limits.glsl_vs_float_constants - 3;
+                if(ctx_priv->cur_vs_args->clip_enabled)
+                {
+                    max_constantsF -= gl_info->limits.clipplanes;
+                }
+                max_constantsF -= count_bits(reg_maps->integer_constants);
+                /* Strictly speaking a bool only uses one scalar, but the nvidia(Linux) compiler doesn't pack them properly,
+                 * so each scalar requires a full vec4. We could work around this by packing the booleans ourselves, but
+                 * for now take this into account when calculating the number of available constants
+                 */
+                max_constantsF -= count_bits(reg_maps->boolean_constants);
+                /* Set by driver quirks in directx.c */
+                max_constantsF -= gl_info->reserved_glsl_constants;
+
+                if (max_constantsF < shader->limits.constant_float)
+                {
+                    static unsigned int once;
+
+                    if (!once++)
+                        ERR_(winediag)("The hardware does not support enough uniform components to run this shader,"
+                                " it may not render correctly.\n");
+                    else
+                        WARN("The hardware does not support enough uniform components to run this shader.\n");
+                }
+            }
+            else
+            {
+                max_constantsF = gl_info->limits.glsl_vs_float_constants;
+            }
+        }
+        max_constantsF = min(shader->limits.constant_float, max_constantsF);
+        shader_addline(buffer, "uniform vec4 %s_c[%u];\n", prefix, max_constantsF);
+    }
+
+    /* Always declare the full set of constants, the compiler can remove the
+     * unused ones because d3d doesn't (yet) support indirect int and bool
+     * constant addressing. This avoids problems if the app uses e.g. i0 and i9. */
+    if (shader->limits.constant_int > 0 && reg_maps->integer_constants)
+        shader_addline(buffer, "uniform ivec4 %s_i[%u];\n", prefix, shader->limits.constant_int);
+
+    if (shader->limits.constant_bool > 0 && reg_maps->boolean_constants)
+        shader_addline(buffer, "uniform bool %s_b[%u];\n", prefix, shader->limits.constant_bool);
+
+    for (i = 0; i < WINED3D_MAX_CBS; ++i)
+    {
+        if (reg_maps->cb_sizes[i])
+            shader_addline(buffer, "uniform vec4 %s_cb%u[%u];\n", prefix, i, reg_maps->cb_sizes[i]);
+    }
+
+    /* Declare texture samplers */
+    for (i = 0; i < shader->limits.sampler; ++i)
+    {
+        if (reg_maps->sampler_type[i])
+        {
+            BOOL shadow_sampler = version->type == WINED3D_SHADER_TYPE_PIXEL && (ps_args->shadow & (1 << i));
+            BOOL tex_rect;
+
+            switch (reg_maps->sampler_type[i])
+            {
+                case WINED3DSTT_1D:
+                    if (shadow_sampler)
+                        shader_addline(buffer, "uniform sampler1DShadow %s_sampler%u;\n", prefix, i);
+                    else
+                        shader_addline(buffer, "uniform sampler1D %s_sampler%u;\n", prefix, i);
+                    break;
+                case WINED3DSTT_2D:
+                    tex_rect = version->type == WINED3D_SHADER_TYPE_PIXEL && (ps_args->np2_fixup & (1 << i));
+                    tex_rect = tex_rect && gl_info->supported[ARB_TEXTURE_RECTANGLE];
+                    if (shadow_sampler)
+                    {
+                        if (tex_rect)
+                            shader_addline(buffer, "uniform sampler2DRectShadow %s_sampler%u;\n", prefix, i);
+                        else
+                            shader_addline(buffer, "uniform sampler2DShadow %s_sampler%u;\n", prefix, i);
+                    }
+                    else
+                    {
+                        if (tex_rect)
+                            shader_addline(buffer, "uniform sampler2DRect %s_sampler%u;\n", prefix, i);
+                        else
+                            shader_addline(buffer, "uniform sampler2D %s_sampler%u;\n", prefix, i);
+                    }
+                    break;
+                case WINED3DSTT_CUBE:
+                    if (shadow_sampler)
+                        FIXME("Unsupported Cube shadow sampler.\n");
+                    shader_addline(buffer, "uniform samplerCube %s_sampler%u;\n", prefix, i);
+                    break;
+                case WINED3DSTT_VOLUME:
+                    if (shadow_sampler)
+                        FIXME("Unsupported 3D shadow sampler.\n");
+                    shader_addline(buffer, "uniform sampler3D %s_sampler%u;\n", prefix, i);
+                    break;
+                default:
+                    shader_addline(buffer, "uniform unsupported_sampler %s_sampler%u;\n", prefix, i);
+                    FIXME("Unrecognized sampler type: %#x\n", reg_maps->sampler_type[i]);
+                    break;
+            }
+        }
+    }
+
+    /* Declare uniforms for NP2 texcoord fixup:
+     * This is NOT done inside the loop that declares the texture samplers
+     * since the NP2 fixup code is currently only used for the GeforceFX
+     * series and when forcing the ARB_npot extension off. Modern cards just
+     * skip the code anyway, so put it inside a separate loop. */
+    if (version->type == WINED3D_SHADER_TYPE_PIXEL && ps_args->np2_fixup)
+    {
+        struct ps_np2fixup_info *fixup = ctx_priv->cur_np2fixup_info;
+        UINT cur = 0;
+
+        /* NP2/RECT textures in OpenGL use texcoords in the range [0,width]x[0,height]
+         * while D3D has them in the (normalized) [0,1]x[0,1] range.
+         * samplerNP2Fixup stores texture dimensions and is updated through
+         * shader_glsl_load_np2fixup_constants when the sampler changes. */
+
+        for (i = 0; i < shader->limits.sampler; ++i)
+        {
+            if (reg_maps->sampler_type[i])
+            {
+                if (!(ps_args->np2_fixup & (1 << i))) continue;
+
+                if (WINED3DSTT_2D != reg_maps->sampler_type[i]) {
+                    FIXME("Non-2D texture is flagged for NP2 texcoord fixup.\n");
+                    continue;
+                }
+
+                fixup->idx[i] = cur++;
+            }
+        }
+
+        fixup->num_consts = (cur + 1) >> 1;
+        fixup->active = ps_args->np2_fixup;
+        shader_addline(buffer, "uniform vec4 %s_samplerNP2Fixup[%u];\n", prefix, fixup->num_consts);
+    }
+
+    /* Declare address variables */
+    for (i = 0, map = reg_maps->address; map; map >>= 1, ++i)
+    {
+        if (map & 1) shader_addline(buffer, "ivec4 A%u;\n", i);
+    }
+
+    /* Declare texture coordinate temporaries and initialize them */
+    for (i = 0, map = reg_maps->texcoord; map; map >>= 1, ++i)
+    {
+        if (map & 1) shader_addline(buffer, "vec4 T%u = gl_TexCoord[%u];\n", i, i);
+    }
+
+    if (version->type == WINED3D_SHADER_TYPE_VERTEX)
+    {
+        /* Declare attributes. */
+        for (i = 0, map = reg_maps->input_registers; map; map >>= 1, ++i)
+        {
+            if (map & 1)
+                shader_addline(buffer, "attribute vec4 %s_in%u;\n", prefix, i);
+        }
+
+        shader_addline(buffer, "uniform vec4 posFixup;\n");
+        shader_addline(buffer, "void order_ps_input(in vec4[%u]);\n", shader->limits.packed_output);
+    }
+    else if (version->type == WINED3D_SHADER_TYPE_GEOMETRY)
+    {
+        shader_addline(buffer, "varying in vec4 gs_in[][%u];\n", shader->limits.packed_input);
+    }
+    else if (version->type == WINED3D_SHADER_TYPE_PIXEL)
+    {
+        if (version->major >= 3)
+        {
+            UINT in_count = min(vec4_varyings(version->major, gl_info), shader->limits.packed_input);
+
+            if (use_vs(state))
+                shader_addline(buffer, "varying vec4 %s_in[%u];\n", prefix, in_count);
+            else
+                /* TODO: Write a replacement shader for the fixed function
+                 * vertex pipeline, so this isn't needed. For fixed function
+                 * vertex processing + 3.0 pixel shader we need a separate
+                 * function in the pixel shader that reads the fixed function
+                 * color into the packed input registers. */
+                shader_addline(buffer, "vec4 %s_in[%u];\n", prefix, in_count);
+        }
+
+        for (i = 0, map = reg_maps->bumpmat; map; map >>= 1, ++i)
+        {
+            if (!(map & 1))
+                continue;
+
+            shader_addline(buffer, "uniform mat2 bumpenv_mat%u;\n", i);
+
+            if (reg_maps->luminanceparams & (1 << i))
+            {
+                shader_addline(buffer, "uniform float bumpenv_lum_scale%u;\n", i);
+                shader_addline(buffer, "uniform float bumpenv_lum_offset%u;\n", i);
+                extra_constants_needed++;
+            }
+
+            extra_constants_needed++;
+        }
+
+        if (ps_args->srgb_correction)
+        {
+            shader_addline(buffer, "const vec4 srgb_const0 = vec4(%.8e, %.8e, %.8e, %.8e);\n",
+                    srgb_pow, srgb_mul_high, srgb_sub_high, srgb_mul_low);
+            shader_addline(buffer, "const vec4 srgb_const1 = vec4(%.8e, 0.0, 0.0, 0.0);\n",
+                    srgb_cmp);
+        }
+        if (reg_maps->vpos || reg_maps->usesdsy)
+        {
+            if (shader->limits.constant_float + extra_constants_needed
+                    + 1 < gl_info->limits.glsl_ps_float_constants)
+            {
+                shader_addline(buffer, "uniform vec4 ycorrection;\n");
+                extra_constants_needed++;
+            }
+            else
+            {
+                /* This happens because we do not have proper tracking of the constant registers that are
+                 * actually used, only the max limit of the shader version
+                 */
+                FIXME("Cannot find a free uniform for vpos correction params\n");
+                shader_addline(buffer, "const vec4 ycorrection = vec4(%f, %f, 0.0, 0.0);\n",
+                        context->render_offscreen ? 0.0f : fb->render_targets[0]->resource.height,
+                        context->render_offscreen ? 1.0f : -1.0f);
+            }
+            shader_addline(buffer, "vec4 vpos;\n");
+        }
+    }
+
+    /* Declare output register temporaries */
+    if (shader->limits.packed_output)
+        shader_addline(buffer, "vec4 %s_out[%u];\n", prefix, shader->limits.packed_output);
+
+    /* Declare temporary variables */
+    for (i = 0, map = reg_maps->temporary; map; map >>= 1, ++i)
+    {
+        if (map & 1) shader_addline(buffer, "vec4 R%u;\n", i);
+    }
+
+    /* Declare loop registers aLx */
+    if (version->major < 4)
+    {
+        for (i = 0; i < reg_maps->loop_depth; ++i)
+        {
+            shader_addline(buffer, "int aL%u;\n", i);
+            shader_addline(buffer, "int tmpInt%u;\n", i);
+        }
+    }
+
+    /* Temporary variables for matrix operations */
+    shader_addline(buffer, "vec4 tmp0;\n");
+    shader_addline(buffer, "vec4 tmp1;\n");
+
+    if (!shader->load_local_constsF)
+    {
+        LIST_FOR_EACH_ENTRY(lconst, &shader->constantsF, struct wined3d_shader_lconst, entry)
+        {
+            const float *value;
+            value = (const float *)lconst->value;
+            shader_addline(buffer, "const vec4 %s_lc%u = vec4(%.8e, %.8e, %.8e, %.8e);\n",
+                    prefix, lconst->idx, value[0], value[1], value[2], value[3]);
+        }
+    }
+
+    /* Start the main program. */
+    shader_addline(buffer, "void main()\n{\n");
+
+    /* Direct3D applications expect integer vPos values, while OpenGL drivers
+     * add approximately 0.5. This causes off-by-one problems as spotted by
+     * the vPos d3d9 visual test. Unfortunately ATI cards do not add exactly
+     * 0.5, but rather something like 0.49999999 or 0.50000001, which still
+     * causes precision troubles when we just subtract 0.5.
+     *
+     * To deal with that, just floor() the position. This will eliminate the
+     * fraction on all cards.
+     *
+     * TODO: Test how this behaves with multisampling.
+     *
+     * An advantage of floor is that it works even if the driver doesn't add
+     * 0.5. It is somewhat questionable if 1.5, 2.5, ... are the proper values
+     * to return in gl_FragCoord, even though coordinates specify the pixel
+     * centers instead of the pixel corners. This code will behave correctly
+     * on drivers that returns integer values. */
+    if (version->type == WINED3D_SHADER_TYPE_PIXEL && reg_maps->vpos)
+        shader_addline(buffer,
+                "vpos = floor(vec4(0, ycorrection[0], 0, 0) + gl_FragCoord * vec4(1, ycorrection[1], 1, 1));\n");
+}
+
+/*****************************************************************************
+ * Functions to generate GLSL strings from DirectX Shader bytecode begin here.
+ *
+ * For more information, see http://wiki.winehq.org/DirectX-Shaders
+ ****************************************************************************/
+
+/* Prototypes */
+static void shader_glsl_add_src_param(const struct wined3d_shader_instruction *ins,
+        const struct wined3d_shader_src_param *wined3d_src, DWORD mask, struct glsl_src_param *glsl_src);
+
+/** Used for opcode modifiers - They multiply the result by the specified amount */
+static const char * const shift_glsl_tab[] = {
+    "",           /*  0 (none) */
+    "2.0 * ",     /*  1 (x2)   */
+    "4.0 * ",     /*  2 (x4)   */
+    "8.0 * ",     /*  3 (x8)   */
+    "16.0 * ",    /*  4 (x16)  */
+    "32.0 * ",    /*  5 (x32)  */
+    "",           /*  6 (x64)  */
+    "",           /*  7 (x128) */
+    "",           /*  8 (d256) */
+    "",           /*  9 (d128) */
+    "",           /* 10 (d64)  */
+    "",           /* 11 (d32)  */
+    "0.0625 * ",  /* 12 (d16)  */
+    "0.125 * ",   /* 13 (d8)   */
+    "0.25 * ",    /* 14 (d4)   */
+    "0.5 * "      /* 15 (d2)   */
+};
+
+/* Generate a GLSL parameter that does the input modifier computation and return the input register/mask to use */
+static void shader_glsl_gen_modifier(enum wined3d_shader_src_modifier src_modifier,
+        const char *in_reg, const char *in_regswizzle, char *out_str)
+{
+    out_str[0] = 0;
+
+    switch (src_modifier)
+    {
+    case WINED3DSPSM_DZ: /* Need to handle this in the instructions itself (texld & texcrd). */
+    case WINED3DSPSM_DW:
+    case WINED3DSPSM_NONE:
+        sprintf(out_str, "%s%s", in_reg, in_regswizzle);
+        break;
+    case WINED3DSPSM_NEG:
+        sprintf(out_str, "-%s%s", in_reg, in_regswizzle);
+        break;
+    case WINED3DSPSM_NOT:
+        sprintf(out_str, "!%s%s", in_reg, in_regswizzle);
+        break;
+    case WINED3DSPSM_BIAS:
+        sprintf(out_str, "(%s%s - vec4(0.5)%s)", in_reg, in_regswizzle, in_regswizzle);
+        break;
+    case WINED3DSPSM_BIASNEG:
+        sprintf(out_str, "-(%s%s - vec4(0.5)%s)", in_reg, in_regswizzle, in_regswizzle);
+        break;
+    case WINED3DSPSM_SIGN:
+        sprintf(out_str, "(2.0 * (%s%s - 0.5))", in_reg, in_regswizzle);
+        break;
+    case WINED3DSPSM_SIGNNEG:
+        sprintf(out_str, "-(2.0 * (%s%s - 0.5))", in_reg, in_regswizzle);
+        break;
+    case WINED3DSPSM_COMP:
+        sprintf(out_str, "(1.0 - %s%s)", in_reg, in_regswizzle);
+        break;
+    case WINED3DSPSM_X2:
+        sprintf(out_str, "(2.0 * %s%s)", in_reg, in_regswizzle);
+        break;
+    case WINED3DSPSM_X2NEG:
+        sprintf(out_str, "-(2.0 * %s%s)", in_reg, in_regswizzle);
+        break;
+    case WINED3DSPSM_ABS:
+        sprintf(out_str, "abs(%s%s)", in_reg, in_regswizzle);
+        break;
+    case WINED3DSPSM_ABSNEG:
+        sprintf(out_str, "-abs(%s%s)", in_reg, in_regswizzle);
+        break;
+    default:
+        FIXME("Unhandled modifier %u\n", src_modifier);
+        sprintf(out_str, "%s%s", in_reg, in_regswizzle);
+    }
+}
+
+/** Writes the GLSL variable name that corresponds to the register that the
+ * DX opcode parameter is trying to access */
+static void shader_glsl_get_register_name(const struct wined3d_shader_register *reg,
+        char *register_name, BOOL *is_color, const struct wined3d_shader_instruction *ins)
+{
+    /* oPos, oFog and oPts in D3D */
+    static const char * const hwrastout_reg_names[] = {"vs_out[10]", "vs_out[11].x", "vs_out[11].y"};
+
+    const struct wined3d_shader *shader = ins->ctx->shader;
+    const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps;
+    const struct wined3d_shader_version *version = &reg_maps->shader_version;
+    const struct wined3d_gl_info *gl_info = ins->ctx->gl_info;
+    const char *prefix = shader_glsl_get_prefix(version->type);
+    struct glsl_src_param rel_param0, rel_param1;
+
+    if (reg->idx[0].offset != ~0U && reg->idx[0].rel_addr)
+        shader_glsl_add_src_param(ins, reg->idx[0].rel_addr, WINED3DSP_WRITEMASK_0, &rel_param0);
+    if (reg->idx[1].offset != ~0U && reg->idx[1].rel_addr)
+        shader_glsl_add_src_param(ins, reg->idx[1].rel_addr, WINED3DSP_WRITEMASK_0, &rel_param1);
+    *is_color = FALSE;
+
+    switch (reg->type)
+    {
+        case WINED3DSPR_TEMP:
+            sprintf(register_name, "R%u", reg->idx[0].offset);
+            break;
+
+        case WINED3DSPR_INPUT:
+            /* vertex shaders */
+            if (version->type == WINED3D_SHADER_TYPE_VERTEX)
+            {
+                struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data;
+                if (priv->cur_vs_args->swizzle_map & (1 << reg->idx[0].offset))
+                    *is_color = TRUE;
+                sprintf(register_name, "%s_in%u", prefix, reg->idx[0].offset);
+                break;
+            }
+
+            if (version->type == WINED3D_SHADER_TYPE_GEOMETRY)
+            {
+                if (reg->idx[0].rel_addr)
+                {
+                    if (reg->idx[1].rel_addr)
+                        sprintf(register_name, "gs_in[%s + %u][%s + %u]",
+                                rel_param0.param_str, reg->idx[0].offset, rel_param1.param_str, reg->idx[1].offset);
+                    else
+                        sprintf(register_name, "gs_in[%s + %u][%u]",
+                                rel_param0.param_str, reg->idx[0].offset, reg->idx[1].offset);
+                }
+                else if (reg->idx[1].rel_addr)
+                    sprintf(register_name, "gs_in[%u][%s + %u]",
+                            reg->idx[0].offset, rel_param1.param_str, reg->idx[1].offset);
+                else
+                    sprintf(register_name, "gs_in[%u][%u]", reg->idx[0].offset, reg->idx[1].offset);
+                break;
+            }
+
+            /* pixel shaders >= 3.0 */
+            if (version->major >= 3)
+            {
+                DWORD idx = shader->u.ps.input_reg_map[reg->idx[0].offset];
+                unsigned int in_count = vec4_varyings(version->major, gl_info);
+
+                if (reg->idx[0].rel_addr)
+                {
+                    /* Removing a + 0 would be an obvious optimization, but
+                     * OS X doesn't see the NOP operation there. */
+                    if (idx)
+                    {
+                        if (shader->u.ps.declared_in_count > in_count)
+                        {
+                            sprintf(register_name,
+                                    "((%s + %u) > %u ? (%s + %u) > %u ? gl_SecondaryColor : gl_Color : %s_in[%s + %u])",
+                                    rel_param0.param_str, idx, in_count - 1, rel_param0.param_str, idx, in_count,
+                                    prefix, rel_param0.param_str, idx);
+                        }
+                        else
+                        {
+                            sprintf(register_name, "%s_in[%s + %u]", prefix, rel_param0.param_str, idx);
+                        }
+                    }
+                    else
+                    {
+                        if (shader->u.ps.declared_in_count > in_count)
+                        {
+                            sprintf(register_name, "((%s) > %u ? (%s) > %u ? gl_SecondaryColor : gl_Color : %s_in[%s])",
+                                    rel_param0.param_str, in_count - 1, rel_param0.param_str, in_count,
+                                    prefix, rel_param0.param_str);
+                        }
+                        else
+                        {
+                            sprintf(register_name, "%s_in[%s]", prefix, rel_param0.param_str);
+                        }
+                    }
+                }
+                else
+                {
+                    if (idx == in_count) sprintf(register_name, "gl_Color");
+                    else if (idx == in_count + 1) sprintf(register_name, "gl_SecondaryColor");
+                    else sprintf(register_name, "%s_in[%u]", prefix, idx);
+                }
+            }
+            else
+            {
+                if (!reg->idx[0].offset)
+                    strcpy(register_name, "gl_Color");
+                else
+                    strcpy(register_name, "gl_SecondaryColor");
+                break;
+            }
+            break;
+
+        case WINED3DSPR_CONST:
+            {
+                /* Relative addressing */
+                if (reg->idx[0].rel_addr)
+                {
+                    if (reg->idx[0].offset)
+                        sprintf(register_name, "%s_c[%s + %u]", prefix, rel_param0.param_str, reg->idx[0].offset);
+                    else
+                        sprintf(register_name, "%s_c[%s]", prefix, rel_param0.param_str);
+                }
+                else
+                {
+                    if (shader_constant_is_local(shader, reg->idx[0].offset))
+                        sprintf(register_name, "%s_lc%u", prefix, reg->idx[0].offset);
+                    else
+                        sprintf(register_name, "%s_c[%u]", prefix, reg->idx[0].offset);
+                }
+            }
+            break;
+
+        case WINED3DSPR_CONSTINT:
+            sprintf(register_name, "%s_i[%u]", prefix, reg->idx[0].offset);
+            break;
+
+        case WINED3DSPR_CONSTBOOL:
+            sprintf(register_name, "%s_b[%u]", prefix, reg->idx[0].offset);
+            break;
+
+        case WINED3DSPR_TEXTURE: /* case WINED3DSPR_ADDR: */
+            if (version->type == WINED3D_SHADER_TYPE_PIXEL)
+                sprintf(register_name, "T%u", reg->idx[0].offset);
+            else
+                sprintf(register_name, "A%u", reg->idx[0].offset);
+            break;
+
+        case WINED3DSPR_LOOP:
+            sprintf(register_name, "aL%u", ins->ctx->loop_state->current_reg - 1);
+            break;
+
+        case WINED3DSPR_SAMPLER:
+            sprintf(register_name, "%s_sampler%u", prefix, reg->idx[0].offset);
+            break;
+
+        case WINED3DSPR_COLOROUT:
+            if (reg->idx[0].offset >= gl_info->limits.buffers)
+                WARN("Write to render target %u, only %d supported.\n",
+                        reg->idx[0].offset, gl_info->limits.buffers);
+
+            sprintf(register_name, "gl_FragData[%u]", reg->idx[0].offset);
+            break;
+
+        case WINED3DSPR_RASTOUT:
+            sprintf(register_name, "%s", hwrastout_reg_names[reg->idx[0].offset]);
+            break;
+
+        case WINED3DSPR_DEPTHOUT:
+            sprintf(register_name, "gl_FragDepth");
+            break;
+
+        case WINED3DSPR_ATTROUT:
+            if (!reg->idx[0].offset)
+                sprintf(register_name, "%s_out[8]", prefix);
+            else
+                sprintf(register_name, "%s_out[9]", prefix);
+            break;
+
+        case WINED3DSPR_TEXCRDOUT:
+            /* Vertex shaders >= 3.0: WINED3DSPR_OUTPUT */
+            sprintf(register_name, "%s_out[%u]", prefix, reg->idx[0].offset);
+            break;
+
+        case WINED3DSPR_MISCTYPE:
+            if (!reg->idx[0].offset)
+            {
+                /* vPos */
+                sprintf(register_name, "vpos");
+            }
+            else if (reg->idx[0].offset == 1)
+            {
+                /* Note that gl_FrontFacing is a bool, while vFace is
+                 * a float for which the sign determines front/back */
+                sprintf(register_name, "(gl_FrontFacing ? 1.0 : -1.0)");
+            }
+            else
+            {
+                FIXME("Unhandled misctype register %u.\n", reg->idx[0].offset);
+                sprintf(register_name, "unrecognized_register");
+            }
+            break;
+
+        case WINED3DSPR_IMMCONST:
+            switch (reg->immconst_type)
+            {
+                case WINED3D_IMMCONST_SCALAR:
+                    switch (reg->data_type)
+                    {
+                        case WINED3D_DATA_FLOAT:
+                            sprintf(register_name, "%.8e", *(const float *)reg->immconst_data);
+                            break;
+                        case WINED3D_DATA_INT:
+                            sprintf(register_name, "%#x", reg->immconst_data[0]);
+                            break;
+                        case WINED3D_DATA_RESOURCE:
+                        case WINED3D_DATA_SAMPLER:
+                        case WINED3D_DATA_UINT:
+                            sprintf(register_name, "%#xu", reg->immconst_data[0]);
+                            break;
+                        default:
+                            sprintf(register_name, "<unhandled data type %#x>", reg->data_type);
+                            break;
+                    }
+                    break;
+
+                case WINED3D_IMMCONST_VEC4:
+                    switch (reg->data_type)
+                    {
+                        case WINED3D_DATA_FLOAT:
+                            sprintf(register_name, "vec4(%.8e, %.8e, %.8e, %.8e)",
+                                    *(const float *)&reg->immconst_data[0], *(const float *)&reg->immconst_data[1],
+                                    *(const float *)&reg->immconst_data[2], *(const float *)&reg->immconst_data[3]);
+                            break;
+                        case WINED3D_DATA_INT:
+                            sprintf(register_name, "ivec4(%#x, %#x, %#x, %#x)",
+                                    reg->immconst_data[0], reg->immconst_data[1],
+                                    reg->immconst_data[2], reg->immconst_data[3]);
+                            break;
+                        case WINED3D_DATA_RESOURCE:
+                        case WINED3D_DATA_SAMPLER:
+                        case WINED3D_DATA_UINT:
+                            sprintf(register_name, "uvec4(%#xu, %#xu, %#xu, %#xu)",
+                                    reg->immconst_data[0], reg->immconst_data[1],
+                                    reg->immconst_data[2], reg->immconst_data[3]);
+                            break;
+                        default:
+                            sprintf(register_name, "<unhandled data type %#x>", reg->data_type);
+                            break;
+                    }
+                    break;
+
+                default:
+                    FIXME("Unhandled immconst type %#x\n", reg->immconst_type);
+                    sprintf(register_name, "<unhandled_immconst_type %#x>", reg->immconst_type);
+            }
+            break;
+
+        case WINED3DSPR_CONSTBUFFER:
+            if (reg->idx[1].rel_addr)
+                sprintf(register_name, "%s_cb%u[%s + %u]",
+                        prefix, reg->idx[0].offset, rel_param1.param_str, reg->idx[1].offset);
+            else
+                sprintf(register_name, "%s_cb%u[%u]", prefix, reg->idx[0].offset, reg->idx[1].offset);
+            break;
+
+        case WINED3DSPR_PRIMID:
+            sprintf(register_name, "uint(gl_PrimitiveIDIn)");
+            break;
+
+        default:
+            FIXME("Unhandled register type %#x.\n", reg->type);
+            sprintf(register_name, "unrecognized_register");
+            break;
+    }
+}
+
+static void shader_glsl_write_mask_to_str(DWORD write_mask, char *str)
+{
+    *str++ = '.';
+    if (write_mask & WINED3DSP_WRITEMASK_0) *str++ = 'x';
+    if (write_mask & WINED3DSP_WRITEMASK_1) *str++ = 'y';
+    if (write_mask & WINED3DSP_WRITEMASK_2) *str++ = 'z';
+    if (write_mask & WINED3DSP_WRITEMASK_3) *str++ = 'w';
+    *str = '\0';
+}
+
+/* Get the GLSL write mask for the destination register */
+static DWORD shader_glsl_get_write_mask(const struct wined3d_shader_dst_param *param, char *write_mask)
+{
+    DWORD mask = param->write_mask;
+
+    if (shader_is_scalar(&param->reg))
+    {
+        mask = WINED3DSP_WRITEMASK_0;
+        *write_mask = '\0';
+    }
+    else
+    {
+        shader_glsl_write_mask_to_str(mask, write_mask);
+    }
+
+    return mask;
+}
+
+static unsigned int shader_glsl_get_write_mask_size(DWORD write_mask) {
+    unsigned int size = 0;
+
+    if (write_mask & WINED3DSP_WRITEMASK_0) ++size;
+    if (write_mask & WINED3DSP_WRITEMASK_1) ++size;
+    if (write_mask & WINED3DSP_WRITEMASK_2) ++size;
+    if (write_mask & WINED3DSP_WRITEMASK_3) ++size;
+
+    return size;
+}
+
+static void shader_glsl_swizzle_to_str(const DWORD swizzle, BOOL fixup, DWORD mask, char *str)
+{
+    /* For registers of type WINED3DDECLTYPE_D3DCOLOR, data is stored as "bgra",
+     * but addressed as "rgba". To fix this we need to swap the register's x
+     * and z components. */
+    const char *swizzle_chars = fixup ? "zyxw" : "xyzw";
+
+    *str++ = '.';
+    /* swizzle bits fields: wwzzyyxx */
+    if (mask & WINED3DSP_WRITEMASK_0) *str++ = swizzle_chars[swizzle & 0x03];
+    if (mask & WINED3DSP_WRITEMASK_1) *str++ = swizzle_chars[(swizzle >> 2) & 0x03];
+    if (mask & WINED3DSP_WRITEMASK_2) *str++ = swizzle_chars[(swizzle >> 4) & 0x03];
+    if (mask & WINED3DSP_WRITEMASK_3) *str++ = swizzle_chars[(swizzle >> 6) & 0x03];
+    *str = '\0';
+}
+
+static void shader_glsl_get_swizzle(const struct wined3d_shader_src_param *param,
+        BOOL fixup, DWORD mask, char *swizzle_str)
+{
+    if (shader_is_scalar(&param->reg))
+        *swizzle_str = '\0';
+    else
+        shader_glsl_swizzle_to_str(param->swizzle, fixup, mask, swizzle_str);
+}
+
+/* From a given parameter token, generate the corresponding GLSL string.
+ * Also, return the actual register name and swizzle in case the
+ * caller needs this information as well. */
+static void shader_glsl_add_src_param(const struct wined3d_shader_instruction *ins,
+        const struct wined3d_shader_src_param *wined3d_src, DWORD mask, struct glsl_src_param *glsl_src)
+{
+    BOOL is_color = FALSE;
+    char swizzle_str[6];
+
+    glsl_src->reg_name[0] = '\0';
+    glsl_src->param_str[0] = '\0';
+    swizzle_str[0] = '\0';
+
+    shader_glsl_get_register_name(&wined3d_src->reg, glsl_src->reg_name, &is_color, ins);
+    shader_glsl_get_swizzle(wined3d_src, is_color, mask, swizzle_str);
+
+    if (wined3d_src->reg.type == WINED3DSPR_IMMCONST || wined3d_src->reg.type == WINED3DSPR_PRIMID)
+    {
+        shader_glsl_gen_modifier(wined3d_src->modifiers, glsl_src->reg_name, swizzle_str, glsl_src->param_str);
+    }
+    else
+    {
+        char param_str[200];
+
+        shader_glsl_gen_modifier(wined3d_src->modifiers, glsl_src->reg_name, swizzle_str, param_str);
+
+        switch (wined3d_src->reg.data_type)
+        {
+            case WINED3D_DATA_FLOAT:
+                sprintf(glsl_src->param_str, "%s", param_str);
+                break;
+            case WINED3D_DATA_INT:
+                sprintf(glsl_src->param_str, "floatBitsToInt(%s)", param_str);
+                break;
+            case WINED3D_DATA_RESOURCE:
+            case WINED3D_DATA_SAMPLER:
+            case WINED3D_DATA_UINT:
+                sprintf(glsl_src->param_str, "floatBitsToUint(%s)", param_str);
+                break;
+            default:
+                FIXME("Unhandled data type %#x.\n", wined3d_src->reg.data_type);
+                sprintf(glsl_src->param_str, "%s", param_str);
+                break;
+        }
+    }
+}
+
+/* From a given parameter token, generate the corresponding GLSL string.
+ * Also, return the actual register name and swizzle in case the
+ * caller needs this information as well. */
+static DWORD shader_glsl_add_dst_param(const struct wined3d_shader_instruction *ins,
+        const struct wined3d_shader_dst_param *wined3d_dst, struct glsl_dst_param *glsl_dst)
+{
+    BOOL is_color = FALSE;
+
+    glsl_dst->mask_str[0] = '\0';
+    glsl_dst->reg_name[0] = '\0';
+
+    shader_glsl_get_register_name(&wined3d_dst->reg, glsl_dst->reg_name, &is_color, ins);
+    return shader_glsl_get_write_mask(wined3d_dst, glsl_dst->mask_str);
+}
+
+/* Append the destination part of the instruction to the buffer, return the effective write mask */
+static DWORD shader_glsl_append_dst_ext(struct wined3d_shader_buffer *buffer,
+        const struct wined3d_shader_instruction *ins, const struct wined3d_shader_dst_param *dst)
+{
+    struct glsl_dst_param glsl_dst;
+    DWORD mask;
+
+    if ((mask = shader_glsl_add_dst_param(ins, dst, &glsl_dst)))
+    {
+        switch (dst->reg.data_type)
+        {
+            case WINED3D_DATA_FLOAT:
+                shader_addline(buffer, "%s%s = %s(",
+                        glsl_dst.reg_name, glsl_dst.mask_str, shift_glsl_tab[dst->shift]);
+                break;
+            case WINED3D_DATA_INT:
+                shader_addline(buffer, "%s%s = %sintBitsToFloat(",
+                        glsl_dst.reg_name, glsl_dst.mask_str, shift_glsl_tab[dst->shift]);
+                break;
+            case WINED3D_DATA_RESOURCE:
+            case WINED3D_DATA_SAMPLER:
+            case WINED3D_DATA_UINT:
+                shader_addline(buffer, "%s%s = %suintBitsToFloat(",
+                        glsl_dst.reg_name, glsl_dst.mask_str, shift_glsl_tab[dst->shift]);
+                break;
+            default:
+                FIXME("Unhandled data type %#x.\n", dst->reg.data_type);
+                shader_addline(buffer, "%s%s = %s(",
+                        glsl_dst.reg_name, glsl_dst.mask_str, shift_glsl_tab[dst->shift]);
+                break;
+        }
+    }
+
+    return mask;
+}
+
+/* Append the destination part of the instruction to the buffer, return the effective write mask */
+static DWORD shader_glsl_append_dst(struct wined3d_shader_buffer *buffer, const struct wined3d_shader_instruction *ins)
+{
+    return shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0]);
+}
+
+/** Process GLSL instruction modifiers */
+static void shader_glsl_add_instruction_modifiers(const struct wined3d_shader_instruction *ins)
+{
+    struct glsl_dst_param dst_param;
+    DWORD modifiers;
+
+    if (!ins->dst_count) return;
+
+    modifiers = ins->dst[0].modifiers;
+    if (!modifiers) return;
+
+    shader_glsl_add_dst_param(ins, &ins->dst[0], &dst_param);
+
+    if (modifiers & WINED3DSPDM_SATURATE)
+    {
+        /* _SAT means to clamp the value of the register to between 0 and 1 */
+        shader_addline(ins->ctx->buffer, "%s%s = clamp(%s%s, 0.0, 1.0);\n", dst_param.reg_name,
+                dst_param.mask_str, dst_param.reg_name, dst_param.mask_str);
+    }
+
+    if (modifiers & WINED3DSPDM_MSAMPCENTROID)
+    {
+        FIXME("_centroid modifier not handled\n");
+    }
+
+    if (modifiers & WINED3DSPDM_PARTIALPRECISION)
+    {
+        /* MSDN says this modifier can be safely ignored, so that's what we'll do. */
+    }
+}
+
+static const char *shader_glsl_get_rel_op(enum wined3d_shader_rel_op op)
+{
+    switch (op)
+    {
+        case WINED3D_SHADER_REL_OP_GT: return ">";
+        case WINED3D_SHADER_REL_OP_EQ: return "==";
+        case WINED3D_SHADER_REL_OP_GE: return ">=";
+        case WINED3D_SHADER_REL_OP_LT: return "<";
+        case WINED3D_SHADER_REL_OP_NE: return "!=";
+        case WINED3D_SHADER_REL_OP_LE: return "<=";
+        default:
+            FIXME("Unrecognized operator %#x.\n", op);
+            return "(\?\?)";
+    }
+}
+
+static void shader_glsl_get_sample_function(const struct wined3d_shader_context *ctx,
+        DWORD sampler_idx, DWORD flags, struct glsl_sample_function *sample_function)
+{
+    enum wined3d_sampler_texture_type sampler_type = ctx->reg_maps->sampler_type[sampler_idx];
+    const struct wined3d_gl_info *gl_info = ctx->gl_info;
+    BOOL shadow = ctx->reg_maps->shader_version.type == WINED3D_SHADER_TYPE_PIXEL
+            && (((const struct shader_glsl_ctx_priv *)ctx->backend_data)->cur_ps_args->shadow & (1 << sampler_idx));
+    BOOL projected = flags & WINED3D_GLSL_SAMPLE_PROJECTED;
+    BOOL texrect = flags & WINED3D_GLSL_SAMPLE_NPOT && gl_info->supported[ARB_TEXTURE_RECTANGLE];
+    BOOL lod = flags & WINED3D_GLSL_SAMPLE_LOD;
+    BOOL grad = flags & WINED3D_GLSL_SAMPLE_GRAD;
+
+    /* Note that there's no such thing as a projected cube texture. */
+    switch(sampler_type) {
+        case WINED3DSTT_1D:
+            if (shadow)
+            {
+                if (lod)
+                {
+                    sample_function->name = projected ? "shadow1DProjLod" : "shadow1DLod";
+                }
+                else if (grad)
+                {
+                    if (gl_info->supported[EXT_GPU_SHADER4])
+                        sample_function->name = projected ? "shadow1DProjGrad" : "shadow1DGrad";
+                    else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD])
+                        sample_function->name = projected ? "shadow1DProjGradARB" : "shadow1DGradARB";
+                    else
+                    {
+                        FIXME("Unsupported 1D shadow grad function.\n");
+                        sample_function->name = "unsupported1DGrad";
+                    }
+                }
+                else
+                {
+                    sample_function->name = projected ? "shadow1DProj" : "shadow1D";
+                }
+                sample_function->coord_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1;
+            }
+            else
+            {
+                if (lod)
+                {
+                    sample_function->name = projected ? "texture1DProjLod" : "texture1DLod";
+                }
+                else if (grad)
+                {
+                    if (gl_info->supported[EXT_GPU_SHADER4])
+                        sample_function->name = projected ? "texture1DProjGrad" : "texture1DGrad";
+                    else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD])
+                        sample_function->name = projected ? "texture1DProjGradARB" : "texture1DGradARB";
+                    else
+                    {
+                        FIXME("Unsupported 1D grad function.\n");
+                        sample_function->name = "unsupported1DGrad";
+                    }
+                }
+                else
+                {
+                    sample_function->name = projected ? "texture1DProj" : "texture1D";
+                }
+                sample_function->coord_mask = WINED3DSP_WRITEMASK_0;
+            }
+            break;
+
+        case WINED3DSTT_2D:
+            if (shadow)
+            {
+                if (texrect)
+                {
+                    if (lod)
+                    {
+                        sample_function->name = projected ? "shadow2DRectProjLod" : "shadow2DRectLod";
+                    }
+                    else if (grad)
+                    {
+                        if (gl_info->supported[EXT_GPU_SHADER4])
+                            sample_function->name = projected ? "shadow2DRectProjGrad" : "shadow2DRectGrad";
+                        else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD])
+                            sample_function->name = projected ? "shadow2DRectProjGradARB" : "shadow2DRectGradARB";
+                        else
+                        {
+                            FIXME("Unsupported RECT shadow grad function.\n");
+                            sample_function->name = "unsupported2DRectGrad";
+                        }
+                    }
+                    else
+                    {
+                        sample_function->name = projected ? "shadow2DRectProj" : "shadow2DRect";
+                    }
+                }
+                else
+                {
+                    if (lod)
+                    {
+                        sample_function->name = projected ? "shadow2DProjLod" : "shadow2DLod";
+                    }
+                    else if (grad)
+                    {
+                        if (gl_info->supported[EXT_GPU_SHADER4])
+                            sample_function->name = projected ? "shadow2DProjGrad" : "shadow2DGrad";
+                        else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD])
+                            sample_function->name = projected ? "shadow2DProjGradARB" : "shadow2DGradARB";
+                        else
+                        {
+                            FIXME("Unsupported 2D shadow grad function.\n");
+                            sample_function->name = "unsupported2DGrad";
+                        }
+                    }
+                    else
+                    {
+                        sample_function->name = projected ? "shadow2DProj" : "shadow2D";
+                    }
+                }
+                sample_function->coord_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
+            }
+            else
+            {
+                if (texrect)
+                {
+                    if (lod)
+                    {
+                        sample_function->name = projected ? "texture2DRectProjLod" : "texture2DRectLod";
+                    }
+                    else if (grad)
+                    {
+                        if (gl_info->supported[EXT_GPU_SHADER4])
+                            sample_function->name = projected ? "texture2DRectProjGrad" : "texture2DRectGrad";
+                        else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD])
+                            sample_function->name = projected ? "texture2DRectProjGradARB" : "texture2DRectGradARB";
+                        else
+                        {
+                            FIXME("Unsupported RECT grad function.\n");
+                            sample_function->name = "unsupported2DRectGrad";
+                        }
+                    }
+                    else
+                    {
+                        sample_function->name = projected ? "texture2DRectProj" : "texture2DRect";
+                    }
+                }
+                else
+                {
+                    if (lod)
+                    {
+                        sample_function->name = projected ? "texture2DProjLod" : "texture2DLod";
+                    }
+                    else if (grad)
+                    {
+                        if (gl_info->supported[EXT_GPU_SHADER4])
+                            sample_function->name = projected ? "texture2DProjGrad" : "texture2DGrad";
+                        else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD])
+                            sample_function->name = projected ? "texture2DProjGradARB" : "texture2DGradARB";
+                        else
+                        {
+                            FIXME("Unsupported 2D grad function.\n");
+                            sample_function->name = "unsupported2DGrad";
+                        }
+                    }
+                    else
+                    {
+                        sample_function->name = projected ? "texture2DProj" : "texture2D";
+                    }
+                }
+                sample_function->coord_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1;
+            }
+            break;
+
+        case WINED3DSTT_CUBE:
+            if (shadow)
+            {
+                FIXME("Unsupported Cube shadow function.\n");
+                sample_function->name = "unsupportedCubeShadow";
+                sample_function->coord_mask = 0;
+            }
+            else
+            {
+                if (lod)
+                {
+                    sample_function->name = "textureCubeLod";
+                }
+                else if (grad)
+                {
+                    if (gl_info->supported[EXT_GPU_SHADER4])
+                        sample_function->name = "textureCubeGrad";
+                    else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD])
+                        sample_function->name = "textureCubeGradARB";
+                    else
+                    {
+                        FIXME("Unsupported Cube grad function.\n");
+                        sample_function->name = "unsupportedCubeGrad";
+                    }
+                }
+                else
+                {
+                    sample_function->name = "textureCube";
+                }
+                sample_function->coord_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
+            }
+            break;
+
+        case WINED3DSTT_VOLUME:
+            if (shadow)
+            {
+                FIXME("Unsupported 3D shadow function.\n");
+                sample_function->name = "unsupported3DShadow";
+                sample_function->coord_mask = 0;
+            }
+            else
+            {
+                if (lod)
+                {
+                    sample_function->name = projected ? "texture3DProjLod" : "texture3DLod";
+                }
+                else  if (grad)
+                {
+                    if (gl_info->supported[EXT_GPU_SHADER4])
+                        sample_function->name = projected ? "texture3DProjGrad" : "texture3DGrad";
+                    else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD])
+                        sample_function->name = projected ? "texture3DProjGradARB" : "texture3DGradARB";
+                    else
+                    {
+                        FIXME("Unsupported 3D grad function.\n");
+                        sample_function->name = "unsupported3DGrad";
+                    }
+                }
+                else
+                {
+                    sample_function->name = projected ? "texture3DProj" : "texture3D";
+                }
+                sample_function->coord_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
+            }
+            break;
+
+        default:
+            sample_function->name = "";
+            sample_function->coord_mask = 0;
+            FIXME("Unrecognized sampler type: %#x;\n", sampler_type);
+            break;
+    }
+}
+
+static void shader_glsl_append_fixup_arg(char *arguments, const char *reg_name,
+        BOOL sign_fixup, enum fixup_channel_source channel_source)
+{
+    switch(channel_source)
+    {
+        case CHANNEL_SOURCE_ZERO:
+            strcat(arguments, "0.0");
+            break;
+
+        case CHANNEL_SOURCE_ONE:
+            strcat(arguments, "1.0");
+            break;
+
+        case CHANNEL_SOURCE_X:
+            strcat(arguments, reg_name);
+            strcat(arguments, ".x");
+            break;
+
+        case CHANNEL_SOURCE_Y:
+            strcat(arguments, reg_name);
+            strcat(arguments, ".y");
+            break;
+
+        case CHANNEL_SOURCE_Z:
+            strcat(arguments, reg_name);
+            strcat(arguments, ".z");
+            break;
+
+        case CHANNEL_SOURCE_W:
+            strcat(arguments, reg_name);
+            strcat(arguments, ".w");
+            break;
+
+        default:
+            FIXME("Unhandled channel source %#x\n", channel_source);
+            strcat(arguments, "undefined");
+            break;
+    }
+
+    if (sign_fixup) strcat(arguments, " * 2.0 - 1.0");
+}
+
+static void shader_glsl_color_correction_ext(struct wined3d_shader_buffer *buffer,
+        const char *reg_name, DWORD mask, struct color_fixup_desc fixup)
+{
+    unsigned int mask_size, remaining;
+    DWORD fixup_mask = 0;
+    char arguments[256];
+    char mask_str[6];
+
+    if (fixup.x_sign_fixup || fixup.x_source != CHANNEL_SOURCE_X) fixup_mask |= WINED3DSP_WRITEMASK_0;
+    if (fixup.y_sign_fixup || fixup.y_source != CHANNEL_SOURCE_Y) fixup_mask |= WINED3DSP_WRITEMASK_1;
+    if (fixup.z_sign_fixup || fixup.z_source != CHANNEL_SOURCE_Z) fixup_mask |= WINED3DSP_WRITEMASK_2;
+    if (fixup.w_sign_fixup || fixup.w_source != CHANNEL_SOURCE_W) fixup_mask |= WINED3DSP_WRITEMASK_3;
+    if (!(mask &= fixup_mask))
+        return;
+
+    if (is_complex_fixup(fixup))
+    {
+        enum complex_fixup complex_fixup = get_complex_fixup(fixup);
+        FIXME("Complex fixup (%#x) not supported\n",complex_fixup);
+        return;
+    }
+
+    shader_glsl_write_mask_to_str(mask, mask_str);
+    mask_size = shader_glsl_get_write_mask_size(mask);
+
+    arguments[0] = '\0';
+    remaining = mask_size;
+    if (mask & WINED3DSP_WRITEMASK_0)
+    {
+        shader_glsl_append_fixup_arg(arguments, reg_name, fixup.x_sign_fixup, fixup.x_source);
+        if (--remaining) strcat(arguments, ", ");
+    }
+    if (mask & WINED3DSP_WRITEMASK_1)
+    {
+        shader_glsl_append_fixup_arg(arguments, reg_name, fixup.y_sign_fixup, fixup.y_source);
+        if (--remaining) strcat(arguments, ", ");
+    }
+    if (mask & WINED3DSP_WRITEMASK_2)
+    {
+        shader_glsl_append_fixup_arg(arguments, reg_name, fixup.z_sign_fixup, fixup.z_source);
+        if (--remaining) strcat(arguments, ", ");
+    }
+    if (mask & WINED3DSP_WRITEMASK_3)
+    {
+        shader_glsl_append_fixup_arg(arguments, reg_name, fixup.w_sign_fixup, fixup.w_source);
+        if (--remaining) strcat(arguments, ", ");
+    }
+
+    if (mask_size > 1)
+        shader_addline(buffer, "%s%s = vec%u(%s);\n", reg_name, mask_str, mask_size, arguments);
+    else
+        shader_addline(buffer, "%s%s = %s;\n", reg_name, mask_str, arguments);
+}
+
+static void shader_glsl_color_correction(const struct wined3d_shader_instruction *ins, struct color_fixup_desc fixup)
+{
+    char reg_name[256];
+    BOOL is_color;
+
+    shader_glsl_get_register_name(&ins->dst[0].reg, reg_name, &is_color, ins);
+    shader_glsl_color_correction_ext(ins->ctx->buffer, reg_name, ins->dst[0].write_mask, fixup);
+}
+
+static void PRINTF_ATTR(8, 9) shader_glsl_gen_sample_code(const struct wined3d_shader_instruction *ins,
+        DWORD sampler, const struct glsl_sample_function *sample_function, DWORD swizzle,
+        const char *dx, const char *dy, const char *bias, const char *coord_reg_fmt, ...)
+{
+    const struct wined3d_shader_version *version = &ins->ctx->reg_maps->shader_version;
+    char dst_swizzle[6];
+    struct color_fixup_desc fixup;
+    BOOL np2_fixup = FALSE;
+    va_list args;
+
+    shader_glsl_swizzle_to_str(swizzle, FALSE, ins->dst[0].write_mask, dst_swizzle);
+
+    if (version->type == WINED3D_SHADER_TYPE_PIXEL)
+    {
+        const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data;
+        fixup = priv->cur_ps_args->color_fixup[sampler];
+
+        if(priv->cur_ps_args->np2_fixup & (1 << sampler)) {
+            if(bias) {
+                FIXME("Biased sampling from NP2 textures is unsupported\n");
+            } else {
+                np2_fixup = TRUE;
+            }
+        }
+    }
+    else
+    {
+        fixup = COLOR_FIXUP_IDENTITY; /* FIXME: Vshader color fixup */
+    }
+
+    shader_glsl_append_dst(ins->ctx->buffer, ins);
+
+    shader_addline(ins->ctx->buffer, "%s(%s_sampler%u, ",
+            sample_function->name, shader_glsl_get_prefix(version->type), sampler);
+
+    va_start(args, coord_reg_fmt);
+    shader_vaddline(ins->ctx->buffer, coord_reg_fmt, args);
+    va_end(args);
+
+    if(bias) {
+        shader_addline(ins->ctx->buffer, ", %s)%s);\n", bias, dst_swizzle);
+    } else {
+        if (np2_fixup) {
+            const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data;
+            const unsigned char idx = priv->cur_np2fixup_info->idx[sampler];
+
+            shader_addline(ins->ctx->buffer, " * ps_samplerNP2Fixup[%u].%s)%s);\n", idx >> 1,
+                           (idx % 2) ? "zw" : "xy", dst_swizzle);
+        } else if(dx && dy) {
+            shader_addline(ins->ctx->buffer, ", %s, %s)%s);\n", dx, dy, dst_swizzle);
+        } else {
+            shader_addline(ins->ctx->buffer, ")%s);\n", dst_swizzle);
+        }
+    }
+
+    if(!is_identity_fixup(fixup)) {
+        shader_glsl_color_correction(ins, fixup);
+    }
+}
+
+/*****************************************************************************
+ * Begin processing individual instruction opcodes
+ ****************************************************************************/
+
+static void shader_glsl_binop(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    struct glsl_src_param src0_param;
+    struct glsl_src_param src1_param;
+    DWORD write_mask;
+    const char *op;
+
+    /* Determine the GLSL operator to use based on the opcode */
+    switch (ins->handler_idx)
+    {
+        case WINED3DSIH_ADD:  op = "+";  break;
+        case WINED3DSIH_AND:  op = "&";  break;
+        case WINED3DSIH_DIV:  op = "/";  break;
+        case WINED3DSIH_IADD: op = "+";  break;
+        case WINED3DSIH_MUL:  op = "*";  break;
+        case WINED3DSIH_SUB:  op = "-";  break;
+        case WINED3DSIH_USHR: op = ">>"; break;
+        case WINED3DSIH_XOR:  op = "^";  break;
+        default:
+            op = "<unhandled operator>";
+            FIXME("Opcode %#x not yet handled in GLSL\n", ins->handler_idx);
+            break;
+    }
+
+    write_mask = shader_glsl_append_dst(buffer, ins);
+    shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
+    shader_addline(buffer, "%s %s %s);\n", src0_param.param_str, op, src1_param.param_str);
+}
+
+static void shader_glsl_relop(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    struct glsl_src_param src0_param;
+    struct glsl_src_param src1_param;
+    unsigned int mask_size;
+    DWORD write_mask;
+    const char *op;
+
+    write_mask = shader_glsl_append_dst(buffer, ins);
+    mask_size = shader_glsl_get_write_mask_size(write_mask);
+    shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
+
+    if (mask_size > 1)
+    {
+        switch (ins->handler_idx)
+        {
+            case WINED3DSIH_EQ:  op = "equal"; break;
+            case WINED3DSIH_GE:  op = "greaterThanEqual"; break;
+            case WINED3DSIH_IGE: op = "greaterThanEqual"; break;
+            case WINED3DSIH_LT:  op = "lessThan"; break;
+            default:
+                op = "<unhandled operator>";
+                ERR("Unhandled opcode %#x.\n", ins->handler_idx);
+                break;
+        }
+
+        shader_addline(buffer, "uvec%u(%s(%s, %s)) * 0xffffffffu);\n",
+                mask_size, op, src0_param.param_str, src1_param.param_str);
+    }
+    else
+    {
+        switch (ins->handler_idx)
+        {
+            case WINED3DSIH_EQ:  op = "=="; break;
+            case WINED3DSIH_GE:  op = ">="; break;
+            case WINED3DSIH_IGE: op = ">="; break;
+            case WINED3DSIH_LT:  op = "<"; break;
+            default:
+                op = "<unhandled operator>";
+                ERR("Unhandled opcode %#x.\n", ins->handler_idx);
+                break;
+        }
+
+        shader_addline(buffer, "%s %s %s ? 0xffffffffu : 0u);\n",
+                src0_param.param_str, op, src1_param.param_str);
+    }
+}
+
+static void shader_glsl_imul(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    struct glsl_src_param src0_param;
+    struct glsl_src_param src1_param;
+    DWORD write_mask;
+
+    /* If we have ARB_gpu_shader5 or GLSL 4.0, we can use imulExtended(). If
+     * not, we can emulate it. */
+    if (ins->dst[0].reg.type != WINED3DSPR_NULL)
+        FIXME("64-bit integer multiplies not implemented.\n");
+
+    if (ins->dst[1].reg.type != WINED3DSPR_NULL)
+    {
+        write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[1]);
+        shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
+        shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
+
+        shader_addline(ins->ctx->buffer, "%s * %s);\n",
+                src0_param.param_str, src1_param.param_str);
+    }
+}
+
+static void shader_glsl_udiv(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    struct glsl_src_param src0_param, src1_param;
+    DWORD write_mask;
+
+    if (ins->dst[0].reg.type != WINED3DSPR_NULL)
+    {
+
+        if (ins->dst[1].reg.type != WINED3DSPR_NULL)
+        {
+            char dst_mask[6];
+
+            write_mask = shader_glsl_get_write_mask(&ins->dst[0], dst_mask);
+            shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
+            shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
+            shader_addline(buffer, "tmp0%s = %s / %s;\n",
+                    dst_mask, src0_param.param_str, src1_param.param_str);
+
+            write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[1]);
+            shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
+            shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
+            shader_addline(buffer, "%s %% %s));\n", src0_param.param_str, src1_param.param_str);
+
+            shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0]);
+            shader_addline(buffer, "tmp0%s);\n", dst_mask);
+        }
+        else
+        {
+            write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0]);
+            shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
+            shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
+            shader_addline(buffer, "%s / %s);\n", src0_param.param_str, src1_param.param_str);
+        }
+    }
+    else if (ins->dst[1].reg.type != WINED3DSPR_NULL)
+    {
+        write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[1]);
+        shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
+        shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
+        shader_addline(buffer, "%s %% %s);\n", src0_param.param_str, src1_param.param_str);
+    }
+}
+
+/* Process the WINED3DSIO_MOV opcode using GLSL (dst = src) */
+static void shader_glsl_mov(const struct wined3d_shader_instruction *ins)
+{
+    const struct wined3d_gl_info *gl_info = ins->ctx->gl_info;
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    struct glsl_src_param src0_param;
+    DWORD write_mask;
+
+    write_mask = shader_glsl_append_dst(buffer, ins);
+    shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
+
+    /* In vs_1_1 WINED3DSIO_MOV can write to the address register. In later
+     * shader versions WINED3DSIO_MOVA is used for this. */
+    if (ins->ctx->reg_maps->shader_version.major == 1
+            && ins->ctx->reg_maps->shader_version.type == WINED3D_SHADER_TYPE_VERTEX
+            && ins->dst[0].reg.type == WINED3DSPR_ADDR)
+    {
+        /* This is a simple floor() */
+        unsigned int mask_size = shader_glsl_get_write_mask_size(write_mask);
+        if (mask_size > 1) {
+            shader_addline(buffer, "ivec%d(floor(%s)));\n", mask_size, src0_param.param_str);
+        } else {
+            shader_addline(buffer, "int(floor(%s)));\n", src0_param.param_str);
+        }
+    }
+    else if(ins->handler_idx == WINED3DSIH_MOVA)
+    {
+        /* We need to *round* to the nearest int here. */
+        unsigned int mask_size = shader_glsl_get_write_mask_size(write_mask);
+
+        if (gl_info->supported[EXT_GPU_SHADER4])
+        {
+            if (mask_size > 1)
+                shader_addline(buffer, "ivec%d(round(%s)));\n", mask_size, src0_param.param_str);
+            else
+                shader_addline(buffer, "int(round(%s)));\n", src0_param.param_str);
+        }
+        else
+        {
+            if (mask_size > 1)
+                shader_addline(buffer, "ivec%d(floor(abs(%s) + vec%d(0.5)) * sign(%s)));\n",
+                        mask_size, src0_param.param_str, mask_size, src0_param.param_str);
+            else
+                shader_addline(buffer, "int(floor(abs(%s) + 0.5) * sign(%s)));\n",
+                        src0_param.param_str, src0_param.param_str);
+        }
+    }
+    else
+    {
+        shader_addline(buffer, "%s);\n", src0_param.param_str);
+    }
+}
+
+/* Process the dot product operators DP3 and DP4 in GLSL (dst = dot(src0, src1)) */
+static void shader_glsl_dot(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    struct glsl_src_param src0_param;
+    struct glsl_src_param src1_param;
+    DWORD dst_write_mask, src_write_mask;
+    unsigned int dst_size = 0;
+
+    dst_write_mask = shader_glsl_append_dst(buffer, ins);
+    dst_size = shader_glsl_get_write_mask_size(dst_write_mask);
+
+    /* dp3 works on vec3, dp4 on vec4 */
+    if (ins->handler_idx == WINED3DSIH_DP4)
+    {
+        src_write_mask = WINED3DSP_WRITEMASK_ALL;
+    } else {
+        src_write_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
+    }
+
+    shader_glsl_add_src_param(ins, &ins->src[0], src_write_mask, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[1], src_write_mask, &src1_param);
+
+    if (dst_size > 1) {
+        shader_addline(buffer, "vec%d(dot(%s, %s)));\n", dst_size, src0_param.param_str, src1_param.param_str);
+    } else {
+        shader_addline(buffer, "dot(%s, %s));\n", src0_param.param_str, src1_param.param_str);
+    }
+}
+
+/* Note that this instruction has some restrictions. The destination write mask
+ * can't contain the w component, and the source swizzles have to be .xyzw */
+static void shader_glsl_cross(const struct wined3d_shader_instruction *ins)
+{
+    DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
+    struct glsl_src_param src0_param;
+    struct glsl_src_param src1_param;
+    char dst_mask[6];
+
+    shader_glsl_get_write_mask(&ins->dst[0], dst_mask);
+    shader_glsl_append_dst(ins->ctx->buffer, ins);
+    shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[1], src_mask, &src1_param);
+    shader_addline(ins->ctx->buffer, "cross(%s, %s)%s);\n", src0_param.param_str, src1_param.param_str, dst_mask);
+}
+
+static void shader_glsl_cut(const struct wined3d_shader_instruction *ins)
+{
+    shader_addline(ins->ctx->buffer, "EndPrimitive();\n");
+}
+
+/* Process the WINED3DSIO_POW instruction in GLSL (dst = |src0|^src1)
+ * Src0 and src1 are scalars. Note that D3D uses the absolute of src0, while
+ * GLSL uses the value as-is. */
+static void shader_glsl_pow(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    struct glsl_src_param src0_param;
+    struct glsl_src_param src1_param;
+    DWORD dst_write_mask;
+    unsigned int dst_size;
+
+    dst_write_mask = shader_glsl_append_dst(buffer, ins);
+    dst_size = shader_glsl_get_write_mask_size(dst_write_mask);
+
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0, &src1_param);
+
+    if (dst_size > 1)
+    {
+        shader_addline(buffer, "vec%u(%s == 0.0 ? 1.0 : pow(abs(%s), %s)));\n",
+                dst_size, src1_param.param_str, src0_param.param_str, src1_param.param_str);
+    }
+    else
+    {
+        shader_addline(buffer, "%s == 0.0 ? 1.0 : pow(abs(%s), %s));\n",
+                src1_param.param_str, src0_param.param_str, src1_param.param_str);
+    }
+}
+
+/* Process the WINED3DSIO_LOG instruction in GLSL (dst = log2(|src0|))
+ * Src0 is a scalar. Note that D3D uses the absolute of src0, while
+ * GLSL uses the value as-is. */
+static void shader_glsl_log(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    struct glsl_src_param src0_param;
+    DWORD dst_write_mask;
+    unsigned int dst_size;
+
+    dst_write_mask = shader_glsl_append_dst(buffer, ins);
+    dst_size = shader_glsl_get_write_mask_size(dst_write_mask);
+
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param);
+
+    if (dst_size > 1)
+    {
+        shader_addline(buffer, "vec%u(log2(abs(%s))));\n",
+                dst_size, src0_param.param_str);
+    }
+    else
+    {
+        shader_addline(buffer, "log2(abs(%s)));\n",
+                src0_param.param_str);
+    }
+}
+
+/* Map the opcode 1-to-1 to the GL code (arg->dst = instruction(src0, src1, ...) */
+static void shader_glsl_map2gl(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    struct glsl_src_param src_param;
+    const char *instruction;
+    DWORD write_mask;
+    unsigned i;
+
+    /* Determine the GLSL function to use based on the opcode */
+    /* TODO: Possibly make this a table for faster lookups */
+    switch (ins->handler_idx)
+    {
+        case WINED3DSIH_MIN: instruction = "min"; break;
+        case WINED3DSIH_MAX: instruction = "max"; break;
+        case WINED3DSIH_ABS: instruction = "abs"; break;
+        case WINED3DSIH_FRC: instruction = "fract"; break;
+        case WINED3DSIH_EXP: instruction = "exp2"; break;
+        case WINED3DSIH_DSX: instruction = "dFdx"; break;
+        case WINED3DSIH_DSY: instruction = "ycorrection.y * dFdy"; break;
+        case WINED3DSIH_ROUND_NI: instruction = "floor"; break;
+        default: instruction = "";
+            FIXME("Opcode %#x not yet handled in GLSL\n", ins->handler_idx);
+            break;
+    }
+
+    write_mask = shader_glsl_append_dst(buffer, ins);
+
+    shader_addline(buffer, "%s(", instruction);
+
+    if (ins->src_count)
+    {
+        shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src_param);
+        shader_addline(buffer, "%s", src_param.param_str);
+        for (i = 1; i < ins->src_count; ++i)
+        {
+            shader_glsl_add_src_param(ins, &ins->src[i], write_mask, &src_param);
+            shader_addline(buffer, ", %s", src_param.param_str);
+        }
+    }
+
+    shader_addline(buffer, "));\n");
+}
+
+static void shader_glsl_nop(const struct wined3d_shader_instruction *ins) {}
+
+static void shader_glsl_nrm(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    struct glsl_src_param src_param;
+    unsigned int mask_size;
+    DWORD write_mask;
+    char dst_mask[6];
+
+    write_mask = shader_glsl_get_write_mask(ins->dst, dst_mask);
+    mask_size = shader_glsl_get_write_mask_size(write_mask);
+    shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src_param);
+
+    shader_addline(buffer, "tmp0.x = dot(%s, %s);\n",
+            src_param.param_str, src_param.param_str);
+    shader_glsl_append_dst(buffer, ins);
+
+    if (mask_size > 1)
+    {
+        shader_addline(buffer, "tmp0.x == 0.0 ? vec%u(0.0) : (%s * inversesqrt(tmp0.x)));\n",
+                mask_size, src_param.param_str);
+    }
+    else
+    {
+        shader_addline(buffer, "tmp0.x == 0.0 ? 0.0 : (%s * inversesqrt(tmp0.x)));\n",
+                src_param.param_str);
+    }
+}
+
+/** Process the WINED3DSIO_EXPP instruction in GLSL:
+ * For shader model 1.x, do the following (and honor the writemask, so use a temporary variable):
+ *   dst.x = 2^(floor(src))
+ *   dst.y = src - floor(src)
+ *   dst.z = 2^src   (partial precision is allowed, but optional)
+ *   dst.w = 1.0;
+ * For 2.0 shaders, just do this (honoring writemask and swizzle):
+ *   dst = 2^src;    (partial precision is allowed, but optional)
+ */
+static void shader_glsl_expp(const struct wined3d_shader_instruction *ins)
+{
+    struct glsl_src_param src_param;
+
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src_param);
+
+    if (ins->ctx->reg_maps->shader_version.major < 2)
+    {
+        char dst_mask[6];
+
+        shader_addline(ins->ctx->buffer, "tmp0.x = exp2(floor(%s));\n", src_param.param_str);
+        shader_addline(ins->ctx->buffer, "tmp0.y = %s - floor(%s);\n", src_param.param_str, src_param.param_str);
+        shader_addline(ins->ctx->buffer, "tmp0.z = exp2(%s);\n", src_param.param_str);
+        shader_addline(ins->ctx->buffer, "tmp0.w = 1.0;\n");
+
+        shader_glsl_append_dst(ins->ctx->buffer, ins);
+        shader_glsl_get_write_mask(&ins->dst[0], dst_mask);
+        shader_addline(ins->ctx->buffer, "tmp0%s);\n", dst_mask);
+    } else {
+        DWORD write_mask;
+        unsigned int mask_size;
+
+        write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
+        mask_size = shader_glsl_get_write_mask_size(write_mask);
+
+        if (mask_size > 1) {
+            shader_addline(ins->ctx->buffer, "vec%d(exp2(%s)));\n", mask_size, src_param.param_str);
+        } else {
+            shader_addline(ins->ctx->buffer, "exp2(%s));\n", src_param.param_str);
+        }
+    }
+}
+
+static void shader_glsl_to_int(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    struct glsl_src_param src_param;
+    unsigned int mask_size;
+    DWORD write_mask;
+
+    write_mask = shader_glsl_append_dst(buffer, ins);
+    mask_size = shader_glsl_get_write_mask_size(write_mask);
+    shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src_param);
+
+    if (mask_size > 1)
+        shader_addline(buffer, "ivec%u(%s));\n", mask_size, src_param.param_str);
+    else
+        shader_addline(buffer, "int(%s));\n", src_param.param_str);
+}
+
+static void shader_glsl_to_float(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    struct glsl_src_param src_param;
+    unsigned int mask_size;
+    DWORD write_mask;
+
+    write_mask = shader_glsl_append_dst(buffer, ins);
+    mask_size = shader_glsl_get_write_mask_size(write_mask);
+    shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src_param);
+
+    if (mask_size > 1)
+        shader_addline(buffer, "vec%u(%s));\n", mask_size, src_param.param_str);
+    else
+        shader_addline(buffer, "float(%s));\n", src_param.param_str);
+}
+
+/** Process the RCP (reciprocal or inverse) opcode in GLSL (dst = 1 / src) */
+static void shader_glsl_rcp(const struct wined3d_shader_instruction *ins)
+{
+    struct glsl_src_param src_param;
+    DWORD write_mask;
+    unsigned int mask_size;
+
+    write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
+    mask_size = shader_glsl_get_write_mask_size(write_mask);
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &src_param);
+
+    if (mask_size > 1)
+    {
+        shader_addline(ins->ctx->buffer, "vec%u(1.0 / %s));\n",
+                mask_size, src_param.param_str);
+    }
+    else
+    {
+        shader_addline(ins->ctx->buffer, "1.0 / %s);\n",
+                src_param.param_str);
+    }
+}
+
+static void shader_glsl_rsq(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    struct glsl_src_param src_param;
+    DWORD write_mask;
+    unsigned int mask_size;
+
+    write_mask = shader_glsl_append_dst(buffer, ins);
+    mask_size = shader_glsl_get_write_mask_size(write_mask);
+
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &src_param);
+
+    if (mask_size > 1)
+    {
+        shader_addline(buffer, "vec%u(inversesqrt(abs(%s))));\n",
+                mask_size, src_param.param_str);
+    }
+    else
+    {
+        shader_addline(buffer, "inversesqrt(abs(%s)));\n",
+                src_param.param_str);
+    }
+}
+
+/** Process signed comparison opcodes in GLSL. */
+static void shader_glsl_compare(const struct wined3d_shader_instruction *ins)
+{
+    struct glsl_src_param src0_param;
+    struct glsl_src_param src1_param;
+    DWORD write_mask;
+    unsigned int mask_size;
+
+    write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
+    mask_size = shader_glsl_get_write_mask_size(write_mask);
+    shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
+
+    if (mask_size > 1) {
+        const char *compare;
+
+        switch(ins->handler_idx)
+        {
+            case WINED3DSIH_SLT: compare = "lessThan"; break;
+            case WINED3DSIH_SGE: compare = "greaterThanEqual"; break;
+            default: compare = "";
+                FIXME("Can't handle opcode %#x\n", ins->handler_idx);
+        }
+
+        shader_addline(ins->ctx->buffer, "vec%d(%s(%s, %s)));\n", mask_size, compare,
+                src0_param.param_str, src1_param.param_str);
+    } else {
+        switch(ins->handler_idx)
+        {
+            case WINED3DSIH_SLT:
+                /* Step(src0, src1) is not suitable here because if src0 == src1 SLT is supposed,
+                 * to return 0.0 but step returns 1.0 because step is not < x
+                 * An alternative is a bvec compare padded with an unused second component.
+                 * step(src1 * -1.0, src0 * -1.0) is not an option because it suffers from the same
+                 * issue. Playing with not() is not possible either because not() does not accept
+                 * a scalar.
+                 */
+                shader_addline(ins->ctx->buffer, "(%s < %s) ? 1.0 : 0.0);\n",
+                        src0_param.param_str, src1_param.param_str);
+                break;
+            case WINED3DSIH_SGE:
+                /* Here we can use the step() function and safe a conditional */
+                shader_addline(ins->ctx->buffer, "step(%s, %s));\n", src1_param.param_str, src0_param.param_str);
+                break;
+            default:
+                FIXME("Can't handle opcode %#x\n", ins->handler_idx);
+        }
+
+    }
+}
+
+static void shader_glsl_conditional_move(const struct wined3d_shader_instruction *ins)
+{
+    const char *condition_prefix, *condition_suffix;
+    struct wined3d_shader_dst_param dst;
+    struct glsl_src_param src0_param;
+    struct glsl_src_param src1_param;
+    struct glsl_src_param src2_param;
+    BOOL temp_destination = FALSE;
+    DWORD cmp_channel = 0;
+    unsigned int i, j;
+    char mask_char[6];
+    DWORD write_mask;
+
+    switch (ins->handler_idx)
+    {
+        case WINED3DSIH_CMP:
+            condition_prefix = "";
+            condition_suffix = " >= 0.0";
+            break;
+
+        case WINED3DSIH_CND:
+            condition_prefix = "";
+            condition_suffix = " > 0.5";
+            break;
+
+        case WINED3DSIH_MOVC:
+            condition_prefix = "bool(";
+            condition_suffix = ")";
+            break;
+
+        default:
+            FIXME("Unhandled instruction %#x.\n", ins->handler_idx);
+            condition_prefix = "<unhandled prefix>";
+            condition_suffix = "<unhandled suffix>";
+            break;
+    }
+
+    if (shader_is_scalar(&ins->dst[0].reg) || shader_is_scalar(&ins->src[0].reg))
+    {
+        write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
+        shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
+        shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
+        shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param);
+
+        shader_addline(ins->ctx->buffer, "%s%s%s ? %s : %s);\n",
+                condition_prefix, src0_param.param_str, condition_suffix,
+                src1_param.param_str, src2_param.param_str);
+        return;
+    }
+
+    dst = ins->dst[0];
+
+    /* Splitting the instruction up in multiple lines imposes a problem:
+     * The first lines may overwrite source parameters of the following lines.
+     * Deal with that by using a temporary destination register if needed. */
+    if ((ins->src[0].reg.idx[0].offset == dst.reg.idx[0].offset
+                && ins->src[0].reg.type == dst.reg.type)
+            || (ins->src[1].reg.idx[0].offset == dst.reg.idx[0].offset
+                && ins->src[1].reg.type == dst.reg.type)
+            || (ins->src[2].reg.idx[0].offset == dst.reg.idx[0].offset
+                && ins->src[2].reg.type == dst.reg.type))
+        temp_destination = TRUE;
+
+    /* Cycle through all source0 channels. */
+    for (i = 0; i < 4; ++i)
+    {
+        write_mask = 0;
+        /* Find the destination channels which use the current source0 channel. */
+        for (j = 0; j < 4; ++j)
+        {
+            if (((ins->src[0].swizzle >> (2 * j)) & 0x3) == i)
+            {
+                write_mask |= WINED3DSP_WRITEMASK_0 << j;
+                cmp_channel = WINED3DSP_WRITEMASK_0 << j;
+            }
+        }
+        dst.write_mask = ins->dst[0].write_mask & write_mask;
+
+        if (temp_destination)
+        {
+            if (!(write_mask = shader_glsl_get_write_mask(&dst, mask_char)))
+                continue;
+            shader_addline(ins->ctx->buffer, "tmp0%s = (", mask_char);
+        }
+        else if (!(write_mask = shader_glsl_append_dst_ext(ins->ctx->buffer, ins, &dst)))
+            continue;
+
+        shader_glsl_add_src_param(ins, &ins->src[0], cmp_channel, &src0_param);
+        shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
+        shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param);
+
+        shader_addline(ins->ctx->buffer, "%s%s%s ? %s : %s);\n",
+                condition_prefix, src0_param.param_str, condition_suffix,
+                src1_param.param_str, src2_param.param_str);
+    }
+
+    if (temp_destination)
+    {
+        shader_glsl_get_write_mask(&ins->dst[0], mask_char);
+        shader_glsl_append_dst(ins->ctx->buffer, ins);
+        shader_addline(ins->ctx->buffer, "tmp0%s);\n", mask_char);
+    }
+}
+
+/** Process the CND opcode in GLSL (dst = (src0 > 0.5) ? src1 : src2) */
+/* For ps 1.1-1.3, only a single component of src0 is used. For ps 1.4
+ * the compare is done per component of src0. */
+static void shader_glsl_cnd(const struct wined3d_shader_instruction *ins)
+{
+    struct glsl_src_param src0_param;
+    struct glsl_src_param src1_param;
+    struct glsl_src_param src2_param;
+    DWORD write_mask;
+    DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major,
+            ins->ctx->reg_maps->shader_version.minor);
+
+    if (shader_version < WINED3D_SHADER_VERSION(1, 4))
+    {
+        write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
+        shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param);
+        shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
+        shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param);
+
+        /* Fun: The D3DSI_COISSUE flag changes the semantic of the cnd instruction for < 1.4 shaders */
+        if (ins->coissue)
+        {
+            shader_addline(ins->ctx->buffer, "%s /* COISSUE! */);\n", src1_param.param_str);
+        } else {
+            shader_addline(ins->ctx->buffer, "%s > 0.5 ? %s : %s);\n",
+                    src0_param.param_str, src1_param.param_str, src2_param.param_str);
+        }
+        return;
+    }
+
+    shader_glsl_conditional_move(ins);
+}
+
+/** GLSL code generation for WINED3DSIO_MAD: Multiply the first 2 opcodes, then add the last */
+static void shader_glsl_mad(const struct wined3d_shader_instruction *ins)
+{
+    struct glsl_src_param src0_param;
+    struct glsl_src_param src1_param;
+    struct glsl_src_param src2_param;
+    DWORD write_mask;
+
+    write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
+    shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
+    shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param);
+    shader_addline(ins->ctx->buffer, "(%s * %s) + %s);\n",
+            src0_param.param_str, src1_param.param_str, src2_param.param_str);
+}
+
+/* Handles transforming all WINED3DSIO_M?x? opcodes for
+   Vertex shaders to GLSL codes */
+static void shader_glsl_mnxn(const struct wined3d_shader_instruction *ins)
+{
+    int i;
+    int nComponents = 0;
+    struct wined3d_shader_dst_param tmp_dst = {{0}};
+    struct wined3d_shader_src_param tmp_src[2] = {{{0}}};
+    struct wined3d_shader_instruction tmp_ins;
+
+    memset(&tmp_ins, 0, sizeof(tmp_ins));
+
+    /* Set constants for the temporary argument */
+    tmp_ins.ctx = ins->ctx;
+    tmp_ins.dst_count = 1;
+    tmp_ins.dst = &tmp_dst;
+    tmp_ins.src_count = 2;
+    tmp_ins.src = tmp_src;
+
+    switch(ins->handler_idx)
+    {
+        case WINED3DSIH_M4x4:
+            nComponents = 4;
+            tmp_ins.handler_idx = WINED3DSIH_DP4;
+            break;
+        case WINED3DSIH_M4x3:
+            nComponents = 3;
+            tmp_ins.handler_idx = WINED3DSIH_DP4;
+            break;
+        case WINED3DSIH_M3x4:
+            nComponents = 4;
+            tmp_ins.handler_idx = WINED3DSIH_DP3;
+            break;
+        case WINED3DSIH_M3x3:
+            nComponents = 3;
+            tmp_ins.handler_idx = WINED3DSIH_DP3;
+            break;
+        case WINED3DSIH_M3x2:
+            nComponents = 2;
+            tmp_ins.handler_idx = WINED3DSIH_DP3;
+            break;
+        default:
+            break;
+    }
+
+    tmp_dst = ins->dst[0];
+    tmp_src[0] = ins->src[0];
+    tmp_src[1] = ins->src[1];
+    for (i = 0; i < nComponents; ++i)
+    {
+        tmp_dst.write_mask = WINED3DSP_WRITEMASK_0 << i;
+        shader_glsl_dot(&tmp_ins);
+        ++tmp_src[1].reg.idx[0].offset;
+    }
+}
+
+/**
+    The LRP instruction performs a component-wise linear interpolation
+    between the second and third operands using the first operand as the
+    blend factor.  Equation:  (dst = src2 + src0 * (src1 - src2))
+    This is equivalent to mix(src2, src1, src0);
+*/
+static void shader_glsl_lrp(const struct wined3d_shader_instruction *ins)
+{
+    struct glsl_src_param src0_param;
+    struct glsl_src_param src1_param;
+    struct glsl_src_param src2_param;
+    DWORD write_mask;
+
+    write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
+
+    shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
+    shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param);
+
+    shader_addline(ins->ctx->buffer, "mix(%s, %s, %s));\n",
+            src2_param.param_str, src1_param.param_str, src0_param.param_str);
+}
+
+/** Process the WINED3DSIO_LIT instruction in GLSL:
+ * dst.x = dst.w = 1.0
+ * dst.y = (src0.x > 0) ? src0.x
+ * dst.z = (src0.x > 0) ? ((src0.y > 0) ? pow(src0.y, src.w) : 0) : 0
+ *                                        where src.w is clamped at +- 128
+ */
+static void shader_glsl_lit(const struct wined3d_shader_instruction *ins)
+{
+    struct glsl_src_param src0_param;
+    struct glsl_src_param src1_param;
+    struct glsl_src_param src3_param;
+    char dst_mask[6];
+
+    shader_glsl_append_dst(ins->ctx->buffer, ins);
+    shader_glsl_get_write_mask(&ins->dst[0], dst_mask);
+
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_1, &src1_param);
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &src3_param);
+
+    /* The sdk specifies the instruction like this
+     * dst.x = 1.0;
+     * if(src.x > 0.0) dst.y = src.x
+     * else dst.y = 0.0.
+     * if(src.x > 0.0 && src.y > 0.0) dst.z = pow(src.y, power);
+     * else dst.z = 0.0;
+     * dst.w = 1.0;
+     * (where power = src.w clamped between -128 and 128)
+     *
+     * Obviously that has quite a few conditionals in it which we don't like. So the first step is this:
+     * dst.x = 1.0                                  ... No further explanation needed
+     * dst.y = max(src.y, 0.0);                     ... If x < 0.0, use 0.0, otherwise x. Same as the conditional
+     * dst.z = x > 0.0 ? pow(max(y, 0.0), p) : 0;   ... 0 ^ power is 0, and otherwise we use y anyway
+     * dst.w = 1.0.                                 ... Nothing fancy.
+     *
+     * So we still have one conditional in there. So do this:
+     * dst.z = pow(max(0.0, src.y) * step(0.0, src.x), power);
+     *
+     * step(0.0, x) will return 1 if src.x > 0.0, and 0 otherwise. So if y is 0 we get pow(0.0 * 1.0, power),
+     * which sets dst.z to 0. If y > 0, but x = 0.0, we get pow(y * 0.0, power), which results in 0 too.
+     * if both x and y are > 0, we get pow(y * 1.0, power), as it is supposed to.
+     *
+     * Unfortunately pow(0.0 ^ 0.0) returns NaN on most GPUs, but lit with src.y = 0 and src.w = 0 returns
+     * a non-NaN value in dst.z. What we return doesn't matter, as long as it is not NaN. Return 0, which is
+     * what all Windows HW drivers and GL_ARB_vertex_program's LIT do.
+     */
+    shader_addline(ins->ctx->buffer,
+            "vec4(1.0, max(%s, 0.0), %s == 0.0 ? 0.0 : "
+            "pow(max(0.0, %s) * step(0.0, %s), clamp(%s, -128.0, 128.0)), 1.0)%s);\n",
+            src0_param.param_str, src3_param.param_str, src1_param.param_str,
+            src0_param.param_str, src3_param.param_str, dst_mask);
+}
+
+/** Process the WINED3DSIO_DST instruction in GLSL:
+ * dst.x = 1.0
+ * dst.y = src0.x * src0.y
+ * dst.z = src0.z
+ * dst.w = src1.w
+ */
+static void shader_glsl_dst(const struct wined3d_shader_instruction *ins)
+{
+    struct glsl_src_param src0y_param;
+    struct glsl_src_param src0z_param;
+    struct glsl_src_param src1y_param;
+    struct glsl_src_param src1w_param;
+    char dst_mask[6];
+
+    shader_glsl_append_dst(ins->ctx->buffer, ins);
+    shader_glsl_get_write_mask(&ins->dst[0], dst_mask);
+
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_1, &src0y_param);
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_2, &src0z_param);
+    shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_1, &src1y_param);
+    shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_3, &src1w_param);
+
+    shader_addline(ins->ctx->buffer, "vec4(1.0, %s * %s, %s, %s))%s;\n",
+            src0y_param.param_str, src1y_param.param_str, src0z_param.param_str, src1w_param.param_str, dst_mask);
+}
+
+/** Process the WINED3DSIO_SINCOS instruction in GLSL:
+ * VS 2.0 requires that specific cosine and sine constants be passed to this instruction so the hardware
+ * can handle it.  But, these functions are built-in for GLSL, so we can just ignore the last 2 params.
+ *
+ * dst.x = cos(src0.?)
+ * dst.y = sin(src0.?)
+ * dst.z = dst.z
+ * dst.w = dst.w
+ */
+static void shader_glsl_sincos(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    struct glsl_src_param src0_param;
+    DWORD write_mask;
+
+    if (ins->ctx->reg_maps->shader_version.major < 4)
+    {
+        shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param);
+
+        write_mask = shader_glsl_append_dst(buffer, ins);
+        switch (write_mask)
+        {
+            case WINED3DSP_WRITEMASK_0:
+                shader_addline(buffer, "cos(%s));\n", src0_param.param_str);
+                break;
+
+            case WINED3DSP_WRITEMASK_1:
+                shader_addline(buffer, "sin(%s));\n", src0_param.param_str);
+                break;
+
+            case (WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1):
+                shader_addline(buffer, "vec2(cos(%s), sin(%s)));\n",
+                        src0_param.param_str, src0_param.param_str);
+                break;
+
+            default:
+                ERR("Write mask should be .x, .y or .xy\n");
+                break;
+        }
+
+        return;
+    }
+
+    if (ins->dst[0].reg.type != WINED3DSPR_NULL)
+    {
+
+        if (ins->dst[1].reg.type != WINED3DSPR_NULL)
+        {
+            char dst_mask[6];
+
+            write_mask = shader_glsl_get_write_mask(&ins->dst[0], dst_mask);
+            shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
+            shader_addline(buffer, "tmp0%s = sin(%s);\n", dst_mask, src0_param.param_str);
+
+            write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[1]);
+            shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
+            shader_addline(buffer, "cos(%s));\n", src0_param.param_str);
+
+            shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0]);
+            shader_addline(buffer, "tmp0%s);\n", dst_mask);
+        }
+        else
+        {
+            write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0]);
+            shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
+            shader_addline(buffer, "sin(%s));\n", src0_param.param_str);
+        }
+    }
+    else if (ins->dst[1].reg.type != WINED3DSPR_NULL)
+    {
+        write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[1]);
+        shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
+        shader_addline(buffer, "cos(%s));\n", src0_param.param_str);
+    }
+}
+
+/* sgn in vs_2_0 has 2 extra parameters(registers for temporary storage) which we don't use
+ * here. But those extra parameters require a dedicated function for sgn, since map2gl would
+ * generate invalid code
+ */
+static void shader_glsl_sgn(const struct wined3d_shader_instruction *ins)
+{
+    struct glsl_src_param src0_param;
+    DWORD write_mask;
+
+    write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
+    shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
+
+    shader_addline(ins->ctx->buffer, "sign(%s));\n", src0_param.param_str);
+}
+
+/** Process the WINED3DSIO_LOOP instruction in GLSL:
+ * Start a for() loop where src1.y is the initial value of aL,
+ *  increment aL by src1.z for a total of src1.x iterations.
+ *  Need to use a temporary variable for this operation.
+ */
+/* FIXME: I don't think nested loops will work correctly this way. */
+static void shader_glsl_loop(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_loop_state *loop_state = ins->ctx->loop_state;
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    const struct wined3d_shader *shader = ins->ctx->shader;
+    const struct wined3d_shader_lconst *constant;
+    struct glsl_src_param src1_param;
+    const DWORD *control_values = NULL;
+
+    if (ins->ctx->reg_maps->shader_version.major < 4)
+    {
+        shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_ALL, &src1_param);
+
+        /* Try to hardcode the loop control parameters if possible. Direct3D 9
+         * class hardware doesn't support real varying indexing, but Microsoft
+         * designed this feature for Shader model 2.x+. If the loop control is
+         * known at compile time, the GLSL compiler can unroll the loop, and
+         * replace indirect addressing with direct addressing. */
+        if (ins->src[1].reg.type == WINED3DSPR_CONSTINT)
+        {
+            LIST_FOR_EACH_ENTRY(constant, &shader->constantsI, struct wined3d_shader_lconst, entry)
+            {
+                if (constant->idx == ins->src[1].reg.idx[0].offset)
+                {
+                    control_values = constant->value;
+                    break;
+                }
+            }
+        }
+
+        if (control_values)
+        {
+            struct wined3d_shader_loop_control loop_control;
+            loop_control.count = control_values[0];
+            loop_control.start = control_values[1];
+            loop_control.step = (int)control_values[2];
+
+            if (loop_control.step > 0)
+            {
+                shader_addline(buffer, "for (aL%u = %u; aL%u < (%u * %d + %u); aL%u += %d)\n{\n",
+                        loop_state->current_depth, loop_control.start,
+                        loop_state->current_depth, loop_control.count, loop_control.step, loop_control.start,
+                        loop_state->current_depth, loop_control.step);
+            }
+            else if (loop_control.step < 0)
+            {
+                shader_addline(buffer, "for (aL%u = %u; aL%u > (%u * %d + %u); aL%u += %d)\n{\n",
+                        loop_state->current_depth, loop_control.start,
+                        loop_state->current_depth, loop_control.count, loop_control.step, loop_control.start,
+                        loop_state->current_depth, loop_control.step);
+            }
+            else
+            {
+                shader_addline(buffer, "for (aL%u = %u, tmpInt%u = 0; tmpInt%u < %u; tmpInt%u++)\n{\n",
+                        loop_state->current_depth, loop_control.start, loop_state->current_depth,
+                        loop_state->current_depth, loop_control.count,
+                        loop_state->current_depth);
+            }
+        }
+        else
+        {
+            shader_addline(buffer, "for (tmpInt%u = 0, aL%u = %s.y; tmpInt%u < %s.x; tmpInt%u++, aL%u += %s.z)\n{\n",
+                    loop_state->current_depth, loop_state->current_reg,
+                    src1_param.reg_name, loop_state->current_depth, src1_param.reg_name,
+                    loop_state->current_depth, loop_state->current_reg, src1_param.reg_name);
+        }
+
+        ++loop_state->current_reg;
+    }
+    else
+    {
+        shader_addline(buffer, "for (;;)\n{\n");
+    }
+
+    ++loop_state->current_depth;
+}
+
+static void shader_glsl_end(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_loop_state *loop_state = ins->ctx->loop_state;
+
+    shader_addline(ins->ctx->buffer, "}\n");
+
+    if (ins->handler_idx == WINED3DSIH_ENDLOOP)
+    {
+        --loop_state->current_depth;
+        --loop_state->current_reg;
+    }
+
+    if (ins->handler_idx == WINED3DSIH_ENDREP)
+    {
+        --loop_state->current_depth;
+    }
+}
+
+static void shader_glsl_rep(const struct wined3d_shader_instruction *ins)
+{
+    const struct wined3d_shader *shader = ins->ctx->shader;
+    struct wined3d_shader_loop_state *loop_state = ins->ctx->loop_state;
+    const struct wined3d_shader_lconst *constant;
+    struct glsl_src_param src0_param;
+    const DWORD *control_values = NULL;
+
+    /* Try to hardcode local values to help the GLSL compiler to unroll and optimize the loop */
+    if (ins->src[0].reg.type == WINED3DSPR_CONSTINT)
+    {
+        LIST_FOR_EACH_ENTRY(constant, &shader->constantsI, struct wined3d_shader_lconst, entry)
+        {
+            if (constant->idx == ins->src[0].reg.idx[0].offset)
+            {
+                control_values = constant->value;
+                break;
+            }
+        }
+    }
+
+    if (control_values)
+    {
+        shader_addline(ins->ctx->buffer, "for (tmpInt%d = 0; tmpInt%d < %d; tmpInt%d++) {\n",
+                loop_state->current_depth, loop_state->current_depth,
+                control_values[0], loop_state->current_depth);
+    }
+    else
+    {
+        shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param);
+        shader_addline(ins->ctx->buffer, "for (tmpInt%d = 0; tmpInt%d < %s; tmpInt%d++) {\n",
+                loop_state->current_depth, loop_state->current_depth,
+                src0_param.param_str, loop_state->current_depth);
+    }
+
+    ++loop_state->current_depth;
+}
+
+static void shader_glsl_if(const struct wined3d_shader_instruction *ins)
+{
+    struct glsl_src_param src0_param;
+
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param);
+    shader_addline(ins->ctx->buffer, "if (%s) {\n", src0_param.param_str);
+}
+
+static void shader_glsl_ifc(const struct wined3d_shader_instruction *ins)
+{
+    struct glsl_src_param src0_param;
+    struct glsl_src_param src1_param;
+
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0, &src1_param);
+
+    shader_addline(ins->ctx->buffer, "if (%s %s %s) {\n",
+            src0_param.param_str, shader_glsl_get_rel_op(ins->flags), src1_param.param_str);
+}
+
+static void shader_glsl_else(const struct wined3d_shader_instruction *ins)
+{
+    shader_addline(ins->ctx->buffer, "} else {\n");
+}
+
+static void shader_glsl_emit(const struct wined3d_shader_instruction *ins)
+{
+    shader_addline(ins->ctx->buffer, "EmitVertex();\n");
+}
+
+static void shader_glsl_break(const struct wined3d_shader_instruction *ins)
+{
+    shader_addline(ins->ctx->buffer, "break;\n");
+}
+
+/* FIXME: According to MSDN the compare is done per component. */
+static void shader_glsl_breakc(const struct wined3d_shader_instruction *ins)
+{
+    struct glsl_src_param src0_param;
+    struct glsl_src_param src1_param;
+
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0, &src1_param);
+
+    shader_addline(ins->ctx->buffer, "if (%s %s %s) break;\n",
+            src0_param.param_str, shader_glsl_get_rel_op(ins->flags), src1_param.param_str);
+}
+
+static void shader_glsl_breakp(const struct wined3d_shader_instruction *ins)
+{
+    struct glsl_src_param src_param;
+
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src_param);
+    shader_addline(ins->ctx->buffer, "if (bool(%s)) break;\n", src_param.param_str);
+}
+
+static void shader_glsl_label(const struct wined3d_shader_instruction *ins)
+{
+    shader_addline(ins->ctx->buffer, "}\n");
+    shader_addline(ins->ctx->buffer, "void subroutine%u()\n{\n", ins->src[0].reg.idx[0].offset);
+}
+
+static void shader_glsl_call(const struct wined3d_shader_instruction *ins)
+{
+    shader_addline(ins->ctx->buffer, "subroutine%u();\n", ins->src[0].reg.idx[0].offset);
+}
+
+static void shader_glsl_callnz(const struct wined3d_shader_instruction *ins)
+{
+    struct glsl_src_param src1_param;
+
+    shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0, &src1_param);
+    shader_addline(ins->ctx->buffer, "if (%s) subroutine%u();\n",
+            src1_param.param_str, ins->src[0].reg.idx[0].offset);
+}
+
+static void shader_glsl_ret(const struct wined3d_shader_instruction *ins)
+{
+    /* No-op. The closing } is written when a new function is started, and at the end of the shader. This
+     * function only suppresses the unhandled instruction warning
+     */
+}
+
+/*********************************************
+ * Pixel Shader Specific Code begins here
+ ********************************************/
+static void shader_glsl_tex(const struct wined3d_shader_instruction *ins)
+{
+    DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major,
+            ins->ctx->reg_maps->shader_version.minor);
+    struct glsl_sample_function sample_function;
+    DWORD sample_flags = 0;
+    DWORD sampler_idx;
+    DWORD mask = 0, swizzle;
+    const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data;
+
+    /* 1.0-1.4: Use destination register as sampler source.
+     * 2.0+: Use provided sampler source. */
+    if (shader_version < WINED3D_SHADER_VERSION(2,0))
+        sampler_idx = ins->dst[0].reg.idx[0].offset;
+    else
+        sampler_idx = ins->src[1].reg.idx[0].offset;
+
+    if (shader_version < WINED3D_SHADER_VERSION(1,4))
+    {
+        DWORD flags = (priv->cur_ps_args->tex_transform >> sampler_idx * WINED3D_PSARGS_TEXTRANSFORM_SHIFT)
+                & WINED3D_PSARGS_TEXTRANSFORM_MASK;
+        enum wined3d_sampler_texture_type sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx];
+
+        /* Projected cube textures don't make a lot of sense, the resulting coordinates stay the same. */
+        if (flags & WINED3D_PSARGS_PROJECTED && sampler_type != WINED3DSTT_CUBE)
+        {
+            sample_flags |= WINED3D_GLSL_SAMPLE_PROJECTED;
+            switch (flags & ~WINED3D_PSARGS_PROJECTED)
+            {
+                case WINED3D_TTFF_COUNT1:
+                    FIXME("WINED3D_TTFF_PROJECTED with WINED3D_TTFF_COUNT1?\n");
+                    break;
+                case WINED3D_TTFF_COUNT2:
+                    mask = WINED3DSP_WRITEMASK_1;
+                    break;
+                case WINED3D_TTFF_COUNT3:
+                    mask = WINED3DSP_WRITEMASK_2;
+                    break;
+                case WINED3D_TTFF_COUNT4:
+                case WINED3D_TTFF_DISABLE:
+                    mask = WINED3DSP_WRITEMASK_3;
+                    break;
+            }
+        }
+    }
+    else if (shader_version < WINED3D_SHADER_VERSION(2,0))
+    {
+        enum wined3d_shader_src_modifier src_mod = ins->src[0].modifiers;
+
+        if (src_mod == WINED3DSPSM_DZ) {
+            sample_flags |= WINED3D_GLSL_SAMPLE_PROJECTED;
+            mask = WINED3DSP_WRITEMASK_2;
+        } else if (src_mod == WINED3DSPSM_DW) {
+            sample_flags |= WINED3D_GLSL_SAMPLE_PROJECTED;
+            mask = WINED3DSP_WRITEMASK_3;
+        }
+    }
+    else
+    {
+        if ((ins->flags & WINED3DSI_TEXLD_PROJECT)
+                && ins->ctx->reg_maps->sampler_type[sampler_idx] != WINED3DSTT_CUBE)
+        {
+            /* ps 2.0 texldp instruction always divides by the fourth component. */
+            sample_flags |= WINED3D_GLSL_SAMPLE_PROJECTED;
+            mask = WINED3DSP_WRITEMASK_3;
+        }
+    }
+
+    if (priv->cur_ps_args->np2_fixup & (1 << sampler_idx))
+        sample_flags |= WINED3D_GLSL_SAMPLE_NPOT;
+
+    shader_glsl_get_sample_function(ins->ctx, sampler_idx, sample_flags, &sample_function);
+    mask |= sample_function.coord_mask;
+
+    if (shader_version < WINED3D_SHADER_VERSION(2,0)) swizzle = WINED3DSP_NOSWIZZLE;
+    else swizzle = ins->src[1].swizzle;
+
+    /* 1.0-1.3: Use destination register as coordinate source.
+       1.4+: Use provided coordinate source register. */
+    if (shader_version < WINED3D_SHADER_VERSION(1,4))
+    {
+        char coord_mask[6];
+        shader_glsl_write_mask_to_str(mask, coord_mask);
+        shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, swizzle, NULL, NULL, NULL,
+                "T%u%s", sampler_idx, coord_mask);
+    }
+    else
+    {
+        struct glsl_src_param coord_param;
+        shader_glsl_add_src_param(ins, &ins->src[0], mask, &coord_param);
+        if (ins->flags & WINED3DSI_TEXLD_BIAS)
+        {
+            struct glsl_src_param bias;
+            shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &bias);
+            shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, swizzle, NULL, NULL, bias.param_str,
+                    "%s", coord_param.param_str);
+        } else {
+            shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, swizzle, NULL, NULL, NULL,
+                    "%s", coord_param.param_str);
+        }
+    }
+}
+
+static void shader_glsl_texldd(const struct wined3d_shader_instruction *ins)
+{
+    const struct wined3d_gl_info *gl_info = ins->ctx->gl_info;
+    struct glsl_src_param coord_param, dx_param, dy_param;
+    DWORD sample_flags = WINED3D_GLSL_SAMPLE_GRAD;
+    struct glsl_sample_function sample_function;
+    DWORD sampler_idx;
+    DWORD swizzle = ins->src[1].swizzle;
+    const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data;
+
+    if (!gl_info->supported[ARB_SHADER_TEXTURE_LOD] && !gl_info->supported[EXT_GPU_SHADER4])
+    {
+        FIXME("texldd used, but not supported by hardware. Falling back to regular tex\n");
+        shader_glsl_tex(ins);
+        return;
+    }
+
+    sampler_idx = ins->src[1].reg.idx[0].offset;
+    if (priv->cur_ps_args->np2_fixup & (1 << sampler_idx))
+        sample_flags |= WINED3D_GLSL_SAMPLE_NPOT;
+
+    shader_glsl_get_sample_function(ins->ctx, sampler_idx, sample_flags, &sample_function);
+    shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &coord_param);
+    shader_glsl_add_src_param(ins, &ins->src[2], sample_function.coord_mask, &dx_param);
+    shader_glsl_add_src_param(ins, &ins->src[3], sample_function.coord_mask, &dy_param);
+
+    shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, swizzle, dx_param.param_str, dy_param.param_str, NULL,
+                                "%s", coord_param.param_str);
+}
+
+static void shader_glsl_texldl(const struct wined3d_shader_instruction *ins)
+{
+    const struct wined3d_gl_info *gl_info = ins->ctx->gl_info;
+    struct glsl_src_param coord_param, lod_param;
+    DWORD sample_flags = WINED3D_GLSL_SAMPLE_LOD;
+    struct glsl_sample_function sample_function;
+    DWORD sampler_idx;
+    DWORD swizzle = ins->src[1].swizzle;
+    const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data;
+
+    sampler_idx = ins->src[1].reg.idx[0].offset;
+    if (ins->ctx->reg_maps->shader_version.type == WINED3D_SHADER_TYPE_PIXEL
+            && priv->cur_ps_args->np2_fixup & (1 << sampler_idx))
+        sample_flags |= WINED3D_GLSL_SAMPLE_NPOT;
+
+    shader_glsl_get_sample_function(ins->ctx, sampler_idx, sample_flags, &sample_function);
+    shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &coord_param);
+
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &lod_param);
+
+    if (!gl_info->supported[ARB_SHADER_TEXTURE_LOD] && !gl_info->supported[EXT_GPU_SHADER4]
+            && ins->ctx->reg_maps->shader_version.type == WINED3D_SHADER_TYPE_PIXEL)
+    {
+        /* Plain GLSL only supports Lod sampling functions in vertex shaders.
+         * However, the NVIDIA drivers allow them in fragment shaders as well,
+         * even without the appropriate extension. */
+        WARN("Using %s in fragment shader.\n", sample_function.name);
+    }
+    shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, swizzle, NULL, NULL, lod_param.param_str,
+            "%s", coord_param.param_str);
+}
+
+static void shader_glsl_texcoord(const struct wined3d_shader_instruction *ins)
+{
+    /* FIXME: Make this work for more than just 2D textures */
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    DWORD write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
+
+    if (!(ins->ctx->reg_maps->shader_version.major == 1 && ins->ctx->reg_maps->shader_version.minor == 4))
+    {
+        char dst_mask[6];
+
+        shader_glsl_get_write_mask(&ins->dst[0], dst_mask);
+        shader_addline(buffer, "clamp(gl_TexCoord[%u], 0.0, 1.0)%s);\n",
+                ins->dst[0].reg.idx[0].offset, dst_mask);
+    }
+    else
+    {
+        enum wined3d_shader_src_modifier src_mod = ins->src[0].modifiers;
+        DWORD reg = ins->src[0].reg.idx[0].offset;
+        char dst_swizzle[6];
+
+        shader_glsl_get_swizzle(&ins->src[0], FALSE, write_mask, dst_swizzle);
+
+        if (src_mod == WINED3DSPSM_DZ)
+        {
+            unsigned int mask_size = shader_glsl_get_write_mask_size(write_mask);
+            struct glsl_src_param div_param;
+
+            shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_2, &div_param);
+
+            if (mask_size > 1) {
+                shader_addline(buffer, "gl_TexCoord[%u]%s / vec%d(%s));\n", reg, dst_swizzle, mask_size, div_param.param_str);
+            } else {
+                shader_addline(buffer, "gl_TexCoord[%u]%s / %s);\n", reg, dst_swizzle, div_param.param_str);
+            }
+        }
+        else if (src_mod == WINED3DSPSM_DW)
+        {
+            unsigned int mask_size = shader_glsl_get_write_mask_size(write_mask);
+            struct glsl_src_param div_param;
+
+            shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &div_param);
+
+            if (mask_size > 1) {
+                shader_addline(buffer, "gl_TexCoord[%u]%s / vec%d(%s));\n", reg, dst_swizzle, mask_size, div_param.param_str);
+            } else {
+                shader_addline(buffer, "gl_TexCoord[%u]%s / %s);\n", reg, dst_swizzle, div_param.param_str);
+            }
+        } else {
+            shader_addline(buffer, "gl_TexCoord[%u]%s);\n", reg, dst_swizzle);
+        }
+    }
+}
+
+/** Process the WINED3DSIO_TEXDP3TEX instruction in GLSL:
+ * Take a 3-component dot product of the TexCoord[dstreg] and src,
+ * then perform a 1D texture lookup from stage dstregnum, place into dst. */
+static void shader_glsl_texdp3tex(const struct wined3d_shader_instruction *ins)
+{
+    DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
+    DWORD sampler_idx = ins->dst[0].reg.idx[0].offset;
+    struct glsl_sample_function sample_function;
+    struct glsl_src_param src0_param;
+    UINT mask_size;
+
+    shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
+
+    /* Do I have to take care about the projected bit? I don't think so, since the dp3 returns only one
+     * scalar, and projected sampling would require 4.
+     *
+     * It is a dependent read - not valid with conditional NP2 textures
+     */
+    shader_glsl_get_sample_function(ins->ctx, sampler_idx, 0, &sample_function);
+    mask_size = shader_glsl_get_write_mask_size(sample_function.coord_mask);
+
+    switch(mask_size)
+    {
+        case 1:
+            shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL,
+                    "dot(gl_TexCoord[%u].xyz, %s)", sampler_idx, src0_param.param_str);
+            break;
+
+        case 2:
+            shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL,
+                    "vec2(dot(gl_TexCoord[%u].xyz, %s), 0.0)", sampler_idx, src0_param.param_str);
+            break;
+
+        case 3:
+            shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL,
+                    "vec3(dot(gl_TexCoord[%u].xyz, %s), 0.0, 0.0)", sampler_idx, src0_param.param_str);
+            break;
+
+        default:
+            FIXME("Unexpected mask size %u\n", mask_size);
+            break;
+    }
+}
+
+/** Process the WINED3DSIO_TEXDP3 instruction in GLSL:
+ * Take a 3-component dot product of the TexCoord[dstreg] and src. */
+static void shader_glsl_texdp3(const struct wined3d_shader_instruction *ins)
+{
+    DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
+    DWORD dstreg = ins->dst[0].reg.idx[0].offset;
+    struct glsl_src_param src0_param;
+    DWORD dst_mask;
+    unsigned int mask_size;
+
+    dst_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
+    mask_size = shader_glsl_get_write_mask_size(dst_mask);
+    shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
+
+    if (mask_size > 1) {
+        shader_addline(ins->ctx->buffer, "vec%d(dot(T%u.xyz, %s)));\n", mask_size, dstreg, src0_param.param_str);
+    } else {
+        shader_addline(ins->ctx->buffer, "dot(T%u.xyz, %s));\n", dstreg, src0_param.param_str);
+    }
+}
+
+/** Process the WINED3DSIO_TEXDEPTH instruction in GLSL:
+ * Calculate the depth as dst.x / dst.y   */
+static void shader_glsl_texdepth(const struct wined3d_shader_instruction *ins)
+{
+    struct glsl_dst_param dst_param;
+
+    shader_glsl_add_dst_param(ins, &ins->dst[0], &dst_param);
+
+    /* Tests show that texdepth never returns anything below 0.0, and that r5.y is clamped to 1.0.
+     * Negative input is accepted, -0.25 / -0.5 returns 0.5. GL should clamp gl_FragDepth to [0;1], but
+     * this doesn't always work, so clamp the results manually. Whether or not the x value is clamped at 1
+     * too is irrelevant, since if x = 0, any y value < 1.0 (and > 1.0 is not allowed) results in a result
+     * >= 1.0 or < 0.0
+     */
+    shader_addline(ins->ctx->buffer, "gl_FragDepth = clamp((%s.x / min(%s.y, 1.0)), 0.0, 1.0);\n",
+            dst_param.reg_name, dst_param.reg_name);
+}
+
+/** Process the WINED3DSIO_TEXM3X2DEPTH instruction in GLSL:
+ * Last row of a 3x2 matrix multiply, use the result to calculate the depth:
+ * Calculate tmp0.y = TexCoord[dstreg] . src.xyz;  (tmp0.x has already been calculated)
+ * depth = (tmp0.y == 0.0) ? 1.0 : tmp0.x / tmp0.y
+ */
+static void shader_glsl_texm3x2depth(const struct wined3d_shader_instruction *ins)
+{
+    DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
+    DWORD dstreg = ins->dst[0].reg.idx[0].offset;
+    struct glsl_src_param src0_param;
+
+    shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
+
+    shader_addline(ins->ctx->buffer, "tmp0.y = dot(T%u.xyz, %s);\n", dstreg, src0_param.param_str);
+    shader_addline(ins->ctx->buffer, "gl_FragDepth = (tmp0.y == 0.0) ? 1.0 : clamp(tmp0.x / tmp0.y, 0.0, 1.0);\n");
+}
+
+/** Process the WINED3DSIO_TEXM3X2PAD instruction in GLSL
+ * Calculate the 1st of a 2-row matrix multiplication. */
+static void shader_glsl_texm3x2pad(const struct wined3d_shader_instruction *ins)
+{
+    DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
+    DWORD reg = ins->dst[0].reg.idx[0].offset;
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    struct glsl_src_param src0_param;
+
+    shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
+    shader_addline(buffer, "tmp0.x = dot(T%u.xyz, %s);\n", reg, src0_param.param_str);
+}
+
+/** Process the WINED3DSIO_TEXM3X3PAD instruction in GLSL
+ * Calculate the 1st or 2nd row of a 3-row matrix multiplication. */
+static void shader_glsl_texm3x3pad(const struct wined3d_shader_instruction *ins)
+{
+    DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    struct wined3d_shader_tex_mx *tex_mx = ins->ctx->tex_mx;
+    DWORD reg = ins->dst[0].reg.idx[0].offset;
+    struct glsl_src_param src0_param;
+
+    shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
+    shader_addline(buffer, "tmp0.%c = dot(T%u.xyz, %s);\n", 'x' + tex_mx->current_row, reg, src0_param.param_str);
+    tex_mx->texcoord_w[tex_mx->current_row++] = reg;
+}
+
+static void shader_glsl_texm3x2tex(const struct wined3d_shader_instruction *ins)
+{
+    DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    struct glsl_sample_function sample_function;
+    DWORD reg = ins->dst[0].reg.idx[0].offset;
+    struct glsl_src_param src0_param;
+
+    shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
+    shader_addline(buffer, "tmp0.y = dot(T%u.xyz, %s);\n", reg, src0_param.param_str);
+
+    shader_glsl_get_sample_function(ins->ctx, reg, 0, &sample_function);
+
+    /* Sample the texture using the calculated coordinates */
+    shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, "tmp0.xy");
+}
+
+/** Process the WINED3DSIO_TEXM3X3TEX instruction in GLSL
+ * Perform the 3rd row of a 3x3 matrix multiply, then sample the texture using the calculated coordinates */
+static void shader_glsl_texm3x3tex(const struct wined3d_shader_instruction *ins)
+{
+    DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
+    struct wined3d_shader_tex_mx *tex_mx = ins->ctx->tex_mx;
+    struct glsl_sample_function sample_function;
+    DWORD reg = ins->dst[0].reg.idx[0].offset;
+    struct glsl_src_param src0_param;
+
+    shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
+    shader_addline(ins->ctx->buffer, "tmp0.z = dot(T%u.xyz, %s);\n", reg, src0_param.param_str);
+
+    /* Dependent read, not valid with conditional NP2 */
+    shader_glsl_get_sample_function(ins->ctx, reg, 0, &sample_function);
+
+    /* Sample the texture using the calculated coordinates */
+    shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, "tmp0.xyz");
+
+    tex_mx->current_row = 0;
+}
+
+/** Process the WINED3DSIO_TEXM3X3 instruction in GLSL
+ * Perform the 3rd row of a 3x3 matrix multiply */
+static void shader_glsl_texm3x3(const struct wined3d_shader_instruction *ins)
+{
+    DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
+    struct wined3d_shader_tex_mx *tex_mx = ins->ctx->tex_mx;
+    DWORD reg = ins->dst[0].reg.idx[0].offset;
+    struct glsl_src_param src0_param;
+    char dst_mask[6];
+
+    shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
+
+    shader_glsl_append_dst(ins->ctx->buffer, ins);
+    shader_glsl_get_write_mask(&ins->dst[0], dst_mask);
+    shader_addline(ins->ctx->buffer, "vec4(tmp0.xy, dot(T%u.xyz, %s), 1.0)%s);\n", reg, src0_param.param_str, dst_mask);
+
+    tex_mx->current_row = 0;
+}
+
+/* Process the WINED3DSIO_TEXM3X3SPEC instruction in GLSL
+ * Perform the final texture lookup based on the previous 2 3x3 matrix multiplies */
+static void shader_glsl_texm3x3spec(const struct wined3d_shader_instruction *ins)
+{
+    struct glsl_src_param src0_param;
+    struct glsl_src_param src1_param;
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    struct wined3d_shader_tex_mx *tex_mx = ins->ctx->tex_mx;
+    DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
+    struct glsl_sample_function sample_function;
+    DWORD reg = ins->dst[0].reg.idx[0].offset;
+    char coord_mask[6];
+
+    shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[1], src_mask, &src1_param);
+
+    /* Perform the last matrix multiply operation */
+    shader_addline(buffer, "tmp0.z = dot(T%u.xyz, %s);\n", reg, src0_param.param_str);
+    /* Reflection calculation */
+    shader_addline(buffer, "tmp0.xyz = -reflect((%s), normalize(tmp0.xyz));\n", src1_param.param_str);
+
+    /* Dependent read, not valid with conditional NP2 */
+    shader_glsl_get_sample_function(ins->ctx, reg, 0, &sample_function);
+    shader_glsl_write_mask_to_str(sample_function.coord_mask, coord_mask);
+
+    /* Sample the texture */
+    shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE,
+            NULL, NULL, NULL, "tmp0%s", coord_mask);
+
+    tex_mx->current_row = 0;
+}
+
+/* Process the WINED3DSIO_TEXM3X3VSPEC instruction in GLSL
+ * Perform the final texture lookup based on the previous 2 3x3 matrix multiplies */
+static void shader_glsl_texm3x3vspec(const struct wined3d_shader_instruction *ins)
+{
+    struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
+    struct wined3d_shader_tex_mx *tex_mx = ins->ctx->tex_mx;
+    DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
+    struct glsl_sample_function sample_function;
+    DWORD reg = ins->dst[0].reg.idx[0].offset;
+    struct glsl_src_param src0_param;
+    char coord_mask[6];
+
+    shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
+
+    /* Perform the last matrix multiply operation */
+    shader_addline(buffer, "tmp0.z = dot(vec3(T%u), vec3(%s));\n", reg, src0_param.param_str);
+
+    /* Construct the eye-ray vector from w coordinates */
+    shader_addline(buffer, "tmp1.xyz = normalize(vec3(gl_TexCoord[%u].w, gl_TexCoord[%u].w, gl_TexCoord[%u].w));\n",
+            tex_mx->texcoord_w[0], tex_mx->texcoord_w[1], reg);
+    shader_addline(buffer, "tmp0.xyz = -reflect(tmp1.xyz, normalize(tmp0.xyz));\n");
+
+    /* Dependent read, not valid with conditional NP2 */
+    shader_glsl_get_sample_function(ins->ctx, reg, 0, &sample_function);
+    shader_glsl_write_mask_to_str(sample_function.coord_mask, coord_mask);
+
+    /* Sample the texture using the calculated coordinates */
+    shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE,
+            NULL, NULL, NULL, "tmp0%s", coord_mask);
+
+    tex_mx->current_row = 0;
+}
+
+/** Process the WINED3DSIO_TEXBEM instruction in GLSL.
+ * Apply a fake bump map transform.
+ * texbem is pshader <= 1.3 only, this saves a few version checks
+ */
+static void shader_glsl_texbem(const struct wined3d_shader_instruction *ins)
+{
+    const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data;
+    struct glsl_sample_function sample_function;
+    struct glsl_src_param coord_param;
+    DWORD sampler_idx;
+    DWORD mask;
+    DWORD flags;
+    char coord_mask[6];
+
+    sampler_idx = ins->dst[0].reg.idx[0].offset;
+    flags = (priv->cur_ps_args->tex_transform >> sampler_idx * WINED3D_PSARGS_TEXTRANSFORM_SHIFT)
+            & WINED3D_PSARGS_TEXTRANSFORM_MASK;
+
+    /* Dependent read, not valid with conditional NP2 */
+    shader_glsl_get_sample_function(ins->ctx, sampler_idx, 0, &sample_function);
+    mask = sample_function.coord_mask;
+
+    shader_glsl_write_mask_to_str(mask, coord_mask);
+
+    /* With projected textures, texbem only divides the static texture coord,
+     * not the displacement, so we can't let GL handle this. */
+    if (flags & WINED3D_PSARGS_PROJECTED)
+    {
+        DWORD div_mask=0;
+        char coord_div_mask[3];
+        switch (flags & ~WINED3D_PSARGS_PROJECTED)
+        {
+            case WINED3D_TTFF_COUNT1:
+                FIXME("WINED3D_TTFF_PROJECTED with WINED3D_TTFF_COUNT1?\n");
+                break;
+            case WINED3D_TTFF_COUNT2:
+                div_mask = WINED3DSP_WRITEMASK_1;
+                break;
+            case WINED3D_TTFF_COUNT3:
+                div_mask = WINED3DSP_WRITEMASK_2;
+                break;
+            case WINED3D_TTFF_COUNT4:
+            case WINED3D_TTFF_DISABLE:
+                div_mask = WINED3DSP_WRITEMASK_3;
+                break;
+        }
+        shader_glsl_write_mask_to_str(div_mask, coord_div_mask);
+        shader_addline(ins->ctx->buffer, "T%u%s /= T%u%s;\n", sampler_idx, coord_mask, sampler_idx, coord_div_mask);
+    }
+
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &coord_param);
+
+    shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL,
+            "T%u%s + vec4(bumpenv_mat%u * %s, 0.0, 0.0)%s", sampler_idx, coord_mask, sampler_idx,
+            coord_param.param_str, coord_mask);
+
+    if (ins->handler_idx == WINED3DSIH_TEXBEML)
+    {
+        struct glsl_src_param luminance_param;
+        struct glsl_dst_param dst_param;
+
+        shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_2, &luminance_param);
+        shader_glsl_add_dst_param(ins, &ins->dst[0], &dst_param);
+
+        shader_addline(ins->ctx->buffer, "%s%s *= (%s * bumpenv_lum_scale%u + bumpenv_lum_offset%u);\n",
+                dst_param.reg_name, dst_param.mask_str,
+                luminance_param.param_str, sampler_idx, sampler_idx);
+    }
+}
+
+static void shader_glsl_bem(const struct wined3d_shader_instruction *ins)
+{
+    DWORD sampler_idx = ins->dst[0].reg.idx[0].offset;
+    struct glsl_src_param src0_param, src1_param;
+
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &src1_param);
+
+    shader_glsl_append_dst(ins->ctx->buffer, ins);
+    shader_addline(ins->ctx->buffer, "%s + bumpenv_mat%u * %s);\n",
+            src0_param.param_str, sampler_idx, src1_param.param_str);
+}
+
+/** Process the WINED3DSIO_TEXREG2AR instruction in GLSL
+ * Sample 2D texture at dst using the alpha & red (wx) components of src as texture coordinates */
+static void shader_glsl_texreg2ar(const struct wined3d_shader_instruction *ins)
+{
+    DWORD sampler_idx = ins->dst[0].reg.idx[0].offset;
+    struct glsl_sample_function sample_function;
+    struct glsl_src_param src0_param;
+
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_ALL, &src0_param);
+
+    shader_glsl_get_sample_function(ins->ctx, sampler_idx, 0, &sample_function);
+    shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL,
+            "%s.wx", src0_param.reg_name);
+}
+
+/** Process the WINED3DSIO_TEXREG2GB instruction in GLSL
+ * Sample 2D texture at dst using the green & blue (yz) components of src as texture coordinates */
+static void shader_glsl_texreg2gb(const struct wined3d_shader_instruction *ins)
+{
+    DWORD sampler_idx = ins->dst[0].reg.idx[0].offset;
+    struct glsl_sample_function sample_function;
+    struct glsl_src_param src0_param;
+
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_ALL, &src0_param);
+
+    shader_glsl_get_sample_function(ins->ctx, sampler_idx, 0, &sample_function);
+    shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL,
+            "%s.yz", src0_param.reg_name);
+}
+
+/** Process the WINED3DSIO_TEXREG2RGB instruction in GLSL
+ * Sample texture at dst using the rgb (xyz) components of src as texture coordinates */
+static void shader_glsl_texreg2rgb(const struct wined3d_shader_instruction *ins)
+{
+    DWORD sampler_idx = ins->dst[0].reg.idx[0].offset;
+    struct glsl_sample_function sample_function;
+    struct glsl_src_param src0_param;
+
+    /* Dependent read, not valid with conditional NP2 */
+    shader_glsl_get_sample_function(ins->ctx, sampler_idx, 0, &sample_function);
+    shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &src0_param);
+
+    shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL,
+            "%s", src0_param.param_str);
+}
+
+/** Process the WINED3DSIO_TEXKILL instruction in GLSL.
+ * If any of the first 3 components are < 0, discard this pixel */
+static void shader_glsl_texkill(const struct wined3d_shader_instruction *ins)
+{
+    struct glsl_dst_param dst_param;
+
+    /* The argument is a destination parameter, and no writemasks are allowed */
+    shader_glsl_add_dst_param(ins, &ins->dst[0], &dst_param);
+    if (ins->ctx->reg_maps->shader_version.major >= 2)
+    {
+        /* 2.0 shaders compare all 4 components in texkill */
+        shader_addline(ins->ctx->buffer, "if (any(lessThan(%s.xyzw, vec4(0.0)))) discard;\n", dst_param.reg_name);
+    } else {
+        /* 1.X shaders only compare the first 3 components, probably due to the nature of the texkill
+         * instruction as a tex* instruction, and phase, which kills all a / w components. Even if all
+         * 4 components are defined, only the first 3 are used
+         */
+        shader_addline(ins->ctx->buffer, "if (any(lessThan(%s.xyz, vec3(0.0)))) discard;\n", dst_param.reg_name);
+    }
+}
+
+/** Process the WINED3DSIO_DP2ADD instruction in GLSL.
+ * dst = dot2(src0, src1) + src2 */
+static void shader_glsl_dp2add(const struct wined3d_shader_instruction *ins)
+{
+    struct glsl_src_param src0_param;
+    struct glsl_src_param src1_param;
+    struct glsl_src_param src2_param;
+    DWORD write_mask;
+    unsigned int mask_size;
+
+    write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
+    mask_size = shader_glsl_get_write_mask_size(write_mask);
+
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &src1_param);
+    shader_glsl_add_src_param(ins, &ins->src[2], WINED3DSP_WRITEMASK_0, &src2_param);
+
+    if (mask_size > 1) {
+        shader_addline(ins->ctx->buffer, "vec%d(dot(%s, %s) + %s));\n",
+                mask_size, src0_param.param_str, src1_param.param_str, src2_param.param_str);
+    } else {
+        shader_addline(ins->ctx->buffer, "dot(%s, %s) + %s);\n",
+                src0_param.param_str, src1_param.param_str, src2_param.param_str);
+    }
+}
+
+static void shader_glsl_input_pack(const struct wined3d_shader *shader, struct wined3d_shader_buffer *buffer,
+        const struct wined3d_shader_signature_element *input_signature,
+        const struct wined3d_shader_reg_maps *reg_maps,
+        enum vertexprocessing_mode vertexprocessing)
+{
+    WORD map = reg_maps->input_registers;
+    unsigned int i;
+
+    for (i = 0; map; map >>= 1, ++i)
+    {
+        const char *semantic_name;
+        UINT semantic_idx;
+        char reg_mask[6];
+
+        /* Unused */
+        if (!(map & 1)) continue;
+
+        semantic_name = input_signature[i].semantic_name;
+        semantic_idx = input_signature[i].semantic_idx;
+        shader_glsl_write_mask_to_str(input_signature[i].mask, reg_mask);
+
+        if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_TEXCOORD))
+        {
+            if (semantic_idx < 8 && vertexprocessing == pretransformed)
+                shader_addline(buffer, "ps_in[%u]%s = gl_TexCoord[%u]%s;\n",
+                        shader->u.ps.input_reg_map[i], reg_mask, semantic_idx, reg_mask);
+            else
+                shader_addline(buffer, "ps_in[%u]%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n",
+                        shader->u.ps.input_reg_map[i], reg_mask, reg_mask);
+        }
+        else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_COLOR))
+        {
+            if (!semantic_idx)
+                shader_addline(buffer, "ps_in[%u]%s = vec4(gl_Color)%s;\n",
+                        shader->u.ps.input_reg_map[i], reg_mask, reg_mask);
+            else if (semantic_idx == 1)
+                shader_addline(buffer, "ps_in[%u]%s = vec4(gl_SecondaryColor)%s;\n",
+                        shader->u.ps.input_reg_map[i], reg_mask, reg_mask);
+            else
+                shader_addline(buffer, "ps_in[%u]%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n",
+                        shader->u.ps.input_reg_map[i], reg_mask, reg_mask);
+        }
+        else
+        {
+            shader_addline(buffer, "ps_in[%u]%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n",
+                    shader->u.ps.input_reg_map[i], reg_mask, reg_mask);
+        }
+    }
+}
+
+/*********************************************
+ * Vertex Shader Specific Code begins here
+ ********************************************/
+
+static void add_glsl_program_entry(struct shader_glsl_priv *priv, struct glsl_shader_prog_link *entry)
+{
+    struct glsl_program_key key;
+
+    key.vs_id = entry->vs.id;
+    key.gs_id = entry->gs.id;
+    key.ps_id = entry->ps.id;
+
+    if (wine_rb_put(&priv->program_lookup, &key, &entry->program_lookup_entry) == -1)
+    {
+        ERR("Failed to insert program entry.\n");
+    }
+}
+
+static struct glsl_shader_prog_link *get_glsl_program_entry(const struct shader_glsl_priv *priv,
+        GLhandleARB vs_id, GLhandleARB gs_id, GLhandleARB ps_id)
+{
+    struct wine_rb_entry *entry;
+    struct glsl_program_key key;
+
+    key.vs_id = vs_id;
+    key.gs_id = gs_id;
+    key.ps_id = ps_id;
+
+    entry = wine_rb_get(&priv->program_lookup, &key);
+    return entry ? WINE_RB_ENTRY_VALUE(entry, struct glsl_shader_prog_link, program_lookup_entry) : NULL;
+}
+
+/* Context activation is done by the caller. */
+static void delete_glsl_program_entry(struct shader_glsl_priv *priv, const struct wined3d_gl_info *gl_info,
+        struct glsl_shader_prog_link *entry)
+{
+    struct glsl_program_key key;
+
+    key.vs_id = entry->vs.id;
+    key.gs_id = entry->gs.id;
+    key.ps_id = entry->ps.id;
+    wine_rb_remove(&priv->program_lookup, &key);
+
+    GL_EXTCALL(glDeleteObjectARB(entry->programId));
+    if (entry->vs.id)
+        list_remove(&entry->vs.shader_entry);
+    if (entry->gs.id)
+        list_remove(&entry->gs.shader_entry);
+    if (entry->ps.id)
+        list_remove(&entry->ps.shader_entry);
+    HeapFree(GetProcessHeap(), 0, entry->vs.uniform_f_locations);
+    HeapFree(GetProcessHeap(), 0, entry->ps.uniform_f_locations);
+    HeapFree(GetProcessHeap(), 0, entry);
+}
+
+static void handle_ps3_input(struct wined3d_shader_buffer *buffer,
+        const struct wined3d_gl_info *gl_info, const DWORD *map,
+        const struct wined3d_shader_signature_element *input_signature,
+        const struct wined3d_shader_reg_maps *reg_maps_in,
+        const struct wined3d_shader_signature_element *output_signature,
+        const struct wined3d_shader_reg_maps *reg_maps_out)
+{
+    unsigned int i, j;
+    const char *semantic_name_in;
+    UINT semantic_idx_in;
+    DWORD *set;
+    DWORD in_idx;
+    unsigned int in_count = vec4_varyings(3, gl_info);
+    char reg_mask[6];
+    char destination[50];
+    WORD input_map, output_map;
+
+    set = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*set) * (in_count + 2));
+
+    input_map = reg_maps_in->input_registers;
+    for (i = 0; input_map; input_map >>= 1, ++i)
+    {
+        if (!(input_map & 1)) continue;
+
+        in_idx = map[i];
+        /* Declared, but not read register */
+        if (in_idx == ~0U) continue;
+        if (in_idx >= (in_count + 2))
+        {
+            FIXME("More input varyings declared than supported, expect issues.\n");
+            continue;
+        }
+
+        if (in_idx == in_count)
+            sprintf(destination, "gl_FrontColor");
+        else if (in_idx == in_count + 1)
+            sprintf(destination, "gl_FrontSecondaryColor");
+        else
+            sprintf(destination, "ps_in[%u]", in_idx);
+
+        semantic_name_in = input_signature[i].semantic_name;
+        semantic_idx_in = input_signature[i].semantic_idx;
+        set[in_idx] = ~0U;
+
+        output_map = reg_maps_out->output_registers;
+        for (j = 0; output_map; output_map >>= 1, ++j)
+        {
+            DWORD mask;
+
+            if (!(output_map & 1)
+                    || semantic_idx_in != output_signature[j].semantic_idx
+                    || strcmp(semantic_name_in, output_signature[j].semantic_name)
+                    || !(mask = input_signature[i].mask & output_signature[j].mask))
+                continue;
+
+            set[in_idx] = mask;
+            shader_glsl_write_mask_to_str(mask, reg_mask);
+
+            shader_addline(buffer, "%s%s = vs_out[%u]%s;\n",
+                    destination, reg_mask, j, reg_mask);
+        }
+    }
+
+    for (i = 0; i < in_count + 2; ++i)
+    {
+        unsigned int size;
+
+        if (!set[i] || set[i] == WINED3DSP_WRITEMASK_ALL)
+            continue;
+
+        if (set[i] == ~0U) set[i] = 0;
+
+        size = 0;
+        if (!(set[i] & WINED3DSP_WRITEMASK_0)) reg_mask[size++] = 'x';
+        if (!(set[i] & WINED3DSP_WRITEMASK_1)) reg_mask[size++] = 'y';
+        if (!(set[i] & WINED3DSP_WRITEMASK_2)) reg_mask[size++] = 'z';
+        if (!(set[i] & WINED3DSP_WRITEMASK_3)) reg_mask[size++] = 'w';
+        reg_mask[size] = '\0';
+
+        if (i == in_count)
+            sprintf(destination, "gl_FrontColor");
+        else if (i == in_count + 1)
+            sprintf(destination, "gl_FrontSecondaryColor");
+        else
+            sprintf(destination, "ps_in[%u]", i);
+
+        if (size == 1) shader_addline(buffer, "%s.%s = 0.0;\n", destination, reg_mask);
+        else shader_addline(buffer, "%s.%s = vec%u(0.0);\n", destination, reg_mask, size);
+    }
+
+    HeapFree(GetProcessHeap(), 0, set);
+}
+
+/* Context activation is done by the caller. */
+static GLhandleARB generate_param_reorder_function(struct wined3d_shader_buffer *buffer,
+        const struct wined3d_shader *vs, const struct wined3d_shader *ps,
+        const struct wined3d_gl_info *gl_info)
+{
+    GLhandleARB ret = 0;
+    DWORD ps_major = ps ? ps->reg_maps.shader_version.major : 0;
+    unsigned int i;
+    const char *semantic_name;
+    UINT semantic_idx;
+    char reg_mask[6];
+    const struct wined3d_shader_signature_element *output_signature = vs->output_signature;
+    WORD map = vs->reg_maps.output_registers;
+
+    shader_buffer_clear(buffer);
+
+    shader_addline(buffer, "#version 120\n");
+
+    if (ps_major < 3)
+    {
+        shader_addline(buffer, "void order_ps_input(in vec4 vs_out[%u])\n{\n", vs->limits.packed_output);
+
+        for (i = 0; map; map >>= 1, ++i)
+        {
+            DWORD write_mask;
+
+            if (!(map & 1)) continue;
+
+            semantic_name = output_signature[i].semantic_name;
+            semantic_idx = output_signature[i].semantic_idx;
+            write_mask = output_signature[i].mask;
+            shader_glsl_write_mask_to_str(write_mask, reg_mask);
+
+            if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_COLOR))
+            {
+                if (!semantic_idx)
+                    shader_addline(buffer, "gl_FrontColor%s = vs_out[%u]%s;\n",
+                            reg_mask, i, reg_mask);
+                else if (semantic_idx == 1)
+                    shader_addline(buffer, "gl_FrontSecondaryColor%s = vs_out[%u]%s;\n",
+                            reg_mask, i, reg_mask);
+            }
+            else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_POSITION))
+            {
+                shader_addline(buffer, "gl_Position%s = vs_out[%u]%s;\n",
+                        reg_mask, i, reg_mask);
+            }
+            else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_TEXCOORD))
+            {
+                if (semantic_idx < 8)
+                {
+                    if (!(gl_info->quirks & WINED3D_QUIRK_SET_TEXCOORD_W) || ps_major > 0)
+                        write_mask |= WINED3DSP_WRITEMASK_3;
+
+                    shader_addline(buffer, "gl_TexCoord[%u]%s = vs_out[%u]%s;\n",
+                            semantic_idx, reg_mask, i, reg_mask);
+                    if (!(write_mask & WINED3DSP_WRITEMASK_3))
+                        shader_addline(buffer, "gl_TexCoord[%u].w = 1.0;\n", semantic_idx);
+                }
+            }
+            else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_PSIZE))
+            {
+                shader_addline(buffer, "gl_PointSize = vs_out[%u].%c;\n", i, reg_mask[1]);
+            }
+            else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_FOG))
+            {
+                shader_addline(buffer, "gl_FogFragCoord = clamp(vs_out[%u].%c, 0.0, 1.0);\n", i, reg_mask[1]);
+            }
+        }
+        shader_addline(buffer, "}\n");
+    }
+    else
+    {
+        UINT in_count = min(vec4_varyings(ps_major, gl_info), ps->limits.packed_input);
+        /* This one is tricky: a 3.0 pixel shader reads from a 3.0 vertex shader */
+        shader_addline(buffer, "varying vec4 ps_in[%u];\n", in_count);
+        shader_addline(buffer, "void order_ps_input(in vec4 vs_out[%u])\n{\n", vs->limits.packed_output);
+
+        /* First, sort out position and point size. Those are not passed to the pixel shader */
+        for (i = 0; map; map >>= 1, ++i)
+        {
+            if (!(map & 1)) continue;
+
+            semantic_name = output_signature[i].semantic_name;
+            shader_glsl_write_mask_to_str(output_signature[i].mask, reg_mask);
+
+            if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_POSITION))
+            {
+                shader_addline(buffer, "gl_Position%s = vs_out[%u]%s;\n",
+                        reg_mask, i, reg_mask);
+            }
+            else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_PSIZE))
+            {
+                shader_addline(buffer, "gl_PointSize = vs_out[%u].%c;\n", i, reg_mask[1]);
+            }
+        }
+
+        /* Then, fix the pixel shader input */
+        handle_ps3_input(buffer, gl_info, ps->u.ps.input_reg_map, ps->input_signature,
+                &ps->reg_maps, output_signature, &vs->reg_maps);
+
+        shader_addline(buffer, "}\n");
+    }
+
+    ret = GL_EXTCALL(glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB));
+    checkGLcall("glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB)");
+    shader_glsl_compile(gl_info, ret, buffer->buffer);
+
+    return ret;
+}
+
+static void shader_glsl_generate_srgb_write_correction(struct wined3d_shader_buffer *buffer)
+{
+    shader_addline(buffer, "tmp0.xyz = pow(gl_FragData[0].xyz, vec3(srgb_const0.x));\n");
+    shader_addline(buffer, "tmp0.xyz = tmp0.xyz * vec3(srgb_const0.y) - vec3(srgb_const0.z);\n");
+    shader_addline(buffer, "tmp1.xyz = gl_FragData[0].xyz * vec3(srgb_const0.w);\n");
+    shader_addline(buffer, "bvec3 srgb_compare = lessThan(gl_FragData[0].xyz, vec3(srgb_const1.x));\n");
+    shader_addline(buffer, "gl_FragData[0].xyz = mix(tmp0.xyz, tmp1.xyz, vec3(srgb_compare));\n");
+    shader_addline(buffer, "gl_FragData[0] = clamp(gl_FragData[0], 0.0, 1.0);\n");
+}
+
+static void shader_glsl_generate_fog_code(struct wined3d_shader_buffer *buffer, enum wined3d_ffp_ps_fog_mode mode)
+{
+    switch (mode)
+    {
+        case WINED3D_FFP_PS_FOG_OFF:
+            return;
+
+        case WINED3D_FFP_PS_FOG_LINEAR:
+            /* Fog = (gl_Fog.end - gl_FogFragCoord) / (gl_Fog.end - gl_Fog.start) */
+            shader_addline(buffer, "float Fog = (gl_Fog.end - gl_FogFragCoord) / (gl_Fog.end - gl_Fog.start);\n");
+            break;
+
+        case WINED3D_FFP_PS_FOG_EXP:
+            /* Fog = e^-(gl_Fog.density * gl_FogFragCoord) */
+            shader_addline(buffer, "float Fog = exp(-gl_Fog.density * gl_FogFragCoord);\n");
+            break;
+
+        case WINED3D_FFP_PS_FOG_EXP2:
+            /* Fog = e^-((gl_Fog.density * gl_FogFragCoord)^2) */
+            shader_addline(buffer, "float Fog = exp(-gl_Fog.density * gl_Fog.density * gl_FogFragCoord * gl_FogFragCoord);\n");
+            break;
+
+        default:
+            ERR("Invalid fog mode %#x.\n", mode);
+            return;
+    }
+
+    shader_addline(buffer, "gl_FragData[0].xyz = mix(gl_Fog.color.xyz, gl_FragData[0].xyz, clamp(Fog, 0.0, 1.0));\n");
+}
+
+/* Context activation is done by the caller. */
+static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context,
+        struct wined3d_shader_buffer *buffer, const struct wined3d_shader *shader,
+        const struct ps_compile_args *args, struct ps_np2fixup_info *np2fixup_info)
+{
+    const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    const DWORD *function = shader->function;
+    struct shader_glsl_ctx_priv priv_ctx;
+
+    /* Create the hw GLSL shader object and assign it as the shader->prgId */
+    GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB));
+
+    memset(&priv_ctx, 0, sizeof(priv_ctx));
+    priv_ctx.cur_ps_args = args;
+    priv_ctx.cur_np2fixup_info = np2fixup_info;
+
+    shader_addline(buffer, "#version 120\n");
+
+    if (gl_info->supported[ARB_SHADER_BIT_ENCODING])
+        shader_addline(buffer, "#extension GL_ARB_shader_bit_encoding : enable\n");
+    if (gl_info->supported[ARB_SHADER_TEXTURE_LOD])
+        shader_addline(buffer, "#extension GL_ARB_shader_texture_lod : enable\n");
+    /* The spec says that it doesn't have to be explicitly enabled, but the
+     * nvidia drivers write a warning if we don't do so. */
+    if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
+        shader_addline(buffer, "#extension GL_ARB_texture_rectangle : enable\n");
+    if (gl_info->supported[EXT_GPU_SHADER4])
+        shader_addline(buffer, "#extension GL_EXT_gpu_shader4 : enable\n");
+
+    /* Base Declarations */
+    shader_generate_glsl_declarations(context, buffer, shader, reg_maps, &priv_ctx);
+
+    /* Pack 3.0 inputs */
+    if (reg_maps->shader_version.major >= 3 && args->vp_mode != vertexshader)
+        shader_glsl_input_pack(shader, buffer, shader->input_signature, reg_maps, args->vp_mode);
+
+    /* Base Shader Body */
+    shader_generate_main(shader, buffer, reg_maps, function, &priv_ctx);
+
+    /* Pixel shaders < 2.0 place the resulting color in R0 implicitly */
+    if (reg_maps->shader_version.major < 2)
+    {
+        /* Some older cards like GeforceFX ones don't support multiple buffers, so also not gl_FragData */
+        shader_addline(buffer, "gl_FragData[0] = R0;\n");
+    }
+
+    if (args->srgb_correction)
+        shader_glsl_generate_srgb_write_correction(buffer);
+
+    /* SM < 3 does not replace the fog stage. */
+    if (reg_maps->shader_version.major < 3)
+        shader_glsl_generate_fog_code(buffer, args->fog);
+
+    shader_addline(buffer, "}\n");
+
+    TRACE("Compiling shader object %u\n", shader_obj);
+    shader_glsl_compile(gl_info, shader_obj, buffer->buffer);
+
+    /* Store the shader object */
+    return shader_obj;
+}
+
+/* Context activation is done by the caller. */
+static GLuint shader_glsl_generate_vshader(const struct wined3d_context *context,
+        struct wined3d_shader_buffer *buffer, const struct wined3d_shader *shader,
+        const struct vs_compile_args *args)
+{
+    const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    const DWORD *function = shader->function;
+    struct shader_glsl_ctx_priv priv_ctx;
+
+    /* Create the hw GLSL shader program and assign it as the shader->prgId */
+    GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB));
+
+    shader_addline(buffer, "#version 120\n");
+
+    if (gl_info->supported[ARB_SHADER_BIT_ENCODING])
+        shader_addline(buffer, "#extension GL_ARB_shader_bit_encoding : enable\n");
+    if (gl_info->supported[EXT_GPU_SHADER4])
+        shader_addline(buffer, "#extension GL_EXT_gpu_shader4 : enable\n");
+
+    memset(&priv_ctx, 0, sizeof(priv_ctx));
+    priv_ctx.cur_vs_args = args;
+
+    /* Base Declarations */
+    shader_generate_glsl_declarations(context, buffer, shader, reg_maps, &priv_ctx);
+
+    /* Base Shader Body */
+    shader_generate_main(shader, buffer, reg_maps, function, &priv_ctx);
+
+    /* Unpack outputs */
+    shader_addline(buffer, "order_ps_input(vs_out);\n");
+
+    /* The D3DRS_FOGTABLEMODE render state defines if the shader-generated fog coord is used
+     * or if the fragment depth is used. If the fragment depth is used(FOGTABLEMODE != NONE),
+     * the fog frag coord is thrown away. If the fog frag coord is used, but not written by
+     * the shader, it is set to 0.0(fully fogged, since start = 1.0, end = 0.0)
+     */
+    if (args->fog_src == VS_FOG_Z)
+        shader_addline(buffer, "gl_FogFragCoord = gl_Position.z;\n");
+    else if (!reg_maps->fog)
+        shader_addline(buffer, "gl_FogFragCoord = 0.0;\n");
+
+    /* We always store the clipplanes without y inversion */
+    if (args->clip_enabled)
+        shader_addline(buffer, "gl_ClipVertex = gl_Position;\n");
+
+    /* Write the final position.
+     *
+     * OpenGL coordinates specify the center of the pixel while d3d coords specify
+     * the corner. The offsets are stored in z and w in posFixup. posFixup.y contains
+     * 1.0 or -1.0 to turn the rendering upside down for offscreen rendering. PosFixup.x
+     * contains 1.0 to allow a mad.
+     */
+    shader_addline(buffer, "gl_Position.y = gl_Position.y * posFixup.y;\n");
+    shader_addline(buffer, "gl_Position.xy += posFixup.zw * gl_Position.ww;\n");
+
+    /* Z coord [0;1]->[-1;1] mapping, see comment in transform_projection in state.c
+     *
+     * Basically we want (in homogeneous coordinates) z = z * 2 - 1. However, shaders are run
+     * before the homogeneous divide, so we have to take the w into account: z = ((z / w) * 2 - 1) * w,
+     * which is the same as z = z * 2 - w.
+     */
+    shader_addline(buffer, "gl_Position.z = gl_Position.z * 2.0 - gl_Position.w;\n");
+
+    shader_addline(buffer, "}\n");
+
+    TRACE("Compiling shader object %u\n", shader_obj);
+    shader_glsl_compile(gl_info, shader_obj, buffer->buffer);
+
+    return shader_obj;
+}
+
+/* Context activation is done by the caller. */
+static GLhandleARB shader_glsl_generate_geometry_shader(const struct wined3d_context *context,
+        struct wined3d_shader_buffer *buffer, const struct wined3d_shader *shader)
+{
+    const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    const DWORD *function = shader->function;
+    struct shader_glsl_ctx_priv priv_ctx;
+    GLhandleARB shader_id;
+
+    shader_id = GL_EXTCALL(glCreateShaderObjectARB(GL_GEOMETRY_SHADER_ARB));
+
+    shader_addline(buffer, "#version 120\n");
+
+    if (gl_info->supported[ARB_GEOMETRY_SHADER4])
+        shader_addline(buffer, "#extension GL_ARB_geometry_shader4 : enable\n");
+    if (gl_info->supported[ARB_SHADER_BIT_ENCODING])
+        shader_addline(buffer, "#extension GL_ARB_shader_bit_encoding : enable\n");
+    if (gl_info->supported[EXT_GPU_SHADER4])
+        shader_addline(buffer, "#extension GL_EXT_gpu_shader4 : enable\n");
+
+    memset(&priv_ctx, 0, sizeof(priv_ctx));
+    shader_generate_glsl_declarations(context, buffer, shader, reg_maps, &priv_ctx);
+    shader_generate_main(shader, buffer, reg_maps, function, &priv_ctx);
+    shader_addline(buffer, "}\n");
+
+    TRACE("Compiling shader object %u.\n", shader_id);
+    shader_glsl_compile(gl_info, shader_id, buffer->buffer);
+
+    return shader_id;
+}
+
+static GLhandleARB find_glsl_pshader(const struct wined3d_context *context,
+        struct wined3d_shader_buffer *buffer, struct wined3d_shader *shader,
+        const struct ps_compile_args *args, const struct ps_np2fixup_info **np2fixup_info)
+{
+    struct glsl_ps_compiled_shader *gl_shaders, *new_array;
+    struct glsl_shader_private *shader_data;
+    struct ps_np2fixup_info *np2fixup;
+    UINT i;
+    DWORD new_size;
+    GLhandleARB ret;
+
+    if (!shader->backend_data)
+    {
+        shader->backend_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*shader_data));
+        if (!shader->backend_data)
+        {
+            ERR("Failed to allocate backend data.\n");
+            return 0;
+        }
+    }
+    shader_data = shader->backend_data;
+    gl_shaders = shader_data->gl_shaders.ps;
+
+    /* Usually we have very few GL shaders for each d3d shader(just 1 or maybe 2),
+     * so a linear search is more performant than a hashmap or a binary search
+     * (cache coherency etc)
+     */
+    for (i = 0; i < shader_data->num_gl_shaders; ++i)
+    {
+        if (!memcmp(&gl_shaders[i].args, args, sizeof(*args)))
+        {
+            if (args->np2_fixup)
+                *np2fixup_info = &gl_shaders[i].np2fixup;
+            return gl_shaders[i].prgId;
+        }
+    }
+
+    TRACE("No matching GL shader found for shader %p, compiling a new shader.\n", shader);
+    if(shader_data->shader_array_size == shader_data->num_gl_shaders) {
+        if (shader_data->num_gl_shaders)
+        {
+            new_size = shader_data->shader_array_size + max(1, shader_data->shader_array_size / 2);
+            new_array = HeapReAlloc(GetProcessHeap(), 0, shader_data->gl_shaders.ps,
+                    new_size * sizeof(*gl_shaders));
+        }
+        else
+        {
+            new_array = HeapAlloc(GetProcessHeap(), 0, sizeof(*gl_shaders));
+            new_size = 1;
+        }
+
+        if(!new_array) {
+            ERR("Out of memory\n");
+            return 0;
+        }
+        shader_data->gl_shaders.ps = new_array;
+        shader_data->shader_array_size = new_size;
+        gl_shaders = new_array;
+    }
+
+    gl_shaders[shader_data->num_gl_shaders].args = *args;
+
+    np2fixup = &gl_shaders[shader_data->num_gl_shaders].np2fixup;
+    memset(np2fixup, 0, sizeof(*np2fixup));
+    *np2fixup_info = args->np2_fixup ? np2fixup : NULL;
+
+    pixelshader_update_samplers(shader, args->tex_types);
+
+    shader_buffer_clear(buffer);
+    ret = shader_glsl_generate_pshader(context, buffer, shader, args, np2fixup);
+    gl_shaders[shader_data->num_gl_shaders++].prgId = ret;
+
+    return ret;
+}
+
+static inline BOOL vs_args_equal(const struct vs_compile_args *stored, const struct vs_compile_args *new,
+                                 const DWORD use_map) {
+    if((stored->swizzle_map & use_map) != new->swizzle_map) return FALSE;
+    if((stored->clip_enabled) != new->clip_enabled) return FALSE;
+    return stored->fog_src == new->fog_src;
+}
+
+static GLhandleARB find_glsl_vshader(const struct wined3d_context *context,
+        struct wined3d_shader_buffer *buffer, struct wined3d_shader *shader,
+        const struct vs_compile_args *args)
+{
+    UINT i;
+    DWORD new_size;
+    DWORD use_map = shader->device->stream_info.use_map;
+    struct glsl_vs_compiled_shader *gl_shaders, *new_array;
+    struct glsl_shader_private *shader_data;
+    GLhandleARB ret;
+
+    if (!shader->backend_data)
+    {
+        shader->backend_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*shader_data));
+        if (!shader->backend_data)
+        {
+            ERR("Failed to allocate backend data.\n");
+            return 0;
+        }
+    }
+    shader_data = shader->backend_data;
+    gl_shaders = shader_data->gl_shaders.vs;
+
+    /* Usually we have very few GL shaders for each d3d shader(just 1 or maybe 2),
+     * so a linear search is more performant than a hashmap or a binary search
+     * (cache coherency etc)
+     */
+    for (i = 0; i < shader_data->num_gl_shaders; ++i)
+    {
+        if (vs_args_equal(&gl_shaders[i].args, args, use_map))
+            return gl_shaders[i].prgId;
+    }
+
+    TRACE("No matching GL shader found for shader %p, compiling a new shader.\n", shader);
+
+    if(shader_data->shader_array_size == shader_data->num_gl_shaders) {
+        if (shader_data->num_gl_shaders)
+        {
+            new_size = shader_data->shader_array_size + max(1, shader_data->shader_array_size / 2);
+            new_array = HeapReAlloc(GetProcessHeap(), 0, shader_data->gl_shaders.vs,
+                    new_size * sizeof(*gl_shaders));
+        }
+        else
+        {
+            new_array = HeapAlloc(GetProcessHeap(), 0, sizeof(*gl_shaders));
+            new_size = 1;
+        }
+
+        if(!new_array) {
+            ERR("Out of memory\n");
+            return 0;
+        }
+        shader_data->gl_shaders.vs = new_array;
+        shader_data->shader_array_size = new_size;
+        gl_shaders = new_array;
+    }
+
+    gl_shaders[shader_data->num_gl_shaders].args = *args;
+
+    shader_buffer_clear(buffer);
+    ret = shader_glsl_generate_vshader(context, buffer, shader, args);
+    gl_shaders[shader_data->num_gl_shaders++].prgId = ret;
+
+    return ret;
+}
+
+static GLhandleARB find_glsl_geometry_shader(const struct wined3d_context *context,
+        struct wined3d_shader_buffer *buffer, struct wined3d_shader *shader)
+{
+    struct glsl_gs_compiled_shader *gl_shaders;
+    struct glsl_shader_private *shader_data;
+    GLhandleARB ret;
+
+    if (!shader->backend_data)
+    {
+        if (!(shader->backend_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*shader_data))))
+        {
+            ERR("Failed to allocate backend data.\n");
+            return 0;
+        }
+    }
+    shader_data = shader->backend_data;
+    gl_shaders = shader_data->gl_shaders.gs;
+
+    if (shader_data->num_gl_shaders)
+        return gl_shaders[0].id;
+
+    TRACE("No matching GL shader found for shader %p, compiling a new shader.\n", shader);
+
+    if (!(shader_data->gl_shaders.gs = HeapAlloc(GetProcessHeap(), 0, sizeof(*gl_shaders))))
+    {
+        ERR("Failed to allocate GL shader array.\n");
+        return 0;
+    }
+    shader_data->shader_array_size = 1;
+    gl_shaders = shader_data->gl_shaders.gs;
+
+    shader_buffer_clear(buffer);
+    ret = shader_glsl_generate_geometry_shader(context, buffer, shader);
+    gl_shaders[shader_data->num_gl_shaders++].id = ret;
+
+    return ret;
+}
+
+static const char *shader_glsl_ffp_mcs(enum wined3d_material_color_source mcs, const char *material)
+{
+    switch (mcs)
+    {
+        case WINED3D_MCS_MATERIAL:
+            return material;
+        case WINED3D_MCS_COLOR1:
+            return "gl_Color";
+        case WINED3D_MCS_COLOR2:
+            return "gl_SecondaryColor";
+        default:
+            ERR("Invalid material color source %#x.\n", mcs);
+            return "<invalid>";
+    }
+}
+
+static void shader_glsl_ffp_vertex_lighting(struct wined3d_shader_buffer *buffer,
+        const struct wined3d_ffp_vs_settings *settings, const struct wined3d_gl_info *gl_info)
+{
+    const char *diffuse, *specular, *emission, *ambient;
+    enum wined3d_light_type light_type;
+    unsigned int i;
+
+    if (!settings->lighting)
+    {
+        shader_addline(buffer, "gl_FrontColor = gl_Color;\n");
+        shader_addline(buffer, "gl_FrontSecondaryColor = gl_SecondaryColor;\n");
+        return;
+    }
+
+    shader_addline(buffer, "vec3 ambient = gl_LightModel.ambient.xyz;\n");
+    shader_addline(buffer, "vec3 diffuse = vec3(0.0);\n");
+    shader_addline(buffer, "vec4 specular = vec4(0.0);\n");
+    shader_addline(buffer, "vec3 dir, dst;\n");
+    shader_addline(buffer, "float att, t;\n");
+
+    ambient = shader_glsl_ffp_mcs(settings->ambient_source, "gl_FrontMaterial.ambient");
+    diffuse = shader_glsl_ffp_mcs(settings->diffuse_source, "gl_FrontMaterial.diffuse");
+    specular = shader_glsl_ffp_mcs(settings->specular_source, "gl_FrontMaterial.specular");
+    emission = shader_glsl_ffp_mcs(settings->emission_source, "gl_FrontMaterial.emission");
+
+    for (i = 0; i < MAX_ACTIVE_LIGHTS; ++i)
+    {
+        light_type = (settings->light_type >> WINED3D_FFP_LIGHT_TYPE_SHIFT(i)) & WINED3D_FFP_LIGHT_TYPE_MASK;
+        switch (light_type)
+        {
+            case WINED3D_LIGHT_POINT:
+                shader_addline(buffer, "dir = gl_LightSource[%u].position.xyz - ec_pos.xyz;\n", i);
+                shader_addline(buffer, "dst.z = dot(dir, dir);\n");
+                shader_addline(buffer, "dst.y = sqrt(dst.z);\n");
+                shader_addline(buffer, "dst.x = 1.0;\n");
+                shader_addline(buffer, "att = dot(dst.xyz, vec3(gl_LightSource[%u].constantAttenuation,"
+                        " gl_LightSource[%u].linearAttenuation, gl_LightSource[%u].quadraticAttenuation));\n", i, i, i);
+                shader_addline(buffer, "ambient += gl_LightSource[%u].ambient.xyz / att;\n", i);
+                if (!settings->normal)
+                    break;
+                shader_addline(buffer, "dir = normalize(dir);\n");
+                shader_addline(buffer, "diffuse += (max(0.0, dot(dir, normal))"
+                        " * gl_LightSource[%u].diffuse.xyz) / att;\n", i);
+                if (settings->localviewer)
+                    shader_addline(buffer, "t = dot(normal, normalize(dir - normalize(ec_pos.xyz)));\n");
+                else
+                    shader_addline(buffer, "t = dot(normal, normalize(dir + vec3(0.0, 0.0, 1.0)));\n");
+                shader_addline(buffer, "if (t > 0.0) specular += (pow(t, gl_FrontMaterial.shininess)"
+                        " * gl_LightSource[%u].specular) / att;\n", i);
+                break;
+
+            case WINED3D_LIGHT_SPOT:
+                shader_addline(buffer, "dir = gl_LightSource[%u].position.xyz - ec_pos.xyz;\n", i);
+                shader_addline(buffer, "dst.z = dot(dir, dir);\n");
+                shader_addline(buffer, "dst.y = sqrt(dst.z);\n");
+                shader_addline(buffer, "dst.x = 1.0;\n");
+                shader_addline(buffer, "dir = normalize(dir);\n");
+                shader_addline(buffer, "t = dot(-dir, normalize(gl_LightSource[%u].spotDirection));\n", i);
+                shader_addline(buffer, "if (t < gl_LightSource[%u].spotCosCutoff) att = 0.0;\n", i);
+                shader_addline(buffer, "else att = pow(t, gl_LightSource[%u].spotExponent)"
+                        " / dot(dst.xyz, vec3(gl_LightSource[%u].constantAttenuation,"
+                        " gl_LightSource[%u].linearAttenuation, gl_LightSource[%u].quadraticAttenuation));\n",
+                        i, i, i, i);
+                shader_addline(buffer, "ambient += gl_LightSource[%u].ambient.xyz * att;\n", i);
+                if (!settings->normal)
+                    break;
+                shader_addline(buffer, "diffuse += (max(0.0, dot(dir, normal))"
+                        " * gl_LightSource[%u].diffuse.xyz) * att;\n", i);
+                if (settings->localviewer)
+                    shader_addline(buffer, "t = dot(normal, normalize(dir - normalize(ec_pos.xyz)));\n");
+                else
+                    shader_addline(buffer, "t = dot(normal, normalize(dir + vec3(0.0, 0.0, 1.0)));\n");
+                shader_addline(buffer, "if (t > 0.0) specular += (pow(t, gl_FrontMaterial.shininess)"
+                        " * gl_LightSource[%u].specular) * att;\n", i);
+                break;
+
+            case WINED3D_LIGHT_DIRECTIONAL:
+                shader_addline(buffer, "ambient += gl_LightSource[%u].ambient.xyz;\n", i);
+                if (!settings->normal)
+                    break;
+                shader_addline(buffer, "dir = normalize(gl_LightSource[%u].position.xyz);\n", i);
+                shader_addline(buffer, "diffuse += max(0.0, dot(dir, normal)) * gl_LightSource[%u].diffuse.xyz;\n", i);
+                shader_addline(buffer, "t = dot(normal, gl_LightSource[%u].halfVector.xyz);\n", i);
+                shader_addline(buffer, "if (t > 0.0) specular += pow(t, gl_FrontMaterial.shininess)"
+                        " * gl_LightSource[%u].specular;\n", i);
+                break;
+
+            default:
+                if (light_type)
+                    FIXME("Unhandled light type %#x.\n", light_type);
+                continue;
+        }
+    }
+
+    shader_addline(buffer, "gl_FrontColor.xyz = %s.xyz * ambient + %s.xyz * diffuse + %s.xyz;\n",
+            ambient, diffuse, emission);
+    shader_addline(buffer, "gl_FrontColor.w = %s.w;\n", diffuse);
+    shader_addline(buffer, "gl_FrontSecondaryColor = %s * specular;\n", specular);
+}
+
+/* Context activation is done by the caller. */
+static GLhandleARB shader_glsl_generate_ffp_vertex_shader(struct wined3d_shader_buffer *buffer,
+        const struct wined3d_ffp_vs_settings *settings, const struct wined3d_gl_info *gl_info)
+{
+    GLhandleARB shader_obj;
+    unsigned int i;
+
+    shader_buffer_clear(buffer);
+
+    shader_addline(buffer, "#version 120\n");
+    shader_addline(buffer, "\n");
+    shader_addline(buffer, "void main()\n{\n");
+    shader_addline(buffer, "float m;\n");
+    shader_addline(buffer, "vec3 r;\n");
+
+    shader_addline(buffer, "vec4 ec_pos = gl_ModelViewMatrix * gl_Vertex;\n");
+    shader_addline(buffer, "gl_Position = gl_ProjectionMatrix * ec_pos;\n");
+    if (settings->clipping)
+        shader_addline(buffer, "gl_ClipVertex = ec_pos;\n");
+    shader_addline(buffer, "ec_pos /= ec_pos.w;\n");
+
+    if (!settings->normal)
+        shader_addline(buffer, "vec3 normal = vec3(0.0);\n");
+    else if (settings->normalize)
+        shader_addline(buffer, "vec3 normal = normalize(gl_NormalMatrix * gl_Normal);\n");
+    else
+        shader_addline(buffer, "vec3 normal = gl_NormalMatrix * gl_Normal;\n");
+
+    shader_glsl_ffp_vertex_lighting(buffer, settings, gl_info);
+
+    for (i = 0; i < MAX_TEXTURES; ++i)
+    {
+        switch (settings->texgen[i] << WINED3D_FFP_TCI_SHIFT)
+        {
+            case WINED3DTSS_TCI_PASSTHRU:
+                if (settings->texcoords & (1 << i))
+                    shader_addline(buffer, "gl_TexCoord[%u] = gl_TextureMatrix[%u] * gl_MultiTexCoord%d;\n",
+                            i, i, i);
+                break;
+
+            case WINED3DTSS_TCI_CAMERASPACENORMAL:
+                shader_addline(buffer, "gl_TexCoord[%u] = gl_TextureMatrix[%u] * vec4(normal, 1.0);\n", i, i);
+                break;
+
+            case WINED3DTSS_TCI_CAMERASPACEPOSITION:
+                shader_addline(buffer, "gl_TexCoord[%u] = gl_TextureMatrix[%u] * ec_pos;\n", i, i);
+                break;
+
+            case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
+                shader_addline(buffer, "gl_TexCoord[%u] = gl_TextureMatrix[%u]"
+                        " * vec4(reflect(normalize(ec_pos.xyz), normal), 1.0);\n", i, i);
+                break;
+
+            case WINED3DTSS_TCI_SPHEREMAP:
+                shader_addline(buffer, "r = reflect(normalize(ec_pos.xyz), normal);\n");
+                shader_addline(buffer, "m = 2.0 * length(vec3(r.x, r.y, r.z + 1.0));\n");
+                shader_addline(buffer, "gl_TexCoord[%u] = gl_TextureMatrix[%u]"
+                        " * vec4(r.x / m + 0.5, r.y / m + 0.5, 0.0, 1.0);\n", i, i);
+                break;
+
+            default:
+                ERR("Unhandled texgen %#x.\n", settings->texgen[i]);
+                break;
+        }
+    }
+
+    switch (settings->fog_mode)
+    {
+        case WINED3D_FFP_VS_FOG_OFF:
+            break;
+
+        case WINED3D_FFP_VS_FOG_FOGCOORD:
+            shader_addline(buffer, "gl_FogFragCoord = gl_SecondaryColor.w * 255.0;\n");
+            break;
+
+        case WINED3D_FFP_VS_FOG_RANGE:
+            shader_addline(buffer, "gl_FogFragCoord = length(ec_pos.xyz);\n");
+            break;
+
+        case WINED3D_FFP_VS_FOG_DEPTH:
+            shader_addline(buffer, "gl_FogFragCoord = ec_pos.z;\n");
+            break;
+
+        default:
+            ERR("Unhandled fog mode %#x.\n", settings->fog_mode);
+            break;
+    }
+
+    if (settings->point_size)
+    {
+        shader_addline(buffer, "gl_PointSize = gl_Point.size / sqrt(gl_Point.distanceConstantAttenuation"
+                " + gl_Point.distanceLinearAttenuation * length(ec_pos.xyz)"
+                " + gl_Point.distanceQuadraticAttenuation * dot(ec_pos.xyz, ec_pos.xyz));\n");
+        shader_addline(buffer, "gl_PointSize = clamp(gl_PointSize, gl_Point.sizeMin, gl_Point.sizeMax);\n");
+    }
+
+    shader_addline(buffer, "}\n");
+
+    shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB));
+    shader_glsl_compile(gl_info, shader_obj, buffer->buffer);
+
+    return shader_obj;
+}
+
+static const char *shader_glsl_get_ffp_fragment_op_arg(struct wined3d_shader_buffer *buffer,
+        DWORD argnum, unsigned int stage, DWORD arg)
+{
+    const char *ret;
+
+    if (arg == ARG_UNUSED)
+        return "<unused arg>";
+
+    switch (arg & WINED3DTA_SELECTMASK)
+    {
+        case WINED3DTA_DIFFUSE:
+            ret = "gl_Color";
+            break;
+
+        case WINED3DTA_CURRENT:
+            if (!stage)
+                ret = "gl_Color";
+            else
+                ret = "ret";
+            break;
+
+        case WINED3DTA_TEXTURE:
+            switch (stage)
+            {
+                case 0: ret = "tex0"; break;
+                case 1: ret = "tex1"; break;
+                case 2: ret = "tex2"; break;
+                case 3: ret = "tex3"; break;
+                case 4: ret = "tex4"; break;
+                case 5: ret = "tex5"; break;
+                case 6: ret = "tex6"; break;
+                case 7: ret = "tex7"; break;
+                default:
+                    ret = "<invalid texture>";
+                    break;
+            }
+            break;
+
+        case WINED3DTA_TFACTOR:
+            ret = "tex_factor";
+            break;
+
+        case WINED3DTA_SPECULAR:
+            ret = "gl_SecondaryColor";
+            break;
+
+        case WINED3DTA_TEMP:
+            ret = "temp_reg";
+            break;
+
+        case WINED3DTA_CONSTANT:
+            FIXME("Per-stage constants not implemented.\n");
+            switch (stage)
+            {
+                case 0: ret = "const0"; break;
+                case 1: ret = "const1"; break;
+                case 2: ret = "const2"; break;
+                case 3: ret = "const3"; break;
+                case 4: ret = "const4"; break;
+                case 5: ret = "const5"; break;
+                case 6: ret = "const6"; break;
+                case 7: ret = "const7"; break;
+                default:
+                    ret = "<invalid constant>";
+                    break;
+            }
+            break;
+
+        default:
+            return "<unhandled arg>";
+    }
+
+    if (arg & WINED3DTA_COMPLEMENT)
+    {
+        shader_addline(buffer, "arg%u = vec4(1.0) - %s;\n", argnum, ret);
+        if (argnum == 0)
+            ret = "arg0";
+        else if (argnum == 1)
+            ret = "arg1";
+        else if (argnum == 2)
+            ret = "arg2";
+    }
+
+    if (arg & WINED3DTA_ALPHAREPLICATE)
+    {
+        shader_addline(buffer, "arg%u = vec4(%s.w);\n", argnum, ret);
+        if (argnum == 0)
+            ret = "arg0";
+        else if (argnum == 1)
+            ret = "arg1";
+        else if (argnum == 2)
+            ret = "arg2";
+    }
+
+    return ret;
+}
+
+static void shader_glsl_ffp_fragment_op(struct wined3d_shader_buffer *buffer, unsigned int stage, BOOL color,
+        BOOL alpha, DWORD dst, DWORD op, DWORD dw_arg0, DWORD dw_arg1, DWORD dw_arg2)
+{
+    const char *dstmask, *dstreg, *arg0, *arg1, *arg2;
+
+    if (color && alpha)
+        dstmask = "";
+    else if (color)
+        dstmask = ".xyz";
+    else
+        dstmask = ".w";
+
+    if (dst == tempreg)
+        dstreg = "temp_reg";
+    else
+        dstreg = "ret";
+
+    arg0 = shader_glsl_get_ffp_fragment_op_arg(buffer, 0, stage, dw_arg0);
+    arg1 = shader_glsl_get_ffp_fragment_op_arg(buffer, 1, stage, dw_arg1);
+    arg2 = shader_glsl_get_ffp_fragment_op_arg(buffer, 2, stage, dw_arg2);
+
+    switch (op)
+    {
+        case WINED3D_TOP_DISABLE:
+            if (!stage)
+                shader_addline(buffer, "%s%s = gl_Color%s;\n", dstreg, dstmask, dstmask);
+            break;
+
+        case WINED3D_TOP_SELECT_ARG1:
+            shader_addline(buffer, "%s%s = %s%s;\n", dstreg, dstmask, arg1, dstmask);
+            break;
+
+        case WINED3D_TOP_SELECT_ARG2:
+            shader_addline(buffer, "%s%s = %s%s;\n", dstreg, dstmask, arg2, dstmask);
+            break;
+
+        case WINED3D_TOP_MODULATE:
+            shader_addline(buffer, "%s%s = %s%s * %s%s;\n", dstreg, dstmask, arg1, dstmask, arg2, dstmask);
+            break;
+
+        case WINED3D_TOP_MODULATE_4X:
+            shader_addline(buffer, "%s%s = clamp(%s%s * %s%s * 4.0, 0.0, 1.0);\n",
+                    dstreg, dstmask, arg1, dstmask, arg2, dstmask);
+            break;
+
+        case WINED3D_TOP_MODULATE_2X:
+            shader_addline(buffer, "%s%s = clamp(%s%s * %s%s * 2.0, 0.0, 1.0);\n",
+                    dstreg, dstmask, arg1, dstmask, arg2, dstmask);
+            break;
+
+        case WINED3D_TOP_ADD:
+            shader_addline(buffer, "%s%s = clamp(%s%s + %s%s, 0.0, 1.0);\n",
+                    dstreg, dstmask, arg1, dstmask, arg2, dstmask);
+            break;
+
+        case WINED3D_TOP_ADD_SIGNED:
+            shader_addline(buffer, "%s%s = clamp(%s%s + (%s - vec4(0.5))%s, 0.0, 1.0);\n",
+                    dstreg, dstmask, arg1, dstmask, arg2, dstmask);
+            break;
+
+        case WINED3D_TOP_ADD_SIGNED_2X:
+            shader_addline(buffer, "%s%s = clamp((%s%s + (%s - vec4(0.5))%s) * 2.0, 0.0, 1.0);\n",
+                    dstreg, dstmask, arg1, dstmask, arg2, dstmask);
+            break;
+
+        case WINED3D_TOP_SUBTRACT:
+            shader_addline(buffer, "%s%s = clamp(%s%s - %s%s, 0.0, 1.0);\n",
+                    dstreg, dstmask, arg1, dstmask, arg2, dstmask);
+            break;
+
+        case WINED3D_TOP_ADD_SMOOTH:
+            shader_addline(buffer, "%s%s = clamp((vec4(1.0) - %s)%s * %s%s + %s%s, 0.0, 1.0);\n",
+                    dstreg, dstmask, arg1, dstmask, arg2, dstmask, arg1, dstmask);
+            break;
+
+        case WINED3D_TOP_BLEND_DIFFUSE_ALPHA:
+            arg0 = shader_glsl_get_ffp_fragment_op_arg(buffer, 0, stage, WINED3DTA_DIFFUSE);
+            shader_addline(buffer, "%s%s = mix(%s%s, %s%s, %s.w);\n",
+                    dstreg, dstmask, arg2, dstmask, arg1, dstmask, arg0);
+            break;
+
+        case WINED3D_TOP_BLEND_TEXTURE_ALPHA:
+            arg0 = shader_glsl_get_ffp_fragment_op_arg(buffer, 0, stage, WINED3DTA_TEXTURE);
+            shader_addline(buffer, "%s%s = mix(%s%s, %s%s, %s.w);\n",
+                    dstreg, dstmask, arg2, dstmask, arg1, dstmask, arg0);
+            break;
+
+        case WINED3D_TOP_BLEND_FACTOR_ALPHA:
+            arg0 = shader_glsl_get_ffp_fragment_op_arg(buffer, 0, stage, WINED3DTA_TFACTOR);
+            shader_addline(buffer, "%s%s = mix(%s%s, %s%s, %s.w);\n",
+                    dstreg, dstmask, arg2, dstmask, arg1, dstmask, arg0);
+            break;
+
+        case WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM:
+            arg0 = shader_glsl_get_ffp_fragment_op_arg(buffer, 0, stage, WINED3DTA_TEXTURE);
+            shader_addline(buffer, "%s%s = clamp(%s%s * (1.0 - %s.w) + %s%s, 0.0, 1.0);\n",
+                    dstreg, dstmask, arg2, dstmask, arg0, arg1, dstmask);
+            break;
+
+        case WINED3D_TOP_BLEND_CURRENT_ALPHA:
+            arg0 = shader_glsl_get_ffp_fragment_op_arg(buffer, 0, stage, WINED3DTA_CURRENT);
+            shader_addline(buffer, "%s%s = mix(%s%s, %s%s, %s.w);\n",
+                    dstreg, dstmask, arg2, dstmask, arg1, dstmask, arg0);
+            break;
+
+        case WINED3D_TOP_MODULATE_ALPHA_ADD_COLOR:
+            shader_addline(buffer, "%s%s = clamp(%s%s * %s.w + %s%s, 0.0, 1.0);\n",
+                    dstreg, dstmask, arg2, dstmask, arg1, arg1, dstmask);
+            break;
+
+        case WINED3D_TOP_MODULATE_COLOR_ADD_ALPHA:
+            shader_addline(buffer, "%s%s = clamp(%s%s * %s%s + %s.w, 0.0, 1.0);\n",
+                    dstreg, dstmask, arg1, dstmask, arg2, dstmask, arg1);
+            break;
+
+        case WINED3D_TOP_MODULATE_INVALPHA_ADD_COLOR:
+            shader_addline(buffer, "%s%s = clamp(%s%s * (1.0 - %s.w) + %s%s, 0.0, 1.0);\n",
+                    dstreg, dstmask, arg2, dstmask, arg1, arg1, dstmask);
+            break;
+        case WINED3D_TOP_MODULATE_INVCOLOR_ADD_ALPHA:
+            shader_addline(buffer, "%s%s = clamp((vec4(1.0) - %s)%s * %s%s + %s.w, 0.0, 1.0);\n",
+                    dstreg, dstmask, arg1, dstmask, arg2, dstmask, arg1);
+            break;
+
+        case WINED3D_TOP_BUMPENVMAP:
+        case WINED3D_TOP_BUMPENVMAP_LUMINANCE:
+            /* These are handled in the first pass, nothing to do. */
+            break;
+
+        case WINED3D_TOP_DOTPRODUCT3:
+            shader_addline(buffer, "%s%s = vec4(clamp(dot(%s.xyz - 0.5, %s.xyz - 0.5) * 4.0, 0.0, 1.0))%s;\n",
+                    dstreg, dstmask, arg1, arg2, dstmask);
+            break;
+
+        case WINED3D_TOP_MULTIPLY_ADD:
+            shader_addline(buffer, "%s%s = clamp(%s%s * %s%s + %s%s, 0.0, 1.0);\n",
+                    dstreg, dstmask, arg1, dstmask, arg2, dstmask, arg0, dstmask);
+            break;
+
+        case WINED3D_TOP_LERP:
+            /* MSDN isn't quite right here. */
+            shader_addline(buffer, "%s%s = mix(%s%s, %s%s, %s%s);\n",
+                    dstreg, dstmask, arg2, dstmask, arg1, dstmask, arg0, dstmask);
+            break;
+
+        default:
+            FIXME("Unhandled operation %#x.\n", op);
+            break;
+    }
+}
+
+/* Context activation is done by the caller. */
+static GLuint shader_glsl_generate_ffp_fragment_shader(struct wined3d_shader_buffer *buffer,
+        const struct ffp_frag_settings *settings, const struct wined3d_gl_info *gl_info)
+{
+    BOOL tempreg_used = FALSE, tfactor_used = FALSE;
+    BYTE lum_map = 0, bump_map = 0, tex_map = 0;
+    const char *final_combiner_src = "ret";
+    UINT lowest_disabled_stage;
+    GLhandleARB shader_obj;
+    DWORD arg0, arg1, arg2;
+    unsigned int stage;
+
+    shader_buffer_clear(buffer);
+
+    /* Find out which textures are read */
+    for (stage = 0; stage < MAX_TEXTURES; ++stage)
+    {
+        if (settings->op[stage].cop == WINED3D_TOP_DISABLE)
+            break;
+
+        arg0 = settings->op[stage].carg0 & WINED3DTA_SELECTMASK;
+        arg1 = settings->op[stage].carg1 & WINED3DTA_SELECTMASK;
+        arg2 = settings->op[stage].carg2 & WINED3DTA_SELECTMASK;
+
+        if (arg0 == WINED3DTA_TEXTURE || arg1 == WINED3DTA_TEXTURE || arg2 == WINED3DTA_TEXTURE)
+            tex_map |= 1 << stage;
+        if (arg0 == WINED3DTA_TFACTOR || arg1 == WINED3DTA_TFACTOR || arg2 == WINED3DTA_TFACTOR)
+            tfactor_used = TRUE;
+        if (arg0 == WINED3DTA_TEMP || arg1 == WINED3DTA_TEMP || arg2 == WINED3DTA_TEMP)
+            tempreg_used = TRUE;
+        if (settings->op[stage].dst == tempreg)
+            tempreg_used = TRUE;
+
+        switch (settings->op[stage].cop)
+        {
+            case WINED3D_TOP_BUMPENVMAP_LUMINANCE:
+                lum_map |= 1 << stage;
+                /* fall through */
+            case WINED3D_TOP_BUMPENVMAP:
+                bump_map |= 1 << stage;
+                /* fall through */
+            case WINED3D_TOP_BLEND_TEXTURE_ALPHA:
+            case WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM:
+                tex_map |= 1 << stage;
+                break;
+
+            case WINED3D_TOP_BLEND_FACTOR_ALPHA:
+                tfactor_used = TRUE;
+                break;
+
+            default:
+                break;
+        }
+
+        if (settings->op[stage].aop == WINED3D_TOP_DISABLE)
+            continue;
+
+        arg0 = settings->op[stage].aarg0 & WINED3DTA_SELECTMASK;
+        arg1 = settings->op[stage].aarg1 & WINED3DTA_SELECTMASK;
+        arg2 = settings->op[stage].aarg2 & WINED3DTA_SELECTMASK;
+
+        if (arg0 == WINED3DTA_TEXTURE || arg1 == WINED3DTA_TEXTURE || arg2 == WINED3DTA_TEXTURE)
+            tex_map |= 1 << stage;
+        if (arg0 == WINED3DTA_TFACTOR || arg1 == WINED3DTA_TFACTOR || arg2 == WINED3DTA_TFACTOR)
+            tfactor_used = TRUE;
+        if (arg0 == WINED3DTA_TEMP || arg1 == WINED3DTA_TEMP || arg2 == WINED3DTA_TEMP)
+            tempreg_used = TRUE;
+    }
+    lowest_disabled_stage = stage;
+
+    shader_addline(buffer, "#version 120\n");
+
+    if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
+        shader_addline(buffer, "#extension GL_ARB_texture_rectangle : enable\n");
+
+    shader_addline(buffer, "vec4 tmp0, tmp1;\n");
+    shader_addline(buffer, "vec4 ret;\n");
+    if (tempreg_used || settings->sRGB_write)
+        shader_addline(buffer, "vec4 temp_reg;\n");
+    shader_addline(buffer, "vec4 arg0, arg1, arg2;\n");
+
+    for (stage = 0; stage < MAX_TEXTURES; ++stage)
+    {
+        if (!(tex_map & (1 << stage)))
+            continue;
+
+        switch (settings->op[stage].tex_type)
+        {
+            case tex_1d:
+                shader_addline(buffer, "uniform sampler1D ps_sampler%u;\n", stage);
+                break;
+            case tex_2d:
+                shader_addline(buffer, "uniform sampler2D ps_sampler%u;\n", stage);
+                break;
+            case tex_3d:
+                shader_addline(buffer, "uniform sampler3D ps_sampler%u;\n", stage);
+                break;
+            case tex_cube:
+                shader_addline(buffer, "uniform samplerCube ps_sampler%u;\n", stage);
+                break;
+            case tex_rect:
+                shader_addline(buffer, "uniform sampler2DRect ps_sampler%u;\n", stage);
+                break;
+            default:
+                FIXME("Unhandled sampler type %#x.\n", settings->op[stage].tex_type);
+                break;
+        }
+
+        shader_addline(buffer, "vec4 tex%u;\n", stage);
+
+        if (!(bump_map & (1 << stage)))
+            continue;
+        shader_addline(buffer, "uniform mat2 bumpenv_mat%u;\n", stage);
+
+        if (!(lum_map & (1 << stage)))
+            continue;
+        shader_addline(buffer, "uniform float bumpenv_lum_scale%u;\n", stage);
+        shader_addline(buffer, "uniform float bumpenv_lum_offset%u;\n", stage);
+    }
+    if (tfactor_used)
+        shader_addline(buffer, "uniform vec4 tex_factor;\n");
+    shader_addline(buffer, "uniform vec4 specular_enable;\n");
+
+    if (settings->sRGB_write)
+    {
+        shader_addline(buffer, "const vec4 srgb_const0 = vec4(%.8e, %.8e, %.8e, %.8e);\n",
+                srgb_pow, srgb_mul_high, srgb_sub_high, srgb_mul_low);
+        shader_addline(buffer, "const vec4 srgb_const1 = vec4(%.8e, 0.0, 0.0, 0.0);\n",
+                srgb_cmp);
+    }
+
+    shader_addline(buffer, "void main()\n{\n");
+
+    if (lowest_disabled_stage < 7 && settings->emul_clipplanes)
+        shader_addline(buffer, "if (any(lessThan(gl_TexCoord[7], vec4(0.0)))) discard;\n");
+
+    /* Generate texture sampling instructions) */
+    for (stage = 0; stage < MAX_TEXTURES && settings->op[stage].cop != WINED3D_TOP_DISABLE; ++stage)
+    {
+        const char *texture_function, *coord_mask;
+        char tex_reg_name[8];
+        BOOL proj, clamp;
+
+        if (!(tex_map & (1 << stage)))
+            continue;
+
+        if (settings->op[stage].projected == proj_none)
+        {
+            proj = FALSE;
+        }
+        else if (settings->op[stage].projected == proj_count4
+                || settings->op[stage].projected == proj_count3)
+        {
+            proj = TRUE;
+        }
+        else
+        {
+            FIXME("Unexpected projection mode %d\n", settings->op[stage].projected);
+            proj = TRUE;
+        }
+
+        if (settings->op[stage].cop == WINED3D_TOP_BUMPENVMAP
+                || settings->op[stage].cop == WINED3D_TOP_BUMPENVMAP_LUMINANCE)
+            clamp = FALSE;
+        else
+            clamp = TRUE;
+
+        switch (settings->op[stage].tex_type)
+        {
+            case tex_1d:
+                if (proj)
+                {
+                    texture_function = "texture1DProj";
+                    coord_mask = "xw";
+                }
+                else
+                {
+                    texture_function = "texture1D";
+                    coord_mask = "x";
+                }
+                break;
+            case tex_2d:
+                if (proj)
+                {
+                    texture_function = "texture2DProj";
+                    coord_mask = "xyw";
+                }
+                else
+                {
+                    texture_function = "texture2D";
+                    coord_mask = "xy";
+                }
+                break;
+            case tex_3d:
+                if (proj)
+                {
+                    texture_function = "texture3DProj";
+                    coord_mask = "xyzw";
+                }
+                else
+                {
+                    texture_function = "texture3D";
+                    coord_mask = "xyz";
+                }
+                break;
+            case tex_cube:
+                texture_function = "textureCube";
+                coord_mask = "xyz";
+                break;
+            case tex_rect:
+                if (proj)
+                {
+                    texture_function = "texture2DRectProj";
+                    coord_mask = "xyw";
+                }
+                else
+                {
+                    texture_function = "texture2DRect";
+                    coord_mask = "xy";
+                }
+                break;
+            default:
+                FIXME("Unhandled texture type %#x.\n", settings->op[stage].tex_type);
+                texture_function = "";
+                coord_mask = "xyzw";
+                break;
+        }
+
+        if (stage > 0
+                && (settings->op[stage - 1].cop == WINED3D_TOP_BUMPENVMAP
+                || settings->op[stage - 1].cop == WINED3D_TOP_BUMPENVMAP_LUMINANCE))
+        {
+            shader_addline(buffer, "ret.xy = bumpenv_mat%u * tex%u.xy;\n", stage - 1, stage - 1);
+
+            /* With projective textures, texbem only divides the static
+             * texture coord, not the displacement, so multiply the
+             * displacement with the dividing parameter before passing it to
+             * TXP. */
+            if (settings->op[stage].projected != proj_none)
+            {
+                if (settings->op[stage].projected == proj_count4)
+                {
+                    shader_addline(buffer, "ret.xy = (ret.xy * gl_TexCoord[%u].w) + gl_TexCoord[%u].xy;\n",
+                            stage, stage);
+                    shader_addline(buffer, "ret.zw = gl_TexCoord[%u].ww;\n", stage);
+                }
+                else
+                {
+                    shader_addline(buffer, "ret.xy = (ret.xy * gl_TexCoord[%u].z) + gl_TexCoord[%u].xy;\n",
+                            stage, stage);
+                    shader_addline(buffer, "ret.zw = gl_TexCoord[%u].zz;\n", stage);
+                }
+            }
+            else
+            {
+                shader_addline(buffer, "ret = gl_TexCoord[%u] + ret.xyxy;\n", stage);
+            }
+
+            if (clamp)
+                shader_addline(buffer, "tex%u = clamp(%s(ps_sampler%u, ret.%s), 0.0, 1.0);\n",
+                        stage, texture_function, stage, coord_mask);
+            else
+                shader_addline(buffer, "tex%u = %s(ps_sampler%u, ret.%s);\n",
+                        stage, texture_function, stage, coord_mask);
+
+            if (settings->op[stage - 1].cop == WINED3D_TOP_BUMPENVMAP_LUMINANCE)
+                shader_addline(buffer, "tex%u *= clamp(tex%u.z * bumpenv_lum_scale%u + bumpenv_lum_offset%u, 0.0, 1.0);\n",
+                        stage, stage - 1, stage - 1, stage - 1);
+        }
+        else if (settings->op[stage].projected == proj_count3)
+        {
+            if (clamp)
+                shader_addline(buffer, "tex%u = clamp(%s(ps_sampler%u, gl_TexCoord[%u].xyz), 0.0, 1.0);\n",
+                        stage, texture_function, stage, stage);
+            else
+                shader_addline(buffer, "tex%u = %s(ps_sampler%u, gl_TexCoord[%u].xyz);\n",
+                        stage, texture_function, stage, stage);
+        }
+        else
+        {
+            if (clamp)
+                shader_addline(buffer, "tex%u = clamp(%s(ps_sampler%u, gl_TexCoord[%u].%s), 0.0, 1.0);\n",
+                        stage, texture_function, stage, stage, coord_mask);
+            else
+                shader_addline(buffer, "tex%u = %s(ps_sampler%u, gl_TexCoord[%u].%s);\n",
+                        stage, texture_function, stage, stage, coord_mask);
+        }
+
+        sprintf(tex_reg_name, "tex%u", stage);
+        shader_glsl_color_correction_ext(buffer, tex_reg_name, WINED3DSP_WRITEMASK_ALL,
+                settings->op[stage].color_fixup);
+    }
+
+    /* Generate the main shader */
+    for (stage = 0; stage < MAX_TEXTURES; ++stage)
+    {
+        BOOL op_equal;
+
+        if (settings->op[stage].cop == WINED3D_TOP_DISABLE)
+        {
+            if (!stage)
+                final_combiner_src = "gl_Color";
+            break;
+        }
+
+        if (settings->op[stage].cop == WINED3D_TOP_SELECT_ARG1
+                && settings->op[stage].aop == WINED3D_TOP_SELECT_ARG1)
+            op_equal = settings->op[stage].carg1 == settings->op[stage].aarg1;
+        else if (settings->op[stage].cop == WINED3D_TOP_SELECT_ARG1
+                && settings->op[stage].aop == WINED3D_TOP_SELECT_ARG2)
+            op_equal = settings->op[stage].carg1 == settings->op[stage].aarg2;
+        else if (settings->op[stage].cop == WINED3D_TOP_SELECT_ARG2
+                && settings->op[stage].aop == WINED3D_TOP_SELECT_ARG1)
+            op_equal = settings->op[stage].carg2 == settings->op[stage].aarg1;
+        else if (settings->op[stage].cop == WINED3D_TOP_SELECT_ARG2
+                && settings->op[stage].aop == WINED3D_TOP_SELECT_ARG2)
+            op_equal = settings->op[stage].carg2 == settings->op[stage].aarg2;
+        else
+            op_equal = settings->op[stage].aop == settings->op[stage].cop
+                    && settings->op[stage].carg0 == settings->op[stage].aarg0
+                    && settings->op[stage].carg1 == settings->op[stage].aarg1
+                    && settings->op[stage].carg2 == settings->op[stage].aarg2;
+
+        if (settings->op[stage].aop == WINED3D_TOP_DISABLE)
+        {
+            shader_glsl_ffp_fragment_op(buffer, stage, TRUE, FALSE, settings->op[stage].dst,
+                    settings->op[stage].cop, settings->op[stage].carg0,
+                    settings->op[stage].carg1, settings->op[stage].carg2);
+            if (!stage)
+                shader_addline(buffer, "ret.w = gl_Color.w;\n");
+        }
+        else if (op_equal)
+        {
+            shader_glsl_ffp_fragment_op(buffer, stage, TRUE, TRUE, settings->op[stage].dst,
+                    settings->op[stage].cop, settings->op[stage].carg0,
+                    settings->op[stage].carg1, settings->op[stage].carg2);
+        }
+        else
+        {
+            shader_glsl_ffp_fragment_op(buffer, stage, TRUE, FALSE, settings->op[stage].dst,
+                    settings->op[stage].cop, settings->op[stage].carg0,
+                    settings->op[stage].carg1, settings->op[stage].carg2);
+            shader_glsl_ffp_fragment_op(buffer, stage, FALSE, TRUE, settings->op[stage].dst,
+                    settings->op[stage].aop, settings->op[stage].aarg0,
+                    settings->op[stage].aarg1, settings->op[stage].aarg2);
+        }
+    }
+
+    shader_addline(buffer, "gl_FragData[0] = gl_SecondaryColor * specular_enable + %s;\n", final_combiner_src);
+
+    if (settings->sRGB_write)
+        shader_glsl_generate_srgb_write_correction(buffer);
+
+    shader_glsl_generate_fog_code(buffer, settings->fog);
+
+    shader_addline(buffer, "}\n");
+
+    shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB));
+    shader_glsl_compile(gl_info, shader_obj, buffer->buffer);
+    return shader_obj;
+}
+
+static struct glsl_ffp_vertex_shader *shader_glsl_find_ffp_vertex_shader(struct shader_glsl_priv *priv,
+        const struct wined3d_gl_info *gl_info, const struct wined3d_ffp_vs_settings *settings)
+{
+    struct glsl_ffp_vertex_shader *shader;
+    const struct wine_rb_entry *entry;
+
+    if ((entry = wine_rb_get(&priv->ffp_vertex_shaders, settings)))
+        return WINE_RB_ENTRY_VALUE(entry, struct glsl_ffp_vertex_shader, desc.entry);
+
+    if (!(shader = HeapAlloc(GetProcessHeap(), 0, sizeof(*shader))))
+        return NULL;
+
+    shader->desc.settings = *settings;
+    shader->id = shader_glsl_generate_ffp_vertex_shader(&priv->shader_buffer, settings, gl_info);
+    list_init(&shader->linked_programs);
+    if (wine_rb_put(&priv->ffp_vertex_shaders, &shader->desc.settings, &shader->desc.entry) == -1)
+        ERR("Failed to insert ffp vertex shader.\n");
+
+    return shader;
+}
+
+static struct glsl_ffp_fragment_shader *shader_glsl_find_ffp_fragment_shader(struct shader_glsl_priv *priv,
+        const struct wined3d_gl_info *gl_info, const struct ffp_frag_settings *args)
+{
+    struct glsl_ffp_fragment_shader *glsl_desc;
+    const struct ffp_frag_desc *desc;
+
+    if ((desc = find_ffp_frag_shader(&priv->ffp_fragment_shaders, args)))
+        return CONTAINING_RECORD(desc, struct glsl_ffp_fragment_shader, entry);
+
+    if (!(glsl_desc = HeapAlloc(GetProcessHeap(), 0, sizeof(*glsl_desc))))
+        return NULL;
+
+    glsl_desc->entry.settings = *args;
+    glsl_desc->id = shader_glsl_generate_ffp_fragment_shader(&priv->shader_buffer, args, gl_info);
+    list_init(&glsl_desc->linked_programs);
+    add_ffp_frag_shader(&priv->ffp_fragment_shaders, &glsl_desc->entry);
+
+    return glsl_desc;
+}
+
+
+static void shader_glsl_init_vs_uniform_locations(const struct wined3d_gl_info *gl_info,
+        GLhandleARB program_id, struct glsl_vs_program *vs)
+{
+    unsigned int i;
+    char name[32];
+
+    vs->uniform_f_locations = HeapAlloc(GetProcessHeap(), 0,
+            sizeof(GLhandleARB) * gl_info->limits.glsl_vs_float_constants);
+    for (i = 0; i < gl_info->limits.glsl_vs_float_constants; ++i)
+    {
+        snprintf(name, sizeof(name), "vs_c[%u]", i);
+        vs->uniform_f_locations[i] = GL_EXTCALL(glGetUniformLocationARB(program_id, name));
+    }
+
+    for (i = 0; i < MAX_CONST_I; ++i)
+    {
+        snprintf(name, sizeof(name), "vs_i[%u]", i);
+        vs->uniform_i_locations[i] = GL_EXTCALL(glGetUniformLocationARB(program_id, name));
+    }
+
+    vs->pos_fixup_location = GL_EXTCALL(glGetUniformLocationARB(program_id, "posFixup"));
+}
+
+static void shader_glsl_init_ps_uniform_locations(const struct wined3d_gl_info *gl_info,
+        GLhandleARB program_id, struct glsl_ps_program *ps)
+{
+    unsigned int i;
+    char name[32];
+
+    ps->uniform_f_locations = HeapAlloc(GetProcessHeap(), 0,
+            sizeof(GLhandleARB) * gl_info->limits.glsl_ps_float_constants);
+    for (i = 0; i < gl_info->limits.glsl_ps_float_constants; ++i)
+    {
+        snprintf(name, sizeof(name), "ps_c[%u]", i);
+        ps->uniform_f_locations[i] = GL_EXTCALL(glGetUniformLocationARB(program_id, name));
+    }
+
+    for (i = 0; i < MAX_CONST_I; ++i)
+    {
+        snprintf(name, sizeof(name), "ps_i[%u]", i);
+        ps->uniform_i_locations[i] = GL_EXTCALL(glGetUniformLocationARB(program_id, name));
+    }
+
+    for (i = 0; i < MAX_TEXTURES; ++i)
+    {
+        snprintf(name, sizeof(name), "bumpenv_mat%u", i);
+        ps->bumpenv_mat_location[i] = GL_EXTCALL(glGetUniformLocationARB(program_id, name));
+        snprintf(name, sizeof(name), "bumpenv_lum_scale%u", i);
+        ps->bumpenv_lum_scale_location[i] = GL_EXTCALL(glGetUniformLocationARB(program_id, name));
+        snprintf(name, sizeof(name), "bumpenv_lum_offset%u", i);
+        ps->bumpenv_lum_offset_location[i] = GL_EXTCALL(glGetUniformLocationARB(program_id, name));
+    }
+
+    ps->tex_factor_location = GL_EXTCALL(glGetUniformLocationARB(program_id, "tex_factor"));
+    ps->specular_enable_location = GL_EXTCALL(glGetUniformLocationARB(program_id, "specular_enable"));
+    ps->np2_fixup_location = GL_EXTCALL(glGetUniformLocationARB(program_id, "ps_samplerNP2Fixup"));
+    ps->ycorrection_location = GL_EXTCALL(glGetUniformLocationARB(program_id, "ycorrection"));
+}
+
+/* Context activation is done by the caller. */
+static void set_glsl_shader_program(const struct wined3d_context *context, const struct wined3d_state *state,
+        struct shader_glsl_priv *priv)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    const struct ps_np2fixup_info *np2fixup_info = NULL;
+    struct glsl_shader_prog_link *entry = NULL;
+    struct wined3d_shader *vshader = NULL;
+    struct wined3d_shader *gshader = NULL;
+    struct wined3d_shader *pshader = NULL;
+    GLhandleARB programId                  = 0;
+    GLhandleARB reorder_shader_id          = 0;
+    unsigned int i;
+    struct ps_compile_args ps_compile_args;
+    struct vs_compile_args vs_compile_args;
+    GLhandleARB vs_id, gs_id, ps_id;
+    struct list *ps_list, *vs_list;
+    struct wined3d_device *device = context->swapchain->device;
+
+    if (use_vs(state))
+    {
+        vshader = state->vertex_shader;
+        find_vs_compile_args(state, vshader, &vs_compile_args);
+        vs_id = find_glsl_vshader(context, &priv->shader_buffer, vshader, &vs_compile_args);
+        vs_list = &vshader->linked_programs;
+
+        if ((gshader = state->geometry_shader))
+            gs_id = find_glsl_geometry_shader(context, &priv->shader_buffer, gshader);
+        else
+            gs_id = 0;
+    }
+    else if (priv->vertex_pipe == &glsl_vertex_pipe)
+    {
+        struct glsl_ffp_vertex_shader *ffp_shader;
+        struct wined3d_ffp_vs_settings settings;
+
+        wined3d_ffp_get_vs_settings(state, &device->stream_info, &settings);
+        ffp_shader = shader_glsl_find_ffp_vertex_shader(priv, gl_info, &settings);
+        vs_id = ffp_shader->id;
+        vs_list = &ffp_shader->linked_programs;
+
+        gs_id = 0;
+    }
+    else
+    {
+        vs_id = 0;
+        gs_id = 0;
+    }
+
+    if (use_ps(state))
+    {
+        pshader = state->pixel_shader;
+        find_ps_compile_args(state, pshader, &ps_compile_args);
+        ps_id = find_glsl_pshader(context, &priv->shader_buffer,
+                pshader, &ps_compile_args, &np2fixup_info);
+        ps_list = &pshader->linked_programs;
+    }
+    else if (priv->fragment_pipe == &glsl_fragment_pipe)
+    {
+        struct glsl_ffp_fragment_shader *ffp_shader;
+        struct ffp_frag_settings settings;
+
+        gen_ffp_frag_op(context, state, &settings, FALSE);
+        ffp_shader = shader_glsl_find_ffp_fragment_shader(priv, gl_info, &settings);
+        ps_id = ffp_shader->id;
+        ps_list = &ffp_shader->linked_programs;
+    }
+    else
+    {
+        ps_id = 0;
+    }
+
+    if ((!vs_id && !gs_id && !ps_id) || (entry = get_glsl_program_entry(priv, vs_id, gs_id, ps_id)))
+    {
+        priv->glsl_program = entry;
+        return;
+    }
+
+    /* If we get to this point, then no matching program exists, so we create one */
+    programId = GL_EXTCALL(glCreateProgramObjectARB());
+    TRACE("Created new GLSL shader program %u\n", programId);
+
+    /* Create the entry */
+    entry = HeapAlloc(GetProcessHeap(), 0, sizeof(struct glsl_shader_prog_link));
+    entry->programId = programId;
+    entry->vs.id = vs_id;
+    entry->gs.id = gs_id;
+    entry->ps.id = ps_id;
+    entry->constant_version = 0;
+    entry->ps.np2_fixup_info = np2fixup_info;
+    /* Add the hash table entry */
+    add_glsl_program_entry(priv, entry);
+
+    /* Set the current program */
+    priv->glsl_program = entry;
+
+    /* Attach GLSL vshader */
+    if (vs_id)
+    {
+        TRACE("Attaching GLSL shader object %u to program %u.\n", vs_id, programId);
+        GL_EXTCALL(glAttachObjectARB(programId, vs_id));
+        checkGLcall("glAttachObjectARB");
+
+        list_add_head(vs_list, &entry->vs.shader_entry);
+    }
+
+    if (vshader)
+    {
+        WORD map = vshader->reg_maps.input_registers;
+        char tmp_name[10];
+
+        reorder_shader_id = generate_param_reorder_function(&priv->shader_buffer, vshader, pshader, gl_info);
+        TRACE("Attaching GLSL shader object %u to program %u\n", reorder_shader_id, programId);
+        GL_EXTCALL(glAttachObjectARB(programId, reorder_shader_id));
+        checkGLcall("glAttachObjectARB");
+        /* Flag the reorder function for deletion, then it will be freed automatically when the program
+         * is destroyed
+         */
+        GL_EXTCALL(glDeleteObjectARB(reorder_shader_id));
+
+        /* Bind vertex attributes to a corresponding index number to match
+         * the same index numbers as ARB_vertex_programs (makes loading
+         * vertex attributes simpler).  With this method, we can use the
+         * exact same code to load the attributes later for both ARB and
+         * GLSL shaders.
+         *
+         * We have to do this here because we need to know the Program ID
+         * in order to make the bindings work, and it has to be done prior
+         * to linking the GLSL program. */
+        for (i = 0; map; map >>= 1, ++i)
+        {
+            if (!(map & 1)) continue;
+
+            snprintf(tmp_name, sizeof(tmp_name), "vs_in%u", i);
+            GL_EXTCALL(glBindAttribLocationARB(programId, i, tmp_name));
+        }
+        checkGLcall("glBindAttribLocationARB");
+    }
+
+    if (gshader)
+    {
+        TRACE("Attaching GLSL geometry shader object %u to program %u.\n", gs_id, programId);
+        GL_EXTCALL(glAttachObjectARB(programId, gs_id));
+        checkGLcall("glAttachObjectARB");
+
+        TRACE("input type %s, output type %s, vertices out %u.\n",
+                debug_d3dprimitivetype(gshader->u.gs.input_type),
+                debug_d3dprimitivetype(gshader->u.gs.output_type),
+                gshader->u.gs.vertices_out);
+        GL_EXTCALL(glProgramParameteriARB(programId, GL_GEOMETRY_INPUT_TYPE_ARB,
+                gl_primitive_type_from_d3d(gshader->u.gs.input_type)));
+        GL_EXTCALL(glProgramParameteriARB(programId, GL_GEOMETRY_OUTPUT_TYPE_ARB,
+                gl_primitive_type_from_d3d(gshader->u.gs.output_type)));
+        GL_EXTCALL(glProgramParameteriARB(programId, GL_GEOMETRY_VERTICES_OUT_ARB,
+                gshader->u.gs.vertices_out));
+        checkGLcall("glProgramParameteriARB");
+
+        list_add_head(&gshader->linked_programs, &entry->gs.shader_entry);
+    }
+
+    /* Attach GLSL pshader */
+    if (ps_id)
+    {
+        TRACE("Attaching GLSL shader object %u to program %u.\n", ps_id, programId);
+        GL_EXTCALL(glAttachObjectARB(programId, ps_id));
+        checkGLcall("glAttachObjectARB");
+
+        list_add_head(ps_list, &entry->ps.shader_entry);
+    }
+
+    /* Link the program */
+    TRACE("Linking GLSL shader program %u\n", programId);
+    GL_EXTCALL(glLinkProgramARB(programId));
+    shader_glsl_validate_link(gl_info, programId);
+
+    shader_glsl_init_vs_uniform_locations(gl_info, programId, &entry->vs);
+    shader_glsl_init_ps_uniform_locations(gl_info, programId, &entry->ps);
+    checkGLcall("Find glsl program uniform locations");
+
+    if (pshader && pshader->reg_maps.shader_version.major >= 3
+            && pshader->u.ps.declared_in_count > vec4_varyings(3, gl_info))
+    {
+        TRACE("Shader %d needs vertex color clamping disabled\n", programId);
+        entry->vs.vertex_color_clamp = GL_FALSE;
+    }
+    else
+    {
+        entry->vs.vertex_color_clamp = GL_FIXED_ONLY_ARB;
+    }
+
+    /* Set the shader to allow uniform loading on it */
+    GL_EXTCALL(glUseProgramObjectARB(programId));
+    checkGLcall("glUseProgramObjectARB(programId)");
+
+    /* Load the vertex and pixel samplers now. The function that finds the mappings makes sure
+     * that it stays the same for each vertexshader-pixelshader pair(=linked glsl program). If
+     * a pshader with fixed function pipeline is used there are no vertex samplers, and if a
+     * vertex shader with fixed function pixel processing is used we make sure that the card
+     * supports enough samplers to allow the max number of vertex samplers with all possible
+     * fixed function fragment processing setups. So once the program is linked these samplers
+     * won't change.
+     */
+    shader_glsl_load_vsamplers(gl_info, device->texUnitMap, programId);
+    shader_glsl_load_psamplers(gl_info, device->texUnitMap, programId);
+}
+
+/* Context activation is done by the caller. */
+static GLhandleARB create_glsl_blt_shader(const struct wined3d_gl_info *gl_info, enum tex_types tex_type, BOOL masked)
+{
+    GLhandleARB program_id;
+    GLhandleARB vshader_id, pshader_id;
+    const char *blt_pshader;
+
+    static const char *blt_vshader =
+        "#version 120\n"
+        "void main(void)\n"
+        "{\n"
+        "    gl_Position = gl_Vertex;\n"
+        "    gl_FrontColor = vec4(1.0);\n"
+        "    gl_TexCoord[0] = gl_MultiTexCoord0;\n"
+        "}\n";
+
+    static const char * const blt_pshaders_full[tex_type_count] =
+    {
+        /* tex_1d */
+        NULL,
+        /* tex_2d */
+        "#version 120\n"
+        "uniform sampler2D sampler;\n"
+        "void main(void)\n"
+        "{\n"
+        "    gl_FragDepth = texture2D(sampler, gl_TexCoord[0].xy).x;\n"
+        "}\n",
+        /* tex_3d */
+        NULL,
+        /* tex_cube */
+        "#version 120\n"
+        "uniform samplerCube sampler;\n"
+        "void main(void)\n"
+        "{\n"
+        "    gl_FragDepth = textureCube(sampler, gl_TexCoord[0].xyz).x;\n"
+        "}\n",
+        /* tex_rect */
+        "#version 120\n"
+        "#extension GL_ARB_texture_rectangle : enable\n"
+        "uniform sampler2DRect sampler;\n"
+        "void main(void)\n"
+        "{\n"
+        "    gl_FragDepth = texture2DRect(sampler, gl_TexCoord[0].xy).x;\n"
+        "}\n",
+    };
+
+    static const char * const blt_pshaders_masked[tex_type_count] =
+    {
+        /* tex_1d */
+        NULL,
+        /* tex_2d */
+        "#version 120\n"
+        "uniform sampler2D sampler;\n"
+        "uniform vec4 mask;\n"
+        "void main(void)\n"
+        "{\n"
+        "    if (all(lessThan(gl_FragCoord.xy, mask.zw))) discard;\n"
+        "    gl_FragDepth = texture2D(sampler, gl_TexCoord[0].xy).x;\n"
+        "}\n",
+        /* tex_3d */
+        NULL,
+        /* tex_cube */
+        "#version 120\n"
+        "uniform samplerCube sampler;\n"
+        "uniform vec4 mask;\n"
+        "void main(void)\n"
+        "{\n"
+        "    if (all(lessThan(gl_FragCoord.xy, mask.zw))) discard;\n"
+        "    gl_FragDepth = textureCube(sampler, gl_TexCoord[0].xyz).x;\n"
+        "}\n",
+        /* tex_rect */
+        "#version 120\n"
+        "#extension GL_ARB_texture_rectangle : enable\n"
+        "uniform sampler2DRect sampler;\n"
+        "uniform vec4 mask;\n"
+        "void main(void)\n"
+        "{\n"
+        "    if (all(lessThan(gl_FragCoord.xy, mask.zw))) discard;\n"
+        "    gl_FragDepth = texture2DRect(sampler, gl_TexCoord[0].xy).x;\n"
+        "}\n",
+    };
+
+    blt_pshader = masked ? blt_pshaders_masked[tex_type] : blt_pshaders_full[tex_type];
+    if (!blt_pshader)
+    {
+        FIXME("tex_type %#x not supported\n", tex_type);
+        return 0;
+    }
+
+    vshader_id = GL_EXTCALL(glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB));
+    shader_glsl_compile(gl_info, vshader_id, blt_vshader);
+
+    pshader_id = GL_EXTCALL(glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB));
+    shader_glsl_compile(gl_info, pshader_id, blt_pshader);
+
+    program_id = GL_EXTCALL(glCreateProgramObjectARB());
+    GL_EXTCALL(glAttachObjectARB(program_id, vshader_id));
+    GL_EXTCALL(glAttachObjectARB(program_id, pshader_id));
+    GL_EXTCALL(glLinkProgramARB(program_id));
+
+    shader_glsl_validate_link(gl_info, program_id);
+
+    /* Once linked we can mark the shaders for deletion. They will be deleted once the program
+     * is destroyed
+     */
+    GL_EXTCALL(glDeleteObjectARB(vshader_id));
+    GL_EXTCALL(glDeleteObjectARB(pshader_id));
+    return program_id;
+}
+
+/* Context activation is done by the caller. */
+static void shader_glsl_select(void *shader_priv, const struct wined3d_context *context,
+        const struct wined3d_state *state)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    struct shader_glsl_priv *priv = shader_priv;
+    GLhandleARB program_id = 0;
+    GLenum old_vertex_color_clamp, current_vertex_color_clamp;
+
+    priv->vertex_pipe->vp_enable(gl_info, !use_vs(state));
+    priv->fragment_pipe->enable_extension(gl_info, !use_ps(state));
+
+    old_vertex_color_clamp = priv->glsl_program ? priv->glsl_program->vs.vertex_color_clamp : GL_FIXED_ONLY_ARB;
+    set_glsl_shader_program(context, state, priv);
+    current_vertex_color_clamp = priv->glsl_program ? priv->glsl_program->vs.vertex_color_clamp : GL_FIXED_ONLY_ARB;
+    if (old_vertex_color_clamp != current_vertex_color_clamp)
+    {
+        if (gl_info->supported[ARB_COLOR_BUFFER_FLOAT])
+        {
+            GL_EXTCALL(glClampColorARB(GL_CLAMP_VERTEX_COLOR_ARB, current_vertex_color_clamp));
+            checkGLcall("glClampColorARB");
+        }
+        else
+        {
+            FIXME("vertex color clamp needs to be changed, but extension not supported.\n");
+        }
+    }
+
+    program_id = priv->glsl_program ? priv->glsl_program->programId : 0;
+    if (program_id) TRACE("Using GLSL program %u\n", program_id);
+    GL_EXTCALL(glUseProgramObjectARB(program_id));
+    checkGLcall("glUseProgramObjectARB");
+
+    /* In case that NP2 texcoord fixup data is found for the selected program, trigger a reload of the
+     * constants. This has to be done because it can't be guaranteed that sampler() (from state.c) is
+     * called between selecting the shader and using it, which results in wrong fixup for some frames. */
+    if (priv->glsl_program && priv->glsl_program->ps.np2_fixup_info)
+    {
+        shader_glsl_load_np2fixup_constants(priv, gl_info, state);
+    }
+}
+
+/* Context activation is done by the caller. */
+static void shader_glsl_disable(void *shader_priv, const struct wined3d_context *context)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    struct shader_glsl_priv *priv = shader_priv;
+
+    priv->glsl_program = NULL;
+    GL_EXTCALL(glUseProgramObjectARB(0));
+    checkGLcall("glUseProgramObjectARB");
+
+    priv->vertex_pipe->vp_enable(gl_info, FALSE);
+    priv->fragment_pipe->enable_extension(gl_info, FALSE);
+
+    if (gl_info->supported[ARB_COLOR_BUFFER_FLOAT])
+    {
+        GL_EXTCALL(glClampColorARB(GL_CLAMP_VERTEX_COLOR_ARB, GL_FIXED_ONLY_ARB));
+        checkGLcall("glClampColorARB");
+    }
+}
+
+/* Context activation is done by the caller. */
+static void shader_glsl_select_depth_blt(void *shader_priv, const struct wined3d_gl_info *gl_info,
+        enum tex_types tex_type, const SIZE *ds_mask_size)
+{
+    BOOL masked = ds_mask_size->cx && ds_mask_size->cy;
+    struct shader_glsl_priv *priv = shader_priv;
+    GLhandleARB *blt_program;
+    GLint loc;
+
+    blt_program = masked ? &priv->depth_blt_program_masked[tex_type] : &priv->depth_blt_program_full[tex_type];
+    if (!*blt_program)
+    {
+        *blt_program = create_glsl_blt_shader(gl_info, tex_type, masked);
+        loc = GL_EXTCALL(glGetUniformLocationARB(*blt_program, "sampler"));
+        GL_EXTCALL(glUseProgramObjectARB(*blt_program));
+        GL_EXTCALL(glUniform1iARB(loc, 0));
+    }
+    else
+    {
+        GL_EXTCALL(glUseProgramObjectARB(*blt_program));
+    }
+
+    if (masked)
+    {
+        loc = GL_EXTCALL(glGetUniformLocationARB(*blt_program, "mask"));
+        GL_EXTCALL(glUniform4fARB(loc, 0.0f, 0.0f, (float)ds_mask_size->cx, (float)ds_mask_size->cy));
+    }
+}
+
+/* Context activation is done by the caller. */
+static void shader_glsl_deselect_depth_blt(void *shader_priv, const struct wined3d_gl_info *gl_info)
+{
+    struct shader_glsl_priv *priv = shader_priv;
+    GLhandleARB program_id;
+
+    program_id = priv->glsl_program ? priv->glsl_program->programId : 0;
+    if (program_id) TRACE("Using GLSL program %u\n", program_id);
+
+    GL_EXTCALL(glUseProgramObjectARB(program_id));
+    checkGLcall("glUseProgramObjectARB");
+}
+
+static void shader_glsl_destroy(struct wined3d_shader *shader)
+{
+    struct glsl_shader_private *shader_data = shader->backend_data;
+    struct wined3d_device *device = shader->device;
+    struct shader_glsl_priv *priv = device->shader_priv;
+    const struct wined3d_gl_info *gl_info;
+    const struct list *linked_programs;
+    struct wined3d_context *context;
+
+    if (!shader_data || !shader_data->num_gl_shaders)
+    {
+        HeapFree(GetProcessHeap(), 0, shader_data);
+        shader->backend_data = NULL;
+        return;
+    }
+
+    context = context_acquire(device, NULL);
+    gl_info = context->gl_info;
+
+    TRACE("Deleting linked programs.\n");
+    linked_programs = &shader->linked_programs;
+    if (linked_programs->next)
+    {
+        struct glsl_shader_prog_link *entry, *entry2;
+        UINT i;
+
+        switch (shader->reg_maps.shader_version.type)
+        {
+            case WINED3D_SHADER_TYPE_PIXEL:
+            {
+                struct glsl_ps_compiled_shader *gl_shaders = shader_data->gl_shaders.ps;
+
+                LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs,
+                        struct glsl_shader_prog_link, ps.shader_entry)
+                {
+                    delete_glsl_program_entry(priv, gl_info, entry);
+                }
+
+                for (i = 0; i < shader_data->num_gl_shaders; ++i)
+                {
+                    TRACE("Deleting pixel shader %u.\n", gl_shaders[i].prgId);
+                    if (priv->glsl_program && priv->glsl_program->ps.id == gl_shaders[i].prgId)
+                        shader_glsl_disable(priv, context);
+                    GL_EXTCALL(glDeleteObjectARB(gl_shaders[i].prgId));
+                    checkGLcall("glDeleteObjectARB");
+                }
+                HeapFree(GetProcessHeap(), 0, shader_data->gl_shaders.ps);
+
+                break;
+            }
+
+            case WINED3D_SHADER_TYPE_VERTEX:
+            {
+                struct glsl_vs_compiled_shader *gl_shaders = shader_data->gl_shaders.vs;
+
+                LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs,
+                        struct glsl_shader_prog_link, vs.shader_entry)
+                {
+                    delete_glsl_program_entry(priv, gl_info, entry);
+                }
+
+                for (i = 0; i < shader_data->num_gl_shaders; ++i)
+                {
+                    TRACE("Deleting vertex shader %u.\n", gl_shaders[i].prgId);
+                    if (priv->glsl_program && priv->glsl_program->vs.id == gl_shaders[i].prgId)
+                        shader_glsl_disable(priv, context);
+                    GL_EXTCALL(glDeleteObjectARB(gl_shaders[i].prgId));
+                    checkGLcall("glDeleteObjectARB");
+                }
+                HeapFree(GetProcessHeap(), 0, shader_data->gl_shaders.vs);
+
+                break;
+            }
+
+            case WINED3D_SHADER_TYPE_GEOMETRY:
+            {
+                struct glsl_gs_compiled_shader *gl_shaders = shader_data->gl_shaders.gs;
+
+                LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs,
+                        struct glsl_shader_prog_link, gs.shader_entry)
+                {
+                    delete_glsl_program_entry(priv, gl_info, entry);
+                }
+
+                for (i = 0; i < shader_data->num_gl_shaders; ++i)
+                {
+                    TRACE("Deleting geometry shader %u.\n", gl_shaders[i].id);
+                    if (priv->glsl_program && priv->glsl_program->gs.id == gl_shaders[i].id)
+                        shader_glsl_disable(priv, context);
+                    GL_EXTCALL(glDeleteObjectARB(gl_shaders[i].id));
+                    checkGLcall("glDeleteObjectARB");
+                }
+                HeapFree(GetProcessHeap(), 0, shader_data->gl_shaders.gs);
+
+                break;
+            }
+
+            default:
+                ERR("Unhandled shader type %#x.\n", shader->reg_maps.shader_version.type);
+                break;
+        }
+    }
+
+    HeapFree(GetProcessHeap(), 0, shader->backend_data);
+    shader->backend_data = NULL;
+
+    context_release(context);
+}
+
+static int glsl_program_key_compare(const void *key, const struct wine_rb_entry *entry)
+{
+    const struct glsl_program_key *k = key;
+    const struct glsl_shader_prog_link *prog = WINE_RB_ENTRY_VALUE(entry,
+            const struct glsl_shader_prog_link, program_lookup_entry);
+
+    if (k->vs_id > prog->vs.id) return 1;
+    else if (k->vs_id < prog->vs.id) return -1;
+
+    if (k->gs_id > prog->gs.id) return 1;
+    else if (k->gs_id < prog->gs.id) return -1;
+
+    if (k->ps_id > prog->ps.id) return 1;
+    else if (k->ps_id < prog->ps.id) return -1;
+
+    return 0;
+}
+
+static BOOL constant_heap_init(struct constant_heap *heap, unsigned int constant_count)
+{
+    SIZE_T size = (constant_count + 1) * sizeof(*heap->entries) + constant_count * sizeof(*heap->positions);
+    void *mem = HeapAlloc(GetProcessHeap(), 0, size);
+
+    if (!mem)
+    {
+        ERR("Failed to allocate memory\n");
+        return FALSE;
+    }
+
+    heap->entries = mem;
+    heap->entries[1].version = 0;
+    heap->positions = (unsigned int *)(heap->entries + constant_count + 1);
+    heap->size = 1;
+
+    return TRUE;
+}
+
+static void constant_heap_free(struct constant_heap *heap)
+{
+    HeapFree(GetProcessHeap(), 0, heap->entries);
+}
+
+static const struct wine_rb_functions wined3d_glsl_program_rb_functions =
+{
+    wined3d_rb_alloc,
+    wined3d_rb_realloc,
+    wined3d_rb_free,
+    glsl_program_key_compare,
+};
+
+static HRESULT shader_glsl_alloc(struct wined3d_device *device, const struct wined3d_vertex_pipe_ops *vertex_pipe,
+        const struct fragment_pipeline *fragment_pipe)
+{
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    struct shader_glsl_priv *priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct shader_glsl_priv));
+    SIZE_T stack_size = wined3d_log2i(max(gl_info->limits.glsl_vs_float_constants,
+            gl_info->limits.glsl_ps_float_constants)) + 1;
+    struct fragment_caps fragment_caps;
+    void *vertex_priv, *fragment_priv;
+
+    if (!(vertex_priv = vertex_pipe->vp_alloc(&glsl_shader_backend, priv)))
+    {
+        ERR("Failed to initialize vertex pipe.\n");
+        HeapFree(GetProcessHeap(), 0, priv);
+        return E_FAIL;
+    }
+
+    if (!(fragment_priv = fragment_pipe->alloc_private(&glsl_shader_backend, priv)))
+    {
+        ERR("Failed to initialize fragment pipe.\n");
+        vertex_pipe->vp_free(device);
+        HeapFree(GetProcessHeap(), 0, priv);
+        return E_FAIL;
+    }
+
+    if (!shader_buffer_init(&priv->shader_buffer))
+    {
+        ERR("Failed to initialize shader buffer.\n");
+        goto fail;
+    }
+
+    priv->stack = HeapAlloc(GetProcessHeap(), 0, stack_size * sizeof(*priv->stack));
+    if (!priv->stack)
+    {
+        ERR("Failed to allocate memory.\n");
+        goto fail;
+    }
+
+    if (!constant_heap_init(&priv->vconst_heap, gl_info->limits.glsl_vs_float_constants))
+    {
+        ERR("Failed to initialize vertex shader constant heap\n");
+        goto fail;
+    }
+
+    if (!constant_heap_init(&priv->pconst_heap, gl_info->limits.glsl_ps_float_constants))
+    {
+        ERR("Failed to initialize pixel shader constant heap\n");
+        goto fail;
+    }
+
+    if (wine_rb_init(&priv->program_lookup, &wined3d_glsl_program_rb_functions) == -1)
+    {
+        ERR("Failed to initialize rbtree.\n");
+        goto fail;
+    }
+
+    priv->next_constant_version = 1;
+    priv->vertex_pipe = vertex_pipe;
+    priv->fragment_pipe = fragment_pipe;
+    fragment_pipe->get_caps(gl_info, &fragment_caps);
+    priv->ffp_proj_control = fragment_caps.wined3d_caps & WINED3D_FRAGMENT_CAP_PROJ_CONTROL;
+
+    device->vertex_priv = vertex_priv;
+    device->fragment_priv = fragment_priv;
+    device->shader_priv = priv;
+
+    return WINED3D_OK;
+
+fail:
+    constant_heap_free(&priv->pconst_heap);
+    constant_heap_free(&priv->vconst_heap);
+    HeapFree(GetProcessHeap(), 0, priv->stack);
+    shader_buffer_free(&priv->shader_buffer);
+    fragment_pipe->free_private(device);
+    vertex_pipe->vp_free(device);
+    HeapFree(GetProcessHeap(), 0, priv);
+    return E_OUTOFMEMORY;
+}
+
+/* Context activation is done by the caller. */
+static void shader_glsl_free(struct wined3d_device *device)
+{
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    struct shader_glsl_priv *priv = device->shader_priv;
+    int i;
+
+    for (i = 0; i < tex_type_count; ++i)
+    {
+        if (priv->depth_blt_program_full[i])
+        {
+            GL_EXTCALL(glDeleteObjectARB(priv->depth_blt_program_full[i]));
+        }
+        if (priv->depth_blt_program_masked[i])
+        {
+            GL_EXTCALL(glDeleteObjectARB(priv->depth_blt_program_masked[i]));
+        }
+    }
+
+    wine_rb_destroy(&priv->program_lookup, NULL, NULL);
+    constant_heap_free(&priv->pconst_heap);
+    constant_heap_free(&priv->vconst_heap);
+    HeapFree(GetProcessHeap(), 0, priv->stack);
+    shader_buffer_free(&priv->shader_buffer);
+    priv->fragment_pipe->free_private(device);
+    priv->vertex_pipe->vp_free(device);
+
+    HeapFree(GetProcessHeap(), 0, device->shader_priv);
+    device->shader_priv = NULL;
+}
+
+static void shader_glsl_context_destroyed(void *shader_priv, const struct wined3d_context *context) {}
+
+static void shader_glsl_get_caps(const struct wined3d_gl_info *gl_info, struct shader_caps *caps)
+{
+    UINT shader_model;
+
+    if (gl_info->supported[EXT_GPU_SHADER4] && gl_info->supported[ARB_SHADER_BIT_ENCODING]
+            && gl_info->supported[ARB_GEOMETRY_SHADER4] && gl_info->glsl_version >= MAKEDWORD_VERSION(1, 50)
+            && gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX] && gl_info->supported[ARB_DRAW_INSTANCED])
+        shader_model = 4;
+    /* ARB_shader_texture_lod or EXT_gpu_shader4 is required for the SM3
+     * texldd and texldl instructions. */
+    else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD] || gl_info->supported[EXT_GPU_SHADER4])
+        shader_model = 3;
+    else
+        shader_model = 2;
+    TRACE("Shader model %u.\n", shader_model);
+
+    caps->vs_version = min(wined3d_settings.max_sm_vs, shader_model);
+    caps->gs_version = min(wined3d_settings.max_sm_gs, shader_model);
+    caps->ps_version = min(wined3d_settings.max_sm_ps, shader_model);
+
+    caps->vs_uniform_count = gl_info->limits.glsl_vs_float_constants;
+    caps->ps_uniform_count = gl_info->limits.glsl_ps_float_constants;
+
+    /* FIXME: The following line is card dependent. -8.0 to 8.0 is the
+     * Direct3D minimum requirement.
+     *
+     * Both GL_ARB_fragment_program and GLSL require a "maximum representable magnitude"
+     * of colors to be 2^10, and 2^32 for other floats. Should we use 1024 here?
+     *
+     * The problem is that the refrast clamps temporary results in the shader to
+     * [-MaxValue;+MaxValue]. If the card's max value is bigger than the one we advertize here,
+     * then applications may miss the clamping behavior. On the other hand, if it is smaller,
+     * the shader will generate incorrect results too. Unfortunately, GL deliberately doesn't
+     * offer a way to query this.
+     */
+    caps->ps_1x_max_value = 8.0;
+
+    /* Ideally we'd only set caps like sRGB writes here if supported by both
+     * the shader backend and the fragment pipe, but we can get called before
+     * shader_glsl_alloc(). */
+    caps->wined3d_caps = WINED3D_SHADER_CAP_VS_CLIPPING
+            | WINED3D_SHADER_CAP_SRGB_WRITE;
+}
+
+static BOOL shader_glsl_color_fixup_supported(struct color_fixup_desc fixup)
+{
+    if (TRACE_ON(d3d_shader) && TRACE_ON(d3d))
+    {
+        TRACE("Checking support for fixup:\n");
+        dump_color_fixup_desc(fixup);
+    }
+
+    /* We support everything except YUV conversions. */
+    if (!is_complex_fixup(fixup))
+    {
+        TRACE("[OK]\n");
+        return TRUE;
+    }
+
+    TRACE("[FAILED]\n");
+    return FALSE;
+}
+
+static const SHADER_HANDLER shader_glsl_instruction_handler_table[WINED3DSIH_TABLE_SIZE] =
+{
+    /* WINED3DSIH_ABS                   */ shader_glsl_map2gl,
+    /* WINED3DSIH_ADD                   */ shader_glsl_binop,
+    /* WINED3DSIH_AND                   */ shader_glsl_binop,
+    /* WINED3DSIH_BEM                   */ shader_glsl_bem,
+    /* WINED3DSIH_BREAK                 */ shader_glsl_break,
+    /* WINED3DSIH_BREAKC                */ shader_glsl_breakc,
+    /* WINED3DSIH_BREAKP                */ shader_glsl_breakp,
+    /* WINED3DSIH_CALL                  */ shader_glsl_call,
+    /* WINED3DSIH_CALLNZ                */ shader_glsl_callnz,
+    /* WINED3DSIH_CMP                   */ shader_glsl_conditional_move,
+    /* WINED3DSIH_CND                   */ shader_glsl_cnd,
+    /* WINED3DSIH_CRS                   */ shader_glsl_cross,
+    /* WINED3DSIH_CUT                   */ shader_glsl_cut,
+    /* WINED3DSIH_DCL                   */ shader_glsl_nop,
+    /* WINED3DSIH_DCL_CONSTANT_BUFFER   */ shader_glsl_nop,
+    /* WINED3DSIH_DCL_INPUT_PRIMITIVE   */ shader_glsl_nop,
+    /* WINED3DSIH_DCL_OUTPUT_TOPOLOGY   */ shader_glsl_nop,
+    /* WINED3DSIH_DCL_VERTICES_OUT      */ shader_glsl_nop,
+    /* WINED3DSIH_DEF                   */ shader_glsl_nop,
+    /* WINED3DSIH_DEFB                  */ shader_glsl_nop,
+    /* WINED3DSIH_DEFI                  */ shader_glsl_nop,
+    /* WINED3DSIH_DIV                   */ shader_glsl_binop,
+    /* WINED3DSIH_DP2ADD                */ shader_glsl_dp2add,
+    /* WINED3DSIH_DP3                   */ shader_glsl_dot,
+    /* WINED3DSIH_DP4                   */ shader_glsl_dot,
+    /* WINED3DSIH_DST                   */ shader_glsl_dst,
+    /* WINED3DSIH_DSX                   */ shader_glsl_map2gl,
+    /* WINED3DSIH_DSY                   */ shader_glsl_map2gl,
+    /* WINED3DSIH_ELSE                  */ shader_glsl_else,
+    /* WINED3DSIH_EMIT                  */ shader_glsl_emit,
+    /* WINED3DSIH_ENDIF                 */ shader_glsl_end,
+    /* WINED3DSIH_ENDLOOP               */ shader_glsl_end,
+    /* WINED3DSIH_ENDREP                */ shader_glsl_end,
+    /* WINED3DSIH_EQ                    */ shader_glsl_relop,
+    /* WINED3DSIH_EXP                   */ shader_glsl_map2gl,
+    /* WINED3DSIH_EXPP                  */ shader_glsl_expp,
+    /* WINED3DSIH_FRC                   */ shader_glsl_map2gl,
+    /* WINED3DSIH_FTOI                  */ shader_glsl_to_int,
+    /* WINED3DSIH_GE                    */ shader_glsl_relop,
+    /* WINED3DSIH_IADD                  */ shader_glsl_binop,
+    /* WINED3DSIH_IEQ                   */ NULL,
+    /* WINED3DSIH_IF                    */ shader_glsl_if,
+    /* WINED3DSIH_IFC                   */ shader_glsl_ifc,
+    /* WINED3DSIH_IGE                   */ shader_glsl_relop,
+    /* WINED3DSIH_IMUL                  */ shader_glsl_imul,
+    /* WINED3DSIH_ITOF                  */ shader_glsl_to_float,
+    /* WINED3DSIH_LABEL                 */ shader_glsl_label,
+    /* WINED3DSIH_LD                    */ NULL,
+    /* WINED3DSIH_LIT                   */ shader_glsl_lit,
+    /* WINED3DSIH_LOG                   */ shader_glsl_log,
+    /* WINED3DSIH_LOGP                  */ shader_glsl_log,
+    /* WINED3DSIH_LOOP                  */ shader_glsl_loop,
+    /* WINED3DSIH_LRP                   */ shader_glsl_lrp,
+    /* WINED3DSIH_LT                    */ shader_glsl_relop,
+    /* WINED3DSIH_M3x2                  */ shader_glsl_mnxn,
+    /* WINED3DSIH_M3x3                  */ shader_glsl_mnxn,
+    /* WINED3DSIH_M3x4                  */ shader_glsl_mnxn,
+    /* WINED3DSIH_M4x3                  */ shader_glsl_mnxn,
+    /* WINED3DSIH_M4x4                  */ shader_glsl_mnxn,
+    /* WINED3DSIH_MAD                   */ shader_glsl_mad,
+    /* WINED3DSIH_MAX                   */ shader_glsl_map2gl,
+    /* WINED3DSIH_MIN                   */ shader_glsl_map2gl,
+    /* WINED3DSIH_MOV                   */ shader_glsl_mov,
+    /* WINED3DSIH_MOVA                  */ shader_glsl_mov,
+    /* WINED3DSIH_MOVC                  */ shader_glsl_conditional_move,
+    /* WINED3DSIH_MUL                   */ shader_glsl_binop,
+    /* WINED3DSIH_NOP                   */ shader_glsl_nop,
+    /* WINED3DSIH_NRM                   */ shader_glsl_nrm,
+    /* WINED3DSIH_PHASE                 */ shader_glsl_nop,
+    /* WINED3DSIH_POW                   */ shader_glsl_pow,
+    /* WINED3DSIH_RCP                   */ shader_glsl_rcp,
+    /* WINED3DSIH_REP                   */ shader_glsl_rep,
+    /* WINED3DSIH_RET                   */ shader_glsl_ret,
+    /* WINED3DSIH_ROUND_NI              */ shader_glsl_map2gl,
+    /* WINED3DSIH_RSQ                   */ shader_glsl_rsq,
+    /* WINED3DSIH_SAMPLE                */ NULL,
+    /* WINED3DSIH_SAMPLE_GRAD           */ NULL,
+    /* WINED3DSIH_SAMPLE_LOD            */ NULL,
+    /* WINED3DSIH_SETP                  */ NULL,
+    /* WINED3DSIH_SGE                   */ shader_glsl_compare,
+    /* WINED3DSIH_SGN                   */ shader_glsl_sgn,
+    /* WINED3DSIH_SINCOS                */ shader_glsl_sincos,
+    /* WINED3DSIH_SLT                   */ shader_glsl_compare,
+    /* WINED3DSIH_SQRT                  */ NULL,
+    /* WINED3DSIH_SUB                   */ shader_glsl_binop,
+    /* WINED3DSIH_TEX                   */ shader_glsl_tex,
+    /* WINED3DSIH_TEXBEM                */ shader_glsl_texbem,
+    /* WINED3DSIH_TEXBEML               */ shader_glsl_texbem,
+    /* WINED3DSIH_TEXCOORD              */ shader_glsl_texcoord,
+    /* WINED3DSIH_TEXDEPTH              */ shader_glsl_texdepth,
+    /* WINED3DSIH_TEXDP3                */ shader_glsl_texdp3,
+    /* WINED3DSIH_TEXDP3TEX             */ shader_glsl_texdp3tex,
+    /* WINED3DSIH_TEXKILL               */ shader_glsl_texkill,
+    /* WINED3DSIH_TEXLDD                */ shader_glsl_texldd,
+    /* WINED3DSIH_TEXLDL                */ shader_glsl_texldl,
+    /* WINED3DSIH_TEXM3x2DEPTH          */ shader_glsl_texm3x2depth,
+    /* WINED3DSIH_TEXM3x2PAD            */ shader_glsl_texm3x2pad,
+    /* WINED3DSIH_TEXM3x2TEX            */ shader_glsl_texm3x2tex,
+    /* WINED3DSIH_TEXM3x3               */ shader_glsl_texm3x3,
+    /* WINED3DSIH_TEXM3x3DIFF           */ NULL,
+    /* WINED3DSIH_TEXM3x3PAD            */ shader_glsl_texm3x3pad,
+    /* WINED3DSIH_TEXM3x3SPEC           */ shader_glsl_texm3x3spec,
+    /* WINED3DSIH_TEXM3x3TEX            */ shader_glsl_texm3x3tex,
+    /* WINED3DSIH_TEXM3x3VSPEC          */ shader_glsl_texm3x3vspec,
+    /* WINED3DSIH_TEXREG2AR             */ shader_glsl_texreg2ar,
+    /* WINED3DSIH_TEXREG2GB             */ shader_glsl_texreg2gb,
+    /* WINED3DSIH_TEXREG2RGB            */ shader_glsl_texreg2rgb,
+    /* WINED3DSIH_UDIV                  */ shader_glsl_udiv,
+    /* WINED3DSIH_USHR                  */ shader_glsl_binop,
+    /* WINED3DSIH_UTOF                  */ shader_glsl_to_float,
+    /* WINED3DSIH_XOR                   */ shader_glsl_binop,
+};
+
+static void shader_glsl_handle_instruction(const struct wined3d_shader_instruction *ins) {
+    SHADER_HANDLER hw_fct;
+
+    /* Select handler */
+    hw_fct = shader_glsl_instruction_handler_table[ins->handler_idx];
+
+    /* Unhandled opcode */
+    if (!hw_fct)
+    {
+        FIXME("Backend can't handle opcode %#x\n", ins->handler_idx);
+        return;
+    }
+    hw_fct(ins);
+
+    shader_glsl_add_instruction_modifiers(ins);
+}
+
+static BOOL shader_glsl_has_ffp_proj_control(void *shader_priv)
+{
+    struct shader_glsl_priv *priv = shader_priv;
+
+    return priv->ffp_proj_control;
+}
+
+const struct wined3d_shader_backend_ops glsl_shader_backend =
+{
+    shader_glsl_handle_instruction,
+    shader_glsl_select,
+    shader_glsl_disable,
+    shader_glsl_select_depth_blt,
+    shader_glsl_deselect_depth_blt,
+    shader_glsl_update_float_vertex_constants,
+    shader_glsl_update_float_pixel_constants,
+    shader_glsl_load_constants,
+    shader_glsl_load_np2fixup_constants,
+    shader_glsl_destroy,
+    shader_glsl_alloc,
+    shader_glsl_free,
+    shader_glsl_context_destroyed,
+    shader_glsl_get_caps,
+    shader_glsl_color_fixup_supported,
+    shader_glsl_has_ffp_proj_control,
+};
+
+static void glsl_vertex_pipe_vp_enable(const struct wined3d_gl_info *gl_info, BOOL enable)
+{
+    if (enable)
+        gl_info->gl_ops.gl.p_glEnable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB);
+    else
+        gl_info->gl_ops.gl.p_glDisable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB);
+    checkGLcall("GL_VERTEX_PROGRAM_POINT_SIZE_ARB");
+}
+
+static void glsl_vertex_pipe_vp_get_caps(const struct wined3d_gl_info *gl_info, struct wined3d_vertex_caps *caps)
+{
+    caps->max_active_lights = gl_info->limits.lights;
+    caps->max_vertex_blend_matrices = 0;
+    caps->max_vertex_blend_matrix_index = 0;
+    caps->vertex_processing_caps = WINED3DVTXPCAPS_TEXGEN
+            | WINED3DVTXPCAPS_MATERIALSOURCE7
+            | WINED3DVTXPCAPS_VERTEXFOG
+            | WINED3DVTXPCAPS_DIRECTIONALLIGHTS
+            | WINED3DVTXPCAPS_POSITIONALLIGHTS
+            | WINED3DVTXPCAPS_LOCALVIEWER
+            | WINED3DVTXPCAPS_TEXGEN_SPHEREMAP;
+    caps->fvf_caps = WINED3DFVFCAPS_PSIZE | 8; /* 8 texture coordinates. */
+    caps->max_user_clip_planes = gl_info->limits.clipplanes;
+    caps->raster_caps = WINED3DPRASTERCAPS_FOGRANGE;
+}
+
+static void *glsl_vertex_pipe_vp_alloc(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv)
+{
+    struct shader_glsl_priv *priv;
+
+    if (shader_backend == &glsl_shader_backend)
+    {
+        priv = shader_priv;
+
+        if (wine_rb_init(&priv->ffp_vertex_shaders, &wined3d_ffp_vertex_program_rb_functions) == -1)
+        {
+            ERR("Failed to initialize rbtree.\n");
+            return NULL;
+        }
+
+        return priv;
+    }
+
+    FIXME("GLSL vertex pipe without GLSL shader backend not implemented.\n");
+
+    return NULL;
+}
+
+static void shader_glsl_free_ffp_vertex_shader(struct wine_rb_entry *entry, void *context)
+{
+    struct glsl_ffp_vertex_shader *shader = WINE_RB_ENTRY_VALUE(entry,
+            struct glsl_ffp_vertex_shader, desc.entry);
+    struct glsl_shader_prog_link *program, *program2;
+    struct glsl_ffp_destroy_ctx *ctx = context;
+
+    LIST_FOR_EACH_ENTRY_SAFE(program, program2, &shader->linked_programs,
+            struct glsl_shader_prog_link, vs.shader_entry)
+    {
+        delete_glsl_program_entry(ctx->priv, ctx->gl_info, program);
+    }
+    ctx->gl_info->gl_ops.ext.p_glDeleteObjectARB(shader->id);
+    HeapFree(GetProcessHeap(), 0, shader);
+}
+
+/* Context activation is done by the caller. */
+static void glsl_vertex_pipe_vp_free(struct wined3d_device *device)
+{
+    struct shader_glsl_priv *priv = device->vertex_priv;
+    struct glsl_ffp_destroy_ctx ctx;
+
+    ctx.priv = priv;
+    ctx.gl_info = &device->adapter->gl_info;
+    wine_rb_destroy(&priv->ffp_vertex_shaders, shader_glsl_free_ffp_vertex_shader, &ctx);
+}
+
+static void glsl_vertex_pipe_shader(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id)
+{
+    context->select_shader = 1;
+}
+
+static const struct StateEntryTemplate glsl_vertex_pipe_vp_states[] =
+{
+    {STATE_VDECL,                                                {STATE_VDECL,                                                vertexdeclaration      }, WINED3D_GL_EXT_NONE          },
+    {STATE_VSHADER,                                              {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_MATERIAL,                                             {STATE_RENDER(WINED3D_RS_SPECULARENABLE),                    NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_SPECULARENABLE),                    {STATE_RENDER(WINED3D_RS_SPECULARENABLE),                    state_specularenable   }, WINED3D_GL_EXT_NONE          },
+    /* Clip planes */
+    {STATE_CLIPPLANE(0),                                         {STATE_CLIPPLANE(0),                                         clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(1),                                         {STATE_CLIPPLANE(1),                                         clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(2),                                         {STATE_CLIPPLANE(2),                                         clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(3),                                         {STATE_CLIPPLANE(3),                                         clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(4),                                         {STATE_CLIPPLANE(4),                                         clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(5),                                         {STATE_CLIPPLANE(5),                                         clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(6),                                         {STATE_CLIPPLANE(6),                                         clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(7),                                         {STATE_CLIPPLANE(7),                                         clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(8),                                         {STATE_CLIPPLANE(8),                                         clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(9),                                         {STATE_CLIPPLANE(9),                                         clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(10),                                        {STATE_CLIPPLANE(10),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(11),                                        {STATE_CLIPPLANE(11),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(12),                                        {STATE_CLIPPLANE(12),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(13),                                        {STATE_CLIPPLANE(13),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(14),                                        {STATE_CLIPPLANE(14),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(15),                                        {STATE_CLIPPLANE(15),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(16),                                        {STATE_CLIPPLANE(16),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(17),                                        {STATE_CLIPPLANE(17),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(18),                                        {STATE_CLIPPLANE(18),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(19),                                        {STATE_CLIPPLANE(19),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(20),                                        {STATE_CLIPPLANE(20),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(21),                                        {STATE_CLIPPLANE(21),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(22),                                        {STATE_CLIPPLANE(22),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(23),                                        {STATE_CLIPPLANE(23),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(24),                                        {STATE_CLIPPLANE(24),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(25),                                        {STATE_CLIPPLANE(25),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(26),                                        {STATE_CLIPPLANE(26),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(27),                                        {STATE_CLIPPLANE(27),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(28),                                        {STATE_CLIPPLANE(28),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(29),                                        {STATE_CLIPPLANE(29),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(30),                                        {STATE_CLIPPLANE(30),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(31),                                        {STATE_CLIPPLANE(31),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    /* Lights */
+    {STATE_LIGHT_TYPE,                                           {STATE_RENDER(WINED3D_RS_FOGENABLE),                         NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_ACTIVELIGHT(0),                                       {STATE_ACTIVELIGHT(0),                                       light                  }, WINED3D_GL_EXT_NONE          },
+    {STATE_ACTIVELIGHT(1),                                       {STATE_ACTIVELIGHT(1),                                       light                  }, WINED3D_GL_EXT_NONE          },
+    {STATE_ACTIVELIGHT(2),                                       {STATE_ACTIVELIGHT(2),                                       light                  }, WINED3D_GL_EXT_NONE          },
+    {STATE_ACTIVELIGHT(3),                                       {STATE_ACTIVELIGHT(3),                                       light                  }, WINED3D_GL_EXT_NONE          },
+    {STATE_ACTIVELIGHT(4),                                       {STATE_ACTIVELIGHT(4),                                       light                  }, WINED3D_GL_EXT_NONE          },
+    {STATE_ACTIVELIGHT(5),                                       {STATE_ACTIVELIGHT(5),                                       light                  }, WINED3D_GL_EXT_NONE          },
+    {STATE_ACTIVELIGHT(6),                                       {STATE_ACTIVELIGHT(6),                                       light                  }, WINED3D_GL_EXT_NONE          },
+    {STATE_ACTIVELIGHT(7),                                       {STATE_ACTIVELIGHT(7),                                       light                  }, WINED3D_GL_EXT_NONE          },
+    /* Viewport */
+    {STATE_VIEWPORT,                                             {STATE_VIEWPORT,                                             viewport_vertexpart    }, WINED3D_GL_EXT_NONE          },
+    /* Transform states */
+    {STATE_TRANSFORM(WINED3D_TS_VIEW),                           {STATE_TRANSFORM(WINED3D_TS_VIEW),                           transform_view         }, WINED3D_GL_EXT_NONE          },
+    {STATE_TRANSFORM(WINED3D_TS_PROJECTION),                     {STATE_TRANSFORM(WINED3D_TS_PROJECTION),                     transform_projection   }, WINED3D_GL_EXT_NONE          },
+    {STATE_TRANSFORM(WINED3D_TS_TEXTURE0),                       {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_TRANSFORM(WINED3D_TS_TEXTURE1),                       {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_TRANSFORM(WINED3D_TS_TEXTURE2),                       {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_TRANSFORM(WINED3D_TS_TEXTURE3),                       {STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_TRANSFORM(WINED3D_TS_TEXTURE4),                       {STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_TRANSFORM(WINED3D_TS_TEXTURE5),                       {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_TRANSFORM(WINED3D_TS_TEXTURE6),                       {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_TRANSFORM(WINED3D_TS_TEXTURE7),                       {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)),                {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)),                transform_world        }, WINED3D_GL_EXT_NONE          },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture      }, WINED3D_GL_EXT_NONE          },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture      }, WINED3D_GL_EXT_NONE          },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture      }, WINED3D_GL_EXT_NONE          },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture      }, WINED3D_GL_EXT_NONE          },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture      }, WINED3D_GL_EXT_NONE          },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture      }, WINED3D_GL_EXT_NONE          },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture      }, WINED3D_GL_EXT_NONE          },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture      }, WINED3D_GL_EXT_NONE          },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXCOORD_INDEX),          {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXCOORD_INDEX),          {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXCOORD_INDEX),          {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXCOORD_INDEX),          {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXCOORD_INDEX),          {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXCOORD_INDEX),          {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXCOORD_INDEX),          {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXCOORD_INDEX),          {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    /* Fog */
+    {STATE_RENDER(WINED3D_RS_FOGENABLE),                         {STATE_RENDER(WINED3D_RS_FOGENABLE),                         glsl_vertex_pipe_shader}, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_FOGTABLEMODE),                      {STATE_RENDER(WINED3D_RS_FOGENABLE),                         NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_FOGVERTEXMODE),                     {STATE_RENDER(WINED3D_RS_FOGENABLE),                         NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_RANGEFOGENABLE),                    {STATE_RENDER(WINED3D_RS_FOGENABLE),                         NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_CLIPPING),                          {STATE_RENDER(WINED3D_RS_CLIPPING),                          state_clipping         }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_CLIPPLANEENABLE),                   {STATE_RENDER(WINED3D_RS_CLIPPING),                          NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_LIGHTING),                          {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_AMBIENT),                           {STATE_RENDER(WINED3D_RS_AMBIENT),                           state_ambient          }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_COLORVERTEX),                       {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_LOCALVIEWER),                       {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_NORMALIZENORMALS),                  {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_DIFFUSEMATERIALSOURCE),             {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_SPECULARMATERIALSOURCE),            {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_AMBIENTMATERIALSOURCE),             {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_EMISSIVEMATERIALSOURCE),            {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_VERTEXBLEND),                       {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_POINTSIZE),                         {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE),                  NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),                     {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),                     state_psizemin_arb     }, ARB_POINT_PARAMETERS         },
+    {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),                     {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),                     state_psizemin_ext     }, EXT_POINT_PARAMETERS         },
+    {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),                     {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),                     state_psizemin_w       }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE),                 {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE),                 state_pointsprite      }, ARB_POINT_SPRITE             },
+    {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE),                 {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE),                 state_pointsprite_w    }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE),                  {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE),                  state_pscale           }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_POINTSCALE_A),                      {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE),                  NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_POINTSCALE_B),                      {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE),                  NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_POINTSCALE_C),                      {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE),                  NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_POINTSIZE_MAX),                     {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),                     NULL                   }, ARB_POINT_PARAMETERS         },
+    {STATE_RENDER(WINED3D_RS_POINTSIZE_MAX),                     {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),                     NULL                   }, EXT_POINT_PARAMETERS         },
+    {STATE_RENDER(WINED3D_RS_POINTSIZE_MAX),                     {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),                     NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_TWEENFACTOR),                       {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_INDEXEDVERTEXBLENDENABLE),          {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    /* Samplers for NP2 texture matrix adjustions. They are not needed if
+     * GL_ARB_texture_non_power_of_two is supported, so register a NULL state
+     * handler in that case to get the vertex part of sampler() skipped (VTF
+     * is handled in the misc states). Otherwise, register
+     * sampler_texmatrix(), which takes care of updating the texture matrix. */
+    {STATE_SAMPLER(0),                                           {0,                                                          NULL                   }, ARB_TEXTURE_NON_POWER_OF_TWO },
+    {STATE_SAMPLER(0),                                           {0,                                                          NULL                   }, WINED3D_GL_NORMALIZED_TEXRECT},
+    {STATE_SAMPLER(0),                                           {STATE_SAMPLER(0),                                           sampler_texmatrix      }, WINED3D_GL_EXT_NONE          },
+    {STATE_SAMPLER(1),                                           {0,                                                          NULL                   }, ARB_TEXTURE_NON_POWER_OF_TWO },
+    {STATE_SAMPLER(1),                                           {0,                                                          NULL                   }, WINED3D_GL_NORMALIZED_TEXRECT},
+    {STATE_SAMPLER(1),                                           {STATE_SAMPLER(1),                                           sampler_texmatrix      }, WINED3D_GL_EXT_NONE          },
+    {STATE_SAMPLER(2),                                           {0,                                                          NULL                   }, ARB_TEXTURE_NON_POWER_OF_TWO },
+    {STATE_SAMPLER(2),                                           {0,                                                          NULL                   }, WINED3D_GL_NORMALIZED_TEXRECT},
+    {STATE_SAMPLER(2),                                           {STATE_SAMPLER(2),                                           sampler_texmatrix      }, WINED3D_GL_EXT_NONE          },
+    {STATE_SAMPLER(3),                                           {0,                                                          NULL                   }, ARB_TEXTURE_NON_POWER_OF_TWO },
+    {STATE_SAMPLER(3),                                           {0,                                                          NULL                   }, WINED3D_GL_NORMALIZED_TEXRECT},
+    {STATE_SAMPLER(3),                                           {STATE_SAMPLER(3),                                           sampler_texmatrix      }, WINED3D_GL_EXT_NONE          },
+    {STATE_SAMPLER(4),                                           {0,                                                          NULL                   }, ARB_TEXTURE_NON_POWER_OF_TWO },
+    {STATE_SAMPLER(4),                                           {0,                                                          NULL                   }, WINED3D_GL_NORMALIZED_TEXRECT},
+    {STATE_SAMPLER(4),                                           {STATE_SAMPLER(4),                                           sampler_texmatrix      }, WINED3D_GL_EXT_NONE          },
+    {STATE_SAMPLER(5),                                           {0,                                                          NULL                   }, ARB_TEXTURE_NON_POWER_OF_TWO },
+    {STATE_SAMPLER(5),                                           {0,                                                          NULL                   }, WINED3D_GL_NORMALIZED_TEXRECT},
+    {STATE_SAMPLER(5),                                           {STATE_SAMPLER(5),                                           sampler_texmatrix      }, WINED3D_GL_EXT_NONE          },
+    {STATE_SAMPLER(6),                                           {0,                                                          NULL                   }, ARB_TEXTURE_NON_POWER_OF_TWO },
+    {STATE_SAMPLER(6),                                           {0,                                                          NULL                   }, WINED3D_GL_NORMALIZED_TEXRECT},
+    {STATE_SAMPLER(6),                                           {STATE_SAMPLER(6),                                           sampler_texmatrix      }, WINED3D_GL_EXT_NONE          },
+    {STATE_SAMPLER(7),                                           {0,                                                          NULL                   }, ARB_TEXTURE_NON_POWER_OF_TWO },
+    {STATE_SAMPLER(7),                                           {0,                                                          NULL                   }, WINED3D_GL_NORMALIZED_TEXRECT},
+    {STATE_SAMPLER(7),                                           {STATE_SAMPLER(7),                                           sampler_texmatrix      }, WINED3D_GL_EXT_NONE          },
+    {STATE_POINT_SIZE_ENABLE,                                    {STATE_RENDER(WINED3D_RS_FOGENABLE),                         NULL                   }, WINED3D_GL_EXT_NONE          },
+    {0 /* Terminate */,                                          {0,                                                          NULL                   }, WINED3D_GL_EXT_NONE          },
+};
+
+/* TODO:
+ *   - This currently depends on GL fixed function functions to set things
+ *     like light parameters. Ideally we'd use regular uniforms for that.
+ *   - In part because of the previous point, much of this is modelled after
+ *     GL fixed function, and has much of the same limitations. For example,
+ *     D3D spot lights are slightly different from GL spot lights.
+ *   - We can now implement drawing transformed vertices using the GLSL pipe,
+ *     instead of using the immediate mode fallback.
+ *   - Similarly, we don't need the fallback for certain combinations of
+ *     material sources anymore.
+ *   - Implement vertex blending and vertex tweening.
+ *   - Handle WINED3D_TSS_TEXCOORD_INDEX in the shader, instead of duplicating
+ *     attribute arrays in load_tex_coords().
+ *   - Per-vertex point sizes. */
+const struct wined3d_vertex_pipe_ops glsl_vertex_pipe =
+{
+    glsl_vertex_pipe_vp_enable,
+    glsl_vertex_pipe_vp_get_caps,
+    glsl_vertex_pipe_vp_alloc,
+    glsl_vertex_pipe_vp_free,
+    glsl_vertex_pipe_vp_states,
+};
+
+static void glsl_fragment_pipe_enable(const struct wined3d_gl_info *gl_info, BOOL enable)
+{
+    /* Nothing to do. */
+}
+
+static void glsl_fragment_pipe_get_caps(const struct wined3d_gl_info *gl_info, struct fragment_caps *caps)
+{
+    caps->wined3d_caps = WINED3D_FRAGMENT_CAP_PROJ_CONTROL
+            | WINED3D_FRAGMENT_CAP_SRGB_WRITE;
+    caps->PrimitiveMiscCaps = WINED3DPMISCCAPS_TSSARGTEMP;
+    caps->TextureOpCaps = WINED3DTEXOPCAPS_DISABLE
+            | WINED3DTEXOPCAPS_SELECTARG1
+            | WINED3DTEXOPCAPS_SELECTARG2
+            | WINED3DTEXOPCAPS_MODULATE4X
+            | WINED3DTEXOPCAPS_MODULATE2X
+            | WINED3DTEXOPCAPS_MODULATE
+            | WINED3DTEXOPCAPS_ADDSIGNED2X
+            | WINED3DTEXOPCAPS_ADDSIGNED
+            | WINED3DTEXOPCAPS_ADD
+            | WINED3DTEXOPCAPS_SUBTRACT
+            | WINED3DTEXOPCAPS_ADDSMOOTH
+            | WINED3DTEXOPCAPS_BLENDCURRENTALPHA
+            | WINED3DTEXOPCAPS_BLENDFACTORALPHA
+            | WINED3DTEXOPCAPS_BLENDTEXTUREALPHA
+            | WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA
+            | WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM
+            | WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR
+            | WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA
+            | WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA
+            | WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR
+            | WINED3DTEXOPCAPS_DOTPRODUCT3
+            | WINED3DTEXOPCAPS_MULTIPLYADD
+            | WINED3DTEXOPCAPS_LERP
+            | WINED3DTEXOPCAPS_BUMPENVMAP
+            | WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE;
+    caps->MaxTextureBlendStages = 8;
+    caps->MaxSimultaneousTextures = min(gl_info->limits.fragment_samplers, 8);
+}
+
+static void *glsl_fragment_pipe_alloc(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv)
+{
+    struct shader_glsl_priv *priv;
+
+    if (shader_backend == &glsl_shader_backend)
+    {
+        priv = shader_priv;
+
+        if (wine_rb_init(&priv->ffp_fragment_shaders, &wined3d_ffp_frag_program_rb_functions) == -1)
+        {
+            ERR("Failed to initialize rbtree.\n");
+            return NULL;
+        }
+
+        return priv;
+    }
+
+    FIXME("GLSL fragment pipe without GLSL shader backend not implemented.\n");
+
+    return NULL;
+}
+
+static void shader_glsl_free_ffp_fragment_shader(struct wine_rb_entry *entry, void *context)
+{
+    struct glsl_ffp_fragment_shader *shader = WINE_RB_ENTRY_VALUE(entry,
+            struct glsl_ffp_fragment_shader, entry.entry);
+    struct glsl_shader_prog_link *program, *program2;
+    struct glsl_ffp_destroy_ctx *ctx = context;
+
+    LIST_FOR_EACH_ENTRY_SAFE(program, program2, &shader->linked_programs,
+            struct glsl_shader_prog_link, ps.shader_entry)
+    {
+        delete_glsl_program_entry(ctx->priv, ctx->gl_info, program);
+    }
+    ctx->gl_info->gl_ops.ext.p_glDeleteObjectARB(shader->id);
+    HeapFree(GetProcessHeap(), 0, shader);
+}
+
+/* Context activation is done by the caller. */
+static void glsl_fragment_pipe_free(struct wined3d_device *device)
+{
+    struct shader_glsl_priv *priv = device->fragment_priv;
+    struct glsl_ffp_destroy_ctx ctx;
+
+    ctx.priv = priv;
+    ctx.gl_info = &device->adapter->gl_info;
+    wine_rb_destroy(&priv->ffp_fragment_shaders, shader_glsl_free_ffp_fragment_shader, &ctx);
+}
+
+static void glsl_fragment_pipe_shader(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id)
+{
+    context->last_was_pshader = use_ps(state);
+
+    context->select_shader = 1;
+    context->load_constants = 1;
+}
+
+static void glsl_fragment_pipe_fog(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id)
+{
+    BOOL use_vshader = use_vs(state);
+    enum fogsource new_source;
+
+    context->select_shader = 1;
+    context->load_constants = 1;
+
+    if (!state->render_states[WINED3D_RS_FOGENABLE])
+        return;
+
+    if (state->render_states[WINED3D_RS_FOGTABLEMODE] == WINED3D_FOG_NONE)
+    {
+        if (use_vshader)
+            new_source = FOGSOURCE_VS;
+        else if (state->render_states[WINED3D_RS_FOGVERTEXMODE] == WINED3D_FOG_NONE || context->last_was_rhw)
+            new_source = FOGSOURCE_COORD;
+        else
+            new_source = FOGSOURCE_FFP;
+    }
+    else
+    {
+        new_source = FOGSOURCE_FFP;
+    }
+
+    if (new_source != context->fog_source)
+    {
+        context->fog_source = new_source;
+        state_fogstartend(context, state, STATE_RENDER(WINED3D_RS_FOGSTART));
+    }
+}
+
+static void glsl_fragment_pipe_tex_transform(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id)
+{
+    context->select_shader = 1;
+    context->load_constants = 1;
+}
+
+static void glsl_fragment_pipe_invalidate_constants(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id)
+{
+    context->load_constants = 1;
+}
+
+static const struct StateEntryTemplate glsl_fragment_pipe_state_template[] =
+{
+    {STATE_RENDER(WINED3D_RS_TEXTUREFACTOR),                    {STATE_RENDER(WINED3D_RS_TEXTUREFACTOR),                     glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),               {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG1),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG2),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG0),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_OP),               {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG1),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG2),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG0),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_RESULT_ARG),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),          {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),           glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT01),          {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT10),          {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT11),          {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE),         {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE),          glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LOFFSET),        {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE),          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_OP),               {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG1),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG2),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG0),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_OP),               {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG1),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG2),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG0),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_RESULT_ARG),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),          {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),           glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT01),          {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT10),          {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT11),          {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE),         {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE),          glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LOFFSET),        {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE),          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_OP),               {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG1),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG2),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG0),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_OP),               {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG1),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG2),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG0),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_RESULT_ARG),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),          {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),           glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT01),          {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT10),          {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT11),          {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE),         {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE),          glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LOFFSET),        {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE),          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_OP),               {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG1),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG2),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG0),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_OP),               {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG1),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG2),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG0),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_RESULT_ARG),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),          {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),           glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT01),          {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT10),          {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT11),          {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE),         {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE),          glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LOFFSET),        {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE),          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_OP),               {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG1),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG2),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG0),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_OP),               {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG1),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG2),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG0),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_RESULT_ARG),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),          {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),           glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT01),          {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT10),          {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT11),          {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE),         {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE),          glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LOFFSET),        {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE),          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_OP),               {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG1),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG2),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG0),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_OP),               {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG1),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG2),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG0),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_RESULT_ARG),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),          {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),           glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT01),          {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT10),          {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT11),          {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE),         {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE),          glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LOFFSET),        {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE),          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_OP),               {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG1),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG2),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG0),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_OP),               {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG1),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG2),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG0),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_RESULT_ARG),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),          {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),           glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT01),          {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT10),          {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT11),          {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE),         {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE),          glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LOFFSET),        {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE),          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_OP),               {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG1),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG2),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG0),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_OP),               {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG1),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG2),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG0),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_RESULT_ARG),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),          {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),           glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT01),          {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT10),          {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT11),          {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE),         {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE),          glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LOFFSET),        {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE),          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_PIXELSHADER,                                         {STATE_PIXELSHADER,                                          glsl_fragment_pipe_shader              }, WINED3D_GL_EXT_NONE },
+    {STATE_RENDER(WINED3D_RS_FOGENABLE),                        {STATE_RENDER(WINED3D_RS_FOGENABLE),                         glsl_fragment_pipe_fog                 }, WINED3D_GL_EXT_NONE },
+    {STATE_RENDER(WINED3D_RS_FOGTABLEMODE),                     {STATE_RENDER(WINED3D_RS_FOGENABLE),                         NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_RENDER(WINED3D_RS_FOGVERTEXMODE),                    {STATE_RENDER(WINED3D_RS_FOGENABLE),                         NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_RENDER(WINED3D_RS_FOGSTART),                         {STATE_RENDER(WINED3D_RS_FOGSTART),                          state_fogstartend                      }, WINED3D_GL_EXT_NONE },
+    {STATE_RENDER(WINED3D_RS_FOGEND),                           {STATE_RENDER(WINED3D_RS_FOGSTART),                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE),                  {STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE),                   state_srgbwrite                        }, ARB_FRAMEBUFFER_SRGB},
+    {STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE),                  {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
+    {STATE_RENDER(WINED3D_RS_FOGCOLOR),                         {STATE_RENDER(WINED3D_RS_FOGCOLOR),                          state_fogcolor                         }, WINED3D_GL_EXT_NONE },
+    {STATE_RENDER(WINED3D_RS_FOGDENSITY),                       {STATE_RENDER(WINED3D_RS_FOGDENSITY),                        state_fogdensity                       }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(0,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_fragment_pipe_tex_transform       }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(1,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_fragment_pipe_tex_transform       }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(2,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_fragment_pipe_tex_transform       }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(3,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_fragment_pipe_tex_transform       }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(4,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_fragment_pipe_tex_transform       }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(5,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_fragment_pipe_tex_transform       }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(6,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_fragment_pipe_tex_transform       }, WINED3D_GL_EXT_NONE },
+    {STATE_TEXTURESTAGE(7,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_fragment_pipe_tex_transform       }, WINED3D_GL_EXT_NONE },
+    {STATE_RENDER(WINED3D_RS_SPECULARENABLE),                   {STATE_RENDER(WINED3D_RS_SPECULARENABLE),                    glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
+    {0 /* Terminate */,                                         {0,                                                          0                                      }, WINED3D_GL_EXT_NONE },
+};
+
+const struct fragment_pipeline glsl_fragment_pipe =
+{
+    glsl_fragment_pipe_enable,
+    glsl_fragment_pipe_get_caps,
+    glsl_fragment_pipe_alloc,
+    glsl_fragment_pipe_free,
+    shader_glsl_color_fixup_supported,
+    glsl_fragment_pipe_state_template,
+};
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/nvidia_texture_shader.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/nvidia_texture_shader.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/nvidia_texture_shader.c	(revision 46521)
@@ -0,0 +1,911 @@
+/*
+ * Fixed function pipeline replacement using GL_NV_register_combiners
+ * and GL_NV_texture_shader
+ *
+ * Copyright 2006 Henri Verbeet
+ * Copyright 2008 Stefan Dösinger(for CodeWeavers)
+ *
+ * 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 <math.h>
+#include <stdio.h>
+
+#include "wined3d_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d);
+
+/* Context activation for state handlers is done by the caller. */
+
+static void nvts_activate_dimensions(const struct wined3d_state *state, DWORD stage, struct wined3d_context *context)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    BOOL bumpmap = FALSE;
+
+    if (stage > 0
+            && (state->texture_states[stage - 1][WINED3D_TSS_COLOR_OP] == WINED3D_TOP_BUMPENVMAP_LUMINANCE
+            || state->texture_states[stage - 1][WINED3D_TSS_COLOR_OP] == WINED3D_TOP_BUMPENVMAP))
+    {
+        bumpmap = TRUE;
+        context->texShaderBumpMap |= (1 << stage);
+    } else {
+        context->texShaderBumpMap &= ~(1 << stage);
+    }
+
+    if (state->textures[stage])
+    {
+        switch (state->textures[stage]->target)
+        {
+            case GL_TEXTURE_2D:
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV,
+                        bumpmap ? GL_OFFSET_TEXTURE_2D_NV : GL_TEXTURE_2D);
+                checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, ...)");
+                break;
+            case GL_TEXTURE_RECTANGLE_ARB:
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV,
+                        bumpmap ? GL_OFFSET_TEXTURE_2D_NV : GL_TEXTURE_RECTANGLE_ARB);
+                checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, ...)");
+                break;
+            case GL_TEXTURE_3D:
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_3D);
+                checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_3D)");
+                break;
+            case GL_TEXTURE_CUBE_MAP_ARB:
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_CUBE_MAP_ARB);
+                checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_CUBE_MAP_ARB)");
+                break;
+        }
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE);
+        checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE)");
+    }
+}
+
+struct tex_op_args
+{
+    GLenum input[3];
+    GLenum mapping[3];
+    GLenum component_usage[3];
+};
+
+static GLenum d3dta_to_combiner_input(DWORD d3dta, DWORD stage, INT texture_idx) {
+    switch (d3dta) {
+        case WINED3DTA_DIFFUSE:
+            return GL_PRIMARY_COLOR_NV;
+
+        case WINED3DTA_CURRENT:
+            if (stage) return GL_SPARE0_NV;
+            else return GL_PRIMARY_COLOR_NV;
+
+        case WINED3DTA_TEXTURE:
+            if (texture_idx > -1) return GL_TEXTURE0_ARB + texture_idx;
+            else return GL_PRIMARY_COLOR_NV;
+
+        case WINED3DTA_TFACTOR:
+            return GL_CONSTANT_COLOR0_NV;
+
+        case WINED3DTA_SPECULAR:
+            return GL_SECONDARY_COLOR_NV;
+
+        case WINED3DTA_TEMP:
+            return GL_SPARE1_NV;
+
+        case WINED3DTA_CONSTANT:
+            /* TODO: Support per stage constants (WINED3D_TSS_CONSTANT, NV_register_combiners2) */
+            FIXME("WINED3DTA_CONSTANT, not properly supported.\n");
+            return GL_CONSTANT_COLOR1_NV;
+
+        default:
+            FIXME("Unrecognized texture arg %#x\n", d3dta);
+            return GL_TEXTURE;
+    }
+}
+
+static GLenum invert_mapping(GLenum mapping) {
+    if (mapping == GL_UNSIGNED_INVERT_NV) return GL_UNSIGNED_IDENTITY_NV;
+    else if (mapping == GL_UNSIGNED_IDENTITY_NV) return GL_UNSIGNED_INVERT_NV;
+
+    FIXME("Unhandled mapping %#x\n", mapping);
+    return mapping;
+}
+
+static void get_src_and_opr_nvrc(DWORD stage, DWORD arg, BOOL is_alpha, GLenum* input, GLenum* mapping, GLenum *component_usage, INT texture_idx) {
+    /* The WINED3DTA_COMPLEMENT flag specifies the complement of the input should
+    * be used. */
+    if (arg & WINED3DTA_COMPLEMENT) *mapping = GL_UNSIGNED_INVERT_NV;
+    else *mapping = GL_UNSIGNED_IDENTITY_NV; /* Clamp all values to positive ranges */
+
+    /* The WINED3DTA_ALPHAREPLICATE flag specifies the alpha component of the input
+    * should be used for all input components. */
+    if (is_alpha || arg & WINED3DTA_ALPHAREPLICATE) *component_usage = GL_ALPHA;
+    else *component_usage = GL_RGB;
+
+    *input = d3dta_to_combiner_input(arg & WINED3DTA_SELECTMASK, stage, texture_idx);
+}
+
+void set_tex_op_nvrc(const struct wined3d_gl_info *gl_info, const struct wined3d_state *state, BOOL is_alpha,
+        int stage, enum wined3d_texture_op op, DWORD arg1, DWORD arg2, DWORD arg3, INT texture_idx, DWORD dst)
+{
+    struct tex_op_args tex_op_args = {{0}, {0}, {0}};
+    GLenum portion = is_alpha ? GL_ALPHA : GL_RGB;
+    GLenum target = GL_COMBINER0_NV + stage;
+    GLenum output;
+
+    TRACE("stage %d, is_alpha %d, op %s, arg1 %#x, arg2 %#x, arg3 %#x, texture_idx %d\n",
+          stage, is_alpha, debug_d3dtop(op), arg1, arg2, arg3, texture_idx);
+
+    /* If a texture stage references an invalid texture unit the stage just
+    * passes through the result from the previous stage */
+    if (is_invalid_op(state, stage, op, arg1, arg2, arg3))
+    {
+        arg1 = WINED3DTA_CURRENT;
+        op = WINED3D_TOP_SELECT_ARG1;
+    }
+
+    get_src_and_opr_nvrc(stage, arg1, is_alpha, &tex_op_args.input[0],
+                         &tex_op_args.mapping[0], &tex_op_args.component_usage[0], texture_idx);
+    get_src_and_opr_nvrc(stage, arg2, is_alpha, &tex_op_args.input[1],
+                         &tex_op_args.mapping[1], &tex_op_args.component_usage[1], texture_idx);
+    get_src_and_opr_nvrc(stage, arg3, is_alpha, &tex_op_args.input[2],
+                         &tex_op_args.mapping[2], &tex_op_args.component_usage[2], texture_idx);
+
+
+    if(dst == WINED3DTA_TEMP) {
+        output = GL_SPARE1_NV;
+    } else {
+        output = GL_SPARE0_NV;
+    }
+
+    /* This is called by a state handler which has the gl lock held and a context for the thread */
+    switch (op)
+    {
+        case WINED3D_TOP_DISABLE:
+            /* Only for alpha */
+            if (!is_alpha)
+                ERR("Shouldn't be called for WINED3D_TSS_COLOR_OP (WINED3DTOP_DISABLE).\n");
+            /* Input, prev_alpha*1 */
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
+                       GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA));
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
+                       GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA));
+
+            /* Output */
+            GL_EXTCALL(glCombinerOutputNV(target, portion, GL_SPARE0_NV, GL_DISCARD_NV,
+                       GL_DISCARD_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
+            break;
+
+        case WINED3D_TOP_SELECT_ARG1:
+        case WINED3D_TOP_SELECT_ARG2:
+            /* Input, arg*1 */
+            if (op == WINED3D_TOP_SELECT_ARG1)
+                GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
+                           tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0]));
+            else
+                GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
+                           tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
+                       GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));
+
+            /* Output */
+            GL_EXTCALL(glCombinerOutputNV(target, portion, output, GL_DISCARD_NV,
+                       GL_DISCARD_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
+            break;
+
+        case WINED3D_TOP_MODULATE:
+        case WINED3D_TOP_MODULATE_2X:
+        case WINED3D_TOP_MODULATE_4X:
+            /* Input, arg1*arg2 */
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
+                       tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0]));
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
+                       tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));
+
+            /* Output */
+            if (op == WINED3D_TOP_MODULATE)
+                GL_EXTCALL(glCombinerOutputNV(target, portion, output, GL_DISCARD_NV,
+                           GL_DISCARD_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
+            else if (op == WINED3D_TOP_MODULATE_2X)
+                GL_EXTCALL(glCombinerOutputNV(target, portion, output, GL_DISCARD_NV,
+                           GL_DISCARD_NV, GL_SCALE_BY_TWO_NV, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
+            else if (op == WINED3D_TOP_MODULATE_4X)
+                GL_EXTCALL(glCombinerOutputNV(target, portion, output, GL_DISCARD_NV,
+                           GL_DISCARD_NV, GL_SCALE_BY_FOUR_NV, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
+            break;
+
+        case WINED3D_TOP_ADD:
+        case WINED3D_TOP_ADD_SIGNED:
+        case WINED3D_TOP_ADD_SIGNED_2X:
+            /* Input, arg1*1+arg2*1 */
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
+                       tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0]));
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
+                       GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV,
+                       tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV,
+                       GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));
+
+            /* Output */
+            if (op == WINED3D_TOP_ADD)
+                GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
+                           output, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
+            else if (op == WINED3D_TOP_ADD_SIGNED)
+                GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
+                           output, GL_NONE, GL_BIAS_BY_NEGATIVE_ONE_HALF_NV, GL_FALSE, GL_FALSE, GL_FALSE));
+            else if (op == WINED3D_TOP_ADD_SIGNED_2X)
+                GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
+                           output, GL_SCALE_BY_TWO_NV, GL_BIAS_BY_NEGATIVE_ONE_HALF_NV, GL_FALSE, GL_FALSE, GL_FALSE));
+            break;
+
+        case WINED3D_TOP_SUBTRACT:
+            /* Input, arg1*1+-arg2*1 */
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
+                       tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0]));
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
+                       GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV,
+                       tex_op_args.input[1], GL_SIGNED_NEGATE_NV, tex_op_args.component_usage[1]));
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV,
+                       GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));
+
+            /* Output */
+            GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
+                       output, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
+            break;
+
+        case WINED3D_TOP_ADD_SMOOTH:
+            /* Input, arg1*1+(1-arg1)*arg2 */
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
+                       tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0]));
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
+                       GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV,
+                       tex_op_args.input[0], invert_mapping(tex_op_args.mapping[0]), tex_op_args.component_usage[0]));
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV,
+                       tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));
+
+            /* Output */
+            GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
+                       output, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
+            break;
+
+        case WINED3D_TOP_BLEND_DIFFUSE_ALPHA:
+        case WINED3D_TOP_BLEND_TEXTURE_ALPHA:
+        case WINED3D_TOP_BLEND_FACTOR_ALPHA:
+        case WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM:
+        case WINED3D_TOP_BLEND_CURRENT_ALPHA:
+        {
+            GLenum alpha_src = GL_PRIMARY_COLOR_NV;
+            if (op == WINED3D_TOP_BLEND_DIFFUSE_ALPHA)
+                alpha_src = d3dta_to_combiner_input(WINED3DTA_DIFFUSE, stage, texture_idx);
+            else if (op == WINED3D_TOP_BLEND_TEXTURE_ALPHA)
+                alpha_src = d3dta_to_combiner_input(WINED3DTA_TEXTURE, stage, texture_idx);
+            else if (op == WINED3D_TOP_BLEND_FACTOR_ALPHA)
+                alpha_src = d3dta_to_combiner_input(WINED3DTA_TFACTOR, stage, texture_idx);
+            else if (op == WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM)
+                alpha_src = d3dta_to_combiner_input(WINED3DTA_TEXTURE, stage, texture_idx);
+            else if (op == WINED3D_TOP_BLEND_CURRENT_ALPHA)
+                alpha_src = d3dta_to_combiner_input(WINED3DTA_CURRENT, stage, texture_idx);
+            else
+                FIXME("Unhandled texture op %s, shouldn't happen.\n", debug_d3dtop(op));
+
+            /* Input, arg1*alpha_src+arg2*(1-alpha_src) */
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
+                       tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0]));
+            if (op == WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM)
+            {
+                GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
+                           GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));
+            } else {
+                GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
+                           alpha_src, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA));
+            }
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV,
+                       tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV,
+                       alpha_src, GL_UNSIGNED_INVERT_NV, GL_ALPHA));
+
+            /* Output */
+            GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
+                       output, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
+            break;
+        }
+
+        case WINED3D_TOP_MODULATE_ALPHA_ADD_COLOR:
+            /* Input, arg1_alpha*arg2_rgb+arg1_rgb*1 */
+            if (is_alpha)
+                ERR("Only supported for WINED3D_TSS_COLOR_OP (WINED3DTOP_MODULATEALPHA_ADDCOLOR).\n");
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
+                       tex_op_args.input[0], tex_op_args.mapping[0], GL_ALPHA));
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
+                       tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV,
+                       tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0]));
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV,
+                       GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));
+
+            /* Output */
+            GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
+                       output, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
+            break;
+
+        case WINED3D_TOP_MODULATE_COLOR_ADD_ALPHA:
+            /* Input, arg1_rgb*arg2_rgb+arg1_alpha*1 */
+            if (is_alpha)
+                ERR("Only supported for WINED3D_TSS_COLOR_OP (WINED3DTOP_MODULATECOLOR_ADDALPHA).\n");
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
+                       tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0]));
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
+                       tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV,
+                       tex_op_args.input[0], tex_op_args.mapping[0], GL_ALPHA));
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV,
+                       GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));
+
+            /* Output */
+            GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
+                       output, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
+            break;
+
+        case WINED3D_TOP_MODULATE_INVALPHA_ADD_COLOR:
+            /* Input, (1-arg1_alpha)*arg2_rgb+arg1_rgb*1 */
+            if (is_alpha)
+                ERR("Only supported for WINED3D_TSS_COLOR_OP (WINED3DTOP_MODULATEINVALPHA_ADDCOLOR).\n");
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
+                       tex_op_args.input[0], invert_mapping(tex_op_args.mapping[0]), GL_ALPHA));
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
+                       tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV,
+                       tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0]));
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV,
+                       GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));
+
+            /* Output */
+            GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
+                       output, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
+            break;
+
+        case WINED3D_TOP_MODULATE_INVCOLOR_ADD_ALPHA:
+            /* Input, (1-arg1_rgb)*arg2_rgb+arg1_alpha*1 */
+            if (is_alpha)
+                ERR("Only supported for WINED3D_TSS_COLOR_OP (WINED3DTOP_MODULATEINVCOLOR_ADDALPHA).\n");
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
+                       tex_op_args.input[0], invert_mapping(tex_op_args.mapping[0]), tex_op_args.component_usage[0]));
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
+                       tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV,
+                       tex_op_args.input[0], tex_op_args.mapping[0], GL_ALPHA));
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV,
+                       GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));
+
+            /* Output */
+            GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
+                       output, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
+            break;
+
+        case WINED3D_TOP_DOTPRODUCT3:
+            /* Input, arg1 . arg2 */
+            /* FIXME: DX7 uses a different calculation? */
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
+                       tex_op_args.input[0], GL_EXPAND_NORMAL_NV, tex_op_args.component_usage[0]));
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
+                       tex_op_args.input[1], GL_EXPAND_NORMAL_NV, tex_op_args.component_usage[1]));
+
+            /* Output */
+            GL_EXTCALL(glCombinerOutputNV(target, portion, output, GL_DISCARD_NV,
+                       GL_DISCARD_NV, GL_NONE, GL_NONE, GL_TRUE, GL_FALSE, GL_FALSE));
+            break;
+
+        case WINED3D_TOP_MULTIPLY_ADD:
+            /* Input, arg3*1+arg1*arg2 */
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
+                       tex_op_args.input[2], tex_op_args.mapping[2], tex_op_args.component_usage[2]));
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
+                       GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV,
+                       tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0]));
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV,
+                       tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));
+
+            /* Output */
+            GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
+                       output, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
+            break;
+
+        case WINED3D_TOP_LERP:
+            /* Input, arg3*arg1+(1-arg3)*arg2 */
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
+                       tex_op_args.input[2], tex_op_args.mapping[2], tex_op_args.component_usage[2]));
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
+                       tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0]));
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV,
+                       tex_op_args.input[2], invert_mapping(tex_op_args.mapping[2]), tex_op_args.component_usage[2]));
+            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV,
+                       tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));
+
+            /* Output */
+            GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
+                       output, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
+            break;
+
+        case WINED3D_TOP_BUMPENVMAP_LUMINANCE:
+        case WINED3D_TOP_BUMPENVMAP:
+            if (!gl_info->supported[NV_TEXTURE_SHADER])
+            {
+                WARN("BUMPENVMAP requires GL_NV_texture_shader in this codepath\n");
+                break;
+            }
+
+                /* The bump map stage itself isn't exciting, just read the texture. But tell the next stage to
+                 * perform bump mapping and source from the current stage. Pretty much a SELECTARG2.
+                 * ARG2 is passed through unmodified(apps will most likely use D3DTA_CURRENT for arg2, arg1
+             * (which will most likely be D3DTA_TEXTURE) is available as a texture shader input for the
+             * next stage */
+                GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
+                           tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));
+                GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
+                           GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));
+                /* Always pass through to CURRENT, ignore temp arg */
+                GL_EXTCALL(glCombinerOutputNV(target, portion, GL_SPARE0_NV, GL_DISCARD_NV,
+                           GL_DISCARD_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
+                break;
+
+        default:
+            FIXME("Unhandled texture op: stage %d, is_alpha %d, op %s (%#x), arg1 %#x, arg2 %#x, arg3 %#x, texture_idx %d.\n",
+                  stage, is_alpha, debug_d3dtop(op), op, arg1, arg2, arg3, texture_idx);
+    }
+
+    checkGLcall("set_tex_op_nvrc()");
+}
+
+
+static void nvrc_colorop(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
+    const struct wined3d_device *device = context->swapchain->device;
+    BOOL tex_used = device->fixed_function_usage_map & (1 << stage);
+    DWORD mapped_stage = device->texUnitMap[stage];
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    TRACE("Setting color op for stage %u.\n", stage);
+
+    /* Using a pixel shader? Don't care for anything here, the shader applying does it */
+    if (use_ps(state)) return;
+
+    if (stage != mapped_stage) WARN("Using non 1:1 mapping: %d -> %d!\n", stage, mapped_stage);
+
+    if (mapped_stage != WINED3D_UNMAPPED_STAGE)
+    {
+        if (tex_used && mapped_stage >= gl_info->limits.textures)
+        {
+            FIXME("Attempt to enable unsupported stage!\n");
+            return;
+        }
+        context_active_texture(context, gl_info, mapped_stage);
+    }
+
+    if (state->lowest_disabled_stage > 0)
+    {
+        gl_info->gl_ops.gl.p_glEnable(GL_REGISTER_COMBINERS_NV);
+        GL_EXTCALL(glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, state->lowest_disabled_stage));
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_REGISTER_COMBINERS_NV);
+    }
+    if (stage >= state->lowest_disabled_stage)
+    {
+        TRACE("Stage disabled\n");
+        if (mapped_stage != WINED3D_UNMAPPED_STAGE)
+        {
+            /* Disable everything here */
+            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
+            checkGLcall("glDisable(GL_TEXTURE_2D)");
+            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
+            checkGLcall("glDisable(GL_TEXTURE_3D)");
+            if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
+            {
+                gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB);
+                checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
+            }
+            if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
+            {
+                gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB);
+                checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
+            }
+            if (gl_info->supported[NV_TEXTURE_SHADER2] && mapped_stage < gl_info->limits.textures)
+            {
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE);
+            }
+        }
+        /* All done */
+        return;
+    }
+
+    /* The sampler will also activate the correct texture dimensions, so no need to do it here
+     * if the sampler for this stage is dirty
+     */
+    if (!isStateDirty(context, STATE_SAMPLER(stage)))
+    {
+        if (tex_used)
+        {
+            if (gl_info->supported[NV_TEXTURE_SHADER2])
+            {
+                nvts_activate_dimensions(state, stage, context);
+            }
+            else
+            {
+                texture_activate_dimensions(state->textures[stage], gl_info);
+            }
+        }
+    }
+
+    /* Set the texture combiners */
+    set_tex_op_nvrc(gl_info, state, FALSE, stage,
+            state->texture_states[stage][WINED3D_TSS_COLOR_OP],
+            state->texture_states[stage][WINED3D_TSS_COLOR_ARG1],
+            state->texture_states[stage][WINED3D_TSS_COLOR_ARG2],
+            state->texture_states[stage][WINED3D_TSS_COLOR_ARG0],
+            mapped_stage,
+            state->texture_states[stage][WINED3D_TSS_RESULT_ARG]);
+
+    /* In register combiners bump mapping is done in the stage AFTER the one that has the bump map operation set,
+     * thus the texture shader may have to be updated
+     */
+    if (gl_info->supported[NV_TEXTURE_SHADER2])
+    {
+        BOOL usesBump = (state->texture_states[stage][WINED3D_TSS_COLOR_OP] == WINED3D_TOP_BUMPENVMAP_LUMINANCE
+                || state->texture_states[stage][WINED3D_TSS_COLOR_OP] == WINED3D_TOP_BUMPENVMAP);
+        BOOL usedBump = !!(context->texShaderBumpMap & 1 << (stage + 1));
+        if (usesBump != usedBump)
+        {
+            context_active_texture(context, gl_info, mapped_stage + 1);
+            nvts_activate_dimensions(state, stage + 1, context);
+            context_active_texture(context, gl_info, mapped_stage);
+        }
+    }
+}
+
+static void nvts_texdim(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    DWORD sampler = state_id - STATE_SAMPLER(0);
+    DWORD mapped_stage = context->swapchain->device->texUnitMap[sampler];
+
+    /* No need to enable / disable anything here for unused samplers. The tex_colorop
+    * handler takes care. Also no action is needed with pixel shaders, or if tex_colorop
+    * will take care of this business. */
+    if (mapped_stage == WINED3D_UNMAPPED_STAGE || mapped_stage >= context->gl_info->limits.textures)
+        return;
+    if (sampler >= state->lowest_disabled_stage)
+        return;
+    if (isStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3D_TSS_COLOR_OP)))
+        return;
+
+    nvts_activate_dimensions(state, sampler, context);
+}
+
+static void nvts_bumpenvmat(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
+    DWORD mapped_stage = context->swapchain->device->texUnitMap[stage + 1];
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    float mat[2][2];
+
+    /* Direct3D sets the matrix in the stage reading the perturbation map. The result is used to
+     * offset the destination stage(always stage + 1 in d3d). In GL_NV_texture_shader, the bump
+     * map offsetting is done in the stage reading the bump mapped texture, and the perturbation
+     * map is read from a specified source stage(always stage - 1 for d3d). Thus set the matrix
+     * for stage + 1. Keep the nvrc tex unit mapping in mind too
+     */
+    if (mapped_stage < gl_info->limits.textures)
+    {
+        context_active_texture(context, gl_info, mapped_stage);
+
+        /* We can't just pass a pointer to the state to GL due to the
+         * different matrix format (column major vs row major). */
+        mat[0][0] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_MAT00]);
+        mat[1][0] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_MAT01]);
+        mat[0][1] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_MAT10]);
+        mat[1][1] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_MAT11]);
+        gl_info->gl_ops.gl.p_glTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, (float *)mat);
+        checkGLcall("glTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, mat)");
+    }
+}
+
+static void nvrc_texfactor(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    float col[4];
+
+    D3DCOLORTOGLFLOAT4(state->render_states[WINED3D_RS_TEXTUREFACTOR], col);
+    GL_EXTCALL(glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, &col[0]));
+}
+
+/* Context activation is done by the caller. */
+static void nvrc_enable(const struct wined3d_gl_info *gl_info, BOOL enable)
+{
+    if (enable)
+    {
+        gl_info->gl_ops.gl.p_glEnable(GL_REGISTER_COMBINERS_NV);
+        checkGLcall("glEnable(GL_REGISTER_COMBINERS_NV)");
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_REGISTER_COMBINERS_NV);
+        checkGLcall("glDisable(GL_REGISTER_COMBINERS_NV)");
+    }
+}
+
+/* Context activation is done by the caller. */
+static void nvts_enable(const struct wined3d_gl_info *gl_info, BOOL enable)
+{
+    nvrc_enable(gl_info, enable);
+    if (enable)
+    {
+        gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_SHADER_NV);
+        checkGLcall("glEnable(GL_TEXTURE_SHADER_NV)");
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_SHADER_NV);
+        checkGLcall("glDisable(GL_TEXTURE_SHADER_NV)");
+    }
+}
+
+static void nvrc_fragment_get_caps(const struct wined3d_gl_info *gl_info, struct fragment_caps *caps)
+{
+    caps->wined3d_caps = 0;
+    caps->PrimitiveMiscCaps = WINED3DPMISCCAPS_TSSARGTEMP;
+
+    /* The caps below can be supported but aren't handled yet in utils.c
+     * 'd3dta_to_combiner_input', disable them until support is fixed */
+#if 0
+    if (gl_info->supported[NV_REGISTER_COMBINERS2])
+        caps->PrimitiveMiscCaps |=  WINED3DPMISCCAPS_PERSTAGECONSTANT;
+#endif
+
+    caps->TextureOpCaps = WINED3DTEXOPCAPS_ADD
+            | WINED3DTEXOPCAPS_ADDSIGNED
+            | WINED3DTEXOPCAPS_ADDSIGNED2X
+            | WINED3DTEXOPCAPS_MODULATE
+            | WINED3DTEXOPCAPS_MODULATE2X
+            | WINED3DTEXOPCAPS_MODULATE4X
+            | WINED3DTEXOPCAPS_SELECTARG1
+            | WINED3DTEXOPCAPS_SELECTARG2
+            | WINED3DTEXOPCAPS_DISABLE
+            | WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA
+            | WINED3DTEXOPCAPS_BLENDTEXTUREALPHA
+            | WINED3DTEXOPCAPS_BLENDFACTORALPHA
+            | WINED3DTEXOPCAPS_BLENDCURRENTALPHA
+            | WINED3DTEXOPCAPS_LERP
+            | WINED3DTEXOPCAPS_SUBTRACT
+            | WINED3DTEXOPCAPS_ADDSMOOTH
+            | WINED3DTEXOPCAPS_MULTIPLYADD
+            | WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR
+            | WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA
+            | WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM
+            | WINED3DTEXOPCAPS_DOTPRODUCT3
+            | WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR
+            | WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
+
+    if (gl_info->supported[NV_TEXTURE_SHADER2])
+    {
+        /* Bump mapping is supported already in NV_TEXTURE_SHADER, but that extension does
+         * not support 3D textures. This asks for trouble if an app uses both bump mapping
+         * and 3D textures. It also allows us to keep the code simpler by having texture
+         * shaders constantly enabled. */
+        caps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
+        /* TODO: Luminance bump map? */
+    }
+
+#if 0
+    /* FIXME: Add
+            caps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
+            WINED3DTEXOPCAPS_PREMODULATE */
+#endif
+
+    caps->MaxTextureBlendStages = min(MAX_TEXTURES, gl_info->limits.general_combiners);
+    caps->MaxSimultaneousTextures = gl_info->limits.textures;
+}
+
+static void *nvrc_fragment_alloc(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv)
+{
+    return shader_priv;
+}
+
+/* Context activation is done by the caller. */
+static void nvrc_fragment_free(struct wined3d_device *device) {}
+
+/* Two fixed function pipeline implementations using GL_NV_register_combiners and
+ * GL_NV_texture_shader. The nvts_fragment_pipeline assumes that both extensions
+ * are available(geforce 3 and newer), while nvrc_fragment_pipeline uses only the
+ * register combiners extension(Pre-GF3).
+ */
+
+static BOOL nvts_color_fixup_supported(struct color_fixup_desc fixup)
+{
+    if (TRACE_ON(d3d))
+    {
+        TRACE("Checking support for fixup:\n");
+        dump_color_fixup_desc(fixup);
+    }
+
+    /* We only support identity conversions. */
+    if (is_identity_fixup(fixup))
+    {
+        TRACE("[OK]\n");
+        return TRUE;
+    }
+
+    TRACE("[FAILED]\n");
+    return FALSE;
+}
+
+static const struct StateEntryTemplate nvrc_fragmentstate_template[] =
+{
+    { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        nvrc_colorop        }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG1),      { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG2),      { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_OP),        { STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_OP),        tex_alphaop         }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG1),      { STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG2),      { STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   nvts_bumpenvmat     }, NV_TEXTURE_SHADER2              },
+    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
+    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
+    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
+    { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG0),      { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG0),      { STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(0, WINED3D_TSS_RESULT_ARG),      { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_OP),        { STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_OP),        nvrc_colorop        }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG1),      { STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG2),      { STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_OP),        { STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_OP),        tex_alphaop         }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG1),      { STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG2),      { STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   nvts_bumpenvmat     }, NV_TEXTURE_SHADER2              },
+    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
+    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
+    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
+    { STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG0),      { STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG0),      { STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(1, WINED3D_TSS_RESULT_ARG),      { STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_OP),        { STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_OP),        nvrc_colorop        }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG1),      { STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG2),      { STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_OP),        { STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_OP),        tex_alphaop         }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG1),      { STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG2),      { STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   nvts_bumpenvmat     }, NV_TEXTURE_SHADER2              },
+    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
+    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
+    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
+    { STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG0),      { STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG0),      { STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(2, WINED3D_TSS_RESULT_ARG),      { STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_OP),        { STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_OP),        nvrc_colorop        }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG1),      { STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG2),      { STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_OP),        { STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_OP),        tex_alphaop         }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG1),      { STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG2),      { STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   nvts_bumpenvmat     }, NV_TEXTURE_SHADER2              },
+    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
+    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
+    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
+    { STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG0),      { STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG0),      { STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(3, WINED3D_TSS_RESULT_ARG),      { STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_OP),        { STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_OP),        nvrc_colorop        }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG1),      { STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG2),      { STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_OP),        { STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_OP),        tex_alphaop         }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG1),      { STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG2),      { STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   nvts_bumpenvmat     }, NV_TEXTURE_SHADER2              },
+    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
+    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
+    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
+    { STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG0),      { STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG0),      { STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(4, WINED3D_TSS_RESULT_ARG),      { STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_OP),        { STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_OP),        nvrc_colorop        }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG1),      { STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG2),      { STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_OP),        { STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_OP),        tex_alphaop         }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG1),      { STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG2),      { STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   nvts_bumpenvmat     }, NV_TEXTURE_SHADER2              },
+    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
+    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
+    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
+    { STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG0),      { STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG0),      { STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(5, WINED3D_TSS_RESULT_ARG),      { STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_OP),        { STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_OP),        nvrc_colorop        }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG1),      { STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG2),      { STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_OP),        { STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_OP),        tex_alphaop         }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG1),      { STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG2),      { STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   nvts_bumpenvmat     }, NV_TEXTURE_SHADER2              },
+    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
+    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
+    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
+    { STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG0),      { STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG0),      { STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(6, WINED3D_TSS_RESULT_ARG),      { STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_OP),        { STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_OP),        nvrc_colorop        }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG1),      { STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG2),      { STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_OP),        { STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_OP),        tex_alphaop         }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG1),      { STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG2),      { STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   nvts_bumpenvmat     }, NV_TEXTURE_SHADER2              },
+    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
+    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
+    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
+    { STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG0),      { STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG0),      { STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(7, WINED3D_TSS_RESULT_ARG),      { STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_PIXELSHADER,                                  { STATE_PIXELSHADER,                                  apply_pixelshader   }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE),           { STATE_PIXELSHADER,                                  NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_TEXTUREFACTOR),             { STATE_RENDER(WINED3D_RS_TEXTUREFACTOR),             nvrc_texfactor      }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_FOGCOLOR),                  { STATE_RENDER(WINED3D_RS_FOGCOLOR),                  state_fogcolor      }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_FOGDENSITY),                { STATE_RENDER(WINED3D_RS_FOGDENSITY),                state_fogdensity    }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_FOGENABLE),                 { STATE_RENDER(WINED3D_RS_FOGENABLE),                 state_fog_fragpart  }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_FOGTABLEMODE),              { STATE_RENDER(WINED3D_RS_FOGENABLE),                 NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_FOGVERTEXMODE),             { STATE_RENDER(WINED3D_RS_FOGENABLE),                 NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_FOGSTART),                  { STATE_RENDER(WINED3D_RS_FOGSTART),                  state_fogstartend   }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_FOGEND),                    { STATE_RENDER(WINED3D_RS_FOGSTART),                  NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(0),                                   { STATE_SAMPLER(0),                                   nvts_texdim         }, NV_TEXTURE_SHADER2              },
+    { STATE_SAMPLER(0),                                   { STATE_SAMPLER(0),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(1),                                   { STATE_SAMPLER(1),                                   nvts_texdim         }, NV_TEXTURE_SHADER2              },
+    { STATE_SAMPLER(1),                                   { STATE_SAMPLER(1),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(2),                                   { STATE_SAMPLER(2),                                   nvts_texdim         }, NV_TEXTURE_SHADER2              },
+    { STATE_SAMPLER(2),                                   { STATE_SAMPLER(2),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(3),                                   { STATE_SAMPLER(3),                                   nvts_texdim         }, NV_TEXTURE_SHADER2              },
+    { STATE_SAMPLER(3),                                   { STATE_SAMPLER(3),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(4),                                   { STATE_SAMPLER(4),                                   nvts_texdim         }, NV_TEXTURE_SHADER2              },
+    { STATE_SAMPLER(4),                                   { STATE_SAMPLER(4),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(5),                                   { STATE_SAMPLER(5),                                   nvts_texdim         }, NV_TEXTURE_SHADER2              },
+    { STATE_SAMPLER(5),                                   { STATE_SAMPLER(5),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(6),                                   { STATE_SAMPLER(6),                                   nvts_texdim         }, NV_TEXTURE_SHADER2              },
+    { STATE_SAMPLER(6),                                   { STATE_SAMPLER(6),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(7),                                   { STATE_SAMPLER(7),                                   nvts_texdim         }, NV_TEXTURE_SHADER2              },
+    { STATE_SAMPLER(7),                                   { STATE_SAMPLER(7),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
+    {0 /* Terminate */,                                   { 0,                                                  0                   }, WINED3D_GL_EXT_NONE             },
+};
+
+const struct fragment_pipeline nvts_fragment_pipeline = {
+    nvts_enable,
+    nvrc_fragment_get_caps,
+    nvrc_fragment_alloc,
+    nvrc_fragment_free,
+    nvts_color_fixup_supported,
+    nvrc_fragmentstate_template,
+};
+
+const struct fragment_pipeline nvrc_fragment_pipeline = {
+    nvrc_enable,
+    nvrc_fragment_get_caps,
+    nvrc_fragment_alloc,
+    nvrc_fragment_free,
+    nvts_color_fixup_supported,
+    nvrc_fragmentstate_template,
+};
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/palette.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/palette.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/palette.c	(revision 46521)
@@ -0,0 +1,216 @@
+/*              DirectDraw - IDirectPalette base interface
+ *
+ * Copyright 1997-2000 Marcus Meissner
+ * Copyright 2000-2001 TransGaming Technologies Inc.
+ * Copyright 2006 Stefan Dösinger for CodeWeavers
+ *
+ * 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 "winerror.h"
+#include "wine/debug.h"
+
+#include <string.h>
+
+#include "wined3d_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d);
+
+#define SIZE_BITS (WINEDDPCAPS_1BIT | WINEDDPCAPS_2BIT | WINEDDPCAPS_4BIT | WINEDDPCAPS_8BIT)
+
+ULONG CDECL wined3d_palette_incref(struct wined3d_palette *palette)
+{
+    ULONG refcount = InterlockedIncrement(&palette->ref);
+
+    TRACE("%p increasing refcount to %u.\n", palette, refcount);
+
+    return refcount;
+}
+
+ULONG CDECL wined3d_palette_decref(struct wined3d_palette *palette)
+{
+    ULONG refcount = InterlockedDecrement(&palette->ref);
+
+    TRACE("%p decreasing refcount to %u.\n", palette, refcount);
+
+    if (!refcount)
+    {
+        DeleteObject(palette->hpal);
+        HeapFree(GetProcessHeap(), 0, palette);
+    }
+
+    return refcount;
+}
+
+static WORD wined3d_palette_size(DWORD flags)
+{
+    switch (flags & SIZE_BITS)
+    {
+        case WINEDDPCAPS_1BIT: return 2;
+        case WINEDDPCAPS_2BIT: return 4;
+        case WINEDDPCAPS_4BIT: return 16;
+        case WINEDDPCAPS_8BIT: return 256;
+        default:
+            FIXME("Unhandled size bits %#x.\n", flags & SIZE_BITS);
+            return 256;
+    }
+}
+
+HRESULT CDECL wined3d_palette_get_entries(const struct wined3d_palette *palette,
+        DWORD flags, DWORD start, DWORD count, PALETTEENTRY *entries)
+{
+    TRACE("palette %p, flags %#x, start %u, count %u, entries %p.\n",
+            palette, flags, start, count, entries);
+
+    if (flags) return WINED3DERR_INVALIDCALL; /* unchecked */
+    if (start + count > wined3d_palette_size(palette->flags))
+        return WINED3DERR_INVALIDCALL;
+
+    if (palette->flags & WINEDDPCAPS_8BITENTRIES)
+    {
+        BYTE *entry = (BYTE *)entries;
+        unsigned int i;
+
+        for (i = start; i < count + start; ++i)
+            *entry++ = palette->palents[i].peRed;
+    }
+    else
+        memcpy(entries, palette->palents + start, count * sizeof(*entries));
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_palette_set_entries(struct wined3d_palette *palette,
+        DWORD flags, DWORD start, DWORD count, const PALETTEENTRY *entries)
+{
+    struct wined3d_resource *resource;
+
+    TRACE("palette %p, flags %#x, start %u, count %u, entries %p.\n",
+            palette, flags, start, count, entries);
+    TRACE("Palette flags: %#x.\n", palette->flags);
+
+    if (palette->flags & WINEDDPCAPS_8BITENTRIES)
+    {
+        const BYTE *entry = (const BYTE *)entries;
+        unsigned int i;
+
+        for (i = start; i < count + start; ++i)
+            palette->palents[i].peRed = *entry++;
+    }
+    else
+    {
+        memcpy(palette->palents + start, entries, count * sizeof(*palette->palents));
+
+        /* When WINEDDCAPS_ALLOW256 isn't set we need to override entry 0 with black and 255 with white */
+        if (!(palette->flags & WINEDDPCAPS_ALLOW256))
+        {
+            TRACE("WINEDDPCAPS_ALLOW256 set, overriding palette entry 0 with black and 255 with white\n");
+            palette->palents[0].peRed = 0;
+            palette->palents[0].peGreen = 0;
+            palette->palents[0].peBlue = 0;
+
+            palette->palents[255].peRed = 255;
+            palette->palents[255].peGreen = 255;
+            palette->palents[255].peBlue = 255;
+        }
+
+        if (palette->hpal)
+            SetPaletteEntries(palette->hpal, start, count, palette->palents + start);
+    }
+
+    /* If the palette is attached to the render target, update all render targets */
+    LIST_FOR_EACH_ENTRY(resource, &palette->device->resources, struct wined3d_resource, resource_list_entry)
+    {
+        if (resource->type == WINED3D_RTYPE_SURFACE)
+        {
+            struct wined3d_surface *surface = surface_from_resource(resource);
+            if (surface->palette == palette)
+                surface->surface_ops->surface_realize_palette(surface);
+        }
+    }
+
+    return WINED3D_OK;
+}
+
+DWORD CDECL wined3d_palette_get_flags(const struct wined3d_palette *palette)
+{
+    TRACE("palette %p.\n", palette);
+
+    return palette->flags;
+}
+
+void * CDECL wined3d_palette_get_parent(const struct wined3d_palette *palette)
+{
+    TRACE("palette %p.\n", palette);
+
+    return palette->parent;
+}
+
+static HRESULT wined3d_palette_init(struct wined3d_palette *palette, struct wined3d_device *device,
+        DWORD flags, const PALETTEENTRY *entries, void *parent)
+{
+    HRESULT hr;
+
+    palette->ref = 1;
+    palette->parent = parent;
+    palette->device = device;
+    palette->flags = flags;
+
+    palette->palNumEntries = wined3d_palette_size(flags);
+    palette->hpal = CreatePalette((const LOGPALETTE *)&palette->palVersion);
+    if (!palette->hpal)
+    {
+        WARN("Failed to create palette.\n");
+        return E_FAIL;
+    }
+
+    hr = wined3d_palette_set_entries(palette, 0, 0, wined3d_palette_size(flags), entries);
+    if (FAILED(hr))
+    {
+        WARN("Failed to set palette entries, hr %#x.\n", hr);
+        DeleteObject(palette->hpal);
+        return hr;
+    }
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_palette_create(struct wined3d_device *device, DWORD flags,
+        const PALETTEENTRY *entries, void *parent, struct wined3d_palette **palette)
+{
+    struct wined3d_palette *object;
+    HRESULT hr;
+
+    TRACE("device %p, flags %#x, entries %p, palette %p, parent %p.\n",
+            device, flags, entries, palette, parent);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return E_OUTOFMEMORY;
+
+    hr = wined3d_palette_init(object, device, flags, entries, parent);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize palette, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created palette %p.\n", object);
+    *palette = object;
+
+    return WINED3D_OK;
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/query.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/query.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/query.c	(revision 46521)
@@ -0,0 +1,645 @@
+/*
+ * Copyright 2005 Oliver Stieber
+ * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
+ * Copyright 2009-2010 Henri Verbeet for CodeWeavers.
+ *
+ * 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 "wined3d_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d);
+
+BOOL wined3d_event_query_supported(const struct wined3d_gl_info *gl_info)
+{
+    return gl_info->supported[ARB_SYNC] || gl_info->supported[NV_FENCE] || gl_info->supported[APPLE_FENCE];
+}
+
+void wined3d_event_query_destroy(struct wined3d_event_query *query)
+{
+    if (query->context) context_free_event_query(query);
+    HeapFree(GetProcessHeap(), 0, query);
+}
+
+static enum wined3d_event_query_result wined3d_event_query_test(const struct wined3d_event_query *query,
+        const struct wined3d_device *device)
+{
+    struct wined3d_context *context;
+    const struct wined3d_gl_info *gl_info;
+    enum wined3d_event_query_result ret;
+    BOOL fence_result;
+
+    TRACE("(%p) : device %p\n", query, device);
+
+    if (!query->context)
+    {
+        TRACE("Query not started\n");
+        return WINED3D_EVENT_QUERY_NOT_STARTED;
+    }
+
+#if !defined(VBOX_WINE_WITH_SINGLE_CONTEXT) && !defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
+    if (!query->context->gl_info->supported[ARB_SYNC] && query->context->tid != GetCurrentThreadId())
+    {
+        WARN("Event query tested from wrong thread\n");
+        return WINED3D_EVENT_QUERY_WRONG_THREAD;
+    }
+#endif
+
+    context = context_acquire(device, query->context->current_rt);
+    gl_info = context->gl_info;
+
+    if (gl_info->supported[ARB_SYNC])
+    {
+        GLenum gl_ret = GL_EXTCALL(glClientWaitSync(query->object.sync, 0, 0));
+        checkGLcall("glClientWaitSync");
+
+        switch (gl_ret)
+        {
+            case GL_ALREADY_SIGNALED:
+            case GL_CONDITION_SATISFIED:
+                ret = WINED3D_EVENT_QUERY_OK;
+                break;
+
+            case GL_TIMEOUT_EXPIRED:
+                ret = WINED3D_EVENT_QUERY_WAITING;
+                break;
+
+            case GL_WAIT_FAILED:
+            default:
+                ERR("glClientWaitSync returned %#x.\n", gl_ret);
+                ret = WINED3D_EVENT_QUERY_ERROR;
+        }
+    }
+    else if (gl_info->supported[APPLE_FENCE])
+    {
+        fence_result = GL_EXTCALL(glTestFenceAPPLE(query->object.id));
+        checkGLcall("glTestFenceAPPLE");
+        if (fence_result) ret = WINED3D_EVENT_QUERY_OK;
+        else ret = WINED3D_EVENT_QUERY_WAITING;
+    }
+    else if (gl_info->supported[NV_FENCE])
+    {
+        fence_result = GL_EXTCALL(glTestFenceNV(query->object.id));
+        checkGLcall("glTestFenceNV");
+        if (fence_result) ret = WINED3D_EVENT_QUERY_OK;
+        else ret = WINED3D_EVENT_QUERY_WAITING;
+    }
+    else
+    {
+#ifdef VBOX_WITH_WDDM
+        /* doing Flush (rather than Finish) should be enough since we're serialized on the host in any way */
+        gl_info->gl_ops.gl.p_glFlush();
+        ret = WINED3D_EVENT_QUERY_OK;
+#else
+        ERR("Event query created despite lack of GL support\n");
+        ret = WINED3D_EVENT_QUERY_ERROR;
+#endif
+    }
+
+    context_release(context);
+    return ret;
+}
+
+enum wined3d_event_query_result wined3d_event_query_finish(const struct wined3d_event_query *query,
+        const struct wined3d_device *device)
+{
+    struct wined3d_context *context;
+    const struct wined3d_gl_info *gl_info;
+    enum wined3d_event_query_result ret;
+
+    TRACE("(%p)\n", query);
+
+    if (!query->context)
+    {
+        TRACE("Query not started\n");
+        return WINED3D_EVENT_QUERY_NOT_STARTED;
+    }
+    gl_info = query->context->gl_info;
+
+#if !defined(VBOX_WINE_WITH_SINGLE_CONTEXT) && !defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
+    if (query->context->tid != GetCurrentThreadId() && !gl_info->supported[ARB_SYNC])
+    {
+        /* A glFinish does not reliably wait for draws in other contexts. The caller has
+         * to find its own way to cope with the thread switch
+         */
+        WARN("Event query finished from wrong thread\n");
+        return WINED3D_EVENT_QUERY_WRONG_THREAD;
+    }
+#endif
+
+    context = context_acquire(device, query->context->current_rt);
+
+    if (gl_info->supported[ARB_SYNC])
+    {
+        /* Apple seems to be into arbitrary limits, and timeouts larger than
+         * 0xfffffffffffffbff immediately return GL_TIMEOUT_EXPIRED. We don't
+         * really care and can live with waiting a few μs less. (OS X 10.7.4). */
+        GLenum gl_ret = GL_EXTCALL(glClientWaitSync(query->object.sync, GL_SYNC_FLUSH_COMMANDS_BIT, ~(GLuint64)0xffff));
+        checkGLcall("glClientWaitSync");
+
+        switch (gl_ret)
+        {
+            case GL_ALREADY_SIGNALED:
+            case GL_CONDITION_SATISFIED:
+                ret = WINED3D_EVENT_QUERY_OK;
+                break;
+
+                /* We don't expect a timeout for a ~584 year wait */
+            default:
+                ERR("glClientWaitSync returned %#x.\n", gl_ret);
+                ret = WINED3D_EVENT_QUERY_ERROR;
+        }
+    }
+    else if (context->gl_info->supported[APPLE_FENCE])
+    {
+        GL_EXTCALL(glFinishFenceAPPLE(query->object.id));
+        checkGLcall("glFinishFenceAPPLE");
+        ret = WINED3D_EVENT_QUERY_OK;
+    }
+    else if (context->gl_info->supported[NV_FENCE])
+    {
+        GL_EXTCALL(glFinishFenceNV(query->object.id));
+        checkGLcall("glFinishFenceNV");
+        ret = WINED3D_EVENT_QUERY_OK;
+    }
+    else
+    {
+        ERR("Event query created without GL support\n");
+        ret = WINED3D_EVENT_QUERY_ERROR;
+    }
+
+    context_release(context);
+    return ret;
+}
+
+void wined3d_event_query_issue(struct wined3d_event_query *query, const struct wined3d_device *device)
+{
+    const struct wined3d_gl_info *gl_info;
+    struct wined3d_context *context;
+
+    if (query->context)
+    {
+#if !defined(VBOX_WINE_WITH_SINGLE_CONTEXT) && !defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
+        if (!query->context->gl_info->supported[ARB_SYNC] && query->context->tid != GetCurrentThreadId())
+        {
+            context_free_event_query(query);
+            context = context_acquire(device, NULL);
+            context_alloc_event_query(context, query);
+        }
+        else
+#endif
+        {
+            context = context_acquire(device, query->context->current_rt);
+        }
+    }
+    else
+    {
+        context = context_acquire(device, NULL);
+        context_alloc_event_query(context, query);
+    }
+
+    gl_info = context->gl_info;
+
+    if (gl_info->supported[ARB_SYNC])
+    {
+        if (query->object.sync) GL_EXTCALL(glDeleteSync(query->object.sync));
+        checkGLcall("glDeleteSync");
+        query->object.sync = GL_EXTCALL(glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0));
+        checkGLcall("glFenceSync");
+    }
+    else if (gl_info->supported[APPLE_FENCE])
+    {
+        GL_EXTCALL(glSetFenceAPPLE(query->object.id));
+        checkGLcall("glSetFenceAPPLE");
+    }
+    else if (gl_info->supported[NV_FENCE])
+    {
+        GL_EXTCALL(glSetFenceNV(query->object.id, GL_ALL_COMPLETED_NV));
+        checkGLcall("glSetFenceNV");
+    }
+
+    context_release(context);
+}
+
+ULONG CDECL wined3d_query_incref(struct wined3d_query *query)
+{
+    ULONG refcount = InterlockedIncrement(&query->ref);
+
+    TRACE("%p increasing refcount to %u.\n", query, refcount);
+
+    return refcount;
+}
+
+ULONG CDECL wined3d_query_decref(struct wined3d_query *query)
+{
+    ULONG refcount = InterlockedDecrement(&query->ref);
+
+    TRACE("%p decreasing refcount to %u.\n", query, refcount);
+
+    if (!refcount)
+    {
+        /* Queries are specific to the GL context that created them. Not
+         * deleting the query will obviously leak it, but that's still better
+         * than potentially deleting a different query with the same id in this
+         * context, and (still) leaking the actual query. */
+        if (query->type == WINED3D_QUERY_TYPE_EVENT)
+        {
+            struct wined3d_event_query *event_query = query->extendedData;
+            if (event_query) wined3d_event_query_destroy(event_query);
+        }
+        else if (query->type == WINED3D_QUERY_TYPE_OCCLUSION)
+        {
+            struct wined3d_occlusion_query *oq = query->extendedData;
+
+            if (oq->context) context_free_occlusion_query(oq);
+            HeapFree(GetProcessHeap(), 0, query->extendedData);
+        }
+
+        HeapFree(GetProcessHeap(), 0, query);
+    }
+
+    return refcount;
+}
+
+HRESULT CDECL wined3d_query_get_data(struct wined3d_query *query,
+        void *data, UINT data_size, DWORD flags)
+{
+    TRACE("query %p, data %p, data_size %u, flags %#x.\n",
+            query, data, data_size, flags);
+
+    return query->query_ops->query_get_data(query, data, data_size, flags);
+}
+
+UINT CDECL wined3d_query_get_data_size(const struct wined3d_query *query)
+{
+    TRACE("query %p.\n", query);
+
+    return query->data_size;
+}
+
+HRESULT CDECL wined3d_query_issue(struct wined3d_query *query, DWORD flags)
+{
+    TRACE("query %p, flags %#x.\n", query, flags);
+
+    return query->query_ops->query_issue(query, flags);
+}
+
+static HRESULT wined3d_occlusion_query_ops_get_data(struct wined3d_query *query,
+        void *pData, DWORD dwSize, DWORD flags)
+{
+    struct wined3d_occlusion_query *oq = query->extendedData;
+    struct wined3d_device *device = query->device;
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    struct wined3d_context *context;
+    DWORD* data = pData;
+    GLuint available;
+    GLuint samples;
+    HRESULT res;
+
+    TRACE("(%p) : type D3DQUERY_OCCLUSION, pData %p, dwSize %#x, flags %#x.\n", query, pData, dwSize, flags);
+
+    if (!oq->context)
+        query->state = QUERY_CREATED;
+
+    if (query->state == QUERY_CREATED)
+    {
+        /* D3D allows GetData on a new query, OpenGL doesn't. So just invent the data ourselves */
+        TRACE("Query wasn't yet started, returning S_OK\n");
+        if(data) *data = 0;
+        return S_OK;
+    }
+
+    if (query->state == QUERY_BUILDING)
+    {
+        /* Msdn says this returns an error, but our tests show that S_FALSE is returned */
+        TRACE("Query is building, returning S_FALSE\n");
+        return S_FALSE;
+    }
+
+    if (!gl_info->supported[ARB_OCCLUSION_QUERY])
+    {
+        WARN("%p Occlusion queries not supported. Returning 1.\n", query);
+        *data = 1;
+        return S_OK;
+    }
+
+#if !defined(VBOX_WINE_WITH_SINGLE_CONTEXT) && !defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
+    if (oq->context->tid != GetCurrentThreadId())
+    {
+        FIXME("%p Wrong thread, returning 1.\n", query);
+        *data = 1;
+        return S_OK;
+    }
+#endif
+
+    context = context_acquire(query->device, oq->context->current_rt);
+
+    GL_EXTCALL(glGetQueryObjectuivARB(oq->id, GL_QUERY_RESULT_AVAILABLE_ARB, &available));
+    checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT_AVAILABLE)");
+    TRACE("available %#x.\n", available);
+
+    if (available)
+    {
+        if (data)
+        {
+            GL_EXTCALL(glGetQueryObjectuivARB(oq->id, GL_QUERY_RESULT_ARB, &samples));
+            checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT)");
+            TRACE("Returning %d samples.\n", samples);
+            *data = samples;
+        }
+        res = S_OK;
+    }
+    else
+    {
+        res = S_FALSE;
+    }
+
+    context_release(context);
+
+    return res;
+}
+
+static HRESULT wined3d_event_query_ops_get_data(struct wined3d_query *query,
+        void *pData, DWORD dwSize, DWORD flags)
+{
+    struct wined3d_event_query *event_query = query->extendedData;
+    BOOL *data = pData;
+    enum wined3d_event_query_result ret;
+
+    TRACE("query %p, pData %p, dwSize %#x, flags %#x.\n", query, pData, dwSize, flags);
+
+    if (!pData || !dwSize) return S_OK;
+    if (!event_query)
+    {
+        WARN("Event query not supported by GL, reporting GPU idle.\n");
+        *data = TRUE;
+        return S_OK;
+    }
+
+    ret = wined3d_event_query_test(event_query, query->device);
+    switch(ret)
+    {
+        case WINED3D_EVENT_QUERY_OK:
+        case WINED3D_EVENT_QUERY_NOT_STARTED:
+            *data = TRUE;
+            break;
+
+        case WINED3D_EVENT_QUERY_WAITING:
+            *data = FALSE;
+            break;
+
+        case WINED3D_EVENT_QUERY_WRONG_THREAD:
+            FIXME("(%p) Wrong thread, reporting GPU idle.\n", query);
+            *data = TRUE;
+            break;
+
+        case WINED3D_EVENT_QUERY_ERROR:
+            ERR("The GL event query failed, returning D3DERR_INVALIDCALL\n");
+            return WINED3DERR_INVALIDCALL;
+    }
+
+    return S_OK;
+}
+
+enum wined3d_query_type CDECL wined3d_query_get_type(const struct wined3d_query *query)
+{
+    TRACE("query %p.\n", query);
+
+    return query->type;
+}
+
+static HRESULT wined3d_event_query_ops_issue(struct wined3d_query *query, DWORD flags)
+{
+    TRACE("query %p, flags %#x.\n", query, flags);
+
+    TRACE("(%p) : flags %#x, type D3DQUERY_EVENT\n", query, flags);
+    if (flags & WINED3DISSUE_END)
+    {
+        struct wined3d_event_query *event_query = query->extendedData;
+
+        /* Faked event query support */
+        if (!event_query) return WINED3D_OK;
+
+        wined3d_event_query_issue(event_query, query->device);
+    }
+    else if (flags & WINED3DISSUE_BEGIN)
+    {
+        /* Started implicitly at device creation */
+        ERR("Event query issued with START flag - what to do?\n");
+    }
+
+    if (flags & WINED3DISSUE_BEGIN)
+        query->state = QUERY_BUILDING;
+    else
+        query->state = QUERY_SIGNALLED;
+
+    return WINED3D_OK;
+}
+
+static HRESULT wined3d_occlusion_query_ops_issue(struct wined3d_query *query, DWORD flags)
+{
+    struct wined3d_device *device = query->device;
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+
+    TRACE("query %p, flags %#x.\n", query, flags);
+
+    if (gl_info->supported[ARB_OCCLUSION_QUERY])
+    {
+        struct wined3d_occlusion_query *oq = query->extendedData;
+        struct wined3d_context *context;
+
+        /* This is allowed according to msdn and our tests. Reset the query and restart */
+        if (flags & WINED3DISSUE_BEGIN)
+        {
+            if (query->state == QUERY_BUILDING)
+            {
+#if !defined(VBOX_WINE_WITH_SINGLE_CONTEXT) && !defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
+                if (oq->context->tid != GetCurrentThreadId())
+                {
+                    FIXME("Wrong thread, can't restart query.\n");
+
+                    context_free_occlusion_query(oq);
+                    context = context_acquire(query->device, NULL);
+                    context_alloc_occlusion_query(context, oq);
+                }
+                else
+#endif
+                {
+                    context = context_acquire(query->device, oq->context->current_rt);
+
+                    GL_EXTCALL(glEndQueryARB(GL_SAMPLES_PASSED_ARB));
+                    checkGLcall("glEndQuery()");
+                }
+            }
+            else
+            {
+                if (oq->context) context_free_occlusion_query(oq);
+                context = context_acquire(query->device, NULL);
+                context_alloc_occlusion_query(context, oq);
+            }
+
+            GL_EXTCALL(glBeginQueryARB(GL_SAMPLES_PASSED_ARB, oq->id));
+            checkGLcall("glBeginQuery()");
+
+            context_release(context);
+        }
+        if (flags & WINED3DISSUE_END)
+        {
+            /* Msdn says _END on a non-building occlusion query returns an error, but
+             * our tests show that it returns OK. But OpenGL doesn't like it, so avoid
+             * generating an error
+             */
+            if (query->state == QUERY_BUILDING)
+            {
+#if !defined(VBOX_WINE_WITH_SINGLE_CONTEXT) && !defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
+                if (oq->context->tid != GetCurrentThreadId())
+                {
+                    FIXME("Wrong thread, can't end query.\n");
+                }
+                else
+#endif
+                {
+                    context = context_acquire(query->device, oq->context->current_rt);
+
+                    GL_EXTCALL(glEndQueryARB(GL_SAMPLES_PASSED_ARB));
+                    checkGLcall("glEndQuery()");
+
+                    context_release(context);
+                }
+            }
+        }
+    }
+    else
+    {
+        FIXME("%p Occlusion queries not supported.\n", query);
+    }
+
+    if (flags & WINED3DISSUE_BEGIN)
+        query->state = QUERY_BUILDING;
+    else
+        query->state = QUERY_SIGNALLED;
+
+    return WINED3D_OK; /* can be WINED3DERR_INVALIDCALL.    */
+}
+
+static const struct wined3d_query_ops event_query_ops =
+{
+    wined3d_event_query_ops_get_data,
+    wined3d_event_query_ops_issue,
+};
+
+static const struct wined3d_query_ops occlusion_query_ops =
+{
+    wined3d_occlusion_query_ops_get_data,
+    wined3d_occlusion_query_ops_issue,
+};
+
+static HRESULT query_init(struct wined3d_query *query, struct wined3d_device *device, enum wined3d_query_type type)
+{
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+
+    switch (type)
+    {
+        case WINED3D_QUERY_TYPE_OCCLUSION:
+            TRACE("Occlusion query.\n");
+            if (!gl_info->supported[ARB_OCCLUSION_QUERY])
+            {
+                WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY.\n");
+                return WINED3DERR_NOTAVAILABLE;
+            }
+            query->query_ops = &occlusion_query_ops;
+            query->data_size = sizeof(DWORD);
+            query->extendedData = HeapAlloc(GetProcessHeap(), 0, sizeof(struct wined3d_occlusion_query));
+            if (!query->extendedData)
+            {
+                ERR("Failed to allocate occlusion query extended data.\n");
+                return E_OUTOFMEMORY;
+            }
+            ((struct wined3d_occlusion_query *)query->extendedData)->context = NULL;
+            break;
+
+        case WINED3D_QUERY_TYPE_EVENT:
+            TRACE("Event query.\n");
+            if (!wined3d_event_query_supported(gl_info))
+            {
+                /* Half-Life 2 needs this query. It does not render the main
+                 * menu correctly otherwise. Pretend to support it, faking
+                 * this query does not do much harm except potentially
+                 * lowering performance. */
+                FIXME("Event query: Unimplemented, but pretending to be supported.\n");
+            }
+            query->query_ops = &event_query_ops;
+            query->data_size = sizeof(BOOL);
+            query->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct wined3d_event_query));
+            if (!query->extendedData)
+            {
+                ERR("Failed to allocate event query memory.\n");
+                return E_OUTOFMEMORY;
+            }
+            break;
+
+        case WINED3D_QUERY_TYPE_VCACHE:
+        case WINED3D_QUERY_TYPE_RESOURCE_MANAGER:
+        case WINED3D_QUERY_TYPE_VERTEX_STATS:
+        case WINED3D_QUERY_TYPE_TIMESTAMP:
+        case WINED3D_QUERY_TYPE_TIMESTAMP_DISJOINT:
+        case WINED3D_QUERY_TYPE_TIMESTAMP_FREQ:
+        case WINED3D_QUERY_TYPE_PIPELINE_TIMINGS:
+        case WINED3D_QUERY_TYPE_INTERFACE_TIMINGS:
+        case WINED3D_QUERY_TYPE_VERTEX_TIMINGS:
+        case WINED3D_QUERY_TYPE_PIXEL_TIMINGS:
+        case WINED3D_QUERY_TYPE_BANDWIDTH_TIMINGS:
+        case WINED3D_QUERY_TYPE_CACHE_UTILIZATION:
+        default:
+            FIXME("Unhandled query type %#x.\n", type);
+            return WINED3DERR_NOTAVAILABLE;
+    }
+
+    query->type = type;
+    query->state = QUERY_CREATED;
+    query->device = device;
+    query->ref = 1;
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_query_create(struct wined3d_device *device,
+        enum wined3d_query_type type, struct wined3d_query **query)
+{
+    struct wined3d_query *object;
+    HRESULT hr;
+
+    TRACE("device %p, type %#x, query %p.\n", device, type, query);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return E_OUTOFMEMORY;
+
+    hr = query_init(object, device, type);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize query, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created query %p.\n", object);
+    *query = object;
+
+    return WINED3D_OK;
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/resource.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/resource.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/resource.c	(revision 46521)
@@ -0,0 +1,368 @@
+/*
+ * Copyright 2002-2004 Jason Edmeades
+ * Copyright 2003-2004 Raphael Junqueira
+ * Copyright 2004 Christian Costa
+ * Copyright 2005 Oliver Stieber
+ * Copyright 2009-2010 Henri Verbeet for CodeWeavers
+ *
+ * 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 "wined3d_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d);
+
+struct private_data
+{
+    struct list entry;
+
+    GUID tag;
+    DWORD flags; /* DDSPD_* */
+
+    union
+    {
+        void *data;
+        IUnknown *object;
+    } ptr;
+
+    DWORD size;
+};
+
+static DWORD resource_access_from_pool(enum wined3d_pool pool)
+{
+    switch (pool)
+    {
+        case WINED3D_POOL_DEFAULT:
+            return WINED3D_RESOURCE_ACCESS_GPU;
+
+        case WINED3D_POOL_MANAGED:
+            return WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_CPU;
+
+        case WINED3D_POOL_SYSTEM_MEM:
+            return WINED3D_RESOURCE_ACCESS_CPU;
+
+        case WINED3D_POOL_SCRATCH:
+            return WINED3D_RESOURCE_ACCESS_SCRATCH;
+
+        default:
+            FIXME("Unhandled pool %#x.\n", pool);
+            return 0;
+    }
+}
+
+static void resource_check_usage(DWORD usage)
+{
+    static const DWORD handled = WINED3DUSAGE_RENDERTARGET
+            | WINED3DUSAGE_DEPTHSTENCIL
+            | WINED3DUSAGE_DYNAMIC
+            | WINED3DUSAGE_AUTOGENMIPMAP
+            | WINED3DUSAGE_STATICDECL
+            | WINED3DUSAGE_OVERLAY;
+
+    if (usage & ~handled)
+        FIXME("Unhandled usage flags %#x.\n", usage & ~handled);
+}
+
+HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device *device,
+        enum wined3d_resource_type type, const struct wined3d_format *format,
+        enum wined3d_multisample_type multisample_type, UINT multisample_quality,
+        DWORD usage, enum wined3d_pool pool, UINT width, UINT height, UINT depth, UINT size,
+        void *parent, const struct wined3d_parent_ops *parent_ops,
+        const struct wined3d_resource_ops *resource_ops
+#ifdef VBOX_WITH_WDDM
+        , HANDLE *shared_handle
+        , void *pvClientMem
+#endif
+        )
+{
+    const struct wined3d *d3d = device->wined3d;
+
+    resource->ref = 1;
+    resource->device = device;
+    resource->type = type;
+    resource->format = format;
+    resource->multisample_type = multisample_type;
+    resource->multisample_quality = multisample_quality;
+    resource->usage = usage;
+    resource->pool = pool;
+    resource->access_flags = resource_access_from_pool(pool);
+    if (usage & WINED3DUSAGE_DYNAMIC)
+        resource->access_flags |= WINED3D_RESOURCE_ACCESS_CPU;
+    resource->width = width;
+    resource->height = height;
+    resource->depth = depth;
+    resource->size = size;
+    resource->priority = 0;
+    resource->parent = parent;
+    resource->parent_ops = parent_ops;
+    resource->resource_ops = resource_ops;
+    list_init(&resource->privateData);
+
+    resource_check_usage(usage);
+
+#ifdef VBOX_WITH_WDDM
+    resource->sharerc_handle = 0;
+    resource->sharerc_flags = 0;
+    resource->sharerc_locks = 0;
+    if (pool == WINED3D_POOL_SYSTEM_MEM && pvClientMem)
+    {
+        resource->allocatedMemory = pvClientMem;
+        resource->heapMemory = NULL;
+    }
+    else
+#endif
+    {
+#ifdef VBOX_WITH_WDDM
+        if (pool == WINED3D_POOL_DEFAULT && shared_handle)
+        {
+            resource->sharerc_handle = (DWORD)*shared_handle;
+            resource->sharerc_flags = VBOXSHRC_F_SHARED;
+            if (*shared_handle)
+                resource->sharerc_flags |= VBOXSHRC_F_SHARED_OPENED;
+        }
+#endif
+
+        if (size)
+        {
+            resource->heapMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size + RESOURCE_ALIGNMENT);
+            if (!resource->heapMemory)
+            {
+                ERR("Out of memory!\n");
+                return WINED3DERR_OUTOFVIDEOMEMORY;
+            }
+        }
+        else
+        {
+            resource->heapMemory = NULL;
+        }
+        resource->allocatedMemory = (BYTE *)(((ULONG_PTR)resource->heapMemory
+                + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1));
+    }
+
+#ifndef VBOX_WITH_WDDM
+    /* Check that we have enough video ram left */
+    if (pool == WINED3D_POOL_DEFAULT && d3d->flags & WINED3D_VIDMEM_ACCOUNTING)
+    {
+        if (size > wined3d_device_get_available_texture_mem(device))
+        {
+            ERR("Out of adapter memory\n");
+            HeapFree(GetProcessHeap(), 0, resource->heapMemory);
+            return WINED3DERR_OUTOFVIDEOMEMORY;
+        }
+        adapter_adjust_memory(device->adapter, size);
+    }
+#endif
+
+    device_resource_add(device, resource);
+
+    return WINED3D_OK;
+}
+
+void resource_cleanup(struct wined3d_resource *resource)
+{
+    const struct wined3d *d3d = resource->device->wined3d;
+    struct private_data *data;
+    struct list *e1, *e2;
+    HRESULT hr;
+
+    TRACE("Cleaning up resource %p.\n", resource);
+#ifndef VBOX_WITH_WDDM
+    if (resource->pool == WINED3D_POOL_DEFAULT && d3d->flags & WINED3D_VIDMEM_ACCOUNTING)
+    {
+        TRACE("Decrementing device memory pool by %u.\n", resource->size);
+        adapter_adjust_memory(resource->device->adapter, 0 - resource->size);
+    }
+#endif
+
+    LIST_FOR_EACH_SAFE(e1, e2, &resource->privateData)
+    {
+        data = LIST_ENTRY(e1, struct private_data, entry);
+        hr = wined3d_resource_free_private_data(resource, &data->tag);
+        if (FAILED(hr))
+            ERR("Failed to free private data when destroying resource %p, hr = %#x.\n", resource, hr);
+    }
+
+    HeapFree(GetProcessHeap(), 0, resource->heapMemory);
+    resource->allocatedMemory = 0;
+    resource->heapMemory = 0;
+
+        device_resource_released(resource->device, resource);
+}
+
+void resource_unload(struct wined3d_resource *resource)
+{
+    if (resource->map_count)
+        ERR("Resource %p is being unloaded while mapped.\n", resource);
+
+    context_resource_unloaded(resource->device,
+            resource, resource->type);
+}
+
+static struct private_data *resource_find_private_data(const struct wined3d_resource *resource, REFGUID tag)
+{
+    struct private_data *data;
+    struct list *entry;
+
+    TRACE("Searching for private data %s\n", debugstr_guid(tag));
+    LIST_FOR_EACH(entry, &resource->privateData)
+    {
+        data = LIST_ENTRY(entry, struct private_data, entry);
+        if (IsEqualGUID(&data->tag, tag)) {
+            TRACE("Found %p\n", data);
+            return data;
+        }
+    }
+    TRACE("Not found\n");
+    return NULL;
+}
+
+HRESULT CDECL wined3d_resource_set_private_data(struct wined3d_resource *resource, REFGUID guid,
+        const void *data, DWORD data_size, DWORD flags)
+{
+    struct private_data *d;
+
+    TRACE("resource %p, riid %s, data %p, data_size %u, flags %#x.\n",
+            resource, debugstr_guid(guid), data, data_size, flags);
+
+    wined3d_resource_free_private_data(resource, guid);
+
+    d = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*d));
+    if (!d) return E_OUTOFMEMORY;
+
+    d->tag = *guid;
+    d->flags = flags;
+
+    if (flags & WINED3DSPD_IUNKNOWN)
+    {
+        if (data_size != sizeof(IUnknown *))
+        {
+            WARN("IUnknown data with size %u, returning WINED3DERR_INVALIDCALL.\n", data_size);
+            HeapFree(GetProcessHeap(), 0, d);
+            return WINED3DERR_INVALIDCALL;
+        }
+        d->ptr.object = (IUnknown *)data;
+        d->size = sizeof(IUnknown *);
+        IUnknown_AddRef(d->ptr.object);
+    }
+    else
+    {
+        d->ptr.data = HeapAlloc(GetProcessHeap(), 0, data_size);
+        if (!d->ptr.data)
+        {
+            HeapFree(GetProcessHeap(), 0, d);
+            return E_OUTOFMEMORY;
+        }
+        d->size = data_size;
+        memcpy(d->ptr.data, data, data_size);
+    }
+    list_add_tail(&resource->privateData, &d->entry);
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_resource_get_private_data(const struct wined3d_resource *resource, REFGUID guid,
+        void *data, DWORD *data_size)
+{
+    const struct private_data *d;
+
+    TRACE("resource %p, guid %s, data %p, data_size %p.\n",
+            resource, debugstr_guid(guid), data, data_size);
+
+    d = resource_find_private_data(resource, guid);
+    if (!d) return WINED3DERR_NOTFOUND;
+
+    if (*data_size < d->size)
+    {
+        *data_size = d->size;
+        return WINED3DERR_MOREDATA;
+    }
+
+    if (d->flags & WINED3DSPD_IUNKNOWN)
+    {
+        *(IUnknown **)data = d->ptr.object;
+        if (resource->device->wined3d->dxVersion != 7)
+        {
+            /* D3D8 and D3D9 addref the private data, DDraw does not. This
+             * can't be handled in ddraw because it doesn't know if the
+             * pointer returned is an IUnknown * or just a blob. */
+            IUnknown_AddRef(d->ptr.object);
+        }
+    }
+    else
+    {
+        memcpy(data, d->ptr.data, d->size);
+    }
+
+    return WINED3D_OK;
+}
+HRESULT CDECL wined3d_resource_free_private_data(struct wined3d_resource *resource, REFGUID guid)
+{
+    struct private_data *data;
+
+    TRACE("resource %p, guid %s.\n", resource, debugstr_guid(guid));
+
+    data = resource_find_private_data(resource, guid);
+    if (!data) return WINED3DERR_NOTFOUND;
+
+    if (data->flags & WINED3DSPD_IUNKNOWN)
+    {
+        if (data->ptr.object)
+            IUnknown_Release(data->ptr.object);
+    }
+    else
+    {
+        HeapFree(GetProcessHeap(), 0, data->ptr.data);
+    }
+    list_remove(&data->entry);
+
+    HeapFree(GetProcessHeap(), 0, data);
+
+    return WINED3D_OK;
+}
+
+DWORD resource_set_priority(struct wined3d_resource *resource, DWORD priority)
+{
+    DWORD prev = resource->priority;
+    resource->priority = priority;
+    TRACE("resource %p, new priority %u, returning old priority %u.\n", resource, priority, prev);
+    return prev;
+}
+
+DWORD resource_get_priority(const struct wined3d_resource *resource)
+{
+    TRACE("resource %p, returning %u.\n", resource, resource->priority);
+    return resource->priority;
+}
+
+void * CDECL wined3d_resource_get_parent(const struct wined3d_resource *resource)
+{
+    return resource->parent;
+}
+
+void CDECL wined3d_resource_get_desc(const struct wined3d_resource *resource, struct wined3d_resource_desc *desc)
+{
+    desc->resource_type = resource->type;
+    desc->format = resource->format->id;
+    desc->multisample_type = resource->multisample_type;
+    desc->multisample_quality = resource->multisample_quality;
+    desc->usage = resource->usage;
+    desc->pool = resource->pool;
+    desc->width = resource->width;
+    desc->height = resource->height;
+    desc->depth = resource->depth;
+    desc->size = resource->size;
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/shader.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/shader.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/shader.c	(revision 46521)
@@ -0,0 +1,2606 @@
+/*
+ * Copyright 2002-2003 Jason Edmeades
+ * Copyright 2002-2003 Raphael Junqueira
+ * Copyright 2004 Christian Costa
+ * Copyright 2005 Oliver Stieber
+ * Copyright 2006 Ivan Gyurdiev
+ * Copyright 2007-2008, 2013 Stefan Dösinger for CodeWeavers
+ * Copyright 2009-2011 Henri Verbeet for CodeWeavers
+ *
+ * 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 <math.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "wined3d_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
+
+#ifdef VBOX_WINE_WITH_SHADER_CACHE
+static void shader_chache_put(PVBOXEXT_HASHCACHE pCache, struct wined3d_shader *shader);
+#endif
+
+static const char * const shader_opcode_names[] =
+{
+    /* WINED3DSIH_ABS                   */ "abs",
+    /* WINED3DSIH_ADD                   */ "add",
+    /* WINED3DSIH_AND                   */ "and",
+    /* WINED3DSIH_BEM                   */ "bem",
+    /* WINED3DSIH_BREAK                 */ "break",
+    /* WINED3DSIH_BREAKC                */ "breakc",
+    /* WINED3DSIH_BREAKP                */ "breakp",
+    /* WINED3DSIH_CALL                  */ "call",
+    /* WINED3DSIH_CALLNZ                */ "callnz",
+    /* WINED3DSIH_CMP                   */ "cmp",
+    /* WINED3DSIH_CND                   */ "cnd",
+    /* WINED3DSIH_CRS                   */ "crs",
+    /* WINED3DSIH_CUT                   */ "cut",
+    /* WINED3DSIH_DCL                   */ "dcl",
+    /* WINED3DSIH_DCL_CONSTANT_BUFFER   */ "dcl_constantBuffer",
+    /* WINED3DSIH_DCL_INPUT_PRIMITIVE   */ "dcl_inputPrimitive",
+    /* WINED3DSIH_DCL_OUTPUT_TOPOLOGY   */ "dcl_outputTopology",
+    /* WINED3DSIH_DCL_VERTICES_OUT      */ "dcl_maxOutputVertexCount",
+    /* WINED3DSIH_DEF                   */ "def",
+    /* WINED3DSIH_DEFB                  */ "defb",
+    /* WINED3DSIH_DEFI                  */ "defi",
+    /* WINED3DSIH_DIV                   */ "div",
+    /* WINED3DSIH_DP2ADD                */ "dp2add",
+    /* WINED3DSIH_DP3                   */ "dp3",
+    /* WINED3DSIH_DP4                   */ "dp4",
+    /* WINED3DSIH_DST                   */ "dst",
+    /* WINED3DSIH_DSX                   */ "dsx",
+    /* WINED3DSIH_DSY                   */ "dsy",
+    /* WINED3DSIH_ELSE                  */ "else",
+    /* WINED3DSIH_EMIT                  */ "emit",
+    /* WINED3DSIH_ENDIF                 */ "endif",
+    /* WINED3DSIH_ENDLOOP               */ "endloop",
+    /* WINED3DSIH_ENDREP                */ "endrep",
+    /* WINED3DSIH_EQ                    */ "eq",
+    /* WINED3DSIH_EXP                   */ "exp",
+    /* WINED3DSIH_EXPP                  */ "expp",
+    /* WINED3DSIH_FRC                   */ "frc",
+    /* WINED3DSIH_FTOI                  */ "ftoi",
+    /* WINED3DSIH_GE                    */ "ge",
+    /* WINED3DSIH_IADD                  */ "iadd",
+    /* WINED3DSIH_IEQ                   */ "ieq",
+    /* WINED3DSIH_IF                    */ "if",
+    /* WINED3DSIH_IFC                   */ "ifc",
+    /* WINED3DSIH_IGE                   */ "ige",
+    /* WINED3DSIH_IMUL                  */ "imul",
+    /* WINED3DSIH_ITOF                  */ "itof",
+    /* WINED3DSIH_LABEL                 */ "label",
+    /* WINED3DSIH_LD                    */ "ld",
+    /* WINED3DSIH_LIT                   */ "lit",
+    /* WINED3DSIH_LOG                   */ "log",
+    /* WINED3DSIH_LOGP                  */ "logp",
+    /* WINED3DSIH_LOOP                  */ "loop",
+    /* WINED3DSIH_LRP                   */ "lrp",
+    /* WINED3DSIH_LT                    */ "lt",
+    /* WINED3DSIH_M3x2                  */ "m3x2",
+    /* WINED3DSIH_M3x3                  */ "m3x3",
+    /* WINED3DSIH_M3x4                  */ "m3x4",
+    /* WINED3DSIH_M4x3                  */ "m4x3",
+    /* WINED3DSIH_M4x4                  */ "m4x4",
+    /* WINED3DSIH_MAD                   */ "mad",
+    /* WINED3DSIH_MAX                   */ "max",
+    /* WINED3DSIH_MIN                   */ "min",
+    /* WINED3DSIH_MOV                   */ "mov",
+    /* WINED3DSIH_MOVA                  */ "mova",
+    /* WINED3DSIH_MOVC                  */ "movc",
+    /* WINED3DSIH_MUL                   */ "mul",
+    /* WINED3DSIH_NOP                   */ "nop",
+    /* WINED3DSIH_NRM                   */ "nrm",
+    /* WINED3DSIH_PHASE                 */ "phase",
+    /* WINED3DSIH_POW                   */ "pow",
+    /* WINED3DSIH_RCP                   */ "rcp",
+    /* WINED3DSIH_REP                   */ "rep",
+    /* WINED3DSIH_RET                   */ "ret",
+    /* WINED3DSIH_ROUND_NI              */ "round_ni",
+    /* WINED3DSIH_RSQ                   */ "rsq",
+    /* WINED3DSIH_SAMPLE                */ "sample",
+    /* WINED3DSIH_SAMPLE_GRAD           */ "sample_d",
+    /* WINED3DSIH_SAMPLE_LOD            */ "sample_l",
+    /* WINED3DSIH_SETP                  */ "setp",
+    /* WINED3DSIH_SGE                   */ "sge",
+    /* WINED3DSIH_SGN                   */ "sgn",
+    /* WINED3DSIH_SINCOS                */ "sincos",
+    /* WINED3DSIH_SLT                   */ "slt",
+    /* WINED3DSIH_SQRT                  */ "sqrt",
+    /* WINED3DSIH_SUB                   */ "sub",
+    /* WINED3DSIH_TEX                   */ "texld",
+    /* WINED3DSIH_TEXBEM                */ "texbem",
+    /* WINED3DSIH_TEXBEML               */ "texbeml",
+    /* WINED3DSIH_TEXCOORD              */ "texcrd",
+    /* WINED3DSIH_TEXDEPTH              */ "texdepth",
+    /* WINED3DSIH_TEXDP3                */ "texdp3",
+    /* WINED3DSIH_TEXDP3TEX             */ "texdp3tex",
+    /* WINED3DSIH_TEXKILL               */ "texkill",
+    /* WINED3DSIH_TEXLDD                */ "texldd",
+    /* WINED3DSIH_TEXLDL                */ "texldl",
+    /* WINED3DSIH_TEXM3x2DEPTH          */ "texm3x2depth",
+    /* WINED3DSIH_TEXM3x2PAD            */ "texm3x2pad",
+    /* WINED3DSIH_TEXM3x2TEX            */ "texm3x2tex",
+    /* WINED3DSIH_TEXM3x3               */ "texm3x3",
+    /* WINED3DSIH_TEXM3x3DIFF           */ "texm3x3diff",
+    /* WINED3DSIH_TEXM3x3PAD            */ "texm3x3pad",
+    /* WINED3DSIH_TEXM3x3SPEC           */ "texm3x3spec",
+    /* WINED3DSIH_TEXM3x3TEX            */ "texm3x3tex",
+    /* WINED3DSIH_TEXM3x3VSPEC          */ "texm3x3vspec",
+    /* WINED3DSIH_TEXREG2AR             */ "texreg2ar",
+    /* WINED3DSIH_TEXREG2GB             */ "texreg2gb",
+    /* WINED3DSIH_TEXREG2RGB            */ "texreg2rgb",
+    /* WINED3DSIH_UDIV                  */ "udiv",
+    /* WINED3DSIH_USHR                  */ "ushr",
+    /* WINED3DSIH_UTOF                  */ "utof",
+    /* WINED3DSIH_XOR                   */ "xor",
+};
+
+static const char * const semantic_names[] =
+{
+    /* WINED3D_DECL_USAGE_POSITION      */ "SV_POSITION",
+    /* WINED3D_DECL_USAGE_BLEND_WEIGHT  */ "BLENDWEIGHT",
+    /* WINED3D_DECL_USAGE_BLEND_INDICES */ "BLENDINDICES",
+    /* WINED3D_DECL_USAGE_NORMAL        */ "NORMAL",
+    /* WINED3D_DECL_USAGE_PSIZE         */ "PSIZE",
+    /* WINED3D_DECL_USAGE_TEXCOORD      */ "TEXCOORD",
+    /* WINED3D_DECL_USAGE_TANGENT       */ "TANGENT",
+    /* WINED3D_DECL_USAGE_BINORMAL      */ "BINORMAL",
+    /* WINED3D_DECL_USAGE_TESS_FACTOR   */ "TESSFACTOR",
+    /* WINED3D_DECL_USAGE_POSITIONT     */ "POSITIONT",
+    /* WINED3D_DECL_USAGE_COLOR         */ "COLOR",
+    /* WINED3D_DECL_USAGE_FOG           */ "FOG",
+    /* WINED3D_DECL_USAGE_DEPTH         */ "DEPTH",
+    /* WINED3D_DECL_USAGE_SAMPLE        */ "SAMPLE",
+};
+
+static const char *shader_semantic_name_from_usage(enum wined3d_decl_usage usage)
+{
+    if (usage >= sizeof(semantic_names) / sizeof(*semantic_names))
+    {
+        FIXME("Unrecognized usage %#x.\n", usage);
+        return "UNRECOGNIZED";
+    }
+
+    return semantic_names[usage];
+}
+
+static enum wined3d_decl_usage shader_usage_from_semantic_name(const char *name)
+{
+    unsigned int i;
+
+    for (i = 0; i < sizeof(semantic_names) / sizeof(*semantic_names); ++i)
+    {
+        if (!strcmp(name, semantic_names[i])) return i;
+    }
+
+    return ~0U;
+}
+
+BOOL shader_match_semantic(const char *semantic_name, enum wined3d_decl_usage usage)
+{
+    return !strcmp(semantic_name, shader_semantic_name_from_usage(usage));
+}
+
+static void shader_signature_from_semantic(struct wined3d_shader_signature_element *e,
+        const struct wined3d_shader_semantic *s)
+{
+    e->semantic_name = shader_semantic_name_from_usage(s->usage);
+    e->semantic_idx = s->usage_idx;
+    e->sysval_semantic = 0;
+    e->component_type = 0;
+    e->register_idx = s->reg.reg.idx[0].offset;
+    e->mask = s->reg.write_mask;
+}
+
+static void shader_signature_from_usage(struct wined3d_shader_signature_element *e,
+        enum wined3d_decl_usage usage, UINT usage_idx, UINT reg_idx, DWORD write_mask)
+{
+    e->semantic_name = shader_semantic_name_from_usage(usage);
+    e->semantic_idx = usage_idx;
+    e->sysval_semantic = 0;
+    e->component_type = 0;
+    e->register_idx = reg_idx;
+    e->mask = write_mask;
+}
+
+static const struct wined3d_shader_frontend *shader_select_frontend(DWORD version_token)
+{
+    switch (version_token >> 16)
+    {
+        case WINED3D_SM1_VS:
+        case WINED3D_SM1_PS:
+            return &sm1_shader_frontend;
+
+        case WINED3D_SM4_PS:
+        case WINED3D_SM4_VS:
+        case WINED3D_SM4_GS:
+            return &sm4_shader_frontend;
+
+        default:
+            FIXME("Unrecognised version token %#x\n", version_token);
+            return NULL;
+    }
+}
+
+void shader_buffer_clear(struct wined3d_shader_buffer *buffer)
+{
+    buffer->buffer[0] = '\0';
+    buffer->content_size = 0;
+    buffer->lineNo = 0;
+    buffer->newline = TRUE;
+}
+
+BOOL shader_buffer_init(struct wined3d_shader_buffer *buffer)
+{
+    buffer->buffer = HeapAlloc(GetProcessHeap(), 0, SHADER_PGMSIZE);
+    if (!buffer->buffer)
+    {
+        ERR("Failed to allocate shader buffer memory.\n");
+        return FALSE;
+    }
+    buffer->buffer_size = SHADER_PGMSIZE;
+
+    shader_buffer_clear(buffer);
+    return TRUE;
+}
+
+void shader_buffer_free(struct wined3d_shader_buffer *buffer)
+{
+    HeapFree(GetProcessHeap(), 0, buffer->buffer);
+}
+
+int shader_vaddline(struct wined3d_shader_buffer *buffer, const char *format, va_list args)
+{
+    char *base = buffer->buffer + buffer->content_size;
+    int rc;
+    char *new_buffer;
+
+    while(1)
+    {
+        rc = vsnprintf(base, buffer->buffer_size - buffer->content_size, format, args);
+        if (rc < 0 /* C89 */ || (unsigned int)rc >= buffer->buffer_size - buffer->content_size /* C99 */)
+        {
+            new_buffer = HeapReAlloc(GetProcessHeap(), 0, buffer->buffer, buffer->buffer_size * 2);
+            if (!new_buffer)
+    {
+                ERR("The buffer allocated for the shader program string is too small at %d bytes.\n", buffer->buffer_size);
+                buffer->content_size = buffer->buffer_size - 1;
+        return -1;
+    }
+            buffer->buffer = new_buffer;
+            buffer->buffer_size = buffer->buffer_size * 2;
+            base = buffer->buffer + buffer->content_size;
+        }
+        else
+        {
+            break;
+        }
+    }
+
+    if (buffer->newline)
+    {
+        TRACE("GL HW (%u, %u) : %s", buffer->lineNo + 1, buffer->content_size, base);
+        buffer->newline = FALSE;
+    }
+    else
+    {
+        TRACE("%s", base);
+    }
+
+    buffer->content_size += rc;
+    if (buffer->buffer[buffer->content_size-1] == '\n')
+    {
+        ++buffer->lineNo;
+        buffer->newline = TRUE;
+    }
+
+    return 0;
+}
+
+int shader_addline(struct wined3d_shader_buffer *buffer, const char *format, ...)
+{
+    va_list args;
+    int ret;
+
+    va_start(args, format);
+    ret = shader_vaddline(buffer, format, args);
+    va_end(args);
+
+    return ret;
+}
+
+static void shader_init(struct wined3d_shader *shader, struct wined3d_device *device,
+        void *parent, const struct wined3d_parent_ops *parent_ops)
+{
+    shader->ref = 1;
+    shader->device = device;
+    shader->parent = parent;
+    shader->parent_ops = parent_ops;
+    list_init(&shader->linked_programs);
+    list_add_head(&device->shaders, &shader->shader_list_entry);
+}
+
+/* Convert floating point offset relative to a register file to an absolute
+ * offset for float constants. */
+static unsigned int shader_get_float_offset(enum wined3d_shader_register_type register_type, UINT register_idx)
+{
+    switch (register_type)
+    {
+        case WINED3DSPR_CONST: return register_idx;
+        case WINED3DSPR_CONST2: return 2048 + register_idx;
+        case WINED3DSPR_CONST3: return 4096 + register_idx;
+        case WINED3DSPR_CONST4: return 6144 + register_idx;
+        default:
+            FIXME("Unsupported register type: %u.\n", register_type);
+            return register_idx;
+    }
+}
+
+static void shader_delete_constant_list(struct list *clist)
+{
+    struct wined3d_shader_lconst *constant;
+    struct list *ptr;
+
+    ptr = list_head(clist);
+    while (ptr)
+    {
+        constant = LIST_ENTRY(ptr, struct wined3d_shader_lconst, entry);
+        ptr = list_next(clist, ptr);
+        HeapFree(GetProcessHeap(), 0, constant);
+    }
+    list_init(clist);
+}
+
+static inline void set_bitmap_bit(DWORD *bitmap, DWORD bit)
+{
+    DWORD idx, shift;
+    idx = bit >> 5;
+    shift = bit & 0x1f;
+    bitmap[idx] |= (1 << shift);
+}
+
+static void shader_record_register_usage(struct wined3d_shader *shader, struct wined3d_shader_reg_maps *reg_maps,
+        const struct wined3d_shader_register *reg, enum wined3d_shader_type shader_type)
+{
+    switch (reg->type)
+    {
+        case WINED3DSPR_TEXTURE: /* WINED3DSPR_ADDR */
+            if (shader_type == WINED3D_SHADER_TYPE_PIXEL)
+                reg_maps->texcoord |= 1 << reg->idx[0].offset;
+            else
+                reg_maps->address |= 1 << reg->idx[0].offset;
+            break;
+
+        case WINED3DSPR_TEMP:
+            reg_maps->temporary |= 1 << reg->idx[0].offset;
+            break;
+
+        case WINED3DSPR_INPUT:
+            if (shader_type == WINED3D_SHADER_TYPE_PIXEL)
+            {
+                if (reg->idx[0].rel_addr)
+                {
+                    /* If relative addressing is used, we must assume that all registers
+                     * are used. Even if it is a construct like v3[aL], we can't assume
+                     * that v0, v1 and v2 aren't read because aL can be negative */
+                    unsigned int i;
+                    for (i = 0; i < MAX_REG_INPUT; ++i)
+                    {
+                        shader->u.ps.input_reg_used[i] = TRUE;
+                    }
+                }
+                else
+                {
+                    shader->u.ps.input_reg_used[reg->idx[0].offset] = TRUE;
+                }
+            }
+            else
+                reg_maps->input_registers |= 1 << reg->idx[0].offset;
+            break;
+
+        case WINED3DSPR_RASTOUT:
+            if (reg->idx[0].offset == 1)
+                reg_maps->fog = 1;
+            break;
+
+        case WINED3DSPR_MISCTYPE:
+            if (shader_type == WINED3D_SHADER_TYPE_PIXEL)
+            {
+                if (!reg->idx[0].offset)
+                    reg_maps->vpos = 1;
+                else if (reg->idx[0].offset == 1)
+                    reg_maps->usesfacing = 1;
+            }
+            break;
+
+        case WINED3DSPR_CONST:
+            if (reg->idx[0].rel_addr)
+            {
+                if (reg->idx[0].offset < reg_maps->min_rel_offset)
+                    reg_maps->min_rel_offset = reg->idx[0].offset;
+                if (reg->idx[0].offset > reg_maps->max_rel_offset)
+                    reg_maps->max_rel_offset = reg->idx[0].offset;
+                reg_maps->usesrelconstF = TRUE;
+            }
+            else
+            {
+                set_bitmap_bit(reg_maps->constf, reg->idx[0].offset);
+            }
+            break;
+
+        case WINED3DSPR_CONSTINT:
+            reg_maps->integer_constants |= (1 << reg->idx[0].offset);
+            break;
+
+        case WINED3DSPR_CONSTBOOL:
+            reg_maps->boolean_constants |= (1 << reg->idx[0].offset);
+            break;
+
+        case WINED3DSPR_COLOROUT:
+            reg_maps->rt_mask |= (1 << reg->idx[0].offset);
+            break;
+
+        default:
+            TRACE("Not recording register of type %#x and [%#x][%#x].\n",
+                    reg->type, reg->idx[0].offset, reg->idx[1].offset);
+            break;
+    }
+}
+
+static unsigned int get_instr_extra_regcount(enum WINED3D_SHADER_INSTRUCTION_HANDLER instr, unsigned int param)
+{
+    switch (instr)
+    {
+        case WINED3DSIH_M4x4:
+        case WINED3DSIH_M3x4:
+            return param == 1 ? 3 : 0;
+
+        case WINED3DSIH_M4x3:
+        case WINED3DSIH_M3x3:
+            return param == 1 ? 2 : 0;
+
+        case WINED3DSIH_M3x2:
+            return param == 1 ? 1 : 0;
+
+        default:
+            return 0;
+    }
+}
+
+/* Note that this does not count the loop register as an address register. */
+static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const struct wined3d_shader_frontend *fe,
+        struct wined3d_shader_reg_maps *reg_maps, struct wined3d_shader_signature_element *input_signature,
+        struct wined3d_shader_signature_element *output_signature, const DWORD *byte_code, DWORD constf_size)
+{
+    unsigned int cur_loop_depth = 0, max_loop_depth = 0;
+    void *fe_data = shader->frontend_data;
+    struct wined3d_shader_version shader_version;
+    const DWORD *ptr = byte_code;
+
+    memset(reg_maps, 0, sizeof(*reg_maps));
+    reg_maps->min_rel_offset = ~0U;
+
+    fe->shader_read_header(fe_data, &ptr, &shader_version);
+    reg_maps->shader_version = shader_version;
+
+    reg_maps->constf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+            sizeof(*reg_maps->constf) * ((constf_size + 31) / 32));
+    if (!reg_maps->constf)
+    {
+        ERR("Failed to allocate constant map memory.\n");
+        return E_OUTOFMEMORY;
+    }
+
+    while (!fe->shader_is_end(fe_data, &ptr))
+    {
+        struct wined3d_shader_instruction ins;
+
+        /* Fetch opcode. */
+        fe->shader_read_instruction(fe_data, &ptr, &ins);
+
+        /* Unhandled opcode, and its parameters. */
+        if (ins.handler_idx == WINED3DSIH_TABLE_SIZE)
+        {
+            TRACE("Skipping unrecognized instruction.\n");
+            continue;
+        }
+
+        /* Handle declarations. */
+        if (ins.handler_idx == WINED3DSIH_DCL)
+        {
+            struct wined3d_shader_semantic *semantic = &ins.declaration.semantic;
+
+            switch (semantic->reg.reg.type)
+            {
+                /* Mark input registers used. */
+                case WINED3DSPR_INPUT:
+                    reg_maps->input_registers |= 1 << semantic->reg.reg.idx[0].offset;
+                    shader_signature_from_semantic(&input_signature[semantic->reg.reg.idx[0].offset], semantic);
+                    break;
+
+                /* Vertex shader: mark 3.0 output registers used, save token. */
+                case WINED3DSPR_OUTPUT:
+                    reg_maps->output_registers |= 1 << semantic->reg.reg.idx[0].offset;
+                    shader_signature_from_semantic(&output_signature[semantic->reg.reg.idx[0].offset], semantic);
+                    if (semantic->usage == WINED3D_DECL_USAGE_FOG)
+                        reg_maps->fog = 1;
+                    break;
+
+                /* Save sampler usage token. */
+                case WINED3DSPR_SAMPLER:
+                    reg_maps->sampler_type[semantic->reg.reg.idx[0].offset] = semantic->sampler_type;
+                    break;
+
+                default:
+                    TRACE("Not recording DCL register type %#x.\n", semantic->reg.reg.type);
+                    break;
+            }
+        }
+        else if (ins.handler_idx == WINED3DSIH_DCL_CONSTANT_BUFFER)
+        {
+            struct wined3d_shader_register *reg = &ins.declaration.src.reg;
+            if (reg->idx[0].offset >= WINED3D_MAX_CBS)
+                ERR("Invalid CB index %u.\n", reg->idx[0].offset);
+            else
+                reg_maps->cb_sizes[reg->idx[0].offset] = reg->idx[1].offset;
+        }
+        else if (ins.handler_idx == WINED3DSIH_DCL_INPUT_PRIMITIVE)
+        {
+            if (shader_version.type == WINED3D_SHADER_TYPE_GEOMETRY)
+                shader->u.gs.input_type = ins.declaration.primitive_type;
+            else
+                FIXME("Invalid instruction %#x for shader type %#x.\n",
+                        ins.handler_idx, shader_version.type);
+        }
+        else if (ins.handler_idx == WINED3DSIH_DCL_OUTPUT_TOPOLOGY)
+        {
+            if (shader_version.type == WINED3D_SHADER_TYPE_GEOMETRY)
+                shader->u.gs.output_type = ins.declaration.primitive_type;
+            else
+                FIXME("Invalid instruction %#x for shader type %#x.\n",
+                        ins.handler_idx, shader_version.type);
+        }
+        else if (ins.handler_idx == WINED3DSIH_DCL_VERTICES_OUT)
+        {
+            if (shader_version.type == WINED3D_SHADER_TYPE_GEOMETRY)
+                shader->u.gs.vertices_out = ins.declaration.count;
+            else
+                FIXME("Invalid instruction %#x for shader type %#x.\n",
+                        ins.handler_idx, shader_version.type);
+        }
+        else if (ins.handler_idx == WINED3DSIH_DEF)
+        {
+            struct wined3d_shader_lconst *lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(*lconst));
+            float *value;
+            if (!lconst) return E_OUTOFMEMORY;
+
+            lconst->idx = ins.dst[0].reg.idx[0].offset;
+            memcpy(lconst->value, ins.src[0].reg.immconst_data, 4 * sizeof(DWORD));
+            value = (float *)lconst->value;
+
+            /* In pixel shader 1.X shaders, the constants are clamped between [-1;1] */
+            if (shader_version.major == 1 && shader_version.type == WINED3D_SHADER_TYPE_PIXEL)
+            {
+                if (value[0] < -1.0f) value[0] = -1.0f;
+                else if (value[0] > 1.0f) value[0] = 1.0f;
+                if (value[1] < -1.0f) value[1] = -1.0f;
+                else if (value[1] > 1.0f) value[1] = 1.0f;
+                if (value[2] < -1.0f) value[2] = -1.0f;
+                else if (value[2] > 1.0f) value[2] = 1.0f;
+                if (value[3] < -1.0f) value[3] = -1.0f;
+                else if (value[3] > 1.0f) value[3] = 1.0f;
+            }
+
+            list_add_head(&shader->constantsF, &lconst->entry);
+
+            if (isinf(value[0]) || isnan(value[0]) || isinf(value[1]) || isnan(value[1])
+                    || isinf(value[2]) || isnan(value[2]) || isinf(value[3]) || isnan(value[3]))
+            {
+                shader->lconst_inf_or_nan = TRUE;
+            }
+        }
+        else if (ins.handler_idx == WINED3DSIH_DEFI)
+        {
+            struct wined3d_shader_lconst *lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(*lconst));
+            if (!lconst) return E_OUTOFMEMORY;
+
+            lconst->idx = ins.dst[0].reg.idx[0].offset;
+            memcpy(lconst->value, ins.src[0].reg.immconst_data, 4 * sizeof(DWORD));
+
+            list_add_head(&shader->constantsI, &lconst->entry);
+            reg_maps->local_int_consts |= (1 << lconst->idx);
+        }
+        else if (ins.handler_idx == WINED3DSIH_DEFB)
+        {
+            struct wined3d_shader_lconst *lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(*lconst));
+            if (!lconst) return E_OUTOFMEMORY;
+
+            lconst->idx = ins.dst[0].reg.idx[0].offset;
+            memcpy(lconst->value, ins.src[0].reg.immconst_data, sizeof(DWORD));
+
+            list_add_head(&shader->constantsB, &lconst->entry);
+            reg_maps->local_bool_consts |= (1 << lconst->idx);
+        }
+        /* For subroutine prototypes. */
+        else if (ins.handler_idx == WINED3DSIH_LABEL)
+        {
+            reg_maps->labels |= 1 << ins.src[0].reg.idx[0].offset;
+        }
+        /* Set texture, address, temporary registers. */
+        else
+        {
+            BOOL color0_mov = FALSE;
+            unsigned int i;
+
+            /* This will loop over all the registers and try to
+             * make a bitmask of the ones we're interested in.
+             *
+             * Relative addressing tokens are ignored, but that's
+             * okay, since we'll catch any address registers when
+             * they are initialized (required by spec). */
+            for (i = 0; i < ins.dst_count; ++i)
+            {
+                shader_record_register_usage(shader, reg_maps, &ins.dst[i].reg, shader_version.type);
+
+                /* WINED3DSPR_TEXCRDOUT is the same as WINED3DSPR_OUTPUT. _OUTPUT can be > MAX_REG_TEXCRD and
+                 * is used in >= 3.0 shaders. Filter 3.0 shaders to prevent overflows, and also filter pixel
+                 * shaders because TECRDOUT isn't used in them, but future register types might cause issues */
+                if (shader_version.type == WINED3D_SHADER_TYPE_VERTEX && shader_version.major < 3)
+                {
+                    UINT idx = ins.dst[i].reg.idx[0].offset;
+
+                    switch (ins.dst[i].reg.type)
+                    {
+                        case WINED3DSPR_RASTOUT:
+                            switch (idx)
+                            {
+                                case 0: /* oPos */
+                                    reg_maps->output_registers |= 1 << 10;
+                                    shader_signature_from_usage(&output_signature[10],
+                                            WINED3D_DECL_USAGE_POSITION, 0, 10, WINED3DSP_WRITEMASK_ALL);
+                                    break;
+
+                                case 1: /* oFog */
+                                    reg_maps->output_registers |= 1 << 11;
+                                    shader_signature_from_usage(&output_signature[11],
+                                            WINED3D_DECL_USAGE_FOG, 0, 11, WINED3DSP_WRITEMASK_0);
+                                    break;
+
+                                case 2: /* oPts */
+                                    reg_maps->output_registers |= 1 << 11;
+                                    shader_signature_from_usage(&output_signature[11],
+                                            WINED3D_DECL_USAGE_PSIZE, 0, 11, WINED3DSP_WRITEMASK_1);
+                                    break;
+                            }
+                            break;
+
+                        case WINED3DSPR_ATTROUT:
+                            if (idx < 2)
+                            {
+                                idx += 8;
+                                if (reg_maps->output_registers & (1 << idx))
+                                {
+                                    output_signature[idx].mask |= ins.dst[i].write_mask;
+                                }
+                                else
+                                {
+                                    reg_maps->output_registers |= 1 << idx;
+                                    shader_signature_from_usage(&output_signature[idx],
+                                            WINED3D_DECL_USAGE_COLOR, idx - 8, idx, ins.dst[i].write_mask);
+                                }
+                            }
+                            break;
+
+                        case WINED3DSPR_TEXCRDOUT:
+
+                            reg_maps->texcoord_mask[idx] |= ins.dst[i].write_mask;
+                            if (reg_maps->output_registers & (1 << idx))
+                            {
+                                output_signature[idx].mask |= ins.dst[i].write_mask;
+                            }
+                            else
+                            {
+                                reg_maps->output_registers |= 1 << idx;
+                                shader_signature_from_usage(&output_signature[idx],
+                                        WINED3D_DECL_USAGE_TEXCOORD, idx, idx, ins.dst[i].write_mask);
+                            }
+                            break;
+
+                        default:
+                            break;
+                    }
+                }
+
+                if (shader_version.type == WINED3D_SHADER_TYPE_PIXEL)
+                {
+                    if (ins.dst[i].reg.type == WINED3DSPR_COLOROUT && !ins.dst[i].reg.idx[0].offset)
+                    {
+                        /* Many 2.0 and 3.0 pixel shaders end with a MOV from a temp register to
+                         * COLOROUT 0. If we know this in advance, the ARB shader backend can skip
+                         * the mov and perform the sRGB write correction from the source register.
+                         *
+                         * However, if the mov is only partial, we can't do this, and if the write
+                         * comes from an instruction other than MOV it is hard to do as well. If
+                         * COLOROUT 0 is overwritten partially later, the marker is dropped again. */
+                        shader->u.ps.color0_mov = FALSE;
+                        if (ins.handler_idx == WINED3DSIH_MOV
+                                && ins.dst[i].write_mask == WINED3DSP_WRITEMASK_ALL)
+                        {
+                            /* Used later when the source register is read. */
+                            color0_mov = TRUE;
+                        }
+                    }
+                    /* Also drop the MOV marker if the source register is overwritten prior to the shader
+                     * end
+                     */
+                    else if (ins.dst[i].reg.type == WINED3DSPR_TEMP
+                            && ins.dst[i].reg.idx[0].offset == shader->u.ps.color0_reg)
+                    {
+                        shader->u.ps.color0_mov = FALSE;
+                    }
+                }
+
+                /* Declare 1.x samplers implicitly, based on the destination reg. number. */
+                if (shader_version.major == 1
+                        && (ins.handler_idx == WINED3DSIH_TEX
+                            || ins.handler_idx == WINED3DSIH_TEXBEM
+                            || ins.handler_idx == WINED3DSIH_TEXBEML
+                            || ins.handler_idx == WINED3DSIH_TEXDP3TEX
+                            || ins.handler_idx == WINED3DSIH_TEXM3x2TEX
+                            || ins.handler_idx == WINED3DSIH_TEXM3x3SPEC
+                            || ins.handler_idx == WINED3DSIH_TEXM3x3TEX
+                            || ins.handler_idx == WINED3DSIH_TEXM3x3VSPEC
+                            || ins.handler_idx == WINED3DSIH_TEXREG2AR
+                            || ins.handler_idx == WINED3DSIH_TEXREG2GB
+                            || ins.handler_idx == WINED3DSIH_TEXREG2RGB))
+                {
+                    /* Fake sampler usage, only set reserved bit and type. */
+                    DWORD sampler_code = ins.dst[i].reg.idx[0].offset;
+
+                    TRACE("Setting fake 2D sampler for 1.x pixelshader.\n");
+                    reg_maps->sampler_type[sampler_code] = WINED3DSTT_2D;
+
+                    /* texbem is only valid with < 1.4 pixel shaders */
+                    if (ins.handler_idx == WINED3DSIH_TEXBEM
+                            || ins.handler_idx == WINED3DSIH_TEXBEML)
+                    {
+                        reg_maps->bumpmat |= 1 << ins.dst[i].reg.idx[0].offset;
+                        if (ins.handler_idx == WINED3DSIH_TEXBEML)
+                        {
+                            reg_maps->luminanceparams |= 1 << ins.dst[i].reg.idx[0].offset;
+                        }
+                    }
+                }
+                else if (ins.handler_idx == WINED3DSIH_BEM)
+                {
+                    reg_maps->bumpmat |= 1 << ins.dst[i].reg.idx[0].offset;
+                }
+            }
+
+            if (ins.handler_idx == WINED3DSIH_NRM) reg_maps->usesnrm = 1;
+            else if (ins.handler_idx == WINED3DSIH_DSY) reg_maps->usesdsy = 1;
+            else if (ins.handler_idx == WINED3DSIH_DSX) reg_maps->usesdsx = 1;
+            else if (ins.handler_idx == WINED3DSIH_TEXLDD) reg_maps->usestexldd = 1;
+            else if (ins.handler_idx == WINED3DSIH_TEXLDL) reg_maps->usestexldl = 1;
+            else if (ins.handler_idx == WINED3DSIH_MOVA) reg_maps->usesmova = 1;
+            else if (ins.handler_idx == WINED3DSIH_IFC) reg_maps->usesifc = 1;
+            else if (ins.handler_idx == WINED3DSIH_CALL) reg_maps->usescall = 1;
+            else if (ins.handler_idx == WINED3DSIH_POW) reg_maps->usespow = 1;
+            else if (ins.handler_idx == WINED3DSIH_LOOP
+                    || ins.handler_idx == WINED3DSIH_REP)
+            {
+                ++cur_loop_depth;
+                if (cur_loop_depth > max_loop_depth)
+                    max_loop_depth = cur_loop_depth;
+            }
+            else if (ins.handler_idx == WINED3DSIH_ENDLOOP
+                    || ins.handler_idx == WINED3DSIH_ENDREP)
+                --cur_loop_depth;
+
+            if (ins.predicate)
+                shader_record_register_usage(shader, reg_maps, &ins.predicate->reg, shader_version.type);
+
+            for (i = 0; i < ins.src_count; ++i)
+            {
+                unsigned int count = get_instr_extra_regcount(ins.handler_idx, i);
+                struct wined3d_shader_register reg = ins.src[i].reg;
+
+                shader_record_register_usage(shader, reg_maps, &ins.src[i].reg, shader_version.type);
+                while (count)
+                {
+                    ++reg.idx[0].offset;
+                    shader_record_register_usage(shader, reg_maps, &reg, shader_version.type);
+                    --count;
+                }
+
+                if (color0_mov)
+                {
+                    if (ins.src[i].reg.type == WINED3DSPR_TEMP
+                            && ins.src[i].swizzle == WINED3DSP_NOSWIZZLE)
+                    {
+                        shader->u.ps.color0_mov = TRUE;
+                        shader->u.ps.color0_reg = ins.src[i].reg.idx[0].offset;
+                    }
+                }
+            }
+        }
+    }
+    reg_maps->loop_depth = max_loop_depth;
+
+    /* PS before 2.0 don't have explicit color outputs. Instead the value of
+     * R0 is written to the render target. */
+    if (shader_version.major < 2 && shader_version.type == WINED3D_SHADER_TYPE_PIXEL)
+        reg_maps->rt_mask |= (1 << 0);
+
+    shader->functionLength = ((const char *)ptr - (const char *)byte_code);
+
+    return WINED3D_OK;
+}
+
+unsigned int shader_find_free_input_register(const struct wined3d_shader_reg_maps *reg_maps, unsigned int max)
+{
+    DWORD map = 1 << max;
+    map |= map - 1;
+    map &= reg_maps->shader_version.major < 3 ? ~reg_maps->texcoord : ~reg_maps->input_registers;
+
+    return wined3d_log2i(map);
+}
+
+static void shader_dump_decl_usage(const struct wined3d_shader_semantic *semantic,
+        const struct wined3d_shader_version *shader_version)
+{
+    TRACE("dcl");
+
+    if (semantic->reg.reg.type == WINED3DSPR_SAMPLER)
+    {
+        switch (semantic->sampler_type)
+        {
+            case WINED3DSTT_2D: TRACE("_2d"); break;
+            case WINED3DSTT_CUBE: TRACE("_cube"); break;
+            case WINED3DSTT_VOLUME: TRACE("_volume"); break;
+            default: TRACE("_unknown_ttype(0x%08x)", semantic->sampler_type);
+        }
+    }
+    else
+    {
+        /* Pixel shaders 3.0 don't have usage semantics. */
+        if (shader_version->major < 3 && shader_version->type == WINED3D_SHADER_TYPE_PIXEL) return;
+        else TRACE("_");
+
+        switch (semantic->usage)
+        {
+            case WINED3D_DECL_USAGE_POSITION:
+                TRACE("position%u", semantic->usage_idx);
+                break;
+
+            case WINED3D_DECL_USAGE_BLEND_INDICES:
+                TRACE("blend");
+                break;
+
+            case WINED3D_DECL_USAGE_BLEND_WEIGHT:
+                TRACE("weight");
+                break;
+
+            case WINED3D_DECL_USAGE_NORMAL:
+                TRACE("normal%u", semantic->usage_idx);
+                break;
+
+            case WINED3D_DECL_USAGE_PSIZE:
+                TRACE("psize");
+                break;
+
+            case WINED3D_DECL_USAGE_COLOR:
+                if (!semantic->usage_idx) TRACE("color");
+                else TRACE("specular%u", (semantic->usage_idx - 1));
+                break;
+
+            case WINED3D_DECL_USAGE_TEXCOORD:
+                TRACE("texture%u", semantic->usage_idx);
+                break;
+
+            case WINED3D_DECL_USAGE_TANGENT:
+                TRACE("tangent");
+                break;
+
+            case WINED3D_DECL_USAGE_BINORMAL:
+                TRACE("binormal");
+                break;
+
+            case WINED3D_DECL_USAGE_TESS_FACTOR:
+                TRACE("tessfactor");
+                break;
+
+            case WINED3D_DECL_USAGE_POSITIONT:
+                TRACE("positionT%u", semantic->usage_idx);
+                break;
+
+            case WINED3D_DECL_USAGE_FOG:
+                TRACE("fog");
+                break;
+
+            case WINED3D_DECL_USAGE_DEPTH:
+                TRACE("depth");
+                break;
+
+            case WINED3D_DECL_USAGE_SAMPLE:
+                TRACE("sample");
+                break;
+
+            default:
+                FIXME("unknown_semantics(0x%08x)", semantic->usage);
+        }
+    }
+}
+
+static void shader_dump_register(const struct wined3d_shader_register *reg,
+        const struct wined3d_shader_version *shader_version)
+{
+    static const char * const rastout_reg_names[] = {"oPos", "oFog", "oPts"};
+    static const char * const misctype_reg_names[] = {"vPos", "vFace"};
+    UINT offset = reg->idx[0].offset;
+
+    switch (reg->type)
+    {
+        case WINED3DSPR_TEMP:
+            TRACE("r");
+            break;
+
+        case WINED3DSPR_INPUT:
+            TRACE("v");
+            break;
+
+        case WINED3DSPR_CONST:
+        case WINED3DSPR_CONST2:
+        case WINED3DSPR_CONST3:
+        case WINED3DSPR_CONST4:
+            TRACE("c");
+            offset = shader_get_float_offset(reg->type, offset);
+            break;
+
+        case WINED3DSPR_TEXTURE: /* vs: case WINED3DSPR_ADDR */
+            TRACE("%c", shader_version->type == WINED3D_SHADER_TYPE_PIXEL ? 't' : 'a');
+            break;
+
+        case WINED3DSPR_RASTOUT:
+            TRACE("%s", rastout_reg_names[offset]);
+            break;
+
+        case WINED3DSPR_COLOROUT:
+            TRACE("oC");
+            break;
+
+        case WINED3DSPR_DEPTHOUT:
+            TRACE("oDepth");
+            break;
+
+        case WINED3DSPR_ATTROUT:
+            TRACE("oD");
+            break;
+
+        case WINED3DSPR_TEXCRDOUT:
+            /* Vertex shaders >= 3.0 use general purpose output registers
+             * (WINED3DSPR_OUTPUT), which can include an address token. */
+            if (shader_version->major >= 3) TRACE("o");
+            else TRACE("oT");
+            break;
+
+        case WINED3DSPR_CONSTINT:
+            TRACE("i");
+            break;
+
+        case WINED3DSPR_CONSTBOOL:
+            TRACE("b");
+            break;
+
+        case WINED3DSPR_LABEL:
+            TRACE("l");
+            break;
+
+        case WINED3DSPR_LOOP:
+            TRACE("aL");
+            break;
+
+        case WINED3DSPR_SAMPLER:
+            TRACE("s");
+            break;
+
+        case WINED3DSPR_MISCTYPE:
+            if (offset > 1)
+                FIXME("Unhandled misctype register %u.\n", offset);
+            else
+                TRACE("%s", misctype_reg_names[offset]);
+            break;
+
+        case WINED3DSPR_PREDICATE:
+            TRACE("p");
+            break;
+
+        case WINED3DSPR_IMMCONST:
+            TRACE("l");
+            break;
+
+        case WINED3DSPR_CONSTBUFFER:
+            TRACE("cb");
+            break;
+
+        case WINED3DSPR_PRIMID:
+            TRACE("primID");
+            break;
+
+        case WINED3DSPR_NULL:
+            TRACE("null");
+            break;
+
+        case WINED3DSPR_RESOURCE:
+            TRACE("t");
+            break;
+
+        default:
+            TRACE("unhandled_rtype(%#x)", reg->type);
+            break;
+    }
+
+    if (reg->type == WINED3DSPR_IMMCONST)
+    {
+        TRACE("(");
+        switch (reg->immconst_type)
+        {
+            case WINED3D_IMMCONST_SCALAR:
+                switch (reg->data_type)
+                {
+                    case WINED3D_DATA_FLOAT:
+                        TRACE("%.8e", *(const float *)reg->immconst_data);
+                        break;
+                    case WINED3D_DATA_INT:
+                        TRACE("%d", reg->immconst_data[0]);
+                        break;
+                    case WINED3D_DATA_RESOURCE:
+                    case WINED3D_DATA_SAMPLER:
+                    case WINED3D_DATA_UINT:
+                        TRACE("%u", reg->immconst_data[0]);
+                        break;
+                    default:
+                        TRACE("<unhandled data type %#x>", reg->data_type);
+                        break;
+                }
+                break;
+
+            case WINED3D_IMMCONST_VEC4:
+                switch (reg->data_type)
+                {
+                    case WINED3D_DATA_FLOAT:
+                        TRACE("%.8e, %.8e, %.8e, %.8e",
+                                *(const float *)&reg->immconst_data[0], *(const float *)&reg->immconst_data[1],
+                                *(const float *)&reg->immconst_data[2], *(const float *)&reg->immconst_data[3]);
+                        break;
+                    case WINED3D_DATA_INT:
+                        TRACE("%d, %d, %d, %d",
+                                reg->immconst_data[0], reg->immconst_data[1],
+                                reg->immconst_data[2], reg->immconst_data[3]);
+                        break;
+                    case WINED3D_DATA_RESOURCE:
+                    case WINED3D_DATA_SAMPLER:
+                    case WINED3D_DATA_UINT:
+                        TRACE("%u, %u, %u, %u",
+                                reg->immconst_data[0], reg->immconst_data[1],
+                                reg->immconst_data[2], reg->immconst_data[3]);
+                        break;
+                    default:
+                        TRACE("<unhandled data type %#x>", reg->data_type);
+                        break;
+                }
+                break;
+
+            default:
+                TRACE("<unhandled immconst_type %#x>", reg->immconst_type);
+                break;
+        }
+        TRACE(")");
+    }
+    else if (reg->type != WINED3DSPR_RASTOUT
+            && reg->type != WINED3DSPR_MISCTYPE
+            && reg->type != WINED3DSPR_NULL)
+    {
+        if (offset != ~0U)
+        {
+            TRACE("[");
+            if (reg->idx[0].rel_addr)
+            {
+                shader_dump_src_param(reg->idx[0].rel_addr, shader_version);
+                TRACE(" + ");
+        }
+            TRACE("%u]", offset);
+
+            if (reg->idx[1].offset != ~0U)
+            {
+                TRACE("[");
+                if (reg->idx[1].rel_addr)
+                {
+                    shader_dump_src_param(reg->idx[1].rel_addr, shader_version);
+                TRACE(" + ");
+            }
+                TRACE("%u]", reg->idx[1].offset);
+            }
+        }
+    }
+}
+
+void shader_dump_dst_param(const struct wined3d_shader_dst_param *param,
+        const struct wined3d_shader_version *shader_version)
+{
+    DWORD write_mask = param->write_mask;
+
+    shader_dump_register(&param->reg, shader_version);
+
+    if (write_mask && write_mask != WINED3DSP_WRITEMASK_ALL)
+    {
+        static const char *write_mask_chars = "xyzw";
+
+        TRACE(".");
+        if (write_mask & WINED3DSP_WRITEMASK_0) TRACE("%c", write_mask_chars[0]);
+        if (write_mask & WINED3DSP_WRITEMASK_1) TRACE("%c", write_mask_chars[1]);
+        if (write_mask & WINED3DSP_WRITEMASK_2) TRACE("%c", write_mask_chars[2]);
+        if (write_mask & WINED3DSP_WRITEMASK_3) TRACE("%c", write_mask_chars[3]);
+    }
+}
+
+void shader_dump_src_param(const struct wined3d_shader_src_param *param,
+        const struct wined3d_shader_version *shader_version)
+{
+    enum wined3d_shader_src_modifier src_modifier = param->modifiers;
+    DWORD swizzle = param->swizzle;
+
+    if (src_modifier == WINED3DSPSM_NEG
+            || src_modifier == WINED3DSPSM_BIASNEG
+            || src_modifier == WINED3DSPSM_SIGNNEG
+            || src_modifier == WINED3DSPSM_X2NEG
+            || src_modifier == WINED3DSPSM_ABSNEG)
+        TRACE("-");
+    else if (src_modifier == WINED3DSPSM_COMP)
+        TRACE("1-");
+    else if (src_modifier == WINED3DSPSM_NOT)
+        TRACE("!");
+
+    if (src_modifier == WINED3DSPSM_ABS || src_modifier == WINED3DSPSM_ABSNEG)
+        TRACE("abs(");
+
+    shader_dump_register(&param->reg, shader_version);
+
+    if (src_modifier)
+    {
+        switch (src_modifier)
+        {
+            case WINED3DSPSM_NONE:    break;
+            case WINED3DSPSM_NEG:     break;
+            case WINED3DSPSM_NOT:     break;
+            case WINED3DSPSM_BIAS:    TRACE("_bias"); break;
+            case WINED3DSPSM_BIASNEG: TRACE("_bias"); break;
+            case WINED3DSPSM_SIGN:    TRACE("_bx2"); break;
+            case WINED3DSPSM_SIGNNEG: TRACE("_bx2"); break;
+            case WINED3DSPSM_COMP:    break;
+            case WINED3DSPSM_X2:      TRACE("_x2"); break;
+            case WINED3DSPSM_X2NEG:   TRACE("_x2"); break;
+            case WINED3DSPSM_DZ:      TRACE("_dz"); break;
+            case WINED3DSPSM_DW:      TRACE("_dw"); break;
+            case WINED3DSPSM_ABSNEG:  TRACE(")"); break;
+            case WINED3DSPSM_ABS:     TRACE(")"); break;
+            default:                  TRACE("_unknown_modifier(%#x)", src_modifier);
+        }
+    }
+
+    if (swizzle != WINED3DSP_NOSWIZZLE)
+    {
+        static const char *swizzle_chars = "xyzw";
+        DWORD swizzle_x = swizzle & 0x03;
+        DWORD swizzle_y = (swizzle >> 2) & 0x03;
+        DWORD swizzle_z = (swizzle >> 4) & 0x03;
+        DWORD swizzle_w = (swizzle >> 6) & 0x03;
+
+        if (swizzle_x == swizzle_y
+                && swizzle_x == swizzle_z
+                && swizzle_x == swizzle_w)
+        {
+            TRACE(".%c", swizzle_chars[swizzle_x]);
+        }
+        else
+        {
+            TRACE(".%c%c%c%c", swizzle_chars[swizzle_x], swizzle_chars[swizzle_y],
+                    swizzle_chars[swizzle_z], swizzle_chars[swizzle_w]);
+        }
+    }
+}
+
+/* Shared code in order to generate the bulk of the shader string.
+ * NOTE: A description of how to parse tokens can be found on MSDN. */
+void shader_generate_main(const struct wined3d_shader *shader, struct wined3d_shader_buffer *buffer,
+        const struct wined3d_shader_reg_maps *reg_maps, const DWORD *byte_code, void *backend_ctx)
+{
+    struct wined3d_device *device = shader->device;
+    const struct wined3d_shader_frontend *fe = shader->frontend;
+    void *fe_data = shader->frontend_data;
+    struct wined3d_shader_version shader_version;
+    struct wined3d_shader_loop_state loop_state;
+    struct wined3d_shader_instruction ins;
+    struct wined3d_shader_tex_mx tex_mx;
+    struct wined3d_shader_context ctx;
+    const DWORD *ptr = byte_code;
+
+    /* Initialize current parsing state. */
+    tex_mx.current_row = 0;
+    loop_state.current_depth = 0;
+    loop_state.current_reg = 0;
+
+    ctx.shader = shader;
+    ctx.gl_info = &device->adapter->gl_info;
+    ctx.reg_maps = reg_maps;
+    ctx.buffer = buffer;
+    ctx.tex_mx = &tex_mx;
+    ctx.loop_state = &loop_state;
+    ctx.backend_data = backend_ctx;
+    ins.ctx = &ctx;
+
+    fe->shader_read_header(fe_data, &ptr, &shader_version);
+
+    while (!fe->shader_is_end(fe_data, &ptr))
+    {
+        /* Read opcode. */
+        fe->shader_read_instruction(fe_data, &ptr, &ins);
+
+        /* Unknown opcode and its parameters. */
+        if (ins.handler_idx == WINED3DSIH_TABLE_SIZE)
+        {
+            TRACE("Skipping unrecognized instruction.\n");
+            continue;
+        }
+
+        if (ins.predicate)
+            FIXME("Predicates not implemented.\n");
+
+        /* Call appropriate function for output target */
+        device->shader_backend->shader_handle_instruction(&ins);
+    }
+}
+
+static void shader_dump_ins_modifiers(const struct wined3d_shader_dst_param *dst)
+{
+    DWORD mmask = dst->modifiers;
+
+    switch (dst->shift)
+    {
+        case 0: break;
+        case 13: TRACE("_d8"); break;
+        case 14: TRACE("_d4"); break;
+        case 15: TRACE("_d2"); break;
+        case 1: TRACE("_x2"); break;
+        case 2: TRACE("_x4"); break;
+        case 3: TRACE("_x8"); break;
+        default: TRACE("_unhandled_shift(%d)", dst->shift); break;
+    }
+
+    if (mmask & WINED3DSPDM_SATURATE)         TRACE("_sat");
+    if (mmask & WINED3DSPDM_PARTIALPRECISION) TRACE("_pp");
+    if (mmask & WINED3DSPDM_MSAMPCENTROID)    TRACE("_centroid");
+
+    mmask &= ~(WINED3DSPDM_SATURATE | WINED3DSPDM_PARTIALPRECISION | WINED3DSPDM_MSAMPCENTROID);
+    if (mmask) FIXME("_unrecognized_modifier(%#x)", mmask);
+}
+
+static void shader_dump_primitive_type(enum wined3d_primitive_type primitive_type)
+{
+    switch (primitive_type)
+    {
+        case WINED3D_PT_UNDEFINED:
+            TRACE("undefined");
+            break;
+        case WINED3D_PT_POINTLIST:
+            TRACE("pointlist");
+            break;
+        case WINED3D_PT_LINELIST:
+            TRACE("linelist");
+            break;
+        case WINED3D_PT_LINESTRIP:
+            TRACE("linestrip");
+            break;
+        case WINED3D_PT_TRIANGLELIST:
+            TRACE("trianglelist");
+            break;
+        case WINED3D_PT_TRIANGLESTRIP:
+            TRACE("trianglestrip");
+            break;
+        case WINED3D_PT_TRIANGLEFAN:
+            TRACE("trianglefan");
+            break;
+        case WINED3D_PT_LINELIST_ADJ:
+            TRACE("linelist_adj");
+            break;
+        case WINED3D_PT_LINESTRIP_ADJ:
+            TRACE("linestrip_adj");
+            break;
+        case WINED3D_PT_TRIANGLELIST_ADJ:
+            TRACE("trianglelist_adj");
+            break;
+        case WINED3D_PT_TRIANGLESTRIP_ADJ:
+            TRACE("trianglestrip_adj");
+            break;
+        default:
+            TRACE("<unrecognized_primitive_type %#x>", primitive_type);
+            break;
+    }
+}
+
+static void shader_trace_init(const struct wined3d_shader_frontend *fe, void *fe_data, const DWORD *byte_code)
+{
+    struct wined3d_shader_version shader_version;
+    const DWORD *ptr = byte_code;
+    const char *type_prefix;
+    DWORD i;
+
+    TRACE("Parsing %p.\n", byte_code);
+
+    fe->shader_read_header(fe_data, &ptr, &shader_version);
+
+    switch (shader_version.type)
+    {
+        case WINED3D_SHADER_TYPE_VERTEX:
+            type_prefix = "vs";
+            break;
+
+        case WINED3D_SHADER_TYPE_GEOMETRY:
+            type_prefix = "gs";
+            break;
+
+        case WINED3D_SHADER_TYPE_PIXEL:
+            type_prefix = "ps";
+            break;
+
+        default:
+            FIXME("Unhandled shader type %#x.\n", shader_version.type);
+            type_prefix = "unknown";
+            break;
+    }
+
+    TRACE("%s_%u_%u\n", type_prefix, shader_version.major, shader_version.minor);
+
+    while (!fe->shader_is_end(fe_data, &ptr))
+    {
+        struct wined3d_shader_instruction ins;
+
+        fe->shader_read_instruction(fe_data, &ptr, &ins);
+        if (ins.handler_idx == WINED3DSIH_TABLE_SIZE)
+        {
+            TRACE("Skipping unrecognized instruction.\n");
+            continue;
+        }
+
+        if (ins.handler_idx == WINED3DSIH_DCL)
+        {
+            shader_dump_decl_usage(&ins.declaration.semantic, &shader_version);
+            shader_dump_ins_modifiers(&ins.declaration.semantic.reg);
+            TRACE(" ");
+            shader_dump_dst_param(&ins.declaration.semantic.reg, &shader_version);
+        }
+        else if (ins.handler_idx == WINED3DSIH_DCL_CONSTANT_BUFFER)
+        {
+            TRACE("%s ", shader_opcode_names[ins.handler_idx]);
+            shader_dump_src_param(&ins.declaration.src, &shader_version);
+            TRACE(", %s", ins.flags & WINED3DSI_INDEXED_DYNAMIC ? "dynamicIndexed" : "immediateIndexed");
+        }
+        else if (ins.handler_idx == WINED3DSIH_DCL_INPUT_PRIMITIVE
+                || ins.handler_idx == WINED3DSIH_DCL_OUTPUT_TOPOLOGY)
+        {
+            TRACE("%s ", shader_opcode_names[ins.handler_idx]);
+            shader_dump_primitive_type(ins.declaration.primitive_type);
+        }
+        else if (ins.handler_idx == WINED3DSIH_DCL_VERTICES_OUT)
+        {
+            TRACE("%s %u", shader_opcode_names[ins.handler_idx], ins.declaration.count);
+        }
+        else if (ins.handler_idx == WINED3DSIH_DEF)
+        {
+            TRACE("def c%u = %f, %f, %f, %f", shader_get_float_offset(ins.dst[0].reg.type,
+                    ins.dst[0].reg.idx[0].offset),
+                    *(const float *)&ins.src[0].reg.immconst_data[0],
+                    *(const float *)&ins.src[0].reg.immconst_data[1],
+                    *(const float *)&ins.src[0].reg.immconst_data[2],
+                    *(const float *)&ins.src[0].reg.immconst_data[3]);
+        }
+        else if (ins.handler_idx == WINED3DSIH_DEFI)
+        {
+            TRACE("defi i%u = %d, %d, %d, %d", ins.dst[0].reg.idx[0].offset,
+                    ins.src[0].reg.immconst_data[0],
+                    ins.src[0].reg.immconst_data[1],
+                    ins.src[0].reg.immconst_data[2],
+                    ins.src[0].reg.immconst_data[3]);
+        }
+        else if (ins.handler_idx == WINED3DSIH_DEFB)
+        {
+            TRACE("defb b%u = %s", ins.dst[0].reg.idx[0].offset, ins.src[0].reg.immconst_data[0] ? "true" : "false");
+        }
+        else
+        {
+            if (ins.predicate)
+            {
+                TRACE("(");
+                shader_dump_src_param(ins.predicate, &shader_version);
+                TRACE(") ");
+            }
+
+            /* PixWin marks instructions with the coissue flag with a '+' */
+            if (ins.coissue) TRACE("+");
+
+            TRACE("%s", shader_opcode_names[ins.handler_idx]);
+
+            if (ins.handler_idx == WINED3DSIH_IFC
+                    || ins.handler_idx == WINED3DSIH_BREAKC)
+            {
+                switch (ins.flags)
+                {
+                    case WINED3D_SHADER_REL_OP_GT: TRACE("_gt"); break;
+                    case WINED3D_SHADER_REL_OP_EQ: TRACE("_eq"); break;
+                    case WINED3D_SHADER_REL_OP_GE: TRACE("_ge"); break;
+                    case WINED3D_SHADER_REL_OP_LT: TRACE("_lt"); break;
+                    case WINED3D_SHADER_REL_OP_NE: TRACE("_ne"); break;
+                    case WINED3D_SHADER_REL_OP_LE: TRACE("_le"); break;
+                    default: TRACE("_(%u)", ins.flags);
+                }
+            }
+            else if (ins.handler_idx == WINED3DSIH_TEX
+                    && shader_version.major >= 2
+                    && (ins.flags & WINED3DSI_TEXLD_PROJECT))
+            {
+                TRACE("p");
+            }
+
+            for (i = 0; i < ins.dst_count; ++i)
+            {
+                shader_dump_ins_modifiers(&ins.dst[i]);
+                TRACE(!i ? " " : ", ");
+                shader_dump_dst_param(&ins.dst[i], &shader_version);
+            }
+
+            /* Other source tokens */
+            for (i = ins.dst_count; i < (ins.dst_count + ins.src_count); ++i)
+            {
+                TRACE(!i ? " " : ", ");
+                shader_dump_src_param(&ins.src[i - ins.dst_count], &shader_version);
+            }
+        }
+        TRACE("\n");
+    }
+}
+
+static void shader_cleanup(struct wined3d_shader *shader)
+{
+    shader->device->shader_backend->shader_destroy(shader);
+    HeapFree(GetProcessHeap(), 0, shader->reg_maps.constf);
+    HeapFree(GetProcessHeap(), 0, shader->function);
+    shader_delete_constant_list(&shader->constantsF);
+    shader_delete_constant_list(&shader->constantsB);
+    shader_delete_constant_list(&shader->constantsI);
+    list_remove(&shader->shader_list_entry);
+
+    if (shader->frontend && shader->frontend_data)
+        shader->frontend->shader_free(shader->frontend_data);
+}
+
+struct shader_none_priv
+{
+    const struct wined3d_vertex_pipe_ops *vertex_pipe;
+    const struct fragment_pipeline *fragment_pipe;
+    BOOL ffp_proj_control;
+};
+
+static void shader_none_handle_instruction(const struct wined3d_shader_instruction *ins) {}
+static void shader_none_select_depth_blt(void *shader_priv, const struct wined3d_gl_info *gl_info,
+        enum tex_types tex_type, const SIZE *ds_mask_size) {}
+static void shader_none_deselect_depth_blt(void *shader_priv, const struct wined3d_gl_info *gl_info) {}
+static void shader_none_update_float_vertex_constants(struct wined3d_device *device, UINT start, UINT count) {}
+static void shader_none_update_float_pixel_constants(struct wined3d_device *device, UINT start, UINT count) {}
+static void shader_none_load_constants(void *shader_priv, const struct wined3d_context *context,
+        const struct wined3d_state *state) {}
+static void shader_none_load_np2fixup_constants(void *shader_priv,
+        const struct wined3d_gl_info *gl_info, const struct wined3d_state *state) {}
+static void shader_none_destroy(struct wined3d_shader *shader) {}
+static void shader_none_context_destroyed(void *shader_priv, const struct wined3d_context *context) {}
+
+/* Context activation is done by the caller. */
+static void shader_none_select(void *shader_priv, const struct wined3d_context *context,
+        const struct wined3d_state *state)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    struct shader_none_priv *priv = shader_priv;
+
+    priv->vertex_pipe->vp_enable(gl_info, !use_vs(state));
+    priv->fragment_pipe->enable_extension(gl_info, !use_ps(state));
+}
+
+/* Context activation is done by the caller. */
+static void shader_none_disable(void *shader_priv, const struct wined3d_context *context)
+{
+    struct shader_none_priv *priv = shader_priv;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    priv->vertex_pipe->vp_enable(gl_info, FALSE);
+    priv->fragment_pipe->enable_extension(gl_info, FALSE);
+}
+
+static HRESULT shader_none_alloc(struct wined3d_device *device, const struct wined3d_vertex_pipe_ops *vertex_pipe,
+        const struct fragment_pipeline *fragment_pipe)
+{
+    struct fragment_caps fragment_caps;
+    void *vertex_priv, *fragment_priv;
+    struct shader_none_priv *priv;
+
+    if (!(priv = HeapAlloc(GetProcessHeap(), 0, sizeof(*priv))))
+        return E_OUTOFMEMORY;
+
+    if (!(vertex_priv = vertex_pipe->vp_alloc(&none_shader_backend, priv)))
+    {
+        ERR("Failed to initialize vertex pipe.\n");
+        HeapFree(GetProcessHeap(), 0, priv);
+        return E_FAIL;
+    }
+
+    if (!(fragment_priv = fragment_pipe->alloc_private(&none_shader_backend, priv)))
+    {
+        ERR("Failed to initialize fragment pipe.\n");
+        vertex_pipe->vp_free(device);
+        HeapFree(GetProcessHeap(), 0, priv);
+        return E_FAIL;
+    }
+
+    priv->vertex_pipe = vertex_pipe;
+    priv->fragment_pipe = fragment_pipe;
+    fragment_pipe->get_caps(&device->adapter->gl_info, &fragment_caps);
+    priv->ffp_proj_control = fragment_caps.wined3d_caps & WINED3D_FRAGMENT_CAP_PROJ_CONTROL;
+
+    device->vertex_priv = vertex_priv;
+    device->fragment_priv = fragment_priv;
+    device->shader_priv = priv;
+
+    return WINED3D_OK;
+}
+
+static void shader_none_free(struct wined3d_device *device)
+{
+    struct shader_none_priv *priv = device->shader_priv;
+
+    priv->fragment_pipe->free_private(device);
+    priv->vertex_pipe->vp_free(device);
+    HeapFree(GetProcessHeap(), 0, priv);
+}
+
+static void shader_none_get_caps(const struct wined3d_gl_info *gl_info, struct shader_caps *caps)
+{
+    /* Set the shader caps to 0 for the none shader backend */
+    caps->vs_version = 0;
+    caps->gs_version = 0;
+    caps->ps_version = 0;
+    caps->vs_uniform_count = 0;
+    caps->ps_uniform_count = 0;
+    caps->ps_1x_max_value = 0.0f;
+    caps->wined3d_caps = 0;
+}
+
+static BOOL shader_none_color_fixup_supported(struct color_fixup_desc fixup)
+{
+    /* We "support" every possible fixup, since we don't support any shader
+     * model, and will never have to actually sample a texture. */
+        return TRUE;
+}
+
+static BOOL shader_none_has_ffp_proj_control(void *shader_priv)
+{
+    struct shader_none_priv *priv = shader_priv;
+
+    return priv->ffp_proj_control;
+}
+
+const struct wined3d_shader_backend_ops none_shader_backend =
+{
+    shader_none_handle_instruction,
+    shader_none_select,
+    shader_none_disable,
+    shader_none_select_depth_blt,
+    shader_none_deselect_depth_blt,
+    shader_none_update_float_vertex_constants,
+    shader_none_update_float_pixel_constants,
+    shader_none_load_constants,
+    shader_none_load_np2fixup_constants,
+    shader_none_destroy,
+    shader_none_alloc,
+    shader_none_free,
+    shader_none_context_destroyed,
+    shader_none_get_caps,
+    shader_none_color_fixup_supported,
+    shader_none_has_ffp_proj_control,
+};
+
+static HRESULT shader_set_function(struct wined3d_shader *shader, const DWORD *byte_code,
+        const struct wined3d_shader_signature *output_signature, DWORD float_const_count,
+        enum wined3d_shader_type type, unsigned int max_version)
+{
+    struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
+    const struct wined3d_shader_frontend *fe;
+    HRESULT hr;
+    unsigned int backend_version;
+    const struct wined3d_d3d_info *d3d_info = &shader->device->adapter->d3d_info;
+
+    TRACE("shader %p, byte_code %p, output_signature %p, float_const_count %u.\n",
+            shader, byte_code, output_signature, float_const_count);
+
+    fe = shader_select_frontend(*byte_code);
+    if (!fe)
+    {
+        FIXME("Unable to find frontend for shader.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+    shader->frontend = fe;
+    shader->frontend_data = fe->shader_init(byte_code, output_signature);
+    if (!shader->frontend_data)
+    {
+        FIXME("Failed to initialize frontend.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    /* First pass: trace shader. */
+    if (TRACE_ON(d3d_shader))
+        shader_trace_init(fe, shader->frontend_data, byte_code);
+
+    /* Initialize immediate constant lists. */
+    list_init(&shader->constantsF);
+    list_init(&shader->constantsB);
+    list_init(&shader->constantsI);
+    shader->lconst_inf_or_nan = FALSE;
+
+    /* Second pass: figure out which registers are used, what the semantics are, etc. */
+    hr = shader_get_registers_used(shader, fe,
+            reg_maps, shader->input_signature, shader->output_signature,
+            byte_code, float_const_count);
+    if (FAILED(hr)) return hr;
+
+    if (reg_maps->shader_version.type != type)
+    {
+        WARN("Wrong shader type %d.\n", reg_maps->shader_version.type);
+        return WINED3DERR_INVALIDCALL;
+    }
+    if (reg_maps->shader_version.major > max_version)
+    {
+        WARN("Shader version %d not supported by this D3D API version.\n", reg_maps->shader_version.major);
+        return WINED3DERR_INVALIDCALL;
+    }
+    switch (type)
+    {
+        case WINED3D_SHADER_TYPE_VERTEX:
+            backend_version = d3d_info->limits.vs_version;
+            break;
+        case WINED3D_SHADER_TYPE_GEOMETRY:
+            backend_version = d3d_info->limits.gs_version;
+            break;
+        case WINED3D_SHADER_TYPE_PIXEL:
+            backend_version = d3d_info->limits.ps_version;
+            break;
+        default:
+            FIXME("No backend version-checking for this shader type\n");
+            backend_version = 0;
+    }
+    if (reg_maps->shader_version.major > backend_version)
+    {
+        WARN("Shader version %d.%d not supported by your GPU with the current shader backend.\n",
+                reg_maps->shader_version.major, reg_maps->shader_version.minor);
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    shader->function = HeapAlloc(GetProcessHeap(), 0, shader->functionLength);
+    if (!shader->function)
+        return E_OUTOFMEMORY;
+    memcpy(shader->function, byte_code, shader->functionLength);
+
+    return WINED3D_OK;
+}
+
+ULONG CDECL wined3d_shader_incref(struct wined3d_shader *shader)
+{
+    ULONG refcount = InterlockedIncrement(&shader->ref);
+
+    TRACE("%p increasing refcount to %u.\n", shader, refcount);
+
+    return refcount;
+}
+
+/* Do not call while under the GL lock. */
+ULONG CDECL wined3d_shader_decref(struct wined3d_shader *shader)
+{
+    ULONG refcount = InterlockedDecrement(&shader->ref);
+
+    TRACE("%p decreasing refcount to %u.\n", shader, refcount);
+
+    if (!refcount)
+    {
+#ifdef VBOX_WINE_WITH_SHADER_CACHE
+        shader_chache_put(shader->shaderCache, shader);
+#else
+        shader_cleanup(shader);
+        shader->parent_ops->wined3d_object_destroyed(shader->parent);
+        HeapFree(GetProcessHeap(), 0, shader);
+#endif
+    }
+
+    return refcount;
+}
+
+void * CDECL wined3d_shader_get_parent(const struct wined3d_shader *shader)
+{
+    TRACE("shader %p.\n", shader);
+
+    return shader->parent;
+}
+
+HRESULT CDECL wined3d_shader_get_byte_code(const struct wined3d_shader *shader,
+        void *byte_code, UINT *byte_code_size)
+{
+    TRACE("shader %p, byte_code %p, byte_code_size %p.\n", shader, byte_code, byte_code_size);
+
+    if (!byte_code)
+    {
+        *byte_code_size = shader->functionLength;
+        return WINED3D_OK;
+    }
+
+    if (*byte_code_size < shader->functionLength)
+    {
+        /* MSDN claims (for d3d8 at least) that if *byte_code_size is smaller
+         * than the required size we should write the required size and
+         * return D3DERR_MOREDATA. That's not actually true. */
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    memcpy(byte_code, shader->function, shader->functionLength);
+
+    return WINED3D_OK;
+}
+
+/* Set local constants for d3d8 shaders. */
+HRESULT CDECL wined3d_shader_set_local_constants_float(struct wined3d_shader *shader,
+        UINT start_idx, const float *src_data, UINT count)
+{
+    UINT end_idx = start_idx + count;
+    UINT i;
+
+    TRACE("shader %p, start_idx %u, src_data %p, count %u.\n", shader, start_idx, src_data, count);
+
+    if (end_idx > shader->limits.constant_float)
+    {
+        WARN("end_idx %u > float constants limit %u.\n",
+                end_idx, shader->limits.constant_float);
+        end_idx = shader->limits.constant_float;
+    }
+
+    for (i = start_idx; i < end_idx; ++i)
+    {
+        struct wined3d_shader_lconst *lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(*lconst));
+        float *value;
+        if (!lconst)
+            return E_OUTOFMEMORY;
+
+        lconst->idx = i;
+        value = (float *)lconst->value;
+        memcpy(value, src_data + (i - start_idx) * 4 /* 4 components */, 4 * sizeof(float));
+        list_add_head(&shader->constantsF, &lconst->entry);
+
+        if (isinf(value[0]) || isnan(value[0]) || isinf(value[1]) || isnan(value[1])
+                || isinf(value[2]) || isnan(value[2]) || isinf(value[3]) || isnan(value[3]))
+        {
+            shader->lconst_inf_or_nan = TRUE;
+        }
+    }
+
+    return WINED3D_OK;
+}
+
+void find_vs_compile_args(const struct wined3d_state *state,
+        const struct wined3d_shader *shader, struct vs_compile_args *args)
+{
+    args->fog_src = state->render_states[WINED3D_RS_FOGTABLEMODE]
+            == WINED3D_FOG_NONE ? VS_FOG_COORD : VS_FOG_Z;
+    args->clip_enabled = state->render_states[WINED3D_RS_CLIPPING]
+            && state->render_states[WINED3D_RS_CLIPPLANEENABLE];
+    args->swizzle_map = shader->device->stream_info.swizzle_map;
+}
+
+static BOOL match_usage(BYTE usage1, BYTE usage_idx1, BYTE usage2, BYTE usage_idx2)
+{
+    if (usage_idx1 != usage_idx2)
+        return FALSE;
+    if (usage1 == usage2)
+        return TRUE;
+    if (usage1 == WINED3D_DECL_USAGE_POSITION && usage2 == WINED3D_DECL_USAGE_POSITIONT)
+        return TRUE;
+    if (usage2 == WINED3D_DECL_USAGE_POSITION && usage1 == WINED3D_DECL_USAGE_POSITIONT)
+        return TRUE;
+
+    return FALSE;
+}
+
+BOOL vshader_get_input(const struct wined3d_shader *shader,
+        BYTE usage_req, BYTE usage_idx_req, unsigned int *regnum)
+{
+    WORD map = shader->reg_maps.input_registers;
+    unsigned int i;
+
+    for (i = 0; map; map >>= 1, ++i)
+    {
+        if (!(map & 1)) continue;
+
+        if (match_usage(shader->u.vs.attributes[i].usage,
+                shader->u.vs.attributes[i].usage_idx, usage_req, usage_idx_req))
+        {
+            *regnum = i;
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+static void vertexshader_set_limits(struct wined3d_shader *shader)
+{
+    DWORD shader_version = WINED3D_SHADER_VERSION(shader->reg_maps.shader_version.major,
+            shader->reg_maps.shader_version.minor);
+    struct wined3d_device *device = shader->device;
+    const DWORD vs_uniform_count = device->adapter->d3d_info.limits.vs_uniform_count;
+
+    shader->limits.packed_input = 0;
+
+    switch (shader_version)
+    {
+        case WINED3D_SHADER_VERSION(1, 0):
+        case WINED3D_SHADER_VERSION(1, 1):
+            shader->limits.constant_bool = 0;
+            shader->limits.constant_int = 0;
+            shader->limits.packed_output = 12;
+            shader->limits.sampler = 0;
+            /* TODO: vs_1_1 has a minimum of 96 constants. What happens when
+             * a vs_1_1 shader is used on a vs_3_0 capable card that has 256
+             * constants? */
+            shader->limits.constant_float = min(256, vs_uniform_count);
+            break;
+
+        case WINED3D_SHADER_VERSION(2, 0):
+        case WINED3D_SHADER_VERSION(2, 1):
+            shader->limits.constant_bool = 16;
+            shader->limits.constant_int = 16;
+            shader->limits.packed_output = 12;
+            shader->limits.sampler = 0;
+            shader->limits.constant_float = min(256, vs_uniform_count);
+            break;
+
+        case WINED3D_SHADER_VERSION(3, 0):
+            shader->limits.constant_bool = 16;
+            shader->limits.constant_int = 16;
+            shader->limits.packed_output = 12;
+            shader->limits.sampler = 4;
+            /* DX10 cards on Windows advertise a d3d9 constant limit of 256
+             * even though they are capable of supporting much more (GL
+             * drivers advertise 1024). d3d9.dll and d3d8.dll clamp the
+             * wined3d-advertised maximum. Clamp the constant limit for <= 3.0
+             * shaders to 256. */
+            shader->limits.constant_float = min(256, vs_uniform_count);
+            break;
+
+        case WINED3D_SHADER_VERSION(4, 0):
+            shader->limits.sampler = 16; /* FIXME: 128 resources, 16 sampler states */
+            shader->limits.constant_int = 0;
+            shader->limits.constant_float = 0;
+            shader->limits.constant_bool = 0;
+            shader->limits.packed_output = 16;
+            shader->limits.packed_input = 0;
+            break;
+
+        default:
+            shader->limits.constant_bool = 16;
+            shader->limits.constant_int = 16;
+            shader->limits.packed_output = 12;
+            shader->limits.sampler = 0;
+            shader->limits.constant_float = min(256, vs_uniform_count);
+            FIXME("Unrecognized vertex shader version \"%u.%u\".\n",
+                    shader->reg_maps.shader_version.major,
+                    shader->reg_maps.shader_version.minor);
+    }
+}
+
+static HRESULT vertexshader_init(struct wined3d_shader *shader, struct wined3d_device *device,
+        const DWORD *byte_code, const struct wined3d_shader_signature *output_signature,
+        void *parent, const struct wined3d_parent_ops *parent_ops, unsigned int max_version)
+{
+    struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
+    unsigned int i;
+    HRESULT hr;
+    WORD map;
+    const DWORD vs_uniform_count = device->adapter->d3d_info.limits.vs_uniform_count;
+
+    if (!byte_code) return WINED3DERR_INVALIDCALL;
+
+    shader_init(shader, device, parent, parent_ops);
+    hr = shader_set_function(shader, byte_code, output_signature, vs_uniform_count,
+            WINED3D_SHADER_TYPE_VERTEX, max_version);
+    if (FAILED(hr))
+    {
+        WARN("Failed to set function, hr %#x.\n", hr);
+        shader_cleanup(shader);
+        return hr;
+    }
+
+    map = reg_maps->input_registers;
+    for (i = 0; map; map >>= 1, ++i)
+    {
+        if (!(map & 1) || !shader->input_signature[i].semantic_name)
+            continue;
+
+        shader->u.vs.attributes[i].usage =
+                shader_usage_from_semantic_name(shader->input_signature[i].semantic_name);
+        shader->u.vs.attributes[i].usage_idx = shader->input_signature[i].semantic_idx;
+    }
+
+    if (output_signature)
+    {
+        for (i = 0; i < output_signature->element_count; ++i)
+        {
+            struct wined3d_shader_signature_element *e = &output_signature->elements[i];
+            reg_maps->output_registers |= 1 << e->register_idx;
+            shader->output_signature[e->register_idx] = *e;
+        }
+    }
+
+    vertexshader_set_limits(shader);
+
+    shader->load_local_constsF = (reg_maps->usesrelconstF && !list_empty(&shader->constantsF)) ||
+            shader->lconst_inf_or_nan;
+
+    return WINED3D_OK;
+}
+
+static void geometryshader_set_limits(struct wined3d_shader *shader)
+{
+    DWORD shader_version = WINED3D_SHADER_VERSION(shader->reg_maps.shader_version.major,
+            shader->reg_maps.shader_version.minor);
+
+    switch (shader_version)
+    {
+        case WINED3D_SHADER_VERSION(4, 0):
+            shader->limits.sampler = 16; /* FIXME: 128 resources, 16 sampler states */
+            shader->limits.constant_int = 0;
+            shader->limits.constant_float = 0;
+            shader->limits.constant_bool = 0;
+            shader->limits.packed_output = 32;
+            shader->limits.packed_input = 16;
+            break;
+
+        default:
+            memset(&shader->limits, 0, sizeof(shader->limits));
+            FIXME("Unhandled geometry shader version \"%u.%u\".\n",
+                    shader->reg_maps.shader_version.major,
+                    shader->reg_maps.shader_version.minor);
+    }
+}
+
+static HRESULT geometryshader_init(struct wined3d_shader *shader, struct wined3d_device *device,
+        const DWORD *byte_code, const struct wined3d_shader_signature *output_signature,
+        void *parent, const struct wined3d_parent_ops *parent_ops, unsigned int max_version)
+{
+    HRESULT hr;
+
+    shader_init(shader, device, parent, parent_ops);
+    hr = shader_set_function(shader, byte_code, output_signature, 0,
+            WINED3D_SHADER_TYPE_GEOMETRY, max_version);
+    if (FAILED(hr))
+    {
+        WARN("Failed to set function, hr %#x.\n", hr);
+        shader_cleanup(shader);
+        return hr;
+    }
+
+    geometryshader_set_limits(shader);
+
+    shader->load_local_constsF = shader->lconst_inf_or_nan;
+
+    return WINED3D_OK;
+}
+
+void find_ps_compile_args(const struct wined3d_state *state,
+        const struct wined3d_shader *shader, struct ps_compile_args *args)
+{
+    struct wined3d_device *device = shader->device;
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    const struct wined3d_texture *texture;
+    UINT i;
+
+    memset(args, 0, sizeof(*args)); /* FIXME: Make sure all bits are set. */
+    if (!gl_info->supported[ARB_FRAMEBUFFER_SRGB] && state->render_states[WINED3D_RS_SRGBWRITEENABLE])
+    {
+        const struct wined3d_surface *rt = state->fb->render_targets[0];
+        if (rt->resource.format->flags & WINED3DFMT_FLAG_SRGB_WRITE)
+        {
+            static unsigned int warned = 0;
+
+            args->srgb_correction = 1;
+            if (state->render_states[WINED3D_RS_ALPHABLENDENABLE] && !warned++)
+                WARN("Blending into a sRGB render target with no GL_ARB_framebuffer_sRGB "
+                        "support, expect rendering artifacts.\n");
+        }
+    }
+
+    if (shader->reg_maps.shader_version.major == 1
+            && shader->reg_maps.shader_version.minor <= 3)
+    {
+        for (i = 0; i < shader->limits.sampler; ++i)
+        {
+            DWORD flags = state->texture_states[i][WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS];
+
+            if (flags & WINED3D_TTFF_PROJECTED)
+            {
+                DWORD tex_transform = flags & ~WINED3D_TTFF_PROJECTED;
+
+                if (!state->vertex_shader)
+                {
+                    unsigned int j;
+                    unsigned int index = state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX];
+                    DWORD max_valid = WINED3D_TTFF_COUNT4;
+                    enum wined3d_sampler_texture_type sampler_type = shader->reg_maps.sampler_type[i];
+
+                    for (j = 0; j < state->vertex_declaration->element_count; ++j)
+                    {
+                        struct wined3d_vertex_declaration_element *element =
+                                &state->vertex_declaration->elements[j];
+
+                        if (element->usage == WINED3D_DECL_USAGE_TEXCOORD
+                                && element->usage_idx == index)
+                        {
+                            max_valid = element->format->component_count;
+                            break;
+                        }
+                    }
+                    if (!tex_transform || tex_transform > max_valid)
+                    {
+                        WARN("Fixing up projected texture transform flags from %#x to %#x.\n",
+                                tex_transform, max_valid);
+                        tex_transform = max_valid;
+                    }
+                    if ((sampler_type == WINED3DSTT_1D && tex_transform > WINED3D_TTFF_COUNT1)
+                            || (sampler_type == WINED3DSTT_2D && tex_transform > WINED3D_TTFF_COUNT2)
+                            || (sampler_type == WINED3DSTT_VOLUME && tex_transform > WINED3D_TTFF_COUNT3))
+                        tex_transform |= WINED3D_PSARGS_PROJECTED;
+                    else
+                    {
+                        WARN("Application requested projected texture with unsuitable texture coordinates.\n");
+                        WARN("(texture unit %u, transform flags %#x, sampler type %u).\n",
+                                i, tex_transform, sampler_type);
+                    }
+                }
+                else
+                    tex_transform = WINED3D_TTFF_COUNT4 | WINED3D_PSARGS_PROJECTED;
+
+                args->tex_transform |= tex_transform << i * WINED3D_PSARGS_TEXTRANSFORM_SHIFT;
+            }
+        }
+    }
+    if (shader->reg_maps.shader_version.major == 1
+            && shader->reg_maps.shader_version.minor <= 4)
+    {
+        for (i = 0; i < shader->limits.sampler; ++i)
+        {
+            const struct wined3d_texture *texture = state->textures[i];
+
+            if (!shader->reg_maps.sampler_type[i])
+                continue;
+
+            /* Treat unbound textures as 2D. The dummy texture will provide
+             * the proper sample value. The tex_types bitmap defaults to
+             * 2D because of the memset. */
+            if (!texture)
+                continue;
+
+            switch (texture->target)
+            {
+                /* RECT textures are distinguished from 2D textures via np2_fixup */
+                case GL_TEXTURE_RECTANGLE_ARB:
+                case GL_TEXTURE_2D:
+                    break;
+
+                case GL_TEXTURE_3D:
+                    args->tex_types |= WINED3D_SHADER_TEX_3D << i * WINED3D_PSARGS_TEXTYPE_SHIFT;
+                    break;
+
+                case GL_TEXTURE_CUBE_MAP_ARB:
+                    args->tex_types |= WINED3D_SHADER_TEX_CUBE << i * WINED3D_PSARGS_TEXTYPE_SHIFT;
+                    break;
+            }
+        }
+    }
+
+    for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i)
+    {
+        if (!shader->reg_maps.sampler_type[i])
+            continue;
+
+        texture = state->textures[i];
+        if (!texture)
+        {
+            args->color_fixup[i] = COLOR_FIXUP_IDENTITY;
+            continue;
+        }
+        args->color_fixup[i] = texture->resource.format->color_fixup;
+
+        if (texture->resource.format->flags & WINED3DFMT_FLAG_SHADOW)
+            args->shadow |= 1 << i;
+
+        /* Flag samplers that need NP2 texcoord fixup. */
+        if (!(texture->flags & WINED3D_TEXTURE_POW2_MAT_IDENT))
+            args->np2_fixup |= (1 << i);
+    }
+    if (shader->reg_maps.shader_version.major >= 3)
+    {
+        if (device->stream_info.position_transformed)
+            args->vp_mode = pretransformed;
+        else if (use_vs(state))
+            args->vp_mode = vertexshader;
+        else
+            args->vp_mode = fixedfunction;
+        args->fog = WINED3D_FFP_PS_FOG_OFF;
+    }
+    else
+    {
+        args->vp_mode = vertexshader;
+        if (state->render_states[WINED3D_RS_FOGENABLE])
+        {
+            switch (state->render_states[WINED3D_RS_FOGTABLEMODE])
+            {
+                case WINED3D_FOG_NONE:
+                    if (device->stream_info.position_transformed || use_vs(state))
+                    {
+                        args->fog = WINED3D_FFP_PS_FOG_LINEAR;
+                        break;
+                    }
+
+                    switch (state->render_states[WINED3D_RS_FOGVERTEXMODE])
+                    {
+                        case WINED3D_FOG_NONE: /* Fall through. */
+                        case WINED3D_FOG_LINEAR: args->fog = WINED3D_FFP_PS_FOG_LINEAR; break;
+                        case WINED3D_FOG_EXP:    args->fog = WINED3D_FFP_PS_FOG_EXP;    break;
+                        case WINED3D_FOG_EXP2:   args->fog = WINED3D_FFP_PS_FOG_EXP2;   break;
+                    }
+                    break;
+
+                case WINED3D_FOG_LINEAR: args->fog = WINED3D_FFP_PS_FOG_LINEAR; break;
+                case WINED3D_FOG_EXP:    args->fog = WINED3D_FFP_PS_FOG_EXP;    break;
+                case WINED3D_FOG_EXP2:   args->fog = WINED3D_FFP_PS_FOG_EXP2;   break;
+            }
+        }
+        else
+        {
+            args->fog = WINED3D_FFP_PS_FOG_OFF;
+        }
+    }
+}
+
+static void pixelshader_set_limits(struct wined3d_shader *shader)
+{
+    DWORD shader_version = WINED3D_SHADER_VERSION(shader->reg_maps.shader_version.major,
+            shader->reg_maps.shader_version.minor);
+
+    shader->limits.packed_output = 0;
+
+    switch (shader_version)
+    {
+        case WINED3D_SHADER_VERSION(1, 0):
+        case WINED3D_SHADER_VERSION(1, 1):
+        case WINED3D_SHADER_VERSION(1, 2):
+        case WINED3D_SHADER_VERSION(1, 3):
+            shader->limits.constant_float = 8;
+            shader->limits.constant_int = 0;
+            shader->limits.constant_bool = 0;
+            shader->limits.sampler = 4;
+            shader->limits.packed_input = 0;
+            break;
+
+        case WINED3D_SHADER_VERSION(1, 4):
+            shader->limits.constant_float = 8;
+            shader->limits.constant_int = 0;
+            shader->limits.constant_bool = 0;
+            shader->limits.sampler = 6;
+            shader->limits.packed_input = 0;
+            break;
+
+        /* FIXME: Temporaries must match D3DPSHADERCAPS2_0.NumTemps. */
+        case WINED3D_SHADER_VERSION(2, 0):
+            shader->limits.constant_float = 32;
+            shader->limits.constant_int = 16;
+            shader->limits.constant_bool = 16;
+            shader->limits.sampler = 16;
+            shader->limits.packed_input = 0;
+            break;
+
+        case WINED3D_SHADER_VERSION(2, 1):
+            shader->limits.constant_float = 32;
+            shader->limits.constant_int = 16;
+            shader->limits.constant_bool = 16;
+            shader->limits.sampler = 16;
+            shader->limits.packed_input = 0;
+            break;
+
+        case WINED3D_SHADER_VERSION(3, 0):
+            shader->limits.constant_float = 224;
+            shader->limits.constant_int = 16;
+            shader->limits.constant_bool = 16;
+            shader->limits.sampler = 16;
+            shader->limits.packed_input = 12;
+            break;
+
+        case WINED3D_SHADER_VERSION(4, 0):
+            shader->limits.sampler = 16; /* FIXME: 128 resources, 16 sampler states */
+            shader->limits.constant_int = 0;
+            shader->limits.constant_float = 0;
+            shader->limits.constant_bool = 0;
+            shader->limits.packed_input = 32;
+            break;
+
+        default:
+            shader->limits.constant_float = 32;
+            shader->limits.constant_int = 16;
+            shader->limits.constant_bool = 16;
+            shader->limits.sampler = 16;
+            shader->limits.packed_input = 0;
+            FIXME("Unrecognized pixel shader version %u.%u\n",
+                    shader->reg_maps.shader_version.major,
+                    shader->reg_maps.shader_version.minor);
+    }
+}
+
+static HRESULT pixelshader_init(struct wined3d_shader *shader, struct wined3d_device *device,
+        const DWORD *byte_code, const struct wined3d_shader_signature *output_signature,
+        void *parent, const struct wined3d_parent_ops *parent_ops, unsigned int max_version)
+{
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    unsigned int i, highest_reg_used = 0, num_regs_used = 0;
+    HRESULT hr;
+    const DWORD ps_uniform_count = device->adapter->d3d_info.limits.ps_uniform_count;
+
+    if (!byte_code) return WINED3DERR_INVALIDCALL;
+
+    shader_init(shader, device, parent, parent_ops);
+    hr = shader_set_function(shader, byte_code, output_signature, ps_uniform_count,
+            WINED3D_SHADER_TYPE_PIXEL, max_version);
+    if (FAILED(hr))
+    {
+        WARN("Failed to set function, hr %#x.\n", hr);
+        shader_cleanup(shader);
+        return hr;
+    }
+
+    pixelshader_set_limits(shader);
+
+    for (i = 0; i < MAX_REG_INPUT; ++i)
+    {
+        if (shader->u.ps.input_reg_used[i])
+        {
+            ++num_regs_used;
+            highest_reg_used = i;
+        }
+    }
+
+    /* Don't do any register mapping magic if it is not needed, or if we can't
+     * achieve anything anyway */
+    if (highest_reg_used < (gl_info->limits.glsl_varyings / 4)
+            || num_regs_used > (gl_info->limits.glsl_varyings / 4))
+    {
+        if (num_regs_used > (gl_info->limits.glsl_varyings / 4))
+        {
+            /* This happens with relative addressing. The input mapper function
+             * warns about this if the higher registers are declared too, so
+             * don't write a FIXME here */
+            WARN("More varying registers used than supported\n");
+        }
+
+        for (i = 0; i < MAX_REG_INPUT; ++i)
+        {
+            shader->u.ps.input_reg_map[i] = i;
+        }
+
+        shader->u.ps.declared_in_count = highest_reg_used + 1;
+    }
+    else
+    {
+        shader->u.ps.declared_in_count = 0;
+        for (i = 0; i < MAX_REG_INPUT; ++i)
+        {
+            if (shader->u.ps.input_reg_used[i])
+                shader->u.ps.input_reg_map[i] = shader->u.ps.declared_in_count++;
+            else shader->u.ps.input_reg_map[i] = ~0U;
+        }
+    }
+
+    shader->load_local_constsF = shader->lconst_inf_or_nan;
+
+    return WINED3D_OK;
+}
+
+void pixelshader_update_samplers(struct wined3d_shader *shader, WORD tex_types)
+{
+    struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
+    enum wined3d_sampler_texture_type *sampler_type = reg_maps->sampler_type;
+    unsigned int i;
+
+    if (reg_maps->shader_version.major != 1) return;
+
+    for (i = 0; i < shader->limits.sampler; ++i)
+    {
+        /* We don't sample from this sampler. */
+        if (!sampler_type[i]) continue;
+
+        switch ((tex_types >> i * WINED3D_PSARGS_TEXTYPE_SHIFT) & WINED3D_PSARGS_TEXTYPE_MASK)
+        {
+            case WINED3D_SHADER_TEX_2D:
+                sampler_type[i] = WINED3DSTT_2D;
+                break;
+
+            case WINED3D_SHADER_TEX_3D:
+                sampler_type[i] = WINED3DSTT_VOLUME;
+                break;
+
+            case WINED3D_SHADER_TEX_CUBE:
+                sampler_type[i] = WINED3DSTT_CUBE;
+                break;
+        }
+    }
+}
+
+HRESULT CDECL wined3d_shader_create_gs(struct wined3d_device *device, const DWORD *byte_code,
+        const struct wined3d_shader_signature *output_signature, void *parent,
+        const struct wined3d_parent_ops *parent_ops, struct wined3d_shader **shader, unsigned int max_version)
+{
+    struct wined3d_shader *object;
+    HRESULT hr;
+
+    TRACE("device %p, byte_code %p, output_signature %p, parent %p, parent_ops %p, shader %p.\n",
+            device, byte_code, output_signature, parent, parent_ops, shader);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return E_OUTOFMEMORY;
+
+    hr = geometryshader_init(object, device, byte_code, output_signature, parent, parent_ops, max_version);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize geometry shader, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created geometry shader %p.\n", object);
+    *shader = object;
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_shader_create_ps(struct wined3d_device *device, const DWORD *byte_code,
+        const struct wined3d_shader_signature *output_signature, void *parent,
+        const struct wined3d_parent_ops *parent_ops, struct wined3d_shader **shader, unsigned int max_version)
+{
+    struct wined3d_shader *object;
+    HRESULT hr;
+
+    TRACE("device %p, byte_code %p, output_signature %p, parent %p, parent_ops %p, shader %p.\n",
+            device, byte_code, output_signature, parent, parent_ops, shader);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return E_OUTOFMEMORY;
+
+    hr = pixelshader_init(object, device, byte_code, output_signature, parent, parent_ops, max_version);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize pixel shader, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+#ifdef VBOX_WINE_WITH_SHADER_CACHE
+    object = pixelshader_check_cached(device, object);
+#endif
+
+    TRACE("Created pixel shader %p.\n", object);
+    *shader = object;
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_shader_create_vs(struct wined3d_device *device, const DWORD *byte_code,
+        const struct wined3d_shader_signature *output_signature, void *parent,
+        const struct wined3d_parent_ops *parent_ops, struct wined3d_shader **shader, unsigned int max_version)
+{
+    struct wined3d_shader *object;
+    HRESULT hr;
+
+    TRACE("device %p, byte_code %p, output_signature %p, parent %p, parent_ops %p, shader %p.\n",
+            device, byte_code, output_signature, parent, parent_ops, shader);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return E_OUTOFMEMORY;
+
+    hr = vertexshader_init(object, device, byte_code, output_signature, parent, parent_ops, max_version);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize vertex shader, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+#ifdef VBOX_WINE_WITH_SHADER_CACHE
+    object = vertexshader_check_cached(device, object);
+#endif
+
+    TRACE("Created vertex shader %p.\n", object);
+    *shader = object;
+
+    return WINED3D_OK;
+}
+
+#ifdef VBOX_WINE_WITH_SHADER_CACHE
+
+static void shader_reinit(struct wined3d_shader *shader, struct wined3d_device *device,
+        void *parent, const struct wined3d_parent_ops *parent_ops)
+{
+    shader->ref = 1;
+    shader->device = device;
+    shader->parent = parent;
+    shader->parent_ops = parent_ops;
+#ifdef DEBUG
+    {
+        struct wined3d_shader *tst_shader;
+        LIST_FOR_EACH_ENTRY(tst_shader, &device->shaders, struct wined3d_shader, shader_list_entry) {
+            if (tst_shader == shader)
+                return;
+        }
+        ERR("shader not in list!");
+    }
+#endif
+}
+
+static DECLCALLBACK(uint32_t) shader_cache_hash(void *pvKey)
+{
+    uint32_t u32Hash, i;
+    DWORD *function;
+    struct wined3d_shader * shader = (struct wined3d_shader *)pvKey;
+    if (shader->u32CacheDataInited)
+        return shader->u32Hash;
+
+    u32Hash = shader->functionLength;
+    function = shader->function;
+    for (i = 0; i < shader->functionLength / 4; ++i)
+    {
+        u32Hash += *function++;
+    }
+
+    for (i = 0; i < shader->functionLength % 4; ++i)
+    {
+        u32Hash += *((uint8_t*)function)++;
+    }
+
+    shader->u32Hash = u32Hash;
+    shader->u32CacheDataInited = TRUE;
+    return shader->u32Hash;
+}
+
+static DECLCALLBACK(bool) shader_cache_equal(void *pvKey1, void *pvKey2)
+{
+    struct wined3d_shader *shader1 = (struct wined3d_shader *)pvKey1;
+    struct wined3d_shader *shader2 = (struct wined3d_shader *)pvKey2;
+
+    if (shader1 == shader2)
+        return TRUE;
+
+    if (shader1->functionLength != shader2->functionLength)
+        return FALSE;
+
+    if (shader_cache_hash(pvKey1) != shader_cache_hash(pvKey2))
+    {
+#ifdef DEBUG_misha
+        Assert(memcmp(shader1->function, shader2->function, shader1->functionLength));
+#endif
+        return FALSE;
+    }
+
+    return !memcmp(shader1->function, shader2->function, shader1->functionLength);
+}
+
+#define VBOX_SHADER_FROM_CACHE_ENTRY(_pEntry) RT_FROM_MEMBER((_pEntry), struct wined3d_shader, CacheEntry)
+
+static DECLCALLBACK(void) shader_cache_cleanup_entry(void *pvKey, struct VBOXEXT_HASHCACHE_ENTRY *pEntry)
+{
+    struct wined3d_shader *shader = VBOX_SHADER_FROM_CACHE_ENTRY(pEntry);
+    shader_cleanup(shader);
+    if (shader->parent)
+        shader->parent_ops->wined3d_object_destroyed(shader->parent);
+    HeapFree(GetProcessHeap(), 0, shader);
+}
+
+static void shader_chache_init(PVBOXEXT_HASHCACHE pCache)
+{
+    VBoxExtCacheInit(pCache, 1024, shader_cache_hash, shader_cache_equal, shader_cache_cleanup_entry);
+}
+
+static void shader_chache_term(PVBOXEXT_HASHCACHE pCache)
+{
+    VBoxExtCacheTerm(pCache);
+}
+
+static void shader_chache_put(PVBOXEXT_HASHCACHE pCache, struct wined3d_shader *shader)
+{
+    if (shader->parent)
+    {
+        shader->parent_ops->wined3d_object_destroyed(shader->parent);
+        shader->parent = NULL;
+    }
+
+    VBoxExtCachePut(pCache, shader, &shader->CacheEntry);
+}
+
+static struct wined3d_shader* shader_chache_get(PVBOXEXT_HASHCACHE pCache, struct wined3d_shader *shader)
+{
+    PVBOXEXT_HASHCACHE_ENTRY pEntry = VBoxExtCacheGet(pCache, shader);
+    struct wined3d_shader *cached_shader;
+
+    if (!pEntry)
+        return shader;
+
+    cached_shader = VBOX_SHADER_FROM_CACHE_ENTRY(pEntry);
+    shader_reinit(cached_shader, shader->device,
+            shader->parent, shader->parent_ops);
+    shader->parent = NULL;
+    /* we can not do a IWineD3DBaseShader_Release here since this would result in putting a shader to the cache */
+    shader_cleanup(shader);
+    HeapFree(GetProcessHeap(), 0, shader);
+    return cached_shader;
+}
+
+struct wined3d_shader * vertexshader_check_cached(struct wined3d_device *device, struct wined3d_shader *object)
+{
+    object->shaderCache = &device->vshaderCache;
+    return shader_chache_get(&device->vshaderCache, (struct wined3d_shader *)object);
+}
+
+struct wined3d_shader * pixelshader_check_cached(struct wined3d_device *device, struct wined3d_shader *object)
+{
+    object->shaderCache = &device->pshaderCache;
+    return shader_chache_get(&device->pshaderCache, (struct wined3d_shader *)object);
+}
+
+void shader_chaches_init(struct wined3d_device *device)
+{
+    shader_chache_init(&device->vshaderCache);
+    shader_chache_init(&device->pshaderCache);
+}
+
+void shader_chaches_term(struct wined3d_device *device)
+{
+    shader_chache_term(&device->vshaderCache);
+    shader_chache_term(&device->pshaderCache);
+}
+#endif
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/shader_sm1.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/shader_sm1.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/shader_sm1.c	(revision 46521)
@@ -0,0 +1,776 @@
+/*
+ * Copyright 2002-2003 Jason Edmeades
+ * Copyright 2002-2003 Raphael Junqueira
+ * Copyright 2004 Christian Costa
+ * Copyright 2005 Oliver Stieber
+ * Copyright 2006 Ivan Gyurdiev
+ * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
+ * Copyright 2009 Henri Verbeet for CodeWeavers
+ *
+ * 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 "wined3d_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
+
+/* DCL usage masks */
+#define WINED3DSP_DCL_USAGE_SHIFT               0
+#define WINED3DSP_DCL_USAGE_MASK                (0xf << WINED3DSP_DCL_USAGE_SHIFT)
+#define WINED3DSP_DCL_USAGEINDEX_SHIFT          16
+#define WINED3DSP_DCL_USAGEINDEX_MASK           (0xf << WINED3DSP_DCL_USAGEINDEX_SHIFT)
+
+/* DCL sampler type */
+#define WINED3DSP_TEXTURETYPE_SHIFT             27
+#define WINED3DSP_TEXTURETYPE_MASK              (0xf << WINED3DSP_TEXTURETYPE_SHIFT)
+
+/* Opcode-related masks */
+#define WINED3DSI_OPCODE_MASK                   0x0000ffff
+
+#define WINED3D_OPCODESPECIFICCONTROL_SHIFT     16
+#define WINED3D_OPCODESPECIFICCONTROL_MASK      (0xff << WINED3D_OPCODESPECIFICCONTROL_SHIFT)
+
+#define WINED3DSI_INSTLENGTH_SHIFT              24
+#define WINED3DSI_INSTLENGTH_MASK               (0xf << WINED3DSI_INSTLENGTH_SHIFT)
+
+#define WINED3DSI_COISSUE                       (1 << 30)
+
+#define WINED3DSI_COMMENTSIZE_SHIFT             16
+#define WINED3DSI_COMMENTSIZE_MASK              (0x7fff << WINED3DSI_COMMENTSIZE_SHIFT)
+
+#define WINED3DSHADER_INSTRUCTION_PREDICATED    (1 << 28)
+
+/* Register number mask */
+#define WINED3DSP_REGNUM_MASK                   0x000007ff
+
+/* Register type masks  */
+#define WINED3DSP_REGTYPE_SHIFT                 28
+#define WINED3DSP_REGTYPE_MASK                  (0x7 << WINED3DSP_REGTYPE_SHIFT)
+#define WINED3DSP_REGTYPE_SHIFT2                8
+#define WINED3DSP_REGTYPE_MASK2                 (0x18 << WINED3DSP_REGTYPE_SHIFT2)
+
+/* Relative addressing mask */
+#define WINED3DSHADER_ADDRESSMODE_SHIFT         13
+#define WINED3DSHADER_ADDRESSMODE_MASK          (1 << WINED3DSHADER_ADDRESSMODE_SHIFT)
+
+/* Destination modifier mask */
+#define WINED3DSP_DSTMOD_SHIFT                  20
+#define WINED3DSP_DSTMOD_MASK                   (0xf << WINED3DSP_DSTMOD_SHIFT)
+
+/* Destination shift mask */
+#define WINED3DSP_DSTSHIFT_SHIFT                24
+#define WINED3DSP_DSTSHIFT_MASK                 (0xf << WINED3DSP_DSTSHIFT_SHIFT)
+
+/* Write mask */
+#define WINED3D_SM1_WRITEMASK_SHIFT             16
+#define WINED3D_SM1_WRITEMASK_MASK              (0xf << WINED3D_SM1_WRITEMASK_SHIFT)
+
+/* Swizzle mask */
+#define WINED3DSP_SWIZZLE_SHIFT                 16
+#define WINED3DSP_SWIZZLE_MASK                  (0xff << WINED3DSP_SWIZZLE_SHIFT)
+
+/* Source modifier mask */
+#define WINED3DSP_SRCMOD_SHIFT                  24
+#define WINED3DSP_SRCMOD_MASK                   (0xf << WINED3DSP_SRCMOD_SHIFT)
+
+#define WINED3DSP_END                           0x0000ffff
+
+#define WINED3D_SM1_VERSION_MAJOR(version)      (((version) >> 8) & 0xff)
+#define WINED3D_SM1_VERSION_MINOR(version)      (((version) >> 0) & 0xff)
+
+enum WINED3DSHADER_ADDRESSMODE_TYPE
+{
+    WINED3DSHADER_ADDRMODE_ABSOLUTE = 0 << WINED3DSHADER_ADDRESSMODE_SHIFT,
+    WINED3DSHADER_ADDRMODE_RELATIVE = 1 << WINED3DSHADER_ADDRESSMODE_SHIFT,
+};
+
+enum wined3d_sm1_opcode
+{
+    WINED3D_SM1_OP_NOP          = 0x00,
+    WINED3D_SM1_OP_MOV          = 0x01,
+    WINED3D_SM1_OP_ADD          = 0x02,
+    WINED3D_SM1_OP_SUB          = 0x03,
+    WINED3D_SM1_OP_MAD          = 0x04,
+    WINED3D_SM1_OP_MUL          = 0x05,
+    WINED3D_SM1_OP_RCP          = 0x06,
+    WINED3D_SM1_OP_RSQ          = 0x07,
+    WINED3D_SM1_OP_DP3          = 0x08,
+    WINED3D_SM1_OP_DP4          = 0x09,
+    WINED3D_SM1_OP_MIN          = 0x0a,
+    WINED3D_SM1_OP_MAX          = 0x0b,
+    WINED3D_SM1_OP_SLT          = 0x0c,
+    WINED3D_SM1_OP_SGE          = 0x0d,
+    WINED3D_SM1_OP_EXP          = 0x0e,
+    WINED3D_SM1_OP_LOG          = 0x0f,
+    WINED3D_SM1_OP_LIT          = 0x10,
+    WINED3D_SM1_OP_DST          = 0x11,
+    WINED3D_SM1_OP_LRP          = 0x12,
+    WINED3D_SM1_OP_FRC          = 0x13,
+    WINED3D_SM1_OP_M4x4         = 0x14,
+    WINED3D_SM1_OP_M4x3         = 0x15,
+    WINED3D_SM1_OP_M3x4         = 0x16,
+    WINED3D_SM1_OP_M3x3         = 0x17,
+    WINED3D_SM1_OP_M3x2         = 0x18,
+    WINED3D_SM1_OP_CALL         = 0x19,
+    WINED3D_SM1_OP_CALLNZ       = 0x1a,
+    WINED3D_SM1_OP_LOOP         = 0x1b,
+    WINED3D_SM1_OP_RET          = 0x1c,
+    WINED3D_SM1_OP_ENDLOOP      = 0x1d,
+    WINED3D_SM1_OP_LABEL        = 0x1e,
+    WINED3D_SM1_OP_DCL          = 0x1f,
+    WINED3D_SM1_OP_POW          = 0x20,
+    WINED3D_SM1_OP_CRS          = 0x21,
+    WINED3D_SM1_OP_SGN          = 0x22,
+    WINED3D_SM1_OP_ABS          = 0x23,
+    WINED3D_SM1_OP_NRM          = 0x24,
+    WINED3D_SM1_OP_SINCOS       = 0x25,
+    WINED3D_SM1_OP_REP          = 0x26,
+    WINED3D_SM1_OP_ENDREP       = 0x27,
+    WINED3D_SM1_OP_IF           = 0x28,
+    WINED3D_SM1_OP_IFC          = 0x29,
+    WINED3D_SM1_OP_ELSE         = 0x2a,
+    WINED3D_SM1_OP_ENDIF        = 0x2b,
+    WINED3D_SM1_OP_BREAK        = 0x2c,
+    WINED3D_SM1_OP_BREAKC       = 0x2d,
+    WINED3D_SM1_OP_MOVA         = 0x2e,
+    WINED3D_SM1_OP_DEFB         = 0x2f,
+    WINED3D_SM1_OP_DEFI         = 0x30,
+
+    WINED3D_SM1_OP_TEXCOORD     = 0x40,
+    WINED3D_SM1_OP_TEXKILL      = 0x41,
+    WINED3D_SM1_OP_TEX          = 0x42,
+    WINED3D_SM1_OP_TEXBEM       = 0x43,
+    WINED3D_SM1_OP_TEXBEML      = 0x44,
+    WINED3D_SM1_OP_TEXREG2AR    = 0x45,
+    WINED3D_SM1_OP_TEXREG2GB    = 0x46,
+    WINED3D_SM1_OP_TEXM3x2PAD   = 0x47,
+    WINED3D_SM1_OP_TEXM3x2TEX   = 0x48,
+    WINED3D_SM1_OP_TEXM3x3PAD   = 0x49,
+    WINED3D_SM1_OP_TEXM3x3TEX   = 0x4a,
+    WINED3D_SM1_OP_TEXM3x3DIFF  = 0x4b,
+    WINED3D_SM1_OP_TEXM3x3SPEC  = 0x4c,
+    WINED3D_SM1_OP_TEXM3x3VSPEC = 0x4d,
+    WINED3D_SM1_OP_EXPP         = 0x4e,
+    WINED3D_SM1_OP_LOGP         = 0x4f,
+    WINED3D_SM1_OP_CND          = 0x50,
+    WINED3D_SM1_OP_DEF          = 0x51,
+    WINED3D_SM1_OP_TEXREG2RGB   = 0x52,
+    WINED3D_SM1_OP_TEXDP3TEX    = 0x53,
+    WINED3D_SM1_OP_TEXM3x2DEPTH = 0x54,
+    WINED3D_SM1_OP_TEXDP3       = 0x55,
+    WINED3D_SM1_OP_TEXM3x3      = 0x56,
+    WINED3D_SM1_OP_TEXDEPTH     = 0x57,
+    WINED3D_SM1_OP_CMP          = 0x58,
+    WINED3D_SM1_OP_BEM          = 0x59,
+    WINED3D_SM1_OP_DP2ADD       = 0x5a,
+    WINED3D_SM1_OP_DSX          = 0x5b,
+    WINED3D_SM1_OP_DSY          = 0x5c,
+    WINED3D_SM1_OP_TEXLDD       = 0x5d,
+    WINED3D_SM1_OP_SETP         = 0x5e,
+    WINED3D_SM1_OP_TEXLDL       = 0x5f,
+    WINED3D_SM1_OP_BREAKP       = 0x60,
+
+    WINED3D_SM1_OP_PHASE        = 0xfffd,
+    WINED3D_SM1_OP_COMMENT      = 0xfffe,
+    WINED3D_SM1_OP_END          = 0Xffff,
+};
+
+struct wined3d_sm1_opcode_info
+{
+    enum wined3d_sm1_opcode opcode;
+    UINT dst_count;
+    UINT param_count;
+    enum WINED3D_SHADER_INSTRUCTION_HANDLER handler_idx;
+    DWORD min_version;
+    DWORD max_version;
+};
+
+struct wined3d_sm1_data
+{
+    struct wined3d_shader_version shader_version;
+    const struct wined3d_sm1_opcode_info *opcode_table;
+
+    struct wined3d_shader_src_param src_rel_addr[4];
+    struct wined3d_shader_src_param pred_rel_addr;
+    struct wined3d_shader_src_param dst_rel_addr;
+    struct wined3d_shader_src_param src_param[4];
+    struct wined3d_shader_src_param pred_param;
+    struct wined3d_shader_dst_param dst_param;
+};
+
+/* This table is not order or position dependent. */
+static const struct wined3d_sm1_opcode_info vs_opcode_table[] =
+{
+    /* Arithmetic */
+    {WINED3D_SM1_OP_NOP,      0, 0, WINED3DSIH_NOP,          0,                           0                          },
+    {WINED3D_SM1_OP_MOV,      1, 2, WINED3DSIH_MOV,          0,                           0                          },
+    {WINED3D_SM1_OP_MOVA,     1, 2, WINED3DSIH_MOVA,         WINED3D_SHADER_VERSION(2,0), -1                         },
+    {WINED3D_SM1_OP_ADD,      1, 3, WINED3DSIH_ADD,          0,                           0                          },
+    {WINED3D_SM1_OP_SUB,      1, 3, WINED3DSIH_SUB,          0,                           0                          },
+    {WINED3D_SM1_OP_MAD,      1, 4, WINED3DSIH_MAD,          0,                           0                          },
+    {WINED3D_SM1_OP_MUL,      1, 3, WINED3DSIH_MUL,          0,                           0                          },
+    {WINED3D_SM1_OP_RCP,      1, 2, WINED3DSIH_RCP,          0,                           0                          },
+    {WINED3D_SM1_OP_RSQ,      1, 2, WINED3DSIH_RSQ,          0,                           0                          },
+    {WINED3D_SM1_OP_DP3,      1, 3, WINED3DSIH_DP3,          0,                           0                          },
+    {WINED3D_SM1_OP_DP4,      1, 3, WINED3DSIH_DP4,          0,                           0                          },
+    {WINED3D_SM1_OP_MIN,      1, 3, WINED3DSIH_MIN,          0,                           0                          },
+    {WINED3D_SM1_OP_MAX,      1, 3, WINED3DSIH_MAX,          0,                           0                          },
+    {WINED3D_SM1_OP_SLT,      1, 3, WINED3DSIH_SLT,          0,                           0                          },
+    {WINED3D_SM1_OP_SGE,      1, 3, WINED3DSIH_SGE,          0,                           0                          },
+    {WINED3D_SM1_OP_ABS,      1, 2, WINED3DSIH_ABS,          0,                           0                          },
+    {WINED3D_SM1_OP_EXP,      1, 2, WINED3DSIH_EXP,          0,                           0                          },
+    {WINED3D_SM1_OP_LOG,      1, 2, WINED3DSIH_LOG,          0,                           0                          },
+    {WINED3D_SM1_OP_EXPP,     1, 2, WINED3DSIH_EXPP,         0,                           0                          },
+    {WINED3D_SM1_OP_LOGP,     1, 2, WINED3DSIH_LOGP,         0,                           0                          },
+    {WINED3D_SM1_OP_LIT,      1, 2, WINED3DSIH_LIT,          0,                           0                          },
+    {WINED3D_SM1_OP_DST,      1, 3, WINED3DSIH_DST,          0,                           0                          },
+    {WINED3D_SM1_OP_LRP,      1, 4, WINED3DSIH_LRP,          0,                           0                          },
+    {WINED3D_SM1_OP_FRC,      1, 2, WINED3DSIH_FRC,          0,                           0                          },
+    {WINED3D_SM1_OP_POW,      1, 3, WINED3DSIH_POW,          0,                           0                          },
+    {WINED3D_SM1_OP_CRS,      1, 3, WINED3DSIH_CRS,          0,                           0                          },
+    {WINED3D_SM1_OP_SGN,      1, 4, WINED3DSIH_SGN,          WINED3D_SHADER_VERSION(2,0), WINED3D_SHADER_VERSION(2,1)},
+    {WINED3D_SM1_OP_SGN,      1, 2, WINED3DSIH_SGN,          WINED3D_SHADER_VERSION(3,0), -1                         },
+    {WINED3D_SM1_OP_NRM,      1, 2, WINED3DSIH_NRM,          0,                           0                          },
+    {WINED3D_SM1_OP_SINCOS,   1, 4, WINED3DSIH_SINCOS,       WINED3D_SHADER_VERSION(2,0), WINED3D_SHADER_VERSION(2,1)},
+    {WINED3D_SM1_OP_SINCOS,   1, 2, WINED3DSIH_SINCOS,       WINED3D_SHADER_VERSION(3,0), -1                         },
+    /* Matrix */
+    {WINED3D_SM1_OP_M4x4,     1, 3, WINED3DSIH_M4x4,         0,                           0                          },
+    {WINED3D_SM1_OP_M4x3,     1, 3, WINED3DSIH_M4x3,         0,                           0                          },
+    {WINED3D_SM1_OP_M3x4,     1, 3, WINED3DSIH_M3x4,         0,                           0                          },
+    {WINED3D_SM1_OP_M3x3,     1, 3, WINED3DSIH_M3x3,         0,                           0                          },
+    {WINED3D_SM1_OP_M3x2,     1, 3, WINED3DSIH_M3x2,         0,                           0                          },
+    /* Declare registers */
+    {WINED3D_SM1_OP_DCL,      0, 2, WINED3DSIH_DCL,          0,                           0                          },
+    /* Constant definitions */
+    {WINED3D_SM1_OP_DEF,      1, 5, WINED3DSIH_DEF,          0,                           0                          },
+    {WINED3D_SM1_OP_DEFB,     1, 2, WINED3DSIH_DEFB,         0,                           0                          },
+    {WINED3D_SM1_OP_DEFI,     1, 5, WINED3DSIH_DEFI,         0,                           0                          },
+    /* Flow control */
+    {WINED3D_SM1_OP_REP,      0, 1, WINED3DSIH_REP,          WINED3D_SHADER_VERSION(2,0), -1                         },
+    {WINED3D_SM1_OP_ENDREP,   0, 0, WINED3DSIH_ENDREP,       WINED3D_SHADER_VERSION(2,0), -1                         },
+    {WINED3D_SM1_OP_IF,       0, 1, WINED3DSIH_IF,           WINED3D_SHADER_VERSION(2,0), -1                         },
+#ifndef VBOX_WITH_WINE_FIXES
+    {WINED3D_SM1_OP_IFC,      0, 2, WINED3DSIH_IFC,          WINED3D_SHADER_VERSION(2,1), -1                         },
+#else
+    {WINED3D_SM1_OP_IFC,      0, 2, WINED3DSIH_IFC,          WINED3D_SHADER_VERSION(2,0), -1                         },
+#endif
+    {WINED3D_SM1_OP_ELSE,     0, 0, WINED3DSIH_ELSE,         WINED3D_SHADER_VERSION(2,0), -1                         },
+    {WINED3D_SM1_OP_ENDIF,    0, 0, WINED3DSIH_ENDIF,        WINED3D_SHADER_VERSION(2,0), -1                         },
+    {WINED3D_SM1_OP_BREAK,    0, 0, WINED3DSIH_BREAK,        WINED3D_SHADER_VERSION(2,1), -1                         },
+    {WINED3D_SM1_OP_BREAKC,   0, 2, WINED3DSIH_BREAKC,       WINED3D_SHADER_VERSION(2,1), -1                         },
+    {WINED3D_SM1_OP_BREAKP,   0, 1, WINED3DSIH_BREAKP,       0,                           0                          },
+    {WINED3D_SM1_OP_CALL,     0, 1, WINED3DSIH_CALL,         WINED3D_SHADER_VERSION(2,0), -1                         },
+    {WINED3D_SM1_OP_CALLNZ,   0, 2, WINED3DSIH_CALLNZ,       WINED3D_SHADER_VERSION(2,0), -1                         },
+    {WINED3D_SM1_OP_LOOP,     0, 2, WINED3DSIH_LOOP,         WINED3D_SHADER_VERSION(2,0), -1                         },
+    {WINED3D_SM1_OP_RET,      0, 0, WINED3DSIH_RET,          WINED3D_SHADER_VERSION(2,0), -1                         },
+    {WINED3D_SM1_OP_ENDLOOP,  0, 0, WINED3DSIH_ENDLOOP,      WINED3D_SHADER_VERSION(2,0), -1                         },
+    {WINED3D_SM1_OP_LABEL,    0, 1, WINED3DSIH_LABEL,        WINED3D_SHADER_VERSION(2,0), -1                         },
+
+    {WINED3D_SM1_OP_SETP,     1, 3, WINED3DSIH_SETP,         0,                           0                          },
+    {WINED3D_SM1_OP_TEXLDL,   1, 3, WINED3DSIH_TEXLDL,       WINED3D_SHADER_VERSION(3,0), -1                         },
+    {0,                       0, 0, WINED3DSIH_TABLE_SIZE,   0,                           0                          },
+};
+
+static const struct wined3d_sm1_opcode_info ps_opcode_table[] =
+{
+    /* Arithmetic */
+    {WINED3D_SM1_OP_NOP,      0, 0, WINED3DSIH_NOP,          0,                           0                          },
+    {WINED3D_SM1_OP_MOV,      1, 2, WINED3DSIH_MOV,          0,                           0                          },
+    {WINED3D_SM1_OP_ADD,      1, 3, WINED3DSIH_ADD,          0,                           0                          },
+    {WINED3D_SM1_OP_SUB,      1, 3, WINED3DSIH_SUB,          0,                           0                          },
+    {WINED3D_SM1_OP_MAD,      1, 4, WINED3DSIH_MAD,          0,                           0                          },
+    {WINED3D_SM1_OP_MUL,      1, 3, WINED3DSIH_MUL,          0,                           0                          },
+    {WINED3D_SM1_OP_RCP,      1, 2, WINED3DSIH_RCP,          0,                           0                          },
+    {WINED3D_SM1_OP_RSQ,      1, 2, WINED3DSIH_RSQ,          0,                           0                          },
+    {WINED3D_SM1_OP_DP3,      1, 3, WINED3DSIH_DP3,          0,                           0                          },
+    {WINED3D_SM1_OP_DP4,      1, 3, WINED3DSIH_DP4,          0,                           0                          },
+    {WINED3D_SM1_OP_MIN,      1, 3, WINED3DSIH_MIN,          0,                           0                          },
+    {WINED3D_SM1_OP_MAX,      1, 3, WINED3DSIH_MAX,          0,                           0                          },
+    {WINED3D_SM1_OP_SLT,      1, 3, WINED3DSIH_SLT,          0,                           0                          },
+    {WINED3D_SM1_OP_SGE,      1, 3, WINED3DSIH_SGE,          0,                           0                          },
+    {WINED3D_SM1_OP_ABS,      1, 2, WINED3DSIH_ABS,          0,                           0                          },
+    {WINED3D_SM1_OP_EXP,      1, 2, WINED3DSIH_EXP,          0,                           0                          },
+    {WINED3D_SM1_OP_LOG,      1, 2, WINED3DSIH_LOG,          0,                           0                          },
+    {WINED3D_SM1_OP_EXPP,     1, 2, WINED3DSIH_EXPP,         0,                           0                          },
+    {WINED3D_SM1_OP_LOGP,     1, 2, WINED3DSIH_LOGP,         0,                           0                          },
+    {WINED3D_SM1_OP_DST,      1, 3, WINED3DSIH_DST,          0,                           0                          },
+    {WINED3D_SM1_OP_LRP,      1, 4, WINED3DSIH_LRP,          0,                           0                          },
+    {WINED3D_SM1_OP_FRC,      1, 2, WINED3DSIH_FRC,          0,                           0                          },
+    {WINED3D_SM1_OP_CND,      1, 4, WINED3DSIH_CND,          WINED3D_SHADER_VERSION(1,0), WINED3D_SHADER_VERSION(1,4)},
+    {WINED3D_SM1_OP_CMP,      1, 4, WINED3DSIH_CMP,          WINED3D_SHADER_VERSION(1,2), WINED3D_SHADER_VERSION(3,0)},
+    {WINED3D_SM1_OP_POW,      1, 3, WINED3DSIH_POW,          0,                           0                          },
+    {WINED3D_SM1_OP_CRS,      1, 3, WINED3DSIH_CRS,          0,                           0                          },
+    {WINED3D_SM1_OP_NRM,      1, 2, WINED3DSIH_NRM,          0,                           0                          },
+    {WINED3D_SM1_OP_SINCOS,   1, 4, WINED3DSIH_SINCOS,       WINED3D_SHADER_VERSION(2,0), WINED3D_SHADER_VERSION(2,1)},
+    {WINED3D_SM1_OP_SINCOS,   1, 2, WINED3DSIH_SINCOS,       WINED3D_SHADER_VERSION(3,0), -1                         },
+    {WINED3D_SM1_OP_DP2ADD,   1, 4, WINED3DSIH_DP2ADD,       WINED3D_SHADER_VERSION(2,0), -1                         },
+    /* Matrix */
+    {WINED3D_SM1_OP_M4x4,     1, 3, WINED3DSIH_M4x4,         0,                           0                          },
+    {WINED3D_SM1_OP_M4x3,     1, 3, WINED3DSIH_M4x3,         0,                           0                          },
+    {WINED3D_SM1_OP_M3x4,     1, 3, WINED3DSIH_M3x4,         0,                           0                          },
+    {WINED3D_SM1_OP_M3x3,     1, 3, WINED3DSIH_M3x3,         0,                           0                          },
+    {WINED3D_SM1_OP_M3x2,     1, 3, WINED3DSIH_M3x2,         0,                           0                          },
+    /* Register declarations */
+    {WINED3D_SM1_OP_DCL,      0, 2, WINED3DSIH_DCL,          0,                           0                          },
+    /* Flow control */
+    {WINED3D_SM1_OP_REP,      0, 1, WINED3DSIH_REP,          WINED3D_SHADER_VERSION(2,1), -1                         },
+    {WINED3D_SM1_OP_ENDREP,   0, 0, WINED3DSIH_ENDREP,       WINED3D_SHADER_VERSION(2,1), -1                         },
+    {WINED3D_SM1_OP_IF,       0, 1, WINED3DSIH_IF,           WINED3D_SHADER_VERSION(2,1), -1                         },
+    {WINED3D_SM1_OP_IFC,      0, 2, WINED3DSIH_IFC,          WINED3D_SHADER_VERSION(2,1), -1                         },
+    {WINED3D_SM1_OP_ELSE,     0, 0, WINED3DSIH_ELSE,         WINED3D_SHADER_VERSION(2,1), -1                         },
+    {WINED3D_SM1_OP_ENDIF,    0, 0, WINED3DSIH_ENDIF,        WINED3D_SHADER_VERSION(2,1), -1                         },
+    {WINED3D_SM1_OP_BREAK,    0, 0, WINED3DSIH_BREAK,        WINED3D_SHADER_VERSION(2,1), -1                         },
+    {WINED3D_SM1_OP_BREAKC,   0, 2, WINED3DSIH_BREAKC,       WINED3D_SHADER_VERSION(2,1), -1                         },
+    {WINED3D_SM1_OP_BREAKP,   0, 1, WINED3DSIH_BREAKP,       0,                           0                          },
+    {WINED3D_SM1_OP_CALL,     0, 1, WINED3DSIH_CALL,         WINED3D_SHADER_VERSION(2,1), -1                         },
+    {WINED3D_SM1_OP_CALLNZ,   0, 2, WINED3DSIH_CALLNZ,       WINED3D_SHADER_VERSION(2,1), -1                         },
+    {WINED3D_SM1_OP_LOOP,     0, 2, WINED3DSIH_LOOP,         WINED3D_SHADER_VERSION(3,0), -1                         },
+    {WINED3D_SM1_OP_RET,      0, 0, WINED3DSIH_RET,          WINED3D_SHADER_VERSION(2,1), -1                         },
+    {WINED3D_SM1_OP_ENDLOOP,  0, 0, WINED3DSIH_ENDLOOP,      WINED3D_SHADER_VERSION(3,0), -1                         },
+    {WINED3D_SM1_OP_LABEL,    0, 1, WINED3DSIH_LABEL,        WINED3D_SHADER_VERSION(2,1), -1                         },
+    /* Constant definitions */
+    {WINED3D_SM1_OP_DEF,      1, 5, WINED3DSIH_DEF,          0,                           0                          },
+    {WINED3D_SM1_OP_DEFB,     1, 2, WINED3DSIH_DEFB,         0,                           0                          },
+    {WINED3D_SM1_OP_DEFI,     1, 5, WINED3DSIH_DEFI,         0,                           0                          },
+    /* Texture */
+    {WINED3D_SM1_OP_TEXCOORD, 1, 1, WINED3DSIH_TEXCOORD,     0,                           WINED3D_SHADER_VERSION(1,3)},
+    {WINED3D_SM1_OP_TEXCOORD, 1, 2, WINED3DSIH_TEXCOORD,     WINED3D_SHADER_VERSION(1,4), WINED3D_SHADER_VERSION(1,4)},
+    {WINED3D_SM1_OP_TEXKILL,  1, 1, WINED3DSIH_TEXKILL,      WINED3D_SHADER_VERSION(1,0), WINED3D_SHADER_VERSION(3,0)},
+    {WINED3D_SM1_OP_TEX,      1, 1, WINED3DSIH_TEX,          0,                           WINED3D_SHADER_VERSION(1,3)},
+    {WINED3D_SM1_OP_TEX,      1, 2, WINED3DSIH_TEX,          WINED3D_SHADER_VERSION(1,4), WINED3D_SHADER_VERSION(1,4)},
+    {WINED3D_SM1_OP_TEX,      1, 3, WINED3DSIH_TEX,          WINED3D_SHADER_VERSION(2,0), -1                         },
+    {WINED3D_SM1_OP_TEXBEM,   1, 2, WINED3DSIH_TEXBEM,       0,                           WINED3D_SHADER_VERSION(1,3)},
+    {WINED3D_SM1_OP_TEXBEML,  1, 2, WINED3DSIH_TEXBEML,      WINED3D_SHADER_VERSION(1,0), WINED3D_SHADER_VERSION(1,3)},
+    {WINED3D_SM1_OP_TEXREG2AR,      1, 2, WINED3DSIH_TEXREG2AR,    WINED3D_SHADER_VERSION(1,0), WINED3D_SHADER_VERSION(1,3)},
+    {WINED3D_SM1_OP_TEXREG2GB,      1, 2, WINED3DSIH_TEXREG2GB,    WINED3D_SHADER_VERSION(1,0), WINED3D_SHADER_VERSION(1,3)},
+    {WINED3D_SM1_OP_TEXREG2RGB,     1, 2, WINED3DSIH_TEXREG2RGB,   WINED3D_SHADER_VERSION(1,2), WINED3D_SHADER_VERSION(1,3)},
+    {WINED3D_SM1_OP_TEXM3x2PAD,     1, 2, WINED3DSIH_TEXM3x2PAD,   WINED3D_SHADER_VERSION(1,0), WINED3D_SHADER_VERSION(1,3)},
+    {WINED3D_SM1_OP_TEXM3x2TEX,     1, 2, WINED3DSIH_TEXM3x2TEX,   WINED3D_SHADER_VERSION(1,0), WINED3D_SHADER_VERSION(1,3)},
+    {WINED3D_SM1_OP_TEXM3x3PAD,     1, 2, WINED3DSIH_TEXM3x3PAD,   WINED3D_SHADER_VERSION(1,0), WINED3D_SHADER_VERSION(1,3)},
+    {WINED3D_SM1_OP_TEXM3x3DIFF,    1, 2, WINED3DSIH_TEXM3x3DIFF,  WINED3D_SHADER_VERSION(0,0), WINED3D_SHADER_VERSION(0,0)},
+    {WINED3D_SM1_OP_TEXM3x3SPEC,    1, 3, WINED3DSIH_TEXM3x3SPEC,  WINED3D_SHADER_VERSION(1,0), WINED3D_SHADER_VERSION(1,3)},
+    {WINED3D_SM1_OP_TEXM3x3VSPEC,   1, 2, WINED3DSIH_TEXM3x3VSPEC, WINED3D_SHADER_VERSION(1,0), WINED3D_SHADER_VERSION(1,3)},
+    {WINED3D_SM1_OP_TEXM3x3TEX,     1, 2, WINED3DSIH_TEXM3x3TEX,   WINED3D_SHADER_VERSION(1,0), WINED3D_SHADER_VERSION(1,3)},
+    {WINED3D_SM1_OP_TEXDP3TEX,      1, 2, WINED3DSIH_TEXDP3TEX,    WINED3D_SHADER_VERSION(1,2), WINED3D_SHADER_VERSION(1,3)},
+    {WINED3D_SM1_OP_TEXM3x2DEPTH,   1, 2, WINED3DSIH_TEXM3x2DEPTH, WINED3D_SHADER_VERSION(1,3), WINED3D_SHADER_VERSION(1,3)},
+    {WINED3D_SM1_OP_TEXDP3,   1, 2, WINED3DSIH_TEXDP3,       WINED3D_SHADER_VERSION(1,2), WINED3D_SHADER_VERSION(1,3)},
+    {WINED3D_SM1_OP_TEXM3x3,  1, 2, WINED3DSIH_TEXM3x3,      WINED3D_SHADER_VERSION(1,2), WINED3D_SHADER_VERSION(1,3)},
+    {WINED3D_SM1_OP_TEXDEPTH, 1, 1, WINED3DSIH_TEXDEPTH,     WINED3D_SHADER_VERSION(1,4), WINED3D_SHADER_VERSION(1,4)},
+    {WINED3D_SM1_OP_BEM,      1, 3, WINED3DSIH_BEM,          WINED3D_SHADER_VERSION(1,4), WINED3D_SHADER_VERSION(1,4)},
+    {WINED3D_SM1_OP_DSX,      1, 2, WINED3DSIH_DSX,          WINED3D_SHADER_VERSION(2,1), -1                         },
+    {WINED3D_SM1_OP_DSY,      1, 2, WINED3DSIH_DSY,          WINED3D_SHADER_VERSION(2,1), -1                         },
+    {WINED3D_SM1_OP_TEXLDD,   1, 5, WINED3DSIH_TEXLDD,       WINED3D_SHADER_VERSION(2,1), -1                         },
+    {WINED3D_SM1_OP_SETP,     1, 3, WINED3DSIH_SETP,         0,                           0                          },
+    {WINED3D_SM1_OP_TEXLDL,   1, 3, WINED3DSIH_TEXLDL,       WINED3D_SHADER_VERSION(3,0), -1                         },
+    {WINED3D_SM1_OP_PHASE,    0, 0, WINED3DSIH_PHASE,        0,                           0                          },
+    {0,                       0, 0, WINED3DSIH_TABLE_SIZE,   0,                           0                          },
+};
+
+/* Read a parameter opcode from the input stream,
+ * and possibly a relative addressing token.
+ * Return the number of tokens read */
+static int shader_get_param(const struct wined3d_sm1_data *priv, const DWORD *ptr, DWORD *token, DWORD *addr_token)
+{
+    UINT count = 1;
+
+    *token = *ptr;
+
+    /* PS >= 3.0 have relative addressing (with token)
+     * VS >= 2.0 have relative addressing (with token)
+     * VS >= 1.0 < 2.0 have relative addressing (without token)
+     * The version check below should work in general */
+    if (*ptr & WINED3DSHADER_ADDRMODE_RELATIVE)
+    {
+        if (priv->shader_version.major < 2)
+        {
+            *addr_token = (1 << 31)
+                    | ((WINED3DSPR_ADDR << WINED3DSP_REGTYPE_SHIFT2) & WINED3DSP_REGTYPE_MASK2)
+                    | ((WINED3DSPR_ADDR << WINED3DSP_REGTYPE_SHIFT) & WINED3DSP_REGTYPE_MASK)
+                    | (WINED3DSP_NOSWIZZLE << WINED3DSP_SWIZZLE_SHIFT);
+        }
+        else
+        {
+            *addr_token = *(ptr + 1);
+            ++count;
+        }
+    }
+
+    return count;
+}
+
+static const struct wined3d_sm1_opcode_info *shader_get_opcode(const struct wined3d_sm1_data *priv, DWORD code)
+{
+    DWORD shader_version = WINED3D_SHADER_VERSION(priv->shader_version.major, priv->shader_version.minor);
+    const struct wined3d_sm1_opcode_info *opcode_table = priv->opcode_table;
+    DWORD i = 0;
+
+    while (opcode_table[i].handler_idx != WINED3DSIH_TABLE_SIZE)
+    {
+        if ((code & WINED3DSI_OPCODE_MASK) == opcode_table[i].opcode
+                && shader_version >= opcode_table[i].min_version
+                && (!opcode_table[i].max_version || shader_version <= opcode_table[i].max_version))
+        {
+            return &opcode_table[i];
+        }
+        ++i;
+    }
+
+    FIXME("Unsupported opcode %#x(%d) masked %#x, shader version %#x\n",
+            code, code, code & WINED3DSI_OPCODE_MASK, shader_version);
+
+    return NULL;
+}
+
+/* Return the number of parameters to skip for an opcode */
+static int shader_skip_opcode(const struct wined3d_sm1_data *priv,
+        const struct wined3d_sm1_opcode_info *opcode_info, DWORD opcode_token)
+{
+   /* Shaders >= 2.0 may contain address tokens, but fortunately they
+    * have a useful length mask - use it here. Shaders 1.0 contain no such tokens */
+    return (priv->shader_version.major >= 2)
+            ? ((opcode_token & WINED3DSI_INSTLENGTH_MASK) >> WINED3DSI_INSTLENGTH_SHIFT) : opcode_info->param_count;
+}
+
+static void shader_parse_src_param(DWORD param, const struct wined3d_shader_src_param *rel_addr,
+        struct wined3d_shader_src_param *src)
+{
+    src->reg.type = ((param & WINED3DSP_REGTYPE_MASK) >> WINED3DSP_REGTYPE_SHIFT)
+            | ((param & WINED3DSP_REGTYPE_MASK2) >> WINED3DSP_REGTYPE_SHIFT2);
+    src->reg.data_type = WINED3D_DATA_FLOAT;
+    src->reg.idx[0].offset = param & WINED3DSP_REGNUM_MASK;
+    src->reg.idx[0].rel_addr = rel_addr;
+    src->reg.idx[1].offset = ~0U;
+    src->reg.idx[1].rel_addr = NULL;
+    src->swizzle = (param & WINED3DSP_SWIZZLE_MASK) >> WINED3DSP_SWIZZLE_SHIFT;
+    src->modifiers = (param & WINED3DSP_SRCMOD_MASK) >> WINED3DSP_SRCMOD_SHIFT;
+}
+
+static void shader_parse_dst_param(DWORD param, const struct wined3d_shader_src_param *rel_addr,
+        struct wined3d_shader_dst_param *dst)
+{
+    dst->reg.type = ((param & WINED3DSP_REGTYPE_MASK) >> WINED3DSP_REGTYPE_SHIFT)
+            | ((param & WINED3DSP_REGTYPE_MASK2) >> WINED3DSP_REGTYPE_SHIFT2);
+    dst->reg.data_type = WINED3D_DATA_FLOAT;
+    dst->reg.idx[0].offset = param & WINED3DSP_REGNUM_MASK;
+    dst->reg.idx[0].rel_addr = rel_addr;
+    dst->reg.idx[1].offset = ~0U;
+    dst->reg.idx[1].rel_addr = NULL;
+    dst->write_mask = (param & WINED3D_SM1_WRITEMASK_MASK) >> WINED3D_SM1_WRITEMASK_SHIFT;
+    dst->modifiers = (param & WINED3DSP_DSTMOD_MASK) >> WINED3DSP_DSTMOD_SHIFT;
+    dst->shift = (param & WINED3DSP_DSTSHIFT_MASK) >> WINED3DSP_DSTSHIFT_SHIFT;
+}
+
+/* Read the parameters of an unrecognized opcode from the input stream
+ * Return the number of tokens read.
+ *
+ * Note: This function assumes source or destination token format.
+ * It will not work with specially-formatted tokens like DEF or DCL,
+ * but hopefully those would be recognized */
+static int shader_skip_unrecognized(const struct wined3d_sm1_data *priv, const DWORD *ptr)
+{
+    int tokens_read = 0;
+    int i = 0;
+
+    /* TODO: Think of a good name for 0x80000000 and replace it with a constant */
+    while (*ptr & 0x80000000)
+    {
+        DWORD token, addr_token = 0;
+        struct wined3d_shader_src_param rel_addr;
+
+        tokens_read += shader_get_param(priv, ptr, &token, &addr_token);
+        ptr += tokens_read;
+
+        FIXME("Unrecognized opcode param: token=0x%08x addr_token=0x%08x name=", token, addr_token);
+
+        if (token & WINED3DSHADER_ADDRMODE_RELATIVE) shader_parse_src_param(addr_token, NULL, &rel_addr);
+
+        if (!i)
+        {
+            struct wined3d_shader_dst_param dst;
+
+            shader_parse_dst_param(token, token & WINED3DSHADER_ADDRMODE_RELATIVE ? &rel_addr : NULL, &dst);
+            shader_dump_dst_param(&dst, &priv->shader_version);
+        }
+        else
+        {
+            struct wined3d_shader_src_param src;
+
+            shader_parse_src_param(token, token & WINED3DSHADER_ADDRMODE_RELATIVE ? &rel_addr : NULL, &src);
+            shader_dump_src_param(&src, &priv->shader_version);
+        }
+        FIXME("\n");
+        ++i;
+    }
+    return tokens_read;
+}
+
+static void *shader_sm1_init(const DWORD *byte_code, const struct wined3d_shader_signature *output_signature)
+{
+    struct wined3d_sm1_data *priv;
+    BYTE major, minor;
+
+    major = WINED3D_SM1_VERSION_MAJOR(*byte_code);
+    minor = WINED3D_SM1_VERSION_MINOR(*byte_code);
+    if (WINED3D_SHADER_VERSION(major, minor) > WINED3D_SHADER_VERSION(3, 0))
+    {
+        WARN("Invalid shader version %u.%u (%#x).\n", major, minor, *byte_code);
+        return NULL;
+    }
+
+    priv = HeapAlloc(GetProcessHeap(), 0, sizeof(*priv));
+    if (!priv)
+        return NULL;
+
+    if (output_signature)
+    {
+        FIXME("SM 1-3 shader shouldn't have output signatures.\n");
+    }
+
+    switch (*byte_code >> 16)
+    {
+        case WINED3D_SM1_VS:
+            priv->shader_version.type = WINED3D_SHADER_TYPE_VERTEX;
+            priv->opcode_table = vs_opcode_table;
+            break;
+
+        case WINED3D_SM1_PS:
+            priv->shader_version.type = WINED3D_SHADER_TYPE_PIXEL;
+            priv->opcode_table = ps_opcode_table;
+            break;
+
+        default:
+            FIXME("Unrecognized shader type %#x\n", *byte_code >> 16);
+            HeapFree(GetProcessHeap(), 0, priv);
+            return NULL;
+    }
+
+    return priv;
+}
+
+static void shader_sm1_free(void *data)
+{
+    HeapFree(GetProcessHeap(), 0, data);
+}
+
+static void shader_sm1_read_header(void *data, const DWORD **ptr, struct wined3d_shader_version *shader_version)
+{
+    struct wined3d_sm1_data *priv = data;
+    DWORD version_token;
+
+    version_token = *(*ptr)++;
+    TRACE("version: 0x%08x\n", version_token);
+
+    priv->shader_version.major = WINED3D_SM1_VERSION_MAJOR(version_token);
+    priv->shader_version.minor = WINED3D_SM1_VERSION_MINOR(version_token);
+    *shader_version = priv->shader_version;
+}
+
+static void shader_sm1_read_src_param(struct wined3d_sm1_data *priv, const DWORD **ptr,
+        struct wined3d_shader_src_param *src_param, struct wined3d_shader_src_param *src_rel_addr)
+{
+    DWORD token, addr_token;
+
+    *ptr += shader_get_param(priv, *ptr, &token, &addr_token);
+    if (token & WINED3DSHADER_ADDRMODE_RELATIVE)
+    {
+        shader_parse_src_param(addr_token, NULL, src_rel_addr);
+        shader_parse_src_param(token, src_rel_addr, src_param);
+    }
+    else
+    {
+        shader_parse_src_param(token, NULL, src_param);
+    }
+}
+
+static void shader_sm1_read_dst_param(struct wined3d_sm1_data *priv, const DWORD **ptr,
+        struct wined3d_shader_dst_param *dst_param, struct wined3d_shader_src_param *dst_rel_addr)
+{
+    DWORD token, addr_token;
+
+    *ptr += shader_get_param(priv, *ptr, &token, &addr_token);
+    if (token & WINED3DSHADER_ADDRMODE_RELATIVE)
+    {
+        shader_parse_src_param(addr_token, NULL, dst_rel_addr);
+        shader_parse_dst_param(token, dst_rel_addr, dst_param);
+    }
+    else
+    {
+        shader_parse_dst_param(token, NULL, dst_param);
+    }
+}
+
+static void shader_sm1_read_semantic(const DWORD **ptr, struct wined3d_shader_semantic *semantic)
+{
+    DWORD usage_token = *(*ptr)++;
+    DWORD dst_token = *(*ptr)++;
+
+    semantic->usage = (usage_token & WINED3DSP_DCL_USAGE_MASK) >> WINED3DSP_DCL_USAGE_SHIFT;
+    semantic->usage_idx = (usage_token & WINED3DSP_DCL_USAGEINDEX_MASK) >> WINED3DSP_DCL_USAGEINDEX_SHIFT;
+    semantic->sampler_type = (usage_token & WINED3DSP_TEXTURETYPE_MASK) >> WINED3DSP_TEXTURETYPE_SHIFT;
+    shader_parse_dst_param(dst_token, NULL, &semantic->reg);
+}
+
+static void shader_sm1_read_immconst(const DWORD **ptr, struct wined3d_shader_src_param *src_param,
+        enum wined3d_immconst_type type, enum wined3d_data_type data_type)
+{
+    UINT count = type == WINED3D_IMMCONST_VEC4 ? 4 : 1;
+    src_param->reg.type = WINED3DSPR_IMMCONST;
+    src_param->reg.data_type = data_type;
+    src_param->reg.idx[0].offset = ~0U;
+    src_param->reg.idx[0].rel_addr = NULL;
+    src_param->reg.idx[1].offset = ~0U;
+    src_param->reg.idx[1].rel_addr = NULL;
+    src_param->reg.immconst_type = type;
+    memcpy(src_param->reg.immconst_data, *ptr, count * sizeof(DWORD));
+    src_param->swizzle = WINED3DSP_NOSWIZZLE;
+    src_param->modifiers = 0;
+
+    *ptr += count;
+}
+
+static void shader_sm1_read_comment(const DWORD **ptr)
+{
+    DWORD token = **ptr;
+    const char *comment;
+    UINT size;
+
+    while ((token & WINED3DSI_OPCODE_MASK) == WINED3D_SM1_OP_COMMENT)
+    {
+        size = (token & WINED3DSI_COMMENTSIZE_MASK) >> WINED3DSI_COMMENTSIZE_SHIFT;
+        comment = (const char *)++(*ptr);
+        *ptr += size;
+
+        if (size > 1 && *(const DWORD *)comment == WINEMAKEFOURCC('T', 'E', 'X', 'T'))
+        {
+            const char *end = comment + size * sizeof(token);
+            const char *p = comment + sizeof(token);
+            const char *line = p;
+
+            TRACE("// TEXT\n");
+            while (p != end)
+            {
+                if (*p == '\n')
+                {
+                    UINT len = p - line;
+                    if (len && *(p - 1) == '\r') --len;
+                    TRACE("// %s\n", debugstr_an(line, len));
+                    line = ++p;
+                }
+                else ++p;
+            }
+            if (line != p)
+                TRACE("// %s\n", debugstr_an(line, p - line));
+        }
+        else if (size)
+            TRACE("// %s\n", debugstr_an(comment, size * sizeof(token)));
+        else
+            break;
+
+        token = **ptr;
+    }
+}
+
+static void shader_sm1_read_instruction(void *data, const DWORD **ptr, struct wined3d_shader_instruction *ins)
+{
+    const struct wined3d_sm1_opcode_info *opcode_info;
+    struct wined3d_sm1_data *priv = data;
+    DWORD opcode_token;
+    unsigned int i;
+    const DWORD *p;
+
+    shader_sm1_read_comment(ptr);
+
+    opcode_token = *(*ptr)++;
+    if (!(opcode_info = shader_get_opcode(priv, opcode_token)))
+    {
+        FIXME("Unrecognized opcode: token=0x%08x.\n", opcode_token);
+        ins->handler_idx = WINED3DSIH_TABLE_SIZE;
+        *ptr += shader_skip_unrecognized(priv, *ptr);
+        return;
+    }
+
+    ins->handler_idx = opcode_info->handler_idx;
+    ins->flags = (opcode_token & WINED3D_OPCODESPECIFICCONTROL_MASK) >> WINED3D_OPCODESPECIFICCONTROL_SHIFT;
+    ins->coissue = opcode_token & WINED3DSI_COISSUE;
+    ins->predicate = opcode_token & WINED3DSHADER_INSTRUCTION_PREDICATED ? &priv->pred_param : NULL;
+    ins->dst_count = opcode_info->dst_count ? 1 : 0;
+    ins->dst = &priv->dst_param;
+    ins->src_count = opcode_info->param_count - opcode_info->dst_count;
+    ins->src = priv->src_param;
+
+    p = *ptr;
+    *ptr += shader_skip_opcode(priv, opcode_info, opcode_token);
+
+    if (ins->handler_idx == WINED3DSIH_DCL)
+    {
+        shader_sm1_read_semantic(&p, &ins->declaration.semantic);
+    }
+    else if (ins->handler_idx == WINED3DSIH_DEF)
+    {
+        shader_sm1_read_dst_param(priv, &p, &priv->dst_param, &priv->dst_rel_addr);
+        shader_sm1_read_immconst(&p, &priv->src_param[0], WINED3D_IMMCONST_VEC4, WINED3D_DATA_FLOAT);
+    }
+    else if (ins->handler_idx == WINED3DSIH_DEFI)
+    {
+        shader_sm1_read_dst_param(priv, &p, &priv->dst_param, &priv->dst_rel_addr);
+        shader_sm1_read_immconst(&p, &priv->src_param[0], WINED3D_IMMCONST_VEC4, WINED3D_DATA_INT);
+    }
+    else if (ins->handler_idx == WINED3DSIH_DEFB)
+    {
+        shader_sm1_read_dst_param(priv, &p, &priv->dst_param, &priv->dst_rel_addr);
+        shader_sm1_read_immconst(&p, &priv->src_param[0], WINED3D_IMMCONST_SCALAR, WINED3D_DATA_UINT);
+    }
+    else
+    {
+        /* Destination token */
+        if (ins->dst_count)
+            shader_sm1_read_dst_param(priv, &p, &priv->dst_param, &priv->dst_rel_addr);
+
+        /* Predication token */
+        if (ins->predicate)
+            shader_sm1_read_src_param(priv, &p, &priv->pred_param, &priv->pred_rel_addr);
+
+        /* Other source tokens */
+        for (i = 0; i < ins->src_count; ++i)
+        {
+            shader_sm1_read_src_param(priv, &p, &priv->src_param[i], &priv->src_rel_addr[i]);
+        }
+    }
+}
+
+static BOOL shader_sm1_is_end(void *data, const DWORD **ptr)
+{
+    shader_sm1_read_comment(ptr);
+
+    if (**ptr == WINED3DSP_END)
+    {
+        ++(*ptr);
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+const struct wined3d_shader_frontend sm1_shader_frontend =
+{
+    shader_sm1_init,
+    shader_sm1_free,
+    shader_sm1_read_header,
+    shader_sm1_read_instruction,
+    shader_sm1_is_end,
+};
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/shader_sm4.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/shader_sm4.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/shader_sm4.c	(revision 46521)
@@ -0,0 +1,806 @@
+/*
+ * Copyright 2009 Henri Verbeet for CodeWeavers
+ *
+ * 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 "wined3d_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
+WINE_DECLARE_DEBUG_CHANNEL(d3d_bytecode);
+
+#define WINED3D_SM4_INSTRUCTION_MODIFIER        (1 << 31)
+
+#define WINED3D_SM4_INSTRUCTION_LENGTH_SHIFT    24
+#define WINED3D_SM4_INSTRUCTION_LENGTH_MASK     (0xf << WINED3D_SM4_INSTRUCTION_LENGTH_SHIFT)
+
+#define WINED3D_SM4_PRIMITIVE_TYPE_SHIFT        11
+#define WINED3D_SM4_PRIMITIVE_TYPE_MASK         (0x7 << WINED3D_SM4_PRIMITIVE_TYPE_SHIFT)
+
+#define WINED3D_SM4_INDEX_TYPE_SHIFT            11
+#define WINED3D_SM4_INDEX_TYPE_MASK             (0x1 << WINED3D_SM4_INDEX_TYPE_SHIFT)
+
+#define WINED3D_SM4_OPCODE_MASK                 0xff
+
+#define WINED3D_SM4_REGISTER_MODIFIER           (1 << 31)
+
+#define WINED3D_SM4_ADDRESSING_SHIFT1           25
+#define WINED3D_SM4_ADDRESSING_MASK1            (0x3 << WINED3D_SM4_ADDRESSING_SHIFT1)
+
+#define WINED3D_SM4_ADDRESSING_SHIFT0           22
+#define WINED3D_SM4_ADDRESSING_MASK0            (0x3 << WINED3D_SM4_ADDRESSING_SHIFT0)
+
+#define WINED3D_SM4_REGISTER_ORDER_SHIFT        20
+#define WINED3D_SM4_REGISTER_ORDER_MASK         (0x3 << WINED3D_SM4_REGISTER_ORDER_SHIFT)
+
+#define WINED3D_SM4_REGISTER_TYPE_SHIFT         12
+#define WINED3D_SM4_REGISTER_TYPE_MASK          (0xf << WINED3D_SM4_REGISTER_TYPE_SHIFT)
+
+#define WINED3D_SM4_SWIZZLE_TYPE_SHIFT          2
+#define WINED3D_SM4_SWIZZLE_TYPE_MASK           (0x3 << WINED3D_SM4_SWIZZLE_TYPE_SHIFT)
+
+#define WINED3D_SM4_IMMCONST_TYPE_SHIFT         0
+#define WINED3D_SM4_IMMCONST_TYPE_MASK          (0x3 << WINED3D_SM4_IMMCONST_TYPE_SHIFT)
+
+#define WINED3D_SM4_WRITEMASK_SHIFT             4
+#define WINED3D_SM4_WRITEMASK_MASK              (0xf << WINED3D_SM4_WRITEMASK_SHIFT)
+
+#define WINED3D_SM4_SWIZZLE_SHIFT               4
+#define WINED3D_SM4_SWIZZLE_MASK                (0xff << WINED3D_SM4_SWIZZLE_SHIFT)
+
+#define WINED3D_SM4_VERSION_MAJOR(version)      (((version) >> 4) & 0xf)
+#define WINED3D_SM4_VERSION_MINOR(version)      (((version) >> 0) & 0xf)
+
+#define WINED3D_SM4_ADDRESSING_RELATIVE         0x2
+#define WINED3D_SM4_ADDRESSING_OFFSET           0x1
+
+enum wined3d_sm4_opcode
+{
+    WINED3D_SM4_OP_ADD                  = 0x00,
+    WINED3D_SM4_OP_AND                  = 0x01,
+    WINED3D_SM4_OP_BREAK                = 0x02,
+    WINED3D_SM4_OP_BREAKC               = 0x03,
+    WINED3D_SM4_OP_CUT                  = 0x09,
+    WINED3D_SM4_OP_DERIV_RTX            = 0x0b,
+    WINED3D_SM4_OP_DERIV_RTY            = 0x0c,
+    WINED3D_SM4_OP_DIV                  = 0x0e,
+    WINED3D_SM4_OP_DP3                  = 0x10,
+    WINED3D_SM4_OP_DP4                  = 0x11,
+    WINED3D_SM4_OP_EMIT                 = 0x13,
+    WINED3D_SM4_OP_ENDIF                = 0x15,
+    WINED3D_SM4_OP_ENDLOOP              = 0x16,
+    WINED3D_SM4_OP_EQ                   = 0x18,
+    WINED3D_SM4_OP_EXP                  = 0x19,
+    WINED3D_SM4_OP_FRC                  = 0x1a,
+    WINED3D_SM4_OP_FTOI                 = 0x1b,
+    WINED3D_SM4_OP_GE                   = 0x1d,
+    WINED3D_SM4_OP_IADD                 = 0x1e,
+    WINED3D_SM4_OP_IF                   = 0x1f,
+    WINED3D_SM4_OP_IEQ                  = 0x20,
+    WINED3D_SM4_OP_IGE                  = 0x21,
+    WINED3D_SM4_OP_IMUL                 = 0x26,
+    WINED3D_SM4_OP_ITOF                 = 0x2b,
+    WINED3D_SM4_OP_LD                   = 0x2d,
+    WINED3D_SM4_OP_LOG                  = 0x2f,
+    WINED3D_SM4_OP_LOOP                 = 0x30,
+    WINED3D_SM4_OP_LT                   = 0x31,
+    WINED3D_SM4_OP_MAD                  = 0x32,
+    WINED3D_SM4_OP_MIN                  = 0x33,
+    WINED3D_SM4_OP_MAX                  = 0x34,
+    WINED3D_SM4_OP_MOV                  = 0x36,
+    WINED3D_SM4_OP_MOVC                 = 0x37,
+    WINED3D_SM4_OP_MUL                  = 0x38,
+    WINED3D_SM4_OP_RET                  = 0x3e,
+    WINED3D_SM4_OP_ROUND_NI             = 0x41,
+    WINED3D_SM4_OP_RSQ                  = 0x44,
+    WINED3D_SM4_OP_SAMPLE               = 0x45,
+    WINED3D_SM4_OP_SAMPLE_LOD           = 0x48,
+    WINED3D_SM4_OP_SAMPLE_GRAD          = 0x49,
+    WINED3D_SM4_OP_SQRT                 = 0x4b,
+    WINED3D_SM4_OP_SINCOS               = 0x4d,
+    WINED3D_SM4_OP_UDIV                 = 0x4e,
+    WINED3D_SM4_OP_USHR                 = 0x55,
+    WINED3D_SM4_OP_UTOF                 = 0x56,
+    WINED3D_SM4_OP_XOR                  = 0x57,
+    WINED3D_SM4_OP_DCL_CONSTANT_BUFFER  = 0x59,
+    WINED3D_SM4_OP_DCL_OUTPUT_TOPOLOGY  = 0x5c,
+    WINED3D_SM4_OP_DCL_INPUT_PRIMITIVE  = 0x5d,
+    WINED3D_SM4_OP_DCL_VERTICES_OUT     = 0x5e,
+};
+
+enum wined3d_sm4_register_type
+{
+    WINED3D_SM4_RT_TEMP         = 0x0,
+    WINED3D_SM4_RT_INPUT        = 0x1,
+    WINED3D_SM4_RT_OUTPUT       = 0x2,
+    WINED3D_SM4_RT_IMMCONST     = 0x4,
+    WINED3D_SM4_RT_SAMPLER      = 0x6,
+    WINED3D_SM4_RT_CONSTBUFFER  = 0x8,
+    WINED3D_SM4_RT_PRIMID       = 0xb,
+    WINED3D_SM4_RT_NULL         = 0xd,
+};
+
+enum wined3d_sm4_output_primitive_type
+{
+    WINED3D_SM4_OUTPUT_PT_POINTLIST     = 0x1,
+    WINED3D_SM4_OUTPUT_PT_LINELIST      = 0x3,
+    WINED3D_SM4_OUTPUT_PT_TRIANGLESTRIP = 0x5,
+};
+
+enum wined3d_sm4_input_primitive_type
+{
+    WINED3D_SM4_INPUT_PT_POINT          = 0x1,
+    WINED3D_SM4_INPUT_PT_LINE           = 0x2,
+    WINED3D_SM4_INPUT_PT_TRIANGLE       = 0x3,
+    WINED3D_SM4_INPUT_PT_LINEADJ        = 0x6,
+    WINED3D_SM4_INPUT_PT_TRIANGLEADJ    = 0x7,
+};
+
+enum wined3d_sm4_swizzle_type
+{
+    WINED3D_SM4_SWIZZLE_VEC4            = 0x1,
+    WINED3D_SM4_SWIZZLE_SCALAR          = 0x2,
+};
+
+enum wined3d_sm4_immconst_type
+{
+    WINED3D_SM4_IMMCONST_SCALAR = 0x1,
+    WINED3D_SM4_IMMCONST_VEC4   = 0x2,
+};
+
+struct wined3d_shader_src_param_entry
+{
+    struct list entry;
+    struct wined3d_shader_src_param param;
+};
+
+struct wined3d_sm4_data
+{
+    struct wined3d_shader_version shader_version;
+    const DWORD *end;
+    const struct wined3d_shader_signature *output_signature;
+
+    struct wined3d_shader_src_param src_param[5];
+    struct wined3d_shader_dst_param dst_param[2];
+    struct list src_free;
+    struct list src;
+};
+
+struct wined3d_sm4_opcode_info
+{
+    enum wined3d_sm4_opcode opcode;
+    enum WINED3D_SHADER_INSTRUCTION_HANDLER handler_idx;
+    const char *dst_info;
+    const char *src_info;
+};
+
+struct sysval_map
+{
+    enum wined3d_sysval_semantic sysval;
+    enum wined3d_shader_register_type register_type;
+    UINT register_idx;
+};
+
+/*
+ * F -> WINED3D_DATA_FLOAT
+ * I -> WINED3D_DATA_INT
+ * R -> WINED3D_DATA_RESOURCE
+ * S -> WINED3D_DATA_SAMPLER
+ * U -> WINED3D_DATA_UINT
+ */
+static const struct wined3d_sm4_opcode_info opcode_table[] =
+{
+    {WINED3D_SM4_OP_ADD,                    WINED3DSIH_ADD,                 "F",    "FF"},
+    {WINED3D_SM4_OP_AND,                    WINED3DSIH_AND,                 "U",    "UU"},
+    {WINED3D_SM4_OP_BREAK,                  WINED3DSIH_BREAK,               "",     ""},
+    {WINED3D_SM4_OP_BREAKC,                 WINED3DSIH_BREAKP,              "",     "U"},
+    {WINED3D_SM4_OP_CUT,                    WINED3DSIH_CUT,                 "",     ""},
+    {WINED3D_SM4_OP_DERIV_RTX,              WINED3DSIH_DSX,                 "F",    "F"},
+    {WINED3D_SM4_OP_DERIV_RTY,              WINED3DSIH_DSY,                 "F",    "F"},
+    {WINED3D_SM4_OP_DIV,                    WINED3DSIH_DIV,                 "F",    "FF"},
+    {WINED3D_SM4_OP_DP3,                    WINED3DSIH_DP3,                 "F",    "FF"},
+    {WINED3D_SM4_OP_DP4,                    WINED3DSIH_DP4,                 "F",    "FF"},
+    {WINED3D_SM4_OP_EMIT,                   WINED3DSIH_EMIT,                "",     ""},
+    {WINED3D_SM4_OP_ENDIF,                  WINED3DSIH_ENDIF,               "",     ""},
+    {WINED3D_SM4_OP_ENDLOOP,                WINED3DSIH_ENDLOOP,             "",     ""},
+    {WINED3D_SM4_OP_EQ,                     WINED3DSIH_EQ,                  "U",    "FF"},
+    {WINED3D_SM4_OP_EXP,                    WINED3DSIH_EXP,                 "F",    "F"},
+    {WINED3D_SM4_OP_FRC,                    WINED3DSIH_FRC,                 "F",    "F"},
+    {WINED3D_SM4_OP_FTOI,                   WINED3DSIH_FTOI,                "I",    "F"},
+    {WINED3D_SM4_OP_GE,                     WINED3DSIH_GE,                  "U",    "FF"},
+    {WINED3D_SM4_OP_IADD,                   WINED3DSIH_IADD,                "I",    "II"},
+    {WINED3D_SM4_OP_IF,                     WINED3DSIH_IF,                  "",     "U"},
+    {WINED3D_SM4_OP_IEQ,                    WINED3DSIH_IEQ,                 "U",    "II"},
+    {WINED3D_SM4_OP_IGE,                    WINED3DSIH_IGE,                 "U",    "II"},
+    {WINED3D_SM4_OP_IMUL,                   WINED3DSIH_IMUL,                "II",   "II"},
+    {WINED3D_SM4_OP_ITOF,                   WINED3DSIH_ITOF,                "F",    "I"},
+    {WINED3D_SM4_OP_LD,                     WINED3DSIH_LD,                  "U",    "FR"},
+    {WINED3D_SM4_OP_LOG,                    WINED3DSIH_LOG,                 "F",    "F"},
+    {WINED3D_SM4_OP_LOOP,                   WINED3DSIH_LOOP,                "",     ""},
+    {WINED3D_SM4_OP_LT,                     WINED3DSIH_LT,                  "U",    "FF"},
+    {WINED3D_SM4_OP_MAD,                    WINED3DSIH_MAD,                 "F",    "FFF"},
+    {WINED3D_SM4_OP_MIN,                    WINED3DSIH_MIN,                 "F",    "FF"},
+    {WINED3D_SM4_OP_MAX,                    WINED3DSIH_MAX,                 "F",    "FF"},
+    {WINED3D_SM4_OP_MOV,                    WINED3DSIH_MOV,                 "F",    "F"},
+    {WINED3D_SM4_OP_MOVC,                   WINED3DSIH_MOVC,                "F",    "UFF"},
+    {WINED3D_SM4_OP_MUL,                    WINED3DSIH_MUL,                 "F",    "FF"},
+    {WINED3D_SM4_OP_RET,                    WINED3DSIH_RET,                 "",     ""},
+    {WINED3D_SM4_OP_ROUND_NI,               WINED3DSIH_ROUND_NI,            "F",    "F"},
+    {WINED3D_SM4_OP_RSQ,                    WINED3DSIH_RSQ,                 "F",    "F"},
+    {WINED3D_SM4_OP_SAMPLE,                 WINED3DSIH_SAMPLE,              "U",    "FRS"},
+    {WINED3D_SM4_OP_SAMPLE_LOD,             WINED3DSIH_SAMPLE_LOD,          "U",    "FRSF"},
+    {WINED3D_SM4_OP_SAMPLE_GRAD,            WINED3DSIH_SAMPLE_GRAD,         "U",    "FRSFF"},
+    {WINED3D_SM4_OP_SQRT,                   WINED3DSIH_SQRT,                "F",    "F"},
+    {WINED3D_SM4_OP_SINCOS,                 WINED3DSIH_SINCOS,              "FF",   "F"},
+    {WINED3D_SM4_OP_UDIV,                   WINED3DSIH_UDIV,                "UU",   "UU"},
+    {WINED3D_SM4_OP_USHR,                   WINED3DSIH_USHR,                "U",    "UU"},
+    {WINED3D_SM4_OP_UTOF,                   WINED3DSIH_UTOF,                "F",    "U"},
+    {WINED3D_SM4_OP_XOR,                    WINED3DSIH_XOR,                 "U",    "UU"},
+    {WINED3D_SM4_OP_DCL_CONSTANT_BUFFER,    WINED3DSIH_DCL_CONSTANT_BUFFER, "",     ""},
+    {WINED3D_SM4_OP_DCL_OUTPUT_TOPOLOGY,    WINED3DSIH_DCL_OUTPUT_TOPOLOGY, "",     ""},
+    {WINED3D_SM4_OP_DCL_INPUT_PRIMITIVE,    WINED3DSIH_DCL_INPUT_PRIMITIVE, "",     ""},
+    {WINED3D_SM4_OP_DCL_VERTICES_OUT,       WINED3DSIH_DCL_VERTICES_OUT,    "",     ""},
+};
+
+static const enum wined3d_shader_register_type register_type_table[] =
+{
+    /* WINED3D_SM4_RT_TEMP */           WINED3DSPR_TEMP,
+    /* WINED3D_SM4_RT_INPUT */          WINED3DSPR_INPUT,
+    /* WINED3D_SM4_RT_OUTPUT */         WINED3DSPR_OUTPUT,
+    /* UNKNOWN */                       0,
+    /* WINED3D_SM4_RT_IMMCONST */       WINED3DSPR_IMMCONST,
+    /* UNKNOWN */                       0,
+    /* WINED3D_SM4_RT_SAMPLER */        WINED3DSPR_SAMPLER,
+    /* WINED3D_SM4_RT_RESOURCE */       WINED3DSPR_RESOURCE,
+    /* WINED3D_SM4_RT_CONSTBUFFER */    WINED3DSPR_CONSTBUFFER,
+    /* UNKNOWN */                       0,
+    /* UNKNOWN */                       0,
+    /* WINED3D_SM4_RT_PRIMID */         WINED3DSPR_PRIMID,
+    /* UNKNOWN */                       0,
+    /* WINED3D_SM4_RT_NULL */           WINED3DSPR_NULL,
+};
+
+static const enum wined3d_primitive_type output_primitive_type_table[] =
+{
+    /* UNKNOWN */                               WINED3D_PT_UNDEFINED,
+    /* WINED3D_SM4_OUTPUT_PT_POINTLIST */       WINED3D_PT_POINTLIST,
+    /* UNKNOWN */                               WINED3D_PT_UNDEFINED,
+    /* WINED3D_SM4_OUTPUT_PT_LINELIST */        WINED3D_PT_LINELIST,
+    /* UNKNOWN */                               WINED3D_PT_UNDEFINED,
+    /* WINED3D_SM4_OUTPUT_PT_TRIANGLESTRIP */   WINED3D_PT_TRIANGLESTRIP,
+};
+
+static const enum wined3d_primitive_type input_primitive_type_table[] =
+{
+    /* UNKNOWN */                               WINED3D_PT_UNDEFINED,
+    /* WINED3D_SM4_INPUT_PT_POINT */            WINED3D_PT_POINTLIST,
+    /* WINED3D_SM4_INPUT_PT_LINE */             WINED3D_PT_LINELIST,
+    /* WINED3D_SM4_INPUT_PT_TRIANGLE */         WINED3D_PT_TRIANGLELIST,
+    /* UNKNOWN */                               WINED3D_PT_UNDEFINED,
+    /* UNKNOWN */                               WINED3D_PT_UNDEFINED,
+    /* WINED3D_SM4_INPUT_PT_LINEADJ */          WINED3D_PT_LINELIST_ADJ,
+    /* WINED3D_SM4_INPUT_PT_TRIANGLEADJ */      WINED3D_PT_TRIANGLELIST_ADJ,
+};
+
+static const struct sysval_map sysval_map[] =
+{
+    {WINED3D_SV_DEPTH,      WINED3DSPR_DEPTHOUT,    0},
+    {WINED3D_SV_TARGET0,    WINED3DSPR_COLOROUT,    0},
+    {WINED3D_SV_TARGET1,    WINED3DSPR_COLOROUT,    1},
+    {WINED3D_SV_TARGET2,    WINED3DSPR_COLOROUT,    2},
+    {WINED3D_SV_TARGET3,    WINED3DSPR_COLOROUT,    3},
+    {WINED3D_SV_TARGET4,    WINED3DSPR_COLOROUT,    4},
+    {WINED3D_SV_TARGET5,    WINED3DSPR_COLOROUT,    5},
+    {WINED3D_SV_TARGET6,    WINED3DSPR_COLOROUT,    6},
+    {WINED3D_SV_TARGET7,    WINED3DSPR_COLOROUT,    7},
+};
+
+static BOOL shader_sm4_read_src_param(struct wined3d_sm4_data *priv, const DWORD **ptr,
+        enum wined3d_data_type data_type, struct wined3d_shader_src_param *src_param);
+
+static const struct wined3d_sm4_opcode_info *get_opcode_info(enum wined3d_sm4_opcode opcode)
+{
+    unsigned int i;
+
+    for (i = 0; i < sizeof(opcode_table) / sizeof(*opcode_table); ++i)
+    {
+        if (opcode == opcode_table[i].opcode) return &opcode_table[i];
+    }
+
+    return NULL;
+}
+
+static void map_sysval(enum wined3d_sysval_semantic sysval, struct wined3d_shader_register *reg)
+{
+    unsigned int i;
+
+    for (i = 0; i < sizeof(sysval_map) / sizeof(*sysval_map); ++i)
+    {
+        if (sysval == sysval_map[i].sysval)
+        {
+            reg->type = sysval_map[i].register_type;
+            reg->idx[0].offset = sysval_map[i].register_idx;
+        }
+    }
+}
+
+static void map_register(const struct wined3d_sm4_data *priv, struct wined3d_shader_register *reg)
+{
+    switch (priv->shader_version.type)
+    {
+        case WINED3D_SHADER_TYPE_PIXEL:
+            if (reg->type == WINED3DSPR_OUTPUT)
+            {
+                unsigned int i;
+                const struct wined3d_shader_signature *s = priv->output_signature;
+
+                if (!s)
+                {
+                    ERR("Shader has no output signature, unable to map register.\n");
+                    break;
+                }
+
+                for (i = 0; i < s->element_count; ++i)
+                {
+                    if (s->elements[i].register_idx == reg->idx[0].offset)
+                    {
+                        map_sysval(s->elements[i].sysval_semantic, reg);
+                        break;
+                    }
+                }
+            }
+            break;
+
+        default:
+            break;
+    }
+}
+
+static enum wined3d_data_type map_data_type(char t)
+{
+    switch (t)
+    {
+        case 'F':
+            return WINED3D_DATA_FLOAT;
+        case 'I':
+            return WINED3D_DATA_INT;
+        case 'R':
+            return WINED3D_DATA_RESOURCE;
+        case 'S':
+            return WINED3D_DATA_SAMPLER;
+        case 'U':
+            return WINED3D_DATA_UINT;
+        default:
+            ERR("Invalid data type '%c'.\n", t);
+            return WINED3D_DATA_FLOAT;
+    }
+}
+
+static void *shader_sm4_init(const DWORD *byte_code, const struct wined3d_shader_signature *output_signature)
+{
+    struct wined3d_sm4_data *priv = HeapAlloc(GetProcessHeap(), 0, sizeof(*priv));
+    if (!priv)
+    {
+        ERR("Failed to allocate private data\n");
+        return NULL;
+    }
+
+    priv->output_signature = output_signature;
+    list_init(&priv->src_free);
+    list_init(&priv->src);
+
+    return priv;
+}
+
+static void shader_sm4_free(void *data)
+{
+    struct wined3d_shader_src_param_entry *e1, *e2;
+    struct wined3d_sm4_data *priv = data;
+
+    list_move_head(&priv->src_free, &priv->src);
+    LIST_FOR_EACH_ENTRY_SAFE(e1, e2, &priv->src_free, struct wined3d_shader_src_param_entry, entry)
+    {
+        HeapFree(GetProcessHeap(), 0, e1);
+    }
+    HeapFree(GetProcessHeap(), 0, priv);
+}
+
+static struct wined3d_shader_src_param *get_src_param(struct wined3d_sm4_data *priv)
+{
+    struct wined3d_shader_src_param_entry *e;
+    struct list *elem;
+
+    if (!list_empty(&priv->src_free))
+    {
+        elem = list_head(&priv->src_free);
+        list_remove(elem);
+    }
+    else
+    {
+        if (!(e = HeapAlloc(GetProcessHeap(), 0, sizeof(*e))))
+            return NULL;
+        elem = &e->entry;
+    }
+
+    list_add_tail(&priv->src, elem);
+    e = LIST_ENTRY(elem, struct wined3d_shader_src_param_entry, entry);
+    return &e->param;
+}
+
+static void shader_sm4_read_header(void *data, const DWORD **ptr, struct wined3d_shader_version *shader_version)
+{
+    struct wined3d_sm4_data *priv = data;
+    DWORD version_token;
+
+    priv->end = *ptr;
+
+    version_token = *(*ptr)++;
+    TRACE("version: 0x%08x\n", version_token);
+
+    TRACE("token count: %u\n", **ptr);
+    priv->end += *(*ptr)++;
+
+    switch (version_token >> 16)
+    {
+        case WINED3D_SM4_PS:
+            priv->shader_version.type = WINED3D_SHADER_TYPE_PIXEL;
+            break;
+
+        case WINED3D_SM4_VS:
+            priv->shader_version.type = WINED3D_SHADER_TYPE_VERTEX;
+            break;
+
+        case WINED3D_SM4_GS:
+            priv->shader_version.type = WINED3D_SHADER_TYPE_GEOMETRY;
+            break;
+
+        default:
+            FIXME("Unrecognized shader type %#x\n", version_token >> 16);
+    }
+    priv->shader_version.major = WINED3D_SM4_VERSION_MAJOR(version_token);
+    priv->shader_version.minor = WINED3D_SM4_VERSION_MINOR(version_token);
+
+    *shader_version = priv->shader_version;
+}
+
+static BOOL shader_sm4_read_reg_idx(struct wined3d_sm4_data *priv, const DWORD **ptr,
+        DWORD addressing, struct wined3d_shader_register_index *reg_idx)
+{
+    if (addressing & WINED3D_SM4_ADDRESSING_RELATIVE)
+    {
+        struct wined3d_shader_src_param *rel_addr = get_src_param(priv);
+
+        if (!(reg_idx->rel_addr = rel_addr))
+        {
+            ERR("Failed to get src param for relative addressing.\n");
+            return FALSE;
+        }
+
+        if (addressing & WINED3D_SM4_ADDRESSING_OFFSET)
+            reg_idx->offset = *(*ptr)++;
+        else
+            reg_idx->offset = 0;
+        shader_sm4_read_src_param(priv, ptr, WINED3D_DATA_INT, rel_addr);
+    }
+    else
+    {
+        reg_idx->rel_addr = NULL;
+        reg_idx->offset = *(*ptr)++;
+    }
+
+    return TRUE;
+}
+
+static BOOL shader_sm4_read_param(struct wined3d_sm4_data *priv, const DWORD **ptr,
+        enum wined3d_data_type data_type, struct wined3d_shader_register *param,
+        enum wined3d_shader_src_modifier *modifier)
+{
+    enum wined3d_sm4_register_type register_type;
+    DWORD token = *(*ptr)++;
+    DWORD order;
+
+    register_type = (token & WINED3D_SM4_REGISTER_TYPE_MASK) >> WINED3D_SM4_REGISTER_TYPE_SHIFT;
+    if (register_type >= sizeof(register_type_table) / sizeof(*register_type_table))
+    {
+        FIXME("Unhandled register type %#x.\n", register_type);
+        param->type = WINED3DSPR_TEMP;
+    }
+    else
+    {
+        param->type = register_type_table[register_type];
+    }
+    param->data_type = data_type;
+
+    if (token & WINED3D_SM4_REGISTER_MODIFIER)
+    {
+        DWORD m = *(*ptr)++;
+
+        /* FIXME: This will probably break down at some point. The SM4
+         * modifiers look like flags, while wined3d currently has an enum
+         * with possible combinations, e.g. WINED3DSPSM_ABSNEG. */
+        switch (m)
+        {
+            case 0x41:
+                *modifier = WINED3DSPSM_NEG;
+                break;
+
+            case 0x81:
+                *modifier = WINED3DSPSM_ABS;
+                break;
+
+            default:
+                FIXME("Skipping modifier 0x%08x.\n", m);
+                *modifier = WINED3DSPSM_NONE;
+                break;
+        }
+    }
+    else
+    {
+        *modifier = WINED3DSPSM_NONE;
+    }
+
+    order = (token & WINED3D_SM4_REGISTER_ORDER_MASK) >> WINED3D_SM4_REGISTER_ORDER_SHIFT;
+
+    if (order < 1)
+        param->idx[0].offset = ~0U;
+    else
+    {
+        DWORD addressing = (token & WINED3D_SM4_ADDRESSING_MASK0) >> WINED3D_SM4_ADDRESSING_SHIFT0;
+        if (!(shader_sm4_read_reg_idx(priv, ptr, addressing, &param->idx[0])))
+        {
+            ERR("Failed to read register index.\n");
+            return FALSE;
+        }
+    }
+
+    if (order < 2)
+        param->idx[1].offset = ~0U;
+    else
+    {
+        DWORD addressing = (token & WINED3D_SM4_ADDRESSING_MASK1) >> WINED3D_SM4_ADDRESSING_SHIFT1;
+        if (!(shader_sm4_read_reg_idx(priv, ptr, addressing, &param->idx[1])))
+        {
+            ERR("Failed to read register index.\n");
+            return FALSE;
+        }
+    }
+
+    if (order > 2)
+        FIXME("Unhandled order %u.\n", order);
+
+    if (register_type == WINED3D_SM4_RT_IMMCONST)
+    {
+        enum wined3d_sm4_immconst_type immconst_type =
+                (token & WINED3D_SM4_IMMCONST_TYPE_MASK) >> WINED3D_SM4_IMMCONST_TYPE_SHIFT;
+
+        switch (immconst_type)
+        {
+            case WINED3D_SM4_IMMCONST_SCALAR:
+                param->immconst_type = WINED3D_IMMCONST_SCALAR;
+                memcpy(param->immconst_data, *ptr, 1 * sizeof(DWORD));
+                *ptr += 1;
+                break;
+
+            case WINED3D_SM4_IMMCONST_VEC4:
+                param->immconst_type = WINED3D_IMMCONST_VEC4;
+                memcpy(param->immconst_data, *ptr, 4 * sizeof(DWORD));
+                *ptr += 4;
+                break;
+
+            default:
+                FIXME("Unhandled immediate constant type %#x.\n", immconst_type);
+                break;
+        }
+    }
+
+    map_register(priv, param);
+
+    return TRUE;
+}
+
+static BOOL shader_sm4_read_src_param(struct wined3d_sm4_data *priv, const DWORD **ptr,
+        enum wined3d_data_type data_type, struct wined3d_shader_src_param *src_param)
+{
+    DWORD token = **ptr;
+
+    if (!shader_sm4_read_param(priv, ptr, data_type, &src_param->reg, &src_param->modifiers))
+    {
+        ERR("Failed to read parameter.\n");
+        return FALSE;
+    }
+
+    if (src_param->reg.type == WINED3DSPR_IMMCONST)
+    {
+        src_param->swizzle = WINED3DSP_NOSWIZZLE;
+    }
+    else
+    {
+        enum wined3d_sm4_swizzle_type swizzle_type =
+                (token & WINED3D_SM4_SWIZZLE_TYPE_MASK) >> WINED3D_SM4_SWIZZLE_TYPE_SHIFT;
+
+        switch (swizzle_type)
+        {
+            case WINED3D_SM4_SWIZZLE_SCALAR:
+                src_param->swizzle = (token & WINED3D_SM4_SWIZZLE_MASK) >> WINED3D_SM4_SWIZZLE_SHIFT;
+                src_param->swizzle = (src_param->swizzle & 0x3) * 0x55;
+                break;
+
+            case WINED3D_SM4_SWIZZLE_VEC4:
+                src_param->swizzle = (token & WINED3D_SM4_SWIZZLE_MASK) >> WINED3D_SM4_SWIZZLE_SHIFT;
+                break;
+
+            default:
+                FIXME("Unhandled swizzle type %#x.\n", swizzle_type);
+                break;
+        }
+    }
+
+    return TRUE;
+}
+
+static BOOL shader_sm4_read_dst_param(struct wined3d_sm4_data *priv, const DWORD **ptr,
+        enum wined3d_data_type data_type, struct wined3d_shader_dst_param *dst_param)
+{
+    enum wined3d_shader_src_modifier modifier;
+    DWORD token = **ptr;
+
+    if (!shader_sm4_read_param(priv, ptr, data_type, &dst_param->reg, &modifier))
+    {
+        ERR("Failed to read parameter.\n");
+        return FALSE;
+    }
+
+    if (modifier != WINED3DSPSM_NONE)
+    {
+        ERR("Invalid source modifier %#x on destination register.\n", modifier);
+        return FALSE;
+    }
+
+    dst_param->write_mask = (token & WINED3D_SM4_WRITEMASK_MASK) >> WINED3D_SM4_WRITEMASK_SHIFT;
+    dst_param->modifiers = 0;
+    dst_param->shift = 0;
+
+    return TRUE;
+}
+
+static void shader_sm4_read_instruction(void *data, const DWORD **ptr, struct wined3d_shader_instruction *ins)
+{
+    const struct wined3d_sm4_opcode_info *opcode_info;
+    struct wined3d_sm4_data *priv = data;
+    DWORD opcode_token, opcode;
+    const DWORD *p;
+    UINT i, len;
+
+    list_move_head(&priv->src_free, &priv->src);
+
+    opcode_token = *(*ptr)++;
+    opcode = opcode_token & WINED3D_SM4_OPCODE_MASK;
+    len = ((opcode_token & WINED3D_SM4_INSTRUCTION_LENGTH_MASK) >> WINED3D_SM4_INSTRUCTION_LENGTH_SHIFT) - 1;
+
+    if (TRACE_ON(d3d_bytecode))
+    {
+        TRACE_(d3d_bytecode)("[ %08x ", opcode_token);
+        for (i = 0; i < len; ++i)
+        {
+            TRACE_(d3d_bytecode)("%08x ", (*ptr)[i]);
+        }
+        TRACE_(d3d_bytecode)("]\n");
+    }
+
+    if (!(opcode_info = get_opcode_info(opcode)))
+    {
+        FIXME("Unrecognized opcode %#x, opcode_token 0x%08x.\n", opcode, opcode_token);
+        ins->handler_idx = WINED3DSIH_TABLE_SIZE;
+        *ptr += len;
+        return;
+    }
+
+    ins->handler_idx = opcode_info->handler_idx;
+    ins->flags = 0;
+    ins->coissue = 0;
+    ins->predicate = NULL;
+    ins->dst_count = strlen(opcode_info->dst_info);
+    ins->dst = priv->dst_param;
+    ins->src_count = strlen(opcode_info->src_info);
+    ins->src = priv->src_param;
+
+    p = *ptr;
+    *ptr += len;
+
+    if (opcode_token & WINED3D_SM4_INSTRUCTION_MODIFIER)
+    {
+        DWORD modifier = *p++;
+        FIXME("Skipping modifier 0x%08x.\n", modifier);
+    }
+
+    if (opcode == WINED3D_SM4_OP_DCL_CONSTANT_BUFFER)
+    {
+        shader_sm4_read_src_param(priv, &p, WINED3D_DATA_FLOAT, &ins->declaration.src);
+        if (opcode_token & WINED3D_SM4_INDEX_TYPE_MASK)
+            ins->flags |= WINED3DSI_INDEXED_DYNAMIC;
+    }
+    else if (opcode == WINED3D_SM4_OP_DCL_OUTPUT_TOPOLOGY)
+    {
+        enum wined3d_sm4_output_primitive_type primitive_type;
+
+        primitive_type = (opcode_token & WINED3D_SM4_PRIMITIVE_TYPE_MASK) >> WINED3D_SM4_PRIMITIVE_TYPE_SHIFT;
+        if (primitive_type >= sizeof(output_primitive_type_table) / sizeof(*output_primitive_type_table))
+        {
+            FIXME("Unhandled output primitive type %#x.\n", primitive_type);
+            ins->declaration.primitive_type = WINED3D_PT_UNDEFINED;
+        }
+        else
+        {
+            ins->declaration.primitive_type = output_primitive_type_table[primitive_type];
+        }
+    }
+    else if (opcode == WINED3D_SM4_OP_DCL_INPUT_PRIMITIVE)
+    {
+        enum wined3d_sm4_input_primitive_type primitive_type;
+
+        primitive_type = (opcode_token & WINED3D_SM4_PRIMITIVE_TYPE_MASK) >> WINED3D_SM4_PRIMITIVE_TYPE_SHIFT;
+        if (primitive_type >= sizeof(input_primitive_type_table) / sizeof(*input_primitive_type_table))
+        {
+            FIXME("Unhandled input primitive type %#x.\n", primitive_type);
+            ins->declaration.primitive_type = WINED3D_PT_UNDEFINED;
+        }
+        else
+        {
+            ins->declaration.primitive_type = input_primitive_type_table[primitive_type];
+        }
+    }
+    else if (opcode == WINED3D_SM4_OP_DCL_VERTICES_OUT)
+    {
+        ins->declaration.count = *p++;
+    }
+    else
+    {
+        for (i = 0; i < ins->dst_count; ++i)
+        {
+            if (!(shader_sm4_read_dst_param(priv, &p, map_data_type(opcode_info->dst_info[i]), &priv->dst_param[i])))
+            {
+                ins->handler_idx = WINED3DSIH_TABLE_SIZE;
+                return;
+            }
+        }
+
+        for (i = 0; i < ins->src_count; ++i)
+        {
+            if (!(shader_sm4_read_src_param(priv, &p, map_data_type(opcode_info->src_info[i]), &priv->src_param[i])))
+            {
+                ins->handler_idx = WINED3DSIH_TABLE_SIZE;
+                return;
+            }
+        }
+    }
+}
+
+static BOOL shader_sm4_is_end(void *data, const DWORD **ptr)
+{
+    struct wined3d_sm4_data *priv = data;
+    return *ptr == priv->end;
+}
+
+const struct wined3d_shader_frontend sm4_shader_frontend =
+{
+    shader_sm4_init,
+    shader_sm4_free,
+    shader_sm4_read_header,
+    shader_sm4_read_instruction,
+    shader_sm4_is_end,
+};
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/state.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/state.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/state.c	(revision 46521)
@@ -0,0 +1,6039 @@
+/*
+ * Direct3D state management
+ *
+ * Copyright 2002 Lionel Ulmer
+ * Copyright 2002-2005 Jason Edmeades
+ * Copyright 2003-2004 Raphael Junqueira
+ * Copyright 2004 Christian Costa
+ * Copyright 2005 Oliver Stieber
+ * Copyright 2006 Henri Verbeet
+ * Copyright 2006-2008 Stefan Dösinger for CodeWeavers
+ * Copyright 2009-2011 Henri Verbeet for CodeWeavers
+ *
+ * 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 <stdio.h>
+#ifdef HAVE_FLOAT_H
+# include <float.h>
+#endif
+
+#include "wined3d_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d);
+WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
+
+/* Context activation for state handler is done by the caller. */
+
+static void state_undefined(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+#ifndef VBOX
+    ERR("Undefined state.\n");
+#else
+    WARN("Undefined state.\n");
+#endif
+}
+
+static void state_nop(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    TRACE("%s: nop in current pipe config.\n", debug_d3dstate(state_id));
+}
+
+static void state_fillmode(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    enum wined3d_fill_mode mode = state->render_states[WINED3D_RS_FILLMODE];
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    switch (mode)
+    {
+        case WINED3D_FILL_POINT:
+            gl_info->gl_ops.gl.p_glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
+            checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_POINT)");
+            break;
+        case WINED3D_FILL_WIREFRAME:
+            gl_info->gl_ops.gl.p_glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+            checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)");
+            break;
+        case WINED3D_FILL_SOLID:
+            gl_info->gl_ops.gl.p_glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+            checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)");
+            break;
+        default:
+            FIXME("Unrecognized fill mode %#x.\n", mode);
+    }
+}
+
+static void state_lighting(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    /* Lighting is not enabled if transformed vertices are drawn, but lighting
+     * does not affect the stream sources, so it is not grouped for
+     * performance reasons. This state reads the decoded vertex declaration,
+     * so if it is dirty don't do anything. The vertex declaration applying
+     * function calls this function for updating. */
+    if (isStateDirty(context, STATE_VDECL))
+        return;
+
+    if (state->render_states[WINED3D_RS_LIGHTING]
+            && !context->swapchain->device->stream_info.position_transformed)
+    {
+        gl_info->gl_ops.gl.p_glEnable(GL_LIGHTING);
+        checkGLcall("glEnable GL_LIGHTING");
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_LIGHTING);
+        checkGLcall("glDisable GL_LIGHTING");
+    }
+}
+
+static void state_zenable(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    enum wined3d_depth_buffer_type zenable = state->render_states[WINED3D_RS_ZENABLE];
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    static UINT once;
+
+    /* No z test without depth stencil buffers */
+    if (!state->fb->depth_stencil)
+    {
+        TRACE("No Z buffer - disabling depth test\n");
+        zenable = WINED3D_ZB_FALSE;
+    }
+
+    switch (zenable)
+    {
+        case WINED3D_ZB_FALSE:
+            gl_info->gl_ops.gl.p_glDisable(GL_DEPTH_TEST);
+            checkGLcall("glDisable GL_DEPTH_TEST");
+            break;
+        case WINED3D_ZB_TRUE:
+            gl_info->gl_ops.gl.p_glEnable(GL_DEPTH_TEST);
+            checkGLcall("glEnable GL_DEPTH_TEST");
+            break;
+        case WINED3D_ZB_USEW:
+            gl_info->gl_ops.gl.p_glEnable(GL_DEPTH_TEST);
+            checkGLcall("glEnable GL_DEPTH_TEST");
+            FIXME("W buffer is not well handled\n");
+            break;
+        default:
+            FIXME("Unrecognized depth buffer type %#x.\n", zenable);
+            break;
+    }
+
+    if (context->gl_info->supported[ARB_DEPTH_CLAMP])
+    {
+        if (!zenable && context->swapchain->device->stream_info.position_transformed)
+        {
+            gl_info->gl_ops.gl.p_glEnable(GL_DEPTH_CLAMP);
+            checkGLcall("glEnable(GL_DEPTH_CLAMP)");
+        }
+        else
+        {
+            gl_info->gl_ops.gl.p_glDisable(GL_DEPTH_CLAMP);
+            checkGLcall("glDisable(GL_DEPTH_CLAMP)");
+        }
+    }
+    else if (!zenable && !once++)
+        FIXME("Z buffer disabled, but ARB_depth_clamp isn't supported.\n");
+}
+
+static void state_cullmode(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    /* glFrontFace() is set in context.c at context init and on an
+     * offscreen / onscreen rendering switch. */
+    switch (state->render_states[WINED3D_RS_CULLMODE])
+    {
+        case WINED3D_CULL_NONE:
+            gl_info->gl_ops.gl.p_glDisable(GL_CULL_FACE);
+            checkGLcall("glDisable GL_CULL_FACE");
+            break;
+        case WINED3D_CULL_CW:
+            gl_info->gl_ops.gl.p_glEnable(GL_CULL_FACE);
+            checkGLcall("glEnable GL_CULL_FACE");
+            gl_info->gl_ops.gl.p_glCullFace(GL_FRONT);
+            checkGLcall("glCullFace(GL_FRONT)");
+            break;
+        case WINED3D_CULL_CCW:
+            gl_info->gl_ops.gl.p_glEnable(GL_CULL_FACE);
+            checkGLcall("glEnable GL_CULL_FACE");
+            gl_info->gl_ops.gl.p_glCullFace(GL_BACK);
+            checkGLcall("glCullFace(GL_BACK)");
+            break;
+        default:
+            FIXME("Unrecognized cull mode %#x.\n",
+                    state->render_states[WINED3D_RS_CULLMODE]);
+    }
+}
+
+static void state_shademode(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    switch (state->render_states[WINED3D_RS_SHADEMODE])
+    {
+        case WINED3D_SHADE_FLAT:
+            gl_info->gl_ops.gl.p_glShadeModel(GL_FLAT);
+            checkGLcall("glShadeModel(GL_FLAT)");
+            break;
+        case WINED3D_SHADE_GOURAUD:
+            gl_info->gl_ops.gl.p_glShadeModel(GL_SMOOTH);
+            checkGLcall("glShadeModel(GL_SMOOTH)");
+            break;
+        case WINED3D_SHADE_PHONG:
+            FIXME("WINED3D_SHADE_PHONG isn't supported.\n");
+            break;
+        default:
+            FIXME("Unrecognized shade mode %#x.\n",
+                    state->render_states[WINED3D_RS_SHADEMODE]);
+    }
+}
+
+static void state_ditherenable(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    if (state->render_states[WINED3D_RS_DITHERENABLE])
+    {
+        gl_info->gl_ops.gl.p_glEnable(GL_DITHER);
+        checkGLcall("glEnable GL_DITHER");
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_DITHER);
+        checkGLcall("glDisable GL_DITHER");
+    }
+}
+
+static void state_zwritenable(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    if (state->render_states[WINED3D_RS_ZWRITEENABLE])
+    {
+        gl_info->gl_ops.gl.p_glDepthMask(1);
+        checkGLcall("glDepthMask(1)");
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glDepthMask(0);
+        checkGLcall("glDepthMask(0)");
+    }
+}
+
+static GLenum gl_compare_func(enum wined3d_cmp_func f)
+{
+    switch (f)
+    {
+        case WINED3D_CMP_NEVER:
+            return GL_NEVER;
+        case WINED3D_CMP_LESS:
+            return GL_LESS;
+        case WINED3D_CMP_EQUAL:
+            return GL_EQUAL;
+        case WINED3D_CMP_LESSEQUAL:
+            return GL_LEQUAL;
+        case WINED3D_CMP_GREATER:
+            return GL_GREATER;
+        case WINED3D_CMP_NOTEQUAL:
+            return GL_NOTEQUAL;
+        case WINED3D_CMP_GREATEREQUAL:
+            return GL_GEQUAL;
+        case WINED3D_CMP_ALWAYS:
+            return GL_ALWAYS;
+        default:
+            FIXME("Unrecognized compare function %#x.\n", f);
+            return GL_NONE;
+    }
+}
+
+static void state_zfunc(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    GLenum depth_func = gl_compare_func(state->render_states[WINED3D_RS_ZFUNC]);
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    if (!depth_func) return;
+
+    gl_info->gl_ops.gl.p_glDepthFunc(depth_func);
+    checkGLcall("glDepthFunc");
+}
+
+void state_ambient(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    float col[4];
+
+    D3DCOLORTOGLFLOAT4(state->render_states[WINED3D_RS_AMBIENT], col);
+    TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
+    gl_info->gl_ops.gl.p_glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
+    checkGLcall("glLightModel for MODEL_AMBIENT");
+}
+
+static void state_blendop_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
+}
+
+static GLenum gl_blend_op(enum wined3d_blend_op op)
+{
+    switch (op)
+    {
+        case WINED3D_BLEND_OP_ADD:
+            return GL_FUNC_ADD_EXT;
+        case WINED3D_BLEND_OP_SUBTRACT:
+            return GL_FUNC_SUBTRACT_EXT;
+        case WINED3D_BLEND_OP_REVSUBTRACT:
+            return GL_FUNC_REVERSE_SUBTRACT_EXT;
+        case WINED3D_BLEND_OP_MIN:
+            return GL_MIN_EXT;
+        case WINED3D_BLEND_OP_MAX:
+            return GL_MAX_EXT;
+        default:
+            FIXME("Unhandled blend op %#x.\n", op);
+            return GL_NONE;
+    }
+}
+
+static void state_blendop(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    GLenum blend_equation_alpha = GL_FUNC_ADD_EXT;
+    GLenum blend_equation = GL_FUNC_ADD_EXT;
+
+    /* BLENDOPALPHA requires GL_EXT_blend_equation_separate, so make sure it is around */
+    if (state->render_states[WINED3D_RS_BLENDOPALPHA]
+            && !gl_info->supported[EXT_BLEND_EQUATION_SEPARATE])
+    {
+        WARN("Unsupported in local OpenGL implementation: glBlendEquationSeparateEXT\n");
+        return;
+    }
+
+    blend_equation = gl_blend_op(state->render_states[WINED3D_RS_BLENDOP]);
+    blend_equation_alpha = gl_blend_op(state->render_states[WINED3D_RS_BLENDOPALPHA]);
+    TRACE("blend_equation %#x, blend_equation_alpha %#x.\n", blend_equation, blend_equation_alpha);
+
+    if (state->render_states[WINED3D_RS_SEPARATEALPHABLENDENABLE])
+    {
+        GL_EXTCALL(glBlendEquationSeparateEXT(blend_equation, blend_equation_alpha));
+        checkGLcall("glBlendEquationSeparateEXT");
+    }
+    else
+    {
+        GL_EXTCALL(glBlendEquationEXT(blend_equation));
+        checkGLcall("glBlendEquation");
+    }
+}
+
+static GLenum gl_blend_factor(enum wined3d_blend factor, const struct wined3d_format *dst_format)
+{
+    switch (factor)
+    {
+        case WINED3D_BLEND_ZERO:
+            return GL_ZERO;
+        case WINED3D_BLEND_ONE:
+            return GL_ONE;
+        case WINED3D_BLEND_SRCCOLOR:
+            return GL_SRC_COLOR;
+        case WINED3D_BLEND_INVSRCCOLOR:
+            return GL_ONE_MINUS_SRC_COLOR;
+        case WINED3D_BLEND_SRCALPHA:
+            return GL_SRC_ALPHA;
+        case WINED3D_BLEND_INVSRCALPHA:
+            return GL_ONE_MINUS_SRC_ALPHA;
+        case WINED3D_BLEND_DESTCOLOR:
+            return GL_DST_COLOR;
+        case WINED3D_BLEND_INVDESTCOLOR:
+            return GL_ONE_MINUS_DST_COLOR;
+        /* To compensate for the lack of format switching with backbuffer
+         * offscreen rendering, and with onscreen rendering, we modify the
+         * alpha test parameters for (INV)DESTALPHA if the render target
+         * doesn't support alpha blending. A nonexistent alpha channel
+         * returns 1.0, so WINED3D_BLEND_DESTALPHA becomes GL_ONE, and
+         * WINED3D_BLEND_INVDESTALPHA becomes GL_ZERO. */
+        case WINED3D_BLEND_DESTALPHA:
+            return dst_format->alpha_size ? GL_DST_ALPHA : GL_ONE;
+        case WINED3D_BLEND_INVDESTALPHA:
+            return dst_format->alpha_size ? GL_ONE_MINUS_DST_ALPHA : GL_ZERO;
+        case WINED3D_BLEND_SRCALPHASAT:
+            return GL_SRC_ALPHA_SATURATE;
+        case WINED3D_BLEND_BLENDFACTOR:
+            return GL_CONSTANT_COLOR_EXT;
+        case WINED3D_BLEND_INVBLENDFACTOR:
+            return GL_ONE_MINUS_CONSTANT_COLOR_EXT;
+        default:
+            FIXME("Unhandled blend factor %#x.\n", factor);
+            return GL_NONE;
+    }
+}
+
+static void state_blend(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_surface *target = state->fb->render_targets[0];
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    GLenum srcBlend, dstBlend;
+    enum wined3d_blend d3d_blend;
+
+    /* According to the red book, GL_LINE_SMOOTH needs GL_BLEND with specific
+     * blending parameters to work. */
+    if (state->render_states[WINED3D_RS_ALPHABLENDENABLE]
+            || state->render_states[WINED3D_RS_EDGEANTIALIAS]
+            || state->render_states[WINED3D_RS_ANTIALIASEDLINEENABLE])
+    {
+        /* Disable blending in all cases even without pixelshaders.
+         * With blending on we could face a big performance penalty.
+         * The d3d9 visual test confirms the behavior. */
+        if (context->render_offscreen
+                && !(target->resource.format->flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING))
+        {
+            gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
+            checkGLcall("glDisable GL_BLEND");
+            return;
+        }
+        else
+        {
+            gl_info->gl_ops.gl.p_glEnable(GL_BLEND);
+            checkGLcall("glEnable GL_BLEND");
+        }
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
+        checkGLcall("glDisable GL_BLEND");
+        /* Nothing more to do - get out */
+        return;
+    };
+
+    /* WINED3D_BLEND_BOTHSRCALPHA and WINED3D_BLEND_BOTHINVSRCALPHA are legacy
+     * source blending values which are still valid up to d3d9. They should
+     * not occur as dest blend values. */
+    d3d_blend = state->render_states[WINED3D_RS_SRCBLEND];
+    if (d3d_blend == WINED3D_BLEND_BOTHSRCALPHA)
+    {
+        srcBlend = GL_SRC_ALPHA;
+        dstBlend = GL_ONE_MINUS_SRC_ALPHA;
+    }
+    else if (d3d_blend == WINED3D_BLEND_BOTHINVSRCALPHA)
+    {
+        srcBlend = GL_ONE_MINUS_SRC_ALPHA;
+        dstBlend = GL_SRC_ALPHA;
+    }
+    else
+    {
+        srcBlend = gl_blend_factor(d3d_blend, target->resource.format);
+        dstBlend = gl_blend_factor(state->render_states[WINED3D_RS_DESTBLEND],
+                target->resource.format);
+    }
+
+    if (state->render_states[WINED3D_RS_EDGEANTIALIAS]
+            || state->render_states[WINED3D_RS_ANTIALIASEDLINEENABLE])
+    {
+        gl_info->gl_ops.gl.p_glEnable(GL_LINE_SMOOTH);
+        checkGLcall("glEnable(GL_LINE_SMOOTH)");
+        if (srcBlend != GL_SRC_ALPHA)
+            WARN("WINED3D_RS_EDGEANTIALIAS enabled, but unexpected src blending param.\n");
+        if (dstBlend != GL_ONE_MINUS_SRC_ALPHA && dstBlend != GL_ONE)
+            WARN("WINED3D_RS_EDGEANTIALIAS enabled, but unexpected dst blending param.\n");
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_LINE_SMOOTH);
+        checkGLcall("glDisable(GL_LINE_SMOOTH)");
+    }
+
+    /* Re-apply BLENDOP(ALPHA) because of a possible SEPARATEALPHABLENDENABLE change */
+    if (!isStateDirty(context, STATE_RENDER(WINED3D_RS_BLENDOP)))
+        state_blendop(context, state, STATE_RENDER(WINED3D_RS_BLENDOPALPHA));
+
+    if (state->render_states[WINED3D_RS_SEPARATEALPHABLENDENABLE])
+    {
+        GLenum srcBlendAlpha, dstBlendAlpha;
+
+        /* Separate alpha blending requires GL_EXT_blend_function_separate, so make sure it is around */
+        if (!context->gl_info->supported[EXT_BLEND_FUNC_SEPARATE])
+        {
+            WARN("Unsupported in local OpenGL implementation: glBlendFuncSeparateEXT\n");
+            return;
+        }
+
+        /* WINED3D_BLEND_BOTHSRCALPHA and WINED3D_BLEND_BOTHINVSRCALPHA are legacy
+         * source blending values which are still valid up to d3d9. They should
+         * not occur as dest blend values. */
+        d3d_blend = state->render_states[WINED3D_RS_SRCBLENDALPHA];
+        if (d3d_blend == WINED3D_BLEND_BOTHSRCALPHA)
+        {
+            srcBlendAlpha = GL_SRC_ALPHA;
+            dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
+        }
+        else if (d3d_blend == WINED3D_BLEND_BOTHINVSRCALPHA)
+        {
+            srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
+            dstBlendAlpha = GL_SRC_ALPHA;
+        }
+        else
+        {
+            srcBlendAlpha = gl_blend_factor(d3d_blend, target->resource.format);
+            dstBlendAlpha = gl_blend_factor(state->render_states[WINED3D_RS_DESTBLENDALPHA],
+                    target->resource.format);
+        }
+
+        GL_EXTCALL(glBlendFuncSeparateEXT(srcBlend, dstBlend, srcBlendAlpha, dstBlendAlpha));
+        checkGLcall("glBlendFuncSeparateEXT");
+    }
+    else
+    {
+        TRACE("glBlendFunc src=%x, dst=%x\n", srcBlend, dstBlend);
+        gl_info->gl_ops.gl.p_glBlendFunc(srcBlend, dstBlend);
+        checkGLcall("glBlendFunc");
+    }
+
+    /* Colorkey fixup for stage 0 alphaop depends on
+     * WINED3D_RS_ALPHABLENDENABLE state, so it may need updating. */
+    if (state->render_states[WINED3D_RS_COLORKEYENABLE])
+        context_apply_state(context, state, STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_OP));
+}
+
+static void state_blendfactor_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    WARN("Unsupported in local OpenGL implementation: glBlendColorEXT\n");
+}
+
+static void state_blendfactor(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    float col[4];
+
+    TRACE("Setting blend factor to %#x.\n", state->render_states[WINED3D_RS_BLENDFACTOR]);
+
+    D3DCOLORTOGLFLOAT4(state->render_states[WINED3D_RS_BLENDFACTOR], col);
+    GL_EXTCALL(glBlendColorEXT (col[0],col[1],col[2],col[3]));
+    checkGLcall("glBlendColor");
+}
+
+static void state_alpha(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    int glParm = 0;
+    float ref;
+    BOOL enable_ckey = FALSE;
+
+    TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);
+
+    /* Find out if the texture on the first stage has a ckey set
+     * The alpha state func reads the texture settings, even though alpha and texture are not grouped
+     * together. This is to avoid making a huge alpha+texture+texture stage+ckey block due to the hardly
+     * used WINED3D_RS_COLORKEYENABLE state(which is d3d <= 3 only). The texture function will call alpha
+     * in case it finds some texture+colorkeyenable combination which needs extra care.
+     */
+    if (state->textures[0])
+    {
+        struct wined3d_surface *surface = surface_from_resource(state->textures[0]->sub_resources[0]);
+
+        if (surface->CKeyFlags & WINEDDSD_CKSRCBLT)
+            enable_ckey = TRUE;
+    }
+
+    if (enable_ckey || context->last_was_ckey)
+        context_apply_state(context, state, STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_OP));
+    context->last_was_ckey = enable_ckey;
+
+    if (state->render_states[WINED3D_RS_ALPHATESTENABLE]
+            || (state->render_states[WINED3D_RS_COLORKEYENABLE] && enable_ckey))
+    {
+        gl_info->gl_ops.gl.p_glEnable(GL_ALPHA_TEST);
+        checkGLcall("glEnable GL_ALPHA_TEST");
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_ALPHA_TEST);
+        checkGLcall("glDisable GL_ALPHA_TEST");
+        /* Alpha test is disabled, don't bother setting the params - it will happen on the next
+         * enable call
+         */
+        return;
+    }
+
+    if (state->render_states[WINED3D_RS_COLORKEYENABLE] && enable_ckey)
+    {
+        glParm = GL_NOTEQUAL;
+        ref = 0.0f;
+    }
+    else
+    {
+        ref = ((float)state->render_states[WINED3D_RS_ALPHAREF]) / 255.0f;
+        glParm = gl_compare_func(state->render_states[WINED3D_RS_ALPHAFUNC]);
+    }
+    if (glParm)
+    {
+        gl_info->gl_ops.gl.p_glAlphaFunc(glParm, ref);
+        checkGLcall("glAlphaFunc");
+    }
+}
+
+static void shaderconstant(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    context->load_constants = 1;
+}
+
+void state_clipping(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    DWORD enable  = 0xffffffff;
+    DWORD disable = 0x00000000;
+
+    if (use_vs(state) && !context->d3d_info->vs_clipping)
+            {
+        static BOOL warned;
+
+        /* The OpenGL spec says that clipping planes are disabled when using
+         * shaders. Direct3D planes aren't, so that is an issue. The MacOS ATI
+         * driver keeps clipping planes activated with shaders in some
+         * conditions I got sick of tracking down. The shader state handler
+         * disables all clip planes because of that - don't do anything here
+         * and keep them disabled. */
+        if (state->render_states[WINED3D_RS_CLIPPLANEENABLE] && !warned++)
+                    FIXME("Clipping not supported with vertex shaders\n");
+            return;
+        }
+
+    /* glEnable(GL_CLIP_PLANEx) doesn't apply to (ARB backend) vertex shaders.
+     * The enabled / disabled planes are hardcoded into the shader. Update the
+     * shader to update the enabled clipplanes. In case of fixed function, we
+     * need to update the clipping field from ffp_vertex_settings. */
+        context->select_shader = 1;
+        context->load_constants = 1;
+
+    /* TODO: Keep track of previously enabled clipplanes to avoid unnecessary resetting
+     * of already set values
+     */
+
+    /* If enabling / disabling all
+     * TODO: Is this correct? Doesn't D3DRS_CLIPPING disable clipping on the viewport frustrum?
+     */
+    if (state->render_states[WINED3D_RS_CLIPPING])
+    {
+        enable = state->render_states[WINED3D_RS_CLIPPLANEENABLE];
+        disable = ~state->render_states[WINED3D_RS_CLIPPLANEENABLE];
+    }
+    else
+    {
+        disable = 0xffffffff;
+        enable  = 0x00;
+    }
+
+    if (enable & WINED3DCLIPPLANE0) gl_info->gl_ops.gl.p_glEnable(GL_CLIP_PLANE0);
+    if (enable & WINED3DCLIPPLANE1) gl_info->gl_ops.gl.p_glEnable(GL_CLIP_PLANE1);
+    if (enable & WINED3DCLIPPLANE2) gl_info->gl_ops.gl.p_glEnable(GL_CLIP_PLANE2);
+    if (enable & WINED3DCLIPPLANE3) gl_info->gl_ops.gl.p_glEnable(GL_CLIP_PLANE3);
+    if (enable & WINED3DCLIPPLANE4) gl_info->gl_ops.gl.p_glEnable(GL_CLIP_PLANE4);
+    if (enable & WINED3DCLIPPLANE5) gl_info->gl_ops.gl.p_glEnable(GL_CLIP_PLANE5);
+    checkGLcall("clip plane enable");
+
+    if (disable & WINED3DCLIPPLANE0) gl_info->gl_ops.gl.p_glDisable(GL_CLIP_PLANE0);
+    if (disable & WINED3DCLIPPLANE1) gl_info->gl_ops.gl.p_glDisable(GL_CLIP_PLANE1);
+    if (disable & WINED3DCLIPPLANE2) gl_info->gl_ops.gl.p_glDisable(GL_CLIP_PLANE2);
+    if (disable & WINED3DCLIPPLANE3) gl_info->gl_ops.gl.p_glDisable(GL_CLIP_PLANE3);
+    if (disable & WINED3DCLIPPLANE4) gl_info->gl_ops.gl.p_glDisable(GL_CLIP_PLANE4);
+    if (disable & WINED3DCLIPPLANE5) gl_info->gl_ops.gl.p_glDisable(GL_CLIP_PLANE5);
+    checkGLcall("clip plane disable");
+}
+
+void state_specularenable(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
+     * and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
+     * specular color. This is wrong:
+     * Separate specular color means the specular colour is maintained separately, whereas
+     * single color means it is merged in. However in both cases they are being used to
+     * some extent.
+     * To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
+     * NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
+     * running 1.4 yet!
+     *
+     *
+     * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
+     * Instead, we need to setup the FinalCombiner properly.
+     *
+     * The default setup for the FinalCombiner is:
+     *
+     * <variable>       <input>                             <mapping>               <usage>
+     * GL_VARIABLE_A_NV GL_FOG,                             GL_UNSIGNED_IDENTITY_NV GL_ALPHA
+     * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV   GL_UNSIGNED_IDENTITY_NV GL_RGB
+     * GL_VARIABLE_C_NV GL_FOG                              GL_UNSIGNED_IDENTITY_NV GL_RGB
+     * GL_VARIABLE_D_NV GL_ZERO                             GL_UNSIGNED_IDENTITY_NV GL_RGB
+     * GL_VARIABLE_E_NV GL_ZERO                             GL_UNSIGNED_IDENTITY_NV GL_RGB
+     * GL_VARIABLE_F_NV GL_ZERO                             GL_UNSIGNED_IDENTITY_NV GL_RGB
+     * GL_VARIABLE_G_NV GL_SPARE0_NV                        GL_UNSIGNED_IDENTITY_NV GL_ALPHA
+     *
+     * That's pretty much fine as it is, except for variable B, which needs to take
+     * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
+     * whether WINED3D_RS_SPECULARENABLE is enabled or not.
+     */
+
+    TRACE("Setting specular enable state and materials\n");
+    if (state->render_states[WINED3D_RS_SPECULARENABLE])
+    {
+        gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float *)&state->material.specular);
+        checkGLcall("glMaterialfv");
+
+        if (state->material.power > gl_info->limits.shininess)
+        {
+            /* glMaterialf man page says that the material says that GL_SHININESS must be between 0.0
+             * and 128.0, although in d3d neither -1 nor 129 produce an error. GL_NV_max_light_exponent
+             * allows bigger values. If the extension is supported, gl_info->limits.shininess contains the
+             * value reported by the extension, otherwise 128. For values > gl_info->limits.shininess clamp
+             * them, it should be safe to do so without major visual distortions.
+             */
+            WARN("Material power = %.8e, limit %.8e\n", state->material.power, gl_info->limits.shininess);
+            gl_info->gl_ops.gl.p_glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, gl_info->limits.shininess);
+        }
+        else
+        {
+            gl_info->gl_ops.gl.p_glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, state->material.power);
+        }
+        checkGLcall("glMaterialf(GL_SHININESS)");
+
+        if (gl_info->supported[EXT_SECONDARY_COLOR])
+            gl_info->gl_ops.gl.p_glEnable(GL_COLOR_SUM_EXT);
+        else
+            TRACE("Specular colors cannot be enabled in this version of opengl\n");
+        checkGLcall("glEnable(GL_COLOR_SUM)");
+
+        if (gl_info->supported[NV_REGISTER_COMBINERS])
+        {
+            GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_PLUS_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
+            checkGLcall("glFinalCombinerInputNV()");
+        }
+    } else {
+        static const GLfloat black[] = {0.0f, 0.0f, 0.0f, 0.0f};
+
+        /* for the case of enabled lighting: */
+        gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
+        checkGLcall("glMaterialfv");
+
+        /* for the case of disabled lighting: */
+        if (gl_info->supported[EXT_SECONDARY_COLOR])
+            gl_info->gl_ops.gl.p_glDisable(GL_COLOR_SUM_EXT);
+        else
+            TRACE("Specular colors cannot be disabled in this version of opengl\n");
+        checkGLcall("glDisable(GL_COLOR_SUM)");
+
+        if (gl_info->supported[NV_REGISTER_COMBINERS])
+        {
+            GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
+            checkGLcall("glFinalCombinerInputNV()");
+        }
+    }
+
+    TRACE("diffuse {%.8e, %.8e, %.8e, %.8e}\n",
+            state->material.diffuse.r, state->material.diffuse.g,
+            state->material.diffuse.b, state->material.diffuse.a);
+    TRACE("ambient {%.8e, %.8e, %.8e, %.8e}\n",
+            state->material.ambient.r, state->material.ambient.g,
+            state->material.ambient.b, state->material.ambient.a);
+    TRACE("specular {%.8e, %.8e, %.8e, %.8e}\n",
+            state->material.specular.r, state->material.specular.g,
+            state->material.specular.b, state->material.specular.a);
+    TRACE("emissive {%.8e, %.8e, %.8e, %.8e}\n",
+            state->material.emissive.r, state->material.emissive.g,
+            state->material.emissive.b, state->material.emissive.a);
+
+    gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float *)&state->material.ambient);
+    checkGLcall("glMaterialfv(GL_AMBIENT)");
+    gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float *)&state->material.diffuse);
+    checkGLcall("glMaterialfv(GL_DIFFUSE)");
+    gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float *)&state->material.emissive);
+    checkGLcall("glMaterialfv(GL_EMISSION)");
+}
+
+static void state_texfactor(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    unsigned int i;
+
+    /* Note the texture color applies to all textures whereas
+     * GL_TEXTURE_ENV_COLOR applies to active only. */
+    float col[4];
+    D3DCOLORTOGLFLOAT4(state->render_states[WINED3D_RS_TEXTUREFACTOR], col);
+
+    /* And now the default texture color as well */
+    for (i = 0; i < context->d3d_info->limits.ffp_blend_stages; ++i)
+    {
+        /* Note the WINED3D_RS value applies to all textures, but GL has one
+         * per texture, so apply it now ready to be used! */
+        context_active_texture(context, gl_info, i);
+
+        gl_info->gl_ops.gl.p_glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
+        checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
+    }
+}
+
+static void renderstate_stencil_twosided(struct wined3d_context *context, GLint face,
+        GLint func, GLint ref, GLuint mask, GLint stencilFail, GLint depthFail, GLint stencilPass)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    gl_info->gl_ops.gl.p_glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
+    checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
+    GL_EXTCALL(glActiveStencilFaceEXT(face));
+    checkGLcall("glActiveStencilFaceEXT(...)");
+    gl_info->gl_ops.gl.p_glStencilFunc(func, ref, mask);
+    checkGLcall("glStencilFunc(...)");
+    gl_info->gl_ops.gl.p_glStencilOp(stencilFail, depthFail, stencilPass);
+    checkGLcall("glStencilOp(...)");
+}
+
+static GLenum gl_stencil_op(enum wined3d_stencil_op op)
+{
+    switch (op)
+    {
+        case WINED3D_STENCIL_OP_KEEP:
+            return GL_KEEP;
+        case WINED3D_STENCIL_OP_ZERO:
+            return GL_ZERO;
+        case WINED3D_STENCIL_OP_REPLACE:
+            return GL_REPLACE;
+        case WINED3D_STENCIL_OP_INCR_SAT:
+            return GL_INCR;
+        case WINED3D_STENCIL_OP_DECR_SAT:
+            return GL_DECR;
+        case WINED3D_STENCIL_OP_INVERT:
+            return GL_INVERT;
+        case WINED3D_STENCIL_OP_INCR:
+            return GL_INCR_WRAP_EXT;
+        case WINED3D_STENCIL_OP_DECR:
+            return GL_DECR_WRAP_EXT;
+        default:
+            FIXME("Unrecognized stencil op %#x.\n", op);
+            return GL_KEEP;
+    }
+}
+
+static void state_stencil(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    DWORD onesided_enable = FALSE;
+    DWORD twosided_enable = FALSE;
+    GLint func = GL_ALWAYS;
+    GLint func_ccw = GL_ALWAYS;
+    GLint ref = 0;
+    GLuint mask = 0;
+    GLint stencilFail = GL_KEEP;
+    GLint depthFail = GL_KEEP;
+    GLint stencilPass = GL_KEEP;
+    GLint stencilFail_ccw = GL_KEEP;
+    GLint depthFail_ccw = GL_KEEP;
+    GLint stencilPass_ccw = GL_KEEP;
+
+    /* No stencil test without a stencil buffer. */
+    if (!state->fb->depth_stencil)
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_STENCIL_TEST);
+        checkGLcall("glDisable GL_STENCIL_TEST");
+        return;
+    }
+
+    onesided_enable = state->render_states[WINED3D_RS_STENCILENABLE];
+    twosided_enable = state->render_states[WINED3D_RS_TWOSIDEDSTENCILMODE];
+    if (!(func = gl_compare_func(state->render_states[WINED3D_RS_STENCILFUNC])))
+        func = GL_ALWAYS;
+    if (!(func_ccw = gl_compare_func(state->render_states[WINED3D_RS_CCW_STENCILFUNC])))
+        func_ccw = GL_ALWAYS;
+    ref = state->render_states[WINED3D_RS_STENCILREF];
+    mask = state->render_states[WINED3D_RS_STENCILMASK];
+    stencilFail = gl_stencil_op(state->render_states[WINED3D_RS_STENCILFAIL]);
+    depthFail = gl_stencil_op(state->render_states[WINED3D_RS_STENCILZFAIL]);
+    stencilPass = gl_stencil_op(state->render_states[WINED3D_RS_STENCILPASS]);
+    stencilFail_ccw = gl_stencil_op(state->render_states[WINED3D_RS_CCW_STENCILFAIL]);
+    depthFail_ccw = gl_stencil_op(state->render_states[WINED3D_RS_CCW_STENCILZFAIL]);
+    stencilPass_ccw = gl_stencil_op(state->render_states[WINED3D_RS_CCW_STENCILPASS]);
+
+    TRACE("(onesided %d, twosided %d, ref %x, mask %x, "
+          "GL_FRONT: func: %x, fail %x, zfail %x, zpass %x "
+          "GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
+    onesided_enable, twosided_enable, ref, mask,
+    func, stencilFail, depthFail, stencilPass,
+    func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
+
+    if (twosided_enable && onesided_enable)
+    {
+        gl_info->gl_ops.gl.p_glEnable(GL_STENCIL_TEST);
+        checkGLcall("glEnable GL_STENCIL_TEST");
+
+        if (gl_info->supported[EXT_STENCIL_TWO_SIDE])
+        {
+            /* Apply back first, then front. This function calls glActiveStencilFaceEXT,
+             * which has an effect on the code below too. If we apply the front face
+             * afterwards, we are sure that the active stencil face is set to front,
+             * and other stencil functions which do not use two sided stencil do not have
+             * to set it back
+             */
+            renderstate_stencil_twosided(context, GL_BACK,
+                    func_ccw, ref, mask, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
+            renderstate_stencil_twosided(context, GL_FRONT,
+                    func, ref, mask, stencilFail, depthFail, stencilPass);
+        }
+        else if (gl_info->supported[ATI_SEPARATE_STENCIL])
+        {
+            GL_EXTCALL(glStencilFuncSeparateATI(func, func_ccw, ref, mask));
+            checkGLcall("glStencilFuncSeparateATI(...)");
+            GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT, stencilFail, depthFail, stencilPass));
+            checkGLcall("glStencilOpSeparateATI(GL_FRONT, ...)");
+            GL_EXTCALL(glStencilOpSeparateATI(GL_BACK, stencilFail_ccw, depthFail_ccw, stencilPass_ccw));
+            checkGLcall("glStencilOpSeparateATI(GL_BACK, ...)");
+        } else {
+            ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
+        }
+    }
+    else if(onesided_enable)
+    {
+        if (gl_info->supported[EXT_STENCIL_TWO_SIDE])
+        {
+            gl_info->gl_ops.gl.p_glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
+            checkGLcall("glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
+        }
+
+        /* This code disables the ATI extension as well, since the standard stencil functions are equal
+         * to calling the ATI functions with GL_FRONT_AND_BACK as face parameter
+         */
+        gl_info->gl_ops.gl.p_glEnable(GL_STENCIL_TEST);
+        checkGLcall("glEnable GL_STENCIL_TEST");
+        gl_info->gl_ops.gl.p_glStencilFunc(func, ref, mask);
+        checkGLcall("glStencilFunc(...)");
+        gl_info->gl_ops.gl.p_glStencilOp(stencilFail, depthFail, stencilPass);
+        checkGLcall("glStencilOp(...)");
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_STENCIL_TEST);
+        checkGLcall("glDisable GL_STENCIL_TEST");
+    }
+}
+
+static void state_stencilwrite2s(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    DWORD mask = state->fb->depth_stencil ? state->render_states[WINED3D_RS_STENCILWRITEMASK] : 0;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
+    checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
+    gl_info->gl_ops.gl.p_glStencilMask(mask);
+    checkGLcall("glStencilMask");
+    GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
+    checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
+    gl_info->gl_ops.gl.p_glStencilMask(mask);
+}
+
+static void state_stencilwrite(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    DWORD mask = state->fb->depth_stencil ? state->render_states[WINED3D_RS_STENCILWRITEMASK] : 0;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    gl_info->gl_ops.gl.p_glStencilMask(mask);
+    checkGLcall("glStencilMask");
+}
+
+static void state_fog_vertexpart(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);
+
+    if (!state->render_states[WINED3D_RS_FOGENABLE])
+        return;
+
+    /* Table fog on: Never use fog coords, and use per-fragment fog */
+    if (state->render_states[WINED3D_RS_FOGTABLEMODE] != WINED3D_FOG_NONE)
+    {
+        gl_info->gl_ops.gl.p_glHint(GL_FOG_HINT, GL_NICEST);
+        if (context->fog_coord)
+        {
+            gl_info->gl_ops.gl.p_glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
+            checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
+            context->fog_coord = FALSE;
+        }
+
+        /* Range fog is only used with per-vertex fog in d3d */
+        if (gl_info->supported[NV_FOG_DISTANCE])
+        {
+            gl_info->gl_ops.gl.p_glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
+            checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV)");
+        }
+        return;
+    }
+
+    /* Otherwise use per-vertex fog in any case */
+    gl_info->gl_ops.gl.p_glHint(GL_FOG_HINT, GL_FASTEST);
+
+    if (state->render_states[WINED3D_RS_FOGVERTEXMODE] == WINED3D_FOG_NONE || context->last_was_rhw)
+    {
+        /* No fog at all, or transformed vertices: Use fog coord */
+        if (!context->fog_coord)
+        {
+            gl_info->gl_ops.gl.p_glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
+            checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)");
+            context->fog_coord = TRUE;
+        }
+    }
+    else
+    {
+        /* Otherwise, use the fragment depth */
+        if (context->fog_coord)
+        {
+            gl_info->gl_ops.gl.p_glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
+            checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
+            context->fog_coord = FALSE;
+        }
+
+        if (state->render_states[WINED3D_RS_RANGEFOGENABLE])
+        {
+            if (gl_info->supported[NV_FOG_DISTANCE])
+            {
+                gl_info->gl_ops.gl.p_glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV);
+                checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV)");
+            }
+            else
+            {
+                WARN("Range fog enabled, but not supported by this GL implementation.\n");
+            }
+        }
+        else if (gl_info->supported[NV_FOG_DISTANCE])
+        {
+            gl_info->gl_ops.gl.p_glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
+            checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV)");
+        }
+    }
+}
+
+void state_fogstartend(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    float fogstart, fogend;
+    union {
+        DWORD d;
+        float f;
+    } tmpvalue;
+
+    switch(context->fog_source) {
+        case FOGSOURCE_VS:
+            fogstart = 1.0f;
+            fogend = 0.0f;
+            break;
+
+        case FOGSOURCE_COORD:
+            fogstart = 255.0f;
+            fogend = 0.0f;
+            break;
+
+        case FOGSOURCE_FFP:
+            tmpvalue.d = state->render_states[WINED3D_RS_FOGSTART];
+            fogstart = tmpvalue.f;
+            tmpvalue.d = state->render_states[WINED3D_RS_FOGEND];
+            fogend = tmpvalue.f;
+            /* In GL, fogstart == fogend disables fog, in D3D everything's fogged.*/
+            if(fogstart == fogend) {
+                fogstart = -INFINITY;
+                fogend = 0.0f;
+            }
+            break;
+
+        default:
+            /* This should not happen.context->fog_source is set in wined3d, not the app.
+             * Still this is needed to make the compiler happy
+             */
+            ERR("Unexpected fog coordinate source\n");
+            fogstart = 0.0f;
+            fogend = 0.0f;
+    }
+
+    gl_info->gl_ops.gl.p_glFogf(GL_FOG_START, fogstart);
+    checkGLcall("glFogf(GL_FOG_START, fogstart)");
+    TRACE("Fog Start == %f\n", fogstart);
+
+    gl_info->gl_ops.gl.p_glFogf(GL_FOG_END, fogend);
+    checkGLcall("glFogf(GL_FOG_END, fogend)");
+    TRACE("Fog End == %f\n", fogend);
+}
+
+void state_fog_fragpart(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    enum fogsource new_source;
+
+    TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);
+
+    if (!state->render_states[WINED3D_RS_FOGENABLE])
+    {
+        /* No fog? Disable it, and we're done :-) */
+        glDisableWINE(GL_FOG);
+        checkGLcall("glDisable GL_FOG");
+        return;
+    }
+
+    /* Fog Rules:
+     *
+     * With fixed function vertex processing, Direct3D knows 2 different fog input sources.
+     * It can use the Z value of the vertex, or the alpha component of the specular color.
+     * This depends on the fog vertex, fog table and the vertex declaration. If the Z value
+     * is used, fogstart, fogend and the equation type are used, otherwise linear fog with
+     * start = 255, end = 0 is used. Obviously the msdn is not very clear on that.
+     *
+     * FOGTABLEMODE != NONE:
+     *  The Z value is used, with the equation specified, no matter what vertex type.
+     *
+     * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, untransformed:
+     *  Per vertex fog is calculated using the specified fog equation and the parameters
+     *
+     * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, transformed, OR
+     * FOGTABLEMODE == NONE, FOGVERTEXMODE == NONE, untransformed:
+     *  Linear fog with start = 255.0, end = 0.0, input comes from the specular color
+     *
+     *
+     * Rules for vertex fog with shaders:
+     *
+     * When mixing fixed function functionality with the programmable pipeline, D3D expects
+     * the fog computation to happen during transformation while openGL expects it to happen
+     * during rasterization. Also, prior to pixel shader 3.0 D3D handles fog blending after
+     * the pixel shader while openGL always expects the pixel shader to handle the blending.
+     * To solve this problem, WineD3D does:
+     * 1) implement a linear fog equation and fog blending at the end of every pre 3.0 pixel
+     * shader,
+     * and 2) disables the fog computation (in either the fixed function or programmable
+     * rasterizer) if using a vertex program.
+     *
+     * D3D shaders can provide an explicit fog coordinate. This fog coordinate is used with
+     * D3DRS_FOGTABLEMODE==D3DFOG_NONE. The FOGVERTEXMODE is ignored, d3d always uses linear
+     * fog with start=1.0 and end=0.0 in this case. This is similar to fog coordinates in
+     * the specular color, a vertex shader counts as pretransformed geometry in this case.
+     * There are some GL differences between specular fog coords and vertex shaders though.
+     *
+     * With table fog the vertex shader fog coordinate is ignored.
+     *
+     * If a fogtablemode and a fogvertexmode are specified, table fog is applied (with or
+     * without shaders).
+     */
+
+    /* DX 7 sdk: "If both render states(vertex and table fog) are set to valid modes,
+     * the system will apply only pixel(=table) fog effects."
+     */
+    if (state->render_states[WINED3D_RS_FOGTABLEMODE] == WINED3D_FOG_NONE)
+    {
+        if (use_vs(state))
+        {
+            gl_info->gl_ops.gl.p_glFogi(GL_FOG_MODE, GL_LINEAR);
+            checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
+            new_source = FOGSOURCE_VS;
+        }
+        else
+        {
+            switch (state->render_states[WINED3D_RS_FOGVERTEXMODE])
+            {
+                /* If processed vertices are used, fall through to the NONE case */
+                case WINED3D_FOG_EXP:
+                    if (!context->last_was_rhw)
+                    {
+                        gl_info->gl_ops.gl.p_glFogi(GL_FOG_MODE, GL_EXP);
+                        checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
+                        new_source = FOGSOURCE_FFP;
+                        break;
+                    }
+                    /* drop through */
+
+                case WINED3D_FOG_EXP2:
+                    if (!context->last_was_rhw)
+                    {
+                        gl_info->gl_ops.gl.p_glFogi(GL_FOG_MODE, GL_EXP2);
+                        checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
+                        new_source = FOGSOURCE_FFP;
+                        break;
+                    }
+                    /* drop through */
+
+                case WINED3D_FOG_LINEAR:
+                    if (!context->last_was_rhw)
+                    {
+                        gl_info->gl_ops.gl.p_glFogi(GL_FOG_MODE, GL_LINEAR);
+                        checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
+                        new_source = FOGSOURCE_FFP;
+                        break;
+                    }
+                    /* drop through */
+
+                case WINED3D_FOG_NONE:
+                    /* Both are none? According to msdn the alpha channel of the specular
+                     * color contains a fog factor. Set it in drawStridedSlow.
+                     * Same happens with Vertexfog on transformed vertices
+                     */
+                    new_source = FOGSOURCE_COORD;
+                    gl_info->gl_ops.gl.p_glFogi(GL_FOG_MODE, GL_LINEAR);
+                    checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
+                    break;
+
+                default:
+                    FIXME("Unexpected WINED3D_RS_FOGVERTEXMODE %#x.\n",
+                            state->render_states[WINED3D_RS_FOGVERTEXMODE]);
+                    new_source = FOGSOURCE_FFP; /* Make the compiler happy */
+            }
+        }
+    } else {
+        new_source = FOGSOURCE_FFP;
+
+        switch (state->render_states[WINED3D_RS_FOGTABLEMODE])
+        {
+            case WINED3D_FOG_EXP:
+                gl_info->gl_ops.gl.p_glFogi(GL_FOG_MODE, GL_EXP);
+                checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
+                break;
+
+            case WINED3D_FOG_EXP2:
+                gl_info->gl_ops.gl.p_glFogi(GL_FOG_MODE, GL_EXP2);
+                checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
+                break;
+
+            case WINED3D_FOG_LINEAR:
+                gl_info->gl_ops.gl.p_glFogi(GL_FOG_MODE, GL_LINEAR);
+                checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
+                break;
+
+            case WINED3D_FOG_NONE:   /* Won't happen */
+            default:
+                FIXME("Unexpected WINED3D_RS_FOGTABLEMODE %#x.\n",
+                        state->render_states[WINED3D_RS_FOGTABLEMODE]);
+        }
+    }
+
+    glEnableWINE(GL_FOG);
+    checkGLcall("glEnable GL_FOG");
+    if (new_source != context->fog_source)
+    {
+        context->fog_source = new_source;
+        state_fogstartend(context, state, STATE_RENDER(WINED3D_RS_FOGSTART));
+    }
+}
+
+void state_fogcolor(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    float col[4];
+
+    D3DCOLORTOGLFLOAT4(state->render_states[WINED3D_RS_FOGCOLOR], col);
+    gl_info->gl_ops.gl.p_glFogfv(GL_FOG_COLOR, &col[0]);
+    checkGLcall("glFog GL_FOG_COLOR");
+}
+
+void state_fogdensity(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    union {
+        DWORD d;
+        float f;
+    } tmpvalue;
+
+    tmpvalue.d = state->render_states[WINED3D_RS_FOGDENSITY];
+    gl_info->gl_ops.gl.p_glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
+    checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
+}
+
+static void state_colormat(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_device *device = context->swapchain->device;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    GLenum Parm = 0;
+
+    /* Depends on the decoded vertex declaration to read the existence of diffuse data.
+     * The vertex declaration will call this function if the fixed function pipeline is used.
+     */
+
+    if(isStateDirty(context, STATE_VDECL)) {
+        return;
+    }
+
+    context->num_untracked_materials = 0;
+    if ((device->stream_info.use_map & (1 << WINED3D_FFP_DIFFUSE))
+            && state->render_states[WINED3D_RS_COLORVERTEX])
+    {
+        TRACE("diff %d, amb %d, emis %d, spec %d\n",
+                state->render_states[WINED3D_RS_DIFFUSEMATERIALSOURCE],
+                state->render_states[WINED3D_RS_AMBIENTMATERIALSOURCE],
+                state->render_states[WINED3D_RS_EMISSIVEMATERIALSOURCE],
+                state->render_states[WINED3D_RS_SPECULARMATERIALSOURCE]);
+
+        if (state->render_states[WINED3D_RS_DIFFUSEMATERIALSOURCE] == WINED3D_MCS_COLOR1)
+        {
+            if (state->render_states[WINED3D_RS_AMBIENTMATERIALSOURCE] == WINED3D_MCS_COLOR1)
+                Parm = GL_AMBIENT_AND_DIFFUSE;
+            else
+                Parm = GL_DIFFUSE;
+            if (state->render_states[WINED3D_RS_EMISSIVEMATERIALSOURCE] == WINED3D_MCS_COLOR1)
+            {
+                context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
+                context->num_untracked_materials++;
+            }
+            if (state->render_states[WINED3D_RS_SPECULARMATERIALSOURCE] == WINED3D_MCS_COLOR1)
+            {
+                context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
+                context->num_untracked_materials++;
+            }
+        }
+        else if (state->render_states[WINED3D_RS_AMBIENTMATERIALSOURCE] == WINED3D_MCS_COLOR1)
+        {
+            Parm = GL_AMBIENT;
+            if (state->render_states[WINED3D_RS_EMISSIVEMATERIALSOURCE] == WINED3D_MCS_COLOR1)
+            {
+                context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
+                context->num_untracked_materials++;
+            }
+            if (state->render_states[WINED3D_RS_SPECULARMATERIALSOURCE] == WINED3D_MCS_COLOR1)
+            {
+                context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
+                context->num_untracked_materials++;
+            }
+        }
+        else if (state->render_states[WINED3D_RS_EMISSIVEMATERIALSOURCE] == WINED3D_MCS_COLOR1)
+        {
+            Parm = GL_EMISSION;
+            if (state->render_states[WINED3D_RS_SPECULARMATERIALSOURCE] == WINED3D_MCS_COLOR1)
+            {
+                context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
+                context->num_untracked_materials++;
+            }
+        }
+        else if (state->render_states[WINED3D_RS_SPECULARMATERIALSOURCE] == WINED3D_MCS_COLOR1)
+        {
+            Parm = GL_SPECULAR;
+        }
+    }
+
+    /* Nothing changed, return. */
+    if (Parm == context->tracking_parm) return;
+
+    if (!Parm)
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_COLOR_MATERIAL);
+        checkGLcall("glDisable GL_COLOR_MATERIAL");
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glColorMaterial(GL_FRONT_AND_BACK, Parm);
+        checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
+        gl_info->gl_ops.gl.p_glEnable(GL_COLOR_MATERIAL);
+        checkGLcall("glEnable(GL_COLOR_MATERIAL)");
+    }
+
+    /* Apparently calls to glMaterialfv are ignored for properties we're
+     * tracking with glColorMaterial, so apply those here. */
+    switch (context->tracking_parm)
+    {
+        case GL_AMBIENT_AND_DIFFUSE:
+            gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float *)&state->material.ambient);
+            gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float *)&state->material.diffuse);
+            checkGLcall("glMaterialfv");
+            break;
+
+        case GL_DIFFUSE:
+            gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float *)&state->material.diffuse);
+            checkGLcall("glMaterialfv");
+            break;
+
+        case GL_AMBIENT:
+            gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float *)&state->material.ambient);
+            checkGLcall("glMaterialfv");
+            break;
+
+        case GL_EMISSION:
+            gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float *)&state->material.emissive);
+            checkGLcall("glMaterialfv");
+            break;
+
+        case GL_SPECULAR:
+            /* Only change material color if specular is enabled, otherwise it is set to black */
+            if (state->render_states[WINED3D_RS_SPECULARENABLE])
+            {
+                gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float *)&state->material.specular);
+                checkGLcall("glMaterialfv");
+            }
+            else
+            {
+                static const GLfloat black[] = {0.0f, 0.0f, 0.0f, 0.0f};
+                gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
+                checkGLcall("glMaterialfv");
+            }
+            break;
+    }
+
+    context->tracking_parm = Parm;
+}
+
+static void state_linepattern(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    union
+    {
+        DWORD d;
+        struct wined3d_line_pattern lp;
+    } tmppattern;
+    tmppattern.d = state->render_states[WINED3D_RS_LINEPATTERN];
+
+    TRACE("Line pattern: repeat %d bits %x.\n", tmppattern.lp.repeat_factor, tmppattern.lp.line_pattern);
+
+    if (tmppattern.lp.repeat_factor)
+    {
+        gl_info->gl_ops.gl.p_glLineStipple(tmppattern.lp.repeat_factor, tmppattern.lp.line_pattern);
+        checkGLcall("glLineStipple(repeat, linepattern)");
+        gl_info->gl_ops.gl.p_glEnable(GL_LINE_STIPPLE);
+        checkGLcall("glEnable(GL_LINE_STIPPLE);");
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_LINE_STIPPLE);
+        checkGLcall("glDisable(GL_LINE_STIPPLE);");
+    }
+}
+
+static void state_normalize(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    if (isStateDirty(context, STATE_VDECL))
+        return;
+
+    /* Without vertex normals, we set the current normal to 0/0/0 to remove the diffuse factor
+     * from the opengl lighting equation, as d3d does. Normalization of 0/0/0 can lead to a division
+     * by zero and is not properly defined in opengl, so avoid it
+     */
+    if (state->render_states[WINED3D_RS_NORMALIZENORMALS]
+            && (context->swapchain->device->stream_info.use_map & (1 << WINED3D_FFP_NORMAL)))
+    {
+        gl_info->gl_ops.gl.p_glEnable(GL_NORMALIZE);
+        checkGLcall("glEnable(GL_NORMALIZE);");
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_NORMALIZE);
+        checkGLcall("glDisable(GL_NORMALIZE);");
+    }
+}
+
+void state_psizemin_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    union {
+        DWORD d;
+        float f;
+    } tmpvalue;
+
+    tmpvalue.d = state->render_states[WINED3D_RS_POINTSIZE_MIN];
+    if (tmpvalue.f != 1.0f)
+    {
+        FIXME("WINED3D_RS_POINTSIZE_MIN not supported on this opengl, value is %f\n", tmpvalue.f);
+    }
+    tmpvalue.d = state->render_states[WINED3D_RS_POINTSIZE_MAX];
+    if (tmpvalue.f != 64.0f)
+    {
+        FIXME("WINED3D_RS_POINTSIZE_MAX not supported on this opengl, value is %f\n", tmpvalue.f);
+    }
+
+}
+
+void state_psizemin_ext(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    union
+    {
+        DWORD d;
+        float f;
+    } min, max;
+
+    min.d = state->render_states[WINED3D_RS_POINTSIZE_MIN];
+    max.d = state->render_states[WINED3D_RS_POINTSIZE_MAX];
+
+    /* Max point size trumps min point size */
+    if(min.f > max.f) {
+        min.f = max.f;
+    }
+
+    GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, min.f);
+    checkGLcall("glPointParameterfEXT(...)");
+    GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, max.f);
+    checkGLcall("glPointParameterfEXT(...)");
+}
+
+void state_psizemin_arb(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    union
+    {
+        DWORD d;
+        float f;
+    } min, max;
+
+    min.d = state->render_states[WINED3D_RS_POINTSIZE_MIN];
+    max.d = state->render_states[WINED3D_RS_POINTSIZE_MAX];
+
+    /* Max point size trumps min point size */
+    if(min.f > max.f) {
+        min.f = max.f;
+    }
+
+    GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MIN_ARB, min.f);
+    checkGLcall("glPointParameterfARB(...)");
+    GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MAX_ARB, max.f);
+    checkGLcall("glPointParameterfARB(...)");
+}
+
+void state_pscale(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    /* TODO: Group this with the viewport */
+    /*
+     * POINTSCALEENABLE controls how point size value is treated. If set to
+     * true, the point size is scaled with respect to height of viewport.
+     * When set to false point size is in pixels.
+     */
+
+    /* Default values */
+    GLfloat att[3] = {1.0f, 0.0f, 0.0f};
+    union {
+        DWORD d;
+        float f;
+    } pointSize, A, B, C;
+
+    pointSize.d = state->render_states[WINED3D_RS_POINTSIZE];
+    A.d = state->render_states[WINED3D_RS_POINTSCALE_A];
+    B.d = state->render_states[WINED3D_RS_POINTSCALE_B];
+    C.d = state->render_states[WINED3D_RS_POINTSCALE_C];
+
+    if (state->render_states[WINED3D_RS_POINTSCALEENABLE])
+    {
+        DWORD h = state->viewport.height;
+        GLfloat scaleFactor;
+
+        if (pointSize.f < gl_info->limits.pointsize_min)
+        {
+            /* Minimum valid point size for OpenGL is driver specific. For Direct3D it is
+             * 0.0f. This means that OpenGL will clamp really small point sizes to the
+             * driver minimum. To correct for this we need to multiply by the scale factor when sizes
+             * are less than 1.0f. scale_factor =  1.0f / point_size.
+             */
+            scaleFactor = pointSize.f / gl_info->limits.pointsize_min;
+            /* Clamp the point size, don't rely on the driver to do it. MacOS says min point size
+             * is 1.0, but then accepts points below that and draws too small points
+             */
+            pointSize.f = gl_info->limits.pointsize_min;
+        }
+        else if(pointSize.f > gl_info->limits.pointsize_max)
+        {
+            /* gl already scales the input to glPointSize,
+             * d3d scales the result after the point size scale.
+             * If the point size is bigger than the max size, use the
+             * scaling to scale it bigger, and set the gl point size to max
+             */
+            scaleFactor = pointSize.f / gl_info->limits.pointsize_max;
+            TRACE("scale: %f\n", scaleFactor);
+            pointSize.f = gl_info->limits.pointsize_max;
+        } else {
+            scaleFactor = 1.0f;
+        }
+        scaleFactor = powf(h * scaleFactor, 2);
+
+        att[0] = A.f / scaleFactor;
+        att[1] = B.f / scaleFactor;
+        att[2] = C.f / scaleFactor;
+    }
+
+    if (gl_info->supported[ARB_POINT_PARAMETERS])
+    {
+        GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
+        checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...)");
+    }
+    else if (gl_info->supported[EXT_POINT_PARAMETERS])
+    {
+        GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
+        checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...)");
+    }
+    else if (state->render_states[WINED3D_RS_POINTSCALEENABLE])
+    {
+        WARN("POINT_PARAMETERS not supported in this version of opengl\n");
+    }
+
+    gl_info->gl_ops.gl.p_glPointSize(pointSize.f);
+    checkGLcall("glPointSize(...);");
+}
+
+static void state_debug_monitor(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    WARN("token: %#x.\n", state->render_states[WINED3D_RS_DEBUGMONITORTOKEN]);
+}
+
+static void state_colorwrite(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    DWORD mask0 = state->render_states[WINED3D_RS_COLORWRITEENABLE];
+    DWORD mask1 = state->render_states[WINED3D_RS_COLORWRITEENABLE1];
+    DWORD mask2 = state->render_states[WINED3D_RS_COLORWRITEENABLE2];
+    DWORD mask3 = state->render_states[WINED3D_RS_COLORWRITEENABLE3];
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
+            mask0 & WINED3DCOLORWRITEENABLE_RED ? 1 : 0,
+            mask0 & WINED3DCOLORWRITEENABLE_GREEN ? 1 : 0,
+            mask0 & WINED3DCOLORWRITEENABLE_BLUE ? 1 : 0,
+            mask0 & WINED3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
+    gl_info->gl_ops.gl.p_glColorMask(mask0 & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
+            mask0 & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
+            mask0 & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
+            mask0 & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
+    checkGLcall("glColorMask(...)");
+
+    if (!((mask1 == mask0 && mask2 == mask0 && mask3 == mask0)
+        || (mask1 == 0xf && mask2 == 0xf && mask3 == 0xf)))
+    {
+        FIXME("WINED3D_RS_COLORWRITEENABLE/1/2/3, %#x/%#x/%#x/%#x not yet implemented.\n",
+            mask0, mask1, mask2, mask3);
+        FIXME("Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n");
+    }
+}
+
+static void set_color_mask(const struct wined3d_gl_info *gl_info, UINT index, DWORD mask)
+{
+    GL_EXTCALL(glColorMaskIndexedEXT(index,
+            mask & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
+            mask & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
+            mask & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
+            mask & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE));
+}
+
+static void state_colorwrite0(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    set_color_mask(context->gl_info, 0, state->render_states[WINED3D_RS_COLORWRITEENABLE]);
+}
+
+static void state_colorwrite1(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    set_color_mask(context->gl_info, 1, state->render_states[WINED3D_RS_COLORWRITEENABLE1]);
+}
+
+static void state_colorwrite2(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    set_color_mask(context->gl_info, 2, state->render_states[WINED3D_RS_COLORWRITEENABLE2]);
+}
+
+static void state_colorwrite3(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    set_color_mask(context->gl_info, 3, state->render_states[WINED3D_RS_COLORWRITEENABLE3]);
+}
+
+static void state_localviewer(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    if (state->render_states[WINED3D_RS_LOCALVIEWER])
+    {
+        gl_info->gl_ops.gl.p_glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
+        checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1)");
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
+        checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0)");
+    }
+}
+
+static void state_lastpixel(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    if (state->render_states[WINED3D_RS_LASTPIXEL])
+    {
+        TRACE("Last Pixel Drawing Enabled\n");
+    }
+    else
+    {
+        static BOOL warned;
+        if (!warned) {
+            FIXME("Last Pixel Drawing Disabled, not handled yet\n");
+            warned = TRUE;
+        } else {
+            TRACE("Last Pixel Drawing Disabled, not handled yet\n");
+        }
+    }
+}
+
+void state_pointsprite_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    static BOOL warned;
+
+    /* TODO: NV_POINT_SPRITE */
+    if (!warned && state->render_states[WINED3D_RS_POINTSPRITEENABLE])
+    {
+        /* A FIXME, not a WARN because point sprites should be software emulated if not supported by HW */
+        FIXME("Point sprites not supported\n");
+        warned = TRUE;
+    }
+}
+
+void state_pointsprite(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    if (state->render_states[WINED3D_RS_POINTSPRITEENABLE])
+    {
+        gl_info->gl_ops.gl.p_glEnable(GL_POINT_SPRITE_ARB);
+        checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_POINT_SPRITE_ARB);
+        checkGLcall("glDisable(GL_POINT_SPRITE_ARB)");
+    }
+}
+
+static void state_wrap(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    if (state->render_states[WINED3D_RS_WRAP0]
+            || state->render_states[WINED3D_RS_WRAP1]
+            || state->render_states[WINED3D_RS_WRAP2]
+            || state->render_states[WINED3D_RS_WRAP3]
+            || state->render_states[WINED3D_RS_WRAP4]
+            || state->render_states[WINED3D_RS_WRAP5]
+            || state->render_states[WINED3D_RS_WRAP6]
+            || state->render_states[WINED3D_RS_WRAP7]
+            || state->render_states[WINED3D_RS_WRAP8]
+            || state->render_states[WINED3D_RS_WRAP9]
+            || state->render_states[WINED3D_RS_WRAP10]
+            || state->render_states[WINED3D_RS_WRAP11]
+            || state->render_states[WINED3D_RS_WRAP12]
+            || state->render_states[WINED3D_RS_WRAP13]
+            || state->render_states[WINED3D_RS_WRAP14]
+            || state->render_states[WINED3D_RS_WRAP15])
+        FIXME("(WINED3D_RS_WRAP0) Texture wrapping not yet supported.\n");
+}
+
+static void state_msaa_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    if (state->render_states[WINED3D_RS_MULTISAMPLEANTIALIAS])
+        WARN("Multisample antialiasing not supported by GL.\n");
+}
+
+static void state_msaa(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    if (state->render_states[WINED3D_RS_MULTISAMPLEANTIALIAS])
+    {
+        gl_info->gl_ops.gl.p_glEnable(GL_MULTISAMPLE_ARB);
+        checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_MULTISAMPLE_ARB);
+        checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
+    }
+}
+
+static void state_scissor(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    if (state->render_states[WINED3D_RS_SCISSORTESTENABLE])
+    {
+        gl_info->gl_ops.gl.p_glEnable(GL_SCISSOR_TEST);
+        checkGLcall("glEnable(GL_SCISSOR_TEST)");
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_SCISSOR_TEST);
+        checkGLcall("glDisable(GL_SCISSOR_TEST)");
+    }
+}
+
+/* The Direct3D depth bias is specified in normalized depth coordinates. In
+ * OpenGL the bias is specified in units of "the smallest value that is
+ * guaranteed to produce a resolvable offset for a given implementation". To
+ * convert from D3D to GL we need to divide the D3D depth bias by that value.
+ * There's no practical way to retrieve that value from a given GL
+ * implementation, but the D3D application has essentially the same problem,
+ * which makes a guess of the depth buffer format's highest possible value a
+ * reasonable guess. Note that SLOPESCALEDEPTHBIAS is a scaling factor for the
+ * depth slope, and doesn't need to be scaled. */
+static void state_depthbias(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    if (state->render_states[WINED3D_RS_SLOPESCALEDEPTHBIAS]
+            || state->render_states[WINED3D_RS_DEPTHBIAS])
+    {
+        const struct wined3d_surface *depth = state->fb->depth_stencil;
+        float scale;
+
+        union
+        {
+            DWORD d;
+            float f;
+        } scale_bias, const_bias;
+
+        scale_bias.d = state->render_states[WINED3D_RS_SLOPESCALEDEPTHBIAS];
+        const_bias.d = state->render_states[WINED3D_RS_DEPTHBIAS];
+
+        gl_info->gl_ops.gl.p_glEnable(GL_POLYGON_OFFSET_FILL);
+        checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
+
+        if (context->swapchain->device->wined3d->flags & WINED3D_LEGACY_DEPTH_BIAS)
+        {
+            float bias = -(float)const_bias.d;
+            gl_info->gl_ops.gl.p_glPolygonOffset(bias, bias);
+            checkGLcall("glPolygonOffset");
+        }
+        else
+        {
+            if (depth)
+            {
+                const struct wined3d_format *fmt = depth->resource.format;
+                scale = powf(2, fmt->depth_size) - 1;
+                TRACE("Depth format %s, using depthbias scale of %.8e.\n",
+                      debug_d3dformat(fmt->id), scale);
+            }
+            else
+            {
+                /* The context manager will reapply this state on a depth stencil change */
+                TRACE("No depth stencil, using depthbias scale of 0.0.\n");
+                scale = 0.0f;
+            }
+
+            gl_info->gl_ops.gl.p_glPolygonOffset(scale_bias.f, const_bias.f * scale);
+            checkGLcall("glPolygonOffset(...)");
+        }
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_POLYGON_OFFSET_FILL);
+        checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
+    }
+}
+
+static void state_zvisible(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    if (state->render_states[WINED3D_RS_ZVISIBLE])
+        FIXME("WINED3D_RS_ZVISIBLE not implemented.\n");
+}
+
+static void state_perspective(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    if (state->render_states[WINED3D_RS_TEXTUREPERSPECTIVE])
+    {
+        gl_info->gl_ops.gl.p_glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
+        checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)");
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
+        checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)");
+    }
+}
+
+static void state_stippledalpha(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    if (state->render_states[WINED3D_RS_STIPPLEDALPHA])
+        FIXME("Stippled Alpha not supported yet.\n");
+}
+
+static void state_antialias(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    if (state->render_states[WINED3D_RS_ANTIALIAS])
+        FIXME("Antialias not supported yet.\n");
+}
+
+static void state_multisampmask(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    if (state->render_states[WINED3D_RS_MULTISAMPLEMASK] != 0xffffffff)
+        FIXME("WINED3D_RS_MULTISAMPLEMASK %#x not yet implemented.\n",
+                state->render_states[WINED3D_RS_MULTISAMPLEMASK]);
+}
+
+static void state_patchedgestyle(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    if (state->render_states[WINED3D_RS_PATCHEDGESTYLE] != WINED3D_PATCH_EDGE_DISCRETE)
+        FIXME("WINED3D_RS_PATCHEDGESTYLE %#x not yet implemented.\n",
+                state->render_states[WINED3D_RS_PATCHEDGESTYLE]);
+}
+
+static void state_patchsegments(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    union {
+        DWORD d;
+        float f;
+    } tmpvalue;
+    tmpvalue.f = 1.0f;
+
+    if (state->render_states[WINED3D_RS_PATCHSEGMENTS] != tmpvalue.d)
+    {
+        static BOOL displayed = FALSE;
+
+        tmpvalue.d = state->render_states[WINED3D_RS_PATCHSEGMENTS];
+        if(!displayed)
+            FIXME("(WINED3D_RS_PATCHSEGMENTS,%f) not yet implemented\n", tmpvalue.f);
+
+        displayed = TRUE;
+    }
+}
+
+static void state_positiondegree(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    if (state->render_states[WINED3D_RS_POSITIONDEGREE] != WINED3D_DEGREE_CUBIC)
+        FIXME("WINED3D_RS_POSITIONDEGREE %#x not yet implemented.\n",
+                state->render_states[WINED3D_RS_POSITIONDEGREE]);
+}
+
+static void state_normaldegree(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    if (state->render_states[WINED3D_RS_NORMALDEGREE] != WINED3D_DEGREE_LINEAR)
+        FIXME("WINED3D_RS_NORMALDEGREE %#x not yet implemented.\n",
+                state->render_states[WINED3D_RS_NORMALDEGREE]);
+}
+
+static void state_tessellation(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    if (state->render_states[WINED3D_RS_ENABLEADAPTIVETESSELLATION])
+        FIXME("WINED3D_RS_ENABLEADAPTIVETESSELLATION %#x not yet implemented.\n",
+                state->render_states[WINED3D_RS_ENABLEADAPTIVETESSELLATION]);
+}
+
+static void state_nvdb(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    union {
+        DWORD d;
+        float f;
+    } zmin, zmax;
+
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    if (state->render_states[WINED3D_RS_ADAPTIVETESS_X] == WINED3DFMT_NVDB)
+    {
+        zmin.d = state->render_states[WINED3D_RS_ADAPTIVETESS_Z];
+        zmax.d = state->render_states[WINED3D_RS_ADAPTIVETESS_W];
+
+        /* If zmin is larger than zmax INVALID_VALUE error is generated.
+         * In d3d9 test is not performed in this case*/
+        if (zmin.f <= zmax.f)
+        {
+            gl_info->gl_ops.gl.p_glEnable(GL_DEPTH_BOUNDS_TEST_EXT);
+            checkGLcall("glEnable(GL_DEPTH_BOUNDS_TEST_EXT)");
+            GL_EXTCALL(glDepthBoundsEXT(zmin.f, zmax.f));
+            checkGLcall("glDepthBoundsEXT(...)");
+        }
+        else
+        {
+            gl_info->gl_ops.gl.p_glDisable(GL_DEPTH_BOUNDS_TEST_EXT);
+            checkGLcall("glDisable(GL_DEPTH_BOUNDS_TEST_EXT)");
+        }
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_DEPTH_BOUNDS_TEST_EXT);
+        checkGLcall("glDisable(GL_DEPTH_BOUNDS_TEST_EXT)");
+    }
+
+    state_tessellation(context, state, STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION));
+}
+
+static void state_wrapu(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    if (state->render_states[WINED3D_RS_WRAPU])
+        FIXME("Render state WINED3D_RS_WRAPU not implemented yet.\n");
+}
+
+static void state_wrapv(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    if (state->render_states[WINED3D_RS_WRAPV])
+        FIXME("Render state WINED3D_RS_WRAPV not implemented yet.\n");
+}
+
+static void state_monoenable(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    if (state->render_states[WINED3D_RS_MONOENABLE])
+        FIXME("Render state WINED3D_RS_MONOENABLE not implemented yet.\n");
+}
+
+static void state_rop2(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    if (state->render_states[WINED3D_RS_ROP2])
+        FIXME("Render state WINED3D_RS_ROP2 not implemented yet.\n");
+}
+
+static void state_planemask(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    if (state->render_states[WINED3D_RS_PLANEMASK])
+        FIXME("Render state WINED3D_RS_PLANEMASK not implemented yet.\n");
+}
+
+static void state_subpixel(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    if (state->render_states[WINED3D_RS_SUBPIXEL])
+        FIXME("Render state WINED3D_RS_SUBPIXEL not implemented yet.\n");
+}
+
+static void state_subpixelx(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    if (state->render_states[WINED3D_RS_SUBPIXELX])
+        FIXME("Render state WINED3D_RS_SUBPIXELX not implemented yet.\n");
+}
+
+static void state_stippleenable(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    if (state->render_states[WINED3D_RS_STIPPLEENABLE])
+        FIXME("Render state WINED3D_RS_STIPPLEENABLE not implemented yet.\n");
+}
+
+static void state_mipmaplodbias(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    if (state->render_states[WINED3D_RS_MIPMAPLODBIAS])
+        FIXME("Render state WINED3D_RS_MIPMAPLODBIAS not implemented yet.\n");
+}
+
+static void state_anisotropy(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    if (state->render_states[WINED3D_RS_ANISOTROPY])
+        FIXME("Render state WINED3D_RS_ANISOTROPY not implemented yet.\n");
+}
+
+static void state_flushbatch(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    if (state->render_states[WINED3D_RS_FLUSHBATCH])
+        FIXME("Render state WINED3D_RS_FLUSHBATCH not implemented yet.\n");
+}
+
+static void state_translucentsi(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    if (state->render_states[WINED3D_RS_TRANSLUCENTSORTINDEPENDENT])
+        FIXME("Render state WINED3D_RS_TRANSLUCENTSORTINDEPENDENT not implemented yet.\n");
+}
+
+static void state_extents(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    if (state->render_states[WINED3D_RS_EXTENTS])
+        FIXME("Render state WINED3D_RS_EXTENTS not implemented yet.\n");
+}
+
+static void state_ckeyblend(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    if (state->render_states[WINED3D_RS_COLORKEYBLENDENABLE])
+        FIXME("Render state WINED3D_RS_COLORKEYBLENDENABLE not implemented yet.\n");
+}
+
+static void state_swvp(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    if (state->render_states[WINED3D_RS_SOFTWAREVERTEXPROCESSING])
+        FIXME("Software vertex processing not implemented.\n");
+}
+
+static void get_src_and_opr(DWORD arg, BOOL is_alpha, GLenum* source, GLenum* operand) {
+    /* The WINED3DTA_ALPHAREPLICATE flag specifies the alpha component of the
+    * input should be used for all input components. The WINED3DTA_COMPLEMENT
+    * flag specifies the complement of the input should be used. */
+    BOOL from_alpha = is_alpha || arg & WINED3DTA_ALPHAREPLICATE;
+    BOOL complement = arg & WINED3DTA_COMPLEMENT;
+
+    /* Calculate the operand */
+    if (complement) {
+        if (from_alpha) *operand = GL_ONE_MINUS_SRC_ALPHA;
+        else *operand = GL_ONE_MINUS_SRC_COLOR;
+    } else {
+        if (from_alpha) *operand = GL_SRC_ALPHA;
+        else *operand = GL_SRC_COLOR;
+    }
+
+    /* Calculate the source */
+    switch (arg & WINED3DTA_SELECTMASK) {
+        case WINED3DTA_CURRENT: *source = GL_PREVIOUS_EXT; break;
+        case WINED3DTA_DIFFUSE: *source = GL_PRIMARY_COLOR_EXT; break;
+        case WINED3DTA_TEXTURE: *source = GL_TEXTURE; break;
+        case WINED3DTA_TFACTOR: *source = GL_CONSTANT_EXT; break;
+        case WINED3DTA_SPECULAR:
+            /*
+            * According to the GL_ARB_texture_env_combine specs, SPECULAR is
+            * 'Secondary color' and isn't supported until base GL supports it
+            * There is no concept of temp registers as far as I can tell
+            */
+            FIXME("Unhandled texture arg WINED3DTA_SPECULAR\n");
+            *source = GL_TEXTURE;
+            break;
+        default:
+            FIXME("Unrecognized texture arg %#x\n", arg);
+            *source = GL_TEXTURE;
+            break;
+    }
+}
+
+/* Setup the texture operations texture stage states */
+static void set_tex_op(const struct wined3d_gl_info *gl_info, const struct wined3d_state *state,
+        BOOL isAlpha, int Stage, enum wined3d_texture_op op, DWORD arg1, DWORD arg2, DWORD arg3)
+{
+    GLenum src1, src2, src3;
+    GLenum opr1, opr2, opr3;
+    GLenum comb_target;
+    GLenum src0_target, src1_target, src2_target;
+    GLenum opr0_target, opr1_target, opr2_target;
+    GLenum scal_target;
+    GLenum opr=0, invopr, src3_target, opr3_target;
+    BOOL Handled = FALSE;
+
+    TRACE("Alpha?(%d), Stage:%d Op(%s), a1(%d), a2(%d), a3(%d)\n", isAlpha, Stage, debug_d3dtop(op), arg1, arg2, arg3);
+
+    /* This is called by a state handler which has the gl lock held and a context for the thread */
+
+        /* Note: Operations usually involve two ars, src0 and src1 and are operations of
+    the form (a1 <operation> a2). However, some of the more complex operations
+    take 3 parameters. Instead of the (sensible) addition of a3, Microsoft added
+    in a third parameter called a0. Therefore these are operations of the form
+    a0 <operation> a1 <operation> a2, i.e., the new parameter goes to the front.
+
+    However, below we treat the new (a0) parameter as src2/opr2, so in the actual
+    functions below, expect their syntax to differ slightly to those listed in the
+    manuals, i.e., replace arg1 with arg3, arg2 with arg1 and arg3 with arg2
+    This affects WINED3DTOP_MULTIPLYADD and WINED3DTOP_LERP                     */
+
+    if (isAlpha)
+    {
+        comb_target = GL_COMBINE_ALPHA;
+        src0_target = GL_SOURCE0_ALPHA;
+        src1_target = GL_SOURCE1_ALPHA;
+        src2_target = GL_SOURCE2_ALPHA;
+        opr0_target = GL_OPERAND0_ALPHA;
+        opr1_target = GL_OPERAND1_ALPHA;
+        opr2_target = GL_OPERAND2_ALPHA;
+        scal_target = GL_ALPHA_SCALE;
+    }
+    else
+    {
+        comb_target = GL_COMBINE_RGB;
+        src0_target = GL_SOURCE0_RGB;
+        src1_target = GL_SOURCE1_RGB;
+        src2_target = GL_SOURCE2_RGB;
+        opr0_target = GL_OPERAND0_RGB;
+        opr1_target = GL_OPERAND1_RGB;
+        opr2_target = GL_OPERAND2_RGB;
+        scal_target = GL_RGB_SCALE;
+    }
+
+        /* If a texture stage references an invalid texture unit the stage just
+        * passes through the result from the previous stage */
+    if (is_invalid_op(state, Stage, op, arg1, arg2, arg3))
+    {
+        arg1 = WINED3DTA_CURRENT;
+        op = WINED3D_TOP_SELECT_ARG1;
+    }
+
+    if (isAlpha && !state->textures[Stage] && arg1 == WINED3DTA_TEXTURE)
+    {
+        get_src_and_opr(WINED3DTA_DIFFUSE, isAlpha, &src1, &opr1);
+    } else {
+        get_src_and_opr(arg1, isAlpha, &src1, &opr1);
+    }
+    get_src_and_opr(arg2, isAlpha, &src2, &opr2);
+    get_src_and_opr(arg3, isAlpha, &src3, &opr3);
+
+    TRACE("ct(%x), 1:(%x,%x), 2:(%x,%x), 3:(%x,%x)\n", comb_target, src1, opr1, src2, opr2, src3, opr3);
+
+    Handled = TRUE; /* Assume will be handled */
+
+    /* Other texture operations require special extensions: */
+    if (gl_info->supported[NV_TEXTURE_ENV_COMBINE4])
+    {
+        if (isAlpha) {
+            opr = GL_SRC_ALPHA;
+            invopr = GL_ONE_MINUS_SRC_ALPHA;
+            src3_target = GL_SOURCE3_ALPHA_NV;
+            opr3_target = GL_OPERAND3_ALPHA_NV;
+        } else {
+            opr = GL_SRC_COLOR;
+            invopr = GL_ONE_MINUS_SRC_COLOR;
+            src3_target = GL_SOURCE3_RGB_NV;
+            opr3_target = GL_OPERAND3_RGB_NV;
+        }
+        switch (op)
+        {
+            case WINED3D_TOP_DISABLE: /* Only for alpha */
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT);
+                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA);
+                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
+                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
+                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
+                checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
+                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
+                checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
+                checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
+                break;
+
+            case WINED3D_TOP_SELECT_ARG1: /* = a1 * 1 + 0 * 0 */
+            case WINED3D_TOP_SELECT_ARG2: /* = a2 * 1 + 0 * 0 */
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+                if (op == WINED3D_TOP_SELECT_ARG1)
+                {
+                    gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+                    checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+                    gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+                    checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+                }
+                else
+                {
+                    gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
+                    checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
+                    gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
+                    checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
+                }
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
+                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
+                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
+                checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
+                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
+                checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
+                checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
+                break;
+
+            case WINED3D_TOP_MODULATE:
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
+                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
+                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
+                checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
+                checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+                break;
+            case WINED3D_TOP_MODULATE_2X:
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
+                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
+                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
+                checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
+                checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
+                checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
+                break;
+            case WINED3D_TOP_MODULATE_4X:
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
+                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
+                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
+                checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
+                checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
+                checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
+                break;
+
+            case WINED3D_TOP_ADD:
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
+                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
+                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
+                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
+                checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
+                checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+                break;
+
+            case WINED3D_TOP_ADD_SIGNED:
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD_SIGNED);
+                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD_SIGNED");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
+                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
+                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
+                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
+                checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
+                checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+                break;
+
+            case WINED3D_TOP_ADD_SIGNED_2X:
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD_SIGNED);
+                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD_SIGNED");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
+                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
+                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
+                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
+                checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
+                checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
+                checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
+                break;
+
+            case WINED3D_TOP_ADD_SMOOTH:
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
+                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
+                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
+                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
+                checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
+                switch (opr1) {
+                    case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
+                    case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
+                    case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+                    case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
+                }
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
+                checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+                break;
+
+            case WINED3D_TOP_BLEND_DIFFUSE_ALPHA:
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_PRIMARY_COLOR);
+                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_PRIMARY_COLOR");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
+                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
+                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_PRIMARY_COLOR);
+                checkGLcall("GL_TEXTURE_ENV, src3_target, GL_PRIMARY_COLOR");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
+                checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+                break;
+            case WINED3D_TOP_BLEND_TEXTURE_ALPHA:
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_TEXTURE);
+                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_TEXTURE");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
+                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
+                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
+                checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
+                checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+                break;
+            case WINED3D_TOP_BLEND_FACTOR_ALPHA:
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_CONSTANT);
+                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_CONSTANT");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
+                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
+                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_CONSTANT);
+                checkGLcall("GL_TEXTURE_ENV, src3_target, GL_CONSTANT");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
+                checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+                break;
+            case WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM:
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
+                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
+                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
+                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
+                checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
+                checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+                break;
+            case WINED3D_TOP_MODULATE_ALPHA_ADD_COLOR:
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");                 /* Add = a0*a1 + a2*a3 */
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);  /*  a0 = src1/opr1     */
+                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");                   /*  a1 = 1 (see docs)  */
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
+                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
+                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);  /*  a2 = arg2          */
+                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");                   /*  a3 = src1 alpha    */
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
+                checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
+                switch (opr) {
+                    case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
+                    case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+                }
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
+                checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+                break;
+            case WINED3D_TOP_MODULATE_COLOR_ADD_ALPHA:
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+                checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+                checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
+                checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
+                switch (opr1) {
+                    case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
+                    case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+                }
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
+                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
+                checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
+                checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+                break;
+            case WINED3D_TOP_MODULATE_INVALPHA_ADD_COLOR:
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
+                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
+                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
+                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
+                checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
+                switch (opr1) {
+                    case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+                    case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
+                    case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+                    case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
+                }
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
+                checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+                break;
+            case WINED3D_TOP_MODULATE_INVCOLOR_ADD_ALPHA:
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+                switch (opr1) {
+                    case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
+                    case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
+                    case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+                    case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
+                }
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
+                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+                checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+                checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
+                checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
+                switch (opr1) {
+                    case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
+                    case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+                }
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
+                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
+                checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
+                checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+                break;
+            case WINED3D_TOP_MULTIPLY_ADD:
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src3);
+                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr3);
+                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
+                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
+                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
+                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr1);
+                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, src2);
+                checkGLcall("GL_TEXTURE_ENV, src3_target, src3");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr2);
+                checkGLcall("GL_TEXTURE_ENV, opr3_target, opr3");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+                break;
+
+            case WINED3D_TOP_BUMPENVMAP:
+            case WINED3D_TOP_BUMPENVMAP_LUMINANCE:
+                FIXME("Implement bump environment mapping in GL_NV_texture_env_combine4 path\n");
+                Handled = FALSE;
+                break;
+
+            default:
+                Handled = FALSE;
+        }
+        if (Handled)
+        {
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
+            checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV");
+
+            return;
+        }
+    } /* GL_NV_texture_env_combine4 */
+
+    Handled = TRUE; /* Again, assume handled */
+    switch (op) {
+        case WINED3D_TOP_DISABLE: /* Only for alpha */
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
+            checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT);
+            checkGLcall("GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA);
+            checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+            checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+            break;
+        case WINED3D_TOP_SELECT_ARG1:
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
+            checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+            checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+            checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+            checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+            break;
+        case WINED3D_TOP_SELECT_ARG2:
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
+            checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
+            checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
+            checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+            checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+            break;
+        case WINED3D_TOP_MODULATE:
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
+            checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+            checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+            checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+            checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+            checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+            checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+            break;
+        case WINED3D_TOP_MODULATE_2X:
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
+            checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+            checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+            checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+            checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+            checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
+            checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
+            break;
+        case WINED3D_TOP_MODULATE_4X:
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
+            checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+            checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+            checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+            checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+            checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
+            checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
+            break;
+        case WINED3D_TOP_ADD:
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+            checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+            checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+            checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+            checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+            checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+            checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+            break;
+        case WINED3D_TOP_ADD_SIGNED:
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD_SIGNED);
+            checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD_SIGNED");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+            checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+            checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+            checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+            checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+            checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+            break;
+        case WINED3D_TOP_ADD_SIGNED_2X:
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD_SIGNED);
+            checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD_SIGNED");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+            checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+            checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+            checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+            checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
+            checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
+            break;
+        case WINED3D_TOP_SUBTRACT:
+            if (gl_info->supported[ARB_TEXTURE_ENV_COMBINE])
+            {
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_SUBTRACT);
+                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_SUBTRACT");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+                checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+                checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+            } else {
+                FIXME("This version of opengl does not support GL_SUBTRACT\n");
+            }
+            break;
+
+        case WINED3D_TOP_BLEND_DIFFUSE_ALPHA:
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_INTERPOLATE);
+            checkGLcall("GL_TEXTURE_ENV, comb_target, GL_INTERPOLATE");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+            checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+            checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+            checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+            checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_PRIMARY_COLOR);
+            checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PRIMARY_COLOR");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
+            checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+            checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+            break;
+        case WINED3D_TOP_BLEND_TEXTURE_ALPHA:
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_INTERPOLATE);
+            checkGLcall("GL_TEXTURE_ENV, comb_target, GL_INTERPOLATE");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+            checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+            checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+            checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+            checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_TEXTURE);
+            checkGLcall("GL_TEXTURE_ENV, src2_target, GL_TEXTURE");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
+            checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+            checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+            break;
+        case WINED3D_TOP_BLEND_FACTOR_ALPHA:
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_INTERPOLATE);
+            checkGLcall("GL_TEXTURE_ENV, comb_target, GL_INTERPOLATE");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+            checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+            checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+            checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+            checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_CONSTANT);
+            checkGLcall("GL_TEXTURE_ENV, src2_target, GL_CONSTANT");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
+            checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+            checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+            break;
+        case WINED3D_TOP_BLEND_CURRENT_ALPHA:
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_INTERPOLATE);
+            checkGLcall("GL_TEXTURE_ENV, comb_target, GL_INTERPOLATE");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+            checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+            checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+            checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+            checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_PREVIOUS);
+            checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PREVIOUS");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
+            checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+            checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+            break;
+        case WINED3D_TOP_DOTPRODUCT3:
+            if (gl_info->supported[ARB_TEXTURE_ENV_DOT3])
+            {
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB);
+                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB");
+            }
+            else if (gl_info->supported[EXT_TEXTURE_ENV_DOT3])
+            {
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT);
+                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT");
+            } else {
+                FIXME("This version of opengl does not support GL_DOT3\n");
+            }
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+            checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+            checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+            checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+            checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+            checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+            break;
+        case WINED3D_TOP_LERP:
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_INTERPOLATE);
+            checkGLcall("GL_TEXTURE_ENV, comb_target, GL_INTERPOLATE");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+            checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+            checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+            checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+            checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src3);
+            checkGLcall("GL_TEXTURE_ENV, src2_target, src3");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr3);
+            checkGLcall("GL_TEXTURE_ENV, opr2_target, opr3");
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+            checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+            break;
+        case WINED3D_TOP_ADD_SMOOTH:
+            if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
+            {
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
+                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+                switch (opr1) {
+                    case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
+                    case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
+                    case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+                    case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
+                }
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
+                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
+                checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
+                checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
+                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+            } else
+                Handled = FALSE;
+                break;
+        case WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM:
+            if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
+            {
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
+                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_TEXTURE);
+                checkGLcall("GL_TEXTURE_ENV, src0_target, GL_TEXTURE");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_ALPHA);
+                checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_APHA");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
+                checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
+                checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
+                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+            } else
+                Handled = FALSE;
+                break;
+        case WINED3D_TOP_MODULATE_ALPHA_ADD_COLOR:
+            if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
+            {
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
+                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+                switch (opr1) {
+                    case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
+                    case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+                    case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
+                    case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+                }
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
+                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
+                checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
+                checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
+                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+            } else
+                Handled = FALSE;
+                break;
+        case WINED3D_TOP_MODULATE_COLOR_ADD_ALPHA:
+            if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
+            {
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
+                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
+                checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
+                switch (opr1) {
+                    case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
+                    case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+                    case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
+                    case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+                }
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr);
+                checkGLcall("GL_TEXTURE_ENV, opr1_target, opr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
+                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+            } else
+                Handled = FALSE;
+                break;
+        case WINED3D_TOP_MODULATE_INVALPHA_ADD_COLOR:
+            if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
+            {
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
+                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+                switch (opr1) {
+                    case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+                    case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
+                    case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+                    case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
+                }
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
+                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
+                checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
+                checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
+                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+            } else
+                Handled = FALSE;
+                break;
+        case WINED3D_TOP_MODULATE_INVCOLOR_ADD_ALPHA:
+            if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
+            {
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
+                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+                switch (opr1) {
+                    case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
+                    case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
+                    case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+                    case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
+                }
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
+                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
+                checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
+                switch (opr1) {
+                    case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
+                    case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+                    case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
+                    case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+                }
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr);
+                checkGLcall("GL_TEXTURE_ENV, opr1_target, opr");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
+                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+            } else
+                Handled = FALSE;
+                break;
+        case WINED3D_TOP_MULTIPLY_ADD:
+            if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
+            {
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
+                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src3);
+                checkGLcall("GL_TEXTURE_ENV, src1_target, src3");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr3);
+                checkGLcall("GL_TEXTURE_ENV, opr1_target, opr3");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
+                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+            } else
+                Handled = FALSE;
+                break;
+        case WINED3D_TOP_BUMPENVMAP_LUMINANCE:
+        case WINED3D_TOP_BUMPENVMAP:
+            if (gl_info->supported[NV_TEXTURE_SHADER2])
+            {
+                /* Technically texture shader support without register combiners is possible, but not expected to occur
+                 * on real world cards, so for now a fixme should be enough
+                 */
+                FIXME("Implement bump mapping with GL_NV_texture_shader in non register combiner path\n");
+            }
+            Handled = FALSE;
+            break;
+
+        default:
+            Handled = FALSE;
+    }
+
+    if (Handled) {
+        BOOL  combineOK = TRUE;
+        if (gl_info->supported[NV_TEXTURE_ENV_COMBINE4])
+        {
+            DWORD op2;
+
+            if (isAlpha)
+                op2 = state->texture_states[Stage][WINED3D_TSS_COLOR_OP];
+            else
+                op2 = state->texture_states[Stage][WINED3D_TSS_ALPHA_OP];
+
+            /* Note: If COMBINE4 in effect can't go back to combine! */
+            switch (op2)
+            {
+                case WINED3D_TOP_ADD_SMOOTH:
+                case WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM:
+                case WINED3D_TOP_MODULATE_ALPHA_ADD_COLOR:
+                case WINED3D_TOP_MODULATE_COLOR_ADD_ALPHA:
+                case WINED3D_TOP_MODULATE_INVALPHA_ADD_COLOR:
+                case WINED3D_TOP_MODULATE_INVCOLOR_ADD_ALPHA:
+                case WINED3D_TOP_MULTIPLY_ADD:
+                    /* Ignore those implemented in both cases */
+                    switch (op)
+                    {
+                        case WINED3D_TOP_SELECT_ARG1:
+                        case WINED3D_TOP_SELECT_ARG2:
+                            combineOK = FALSE;
+                            Handled   = FALSE;
+                            break;
+                        default:
+                            FIXME("Can't use COMBINE4 and COMBINE together, thisop=%s, otherop=%s, isAlpha(%d)\n", debug_d3dtop(op), debug_d3dtop(op2), isAlpha);
+                            return;
+                    }
+            }
+        }
+
+        if (combineOK)
+        {
+            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
+            checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE");
+
+            return;
+        }
+    }
+
+    /* After all the extensions, if still unhandled, report fixme */
+    FIXME("Unhandled texture operation %s\n", debug_d3dtop(op));
+}
+
+
+static void tex_colorop(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
+    const struct wined3d_device *device = context->swapchain->device;
+    BOOL tex_used = device->fixed_function_usage_map & (1 << stage);
+    DWORD mapped_stage = device->texUnitMap[stage];
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    TRACE("Setting color op for stage %d\n", stage);
+
+    /* Using a pixel shader? Don't care for anything here, the shader applying does it */
+    if (use_ps(state)) return;
+
+    if (stage != mapped_stage) WARN("Using non 1:1 mapping: %d -> %d!\n", stage, mapped_stage);
+
+    if (mapped_stage != WINED3D_UNMAPPED_STAGE)
+    {
+        if (tex_used && mapped_stage >= gl_info->limits.textures)
+        {
+            FIXME("Attempt to enable unsupported stage!\n");
+            return;
+        }
+        context_active_texture(context, gl_info, mapped_stage);
+    }
+
+    if (stage >= state->lowest_disabled_stage)
+    {
+        TRACE("Stage disabled\n");
+        if (mapped_stage != WINED3D_UNMAPPED_STAGE)
+        {
+            /* Disable everything here */
+            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
+            checkGLcall("glDisable(GL_TEXTURE_2D)");
+            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
+            checkGLcall("glDisable(GL_TEXTURE_3D)");
+            if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
+            {
+                gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB);
+                checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
+            }
+            if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
+            {
+                gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB);
+                checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
+            }
+        }
+        /* All done */
+        return;
+    }
+
+    /* The sampler will also activate the correct texture dimensions, so no
+     * need to do it here if the sampler for this stage is dirty. */
+    if (!isStateDirty(context, STATE_SAMPLER(stage)) && tex_used)
+        texture_activate_dimensions(state->textures[stage], gl_info);
+
+    set_tex_op(gl_info, state, FALSE, stage,
+            state->texture_states[stage][WINED3D_TSS_COLOR_OP],
+            state->texture_states[stage][WINED3D_TSS_COLOR_ARG1],
+            state->texture_states[stage][WINED3D_TSS_COLOR_ARG2],
+            state->texture_states[stage][WINED3D_TSS_COLOR_ARG0]);
+}
+
+void tex_alphaop(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
+    const struct wined3d_device *device = context->swapchain->device;
+    BOOL tex_used = device->fixed_function_usage_map & (1 << stage);
+    DWORD mapped_stage = device->texUnitMap[stage];
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    DWORD op, arg1, arg2, arg0;
+
+    TRACE("Setting alpha op for stage %d\n", stage);
+    /* Do not care for enabled / disabled stages, just assign the settings. colorop disables / enables required stuff */
+    if (mapped_stage != WINED3D_UNMAPPED_STAGE)
+    {
+        if (tex_used && mapped_stage >= gl_info->limits.textures)
+        {
+            FIXME("Attempt to enable unsupported stage!\n");
+            return;
+        }
+        context_active_texture(context, gl_info, mapped_stage);
+    }
+
+    op = state->texture_states[stage][WINED3D_TSS_ALPHA_OP];
+    arg1 = state->texture_states[stage][WINED3D_TSS_ALPHA_ARG1];
+    arg2 = state->texture_states[stage][WINED3D_TSS_ALPHA_ARG2];
+    arg0 = state->texture_states[stage][WINED3D_TSS_ALPHA_ARG0];
+
+    if (state->render_states[WINED3D_RS_COLORKEYENABLE] && !stage && state->textures[0])
+    {
+        struct wined3d_texture *texture = state->textures[0];
+        GLenum texture_dimensions = texture->target;
+
+        if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB)
+        {
+            struct wined3d_surface *surf = surface_from_resource(texture->sub_resources[0]);
+
+            if (surf->CKeyFlags & WINEDDSD_CKSRCBLT && !surf->resource.format->alpha_size)
+            {
+                /* Color keying needs to pass alpha values from the texture through to have the alpha test work
+                 * properly. On the other hand applications can still use texture combiners apparently. This code
+                 * takes care that apps cannot remove the texture's alpha channel entirely.
+                 *
+                 * The fixup is required for Prince of Persia 3D(prison bars), while Moto racer 2 requires
+                 * D3DTOP_MODULATE to work on color keyed surfaces. Aliens vs Predator 1 uses color keyed textures
+                 * and alpha component of diffuse color to draw things like translucent text and perform other
+                 * blending effects.
+                 *
+                 * Aliens vs Predator 1 relies on diffuse alpha having an effect, so it cannot be ignored. To
+                 * provide the behavior expected by the game, while emulating the colorkey, diffuse alpha must be
+                 * modulated with texture alpha. OTOH, Moto racer 2 at some points sets alphaop/alphaarg to
+                 * SELECTARG/CURRENT, yet puts garbage in diffuse alpha (zeroes). This works on native, because the
+                 * game disables alpha test and alpha blending. Alpha test is overwritten by wine's for purposes of
+                 * color-keying though, so this will lead to missing geometry if texture alpha is modulated (pixels
+                 * fail alpha test). To get around this, ALPHABLENDENABLE state is checked: if the app enables alpha
+                 * blending, it can be expected to provide meaningful values in diffuse alpha, so it should be
+                 * modulated with texture alpha; otherwise, selecting diffuse alpha is ignored in favour of texture
+                 * alpha.
+                 *
+                 * What to do with multitexturing? So far no app has been found that uses color keying with
+                 * multitexturing */
+                if (op == WINED3D_TOP_DISABLE)
+                {
+                    arg1 = WINED3DTA_TEXTURE;
+                    op = WINED3D_TOP_SELECT_ARG1;
+                }
+                else if (op == WINED3D_TOP_SELECT_ARG1 && arg1 != WINED3DTA_TEXTURE)
+                {
+                    if (state->render_states[WINED3D_RS_ALPHABLENDENABLE])
+                    {
+                        arg2 = WINED3DTA_TEXTURE;
+                        op = WINED3D_TOP_MODULATE;
+                    }
+                    else arg1 = WINED3DTA_TEXTURE;
+                }
+                else if (op == WINED3D_TOP_SELECT_ARG2 && arg2 != WINED3DTA_TEXTURE)
+                {
+                    if (state->render_states[WINED3D_RS_ALPHABLENDENABLE])
+                    {
+                        arg1 = WINED3DTA_TEXTURE;
+                        op = WINED3D_TOP_MODULATE;
+                    }
+                    else arg2 = WINED3DTA_TEXTURE;
+                }
+            }
+        }
+    }
+
+    /* tex_alphaop is shared between the ffp and nvrc because the difference only comes down to
+     * this if block here, and the other code(color keying, texture unit selection) are the same
+     */
+    TRACE("Setting alpha op for stage %d\n", stage);
+    if (gl_info->supported[NV_REGISTER_COMBINERS])
+    {
+        set_tex_op_nvrc(gl_info, state, TRUE, stage, op, arg1, arg2, arg0,
+                mapped_stage, state->texture_states[stage][WINED3D_TSS_RESULT_ARG]);
+    }
+    else
+    {
+        set_tex_op(gl_info, state, TRUE, stage, op, arg1, arg2, arg0);
+    }
+}
+
+void transform_texture(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    DWORD texUnit = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
+    const struct wined3d_device *device = context->swapchain->device;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    DWORD mapped_stage = device->texUnitMap[texUnit];
+    BOOL generated;
+    int coordIdx;
+
+    /* Ignore this when a vertex shader is used, or if the streams aren't sorted out yet */
+    if (use_vs(state) || isStateDirty(context, STATE_VDECL))
+    {
+        TRACE("Using a vertex shader, or stream sources not sorted out yet, skipping\n");
+        return;
+    }
+
+    if (mapped_stage == WINED3D_UNMAPPED_STAGE) return;
+    if (mapped_stage >= gl_info->limits.textures) return;
+
+    context_active_texture(context, gl_info, mapped_stage);
+    generated = (state->texture_states[texUnit][WINED3D_TSS_TEXCOORD_INDEX] & 0xffff0000) != WINED3DTSS_TCI_PASSTHRU;
+    coordIdx = min(state->texture_states[texUnit][WINED3D_TSS_TEXCOORD_INDEX & 0x0000ffff], MAX_TEXTURES - 1);
+
+    set_texture_matrix(gl_info, &state->transforms[WINED3D_TS_TEXTURE0 + texUnit].u.m[0][0],
+            state->texture_states[texUnit][WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS],
+            generated, context->last_was_rhw,
+            device->stream_info.use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coordIdx))
+            ? device->stream_info.elements[WINED3D_FFP_TEXCOORD0 + coordIdx].format->id
+            : WINED3DFMT_UNKNOWN,
+            device->shader_backend->shader_has_ffp_proj_control(device->shader_priv));
+
+    /* The sampler applying function calls us if this changes */
+    if ((context->lastWasPow2Texture & (1 << texUnit)) && state->textures[texUnit])
+    {
+        if(generated) {
+            FIXME("Non-power2 texture being used with generated texture coords\n");
+        }
+        /* NP2 texcoord fixup is implemented for pixelshaders so only enable the
+           fixed-function-pipeline fixup via pow2Matrix when no PS is used. */
+        if (!use_ps(state))
+        {
+            TRACE("Non power two matrix multiply fixup\n");
+            gl_info->gl_ops.gl.p_glMultMatrixf(state->textures[texUnit]->pow2_matrix);
+        }
+    }
+}
+
+static void unload_tex_coords(const struct wined3d_gl_info *gl_info)
+{
+    unsigned int texture_idx;
+
+    for (texture_idx = 0; texture_idx < gl_info->limits.texture_coords; ++texture_idx)
+    {
+        GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
+        gl_info->gl_ops.gl.p_glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+    }
+}
+
+static void load_tex_coords(const struct wined3d_context *context, const struct wined3d_stream_info *si,
+        GLuint *curVBO, const struct wined3d_state *state)
+{
+    const struct wined3d_device *device = context->swapchain->device;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    unsigned int mapped_stage = 0;
+    unsigned int textureNo = 0;
+
+    for (textureNo = 0; textureNo < context->d3d_info->limits.ffp_blend_stages; ++textureNo)
+    {
+        int coordIdx = state->texture_states[textureNo][WINED3D_TSS_TEXCOORD_INDEX];
+
+        mapped_stage = device->texUnitMap[textureNo];
+        if (mapped_stage == WINED3D_UNMAPPED_STAGE) continue;
+
+        if (mapped_stage >= gl_info->limits.texture_coords)
+        {
+            FIXME("Attempted to load unsupported texture coordinate %u\n", mapped_stage);
+            continue;
+        }
+
+        if (coordIdx < MAX_TEXTURES && (si->use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coordIdx))))
+        {
+            const struct wined3d_stream_info_element *e = &si->elements[WINED3D_FFP_TEXCOORD0 + coordIdx];
+
+            TRACE("Setting up texture %u, idx %d, coordindx %u, data {%#x:%p}.\n",
+                    textureNo, mapped_stage, coordIdx, e->data.buffer_object, e->data.addr);
+
+            if (*curVBO != e->data.buffer_object)
+            {
+                GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->data.buffer_object));
+                checkGLcall("glBindBufferARB");
+                *curVBO = e->data.buffer_object;
+            }
+
+            GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
+            checkGLcall("glClientActiveTextureARB");
+
+            /* The coords to supply depend completely on the fvf / vertex shader */
+            gl_info->gl_ops.gl.p_glTexCoordPointer(e->format->gl_vtx_format, e->format->gl_vtx_type, e->stride,
+                    e->data.addr + state->load_base_vertex_index * e->stride);
+            gl_info->gl_ops.gl.p_glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+        }
+        else
+        {
+            GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + mapped_stage, 0, 0, 0, 1));
+        }
+    }
+    if (gl_info->supported[NV_REGISTER_COMBINERS])
+    {
+        /* The number of the mapped stages increases monotonically, so it's fine to use the last used one. */
+        for (textureNo = mapped_stage + 1; textureNo < gl_info->limits.textures; ++textureNo)
+        {
+            GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
+        }
+    }
+
+    checkGLcall("loadTexCoords");
+}
+
+static void tex_coordindex(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
+    const struct wined3d_device *device = context->swapchain->device;
+    static const GLfloat s_plane[] = { 1.0f, 0.0f, 0.0f, 0.0f };
+    static const GLfloat t_plane[] = { 0.0f, 1.0f, 0.0f, 0.0f };
+    static const GLfloat r_plane[] = { 0.0f, 0.0f, 1.0f, 0.0f };
+    static const GLfloat q_plane[] = { 0.0f, 0.0f, 0.0f, 1.0f };
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    DWORD mapped_stage = device->texUnitMap[stage];
+
+    if (mapped_stage == WINED3D_UNMAPPED_STAGE)
+    {
+        TRACE("No texture unit mapped to stage %d. Skipping texture coordinates.\n", stage);
+        return;
+    }
+
+    if (mapped_stage >= gl_info->limits.fragment_samplers)
+    {
+        WARN("stage %u not mapped to a valid texture unit (%u)\n", stage, mapped_stage);
+        return;
+    }
+    context_active_texture(context, gl_info, mapped_stage);
+
+    /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive
+     *
+     * FIXME: When using generated texture coordinates, the index value is used to specify the wrapping mode.
+     * eg. SetTextureStageState( 0, WINED3D_TSS_TEXCOORDINDEX, WINED3D_TSS_TCI_CAMERASPACEPOSITION | 1 );
+     * means use the vertex position (camera-space) as the input texture coordinates
+     * for this texture stage, and the wrap mode set in the WINED3D_RS_WRAP1 render
+     * state. We do not (yet) support the WINED3DRENDERSTATE_WRAPx values, nor tie them up
+     * to the TEXCOORDINDEX value
+     */
+    switch (state->texture_states[stage][WINED3D_TSS_TEXCOORD_INDEX] & 0xffff0000)
+    {
+        case WINED3DTSS_TCI_PASSTHRU:
+            /* Use the specified texture coordinates contained within the
+             * vertex format. This value resolves to zero. */
+            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_GEN_S);
+            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_GEN_T);
+            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_GEN_R);
+            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_GEN_Q);
+            checkGLcall("WINED3DTSS_TCI_PASSTHRU - Disable texgen.");
+            break;
+
+        case WINED3DTSS_TCI_CAMERASPACEPOSITION:
+            /* CameraSpacePosition means use the vertex position, transformed to camera space,
+             * as the input texture coordinates for this stage's texture transformation. This
+             * equates roughly to EYE_LINEAR */
+
+            gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
+            gl_info->gl_ops.gl.p_glPushMatrix();
+            gl_info->gl_ops.gl.p_glLoadIdentity();
+            gl_info->gl_ops.gl.p_glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
+            gl_info->gl_ops.gl.p_glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
+            gl_info->gl_ops.gl.p_glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
+            gl_info->gl_ops.gl.p_glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
+            gl_info->gl_ops.gl.p_glPopMatrix();
+            checkGLcall("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane.");
+
+            gl_info->gl_ops.gl.p_glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
+            gl_info->gl_ops.gl.p_glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
+            gl_info->gl_ops.gl.p_glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
+            checkGLcall("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set texgen mode.");
+
+            gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_GEN_S);
+            gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_GEN_T);
+            gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_GEN_R);
+            checkGLcall("WINED3DTSS_TCI_CAMERASPACEPOSITION - Enable texgen.");
+
+            break;
+
+        case WINED3DTSS_TCI_CAMERASPACENORMAL:
+            /* Note that NV_TEXGEN_REFLECTION support is implied when
+             * ARB_TEXTURE_CUBE_MAP is supported */
+            if (!gl_info->supported[NV_TEXGEN_REFLECTION])
+            {
+                FIXME("WINED3DTSS_TCI_CAMERASPACENORMAL not supported.\n");
+                break;
+            }
+
+            gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
+            gl_info->gl_ops.gl.p_glPushMatrix();
+            gl_info->gl_ops.gl.p_glLoadIdentity();
+            gl_info->gl_ops.gl.p_glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
+            gl_info->gl_ops.gl.p_glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
+            gl_info->gl_ops.gl.p_glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
+            gl_info->gl_ops.gl.p_glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
+            gl_info->gl_ops.gl.p_glPopMatrix();
+            checkGLcall("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane.");
+
+            gl_info->gl_ops.gl.p_glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
+            gl_info->gl_ops.gl.p_glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
+            gl_info->gl_ops.gl.p_glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
+            checkGLcall("WINED3DTSS_TCI_CAMERASPACENORMAL - Set texgen mode.");
+
+            gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_GEN_S);
+            gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_GEN_T);
+            gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_GEN_R);
+            checkGLcall("WINED3DTSS_TCI_CAMERASPACENORMAL - Enable texgen.");
+
+            break;
+
+        case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
+            /* Note that NV_TEXGEN_REFLECTION support is implied when
+             * ARB_TEXTURE_CUBE_MAP is supported */
+            if (!gl_info->supported[NV_TEXGEN_REFLECTION])
+            {
+                FIXME("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR not supported.\n");
+                break;
+            }
+
+            gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
+            gl_info->gl_ops.gl.p_glPushMatrix();
+            gl_info->gl_ops.gl.p_glLoadIdentity();
+            gl_info->gl_ops.gl.p_glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
+            gl_info->gl_ops.gl.p_glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
+            gl_info->gl_ops.gl.p_glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
+            gl_info->gl_ops.gl.p_glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
+            gl_info->gl_ops.gl.p_glPopMatrix();
+            checkGLcall("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane.");
+
+            gl_info->gl_ops.gl.p_glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
+            gl_info->gl_ops.gl.p_glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
+            gl_info->gl_ops.gl.p_glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
+            checkGLcall("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set texgen mode.");
+
+            gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_GEN_S);
+            gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_GEN_T);
+            gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_GEN_R);
+            checkGLcall("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Enable texgen.");
+
+            break;
+
+        case WINED3DTSS_TCI_SPHEREMAP:
+            gl_info->gl_ops.gl.p_glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
+            gl_info->gl_ops.gl.p_glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
+            checkGLcall("WINED3DTSS_TCI_SPHEREMAP - Set texgen mode.");
+
+            gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_GEN_S);
+            gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_GEN_T);
+            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_GEN_R);
+            checkGLcall("WINED3DTSS_TCI_SPHEREMAP - Enable texgen.");
+
+            break;
+
+        default:
+            FIXME("Unhandled WINED3D_TSS_TEXCOORD_INDEX %#x.\n",
+                    state->texture_states[stage][WINED3D_TSS_TEXCOORD_INDEX]);
+            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_GEN_S);
+            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_GEN_T);
+            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_GEN_R);
+            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_GEN_Q);
+            checkGLcall("Disable texgen.");
+
+            break;
+    }
+
+    /* Update the texture matrix. */
+    if (!isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_TEXTURE0 + stage)))
+        transform_texture(context, state, STATE_TEXTURESTAGE(stage, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS));
+
+    if (!isStateDirty(context, STATE_VDECL) && context->namedArraysLoaded)
+    {
+        /* Reload the arrays if we are using fixed function arrays to reflect the selected coord input
+         * source. Call loadTexCoords directly because there is no need to reparse the vertex declaration
+         * and do all the things linked to it
+         * TODO: Tidy that up to reload only the arrays of the changed unit
+         */
+        GLuint curVBO = gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] ? ~0U : 0;
+
+        unload_tex_coords(gl_info);
+        load_tex_coords(context, &device->stream_info, &curVBO, state);
+    }
+}
+
+static void tex_bumpenvlscale(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
+    const struct wined3d_shader *ps = state->pixel_shader;
+
+    /* The pixel shader has to know the luminance scale. Do a constants update. */
+    if (ps && stage && (ps->reg_maps.luminanceparams & (1 << stage)))
+        context->load_constants = 1;
+}
+
+void sampler_texmatrix(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const DWORD sampler = state_id - STATE_SAMPLER(0);
+    const struct wined3d_texture *texture = state->textures[sampler];
+
+    TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);
+
+    if(!texture) return;
+    /* The fixed function np2 texture emulation uses the texture matrix to fix up the coordinates
+     * wined3d_texture_apply_state_changes() multiplies the set matrix with a fixup matrix. Before the
+     * scaling is reapplied or removed, the texture matrix has to be reapplied
+     *
+     * The mapped stage is already active because the sampler() function below, which is part of the
+     * misc pipeline
+     */
+    if (sampler < MAX_TEXTURES)
+    {
+        const BOOL texIsPow2 = !(texture->flags & WINED3D_TEXTURE_POW2_MAT_IDENT);
+
+        if (texIsPow2 || (context->lastWasPow2Texture & (1 << sampler)))
+        {
+            const struct wined3d_device *device = context->swapchain->device;
+
+            if (texIsPow2)
+                context->lastWasPow2Texture |= 1 << sampler;
+            else
+                context->lastWasPow2Texture &= ~(1 << sampler);
+
+            transform_texture(context, state,
+                    STATE_TEXTURESTAGE(device->texUnitMap[sampler], WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS));
+        }
+    }
+}
+
+static void sampler(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_device *device = context->swapchain->device;
+    DWORD sampler = state_id - STATE_SAMPLER(0);
+    DWORD mapped_stage = device->texUnitMap[sampler];
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    union {
+        float f;
+        DWORD d;
+    } tmpvalue;
+
+    TRACE("Sampler: %d\n", sampler);
+    /* Enabling and disabling texture dimensions is done by texture stage state / pixel shader setup, this function
+     * only has to bind textures and set the per texture states
+     */
+
+    if (mapped_stage == WINED3D_UNMAPPED_STAGE)
+    {
+        TRACE("No sampler mapped to stage %d. Returning.\n", sampler);
+        return;
+    }
+
+    if (mapped_stage >= gl_info->limits.combined_samplers)
+    {
+        return;
+    }
+    context_active_texture(context, gl_info, mapped_stage);
+
+    if (state->textures[sampler])
+    {
+        struct wined3d_texture *texture = state->textures[sampler];
+        BOOL srgb = state->sampler_states[sampler][WINED3D_SAMP_SRGB_TEXTURE];
+
+        texture->texture_ops->texture_bind(texture, context, srgb);
+        wined3d_texture_apply_state_changes(texture, state->sampler_states[sampler], gl_info);
+
+        if (gl_info->supported[EXT_TEXTURE_LOD_BIAS])
+        {
+            tmpvalue.d = state->sampler_states[sampler][WINED3D_SAMP_MIPMAP_LOD_BIAS];
+            gl_info->gl_ops.gl.p_glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
+                      GL_TEXTURE_LOD_BIAS_EXT, tmpvalue.f);
+            checkGLcall("glTexEnvf(GL_TEXTURE_LOD_BIAS_EXT, ...)");
+        }
+
+        if (!use_ps(state) && sampler < state->lowest_disabled_stage)
+        {
+            if (state->render_states[WINED3D_RS_COLORKEYENABLE] && !sampler)
+            {
+                /* If color keying is enabled update the alpha test, it
+                 * depends on the existence of a color key in stage 0. */
+                state_alpha(context, state, WINED3D_RS_COLORKEYENABLE);
+            }
+        }
+
+        /* Trigger shader constant reloading (for NP2 texcoord fixup) */
+        if (!(texture->flags & WINED3D_TEXTURE_POW2_MAT_IDENT))
+            device->shader_backend->shader_load_np2fixup_constants(device->shader_priv, gl_info, state);
+    }
+    else
+    {
+        if (sampler < state->lowest_disabled_stage)
+        {
+            /* TODO: What should I do with pixel shaders here ??? */
+            if (state->render_states[WINED3D_RS_COLORKEYENABLE] && !sampler)
+            {
+                /* If color keying is enabled update the alpha test, it
+                 * depends on the existence of a color key in stage 0. */
+                state_alpha(context, state, WINED3D_RS_COLORKEYENABLE);
+            }
+        } /* Otherwise tex_colorop disables the stage */
+        context_bind_texture(context, GL_NONE, 0);
+    }
+}
+
+void apply_pixelshader(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    unsigned int i;
+
+    if (use_ps(state))
+    {
+        if (!context->last_was_pshader)
+        {
+            /* Former draw without a pixel shader, some samplers may be
+             * disabled because of WINED3D_TSS_COLOR_OP = WINED3DTOP_DISABLE
+             * make sure to enable them. */
+            for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i)
+            {
+                if (!isStateDirty(context, STATE_SAMPLER(i)))
+                    sampler(context, state, STATE_SAMPLER(i));
+            }
+            context->last_was_pshader = TRUE;
+        }
+        else
+        {
+            /* Otherwise all samplers were activated by the code above in
+             * earlier draws, or by sampler() if a different texture was
+             * bound. I don't have to do anything. */
+        }
+    }
+    else
+    {
+        /* Disabled the pixel shader - color ops weren't applied while it was
+         * enabled, so re-apply them. */
+        for (i = 0; i < context->d3d_info->limits.ffp_blend_stages; ++i)
+        {
+            if (!isStateDirty(context, STATE_TEXTURESTAGE(i, WINED3D_TSS_COLOR_OP)))
+                context_apply_state(context, state, STATE_TEXTURESTAGE(i, WINED3D_TSS_COLOR_OP));
+        }
+        context->last_was_pshader = FALSE;
+    }
+
+    context->select_shader = 1;
+    context->load_constants = 1;
+}
+
+static void state_geometry_shader(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    context->select_shader = 1;
+}
+
+static void shader_bumpenvmat(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
+    const struct wined3d_shader *ps = state->pixel_shader;
+
+    /* The pixel shader has to know the bump env matrix. Do a constants update. */
+    if (ps && stage && (ps->reg_maps.bumpmat & (1 << stage)))
+        context->load_constants = 1;
+}
+
+void transform_world(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    /* This function is called by transform_view below if the view matrix was changed too
+     *
+     * Deliberately no check if the vertex declaration is dirty because the vdecl state
+     * does not always update the world matrix, only on a switch between transformed
+     * and untransformed draws. It *may* happen that the world matrix is set 2 times during one
+     * draw, but that should be rather rare and cheaper in total.
+     */
+    gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
+    checkGLcall("glMatrixMode");
+
+    if (context->last_was_rhw)
+    {
+        gl_info->gl_ops.gl.p_glLoadIdentity();
+        checkGLcall("glLoadIdentity()");
+    }
+    else
+    {
+            gl_info->gl_ops.gl.p_glLoadMatrixf(&state->transforms[WINED3D_TS_VIEW].u.m[0][0]);
+            checkGLcall("glLoadMatrixf");
+            gl_info->gl_ops.gl.p_glMultMatrixf(&state->transforms[WINED3D_TS_WORLD_MATRIX(0)].u.m[0][0]);
+            checkGLcall("glMultMatrixf");
+        }
+}
+
+void clipplane(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    UINT index = state_id - STATE_CLIPPLANE(0);
+    GLdouble plane[4];
+
+    if (isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_VIEW)) || index >= gl_info->limits.clipplanes)
+        return;
+
+    gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
+    gl_info->gl_ops.gl.p_glPushMatrix();
+
+    /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
+    if (!use_vs(state))
+        gl_info->gl_ops.gl.p_glLoadMatrixf(&state->transforms[WINED3D_TS_VIEW].u.m[0][0]);
+    else
+        /* With vertex shaders, clip planes are not transformed in Direct3D,
+         * while in OpenGL they are still transformed by the model view matix. */
+        gl_info->gl_ops.gl.p_glLoadIdentity();
+
+    plane[0] = state->clip_planes[index].x;
+    plane[1] = state->clip_planes[index].y;
+    plane[2] = state->clip_planes[index].z;
+    plane[3] = state->clip_planes[index].w;
+
+    TRACE("Clipplane [%.8e, %.8e, %.8e, %.8e]\n",
+            plane[0], plane[1], plane[2], plane[3]);
+    gl_info->gl_ops.gl.p_glClipPlane(GL_CLIP_PLANE0 + index, plane);
+    checkGLcall("glClipPlane");
+
+    gl_info->gl_ops.gl.p_glPopMatrix();
+}
+
+static void transform_worldex(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    UINT matrix = state_id - STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0));
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    GLenum glMat;
+
+    TRACE("Setting world matrix %d\n", matrix);
+
+    if (matrix >= gl_info->limits.blends)
+    {
+        WARN("Unsupported blend matrix set\n");
+        return;
+    }
+
+    if (isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_VIEW)))
+        return;
+
+    /* GL_MODELVIEW0_ARB:  0x1700
+     * GL_MODELVIEW1_ARB:  0x850a
+     * GL_MODELVIEW2_ARB:  0x8722
+     * GL_MODELVIEW3_ARB:  0x8723
+     * etc
+     * GL_MODELVIEW31_ARB: 0x873f
+     */
+    if(matrix == 1) glMat = GL_MODELVIEW1_ARB;
+    else glMat = GL_MODELVIEW2_ARB - 2 + matrix;
+
+    gl_info->gl_ops.gl.p_glMatrixMode(glMat);
+    checkGLcall("glMatrixMode(glMat)");
+
+    /* World matrix 0 is multiplied with the view matrix because d3d uses 3
+     * matrices while gl uses only 2. To avoid weighting the view matrix
+     * incorrectly it has to be multiplied into every GL modelview matrix. */
+        gl_info->gl_ops.gl.p_glLoadMatrixf(&state->transforms[WINED3D_TS_VIEW].u.m[0][0]);
+        checkGLcall("glLoadMatrixf");
+        gl_info->gl_ops.gl.p_glMultMatrixf(&state->transforms[WINED3D_TS_WORLD_MATRIX(matrix)].u.m[0][0]);
+        checkGLcall("glMultMatrixf");
+}
+
+static void state_vertexblend_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    enum wined3d_vertex_blend_flags f = state->render_states[WINED3D_RS_VERTEXBLEND];
+    static unsigned int once;
+
+    if (f == WINED3D_VBF_DISABLE)
+        return;
+
+    if (!once++) FIXME("Vertex blend flags %#x not supported.\n", f);
+    else WARN("Vertex blend flags %#x not supported.\n", f);
+}
+
+static void state_vertexblend(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    enum wined3d_vertex_blend_flags val = state->render_states[WINED3D_RS_VERTEXBLEND];
+    struct wined3d_device *device = context->swapchain->device;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    static unsigned int once;
+
+    switch (val)
+    {
+        case WINED3D_VBF_1WEIGHTS:
+        case WINED3D_VBF_2WEIGHTS:
+        case WINED3D_VBF_3WEIGHTS:
+            gl_info->gl_ops.gl.p_glEnable(GL_VERTEX_BLEND_ARB);
+            checkGLcall("glEnable(GL_VERTEX_BLEND_ARB)");
+
+            /* D3D adds one more matrix which has weight (1 - sum(weights)).
+             * This is enabled at context creation with enabling
+             * GL_WEIGHT_SUM_UNITY_ARB. */
+            GL_EXTCALL(glVertexBlendARB(state->render_states[WINED3D_RS_VERTEXBLEND] + 1));
+
+            if (!device->vertexBlendUsed)
+            {
+                unsigned int i;
+                for (i = 1; i < gl_info->limits.blends; ++i)
+                {
+                    if (!isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(i))))
+                        transform_worldex(context, state, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(i)));
+                }
+                device->vertexBlendUsed = TRUE;
+            }
+            break;
+
+        case WINED3D_VBF_TWEENING:
+        case WINED3D_VBF_0WEIGHTS: /* Indexed vertex blending, not supported. */
+            if (!once++) FIXME("Vertex blend flags %#x not supported.\n", val);
+            else WARN("Vertex blend flags %#x not supported.\n", val);
+            /* Fall through. */
+        case WINED3D_VBF_DISABLE:
+            gl_info->gl_ops.gl.p_glDisable(GL_VERTEX_BLEND_ARB);
+            checkGLcall("glDisable(GL_VERTEX_BLEND_ARB)");
+            break;
+    }
+}
+
+void transform_view(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    const struct wined3d_light_info *light = NULL;
+    unsigned int k;
+
+    /* If we are changing the View matrix, reset the light and clipping planes to the new view
+     * NOTE: We have to reset the positions even if the light/plane is not currently
+     *       enabled, since the call to enable it will not reset the position.
+     * NOTE2: Apparently texture transforms do NOT need reapplying
+     */
+
+    gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
+    checkGLcall("glMatrixMode(GL_MODELVIEW)");
+    gl_info->gl_ops.gl.p_glLoadMatrixf(&state->transforms[WINED3D_TS_VIEW].u.m[0][0]);
+    checkGLcall("glLoadMatrixf(...)");
+
+    /* Reset lights. TODO: Call light apply func */
+    for (k = 0; k < gl_info->limits.lights; ++k)
+    {
+        if (!(light = state->lights[k]))
+            continue;
+        gl_info->gl_ops.gl.p_glLightfv(GL_LIGHT0 + light->glIndex, GL_POSITION, light->lightPosn);
+        checkGLcall("glLightfv posn");
+        gl_info->gl_ops.gl.p_glLightfv(GL_LIGHT0 + light->glIndex, GL_SPOT_DIRECTION, light->lightDirn);
+        checkGLcall("glLightfv dirn");
+    }
+
+    /* Reset Clipping Planes  */
+    for (k = 0; k < gl_info->limits.clipplanes; ++k)
+    {
+        if (!isStateDirty(context, STATE_CLIPPLANE(k)))
+            clipplane(context, state, STATE_CLIPPLANE(k));
+    }
+
+    if (context->last_was_rhw)
+    {
+        gl_info->gl_ops.gl.p_glLoadIdentity();
+        checkGLcall("glLoadIdentity()");
+        /* No need to update the world matrix, the identity is fine */
+        return;
+    }
+
+    /* Call the world matrix state, this will apply the combined WORLD + VIEW matrix
+     * No need to do it here if the state is scheduled for update. */
+    if (!isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0))))
+        transform_world(context, state, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)));
+
+    /* Avoid looping over a number of matrices if the app never used the functionality */
+    if (context->swapchain->device->vertexBlendUsed)
+    {
+        for (k = 1; k < gl_info->limits.blends; ++k)
+        {
+            if (!isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(k))))
+                transform_worldex(context, state, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(k)));
+        }
+    }
+}
+
+void transform_projection(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    gl_info->gl_ops.gl.p_glMatrixMode(GL_PROJECTION);
+    checkGLcall("glMatrixMode(GL_PROJECTION)");
+
+    /* There are a couple of additional things we have to take into account
+     * here besides the projection transformation itself:
+     *   - We need to flip along the y-axis in case of offscreen rendering.
+     *   - OpenGL Z range is {-Wc,...,Wc} while D3D Z range is {0,...,Wc}.
+     *   - D3D coordinates refer to pixel centers while GL coordinates refer
+     *     to pixel corners.
+     *   - D3D has a top-left filling convention. We need to maintain this
+     *     even after the y-flip mentioned above.
+     * In order to handle the last two points, we translate by
+     * (63.0 / 128.0) / VPw and (63.0 / 128.0) / VPh. This is equivalent to
+     * translating slightly less than half a pixel. We want the difference to
+     * be large enough that it doesn't get lost due to rounding inside the
+     * driver, but small enough to prevent it from interfering with any
+     * anti-aliasing. */
+
+    if (context->last_was_rhw)
+    {
+        /* Transform D3D RHW coordinates to OpenGL clip coordinates. */
+        double x = state->viewport.x;
+        double y = state->viewport.y;
+        double w = state->viewport.width;
+        double h = state->viewport.height;
+        double x_scale = 2.0 / w;
+        double x_offset = ((63.0 / 64.0) - (2.0 * x) - w) / w;
+        double y_scale = context->render_offscreen ? 2.0 / h : 2.0 / -h;
+        double y_offset = context->render_offscreen
+                ? ((63.0 / 64.0) - (2.0 * y) - h) / h
+                : ((63.0 / 64.0) - (2.0 * y) - h) / -h;
+        const GLdouble projection[] =
+        {
+             x_scale,      0.0,  0.0, 0.0,
+                 0.0,  y_scale,  0.0, 0.0,
+                 0.0,      0.0,  2.0, 0.0,
+            x_offset, y_offset, -1.0, 1.0,
+        };
+
+        gl_info->gl_ops.gl.p_glLoadMatrixd(projection);
+        checkGLcall("glLoadMatrixd");
+    }
+    else
+    {
+        double y_scale = context->render_offscreen ? -1.0 : 1.0;
+        double x_offset = (63.0 / 64.0) / state->viewport.width;
+        double y_offset = context->render_offscreen
+                ? (63.0 / 64.0) / state->viewport.height
+                : -(63.0 / 64.0) / state->viewport.height;
+        const GLdouble projection[] =
+        {
+                 1.0,      0.0,  0.0, 0.0,
+                 0.0,  y_scale,  0.0, 0.0,
+                 0.0,      0.0,  2.0, 0.0,
+            x_offset, y_offset, -1.0, 1.0,
+        };
+
+        gl_info->gl_ops.gl.p_glLoadMatrixd(projection);
+        checkGLcall("glLoadMatrixd");
+
+        gl_info->gl_ops.gl.p_glMultMatrixf(&state->transforms[WINED3D_TS_PROJECTION].u.m[0][0]);
+        checkGLcall("glLoadMatrixf");
+    }
+}
+
+/* This should match any arrays loaded in load_vertex_data.
+ * TODO: Only load / unload arrays if we have to. */
+static void unload_vertex_data(const struct wined3d_gl_info *gl_info)
+{
+    gl_info->gl_ops.gl.p_glDisableClientState(GL_VERTEX_ARRAY);
+    gl_info->gl_ops.gl.p_glDisableClientState(GL_NORMAL_ARRAY);
+    gl_info->gl_ops.gl.p_glDisableClientState(GL_COLOR_ARRAY);
+    if (gl_info->supported[EXT_SECONDARY_COLOR])
+        gl_info->gl_ops.gl.p_glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
+    if (gl_info->supported[ARB_VERTEX_BLEND])
+        gl_info->gl_ops.gl.p_glDisableClientState(GL_WEIGHT_ARRAY_ARB);
+    unload_tex_coords(gl_info);
+}
+
+static inline void unload_numbered_array(struct wined3d_context *context, int i)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    GL_EXTCALL(glDisableVertexAttribArrayARB(i));
+    checkGLcall("glDisableVertexAttribArrayARB(reg)");
+    if (gl_info->supported[ARB_INSTANCED_ARRAYS])
+        GL_EXTCALL(glVertexAttribDivisorARB(i, 0));
+
+    context->numbered_array_mask &= ~(1 << i);
+}
+
+/* This should match any arrays loaded in loadNumberedArrays
+ * TODO: Only load / unload arrays if we have to. */
+static void unload_numbered_arrays(struct wined3d_context *context)
+{
+    /* disable any attribs (this is the same for both GLSL and ARB modes) */
+    int i;
+
+    for (i = 0; i < context->gl_info->limits.vertex_attribs; ++i) {
+        unload_numbered_array(context, i);
+    }
+}
+
+static void load_numbered_arrays(struct wined3d_context *context,
+        const struct wined3d_stream_info *stream_info, const struct wined3d_state *state)
+{
+    struct wined3d_device *device = context->swapchain->device;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    GLuint curVBO = gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] ? ~0U : 0;
+    int i;
+
+    /* Default to no instancing */
+    device->instance_count = 0;
+
+    for (i = 0; i < MAX_ATTRIBS; i++)
+    {
+        const struct wined3d_stream_state *stream;
+
+        if (!(stream_info->use_map & (1 << i)))
+        {
+            if (context->numbered_array_mask & (1 << i))
+                unload_numbered_array(context, i);
+            if (state->vertex_shader->reg_maps.input_registers & (1 << i))
+                GL_EXTCALL(glVertexAttrib4fARB(i, 0.0f, 0.0f, 0.0f, 0.0f));
+            continue;
+        }
+
+        stream = &state->streams[stream_info->elements[i].stream_idx];
+
+        if (stream->flags & WINED3DSTREAMSOURCE_INSTANCEDATA)
+        {
+            if (!device->instance_count)
+                device->instance_count = state->streams[0].frequency ? state->streams[0].frequency : 1;
+
+            if (!gl_info->supported[ARB_INSTANCED_ARRAYS])
+            {
+                /* Unload instanced arrays, they will be loaded using
+                 * immediate mode instead. */
+                if (context->numbered_array_mask & (1 << i))
+                    unload_numbered_array(context, i);
+            continue;
+        }
+
+            GL_EXTCALL(glVertexAttribDivisorARB(i, 1));
+        }
+        else if (gl_info->supported[ARB_INSTANCED_ARRAYS])
+        {
+            GL_EXTCALL(glVertexAttribDivisorARB(i, 0));
+        }
+
+        TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, stream_info->elements[i].data.buffer_object);
+
+        if (stream_info->elements[i].stride)
+        {
+            if (curVBO != stream_info->elements[i].data.buffer_object)
+            {
+                GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, stream_info->elements[i].data.buffer_object));
+                checkGLcall("glBindBufferARB");
+                curVBO = stream_info->elements[i].data.buffer_object;
+            }
+            /* Use the VBO to find out if a vertex buffer exists, not the vb
+             * pointer. vb can point to a user pointer data blob. In that case
+             * curVBO will be 0. If there is a vertex buffer but no vbo we
+             * won't be load converted attributes anyway. */
+            GL_EXTCALL(glVertexAttribPointerARB(i, stream_info->elements[i].format->gl_vtx_format,
+                    stream_info->elements[i].format->gl_vtx_type,
+                    stream_info->elements[i].format->gl_normalized,
+                    stream_info->elements[i].stride, stream_info->elements[i].data.addr
+                    + state->load_base_vertex_index * stream_info->elements[i].stride));
+
+            if (!(context->numbered_array_mask & (1 << i)))
+            {
+                GL_EXTCALL(glEnableVertexAttribArrayARB(i));
+                context->numbered_array_mask |= (1 << i);
+            }
+        }
+        else
+        {
+            /* Stride = 0 means always the same values.
+             * glVertexAttribPointerARB doesn't do that. Instead disable the
+             * pointer and set up the attribute statically. But we have to
+             * figure out the system memory address. */
+            const BYTE *ptr = stream_info->elements[i].data.addr;
+            if (stream_info->elements[i].data.buffer_object)
+            {
+                ptr += (ULONG_PTR)buffer_get_sysmem(stream->buffer, gl_info);
+            }
+
+            if (context->numbered_array_mask & (1 << i)) unload_numbered_array(context, i);
+
+            switch (stream_info->elements[i].format->id)
+            {
+                case WINED3DFMT_R32_FLOAT:
+                    GL_EXTCALL(glVertexAttrib1fvARB(i, (const GLfloat *)ptr));
+                    break;
+                case WINED3DFMT_R32G32_FLOAT:
+                    GL_EXTCALL(glVertexAttrib2fvARB(i, (const GLfloat *)ptr));
+                    break;
+                case WINED3DFMT_R32G32B32_FLOAT:
+                    GL_EXTCALL(glVertexAttrib3fvARB(i, (const GLfloat *)ptr));
+                    break;
+                case WINED3DFMT_R32G32B32A32_FLOAT:
+                    GL_EXTCALL(glVertexAttrib4fvARB(i, (const GLfloat *)ptr));
+                    break;
+
+                case WINED3DFMT_R8G8B8A8_UINT:
+                    GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
+                    break;
+                case WINED3DFMT_B8G8R8A8_UNORM:
+                    if (gl_info->supported[ARB_VERTEX_ARRAY_BGRA])
+                    {
+                        const DWORD *src = (const DWORD *)ptr;
+                        DWORD c = *src & 0xff00ff00;
+                        c |= (*src & 0xff0000) >> 16;
+                        c |= (*src & 0xff) << 16;
+                        GL_EXTCALL(glVertexAttrib4NubvARB(i, (GLubyte *)&c));
+                        break;
+                    }
+                    /* else fallthrough */
+                case WINED3DFMT_R8G8B8A8_UNORM:
+                    GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
+                    break;
+
+                case WINED3DFMT_R16G16_SINT:
+                    GL_EXTCALL(glVertexAttrib4svARB(i, (const GLshort *)ptr));
+                    break;
+                case WINED3DFMT_R16G16B16A16_SINT:
+                    GL_EXTCALL(glVertexAttrib4svARB(i, (const GLshort *)ptr));
+                    break;
+
+                case WINED3DFMT_R16G16_SNORM:
+                {
+                    const GLshort s[4] = {((const GLshort *)ptr)[0], ((const GLshort *)ptr)[1], 0, 1};
+                    GL_EXTCALL(glVertexAttrib4NsvARB(i, s));
+                    break;
+                }
+                case WINED3DFMT_R16G16_UNORM:
+                {
+                    const GLushort s[4] = {((const GLushort *)ptr)[0], ((const GLushort *)ptr)[1], 0, 1};
+                    GL_EXTCALL(glVertexAttrib4NusvARB(i, s));
+                    break;
+                }
+                case WINED3DFMT_R16G16B16A16_SNORM:
+                    GL_EXTCALL(glVertexAttrib4NsvARB(i, (const GLshort *)ptr));
+                    break;
+                case WINED3DFMT_R16G16B16A16_UNORM:
+                    GL_EXTCALL(glVertexAttrib4NusvARB(i, (const GLushort *)ptr));
+                    break;
+
+                case WINED3DFMT_R10G10B10A2_UINT:
+                    FIXME("Unsure about WINED3DDECLTYPE_UDEC3\n");
+                    /*glVertexAttrib3usvARB(i, (const GLushort *)ptr); Does not exist */
+                    break;
+                case WINED3DFMT_R10G10B10A2_SNORM:
+                    FIXME("Unsure about WINED3DDECLTYPE_DEC3N\n");
+                    /*glVertexAttrib3NusvARB(i, (const GLushort *)ptr); Does not exist */
+                    break;
+
+                case WINED3DFMT_R16G16_FLOAT:
+                    /* Are those 16 bit floats. C doesn't have a 16 bit float type. I could read the single bits and calculate a 4
+                     * byte float according to the IEEE standard
+                     */
+                    FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_2\n");
+                    break;
+                case WINED3DFMT_R16G16B16A16_FLOAT:
+                    FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_4\n");
+                    break;
+
+                default:
+                    ERR("Unexpected declaration in stride 0 attributes\n");
+                    break;
+
+            }
+        }
+    }
+    checkGLcall("Loading numbered arrays");
+}
+
+static void load_vertex_data(const struct wined3d_context *context,
+        const struct wined3d_stream_info *si, const struct wined3d_state *state)
+{
+    struct wined3d_device *device = context->swapchain->device;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    GLuint curVBO = gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] ? ~0U : 0;
+    const struct wined3d_stream_info_element *e;
+
+    TRACE("Using fast vertex array code\n");
+
+    /* This is fixed function pipeline only, and the fixed function pipeline doesn't do instancing */
+    device->instance_count = 0;
+
+    /* Blend Data ---------------------------------------------- */
+    if ((si->use_map & (1 << WINED3D_FFP_BLENDWEIGHT))
+            || si->use_map & (1 << WINED3D_FFP_BLENDINDICES))
+    {
+        e = &si->elements[WINED3D_FFP_BLENDWEIGHT];
+
+        if (gl_info->supported[ARB_VERTEX_BLEND])
+        {
+            TRACE("Blend %u %p %u\n", e->format->component_count,
+                    e->data.addr + state->load_base_vertex_index * e->stride, e->stride);
+
+            gl_info->gl_ops.gl.p_glEnableClientState(GL_WEIGHT_ARRAY_ARB);
+            checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
+
+            GL_EXTCALL(glVertexBlendARB(e->format->component_count + 1));
+
+            if (curVBO != e->data.buffer_object)
+            {
+                GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->data.buffer_object));
+                checkGLcall("glBindBufferARB");
+                curVBO = e->data.buffer_object;
+            }
+
+            TRACE("glWeightPointerARB(%#x, %#x, %#x, %p);\n",
+                    e->format->gl_vtx_format,
+                    e->format->gl_vtx_type,
+                    e->stride,
+                    e->data.addr + state->load_base_vertex_index * e->stride);
+            GL_EXTCALL(glWeightPointerARB(e->format->gl_vtx_format, e->format->gl_vtx_type, e->stride,
+                    e->data.addr + state->load_base_vertex_index * e->stride));
+
+            checkGLcall("glWeightPointerARB");
+
+            if (si->use_map & (1 << WINED3D_FFP_BLENDINDICES))
+            {
+                static BOOL warned;
+                if (!warned)
+                {
+                    FIXME("blendMatrixIndices support\n");
+                    warned = TRUE;
+                }
+            }
+        } else {
+            /* TODO: support blends in drawStridedSlow
+             * No need to write a FIXME here, this is done after the general vertex decl decoding
+             */
+            WARN("unsupported blending in openGl\n");
+        }
+    }
+    else
+    {
+        if (gl_info->supported[ARB_VERTEX_BLEND])
+        {
+            static const GLbyte one = 1;
+            GL_EXTCALL(glWeightbvARB(1, &one));
+            checkGLcall("glWeightbvARB(gl_info->max_blends, weights)");
+        }
+    }
+
+    /* Point Size ----------------------------------------------*/
+    if (si->use_map & (1 << WINED3D_FFP_PSIZE))
+    {
+        /* no such functionality in the fixed function GL pipeline */
+        TRACE("Cannot change ptSize here in openGl\n");
+        /* TODO: Implement this function in using shaders if they are available */
+    }
+
+    /* Vertex Pointers -----------------------------------------*/
+    if (si->use_map & (1 << WINED3D_FFP_POSITION))
+    {
+        e = &si->elements[WINED3D_FFP_POSITION];
+
+        if (curVBO != e->data.buffer_object)
+        {
+            GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->data.buffer_object));
+            checkGLcall("glBindBufferARB");
+            curVBO = e->data.buffer_object;
+        }
+
+        TRACE("glVertexPointer(%#x, %#x, %#x, %p);\n",
+                e->format->gl_vtx_format, e->format->gl_vtx_type, e->stride,
+                e->data.addr + state->load_base_vertex_index * e->stride);
+        gl_info->gl_ops.gl.p_glVertexPointer(e->format->gl_vtx_format, e->format->gl_vtx_type, e->stride,
+                e->data.addr + state->load_base_vertex_index * e->stride);
+        checkGLcall("glVertexPointer(...)");
+        gl_info->gl_ops.gl.p_glEnableClientState(GL_VERTEX_ARRAY);
+        checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
+    }
+
+    /* Normals -------------------------------------------------*/
+    if (si->use_map & (1 << WINED3D_FFP_NORMAL))
+    {
+        e = &si->elements[WINED3D_FFP_NORMAL];
+
+        if (curVBO != e->data.buffer_object)
+        {
+            GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->data.buffer_object));
+            checkGLcall("glBindBufferARB");
+            curVBO = e->data.buffer_object;
+        }
+
+        TRACE("glNormalPointer(%#x, %#x, %p);\n", e->format->gl_vtx_type, e->stride,
+                e->data.addr + state->load_base_vertex_index * e->stride);
+        gl_info->gl_ops.gl.p_glNormalPointer(e->format->gl_vtx_type, e->stride,
+                e->data.addr + state->load_base_vertex_index * e->stride);
+        checkGLcall("glNormalPointer(...)");
+        gl_info->gl_ops.gl.p_glEnableClientState(GL_NORMAL_ARRAY);
+        checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
+
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glNormal3f(0, 0, 0);
+        checkGLcall("glNormal3f(0, 0, 0)");
+    }
+
+    /* Diffuse Colour --------------------------------------------*/
+    if (si->use_map & (1 << WINED3D_FFP_DIFFUSE))
+    {
+        e = &si->elements[WINED3D_FFP_DIFFUSE];
+
+        if (curVBO != e->data.buffer_object)
+        {
+            GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->data.buffer_object));
+            checkGLcall("glBindBufferARB");
+            curVBO = e->data.buffer_object;
+        }
+
+        TRACE("glColorPointer(%#x, %#x %#x, %p);\n",
+                e->format->gl_vtx_format, e->format->gl_vtx_type, e->stride,
+                e->data.addr + state->load_base_vertex_index * e->stride);
+        gl_info->gl_ops.gl.p_glColorPointer(e->format->gl_vtx_format, e->format->gl_vtx_type, e->stride,
+                e->data.addr + state->load_base_vertex_index * e->stride);
+        checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
+        gl_info->gl_ops.gl.p_glEnableClientState(GL_COLOR_ARRAY);
+        checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
+
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+        checkGLcall("glColor4f(1, 1, 1, 1)");
+    }
+
+    /* Specular Colour ------------------------------------------*/
+    if (si->use_map & (1 << WINED3D_FFP_SPECULAR))
+    {
+        TRACE("setting specular colour\n");
+
+        e = &si->elements[WINED3D_FFP_SPECULAR];
+
+        if (gl_info->supported[EXT_SECONDARY_COLOR])
+        {
+            GLenum type = e->format->gl_vtx_type;
+            GLint format = e->format->gl_vtx_format;
+
+            if (curVBO != e->data.buffer_object)
+            {
+                GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->data.buffer_object));
+                checkGLcall("glBindBufferARB");
+                curVBO = e->data.buffer_object;
+            }
+
+            if (format != 4 || (gl_info->quirks & WINED3D_QUIRK_ALLOWS_SPECULAR_ALPHA))
+            {
+                /* Usually specular colors only allow 3 components, since they have no alpha. In D3D, the specular alpha
+                 * contains the fog coordinate, which is passed to GL with GL_EXT_fog_coord. However, the fixed function
+                 * vertex pipeline can pass the specular alpha through, and pixel shaders can read it. So it GL accepts
+                 * 4 component secondary colors use it
+                 */
+                TRACE("glSecondaryColorPointer(%#x, %#x, %#x, %p);\n", format, type, e->stride,
+                        e->data.addr + state->load_base_vertex_index * e->stride);
+                GL_EXTCALL(glSecondaryColorPointerEXT(format, type, e->stride,
+                        e->data.addr + state->load_base_vertex_index * e->stride));
+                checkGLcall("glSecondaryColorPointerEXT(format, type, ...)");
+            }
+            else
+            {
+                switch(type)
+                {
+                    case GL_UNSIGNED_BYTE:
+                        TRACE("glSecondaryColorPointer(3, GL_UNSIGNED_BYTE, %#x, %p);\n", e->stride,
+                                e->data.addr + state->load_base_vertex_index * e->stride);
+                        GL_EXTCALL(glSecondaryColorPointerEXT(3, GL_UNSIGNED_BYTE, e->stride,
+                                e->data.addr + state->load_base_vertex_index * e->stride));
+                        checkGLcall("glSecondaryColorPointerEXT(3, GL_UNSIGNED_BYTE, ...)");
+                        break;
+
+                    default:
+                        FIXME("Add 4 component specular color pointers for type %x\n", type);
+                        /* Make sure that the right color component is dropped */
+                        TRACE("glSecondaryColorPointer(3, %#x, %#x, %p);\n", type, e->stride,
+                                e->data.addr + state->load_base_vertex_index * e->stride);
+                        GL_EXTCALL(glSecondaryColorPointerEXT(3, type, e->stride,
+                                e->data.addr + state->load_base_vertex_index * e->stride));
+                        checkGLcall("glSecondaryColorPointerEXT(3, type, ...)");
+                }
+            }
+            gl_info->gl_ops.gl.p_glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
+            checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
+        }
+        else
+        {
+            WARN("Specular colour is not supported in this GL implementation.\n");
+        }
+    }
+    else
+    {
+        if (gl_info->supported[EXT_SECONDARY_COLOR])
+        {
+            GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
+            checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
+        }
+        else
+        {
+            WARN("Specular colour is not supported in this GL implementation.\n");
+        }
+    }
+
+    /* Texture coords -------------------------------------------*/
+    load_tex_coords(context, si, &curVBO, state);
+}
+
+static void streamsrc(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_device *device = context->swapchain->device;
+    BOOL load_numbered = use_vs(state) && !device->useDrawStridedSlow;
+    BOOL load_named = !use_vs(state) && !device->useDrawStridedSlow;
+
+    if (isStateDirty(context, STATE_VDECL)) return;
+    if (context->numberedArraysLoaded && !load_numbered)
+    {
+        unload_numbered_arrays(context);
+        context->numberedArraysLoaded = FALSE;
+        context->numbered_array_mask = 0;
+    }
+    else if (context->namedArraysLoaded)
+    {
+        unload_vertex_data(context->gl_info);
+        context->namedArraysLoaded = FALSE;
+    }
+
+    if (load_numbered)
+    {
+        TRACE("Loading numbered arrays\n");
+        load_numbered_arrays(context, &device->stream_info, state);
+        context->numberedArraysLoaded = TRUE;
+    }
+    else if (load_named)
+    {
+        TRACE("Loading vertex data\n");
+        load_vertex_data(context, &device->stream_info, state);
+        context->namedArraysLoaded = TRUE;
+    }
+}
+
+static void vdecl_miscpart(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    if (isStateDirty(context, STATE_STREAMSRC))
+        return;
+    streamsrc(context, state, STATE_STREAMSRC);
+}
+
+void vertexdeclaration(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_device *device = context->swapchain->device;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    BOOL useVertexShaderFunction = use_vs(state);
+    BOOL updateFog = FALSE;
+    BOOL transformed;
+    BOOL wasrhw = context->last_was_rhw;
+    unsigned int i;
+
+    transformed = device->stream_info.position_transformed;
+    if (transformed != context->last_was_rhw && !useVertexShaderFunction)
+        updateFog = TRUE;
+
+    context->last_was_rhw = transformed;
+
+    /* Don't have to apply the matrices when vertex shaders are used. When
+     * vshaders are turned off this function will be called again anyway to
+     * make sure they're properly set. */
+    if (!useVertexShaderFunction)
+    {
+        /* TODO: Move this mainly to the viewport state and only apply when
+         * the vp has changed or transformed / untransformed was switched. */
+        if (wasrhw != context->last_was_rhw
+                && !isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_PROJECTION))
+                && !isStateDirty(context, STATE_VIEWPORT))
+            transform_projection(context, state, STATE_TRANSFORM(WINED3D_TS_PROJECTION));
+        /* World matrix needs reapplication here only if we're switching between rhw and non-rhw
+         * mode.
+         *
+         * If a vertex shader is used, the world matrix changed and then vertex shader unbound
+         * this check will fail and the matrix not applied again. This is OK because a simple
+         * world matrix change reapplies the matrix - These checks here are only to satisfy the
+         * needs of the vertex declaration.
+         *
+         * World and view matrix go into the same gl matrix, so only apply them when neither is
+         * dirty
+         */
+        if (transformed != wasrhw && !isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)))
+                && !isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_VIEW)))
+            transform_world(context, state, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)));
+        if (!isStateDirty(context, STATE_RENDER(WINED3D_RS_COLORVERTEX)))
+            state_colormat(context, state, STATE_RENDER(WINED3D_RS_COLORVERTEX));
+        if (!isStateDirty(context, STATE_RENDER(WINED3D_RS_LIGHTING)))
+            state_lighting(context, state, STATE_RENDER(WINED3D_RS_LIGHTING));
+
+        if (context->last_was_vshader)
+        {
+            updateFog = TRUE;
+
+            if (!context->d3d_info->vs_clipping
+                    && !isStateDirty(context, STATE_RENDER(WINED3D_RS_CLIPPLANEENABLE)))
+            {
+                state_clipping(context, state, STATE_RENDER(WINED3D_RS_CLIPPLANEENABLE));
+            }
+
+            for (i = 0; i < gl_info->limits.clipplanes; ++i)
+            {
+                clipplane(context, state, STATE_CLIPPLANE(i));
+            }
+        }
+        if (!isStateDirty(context, STATE_RENDER(WINED3D_RS_NORMALIZENORMALS)))
+            state_normalize(context, state, STATE_RENDER(WINED3D_RS_NORMALIZENORMALS));
+    }
+    else
+    {
+        if(!context->last_was_vshader) {
+            static BOOL warned = FALSE;
+            if (!context->d3d_info->vs_clipping)
+            {
+                /* Disable all clip planes to get defined results on all drivers. See comment in the
+                 * state_clipping state handler
+                 */
+                for (i = 0; i < gl_info->limits.clipplanes; ++i)
+                {
+                    gl_info->gl_ops.gl.p_glDisable(GL_CLIP_PLANE0 + i);
+                    checkGLcall("glDisable(GL_CLIP_PLANE0 + i)");
+                }
+
+                if (!warned && state->render_states[WINED3D_RS_CLIPPLANEENABLE])
+                {
+                    FIXME("Clipping not supported with vertex shaders\n");
+                    warned = TRUE;
+                }
+            }
+            if (wasrhw)
+            {
+                /* Apply the transform matrices when switching from rhw
+                 * drawing to vertex shaders. Vertex shaders themselves do
+                 * not need it, but the matrices are not reapplied
+                 * automatically when switching back from vertex shaders to
+                 * fixed function processing. So make sure we leave the fixed
+                 * function vertex processing states back in a sane state
+                 * before switching to shaders. */
+                if (!isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_PROJECTION)))
+                    transform_projection(context, state, STATE_TRANSFORM(WINED3D_TS_PROJECTION));
+                if (!isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0))))
+                    transform_world(context, state, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)));
+            }
+            updateFog = TRUE;
+
+            /* Vertex shader clipping ignores the view matrix. Update all clipplanes
+             * (Note: ARB shaders can read the clip planes for clipping emulation even if
+             * device->vs_clipping is false.
+             */
+            for (i = 0; i < gl_info->limits.clipplanes; ++i)
+            {
+                clipplane(context, state, STATE_CLIPPLANE(i));
+            }
+        }
+    }
+
+    context->last_was_vshader = useVertexShaderFunction;
+    context->select_shader = 1;
+    context->load_constants = 1;
+
+    if (updateFog)
+        context_apply_state(context, state, STATE_RENDER(WINED3D_RS_FOGVERTEXMODE));
+
+    if (!useVertexShaderFunction)
+    {
+        unsigned int i;
+
+        for (i = 0; i < MAX_TEXTURES; ++i)
+        {
+            if (!isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_TEXTURE0 + i)))
+                transform_texture(context, state, STATE_TEXTURESTAGE(i, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS));
+        }
+    }
+
+    if (transformed != wasrhw && !isStateDirty(context, STATE_RENDER(WINED3D_RS_ZENABLE)))
+        state_zenable(context, state, STATE_RENDER(WINED3D_RS_ZENABLE));
+}
+
+static void viewport_miscpart(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_surface *target = state->fb->render_targets[0];
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    struct wined3d_viewport vp = state->viewport;
+
+    if (vp.width > target->resource.width)
+        vp.width = target->resource.width;
+    if (vp.height > target->resource.height)
+        vp.height = target->resource.height;
+
+    gl_info->gl_ops.gl.p_glDepthRange(vp.min_z, vp.max_z);
+    checkGLcall("glDepthRange");
+    /* Note: GL requires lower left, DirectX supplies upper left. This is
+     * reversed when using offscreen rendering. */
+    if (context->render_offscreen)
+    {
+        gl_info->gl_ops.gl.p_glViewport(vp.x, vp.y, vp.width, vp.height);
+    }
+    else
+    {
+        UINT width, height;
+
+        target->get_drawable_size(context, &width, &height);
+        gl_info->gl_ops.gl.p_glViewport(vp.x, (height - (vp.y + vp.height)),
+                vp.width, vp.height);
+    }
+
+    if (!isStateDirty(context, STATE_RENDER(WINED3D_RS_POINTSCALEENABLE)))
+        state_pscale(context, state, STATE_RENDER(WINED3D_RS_POINTSCALEENABLE));
+
+    checkGLcall("glViewport");
+}
+
+void viewport_vertexpart(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    if (!isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_PROJECTION)))
+        transform_projection(context, state, STATE_TRANSFORM(WINED3D_TS_PROJECTION));
+    if (!isStateDirty(context, STATE_RENDER(WINED3D_RS_POINTSCALEENABLE)))
+        state_pscale(context, state, STATE_RENDER(WINED3D_RS_POINTSCALEENABLE));
+    /* Update the position fixup. */
+    context->load_constants = 1;
+}
+
+void light(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    UINT Index = state_id - STATE_ACTIVELIGHT(0);
+    const struct wined3d_light_info *lightInfo = state->lights[Index];
+
+    if (!lightInfo)
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_LIGHT0 + Index);
+        checkGLcall("glDisable(GL_LIGHT0 + Index)");
+    }
+    else
+    {
+        float quad_att;
+        float colRGBA[] = {0.0f, 0.0f, 0.0f, 0.0f};
+
+        /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
+        gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
+        gl_info->gl_ops.gl.p_glPushMatrix();
+        gl_info->gl_ops.gl.p_glLoadMatrixf(&state->transforms[WINED3D_TS_VIEW].u.m[0][0]);
+
+        /* Diffuse: */
+        colRGBA[0] = lightInfo->OriginalParms.diffuse.r;
+        colRGBA[1] = lightInfo->OriginalParms.diffuse.g;
+        colRGBA[2] = lightInfo->OriginalParms.diffuse.b;
+        colRGBA[3] = lightInfo->OriginalParms.diffuse.a;
+        gl_info->gl_ops.gl.p_glLightfv(GL_LIGHT0 + Index, GL_DIFFUSE, colRGBA);
+        checkGLcall("glLightfv");
+
+        /* Specular */
+        colRGBA[0] = lightInfo->OriginalParms.specular.r;
+        colRGBA[1] = lightInfo->OriginalParms.specular.g;
+        colRGBA[2] = lightInfo->OriginalParms.specular.b;
+        colRGBA[3] = lightInfo->OriginalParms.specular.a;
+        gl_info->gl_ops.gl.p_glLightfv(GL_LIGHT0 + Index, GL_SPECULAR, colRGBA);
+        checkGLcall("glLightfv");
+
+        /* Ambient */
+        colRGBA[0] = lightInfo->OriginalParms.ambient.r;
+        colRGBA[1] = lightInfo->OriginalParms.ambient.g;
+        colRGBA[2] = lightInfo->OriginalParms.ambient.b;
+        colRGBA[3] = lightInfo->OriginalParms.ambient.a;
+        gl_info->gl_ops.gl.p_glLightfv(GL_LIGHT0 + Index, GL_AMBIENT, colRGBA);
+        checkGLcall("glLightfv");
+
+        if ((lightInfo->OriginalParms.range * lightInfo->OriginalParms.range) >= FLT_MIN)
+            quad_att = 1.4f / (lightInfo->OriginalParms.range * lightInfo->OriginalParms.range);
+        else
+            quad_att = 0.0f; /*  0 or  MAX?  (0 seems to be ok) */
+
+        /* Do not assign attenuation values for lights that do not use them. D3D apps are free to pass any junk,
+         * but gl drivers use them and may crash due to bad Attenuation values. Need for Speed most wanted sets
+         * Attenuation0 to NaN and crashes in the gl lib
+         */
+
+        switch (lightInfo->OriginalParms.type)
+        {
+            case WINED3D_LIGHT_POINT:
+                /* Position */
+                gl_info->gl_ops.gl.p_glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
+                checkGLcall("glLightfv");
+                gl_info->gl_ops.gl.p_glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
+                checkGLcall("glLightf");
+                /* Attenuation - Are these right? guessing... */
+                gl_info->gl_ops.gl.p_glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION,
+                        lightInfo->OriginalParms.attenuation0);
+                checkGLcall("glLightf");
+                gl_info->gl_ops.gl.p_glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION,
+                        lightInfo->OriginalParms.attenuation1);
+                checkGLcall("glLightf");
+                if (quad_att < lightInfo->OriginalParms.attenuation2)
+                    quad_att = lightInfo->OriginalParms.attenuation2;
+                gl_info->gl_ops.gl.p_glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
+                checkGLcall("glLightf");
+                /* FIXME: Range */
+                break;
+
+            case WINED3D_LIGHT_SPOT:
+                /* Position */
+                gl_info->gl_ops.gl.p_glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
+                checkGLcall("glLightfv");
+                /* Direction */
+                gl_info->gl_ops.gl.p_glLightfv(GL_LIGHT0 + Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
+                checkGLcall("glLightfv");
+                gl_info->gl_ops.gl.p_glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
+                checkGLcall("glLightf");
+                gl_info->gl_ops.gl.p_glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
+                checkGLcall("glLightf");
+                /* Attenuation - Are these right? guessing... */
+                gl_info->gl_ops.gl.p_glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION,
+                        lightInfo->OriginalParms.attenuation0);
+                checkGLcall("glLightf");
+                gl_info->gl_ops.gl.p_glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION,
+                        lightInfo->OriginalParms.attenuation1);
+                checkGLcall("glLightf");
+                if (quad_att < lightInfo->OriginalParms.attenuation2)
+                    quad_att = lightInfo->OriginalParms.attenuation2;
+                gl_info->gl_ops.gl.p_glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
+                checkGLcall("glLightf");
+                /* FIXME: Range */
+                break;
+
+            case WINED3D_LIGHT_DIRECTIONAL:
+                /* Direction */
+                /* Note GL uses w position of 0 for direction! */
+                gl_info->gl_ops.gl.p_glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
+                checkGLcall("glLightfv");
+                gl_info->gl_ops.gl.p_glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
+                checkGLcall("glLightf");
+                gl_info->gl_ops.gl.p_glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, 0.0f);
+                checkGLcall("glLightf");
+                break;
+
+            default:
+                FIXME("Unrecognized light type %#x.\n", lightInfo->OriginalParms.type);
+        }
+
+        /* Restore the modelview matrix */
+        gl_info->gl_ops.gl.p_glPopMatrix();
+
+        gl_info->gl_ops.gl.p_glEnable(GL_LIGHT0 + Index);
+        checkGLcall("glEnable(GL_LIGHT0 + Index)");
+    }
+}
+
+static void scissorrect(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    const RECT *r = &state->scissor_rect;
+
+    /* Warning: glScissor uses window coordinates, not viewport coordinates,
+     * so our viewport correction does not apply. Warning2: Even in windowed
+     * mode the coords are relative to the window, not the screen. */
+    TRACE("Setting new scissor rect to %s.\n", wine_dbgstr_rect(r));
+
+    if (context->render_offscreen)
+    {
+        gl_info->gl_ops.gl.p_glScissor(r->left, r->top, r->right - r->left, r->bottom - r->top);
+    }
+    else
+    {
+        const struct wined3d_surface *target = state->fb->render_targets[0];
+        UINT height;
+        UINT width;
+
+        target->get_drawable_size(context, &width, &height);
+        gl_info->gl_ops.gl.p_glScissor(r->left, height - r->bottom, r->right - r->left, r->bottom - r->top);
+    }
+    checkGLcall("glScissor");
+}
+
+static void indexbuffer(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_stream_info *stream_info = &context->swapchain->device->stream_info;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    if (!state->index_buffer || !stream_info->all_vbo)
+    {
+        GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
+    }
+    else
+    {
+        struct wined3d_buffer *ib = state->index_buffer;
+        GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ib->buffer_object));
+    }
+}
+
+static void frontface(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    if (context->render_offscreen)
+    {
+        gl_info->gl_ops.gl.p_glFrontFace(GL_CCW);
+        checkGLcall("glFrontFace(GL_CCW)");
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glFrontFace(GL_CW);
+        checkGLcall("glFrontFace(GL_CW)");
+    }
+}
+
+static void psorigin_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    static BOOL warned;
+
+    if (!warned)
+    {
+        WARN("Point sprite coordinate origin switching not supported.\n");
+        warned = TRUE;
+    }
+}
+
+static void psorigin(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    GLint origin = context->render_offscreen ? GL_LOWER_LEFT : GL_UPPER_LEFT;
+
+    if (gl_info->supported[NV_POINT_SPRITE])
+    {
+        GL_EXTCALL(glPointParameteriNV(GL_POINT_SPRITE_COORD_ORIGIN, origin));
+        checkGLcall("glPointParameteriNV(GL_POINT_SPRITE_COORD_ORIGIN, ...)");
+    }
+}
+
+void state_srgbwrite(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    const struct wined3d_surface *rt = state->fb->render_targets[0];
+
+    TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);
+
+    if (state->render_states[WINED3D_RS_SRGBWRITEENABLE]
+            && rt->resource.format->flags & WINED3DFMT_FLAG_SRGB_WRITE)
+        gl_info->gl_ops.gl.p_glEnable(GL_FRAMEBUFFER_SRGB);
+    else
+        gl_info->gl_ops.gl.p_glDisable(GL_FRAMEBUFFER_SRGB);
+}
+
+const struct StateEntryTemplate misc_state_template[] = {
+    { STATE_RENDER(WINED3D_RS_SRCBLEND),                  { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_DESTBLEND),                 { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE),          { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE),          state_blend         }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_EDGEANTIALIAS),             { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_ANTIALIASEDLINEENABLE),     { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_SEPARATEALPHABLENDENABLE),  { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_SRCBLENDALPHA),             { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_DESTBLENDALPHA),            { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_DESTBLENDALPHA),            { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_BLENDOPALPHA),              { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_STREAMSRC,                                    { STATE_STREAMSRC,                                    streamsrc           }, WINED3D_GL_EXT_NONE             },
+    { STATE_VDECL,                                        { STATE_VDECL,                                        vdecl_miscpart      }, WINED3D_GL_EXT_NONE             },
+    { STATE_FRONTFACE,                                    { STATE_FRONTFACE,                                    frontface           }, WINED3D_GL_EXT_NONE             },
+    { STATE_SCISSORRECT,                                  { STATE_SCISSORRECT,                                  scissorrect         }, WINED3D_GL_EXT_NONE             },
+    { STATE_POINTSPRITECOORDORIGIN,                       { STATE_POINTSPRITECOORDORIGIN,                       psorigin            }, WINED3D_GL_VERSION_2_0          },
+    { STATE_POINTSPRITECOORDORIGIN,                       { STATE_POINTSPRITECOORDORIGIN,                       psorigin_w          }, WINED3D_GL_EXT_NONE             },
+
+    /* TODO: Move shader constant loading to vertex and fragment pipeline respectively, as soon as the pshader and
+     * vshader loadings are untied from each other
+     */
+    { STATE_VERTEXSHADERCONSTANT,                         { STATE_VERTEXSHADERCONSTANT,                         shaderconstant      }, WINED3D_GL_EXT_NONE             },
+    { STATE_PIXELSHADERCONSTANT,                          { STATE_VERTEXSHADERCONSTANT,                         NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   shader_bumpenvmat   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   shader_bumpenvmat   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   shader_bumpenvmat   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   shader_bumpenvmat   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   shader_bumpenvmat   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   shader_bumpenvmat   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   shader_bumpenvmat   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   shader_bumpenvmat   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE),  { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE),  tex_bumpenvlscale   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LOFFSET), { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE),  NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE),  { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE),  tex_bumpenvlscale   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LOFFSET), { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE),  NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE),  { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE),  tex_bumpenvlscale   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LOFFSET), { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE),  NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE),  { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE),  tex_bumpenvlscale   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LOFFSET), { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE),  NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE),  { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE),  tex_bumpenvlscale   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LOFFSET), { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE),  NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE),  { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE),  tex_bumpenvlscale   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LOFFSET), { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE),  NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE),  { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE),  tex_bumpenvlscale   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LOFFSET), { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE),  NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE),  { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE),  tex_bumpenvlscale   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LOFFSET), { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE),  NULL                }, WINED3D_GL_EXT_NONE             },
+
+    { STATE_VIEWPORT,                                     { STATE_VIEWPORT,                                     viewport_miscpart   }, WINED3D_GL_EXT_NONE             },
+    { STATE_INDEXBUFFER,                                  { STATE_INDEXBUFFER,                                  indexbuffer         }, ARB_VERTEX_BUFFER_OBJECT        },
+    { STATE_INDEXBUFFER,                                  { STATE_INDEXBUFFER,                                  state_nop           }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_ANTIALIAS),                 { STATE_RENDER(WINED3D_RS_ANTIALIAS),                 state_antialias     }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_TEXTUREPERSPECTIVE),        { STATE_RENDER(WINED3D_RS_TEXTUREPERSPECTIVE),        state_perspective   }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_ZENABLE),                   { STATE_RENDER(WINED3D_RS_ZENABLE),                   state_zenable       }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_WRAPU),                     { STATE_RENDER(WINED3D_RS_WRAPU),                     state_wrapu         }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_WRAPV),                     { STATE_RENDER(WINED3D_RS_WRAPV),                     state_wrapv         }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_FILLMODE),                  { STATE_RENDER(WINED3D_RS_FILLMODE),                  state_fillmode      }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_SHADEMODE),                 { STATE_RENDER(WINED3D_RS_SHADEMODE),                 state_shademode     }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_LINEPATTERN),               { STATE_RENDER(WINED3D_RS_LINEPATTERN),               state_linepattern   }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_MONOENABLE),                { STATE_RENDER(WINED3D_RS_MONOENABLE),                state_monoenable    }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_ROP2),                      { STATE_RENDER(WINED3D_RS_ROP2),                      state_rop2          }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_PLANEMASK),                 { STATE_RENDER(WINED3D_RS_PLANEMASK),                 state_planemask     }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_ZWRITEENABLE),              { STATE_RENDER(WINED3D_RS_ZWRITEENABLE),              state_zwritenable   }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_ALPHATESTENABLE),           { STATE_RENDER(WINED3D_RS_ALPHATESTENABLE),           state_alpha         }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_ALPHAREF),                  { STATE_RENDER(WINED3D_RS_ALPHATESTENABLE),           NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_ALPHAFUNC),                 { STATE_RENDER(WINED3D_RS_ALPHATESTENABLE),           NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_COLORKEYENABLE),            { STATE_RENDER(WINED3D_RS_ALPHATESTENABLE),           NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_LASTPIXEL),                 { STATE_RENDER(WINED3D_RS_LASTPIXEL),                 state_lastpixel     }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_CULLMODE),                  { STATE_RENDER(WINED3D_RS_CULLMODE),                  state_cullmode      }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_ZFUNC),                     { STATE_RENDER(WINED3D_RS_ZFUNC),                     state_zfunc         }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_DITHERENABLE),              { STATE_RENDER(WINED3D_RS_DITHERENABLE),              state_ditherenable  }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_SUBPIXEL),                  { STATE_RENDER(WINED3D_RS_SUBPIXEL),                  state_subpixel      }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_SUBPIXELX),                 { STATE_RENDER(WINED3D_RS_SUBPIXELX),                 state_subpixelx     }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_STIPPLEDALPHA),             { STATE_RENDER(WINED3D_RS_STIPPLEDALPHA),             state_stippledalpha }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_STIPPLEENABLE),             { STATE_RENDER(WINED3D_RS_STIPPLEENABLE),             state_stippleenable }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_MIPMAPLODBIAS),             { STATE_RENDER(WINED3D_RS_MIPMAPLODBIAS),             state_mipmaplodbias }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_ANISOTROPY),                { STATE_RENDER(WINED3D_RS_ANISOTROPY),                state_anisotropy    }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_FLUSHBATCH),                { STATE_RENDER(WINED3D_RS_FLUSHBATCH),                state_flushbatch    }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_TRANSLUCENTSORTINDEPENDENT),{ STATE_RENDER(WINED3D_RS_TRANSLUCENTSORTINDEPENDENT),state_translucentsi }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_STENCILENABLE),             { STATE_RENDER(WINED3D_RS_STENCILENABLE),             state_stencil       }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_STENCILFAIL),               { STATE_RENDER(WINED3D_RS_STENCILENABLE),             NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_STENCILZFAIL),              { STATE_RENDER(WINED3D_RS_STENCILENABLE),             NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_STENCILPASS),               { STATE_RENDER(WINED3D_RS_STENCILENABLE),             NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_STENCILFUNC),               { STATE_RENDER(WINED3D_RS_STENCILENABLE),             NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_STENCILREF),                { STATE_RENDER(WINED3D_RS_STENCILENABLE),             NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_STENCILMASK),               { STATE_RENDER(WINED3D_RS_STENCILENABLE),             NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_STENCILWRITEMASK),          { STATE_RENDER(WINED3D_RS_STENCILWRITEMASK),          state_stencilwrite2s}, EXT_STENCIL_TWO_SIDE            },
+    { STATE_RENDER(WINED3D_RS_STENCILWRITEMASK),          { STATE_RENDER(WINED3D_RS_STENCILWRITEMASK),          state_stencilwrite  }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_TWOSIDEDSTENCILMODE),       { STATE_RENDER(WINED3D_RS_STENCILENABLE),             NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_CCW_STENCILFAIL),           { STATE_RENDER(WINED3D_RS_STENCILENABLE),             NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_CCW_STENCILZFAIL),          { STATE_RENDER(WINED3D_RS_STENCILENABLE),             NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_CCW_STENCILPASS),           { STATE_RENDER(WINED3D_RS_STENCILENABLE),             NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_CCW_STENCILFUNC),           { STATE_RENDER(WINED3D_RS_STENCILENABLE),             NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_WRAP0),                     { STATE_RENDER(WINED3D_RS_WRAP0),                     state_wrap          }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_WRAP1),                     { STATE_RENDER(WINED3D_RS_WRAP0),                     NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_WRAP2),                     { STATE_RENDER(WINED3D_RS_WRAP0),                     NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_WRAP3),                     { STATE_RENDER(WINED3D_RS_WRAP0),                     NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_WRAP4),                     { STATE_RENDER(WINED3D_RS_WRAP0),                     NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_WRAP5),                     { STATE_RENDER(WINED3D_RS_WRAP0),                     NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_WRAP6),                     { STATE_RENDER(WINED3D_RS_WRAP0),                     NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_WRAP7),                     { STATE_RENDER(WINED3D_RS_WRAP0),                     NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_WRAP8),                     { STATE_RENDER(WINED3D_RS_WRAP0),                     NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_WRAP9),                     { STATE_RENDER(WINED3D_RS_WRAP0),                     NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_WRAP10),                    { STATE_RENDER(WINED3D_RS_WRAP0),                     NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_WRAP11),                    { STATE_RENDER(WINED3D_RS_WRAP0),                     NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_WRAP12),                    { STATE_RENDER(WINED3D_RS_WRAP0),                     NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_WRAP13),                    { STATE_RENDER(WINED3D_RS_WRAP0),                     NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_WRAP14),                    { STATE_RENDER(WINED3D_RS_WRAP0),                     NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_WRAP15),                    { STATE_RENDER(WINED3D_RS_WRAP0),                     NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_EXTENTS),                   { STATE_RENDER(WINED3D_RS_EXTENTS),                   state_extents       }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_COLORKEYBLENDENABLE),       { STATE_RENDER(WINED3D_RS_COLORKEYBLENDENABLE),       state_ckeyblend     }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_SOFTWAREVERTEXPROCESSING),  { STATE_RENDER(WINED3D_RS_SOFTWAREVERTEXPROCESSING),  state_swvp          }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_PATCHEDGESTYLE),            { STATE_RENDER(WINED3D_RS_PATCHEDGESTYLE),            state_patchedgestyle}, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_PATCHSEGMENTS),             { STATE_RENDER(WINED3D_RS_PATCHSEGMENTS),             state_patchsegments }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_POSITIONDEGREE),            { STATE_RENDER(WINED3D_RS_POSITIONDEGREE),            state_positiondegree}, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_NORMALDEGREE),              { STATE_RENDER(WINED3D_RS_NORMALDEGREE),              state_normaldegree  }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_MINTESSELLATIONLEVEL),      { STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION),NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_MAXTESSELLATIONLEVEL),      { STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION),NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_ADAPTIVETESS_X),            { STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION),NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_ADAPTIVETESS_Y),            { STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION),NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_ADAPTIVETESS_Z),            { STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION),NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_ADAPTIVETESS_W),            { STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION),NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION),{ STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION),state_nvdb          }, EXT_DEPTH_BOUNDS_TEST           },
+    { STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION),{ STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION),state_tessellation  }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_MULTISAMPLEANTIALIAS),      { STATE_RENDER(WINED3D_RS_MULTISAMPLEANTIALIAS),      state_msaa          }, ARB_MULTISAMPLE                 },
+    { STATE_RENDER(WINED3D_RS_MULTISAMPLEANTIALIAS),      { STATE_RENDER(WINED3D_RS_MULTISAMPLEANTIALIAS),      state_msaa_w        }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_MULTISAMPLEMASK),           { STATE_RENDER(WINED3D_RS_MULTISAMPLEMASK),           state_multisampmask }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_DEBUGMONITORTOKEN),         { STATE_RENDER(WINED3D_RS_DEBUGMONITORTOKEN),         state_debug_monitor }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_COLORWRITEENABLE),          { STATE_RENDER(WINED3D_RS_COLORWRITEENABLE),          state_colorwrite0   }, EXT_DRAW_BUFFERS2               },
+    { STATE_RENDER(WINED3D_RS_COLORWRITEENABLE),          { STATE_RENDER(WINED3D_RS_COLORWRITEENABLE),          state_colorwrite    }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_BLENDOP),                   { STATE_RENDER(WINED3D_RS_BLENDOP),                   state_blendop       }, EXT_BLEND_MINMAX                },
+    { STATE_RENDER(WINED3D_RS_BLENDOP),                   { STATE_RENDER(WINED3D_RS_BLENDOP),                   state_blendop_w     }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_SCISSORTESTENABLE),         { STATE_RENDER(WINED3D_RS_SCISSORTESTENABLE),         state_scissor       }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_SLOPESCALEDEPTHBIAS),       { STATE_RENDER(WINED3D_RS_DEPTHBIAS),                 NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_COLORWRITEENABLE1),         { STATE_RENDER(WINED3D_RS_COLORWRITEENABLE1),         state_colorwrite1   }, EXT_DRAW_BUFFERS2               },
+    { STATE_RENDER(WINED3D_RS_COLORWRITEENABLE1),         { STATE_RENDER(WINED3D_RS_COLORWRITEENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_COLORWRITEENABLE2),         { STATE_RENDER(WINED3D_RS_COLORWRITEENABLE2),         state_colorwrite2   }, EXT_DRAW_BUFFERS2               },
+    { STATE_RENDER(WINED3D_RS_COLORWRITEENABLE2),         { STATE_RENDER(WINED3D_RS_COLORWRITEENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_COLORWRITEENABLE3),         { STATE_RENDER(WINED3D_RS_COLORWRITEENABLE3),         state_colorwrite3   }, EXT_DRAW_BUFFERS2               },
+    { STATE_RENDER(WINED3D_RS_COLORWRITEENABLE3),         { STATE_RENDER(WINED3D_RS_COLORWRITEENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_BLENDFACTOR),               { STATE_RENDER(WINED3D_RS_BLENDFACTOR),               state_blendfactor   }, EXT_BLEND_COLOR                 },
+    { STATE_RENDER(WINED3D_RS_BLENDFACTOR),               { STATE_RENDER(WINED3D_RS_BLENDFACTOR),               state_blendfactor_w }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_DEPTHBIAS),                 { STATE_RENDER(WINED3D_RS_DEPTHBIAS),                 state_depthbias     }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_ZVISIBLE),                  { STATE_RENDER(WINED3D_RS_ZVISIBLE),                  state_zvisible      }, WINED3D_GL_EXT_NONE             },
+    /* Samplers */
+    { STATE_SAMPLER(0),                                   { STATE_SAMPLER(0),                                   sampler             }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(1),                                   { STATE_SAMPLER(1),                                   sampler             }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(2),                                   { STATE_SAMPLER(2),                                   sampler             }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(3),                                   { STATE_SAMPLER(3),                                   sampler             }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(4),                                   { STATE_SAMPLER(4),                                   sampler             }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(5),                                   { STATE_SAMPLER(5),                                   sampler             }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(6),                                   { STATE_SAMPLER(6),                                   sampler             }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(7),                                   { STATE_SAMPLER(7),                                   sampler             }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(8),                                   { STATE_SAMPLER(8),                                   sampler             }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(9),                                   { STATE_SAMPLER(9),                                   sampler             }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(10),                                  { STATE_SAMPLER(10),                                  sampler             }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(11),                                  { STATE_SAMPLER(11),                                  sampler             }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(12),                                  { STATE_SAMPLER(12),                                  sampler             }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(13),                                  { STATE_SAMPLER(13),                                  sampler             }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(14),                                  { STATE_SAMPLER(14),                                  sampler             }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(15),                                  { STATE_SAMPLER(15),                                  sampler             }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(16), /* Vertex sampler 0 */           { STATE_SAMPLER(16),                                  sampler             }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(17), /* Vertex sampler 1 */           { STATE_SAMPLER(17),                                  sampler             }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(18), /* Vertex sampler 2 */           { STATE_SAMPLER(18),                                  sampler             }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(19), /* Vertex sampler 3 */           { STATE_SAMPLER(19),                                  sampler             }, WINED3D_GL_EXT_NONE             },
+    { STATE_BASEVERTEXINDEX,                              { STATE_BASEVERTEXINDEX,                              state_nop,          }, ARB_DRAW_ELEMENTS_BASE_VERTEX   },
+    { STATE_BASEVERTEXINDEX,                              { STATE_STREAMSRC,                                    NULL,               }, WINED3D_GL_EXT_NONE             },
+    { STATE_FRAMEBUFFER,                                  { STATE_FRAMEBUFFER,                                  context_state_fb    }, WINED3D_GL_EXT_NONE             },
+    { STATE_PIXELSHADER,                                  { STATE_PIXELSHADER,                                  context_state_drawbuf},WINED3D_GL_EXT_NONE             },
+    { STATE_GEOMETRY_SHADER,                              { STATE_GEOMETRY_SHADER,                              state_geometry_shader}, WINED3D_GL_EXT_NONE             },
+    {0 /* Terminate */,                                   { 0,                                                  0                   }, WINED3D_GL_EXT_NONE             },
+};
+
+const struct StateEntryTemplate vp_ffp_states[] =
+{
+    { STATE_VDECL,                                        { STATE_VDECL,                                        vertexdeclaration   }, WINED3D_GL_EXT_NONE             },
+    { STATE_VSHADER,                                      { STATE_VDECL,                                        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_MATERIAL,                                     { STATE_RENDER(WINED3D_RS_SPECULARENABLE),            NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_SPECULARENABLE),            { STATE_RENDER(WINED3D_RS_SPECULARENABLE),            state_specularenable}, WINED3D_GL_EXT_NONE             },
+      /* Clip planes */
+    { STATE_CLIPPLANE(0),                                 { STATE_CLIPPLANE(0),                                 clipplane           }, WINED3D_GL_EXT_NONE             },
+    { STATE_CLIPPLANE(1),                                 { STATE_CLIPPLANE(1),                                 clipplane           }, WINED3D_GL_EXT_NONE             },
+    { STATE_CLIPPLANE(2),                                 { STATE_CLIPPLANE(2),                                 clipplane           }, WINED3D_GL_EXT_NONE             },
+    { STATE_CLIPPLANE(3),                                 { STATE_CLIPPLANE(3),                                 clipplane           }, WINED3D_GL_EXT_NONE             },
+    { STATE_CLIPPLANE(4),                                 { STATE_CLIPPLANE(4),                                 clipplane           }, WINED3D_GL_EXT_NONE             },
+    { STATE_CLIPPLANE(5),                                 { STATE_CLIPPLANE(5),                                 clipplane           }, WINED3D_GL_EXT_NONE             },
+    { STATE_CLIPPLANE(6),                                 { STATE_CLIPPLANE(6),                                 clipplane           }, WINED3D_GL_EXT_NONE             },
+    { STATE_CLIPPLANE(7),                                 { STATE_CLIPPLANE(7),                                 clipplane           }, WINED3D_GL_EXT_NONE             },
+    { STATE_CLIPPLANE(8),                                 { STATE_CLIPPLANE(8),                                 clipplane           }, WINED3D_GL_EXT_NONE             },
+    { STATE_CLIPPLANE(9),                                 { STATE_CLIPPLANE(9),                                 clipplane           }, WINED3D_GL_EXT_NONE             },
+    { STATE_CLIPPLANE(10),                                { STATE_CLIPPLANE(10),                                clipplane           }, WINED3D_GL_EXT_NONE             },
+    { STATE_CLIPPLANE(11),                                { STATE_CLIPPLANE(11),                                clipplane           }, WINED3D_GL_EXT_NONE             },
+    { STATE_CLIPPLANE(12),                                { STATE_CLIPPLANE(12),                                clipplane           }, WINED3D_GL_EXT_NONE             },
+    { STATE_CLIPPLANE(13),                                { STATE_CLIPPLANE(13),                                clipplane           }, WINED3D_GL_EXT_NONE             },
+    { STATE_CLIPPLANE(14),                                { STATE_CLIPPLANE(14),                                clipplane           }, WINED3D_GL_EXT_NONE             },
+    { STATE_CLIPPLANE(15),                                { STATE_CLIPPLANE(15),                                clipplane           }, WINED3D_GL_EXT_NONE             },
+    { STATE_CLIPPLANE(16),                                { STATE_CLIPPLANE(16),                                clipplane           }, WINED3D_GL_EXT_NONE             },
+    { STATE_CLIPPLANE(17),                                { STATE_CLIPPLANE(17),                                clipplane           }, WINED3D_GL_EXT_NONE             },
+    { STATE_CLIPPLANE(18),                                { STATE_CLIPPLANE(18),                                clipplane           }, WINED3D_GL_EXT_NONE             },
+    { STATE_CLIPPLANE(19),                                { STATE_CLIPPLANE(19),                                clipplane           }, WINED3D_GL_EXT_NONE             },
+    { STATE_CLIPPLANE(20),                                { STATE_CLIPPLANE(20),                                clipplane           }, WINED3D_GL_EXT_NONE             },
+    { STATE_CLIPPLANE(21),                                { STATE_CLIPPLANE(21),                                clipplane           }, WINED3D_GL_EXT_NONE             },
+    { STATE_CLIPPLANE(22),                                { STATE_CLIPPLANE(22),                                clipplane           }, WINED3D_GL_EXT_NONE             },
+    { STATE_CLIPPLANE(23),                                { STATE_CLIPPLANE(23),                                clipplane           }, WINED3D_GL_EXT_NONE             },
+    { STATE_CLIPPLANE(24),                                { STATE_CLIPPLANE(24),                                clipplane           }, WINED3D_GL_EXT_NONE             },
+    { STATE_CLIPPLANE(25),                                { STATE_CLIPPLANE(25),                                clipplane           }, WINED3D_GL_EXT_NONE             },
+    { STATE_CLIPPLANE(26),                                { STATE_CLIPPLANE(26),                                clipplane           }, WINED3D_GL_EXT_NONE             },
+    { STATE_CLIPPLANE(27),                                { STATE_CLIPPLANE(27),                                clipplane           }, WINED3D_GL_EXT_NONE             },
+    { STATE_CLIPPLANE(28),                                { STATE_CLIPPLANE(28),                                clipplane           }, WINED3D_GL_EXT_NONE             },
+    { STATE_CLIPPLANE(29),                                { STATE_CLIPPLANE(29),                                clipplane           }, WINED3D_GL_EXT_NONE             },
+    { STATE_CLIPPLANE(30),                                { STATE_CLIPPLANE(30),                                clipplane           }, WINED3D_GL_EXT_NONE             },
+    { STATE_CLIPPLANE(31),                                { STATE_CLIPPLANE(31),                                clipplane           }, WINED3D_GL_EXT_NONE             },
+      /* Lights */
+    { STATE_LIGHT_TYPE,                                   { STATE_LIGHT_TYPE,                                   state_nop           }, WINED3D_GL_EXT_NONE             },
+    { STATE_ACTIVELIGHT(0),                               { STATE_ACTIVELIGHT(0),                               light               }, WINED3D_GL_EXT_NONE             },
+    { STATE_ACTIVELIGHT(1),                               { STATE_ACTIVELIGHT(1),                               light               }, WINED3D_GL_EXT_NONE             },
+    { STATE_ACTIVELIGHT(2),                               { STATE_ACTIVELIGHT(2),                               light               }, WINED3D_GL_EXT_NONE             },
+    { STATE_ACTIVELIGHT(3),                               { STATE_ACTIVELIGHT(3),                               light               }, WINED3D_GL_EXT_NONE             },
+    { STATE_ACTIVELIGHT(4),                               { STATE_ACTIVELIGHT(4),                               light               }, WINED3D_GL_EXT_NONE             },
+    { STATE_ACTIVELIGHT(5),                               { STATE_ACTIVELIGHT(5),                               light               }, WINED3D_GL_EXT_NONE             },
+    { STATE_ACTIVELIGHT(6),                               { STATE_ACTIVELIGHT(6),                               light               }, WINED3D_GL_EXT_NONE             },
+    { STATE_ACTIVELIGHT(7),                               { STATE_ACTIVELIGHT(7),                               light               }, WINED3D_GL_EXT_NONE             },
+    /* Viewport */
+    { STATE_VIEWPORT,                                     { STATE_VIEWPORT,                                     viewport_vertexpart }, WINED3D_GL_EXT_NONE             },
+      /* Transform states follow                    */
+    { STATE_TRANSFORM(WINED3D_TS_VIEW),                   { STATE_TRANSFORM(WINED3D_TS_VIEW),                   transform_view      }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_PROJECTION),             { STATE_TRANSFORM(WINED3D_TS_PROJECTION),             transform_projection}, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_TEXTURE0),               { STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL            }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_TEXTURE1),               { STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL            }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_TEXTURE2),               { STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL            }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_TEXTURE3),               { STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL            }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_TEXTURE4),               { STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL            }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_TEXTURE5),               { STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL            }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_TEXTURE6),               { STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL            }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_TEXTURE7),               { STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL            }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  0)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  0)),      transform_world     }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  1)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  1)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  2)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  2)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  3)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  3)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  4)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  4)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  5)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  5)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  6)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  6)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  7)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  7)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  8)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  8)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  9)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  9)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 10)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 10)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 11)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 11)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 12)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 12)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 13)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 13)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 14)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 14)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 15)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 15)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 16)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 16)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 17)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 17)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 18)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 18)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 19)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 19)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 20)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 20)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 21)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 21)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 22)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 22)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 23)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 23)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 24)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 24)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 25)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 25)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 26)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 26)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 27)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 27)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 28)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 28)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 29)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 29)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 30)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 30)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 31)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 31)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 32)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 32)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 33)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 33)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 34)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 34)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 35)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 35)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 36)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 36)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 37)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 37)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 38)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 38)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 39)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 39)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 40)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 40)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 41)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 41)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 42)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 42)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 43)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 43)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 44)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 44)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 45)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 45)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 46)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 46)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 47)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 47)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 48)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 48)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 49)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 49)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 50)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 50)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 51)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 51)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 52)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 52)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 53)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 53)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 54)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 54)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 55)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 55)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 56)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 56)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 57)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 57)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 58)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 58)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 59)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 59)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 60)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 60)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 61)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 61)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 62)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 62)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 63)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 63)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 64)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 64)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 65)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 65)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 66)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 66)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 67)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 67)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 68)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 68)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 69)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 69)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 70)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 70)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 71)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 71)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 72)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 72)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 73)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 73)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 74)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 74)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 75)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 75)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 76)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 76)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 77)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 77)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 78)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 78)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 79)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 79)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 80)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 80)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 81)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 81)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 82)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 82)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 83)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 83)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 84)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 84)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 85)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 85)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 86)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 86)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 87)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 87)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 88)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 88)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 89)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 89)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 90)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 90)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 91)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 91)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 92)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 92)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 93)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 93)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 94)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 94)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 95)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 95)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 96)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 96)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 97)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 97)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 98)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 98)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 99)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 99)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(100)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(100)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(101)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(101)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(102)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(102)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(103)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(103)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(104)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(104)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(105)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(105)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(106)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(106)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(107)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(107)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(108)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(108)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(109)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(109)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(110)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(110)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(111)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(111)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(112)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(112)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(113)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(113)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(114)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(114)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(115)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(115)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(116)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(116)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(117)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(117)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(118)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(118)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(119)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(119)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(120)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(120)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(121)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(121)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(122)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(122)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(123)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(123)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(124)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(124)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(125)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(125)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(126)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(126)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(127)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(127)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(128)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(128)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(129)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(129)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(130)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(130)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(131)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(131)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(132)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(132)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(133)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(133)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(134)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(134)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(135)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(135)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(136)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(136)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(137)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(137)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(138)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(138)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(139)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(139)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(140)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(140)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(141)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(141)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(142)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(142)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(143)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(143)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(144)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(144)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(145)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(145)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(146)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(146)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(147)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(147)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(148)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(148)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(149)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(149)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(150)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(150)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(151)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(151)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(152)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(152)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(153)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(153)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(154)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(154)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(155)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(155)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(156)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(156)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(157)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(157)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(158)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(158)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(159)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(159)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(160)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(160)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(161)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(161)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(162)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(162)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(163)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(163)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(164)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(164)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(165)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(165)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(166)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(166)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(167)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(167)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(168)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(168)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(169)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(169)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(170)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(170)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(171)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(171)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(172)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(172)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(173)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(173)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(174)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(174)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(175)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(175)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(176)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(176)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(177)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(177)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(178)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(178)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(179)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(179)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(180)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(180)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(181)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(181)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(182)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(182)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(183)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(183)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(184)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(184)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(185)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(185)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(186)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(186)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(187)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(187)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(188)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(188)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(189)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(189)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(190)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(190)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(191)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(191)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(192)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(192)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(193)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(193)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(194)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(194)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(195)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(195)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(196)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(196)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(197)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(197)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(198)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(198)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(199)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(199)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(200)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(200)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(201)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(201)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(202)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(202)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(203)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(203)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(204)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(204)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(205)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(205)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(206)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(206)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(207)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(207)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(208)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(208)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(209)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(209)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(210)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(210)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(211)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(211)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(212)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(212)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(213)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(213)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(214)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(214)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(215)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(215)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(216)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(216)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(217)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(217)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(218)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(218)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(219)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(219)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(220)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(220)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(221)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(221)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(222)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(222)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(223)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(223)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(224)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(224)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(225)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(225)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(226)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(226)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(227)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(227)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(228)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(228)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(229)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(229)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(230)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(230)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(231)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(231)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(232)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(232)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(233)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(233)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(234)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(234)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(235)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(235)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(236)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(236)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(237)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(237)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(238)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(238)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(239)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(239)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(240)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(240)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(241)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(241)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(242)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(242)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(243)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(243)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(244)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(244)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(245)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(245)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(246)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(246)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(247)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(247)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(248)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(248)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(249)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(249)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(250)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(250)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(251)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(251)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(252)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(252)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(253)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(253)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(254)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(254)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(255)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(255)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXCOORD_INDEX),  { STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXCOORD_INDEX),  tex_coordindex      }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXCOORD_INDEX),  { STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXCOORD_INDEX),  tex_coordindex      }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXCOORD_INDEX),  { STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXCOORD_INDEX),  tex_coordindex      }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXCOORD_INDEX),  { STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXCOORD_INDEX),  tex_coordindex      }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXCOORD_INDEX),  { STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXCOORD_INDEX),  tex_coordindex      }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXCOORD_INDEX),  { STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXCOORD_INDEX),  tex_coordindex      }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXCOORD_INDEX),  { STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXCOORD_INDEX),  tex_coordindex      }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXCOORD_INDEX),  { STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXCOORD_INDEX),  tex_coordindex      }, WINED3D_GL_EXT_NONE             },
+      /* Fog */
+    { STATE_RENDER(WINED3D_RS_FOGENABLE),                 { STATE_RENDER(WINED3D_RS_FOGENABLE),                 state_fog_vertexpart}, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_FOGTABLEMODE),              { STATE_RENDER(WINED3D_RS_FOGENABLE),                 NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_FOGVERTEXMODE),             { STATE_RENDER(WINED3D_RS_FOGENABLE),                 NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_RANGEFOGENABLE),            { STATE_RENDER(WINED3D_RS_FOGENABLE),                 NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_CLIPPING),                  { STATE_RENDER(WINED3D_RS_CLIPPING),                  state_clipping      }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_CLIPPLANEENABLE),           { STATE_RENDER(WINED3D_RS_CLIPPING),                  NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_LIGHTING),                  { STATE_RENDER(WINED3D_RS_LIGHTING),                  state_lighting      }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_AMBIENT),                   { STATE_RENDER(WINED3D_RS_AMBIENT),                   state_ambient       }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_COLORVERTEX),               { STATE_RENDER(WINED3D_RS_COLORVERTEX),               state_colormat      }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_LOCALVIEWER),               { STATE_RENDER(WINED3D_RS_LOCALVIEWER),               state_localviewer   }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_NORMALIZENORMALS),          { STATE_RENDER(WINED3D_RS_NORMALIZENORMALS),          state_normalize     }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_DIFFUSEMATERIALSOURCE),     { STATE_RENDER(WINED3D_RS_COLORVERTEX),               NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_SPECULARMATERIALSOURCE),    { STATE_RENDER(WINED3D_RS_COLORVERTEX),               NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_AMBIENTMATERIALSOURCE),     { STATE_RENDER(WINED3D_RS_COLORVERTEX),               NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_EMISSIVEMATERIALSOURCE),    { STATE_RENDER(WINED3D_RS_COLORVERTEX),               NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_VERTEXBLEND),               { STATE_RENDER(WINED3D_RS_VERTEXBLEND),               state_vertexblend   }, ARB_VERTEX_BLEND                },
+    { STATE_RENDER(WINED3D_RS_VERTEXBLEND),               { STATE_RENDER(WINED3D_RS_VERTEXBLEND),               state_vertexblend_w }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_POINTSIZE),                 { STATE_RENDER(WINED3D_RS_POINTSCALEENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),             { STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),             state_psizemin_arb  }, ARB_POINT_PARAMETERS            },
+    { STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),             { STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),             state_psizemin_ext  }, EXT_POINT_PARAMETERS            },
+    { STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),             { STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),             state_psizemin_w    }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE),         { STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE),         state_pointsprite   }, ARB_POINT_SPRITE                },
+    { STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE),         { STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE),         state_pointsprite_w }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_POINTSCALEENABLE),          { STATE_RENDER(WINED3D_RS_POINTSCALEENABLE),          state_pscale        }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_POINTSCALE_A),              { STATE_RENDER(WINED3D_RS_POINTSCALEENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_POINTSCALE_B),              { STATE_RENDER(WINED3D_RS_POINTSCALEENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_POINTSCALE_C),              { STATE_RENDER(WINED3D_RS_POINTSCALEENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_POINTSIZE_MAX),             { STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),             NULL                }, ARB_POINT_PARAMETERS            },
+    { STATE_RENDER(WINED3D_RS_POINTSIZE_MAX),             { STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),             NULL                }, EXT_POINT_PARAMETERS            },
+    { STATE_RENDER(WINED3D_RS_POINTSIZE_MAX),             { STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),             NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_TWEENFACTOR),               { STATE_RENDER(WINED3D_RS_VERTEXBLEND),               NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_INDEXEDVERTEXBLENDENABLE),  { STATE_RENDER(WINED3D_RS_VERTEXBLEND),               NULL                }, WINED3D_GL_EXT_NONE             },
+
+    /* Samplers for NP2 texture matrix adjustions. They are not needed if GL_ARB_texture_non_power_of_two is supported,
+     * so register a NULL state handler in that case to get the vertex part of sampler() skipped(VTF is handled in the misc states.
+     * otherwise, register sampler_texmatrix, which takes care of updating the texture matrix
+     */
+    { STATE_SAMPLER(0),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
+    { STATE_SAMPLER(0),                                   { 0,                                                  NULL                }, WINED3D_GL_NORMALIZED_TEXRECT   },
+    { STATE_SAMPLER(0),                                   { STATE_SAMPLER(0),                                   sampler_texmatrix   }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(1),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
+    { STATE_SAMPLER(1),                                   { 0,                                                  NULL                }, WINED3D_GL_NORMALIZED_TEXRECT   },
+    { STATE_SAMPLER(1),                                   { STATE_SAMPLER(1),                                   sampler_texmatrix   }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(2),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
+    { STATE_SAMPLER(2),                                   { 0,                                                  NULL                }, WINED3D_GL_NORMALIZED_TEXRECT   },
+    { STATE_SAMPLER(2),                                   { STATE_SAMPLER(2),                                   sampler_texmatrix   }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(3),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
+    { STATE_SAMPLER(3),                                   { 0,                                                  NULL                }, WINED3D_GL_NORMALIZED_TEXRECT   },
+    { STATE_SAMPLER(3),                                   { STATE_SAMPLER(3),                                   sampler_texmatrix   }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(4),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
+    { STATE_SAMPLER(4),                                   { 0,                                                  NULL                }, WINED3D_GL_NORMALIZED_TEXRECT   },
+    { STATE_SAMPLER(4),                                   { STATE_SAMPLER(4),                                   sampler_texmatrix   }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(5),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
+    { STATE_SAMPLER(5),                                   { 0,                                                  NULL                }, WINED3D_GL_NORMALIZED_TEXRECT   },
+    { STATE_SAMPLER(5),                                   { STATE_SAMPLER(5),                                   sampler_texmatrix   }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(6),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
+    { STATE_SAMPLER(6),                                   { 0,                                                  NULL                }, WINED3D_GL_NORMALIZED_TEXRECT   },
+    { STATE_SAMPLER(6),                                   { STATE_SAMPLER(6),                                   sampler_texmatrix   }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(7),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
+    { STATE_SAMPLER(7),                                   { 0,                                                  NULL                }, WINED3D_GL_NORMALIZED_TEXRECT   },
+    { STATE_SAMPLER(7),                                   { STATE_SAMPLER(7),                                   sampler_texmatrix   }, WINED3D_GL_EXT_NONE             },
+    { STATE_POINT_SIZE_ENABLE,                            { STATE_POINT_SIZE_ENABLE,                            state_nop           }, WINED3D_GL_EXT_NONE             },
+    {0 /* Terminate */,                                   { 0,                                                  0                   }, WINED3D_GL_EXT_NONE             },
+};
+
+static const struct StateEntryTemplate ffp_fragmentstate_template[] = {
+    { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        tex_colorop         }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG1),      { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG2),      { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_OP),        { STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_OP),        tex_alphaop         }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG1),      { STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG2),      { STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG0),      { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG0),      { STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(0, WINED3D_TSS_RESULT_ARG),      { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(0, WINED3D_TSS_CONSTANT),        { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_OP),        { STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_OP),        tex_colorop         }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG1),      { STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG2),      { STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_OP),        { STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_OP),        tex_alphaop         }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG1),      { STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG2),      { STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG0),      { STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG0),      { STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(1, WINED3D_TSS_RESULT_ARG),      { STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(1, WINED3D_TSS_CONSTANT),        { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_OP),        { STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_OP),        tex_colorop         }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG1),      { STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG2),      { STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_OP),        { STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_OP),        tex_alphaop         }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG1),      { STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG2),      { STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG0),      { STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG0),      { STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(2, WINED3D_TSS_RESULT_ARG),      { STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(2, WINED3D_TSS_CONSTANT),        { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_OP),        { STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_OP),        tex_colorop         }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG1),      { STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG2),      { STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_OP),        { STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_OP),        tex_alphaop         }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG1),      { STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG2),      { STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG0),      { STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG0),      { STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(3, WINED3D_TSS_RESULT_ARG),      { STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(3, WINED3D_TSS_CONSTANT),        { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_OP),        { STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_OP),        tex_colorop         }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG1),      { STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG2),      { STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_OP),        { STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_OP),        tex_alphaop         }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG1),      { STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG2),      { STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG0),      { STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG0),      { STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(4, WINED3D_TSS_RESULT_ARG),      { STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(4, WINED3D_TSS_CONSTANT),        { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_OP),        { STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_OP),        tex_colorop         }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG1),      { STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG2),      { STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_OP),        { STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_OP),        tex_alphaop         }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG1),      { STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG2),      { STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG0),      { STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG0),      { STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(5, WINED3D_TSS_RESULT_ARG),      { STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(5, WINED3D_TSS_CONSTANT),        { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_OP),        { STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_OP),        tex_colorop         }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG1),      { STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG2),      { STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_OP),        { STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_OP),        tex_alphaop         }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG1),      { STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG2),      { STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG0),      { STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG0),      { STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(6, WINED3D_TSS_RESULT_ARG),      { STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(6, WINED3D_TSS_CONSTANT),        { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_OP),        { STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_OP),        tex_colorop         }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG1),      { STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG2),      { STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_OP),        { STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_OP),        tex_alphaop         }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG1),      { STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG2),      { STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG0),      { STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG0),      { STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(7, WINED3D_TSS_RESULT_ARG),      { STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(7, WINED3D_TSS_CONSTANT),        { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_PIXELSHADER,                                  { STATE_PIXELSHADER,                                  apply_pixelshader   }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE),           { STATE_PIXELSHADER,                                  NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_TEXTUREFACTOR),             { STATE_RENDER(WINED3D_RS_TEXTUREFACTOR),             state_texfactor     }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_FOGCOLOR),                  { STATE_RENDER(WINED3D_RS_FOGCOLOR),                  state_fogcolor      }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_FOGDENSITY),                { STATE_RENDER(WINED3D_RS_FOGDENSITY),                state_fogdensity    }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_FOGENABLE),                 { STATE_RENDER(WINED3D_RS_FOGENABLE),                 state_fog_fragpart  }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_FOGTABLEMODE),              { STATE_RENDER(WINED3D_RS_FOGENABLE),                 NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_FOGVERTEXMODE),             { STATE_RENDER(WINED3D_RS_FOGENABLE),                 NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_FOGSTART),                  { STATE_RENDER(WINED3D_RS_FOGSTART),                  state_fogstartend   }, WINED3D_GL_EXT_NONE             },
+    { STATE_RENDER(WINED3D_RS_FOGEND),                    { STATE_RENDER(WINED3D_RS_FOGSTART),                  NULL                }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(0),                                   { STATE_SAMPLER(0),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(1),                                   { STATE_SAMPLER(1),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(2),                                   { STATE_SAMPLER(2),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(3),                                   { STATE_SAMPLER(3),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(4),                                   { STATE_SAMPLER(4),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(5),                                   { STATE_SAMPLER(5),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(6),                                   { STATE_SAMPLER(6),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
+    { STATE_SAMPLER(7),                                   { STATE_SAMPLER(7),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
+    {0 /* Terminate */,                                   { 0,                                                  0                   }, WINED3D_GL_EXT_NONE             },
+};
+
+/* Context activation is done by the caller. */
+static void ffp_enable(const struct wined3d_gl_info *gl_info, BOOL enable) {}
+
+static void *ffp_alloc(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv)
+{
+    return shader_priv;
+}
+
+static void ffp_free(struct wined3d_device *device) {}
+
+static void vp_ffp_get_caps(const struct wined3d_gl_info *gl_info, struct wined3d_vertex_caps *caps)
+{
+    caps->max_active_lights = gl_info->limits.lights;
+    caps->max_vertex_blend_matrices = gl_info->limits.blends;
+    caps->max_vertex_blend_matrix_index = 0;
+    caps->vertex_processing_caps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS
+            | WINED3DVTXPCAPS_MATERIALSOURCE7
+            | WINED3DVTXPCAPS_POSITIONALLIGHTS
+            | WINED3DVTXPCAPS_LOCALVIEWER
+            | WINED3DVTXPCAPS_VERTEXFOG
+            | WINED3DVTXPCAPS_TEXGEN
+            | WINED3DVTXPCAPS_TEXGEN_SPHEREMAP;
+    caps->fvf_caps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
+    caps->max_user_clip_planes = gl_info->limits.clipplanes;
+    caps->raster_caps = 0;
+    if (gl_info->supported[NV_FOG_DISTANCE])
+        caps->raster_caps |= WINED3DPRASTERCAPS_FOGRANGE;
+}
+
+const struct wined3d_vertex_pipe_ops ffp_vertex_pipe =
+{
+    ffp_enable,
+    vp_ffp_get_caps,
+    ffp_alloc,
+    ffp_free,
+    vp_ffp_states,
+};
+
+static void ffp_fragment_get_caps(const struct wined3d_gl_info *gl_info, struct fragment_caps *caps)
+{
+    caps->wined3d_caps = 0;
+    caps->PrimitiveMiscCaps = 0;
+    caps->TextureOpCaps = WINED3DTEXOPCAPS_ADD
+            | WINED3DTEXOPCAPS_ADDSIGNED
+            | WINED3DTEXOPCAPS_ADDSIGNED2X
+            | WINED3DTEXOPCAPS_MODULATE
+            | WINED3DTEXOPCAPS_MODULATE2X
+            | WINED3DTEXOPCAPS_MODULATE4X
+            | WINED3DTEXOPCAPS_SELECTARG1
+            | WINED3DTEXOPCAPS_SELECTARG2
+            | WINED3DTEXOPCAPS_DISABLE;
+
+    if (gl_info->supported[ARB_TEXTURE_ENV_COMBINE]
+            || gl_info->supported[EXT_TEXTURE_ENV_COMBINE]
+            || gl_info->supported[NV_TEXTURE_ENV_COMBINE4])
+    {
+        caps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA
+                | WINED3DTEXOPCAPS_BLENDTEXTUREALPHA
+                | WINED3DTEXOPCAPS_BLENDFACTORALPHA
+                | WINED3DTEXOPCAPS_BLENDCURRENTALPHA
+                | WINED3DTEXOPCAPS_LERP
+                | WINED3DTEXOPCAPS_SUBTRACT;
+    }
+    if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3]
+            || gl_info->supported[NV_TEXTURE_ENV_COMBINE4])
+    {
+        caps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH
+                | WINED3DTEXOPCAPS_MULTIPLYADD
+                | WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR
+                | WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA
+                | WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
+    }
+    if (gl_info->supported[ARB_TEXTURE_ENV_DOT3])
+        caps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
+
+    caps->MaxTextureBlendStages = gl_info->limits.textures;
+    caps->MaxSimultaneousTextures = gl_info->limits.textures;
+}
+
+static BOOL ffp_color_fixup_supported(struct color_fixup_desc fixup)
+{
+    if (TRACE_ON(d3d))
+    {
+        TRACE("Checking support for fixup:\n");
+        dump_color_fixup_desc(fixup);
+    }
+
+    /* We only support identity conversions. */
+    if (is_identity_fixup(fixup))
+    {
+        TRACE("[OK]\n");
+        return TRUE;
+    }
+
+    TRACE("[FAILED]\n");
+    return FALSE;
+}
+
+const struct fragment_pipeline ffp_fragment_pipeline = {
+    ffp_enable,
+    ffp_fragment_get_caps,
+    ffp_alloc,
+    ffp_free,
+    ffp_color_fixup_supported,
+    ffp_fragmentstate_template,
+};
+
+static void none_enable(const struct wined3d_gl_info *gl_info, BOOL enable) {}
+
+static void *none_alloc(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv)
+{
+    return shader_priv;
+}
+
+static void none_free(struct wined3d_device *device) {}
+
+static void vp_none_get_caps(const struct wined3d_gl_info *gl_info, struct wined3d_vertex_caps *caps)
+{
+    memset(caps, 0, sizeof(*caps));
+}
+
+const struct wined3d_vertex_pipe_ops none_vertex_pipe =
+{
+    none_enable,
+    vp_none_get_caps,
+    none_alloc,
+    none_free,
+    NULL,
+};
+
+static void fp_none_get_caps(const struct wined3d_gl_info *gl_info, struct fragment_caps *caps)
+{
+    memset(caps, 0, sizeof(*caps));
+}
+
+static BOOL fp_none_color_fixup_supported(struct color_fixup_desc fixup)
+{
+    return is_identity_fixup(fixup);
+}
+
+const struct fragment_pipeline none_fragment_pipe =
+{
+    none_enable,
+    fp_none_get_caps,
+    none_alloc,
+    none_free,
+    fp_none_color_fixup_supported,
+    NULL,
+};
+
+static unsigned int num_handlers(const APPLYSTATEFUNC *funcs)
+{
+    unsigned int i;
+    for(i = 0; funcs[i]; i++);
+    return i;
+}
+
+static void multistate_apply_2(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    context->swapchain->device->multistate_funcs[state_id][0](context, state, state_id);
+    context->swapchain->device->multistate_funcs[state_id][1](context, state, state_id);
+}
+
+static void multistate_apply_3(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    context->swapchain->device->multistate_funcs[state_id][0](context, state, state_id);
+    context->swapchain->device->multistate_funcs[state_id][1](context, state, state_id);
+    context->swapchain->device->multistate_funcs[state_id][2](context, state, state_id);
+}
+
+static void prune_invalid_states(struct StateEntry *state_table, const struct wined3d_gl_info *gl_info,
+        const struct wined3d_d3d_info *d3d_info)
+{
+    unsigned int start, last, i;
+
+    start = STATE_TEXTURESTAGE(d3d_info->limits.ffp_blend_stages, 0);
+    last = STATE_TEXTURESTAGE(MAX_TEXTURES - 1, WINED3D_HIGHEST_TEXTURE_STATE);
+    for (i = start; i <= last; ++i)
+    {
+        state_table[i].representative = 0;
+        state_table[i].apply = state_undefined;
+    }
+
+    start = STATE_TRANSFORM(WINED3D_TS_TEXTURE0 + d3d_info->limits.ffp_blend_stages);
+    last = STATE_TRANSFORM(WINED3D_TS_TEXTURE0 + MAX_TEXTURES - 1);
+    for (i = start; i <= last; ++i)
+    {
+        state_table[i].representative = 0;
+        state_table[i].apply = state_undefined;
+    }
+
+    start = STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(gl_info->limits.blends));
+    last = STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(255));
+    for (i = start; i <= last; ++i)
+    {
+        state_table[i].representative = 0;
+        state_table[i].apply = state_undefined;
+    }
+}
+
+static void validate_state_table(struct StateEntry *state_table)
+{
+    static const struct
+    {
+        DWORD first;
+        DWORD last;
+    }
+    rs_holes[] =
+    {
+        {  1,   1},
+        {  3,   3},
+        { 17,  18},
+        { 21,  21},
+        { 42,  45},
+        { 47,  47},
+        { 61, 127},
+        {149, 150},
+        {169, 169},
+        {177, 177},
+        {196, 197},
+        {  0,   0},
+    };
+    static const DWORD simple_states[] =
+    {
+        STATE_MATERIAL,
+        STATE_VDECL,
+        STATE_STREAMSRC,
+        STATE_INDEXBUFFER,
+        STATE_VERTEXSHADERCONSTANT,
+        STATE_PIXELSHADERCONSTANT,
+        STATE_VSHADER,
+        STATE_GEOMETRY_SHADER,
+        STATE_PIXELSHADER,
+        STATE_VIEWPORT,
+        STATE_LIGHT_TYPE,
+        STATE_SCISSORRECT,
+        STATE_FRONTFACE,
+        STATE_POINTSPRITECOORDORIGIN,
+        STATE_BASEVERTEXINDEX,
+        STATE_FRAMEBUFFER,
+        STATE_POINT_SIZE_ENABLE,
+    };
+    unsigned int i, current;
+
+    for (i = STATE_RENDER(1), current = 0; i <= STATE_RENDER(WINEHIGHEST_RENDER_STATE); ++i)
+    {
+        if (!rs_holes[current].first || i < STATE_RENDER(rs_holes[current].first))
+        {
+            if (!state_table[i].representative)
+                ERR("State %s (%#x) should have a representative.\n", debug_d3dstate(i), i);
+        }
+        else if (state_table[i].representative)
+            ERR("State %s (%#x) shouldn't have a representative.\n", debug_d3dstate(i), i);
+
+        if (i == STATE_RENDER(rs_holes[current].last)) ++current;
+    }
+
+    for (i = 0; i < sizeof(simple_states) / sizeof(*simple_states); ++i)
+    {
+        if (!state_table[simple_states[i]].representative)
+            ERR("State %s (%#x) should have a representative.\n",
+                    debug_d3dstate(simple_states[i]), simple_states[i]);
+    }
+
+    for (i = 0; i < STATE_HIGHEST + 1; ++i)
+    {
+        DWORD rep = state_table[i].representative;
+        if (rep)
+        {
+            if (state_table[rep].representative != rep)
+            {
+                ERR("State %s (%#x) has invalid representative %s (%#x).\n",
+                        debug_d3dstate(i), i, debug_d3dstate(rep), rep);
+                state_table[i].representative = 0;
+            }
+
+            if (rep != i)
+            {
+                if (state_table[i].apply)
+                    ERR("State %s (%#x) has both a handler and representative.\n", debug_d3dstate(i), i);
+            }
+            else if (!state_table[i].apply)
+            {
+                ERR("Self representing state %s (%#x) has no handler.\n", debug_d3dstate(i), i);
+            }
+        }
+    }
+}
+
+HRESULT compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_multistate_funcs,
+        const struct wined3d_gl_info *gl_info, const struct wined3d_d3d_info *d3d_info,
+        const struct wined3d_vertex_pipe_ops *vertex, const struct fragment_pipeline *fragment,
+        const struct StateEntryTemplate *misc)
+{
+    unsigned int i, type, handlers;
+    APPLYSTATEFUNC multistate_funcs[STATE_HIGHEST + 1][3];
+    const struct StateEntryTemplate *cur;
+    BOOL set[STATE_HIGHEST + 1];
+
+    memset(multistate_funcs, 0, sizeof(multistate_funcs));
+
+    for(i = 0; i < STATE_HIGHEST + 1; i++) {
+        StateTable[i].representative = 0;
+        StateTable[i].apply = state_undefined;
+    }
+
+    for(type = 0; type < 3; type++) {
+        /* This switch decides the order in which the states are applied */
+        switch(type) {
+            case 0: cur = misc; break;
+            case 1: cur = fragment->states; break;
+            case 2: cur = vertex->vp_states; break;
+            default: cur = NULL; /* Stupid compiler */
+        }
+        if(!cur) continue;
+
+        /* GL extension filtering should not prevent multiple handlers being applied from different
+         * pipeline parts
+         */
+        memset(set, 0, sizeof(set));
+
+        for(i = 0; cur[i].state; i++) {
+            APPLYSTATEFUNC *funcs_array;
+
+            /* Only use the first matching state with the available extension from one template.
+             * e.g.
+             * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func1}, XYZ_FANCY},
+             * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func2}, 0        }
+             *
+             * if GL_XYZ_fancy is supported, ignore the 2nd line
+             */
+            if(set[cur[i].state]) continue;
+            /* Skip state lines depending on unsupported extensions */
+            if (!gl_info->supported[cur[i].extension]) continue;
+            set[cur[i].state] = TRUE;
+            /* In some cases having an extension means that nothing has to be
+             * done for a state, e.g. if GL_ARB_texture_non_power_of_two is
+             * supported, the texture coordinate fixup can be ignored. If the
+             * apply function is used, mark the state set(done above) to prevent
+             * applying later lines, but do not record anything in the state
+             * table
+             */
+            if (!cur[i].content.representative) continue;
+
+            handlers = num_handlers(multistate_funcs[cur[i].state]);
+            multistate_funcs[cur[i].state][handlers] = cur[i].content.apply;
+            switch(handlers) {
+                case 0:
+                    StateTable[cur[i].state].apply = cur[i].content.apply;
+                    break;
+                case 1:
+                    StateTable[cur[i].state].apply = multistate_apply_2;
+                    dev_multistate_funcs[cur[i].state] = HeapAlloc(GetProcessHeap(),
+                                                                   0,
+                                                                   sizeof(**dev_multistate_funcs) * 2);
+                    if (!dev_multistate_funcs[cur[i].state]) {
+                        goto out_of_mem;
+                    }
+
+                    dev_multistate_funcs[cur[i].state][0] = multistate_funcs[cur[i].state][0];
+                    dev_multistate_funcs[cur[i].state][1] = multistate_funcs[cur[i].state][1];
+                    break;
+                case 2:
+                    StateTable[cur[i].state].apply = multistate_apply_3;
+                    funcs_array = HeapReAlloc(GetProcessHeap(),
+                                              0,
+                                              dev_multistate_funcs[cur[i].state],
+                                              sizeof(**dev_multistate_funcs) * 3);
+                    if (!funcs_array) {
+                        goto out_of_mem;
+                    }
+
+                    dev_multistate_funcs[cur[i].state] = funcs_array;
+                    dev_multistate_funcs[cur[i].state][2] = multistate_funcs[cur[i].state][2];
+                    break;
+                default:
+                    ERR("Unexpected amount of state handlers for state %u: %u\n",
+                        cur[i].state, handlers + 1);
+            }
+
+            if (StateTable[cur[i].state].representative
+                    && StateTable[cur[i].state].representative != cur[i].content.representative)
+            {
+                FIXME("State %s (%#x) has different representatives in different pipeline parts.\n",
+                        debug_d3dstate(cur[i].state), cur[i].state);
+            }
+            StateTable[cur[i].state].representative = cur[i].content.representative;
+        }
+    }
+
+    prune_invalid_states(StateTable, gl_info, d3d_info);
+    validate_state_table(StateTable);
+
+    return WINED3D_OK;
+
+out_of_mem:
+    for (i = 0; i <= STATE_HIGHEST; ++i) {
+        HeapFree(GetProcessHeap(), 0, dev_multistate_funcs[i]);
+    }
+
+    memset(dev_multistate_funcs, 0, (STATE_HIGHEST + 1)*sizeof(*dev_multistate_funcs));
+
+    return E_OUTOFMEMORY;
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/stateblock.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/stateblock.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/stateblock.c	(revision 46521)
@@ -0,0 +1,1485 @@
+/*
+ * state block implementation
+ *
+ * Copyright 2002 Raphael Junqueira
+ * Copyright 2004 Jason Edmeades
+ * Copyright 2005 Oliver Stieber
+ * Copyright 2007 Stefan Dösinger for CodeWeavers
+ * Copyright 2009 Henri Verbeet for CodeWeavers
+ *
+ * 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 "wined3d_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d);
+
+static const DWORD pixel_states_render[] =
+{
+    WINED3D_RS_ALPHABLENDENABLE,
+    WINED3D_RS_ALPHAFUNC,
+    WINED3D_RS_ALPHAREF,
+    WINED3D_RS_ALPHATESTENABLE,
+    WINED3D_RS_ANTIALIASEDLINEENABLE,
+    WINED3D_RS_BLENDFACTOR,
+    WINED3D_RS_BLENDOP,
+    WINED3D_RS_BLENDOPALPHA,
+    WINED3D_RS_CCW_STENCILFAIL,
+    WINED3D_RS_CCW_STENCILPASS,
+    WINED3D_RS_CCW_STENCILZFAIL,
+    WINED3D_RS_COLORWRITEENABLE,
+    WINED3D_RS_COLORWRITEENABLE1,
+    WINED3D_RS_COLORWRITEENABLE2,
+    WINED3D_RS_COLORWRITEENABLE3,
+    WINED3D_RS_DEPTHBIAS,
+    WINED3D_RS_DESTBLEND,
+    WINED3D_RS_DESTBLENDALPHA,
+    WINED3D_RS_DITHERENABLE,
+    WINED3D_RS_FILLMODE,
+    WINED3D_RS_FOGDENSITY,
+    WINED3D_RS_FOGEND,
+    WINED3D_RS_FOGSTART,
+    WINED3D_RS_LASTPIXEL,
+    WINED3D_RS_SCISSORTESTENABLE,
+    WINED3D_RS_SEPARATEALPHABLENDENABLE,
+    WINED3D_RS_SHADEMODE,
+    WINED3D_RS_SLOPESCALEDEPTHBIAS,
+    WINED3D_RS_SRCBLEND,
+    WINED3D_RS_SRCBLENDALPHA,
+    WINED3D_RS_SRGBWRITEENABLE,
+    WINED3D_RS_STENCILENABLE,
+    WINED3D_RS_STENCILFAIL,
+    WINED3D_RS_STENCILFUNC,
+    WINED3D_RS_STENCILMASK,
+    WINED3D_RS_STENCILPASS,
+    WINED3D_RS_STENCILREF,
+    WINED3D_RS_STENCILWRITEMASK,
+    WINED3D_RS_STENCILZFAIL,
+    WINED3D_RS_TEXTUREFACTOR,
+    WINED3D_RS_TWOSIDEDSTENCILMODE,
+    WINED3D_RS_WRAP0,
+    WINED3D_RS_WRAP1,
+    WINED3D_RS_WRAP10,
+    WINED3D_RS_WRAP11,
+    WINED3D_RS_WRAP12,
+    WINED3D_RS_WRAP13,
+    WINED3D_RS_WRAP14,
+    WINED3D_RS_WRAP15,
+    WINED3D_RS_WRAP2,
+    WINED3D_RS_WRAP3,
+    WINED3D_RS_WRAP4,
+    WINED3D_RS_WRAP5,
+    WINED3D_RS_WRAP6,
+    WINED3D_RS_WRAP7,
+    WINED3D_RS_WRAP8,
+    WINED3D_RS_WRAP9,
+    WINED3D_RS_ZENABLE,
+    WINED3D_RS_ZFUNC,
+    WINED3D_RS_ZWRITEENABLE,
+};
+
+static const DWORD pixel_states_texture[] =
+{
+    WINED3D_TSS_ALPHA_ARG0,
+    WINED3D_TSS_ALPHA_ARG1,
+    WINED3D_TSS_ALPHA_ARG2,
+    WINED3D_TSS_ALPHA_OP,
+    WINED3D_TSS_BUMPENV_LOFFSET,
+    WINED3D_TSS_BUMPENV_LSCALE,
+    WINED3D_TSS_BUMPENV_MAT00,
+    WINED3D_TSS_BUMPENV_MAT01,
+    WINED3D_TSS_BUMPENV_MAT10,
+    WINED3D_TSS_BUMPENV_MAT11,
+    WINED3D_TSS_COLOR_ARG0,
+    WINED3D_TSS_COLOR_ARG1,
+    WINED3D_TSS_COLOR_ARG2,
+    WINED3D_TSS_COLOR_OP,
+    WINED3D_TSS_RESULT_ARG,
+    WINED3D_TSS_TEXCOORD_INDEX,
+    WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS,
+};
+
+static const DWORD pixel_states_sampler[] =
+{
+    WINED3D_SAMP_ADDRESS_U,
+    WINED3D_SAMP_ADDRESS_V,
+    WINED3D_SAMP_ADDRESS_W,
+    WINED3D_SAMP_BORDER_COLOR,
+    WINED3D_SAMP_MAG_FILTER,
+    WINED3D_SAMP_MIN_FILTER,
+    WINED3D_SAMP_MIP_FILTER,
+    WINED3D_SAMP_MIPMAP_LOD_BIAS,
+    WINED3D_SAMP_MAX_MIP_LEVEL,
+    WINED3D_SAMP_MAX_ANISOTROPY,
+    WINED3D_SAMP_SRGB_TEXTURE,
+    WINED3D_SAMP_ELEMENT_INDEX,
+};
+
+static const DWORD vertex_states_render[] =
+{
+    WINED3D_RS_ADAPTIVETESS_W,
+    WINED3D_RS_ADAPTIVETESS_X,
+    WINED3D_RS_ADAPTIVETESS_Y,
+    WINED3D_RS_ADAPTIVETESS_Z,
+    WINED3D_RS_AMBIENT,
+    WINED3D_RS_AMBIENTMATERIALSOURCE,
+    WINED3D_RS_CLIPPING,
+    WINED3D_RS_CLIPPLANEENABLE,
+    WINED3D_RS_COLORVERTEX,
+    WINED3D_RS_CULLMODE,
+    WINED3D_RS_DIFFUSEMATERIALSOURCE,
+    WINED3D_RS_EMISSIVEMATERIALSOURCE,
+    WINED3D_RS_ENABLEADAPTIVETESSELLATION,
+    WINED3D_RS_FOGCOLOR,
+    WINED3D_RS_FOGDENSITY,
+    WINED3D_RS_FOGENABLE,
+    WINED3D_RS_FOGEND,
+    WINED3D_RS_FOGSTART,
+    WINED3D_RS_FOGTABLEMODE,
+    WINED3D_RS_FOGVERTEXMODE,
+    WINED3D_RS_INDEXEDVERTEXBLENDENABLE,
+    WINED3D_RS_LIGHTING,
+    WINED3D_RS_LOCALVIEWER,
+    WINED3D_RS_MAXTESSELLATIONLEVEL,
+    WINED3D_RS_MINTESSELLATIONLEVEL,
+    WINED3D_RS_MULTISAMPLEANTIALIAS,
+    WINED3D_RS_MULTISAMPLEMASK,
+    WINED3D_RS_NORMALDEGREE,
+    WINED3D_RS_NORMALIZENORMALS,
+    WINED3D_RS_PATCHEDGESTYLE,
+    WINED3D_RS_POINTSCALE_A,
+    WINED3D_RS_POINTSCALE_B,
+    WINED3D_RS_POINTSCALE_C,
+    WINED3D_RS_POINTSCALEENABLE,
+    WINED3D_RS_POINTSIZE,
+    WINED3D_RS_POINTSIZE_MAX,
+    WINED3D_RS_POINTSIZE_MIN,
+    WINED3D_RS_POINTSPRITEENABLE,
+    WINED3D_RS_POSITIONDEGREE,
+    WINED3D_RS_RANGEFOGENABLE,
+    WINED3D_RS_SHADEMODE,
+    WINED3D_RS_SPECULARENABLE,
+    WINED3D_RS_SPECULARMATERIALSOURCE,
+    WINED3D_RS_TWEENFACTOR,
+    WINED3D_RS_VERTEXBLEND,
+};
+
+static const DWORD vertex_states_texture[] =
+{
+    WINED3D_TSS_TEXCOORD_INDEX,
+    WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS,
+};
+
+static const DWORD vertex_states_sampler[] =
+{
+    WINED3D_SAMP_DMAP_OFFSET,
+};
+
+/* Allocates the correct amount of space for pixel and vertex shader constants,
+ * along with their set/changed flags on the given stateblock object
+ */
+static HRESULT stateblock_allocate_shader_constants(struct wined3d_stateblock *object)
+{
+    const struct wined3d_d3d_info *d3d_info = &object->device->adapter->d3d_info;
+
+    /* Allocate space for floating point constants */
+    object->state.ps_consts_f = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+            sizeof(float) * d3d_info->limits.ps_uniform_count * 4);
+    if (!object->state.ps_consts_f) goto fail;
+
+    object->changed.pixelShaderConstantsF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+            sizeof(BOOL) * d3d_info->limits.ps_uniform_count);
+    if (!object->changed.pixelShaderConstantsF) goto fail;
+
+    object->state.vs_consts_f = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+            sizeof(float) * d3d_info->limits.vs_uniform_count * 4);
+    if (!object->state.vs_consts_f) goto fail;
+
+    object->changed.vertexShaderConstantsF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+            sizeof(BOOL) * d3d_info->limits.vs_uniform_count);
+    if (!object->changed.vertexShaderConstantsF) goto fail;
+
+    object->contained_vs_consts_f = HeapAlloc(GetProcessHeap(), 0,
+            sizeof(DWORD) * d3d_info->limits.vs_uniform_count);
+    if (!object->contained_vs_consts_f) goto fail;
+
+    object->contained_ps_consts_f = HeapAlloc(GetProcessHeap(), 0,
+            sizeof(DWORD) * d3d_info->limits.ps_uniform_count);
+    if (!object->contained_ps_consts_f) goto fail;
+
+    return WINED3D_OK;
+
+fail:
+    ERR("Failed to allocate memory\n");
+    HeapFree(GetProcessHeap(), 0, object->state.ps_consts_f);
+    HeapFree(GetProcessHeap(), 0, object->changed.pixelShaderConstantsF);
+    HeapFree(GetProcessHeap(), 0, object->state.vs_consts_f);
+    HeapFree(GetProcessHeap(), 0, object->changed.vertexShaderConstantsF);
+    HeapFree(GetProcessHeap(), 0, object->contained_vs_consts_f);
+    HeapFree(GetProcessHeap(), 0, object->contained_ps_consts_f);
+    return E_OUTOFMEMORY;
+}
+
+static inline void stateblock_set_bits(DWORD *map, UINT map_size)
+{
+    DWORD mask = (1 << (map_size & 0x1f)) - 1;
+    memset(map, 0xff, (map_size >> 5) * sizeof(*map));
+    if (mask) map[map_size >> 5] = mask;
+}
+
+/* Set all members of a stateblock savedstate to the given value */
+static void stateblock_savedstates_set_all(struct wined3d_saved_states *states, DWORD vs_consts, DWORD ps_consts)
+{
+    unsigned int i;
+
+    /* Single values */
+    states->primitive_type = 1;
+    states->indices = 1;
+    states->material = 1;
+    states->viewport = 1;
+    states->vertexDecl = 1;
+    states->pixelShader = 1;
+    states->vertexShader = 1;
+    states->scissorRect = 1;
+
+    /* Fixed size arrays */
+    states->streamSource = 0xffff;
+    states->streamFreq = 0xffff;
+    states->textures = 0xfffff;
+    stateblock_set_bits(states->transform, HIGHEST_TRANSFORMSTATE + 1);
+    stateblock_set_bits(states->renderState, WINEHIGHEST_RENDER_STATE + 1);
+    for (i = 0; i < MAX_TEXTURES; ++i) states->textureState[i] = 0x3ffff;
+    for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i) states->samplerState[i] = 0x3ffe;
+    states->clipplane = 0xffffffff;
+    states->pixelShaderConstantsB = 0xffff;
+    states->pixelShaderConstantsI = 0xffff;
+    states->vertexShaderConstantsB = 0xffff;
+    states->vertexShaderConstantsI = 0xffff;
+
+    /* Dynamically sized arrays */
+    memset(states->pixelShaderConstantsF, TRUE, sizeof(BOOL) * ps_consts);
+    memset(states->vertexShaderConstantsF, TRUE, sizeof(BOOL) * vs_consts);
+}
+
+static void stateblock_savedstates_set_pixel(struct wined3d_saved_states *states, const DWORD num_constants)
+{
+    DWORD texture_mask = 0;
+    WORD sampler_mask = 0;
+    unsigned int i;
+
+    states->pixelShader = 1;
+
+    for (i = 0; i < sizeof(pixel_states_render) / sizeof(*pixel_states_render); ++i)
+    {
+        DWORD rs = pixel_states_render[i];
+        states->renderState[rs >> 5] |= 1 << (rs & 0x1f);
+    }
+
+    for (i = 0; i < sizeof(pixel_states_texture) / sizeof(*pixel_states_texture); ++i)
+        texture_mask |= 1 << pixel_states_texture[i];
+    for (i = 0; i < MAX_TEXTURES; ++i) states->textureState[i] = texture_mask;
+    for (i = 0; i < sizeof(pixel_states_sampler) / sizeof(*pixel_states_sampler); ++i)
+        sampler_mask |= 1 << pixel_states_sampler[i];
+    for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i) states->samplerState[i] = sampler_mask;
+    states->pixelShaderConstantsB = 0xffff;
+    states->pixelShaderConstantsI = 0xffff;
+
+    memset(states->pixelShaderConstantsF, TRUE, sizeof(BOOL) * num_constants);
+}
+
+static void stateblock_savedstates_set_vertex(struct wined3d_saved_states *states, const DWORD num_constants)
+{
+    DWORD texture_mask = 0;
+    WORD sampler_mask = 0;
+    unsigned int i;
+
+    states->vertexDecl = 1;
+    states->vertexShader = 1;
+
+    for (i = 0; i < sizeof(vertex_states_render) / sizeof(*vertex_states_render); ++i)
+    {
+        DWORD rs = vertex_states_render[i];
+        states->renderState[rs >> 5] |= 1 << (rs & 0x1f);
+    }
+
+    for (i = 0; i < sizeof(vertex_states_texture) / sizeof(*vertex_states_texture); ++i)
+        texture_mask |= 1 << vertex_states_texture[i];
+    for (i = 0; i < MAX_TEXTURES; ++i) states->textureState[i] = texture_mask;
+    for (i = 0; i < sizeof(vertex_states_sampler) / sizeof(*vertex_states_sampler); ++i)
+        sampler_mask |= 1 << vertex_states_sampler[i];
+    for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i) states->samplerState[i] = sampler_mask;
+    states->vertexShaderConstantsB = 0xffff;
+    states->vertexShaderConstantsI = 0xffff;
+
+    memset(states->vertexShaderConstantsF, TRUE, sizeof(BOOL) * num_constants);
+}
+
+void stateblock_init_contained_states(struct wined3d_stateblock *stateblock)
+{
+    const struct wined3d_d3d_info *d3d_info = &stateblock->device->adapter->d3d_info;
+    unsigned int i, j;
+
+    for (i = 0; i <= WINEHIGHEST_RENDER_STATE >> 5; ++i)
+    {
+        DWORD map = stateblock->changed.renderState[i];
+        for (j = 0; map; map >>= 1, ++j)
+        {
+            if (!(map & 1)) continue;
+
+            stateblock->contained_render_states[stateblock->num_contained_render_states] = (i << 5) | j;
+            ++stateblock->num_contained_render_states;
+        }
+    }
+
+    for (i = 0; i <= HIGHEST_TRANSFORMSTATE >> 5; ++i)
+    {
+        DWORD map = stateblock->changed.transform[i];
+        for (j = 0; map; map >>= 1, ++j)
+        {
+            if (!(map & 1)) continue;
+
+            stateblock->contained_transform_states[stateblock->num_contained_transform_states] = (i << 5) | j;
+            ++stateblock->num_contained_transform_states;
+        }
+    }
+
+    for (i = 0; i < d3d_info->limits.vs_uniform_count; ++i)
+    {
+        if (stateblock->changed.vertexShaderConstantsF[i])
+        {
+            stateblock->contained_vs_consts_f[stateblock->num_contained_vs_consts_f] = i;
+            ++stateblock->num_contained_vs_consts_f;
+        }
+    }
+
+    for (i = 0; i < MAX_CONST_I; ++i)
+    {
+        if (stateblock->changed.vertexShaderConstantsI & (1 << i))
+        {
+            stateblock->contained_vs_consts_i[stateblock->num_contained_vs_consts_i] = i;
+            ++stateblock->num_contained_vs_consts_i;
+        }
+    }
+
+    for (i = 0; i < MAX_CONST_B; ++i)
+    {
+        if (stateblock->changed.vertexShaderConstantsB & (1 << i))
+        {
+            stateblock->contained_vs_consts_b[stateblock->num_contained_vs_consts_b] = i;
+            ++stateblock->num_contained_vs_consts_b;
+        }
+    }
+
+    for (i = 0; i < d3d_info->limits.ps_uniform_count; ++i)
+    {
+        if (stateblock->changed.pixelShaderConstantsF[i])
+        {
+            stateblock->contained_ps_consts_f[stateblock->num_contained_ps_consts_f] = i;
+            ++stateblock->num_contained_ps_consts_f;
+        }
+    }
+
+    for (i = 0; i < MAX_CONST_I; ++i)
+    {
+        if (stateblock->changed.pixelShaderConstantsI & (1 << i))
+        {
+            stateblock->contained_ps_consts_i[stateblock->num_contained_ps_consts_i] = i;
+            ++stateblock->num_contained_ps_consts_i;
+        }
+    }
+
+    for (i = 0; i < MAX_CONST_B; ++i)
+    {
+        if (stateblock->changed.pixelShaderConstantsB & (1 << i))
+        {
+            stateblock->contained_ps_consts_b[stateblock->num_contained_ps_consts_b] = i;
+            ++stateblock->num_contained_ps_consts_b;
+        }
+    }
+
+    for (i = 0; i < MAX_TEXTURES; ++i)
+    {
+        DWORD map = stateblock->changed.textureState[i];
+
+        for(j = 0; map; map >>= 1, ++j)
+        {
+            if (!(map & 1)) continue;
+
+            stateblock->contained_tss_states[stateblock->num_contained_tss_states].stage = i;
+            stateblock->contained_tss_states[stateblock->num_contained_tss_states].state = j;
+            ++stateblock->num_contained_tss_states;
+        }
+    }
+
+    for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
+    {
+        DWORD map = stateblock->changed.samplerState[i];
+
+        for (j = 0; map; map >>= 1, ++j)
+        {
+            if (!(map & 1)) continue;
+
+            stateblock->contained_sampler_states[stateblock->num_contained_sampler_states].stage = i;
+            stateblock->contained_sampler_states[stateblock->num_contained_sampler_states].state = j;
+            ++stateblock->num_contained_sampler_states;
+        }
+    }
+}
+
+static void stateblock_init_lights(struct wined3d_stateblock *stateblock, struct list *light_map)
+{
+    unsigned int i;
+
+    for (i = 0; i < LIGHTMAP_SIZE; ++i)
+    {
+        const struct wined3d_light_info *src_light;
+
+        LIST_FOR_EACH_ENTRY(src_light, &light_map[i], struct wined3d_light_info, entry)
+        {
+            struct wined3d_light_info *dst_light = HeapAlloc(GetProcessHeap(), 0, sizeof(*dst_light));
+
+            *dst_light = *src_light;
+            list_add_tail(&stateblock->state.light_map[i], &dst_light->entry);
+        }
+    }
+}
+
+ULONG CDECL wined3d_stateblock_incref(struct wined3d_stateblock *stateblock)
+{
+    ULONG refcount = InterlockedIncrement(&stateblock->ref);
+
+    TRACE("%p increasing refcount to %u.\n", stateblock, refcount);
+
+    return refcount;
+}
+
+void stateblock_unbind_resources(struct wined3d_stateblock *stateblock)
+{
+    struct wined3d_state *state = &stateblock->state;
+    struct wined3d_vertex_declaration *decl;
+    struct wined3d_sampler *sampler;
+    struct wined3d_texture *texture;
+    struct wined3d_buffer *buffer;
+    struct wined3d_shader *shader;
+    unsigned int i;
+
+    if ((decl = state->vertex_declaration))
+    {
+        state->vertex_declaration = NULL;
+        wined3d_vertex_declaration_decref(decl);
+    }
+
+    for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
+    {
+        if ((texture = state->textures[i]))
+        {
+            state->textures[i] = NULL;
+            wined3d_texture_decref(texture);
+        }
+    }
+
+    for (i = 0; i < MAX_STREAM_OUT; ++i)
+    {
+        if ((buffer = state->stream_output[i].buffer))
+        {
+            state->stream_output[i].buffer = NULL;
+            wined3d_buffer_decref(buffer);
+        }
+    }
+
+    for (i = 0; i < MAX_STREAMS; ++i)
+    {
+        if ((buffer = state->streams[i].buffer))
+        {
+            state->streams[i].buffer = NULL;
+            wined3d_buffer_decref(buffer);
+        }
+    }
+
+    if ((buffer = state->index_buffer))
+    {
+        state->index_buffer = NULL;
+        wined3d_buffer_decref(buffer);
+    }
+
+    if ((shader = state->vertex_shader))
+    {
+        state->vertex_shader = NULL;
+        wined3d_shader_decref(shader);
+    }
+
+    for (i = 0; i < MAX_CONSTANT_BUFFERS; ++i)
+    {
+        if ((buffer = state->vs_cb[i]))
+        {
+            state->vs_cb[i] = NULL;
+            wined3d_buffer_decref(buffer);
+        }
+    }
+
+    for (i = 0; i < MAX_SAMPLER_OBJECTS; ++i)
+    {
+        if ((sampler = state->vs_sampler[i]))
+        {
+            state->vs_sampler[i] = NULL;
+            wined3d_sampler_decref(sampler);
+        }
+    }
+
+    if ((shader = state->geometry_shader))
+    {
+        state->geometry_shader = NULL;
+        wined3d_shader_decref(shader);
+    }
+
+    for (i = 0; i < MAX_CONSTANT_BUFFERS; ++i)
+    {
+        if ((buffer = state->gs_cb[i]))
+        {
+            state->gs_cb[i] = NULL;
+            wined3d_buffer_decref(buffer);
+        }
+    }
+
+    for (i = 0; i < MAX_SAMPLER_OBJECTS; ++i)
+    {
+        if ((sampler = state->gs_sampler[i]))
+        {
+            state->gs_sampler[i] = NULL;
+            wined3d_sampler_decref(sampler);
+        }
+    }
+
+    if ((shader = state->pixel_shader))
+    {
+        state->pixel_shader = NULL;
+        wined3d_shader_decref(shader);
+    }
+
+    for (i = 0; i < MAX_SAMPLER_OBJECTS; ++i)
+    {
+        if ((sampler = state->ps_sampler[i]))
+        {
+            state->ps_sampler[i] = NULL;
+            wined3d_sampler_decref(sampler);
+        }
+    }
+
+    for (i = 0; i < MAX_CONSTANT_BUFFERS; ++i)
+    {
+        if ((buffer = state->ps_cb[i]))
+        {
+            state->ps_cb[i] = NULL;
+            wined3d_buffer_decref(buffer);
+        }
+    }
+}
+
+ULONG CDECL wined3d_stateblock_decref(struct wined3d_stateblock *stateblock)
+{
+    ULONG refcount = InterlockedDecrement(&stateblock->ref);
+
+    TRACE("%p decreasing refcount to %u\n", stateblock, refcount);
+
+    if (!refcount)
+    {
+        int counter;
+
+        stateblock_unbind_resources(stateblock);
+
+        for (counter = 0; counter < LIGHTMAP_SIZE; ++counter)
+        {
+            struct list *e1, *e2;
+            LIST_FOR_EACH_SAFE(e1, e2, &stateblock->state.light_map[counter])
+            {
+                struct wined3d_light_info *light = LIST_ENTRY(e1, struct wined3d_light_info, entry);
+                list_remove(&light->entry);
+                HeapFree(GetProcessHeap(), 0, light);
+            }
+        }
+
+        HeapFree(GetProcessHeap(), 0, stateblock->state.vs_consts_f);
+        HeapFree(GetProcessHeap(), 0, stateblock->changed.vertexShaderConstantsF);
+        HeapFree(GetProcessHeap(), 0, stateblock->state.ps_consts_f);
+        HeapFree(GetProcessHeap(), 0, stateblock->changed.pixelShaderConstantsF);
+        HeapFree(GetProcessHeap(), 0, stateblock->contained_vs_consts_f);
+        HeapFree(GetProcessHeap(), 0, stateblock->contained_ps_consts_f);
+        HeapFree(GetProcessHeap(), 0, stateblock);
+    }
+
+    return refcount;
+}
+
+static void wined3d_state_record_lights(struct wined3d_state *dst_state, const struct wined3d_state *src_state)
+{
+    UINT i;
+
+    /* Lights... For a recorded state block, we just had a chain of actions
+     * to perform, so we need to walk that chain and update any actions which
+     * differ. */
+    for (i = 0; i < LIGHTMAP_SIZE; ++i)
+    {
+        struct list *e, *f;
+        LIST_FOR_EACH(e, &dst_state->light_map[i])
+        {
+            BOOL updated = FALSE;
+            struct wined3d_light_info *src = LIST_ENTRY(e, struct wined3d_light_info, entry), *realLight;
+
+            /* Look up the light in the destination */
+            LIST_FOR_EACH(f, &src_state->light_map[i])
+            {
+                realLight = LIST_ENTRY(f, struct wined3d_light_info, entry);
+                if (realLight->OriginalIndex == src->OriginalIndex)
+                {
+                    src->OriginalParms = realLight->OriginalParms;
+
+                    if (realLight->glIndex == -1 && src->glIndex != -1)
+                    {
+                        /* Light disabled */
+                        dst_state->lights[src->glIndex] = NULL;
+                    }
+                    else if (realLight->glIndex != -1 && src->glIndex == -1)
+                    {
+                        /* Light enabled */
+                        dst_state->lights[realLight->glIndex] = src;
+                    }
+                    src->glIndex = realLight->glIndex;
+                    updated = TRUE;
+                    break;
+                }
+            }
+
+            if (!updated)
+            {
+                /* This can happen if the light was originally created as a
+                 * default light for SetLightEnable() while recording. */
+                WARN("Light %u in dst_state %p does not exist in src_state %p.\n",
+                        src->OriginalIndex, dst_state, src_state);
+
+                src->OriginalParms = WINED3D_default_light;
+                if (src->glIndex != -1)
+                {
+                    dst_state->lights[src->glIndex] = NULL;
+                    src->glIndex = -1;
+                }
+            }
+        }
+    }
+}
+
+void CDECL wined3d_stateblock_capture(struct wined3d_stateblock *stateblock)
+{
+    const struct wined3d_state *src_state = &stateblock->device->stateBlock->state;
+    unsigned int i;
+    DWORD map;
+
+    TRACE("stateblock %p.\n", stateblock);
+
+    TRACE("Capturing state %p.\n", src_state);
+
+    if (stateblock->changed.vertexShader && stateblock->state.vertex_shader != src_state->vertex_shader)
+    {
+        TRACE("Updating vertex shader from %p to %p\n",
+                stateblock->state.vertex_shader, src_state->vertex_shader);
+
+        if (src_state->vertex_shader)
+            wined3d_shader_incref(src_state->vertex_shader);
+        if (stateblock->state.vertex_shader)
+            wined3d_shader_decref(stateblock->state.vertex_shader);
+        stateblock->state.vertex_shader = src_state->vertex_shader;
+    }
+
+    /* Vertex shader float constants. */
+    for (i = 0; i < stateblock->num_contained_vs_consts_f; ++i)
+    {
+        unsigned int idx = stateblock->contained_vs_consts_f[i];
+
+        TRACE("Setting vs_consts_f[%u] to {%.8e, %.8e, %.8e, %.8e}.\n", idx,
+                src_state->vs_consts_f[idx * 4 + 0],
+                src_state->vs_consts_f[idx * 4 + 1],
+                src_state->vs_consts_f[idx * 4 + 2],
+                src_state->vs_consts_f[idx * 4 + 3]);
+
+        stateblock->state.vs_consts_f[idx * 4 + 0] = src_state->vs_consts_f[idx * 4 + 0];
+        stateblock->state.vs_consts_f[idx * 4 + 1] = src_state->vs_consts_f[idx * 4 + 1];
+        stateblock->state.vs_consts_f[idx * 4 + 2] = src_state->vs_consts_f[idx * 4 + 2];
+        stateblock->state.vs_consts_f[idx * 4 + 3] = src_state->vs_consts_f[idx * 4 + 3];
+    }
+
+    /* Vertex shader integer constants. */
+    for (i = 0; i < stateblock->num_contained_vs_consts_i; ++i)
+    {
+        unsigned int idx = stateblock->contained_vs_consts_i[i];
+
+        TRACE("Setting vs_consts[%u] to {%d, %d, %d, %d}.\n", idx,
+                src_state->vs_consts_i[idx * 4 + 0],
+                src_state->vs_consts_i[idx * 4 + 1],
+                src_state->vs_consts_i[idx * 4 + 2],
+                src_state->vs_consts_i[idx * 4 + 3]);
+
+        stateblock->state.vs_consts_i[idx * 4 + 0] = src_state->vs_consts_i[idx * 4 + 0];
+        stateblock->state.vs_consts_i[idx * 4 + 1] = src_state->vs_consts_i[idx * 4 + 1];
+        stateblock->state.vs_consts_i[idx * 4 + 2] = src_state->vs_consts_i[idx * 4 + 2];
+        stateblock->state.vs_consts_i[idx * 4 + 3] = src_state->vs_consts_i[idx * 4 + 3];
+    }
+
+    /* Vertex shader boolean constants. */
+    for (i = 0; i < stateblock->num_contained_vs_consts_b; ++i)
+    {
+        unsigned int idx = stateblock->contained_vs_consts_b[i];
+
+        TRACE("Setting vs_consts_b[%u] to %s.\n",
+                idx, src_state->vs_consts_b[idx] ? "TRUE" : "FALSE");
+
+        stateblock->state.vs_consts_b[idx] = src_state->vs_consts_b[idx];
+    }
+
+    /* Pixel shader float constants. */
+    for (i = 0; i < stateblock->num_contained_ps_consts_f; ++i)
+    {
+        unsigned int idx = stateblock->contained_ps_consts_f[i];
+
+        TRACE("Setting ps_consts_f[%u] to {%.8e, %.8e, %.8e, %.8e}.\n", idx,
+                src_state->ps_consts_f[idx * 4 + 0],
+                src_state->ps_consts_f[idx * 4 + 1],
+                src_state->ps_consts_f[idx * 4 + 2],
+                src_state->ps_consts_f[idx * 4 + 3]);
+
+        stateblock->state.ps_consts_f[idx * 4 + 0] = src_state->ps_consts_f[idx * 4 + 0];
+        stateblock->state.ps_consts_f[idx * 4 + 1] = src_state->ps_consts_f[idx * 4 + 1];
+        stateblock->state.ps_consts_f[idx * 4 + 2] = src_state->ps_consts_f[idx * 4 + 2];
+        stateblock->state.ps_consts_f[idx * 4 + 3] = src_state->ps_consts_f[idx * 4 + 3];
+    }
+
+    /* Pixel shader integer constants. */
+    for (i = 0; i < stateblock->num_contained_ps_consts_i; ++i)
+    {
+        unsigned int idx = stateblock->contained_ps_consts_i[i];
+        TRACE("Setting ps_consts_i[%u] to {%d, %d, %d, %d}.\n", idx,
+                src_state->ps_consts_i[idx * 4 + 0],
+                src_state->ps_consts_i[idx * 4 + 1],
+                src_state->ps_consts_i[idx * 4 + 2],
+                src_state->ps_consts_i[idx * 4 + 3]);
+
+        stateblock->state.ps_consts_i[idx * 4 + 0] = src_state->ps_consts_i[idx * 4 + 0];
+        stateblock->state.ps_consts_i[idx * 4 + 1] = src_state->ps_consts_i[idx * 4 + 1];
+        stateblock->state.ps_consts_i[idx * 4 + 2] = src_state->ps_consts_i[idx * 4 + 2];
+        stateblock->state.ps_consts_i[idx * 4 + 3] = src_state->ps_consts_i[idx * 4 + 3];
+    }
+
+    /* Pixel shader boolean constants. */
+    for (i = 0; i < stateblock->num_contained_ps_consts_b; ++i)
+    {
+        unsigned int idx = stateblock->contained_ps_consts_b[i];
+        TRACE("Setting ps_consts_b[%u] to %s.\n",
+                idx, src_state->ps_consts_b[idx] ? "TRUE" : "FALSE");
+
+        stateblock->state.ps_consts_b[idx] = src_state->ps_consts_b[idx];
+    }
+
+    /* Others + Render & Texture */
+    for (i = 0; i < stateblock->num_contained_transform_states; ++i)
+    {
+        enum wined3d_transform_state transform = stateblock->contained_transform_states[i];
+
+        TRACE("Updating transform %#x.\n", transform);
+
+        stateblock->state.transforms[transform] = src_state->transforms[transform];
+    }
+
+    if (stateblock->changed.primitive_type)
+        stateblock->state.gl_primitive_type = src_state->gl_primitive_type;
+
+    if (stateblock->changed.indices
+            && ((stateblock->state.index_buffer != src_state->index_buffer)
+                || (stateblock->state.base_vertex_index != src_state->base_vertex_index)
+                || (stateblock->state.index_format != src_state->index_format)))
+    {
+        TRACE("Updating index buffer to %p, base vertex index to %d.\n",
+                src_state->index_buffer, src_state->base_vertex_index);
+
+        if (src_state->index_buffer)
+            wined3d_buffer_incref(src_state->index_buffer);
+        if (stateblock->state.index_buffer)
+            wined3d_buffer_decref(stateblock->state.index_buffer);
+        stateblock->state.index_buffer = src_state->index_buffer;
+        stateblock->state.base_vertex_index = src_state->base_vertex_index;
+        stateblock->state.index_format = src_state->index_format;
+    }
+
+    if (stateblock->changed.vertexDecl && stateblock->state.vertex_declaration != src_state->vertex_declaration)
+    {
+        TRACE("Updating vertex declaration from %p to %p.\n",
+                stateblock->state.vertex_declaration, src_state->vertex_declaration);
+
+        if (src_state->vertex_declaration)
+                wined3d_vertex_declaration_incref(src_state->vertex_declaration);
+        if (stateblock->state.vertex_declaration)
+                wined3d_vertex_declaration_decref(stateblock->state.vertex_declaration);
+        stateblock->state.vertex_declaration = src_state->vertex_declaration;
+    }
+
+    if (stateblock->changed.material
+            && memcmp(&src_state->material, &stateblock->state.material, sizeof(stateblock->state.material)))
+    {
+        TRACE("Updating material.\n");
+
+        stateblock->state.material = src_state->material;
+    }
+
+    if (stateblock->changed.viewport
+            && memcmp(&src_state->viewport, &stateblock->state.viewport, sizeof(stateblock->state.viewport)))
+    {
+        TRACE("Updating viewport.\n");
+
+        stateblock->state.viewport = src_state->viewport;
+    }
+
+    if (stateblock->changed.scissorRect && memcmp(&src_state->scissor_rect,
+            &stateblock->state.scissor_rect, sizeof(stateblock->state.scissor_rect)))
+    {
+        TRACE("Updating scissor rect.\n");
+
+        stateblock->state.scissor_rect = src_state->scissor_rect;
+    }
+
+    map = stateblock->changed.streamSource;
+    for (i = 0; map; map >>= 1, ++i)
+    {
+        if (!(map & 1)) continue;
+
+        if (stateblock->state.streams[i].stride != src_state->streams[i].stride
+                || stateblock->state.streams[i].buffer != src_state->streams[i].buffer)
+        {
+            TRACE("Updating stream source %u to %p, stride to %u.\n",
+                    i, src_state->streams[i].buffer,
+                    src_state->streams[i].stride);
+
+            stateblock->state.streams[i].stride = src_state->streams[i].stride;
+            if (src_state->streams[i].buffer)
+                    wined3d_buffer_incref(src_state->streams[i].buffer);
+            if (stateblock->state.streams[i].buffer)
+                    wined3d_buffer_decref(stateblock->state.streams[i].buffer);
+            stateblock->state.streams[i].buffer = src_state->streams[i].buffer;
+        }
+    }
+
+    map = stateblock->changed.streamFreq;
+    for (i = 0; map; map >>= 1, ++i)
+    {
+        if (!(map & 1)) continue;
+
+        if (stateblock->state.streams[i].frequency != src_state->streams[i].frequency
+                || stateblock->state.streams[i].flags != src_state->streams[i].flags)
+        {
+            TRACE("Updating stream frequency %u to %u flags to %#x.\n",
+                    i, src_state->streams[i].frequency, src_state->streams[i].flags);
+
+            stateblock->state.streams[i].frequency = src_state->streams[i].frequency;
+            stateblock->state.streams[i].flags = src_state->streams[i].flags;
+        }
+    }
+
+    map = stateblock->changed.clipplane;
+    for (i = 0; map; map >>= 1, ++i)
+    {
+        if (!(map & 1)) continue;
+
+        if (memcmp(&stateblock->state.clip_planes[i], &src_state->clip_planes[i], sizeof(src_state->clip_planes[i])))
+        {
+            TRACE("Updating clipplane %u.\n", i);
+            stateblock->state.clip_planes[i] = src_state->clip_planes[i];
+        }
+    }
+
+    /* Render */
+    for (i = 0; i < stateblock->num_contained_render_states; ++i)
+    {
+        enum wined3d_render_state rs = stateblock->contained_render_states[i];
+
+        TRACE("Updating render state %#x to %u.\n", rs, src_state->render_states[rs]);
+
+        stateblock->state.render_states[rs] = src_state->render_states[rs];
+    }
+
+    /* Texture states */
+    for (i = 0; i < stateblock->num_contained_tss_states; ++i)
+    {
+        DWORD stage = stateblock->contained_tss_states[i].stage;
+        DWORD state = stateblock->contained_tss_states[i].state;
+
+        TRACE("Updating texturestage state %u, %u to %#x (was %#x).\n", stage, state,
+                src_state->texture_states[stage][state], stateblock->state.texture_states[stage][state]);
+
+        stateblock->state.texture_states[stage][state] = src_state->texture_states[stage][state];
+    }
+
+    /* Samplers */
+    map = stateblock->changed.textures;
+    for (i = 0; map; map >>= 1, ++i)
+    {
+        if (!(map & 1)) continue;
+
+        TRACE("Updating texture %u to %p (was %p).\n",
+                i, src_state->textures[i], stateblock->state.textures[i]);
+
+        if (src_state->textures[i])
+            wined3d_texture_incref(src_state->textures[i]);
+        if (stateblock->state.textures[i])
+            wined3d_texture_decref(stateblock->state.textures[i]);
+        stateblock->state.textures[i] = src_state->textures[i];
+    }
+
+    for (i = 0; i < stateblock->num_contained_sampler_states; ++i)
+    {
+        DWORD stage = stateblock->contained_sampler_states[i].stage;
+        DWORD state = stateblock->contained_sampler_states[i].state;
+
+        TRACE("Updating sampler state %u, %u to %#x (was %#x).\n", stage, state,
+                src_state->sampler_states[stage][state], stateblock->state.sampler_states[stage][state]);
+
+        stateblock->state.sampler_states[stage][state] = src_state->sampler_states[stage][state];
+    }
+
+    if (stateblock->changed.pixelShader && stateblock->state.pixel_shader != src_state->pixel_shader)
+    {
+        if (src_state->pixel_shader)
+            wined3d_shader_incref(src_state->pixel_shader);
+        if (stateblock->state.pixel_shader)
+            wined3d_shader_decref(stateblock->state.pixel_shader);
+        stateblock->state.pixel_shader = src_state->pixel_shader;
+    }
+
+    wined3d_state_record_lights(&stateblock->state, src_state);
+
+    TRACE("Capture done.\n");
+}
+
+static void apply_lights(struct wined3d_device *device, const struct wined3d_state *state)
+{
+    UINT i;
+
+    for (i = 0; i < LIGHTMAP_SIZE; ++i)
+    {
+        struct list *e;
+
+        LIST_FOR_EACH(e, &state->light_map[i])
+        {
+            const struct wined3d_light_info *light = LIST_ENTRY(e, struct wined3d_light_info, entry);
+
+            wined3d_device_set_light(device, light->OriginalIndex, &light->OriginalParms);
+            wined3d_device_set_light_enable(device, light->OriginalIndex, light->glIndex != -1);
+        }
+    }
+}
+
+void CDECL wined3d_stateblock_apply(const struct wined3d_stateblock *stateblock)
+{
+    struct wined3d_device *device = stateblock->device;
+    unsigned int i;
+    DWORD map;
+
+    TRACE("Applying stateblock %p to device %p.\n", stateblock, device);
+
+    if (stateblock->changed.vertexShader)
+        wined3d_device_set_vertex_shader(device, stateblock->state.vertex_shader);
+
+    /* Vertex Shader Constants. */
+    for (i = 0; i < stateblock->num_contained_vs_consts_f; ++i)
+    {
+        wined3d_device_set_vs_consts_f(device, stateblock->contained_vs_consts_f[i],
+                stateblock->state.vs_consts_f + stateblock->contained_vs_consts_f[i] * 4, 1);
+    }
+    for (i = 0; i < stateblock->num_contained_vs_consts_i; ++i)
+    {
+        wined3d_device_set_vs_consts_i(device, stateblock->contained_vs_consts_i[i],
+                stateblock->state.vs_consts_i + stateblock->contained_vs_consts_i[i] * 4, 1);
+    }
+    for (i = 0; i < stateblock->num_contained_vs_consts_b; ++i)
+    {
+        wined3d_device_set_vs_consts_b(device, stateblock->contained_vs_consts_b[i],
+                stateblock->state.vs_consts_b + stateblock->contained_vs_consts_b[i], 1);
+    }
+
+    apply_lights(device, &stateblock->state);
+
+    if (stateblock->changed.pixelShader)
+        wined3d_device_set_pixel_shader(device, stateblock->state.pixel_shader);
+
+    /* Pixel Shader Constants. */
+    for (i = 0; i < stateblock->num_contained_ps_consts_f; ++i)
+    {
+        wined3d_device_set_ps_consts_f(device, stateblock->contained_ps_consts_f[i],
+                stateblock->state.ps_consts_f + stateblock->contained_ps_consts_f[i] * 4, 1);
+    }
+    for (i = 0; i < stateblock->num_contained_ps_consts_i; ++i)
+    {
+        wined3d_device_set_ps_consts_i(device, stateblock->contained_ps_consts_i[i],
+                stateblock->state.ps_consts_i + stateblock->contained_ps_consts_i[i] * 4, 1);
+    }
+    for (i = 0; i < stateblock->num_contained_ps_consts_b; ++i)
+    {
+        wined3d_device_set_ps_consts_b(device, stateblock->contained_ps_consts_b[i],
+                stateblock->state.ps_consts_b + stateblock->contained_ps_consts_b[i], 1);
+    }
+
+    /* Render states. */
+    for (i = 0; i < stateblock->num_contained_render_states; ++i)
+    {
+        wined3d_device_set_render_state(device, stateblock->contained_render_states[i],
+                stateblock->state.render_states[stateblock->contained_render_states[i]]);
+    }
+
+    /* Texture states. */
+    for (i = 0; i < stateblock->num_contained_tss_states; ++i)
+    {
+        DWORD stage = stateblock->contained_tss_states[i].stage;
+        DWORD state = stateblock->contained_tss_states[i].state;
+
+        wined3d_device_set_texture_stage_state(device, stage, state, stateblock->state.texture_states[stage][state]);
+    }
+
+    /* Sampler states. */
+    for (i = 0; i < stateblock->num_contained_sampler_states; ++i)
+    {
+        DWORD stage = stateblock->contained_sampler_states[i].stage;
+        DWORD state = stateblock->contained_sampler_states[i].state;
+        DWORD value = stateblock->state.sampler_states[stage][state];
+
+        if (stage >= MAX_FRAGMENT_SAMPLERS) stage += WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS;
+        wined3d_device_set_sampler_state(device, stage, state, value);
+    }
+
+    /* Transform states. */
+    for (i = 0; i < stateblock->num_contained_transform_states; ++i)
+    {
+        wined3d_device_set_transform(device, stateblock->contained_transform_states[i],
+                &stateblock->state.transforms[stateblock->contained_transform_states[i]]);
+    }
+
+    if (stateblock->changed.primitive_type)
+    {
+        GLenum gl_primitive_type, prev;
+
+        device->updateStateBlock->changed.primitive_type = TRUE;
+        gl_primitive_type = stateblock->state.gl_primitive_type;
+        prev = device->updateStateBlock->state.gl_primitive_type;
+        device->updateStateBlock->state.gl_primitive_type = gl_primitive_type;
+        if (gl_primitive_type != prev && (gl_primitive_type == GL_POINTS || prev == GL_POINTS))
+            device_invalidate_state(device, STATE_POINT_SIZE_ENABLE);
+    }
+
+    if (stateblock->changed.indices)
+    {
+        wined3d_device_set_index_buffer(device, stateblock->state.index_buffer, stateblock->state.index_format);
+        wined3d_device_set_base_vertex_index(device, stateblock->state.base_vertex_index);
+    }
+
+    if (stateblock->changed.vertexDecl && stateblock->state.vertex_declaration)
+        wined3d_device_set_vertex_declaration(device, stateblock->state.vertex_declaration);
+
+    if (stateblock->changed.material)
+        wined3d_device_set_material(device, &stateblock->state.material);
+
+    if (stateblock->changed.viewport)
+        wined3d_device_set_viewport(device, &stateblock->state.viewport);
+
+    if (stateblock->changed.scissorRect)
+        wined3d_device_set_scissor_rect(device, &stateblock->state.scissor_rect);
+
+    map = stateblock->changed.streamSource;
+    for (i = 0; map; map >>= 1, ++i)
+    {
+        if (map & 1)
+            wined3d_device_set_stream_source(device, i,
+                    stateblock->state.streams[i].buffer,
+                    0, stateblock->state.streams[i].stride);
+    }
+
+    map = stateblock->changed.streamFreq;
+    for (i = 0; map; map >>= 1, ++i)
+    {
+        if (map & 1)
+            wined3d_device_set_stream_source_freq(device, i,
+                    stateblock->state.streams[i].frequency | stateblock->state.streams[i].flags);
+    }
+
+    map = stateblock->changed.textures;
+    for (i = 0; map; map >>= 1, ++i)
+    {
+        DWORD stage;
+
+        if (!(map & 1)) continue;
+
+        stage = i < MAX_FRAGMENT_SAMPLERS ? i : WINED3DVERTEXTEXTURESAMPLER0 + i - MAX_FRAGMENT_SAMPLERS;
+        wined3d_device_set_texture(device, stage, stateblock->state.textures[i]);
+    }
+
+    map = stateblock->changed.clipplane;
+    for (i = 0; map; map >>= 1, ++i)
+    {
+        if (!(map & 1)) continue;
+
+        wined3d_device_set_clip_plane(device, i, &stateblock->state.clip_planes[i]);
+    }
+
+    stateblock->device->stateBlock->state.lowest_disabled_stage = MAX_TEXTURES - 1;
+    for (i = 0; i < MAX_TEXTURES - 1; ++i)
+    {
+        if (stateblock->device->stateBlock->state.texture_states[i][WINED3D_TSS_COLOR_OP] == WINED3D_TOP_DISABLE)
+        {
+            stateblock->device->stateBlock->state.lowest_disabled_stage = i;
+            break;
+        }
+    }
+
+    TRACE("Applied stateblock %p.\n", stateblock);
+}
+
+void stateblock_init_default_state(struct wined3d_stateblock *stateblock)
+{
+    struct wined3d_device *device = stateblock->device;
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
+    struct wined3d_state *state = &stateblock->state;
+    union
+    {
+        struct wined3d_line_pattern lp;
+        DWORD d;
+    } lp;
+    union {
+        float f;
+        DWORD d;
+    } tmpfloat;
+    unsigned int i;
+    struct wined3d_swapchain *swapchain;
+    struct wined3d_surface *backbuffer;
+    static const struct wined3d_matrix identity =
+    {{{
+        1.0f, 0.0f, 0.0f, 0.0f,
+        0.0f, 1.0f, 0.0f, 0.0f,
+        0.0f, 0.0f, 1.0f, 0.0f,
+        0.0f, 0.0f, 0.0f, 1.0f,
+    }}};
+
+    TRACE("stateblock %p.\n", stateblock);
+
+    memset(stateblock->changed.pixelShaderConstantsF, 0, d3d_info->limits.ps_uniform_count * sizeof(BOOL));
+    memset(stateblock->changed.vertexShaderConstantsF, 0, d3d_info->limits.vs_uniform_count * sizeof(BOOL));
+
+    /* Set some of the defaults for lights, transforms etc */
+    state->transforms[WINED3D_TS_PROJECTION] = identity;
+    state->transforms[WINED3D_TS_VIEW] = identity;
+    for (i = 0; i < 256; ++i)
+    {
+        state->transforms[WINED3D_TS_WORLD_MATRIX(i)] = identity;
+    }
+
+    state->fb = &device->fb;
+
+    TRACE("Render states\n");
+    /* Render states: */
+    if (device->auto_depth_stencil)
+       state->render_states[WINED3D_RS_ZENABLE] = WINED3D_ZB_TRUE;
+    else
+       state->render_states[WINED3D_RS_ZENABLE] = WINED3D_ZB_FALSE;
+    state->render_states[WINED3D_RS_FILLMODE] = WINED3D_FILL_SOLID;
+    state->render_states[WINED3D_RS_SHADEMODE] = WINED3D_SHADE_GOURAUD;
+    lp.lp.repeat_factor = 0;
+    lp.lp.line_pattern = 0;
+    state->render_states[WINED3D_RS_LINEPATTERN] = lp.d;
+    state->render_states[WINED3D_RS_ZWRITEENABLE] = TRUE;
+    state->render_states[WINED3D_RS_ALPHATESTENABLE] = FALSE;
+    state->render_states[WINED3D_RS_LASTPIXEL] = TRUE;
+    state->render_states[WINED3D_RS_SRCBLEND] = WINED3D_BLEND_ONE;
+    state->render_states[WINED3D_RS_DESTBLEND] = WINED3D_BLEND_ZERO;
+    state->render_states[WINED3D_RS_CULLMODE] = WINED3D_CULL_CCW;
+    state->render_states[WINED3D_RS_ZFUNC] = WINED3D_CMP_LESSEQUAL;
+    state->render_states[WINED3D_RS_ALPHAFUNC] = WINED3D_CMP_ALWAYS;
+    state->render_states[WINED3D_RS_ALPHAREF] = 0;
+    state->render_states[WINED3D_RS_DITHERENABLE] = FALSE;
+    state->render_states[WINED3D_RS_ALPHABLENDENABLE] = FALSE;
+    state->render_states[WINED3D_RS_FOGENABLE] = FALSE;
+    state->render_states[WINED3D_RS_SPECULARENABLE] = FALSE;
+    state->render_states[WINED3D_RS_ZVISIBLE] = 0;
+    state->render_states[WINED3D_RS_FOGCOLOR] = 0;
+    state->render_states[WINED3D_RS_FOGTABLEMODE] = WINED3D_FOG_NONE;
+    tmpfloat.f = 0.0f;
+    state->render_states[WINED3D_RS_FOGSTART] = tmpfloat.d;
+    tmpfloat.f = 1.0f;
+    state->render_states[WINED3D_RS_FOGEND] = tmpfloat.d;
+    tmpfloat.f = 1.0f;
+    state->render_states[WINED3D_RS_FOGDENSITY] = tmpfloat.d;
+    state->render_states[WINED3D_RS_EDGEANTIALIAS] = FALSE;
+    state->render_states[WINED3D_RS_RANGEFOGENABLE] = FALSE;
+    state->render_states[WINED3D_RS_STENCILENABLE] = FALSE;
+    state->render_states[WINED3D_RS_STENCILFAIL] = WINED3D_STENCIL_OP_KEEP;
+    state->render_states[WINED3D_RS_STENCILZFAIL] = WINED3D_STENCIL_OP_KEEP;
+    state->render_states[WINED3D_RS_STENCILPASS] = WINED3D_STENCIL_OP_KEEP;
+    state->render_states[WINED3D_RS_STENCILREF] = 0;
+    state->render_states[WINED3D_RS_STENCILMASK] = 0xffffffff;
+    state->render_states[WINED3D_RS_STENCILFUNC] = WINED3D_CMP_ALWAYS;
+    state->render_states[WINED3D_RS_STENCILWRITEMASK] = 0xffffffff;
+    state->render_states[WINED3D_RS_TEXTUREFACTOR] = 0xffffffff;
+    state->render_states[WINED3D_RS_WRAP0] = 0;
+    state->render_states[WINED3D_RS_WRAP1] = 0;
+    state->render_states[WINED3D_RS_WRAP2] = 0;
+    state->render_states[WINED3D_RS_WRAP3] = 0;
+    state->render_states[WINED3D_RS_WRAP4] = 0;
+    state->render_states[WINED3D_RS_WRAP5] = 0;
+    state->render_states[WINED3D_RS_WRAP6] = 0;
+    state->render_states[WINED3D_RS_WRAP7] = 0;
+    state->render_states[WINED3D_RS_CLIPPING] = TRUE;
+    state->render_states[WINED3D_RS_LIGHTING] = TRUE;
+    state->render_states[WINED3D_RS_AMBIENT] = 0;
+    state->render_states[WINED3D_RS_FOGVERTEXMODE] = WINED3D_FOG_NONE;
+    state->render_states[WINED3D_RS_COLORVERTEX] = TRUE;
+    state->render_states[WINED3D_RS_LOCALVIEWER] = TRUE;
+    state->render_states[WINED3D_RS_NORMALIZENORMALS] = FALSE;
+    state->render_states[WINED3D_RS_DIFFUSEMATERIALSOURCE] = WINED3D_MCS_COLOR1;
+    state->render_states[WINED3D_RS_SPECULARMATERIALSOURCE] = WINED3D_MCS_COLOR2;
+    state->render_states[WINED3D_RS_AMBIENTMATERIALSOURCE] = WINED3D_MCS_MATERIAL;
+    state->render_states[WINED3D_RS_EMISSIVEMATERIALSOURCE] = WINED3D_MCS_MATERIAL;
+    state->render_states[WINED3D_RS_VERTEXBLEND] = WINED3D_VBF_DISABLE;
+    state->render_states[WINED3D_RS_CLIPPLANEENABLE] = 0;
+    state->render_states[WINED3D_RS_SOFTWAREVERTEXPROCESSING] = FALSE;
+    tmpfloat.f = 1.0f;
+    state->render_states[WINED3D_RS_POINTSIZE] = tmpfloat.d;
+    tmpfloat.f = 1.0f;
+    state->render_states[WINED3D_RS_POINTSIZE_MIN] = tmpfloat.d;
+    state->render_states[WINED3D_RS_POINTSPRITEENABLE] = FALSE;
+    state->render_states[WINED3D_RS_POINTSCALEENABLE] = FALSE;
+    tmpfloat.f = 1.0f;
+    state->render_states[WINED3D_RS_POINTSCALE_A] = tmpfloat.d;
+    tmpfloat.f = 0.0f;
+    state->render_states[WINED3D_RS_POINTSCALE_B] = tmpfloat.d;
+    tmpfloat.f = 0.0f;
+    state->render_states[WINED3D_RS_POINTSCALE_C] = tmpfloat.d;
+    state->render_states[WINED3D_RS_MULTISAMPLEANTIALIAS] = TRUE;
+    state->render_states[WINED3D_RS_MULTISAMPLEMASK] = 0xffffffff;
+    state->render_states[WINED3D_RS_PATCHEDGESTYLE] = WINED3D_PATCH_EDGE_DISCRETE;
+    tmpfloat.f = 1.0f;
+    state->render_states[WINED3D_RS_PATCHSEGMENTS] = tmpfloat.d;
+    state->render_states[WINED3D_RS_DEBUGMONITORTOKEN] = 0xbaadcafe;
+    tmpfloat.f = gl_info->limits.pointsize_max;
+    state->render_states[WINED3D_RS_POINTSIZE_MAX] = tmpfloat.d;
+    state->render_states[WINED3D_RS_INDEXEDVERTEXBLENDENABLE] = FALSE;
+    state->render_states[WINED3D_RS_COLORWRITEENABLE] = 0x0000000f;
+    tmpfloat.f = 0.0f;
+    state->render_states[WINED3D_RS_TWEENFACTOR] = tmpfloat.d;
+    state->render_states[WINED3D_RS_BLENDOP] = WINED3D_BLEND_OP_ADD;
+    state->render_states[WINED3D_RS_POSITIONDEGREE] = WINED3D_DEGREE_CUBIC;
+    state->render_states[WINED3D_RS_NORMALDEGREE] = WINED3D_DEGREE_LINEAR;
+    /* states new in d3d9 */
+    state->render_states[WINED3D_RS_SCISSORTESTENABLE] = FALSE;
+    state->render_states[WINED3D_RS_SLOPESCALEDEPTHBIAS] = 0;
+    tmpfloat.f = 1.0f;
+    state->render_states[WINED3D_RS_MINTESSELLATIONLEVEL] = tmpfloat.d;
+    state->render_states[WINED3D_RS_MAXTESSELLATIONLEVEL] = tmpfloat.d;
+    state->render_states[WINED3D_RS_ANTIALIASEDLINEENABLE] = FALSE;
+    tmpfloat.f = 0.0f;
+    state->render_states[WINED3D_RS_ADAPTIVETESS_X] = tmpfloat.d;
+    state->render_states[WINED3D_RS_ADAPTIVETESS_Y] = tmpfloat.d;
+    tmpfloat.f = 1.0f;
+    state->render_states[WINED3D_RS_ADAPTIVETESS_Z] = tmpfloat.d;
+    tmpfloat.f = 0.0f;
+    state->render_states[WINED3D_RS_ADAPTIVETESS_W] = tmpfloat.d;
+    state->render_states[WINED3D_RS_ENABLEADAPTIVETESSELLATION] = FALSE;
+    state->render_states[WINED3D_RS_TWOSIDEDSTENCILMODE] = FALSE;
+    state->render_states[WINED3D_RS_CCW_STENCILFAIL] = WINED3D_STENCIL_OP_KEEP;
+    state->render_states[WINED3D_RS_CCW_STENCILZFAIL] = WINED3D_STENCIL_OP_KEEP;
+    state->render_states[WINED3D_RS_CCW_STENCILPASS] = WINED3D_STENCIL_OP_KEEP;
+    state->render_states[WINED3D_RS_CCW_STENCILFUNC] = WINED3D_CMP_ALWAYS;
+    state->render_states[WINED3D_RS_COLORWRITEENABLE1] = 0x0000000f;
+    state->render_states[WINED3D_RS_COLORWRITEENABLE2] = 0x0000000f;
+    state->render_states[WINED3D_RS_COLORWRITEENABLE3] = 0x0000000f;
+    state->render_states[WINED3D_RS_BLENDFACTOR] = 0xffffffff;
+    state->render_states[WINED3D_RS_SRGBWRITEENABLE] = 0;
+    state->render_states[WINED3D_RS_DEPTHBIAS] = 0;
+    state->render_states[WINED3D_RS_WRAP8] = 0;
+    state->render_states[WINED3D_RS_WRAP9] = 0;
+    state->render_states[WINED3D_RS_WRAP10] = 0;
+    state->render_states[WINED3D_RS_WRAP11] = 0;
+    state->render_states[WINED3D_RS_WRAP12] = 0;
+    state->render_states[WINED3D_RS_WRAP13] = 0;
+    state->render_states[WINED3D_RS_WRAP14] = 0;
+    state->render_states[WINED3D_RS_WRAP15] = 0;
+    state->render_states[WINED3D_RS_SEPARATEALPHABLENDENABLE] = FALSE;
+    state->render_states[WINED3D_RS_SRCBLENDALPHA] = WINED3D_BLEND_ONE;
+    state->render_states[WINED3D_RS_DESTBLENDALPHA] = WINED3D_BLEND_ZERO;
+    state->render_states[WINED3D_RS_BLENDOPALPHA] = WINED3D_BLEND_OP_ADD;
+
+    /* Texture Stage States - Put directly into state block, we will call function below */
+    for (i = 0; i < MAX_TEXTURES; ++i)
+    {
+        TRACE("Setting up default texture states for texture Stage %u.\n", i);
+        state->transforms[WINED3D_TS_TEXTURE0 + i] = identity;
+        state->texture_states[i][WINED3D_TSS_COLOR_OP] = i ? WINED3D_TOP_DISABLE : WINED3D_TOP_MODULATE;
+        state->texture_states[i][WINED3D_TSS_COLOR_ARG1] = WINED3DTA_TEXTURE;
+        state->texture_states[i][WINED3D_TSS_COLOR_ARG2] = WINED3DTA_CURRENT;
+        state->texture_states[i][WINED3D_TSS_ALPHA_OP] = i ? WINED3D_TOP_DISABLE : WINED3D_TOP_SELECT_ARG1;
+        state->texture_states[i][WINED3D_TSS_ALPHA_ARG1] = WINED3DTA_TEXTURE;
+        state->texture_states[i][WINED3D_TSS_ALPHA_ARG2] = WINED3DTA_CURRENT;
+        state->texture_states[i][WINED3D_TSS_BUMPENV_MAT00] = 0;
+        state->texture_states[i][WINED3D_TSS_BUMPENV_MAT01] = 0;
+        state->texture_states[i][WINED3D_TSS_BUMPENV_MAT10] = 0;
+        state->texture_states[i][WINED3D_TSS_BUMPENV_MAT11] = 0;
+        state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX] = i;
+        state->texture_states[i][WINED3D_TSS_BUMPENV_LSCALE] = 0;
+        state->texture_states[i][WINED3D_TSS_BUMPENV_LOFFSET] = 0;
+        state->texture_states[i][WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS] = WINED3D_TTFF_DISABLE;
+        state->texture_states[i][WINED3D_TSS_COLOR_ARG0] = WINED3DTA_CURRENT;
+        state->texture_states[i][WINED3D_TSS_ALPHA_ARG0] = WINED3DTA_CURRENT;
+        state->texture_states[i][WINED3D_TSS_RESULT_ARG] = WINED3DTA_CURRENT;
+    }
+    state->lowest_disabled_stage = 1;
+
+        /* Sampler states*/
+    for (i = 0 ; i <  MAX_COMBINED_SAMPLERS; ++i)
+    {
+        TRACE("Setting up default samplers states for sampler %u.\n", i);
+        state->sampler_states[i][WINED3D_SAMP_ADDRESS_U] = WINED3D_TADDRESS_WRAP;
+        state->sampler_states[i][WINED3D_SAMP_ADDRESS_V] = WINED3D_TADDRESS_WRAP;
+        state->sampler_states[i][WINED3D_SAMP_ADDRESS_W] = WINED3D_TADDRESS_WRAP;
+        state->sampler_states[i][WINED3D_SAMP_BORDER_COLOR] = 0;
+        state->sampler_states[i][WINED3D_SAMP_MAG_FILTER] = WINED3D_TEXF_POINT;
+        state->sampler_states[i][WINED3D_SAMP_MIN_FILTER] = WINED3D_TEXF_POINT;
+        state->sampler_states[i][WINED3D_SAMP_MIP_FILTER] = WINED3D_TEXF_NONE;
+        state->sampler_states[i][WINED3D_SAMP_MIPMAP_LOD_BIAS] = 0;
+        state->sampler_states[i][WINED3D_SAMP_MAX_MIP_LEVEL] = 0;
+        state->sampler_states[i][WINED3D_SAMP_MAX_ANISOTROPY] = 1;
+        state->sampler_states[i][WINED3D_SAMP_SRGB_TEXTURE] = 0;
+        /* TODO: Indicates which element of a multielement texture to use. */
+        state->sampler_states[i][WINED3D_SAMP_ELEMENT_INDEX] = 0;
+        /* TODO: Vertex offset in the presampled displacement map. */
+        state->sampler_states[i][WINED3D_SAMP_DMAP_OFFSET] = 0;
+    }
+
+    for (i = 0; i < gl_info->limits.textures; ++i)
+    {
+        state->textures[i] = NULL;
+    }
+
+    /* check the return values, because the GetBackBuffer call isn't valid for ddraw */
+    if ((swapchain = wined3d_device_get_swapchain(device, 0)))
+    {
+        if ((backbuffer = wined3d_swapchain_get_back_buffer(swapchain, 0, WINED3D_BACKBUFFER_TYPE_MONO)))
+        {
+            struct wined3d_resource_desc desc;
+
+            wined3d_resource_get_desc(&backbuffer->resource, &desc);
+
+            /* Set the default scissor rect values */
+            state->scissor_rect.left = 0;
+            state->scissor_rect.right = desc.width;
+            state->scissor_rect.top = 0;
+            state->scissor_rect.bottom = desc.height;
+        }
+
+        /* Set the default viewport */
+        state->viewport.x = 0;
+        state->viewport.y = 0;
+        state->viewport.width = swapchain->desc.backbuffer_width;
+        state->viewport.height = swapchain->desc.backbuffer_height;
+        state->viewport.min_z = 0.0f;
+        state->viewport.max_z = 1.0f;
+    }
+
+    TRACE("Done.\n");
+}
+
+static HRESULT stateblock_init(struct wined3d_stateblock *stateblock,
+        struct wined3d_device *device, enum wined3d_stateblock_type type)
+{
+    unsigned int i;
+    HRESULT hr;
+    const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
+
+    stateblock->ref = 1;
+    stateblock->device = device;
+
+    for (i = 0; i < LIGHTMAP_SIZE; i++)
+    {
+        list_init(&stateblock->state.light_map[i]);
+    }
+
+    hr = stateblock_allocate_shader_constants(stateblock);
+    if (FAILED(hr)) return hr;
+
+    /* The WINED3D_SBT_INIT stateblock type is used during initialization to
+     * produce a placeholder stateblock so other functions called can update a
+     * state block. */
+    if (type == WINED3D_SBT_INIT || type == WINED3D_SBT_RECORDED) return WINED3D_OK;
+
+    TRACE("Updating changed flags appropriate for type %#x.\n", type);
+
+    switch (type)
+    {
+        case WINED3D_SBT_ALL:
+            stateblock_init_lights(stateblock, device->stateBlock->state.light_map);
+            stateblock_savedstates_set_all(&stateblock->changed,
+                    d3d_info->limits.vs_uniform_count, d3d_info->limits.ps_uniform_count);
+            break;
+
+        case WINED3D_SBT_PIXEL_STATE:
+            stateblock_savedstates_set_pixel(&stateblock->changed,
+                    d3d_info->limits.ps_uniform_count);
+            break;
+
+        case WINED3D_SBT_VERTEX_STATE:
+            stateblock_init_lights(stateblock, device->stateBlock->state.light_map);
+            stateblock_savedstates_set_vertex(&stateblock->changed,
+                    d3d_info->limits.vs_uniform_count);
+            break;
+
+        default:
+            FIXME("Unrecognized state block type %#x.\n", type);
+            break;
+    }
+
+    stateblock_init_contained_states(stateblock);
+    wined3d_stateblock_capture(stateblock);
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_stateblock_create(struct wined3d_device *device,
+        enum wined3d_stateblock_type type, struct wined3d_stateblock **stateblock)
+{
+    struct wined3d_stateblock *object;
+    HRESULT hr;
+
+    TRACE("device %p, type %#x, stateblock %p.\n",
+            device, type, stateblock);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return E_OUTOFMEMORY;
+
+    hr = stateblock_init(object, device, type);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize stateblock, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created stateblock %p.\n", object);
+    *stateblock = object;
+
+    return WINED3D_OK;
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/surface.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/surface.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/surface.c	(revision 46521)
@@ -0,0 +1,7768 @@
+/*
+ * Copyright 1997-2000 Marcus Meissner
+ * Copyright 1998-2000 Lionel Ulmer
+ * Copyright 2000-2001 TransGaming Technologies Inc.
+ * Copyright 2002-2005 Jason Edmeades
+ * Copyright 2002-2003 Raphael Junqueira
+ * Copyright 2004 Christian Costa
+ * Copyright 2005 Oliver Stieber
+ * Copyright 2006-2011 Stefan Dösinger for CodeWeavers
+ * Copyright 2007-2008 Henri Verbeet
+ * Copyright 2006-2008 Roderick Colenbrander
+ * Copyright 2009-2011 Henri Verbeet for CodeWeavers
+ *
+ * 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 "wined3d_private.h"
+#ifdef VBOX_WITH_WINE_FIXES
+# include <float.h>
+#endif
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface);
+WINE_DECLARE_DEBUG_CHANNEL(d3d_perf);
+WINE_DECLARE_DEBUG_CHANNEL(d3d);
+
+#ifdef VBOX_WITH_WDDM
+void surface_shrc_lock_surf(struct wined3d_surface *surf)
+{
+    VBOXSHRC_LOCK(surf);
+}
+
+void surface_shrc_unlock_surf(struct wined3d_surface *surf)
+{
+    VBOXSHRC_UNLOCK(surf);
+    if (VBOXSHRC_IS_LOCKED(surf))
+        return;
+
+    /* perform data->texture synchronization */
+    surface_load_location(surf, SFLAG_INTEXTURE, NULL);
+}
+
+void surface_shrc_lock(struct wined3d_surface *surf)
+{
+    if (!VBOXSHRC_IS_SHARED(surf))
+        return;
+
+    surface_shrc_lock_surf(surf);
+}
+
+void surface_shrc_unlock(struct wined3d_surface *surf)
+{
+    if (!VBOXSHRC_IS_SHARED(surf))
+        return;
+    surface_shrc_unlock_surf(surf);
+}
+#endif
+
+static HRESULT surface_cpu_blt(struct wined3d_surface *dst_surface, const RECT *dst_rect,
+        struct wined3d_surface *src_surface, const RECT *src_rect, DWORD flags,
+        const WINEDDBLTFX *fx, enum wined3d_texture_filter_type filter);
+static HRESULT IWineD3DSurfaceImpl_BltOverride(struct wined3d_surface *dst_surface, const RECT *dst_rect,
+        struct wined3d_surface *src_surface, const RECT *src_rect, DWORD flags, const WINEDDBLTFX *fx,
+        enum wined3d_texture_filter_type filter);
+
+static void surface_cleanup(struct wined3d_surface *surface)
+{
+    struct wined3d_surface *overlay, *cur;
+
+    TRACE("surface %p.\n", surface);
+
+    if (surface->texture_name || (surface->flags & SFLAG_PBO)
+             || surface->rb_multisample || surface->rb_resolved
+             || !list_empty(&surface->renderbuffers))
+    {
+        struct wined3d_renderbuffer_entry *entry, *entry2;
+        const struct wined3d_gl_info *gl_info;
+        struct wined3d_context *context;
+
+        context = context_acquire(surface->resource.device, NULL);
+        gl_info = context->gl_info;
+
+        if (surface->texture_name)
+        {
+            TRACE("Deleting texture %u.\n", surface->texture_name);
+#ifdef VBOX_WITH_WDDM
+            texture_gl_delete(surface->texture_name);
+#else
+            gl_info->gl_ops.gl.p_glDeleteTextures(1, &surface->texture_name);
+#endif
+        }
+
+        if (surface->flags & SFLAG_PBO)
+        {
+            TRACE("Deleting PBO %u.\n", surface->pbo);
+            GL_EXTCALL(glDeleteBuffersARB(1, &surface->pbo));
+        }
+
+        if (surface->rb_multisample)
+        {
+            TRACE("Deleting multisample renderbuffer %u.\n", surface->rb_multisample);
+            gl_info->fbo_ops.glDeleteRenderbuffers(1, &surface->rb_multisample);
+        }
+
+        if (surface->rb_resolved)
+        {
+            TRACE("Deleting resolved renderbuffer %u.\n", surface->rb_resolved);
+            gl_info->fbo_ops.glDeleteRenderbuffers(1, &surface->rb_resolved);
+        }
+
+        LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &surface->renderbuffers, struct wined3d_renderbuffer_entry, entry)
+        {
+            TRACE("Deleting renderbuffer %u.\n", entry->id);
+            gl_info->fbo_ops.glDeleteRenderbuffers(1, &entry->id);
+            HeapFree(GetProcessHeap(), 0, entry);
+        }
+
+        context_release(context);
+    }
+
+    if (surface->flags & SFLAG_DIBSECTION)
+    {
+        DeleteDC(surface->hDC);
+        DeleteObject(surface->dib.DIBsection);
+        surface->dib.bitmap_data = NULL;
+        surface->resource.allocatedMemory = NULL;
+    }
+
+    if (surface->flags & SFLAG_USERPTR)
+        wined3d_surface_set_mem(surface, NULL);
+    if (surface->overlay_dest)
+        list_remove(&surface->overlay_entry);
+
+    LIST_FOR_EACH_ENTRY_SAFE(overlay, cur, &surface->overlays, struct wined3d_surface, overlay_entry)
+    {
+        list_remove(&overlay->overlay_entry);
+        overlay->overlay_dest = NULL;
+    }
+
+    resource_cleanup(&surface->resource);
+
+#ifdef VBOX_WITH_WDDM
+    /* @rodo: CHECK AND REMOVE : this should not be necessary anymore */
+    {
+        struct wined3d_device *device = surface->resource.device;
+        struct wined3d_context *context;
+        UINT i;
+        for (i = 0; i < device->context_count; ++i)
+        {
+            context = device->contexts[i];
+            /* pretty hacky, @todo: check if the context is acquired and re-acquire it with the new swapchain */
+            if (context->current_rt  == surface)
+            {
+                Assert(0);
+            }
+        }
+    }
+#endif
+
+}
+
+void surface_update_draw_binding(struct wined3d_surface *surface)
+{
+    if (!surface_is_offscreen(surface) || wined3d_settings.offscreen_rendering_mode != ORM_FBO)
+        surface->draw_binding = SFLAG_INDRAWABLE;
+    else if (surface->resource.multisample_type)
+        surface->draw_binding = SFLAG_INRB_MULTISAMPLE;
+    else
+        surface->draw_binding = SFLAG_INTEXTURE;
+}
+
+void surface_set_swapchain(struct wined3d_surface *surface, struct wined3d_swapchain *swapchain)
+{
+    TRACE("surface %p, swapchain %p.\n", surface, swapchain);
+
+    if (swapchain)
+    {
+        surface->get_drawable_size = get_drawable_size_swapchain;
+    }
+    else
+    {
+        switch (wined3d_settings.offscreen_rendering_mode)
+        {
+            case ORM_FBO:
+                surface->get_drawable_size = get_drawable_size_fbo;
+                break;
+
+            case ORM_BACKBUFFER:
+                surface->get_drawable_size = get_drawable_size_backbuffer;
+                break;
+
+            default:
+                ERR("Unhandled offscreen rendering mode %#x.\n", wined3d_settings.offscreen_rendering_mode);
+                return;
+        }
+    }
+
+    surface->swapchain = swapchain;
+    surface_update_draw_binding(surface);
+}
+
+void surface_set_container(struct wined3d_surface *surface, struct wined3d_texture *container)
+{
+    TRACE("surface %p, container %p.\n", surface, container);
+
+    if (!surface->swapchain)
+    {
+        switch (wined3d_settings.offscreen_rendering_mode)
+        {
+            case ORM_FBO:
+                surface->get_drawable_size = get_drawable_size_fbo;
+                break;
+
+            case ORM_BACKBUFFER:
+                surface->get_drawable_size = get_drawable_size_backbuffer;
+                break;
+
+            default:
+                ERR("Unhandled offscreen rendering mode %#x.\n", wined3d_settings.offscreen_rendering_mode);
+                return;
+        }
+    }
+
+    surface->container = container;
+    surface_update_draw_binding(surface);
+}
+
+struct blt_info
+{
+    GLenum binding;
+    GLenum bind_target;
+    enum tex_types tex_type;
+    GLfloat coords[4][3];
+};
+
+struct float_rect
+{
+    float l;
+    float t;
+    float r;
+    float b;
+};
+
+static inline void cube_coords_float(const RECT *r, UINT w, UINT h, struct float_rect *f)
+{
+    f->l = ((r->left * 2.0f) / w) - 1.0f;
+    f->t = ((r->top * 2.0f) / h) - 1.0f;
+    f->r = ((r->right * 2.0f) / w) - 1.0f;
+    f->b = ((r->bottom * 2.0f) / h) - 1.0f;
+}
+
+static void surface_get_blt_info(GLenum target, const RECT *rect, GLsizei w, GLsizei h, struct blt_info *info)
+{
+    GLfloat (*coords)[3] = info->coords;
+    struct float_rect f;
+
+    switch (target)
+    {
+        default:
+            FIXME("Unsupported texture target %#x\n", target);
+            /* Fall back to GL_TEXTURE_2D */
+        case GL_TEXTURE_2D:
+            info->binding = GL_TEXTURE_BINDING_2D;
+            info->bind_target = GL_TEXTURE_2D;
+            info->tex_type = tex_2d;
+            coords[0][0] = (float)rect->left / w;
+            coords[0][1] = (float)rect->top / h;
+            coords[0][2] = 0.0f;
+
+            coords[1][0] = (float)rect->right / w;
+            coords[1][1] = (float)rect->top / h;
+            coords[1][2] = 0.0f;
+
+            coords[2][0] = (float)rect->left / w;
+            coords[2][1] = (float)rect->bottom / h;
+            coords[2][2] = 0.0f;
+
+            coords[3][0] = (float)rect->right / w;
+            coords[3][1] = (float)rect->bottom / h;
+            coords[3][2] = 0.0f;
+            break;
+
+        case GL_TEXTURE_RECTANGLE_ARB:
+            info->binding = GL_TEXTURE_BINDING_RECTANGLE_ARB;
+            info->bind_target = GL_TEXTURE_RECTANGLE_ARB;
+            info->tex_type = tex_rect;
+            coords[0][0] = rect->left;  coords[0][1] = rect->top;       coords[0][2] = 0.0f;
+            coords[1][0] = rect->right; coords[1][1] = rect->top;       coords[1][2] = 0.0f;
+            coords[2][0] = rect->left;  coords[2][1] = rect->bottom;    coords[2][2] = 0.0f;
+            coords[3][0] = rect->right; coords[3][1] = rect->bottom;    coords[3][2] = 0.0f;
+            break;
+
+        case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+            info->binding = GL_TEXTURE_BINDING_CUBE_MAP_ARB;
+            info->bind_target = GL_TEXTURE_CUBE_MAP_ARB;
+            info->tex_type = tex_cube;
+            cube_coords_float(rect, w, h, &f);
+
+            coords[0][0] =  1.0f;   coords[0][1] = -f.t;   coords[0][2] = -f.l;
+            coords[1][0] =  1.0f;   coords[1][1] = -f.t;   coords[1][2] = -f.r;
+            coords[2][0] =  1.0f;   coords[2][1] = -f.b;   coords[2][2] = -f.l;
+            coords[3][0] =  1.0f;   coords[3][1] = -f.b;   coords[3][2] = -f.r;
+            break;
+
+        case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+            info->binding = GL_TEXTURE_BINDING_CUBE_MAP_ARB;
+            info->bind_target = GL_TEXTURE_CUBE_MAP_ARB;
+            info->tex_type = tex_cube;
+            cube_coords_float(rect, w, h, &f);
+
+            coords[0][0] = -1.0f;   coords[0][1] = -f.t;   coords[0][2] = f.l;
+            coords[1][0] = -1.0f;   coords[1][1] = -f.t;   coords[1][2] = f.r;
+            coords[2][0] = -1.0f;   coords[2][1] = -f.b;   coords[2][2] = f.l;
+            coords[3][0] = -1.0f;   coords[3][1] = -f.b;   coords[3][2] = f.r;
+            break;
+
+        case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+            info->binding = GL_TEXTURE_BINDING_CUBE_MAP_ARB;
+            info->bind_target = GL_TEXTURE_CUBE_MAP_ARB;
+            info->tex_type = tex_cube;
+            cube_coords_float(rect, w, h, &f);
+
+            coords[0][0] = f.l;   coords[0][1] =  1.0f;   coords[0][2] = f.t;
+            coords[1][0] = f.r;   coords[1][1] =  1.0f;   coords[1][2] = f.t;
+            coords[2][0] = f.l;   coords[2][1] =  1.0f;   coords[2][2] = f.b;
+            coords[3][0] = f.r;   coords[3][1] =  1.0f;   coords[3][2] = f.b;
+            break;
+
+        case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+            info->binding = GL_TEXTURE_BINDING_CUBE_MAP_ARB;
+            info->bind_target = GL_TEXTURE_CUBE_MAP_ARB;
+            info->tex_type = tex_cube;
+            cube_coords_float(rect, w, h, &f);
+
+            coords[0][0] = f.l;   coords[0][1] = -1.0f;   coords[0][2] = -f.t;
+            coords[1][0] = f.r;   coords[1][1] = -1.0f;   coords[1][2] = -f.t;
+            coords[2][0] = f.l;   coords[2][1] = -1.0f;   coords[2][2] = -f.b;
+            coords[3][0] = f.r;   coords[3][1] = -1.0f;   coords[3][2] = -f.b;
+            break;
+
+        case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+            info->binding = GL_TEXTURE_BINDING_CUBE_MAP_ARB;
+            info->bind_target = GL_TEXTURE_CUBE_MAP_ARB;
+            info->tex_type = tex_cube;
+            cube_coords_float(rect, w, h, &f);
+
+            coords[0][0] = f.l;   coords[0][1] = -f.t;   coords[0][2] =  1.0f;
+            coords[1][0] = f.r;   coords[1][1] = -f.t;   coords[1][2] =  1.0f;
+            coords[2][0] = f.l;   coords[2][1] = -f.b;   coords[2][2] =  1.0f;
+            coords[3][0] = f.r;   coords[3][1] = -f.b;   coords[3][2] =  1.0f;
+            break;
+
+        case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+            info->binding = GL_TEXTURE_BINDING_CUBE_MAP_ARB;
+            info->bind_target = GL_TEXTURE_CUBE_MAP_ARB;
+            info->tex_type = tex_cube;
+            cube_coords_float(rect, w, h, &f);
+
+            coords[0][0] = -f.l;   coords[0][1] = -f.t;   coords[0][2] = -1.0f;
+            coords[1][0] = -f.r;   coords[1][1] = -f.t;   coords[1][2] = -1.0f;
+            coords[2][0] = -f.l;   coords[2][1] = -f.b;   coords[2][2] = -1.0f;
+            coords[3][0] = -f.r;   coords[3][1] = -f.b;   coords[3][2] = -1.0f;
+            break;
+    }
+}
+
+static void surface_get_rect(const struct wined3d_surface *surface, const RECT *rect_in, RECT *rect_out)
+{
+    if (rect_in)
+        *rect_out = *rect_in;
+    else
+    {
+        rect_out->left = 0;
+        rect_out->top = 0;
+        rect_out->right = surface->resource.width;
+        rect_out->bottom = surface->resource.height;
+    }
+}
+
+/* Context activation is done by the caller. */
+void draw_textured_quad(const struct wined3d_surface *src_surface, struct wined3d_context *context,
+        const RECT *src_rect, const RECT *dst_rect, enum wined3d_texture_filter_type filter)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    struct blt_info info;
+
+    surface_get_blt_info(src_surface->texture_target, src_rect, src_surface->pow2Width, src_surface->pow2Height, &info);
+
+    gl_info->gl_ops.gl.p_glEnable(info.bind_target);
+    checkGLcall("glEnable(bind_target)");
+
+    context_bind_texture(context, info.bind_target, src_surface->texture_name);
+
+    /* Filtering for StretchRect */
+    gl_info->gl_ops.gl.p_glTexParameteri(info.bind_target, GL_TEXTURE_MAG_FILTER,
+            wined3d_gl_mag_filter(magLookup, filter));
+    checkGLcall("glTexParameteri");
+    gl_info->gl_ops.gl.p_glTexParameteri(info.bind_target, GL_TEXTURE_MIN_FILTER,
+            wined3d_gl_min_mip_filter(minMipLookup, filter, WINED3D_TEXF_NONE));
+    checkGLcall("glTexParameteri");
+    gl_info->gl_ops.gl.p_glTexParameteri(info.bind_target, GL_TEXTURE_WRAP_S, GL_CLAMP);
+    gl_info->gl_ops.gl.p_glTexParameteri(info.bind_target, GL_TEXTURE_WRAP_T, GL_CLAMP);
+    if (context->gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
+        gl_info->gl_ops.gl.p_glTexParameteri(info.bind_target, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
+    gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+    checkGLcall("glTexEnvi");
+
+    /* Draw a quad */
+    gl_info->gl_ops.gl.p_glBegin(GL_TRIANGLE_STRIP);
+    gl_info->gl_ops.gl.p_glTexCoord3fv(info.coords[0]);
+    gl_info->gl_ops.gl.p_glVertex2i(dst_rect->left, dst_rect->top);
+
+    gl_info->gl_ops.gl.p_glTexCoord3fv(info.coords[1]);
+    gl_info->gl_ops.gl.p_glVertex2i(dst_rect->right, dst_rect->top);
+
+    gl_info->gl_ops.gl.p_glTexCoord3fv(info.coords[2]);
+    gl_info->gl_ops.gl.p_glVertex2i(dst_rect->left, dst_rect->bottom);
+
+    gl_info->gl_ops.gl.p_glTexCoord3fv(info.coords[3]);
+    gl_info->gl_ops.gl.p_glVertex2i(dst_rect->right, dst_rect->bottom);
+    gl_info->gl_ops.gl.p_glEnd();
+
+    /* Unbind the texture */
+    context_bind_texture(context, info.bind_target, 0);
+
+    /* We changed the filtering settings on the texture. Inform the
+     * container about this to get the filters reset properly next draw. */
+    if (src_surface->container)
+    {
+        struct wined3d_texture *texture = src_surface->container;
+        texture->texture_rgb.states[WINED3DTEXSTA_MAGFILTER] = WINED3D_TEXF_POINT;
+        texture->texture_rgb.states[WINED3DTEXSTA_MINFILTER] = WINED3D_TEXF_POINT;
+        texture->texture_rgb.states[WINED3DTEXSTA_MIPFILTER] = WINED3D_TEXF_NONE;
+        texture->texture_rgb.states[WINED3DTEXSTA_SRGBTEXTURE] = FALSE;
+    }
+}
+
+/* Works correctly only for <= 4 bpp formats. */
+static void get_color_masks(const struct wined3d_format *format, DWORD *masks)
+{
+    masks[0] = ((1 << format->red_size) - 1) << format->red_offset;
+    masks[1] = ((1 << format->green_size) - 1) << format->green_offset;
+    masks[2] = ((1 << format->blue_size) - 1) << format->blue_offset;
+}
+
+static HRESULT surface_create_dib_section(struct wined3d_surface *surface)
+{
+    const struct wined3d_format *format = surface->resource.format;
+    SYSTEM_INFO sysInfo;
+    BITMAPINFO *b_info;
+    int extraline = 0;
+    DWORD *masks;
+
+    TRACE("surface %p.\n", surface);
+
+    if (!(format->flags & WINED3DFMT_FLAG_GETDC))
+    {
+        WARN("Cannot use GetDC on a %s surface.\n", debug_d3dformat(format->id));
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    switch (format->byte_count)
+    {
+        case 2:
+        case 4:
+            /* Allocate extra space to store the RGB bit masks. */
+            b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD));
+            break;
+
+        case 3:
+            b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER));
+            break;
+
+        default:
+            /* Allocate extra space for a palette. */
+            b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+                    sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (1 << (format->byte_count * 8)));
+            break;
+    }
+
+    if (!b_info)
+        return E_OUTOFMEMORY;
+
+    /* Some applications access the surface in via DWORDs, and do not take
+     * the necessary care at the end of the surface. So we need at least
+     * 4 extra bytes at the end of the surface. Check against the page size,
+     * if the last page used for the surface has at least 4 spare bytes we're
+     * safe, otherwise add an extra line to the DIB section. */
+    GetSystemInfo(&sysInfo);
+    if( ((surface->resource.size + 3) % sysInfo.dwPageSize) < 4)
+    {
+        extraline = 1;
+        TRACE("Adding an extra line to the DIB section.\n");
+    }
+
+    b_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+    /* TODO: Is there a nicer way to force a specific alignment? (8 byte for ddraw) */
+    b_info->bmiHeader.biWidth = wined3d_surface_get_pitch(surface) / format->byte_count;
+    b_info->bmiHeader.biHeight = 0 - surface->resource.height - extraline;
+    b_info->bmiHeader.biSizeImage = (surface->resource.height + extraline)
+            * wined3d_surface_get_pitch(surface);
+    b_info->bmiHeader.biPlanes = 1;
+    b_info->bmiHeader.biBitCount = format->byte_count * 8;
+
+    b_info->bmiHeader.biXPelsPerMeter = 0;
+    b_info->bmiHeader.biYPelsPerMeter = 0;
+    b_info->bmiHeader.biClrUsed = 0;
+    b_info->bmiHeader.biClrImportant = 0;
+
+    /* Get the bit masks */
+    masks = (DWORD *)b_info->bmiColors;
+    switch (surface->resource.format->id)
+    {
+        case WINED3DFMT_B8G8R8_UNORM:
+            b_info->bmiHeader.biCompression = BI_RGB;
+            break;
+
+        case WINED3DFMT_B5G5R5X1_UNORM:
+        case WINED3DFMT_B5G5R5A1_UNORM:
+        case WINED3DFMT_B4G4R4A4_UNORM:
+        case WINED3DFMT_B4G4R4X4_UNORM:
+        case WINED3DFMT_B2G3R3_UNORM:
+        case WINED3DFMT_B2G3R3A8_UNORM:
+        case WINED3DFMT_R10G10B10A2_UNORM:
+        case WINED3DFMT_R8G8B8A8_UNORM:
+        case WINED3DFMT_R8G8B8X8_UNORM:
+        case WINED3DFMT_B10G10R10A2_UNORM:
+        case WINED3DFMT_B5G6R5_UNORM:
+        case WINED3DFMT_R16G16B16A16_UNORM:
+            b_info->bmiHeader.biCompression = BI_BITFIELDS;
+            get_color_masks(format, masks);
+            break;
+
+        default:
+            /* Don't know palette */
+            b_info->bmiHeader.biCompression = BI_RGB;
+            break;
+    }
+
+    TRACE("Creating a DIB section with size %dx%dx%d, size=%d.\n",
+            b_info->bmiHeader.biWidth, b_info->bmiHeader.biHeight,
+            b_info->bmiHeader.biBitCount, b_info->bmiHeader.biSizeImage);
+    surface->dib.DIBsection = CreateDIBSection(0, b_info, DIB_RGB_COLORS, &surface->dib.bitmap_data, 0, 0);
+
+    if (!surface->dib.DIBsection)
+    {
+        ERR("Failed to create DIB section.\n");
+        HeapFree(GetProcessHeap(), 0, b_info);
+        return HRESULT_FROM_WIN32(GetLastError());
+    }
+
+    TRACE("DIBSection at %p.\n", surface->dib.bitmap_data);
+    /* Copy the existing surface to the dib section. */
+    if (surface->resource.allocatedMemory)
+    {
+        memcpy(surface->dib.bitmap_data, surface->resource.allocatedMemory,
+                surface->resource.height * wined3d_surface_get_pitch(surface));
+    }
+    else
+    {
+        /* This is to make maps read the GL texture although memory is allocated. */
+        surface->flags &= ~SFLAG_INSYSMEM;
+    }
+    surface->dib.bitmap_size = b_info->bmiHeader.biSizeImage;
+
+    HeapFree(GetProcessHeap(), 0, b_info);
+
+    /* Now allocate a DC. */
+    surface->hDC = CreateCompatibleDC(0);
+    SelectObject(surface->hDC, surface->dib.DIBsection);
+    TRACE("Using wined3d palette %p.\n", surface->palette);
+    SelectPalette(surface->hDC, surface->palette ? surface->palette->hpal : 0, FALSE);
+
+    surface->flags |= SFLAG_DIBSECTION;
+
+    return WINED3D_OK;
+}
+
+static BOOL surface_need_pbo(const struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info)
+{
+    if (surface->resource.pool == WINED3D_POOL_SYSTEM_MEM)
+        return FALSE;
+    if (!(surface->flags & SFLAG_DYNLOCK))
+        return FALSE;
+    if (surface->flags & (SFLAG_CONVERTED | SFLAG_NONPOW2 | SFLAG_PIN_SYSMEM))
+        return FALSE;
+    if (!gl_info->supported[ARB_PIXEL_BUFFER_OBJECT])
+        return FALSE;
+
+    return TRUE;
+}
+
+static void surface_load_pbo(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info)
+{
+    struct wined3d_context *context;
+    GLenum error;
+
+    context = context_acquire(surface->resource.device, NULL);
+
+    GL_EXTCALL(glGenBuffersARB(1, &surface->pbo));
+    error = gl_info->gl_ops.gl.p_glGetError();
+    if (!surface->pbo || error != GL_NO_ERROR)
+        ERR("Failed to create a PBO with error %s (%#x).\n", debug_glerror(error), error);
+
+    TRACE("Binding PBO %u.\n", surface->pbo);
+
+    GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, surface->pbo));
+    checkGLcall("glBindBufferARB");
+
+    GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, surface->resource.size + 4,
+            surface->resource.allocatedMemory, GL_STREAM_DRAW_ARB));
+    checkGLcall("glBufferDataARB");
+
+    GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
+    checkGLcall("glBindBufferARB");
+
+    /* We don't need the system memory anymore and we can't even use it for PBOs. */
+    if (!(surface->flags & SFLAG_CLIENT))
+    {
+        HeapFree(GetProcessHeap(), 0, surface->resource.heapMemory);
+        surface->resource.heapMemory = NULL;
+    }
+    surface->resource.allocatedMemory = NULL;
+    surface->flags |= SFLAG_PBO;
+    context_release(context);
+}
+
+#ifdef VBOX_WITH_WDDM
+static HRESULT d3dfmt_get_conv(const struct wined3d_surface *surface, BOOL need_alpha_ck, BOOL use_texturing,
+        struct wined3d_format *format, enum wined3d_conversion_type *conversion_type);
+
+void surface_setup_location_onopen(struct wined3d_surface *surface)
+{
+    struct wined3d_device *device = surface->resource.device;
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    DWORD alloc_flag = SFLAG_ALLOCATED;
+//    DWORD alloc_flag = srgb ? SFLAG_SRGBALLOCATED : SFLAG_ALLOCATED;
+    enum wined3d_conversion_type convert;
+    struct wined3d_format format;
+
+
+    d3dfmt_get_conv(surface, TRUE, TRUE, &format, &convert);
+    if (convert != WINED3D_CT_NONE || format.convert)
+        surface->flags |= SFLAG_CONVERTED;
+    else surface->flags &= ~SFLAG_CONVERTED;
+
+    if(surface->container)
+    {
+        struct wined3d_context *context = context_acquire(device, NULL);
+        pglChromiumParameteriCR(GL_RCUSAGE_TEXTURE_SET_CR, (GLuint)VBOXSHRC_GET_SHAREHANDLE(surface));
+        context_release(context);
+
+    }
+    /* else -> all should be already set in texture init,
+     * which actually calls the current routine for each of texture's surfaces
+     * for setting up their state */
+
+    surface->flags |= alloc_flag;
+    surface->texture_name = (GLuint)VBOXSHRC_GET_SHAREHANDLE(surface);
+
+    surface_modify_location(surface, SFLAG_INTEXTURE, TRUE);
+}
+#endif
+
+static void surface_prepare_system_memory(struct wined3d_surface *surface)
+{
+    const struct wined3d_gl_info *gl_info = &surface->resource.device->adapter->gl_info;
+
+    TRACE("surface %p.\n", surface);
+
+    if (!(surface->flags & SFLAG_PBO) && surface_need_pbo(surface, gl_info))
+        surface_load_pbo(surface, gl_info);
+    else if (!(surface->resource.allocatedMemory || surface->flags & SFLAG_PBO))
+    {
+        /* Whatever surface we have, make sure that there is memory allocated
+         * for the downloaded copy, or a PBO to map. */
+        if (!surface->resource.heapMemory)
+            surface->resource.heapMemory = HeapAlloc(GetProcessHeap(), 0, surface->resource.size + RESOURCE_ALIGNMENT);
+
+        surface->resource.allocatedMemory = (BYTE *)(((ULONG_PTR)surface->resource.heapMemory
+                + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1));
+
+        if (surface->flags & SFLAG_INSYSMEM)
+            ERR("Surface without memory or PBO has SFLAG_INSYSMEM set.\n");
+    }
+}
+
+static void surface_evict_sysmem(struct wined3d_surface *surface)
+{
+    if (surface->resource.map_count || (surface->flags & SFLAG_DONOTFREE))
+        return;
+
+    HeapFree(GetProcessHeap(), 0, surface->resource.heapMemory);
+    surface->resource.allocatedMemory = NULL;
+    surface->resource.heapMemory = NULL;
+    surface_modify_location(surface, SFLAG_INSYSMEM, FALSE);
+}
+
+/* Context activation is done by the caller. */
+static void surface_bind(struct wined3d_surface *surface, struct wined3d_context *context, BOOL srgb)
+{
+    TRACE("surface %p, context %p, srgb %#x.\n", surface, context, srgb);
+
+    if (surface->container)
+    {
+        struct wined3d_texture *texture = surface->container;
+
+        TRACE("Passing to container (%p).\n", texture);
+        texture->texture_ops->texture_bind(texture, context, srgb);
+    }
+    else
+    {
+        const struct wined3d_gl_info *gl_info = context->gl_info;
+
+        if (surface->texture_level)
+        {
+            ERR("Standalone surface %p is non-zero texture level %u.\n",
+                    surface, surface->texture_level);
+        }
+
+        if (srgb)
+            ERR("Trying to bind standalone surface %p as sRGB.\n", surface);
+
+        if (!surface->texture_name)
+        {
+#ifdef VBOX_WITH_WDDM
+            if (VBOXSHRC_IS_SHARED_OPENED(surface))
+            {
+                struct wined3d_gl_info *gl_info = &surface->resource.device->adapter->gl_info;
+                ERR("should not be here!");
+                surface->texture_name = (GLuint)VBOXSHRC_GET_SHAREHANDLE(surface);
+                Assert(surface->texture_name);
+                pglChromiumParameteriCR(GL_RCUSAGE_TEXTURE_SET_CR, surface->texture_name);
+            }
+            else
+#endif
+            {
+            gl_info->gl_ops.gl.p_glGenTextures(1, &surface->texture_name);
+            checkGLcall("glGenTextures");
+
+            TRACE("Surface %p given name %u.\n", surface, surface->texture_name);
+
+            context_bind_texture(context, surface->texture_target, surface->texture_name);
+            gl_info->gl_ops.gl.p_glTexParameteri(surface->texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+            gl_info->gl_ops.gl.p_glTexParameteri(surface->texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+            gl_info->gl_ops.gl.p_glTexParameteri(surface->texture_target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+            gl_info->gl_ops.gl.p_glTexParameteri(surface->texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+            gl_info->gl_ops.gl.p_glTexParameteri(surface->texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+            checkGLcall("glTexParameteri");
+
+#ifdef VBOX_WITH_WDDM
+            if (VBOXSHRC_IS_SHARED(surface))
+            {
+                VBOXSHRC_SET_SHAREHANDLE(surface, surface->texture_name);
+            }
+#endif
+            }
+        }
+        else
+        {
+            context_bind_texture(context, surface->texture_target, surface->texture_name);
+        }
+
+    }
+}
+
+/* Context activation is done by the caller. */
+static void surface_bind_and_dirtify(struct wined3d_surface *surface,
+        struct wined3d_context *context, BOOL srgb)
+{
+    struct wined3d_device *device = surface->resource.device;
+    DWORD active_sampler;
+
+    /* We don't need a specific texture unit, but after binding the texture
+     * the current unit is dirty. Read the unit back instead of switching to
+     * 0, this avoids messing around with the state manager's GL states. The
+     * current texture unit should always be a valid one.
+     *
+     * To be more specific, this is tricky because we can implicitly be
+     * called from sampler() in state.c. This means we can't touch anything
+     * other than whatever happens to be the currently active texture, or we
+     * would risk marking already applied sampler states dirty again. */
+    active_sampler = device->rev_tex_unit_map[context->active_texture];
+
+#if 0 //def DEBUG_misha
+    {
+        GLint active_texture=GL_TEXTURE0_ARB;
+        glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);
+        Assert(active_texture - GL_TEXTURE0_ARB == context->active_texture);
+    }
+#endif
+
+    if (active_sampler != WINED3D_UNMAPPED_STAGE)
+        device_invalidate_state(device, STATE_SAMPLER(active_sampler));
+    surface_bind(surface, context, srgb);
+}
+
+static void surface_force_reload(struct wined3d_surface *surface)
+{
+    surface->flags &= ~(SFLAG_ALLOCATED | SFLAG_SRGBALLOCATED);
+}
+
+static void surface_release_client_storage(struct wined3d_surface *surface)
+{
+    struct wined3d_context *context = context_acquire(surface->resource.device, NULL);
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
+    if (surface->texture_name)
+    {
+        surface_bind_and_dirtify(surface, context, FALSE);
+        gl_info->gl_ops.gl.p_glTexImage2D(surface->texture_target, surface->texture_level,
+                GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+    }
+    if (surface->texture_name_srgb)
+    {
+        surface_bind_and_dirtify(surface, context, TRUE);
+        gl_info->gl_ops.gl.p_glTexImage2D(surface->texture_target, surface->texture_level,
+                GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+    }
+    gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
+
+    context_release(context);
+
+    surface_modify_location(surface, SFLAG_INSRGBTEX, FALSE);
+    surface_modify_location(surface, SFLAG_INTEXTURE, FALSE);
+    surface_force_reload(surface);
+}
+
+static HRESULT surface_private_setup(struct wined3d_surface *surface)
+{
+    /* TODO: Check against the maximum texture sizes supported by the video card. */
+    const struct wined3d_gl_info *gl_info = &surface->resource.device->adapter->gl_info;
+    unsigned int pow2Width, pow2Height;
+
+    TRACE("surface %p.\n", surface);
+
+    surface->texture_name = 0;
+    surface->texture_target = GL_TEXTURE_2D;
+
+    /* Non-power2 support */
+    if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] || gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT])
+    {
+        pow2Width = surface->resource.width;
+        pow2Height = surface->resource.height;
+    }
+    else
+    {
+        /* Find the nearest pow2 match */
+        pow2Width = pow2Height = 1;
+        while (pow2Width < surface->resource.width)
+            pow2Width <<= 1;
+        while (pow2Height < surface->resource.height)
+            pow2Height <<= 1;
+    }
+    surface->pow2Width = pow2Width;
+    surface->pow2Height = pow2Height;
+
+    if (pow2Width > surface->resource.width || pow2Height > surface->resource.height)
+    {
+        /* TODO: Add support for non power two compressed textures. */
+        if (surface->resource.format->flags & WINED3DFMT_FLAG_COMPRESSED)
+        {
+            FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
+                  surface, surface->resource.width, surface->resource.height);
+            return WINED3DERR_NOTAVAILABLE;
+        }
+    }
+
+    if (pow2Width != surface->resource.width
+            || pow2Height != surface->resource.height)
+    {
+        surface->flags |= SFLAG_NONPOW2;
+    }
+
+    if ((surface->pow2Width > gl_info->limits.texture_size || surface->pow2Height > gl_info->limits.texture_size)
+            && !(surface->resource.usage & (WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_DEPTHSTENCIL)))
+    {
+        /* One of three options:
+         * 1: Do the same as we do with NPOT and scale the texture, (any
+         *    texture ops would require the texture to be scaled which is
+         *    potentially slow)
+         * 2: Set the texture to the maximum size (bad idea).
+         * 3: WARN and return WINED3DERR_NOTAVAILABLE;
+         * 4: Create the surface, but allow it to be used only for DirectDraw
+         *    Blts. Some apps (e.g. Swat 3) create textures with a Height of
+         *    16 and a Width > 3000 and blt 16x16 letter areas from them to
+         *    the render target. */
+        if (surface->resource.pool == WINED3D_POOL_DEFAULT || surface->resource.pool == WINED3D_POOL_MANAGED)
+        {
+            WARN("Unable to allocate a surface which exceeds the maximum OpenGL texture size.\n");
+            return WINED3DERR_NOTAVAILABLE;
+        }
+
+        /* We should never use this surface in combination with OpenGL! */
+        TRACE("Creating an oversized surface: %ux%u.\n",
+                surface->pow2Width, surface->pow2Height);
+    }
+    else
+    {
+        /* Don't use ARB_TEXTURE_RECTANGLE in case the surface format is P8
+         * and EXT_PALETTED_TEXTURE is used in combination with texture
+         * uploads (RTL_READTEX/RTL_TEXTEX). The reason is that
+         * EXT_PALETTED_TEXTURE doesn't work in combination with
+         * ARB_TEXTURE_RECTANGLE. */
+        if (surface->flags & SFLAG_NONPOW2 && gl_info->supported[ARB_TEXTURE_RECTANGLE]
+                && !(surface->resource.format->id == WINED3DFMT_P8_UINT
+                && gl_info->supported[EXT_PALETTED_TEXTURE]
+                && wined3d_settings.rendertargetlock_mode == RTL_READTEX))
+        {
+            surface->texture_target = GL_TEXTURE_RECTANGLE_ARB;
+            surface->pow2Width = surface->resource.width;
+            surface->pow2Height = surface->resource.height;
+            surface->flags &= ~(SFLAG_NONPOW2 | SFLAG_NORMCOORD);
+        }
+    }
+
+    switch (wined3d_settings.offscreen_rendering_mode)
+    {
+        case ORM_FBO:
+            surface->get_drawable_size = get_drawable_size_fbo;
+            break;
+
+        case ORM_BACKBUFFER:
+            surface->get_drawable_size = get_drawable_size_backbuffer;
+            break;
+
+        default:
+            ERR("Unhandled offscreen rendering mode %#x.\n", wined3d_settings.offscreen_rendering_mode);
+            return WINED3DERR_INVALIDCALL;
+    }
+
+    if (surface->resource.usage & WINED3DUSAGE_DEPTHSTENCIL)
+        surface->flags |= SFLAG_DISCARDED;
+
+    return WINED3D_OK;
+}
+
+static void surface_realize_palette(struct wined3d_surface *surface)
+{
+    struct wined3d_palette *palette = surface->palette;
+
+    TRACE("surface %p.\n", surface);
+
+    if (!palette) return;
+
+    if (surface->resource.format->id == WINED3DFMT_P8_UINT
+            || surface->resource.format->id == WINED3DFMT_P8_UINT_A8_UNORM)
+    {
+        if (surface->resource.usage & WINED3DUSAGE_RENDERTARGET)
+        {
+            /* Make sure the texture is up to date. This call doesn't do
+             * anything if the texture is already up to date. */
+            surface_load_location(surface, SFLAG_INTEXTURE, NULL);
+
+            /* We want to force a palette refresh, so mark the drawable as not being up to date */
+            if (!surface_is_offscreen(surface))
+                surface_modify_location(surface, SFLAG_INDRAWABLE, FALSE);
+        }
+        else
+        {
+            if (!(surface->flags & SFLAG_INSYSMEM))
+            {
+                TRACE("Palette changed with surface that does not have an up to date system memory copy.\n");
+                surface_load_location(surface, SFLAG_INSYSMEM, NULL);
+            }
+            surface_modify_location(surface, SFLAG_INSYSMEM, TRUE);
+        }
+    }
+
+    if (surface->flags & SFLAG_DIBSECTION)
+    {
+        RGBQUAD col[256];
+        unsigned int i;
+
+        TRACE("Updating the DC's palette.\n");
+
+        for (i = 0; i < 256; ++i)
+        {
+            col[i].rgbRed   = palette->palents[i].peRed;
+            col[i].rgbGreen = palette->palents[i].peGreen;
+            col[i].rgbBlue  = palette->palents[i].peBlue;
+            col[i].rgbReserved = 0;
+        }
+        SetDIBColorTable(surface->hDC, 0, 256, col);
+    }
+
+    /* Propagate the changes to the drawable when we have a palette. */
+    if (surface->resource.usage & WINED3DUSAGE_RENDERTARGET)
+        surface_load_location(surface, surface->draw_binding, NULL);
+}
+
+static HRESULT surface_draw_overlay(struct wined3d_surface *surface)
+{
+    HRESULT hr;
+
+    /* If there's no destination surface there is nothing to do. */
+    if (!surface->overlay_dest)
+        return WINED3D_OK;
+
+    /* Blt calls ModifyLocation on the dest surface, which in turn calls
+     * DrawOverlay to update the overlay. Prevent an endless recursion. */
+    if (surface->overlay_dest->flags & SFLAG_INOVERLAYDRAW)
+        return WINED3D_OK;
+
+    surface->overlay_dest->flags |= SFLAG_INOVERLAYDRAW;
+    hr = wined3d_surface_blt(surface->overlay_dest, &surface->overlay_destrect, surface,
+            &surface->overlay_srcrect, WINEDDBLT_WAIT, NULL, WINED3D_TEXF_LINEAR);
+    surface->overlay_dest->flags &= ~SFLAG_INOVERLAYDRAW;
+
+    return hr;
+}
+
+static void surface_map(struct wined3d_surface *surface, const RECT *rect, DWORD flags)
+{
+    struct wined3d_device *device = surface->resource.device;
+    const RECT *pass_rect = rect;
+
+    TRACE("surface %p, rect %s, flags %#x.\n",
+            surface, wine_dbgstr_rect(rect), flags);
+
+    if (flags & WINED3D_MAP_DISCARD)
+    {
+        TRACE("WINED3D_MAP_DISCARD flag passed, marking SYSMEM as up to date.\n");
+        surface_prepare_system_memory(surface);
+        surface_modify_location(surface, SFLAG_INSYSMEM, TRUE);
+    }
+    else
+    {
+        if (surface->resource.usage & WINED3DUSAGE_DYNAMIC)
+            WARN_(d3d_perf)("Mapping a dynamic surface without WINED3D_MAP_DISCARD.\n");
+
+        /* surface_load_location() does not check if the rectangle specifies
+         * the full surface. Most callers don't need that, so do it here. */
+        if (rect && !rect->top && !rect->left
+                && rect->right == surface->resource.width
+                && rect->bottom == surface->resource.height)
+            pass_rect = NULL;
+        surface_load_location(surface, SFLAG_INSYSMEM, pass_rect);
+    }
+
+    if (surface->flags & SFLAG_PBO)
+    {
+        const struct wined3d_gl_info *gl_info;
+        struct wined3d_context *context;
+
+        context = context_acquire(device, NULL);
+        gl_info = context->gl_info;
+
+        GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, surface->pbo));
+        checkGLcall("glBindBufferARB");
+
+        /* This shouldn't happen but could occur if some other function
+         * didn't handle the PBO properly. */
+        if (surface->resource.allocatedMemory)
+            ERR("The surface already has PBO memory allocated.\n");
+
+        surface->resource.allocatedMemory = GL_EXTCALL(glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_READ_WRITE_ARB));
+        checkGLcall("glMapBufferARB");
+
+        /* Make sure the PBO isn't set anymore in order not to break non-PBO
+         * calls. */
+        GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
+        checkGLcall("glBindBufferARB");
+
+        context_release(context);
+    }
+
+    if (!(flags & (WINED3D_MAP_NO_DIRTY_UPDATE | WINED3D_MAP_READONLY)))
+    {
+        if (!rect)
+            surface_add_dirty_rect(surface, NULL);
+        else
+        {
+            struct wined3d_box b;
+
+            b.left = rect->left;
+            b.top = rect->top;
+            b.right = rect->right;
+            b.bottom = rect->bottom;
+            b.front = 0;
+            b.back = 1;
+            surface_add_dirty_rect(surface, &b);
+        }
+    }
+}
+
+static void surface_unmap(struct wined3d_surface *surface)
+{
+    struct wined3d_device *device = surface->resource.device;
+    BOOL fullsurface;
+
+    TRACE("surface %p.\n", surface);
+
+    memset(&surface->lockedRect, 0, sizeof(surface->lockedRect));
+
+    if (surface->flags & SFLAG_PBO)
+    {
+        const struct wined3d_gl_info *gl_info;
+        struct wined3d_context *context;
+
+        TRACE("Freeing PBO memory.\n");
+
+        context = context_acquire(device, NULL);
+        gl_info = context->gl_info;
+
+        GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, surface->pbo));
+        GL_EXTCALL(glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB));
+        GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
+        checkGLcall("glUnmapBufferARB");
+        context_release(context);
+
+        surface->resource.allocatedMemory = NULL;
+    }
+
+    TRACE("dirtyfied %u.\n", surface->flags & (SFLAG_INDRAWABLE | SFLAG_INTEXTURE) ? 0 : 1);
+
+    if (surface->flags & (SFLAG_INDRAWABLE | SFLAG_INTEXTURE))
+    {
+        TRACE("Not dirtified, nothing to do.\n");
+        goto done;
+    }
+
+    if (surface->swapchain && surface->swapchain->front_buffer == surface)
+    {
+        if (!surface->dirtyRect.left && !surface->dirtyRect.top
+                && surface->dirtyRect.right == surface->resource.width
+                && surface->dirtyRect.bottom == surface->resource.height)
+        {
+            fullsurface = TRUE;
+        }
+        else
+        {
+            /* TODO: Proper partial rectangle tracking. */
+            fullsurface = FALSE;
+            surface->flags |= SFLAG_INSYSMEM;
+        }
+
+        surface_load_location(surface, surface->draw_binding, fullsurface ? NULL : &surface->dirtyRect);
+
+        /* Partial rectangle tracking is not commonly implemented, it is only
+         * done for render targets. INSYSMEM was set before to tell
+         * surface_load_location() where to read the rectangle from.
+         * Indrawable is set because all modifications from the partial
+         * sysmem copy are written back to the drawable, thus the surface is
+         * merged again in the drawable. The sysmem copy is not fully up to
+         * date because only a subrectangle was read in Map(). */
+        if (!fullsurface)
+        {
+            surface_modify_location(surface, surface->draw_binding, TRUE);
+            surface_evict_sysmem(surface);
+        }
+
+        surface->dirtyRect.left = surface->resource.width;
+        surface->dirtyRect.top = surface->resource.height;
+        surface->dirtyRect.right = 0;
+        surface->dirtyRect.bottom = 0;
+    }
+    else if (surface->resource.format->flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))
+    {
+        FIXME("Depth / stencil buffer locking is not implemented.\n");
+    }
+
+done:
+    /* Overlays have to be redrawn manually after changes with the GL implementation */
+    if (surface->overlay_dest)
+        surface_draw_overlay(surface);
+}
+
+static BOOL surface_is_full_rect(const struct wined3d_surface *surface, const RECT *r)
+{
+    if ((r->left && r->right) || abs(r->right - r->left) != surface->resource.width)
+        return FALSE;
+    if ((r->top && r->bottom) || abs(r->bottom - r->top) != surface->resource.height)
+        return FALSE;
+    return TRUE;
+}
+
+static void surface_depth_blt_fbo(const struct wined3d_device *device,
+        struct wined3d_surface *src_surface, DWORD src_location, const RECT *src_rect,
+        struct wined3d_surface *dst_surface, DWORD dst_location, const RECT *dst_rect)
+{
+    const struct wined3d_gl_info *gl_info;
+    struct wined3d_context *context;
+    DWORD src_mask, dst_mask;
+    GLbitfield gl_mask;
+
+    TRACE("device %p\n", device);
+    TRACE("src_surface %p, src_location %s, src_rect %s,\n",
+            src_surface, debug_surflocation(src_location), wine_dbgstr_rect(src_rect));
+    TRACE("dst_surface %p, dst_location %s, dst_rect %s.\n",
+            dst_surface, debug_surflocation(dst_location), wine_dbgstr_rect(dst_rect));
+
+    src_mask = src_surface->resource.format->flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL);
+    dst_mask = dst_surface->resource.format->flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL);
+
+    if (src_mask != dst_mask)
+    {
+        ERR("Incompatible formats %s and %s.\n",
+                debug_d3dformat(src_surface->resource.format->id),
+                debug_d3dformat(dst_surface->resource.format->id));
+        return;
+    }
+
+    if (!src_mask)
+    {
+        ERR("Not a depth / stencil format: %s.\n",
+                debug_d3dformat(src_surface->resource.format->id));
+        return;
+    }
+
+    gl_mask = 0;
+    if (src_mask & WINED3DFMT_FLAG_DEPTH)
+        gl_mask |= GL_DEPTH_BUFFER_BIT;
+    if (src_mask & WINED3DFMT_FLAG_STENCIL)
+        gl_mask |= GL_STENCIL_BUFFER_BIT;
+
+    /* Make sure the locations are up-to-date. Loading the destination
+     * surface isn't required if the entire surface is overwritten. */
+    surface_load_location(src_surface, src_location, NULL);
+    if (!surface_is_full_rect(dst_surface, dst_rect))
+        surface_load_location(dst_surface, dst_location, NULL);
+
+    context = context_acquire(device, NULL);
+    if (!context->valid)
+    {
+        context_release(context);
+        WARN("Invalid context, skipping blit.\n");
+        return;
+    }
+
+    gl_info = context->gl_info;
+
+    context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, NULL, src_surface, src_location);
+    context_check_fbo_status(context, GL_READ_FRAMEBUFFER);
+
+    context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, NULL, dst_surface, dst_location);
+    context_set_draw_buffer(context, GL_NONE);
+    context_check_fbo_status(context, GL_DRAW_FRAMEBUFFER);
+    context_invalidate_state(context, STATE_FRAMEBUFFER);
+
+    if (gl_mask & GL_DEPTH_BUFFER_BIT)
+    {
+        gl_info->gl_ops.gl.p_glDepthMask(GL_TRUE);
+        context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ZWRITEENABLE));
+    }
+    if (gl_mask & GL_STENCIL_BUFFER_BIT)
+    {
+        if (context->gl_info->supported[EXT_STENCIL_TWO_SIDE])
+        {
+            gl_info->gl_ops.gl.p_glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
+            context_invalidate_state(context, STATE_RENDER(WINED3D_RS_TWOSIDEDSTENCILMODE));
+        }
+        gl_info->gl_ops.gl.p_glStencilMask(~0U);
+        context_invalidate_state(context, STATE_RENDER(WINED3D_RS_STENCILWRITEMASK));
+    }
+
+    gl_info->gl_ops.gl.p_glDisable(GL_SCISSOR_TEST);
+    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_SCISSORTESTENABLE));
+
+    gl_info->fbo_ops.glBlitFramebuffer(src_rect->left, src_rect->top, src_rect->right, src_rect->bottom,
+            dst_rect->left, dst_rect->top, dst_rect->right, dst_rect->bottom, gl_mask, GL_NEAREST);
+    checkGLcall("glBlitFramebuffer()");
+
+    if (wined3d_settings.strict_draw_ordering)
+        gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */
+
+    context_release(context);
+}
+
+/* Blit between surface locations. Onscreen on different swapchains is not supported.
+ * Depth / stencil is not supported. */
+static void surface_blt_fbo(const struct wined3d_device *device, enum wined3d_texture_filter_type filter,
+        struct wined3d_surface *src_surface, DWORD src_location, const RECT *src_rect_in,
+        struct wined3d_surface *dst_surface, DWORD dst_location, const RECT *dst_rect_in)
+{
+    const struct wined3d_gl_info *gl_info;
+    struct wined3d_context *context;
+    RECT src_rect, dst_rect;
+    GLenum gl_filter;
+    GLenum buffer;
+
+    TRACE("device %p, filter %s,\n", device, debug_d3dtexturefiltertype(filter));
+    TRACE("src_surface %p, src_location %s, src_rect %s,\n",
+            src_surface, debug_surflocation(src_location), wine_dbgstr_rect(src_rect_in));
+    TRACE("dst_surface %p, dst_location %s, dst_rect %s.\n",
+            dst_surface, debug_surflocation(dst_location), wine_dbgstr_rect(dst_rect_in));
+
+    src_rect = *src_rect_in;
+    dst_rect = *dst_rect_in;
+
+    switch (filter)
+    {
+        case WINED3D_TEXF_LINEAR:
+            gl_filter = GL_LINEAR;
+            break;
+
+        default:
+            FIXME("Unsupported filter mode %s (%#x).\n", debug_d3dtexturefiltertype(filter), filter);
+        case WINED3D_TEXF_NONE:
+        case WINED3D_TEXF_POINT:
+            gl_filter = GL_NEAREST;
+            break;
+    }
+
+    /* Resolve the source surface first if needed. */
+    if (src_location == SFLAG_INRB_MULTISAMPLE
+            && (src_surface->resource.format->id != dst_surface->resource.format->id
+                || abs(src_rect.bottom - src_rect.top) != abs(dst_rect.bottom - dst_rect.top)
+                || abs(src_rect.right - src_rect.left) != abs(dst_rect.right - dst_rect.left)))
+        src_location = SFLAG_INRB_RESOLVED;
+
+    /* Make sure the locations are up-to-date. Loading the destination
+     * surface isn't required if the entire surface is overwritten. (And is
+     * in fact harmful if we're being called by surface_load_location() with
+     * the purpose of loading the destination surface.) */
+    surface_load_location(src_surface, src_location, NULL);
+    if (!surface_is_full_rect(dst_surface, &dst_rect))
+        surface_load_location(dst_surface, dst_location, NULL);
+
+    if (src_location == SFLAG_INDRAWABLE) context = context_acquire(device, src_surface);
+    else if (dst_location == SFLAG_INDRAWABLE) context = context_acquire(device, dst_surface);
+    else context = context_acquire(device, NULL);
+
+    if (!context->valid)
+    {
+        context_release(context);
+        WARN("Invalid context, skipping blit.\n");
+        return;
+    }
+
+    gl_info = context->gl_info;
+
+    if (src_location == SFLAG_INDRAWABLE)
+    {
+        TRACE("Source surface %p is onscreen.\n", src_surface);
+        buffer = surface_get_gl_buffer(src_surface);
+#ifndef VBOX_WINE_WITH_SINGLE_CONTEXT
+        surface_translate_drawable_coords(src_surface, context->win_handle, &src_rect);
+#else
+        surface_translate_drawable_coords(src_surface, context->swapchain->win_handle, &src_rect);
+#endif
+    }
+    else
+    {
+        TRACE("Source surface %p is offscreen.\n", src_surface);
+        buffer = GL_COLOR_ATTACHMENT0;
+    }
+
+    context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, src_surface, NULL, src_location);
+    gl_info->gl_ops.gl.p_glReadBuffer(buffer);
+    checkGLcall("glReadBuffer()");
+    context_check_fbo_status(context, GL_READ_FRAMEBUFFER);
+
+    if (dst_location == SFLAG_INDRAWABLE)
+    {
+        TRACE("Destination surface %p is onscreen.\n", dst_surface);
+        buffer = surface_get_gl_buffer(dst_surface);
+#ifndef VBOX_WINE_WITH_SINGLE_CONTEXT
+        surface_translate_drawable_coords(dst_surface, context->win_handle, &dst_rect);
+#else
+        surface_translate_drawable_coords(dst_surface, context->swapchain->win_handle, &dst_rect);
+#endif
+    }
+    else
+    {
+        TRACE("Destination surface %p is offscreen.\n", dst_surface);
+        buffer = GL_COLOR_ATTACHMENT0;
+    }
+
+    context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, dst_surface, NULL, dst_location);
+    context_set_draw_buffer(context, buffer);
+    context_check_fbo_status(context, GL_DRAW_FRAMEBUFFER);
+    context_invalidate_state(context, STATE_FRAMEBUFFER);
+
+    gl_info->gl_ops.gl.p_glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE));
+    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE1));
+    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE2));
+    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE3));
+
+    gl_info->gl_ops.gl.p_glDisable(GL_SCISSOR_TEST);
+    context_invalidate_state(context, STATE_RENDER(WINED3D_RS_SCISSORTESTENABLE));
+
+    gl_info->fbo_ops.glBlitFramebuffer(src_rect.left, src_rect.top, src_rect.right, src_rect.bottom,
+            dst_rect.left, dst_rect.top, dst_rect.right, dst_rect.bottom, GL_COLOR_BUFFER_BIT, gl_filter);
+    checkGLcall("glBlitFramebuffer()");
+
+    if (wined3d_settings.strict_draw_ordering
+            || (dst_location == SFLAG_INDRAWABLE
+            && dst_surface->swapchain->front_buffer == dst_surface))
+        gl_info->gl_ops.gl.p_glFlush();
+
+    context_release(context);
+}
+
+static BOOL fbo_blit_supported(const struct wined3d_gl_info *gl_info, enum wined3d_blit_op blit_op,
+        const RECT *src_rect, DWORD src_usage, enum wined3d_pool src_pool, const struct wined3d_format *src_format,
+        const RECT *dst_rect, DWORD dst_usage, enum wined3d_pool dst_pool, const struct wined3d_format *dst_format)
+{
+    if ((wined3d_settings.offscreen_rendering_mode != ORM_FBO) || !gl_info->fbo_ops.glBlitFramebuffer)
+        return FALSE;
+
+    /* Source and/or destination need to be on the GL side */
+    if (src_pool == WINED3D_POOL_SYSTEM_MEM || dst_pool == WINED3D_POOL_SYSTEM_MEM)
+        return FALSE;
+
+    switch (blit_op)
+    {
+        case WINED3D_BLIT_OP_COLOR_BLIT:
+            if (!((src_format->flags & WINED3DFMT_FLAG_FBO_ATTACHABLE) || (src_usage & WINED3DUSAGE_RENDERTARGET)))
+                return FALSE;
+            if (!((dst_format->flags & WINED3DFMT_FLAG_FBO_ATTACHABLE) || (dst_usage & WINED3DUSAGE_RENDERTARGET)))
+                return FALSE;
+            break;
+
+        case WINED3D_BLIT_OP_DEPTH_BLIT:
+            if (!(src_format->flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)))
+                return FALSE;
+            if (!(dst_format->flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)))
+                return FALSE;
+            break;
+
+        default:
+            return FALSE;
+    }
+
+    if (!(src_format->id == dst_format->id
+            || (is_identity_fixup(src_format->color_fixup)
+            && is_identity_fixup(dst_format->color_fixup))))
+        return FALSE;
+
+    return TRUE;
+}
+
+/* This function checks if the primary render target uses the 8bit paletted format. */
+static BOOL primary_render_target_is_p8(const struct wined3d_device *device)
+{
+    if (device->fb.render_targets && device->fb.render_targets[0])
+    {
+        const struct wined3d_surface *render_target = device->fb.render_targets[0];
+        if ((render_target->resource.usage & WINED3DUSAGE_RENDERTARGET)
+                && (render_target->resource.format->id == WINED3DFMT_P8_UINT))
+            return TRUE;
+    }
+    return FALSE;
+}
+
+static BOOL surface_convert_color_to_float(const struct wined3d_surface *surface,
+        DWORD color, struct wined3d_color *float_color)
+{
+    const struct wined3d_format *format = surface->resource.format;
+    const struct wined3d_device *device = surface->resource.device;
+
+    switch (format->id)
+    {
+        case WINED3DFMT_P8_UINT:
+            if (surface->palette)
+            {
+                float_color->r = surface->palette->palents[color].peRed / 255.0f;
+                float_color->g = surface->palette->palents[color].peGreen / 255.0f;
+                float_color->b = surface->palette->palents[color].peBlue / 255.0f;
+            }
+            else
+            {
+                float_color->r = 0.0f;
+                float_color->g = 0.0f;
+                float_color->b = 0.0f;
+            }
+            float_color->a = primary_render_target_is_p8(device) ? color / 255.0f : 1.0f;
+            break;
+
+        case WINED3DFMT_B5G6R5_UNORM:
+            float_color->r = ((color >> 11) & 0x1f) / 31.0f;
+            float_color->g = ((color >> 5) & 0x3f) / 63.0f;
+            float_color->b = (color & 0x1f) / 31.0f;
+            float_color->a = 1.0f;
+            break;
+
+        case WINED3DFMT_B8G8R8_UNORM:
+        case WINED3DFMT_B8G8R8X8_UNORM:
+            float_color->r = D3DCOLOR_R(color);
+            float_color->g = D3DCOLOR_G(color);
+            float_color->b = D3DCOLOR_B(color);
+            float_color->a = 1.0f;
+            break;
+
+        case WINED3DFMT_B8G8R8A8_UNORM:
+            float_color->r = D3DCOLOR_R(color);
+            float_color->g = D3DCOLOR_G(color);
+            float_color->b = D3DCOLOR_B(color);
+            float_color->a = D3DCOLOR_A(color);
+            break;
+
+        default:
+            ERR("Unhandled conversion from %s to floating point.\n", debug_d3dformat(format->id));
+            return FALSE;
+    }
+
+    return TRUE;
+}
+
+static BOOL surface_convert_depth_to_float(const struct wined3d_surface *surface, DWORD depth, float *float_depth)
+{
+    const struct wined3d_format *format = surface->resource.format;
+
+    switch (format->id)
+    {
+        case WINED3DFMT_S1_UINT_D15_UNORM:
+            *float_depth = depth / (float)0x00007fff;
+            break;
+
+        case WINED3DFMT_D16_UNORM:
+            *float_depth = depth / (float)0x0000ffff;
+            break;
+
+        case WINED3DFMT_D24_UNORM_S8_UINT:
+        case WINED3DFMT_X8D24_UNORM:
+            *float_depth = depth / (float)0x00ffffff;
+            break;
+
+        case WINED3DFMT_D32_UNORM:
+            *float_depth = depth / (float)0xffffffff;
+            break;
+
+        default:
+            ERR("Unhandled conversion from %s to floating point.\n", debug_d3dformat(format->id));
+            return FALSE;
+    }
+
+    return TRUE;
+}
+
+/* Do not call while under the GL lock. */
+static HRESULT wined3d_surface_depth_fill(struct wined3d_surface *surface, const RECT *rect, float depth)
+{
+    const struct wined3d_resource *resource = &surface->resource;
+    struct wined3d_device *device = resource->device;
+    const struct blit_shader *blitter;
+
+    blitter = wined3d_select_blitter(&device->adapter->gl_info, WINED3D_BLIT_OP_DEPTH_FILL,
+            NULL, 0, 0, NULL, rect, resource->usage, resource->pool, resource->format);
+    if (!blitter)
+    {
+        FIXME("No blitter is capable of performing the requested depth fill operation.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    return blitter->depth_fill(device, surface, rect, depth);
+}
+
+static HRESULT wined3d_surface_depth_blt(struct wined3d_surface *src_surface, DWORD src_location, const RECT *src_rect,
+        struct wined3d_surface *dst_surface, DWORD dst_location, const RECT *dst_rect)
+{
+    struct wined3d_device *device = src_surface->resource.device;
+
+    if (!fbo_blit_supported(&device->adapter->gl_info, WINED3D_BLIT_OP_DEPTH_BLIT,
+            src_rect, src_surface->resource.usage, src_surface->resource.pool, src_surface->resource.format,
+            dst_rect, dst_surface->resource.usage, dst_surface->resource.pool, dst_surface->resource.format))
+        return WINED3DERR_INVALIDCALL;
+
+    surface_depth_blt_fbo(device, src_surface, src_location, src_rect, dst_surface, dst_location, dst_rect);
+
+    surface_modify_ds_location(dst_surface, dst_location,
+            dst_surface->ds_current_size.cx, dst_surface->ds_current_size.cy);
+
+    return WINED3D_OK;
+}
+
+/* Do not call while under the GL lock. */
+HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst_rect_in,
+        struct wined3d_surface *src_surface, const RECT *src_rect_in, DWORD flags,
+        const WINEDDBLTFX *fx, enum wined3d_texture_filter_type filter)
+{
+    struct wined3d_swapchain *src_swapchain, *dst_swapchain;
+    struct wined3d_device *device = dst_surface->resource.device;
+    DWORD src_ds_flags, dst_ds_flags;
+    RECT src_rect, dst_rect;
+    BOOL scale, convert;
+#ifdef VBOX_WITH_WDDM
+    HRESULT hr = WINED3D_OK;
+#endif
+
+    static const DWORD simple_blit = WINEDDBLT_ASYNC
+            | WINEDDBLT_COLORFILL
+            | WINEDDBLT_WAIT
+            | WINEDDBLT_DEPTHFILL
+            | WINEDDBLT_DONOTWAIT;
+
+    TRACE("dst_surface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p, filter %s.\n",
+            dst_surface, wine_dbgstr_rect(dst_rect_in), src_surface, wine_dbgstr_rect(src_rect_in),
+            flags, fx, debug_d3dtexturefiltertype(filter));
+    TRACE("Usage is %s.\n", debug_d3dusage(dst_surface->resource.usage));
+
+    if (fx)
+    {
+        TRACE("dwSize %#x.\n", fx->dwSize);
+        TRACE("dwDDFX %#x.\n", fx->dwDDFX);
+        TRACE("dwROP %#x.\n", fx->dwROP);
+        TRACE("dwDDROP %#x.\n", fx->dwDDROP);
+        TRACE("dwRotationAngle %#x.\n", fx->dwRotationAngle);
+        TRACE("dwZBufferOpCode %#x.\n", fx->dwZBufferOpCode);
+        TRACE("dwZBufferLow %#x.\n", fx->dwZBufferLow);
+        TRACE("dwZBufferHigh %#x.\n", fx->dwZBufferHigh);
+        TRACE("dwZBufferBaseDest %#x.\n", fx->dwZBufferBaseDest);
+        TRACE("dwZDestConstBitDepth %#x.\n", fx->dwZDestConstBitDepth);
+        TRACE("lpDDSZBufferDest %p.\n", fx->u1.lpDDSZBufferDest);
+        TRACE("dwZSrcConstBitDepth %#x.\n", fx->dwZSrcConstBitDepth);
+        TRACE("lpDDSZBufferSrc %p.\n", fx->u2.lpDDSZBufferSrc);
+        TRACE("dwAlphaEdgeBlendBitDepth %#x.\n", fx->dwAlphaEdgeBlendBitDepth);
+        TRACE("dwAlphaEdgeBlend %#x.\n", fx->dwAlphaEdgeBlend);
+        TRACE("dwReserved %#x.\n", fx->dwReserved);
+        TRACE("dwAlphaDestConstBitDepth %#x.\n", fx->dwAlphaDestConstBitDepth);
+        TRACE("lpDDSAlphaDest %p.\n", fx->u3.lpDDSAlphaDest);
+        TRACE("dwAlphaSrcConstBitDepth %#x.\n", fx->dwAlphaSrcConstBitDepth);
+        TRACE("lpDDSAlphaSrc %p.\n", fx->u4.lpDDSAlphaSrc);
+        TRACE("lpDDSPattern %p.\n", fx->u5.lpDDSPattern);
+        TRACE("ddckDestColorkey {%#x, %#x}.\n",
+                fx->ddckDestColorkey.color_space_low_value,
+                fx->ddckDestColorkey.color_space_high_value);
+        TRACE("ddckSrcColorkey {%#x, %#x}.\n",
+                fx->ddckSrcColorkey.color_space_low_value,
+                fx->ddckSrcColorkey.color_space_high_value);
+    }
+
+    if (dst_surface->resource.map_count || (src_surface && src_surface->resource.map_count))
+    {
+        WARN("Surface is busy, returning WINEDDERR_SURFACEBUSY.\n");
+        return WINEDDERR_SURFACEBUSY;
+    }
+
+    surface_get_rect(dst_surface, dst_rect_in, &dst_rect);
+
+    if (dst_rect.left >= dst_rect.right || dst_rect.top >= dst_rect.bottom
+            || dst_rect.left > dst_surface->resource.width || dst_rect.left < 0
+            || dst_rect.top > dst_surface->resource.height || dst_rect.top < 0
+            || dst_rect.right > dst_surface->resource.width || dst_rect.right < 0
+            || dst_rect.bottom > dst_surface->resource.height || dst_rect.bottom < 0)
+    {
+        WARN("The application gave us a bad destination rectangle.\n");
+        return WINEDDERR_INVALIDRECT;
+    }
+
+    if (src_surface)
+    {
+        surface_get_rect(src_surface, src_rect_in, &src_rect);
+
+        if (src_rect.left >= src_rect.right || src_rect.top >= src_rect.bottom
+                || src_rect.left > src_surface->resource.width || src_rect.left < 0
+                || src_rect.top > src_surface->resource.height || src_rect.top < 0
+                || src_rect.right > src_surface->resource.width || src_rect.right < 0
+                || src_rect.bottom > src_surface->resource.height || src_rect.bottom < 0)
+        {
+            WARN("Application gave us bad source rectangle for Blt.\n");
+            return WINEDDERR_INVALIDRECT;
+        }
+    }
+    else
+    {
+        memset(&src_rect, 0, sizeof(src_rect));
+    }
+
+#ifdef VBOX_WITH_WDDM
+    surface_shrc_lock(dst_surface);
+    if (src_surface) surface_shrc_lock(src_surface);
+
+    /* once we've done locking, we should do unlock on exit,
+     * do goto post_process instead of return below! */
+#endif
+
+    if (!fx || !(fx->dwDDFX))
+        flags &= ~WINEDDBLT_DDFX;
+
+    if (flags & WINEDDBLT_WAIT)
+        flags &= ~WINEDDBLT_WAIT;
+
+    if (flags & WINEDDBLT_ASYNC)
+    {
+        static unsigned int once;
+
+        if (!once++)
+            FIXME("Can't handle WINEDDBLT_ASYNC flag.\n");
+        flags &= ~WINEDDBLT_ASYNC;
+    }
+
+    /* WINEDDBLT_DONOTWAIT appeared in DX7. */
+    if (flags & WINEDDBLT_DONOTWAIT)
+    {
+        static unsigned int once;
+
+        if (!once++)
+            FIXME("Can't handle WINEDDBLT_DONOTWAIT flag.\n");
+        flags &= ~WINEDDBLT_DONOTWAIT;
+    }
+
+    if (!device->d3d_initialized)
+    {
+        WARN("D3D not initialized, using fallback.\n");
+        goto cpu;
+    }
+
+    /* We want to avoid invalidating the sysmem location for converted
+     * surfaces, since otherwise we'd have to convert the data back when
+     * locking them. */
+    if (dst_surface->flags & SFLAG_CONVERTED)
+    {
+        WARN_(d3d_perf)("Converted surface, using CPU blit.\n");
+#ifndef VBOX_WITH_WDDM
+        return surface_cpu_blt(dst_surface, &dst_rect, src_surface, &src_rect, flags, fx, filter);
+#else
+        hr = surface_cpu_blt(dst_surface, &dst_rect, src_surface, &src_rect, flags, fx, filter);
+        goto post_process;
+#endif
+
+    }
+
+    if (flags & ~simple_blit)
+    {
+        WARN_(d3d_perf)("Using fallback for complex blit (%#x).\n", flags);
+        goto fallback;
+    }
+
+    if (src_surface)
+        src_swapchain = src_surface->swapchain;
+    else
+        src_swapchain = NULL;
+
+    dst_swapchain = dst_surface->swapchain;
+
+    /* This isn't strictly needed. FBO blits for example could deal with
+     * cross-swapchain blits by first downloading the source to a texture
+     * before switching to the destination context. We just have this here to
+     * not have to deal with the issue, since cross-swapchain blits should be
+     * rare. */
+    if (src_swapchain && dst_swapchain && src_swapchain != dst_swapchain)
+    {
+        FIXME("Using fallback for cross-swapchain blit.\n");
+        goto fallback;
+    }
+
+    scale = src_surface
+            && (src_rect.right - src_rect.left != dst_rect.right - dst_rect.left
+            || src_rect.bottom - src_rect.top != dst_rect.bottom - dst_rect.top);
+    convert = src_surface && src_surface->resource.format->id != dst_surface->resource.format->id;
+
+    dst_ds_flags = dst_surface->resource.format->flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL);
+    if (src_surface)
+        src_ds_flags = src_surface->resource.format->flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL);
+    else
+        src_ds_flags = 0;
+
+    if (src_ds_flags || dst_ds_flags)
+    {
+        if (flags & WINEDDBLT_DEPTHFILL)
+        {
+            float depth;
+
+            TRACE("Depth fill.\n");
+
+            if (!surface_convert_depth_to_float(dst_surface, fx->u5.dwFillDepth, &depth))
+#ifndef VBOX_WITH_WDDM
+                return WINED3DERR_INVALIDCALL;
+#else
+            {
+                hr = WINED3DERR_INVALIDCALL;
+                goto post_process;
+            }
+#endif
+
+            if (SUCCEEDED(wined3d_surface_depth_fill(dst_surface, &dst_rect, depth)))
+#ifndef VBOX_WITH_WDDM
+                return WINED3D_OK;
+#else
+            {
+                hr = WINED3D_OK;
+                goto post_process;
+            }
+#endif
+        }
+        else
+        {
+            if (src_ds_flags != dst_ds_flags)
+            {
+                WARN("Rejecting depth / stencil blit between incompatible formats.\n");
+#ifndef VBOX_WITH_WDDM
+                return WINED3DERR_INVALIDCALL;
+#else
+                hr = WINED3D_OK;
+                goto post_process;
+#endif
+            }
+
+            if (SUCCEEDED(wined3d_surface_depth_blt(src_surface, src_surface->draw_binding, &src_rect,
+                    dst_surface, dst_surface->draw_binding, &dst_rect)))
+#ifndef VBOX_WITH_WDDM
+                return WINED3D_OK;
+#else
+            {
+                hr = WINED3D_OK;
+                goto post_process;
+            }
+#endif
+        }
+    }
+    else
+    {
+        /* In principle this would apply to depth blits as well, but we don't
+         * implement those in the CPU blitter at the moment. */
+        if ((dst_surface->flags & SFLAG_INSYSMEM)
+                && (!src_surface || (src_surface->flags & SFLAG_INSYSMEM)))
+        {
+#ifdef DEBUG_misha
+            /* if below condition is not specified, i.e. both surfaces are in tecxture locations,
+             * we would perhaps need to fallback to tex->tex hw blitting */
+            Assert(!(dst_surface->flags & SFLAG_INTEXTURE) ||
+                    !src_surface || !(src_surface->flags & SFLAG_INTEXTURE));
+#endif
+            if (scale)
+                TRACE("Not doing sysmem blit because of scaling.\n");
+            else if (convert)
+                TRACE("Not doing sysmem blit because of format conversion.\n");
+            else
+#ifndef VBOX_WITH_WDDM
+                return surface_cpu_blt(dst_surface, &dst_rect, src_surface, &src_rect, flags, fx, filter);
+#else
+            {
+                hr = surface_cpu_blt(dst_surface, &dst_rect, src_surface, &src_rect, flags, fx, filter);
+                goto post_process;
+            }
+#endif
+
+        }
+
+        if (flags & WINEDDBLT_COLORFILL)
+        {
+            struct wined3d_color color;
+
+            TRACE("Color fill.\n");
+
+            if (!surface_convert_color_to_float(dst_surface, fx->u5.dwFillColor, &color))
+                goto fallback;
+
+            if (SUCCEEDED(surface_color_fill(dst_surface, &dst_rect, &color)))
+#ifndef VBOX_WITH_WDDM
+                return WINED3D_OK;
+#else
+            {
+                hr = WINED3D_OK;
+                goto post_process;
+            }
+#endif
+        }
+        else
+        {
+            TRACE("Color blit.\n");
+
+            /* Upload */
+            if ((src_surface->flags & SFLAG_INSYSMEM) && !(dst_surface->flags & SFLAG_INSYSMEM))
+            {
+                if (scale)
+                    TRACE("Not doing upload because of scaling.\n");
+                else if (convert)
+                    TRACE("Not doing upload because of format conversion.\n");
+                else
+                {
+                    POINT dst_point = {dst_rect.left, dst_rect.top};
+
+                    if (SUCCEEDED(surface_upload_from_surface(dst_surface, &dst_point, src_surface, &src_rect)))
+                    {
+                        if (!surface_is_offscreen(dst_surface))
+                            surface_load_location(dst_surface, dst_surface->draw_binding, NULL);
+#ifndef VBOX_WITH_WDDM
+                        return WINED3D_OK;
+#else
+                        hr = WINED3D_OK;
+                        goto post_process;
+#endif
+                    }
+                }
+            }
+
+            /* Use present for back -> front blits. The idea behind this is
+             * that present is potentially faster than a blit, in particular
+             * when FBO blits aren't available. Some ddraw applications like
+             * Half-Life and Prince of Persia 3D use Blt() from the backbuffer
+             * to the frontbuffer instead of doing a Flip(). D3D8 and D3D9
+             * applications can't blit directly to the frontbuffer. */
+            if (dst_swapchain && dst_swapchain->back_buffers
+                    && dst_surface == dst_swapchain->front_buffer
+                    && src_surface == dst_swapchain->back_buffers[0])
+            {
+                enum wined3d_swap_effect swap_effect = dst_swapchain->desc.swap_effect;
+
+                TRACE("Using present for backbuffer -> frontbuffer blit.\n");
+
+                /* Set the swap effect to COPY, we don't want the backbuffer
+                 * to become undefined. */
+                dst_swapchain->desc.swap_effect = WINED3D_SWAP_EFFECT_COPY;
+                wined3d_swapchain_present(dst_swapchain, NULL, NULL, dst_swapchain->win_handle, NULL, 0);
+                dst_swapchain->desc.swap_effect = swap_effect;
+
+#ifndef VBOX_WITH_WDDM
+                return WINED3D_OK;
+#else
+                hr = WINED3D_OK;
+                goto post_process;
+#endif
+            }
+
+            if (fbo_blit_supported(&device->adapter->gl_info, WINED3D_BLIT_OP_COLOR_BLIT,
+                    &src_rect, src_surface->resource.usage, src_surface->resource.pool, src_surface->resource.format,
+                    &dst_rect, dst_surface->resource.usage, dst_surface->resource.pool, dst_surface->resource.format))
+            {
+                TRACE("Using FBO blit.\n");
+
+                surface_blt_fbo(device, filter,
+                        src_surface, src_surface->draw_binding, &src_rect,
+                        dst_surface, dst_surface->draw_binding, &dst_rect);
+                surface_modify_location(dst_surface, dst_surface->draw_binding, TRUE);
+#ifndef VBOX_WITH_WDDM
+                return WINED3D_OK;
+#else
+                hr = WINED3D_OK;
+                goto post_process;
+#endif
+            }
+
+            if (arbfp_blit.blit_supported(&device->adapter->gl_info, WINED3D_BLIT_OP_COLOR_BLIT,
+                    &src_rect, src_surface->resource.usage, src_surface->resource.pool, src_surface->resource.format,
+                    &dst_rect, dst_surface->resource.usage, dst_surface->resource.pool, dst_surface->resource.format))
+            {
+                TRACE("Using arbfp blit.\n");
+
+                if (SUCCEEDED(arbfp_blit_surface(device, filter, src_surface, &src_rect, dst_surface, &dst_rect)))
+#ifndef VBOX_WITH_WDDM
+                    return WINED3D_OK;
+#else
+                {
+                    hr = WINED3D_OK;
+                    goto post_process;
+                }
+#endif
+            }
+        }
+    }
+
+fallback:
+
+#ifdef DEBUG_misha
+    /* test ! */
+    Assert(0);
+#endif
+    /* Special cases for render targets. */
+    if ((dst_surface->resource.usage & WINED3DUSAGE_RENDERTARGET)
+            || (src_surface && (src_surface->resource.usage & WINED3DUSAGE_RENDERTARGET)))
+    {
+        if (SUCCEEDED(IWineD3DSurfaceImpl_BltOverride(dst_surface, &dst_rect,
+                src_surface, &src_rect, flags, fx, filter)))
+#ifndef VBOX_WITH_WDDM
+            return WINED3D_OK;
+#else
+            {
+                hr = WINED3D_OK;
+                goto post_process;
+            }
+#endif
+    }
+
+cpu:
+
+#ifdef DEBUG_misha
+    /* test ! */
+    Assert(0);
+#endif
+
+
+    /* For the rest call the X11 surface implementation. For render targets
+     * this should be implemented OpenGL accelerated in BltOverride, other
+     * blits are rather rare. */
+#ifndef VBOX_WITH_WDDM
+    return surface_cpu_blt(dst_surface, &dst_rect, src_surface, &src_rect, flags, fx, filter);
+#else
+    hr = surface_cpu_blt(dst_surface, &dst_rect, src_surface, &src_rect, flags, fx, filter);
+    goto post_process;
+#endif
+
+#ifdef VBOX_WITH_WDDM
+post_process:
+    surface_shrc_unlock(dst_surface);
+    if (src_surface) surface_shrc_unlock(src_surface);
+    return hr;
+#endif
+}
+
+HRESULT CDECL wined3d_surface_get_render_target_data(struct wined3d_surface *surface,
+        struct wined3d_surface *render_target)
+{
+    TRACE("surface %p, render_target %p.\n", surface, render_target);
+
+    /* TODO: Check surface sizes, pools, etc. */
+
+    if (render_target->resource.multisample_type)
+        return WINED3DERR_INVALIDCALL;
+
+    return wined3d_surface_blt(surface, NULL, render_target, NULL, 0, NULL, WINED3D_TEXF_POINT);
+}
+
+/* Context activation is done by the caller. */
+static void surface_remove_pbo(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info)
+{
+    if (surface->flags & SFLAG_DIBSECTION)
+    {
+        surface->resource.allocatedMemory = surface->dib.bitmap_data;
+    }
+    else
+    {
+        if (!surface->resource.heapMemory)
+            surface->resource.heapMemory = HeapAlloc(GetProcessHeap(), 0, surface->resource.size + RESOURCE_ALIGNMENT);
+        else if (!(surface->flags & SFLAG_CLIENT))
+            ERR("Surface %p has heapMemory %p and flags %#x.\n",
+                    surface, surface->resource.heapMemory, surface->flags);
+
+        surface->resource.allocatedMemory = (BYTE *)(((ULONG_PTR)surface->resource.heapMemory
+                + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1));
+    }
+
+    GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, surface->pbo));
+    checkGLcall("glBindBufferARB(GL_PIXEL_UNPACK_BUFFER, surface->pbo)");
+    GL_EXTCALL(glGetBufferSubDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0,
+            surface->resource.size, surface->resource.allocatedMemory));
+    checkGLcall("glGetBufferSubDataARB");
+    GL_EXTCALL(glDeleteBuffersARB(1, &surface->pbo));
+    checkGLcall("glDeleteBuffersARB");
+
+    surface->pbo = 0;
+    surface->flags &= ~SFLAG_PBO;
+}
+
+static BOOL surface_init_sysmem(struct wined3d_surface *surface)
+{
+    if (!surface->resource.allocatedMemory)
+    {
+        if (!surface->resource.heapMemory)
+        {
+            if (!(surface->resource.heapMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+                    surface->resource.size + RESOURCE_ALIGNMENT)))
+            {
+                ERR("Failed to allocate memory.\n");
+                return FALSE;
+            }
+        }
+        else if (!(surface->flags & SFLAG_CLIENT))
+        {
+            ERR("Surface %p has heapMemory %p and flags %#x.\n",
+                    surface, surface->resource.heapMemory, surface->flags);
+        }
+
+        surface->resource.allocatedMemory =
+            (BYTE *)(((ULONG_PTR)surface->resource.heapMemory + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1));
+    }
+    else
+    {
+        memset(surface->resource.allocatedMemory, 0, surface->resource.size);
+    }
+
+    surface_modify_location(surface, SFLAG_INSYSMEM, TRUE);
+
+    return TRUE;
+}
+
+/* Do not call while under the GL lock. */
+static void surface_unload(struct wined3d_resource *resource)
+{
+    struct wined3d_surface *surface = surface_from_resource(resource);
+    struct wined3d_renderbuffer_entry *entry, *entry2;
+    struct wined3d_device *device = resource->device;
+    const struct wined3d_gl_info *gl_info;
+    struct wined3d_context *context;
+
+    TRACE("surface %p.\n", surface);
+
+    if (resource->pool == WINED3D_POOL_DEFAULT)
+    {
+        /* Default pool resources are supposed to be destroyed before Reset is called.
+         * Implicit resources stay however. So this means we have an implicit render target
+         * or depth stencil. The content may be destroyed, but we still have to tear down
+         * opengl resources, so we cannot leave early.
+         *
+         * Put the surfaces into sysmem, and reset the content. The D3D content is undefined,
+         * but we can't set the sysmem INDRAWABLE because when we're rendering the swapchain
+         * or the depth stencil into an FBO the texture or render buffer will be removed
+         * and all flags get lost
+         */
+        if (!(surface->flags & SFLAG_PBO))
+            surface_init_sysmem(surface);
+        /* We also get here when the ddraw swapchain is destroyed, for example
+         * for a mode switch. In this case this surface won't necessarily be
+         * an implicit surface. We have to mark it lost so that the
+         * application can restore it after the mode switch. */
+        surface->flags |= SFLAG_LOST;
+    }
+    else
+    {
+        /* Load the surface into system memory */
+        surface_load_location(surface, SFLAG_INSYSMEM, NULL);
+        surface_modify_location(surface, surface->draw_binding, FALSE);
+    }
+    surface_modify_location(surface, SFLAG_INTEXTURE, FALSE);
+    surface_modify_location(surface, SFLAG_INSRGBTEX, FALSE);
+    surface->flags &= ~(SFLAG_ALLOCATED | SFLAG_SRGBALLOCATED);
+
+    context = context_acquire(device, NULL);
+    gl_info = context->gl_info;
+
+    /* Destroy PBOs, but load them into real sysmem before */
+    if (surface->flags & SFLAG_PBO)
+        surface_remove_pbo(surface, gl_info);
+
+    /* Destroy fbo render buffers. This is needed for implicit render targets, for
+     * all application-created targets the application has to release the surface
+     * before calling _Reset
+     */
+    LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &surface->renderbuffers, struct wined3d_renderbuffer_entry, entry)
+    {
+        gl_info->fbo_ops.glDeleteRenderbuffers(1, &entry->id);
+        list_remove(&entry->entry);
+        HeapFree(GetProcessHeap(), 0, entry);
+    }
+    list_init(&surface->renderbuffers);
+    surface->current_renderbuffer = NULL;
+
+    /* If we're in a texture, the texture name belongs to the texture.
+     * Otherwise, destroy it. */
+    if (!surface->container)
+    {
+#ifdef VBOX_WITH_WDDM
+        texture_gl_delete(surface->texture_name);
+#else
+        gl_info->gl_ops.gl.p_glDeleteTextures(1, &surface->texture_name);
+#endif
+        surface->texture_name = 0;
+#ifdef VBOX_WITH_WDDM
+        texture_gl_delete(surface->texture_name_srgb);
+#else
+        gl_info->gl_ops.gl.p_glDeleteTextures(1, &surface->texture_name_srgb);
+#endif
+        surface->texture_name_srgb = 0;
+    }
+    if (surface->rb_multisample)
+    {
+        gl_info->fbo_ops.glDeleteRenderbuffers(1, &surface->rb_multisample);
+        surface->rb_multisample = 0;
+    }
+    if (surface->rb_resolved)
+    {
+        gl_info->fbo_ops.glDeleteRenderbuffers(1, &surface->rb_resolved);
+        surface->rb_resolved = 0;
+    }
+
+    context_release(context);
+
+    resource_unload(resource);
+}
+
+static const struct wined3d_resource_ops surface_resource_ops =
+{
+    surface_unload,
+};
+
+static const struct wined3d_surface_ops surface_ops =
+{
+    surface_private_setup,
+    surface_realize_palette,
+    surface_map,
+    surface_unmap,
+};
+
+/*****************************************************************************
+ * Initializes the GDI surface, aka creates the DIB section we render to
+ * The DIB section creation is done by calling GetDC, which will create the
+ * section and releasing the dc to allow the app to use it. The dib section
+ * will stay until the surface is released
+ *
+ * GDI surfaces do not need to be a power of 2 in size, so the pow2 sizes
+ * are set to the real sizes to save memory. The NONPOW2 flag is unset to
+ * avoid confusion in the shared surface code.
+ *
+ * Returns:
+ *  WINED3D_OK on success
+ *  The return values of called methods on failure
+ *
+ *****************************************************************************/
+static HRESULT gdi_surface_private_setup(struct wined3d_surface *surface)
+{
+    HRESULT hr;
+
+    TRACE("surface %p.\n", surface);
+
+    if (surface->resource.usage & WINED3DUSAGE_OVERLAY)
+    {
+        ERR("Overlays not yet supported by GDI surfaces.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    /* Sysmem textures have memory already allocated - release it,
+     * this avoids an unnecessary memcpy. */
+    hr = surface_create_dib_section(surface);
+    if (SUCCEEDED(hr))
+    {
+        HeapFree(GetProcessHeap(), 0, surface->resource.heapMemory);
+        surface->resource.heapMemory = NULL;
+        surface->resource.allocatedMemory = surface->dib.bitmap_data;
+    }
+
+    /* We don't mind the nonpow2 stuff in GDI. */
+    surface->pow2Width = surface->resource.width;
+    surface->pow2Height = surface->resource.height;
+
+    return WINED3D_OK;
+}
+
+static void gdi_surface_realize_palette(struct wined3d_surface *surface)
+{
+    struct wined3d_palette *palette = surface->palette;
+
+    TRACE("surface %p.\n", surface);
+
+    if (!palette) return;
+
+    if (surface->flags & SFLAG_DIBSECTION)
+    {
+        RGBQUAD col[256];
+        unsigned int i;
+
+        TRACE("Updating the DC's palette.\n");
+
+        for (i = 0; i < 256; ++i)
+        {
+            col[i].rgbRed = palette->palents[i].peRed;
+            col[i].rgbGreen = palette->palents[i].peGreen;
+            col[i].rgbBlue = palette->palents[i].peBlue;
+            col[i].rgbReserved = 0;
+        }
+        SetDIBColorTable(surface->hDC, 0, 256, col);
+    }
+
+    /* Update the image because of the palette change. Some games like e.g.
+     * Red Alert call SetEntries a lot to implement fading. */
+    /* Tell the swapchain to update the screen. */
+    if (surface->swapchain && surface == surface->swapchain->front_buffer)
+        x11_copy_to_screen(surface->swapchain, NULL);
+}
+
+static void gdi_surface_map(struct wined3d_surface *surface, const RECT *rect, DWORD flags)
+{
+    TRACE("surface %p, rect %s, flags %#x.\n",
+            surface, wine_dbgstr_rect(rect), flags);
+
+    if (!(surface->flags & SFLAG_DIBSECTION))
+    {
+        HRESULT hr;
+
+        /* This happens on gdi surfaces if the application set a user pointer
+         * and resets it. Recreate the DIB section. */
+        if (FAILED(hr = surface_create_dib_section(surface)))
+        {
+            ERR("Failed to create dib section, hr %#x.\n", hr);
+            return;
+        }
+        HeapFree(GetProcessHeap(), 0, surface->resource.heapMemory);
+        surface->resource.heapMemory = NULL;
+        surface->resource.allocatedMemory = surface->dib.bitmap_data;
+    }
+}
+
+static void gdi_surface_unmap(struct wined3d_surface *surface)
+{
+    TRACE("surface %p.\n", surface);
+
+    /* Tell the swapchain to update the screen. */
+    if (surface->swapchain && surface == surface->swapchain->front_buffer)
+        x11_copy_to_screen(surface->swapchain, &surface->lockedRect);
+
+    memset(&surface->lockedRect, 0, sizeof(RECT));
+}
+
+static const struct wined3d_surface_ops gdi_surface_ops =
+{
+    gdi_surface_private_setup,
+    gdi_surface_realize_palette,
+    gdi_surface_map,
+    gdi_surface_unmap,
+};
+
+void surface_set_texture_name(struct wined3d_surface *surface, GLuint new_name, BOOL srgb)
+{
+    GLuint *name;
+    DWORD flag;
+
+    TRACE("surface %p, new_name %u, srgb %#x.\n", surface, new_name, srgb);
+
+    if(srgb)
+    {
+        name = &surface->texture_name_srgb;
+        flag = SFLAG_INSRGBTEX;
+    }
+    else
+    {
+        name = &surface->texture_name;
+        flag = SFLAG_INTEXTURE;
+    }
+
+    if (!*name && new_name)
+    {
+        /* FIXME: We shouldn't need to remove SFLAG_INTEXTURE if the
+         * surface has no texture name yet. See if we can get rid of this. */
+        if (surface->flags & flag)
+        {
+            ERR("Surface has %s set, but no texture name.\n", debug_surflocation(flag));
+#ifndef VBOX_WITH_WDDM
+            surface_modify_location(surface, flag, FALSE);
+#endif
+        }
+    }
+
+#ifdef VBOX_WITH_WDDM
+    if (VBOXSHRC_IS_SHARED(surface))
+    {
+        Assert(VBOXSHRC_GET_SHAREHANDLE(surface) == NULL
+                || (GLuint)VBOXSHRC_GET_SHAREHANDLE(surface) == new_name
+                || new_name == 0 /* on cleanup */);
+        VBOXSHRC_SET_SHAREHANDLE(surface, new_name);
+    }
+#endif
+    *name = new_name;
+    surface_force_reload(surface);
+}
+
+void surface_set_texture_target(struct wined3d_surface *surface, GLenum target, GLint level)
+{
+    TRACE("surface %p, target %#x.\n", surface, target);
+
+    if (surface->texture_target != target)
+    {
+        if (target == GL_TEXTURE_RECTANGLE_ARB)
+        {
+            surface->flags &= ~SFLAG_NORMCOORD;
+        }
+        else if (surface->texture_target == GL_TEXTURE_RECTANGLE_ARB)
+        {
+            surface->flags |= SFLAG_NORMCOORD;
+        }
+    }
+    surface->texture_target = target;
+    surface->texture_level = level;
+    surface_force_reload(surface);
+}
+
+/* This call just downloads data, the caller is responsible for binding the
+ * correct texture. */
+/* Context activation is done by the caller. */
+static void surface_download_data(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info)
+{
+    const struct wined3d_format *format = surface->resource.format;
+
+    /* Only support read back of converted P8 surfaces. */
+    if (surface->flags & SFLAG_CONVERTED && format->id != WINED3DFMT_P8_UINT)
+    {
+        ERR("Trying to read back converted surface %p with format %s.\n", surface, debug_d3dformat(format->id));
+        return;
+    }
+
+    if (format->flags & WINED3DFMT_FLAG_COMPRESSED)
+    {
+        TRACE("(%p) : Calling glGetCompressedTexImageARB level %d, format %#x, type %#x, data %p.\n",
+                surface, surface->texture_level, format->glFormat, format->glType,
+                surface->resource.allocatedMemory);
+
+        if (surface->flags & SFLAG_PBO)
+        {
+            GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, surface->pbo));
+            checkGLcall("glBindBufferARB");
+            GL_EXTCALL(glGetCompressedTexImageARB(surface->texture_target, surface->texture_level, NULL));
+            checkGLcall("glGetCompressedTexImageARB");
+            GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0));
+            checkGLcall("glBindBufferARB");
+        }
+        else
+        {
+            GL_EXTCALL(glGetCompressedTexImageARB(surface->texture_target,
+                    surface->texture_level, surface->resource.allocatedMemory));
+            checkGLcall("glGetCompressedTexImageARB");
+        }
+
+    }
+    else
+    {
+        void *mem;
+        GLenum gl_format = format->glFormat;
+        GLenum gl_type = format->glType;
+        int src_pitch = 0;
+        int dst_pitch = 0;
+
+        /* In case of P8 the index is stored in the alpha component if the primary render target uses P8. */
+        if (format->id == WINED3DFMT_P8_UINT && primary_render_target_is_p8(surface->resource.device))
+        {
+            gl_format = GL_ALPHA;
+            gl_type = GL_UNSIGNED_BYTE;
+        }
+
+        if (surface->flags & SFLAG_NONPOW2)
+        {
+            unsigned char alignment = surface->resource.device->surface_alignment;
+            src_pitch = format->byte_count * surface->pow2Width;
+            dst_pitch = wined3d_surface_get_pitch(surface);
+            src_pitch = (src_pitch + alignment - 1) & ~(alignment - 1);
+            mem = HeapAlloc(GetProcessHeap(), 0, src_pitch * surface->pow2Height);
+        }
+        else
+        {
+            mem = surface->resource.allocatedMemory;
+        }
+
+        TRACE("(%p) : Calling glGetTexImage level %d, format %#x, type %#x, data %p\n",
+                surface, surface->texture_level, gl_format, gl_type, mem);
+
+        if (surface->flags & SFLAG_PBO)
+        {
+            GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, surface->pbo));
+            checkGLcall("glBindBufferARB");
+
+            gl_info->gl_ops.gl.p_glGetTexImage(surface->texture_target, surface->texture_level,
+                    gl_format, gl_type, NULL);
+            checkGLcall("glGetTexImage");
+
+            GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0));
+            checkGLcall("glBindBufferARB");
+        }
+        else
+        {
+            gl_info->gl_ops.gl.p_glGetTexImage(surface->texture_target, surface->texture_level,
+                    gl_format, gl_type, mem);
+            checkGLcall("glGetTexImage");
+        }
+
+        if (surface->flags & SFLAG_NONPOW2)
+        {
+            const BYTE *src_data;
+            BYTE *dst_data;
+            UINT y;
+            /*
+             * Some games (e.g. warhammer 40k) don't work properly with the odd pitches, preventing
+             * the surface pitch from being used to box non-power2 textures. Instead we have to use a hack to
+             * repack the texture so that the bpp * width pitch can be used instead of bpp * pow2width.
+             *
+             * We're doing this...
+             *
+             * instead of boxing the texture :
+             * |<-texture width ->|  -->pow2width|   /\
+             * |111111111111111111|              |   |
+             * |222 Texture 222222| boxed empty  | texture height
+             * |3333 Data 33333333|              |   |
+             * |444444444444444444|              |   \/
+             * -----------------------------------   |
+             * |     boxed  empty | boxed empty  | pow2height
+             * |                  |              |   \/
+             * -----------------------------------
+             *
+             *
+             * we're repacking the data to the expected texture width
+             *
+             * |<-texture width ->|  -->pow2width|   /\
+             * |111111111111111111222222222222222|   |
+             * |222333333333333333333444444444444| texture height
+             * |444444                           |   |
+             * |                                 |   \/
+             * |                                 |   |
+             * |            empty                | pow2height
+             * |                                 |   \/
+             * -----------------------------------
+             *
+             * == is the same as
+             *
+             * |<-texture width ->|    /\
+             * |111111111111111111|
+             * |222222222222222222|texture height
+             * |333333333333333333|
+             * |444444444444444444|    \/
+             * --------------------
+             *
+             * this also means that any references to allocatedMemory should work with the data as if were a
+             * standard texture with a non-power2 width instead of texture boxed up to be a power2 texture.
+             *
+             * internally the texture is still stored in a boxed format so any references to textureName will
+             * get a boxed texture with width pow2width and not a texture of width resource.width.
+             *
+             * Performance should not be an issue, because applications normally do not lock the surfaces when
+             * rendering. If an app does, the SFLAG_DYNLOCK flag will kick in and the memory copy won't be released,
+             * and doesn't have to be re-read. */
+            src_data = mem;
+            dst_data = surface->resource.allocatedMemory;
+            TRACE("(%p) : Repacking the surface data from pitch %d to pitch %d\n", surface, src_pitch, dst_pitch);
+            for (y = 1; y < surface->resource.height; ++y)
+            {
+                /* skip the first row */
+                src_data += src_pitch;
+                dst_data += dst_pitch;
+                memcpy(dst_data, src_data, dst_pitch);
+            }
+
+            HeapFree(GetProcessHeap(), 0, mem);
+        }
+    }
+
+    /* Surface has now been downloaded */
+    surface->flags |= SFLAG_INSYSMEM;
+}
+
+/* This call just uploads data, the caller is responsible for binding the
+ * correct texture. */
+/* Context activation is done by the caller. */
+static void surface_upload_data(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info,
+        const struct wined3d_format *format, const RECT *src_rect, UINT src_pitch, const POINT *dst_point,
+        BOOL srgb, const struct wined3d_bo_address *data)
+{
+    UINT update_w = src_rect->right - src_rect->left;
+    UINT update_h = src_rect->bottom - src_rect->top;
+
+    TRACE("surface %p, gl_info %p, format %s, src_rect %s, src_pitch %u, dst_point %s, srgb %#x, data {%#x:%p}.\n",
+            surface, gl_info, debug_d3dformat(format->id), wine_dbgstr_rect(src_rect), src_pitch,
+            wine_dbgstr_point(dst_point), srgb, data->buffer_object, data->addr);
+
+    if (surface->resource.map_count)
+    {
+        WARN("Uploading a surface that is currently mapped, setting SFLAG_PIN_SYSMEM.\n");
+        surface->flags |= SFLAG_PIN_SYSMEM;
+    }
+
+    if (format->flags & WINED3DFMT_FLAG_HEIGHT_SCALE)
+    {
+        update_h *= format->height_scale.numerator;
+        update_h /= format->height_scale.denominator;
+    }
+
+    if (data->buffer_object)
+    {
+        GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, data->buffer_object));
+        checkGLcall("glBindBufferARB");
+    }
+
+    if (format->flags & WINED3DFMT_FLAG_COMPRESSED)
+    {
+        UINT row_length = wined3d_format_calculate_size(format, 1, update_w, 1);
+        UINT row_count = (update_h + format->block_height - 1) / format->block_height;
+        const BYTE *addr = data->addr;
+        GLenum internal;
+
+        addr += (src_rect->top / format->block_height) * src_pitch;
+        addr += (src_rect->left / format->block_width) * format->block_byte_count;
+
+        if (srgb)
+            internal = format->glGammaInternal;
+        else if (surface->resource.usage & WINED3DUSAGE_RENDERTARGET && surface_is_offscreen(surface))
+            internal = format->rtInternal;
+        else
+            internal = format->glInternal;
+
+        TRACE("glCompressedTexSubImage2DARB, target %#x, level %d, x %d, y %d, w %d, h %d, "
+                "format %#x, image_size %#x, addr %p.\n", surface->texture_target, surface->texture_level,
+                dst_point->x, dst_point->y, update_w, update_h, internal, row_count * row_length, addr);
+
+        if (row_length == src_pitch)
+        {
+            GL_EXTCALL(glCompressedTexSubImage2DARB(surface->texture_target, surface->texture_level,
+                    dst_point->x, dst_point->y, update_w, update_h, internal, row_count * row_length, addr));
+        }
+        else
+        {
+            UINT row, y;
+
+            /* glCompressedTexSubImage2DARB() ignores pixel store state, so we
+             * can't use the unpack row length like below. */
+            for (row = 0, y = dst_point->y; row < row_count; ++row)
+            {
+                GL_EXTCALL(glCompressedTexSubImage2DARB(surface->texture_target, surface->texture_level,
+                        dst_point->x, y, update_w, format->block_height, internal, row_length, addr));
+                y += format->block_height;
+                addr += src_pitch;
+            }
+        }
+        checkGLcall("glCompressedTexSubImage2DARB");
+    }
+    else
+    {
+        const BYTE *addr = data->addr;
+
+        addr += src_rect->top * src_pitch;
+        addr += src_rect->left * format->byte_count;
+
+        TRACE("glTexSubImage2D, target %#x, level %d, x %d, y %d, w %d, h %d, format %#x, type %#x, addr %p.\n",
+                surface->texture_target, surface->texture_level, dst_point->x, dst_point->y,
+                update_w, update_h, format->glFormat, format->glType, addr);
+
+        gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_ROW_LENGTH, src_pitch / format->byte_count);
+        gl_info->gl_ops.gl.p_glTexSubImage2D(surface->texture_target, surface->texture_level,
+                dst_point->x, dst_point->y, update_w, update_h, format->glFormat, format->glType, addr);
+        gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+        checkGLcall("glTexSubImage2D");
+    }
+
+    if (data->buffer_object)
+    {
+        GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
+        checkGLcall("glBindBufferARB");
+    }
+
+    if (wined3d_settings.strict_draw_ordering)
+        gl_info->gl_ops.gl.p_glFlush();
+
+    if (gl_info->quirks & WINED3D_QUIRK_FBO_TEX_UPDATE)
+    {
+        struct wined3d_device *device = surface->resource.device;
+        unsigned int i;
+
+        for (i = 0; i < device->context_count; ++i)
+        {
+            context_surface_update(device->contexts[i], surface);
+        }
+    }
+}
+
+static HRESULT d3dfmt_get_conv(const struct wined3d_surface *surface, BOOL need_alpha_ck, BOOL use_texturing,
+        struct wined3d_format *format, enum wined3d_conversion_type *conversion_type)
+{
+    BOOL colorkey_active = need_alpha_ck && (surface->CKeyFlags & WINEDDSD_CKSRCBLT);
+    const struct wined3d_device *device = surface->resource.device;
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    BOOL blit_supported = FALSE;
+
+    /* Copy the default values from the surface. Below we might perform fixups */
+    /* TODO: get rid of color keying desc fixups by using e.g. a table. */
+    *format = *surface->resource.format;
+    *conversion_type = WINED3D_CT_NONE;
+
+    /* Ok, now look if we have to do any conversion */
+    switch (surface->resource.format->id)
+    {
+        case WINED3DFMT_P8_UINT:
+            /* Below the call to blit_supported is disabled for Wine 1.2
+             * because the function isn't operating correctly yet. At the
+             * moment 8-bit blits are handled in software and if certain GL
+             * extensions are around, surface conversion is performed at
+             * upload time. The blit_supported call recognizes it as a
+             * destination fixup. This type of upload 'fixup' and 8-bit to
+             * 8-bit blits need to be handled by the blit_shader.
+             * TODO: get rid of this #if 0. */
+#if 0
+            blit_supported = device->blitter->blit_supported(&device->adapter->gl_info, WINED3D_BLIT_OP_COLOR_BLIT,
+                    &rect, surface->resource.usage, surface->resource.pool, surface->resource.format,
+                    &rect, surface->resource.usage, surface->resource.pool, surface->resource.format);
+#endif
+            blit_supported = gl_info->supported[EXT_PALETTED_TEXTURE] || gl_info->supported[ARB_FRAGMENT_PROGRAM];
+
+            /* Use conversion when the blit_shader backend supports it. It only supports this in case of
+             * texturing. Further also use conversion in case of color keying.
+             * Paletted textures can be emulated using shaders but only do that for 2D purposes e.g. situations
+             * in which the main render target uses p8. Some games like GTA Vice City use P8 for texturing which
+             * conflicts with this.
+             */
+            if (!((blit_supported && device->fb.render_targets && surface == device->fb.render_targets[0]))
+                    || colorkey_active || !use_texturing)
+            {
+                format->glFormat = GL_RGBA;
+                format->glInternal = GL_RGBA;
+                format->glType = GL_UNSIGNED_BYTE;
+                format->conv_byte_count = 4;
+                if (colorkey_active)
+                    *conversion_type = WINED3D_CT_PALETTED_CK;
+                else
+                    *conversion_type = WINED3D_CT_PALETTED;
+            }
+            break;
+
+        case WINED3DFMT_B2G3R3_UNORM:
+            /* **********************
+                GL_UNSIGNED_BYTE_3_3_2
+                ********************** */
+            if (colorkey_active) {
+                /* This texture format will never be used.. So do not care about color keying
+                    up until the point in time it will be needed :-) */
+                FIXME(" ColorKeying not supported in the RGB 332 format !\n");
+            }
+            break;
+
+        case WINED3DFMT_B5G6R5_UNORM:
+            if (colorkey_active)
+            {
+                *conversion_type = WINED3D_CT_CK_565;
+                format->glFormat = GL_RGBA;
+                format->glInternal = GL_RGB5_A1;
+                format->glType = GL_UNSIGNED_SHORT_5_5_5_1;
+                format->conv_byte_count = 2;
+            }
+            break;
+
+        case WINED3DFMT_B5G5R5X1_UNORM:
+            if (colorkey_active)
+            {
+                *conversion_type = WINED3D_CT_CK_5551;
+                format->glFormat = GL_BGRA;
+                format->glInternal = GL_RGB5_A1;
+                format->glType = GL_UNSIGNED_SHORT_1_5_5_5_REV;
+                format->conv_byte_count = 2;
+            }
+            break;
+
+        case WINED3DFMT_B8G8R8_UNORM:
+            if (colorkey_active)
+            {
+                *conversion_type = WINED3D_CT_CK_RGB24;
+                format->glFormat = GL_RGBA;
+                format->glInternal = GL_RGBA8;
+                format->glType = GL_UNSIGNED_INT_8_8_8_8;
+                format->conv_byte_count = 4;
+            }
+            break;
+
+        case WINED3DFMT_B8G8R8X8_UNORM:
+            if (colorkey_active)
+            {
+                *conversion_type = WINED3D_CT_RGB32_888;
+                format->glFormat = GL_RGBA;
+                format->glInternal = GL_RGBA8;
+                format->glType = GL_UNSIGNED_INT_8_8_8_8;
+                format->conv_byte_count = 4;
+            }
+            break;
+
+        case WINED3DFMT_B8G8R8A8_UNORM:
+            if (colorkey_active)
+            {
+                *conversion_type = WINED3D_CT_CK_ARGB32;
+                format->conv_byte_count = 4;
+            }
+            break;
+
+        default:
+            break;
+    }
+
+    if (*conversion_type != WINED3D_CT_NONE)
+    {
+        format->rtInternal = format->glInternal;
+        format->glGammaInternal = format->glInternal;
+    }
+
+    return WINED3D_OK;
+}
+
+static BOOL surface_check_block_align(struct wined3d_surface *surface, const RECT *rect)
+{
+    UINT width_mask, height_mask;
+
+    if (!rect->left && !rect->top
+            && rect->right == surface->resource.width
+            && rect->bottom == surface->resource.height)
+        return TRUE;
+
+    /* This assumes power of two block sizes, but NPOT block sizes would be
+     * silly anyway. */
+    width_mask = surface->resource.format->block_width - 1;
+    height_mask = surface->resource.format->block_height - 1;
+
+    if (!(rect->left & width_mask) && !(rect->top & height_mask)
+            && !(rect->right & width_mask) && !(rect->bottom & height_mask))
+        return TRUE;
+
+    return FALSE;
+}
+
+HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const POINT *dst_point,
+        struct wined3d_surface *src_surface, const RECT *src_rect)
+{
+    const struct wined3d_format *src_format;
+    const struct wined3d_format *dst_format;
+    const struct wined3d_gl_info *gl_info;
+    enum wined3d_conversion_type convert;
+    struct wined3d_context *context;
+    struct wined3d_bo_address data;
+    struct wined3d_format format;
+    UINT update_w, update_h;
+    UINT dst_w, dst_h;
+    RECT r, dst_rect;
+    UINT src_pitch;
+    POINT p;
+
+    TRACE("dst_surface %p, dst_point %s, src_surface %p, src_rect %s.\n",
+            dst_surface, wine_dbgstr_point(dst_point),
+            src_surface, wine_dbgstr_rect(src_rect));
+
+    src_format = src_surface->resource.format;
+    dst_format = dst_surface->resource.format;
+
+    if (src_format->id != dst_format->id)
+    {
+        WARN("Source and destination surfaces should have the same format.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    if (!dst_point)
+    {
+        p.x = 0;
+        p.y = 0;
+        dst_point = &p;
+    }
+    else if (dst_point->x < 0 || dst_point->y < 0)
+    {
+        WARN("Invalid destination point.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    if (!src_rect)
+    {
+        r.left = 0;
+        r.top = 0;
+        r.right = src_surface->resource.width;
+        r.bottom = src_surface->resource.height;
+        src_rect = &r;
+    }
+    else if (src_rect->left < 0 || src_rect->left >= src_rect->right
+            || src_rect->top < 0 || src_rect->top >= src_rect->bottom)
+    {
+        WARN("Invalid source rectangle.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    dst_w = dst_surface->resource.width;
+    dst_h = dst_surface->resource.height;
+
+    update_w = src_rect->right - src_rect->left;
+    update_h = src_rect->bottom - src_rect->top;
+
+    if (update_w > dst_w || dst_point->x > dst_w - update_w
+            || update_h > dst_h || dst_point->y > dst_h - update_h)
+    {
+        WARN("Destination out of bounds.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    if ((src_format->flags & WINED3DFMT_FLAG_BLOCKS) && !surface_check_block_align(src_surface, src_rect))
+    {
+        WARN("Source rectangle not block-aligned.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    SetRect(&dst_rect, dst_point->x, dst_point->y, dst_point->x + update_w, dst_point->y + update_h);
+    if ((dst_format->flags & WINED3DFMT_FLAG_BLOCKS) && !surface_check_block_align(dst_surface, &dst_rect))
+    {
+        WARN("Destination rectangle not block-aligned.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    /* Use wined3d_surface_blt() instead of uploading directly if we need conversion. */
+    d3dfmt_get_conv(dst_surface, FALSE, TRUE, &format, &convert);
+    if (convert != WINED3D_CT_NONE || format.convert)
+        return wined3d_surface_blt(dst_surface, &dst_rect, src_surface, src_rect, 0, NULL, WINED3D_TEXF_POINT);
+
+    context = context_acquire(dst_surface->resource.device, NULL);
+    gl_info = context->gl_info;
+
+    /* Only load the surface for partial updates. For newly allocated texture
+     * the texture wouldn't be the current location, and we'd upload zeroes
+     * just to overwrite them again. */
+    if (update_w == dst_w && update_h == dst_h)
+        surface_prepare_texture(dst_surface, context, FALSE);
+    else
+        surface_load_location(dst_surface, SFLAG_INTEXTURE, NULL);
+    surface_bind(dst_surface, context, FALSE);
+
+    data.buffer_object = src_surface->pbo;
+    data.addr = src_surface->resource.allocatedMemory;
+    src_pitch = wined3d_surface_get_pitch(src_surface);
+
+    surface_upload_data(dst_surface, gl_info, src_format, src_rect, src_pitch, dst_point, FALSE, &data);
+
+    invalidate_active_texture(dst_surface->resource.device, context);
+
+    context_release(context);
+
+    surface_modify_location(dst_surface, SFLAG_INTEXTURE, TRUE);
+    return WINED3D_OK;
+}
+
+/* This call just allocates the texture, the caller is responsible for binding
+ * the correct texture. */
+/* Context activation is done by the caller. */
+static void surface_allocate_surface(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info,
+        const struct wined3d_format *format, BOOL srgb)
+{
+    BOOL enable_client_storage = FALSE;
+    GLsizei width = surface->pow2Width;
+    GLsizei height = surface->pow2Height;
+    const BYTE *mem = NULL;
+    GLenum internal;
+
+#ifdef VBOX_WITH_WDDM
+    if (VBOXSHRC_IS_SHARED_OPENED(surface))
+    {
+        ERR("trying to allocate shared openned resource!!, ignoring..\n");
+        return;
+    }
+#endif
+
+    if (srgb)
+    {
+        internal = format->glGammaInternal;
+    }
+    else if (surface->resource.usage & WINED3DUSAGE_RENDERTARGET && surface_is_offscreen(surface))
+    {
+        internal = format->rtInternal;
+    }
+    else
+    {
+        internal = format->glInternal;
+    }
+
+    if (!internal)
+        FIXME("No GL internal format for format %s.\n", debug_d3dformat(format->id));
+
+    if (format->flags & WINED3DFMT_FLAG_HEIGHT_SCALE)
+    {
+        height *= format->height_scale.numerator;
+        height /= format->height_scale.denominator;
+    }
+
+    TRACE("(%p) : Creating surface (target %#x)  level %d, d3d format %s, internal format %#x, width %d, height %d, gl format %#x, gl type=%#x\n",
+            surface, surface->texture_target, surface->texture_level, debug_d3dformat(format->id),
+            internal, width, height, format->glFormat, format->glType);
+
+    if (gl_info->supported[APPLE_CLIENT_STORAGE])
+    {
+        if (surface->flags & (SFLAG_NONPOW2 | SFLAG_DIBSECTION | SFLAG_CONVERTED)
+                || !surface->resource.allocatedMemory)
+        {
+            /* In some cases we want to disable client storage.
+             * SFLAG_NONPOW2 has a bigger opengl texture than the client memory, and different pitches
+             * SFLAG_DIBSECTION: Dibsections may have read / write protections on the memory. Avoid issues...
+             * SFLAG_CONVERTED: The conversion destination memory is freed after loading the surface
+             * allocatedMemory == NULL: Not defined in the extension. Seems to disable client storage effectively
+             */
+            gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
+            checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
+            surface->flags &= ~SFLAG_CLIENT;
+            enable_client_storage = TRUE;
+        }
+        else
+        {
+            surface->flags |= SFLAG_CLIENT;
+
+            /* Point OpenGL to our allocated texture memory. Do not use
+             * resource.allocatedMemory here because it might point into a
+             * PBO. Instead use heapMemory, but get the alignment right. */
+            mem = (BYTE *)(((ULONG_PTR)surface->resource.heapMemory
+                    + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1));
+        }
+    }
+
+    if (format->flags & WINED3DFMT_FLAG_COMPRESSED && mem)
+    {
+        GL_EXTCALL(glCompressedTexImage2DARB(surface->texture_target, surface->texture_level,
+                internal, width, height, 0, surface->resource.size, mem));
+        checkGLcall("glCompressedTexImage2DARB");
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glTexImage2D(surface->texture_target, surface->texture_level,
+                internal, width, height, 0, format->glFormat, format->glType, mem);
+        checkGLcall("glTexImage2D");
+    }
+
+    if (enable_client_storage)
+    {
+        gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
+        checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
+    }
+}
+
+/* In D3D the depth stencil dimensions have to be greater than or equal to the
+ * render target dimensions. With FBOs, the dimensions have to be an exact match. */
+/* TODO: We should synchronize the renderbuffer's content with the texture's content. */
+/* Context activation is done by the caller. */
+void surface_set_compatible_renderbuffer(struct wined3d_surface *surface, const struct wined3d_surface *rt)
+{
+    const struct wined3d_gl_info *gl_info = &surface->resource.device->adapter->gl_info;
+    struct wined3d_renderbuffer_entry *entry;
+    GLuint renderbuffer = 0;
+    unsigned int src_width, src_height;
+    unsigned int width, height;
+
+    if (rt && rt->resource.format->id != WINED3DFMT_NULL)
+    {
+        width = rt->pow2Width;
+        height = rt->pow2Height;
+    }
+    else
+    {
+        width = surface->pow2Width;
+        height = surface->pow2Height;
+    }
+
+    src_width = surface->pow2Width;
+    src_height = surface->pow2Height;
+
+    /* A depth stencil smaller than the render target is not valid */
+    if (width > src_width || height > src_height) return;
+
+    /* Remove any renderbuffer set if the sizes match */
+    if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT]
+            || (width == src_width && height == src_height))
+    {
+        surface->current_renderbuffer = NULL;
+        return;
+    }
+
+    /* Look if we've already got a renderbuffer of the correct dimensions */
+    LIST_FOR_EACH_ENTRY(entry, &surface->renderbuffers, struct wined3d_renderbuffer_entry, entry)
+    {
+        if (entry->width == width && entry->height == height)
+        {
+            renderbuffer = entry->id;
+            surface->current_renderbuffer = entry;
+            break;
+        }
+    }
+
+    if (!renderbuffer)
+    {
+        gl_info->fbo_ops.glGenRenderbuffers(1, &renderbuffer);
+        gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
+        gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER,
+                surface->resource.format->glInternal, width, height);
+
+        entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*entry));
+        entry->width = width;
+        entry->height = height;
+        entry->id = renderbuffer;
+        list_add_head(&surface->renderbuffers, &entry->entry);
+
+        surface->current_renderbuffer = entry;
+    }
+
+    checkGLcall("set_compatible_renderbuffer");
+}
+
+GLenum surface_get_gl_buffer(const struct wined3d_surface *surface)
+{
+    const struct wined3d_swapchain *swapchain = surface->swapchain;
+
+    TRACE("surface %p.\n", surface);
+
+    if (!swapchain)
+    {
+        ERR("Surface %p is not on a swapchain.\n", surface);
+        return GL_NONE;
+    }
+
+    if (swapchain->back_buffers && swapchain->back_buffers[0] == surface)
+    {
+        if (swapchain->render_to_fbo)
+        {
+            TRACE("Returning GL_COLOR_ATTACHMENT0\n");
+            return GL_COLOR_ATTACHMENT0;
+        }
+        TRACE("Returning GL_BACK\n");
+        return GL_BACK;
+    }
+    else if (surface == swapchain->front_buffer)
+    {
+        TRACE("Returning GL_FRONT\n");
+        return GL_FRONT;
+    }
+
+    FIXME("Higher back buffer, returning GL_BACK\n");
+    return GL_BACK;
+}
+
+/* Slightly inefficient way to handle multiple dirty rects but it works :) */
+void surface_add_dirty_rect(struct wined3d_surface *surface, const struct wined3d_box *dirty_rect)
+{
+    TRACE("surface %p, dirty_rect %p.\n", surface, dirty_rect);
+
+    if (!(surface->flags & SFLAG_INSYSMEM) && (surface->flags & SFLAG_INTEXTURE))
+        /* No partial locking for textures yet. */
+        surface_load_location(surface, SFLAG_INSYSMEM, NULL);
+
+    surface_modify_location(surface, SFLAG_INSYSMEM, TRUE);
+    if (dirty_rect)
+    {
+        surface->dirtyRect.left = min(surface->dirtyRect.left, dirty_rect->left);
+        surface->dirtyRect.top = min(surface->dirtyRect.top, dirty_rect->top);
+        surface->dirtyRect.right = max(surface->dirtyRect.right, dirty_rect->right);
+        surface->dirtyRect.bottom = max(surface->dirtyRect.bottom, dirty_rect->bottom);
+    }
+    else
+    {
+        surface->dirtyRect.left = 0;
+        surface->dirtyRect.top = 0;
+        surface->dirtyRect.right = surface->resource.width;
+        surface->dirtyRect.bottom = surface->resource.height;
+    }
+
+    /* if the container is a texture then mark it dirty. */
+    if (surface->container)
+    {
+        TRACE("Passing to container.\n");
+        wined3d_texture_set_dirty(surface->container, TRUE);
+    }
+}
+
+HRESULT surface_load(struct wined3d_surface *surface, BOOL srgb)
+{
+    DWORD flag = srgb ? SFLAG_INSRGBTEX : SFLAG_INTEXTURE;
+    BOOL ck_changed;
+
+    TRACE("surface %p, srgb %#x.\n", surface, srgb);
+
+    if (surface->resource.pool == WINED3D_POOL_SCRATCH)
+    {
+        ERR("Not supported on scratch surfaces.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    ck_changed = !(surface->flags & SFLAG_GLCKEY) != !(surface->CKeyFlags & WINEDDSD_CKSRCBLT);
+
+    /* Reload if either the texture and sysmem have different ideas about the
+     * color key, or the actual key values changed. */
+    if (ck_changed || ((surface->CKeyFlags & WINEDDSD_CKSRCBLT)
+            && (surface->gl_color_key.color_space_low_value != surface->src_blt_color_key.color_space_low_value
+            || surface->gl_color_key.color_space_high_value != surface->src_blt_color_key.color_space_high_value)))
+    {
+        TRACE("Reloading because of color keying\n");
+        /* To perform the color key conversion we need a sysmem copy of
+         * the surface. Make sure we have it. */
+
+        surface_load_location(surface, SFLAG_INSYSMEM, NULL);
+        /* Make sure the texture is reloaded because of the color key change,
+         * this kills performance though :( */
+        /* TODO: This is not necessarily needed with hw palettized texture support. */
+        surface_modify_location(surface, SFLAG_INSYSMEM, TRUE);
+        /* Switching color keying on / off may change the internal format. */
+        if (ck_changed)
+            surface_force_reload(surface);
+    }
+    else if (!(surface->flags & flag))
+    {
+        TRACE("Reloading because surface is dirty.\n");
+    }
+    else
+    {
+        TRACE("surface is already in texture\n");
+        return WINED3D_OK;
+    }
+
+    /* No partial locking for textures yet. */
+    surface_load_location(surface, flag, NULL);
+    surface_evict_sysmem(surface);
+
+    return WINED3D_OK;
+}
+
+/* See also float_16_to_32() in wined3d_private.h */
+static inline unsigned short float_32_to_16(const float *in)
+{
+    int exp = 0;
+    float tmp = fabsf(*in);
+    unsigned int mantissa;
+    unsigned short ret;
+
+    /* Deal with special numbers */
+    if (*in == 0.0f)
+        return 0x0000;
+    if (isnan(*in))
+        return 0x7c01;
+    if (isinf(*in))
+        return (*in < 0.0f ? 0xfc00 : 0x7c00);
+
+    if (tmp < powf(2, 10))
+    {
+        do
+        {
+            tmp = tmp * 2.0f;
+            exp--;
+        } while (tmp < powf(2, 10));
+    }
+    else if (tmp >= powf(2, 11))
+    {
+        do
+        {
+            tmp /= 2.0f;
+            exp++;
+        } while (tmp >= powf(2, 11));
+    }
+
+    mantissa = (unsigned int)tmp;
+    if (tmp - mantissa >= 0.5f)
+        ++mantissa; /* Round to nearest, away from zero. */
+
+    exp += 10;  /* Normalize the mantissa. */
+    exp += 15;  /* Exponent is encoded with excess 15. */
+
+    if (exp > 30) /* too big */
+    {
+        ret = 0x7c00; /* INF */
+    }
+    else if (exp <= 0)
+    {
+        /* exp == 0: Non-normalized mantissa. Returns 0x0000 (=0.0) for too small numbers. */
+        while (exp <= 0)
+        {
+            mantissa = mantissa >> 1;
+            ++exp;
+        }
+        ret = mantissa & 0x3ff;
+    }
+    else
+    {
+        ret = (exp << 10) | (mantissa & 0x3ff);
+    }
+
+    ret |= ((*in < 0.0f ? 1 : 0) << 15); /* Add the sign */
+    return ret;
+}
+
+ULONG CDECL wined3d_surface_incref(struct wined3d_surface *surface)
+{
+    ULONG refcount;
+
+    TRACE("surface %p, swapchain %p, container %p.\n",
+            surface, surface->swapchain, surface->container);
+
+    if (surface->swapchain)
+        return wined3d_swapchain_incref(surface->swapchain);
+
+    if (surface->container)
+        return wined3d_texture_incref(surface->container);
+
+    refcount = InterlockedIncrement(&surface->resource.ref);
+    TRACE("%p increasing refcount to %u.\n", surface, refcount);
+
+    return refcount;
+}
+
+/* Do not call while under the GL lock. */
+ULONG CDECL wined3d_surface_decref(struct wined3d_surface *surface)
+{
+    ULONG refcount;
+
+    TRACE("surface %p, swapchain %p, container %p.\n",
+            surface, surface->swapchain, surface->container);
+
+    if (surface->swapchain)
+        return wined3d_swapchain_decref(surface->swapchain);
+
+    if (surface->container)
+        return wined3d_texture_decref(surface->container);
+
+    refcount = InterlockedDecrement(&surface->resource.ref);
+    TRACE("%p decreasing refcount to %u.\n", surface, refcount);
+
+    if (!refcount)
+    {
+        surface_cleanup(surface);
+        surface->resource.parent_ops->wined3d_object_destroyed(surface->resource.parent);
+
+        TRACE("Destroyed surface %p.\n", surface);
+        HeapFree(GetProcessHeap(), 0, surface);
+    }
+
+    return refcount;
+}
+
+DWORD CDECL wined3d_surface_set_priority(struct wined3d_surface *surface, DWORD priority)
+{
+    return resource_set_priority(&surface->resource, priority);
+}
+
+DWORD CDECL wined3d_surface_get_priority(const struct wined3d_surface *surface)
+{
+    return resource_get_priority(&surface->resource);
+}
+
+void CDECL wined3d_surface_preload(struct wined3d_surface *surface)
+{
+    TRACE("surface %p.\n", surface);
+
+    if (!surface->resource.device->d3d_initialized)
+    {
+        ERR("D3D not initialized.\n");
+        return;
+    }
+
+    surface_internal_preload(surface, SRGB_ANY);
+}
+
+void * CDECL wined3d_surface_get_parent(const struct wined3d_surface *surface)
+{
+    TRACE("surface %p.\n", surface);
+
+    return surface->resource.parent;
+}
+
+struct wined3d_resource * CDECL wined3d_surface_get_resource(struct wined3d_surface *surface)
+{
+    TRACE("surface %p.\n", surface);
+
+    return &surface->resource;
+}
+
+HRESULT CDECL wined3d_surface_get_blt_status(const struct wined3d_surface *surface, DWORD flags)
+{
+    TRACE("surface %p, flags %#x.\n", surface, flags);
+
+    switch (flags)
+    {
+        case WINEDDGBS_CANBLT:
+        case WINEDDGBS_ISBLTDONE:
+            return WINED3D_OK;
+
+        default:
+            return WINED3DERR_INVALIDCALL;
+    }
+}
+
+HRESULT CDECL wined3d_surface_get_flip_status(const struct wined3d_surface *surface, DWORD flags)
+{
+    TRACE("surface %p, flags %#x.\n", surface, flags);
+
+    /* XXX: DDERR_INVALIDSURFACETYPE */
+
+    switch (flags)
+    {
+        case WINEDDGFS_CANFLIP:
+        case WINEDDGFS_ISFLIPDONE:
+            return WINED3D_OK;
+
+        default:
+            return WINED3DERR_INVALIDCALL;
+    }
+}
+
+HRESULT CDECL wined3d_surface_is_lost(const struct wined3d_surface *surface)
+{
+    TRACE("surface %p.\n", surface);
+
+    /* D3D8 and 9 loose full devices, ddraw only surfaces. */
+    return surface->flags & SFLAG_LOST ? WINED3DERR_DEVICELOST : WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_surface_restore(struct wined3d_surface *surface)
+{
+    TRACE("surface %p.\n", surface);
+
+    surface->flags &= ~SFLAG_LOST;
+    return WINED3D_OK;
+}
+
+void CDECL wined3d_surface_set_palette(struct wined3d_surface *surface, struct wined3d_palette *palette)
+{
+    TRACE("surface %p, palette %p.\n", surface, palette);
+
+    if (surface->palette == palette)
+    {
+        TRACE("Nop palette change.\n");
+        return;
+    }
+
+    if (surface->palette && (surface->resource.usage & WINED3DUSAGE_RENDERTARGET))
+        surface->palette->flags &= ~WINEDDPCAPS_PRIMARYSURFACE;
+
+    surface->palette = palette;
+
+    if (palette)
+    {
+        if (surface->resource.usage & WINED3DUSAGE_RENDERTARGET)
+            palette->flags |= WINEDDPCAPS_PRIMARYSURFACE;
+
+        surface->surface_ops->surface_realize_palette(surface);
+    }
+}
+
+HRESULT CDECL wined3d_surface_set_color_key(struct wined3d_surface *surface,
+        DWORD flags, const struct wined3d_color_key *color_key)
+{
+    TRACE("surface %p, flags %#x, color_key %p.\n", surface, flags, color_key);
+
+    if (flags & WINEDDCKEY_COLORSPACE)
+    {
+        FIXME(" colorkey value not supported (%08x) !\n", flags);
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    /* Dirtify the surface, but only if a key was changed. */
+    if (color_key)
+    {
+        switch (flags & ~WINEDDCKEY_COLORSPACE)
+        {
+            case WINEDDCKEY_DESTBLT:
+                surface->dst_blt_color_key = *color_key;
+                surface->CKeyFlags |= WINEDDSD_CKDESTBLT;
+                break;
+
+            case WINEDDCKEY_DESTOVERLAY:
+                surface->dst_overlay_color_key = *color_key;
+                surface->CKeyFlags |= WINEDDSD_CKDESTOVERLAY;
+                break;
+
+            case WINEDDCKEY_SRCOVERLAY:
+                surface->src_overlay_color_key = *color_key;
+                surface->CKeyFlags |= WINEDDSD_CKSRCOVERLAY;
+                break;
+
+            case WINEDDCKEY_SRCBLT:
+                surface->src_blt_color_key = *color_key;
+                surface->CKeyFlags |= WINEDDSD_CKSRCBLT;
+                break;
+        }
+    }
+    else
+    {
+        switch (flags & ~WINEDDCKEY_COLORSPACE)
+        {
+            case WINEDDCKEY_DESTBLT:
+                surface->CKeyFlags &= ~WINEDDSD_CKDESTBLT;
+                break;
+
+            case WINEDDCKEY_DESTOVERLAY:
+                surface->CKeyFlags &= ~WINEDDSD_CKDESTOVERLAY;
+                break;
+
+            case WINEDDCKEY_SRCOVERLAY:
+                surface->CKeyFlags &= ~WINEDDSD_CKSRCOVERLAY;
+                break;
+
+            case WINEDDCKEY_SRCBLT:
+                surface->CKeyFlags &= ~WINEDDSD_CKSRCBLT;
+                break;
+        }
+    }
+
+    return WINED3D_OK;
+}
+
+struct wined3d_palette * CDECL wined3d_surface_get_palette(const struct wined3d_surface *surface)
+{
+    TRACE("surface %p.\n", surface);
+
+    return surface->palette;
+}
+
+DWORD CDECL wined3d_surface_get_pitch(const struct wined3d_surface *surface)
+{
+    const struct wined3d_format *format = surface->resource.format;
+    DWORD pitch;
+
+    TRACE("surface %p.\n", surface);
+
+    if (format->flags & WINED3DFMT_FLAG_BLOCKS)
+    {
+        /* Since compressed formats are block based, pitch means the amount of
+         * bytes to the next row of block rather than the next row of pixels. */
+        UINT row_block_count = (surface->resource.width + format->block_width - 1) / format->block_width;
+        pitch = row_block_count * format->block_byte_count;
+    }
+    else
+    {
+        unsigned char alignment = surface->resource.device->surface_alignment;
+        pitch = surface->resource.format->byte_count * surface->resource.width;  /* Bytes / row */
+        pitch = (pitch + alignment - 1) & ~(alignment - 1);
+    }
+
+    TRACE("Returning %u.\n", pitch);
+
+    return pitch;
+}
+
+HRESULT CDECL wined3d_surface_set_mem(struct wined3d_surface *surface, void *mem)
+{
+#ifndef VBOX_WITH_WDDM
+    TRACE("surface %p, mem %p.\n", surface, mem);
+
+    if (surface->resource.map_count || (surface->flags & SFLAG_DCINUSE))
+    {
+        WARN("Surface is mapped or the DC is in use.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    /* Render targets depend on their hdc, and we can't create an hdc on a user pointer. */
+    if (surface->resource.usage & WINED3DUSAGE_RENDERTARGET)
+    {
+        ERR("Not supported on render targets.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    if (mem && mem != surface->resource.allocatedMemory)
+    {
+        void *release = NULL;
+
+        /* Do I have to copy the old surface content? */
+        if (surface->flags & SFLAG_DIBSECTION)
+        {
+            DeleteDC(surface->hDC);
+            DeleteObject(surface->dib.DIBsection);
+            surface->dib.bitmap_data = NULL;
+            surface->resource.allocatedMemory = NULL;
+            surface->hDC = NULL;
+            surface->flags &= ~SFLAG_DIBSECTION;
+        }
+        else if (!(surface->flags & SFLAG_USERPTR))
+        {
+            release = surface->resource.heapMemory;
+            surface->resource.heapMemory = NULL;
+        }
+        surface->resource.allocatedMemory = mem;
+        surface->flags |= SFLAG_USERPTR;
+
+        /* Now the surface memory is most up do date. Invalidate drawable and texture. */
+        surface_modify_location(surface, SFLAG_INSYSMEM, TRUE);
+
+        /* For client textures OpenGL has to be notified. */
+        if (surface->flags & SFLAG_CLIENT)
+            surface_release_client_storage(surface);
+
+        /* Now free the old memory if any. */
+        HeapFree(GetProcessHeap(), 0, release);
+    }
+    else if (surface->flags & SFLAG_USERPTR)
+    {
+        /* HeapMemory should be NULL already. */
+        if (surface->resource.heapMemory)
+            ERR("User pointer surface has heap memory allocated.\n");
+
+        if (!mem)
+        {
+            surface->resource.allocatedMemory = NULL;
+            surface->flags &= ~(SFLAG_USERPTR | SFLAG_INSYSMEM);
+
+            if (surface->flags & SFLAG_CLIENT)
+                surface_release_client_storage(surface);
+
+            surface_prepare_system_memory(surface);
+        }
+
+        surface_modify_location(surface, SFLAG_INSYSMEM, TRUE);
+    }
+
+    return WINED3D_OK;
+#else
+    ERR("unsupported!");
+    return E_FAIL;
+#endif
+}
+
+HRESULT CDECL wined3d_surface_set_overlay_position(struct wined3d_surface *surface, LONG x, LONG y)
+{
+    LONG w, h;
+
+    TRACE("surface %p, x %d, y %d.\n", surface, x, y);
+
+    if (!(surface->resource.usage & WINED3DUSAGE_OVERLAY))
+    {
+        WARN("Not an overlay surface.\n");
+        return WINEDDERR_NOTAOVERLAYSURFACE;
+    }
+
+    w = surface->overlay_destrect.right - surface->overlay_destrect.left;
+    h = surface->overlay_destrect.bottom - surface->overlay_destrect.top;
+    surface->overlay_destrect.left = x;
+    surface->overlay_destrect.top = y;
+    surface->overlay_destrect.right = x + w;
+    surface->overlay_destrect.bottom = y + h;
+
+    surface_draw_overlay(surface);
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_surface_get_overlay_position(const struct wined3d_surface *surface, LONG *x, LONG *y)
+{
+    TRACE("surface %p, x %p, y %p.\n", surface, x, y);
+
+    if (!(surface->resource.usage & WINED3DUSAGE_OVERLAY))
+    {
+        TRACE("Not an overlay surface.\n");
+        return WINEDDERR_NOTAOVERLAYSURFACE;
+    }
+
+    if (!surface->overlay_dest)
+    {
+        TRACE("Overlay not visible.\n");
+        *x = 0;
+        *y = 0;
+        return WINEDDERR_OVERLAYNOTVISIBLE;
+    }
+
+    *x = surface->overlay_destrect.left;
+    *y = surface->overlay_destrect.top;
+
+    TRACE("Returning position %d, %d.\n", *x, *y);
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_surface_update_overlay_z_order(struct wined3d_surface *surface,
+        DWORD flags, struct wined3d_surface *ref)
+{
+    FIXME("surface %p, flags %#x, ref %p stub!\n", surface, flags, ref);
+
+    if (!(surface->resource.usage & WINED3DUSAGE_OVERLAY))
+    {
+        TRACE("Not an overlay surface.\n");
+        return WINEDDERR_NOTAOVERLAYSURFACE;
+    }
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_surface_update_overlay(struct wined3d_surface *surface, const RECT *src_rect,
+        struct wined3d_surface *dst_surface, const RECT *dst_rect, DWORD flags, const WINEDDOVERLAYFX *fx)
+{
+    TRACE("surface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
+            surface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
+
+    if (!(surface->resource.usage & WINED3DUSAGE_OVERLAY))
+    {
+        WARN("Not an overlay surface.\n");
+        return WINEDDERR_NOTAOVERLAYSURFACE;
+    }
+    else if (!dst_surface)
+    {
+        WARN("Dest surface is NULL.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    if (src_rect)
+    {
+        surface->overlay_srcrect = *src_rect;
+    }
+    else
+    {
+        surface->overlay_srcrect.left = 0;
+        surface->overlay_srcrect.top = 0;
+        surface->overlay_srcrect.right = surface->resource.width;
+        surface->overlay_srcrect.bottom = surface->resource.height;
+    }
+
+    if (dst_rect)
+    {
+        surface->overlay_destrect = *dst_rect;
+    }
+    else
+    {
+        surface->overlay_destrect.left = 0;
+        surface->overlay_destrect.top = 0;
+        surface->overlay_destrect.right = dst_surface ? dst_surface->resource.width : 0;
+        surface->overlay_destrect.bottom = dst_surface ? dst_surface->resource.height : 0;
+    }
+
+    if (surface->overlay_dest && (surface->overlay_dest != dst_surface || flags & WINEDDOVER_HIDE))
+    {
+        surface->overlay_dest = NULL;
+        list_remove(&surface->overlay_entry);
+    }
+
+    if (flags & WINEDDOVER_SHOW)
+    {
+        if (surface->overlay_dest != dst_surface)
+        {
+            surface->overlay_dest = dst_surface;
+            list_add_tail(&dst_surface->overlays, &surface->overlay_entry);
+        }
+    }
+    else if (flags & WINEDDOVER_HIDE)
+    {
+        /* tests show that the rectangles are erased on hide */
+        surface->overlay_srcrect.left = 0; surface->overlay_srcrect.top = 0;
+        surface->overlay_srcrect.right = 0; surface->overlay_srcrect.bottom = 0;
+        surface->overlay_destrect.left = 0; surface->overlay_destrect.top = 0;
+        surface->overlay_destrect.right = 0; surface->overlay_destrect.bottom = 0;
+        surface->overlay_dest = NULL;
+    }
+
+    surface_draw_overlay(surface);
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_surface_update_desc(struct wined3d_surface *surface,
+        UINT width, UINT height, enum wined3d_format_id format_id,
+        enum wined3d_multisample_type multisample_type, UINT multisample_quality)
+{
+    struct wined3d_device *device = surface->resource.device;
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    const struct wined3d_format *format = wined3d_get_format(gl_info, format_id);
+    UINT resource_size = wined3d_format_calculate_size(format, device->surface_alignment, width, height);
+
+    TRACE("surface %p, width %u, height %u, format %s, multisample_type %#x, multisample_quality %u.\n",
+            surface, width, height, debug_d3dformat(format_id), multisample_type, multisample_type);
+
+    if (!resource_size)
+        return WINED3DERR_INVALIDCALL;
+
+    if (device->d3d_initialized)
+        surface->resource.resource_ops->resource_unload(&surface->resource);
+
+    if (surface->flags & SFLAG_DIBSECTION)
+    {
+        DeleteDC(surface->hDC);
+        DeleteObject(surface->dib.DIBsection);
+        surface->dib.bitmap_data = NULL;
+        surface->flags &= ~SFLAG_DIBSECTION;
+    }
+
+    surface->flags &= ~(SFLAG_LOCATIONS | SFLAG_USERPTR);
+    surface->resource.allocatedMemory = NULL;
+    HeapFree(GetProcessHeap(), 0, surface->resource.heapMemory);
+    surface->resource.heapMemory = NULL;
+
+    surface->resource.width = width;
+    surface->resource.height = height;
+    if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] || gl_info->supported[ARB_TEXTURE_RECTANGLE]
+            || gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT])
+    {
+        surface->pow2Width = width;
+        surface->pow2Height = height;
+    }
+    else
+    {
+        surface->pow2Width = surface->pow2Height = 1;
+        while (surface->pow2Width < width)
+            surface->pow2Width <<= 1;
+        while (surface->pow2Height < height)
+            surface->pow2Height <<= 1;
+    }
+
+    if (surface->pow2Width != width || surface->pow2Height != height)
+        surface->flags |= SFLAG_NONPOW2;
+    else
+        surface->flags &= ~SFLAG_NONPOW2;
+
+    surface->resource.format = format;
+    surface->resource.multisample_type = multisample_type;
+    surface->resource.multisample_quality = multisample_quality;
+    surface->resource.size = resource_size;
+
+    if (!surface_init_sysmem(surface))
+        return E_OUTOFMEMORY;
+
+    return WINED3D_OK;
+}
+
+static void convert_r32_float_r16_float(const BYTE *src, BYTE *dst,
+        DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h)
+{
+    unsigned short *dst_s;
+    const float *src_f;
+    unsigned int x, y;
+
+    TRACE("Converting %ux%u pixels, pitches %u %u.\n", w, h, pitch_in, pitch_out);
+
+    for (y = 0; y < h; ++y)
+    {
+        src_f = (const float *)(src + y * pitch_in);
+        dst_s = (unsigned short *) (dst + y * pitch_out);
+        for (x = 0; x < w; ++x)
+        {
+            dst_s[x] = float_32_to_16(src_f + x);
+        }
+    }
+}
+
+static void convert_r5g6b5_x8r8g8b8(const BYTE *src, BYTE *dst,
+        DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h)
+{
+    static const unsigned char convert_5to8[] =
+    {
+        0x00, 0x08, 0x10, 0x19, 0x21, 0x29, 0x31, 0x3a,
+        0x42, 0x4a, 0x52, 0x5a, 0x63, 0x6b, 0x73, 0x7b,
+        0x84, 0x8c, 0x94, 0x9c, 0xa5, 0xad, 0xb5, 0xbd,
+        0xc5, 0xce, 0xd6, 0xde, 0xe6, 0xef, 0xf7, 0xff,
+    };
+    static const unsigned char convert_6to8[] =
+    {
+        0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c,
+        0x20, 0x24, 0x28, 0x2d, 0x31, 0x35, 0x39, 0x3d,
+        0x41, 0x45, 0x49, 0x4d, 0x51, 0x55, 0x59, 0x5d,
+        0x61, 0x65, 0x69, 0x6d, 0x71, 0x75, 0x79, 0x7d,
+        0x82, 0x86, 0x8a, 0x8e, 0x92, 0x96, 0x9a, 0x9e,
+        0xa2, 0xa6, 0xaa, 0xae, 0xb2, 0xb6, 0xba, 0xbe,
+        0xc2, 0xc6, 0xca, 0xce, 0xd2, 0xd7, 0xdb, 0xdf,
+        0xe3, 0xe7, 0xeb, 0xef, 0xf3, 0xf7, 0xfb, 0xff,
+    };
+    unsigned int x, y;
+
+    TRACE("Converting %ux%u pixels, pitches %u %u.\n", w, h, pitch_in, pitch_out);
+
+    for (y = 0; y < h; ++y)
+    {
+        const WORD *src_line = (const WORD *)(src + y * pitch_in);
+        DWORD *dst_line = (DWORD *)(dst + y * pitch_out);
+        for (x = 0; x < w; ++x)
+        {
+            WORD pixel = src_line[x];
+            dst_line[x] = 0xff000000
+                    | convert_5to8[(pixel & 0xf800) >> 11] << 16
+                    | convert_6to8[(pixel & 0x07e0) >> 5] << 8
+                    | convert_5to8[(pixel & 0x001f)];
+        }
+    }
+}
+
+/* We use this for both B8G8R8A8 -> B8G8R8X8 and B8G8R8X8 -> B8G8R8A8, since
+ * in both cases we're just setting the X / Alpha channel to 0xff. */
+static void convert_a8r8g8b8_x8r8g8b8(const BYTE *src, BYTE *dst,
+        DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h)
+{
+    unsigned int x, y;
+
+    TRACE("Converting %ux%u pixels, pitches %u %u.\n", w, h, pitch_in, pitch_out);
+
+    for (y = 0; y < h; ++y)
+    {
+        const DWORD *src_line = (const DWORD *)(src + y * pitch_in);
+        DWORD *dst_line = (DWORD *)(dst + y * pitch_out);
+
+        for (x = 0; x < w; ++x)
+        {
+            dst_line[x] = 0xff000000 | (src_line[x] & 0xffffff);
+        }
+    }
+}
+
+static inline BYTE cliptobyte(int x)
+{
+    return (BYTE)((x < 0) ? 0 : ((x > 255) ? 255 : x));
+}
+
+static void convert_yuy2_x8r8g8b8(const BYTE *src, BYTE *dst,
+        DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h)
+{
+    int c2, d, e, r2 = 0, g2 = 0, b2 = 0;
+    unsigned int x, y;
+
+    TRACE("Converting %ux%u pixels, pitches %u %u.\n", w, h, pitch_in, pitch_out);
+
+    for (y = 0; y < h; ++y)
+    {
+        const BYTE *src_line = src + y * pitch_in;
+        DWORD *dst_line = (DWORD *)(dst + y * pitch_out);
+        for (x = 0; x < w; ++x)
+        {
+            /* YUV to RGB conversion formulas from http://en.wikipedia.org/wiki/YUV:
+             *     C = Y - 16; D = U - 128; E = V - 128;
+             *     R = cliptobyte((298 * C + 409 * E + 128) >> 8);
+             *     G = cliptobyte((298 * C - 100 * D - 208 * E + 128) >> 8);
+             *     B = cliptobyte((298 * C + 516 * D + 128) >> 8);
+             * Two adjacent YUY2 pixels are stored as four bytes: Y0 U Y1 V .
+             * U and V are shared between the pixels. */
+            if (!(x & 1)) /* For every even pixel, read new U and V. */
+            {
+                d = (int) src_line[1] - 128;
+                e = (int) src_line[3] - 128;
+                r2 = 409 * e + 128;
+                g2 = - 100 * d - 208 * e + 128;
+                b2 = 516 * d + 128;
+            }
+            c2 = 298 * ((int) src_line[0] - 16);
+            dst_line[x] = 0xff000000
+                | cliptobyte((c2 + r2) >> 8) << 16    /* red   */
+                | cliptobyte((c2 + g2) >> 8) << 8     /* green */
+                | cliptobyte((c2 + b2) >> 8);         /* blue  */
+                /* Scale RGB values to 0..255 range,
+                 * then clip them if still not in range (may be negative),
+                 * then shift them within DWORD if necessary. */
+            src_line += 2;
+        }
+    }
+}
+
+static void convert_yuy2_r5g6b5(const BYTE *src, BYTE *dst,
+        DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h)
+{
+    unsigned int x, y;
+    int c2, d, e, r2 = 0, g2 = 0, b2 = 0;
+
+    TRACE("Converting %ux%u pixels, pitches %u %u\n", w, h, pitch_in, pitch_out);
+
+    for (y = 0; y < h; ++y)
+    {
+        const BYTE *src_line = src + y * pitch_in;
+        WORD *dst_line = (WORD *)(dst + y * pitch_out);
+        for (x = 0; x < w; ++x)
+        {
+            /* YUV to RGB conversion formulas from http://en.wikipedia.org/wiki/YUV:
+             *     C = Y - 16; D = U - 128; E = V - 128;
+             *     R = cliptobyte((298 * C + 409 * E + 128) >> 8);
+             *     G = cliptobyte((298 * C - 100 * D - 208 * E + 128) >> 8);
+             *     B = cliptobyte((298 * C + 516 * D + 128) >> 8);
+             * Two adjacent YUY2 pixels are stored as four bytes: Y0 U Y1 V .
+             * U and V are shared between the pixels. */
+            if (!(x & 1)) /* For every even pixel, read new U and V. */
+            {
+                d = (int) src_line[1] - 128;
+                e = (int) src_line[3] - 128;
+                r2 = 409 * e + 128;
+                g2 = - 100 * d - 208 * e + 128;
+                b2 = 516 * d + 128;
+            }
+            c2 = 298 * ((int) src_line[0] - 16);
+            dst_line[x] = (cliptobyte((c2 + r2) >> 8) >> 3) << 11   /* red   */
+                | (cliptobyte((c2 + g2) >> 8) >> 2) << 5            /* green */
+                | (cliptobyte((c2 + b2) >> 8) >> 3);                /* blue  */
+                /* Scale RGB values to 0..255 range,
+                 * then clip them if still not in range (may be negative),
+                 * then shift them within DWORD if necessary. */
+            src_line += 2;
+        }
+    }
+}
+
+struct d3dfmt_converter_desc
+{
+    enum wined3d_format_id from, to;
+    void (*convert)(const BYTE *src, BYTE *dst, DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h);
+};
+
+static const struct d3dfmt_converter_desc converters[] =
+{
+    {WINED3DFMT_R32_FLOAT,      WINED3DFMT_R16_FLOAT,       convert_r32_float_r16_float},
+    {WINED3DFMT_B5G6R5_UNORM,   WINED3DFMT_B8G8R8X8_UNORM,  convert_r5g6b5_x8r8g8b8},
+    {WINED3DFMT_B8G8R8A8_UNORM, WINED3DFMT_B8G8R8X8_UNORM,  convert_a8r8g8b8_x8r8g8b8},
+    {WINED3DFMT_B8G8R8X8_UNORM, WINED3DFMT_B8G8R8A8_UNORM,  convert_a8r8g8b8_x8r8g8b8},
+    {WINED3DFMT_YUY2,           WINED3DFMT_B8G8R8X8_UNORM,  convert_yuy2_x8r8g8b8},
+    {WINED3DFMT_YUY2,           WINED3DFMT_B5G6R5_UNORM,    convert_yuy2_r5g6b5},
+};
+
+static inline const struct d3dfmt_converter_desc *find_converter(enum wined3d_format_id from,
+        enum wined3d_format_id to)
+{
+    unsigned int i;
+
+    for (i = 0; i < (sizeof(converters) / sizeof(*converters)); ++i)
+    {
+        if (converters[i].from == from && converters[i].to == to)
+            return &converters[i];
+    }
+
+    return NULL;
+}
+
+/*****************************************************************************
+ * surface_convert_format
+ *
+ * Creates a duplicate of a surface in a different format. Is used by Blt to
+ * blit between surfaces with different formats.
+ *
+ * Parameters
+ *  source: Source surface
+ *  fmt: Requested destination format
+ *
+ *****************************************************************************/
+static struct wined3d_surface *surface_convert_format(struct wined3d_surface *source, enum wined3d_format_id to_fmt)
+{
+    struct wined3d_map_desc src_map, dst_map;
+    const struct d3dfmt_converter_desc *conv;
+    struct wined3d_surface *ret = NULL;
+    HRESULT hr;
+
+    conv = find_converter(source->resource.format->id, to_fmt);
+    if (!conv)
+    {
+        FIXME("Cannot find a conversion function from format %s to %s.\n",
+                debug_d3dformat(source->resource.format->id), debug_d3dformat(to_fmt));
+        return NULL;
+    }
+
+    /* FIXME: Multisampled conversion? */
+#ifdef VBOX_WITH_WDDM
+    if (FAILED(hr = wined3d_surface_create(source->resource.device, source->resource.width, source->resource.height,
+            to_fmt, 0, WINED3D_POOL_SCRATCH, WINED3D_MULTISAMPLE_NONE, 0,
+            WINED3D_SURFACE_MAPPABLE | WINED3D_SURFACE_DISCARD, NULL, &wined3d_null_parent_ops, &ret
+            , NULL, NULL
+            )))
+#else
+    if (FAILED(hr = wined3d_surface_create(source->resource.device, source->resource.width, source->resource.height,
+            to_fmt, 0, WINED3D_POOL_SCRATCH, WINED3D_MULTISAMPLE_NONE, 0,
+            WINED3D_SURFACE_MAPPABLE | WINED3D_SURFACE_DISCARD, NULL, &wined3d_null_parent_ops, &ret)))
+#endif
+    {
+        ERR("Failed to create a destination surface for conversion.\n");
+        return NULL;
+    }
+
+    memset(&src_map, 0, sizeof(src_map));
+    memset(&dst_map, 0, sizeof(dst_map));
+
+    if (FAILED(hr = wined3d_surface_map(source, &src_map, NULL, WINED3D_MAP_READONLY)))
+    {
+        ERR("Failed to lock the source surface.\n");
+        wined3d_surface_decref(ret);
+        return NULL;
+    }
+    if (FAILED(hr = wined3d_surface_map(ret, &dst_map, NULL, WINED3D_MAP_READONLY)))
+    {
+        ERR("Failed to lock the destination surface.\n");
+        wined3d_surface_unmap(source);
+        wined3d_surface_decref(ret);
+        return NULL;
+    }
+
+    conv->convert(src_map.data, dst_map.data, src_map.row_pitch, dst_map.row_pitch,
+            source->resource.width, source->resource.height);
+
+    wined3d_surface_unmap(ret);
+    wined3d_surface_unmap(source);
+
+    return ret;
+}
+
+static HRESULT _Blt_ColorFill(BYTE *buf, unsigned int width, unsigned int height,
+        unsigned int bpp, UINT pitch, DWORD color)
+{
+    BYTE *first;
+    unsigned int x, y;
+
+    /* Do first row */
+
+#define COLORFILL_ROW(type) \
+do { \
+    type *d = (type *)buf; \
+    for (x = 0; x < width; ++x) \
+        d[x] = (type)color; \
+} while(0)
+
+    switch (bpp)
+    {
+        case 1:
+            COLORFILL_ROW(BYTE);
+            break;
+
+        case 2:
+            COLORFILL_ROW(WORD);
+            break;
+
+        case 3:
+        {
+            BYTE *d = buf;
+            for (x = 0; x < width; ++x, d += 3)
+            {
+                d[0] = (color      ) & 0xff;
+                d[1] = (color >>  8) & 0xff;
+                d[2] = (color >> 16) & 0xff;
+            }
+            break;
+        }
+        case 4:
+            COLORFILL_ROW(DWORD);
+            break;
+
+        default:
+            FIXME("Color fill not implemented for bpp %u!\n", bpp * 8);
+            return WINED3DERR_NOTAVAILABLE;
+    }
+
+#undef COLORFILL_ROW
+
+    /* Now copy first row. */
+    first = buf;
+    for (y = 1; y < height; ++y)
+    {
+        buf += pitch;
+        memcpy(buf, first, width * bpp);
+    }
+
+    return WINED3D_OK;
+}
+
+struct wined3d_surface * CDECL wined3d_surface_from_resource(struct wined3d_resource *resource)
+{
+    return surface_from_resource(resource);
+}
+
+HRESULT CDECL wined3d_surface_unmap(struct wined3d_surface *surface)
+{
+    TRACE("surface %p.\n", surface);
+
+    if (!surface->resource.map_count)
+    {
+        WARN("Trying to unmap unmapped surface.\n");
+        return WINEDDERR_NOTLOCKED;
+    }
+    --surface->resource.map_count;
+
+    surface->surface_ops->surface_unmap(surface);
+
+#ifdef VBOX_WITH_WDDM
+    surface_shrc_unlock(surface);
+#endif
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_surface_map(struct wined3d_surface *surface,
+        struct wined3d_map_desc *map_desc, const RECT *rect, DWORD flags)
+{
+    const struct wined3d_format *format = surface->resource.format;
+
+    TRACE("surface %p, map_desc %p, rect %s, flags %#x.\n",
+            surface, map_desc, wine_dbgstr_rect(rect), flags);
+
+    if (surface->resource.map_count)
+    {
+        WARN("Surface is already mapped.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    if ((format->flags & WINED3DFMT_FLAG_BLOCKS) && rect
+            && !surface_check_block_align(surface, rect))
+    {
+        WARN("Map rect %s is misaligned for %ux%u blocks.\n",
+                wine_dbgstr_rect(rect), format->block_width, format->block_height);
+
+        if (surface->resource.pool == WINED3D_POOL_DEFAULT)
+            return WINED3DERR_INVALIDCALL;
+    }
+
+#ifdef VBOX_WITH_WDDM
+    surface_shrc_lock(surface);
+#endif
+
+    ++surface->resource.map_count;
+
+    if (!(surface->flags & SFLAG_LOCKABLE))
+        WARN("Trying to lock unlockable surface.\n");
+
+    /* Performance optimization: Count how often a surface is mapped, if it is
+     * mapped regularly do not throw away the system memory copy. This avoids
+     * the need to download the surface from OpenGL all the time. The surface
+     * is still downloaded if the OpenGL texture is changed. */
+    if (!(surface->flags & SFLAG_DYNLOCK))
+    {
+        if (++surface->lockCount > MAXLOCKCOUNT)
+        {
+            TRACE("Surface is mapped regularly, not freeing the system memory copy any more.\n");
+            surface->flags |= SFLAG_DYNLOCK;
+        }
+    }
+
+    surface->surface_ops->surface_map(surface, rect, flags);
+
+    if (format->flags & WINED3DFMT_FLAG_BROKEN_PITCH)
+        map_desc->row_pitch = surface->resource.width * format->byte_count;
+    else
+        map_desc->row_pitch = wined3d_surface_get_pitch(surface);
+    map_desc->slice_pitch = 0;
+
+    if (!rect)
+    {
+        map_desc->data = surface->resource.allocatedMemory;
+        surface->lockedRect.left = 0;
+        surface->lockedRect.top = 0;
+        surface->lockedRect.right = surface->resource.width;
+        surface->lockedRect.bottom = surface->resource.height;
+    }
+    else
+    {
+        if ((format->flags & (WINED3DFMT_FLAG_BLOCKS | WINED3DFMT_FLAG_BROKEN_PITCH)) == WINED3DFMT_FLAG_BLOCKS)
+        {
+            /* Compressed textures are block based, so calculate the offset of
+             * the block that contains the top-left pixel of the locked rectangle. */
+            map_desc->data = surface->resource.allocatedMemory
+                    + ((rect->top / format->block_height) * map_desc->row_pitch)
+                    + ((rect->left / format->block_width) * format->block_byte_count);
+        }
+        else
+        {
+            map_desc->data = surface->resource.allocatedMemory
+                    + (map_desc->row_pitch * rect->top)
+                    + (rect->left * format->byte_count);
+        }
+        surface->lockedRect.left = rect->left;
+        surface->lockedRect.top = rect->top;
+        surface->lockedRect.right = rect->right;
+        surface->lockedRect.bottom = rect->bottom;
+    }
+
+    TRACE("Locked rect %s.\n", wine_dbgstr_rect(&surface->lockedRect));
+    TRACE("Returning memory %p, pitch %u.\n", map_desc->data, map_desc->row_pitch);
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_surface_getdc(struct wined3d_surface *surface, HDC *dc)
+{
+    struct wined3d_map_desc map;
+    HRESULT hr;
+
+    TRACE("surface %p, dc %p.\n", surface, dc);
+
+    if (surface->flags & SFLAG_USERPTR)
+    {
+        ERR("Not supported on surfaces with application-provided memory.\n");
+        return WINEDDERR_NODC;
+    }
+
+    /* Give more detailed info for ddraw. */
+    if (surface->flags & SFLAG_DCINUSE)
+        return WINEDDERR_DCALREADYCREATED;
+
+    /* Can't GetDC if the surface is locked. */
+    if (surface->resource.map_count)
+        return WINED3DERR_INVALIDCALL;
+
+    /* Create a DIB section if there isn't a dc yet. */
+    if (!surface->hDC)
+    {
+        if (surface->flags & SFLAG_CLIENT)
+        {
+            surface_load_location(surface, SFLAG_INSYSMEM, NULL);
+            surface_release_client_storage(surface);
+        }
+        hr = surface_create_dib_section(surface);
+        if (FAILED(hr))
+            return WINED3DERR_INVALIDCALL;
+
+        /* Use the DIB section from now on if we are not using a PBO. */
+        if (!(surface->flags & (SFLAG_PBO | SFLAG_PIN_SYSMEM)))
+        {
+            HeapFree(GetProcessHeap(), 0, surface->resource.heapMemory);
+            surface->resource.heapMemory = NULL;
+            surface->resource.allocatedMemory = surface->dib.bitmap_data;
+        }
+    }
+
+    /* Map the surface. */
+    hr = wined3d_surface_map(surface, &map, NULL, 0);
+    if (FAILED(hr))
+    {
+        ERR("Map failed, hr %#x.\n", hr);
+        return hr;
+    }
+
+    /* Sync the DIB with the PBO. This can't be done earlier because Map()
+     * activates the allocatedMemory. */
+#ifdef VBOX_WITH_WINE_FIX_PBOPSM
+    if ((surface->flags & (SFLAG_PBO | SFLAG_PIN_SYSMEM)) == (SFLAG_PBO | SFLAG_PIN_SYSMEM))
+#else
+    if (surface->flags & (SFLAG_PBO | SFLAG_PIN_SYSMEM))
+#endif
+        memcpy(surface->dib.bitmap_data, surface->resource.allocatedMemory, surface->resource.size);
+
+    if (surface->resource.format->id == WINED3DFMT_P8_UINT
+            || surface->resource.format->id == WINED3DFMT_P8_UINT_A8_UNORM)
+    {
+        /* GetDC on palettized formats is unsupported in D3D9, and the method
+         * is missing in D3D8, so this should only be used for DX <=7
+         * surfaces (with non-device palettes). */
+        const PALETTEENTRY *pal = NULL;
+
+        if (surface->palette)
+        {
+            pal = surface->palette->palents;
+        }
+        else
+        {
+            struct wined3d_swapchain *swapchain = surface->resource.device->swapchains[0];
+            struct wined3d_surface *dds_primary = swapchain->front_buffer;
+
+            if (dds_primary && dds_primary->palette)
+                pal = dds_primary->palette->palents;
+        }
+
+        if (pal)
+        {
+            RGBQUAD col[256];
+            unsigned int i;
+
+            for (i = 0; i < 256; ++i)
+            {
+                col[i].rgbRed = pal[i].peRed;
+                col[i].rgbGreen = pal[i].peGreen;
+                col[i].rgbBlue = pal[i].peBlue;
+                col[i].rgbReserved = 0;
+            }
+            SetDIBColorTable(surface->hDC, 0, 256, col);
+        }
+    }
+
+    surface->flags |= SFLAG_DCINUSE;
+
+    *dc = surface->hDC;
+    TRACE("Returning dc %p.\n", *dc);
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_surface_releasedc(struct wined3d_surface *surface, HDC dc)
+{
+    TRACE("surface %p, dc %p.\n", surface, dc);
+
+    if (!(surface->flags & SFLAG_DCINUSE))
+        return WINEDDERR_NODC;
+
+    if (surface->hDC != dc)
+    {
+        WARN("Application tries to release invalid DC %p, surface DC is %p.\n",
+                dc, surface->hDC);
+        return WINEDDERR_NODC;
+    }
+
+    /* Copy the contents of the DIB over to the PBO. */
+#ifdef VBOX_WITH_WINE_FIX_PBOPSM
+    if (((surface->flags & (SFLAG_PBO | SFLAG_PIN_SYSMEM)) == (SFLAG_PBO | SFLAG_PIN_SYSMEM)) && surface->resource.allocatedMemory)
+#else
+    if ((surface->flags & (SFLAG_PBO | SFLAG_PIN_SYSMEM)) && surface->resource.allocatedMemory)
+#endif
+        memcpy(surface->resource.allocatedMemory, surface->dib.bitmap_data, surface->resource.size);
+
+    /* We locked first, so unlock now. */
+    wined3d_surface_unmap(surface);
+
+    surface->flags &= ~SFLAG_DCINUSE;
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_surface_flip(struct wined3d_surface *surface, struct wined3d_surface *override, DWORD flags)
+{
+    TRACE("surface %p, override %p, flags %#x.\n", surface, override, flags);
+
+    if (flags)
+    {
+        static UINT once;
+        if (!once++)
+            FIXME("Ignoring flags %#x.\n", flags);
+        else
+            WARN("Ignoring flags %#x.\n", flags);
+    }
+
+    if (surface->swapchain)
+    {
+        ERR("Not supported on swapchain surfaces.\n");
+        return WINEDDERR_NOTFLIPPABLE;
+    }
+
+    /* Flipping is only supported on render targets and overlays. */
+    if (!(surface->resource.usage & (WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_OVERLAY)))
+    {
+        WARN("Tried to flip a non-render target, non-overlay surface.\n");
+        return WINEDDERR_NOTFLIPPABLE;
+    }
+
+    flip_surface(surface, override);
+
+    /* Update overlays if they're visible. */
+    if ((surface->resource.usage & WINED3DUSAGE_OVERLAY) && surface->overlay_dest)
+        return surface_draw_overlay(surface);
+
+    return WINED3D_OK;
+}
+
+/* Do not call while under the GL lock. */
+void surface_internal_preload(struct wined3d_surface *surface, enum WINED3DSRGB srgb)
+{
+    struct wined3d_device *device = surface->resource.device;
+
+    TRACE("iface %p, srgb %#x.\n", surface, srgb);
+
+    if (surface->container)
+    {
+        struct wined3d_texture *texture = surface->container;
+
+        TRACE("Passing to container (%p).\n", texture);
+        texture->texture_ops->texture_preload(texture, srgb);
+    }
+    else
+    {
+        struct wined3d_context *context;
+
+        TRACE("(%p) : About to load surface\n", surface);
+
+        /* TODO: Use already acquired context when possible. */
+        context = context_acquire(device, NULL);
+
+        surface_load(surface, srgb == SRGB_SRGB);
+
+#ifndef VBOX
+        if (surface->resource.pool == WINED3D_POOL_DEFAULT)
+        {
+            /* Tell opengl to try and keep this texture in video ram (well mostly) */
+            GLclampf tmp;
+            tmp = 0.9f;
+            context->gl_info->gl_ops.gl.p_glPrioritizeTextures(1, &surface->texture_name, &tmp);
+        }
+#else
+        /* chromium code on host fails to resolve texture name to texture obj,
+         * most likely because the texture does not get created until it is bound
+         * @todo: investigate */
+#endif
+        context_release(context);
+    }
+}
+
+/* Read the framebuffer back into the surface */
+static void read_from_framebuffer(struct wined3d_surface *surface, const RECT *rect, void *dest, UINT pitch)
+{
+    struct wined3d_device *device = surface->resource.device;
+    const struct wined3d_gl_info *gl_info;
+    struct wined3d_context *context;
+    BYTE *mem;
+    GLint fmt;
+    GLint type;
+    BYTE *row, *top, *bottom;
+    int i;
+    BOOL bpp;
+    RECT local_rect;
+    BOOL srcIsUpsideDown;
+    GLint rowLen = 0;
+    GLint skipPix = 0;
+    GLint skipRow = 0;
+
+    context = context_acquire(device, surface);
+    context_apply_blit_state(context, device);
+    gl_info = context->gl_info;
+
+    /* Select the correct read buffer, and give some debug output.
+     * There is no need to keep track of the current read buffer or reset it, every part of the code
+     * that reads sets the read buffer as desired.
+     */
+    if (surface_is_offscreen(surface))
+    {
+        /* Mapping the primary render target which is not on a swapchain.
+         * Read from the back buffer. */
+        TRACE("Mapping offscreen render target.\n");
+        gl_info->gl_ops.gl.p_glReadBuffer(device->offscreenBuffer);
+        srcIsUpsideDown = TRUE;
+    }
+    else
+    {
+        /* Onscreen surfaces are always part of a swapchain */
+        GLenum buffer = surface_get_gl_buffer(surface);
+        TRACE("Mapping %#x buffer.\n", buffer);
+        gl_info->gl_ops.gl.p_glReadBuffer(buffer);
+        checkGLcall("glReadBuffer");
+        srcIsUpsideDown = FALSE;
+    }
+
+    /* TODO: Get rid of the extra rectangle comparison and construction of a full surface rectangle */
+    if (!rect)
+    {
+        local_rect.left = 0;
+        local_rect.top = 0;
+        local_rect.right = surface->resource.width;
+        local_rect.bottom = surface->resource.height;
+    }
+    else
+    {
+        local_rect = *rect;
+    }
+    /* TODO: Get rid of the extra GetPitch call, LockRect does that too. Cache the pitch */
+
+    switch (surface->resource.format->id)
+    {
+        case WINED3DFMT_P8_UINT:
+        {
+            if (primary_render_target_is_p8(device))
+            {
+                /* In case of P8 render targets the index is stored in the alpha component */
+                fmt = GL_ALPHA;
+                type = GL_UNSIGNED_BYTE;
+                mem = dest;
+                bpp = surface->resource.format->byte_count;
+            }
+            else
+            {
+                /* GL can't return palettized data, so read ARGB pixels into a
+                 * separate block of memory and convert them into palettized format
+                 * in software. Slow, but if the app means to use palettized render
+                 * targets and locks it...
+                 *
+                 * Use GL_RGB, GL_UNSIGNED_BYTE to read the surface for performance reasons
+                 * Don't use GL_BGR as in the WINED3DFMT_R8G8B8 case, instead watch out
+                 * for the color channels when palettizing the colors.
+                 */
+                fmt = GL_RGB;
+                type = GL_UNSIGNED_BYTE;
+                pitch *= 3;
+                mem = HeapAlloc(GetProcessHeap(), 0, surface->resource.size * 3);
+                if (!mem)
+                {
+                    ERR("Out of memory\n");
+                    return;
+                }
+                bpp = surface->resource.format->byte_count * 3;
+            }
+        }
+        break;
+
+        default:
+            mem = dest;
+            fmt = surface->resource.format->glFormat;
+            type = surface->resource.format->glType;
+            bpp = surface->resource.format->byte_count;
+    }
+
+    if (surface->flags & SFLAG_PBO)
+    {
+        GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, surface->pbo));
+        checkGLcall("glBindBufferARB");
+        if (mem)
+        {
+            ERR("mem not null for pbo -- unexpected\n");
+            mem = NULL;
+        }
+    }
+
+    /* Save old pixel store pack state */
+    gl_info->gl_ops.gl.p_glGetIntegerv(GL_PACK_ROW_LENGTH, &rowLen);
+    checkGLcall("glGetIntegerv");
+    gl_info->gl_ops.gl.p_glGetIntegerv(GL_PACK_SKIP_PIXELS, &skipPix);
+    checkGLcall("glGetIntegerv");
+    gl_info->gl_ops.gl.p_glGetIntegerv(GL_PACK_SKIP_ROWS, &skipRow);
+    checkGLcall("glGetIntegerv");
+
+    /* Setup pixel store pack state -- to glReadPixels into the correct place */
+    gl_info->gl_ops.gl.p_glPixelStorei(GL_PACK_ROW_LENGTH, surface->resource.width);
+    checkGLcall("glPixelStorei");
+    gl_info->gl_ops.gl.p_glPixelStorei(GL_PACK_SKIP_PIXELS, local_rect.left);
+    checkGLcall("glPixelStorei");
+    gl_info->gl_ops.gl.p_glPixelStorei(GL_PACK_SKIP_ROWS, local_rect.top);
+    checkGLcall("glPixelStorei");
+
+    gl_info->gl_ops.gl.p_glReadPixels(local_rect.left,
+            !srcIsUpsideDown ? (surface->resource.height - local_rect.bottom) : local_rect.top,
+            local_rect.right - local_rect.left,
+            local_rect.bottom - local_rect.top,
+            fmt, type, mem);
+    checkGLcall("glReadPixels");
+
+    /* Reset previous pixel store pack state */
+    gl_info->gl_ops.gl.p_glPixelStorei(GL_PACK_ROW_LENGTH, rowLen);
+    checkGLcall("glPixelStorei");
+    gl_info->gl_ops.gl.p_glPixelStorei(GL_PACK_SKIP_PIXELS, skipPix);
+    checkGLcall("glPixelStorei");
+    gl_info->gl_ops.gl.p_glPixelStorei(GL_PACK_SKIP_ROWS, skipRow);
+    checkGLcall("glPixelStorei");
+
+    if (surface->flags & SFLAG_PBO)
+    {
+        GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0));
+        checkGLcall("glBindBufferARB");
+
+        /* Check if we need to flip the image. If we need to flip use glMapBufferARB
+         * to get a pointer to it and perform the flipping in software. This is a lot
+         * faster than calling glReadPixels for each line. In case we want more speed
+         * we should rerender it flipped in a FBO and read the data back from the FBO. */
+        if (!srcIsUpsideDown)
+        {
+            GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, surface->pbo));
+            checkGLcall("glBindBufferARB");
+
+            mem = GL_EXTCALL(glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_READ_WRITE_ARB));
+            checkGLcall("glMapBufferARB");
+        }
+    }
+
+    /* TODO: Merge this with the palettization loop below for P8 targets */
+    if(!srcIsUpsideDown) {
+        UINT len, off;
+        /* glReadPixels returns the image upside down, and there is no way to prevent this.
+            Flip the lines in software */
+        len = (local_rect.right - local_rect.left) * bpp;
+        off = local_rect.left * bpp;
+
+        row = HeapAlloc(GetProcessHeap(), 0, len);
+        if(!row) {
+            ERR("Out of memory\n");
+            if (surface->resource.format->id == WINED3DFMT_P8_UINT)
+                HeapFree(GetProcessHeap(), 0, mem);
+            return;
+        }
+
+        top = mem + pitch * local_rect.top;
+        bottom = mem + pitch * (local_rect.bottom - 1);
+        for(i = 0; i < (local_rect.bottom - local_rect.top) / 2; i++) {
+            memcpy(row, top + off, len);
+            memcpy(top + off, bottom + off, len);
+            memcpy(bottom + off, row, len);
+            top += pitch;
+            bottom -= pitch;
+        }
+        HeapFree(GetProcessHeap(), 0, row);
+
+        /* Unmap the temp PBO buffer */
+        if (surface->flags & SFLAG_PBO)
+        {
+            GL_EXTCALL(glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB));
+            GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
+        }
+    }
+
+    context_release(context);
+
+    /* For P8 textures we need to perform an inverse palette lookup. This is
+     * done by searching for a palette index which matches the RGB value.
+     * Note this isn't guaranteed to work when there are multiple entries for
+     * the same color but we have no choice. In case of P8 render targets,
+     * the index is stored in the alpha component so no conversion is needed. */
+    if (surface->resource.format->id == WINED3DFMT_P8_UINT && !primary_render_target_is_p8(device))
+    {
+        const PALETTEENTRY *pal = NULL;
+        DWORD width = pitch / 3;
+        int x, y, c;
+
+        if (surface->palette)
+        {
+            pal = surface->palette->palents;
+        }
+        else
+        {
+            ERR("Palette is missing, cannot perform inverse palette lookup\n");
+            HeapFree(GetProcessHeap(), 0, mem);
+            return;
+        }
+
+        for(y = local_rect.top; y < local_rect.bottom; y++) {
+            for(x = local_rect.left; x < local_rect.right; x++) {
+                /*                      start              lines            pixels      */
+                const BYTE *blue = mem + y * pitch + x * (sizeof(BYTE) * 3);
+                const BYTE *green = blue  + 1;
+                const BYTE *red = green + 1;
+
+                for(c = 0; c < 256; c++) {
+                    if(*red   == pal[c].peRed   &&
+                       *green == pal[c].peGreen &&
+                       *blue  == pal[c].peBlue)
+                    {
+                        *((BYTE *) dest + y * width + x) = c;
+                        break;
+                    }
+                }
+            }
+        }
+        HeapFree(GetProcessHeap(), 0, mem);
+    }
+}
+
+/* Read the framebuffer contents into a texture. Note that this function
+ * doesn't do any kind of flipping. Using this on an onscreen surface will
+ * result in a flipped D3D texture. */
+void surface_load_fb_texture(struct wined3d_surface *surface, BOOL srgb)
+{
+    struct wined3d_device *device = surface->resource.device;
+    const struct wined3d_gl_info *gl_info;
+    struct wined3d_context *context;
+
+    context = context_acquire(device, surface);
+    gl_info = context->gl_info;
+    device_invalidate_state(device, STATE_FRAMEBUFFER);
+
+    surface_prepare_texture(surface, context, srgb);
+    surface_bind_and_dirtify(surface, context, srgb);
+
+    TRACE("Reading back offscreen render target %p.\n", surface);
+
+    if (surface_is_offscreen(surface))
+        gl_info->gl_ops.gl.p_glReadBuffer(device->offscreenBuffer);
+    else
+        gl_info->gl_ops.gl.p_glReadBuffer(surface_get_gl_buffer(surface));
+    checkGLcall("glReadBuffer");
+
+    gl_info->gl_ops.gl.p_glCopyTexSubImage2D(surface->texture_target, surface->texture_level,
+            0, 0, 0, 0, surface->resource.width, surface->resource.height);
+    checkGLcall("glCopyTexSubImage2D");
+
+    context_release(context);
+}
+
+/* Context activation is done by the caller. */
+static void surface_prepare_texture_internal(struct wined3d_surface *surface,
+        struct wined3d_context *context, BOOL srgb)
+{
+    DWORD alloc_flag = srgb ? SFLAG_SRGBALLOCATED : SFLAG_ALLOCATED;
+    enum wined3d_conversion_type convert;
+    struct wined3d_format format;
+
+    if (surface->flags & alloc_flag) return;
+
+    d3dfmt_get_conv(surface, TRUE, TRUE, &format, &convert);
+    if (convert != WINED3D_CT_NONE || format.convert)
+        surface->flags |= SFLAG_CONVERTED;
+    else surface->flags &= ~SFLAG_CONVERTED;
+
+    surface_bind_and_dirtify(surface, context, srgb);
+    surface_allocate_surface(surface, context->gl_info, &format, srgb);
+    surface->flags |= alloc_flag;
+}
+
+/* Context activation is done by the caller. */
+void surface_prepare_texture(struct wined3d_surface *surface, struct wined3d_context *context, BOOL srgb)
+{
+    if (surface->container)
+    {
+        struct wined3d_texture *texture = surface->container;
+        UINT sub_count = texture->level_count * texture->layer_count;
+        UINT i;
+
+        TRACE("surface %p is a subresource of texture %p.\n", surface, texture);
+
+        for (i = 0; i < sub_count; ++i)
+        {
+            struct wined3d_surface *s = surface_from_resource(texture->sub_resources[i]);
+            surface_prepare_texture_internal(s, context, srgb);
+        }
+
+        return;
+    }
+
+    surface_prepare_texture_internal(surface, context, srgb);
+}
+
+void surface_prepare_rb(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info, BOOL multisample)
+{
+    if (multisample)
+    {
+        if (surface->rb_multisample)
+            return;
+
+        gl_info->fbo_ops.glGenRenderbuffers(1, &surface->rb_multisample);
+        gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, surface->rb_multisample);
+        gl_info->fbo_ops.glRenderbufferStorageMultisample(GL_RENDERBUFFER, surface->resource.multisample_type,
+                surface->resource.format->glInternal, surface->pow2Width, surface->pow2Height);
+        TRACE("Created multisample rb %u.\n", surface->rb_multisample);
+    }
+    else
+    {
+        if (surface->rb_resolved)
+            return;
+
+        gl_info->fbo_ops.glGenRenderbuffers(1, &surface->rb_resolved);
+        gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, surface->rb_resolved);
+        gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER, surface->resource.format->glInternal,
+                surface->pow2Width, surface->pow2Height);
+        TRACE("Created resolved rb %u.\n", surface->rb_resolved);
+    }
+}
+
+static void flush_to_framebuffer_drawpixels(struct wined3d_surface *surface,
+        const RECT *rect, GLenum fmt, GLenum type, UINT bpp, const BYTE *mem)
+{
+    struct wined3d_device *device = surface->resource.device;
+    UINT pitch = wined3d_surface_get_pitch(surface);
+    const struct wined3d_gl_info *gl_info;
+    struct wined3d_context *context;
+    RECT local_rect;
+    UINT w, h;
+
+    surface_get_rect(surface, rect, &local_rect);
+
+    mem += local_rect.top * pitch + local_rect.left * bpp;
+    w = local_rect.right - local_rect.left;
+    h = local_rect.bottom - local_rect.top;
+
+    /* Activate the correct context for the render target */
+    context = context_acquire(device, surface);
+    context_apply_blit_state(context, device);
+    gl_info = context->gl_info;
+
+    if (!surface_is_offscreen(surface))
+    {
+        GLenum buffer = surface_get_gl_buffer(surface);
+        TRACE("Unlocking %#x buffer.\n", buffer);
+        context_set_draw_buffer(context, buffer);
+
+#ifndef VBOX_WINE_WITH_SINGLE_CONTEXT
+        surface_translate_drawable_coords(surface, context->win_handle, &local_rect);
+#else
+        surface_translate_drawable_coords(surface, context->swapchain->win_handle, &local_rect);
+#endif
+        gl_info->gl_ops.gl.p_glPixelZoom(1.0f, -1.0f);
+    }
+    else
+    {
+        /* Primary offscreen render target */
+        TRACE("Offscreen render target.\n");
+        context_set_draw_buffer(context, device->offscreenBuffer);
+
+        gl_info->gl_ops.gl.p_glPixelZoom(1.0f, 1.0f);
+    }
+
+    gl_info->gl_ops.gl.p_glRasterPos3i(local_rect.left, local_rect.top, 1);
+    checkGLcall("glRasterPos3i");
+
+    /* If not fullscreen, we need to skip a number of bytes to find the next row of data */
+    gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_ROW_LENGTH, surface->resource.width);
+
+    if (surface->flags & SFLAG_PBO)
+    {
+        GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, surface->pbo));
+        checkGLcall("glBindBufferARB");
+    }
+
+    gl_info->gl_ops.gl.p_glDrawPixels(w, h, fmt, type, mem);
+    checkGLcall("glDrawPixels");
+
+    if (surface->flags & SFLAG_PBO)
+    {
+        GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
+        checkGLcall("glBindBufferARB");
+    }
+
+    gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+    checkGLcall("glPixelStorei(GL_UNPACK_ROW_LENGTH, 0)");
+
+    if (wined3d_settings.strict_draw_ordering
+            || (surface->swapchain && surface->swapchain->front_buffer == surface))
+        gl_info->gl_ops.gl.p_glFlush();
+
+    context_release(context);
+}
+
+static BOOL color_in_range(const struct wined3d_color_key *color_key, DWORD color)
+{
+    /* FIXME: Is this really how color keys are supposed to work? I think it
+     * makes more sense to compare the individual channels. */
+    return color >= color_key->color_space_low_value
+            && color <= color_key->color_space_high_value;
+}
+
+void d3dfmt_p8_init_palette(const struct wined3d_surface *surface, BYTE table[256][4], BOOL colorkey)
+{
+    const struct wined3d_device *device = surface->resource.device;
+    const struct wined3d_palette *pal = surface->palette;
+    BOOL index_in_alpha = FALSE;
+    unsigned int i;
+
+    /* Old games like StarCraft, C&C, Red Alert and others use P8 render targets.
+     * Reading back the RGB output each lockrect (each frame as they lock the whole screen)
+     * is slow. Further RGB->P8 conversion is not possible because palettes can have
+     * duplicate entries. Store the color key in the unused alpha component to speed the
+     * download up and to make conversion unneeded. */
+    index_in_alpha = primary_render_target_is_p8(device);
+
+    if (!pal)
+    {
+        FIXME("No palette set.\n");
+        if (index_in_alpha)
+        {
+            /* Guarantees that memory representation remains correct after sysmem<->texture transfers even if
+             * there's no palette at this time. */
+            for (i = 0; i < 256; i++) table[i][3] = i;
+        }
+    }
+    else
+    {
+        TRACE("Using surface palette %p\n", pal);
+        /* Get the surface's palette */
+        for (i = 0; i < 256; ++i)
+        {
+            table[i][0] = pal->palents[i].peRed;
+            table[i][1] = pal->palents[i].peGreen;
+            table[i][2] = pal->palents[i].peBlue;
+
+            /* When index_in_alpha is set the palette index is stored in the
+             * alpha component. In case of a readback we can then read
+             * GL_ALPHA. Color keying is handled in BltOverride using a
+             * GL_ALPHA_TEST using GL_NOT_EQUAL. In case of index_in_alpha the
+             * color key itself is passed to glAlphaFunc in other cases the
+             * alpha component of pixels that should be masked away is set to 0. */
+            if (index_in_alpha)
+                table[i][3] = i;
+            else if (colorkey && color_in_range(&surface->src_blt_color_key, i))
+                table[i][3] = 0x00;
+            else if (pal->flags & WINEDDPCAPS_ALPHA)
+                table[i][3] = pal->palents[i].peFlags;
+            else
+                table[i][3] = 0xff;
+        }
+    }
+}
+
+static HRESULT d3dfmt_convert_surface(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height,
+        UINT outpitch, enum wined3d_conversion_type conversion_type, struct wined3d_surface *surface)
+{
+    const BYTE *source;
+    BYTE *dest;
+
+    TRACE("src %p, dst %p, pitch %u, width %u, height %u, outpitch %u, conversion_type %#x, surface %p.\n",
+            src, dst, pitch, width, height, outpitch, conversion_type, surface);
+
+    switch (conversion_type)
+    {
+        case WINED3D_CT_NONE:
+        {
+            memcpy(dst, src, pitch * height);
+            break;
+        }
+
+        case WINED3D_CT_PALETTED:
+        case WINED3D_CT_PALETTED_CK:
+        {
+            BYTE table[256][4];
+            unsigned int x, y;
+
+            d3dfmt_p8_init_palette(surface, table, (conversion_type == WINED3D_CT_PALETTED_CK));
+
+            for (y = 0; y < height; y++)
+            {
+                source = src + pitch * y;
+                dest = dst + outpitch * y;
+                /* This is an 1 bpp format, using the width here is fine */
+                for (x = 0; x < width; x++) {
+                    BYTE color = *source++;
+                    *dest++ = table[color][0];
+                    *dest++ = table[color][1];
+                    *dest++ = table[color][2];
+                    *dest++ = table[color][3];
+                }
+            }
+        }
+        break;
+
+        case WINED3D_CT_CK_565:
+        {
+            /* Converting the 565 format in 5551 packed to emulate color-keying.
+
+              Note : in all these conversion, it would be best to average the averaging
+                      pixels to get the color of the pixel that will be color-keyed to
+                      prevent 'color bleeding'. This will be done later on if ever it is
+                      too visible.
+
+              Note2: Nvidia documents say that their driver does not support alpha + color keying
+                     on the same surface and disables color keying in such a case
+            */
+            unsigned int x, y;
+            const WORD *Source;
+            WORD *Dest;
+
+            TRACE("Color keyed 565\n");
+
+            for (y = 0; y < height; y++) {
+                Source = (const WORD *)(src + y * pitch);
+                Dest = (WORD *) (dst + y * outpitch);
+                for (x = 0; x < width; x++ ) {
+                    WORD color = *Source++;
+                    *Dest = ((color & 0xffc0) | ((color & 0x1f) << 1));
+                    if (!color_in_range(&surface->src_blt_color_key, color))
+                        *Dest |= 0x0001;
+                    Dest++;
+                }
+            }
+        }
+        break;
+
+        case WINED3D_CT_CK_5551:
+        {
+            /* Converting X1R5G5B5 format to R5G5B5A1 to emulate color-keying. */
+            unsigned int x, y;
+            const WORD *Source;
+            WORD *Dest;
+            TRACE("Color keyed 5551\n");
+            for (y = 0; y < height; y++) {
+                Source = (const WORD *)(src + y * pitch);
+                Dest = (WORD *) (dst + y * outpitch);
+                for (x = 0; x < width; x++ ) {
+                    WORD color = *Source++;
+                    *Dest = color;
+                    if (!color_in_range(&surface->src_blt_color_key, color))
+                        *Dest |= (1 << 15);
+                    else
+                        *Dest &= ~(1 << 15);
+                    Dest++;
+                }
+            }
+        }
+        break;
+
+        case WINED3D_CT_CK_RGB24:
+        {
+            /* Converting R8G8B8 format to R8G8B8A8 with color-keying. */
+            unsigned int x, y;
+            for (y = 0; y < height; y++)
+            {
+                source = src + pitch * y;
+                dest = dst + outpitch * y;
+                for (x = 0; x < width; x++) {
+                    DWORD color = ((DWORD)source[0] << 16) + ((DWORD)source[1] << 8) + (DWORD)source[2] ;
+                    DWORD dstcolor = color << 8;
+                    if (!color_in_range(&surface->src_blt_color_key, color))
+                        dstcolor |= 0xff;
+                    *(DWORD*)dest = dstcolor;
+                    source += 3;
+                    dest += 4;
+                }
+            }
+        }
+        break;
+
+        case WINED3D_CT_RGB32_888:
+        {
+            /* Converting X8R8G8B8 format to R8G8B8A8 with color-keying. */
+            unsigned int x, y;
+            for (y = 0; y < height; y++)
+            {
+                source = src + pitch * y;
+                dest = dst + outpitch * y;
+                for (x = 0; x < width; x++) {
+                    DWORD color = 0xffffff & *(const DWORD*)source;
+                    DWORD dstcolor = color << 8;
+                    if (!color_in_range(&surface->src_blt_color_key, color))
+                        dstcolor |= 0xff;
+                    *(DWORD*)dest = dstcolor;
+                    source += 4;
+                    dest += 4;
+                }
+            }
+        }
+        break;
+
+        case WINED3D_CT_CK_ARGB32:
+        {
+            unsigned int x, y;
+            for (y = 0; y < height; ++y)
+            {
+                source = src + pitch * y;
+                dest = dst + outpitch * y;
+                for (x = 0; x < width; ++x)
+                {
+                    DWORD color = *(const DWORD *)source;
+                    if (color_in_range(&surface->src_blt_color_key, color))
+                        color &= ~0xff000000;
+                    *(DWORD*)dest = color;
+                    source += 4;
+                    dest += 4;
+                }
+            }
+        }
+        break;
+
+        default:
+            ERR("Unsupported conversion type %#x.\n", conversion_type);
+    }
+    return WINED3D_OK;
+}
+
+void flip_surface(struct wined3d_surface *front, struct wined3d_surface *back)
+{
+    /* Flip the surface contents */
+    /* Flip the DC */
+    {
+        HDC tmp;
+        tmp = front->hDC;
+        front->hDC = back->hDC;
+        back->hDC = tmp;
+    }
+
+    /* Flip the DIBsection */
+    {
+        HBITMAP tmp = front->dib.DIBsection;
+        front->dib.DIBsection = back->dib.DIBsection;
+        back->dib.DIBsection = tmp;
+    }
+
+    /* Flip the surface data */
+    {
+        void* tmp;
+
+        tmp = front->dib.bitmap_data;
+        front->dib.bitmap_data = back->dib.bitmap_data;
+        back->dib.bitmap_data = tmp;
+
+        tmp = front->resource.allocatedMemory;
+        front->resource.allocatedMemory = back->resource.allocatedMemory;
+        back->resource.allocatedMemory = tmp;
+
+        tmp = front->resource.heapMemory;
+        front->resource.heapMemory = back->resource.heapMemory;
+        back->resource.heapMemory = tmp;
+    }
+
+    /* Flip the PBO */
+    {
+        GLuint tmp_pbo = front->pbo;
+        front->pbo = back->pbo;
+        back->pbo = tmp_pbo;
+    }
+
+    /* Flip the opengl texture */
+    {
+        GLuint tmp;
+
+        tmp = back->texture_name;
+        back->texture_name = front->texture_name;
+        front->texture_name = tmp;
+
+        tmp = back->texture_name_srgb;
+        back->texture_name_srgb = front->texture_name_srgb;
+        front->texture_name_srgb = tmp;
+
+        tmp = back->rb_multisample;
+        back->rb_multisample = front->rb_multisample;
+        front->rb_multisample = tmp;
+
+        tmp = back->rb_resolved;
+        back->rb_resolved = front->rb_resolved;
+        front->rb_resolved = tmp;
+
+        resource_unload(&back->resource);
+        resource_unload(&front->resource);
+    }
+
+    {
+        DWORD tmp_flags = back->flags;
+        back->flags = front->flags;
+        front->flags = tmp_flags;
+    }
+}
+
+/* Does a direct frame buffer -> texture copy. Stretching is done with single
+ * pixel copy calls. */
+static void fb_copy_to_texture_direct(struct wined3d_surface *dst_surface, struct wined3d_surface *src_surface,
+        const RECT *src_rect, const RECT *dst_rect_in, enum wined3d_texture_filter_type filter)
+{
+    struct wined3d_device *device = dst_surface->resource.device;
+    const struct wined3d_gl_info *gl_info;
+    float xrel, yrel;
+    struct wined3d_context *context;
+    BOOL upsidedown = FALSE;
+    RECT dst_rect = *dst_rect_in;
+    GLenum dst_target;
+
+    if (dst_surface->container)
+        dst_target = dst_surface->container->target;
+    else
+        dst_target = dst_surface->texture_target;
+
+    /* Make sure that the top pixel is always above the bottom pixel, and keep a separate upside down flag
+     * glCopyTexSubImage is a bit picky about the parameters we pass to it
+     */
+    if(dst_rect.top > dst_rect.bottom) {
+        UINT tmp = dst_rect.bottom;
+        dst_rect.bottom = dst_rect.top;
+        dst_rect.top = tmp;
+        upsidedown = TRUE;
+    }
+
+    context = context_acquire(device, src_surface);
+    gl_info = context->gl_info;
+    context_apply_blit_state(context, device);
+    surface_internal_preload(dst_surface, SRGB_RGB);
+
+    /* Bind the target texture */
+    context_bind_texture(context, dst_target, dst_surface->texture_name);
+    if (surface_is_offscreen(src_surface))
+    {
+        TRACE("Reading from an offscreen target\n");
+        upsidedown = !upsidedown;
+        gl_info->gl_ops.gl.p_glReadBuffer(device->offscreenBuffer);
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glReadBuffer(surface_get_gl_buffer(src_surface));
+    }
+    checkGLcall("glReadBuffer");
+
+    xrel = (float) (src_rect->right - src_rect->left) / (float) (dst_rect.right - dst_rect.left);
+    yrel = (float) (src_rect->bottom - src_rect->top) / (float) (dst_rect.bottom - dst_rect.top);
+
+    if ((xrel - 1.0f < -eps) || (xrel - 1.0f > eps))
+    {
+        FIXME("Doing a pixel by pixel copy from the framebuffer to a texture, expect major performance issues\n");
+
+        if (filter != WINED3D_TEXF_NONE && filter != WINED3D_TEXF_POINT)
+            ERR("Texture filtering not supported in direct blit.\n");
+    }
+    else if ((filter != WINED3D_TEXF_NONE && filter != WINED3D_TEXF_POINT)
+            && ((yrel - 1.0f < -eps) || (yrel - 1.0f > eps)))
+    {
+        ERR("Texture filtering not supported in direct blit\n");
+    }
+
+    if (upsidedown
+            && !((xrel - 1.0f < -eps) || (xrel - 1.0f > eps))
+            && !((yrel - 1.0f < -eps) || (yrel - 1.0f > eps)))
+    {
+        /* Upside down copy without stretching is nice, one glCopyTexSubImage call will do. */
+        gl_info->gl_ops.gl.p_glCopyTexSubImage2D(dst_surface->texture_target, dst_surface->texture_level,
+                dst_rect.left /*xoffset */, dst_rect.top /* y offset */,
+                src_rect->left, src_surface->resource.height - src_rect->bottom,
+                dst_rect.right - dst_rect.left, dst_rect.bottom - dst_rect.top);
+    }
+    else
+    {
+        LONG row;
+        UINT yoffset = src_surface->resource.height - src_rect->top + dst_rect.top - 1;
+        /* I have to process this row by row to swap the image,
+         * otherwise it would be upside down, so stretching in y direction
+         * doesn't cost extra time
+         *
+         * However, stretching in x direction can be avoided if not necessary
+         */
+        for(row = dst_rect.top; row < dst_rect.bottom; row++) {
+            if ((xrel - 1.0f < -eps) || (xrel - 1.0f > eps))
+            {
+                /* Well, that stuff works, but it's very slow.
+                 * find a better way instead
+                 */
+                LONG col;
+
+                for (col = dst_rect.left; col < dst_rect.right; ++col)
+                {
+                    gl_info->gl_ops.gl.p_glCopyTexSubImage2D(dst_surface->texture_target, dst_surface->texture_level,
+                            dst_rect.left + col /* x offset */, row /* y offset */,
+                            src_rect->left + col * xrel, yoffset - (int) (row * yrel), 1, 1);
+                }
+            }
+            else
+            {
+                gl_info->gl_ops.gl.p_glCopyTexSubImage2D(dst_surface->texture_target, dst_surface->texture_level,
+                        dst_rect.left /* x offset */, row /* y offset */,
+                        src_rect->left, yoffset - (int) (row * yrel), dst_rect.right - dst_rect.left, 1);
+            }
+        }
+    }
+    checkGLcall("glCopyTexSubImage2D");
+
+    context_release(context);
+
+    /* The texture is now most up to date - If the surface is a render target and has a drawable, this
+     * path is never entered
+     */
+    surface_modify_location(dst_surface, SFLAG_INTEXTURE, TRUE);
+}
+
+/* Uses the hardware to stretch and flip the image */
+static void fb_copy_to_texture_hwstretch(struct wined3d_surface *dst_surface, struct wined3d_surface *src_surface,
+        const RECT *src_rect, const RECT *dst_rect_in, enum wined3d_texture_filter_type filter)
+{
+    struct wined3d_device *device = dst_surface->resource.device;
+    GLuint src, backup = 0;
+    float left, right, top, bottom; /* Texture coordinates */
+    UINT fbwidth = src_surface->resource.width;
+    UINT fbheight = src_surface->resource.height;
+    const struct wined3d_gl_info *gl_info;
+    struct wined3d_context *context;
+    GLenum drawBuffer = GL_BACK;
+    GLenum texture_target;
+    BOOL noBackBufferBackup;
+    BOOL src_offscreen;
+    BOOL upsidedown = FALSE;
+    RECT dst_rect = *dst_rect_in;
+
+    TRACE("Using hwstretch blit\n");
+    /* Activate the Proper context for reading from the source surface, set it up for blitting */
+    context = context_acquire(device, src_surface);
+    gl_info = context->gl_info;
+    context_apply_blit_state(context, device);
+    surface_internal_preload(dst_surface, SRGB_RGB);
+
+    src_offscreen = surface_is_offscreen(src_surface);
+    noBackBufferBackup = src_offscreen && wined3d_settings.offscreen_rendering_mode == ORM_FBO;
+    if (!noBackBufferBackup && !src_surface->texture_name)
+    {
+        /* Get it a description */
+        surface_internal_preload(src_surface, SRGB_RGB);
+    }
+
+    /* Try to use an aux buffer for drawing the rectangle. This way it doesn't need restoring.
+     * This way we don't have to wait for the 2nd readback to finish to leave this function.
+     */
+    if (context->aux_buffers >= 2)
+    {
+        /* Got more than one aux buffer? Use the 2nd aux buffer */
+        drawBuffer = GL_AUX1;
+    }
+    else if ((!src_offscreen || device->offscreenBuffer == GL_BACK) && context->aux_buffers >= 1)
+    {
+        /* Only one aux buffer, but it isn't used (Onscreen rendering, or non-aux orm)? Use it! */
+        drawBuffer = GL_AUX0;
+    }
+
+    if (noBackBufferBackup)
+    {
+        gl_info->gl_ops.gl.p_glGenTextures(1, &backup);
+        checkGLcall("glGenTextures");
+        context_bind_texture(context, GL_TEXTURE_2D, backup);
+        texture_target = GL_TEXTURE_2D;
+    }
+    else
+    {
+        /* Backup the back buffer and copy the source buffer into a texture to draw an upside down stretched quad. If
+         * we are reading from the back buffer, the backup can be used as source texture
+         */
+        texture_target = src_surface->texture_target;
+        context_bind_texture(context, texture_target, src_surface->texture_name);
+        gl_info->gl_ops.gl.p_glEnable(texture_target);
+        checkGLcall("glEnable(texture_target)");
+
+        /* For now invalidate the texture copy of the back buffer. Drawable and sysmem copy are untouched */
+        src_surface->flags &= ~SFLAG_INTEXTURE;
+    }
+
+    /* Make sure that the top pixel is always above the bottom pixel, and keep a separate upside down flag
+     * glCopyTexSubImage is a bit picky about the parameters we pass to it
+     */
+    if(dst_rect.top > dst_rect.bottom) {
+        UINT tmp = dst_rect.bottom;
+        dst_rect.bottom = dst_rect.top;
+        dst_rect.top = tmp;
+        upsidedown = TRUE;
+    }
+
+    if (src_offscreen)
+    {
+        TRACE("Reading from an offscreen target\n");
+        upsidedown = !upsidedown;
+        gl_info->gl_ops.gl.p_glReadBuffer(device->offscreenBuffer);
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glReadBuffer(surface_get_gl_buffer(src_surface));
+    }
+
+    /* TODO: Only back up the part that will be overwritten */
+    gl_info->gl_ops.gl.p_glCopyTexSubImage2D(texture_target, 0, 0, 0, 0, 0, fbwidth, fbheight);
+
+    checkGLcall("glCopyTexSubImage2D");
+
+    /* No issue with overriding these - the sampler is dirty due to blit usage */
+    gl_info->gl_ops.gl.p_glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER,
+            wined3d_gl_mag_filter(magLookup, filter));
+    checkGLcall("glTexParameteri");
+    gl_info->gl_ops.gl.p_glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER,
+            wined3d_gl_min_mip_filter(minMipLookup, filter, WINED3D_TEXF_NONE));
+    checkGLcall("glTexParameteri");
+
+    if (!src_surface->swapchain || src_surface == src_surface->swapchain->back_buffers[0])
+    {
+        src = backup ? backup : src_surface->texture_name;
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glReadBuffer(GL_FRONT);
+        checkGLcall("glReadBuffer(GL_FRONT)");
+
+        gl_info->gl_ops.gl.p_glGenTextures(1, &src);
+        checkGLcall("glGenTextures(1, &src)");
+        context_bind_texture(context, GL_TEXTURE_2D, src);
+
+        /* TODO: Only copy the part that will be read. Use src_rect->left, src_rect->bottom as origin, but with the width watch
+         * out for power of 2 sizes
+         */
+        gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, src_surface->pow2Width,
+                src_surface->pow2Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+        checkGLcall("glTexImage2D");
+        gl_info->gl_ops.gl.p_glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, fbwidth, fbheight);
+
+        gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        checkGLcall("glTexParameteri");
+        gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        checkGLcall("glTexParameteri");
+
+        gl_info->gl_ops.gl.p_glReadBuffer(GL_BACK);
+        checkGLcall("glReadBuffer(GL_BACK)");
+
+        if (texture_target != GL_TEXTURE_2D)
+        {
+            gl_info->gl_ops.gl.p_glDisable(texture_target);
+            gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_2D);
+            texture_target = GL_TEXTURE_2D;
+        }
+    }
+    checkGLcall("glEnd and previous");
+
+    left = src_rect->left;
+    right = src_rect->right;
+
+    if (!upsidedown)
+    {
+        top = src_surface->resource.height - src_rect->top;
+        bottom = src_surface->resource.height - src_rect->bottom;
+    }
+    else
+    {
+        top = src_surface->resource.height - src_rect->bottom;
+        bottom = src_surface->resource.height - src_rect->top;
+    }
+
+    if (src_surface->flags & SFLAG_NORMCOORD)
+    {
+        left /= src_surface->pow2Width;
+        right /= src_surface->pow2Width;
+        top /= src_surface->pow2Height;
+        bottom /= src_surface->pow2Height;
+    }
+
+    /* draw the source texture stretched and upside down. The correct surface is bound already */
+    gl_info->gl_ops.gl.p_glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP);
+    gl_info->gl_ops.gl.p_glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP);
+
+    context_set_draw_buffer(context, drawBuffer);
+    gl_info->gl_ops.gl.p_glReadBuffer(drawBuffer);
+
+    gl_info->gl_ops.gl.p_glBegin(GL_QUADS);
+        /* bottom left */
+        gl_info->gl_ops.gl.p_glTexCoord2f(left, bottom);
+        gl_info->gl_ops.gl.p_glVertex2i(0, 0);
+
+        /* top left */
+        gl_info->gl_ops.gl.p_glTexCoord2f(left, top);
+        gl_info->gl_ops.gl.p_glVertex2i(0, dst_rect.bottom - dst_rect.top);
+
+        /* top right */
+        gl_info->gl_ops.gl.p_glTexCoord2f(right, top);
+        gl_info->gl_ops.gl.p_glVertex2i(dst_rect.right - dst_rect.left, dst_rect.bottom - dst_rect.top);
+
+        /* bottom right */
+        gl_info->gl_ops.gl.p_glTexCoord2f(right, bottom);
+        gl_info->gl_ops.gl.p_glVertex2i(dst_rect.right - dst_rect.left, 0);
+    gl_info->gl_ops.gl.p_glEnd();
+    checkGLcall("glEnd and previous");
+
+    if (texture_target != dst_surface->texture_target)
+    {
+        gl_info->gl_ops.gl.p_glDisable(texture_target);
+        gl_info->gl_ops.gl.p_glEnable(dst_surface->texture_target);
+        texture_target = dst_surface->texture_target;
+    }
+
+    /* Now read the stretched and upside down image into the destination texture */
+    context_bind_texture(context, texture_target, dst_surface->texture_name);
+    gl_info->gl_ops.gl.p_glCopyTexSubImage2D(texture_target,
+                        0,
+                        dst_rect.left, dst_rect.top, /* xoffset, yoffset */
+                        0, 0, /* We blitted the image to the origin */
+                        dst_rect.right - dst_rect.left, dst_rect.bottom - dst_rect.top);
+    checkGLcall("glCopyTexSubImage2D");
+
+    if (drawBuffer == GL_BACK)
+    {
+        /* Write the back buffer backup back. */
+        if (backup)
+        {
+            if (texture_target != GL_TEXTURE_2D)
+            {
+                gl_info->gl_ops.gl.p_glDisable(texture_target);
+                gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_2D);
+                texture_target = GL_TEXTURE_2D;
+            }
+            context_bind_texture(context, GL_TEXTURE_2D, backup);
+        }
+        else
+        {
+            if (texture_target != src_surface->texture_target)
+            {
+                gl_info->gl_ops.gl.p_glDisable(texture_target);
+                gl_info->gl_ops.gl.p_glEnable(src_surface->texture_target);
+                texture_target = src_surface->texture_target;
+            }
+            context_bind_texture(context, src_surface->texture_target, src_surface->texture_name);
+        }
+
+        gl_info->gl_ops.gl.p_glBegin(GL_QUADS);
+            /* top left */
+            gl_info->gl_ops.gl.p_glTexCoord2f(0.0f, 0.0f);
+            gl_info->gl_ops.gl.p_glVertex2i(0, fbheight);
+
+            /* bottom left */
+            gl_info->gl_ops.gl.p_glTexCoord2f(0.0f, (float)fbheight / (float)src_surface->pow2Height);
+            gl_info->gl_ops.gl.p_glVertex2i(0, 0);
+
+            /* bottom right */
+            gl_info->gl_ops.gl.p_glTexCoord2f((float)fbwidth / (float)src_surface->pow2Width,
+                    (float)fbheight / (float)src_surface->pow2Height);
+            gl_info->gl_ops.gl.p_glVertex2i(fbwidth, 0);
+
+            /* top right */
+            gl_info->gl_ops.gl.p_glTexCoord2f((float)fbwidth / (float)src_surface->pow2Width, 0.0f);
+            gl_info->gl_ops.gl.p_glVertex2i(fbwidth, fbheight);
+        gl_info->gl_ops.gl.p_glEnd();
+    }
+    gl_info->gl_ops.gl.p_glDisable(texture_target);
+    checkGLcall("glDisable(texture_target)");
+
+    /* Cleanup */
+    if (src != src_surface->texture_name && src != backup)
+    {
+        gl_info->gl_ops.gl.p_glDeleteTextures(1, &src);
+        checkGLcall("glDeleteTextures(1, &src)");
+    }
+    if (backup)
+    {
+        gl_info->gl_ops.gl.p_glDeleteTextures(1, &backup);
+        checkGLcall("glDeleteTextures(1, &backup)");
+    }
+
+    if (wined3d_settings.strict_draw_ordering)
+        gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */
+
+    context_release(context);
+
+    /* The texture is now most up to date - If the surface is a render target and has a drawable, this
+     * path is never entered
+     */
+    surface_modify_location(dst_surface, SFLAG_INTEXTURE, TRUE);
+}
+
+/* Front buffer coordinates are always full screen coordinates, but our GL
+ * drawable is limited to the window's client area. The sysmem and texture
+ * copies do have the full screen size. Note that GL has a bottom-left
+ * origin, while D3D has a top-left origin. */
+void surface_translate_drawable_coords(const struct wined3d_surface *surface, HWND window, RECT *rect)
+{
+    UINT drawable_height;
+    if (surface->swapchain && surface == surface->swapchain->front_buffer)
+    {
+#ifndef VBOX_WITH_WINE_FIXES
+        POINT offset = {0, 0};
+        RECT windowsize;
+
+        ScreenToClient(window, &offset);
+        OffsetRect(rect, offset.x, offset.y);
+
+        GetClientRect(window, &windowsize);
+        drawable_height = windowsize.bottom - windowsize.top;
+#else
+# ifdef VBOX_WINE_STRICT
+        ERR("should not be here!");
+# else
+        WARN("should not be here!");
+# endif
+        drawable_height = surface->resource.height;
+#endif
+    }
+    else
+    {
+        drawable_height = surface->resource.height;
+    }
+
+    rect->top = drawable_height - rect->top;
+    rect->bottom = drawable_height - rect->bottom;
+}
+
+static void surface_blt_to_drawable(const struct wined3d_device *device,
+        enum wined3d_texture_filter_type filter, BOOL color_key,
+        struct wined3d_surface *src_surface, const RECT *src_rect_in,
+        struct wined3d_surface *dst_surface, const RECT *dst_rect_in)
+{
+    const struct wined3d_gl_info *gl_info;
+    struct wined3d_context *context;
+    RECT src_rect, dst_rect;
+
+    src_rect = *src_rect_in;
+    dst_rect = *dst_rect_in;
+
+    /* Make sure the surface is up-to-date. This should probably use
+     * surface_load_location() and worry about the destination surface too,
+     * unless we're overwriting it completely. */
+    surface_internal_preload(src_surface, SRGB_RGB);
+
+    /* Activate the destination context, set it up for blitting */
+    context = context_acquire(device, dst_surface);
+    gl_info = context->gl_info;
+    context_apply_blit_state(context, device);
+
+    if (!surface_is_offscreen(dst_surface))
+#ifndef VBOX_WINE_WITH_SINGLE_CONTEXT
+        surface_translate_drawable_coords(dst_surface, context->win_handle, &dst_rect);
+#else
+        surface_translate_drawable_coords(dst_surface, context->swapchain->win_handle, &dst_rect);
+#endif
+
+    device->blitter->set_shader(device->blit_priv, context, src_surface);
+
+    if (color_key)
+    {
+        gl_info->gl_ops.gl.p_glEnable(GL_ALPHA_TEST);
+        checkGLcall("glEnable(GL_ALPHA_TEST)");
+
+        /* When the primary render target uses P8, the alpha component
+         * contains the palette index. Which means that the colorkey is one of
+         * the palette entries. In other cases pixels that should be masked
+         * away have alpha set to 0. */
+        if (primary_render_target_is_p8(device))
+            gl_info->gl_ops.gl.p_glAlphaFunc(GL_NOTEQUAL,
+                    (float)src_surface->src_blt_color_key.color_space_low_value / 256.0f);
+        else
+            gl_info->gl_ops.gl.p_glAlphaFunc(GL_NOTEQUAL, 0.0f);
+        checkGLcall("glAlphaFunc");
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_ALPHA_TEST);
+        checkGLcall("glDisable(GL_ALPHA_TEST)");
+    }
+
+    draw_textured_quad(src_surface, context, &src_rect, &dst_rect, filter);
+
+    if (color_key)
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_ALPHA_TEST);
+        checkGLcall("glDisable(GL_ALPHA_TEST)");
+    }
+
+    /* Leave the opengl state valid for blitting */
+    device->blitter->unset_shader(context->gl_info);
+
+    if (wined3d_settings.strict_draw_ordering
+            || (dst_surface->swapchain && dst_surface->swapchain->front_buffer == dst_surface))
+        gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */
+
+    context_release(context);
+}
+
+/* Do not call while under the GL lock. */
+HRESULT surface_color_fill(struct wined3d_surface *s, const RECT *rect, const struct wined3d_color *color)
+{
+    struct wined3d_device *device = s->resource.device;
+    const struct blit_shader *blitter;
+
+    blitter = wined3d_select_blitter(&device->adapter->gl_info, WINED3D_BLIT_OP_COLOR_FILL,
+            NULL, 0, 0, NULL, rect, s->resource.usage, s->resource.pool, s->resource.format);
+    if (!blitter)
+    {
+        FIXME("No blitter is capable of performing the requested color fill operation.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    return blitter->color_fill(device, s, rect, color);
+}
+
+/* Do not call while under the GL lock. */
+static HRESULT IWineD3DSurfaceImpl_BltOverride(struct wined3d_surface *dst_surface, const RECT *dst_rect,
+        struct wined3d_surface *src_surface, const RECT *src_rect, DWORD flags, const WINEDDBLTFX *DDBltFx,
+        enum wined3d_texture_filter_type filter)
+{
+    struct wined3d_device *device = dst_surface->resource.device;
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    struct wined3d_swapchain *src_swapchain, *dst_swapchain;
+
+    TRACE("dst_surface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, blt_fx %p, filter %s.\n",
+            dst_surface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect),
+            flags, DDBltFx, debug_d3dtexturefiltertype(filter));
+
+    /* Get the swapchain. One of the surfaces has to be a primary surface */
+    if (dst_surface->resource.pool == WINED3D_POOL_SYSTEM_MEM)
+    {
+        WARN("Destination is in sysmem, rejecting gl blt\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    dst_swapchain = dst_surface->swapchain;
+
+    if (src_surface)
+    {
+        if (src_surface->resource.pool == WINED3D_POOL_SYSTEM_MEM)
+        {
+            WARN("Src is in sysmem, rejecting gl blt\n");
+            return WINED3DERR_INVALIDCALL;
+        }
+
+        src_swapchain = src_surface->swapchain;
+    }
+    else
+    {
+        src_swapchain = NULL;
+    }
+
+    /* Early sort out of cases where no render target is used */
+    if (!dst_swapchain && !src_swapchain
+            && src_surface != device->fb.render_targets[0]
+            && dst_surface != device->fb.render_targets[0])
+    {
+        TRACE("No surface is render target, not using hardware blit.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    /* No destination color keying supported */
+    if (flags & (WINEDDBLT_KEYDEST | WINEDDBLT_KEYDESTOVERRIDE))
+    {
+        /* Can we support that with glBlendFunc if blitting to the frame buffer? */
+        TRACE("Destination color key not supported in accelerated Blit, falling back to software\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    if (dst_swapchain && dst_swapchain == src_swapchain)
+    {
+        FIXME("Implement hardware blit between two surfaces on the same swapchain\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    if (dst_swapchain && src_swapchain)
+    {
+        FIXME("Implement hardware blit between two different swapchains\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    if (dst_swapchain)
+    {
+        /* Handled with regular texture -> swapchain blit */
+        if (src_surface == device->fb.render_targets[0])
+            TRACE("Blit from active render target to a swapchain\n");
+    }
+    else if (src_swapchain && dst_surface == device->fb.render_targets[0])
+    {
+        FIXME("Implement blit from a swapchain to the active render target\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    if ((src_swapchain || src_surface == device->fb.render_targets[0]) && !dst_swapchain)
+    {
+        /* Blit from render target to texture */
+        BOOL stretchx;
+
+        /* P8 read back is not implemented */
+        if (src_surface->resource.format->id == WINED3DFMT_P8_UINT
+                || dst_surface->resource.format->id == WINED3DFMT_P8_UINT)
+        {
+            TRACE("P8 read back not supported by frame buffer to texture blit\n");
+            return WINED3DERR_INVALIDCALL;
+        }
+
+        if (flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYSRCOVERRIDE))
+        {
+            TRACE("Color keying not supported by frame buffer to texture blit\n");
+            return WINED3DERR_INVALIDCALL;
+            /* Destination color key is checked above */
+        }
+
+        if (dst_rect->right - dst_rect->left != src_rect->right - src_rect->left)
+            stretchx = TRUE;
+        else
+            stretchx = FALSE;
+
+        /* Blt is a pretty powerful call, while glCopyTexSubImage2D is not. glCopyTexSubImage cannot
+         * flip the image nor scale it.
+         *
+         * -> If the app asks for a unscaled, upside down copy, just perform one glCopyTexSubImage2D call
+         * -> If the app wants a image width an unscaled width, copy it line per line
+         * -> If the app wants a image that is scaled on the x axis, and the destination rectangle is smaller
+         *    than the frame buffer, draw an upside down scaled image onto the fb, read it back and restore the
+         *    back buffer. This is slower than reading line per line, thus not used for flipping
+         * -> If the app wants a scaled image with a dest rect that is bigger than the fb, it has to be copied
+         *    pixel by pixel. */
+        if (!stretchx || dst_rect->right - dst_rect->left > src_surface->resource.width
+                || dst_rect->bottom - dst_rect->top > src_surface->resource.height)
+        {
+            TRACE("No stretching in x direction, using direct framebuffer -> texture copy.\n");
+            fb_copy_to_texture_direct(dst_surface, src_surface, src_rect, dst_rect, filter);
+        }
+        else
+        {
+            TRACE("Using hardware stretching to flip / stretch the texture.\n");
+            fb_copy_to_texture_hwstretch(dst_surface, src_surface, src_rect, dst_rect, filter);
+        }
+
+        if (!dst_surface->resource.map_count && !(dst_surface->flags & SFLAG_DONOTFREE))
+        {
+            HeapFree(GetProcessHeap(), 0, dst_surface->resource.heapMemory);
+            dst_surface->resource.allocatedMemory = NULL;
+            dst_surface->resource.heapMemory = NULL;
+        }
+        else
+        {
+            dst_surface->flags &= ~SFLAG_INSYSMEM;
+        }
+
+        return WINED3D_OK;
+    }
+    else if (src_surface)
+    {
+        /* Blit from offscreen surface to render target */
+        struct wined3d_color_key old_blt_key = src_surface->src_blt_color_key;
+        DWORD oldCKeyFlags = src_surface->CKeyFlags;
+
+        TRACE("Blt from surface %p to rendertarget %p\n", src_surface, dst_surface);
+
+        if (!device->blitter->blit_supported(gl_info, WINED3D_BLIT_OP_COLOR_BLIT,
+                src_rect, src_surface->resource.usage, src_surface->resource.pool, src_surface->resource.format,
+                dst_rect, dst_surface->resource.usage, dst_surface->resource.pool, dst_surface->resource.format))
+        {
+            FIXME("Unsupported blit operation falling back to software\n");
+            return WINED3DERR_INVALIDCALL;
+        }
+
+        /* Color keying: Check if we have to do a color keyed blt,
+         * and if not check if a color key is activated.
+         *
+         * Just modify the color keying parameters in the surface and restore them afterwards
+         * The surface keeps track of the color key last used to load the opengl surface.
+         * PreLoad will catch the change to the flags and color key and reload if necessary.
+         */
+        if (flags & WINEDDBLT_KEYSRC)
+        {
+            /* Use color key from surface */
+        }
+        else if (flags & WINEDDBLT_KEYSRCOVERRIDE)
+        {
+            /* Use color key from DDBltFx */
+            src_surface->CKeyFlags |= WINEDDSD_CKSRCBLT;
+            src_surface->src_blt_color_key = DDBltFx->ddckSrcColorkey;
+        }
+        else
+        {
+            /* Do not use color key */
+            src_surface->CKeyFlags &= ~WINEDDSD_CKSRCBLT;
+        }
+
+        surface_blt_to_drawable(device, filter, flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYSRCOVERRIDE),
+                src_surface, src_rect, dst_surface, dst_rect);
+
+        /* Restore the color key parameters */
+        src_surface->CKeyFlags = oldCKeyFlags;
+        src_surface->src_blt_color_key = old_blt_key;
+
+        surface_modify_location(dst_surface, dst_surface->draw_binding, TRUE);
+
+        return WINED3D_OK;
+    }
+
+    /* Default: Fall back to the generic blt. Not an error, a TRACE is enough */
+    TRACE("Didn't find any usable render target setup for hw blit, falling back to software\n");
+    return WINED3DERR_INVALIDCALL;
+}
+
+/* Context activation is done by the caller. */
+static void surface_depth_blt(const struct wined3d_surface *surface, struct wined3d_context *context,
+        GLuint texture, GLint x, GLint y, GLsizei w, GLsizei h, GLenum target)
+{
+    struct wined3d_device *device = surface->resource.device;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    GLint compare_mode = GL_NONE;
+    struct blt_info info;
+    GLint old_binding = 0;
+    RECT rect;
+
+    gl_info->gl_ops.gl.p_glPushAttrib(GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_VIEWPORT_BIT);
+
+    gl_info->gl_ops.gl.p_glDisable(GL_CULL_FACE);
+    gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
+    gl_info->gl_ops.gl.p_glDisable(GL_ALPHA_TEST);
+    gl_info->gl_ops.gl.p_glDisable(GL_SCISSOR_TEST);
+    gl_info->gl_ops.gl.p_glDisable(GL_STENCIL_TEST);
+    gl_info->gl_ops.gl.p_glEnable(GL_DEPTH_TEST);
+    gl_info->gl_ops.gl.p_glDepthFunc(GL_ALWAYS);
+    gl_info->gl_ops.gl.p_glDepthMask(GL_TRUE);
+    gl_info->gl_ops.gl.p_glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+    gl_info->gl_ops.gl.p_glViewport(x, y, w, h);
+    gl_info->gl_ops.gl.p_glDepthRange(0.0, 1.0);
+
+    SetRect(&rect, 0, h, w, 0);
+    surface_get_blt_info(target, &rect, surface->pow2Width, surface->pow2Height, &info);
+    context_active_texture(context, context->gl_info, 0);
+    gl_info->gl_ops.gl.p_glGetIntegerv(info.binding, &old_binding);
+    gl_info->gl_ops.gl.p_glBindTexture(info.bind_target, texture);
+    if (gl_info->supported[ARB_SHADOW])
+    {
+        gl_info->gl_ops.gl.p_glGetTexParameteriv(info.bind_target, GL_TEXTURE_COMPARE_MODE_ARB, &compare_mode);
+        if (compare_mode != GL_NONE)
+            gl_info->gl_ops.gl.p_glTexParameteri(info.bind_target, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
+    }
+
+    device->shader_backend->shader_select_depth_blt(device->shader_priv,
+            gl_info, info.tex_type, &surface->ds_current_size);
+
+    gl_info->gl_ops.gl.p_glBegin(GL_TRIANGLE_STRIP);
+    gl_info->gl_ops.gl.p_glTexCoord3fv(info.coords[0]);
+    gl_info->gl_ops.gl.p_glVertex2f(-1.0f, -1.0f);
+    gl_info->gl_ops.gl.p_glTexCoord3fv(info.coords[1]);
+    gl_info->gl_ops.gl.p_glVertex2f(1.0f, -1.0f);
+    gl_info->gl_ops.gl.p_glTexCoord3fv(info.coords[2]);
+    gl_info->gl_ops.gl.p_glVertex2f(-1.0f, 1.0f);
+    gl_info->gl_ops.gl.p_glTexCoord3fv(info.coords[3]);
+    gl_info->gl_ops.gl.p_glVertex2f(1.0f, 1.0f);
+    gl_info->gl_ops.gl.p_glEnd();
+
+    if (compare_mode != GL_NONE)
+        gl_info->gl_ops.gl.p_glTexParameteri(info.bind_target, GL_TEXTURE_COMPARE_MODE_ARB, compare_mode);
+    gl_info->gl_ops.gl.p_glBindTexture(info.bind_target, old_binding);
+
+    gl_info->gl_ops.gl.p_glPopAttrib();
+
+    device->shader_backend->shader_deselect_depth_blt(device->shader_priv, gl_info);
+}
+
+void surface_modify_ds_location(struct wined3d_surface *surface,
+        DWORD location, UINT w, UINT h)
+{
+    TRACE("surface %p, new location %#x, w %u, h %u.\n", surface, location, w, h);
+
+    if (location & ~(SFLAG_LOCATIONS | SFLAG_DISCARDED))
+        FIXME("Invalid location (%#x) specified.\n", location);
+
+    if (((surface->flags & SFLAG_INTEXTURE) && !(location & SFLAG_INTEXTURE))
+            || (!(surface->flags & SFLAG_INTEXTURE) && (location & SFLAG_INTEXTURE)))
+    {
+        if (surface->container)
+        {
+            TRACE("Passing to container.\n");
+            wined3d_texture_set_dirty(surface->container, TRUE);
+        }
+    }
+
+    surface->ds_current_size.cx = w;
+    surface->ds_current_size.cy = h;
+    surface->flags &= ~(SFLAG_LOCATIONS | SFLAG_DISCARDED);
+    surface->flags |= location;
+}
+
+/* Context activation is done by the caller. */
+void surface_load_ds_location(struct wined3d_surface *surface, struct wined3d_context *context, DWORD location)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    struct wined3d_device *device = surface->resource.device;
+    GLsizei w, h;
+
+    TRACE("surface %p, new location %#x.\n", surface, location);
+
+    /* TODO: Make this work for modes other than FBO */
+    if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) return;
+
+    if (!(surface->flags & location))
+    {
+        w = surface->ds_current_size.cx;
+        h = surface->ds_current_size.cy;
+        surface->ds_current_size.cx = 0;
+        surface->ds_current_size.cy = 0;
+    }
+    else
+    {
+        w = surface->resource.width;
+        h = surface->resource.height;
+    }
+
+    if (surface->ds_current_size.cx == surface->resource.width
+            && surface->ds_current_size.cy == surface->resource.height)
+    {
+        TRACE("Location (%#x) is already up to date.\n", location);
+        return;
+    }
+
+    if (surface->current_renderbuffer)
+    {
+        FIXME("Not supported with fixed up depth stencil.\n");
+        return;
+    }
+
+    if (surface->flags & SFLAG_DISCARDED)
+    {
+        TRACE("Surface was discarded, no need copy data.\n");
+        switch (location)
+        {
+            case SFLAG_INTEXTURE:
+                surface_prepare_texture(surface, context, FALSE);
+                break;
+            case SFLAG_INRB_MULTISAMPLE:
+                surface_prepare_rb(surface, gl_info, TRUE);
+                break;
+            case SFLAG_INDRAWABLE:
+                /* Nothing to do */
+                break;
+            default:
+                FIXME("Unhandled location %#x\n", location);
+        }
+        surface->flags &= ~SFLAG_DISCARDED;
+        surface->flags |= location;
+        surface->ds_current_size.cx = surface->resource.width;
+        surface->ds_current_size.cy = surface->resource.height;
+        return;
+    }
+
+    if (!(surface->flags & SFLAG_LOCATIONS))
+    {
+        FIXME("No up to date depth stencil location.\n");
+        surface->flags |= location;
+        surface->ds_current_size.cx = surface->resource.width;
+        surface->ds_current_size.cy = surface->resource.height;
+        return;
+    }
+
+    if (location == SFLAG_INTEXTURE)
+    {
+        GLint old_binding = 0;
+        GLenum bind_target;
+
+        /* The render target is allowed to be smaller than the depth/stencil
+         * buffer, so the onscreen depth/stencil buffer is potentially smaller
+         * than the offscreen surface. Don't overwrite the offscreen surface
+         * with undefined data. */
+        w = min(w, context->swapchain->desc.backbuffer_width);
+        h = min(h, context->swapchain->desc.backbuffer_height);
+
+        TRACE("Copying onscreen depth buffer to depth texture.\n");
+
+        if (!device->depth_blt_texture)
+            gl_info->gl_ops.gl.p_glGenTextures(1, &device->depth_blt_texture);
+
+        /* Note that we use depth_blt here as well, rather than glCopyTexImage2D
+         * directly on the FBO texture. That's because we need to flip. */
+        context_apply_fbo_state_blit(context, GL_FRAMEBUFFER,
+                context->swapchain->front_buffer, NULL, SFLAG_INDRAWABLE);
+        if (surface->texture_target == GL_TEXTURE_RECTANGLE_ARB)
+        {
+            gl_info->gl_ops.gl.p_glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &old_binding);
+            bind_target = GL_TEXTURE_RECTANGLE_ARB;
+        }
+        else
+        {
+            gl_info->gl_ops.gl.p_glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_binding);
+            bind_target = GL_TEXTURE_2D;
+        }
+        gl_info->gl_ops.gl.p_glBindTexture(bind_target, device->depth_blt_texture);
+        /* We use GL_DEPTH_COMPONENT instead of the surface's specific
+         * internal format, because the internal format might include stencil
+         * data. In principle we should copy stencil data as well, but unless
+         * the driver supports stencil export it's hard to do, and doesn't
+         * seem to be needed in practice. If the hardware doesn't support
+         * writing stencil data, the glCopyTexImage2D() call might trigger
+         * software fallbacks. */
+        gl_info->gl_ops.gl.p_glCopyTexImage2D(bind_target, 0, GL_DEPTH_COMPONENT, 0, 0, w, h, 0);
+        gl_info->gl_ops.gl.p_glTexParameteri(bind_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        gl_info->gl_ops.gl.p_glTexParameteri(bind_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        gl_info->gl_ops.gl.p_glTexParameteri(bind_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+        gl_info->gl_ops.gl.p_glTexParameteri(bind_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+        gl_info->gl_ops.gl.p_glTexParameteri(bind_target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+        gl_info->gl_ops.gl.p_glTexParameteri(bind_target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
+        gl_info->gl_ops.gl.p_glBindTexture(bind_target, old_binding);
+
+        context_apply_fbo_state_blit(context, GL_FRAMEBUFFER,
+                NULL, surface, SFLAG_INTEXTURE);
+        context_set_draw_buffer(context, GL_NONE);
+
+        /* Do the actual blit */
+        surface_depth_blt(surface, context, device->depth_blt_texture, 0, 0, w, h, bind_target);
+        checkGLcall("depth_blt");
+
+        context_invalidate_state(context, STATE_FRAMEBUFFER);
+
+        if (wined3d_settings.strict_draw_ordering)
+            gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */
+    }
+    else if (location == SFLAG_INDRAWABLE)
+    {
+        TRACE("Copying depth texture to onscreen depth buffer.\n");
+
+        context_apply_fbo_state_blit(context, GL_FRAMEBUFFER,
+                context->swapchain->front_buffer, NULL, SFLAG_INDRAWABLE);
+        surface_depth_blt(surface, context, surface->texture_name,
+                0, surface->pow2Height - h, w, h, surface->texture_target);
+        checkGLcall("depth_blt");
+
+        context_invalidate_state(context, STATE_FRAMEBUFFER);
+
+        if (wined3d_settings.strict_draw_ordering)
+            gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */
+    }
+    else
+    {
+        ERR("Invalid location (%#x) specified.\n", location);
+    }
+
+    surface->flags |= location;
+    surface->ds_current_size.cx = surface->resource.width;
+    surface->ds_current_size.cy = surface->resource.height;
+}
+
+void surface_modify_location(struct wined3d_surface *surface, DWORD location, BOOL persistent)
+{
+    const struct wined3d_gl_info *gl_info = &surface->resource.device->adapter->gl_info;
+    struct wined3d_surface *overlay;
+
+    TRACE("surface %p, location %s, persistent %#x.\n",
+            surface, debug_surflocation(location), persistent);
+
+    if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && surface_is_offscreen(surface)
+            && !(surface->resource.usage & WINED3DUSAGE_DEPTHSTENCIL)
+            && (location & SFLAG_INDRAWABLE))
+        ERR("Trying to invalidate the SFLAG_INDRAWABLE location of an offscreen surface.\n");
+
+    if (location & (SFLAG_INTEXTURE | SFLAG_INSRGBTEX)
+            && gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
+        location |= (SFLAG_INTEXTURE | SFLAG_INSRGBTEX);
+
+    if (persistent)
+    {
+        if (((surface->flags & SFLAG_INTEXTURE) && !(location & SFLAG_INTEXTURE))
+                || ((surface->flags & SFLAG_INSRGBTEX) && !(location & SFLAG_INSRGBTEX)))
+        {
+            if (surface->container)
+            {
+                TRACE("Passing to container.\n");
+                wined3d_texture_set_dirty(surface->container, TRUE);
+            }
+        }
+
+#ifdef VBOX_WITH_WDDM
+        {
+            /* sometimes wine can call ModifyLocation(SFLAG_INTEXTURE, TRUE) for surfaces that do not yet have
+             * ogl texture backend assigned, e.g. when doing ColorFill right after surface creation
+             * to prevent wine state breakage that could occur later on in that case, we check
+             * whether tex gen is needed here and generate it accordingly */
+            if (!surface->texture_name)
+            {
+                Assert(!(surface->flags & SFLAG_INTEXTURE));
+                if (location & SFLAG_INTEXTURE)
+                {
+                    Assert(0);
+//                    struct wined3d_context *context = NULL;
+//                    IWineD3DDeviceImpl *device = This->resource.device;
+//                    const struct wined3d_gl_info *gl_info;
+//
+//                    if (!device->isInDraw) context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD);
+//                    gl_info = context->gl_info;
+//
+//                    surface_prepare_texture(This, gl_info, FALSE);
+//
+//                    if (context) context_release(context);
+                }
+            }
+
+            if (!surface->texture_name_srgb)
+            {
+                Assert(!(surface->flags & SFLAG_INSRGBTEX));
+                if (location & SFLAG_INSRGBTEX)
+                {
+                    Assert(0);
+//                    struct wined3d_context *context = NULL;
+//                    IWineD3DDeviceImpl *device = This->resource.device;
+//                    const struct wined3d_gl_info *gl_info;
+//
+//                    if (!device->isInDraw) context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD);
+//                    gl_info = context->gl_info;
+//
+//                    surface_prepare_texture(This, gl_info, TRUE);
+//
+//                    if (context) context_release(context);
+                }
+            }
+        }
+#endif
+
+        surface->flags &= ~SFLAG_LOCATIONS;
+        surface->flags |= location;
+
+        /* Redraw emulated overlays, if any */
+        if (location & SFLAG_INDRAWABLE && !list_empty(&surface->overlays))
+        {
+            LIST_FOR_EACH_ENTRY(overlay, &surface->overlays, struct wined3d_surface, overlay_entry)
+            {
+                surface_draw_overlay(overlay);
+            }
+        }
+    }
+    else
+    {
+        if ((surface->flags & (SFLAG_INTEXTURE | SFLAG_INSRGBTEX)) && (location & (SFLAG_INTEXTURE | SFLAG_INSRGBTEX)))
+        {
+            if (surface->container)
+            {
+                TRACE("Passing to container\n");
+                wined3d_texture_set_dirty(surface->container, TRUE);
+            }
+        }
+        surface->flags &= ~location;
+    }
+
+#ifdef VBOX_WITH_WDDM
+    if(VBOXSHRC_IS_SHARED_UNLOCKED(surface)) {
+        /* with the shared resource only texture can be considered valid
+         * to make sure changes done to the resource in the other device context are visible
+         * because the resource contents is shared via texture.
+         * This is why we ensure texture location is the one and only which is always valid */
+        if(!(surface->flags & SFLAG_INTEXTURE)) {
+            surface_load_location(surface, SFLAG_INTEXTURE, NULL);
+        } else {
+            surface->flags &= ~SFLAG_LOCATIONS;
+            surface->flags |= SFLAG_INTEXTURE;
+        }
+    }
+    else if (surface->flags & SFLAG_CLIENTMEM)
+    {
+        if(!(surface->flags & SFLAG_INSYSMEM)) {
+            surface_load_location(surface, SFLAG_INSYSMEM, NULL);
+        } else {
+            surface->flags &= ~SFLAG_LOCATIONS;
+            surface->flags |= SFLAG_INSYSMEM;
+        }
+    }
+#endif
+
+
+    if (!(surface->flags & SFLAG_LOCATIONS))
+    {
+        ERR("Surface %p does not have any up to date location.\n", surface);
+    }
+}
+
+static DWORD resource_access_from_location(DWORD location)
+{
+    switch (location)
+    {
+        case SFLAG_INSYSMEM:
+            return WINED3D_RESOURCE_ACCESS_CPU;
+
+        case SFLAG_INDRAWABLE:
+        case SFLAG_INSRGBTEX:
+        case SFLAG_INTEXTURE:
+        case SFLAG_INRB_MULTISAMPLE:
+        case SFLAG_INRB_RESOLVED:
+            return WINED3D_RESOURCE_ACCESS_GPU;
+
+        default:
+            FIXME("Unhandled location %#x.\n", location);
+            return 0;
+    }
+}
+
+static void surface_load_sysmem(struct wined3d_surface *surface,
+        const struct wined3d_gl_info *gl_info, const RECT *rect)
+{
+    surface_prepare_system_memory(surface);
+
+    if (surface->flags & (SFLAG_INRB_MULTISAMPLE | SFLAG_INRB_RESOLVED))
+        surface_load_location(surface, SFLAG_INTEXTURE, NULL);
+
+    /* Download the surface to system memory. */
+    if (surface->flags & (SFLAG_INTEXTURE | SFLAG_INSRGBTEX))
+    {
+        struct wined3d_device *device = surface->resource.device;
+        struct wined3d_context *context;
+
+        /* TODO: Use already acquired context when possible. */
+        context = context_acquire(device, NULL);
+
+        surface_bind_and_dirtify(surface, context, !(surface->flags & SFLAG_INTEXTURE));
+        surface_download_data(surface, gl_info);
+
+        context_release(context);
+
+        return;
+    }
+
+    if (surface->flags & SFLAG_INDRAWABLE)
+    {
+        read_from_framebuffer(surface, rect, surface->resource.allocatedMemory,
+                wined3d_surface_get_pitch(surface));
+        return;
+    }
+
+    FIXME("Can't load surface %p with location flags %#x into sysmem.\n",
+            surface, surface->flags & SFLAG_LOCATIONS);
+}
+
+static HRESULT surface_load_drawable(struct wined3d_surface *surface,
+        const struct wined3d_gl_info *gl_info, const RECT *rect)
+{
+    struct wined3d_device *device = surface->resource.device;
+    enum wined3d_conversion_type convert;
+    struct wined3d_format format;
+    UINT byte_count;
+    BYTE *mem;
+
+    if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && surface_is_offscreen(surface))
+    {
+        ERR("Trying to load offscreen surface into SFLAG_INDRAWABLE.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    if (wined3d_settings.rendertargetlock_mode == RTL_READTEX)
+        surface_load_location(surface, SFLAG_INTEXTURE, NULL);
+
+    if (surface->flags & SFLAG_INTEXTURE)
+    {
+        RECT r;
+
+        surface_get_rect(surface, rect, &r);
+        surface_blt_to_drawable(device, WINED3D_TEXF_POINT, FALSE, surface, &r, surface, &r);
+
+        return WINED3D_OK;
+    }
+
+    if ((surface->flags & SFLAG_LOCATIONS) == SFLAG_INSRGBTEX)
+    {
+        /* This needs colorspace conversion from sRGB to RGB. We take the slow
+         * path through sysmem. */
+        surface_load_location(surface, SFLAG_INSYSMEM, rect);
+    }
+
+    d3dfmt_get_conv(surface, FALSE, FALSE, &format, &convert);
+
+    /* Don't use PBOs for converted surfaces. During PBO conversion we look at
+     * SFLAG_CONVERTED but it isn't set (yet) in all cases where it is getting
+     * called. */
+    if ((convert != WINED3D_CT_NONE) && (surface->flags & SFLAG_PBO))
+    {
+        struct wined3d_context *context;
+
+        TRACE("Removing the pbo attached to surface %p.\n", surface);
+
+        /* TODO: Use already acquired context when possible. */
+        context = context_acquire(device, NULL);
+
+        surface_remove_pbo(surface, gl_info);
+
+        context_release(context);
+    }
+
+    if ((convert != WINED3D_CT_NONE) && surface->resource.allocatedMemory)
+    {
+        UINT height = surface->resource.height;
+        UINT width = surface->resource.width;
+        UINT src_pitch, dst_pitch;
+
+        byte_count = format.conv_byte_count;
+        src_pitch = wined3d_surface_get_pitch(surface);
+
+        /* Stick to the alignment for the converted surface too, makes it
+         * easier to load the surface. */
+        dst_pitch = width * byte_count;
+        dst_pitch = (dst_pitch + device->surface_alignment - 1) & ~(device->surface_alignment - 1);
+
+        if (!(mem = HeapAlloc(GetProcessHeap(), 0, dst_pitch * height)))
+        {
+            ERR("Out of memory (%u).\n", dst_pitch * height);
+            return E_OUTOFMEMORY;
+        }
+
+        d3dfmt_convert_surface(surface->resource.allocatedMemory, mem,
+                src_pitch, width, height, dst_pitch, convert, surface);
+
+        surface->flags |= SFLAG_CONVERTED;
+    }
+    else
+    {
+        surface->flags &= ~SFLAG_CONVERTED;
+        mem = surface->resource.allocatedMemory;
+        byte_count = format.byte_count;
+    }
+
+    flush_to_framebuffer_drawpixels(surface, rect, format.glFormat, format.glType, byte_count, mem);
+
+    /* Don't delete PBO memory. */
+    if ((mem != surface->resource.allocatedMemory) && !(surface->flags & SFLAG_PBO))
+        HeapFree(GetProcessHeap(), 0, mem);
+
+    return WINED3D_OK;
+}
+
+static HRESULT surface_load_texture(struct wined3d_surface *surface,
+        const struct wined3d_gl_info *gl_info, const RECT *rect, BOOL srgb)
+{
+    RECT src_rect = {0, 0, surface->resource.width, surface->resource.height};
+    struct wined3d_device *device = surface->resource.device;
+    enum wined3d_conversion_type convert;
+    struct wined3d_context *context;
+    UINT width, src_pitch, dst_pitch;
+    struct wined3d_bo_address data;
+    struct wined3d_format format;
+    POINT dst_point = {0, 0};
+    BYTE *mem;
+
+    if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
+            && surface_is_offscreen(surface)
+            && (surface->flags & SFLAG_INDRAWABLE))
+    {
+        surface_load_fb_texture(surface, srgb);
+
+        return WINED3D_OK;
+    }
+
+    if (surface->flags & (SFLAG_INSRGBTEX | SFLAG_INTEXTURE)
+            && (surface->resource.format->flags & WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB)
+            && fbo_blit_supported(gl_info, WINED3D_BLIT_OP_COLOR_BLIT,
+                NULL, surface->resource.usage, surface->resource.pool, surface->resource.format,
+                NULL, surface->resource.usage, surface->resource.pool, surface->resource.format))
+    {
+        if (srgb)
+            surface_blt_fbo(device, WINED3D_TEXF_POINT, surface, SFLAG_INTEXTURE,
+                    &src_rect, surface, SFLAG_INSRGBTEX, &src_rect);
+        else
+            surface_blt_fbo(device, WINED3D_TEXF_POINT, surface, SFLAG_INSRGBTEX,
+                    &src_rect, surface, SFLAG_INTEXTURE, &src_rect);
+
+        return WINED3D_OK;
+    }
+
+    if (surface->flags & (SFLAG_INRB_MULTISAMPLE | SFLAG_INRB_RESOLVED)
+            && (!srgb || (surface->resource.format->flags & WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB))
+            && fbo_blit_supported(gl_info, WINED3D_BLIT_OP_COLOR_BLIT,
+                NULL, surface->resource.usage, surface->resource.pool, surface->resource.format,
+                NULL, surface->resource.usage, surface->resource.pool, surface->resource.format))
+    {
+        DWORD src_location = surface->flags & SFLAG_INRB_RESOLVED ? SFLAG_INRB_RESOLVED : SFLAG_INRB_MULTISAMPLE;
+        DWORD dst_location = srgb ? SFLAG_INSRGBTEX : SFLAG_INTEXTURE;
+        RECT rect = {0, 0, surface->resource.width, surface->resource.height};
+
+        surface_blt_fbo(device, WINED3D_TEXF_POINT, surface, src_location,
+                &rect, surface, dst_location, &rect);
+
+        return WINED3D_OK;
+    }
+
+    /* Upload from system memory */
+
+    d3dfmt_get_conv(surface, TRUE /* We need color keying */,
+            TRUE /* We will use textures */, &format, &convert);
+
+    if (srgb)
+    {
+        if ((surface->flags & (SFLAG_INTEXTURE | SFLAG_INSYSMEM)) == SFLAG_INTEXTURE)
+        {
+            /* Performance warning... */
+            FIXME("Downloading RGB surface %p to reload it as sRGB.\n", surface);
+            surface_load_location(surface, SFLAG_INSYSMEM, rect);
+        }
+    }
+    else
+    {
+        if ((surface->flags & (SFLAG_INSRGBTEX | SFLAG_INSYSMEM)) == SFLAG_INSRGBTEX)
+        {
+            /* Performance warning... */
+            FIXME("Downloading sRGB surface %p to reload it as RGB.\n", surface);
+            surface_load_location(surface, SFLAG_INSYSMEM, rect);
+        }
+    }
+
+    if (!(surface->flags & SFLAG_INSYSMEM))
+    {
+        WARN("Trying to load a texture from sysmem, but SFLAG_INSYSMEM is not set.\n");
+        /* Lets hope we get it from somewhere... */
+        surface_load_location(surface, SFLAG_INSYSMEM, rect);
+    }
+
+    /* TODO: Use already acquired context when possible. */
+    context = context_acquire(device, NULL);
+
+    surface_prepare_texture(surface, context, srgb);
+    surface_bind_and_dirtify(surface, context, srgb);
+
+    if (surface->CKeyFlags & WINEDDSD_CKSRCBLT)
+    {
+        surface->flags |= SFLAG_GLCKEY;
+        surface->gl_color_key = surface->src_blt_color_key;
+    }
+    else surface->flags &= ~SFLAG_GLCKEY;
+
+    width = surface->resource.width;
+    src_pitch = wined3d_surface_get_pitch(surface);
+
+    /* Don't use PBOs for converted surfaces. During PBO conversion we look at
+     * SFLAG_CONVERTED but it isn't set (yet) in all cases it is getting
+     * called. */
+    if ((convert != WINED3D_CT_NONE || format.convert) && (surface->flags & SFLAG_PBO))
+    {
+        TRACE("Removing the pbo attached to surface %p.\n", surface);
+        surface_remove_pbo(surface, gl_info);
+    }
+
+    if (format.convert)
+    {
+        /* This code is entered for texture formats which need a fixup. */
+        UINT height = surface->resource.height;
+
+        /* Stick to the alignment for the converted surface too, makes it easier to load the surface */
+        dst_pitch = width * format.conv_byte_count;
+        dst_pitch = (dst_pitch + device->surface_alignment - 1) & ~(device->surface_alignment - 1);
+
+        if (!(mem = HeapAlloc(GetProcessHeap(), 0, dst_pitch * height)))
+        {
+            ERR("Out of memory (%u).\n", dst_pitch * height);
+            context_release(context);
+            return E_OUTOFMEMORY;
+        }
+        format.convert(surface->resource.allocatedMemory, mem, src_pitch, width, height);
+        format.byte_count = format.conv_byte_count;
+        src_pitch = dst_pitch;
+    }
+    else if (convert != WINED3D_CT_NONE && surface->resource.allocatedMemory)
+    {
+        /* This code is only entered for color keying fixups */
+        UINT height = surface->resource.height;
+
+        /* Stick to the alignment for the converted surface too, makes it easier to load the surface */
+        dst_pitch = width * format.conv_byte_count;
+        dst_pitch = (dst_pitch + device->surface_alignment - 1) & ~(device->surface_alignment - 1);
+
+        if (!(mem = HeapAlloc(GetProcessHeap(), 0, dst_pitch * height)))
+        {
+            ERR("Out of memory (%u).\n", dst_pitch * height);
+            context_release(context);
+            return E_OUTOFMEMORY;
+        }
+        d3dfmt_convert_surface(surface->resource.allocatedMemory, mem, src_pitch,
+                width, height, dst_pitch, convert, surface);
+        format.byte_count = format.conv_byte_count;
+        src_pitch = dst_pitch;
+    }
+    else
+    {
+        mem = surface->resource.allocatedMemory;
+    }
+
+    data.buffer_object = surface->pbo;
+    data.addr = mem;
+    surface_upload_data(surface, gl_info, &format, &src_rect, src_pitch, &dst_point, srgb, &data);
+
+    context_release(context);
+
+    /* Don't delete PBO memory. */
+    if ((mem != surface->resource.allocatedMemory) && !(surface->flags & SFLAG_PBO))
+        HeapFree(GetProcessHeap(), 0, mem);
+
+    return WINED3D_OK;
+}
+
+static void surface_multisample_resolve(struct wined3d_surface *surface)
+{
+    RECT rect = {0, 0, surface->resource.width, surface->resource.height};
+
+    if (!(surface->flags & SFLAG_INRB_MULTISAMPLE))
+        ERR("Trying to resolve multisampled surface %p, but location SFLAG_INRB_MULTISAMPLE not current.\n", surface);
+
+    surface_blt_fbo(surface->resource.device, WINED3D_TEXF_POINT,
+            surface, SFLAG_INRB_MULTISAMPLE, &rect, surface, SFLAG_INRB_RESOLVED, &rect);
+}
+
+HRESULT surface_load_location(struct wined3d_surface *surface, DWORD location, const RECT *rect)
+{
+    struct wined3d_device *device = surface->resource.device;
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    HRESULT hr;
+
+    TRACE("surface %p, location %s, rect %s.\n", surface, debug_surflocation(location), wine_dbgstr_rect(rect));
+
+    if (surface->resource.usage & WINED3DUSAGE_DEPTHSTENCIL)
+    {
+        if (location == SFLAG_INTEXTURE && surface->flags & SFLAG_INDRAWABLE)
+        {
+            struct wined3d_context *context = context_acquire(device, NULL);
+            surface_load_ds_location(surface, context, location);
+            context_release(context);
+#ifndef VBOX_WITH_WDDM
+            return WINED3D_OK;
+#else
+            goto post_process;
+#endif
+        }
+        else if (location & surface->flags && surface->draw_binding != SFLAG_INDRAWABLE)
+        {
+            /* Already up to date, nothing to do. */
+#ifndef VBOX_WITH_WDDM
+            return WINED3D_OK;
+#else
+            goto post_process;
+#endif
+        }
+        else
+        {
+            FIXME("Unimplemented copy from %s to %s for depth/stencil buffers.\n",
+                    debug_surflocation(surface->flags & SFLAG_LOCATIONS), debug_surflocation(location));
+            return WINED3DERR_INVALIDCALL;
+        }
+    }
+
+    if (location == SFLAG_INSRGBTEX && gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
+        location = SFLAG_INTEXTURE;
+
+    if (surface->flags & location)
+    {
+        TRACE("Location already up to date.\n");
+
+        if (location == SFLAG_INSYSMEM && !(surface->flags & SFLAG_PBO)
+                && surface_need_pbo(surface, gl_info))
+            surface_load_pbo(surface, gl_info);
+
+#ifndef VBOX_WITH_WDDM
+        return WINED3D_OK;
+#else
+        goto post_process;
+#endif
+    }
+
+    if (WARN_ON(d3d_surface))
+    {
+        DWORD required_access = resource_access_from_location(location);
+        if ((surface->resource.access_flags & required_access) != required_access)
+            WARN("Operation requires %#x access, but surface only has %#x.\n",
+                    required_access, surface->resource.access_flags);
+    }
+
+    if (!(surface->flags & SFLAG_LOCATIONS))
+    {
+        ERR("Surface %p does not have any up to date location.\n", surface);
+        surface->flags |= SFLAG_LOST;
+        return WINED3DERR_DEVICELOST;
+    }
+
+    switch (location)
+    {
+        case SFLAG_INSYSMEM:
+            surface_load_sysmem(surface, gl_info, rect);
+            break;
+
+        case SFLAG_INDRAWABLE:
+            if (FAILED(hr = surface_load_drawable(surface, gl_info, rect)))
+                return hr;
+            break;
+
+        case SFLAG_INRB_RESOLVED:
+            surface_multisample_resolve(surface);
+            break;
+
+        case SFLAG_INTEXTURE:
+        case SFLAG_INSRGBTEX:
+            if (FAILED(hr = surface_load_texture(surface, gl_info, rect, location == SFLAG_INSRGBTEX)))
+                return hr;
+            break;
+
+        default:
+            ERR("Don't know how to handle location %#x.\n", location);
+            break;
+    }
+
+#ifdef VBOX_WITH_WDDM
+post_process:
+
+    if (VBOXSHRC_IS_SHARED_UNLOCKED(surface))
+    {
+        /* with the shared resource only texture can be considered valid
+         * to make sure changes done to the resource in the other device context are visible
+         * because the resource contents is shared via texture.
+         * One can load and use other locations as needed,
+         * but they should be reloaded each time on each usage */
+        Assert(!!(surface->flags & SFLAG_INTEXTURE) || !!(location & SFLAG_INTEXTURE));
+        surface->flags &= ~SFLAG_LOCATIONS;
+        surface->flags |= SFLAG_INTEXTURE;
+        /* @todo: SFLAG_INSRGBTEX ?? */
+//        if (in_fbo)
+//        {
+//            surface->flags |= SFLAG_INDRAWABLE;
+//        }
+    }
+    else if (surface->flags & SFLAG_CLIENTMEM)
+    {
+        Assert(!!(surface->flags & SFLAG_INSYSMEM));
+        surface->flags &= ~SFLAG_LOCATIONS;
+        surface->flags |= SFLAG_INSYSMEM;
+    }
+    else
+#endif
+    {
+    if (!rect)
+    {
+        surface->flags |= location;
+
+        if (location != SFLAG_INSYSMEM && (surface->flags & SFLAG_INSYSMEM))
+            surface_evict_sysmem(surface);
+    }
+
+    if (surface->flags & (SFLAG_INTEXTURE | SFLAG_INSRGBTEX)
+            && gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
+    {
+        surface->flags |= (SFLAG_INTEXTURE | SFLAG_INSRGBTEX);
+    }
+    }
+
+    return WINED3D_OK;
+}
+
+BOOL surface_is_offscreen(const struct wined3d_surface *surface)
+{
+    struct wined3d_swapchain *swapchain;
+
+    /* Not on a swapchain - must be offscreen */
+    if (!(swapchain = surface->swapchain))
+        return TRUE;
+
+    /* The front buffer is always onscreen */
+    if (surface == swapchain->front_buffer) return FALSE;
+
+    /* If the swapchain is rendered to an FBO, the backbuffer is
+     * offscreen, otherwise onscreen */
+    return swapchain->render_to_fbo;
+}
+
+static HRESULT ffp_blit_alloc(struct wined3d_device *device) { return WINED3D_OK; }
+/* Context activation is done by the caller. */
+static void ffp_blit_free(struct wined3d_device *device) { }
+
+/* This function is used in case of 8bit paletted textures using GL_EXT_paletted_texture */
+/* Context activation is done by the caller. */
+static void ffp_blit_p8_upload_palette(const struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info)
+{
+    BYTE table[256][4];
+    BOOL colorkey_active = (surface->CKeyFlags & WINEDDSD_CKSRCBLT) != 0;
+    GLenum target;
+
+    if (surface->container)
+        target = surface->container->target;
+    else
+        target = surface->texture_target;
+
+    d3dfmt_p8_init_palette(surface, table, colorkey_active);
+
+    TRACE("Using GL_EXT_PALETTED_TEXTURE for 8-bit paletted texture support\n");
+    GL_EXTCALL(glColorTableEXT(target, GL_RGBA, 256, GL_RGBA, GL_UNSIGNED_BYTE, table));
+}
+
+/* Context activation is done by the caller. */
+static HRESULT ffp_blit_set(void *blit_priv, struct wined3d_context *context, const struct wined3d_surface *surface)
+{
+    enum complex_fixup fixup = get_complex_fixup(surface->resource.format->color_fixup);
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    GLenum target;
+
+    if (surface->container)
+        target = surface->container->target;
+    else
+        target = surface->texture_target;
+
+    /* When EXT_PALETTED_TEXTURE is around, palette conversion is done by the GPU
+     * else the surface is converted in software at upload time in LoadLocation.
+     */
+    if (!(surface->flags & SFLAG_CONVERTED) && fixup == COMPLEX_FIXUP_P8
+            && gl_info->supported[EXT_PALETTED_TEXTURE])
+        ffp_blit_p8_upload_palette(surface, gl_info);
+
+    gl_info->gl_ops.gl.p_glEnable(target);
+    checkGLcall("glEnable(target)");
+    return WINED3D_OK;
+}
+
+/* Context activation is done by the caller. */
+static void ffp_blit_unset(const struct wined3d_gl_info *gl_info)
+{
+    gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
+    checkGLcall("glDisable(GL_TEXTURE_2D)");
+    if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB);
+        checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
+    }
+    if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB);
+        checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
+    }
+}
+
+static BOOL ffp_blit_supported(const struct wined3d_gl_info *gl_info, enum wined3d_blit_op blit_op,
+        const RECT *src_rect, DWORD src_usage, enum wined3d_pool src_pool, const struct wined3d_format *src_format,
+        const RECT *dst_rect, DWORD dst_usage, enum wined3d_pool dst_pool, const struct wined3d_format *dst_format)
+{
+    enum complex_fixup src_fixup;
+
+    switch (blit_op)
+    {
+        case WINED3D_BLIT_OP_COLOR_BLIT:
+            if (src_pool == WINED3D_POOL_SYSTEM_MEM || dst_pool == WINED3D_POOL_SYSTEM_MEM)
+                return FALSE;
+
+            src_fixup = get_complex_fixup(src_format->color_fixup);
+            if (TRACE_ON(d3d_surface) && TRACE_ON(d3d))
+            {
+                TRACE("Checking support for fixup:\n");
+                dump_color_fixup_desc(src_format->color_fixup);
+            }
+
+            if (!is_identity_fixup(dst_format->color_fixup))
+            {
+                TRACE("Destination fixups are not supported\n");
+                return FALSE;
+            }
+
+            if (src_fixup == COMPLEX_FIXUP_P8 && gl_info->supported[EXT_PALETTED_TEXTURE])
+            {
+                TRACE("P8 fixup supported\n");
+                return TRUE;
+            }
+
+            /* We only support identity conversions. */
+            if (is_identity_fixup(src_format->color_fixup))
+            {
+                TRACE("[OK]\n");
+                return TRUE;
+            }
+
+            TRACE("[FAILED]\n");
+            return FALSE;
+
+        case WINED3D_BLIT_OP_COLOR_FILL:
+            if (dst_pool == WINED3D_POOL_SYSTEM_MEM)
+                return FALSE;
+
+            if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
+            {
+                if (!((dst_format->flags & WINED3DFMT_FLAG_FBO_ATTACHABLE) || (dst_usage & WINED3DUSAGE_RENDERTARGET)))
+                    return FALSE;
+            }
+            else if (!(dst_usage & WINED3DUSAGE_RENDERTARGET))
+            {
+                TRACE("Color fill not supported\n");
+                return FALSE;
+            }
+
+            /* FIXME: We should reject color fills on formats with fixups,
+             * but this would break P8 color fills for example. */
+
+            return TRUE;
+
+        case WINED3D_BLIT_OP_DEPTH_FILL:
+            return TRUE;
+
+        default:
+            TRACE("Unsupported blit_op=%d\n", blit_op);
+            return FALSE;
+    }
+}
+
+/* Do not call while under the GL lock. */
+static HRESULT ffp_blit_color_fill(struct wined3d_device *device, struct wined3d_surface *dst_surface,
+        const RECT *dst_rect, const struct wined3d_color *color)
+{
+    const RECT draw_rect = {0, 0, dst_surface->resource.width, dst_surface->resource.height};
+    struct wined3d_fb_state fb = {&dst_surface, NULL};
+
+    device_clear_render_targets(device, 1, &fb, 1, dst_rect, &draw_rect, WINED3DCLEAR_TARGET, color, 0.0f, 0);
+
+    return WINED3D_OK;
+}
+
+/* Do not call while under the GL lock. */
+static HRESULT ffp_blit_depth_fill(struct wined3d_device *device,
+        struct wined3d_surface *surface, const RECT *rect, float depth)
+{
+    const RECT draw_rect = {0, 0, surface->resource.width, surface->resource.height};
+    struct wined3d_fb_state fb = {NULL, surface};
+
+    device_clear_render_targets(device, 0, &fb, 1, rect, &draw_rect, WINED3DCLEAR_ZBUFFER, 0, depth, 0);
+
+    return WINED3D_OK;
+}
+
+const struct blit_shader ffp_blit =  {
+    ffp_blit_alloc,
+    ffp_blit_free,
+    ffp_blit_set,
+    ffp_blit_unset,
+    ffp_blit_supported,
+    ffp_blit_color_fill,
+    ffp_blit_depth_fill,
+};
+
+static HRESULT cpu_blit_alloc(struct wined3d_device *device)
+{
+    return WINED3D_OK;
+}
+
+/* Context activation is done by the caller. */
+static void cpu_blit_free(struct wined3d_device *device)
+{
+}
+
+/* Context activation is done by the caller. */
+static HRESULT cpu_blit_set(void *blit_priv, struct wined3d_context *context, const struct wined3d_surface *surface)
+{
+    return WINED3D_OK;
+}
+
+/* Context activation is done by the caller. */
+static void cpu_blit_unset(const struct wined3d_gl_info *gl_info)
+{
+}
+
+static BOOL cpu_blit_supported(const struct wined3d_gl_info *gl_info, enum wined3d_blit_op blit_op,
+        const RECT *src_rect, DWORD src_usage, enum wined3d_pool src_pool, const struct wined3d_format *src_format,
+        const RECT *dst_rect, DWORD dst_usage, enum wined3d_pool dst_pool, const struct wined3d_format *dst_format)
+{
+    if (blit_op == WINED3D_BLIT_OP_COLOR_FILL)
+    {
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+static HRESULT surface_cpu_blt_compressed(const BYTE *src_data, BYTE *dst_data,
+        UINT src_pitch, UINT dst_pitch, UINT update_w, UINT update_h,
+        const struct wined3d_format *format, DWORD flags, const WINEDDBLTFX *fx)
+{
+    UINT row_block_count;
+    const BYTE *src_row;
+    BYTE *dst_row;
+    UINT x, y;
+
+    src_row = src_data;
+    dst_row = dst_data;
+
+    row_block_count = (update_w + format->block_width - 1) / format->block_width;
+
+    if (!flags)
+    {
+        for (y = 0; y < update_h; y += format->block_height)
+        {
+            memcpy(dst_row, src_row, row_block_count * format->block_byte_count);
+            src_row += src_pitch;
+            dst_row += dst_pitch;
+        }
+
+        return WINED3D_OK;
+    }
+
+    if (flags == WINEDDBLT_DDFX && fx->dwDDFX == WINEDDBLTFX_MIRRORUPDOWN)
+    {
+        src_row += (((update_h / format->block_height) - 1) * src_pitch);
+
+        switch (format->id)
+        {
+            case WINED3DFMT_DXT1:
+                for (y = 0; y < update_h; y += format->block_height)
+                {
+                    struct block
+                    {
+                        WORD color[2];
+                        BYTE control_row[4];
+                    };
+
+                    const struct block *s = (const struct block *)src_row;
+                    struct block *d = (struct block *)dst_row;
+
+                    for (x = 0; x < row_block_count; ++x)
+                    {
+                        d[x].color[0] = s[x].color[0];
+                        d[x].color[1] = s[x].color[1];
+                        d[x].control_row[0] = s[x].control_row[3];
+                        d[x].control_row[1] = s[x].control_row[2];
+                        d[x].control_row[2] = s[x].control_row[1];
+                        d[x].control_row[3] = s[x].control_row[0];
+                    }
+                    src_row -= src_pitch;
+                    dst_row += dst_pitch;
+                }
+                return WINED3D_OK;
+
+            case WINED3DFMT_DXT3:
+                for (y = 0; y < update_h; y += format->block_height)
+                {
+                    struct block
+                    {
+                        WORD alpha_row[4];
+                        WORD color[2];
+                        BYTE control_row[4];
+                    };
+
+                    const struct block *s = (const struct block *)src_row;
+                    struct block *d = (struct block *)dst_row;
+
+                    for (x = 0; x < row_block_count; ++x)
+                    {
+                        d[x].alpha_row[0] = s[x].alpha_row[3];
+                        d[x].alpha_row[1] = s[x].alpha_row[2];
+                        d[x].alpha_row[2] = s[x].alpha_row[1];
+                        d[x].alpha_row[3] = s[x].alpha_row[0];
+                        d[x].color[0] = s[x].color[0];
+                        d[x].color[1] = s[x].color[1];
+                        d[x].control_row[0] = s[x].control_row[3];
+                        d[x].control_row[1] = s[x].control_row[2];
+                        d[x].control_row[2] = s[x].control_row[1];
+                        d[x].control_row[3] = s[x].control_row[0];
+                    }
+                    src_row -= src_pitch;
+                    dst_row += dst_pitch;
+                }
+                return WINED3D_OK;
+
+            default:
+                FIXME("Compressed flip not implemented for format %s.\n",
+                        debug_d3dformat(format->id));
+                return E_NOTIMPL;
+        }
+    }
+
+    FIXME("Unsupported blit on compressed surface (format %s, flags %#x, DDFX %#x).\n",
+            debug_d3dformat(format->id), flags, flags & WINEDDBLT_DDFX ? fx->dwDDFX : 0);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT surface_cpu_blt(struct wined3d_surface *dst_surface, const RECT *dst_rect,
+        struct wined3d_surface *src_surface, const RECT *src_rect, DWORD flags,
+        const WINEDDBLTFX *fx, enum wined3d_texture_filter_type filter)
+{
+    int bpp, srcheight, srcwidth, dstheight, dstwidth, width;
+    const struct wined3d_format *src_format, *dst_format;
+    struct wined3d_surface *orig_src = src_surface;
+    struct wined3d_map_desc dst_map, src_map;
+    const BYTE *sbase = NULL;
+    HRESULT hr = WINED3D_OK;
+    const BYTE *sbuf;
+    BYTE *dbuf;
+    int x, y;
+
+    TRACE("dst_surface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p, filter %s.\n",
+            dst_surface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect),
+            flags, fx, debug_d3dtexturefiltertype(filter));
+
+    if (src_surface == dst_surface)
+    {
+        wined3d_surface_map(dst_surface, &dst_map, NULL, 0);
+        src_map = dst_map;
+        src_format = dst_surface->resource.format;
+        dst_format = src_format;
+    }
+    else
+    {
+        dst_format = dst_surface->resource.format;
+        if (src_surface)
+        {
+            if (dst_surface->resource.format->id != src_surface->resource.format->id)
+            {
+                src_surface = surface_convert_format(src_surface, dst_format->id);
+                if (!src_surface)
+                {
+                    /* The conv function writes a FIXME */
+                    WARN("Cannot convert source surface format to dest format.\n");
+                    goto release;
+                }
+            }
+            wined3d_surface_map(src_surface, &src_map, NULL, WINED3D_MAP_READONLY);
+            src_format = src_surface->resource.format;
+        }
+        else
+        {
+            src_format = dst_format;
+        }
+
+        wined3d_surface_map(dst_surface, &dst_map, dst_rect, 0);
+    }
+
+    bpp = dst_surface->resource.format->byte_count;
+    srcheight = src_rect->bottom - src_rect->top;
+    srcwidth = src_rect->right - src_rect->left;
+    dstheight = dst_rect->bottom - dst_rect->top;
+    dstwidth = dst_rect->right - dst_rect->left;
+    width = (dst_rect->right - dst_rect->left) * bpp;
+
+    if (src_surface)
+        sbase = (BYTE *)src_map.data
+                + ((src_rect->top / src_format->block_height) * src_map.row_pitch)
+                + ((src_rect->left / src_format->block_width) * src_format->block_byte_count);
+    if (src_surface != dst_surface)
+        dbuf = dst_map.data;
+    else
+        dbuf = (BYTE *)dst_map.data
+                + ((dst_rect->top / dst_format->block_height) * dst_map.row_pitch)
+                + ((dst_rect->left / dst_format->block_width) * dst_format->block_byte_count);
+
+    if (src_format->flags & dst_format->flags & WINED3DFMT_FLAG_BLOCKS)
+    {
+        TRACE("%s -> %s copy.\n", debug_d3dformat(src_format->id), debug_d3dformat(dst_format->id));
+
+        if (src_surface == dst_surface)
+        {
+            FIXME("Only plain blits supported on compressed surfaces.\n");
+            hr = E_NOTIMPL;
+            goto release;
+        }
+
+        if (srcheight != dstheight || srcwidth != dstwidth)
+        {
+            WARN("Stretching not supported on compressed surfaces.\n");
+            hr = WINED3DERR_INVALIDCALL;
+            goto release;
+        }
+
+        if (!surface_check_block_align(src_surface, src_rect))
+        {
+            WARN("Source rectangle not block-aligned.\n");
+            hr = WINED3DERR_INVALIDCALL;
+            goto release;
+        }
+
+        if (!surface_check_block_align(dst_surface, dst_rect))
+        {
+            WARN("Destination rectangle not block-aligned.\n");
+            hr = WINED3DERR_INVALIDCALL;
+            goto release;
+        }
+
+        hr = surface_cpu_blt_compressed(sbase, dbuf,
+                src_map.row_pitch, dst_map.row_pitch, dstwidth, dstheight,
+                src_format, flags, fx);
+        goto release;
+    }
+
+    /* First, all the 'source-less' blits */
+    if (flags & WINEDDBLT_COLORFILL)
+    {
+        hr = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp, dst_map.row_pitch, fx->u5.dwFillColor);
+        flags &= ~WINEDDBLT_COLORFILL;
+    }
+
+    if (flags & WINEDDBLT_DEPTHFILL)
+    {
+        FIXME("DDBLT_DEPTHFILL needs to be implemented!\n");
+    }
+    if (flags & WINEDDBLT_ROP)
+    {
+        /* Catch some degenerate cases here. */
+        switch (fx->dwROP)
+        {
+            case BLACKNESS:
+                hr = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp, dst_map.row_pitch, 0);
+                break;
+            case 0xaa0029: /* No-op */
+                break;
+            case WHITENESS:
+                hr = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp, dst_map.row_pitch, ~0U);
+                break;
+            case SRCCOPY: /* Well, we do that below? */
+                break;
+            default:
+                FIXME("Unsupported raster op: %08x Pattern: %p\n", fx->dwROP, fx->u5.lpDDSPattern);
+                goto error;
+        }
+        flags &= ~WINEDDBLT_ROP;
+    }
+    if (flags & WINEDDBLT_DDROPS)
+    {
+        FIXME("\tDdraw Raster Ops: %08x Pattern: %p\n", fx->dwDDROP, fx->u5.lpDDSPattern);
+    }
+    /* Now the 'with source' blits. */
+    if (src_surface)
+    {
+        int sx, xinc, sy, yinc;
+
+        if (!dstwidth || !dstheight) /* Hmm... stupid program? */
+            goto release;
+
+        if (filter != WINED3D_TEXF_NONE && filter != WINED3D_TEXF_POINT
+                && (srcwidth != dstwidth || srcheight != dstheight))
+        {
+            /* Can happen when d3d9 apps do a StretchRect() call which isn't handled in GL. */
+            FIXME("Filter %s not supported in software blit.\n", debug_d3dtexturefiltertype(filter));
+        }
+
+        xinc = (srcwidth << 16) / dstwidth;
+        yinc = (srcheight << 16) / dstheight;
+
+        if (!flags)
+        {
+            /* No effects, we can cheat here. */
+            if (dstwidth == srcwidth)
+            {
+                if (dstheight == srcheight)
+                {
+                    /* No stretching in either direction. This needs to be as
+                     * fast as possible. */
+                    sbuf = sbase;
+
+                    /* Check for overlapping surfaces. */
+                    if (src_surface != dst_surface || dst_rect->top < src_rect->top
+                            || dst_rect->right <= src_rect->left || src_rect->right <= dst_rect->left)
+                    {
+                        /* No overlap, or dst above src, so copy from top downwards. */
+                        for (y = 0; y < dstheight; ++y)
+                        {
+                            memcpy(dbuf, sbuf, width);
+                            sbuf += src_map.row_pitch;
+                            dbuf += dst_map.row_pitch;
+                        }
+                    }
+                    else if (dst_rect->top > src_rect->top)
+                    {
+                        /* Copy from bottom upwards. */
+                        sbuf += src_map.row_pitch * dstheight;
+                        dbuf += dst_map.row_pitch * dstheight;
+                        for (y = 0; y < dstheight; ++y)
+                        {
+                            sbuf -= src_map.row_pitch;
+                            dbuf -= dst_map.row_pitch;
+                            memcpy(dbuf, sbuf, width);
+                        }
+                    }
+                    else
+                    {
+                        /* Src and dst overlapping on the same line, use memmove. */
+                        for (y = 0; y < dstheight; ++y)
+                        {
+                            memmove(dbuf, sbuf, width);
+                            sbuf += src_map.row_pitch;
+                            dbuf += dst_map.row_pitch;
+                        }
+                    }
+                }
+                else
+                {
+                    /* Stretching in y direction only. */
+                    for (y = sy = 0; y < dstheight; ++y, sy += yinc)
+                    {
+                        sbuf = sbase + (sy >> 16) * src_map.row_pitch;
+                        memcpy(dbuf, sbuf, width);
+                        dbuf += dst_map.row_pitch;
+                    }
+                }
+            }
+            else
+            {
+                /* Stretching in X direction. */
+                int last_sy = -1;
+                for (y = sy = 0; y < dstheight; ++y, sy += yinc)
+                {
+                    sbuf = sbase + (sy >> 16) * src_map.row_pitch;
+
+                    if ((sy >> 16) == (last_sy >> 16))
+                    {
+                        /* This source row is the same as last source row -
+                         * Copy the already stretched row. */
+                        memcpy(dbuf, dbuf - dst_map.row_pitch, width);
+                    }
+                    else
+                    {
+#define STRETCH_ROW(type) \
+do { \
+    const type *s = (const type *)sbuf; \
+    type *d = (type *)dbuf; \
+    for (x = sx = 0; x < dstwidth; ++x, sx += xinc) \
+        d[x] = s[sx >> 16]; \
+} while(0)
+
+                        switch(bpp)
+                        {
+                            case 1:
+                                STRETCH_ROW(BYTE);
+                                break;
+                            case 2:
+                                STRETCH_ROW(WORD);
+                                break;
+                            case 4:
+                                STRETCH_ROW(DWORD);
+                                break;
+                            case 3:
+                            {
+                                const BYTE *s;
+                                BYTE *d = dbuf;
+                                for (x = sx = 0; x < dstwidth; x++, sx+= xinc)
+                                {
+                                    DWORD pixel;
+
+                                    s = sbuf + 3 * (sx >> 16);
+                                    pixel = s[0] | (s[1] << 8) | (s[2] << 16);
+                                    d[0] = (pixel      ) & 0xff;
+                                    d[1] = (pixel >>  8) & 0xff;
+                                    d[2] = (pixel >> 16) & 0xff;
+                                    d += 3;
+                                }
+                                break;
+                            }
+                            default:
+                                FIXME("Stretched blit not implemented for bpp %u!\n", bpp * 8);
+                                hr = WINED3DERR_NOTAVAILABLE;
+                                goto error;
+                        }
+#undef STRETCH_ROW
+                    }
+                    dbuf += dst_map.row_pitch;
+                    last_sy = sy;
+                }
+            }
+        }
+        else
+        {
+            LONG dstyinc = dst_map.row_pitch, dstxinc = bpp;
+            DWORD keylow = 0xffffffff, keyhigh = 0, keymask = 0xffffffff;
+            DWORD destkeylow = 0x0, destkeyhigh = 0xffffffff, destkeymask = 0xffffffff;
+            if (flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYDEST | WINEDDBLT_KEYSRCOVERRIDE | WINEDDBLT_KEYDESTOVERRIDE))
+            {
+                /* The color keying flags are checked for correctness in ddraw */
+                if (flags & WINEDDBLT_KEYSRC)
+                {
+                    keylow  = src_surface->src_blt_color_key.color_space_low_value;
+                    keyhigh = src_surface->src_blt_color_key.color_space_high_value;
+                }
+                else if (flags & WINEDDBLT_KEYSRCOVERRIDE)
+                {
+                    keylow = fx->ddckSrcColorkey.color_space_low_value;
+                    keyhigh = fx->ddckSrcColorkey.color_space_high_value;
+                }
+
+                if (flags & WINEDDBLT_KEYDEST)
+                {
+                    /* Destination color keys are taken from the source surface! */
+                    destkeylow = src_surface->dst_blt_color_key.color_space_low_value;
+                    destkeyhigh = src_surface->dst_blt_color_key.color_space_high_value;
+                }
+                else if (flags & WINEDDBLT_KEYDESTOVERRIDE)
+                {
+                    destkeylow = fx->ddckDestColorkey.color_space_low_value;
+                    destkeyhigh = fx->ddckDestColorkey.color_space_high_value;
+                }
+
+                if (bpp == 1)
+                {
+                    keymask = 0xff;
+                }
+                else
+                {
+                    DWORD masks[3];
+                    get_color_masks(src_format, masks);
+                    keymask = masks[0]
+                            | masks[1]
+                            | masks[2];
+                }
+                flags &= ~(WINEDDBLT_KEYSRC | WINEDDBLT_KEYDEST | WINEDDBLT_KEYSRCOVERRIDE | WINEDDBLT_KEYDESTOVERRIDE);
+            }
+
+            if (flags & WINEDDBLT_DDFX)
+            {
+                BYTE *dTopLeft, *dTopRight, *dBottomLeft, *dBottomRight, *tmp;
+                LONG tmpxy;
+                dTopLeft     = dbuf;
+                dTopRight    = dbuf + ((dstwidth - 1) * bpp);
+                dBottomLeft  = dTopLeft + ((dstheight - 1) * dst_map.row_pitch);
+                dBottomRight = dBottomLeft + ((dstwidth - 1) * bpp);
+
+                if (fx->dwDDFX & WINEDDBLTFX_ARITHSTRETCHY)
+                {
+                    /* I don't think we need to do anything about this flag */
+                    WARN("flags=DDBLT_DDFX nothing done for WINEDDBLTFX_ARITHSTRETCHY\n");
+                }
+                if (fx->dwDDFX & WINEDDBLTFX_MIRRORLEFTRIGHT)
+                {
+                    tmp          = dTopRight;
+                    dTopRight    = dTopLeft;
+                    dTopLeft     = tmp;
+                    tmp          = dBottomRight;
+                    dBottomRight = dBottomLeft;
+                    dBottomLeft  = tmp;
+                    dstxinc = dstxinc * -1;
+                }
+                if (fx->dwDDFX & WINEDDBLTFX_MIRRORUPDOWN)
+                {
+                    tmp          = dTopLeft;
+                    dTopLeft     = dBottomLeft;
+                    dBottomLeft  = tmp;
+                    tmp          = dTopRight;
+                    dTopRight    = dBottomRight;
+                    dBottomRight = tmp;
+                    dstyinc = dstyinc * -1;
+                }
+                if (fx->dwDDFX & WINEDDBLTFX_NOTEARING)
+                {
+                    /* I don't think we need to do anything about this flag */
+                    WARN("flags=DDBLT_DDFX nothing done for WINEDDBLTFX_NOTEARING\n");
+                }
+                if (fx->dwDDFX & WINEDDBLTFX_ROTATE180)
+                {
+                    tmp          = dBottomRight;
+                    dBottomRight = dTopLeft;
+                    dTopLeft     = tmp;
+                    tmp          = dBottomLeft;
+                    dBottomLeft  = dTopRight;
+                    dTopRight    = tmp;
+                    dstxinc = dstxinc * -1;
+                    dstyinc = dstyinc * -1;
+                }
+                if (fx->dwDDFX & WINEDDBLTFX_ROTATE270)
+                {
+                    tmp          = dTopLeft;
+                    dTopLeft     = dBottomLeft;
+                    dBottomLeft  = dBottomRight;
+                    dBottomRight = dTopRight;
+                    dTopRight    = tmp;
+                    tmpxy   = dstxinc;
+                    dstxinc = dstyinc;
+                    dstyinc = tmpxy;
+                    dstxinc = dstxinc * -1;
+                }
+                if (fx->dwDDFX & WINEDDBLTFX_ROTATE90)
+                {
+                    tmp          = dTopLeft;
+                    dTopLeft     = dTopRight;
+                    dTopRight    = dBottomRight;
+                    dBottomRight = dBottomLeft;
+                    dBottomLeft  = tmp;
+                    tmpxy   = dstxinc;
+                    dstxinc = dstyinc;
+                    dstyinc = tmpxy;
+                    dstyinc = dstyinc * -1;
+                }
+                if (fx->dwDDFX & WINEDDBLTFX_ZBUFFERBASEDEST)
+                {
+                    /* I don't think we need to do anything about this flag */
+                    WARN("flags=WINEDDBLT_DDFX nothing done for WINEDDBLTFX_ZBUFFERBASEDEST\n");
+                }
+                dbuf = dTopLeft;
+                flags &= ~(WINEDDBLT_DDFX);
+            }
+
+#define COPY_COLORKEY_FX(type) \
+do { \
+    const type *s; \
+    type *d = (type *)dbuf, *dx, tmp; \
+    for (y = sy = 0; y < dstheight; ++y, sy += yinc) \
+    { \
+        s = (const type *)(sbase + (sy >> 16) * src_map.row_pitch); \
+        dx = d; \
+        for (x = sx = 0; x < dstwidth; ++x, sx += xinc) \
+        { \
+            tmp = s[sx >> 16]; \
+            if (((tmp & keymask) < keylow || (tmp & keymask) > keyhigh) \
+                    && ((dx[0] & destkeymask) >= destkeylow && (dx[0] & destkeymask) <= destkeyhigh)) \
+            { \
+                dx[0] = tmp; \
+            } \
+            dx = (type *)(((BYTE *)dx) + dstxinc); \
+        } \
+        d = (type *)(((BYTE *)d) + dstyinc); \
+    } \
+} while(0)
+
+            switch (bpp)
+            {
+                case 1:
+                    COPY_COLORKEY_FX(BYTE);
+                    break;
+                case 2:
+                    COPY_COLORKEY_FX(WORD);
+                    break;
+                case 4:
+                    COPY_COLORKEY_FX(DWORD);
+                    break;
+                case 3:
+                {
+                    const BYTE *s;
+                    BYTE *d = dbuf, *dx;
+                    for (y = sy = 0; y < dstheight; ++y, sy += yinc)
+                    {
+                        sbuf = sbase + (sy >> 16) * src_map.row_pitch;
+                        dx = d;
+                        for (x = sx = 0; x < dstwidth; ++x, sx+= xinc)
+                        {
+                            DWORD pixel, dpixel = 0;
+                            s = sbuf + 3 * (sx>>16);
+                            pixel = s[0] | (s[1] << 8) | (s[2] << 16);
+                            dpixel = dx[0] | (dx[1] << 8 ) | (dx[2] << 16);
+                            if (((pixel & keymask) < keylow || (pixel & keymask) > keyhigh)
+                                    && ((dpixel & keymask) >= destkeylow || (dpixel & keymask) <= keyhigh))
+                            {
+                                dx[0] = (pixel      ) & 0xff;
+                                dx[1] = (pixel >>  8) & 0xff;
+                                dx[2] = (pixel >> 16) & 0xff;
+                            }
+                            dx += dstxinc;
+                        }
+                        d += dstyinc;
+                    }
+                    break;
+                }
+                default:
+                    FIXME("%s color-keyed blit not implemented for bpp %u!\n",
+                          (flags & WINEDDBLT_KEYSRC) ? "Source" : "Destination", bpp * 8);
+                    hr = WINED3DERR_NOTAVAILABLE;
+                    goto error;
+#undef COPY_COLORKEY_FX
+            }
+        }
+    }
+
+error:
+    if (flags && FIXME_ON(d3d_surface))
+    {
+        FIXME("\tUnsupported flags: %#x.\n", flags);
+    }
+
+release:
+    wined3d_surface_unmap(dst_surface);
+    if (src_surface && src_surface != dst_surface)
+        wined3d_surface_unmap(src_surface);
+    /* Release the converted surface, if any. */
+    if (src_surface && src_surface != orig_src)
+        wined3d_surface_decref(src_surface);
+
+    return hr;
+}
+
+/* Do not call while under the GL lock. */
+static HRESULT cpu_blit_color_fill(struct wined3d_device *device, struct wined3d_surface *dst_surface,
+        const RECT *dst_rect, const struct wined3d_color *color)
+{
+    static const RECT src_rect;
+    WINEDDBLTFX BltFx;
+
+    memset(&BltFx, 0, sizeof(BltFx));
+    BltFx.dwSize = sizeof(BltFx);
+    BltFx.u5.dwFillColor = wined3d_format_convert_from_float(dst_surface, color);
+    return surface_cpu_blt(dst_surface, dst_rect, NULL, &src_rect,
+            WINEDDBLT_COLORFILL, &BltFx, WINED3D_TEXF_POINT);
+}
+
+/* Do not call while under the GL lock. */
+static HRESULT cpu_blit_depth_fill(struct wined3d_device *device,
+        struct wined3d_surface *surface, const RECT *rect, float depth)
+{
+    FIXME("Depth filling not implemented by cpu_blit.\n");
+    return WINED3DERR_INVALIDCALL;
+}
+
+const struct blit_shader cpu_blit =  {
+    cpu_blit_alloc,
+    cpu_blit_free,
+    cpu_blit_set,
+    cpu_blit_unset,
+    cpu_blit_supported,
+    cpu_blit_color_fill,
+    cpu_blit_depth_fill,
+};
+
+static HRESULT surface_init(struct wined3d_surface *surface, UINT alignment, UINT width, UINT height,
+        enum wined3d_multisample_type multisample_type, UINT multisample_quality,
+        struct wined3d_device *device, DWORD usage, enum wined3d_format_id format_id,
+        enum wined3d_pool pool, DWORD flags, void *parent, const struct wined3d_parent_ops *parent_ops
+#ifdef VBOX_WITH_WDDM
+        , HANDLE *shared_handle
+        , void *pvClientMem
+#endif
+        )
+{
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    const struct wined3d_format *format = wined3d_get_format(gl_info, format_id);
+    BOOL lockable = flags & WINED3D_SURFACE_MAPPABLE;
+    unsigned int resource_size;
+    HRESULT hr;
+
+    if (multisample_quality > 0)
+    {
+        FIXME("multisample_quality set to %u, substituting 0.\n", multisample_quality);
+        multisample_quality = 0;
+    }
+
+    /* Quick lockable sanity check.
+     * TODO: remove this after surfaces, usage and lockability have been debugged properly
+     * this function is too deep to need to care about things like this.
+     * Levels need to be checked too, since they all affect what can be done. */
+    switch (pool)
+    {
+        case WINED3D_POOL_SCRATCH:
+            if (!lockable)
+            {
+                FIXME("Called with a pool of SCRATCH and a lockable of FALSE "
+                        "which are mutually exclusive, setting lockable to TRUE.\n");
+                lockable = TRUE;
+            }
+            break;
+
+        case WINED3D_POOL_SYSTEM_MEM:
+            if (!lockable)
+                FIXME("Called with a pool of SYSTEMMEM and a lockable of FALSE, this is acceptable but unexpected.\n");
+            break;
+
+        case WINED3D_POOL_MANAGED:
+            if (usage & WINED3DUSAGE_DYNAMIC)
+                FIXME("Called with a pool of MANAGED and a usage of DYNAMIC which are mutually exclusive.\n");
+            break;
+
+        case WINED3D_POOL_DEFAULT:
+            if (lockable && !(usage & (WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_DEPTHSTENCIL)))
+                WARN("Creating a lockable surface with a POOL of DEFAULT, that doesn't specify DYNAMIC usage.\n");
+            break;
+
+        default:
+            FIXME("Unknown pool %#x.\n", pool);
+            break;
+    };
+
+    if (usage & WINED3DUSAGE_RENDERTARGET && pool != WINED3D_POOL_DEFAULT)
+        FIXME("Trying to create a render target that isn't in the default pool.\n");
+
+    /* FIXME: Check that the format is supported by the device. */
+
+    resource_size = wined3d_format_calculate_size(format, alignment, width, height);
+    if (!resource_size)
+        return WINED3DERR_INVALIDCALL;
+
+    if (device->wined3d->flags & WINED3D_NO3D)
+        surface->surface_ops = &gdi_surface_ops;
+    else
+        surface->surface_ops = &surface_ops;
+
+    hr = resource_init(&surface->resource, device, WINED3D_RTYPE_SURFACE, format,
+            multisample_type, multisample_quality, usage, pool, width, height, 1,
+            resource_size, parent, parent_ops, &surface_resource_ops
+#ifdef VBOX_WITH_WDDM
+            , shared_handle
+            , pvClientMem
+#endif
+            );
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize resource, returning %#x.\n", hr);
+        return hr;
+    }
+
+#ifdef VBOX_WITH_WDDM
+    /* this will be a nop for the non-shared resource,
+     * for the shared resource this will ensure the surface is initialized properly */
+    surface_shrc_lock(surface);
+#endif
+
+    /* "Standalone" surface. */
+    surface_set_container(surface, NULL);
+
+    list_init(&surface->overlays);
+
+    /* Flags */
+    surface->flags = SFLAG_NORMCOORD; /* Default to normalized coords. */
+    if (flags & WINED3D_SURFACE_DISCARD)
+        surface->flags |= SFLAG_DISCARD;
+    if (flags & WINED3D_SURFACE_PIN_SYSMEM)
+        surface->flags |= SFLAG_PIN_SYSMEM;
+    if (lockable || format_id == WINED3DFMT_D16_LOCKABLE)
+        surface->flags |= SFLAG_LOCKABLE;
+    /* I'm not sure if this qualifies as a hack or as an optimization. It
+     * seems reasonable to assume that lockable render targets will get
+     * locked, so we might as well set SFLAG_DYNLOCK right at surface
+     * creation. However, the other reason we want to do this is that several
+     * ddraw applications access surface memory while the surface isn't
+     * mapped. The SFLAG_DYNLOCK behaviour of keeping SYSMEM around for
+     * future locks prevents these from crashing. */
+    if (lockable && (usage & WINED3DUSAGE_RENDERTARGET))
+        surface->flags |= SFLAG_DYNLOCK;
+#ifdef VBOX_WITH_WDDM
+    if (pool == WINED3D_POOL_SYSTEM_MEM && pvClientMem)  surface->flags |= SFLAG_CLIENTMEM;
+#endif
+
+    /* Mark the texture as dirty so that it gets loaded first time around. */
+    surface_add_dirty_rect(surface, NULL);
+    list_init(&surface->renderbuffers);
+
+    TRACE("surface %p, memory %p, size %u\n",
+            surface, surface->resource.allocatedMemory, surface->resource.size);
+
+    /* Call the private setup routine */
+    hr = surface->surface_ops->surface_private_setup(surface);
+    if (FAILED(hr))
+    {
+        ERR("Private setup failed, returning %#x\n", hr);
+        surface_cleanup(surface);
+        return hr;
+    }
+
+    /* Similar to lockable rendertargets above, creating the DIB section
+     * during surface initialization prevents the sysmem pointer from changing
+     * after a wined3d_surface_getdc() call. */
+    if ((usage & WINED3DUSAGE_OWNDC) && !surface->hDC
+            && SUCCEEDED(surface_create_dib_section(surface)))
+    {
+        HeapFree(GetProcessHeap(), 0, surface->resource.heapMemory);
+        surface->resource.heapMemory = NULL;
+        surface->resource.allocatedMemory = surface->dib.bitmap_data;
+    }
+
+#ifdef VBOX_WITH_WDDM
+    if (VBOXSHRC_IS_SHARED(surface))
+    {
+        Assert(shared_handle);
+        if (!VBOXSHRC_IS_SHARED_OPENED(surface))
+        {
+            surface_shrc_unlock(surface);
+            Assert(!(*shared_handle));
+            *shared_handle = VBOXSHRC_GET_SHAREHANDLE(surface);
+        }
+        else
+        {
+            VBOXSHRC_UNLOCK(surface);
+            Assert(!VBOXSHRC_IS_LOCKED(surface));
+#ifdef DEBUG_misha
+            ERR("test this!");
+#endif
+            surface_setup_location_onopen(surface);
+            Assert(*shared_handle);
+            Assert(*shared_handle == VBOXSHRC_GET_SHAREHANDLE(surface));
+        }
+
+        Assert(!device->isInDraw);
+
+        /* flush to ensure the texture is allocated/referenced before it is used/released by another
+         * process opening/creating it */
+        /* flush to ensure the texture is allocated/referenced before it is used/released by another
+         * process opening/creating it */
+        Assert(device->context_count == 1);
+        pVBoxFlushToHost(device->contexts[0]->glCtx);
+    }
+    else
+    {
+        Assert(!shared_handle);
+    }
+#endif
+
+    return hr;
+}
+
+HRESULT CDECL wined3d_surface_create(struct wined3d_device *device, UINT width, UINT height,
+        enum wined3d_format_id format_id, DWORD usage, enum wined3d_pool pool,
+        enum wined3d_multisample_type multisample_type, DWORD multisample_quality, DWORD flags,
+        void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_surface **surface
+#ifdef VBOX_WITH_WDDM
+        , HANDLE *shared_handle
+        , void *pvClientMem
+#endif
+        )
+{
+    struct wined3d_surface *object;
+    HRESULT hr;
+
+    TRACE("device %p, width %u, height %u, format %s\n",
+            device, width, height, debug_d3dformat(format_id));
+    TRACE("surface %p, usage %s (%#x), pool %s, multisample_type %#x, multisample_quality %u\n",
+            surface, debug_d3dusage(usage), usage, debug_d3dpool(pool), multisample_type, multisample_quality);
+    TRACE("flags %#x, parent %p, parent_ops %p.\n", flags, parent, parent_ops);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return WINED3DERR_OUTOFVIDEOMEMORY;
+
+#ifdef VBOX_WITH_WDDM
+    if (FAILED(hr = surface_init(object, device->surface_alignment, width, height, multisample_type,
+            multisample_quality, device, usage, format_id, pool, flags, parent, parent_ops
+            , shared_handle
+            , pvClientMem
+            )))
+#else
+    if (FAILED(hr = surface_init(object, device->surface_alignment, width, height, multisample_type,
+            multisample_quality, device, usage, format_id, pool, flags, parent, parent_ops)))
+#endif
+    {
+        WARN("Failed to initialize surface, returning %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created surface %p.\n", object);
+    *surface = object;
+
+    return hr;
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/swapchain.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/swapchain.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/swapchain.c	(revision 46521)
@@ -0,0 +1,1537 @@
+/*
+ * Copyright 2002-2003 Jason Edmeades
+ * Copyright 2002-2003 Raphael Junqueira
+ * Copyright 2005 Oliver Stieber
+ * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
+ * Copyright 2011 Henri Verbeet for CodeWeavers
+ *
+ * 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 "wined3d_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d);
+WINE_DECLARE_DEBUG_CHANNEL(fps);
+
+#ifdef VBOX_WINE_WITH_SINGLE_CONTEXT
+static VOID swapchain_cleanup_rt_refs(struct wined3d_swapchain *swapchain, struct wined3d_surface * rt, int iBb)
+{
+    struct wined3d_device * device = swapchain->device;
+    struct wined3d_context *context;
+    UINT i;
+    for (i = 0; i < device->context_count; ++i)
+    {
+        context = device->contexts[i];
+
+        if (rt == context->current_rt)
+        {
+            context->current_rt = NULL;
+        }
+    }
+
+    if (device->swapchain_count)
+    {
+        struct wined3d_swapchain *default_swapchain = (struct wined3d_swapchain*)device->swapchains[0];
+        for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i)
+        {
+            if (device->fb.render_targets[i] == rt)
+            {
+                struct wined3d_surface *new_rt;
+                if (i)
+                    new_rt = NULL;
+                else if (iBb == -1) /* front buffer */
+                    new_rt = default_swapchain->front_buffer;
+                else
+                    new_rt = default_swapchain->back_buffers ? default_swapchain->back_buffers[0] : default_swapchain->front_buffer;
+
+                wined3d_device_set_render_target(device, i, new_rt, TRUE);
+            }
+        }
+    }
+}
+
+static VOID swapchain_cleanup_refs(struct wined3d_swapchain *swapchain)
+{
+    /* first make sure the swapchain is not used by anyone */
+    struct wined3d_device * device = swapchain->device;
+    struct wined3d_context *context;
+    UINT i;
+
+    /* Release the swapchain's draw buffers. Make sure swapchain->back_buffers[0]
+     * is the last buffer to be destroyed, FindContext() depends on that. */
+    if (swapchain->front_buffer)
+    {
+        surface_set_swapchain(swapchain->front_buffer, NULL);
+        if (wined3d_surface_decref(swapchain->front_buffer))
+            WARN("Something's still holding the front buffer (%p).\n", swapchain->front_buffer);
+        swapchain->front_buffer = NULL;
+    }
+
+    if (swapchain->back_buffers)
+    {
+        i = swapchain->desc.backbuffer_count;
+
+        while (i--)
+        {
+            surface_set_swapchain(swapchain->back_buffers[i], NULL);
+            if (wined3d_surface_decref(swapchain->back_buffers[i]))
+                WARN("Something's still holding back buffer %u (%p).\n", i, swapchain->back_buffers[i]);
+        }
+        HeapFree(GetProcessHeap(), 0, swapchain->back_buffers);
+        swapchain->back_buffers = NULL;
+    }
+
+    for (i = 0; i < device->context_count; ++i)
+    {
+        context = device->contexts[i];
+        /* pretty hacky, @todo: check if the context is acquired and re-acquire it with a new swapchain */
+        if (context->swapchain == swapchain)
+        {
+            context->swapchain = NULL;
+        }
+    }
+//
+//    if (swapchain->front_buffer)
+//        swapchain_cleanup_rt_refs(swapchain, swapchain->front_buffer, -1);
+//
+//    if (swapchain->back_buffers)
+//    {
+//        for (i = 0; i < swapchain->desc.backbuffer_count; ++i)
+//        {
+//            swapchain_cleanup_rt_refs(swapchain, swapchain->back_buffers[i], i);
+//        }
+//    }
+}
+#endif
+
+#ifdef VBOX_WITH_WDDM
+
+struct wined3d_swapchain * swapchain_find(struct wined3d_device * device, HWND hWnd)
+{
+    UINT i;
+    for (i = 0; i < device->swapchain_count; ++i)
+    {
+        struct wined3d_swapchain *swapchain = device->swapchains[i];
+        if (swapchain->win_handle == hWnd)
+        {
+            return swapchain;
+        }
+    }
+
+    return NULL;
+}
+
+static VOID swapchain_invalidate(struct wined3d_swapchain *swapchain)
+{
+    swapchain_cleanup_refs(swapchain);
+
+    swapchain->win_handle = NULL;
+    swapchain->hDC = NULL;
+}
+#endif
+
+/* Do not call while under the GL lock. */
+static void swapchain_cleanup(struct wined3d_swapchain *swapchain)
+{
+#ifndef VBOX_WITH_WDDM
+    struct wined3d_display_mode mode;
+    HRESULT hr;
+#endif
+    UINT i;
+
+    TRACE("Destroying swapchain %p.\n", swapchain);
+
+#ifndef VBOX_WITH_WDDM
+    wined3d_swapchain_set_gamma_ramp(swapchain, 0, &swapchain->orig_gamma);
+#endif
+
+    /* Release the swapchain's draw buffers. Make sure swapchain->back_buffers[0]
+     * is the last buffer to be destroyed, FindContext() depends on that. */
+    if (swapchain->front_buffer)
+    {
+        surface_set_swapchain(swapchain->front_buffer, NULL);
+        if (wined3d_surface_decref(swapchain->front_buffer))
+            WARN("Something's still holding the front buffer (%p).\n", swapchain->front_buffer);
+        swapchain->front_buffer = NULL;
+    }
+
+    if (swapchain->back_buffers)
+    {
+        i = swapchain->desc.backbuffer_count;
+
+        while (i--)
+        {
+            surface_set_swapchain(swapchain->back_buffers[i], NULL);
+            if (wined3d_surface_decref(swapchain->back_buffers[i]))
+                WARN("Something's still holding back buffer %u (%p).\n", i, swapchain->back_buffers[i]);
+        }
+        HeapFree(GetProcessHeap(), 0, swapchain->back_buffers);
+        swapchain->back_buffers = NULL;
+    }
+
+#ifdef VBOX_WINE_WITH_SINGLE_CONTEXT
+    swapchain_cleanup_refs(swapchain);
+#endif
+
+#ifndef VBOX_WINE_WITH_SINGLE_CONTEXT
+    for (i = 0; i < swapchain->num_contexts; ++i)
+    {
+        context_destroy(swapchain->device, swapchain->context[i]);
+    }
+    HeapFree(GetProcessHeap(), 0, swapchain->context);
+#endif
+#ifndef VBOX_WITH_WDDM
+    /* Restore the screen resolution if we rendered in fullscreen.
+     * This will restore the screen resolution to what it was before creating
+     * the swapchain. In case of d3d8 and d3d9 this will be the original
+     * desktop resolution. In case of d3d7 this will be a NOP because ddraw
+     * sets the resolution before starting up Direct3D, thus orig_width and
+     * orig_height will be equal to the modes in the presentation params. */
+    if (!swapchain->desc.windowed && swapchain->desc.auto_restore_display_mode)
+    {
+        mode.width = swapchain->orig_width;
+        mode.height = swapchain->orig_height;
+        mode.refresh_rate = 0;
+        mode.format_id = swapchain->orig_fmt;
+        mode.scanline_ordering = WINED3D_SCANLINE_ORDERING_UNKNOWN;
+        if (FAILED(hr = wined3d_set_adapter_display_mode(swapchain->device->wined3d,
+                swapchain->device->adapter->ordinal, &mode)))
+            ERR("Failed to restore display mode, hr %#x.\n", hr);
+    }
+
+    if (swapchain->backup_dc)
+    {
+        TRACE("Destroying backup wined3d window %p, dc %p.\n", swapchain->backup_wnd, swapchain->backup_dc);
+
+        ReleaseDC(swapchain->backup_wnd, swapchain->backup_dc);
+        DestroyWindow(swapchain->backup_wnd);
+    }
+#endif
+#ifdef VBOX_WINE_WITH_SINGLE_CONTEXT
+# ifdef VBOX_WITH_WDDM
+    if(swapchain->win_handle) {
+        VBoxExtWndDestroy(swapchain->win_handle, swapchain->hDC);
+        swapchain_invalidate(swapchain);
+    }
+# endif
+#endif
+}
+
+ULONG CDECL wined3d_swapchain_incref(struct wined3d_swapchain *swapchain)
+{
+    ULONG refcount = InterlockedIncrement(&swapchain->ref);
+
+    TRACE("%p increasing refcount to %u.\n", swapchain, refcount);
+
+    return refcount;
+}
+
+/* Do not call while under the GL lock. */
+ULONG CDECL wined3d_swapchain_decref(struct wined3d_swapchain *swapchain)
+{
+    ULONG refcount = InterlockedDecrement(&swapchain->ref);
+
+    TRACE("%p decreasing refcount to %u.\n", swapchain, refcount);
+
+    if (!refcount)
+    {
+        swapchain_cleanup(swapchain);
+        swapchain->parent_ops->wined3d_object_destroyed(swapchain->parent);
+        HeapFree(GetProcessHeap(), 0, swapchain);
+    }
+
+    return refcount;
+}
+
+void * CDECL wined3d_swapchain_get_parent(const struct wined3d_swapchain *swapchain)
+{
+    TRACE("swapchain %p.\n", swapchain);
+
+    return swapchain->parent;
+}
+
+void CDECL wined3d_swapchain_set_window(struct wined3d_swapchain *swapchain, HWND window)
+{
+#ifdef VBOX_WITH_WDDM
+    if (window)
+        ERR("not expected!");
+#else
+    if (!window)
+        window = swapchain->device_window;
+    if (window == swapchain->win_handle)
+        return;
+
+    TRACE("Setting swapchain %p window from %p to %p.\n",
+            swapchain, swapchain->win_handle, window);
+    swapchain->win_handle = window;
+#endif
+}
+
+HRESULT CDECL wined3d_swapchain_present(struct wined3d_swapchain *swapchain,
+        const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override,
+        const RGNDATA *dirty_region, DWORD flags)
+{
+    TRACE("swapchain %p, src_rect %s, dst_rect %s, dst_window_override %p, dirty_region %p, flags %#x.\n",
+            swapchain, wine_dbgstr_rect(src_rect), wine_dbgstr_rect(dst_rect),
+            dst_window_override, dirty_region, flags);
+
+    if (flags)
+        FIXME("Ignoring flags %#x.\n", flags);
+
+    if (!swapchain->back_buffers)
+    {
+        WARN("Swapchain doesn't have a backbuffer, returning WINED3DERR_INVALIDCALL\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    wined3d_swapchain_set_window(swapchain, dst_window_override);
+
+    swapchain->swapchain_ops->swapchain_present(swapchain, src_rect, dst_rect, dirty_region, flags);
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_swapchain_get_front_buffer_data(const struct wined3d_swapchain *swapchain,
+        struct wined3d_surface *dst_surface)
+{
+    struct wined3d_surface *src_surface;
+    RECT src_rect, dst_rect;
+
+    TRACE("swapchain %p, dst_surface %p.\n", swapchain, dst_surface);
+
+    src_surface = swapchain->front_buffer;
+    SetRect(&src_rect, 0, 0, src_surface->resource.width, src_surface->resource.height);
+    dst_rect = src_rect;
+
+#ifndef VBOX_WITH_WINE_FIXES
+    if (swapchain->desc.windowed)
+    {
+        MapWindowPoints(swapchain->win_handle, NULL, (POINT *)&dst_rect, 2);
+        FIXME("Using destination rect %s in windowed mode, this is likely wrong.\n",
+                wine_dbgstr_rect(&dst_rect));
+    }
+#endif
+
+    return wined3d_surface_blt(dst_surface, &dst_rect, src_surface, &src_rect, 0, NULL, WINED3D_TEXF_POINT);
+}
+
+struct wined3d_surface * CDECL wined3d_swapchain_get_back_buffer(const struct wined3d_swapchain *swapchain,
+        UINT back_buffer_idx, enum wined3d_backbuffer_type type)
+{
+    TRACE("swapchain %p, back_buffer_idx %u, type %#x.\n",
+            swapchain, back_buffer_idx, type);
+
+#ifdef VBOX_WITH_WDDM
+    if (back_buffer_idx == ~0UL)
+    {
+        return swapchain->front_buffer;
+    }
+#endif
+
+    /* Return invalid if there is no backbuffer array, otherwise it will
+     * crash when ddraw is used (there swapchain->back_buffers is always
+     * NULL). We need this because this function is called from
+     * stateblock_init_default_state() to get the default scissorrect
+     * dimensions. */
+    if (!swapchain->back_buffers || back_buffer_idx >= swapchain->desc.backbuffer_count)
+    {
+        WARN("Invalid back buffer index.\n");
+        /* Native d3d9 doesn't set NULL here, just as wine's d3d9. But set it
+         * here in wined3d to avoid problems in other libs. */
+        return NULL;
+    }
+
+    TRACE("Returning back buffer %p.\n", swapchain->back_buffers[back_buffer_idx]);
+
+    return swapchain->back_buffers[back_buffer_idx];
+}
+
+HRESULT CDECL wined3d_swapchain_get_raster_status(const struct wined3d_swapchain *swapchain,
+        struct wined3d_raster_status *raster_status)
+{
+    TRACE("swapchain %p, raster_status %p.\n", swapchain, raster_status);
+
+    return wined3d_get_adapter_raster_status(swapchain->device->wined3d,
+            swapchain->device->adapter->ordinal, raster_status);
+}
+
+HRESULT CDECL wined3d_swapchain_get_display_mode(const struct wined3d_swapchain *swapchain,
+        struct wined3d_display_mode *mode, enum wined3d_display_rotation *rotation)
+{
+    HRESULT hr;
+
+    TRACE("swapchain %p, mode %p, rotation %p.\n", swapchain, mode, rotation);
+
+    hr = wined3d_get_adapter_display_mode(swapchain->device->wined3d,
+            swapchain->device->adapter->ordinal, mode, rotation);
+
+    TRACE("Returning w %u, h %u, refresh rate %u, format %s.\n",
+            mode->width, mode->height, mode->refresh_rate, debug_d3dformat(mode->format_id));
+
+    return hr;
+}
+
+struct wined3d_device * CDECL wined3d_swapchain_get_device(const struct wined3d_swapchain *swapchain)
+{
+    TRACE("swapchain %p.\n", swapchain);
+
+    return swapchain->device;
+}
+
+void CDECL wined3d_swapchain_get_desc(const struct wined3d_swapchain *swapchain,
+        struct wined3d_swapchain_desc *desc)
+{
+    TRACE("swapchain %p, desc %p.\n", swapchain, desc);
+
+    *desc = swapchain->desc;
+}
+
+HRESULT CDECL wined3d_swapchain_set_gamma_ramp(const struct wined3d_swapchain *swapchain,
+        DWORD flags, const struct wined3d_gamma_ramp *ramp)
+{
+    HDC dc;
+
+    TRACE("swapchain %p, flags %#x, ramp %p.\n", swapchain, flags, ramp);
+
+    if (flags)
+        FIXME("Ignoring flags %#x.\n", flags);
+
+#ifdef VBOX_WITH_WDDM
+    dc = GetDC(swapchain->win_handle);
+#else
+    dc = GetDC(swapchain->device_window);
+#endif
+    SetDeviceGammaRamp(dc, (void *)ramp);
+#ifdef VBOX_WITH_WDDM
+    ReleaseDC(swapchain->win_handle, dc);
+#else
+    ReleaseDC(swapchain->device_window, dc);
+#endif
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_swapchain_get_gamma_ramp(const struct wined3d_swapchain *swapchain,
+        struct wined3d_gamma_ramp *ramp)
+{
+    HDC dc;
+
+    TRACE("swapchain %p, ramp %p.\n", swapchain, ramp);
+
+#ifdef VBOX_WITH_WDDM
+    dc = GetDC(swapchain->win_handle);
+#else
+    dc = GetDC(swapchain->device_window);
+#endif
+    GetDeviceGammaRamp(dc, ramp);
+#ifdef VBOX_WITH_WDDM
+    ReleaseDC(swapchain->win_handle, dc);
+#else
+    ReleaseDC(swapchain->device_window, dc);
+#endif
+
+    return WINED3D_OK;
+}
+
+/* A GL context is provided by the caller */
+static void swapchain_blit(const struct wined3d_swapchain *swapchain,
+        struct wined3d_context *context, const RECT *src_rect, const RECT *dst_rect)
+{
+    struct wined3d_surface *backbuffer = swapchain->back_buffers[0];
+    UINT src_w = src_rect->right - src_rect->left;
+    UINT src_h = src_rect->bottom - src_rect->top;
+    GLenum gl_filter;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    RECT win_rect;
+    UINT win_h;
+
+    TRACE("swapchain %p, context %p, src_rect %s, dst_rect %s.\n",
+            swapchain, context, wine_dbgstr_rect(src_rect), wine_dbgstr_rect(dst_rect));
+
+    if (src_w == dst_rect->right - dst_rect->left && src_h == dst_rect->bottom - dst_rect->top)
+        gl_filter = GL_NEAREST;
+    else
+        gl_filter = GL_LINEAR;
+
+    GetClientRect(swapchain->win_handle, &win_rect);
+    win_h = win_rect.bottom - win_rect.top;
+
+    if (gl_info->fbo_ops.glBlitFramebuffer && is_identity_fixup(backbuffer->resource.format->color_fixup))
+    {
+        DWORD location = SFLAG_INTEXTURE;
+
+        if (backbuffer->resource.multisample_type)
+        {
+            location = SFLAG_INRB_RESOLVED;
+            surface_load_location(backbuffer, location, NULL);
+        }
+
+        context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, backbuffer, NULL, location);
+        gl_info->gl_ops.gl.p_glReadBuffer(GL_COLOR_ATTACHMENT0);
+        context_check_fbo_status(context, GL_READ_FRAMEBUFFER);
+
+        context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, swapchain->front_buffer, NULL, SFLAG_INDRAWABLE);
+        context_set_draw_buffer(context, GL_BACK);
+        context_invalidate_state(context, STATE_FRAMEBUFFER);
+
+        gl_info->gl_ops.gl.p_glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+        context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE));
+        context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE1));
+        context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE2));
+        context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE3));
+
+        gl_info->gl_ops.gl.p_glDisable(GL_SCISSOR_TEST);
+        context_invalidate_state(context, STATE_RENDER(WINED3D_RS_SCISSORTESTENABLE));
+
+        /* Note that the texture is upside down */
+        gl_info->fbo_ops.glBlitFramebuffer(src_rect->left, src_rect->top, src_rect->right, src_rect->bottom,
+                dst_rect->left, win_h - dst_rect->top, dst_rect->right, win_h - dst_rect->bottom,
+                GL_COLOR_BUFFER_BIT, gl_filter);
+        checkGLcall("Swapchain present blit(EXT_framebuffer_blit)\n");
+    }
+    else
+    {
+        struct wined3d_device *device = swapchain->device;
+        struct wined3d_context *context2;
+        float tex_left = src_rect->left;
+        float tex_top = src_rect->top;
+        float tex_right = src_rect->right;
+        float tex_bottom = src_rect->bottom;
+
+        context2 = context_acquire(device, swapchain->back_buffers[0]);
+        context_apply_blit_state(context2, device);
+
+        if (backbuffer->flags & SFLAG_NORMCOORD)
+        {
+            tex_left /= src_w;
+            tex_right /= src_w;
+            tex_top /= src_h;
+            tex_bottom /= src_h;
+        }
+
+        if (is_complex_fixup(backbuffer->resource.format->color_fixup))
+            gl_filter = GL_NEAREST;
+
+        context_apply_fbo_state_blit(context2, GL_FRAMEBUFFER, swapchain->front_buffer, NULL, SFLAG_INDRAWABLE);
+        context_bind_texture(context2, backbuffer->texture_target, backbuffer->texture_name);
+
+        /* Set up the texture. The surface is not in a wined3d_texture
+         * container, so there are no D3D texture settings to dirtify. */
+        device->blitter->set_shader(device->blit_priv, context2, backbuffer);
+        gl_info->gl_ops.gl.p_glTexParameteri(backbuffer->texture_target, GL_TEXTURE_MIN_FILTER, gl_filter);
+        gl_info->gl_ops.gl.p_glTexParameteri(backbuffer->texture_target, GL_TEXTURE_MAG_FILTER, gl_filter);
+
+        context_set_draw_buffer(context, GL_BACK);
+
+        /* Set the viewport to the destination rectandle, disable any projection
+         * transformation set up by context_apply_blit_state(), and draw a
+         * (-1,-1)-(1,1) quad.
+         *
+         * Back up viewport and matrix to avoid breaking last_was_blit
+         *
+         * Note that context_apply_blit_state() set up viewport and ortho to
+         * match the surface size - we want the GL drawable(=window) size. */
+        gl_info->gl_ops.gl.p_glPushAttrib(GL_VIEWPORT_BIT);
+        gl_info->gl_ops.gl.p_glViewport(dst_rect->left, win_h - dst_rect->bottom,
+                dst_rect->right, win_h - dst_rect->top);
+        gl_info->gl_ops.gl.p_glMatrixMode(GL_PROJECTION);
+        gl_info->gl_ops.gl.p_glPushMatrix();
+        gl_info->gl_ops.gl.p_glLoadIdentity();
+
+        gl_info->gl_ops.gl.p_glBegin(GL_QUADS);
+            /* bottom left */
+            gl_info->gl_ops.gl.p_glTexCoord2f(tex_left, tex_bottom);
+            gl_info->gl_ops.gl.p_glVertex2i(-1, -1);
+
+            /* top left */
+            gl_info->gl_ops.gl.p_glTexCoord2f(tex_left, tex_top);
+            gl_info->gl_ops.gl.p_glVertex2i(-1, 1);
+
+            /* top right */
+            gl_info->gl_ops.gl.p_glTexCoord2f(tex_right, tex_top);
+            gl_info->gl_ops.gl.p_glVertex2i(1, 1);
+
+            /* bottom right */
+            gl_info->gl_ops.gl.p_glTexCoord2f(tex_right, tex_bottom);
+            gl_info->gl_ops.gl.p_glVertex2i(1, -1);
+        gl_info->gl_ops.gl.p_glEnd();
+
+        gl_info->gl_ops.gl.p_glPopMatrix();
+        gl_info->gl_ops.gl.p_glPopAttrib();
+
+        device->blitter->unset_shader(context->gl_info);
+        checkGLcall("Swapchain present blit(manual)\n");
+
+        context_release(context2);
+    }
+}
+
+static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT *src_rect_in,
+        const RECT *dst_rect_in, const RGNDATA *dirty_region, DWORD flags)
+{
+    struct wined3d_surface *back_buffer = swapchain->back_buffers[0];
+    const struct wined3d_fb_state *fb = &swapchain->device->fb;
+    const struct wined3d_gl_info *gl_info;
+    struct wined3d_context *context;
+    RECT src_rect, dst_rect;
+    BOOL render_to_fbo;
+
+    context = context_acquire(swapchain->device, back_buffer);
+    if (!context->valid)
+    {
+        context_release(context);
+        WARN("Invalid context, skipping present.\n");
+        return;
+    }
+
+    gl_info = context->gl_info;
+
+    /* Render the cursor onto the back buffer, using our nifty directdraw blitting code :-) */
+    if (swapchain->device->bCursorVisible &&
+        swapchain->device->cursorTexture &&
+        !swapchain->device->hardwareCursor)
+    {
+        struct wined3d_surface cursor;
+        RECT destRect =
+        {
+            swapchain->device->xScreenSpace - swapchain->device->xHotSpot,
+            swapchain->device->yScreenSpace - swapchain->device->yHotSpot,
+            swapchain->device->xScreenSpace + swapchain->device->cursorWidth - swapchain->device->xHotSpot,
+            swapchain->device->yScreenSpace + swapchain->device->cursorHeight - swapchain->device->yHotSpot,
+        };
+        TRACE("Rendering the cursor. Creating fake surface at %p\n", &cursor);
+        /* Build a fake surface to call the Blitting code. It is not possible to use the interface passed by
+         * the application because we are only supposed to copy the information out. Using a fake surface
+         * allows us to use the Blitting engine and avoid copying the whole texture -> render target blitting code.
+         */
+        memset(&cursor, 0, sizeof(cursor));
+        cursor.resource.ref = 1;
+        cursor.resource.device = swapchain->device;
+        cursor.resource.pool = WINED3D_POOL_SCRATCH;
+        cursor.resource.format = wined3d_get_format(gl_info, WINED3DFMT_B8G8R8A8_UNORM);
+        cursor.resource.type = WINED3D_RTYPE_SURFACE;
+        cursor.texture_name = swapchain->device->cursorTexture;
+        cursor.texture_target = GL_TEXTURE_2D;
+        cursor.texture_level = 0;
+        cursor.resource.width = swapchain->device->cursorWidth;
+        cursor.resource.height = swapchain->device->cursorHeight;
+        /* The cursor must have pow2 sizes */
+        cursor.pow2Width = cursor.resource.width;
+        cursor.pow2Height = cursor.resource.height;
+        /* The surface is in the texture */
+        cursor.flags |= SFLAG_INTEXTURE;
+        /* DDBLT_KEYSRC will cause BltOverride to enable the alpha test with GL_NOTEQUAL, 0.0,
+         * which is exactly what we want :-)
+         */
+#ifndef VBOX_WITH_WINE_FIXES
+        if (swapchain->desc.windowed)
+            MapWindowPoints(NULL, swapchain->win_handle, (POINT *)&destRect, 2);
+#endif
+        wined3d_surface_blt(back_buffer, &destRect, &cursor, NULL, WINEDDBLT_KEYSRC,
+                NULL, WINED3D_TEXF_POINT);
+    }
+
+    if (swapchain->device->logo_surface)
+    {
+        struct wined3d_surface *src_surface = swapchain->device->logo_surface;
+        RECT rect = {0, 0, src_surface->resource.width, src_surface->resource.height};
+
+        /* Blit the logo into the upper left corner of the drawable. */
+        wined3d_surface_blt(back_buffer, &rect, src_surface, &rect, WINEDDBLT_KEYSRC,
+                NULL, WINED3D_TEXF_POINT);
+    }
+
+#ifndef VBOX_WINE_WITH_SINGLE_CONTEXT
+    TRACE("Presenting HDC %p.\n", context->hdc);
+#else
+    TRACE("Presenting HDC %p.\n", context->swapchain->hDC);
+#endif
+
+    render_to_fbo = swapchain->render_to_fbo;
+
+    if (src_rect_in)
+    {
+        src_rect = *src_rect_in;
+        if (!render_to_fbo && (src_rect.left || src_rect.top
+                || src_rect.right != swapchain->desc.backbuffer_width
+                || src_rect.bottom != swapchain->desc.backbuffer_height))
+        {
+            render_to_fbo = TRUE;
+        }
+    }
+    else
+    {
+        src_rect.left = 0;
+        src_rect.top = 0;
+        src_rect.right = swapchain->desc.backbuffer_width;
+        src_rect.bottom = swapchain->desc.backbuffer_height;
+    }
+
+    if (dst_rect_in)
+        dst_rect = *dst_rect_in;
+    else
+        GetClientRect(swapchain->win_handle, &dst_rect);
+
+    if (!render_to_fbo && (dst_rect.left || dst_rect.top
+            || dst_rect.right != swapchain->desc.backbuffer_width
+            || dst_rect.bottom != swapchain->desc.backbuffer_height))
+        render_to_fbo = TRUE;
+
+    /* Rendering to a window of different size, presenting partial rectangles,
+     * or rendering to a different window needs help from FBO_blit or a textured
+     * draw. Render the swapchain to a FBO in the future.
+     *
+     * Note that FBO_blit from the backbuffer to the frontbuffer cannot solve
+     * all these issues - this fails if the window is smaller than the backbuffer.
+     */
+    if (!swapchain->render_to_fbo && render_to_fbo && wined3d_settings.offscreen_rendering_mode == ORM_FBO)
+    {
+        surface_load_location(back_buffer, SFLAG_INTEXTURE, NULL);
+        surface_modify_location(back_buffer, SFLAG_INDRAWABLE, FALSE);
+        swapchain->render_to_fbo = TRUE;
+        swapchain_update_draw_bindings(swapchain);
+    }
+    else
+    {
+        surface_load_location(back_buffer, back_buffer->draw_binding, NULL);
+    }
+
+    if (swapchain->render_to_fbo)
+    {
+        /* This codepath should only be hit with the COPY swapeffect. Otherwise a backbuffer-
+         * window size mismatch is impossible(fullscreen) and src and dst rectangles are
+         * not allowed(they need the COPY swapeffect)
+         *
+         * The DISCARD swap effect is ok as well since any backbuffer content is allowed after
+         * the swap. */
+        if (swapchain->desc.swap_effect == WINED3D_SWAP_EFFECT_FLIP)
+            FIXME("Render-to-fbo with WINED3D_SWAP_EFFECT_FLIP\n");
+
+        swapchain_blit(swapchain, context, &src_rect, &dst_rect);
+    }
+
+#ifndef VBOX_WINE_WITH_SINGLE_CONTEXT
+    if (swapchain->num_contexts > 1)
+        gl_info->gl_ops.gl.p_glFinish();
+#endif
+
+#ifdef VBOX_WINE_WITH_SINGLE_CONTEXT
+# ifdef DEBUG
+    {
+        HWND wnd = WindowFromDC(context->swapchain->hDC);
+        Assert(wnd == context->swapchain->win_handle);
+    }
+# endif
+    /* call wglSwapBuffers through the gl table to avoid confusing the Steam overlay */
+    gl_info->gl_ops.wgl.p_wglSwapBuffers(context->swapchain->hDC); /* TODO: cycle through the swapchain buffers */
+#else
+
+    /* call wglSwapBuffers through the gl table to avoid confusing the Steam overlay */
+    gl_info->gl_ops.wgl.p_wglSwapBuffers(context->hdc); /* TODO: cycle through the swapchain buffers */
+#endif
+
+    TRACE("SwapBuffers called, Starting new frame\n");
+    /* FPS support */
+    if (TRACE_ON(fps))
+    {
+        DWORD time = GetTickCount();
+        ++swapchain->frames;
+
+        /* every 1.5 seconds */
+        if (time - swapchain->prev_time > 1500)
+        {
+            TRACE_(fps)("%p @ approx %.2ffps\n",
+                    swapchain, 1000.0 * swapchain->frames / (time - swapchain->prev_time));
+            swapchain->prev_time = time;
+            swapchain->frames = 0;
+        }
+    }
+
+    /* This is disabled, but the code left in for debug purposes.
+     *
+     * Since we're allowed to modify the new back buffer on a D3DSWAPEFFECT_DISCARD flip,
+     * we can clear it with some ugly color to make bad drawing visible and ease debugging.
+     * The Debug runtime does the same on Windows. However, a few games do not redraw the
+     * screen properly, like Max Payne 2, which leaves a few pixels undefined.
+     *
+     * Tests show that the content of the back buffer after a discard flip is indeed not
+     * reliable, so no game can depend on the exact content. However, it resembles the
+     * old contents in some way, for example by showing fragments at other locations. In
+     * general, the color theme is still intact. So Max payne, which draws rather dark scenes
+     * gets a dark background image. If we clear it with a bright ugly color, the game's
+     * bug shows up much more than it does on Windows, and the players see single pixels
+     * with wrong colors.
+     * (The Max Payne bug has been confirmed on Windows with the debug runtime) */
+    if (FALSE && swapchain->desc.swap_effect == WINED3D_SWAP_EFFECT_DISCARD)
+    {
+        static const struct wined3d_color cyan = {0.0f, 1.0f, 1.0f, 1.0f};
+
+        TRACE("Clearing the color buffer with cyan color\n");
+
+        wined3d_device_clear(swapchain->device, 0, NULL,
+                WINED3DCLEAR_TARGET, &cyan, 1.0f, 0);
+    }
+
+    if (!swapchain->render_to_fbo && ((swapchain->front_buffer->flags & SFLAG_INSYSMEM)
+            || (back_buffer->flags & SFLAG_INSYSMEM)))
+    {
+        /* Both memory copies of the surfaces are ok, flip them around too instead of dirtifying
+         * Doesn't work with render_to_fbo because we're not flipping
+         */
+        struct wined3d_surface *front = swapchain->front_buffer;
+
+        if (front->resource.size == back_buffer->resource.size)
+        {
+            DWORD fbflags;
+            flip_surface(front, back_buffer);
+
+            /* Tell the front buffer surface that is has been modified. However,
+             * the other locations were preserved during that, so keep the flags.
+             * This serves to update the emulated overlay, if any. */
+            fbflags = front->flags;
+            surface_modify_location(front, SFLAG_INDRAWABLE, TRUE);
+            front->flags = fbflags;
+        }
+        else
+        {
+            surface_modify_location(front, SFLAG_INDRAWABLE, TRUE);
+            surface_modify_location(back_buffer, SFLAG_INDRAWABLE, TRUE);
+        }
+    }
+    else
+    {
+        surface_modify_location(swapchain->front_buffer, SFLAG_INDRAWABLE, TRUE);
+        /* If the swapeffect is DISCARD, the back buffer is undefined. That means the SYSMEM
+         * and INTEXTURE copies can keep their old content if they have any defined content.
+         * If the swapeffect is COPY, the content remains the same. If it is FLIP however,
+         * the texture / sysmem copy needs to be reloaded from the drawable
+         */
+        if (swapchain->desc.swap_effect == WINED3D_SWAP_EFFECT_FLIP)
+            surface_modify_location(back_buffer, back_buffer->draw_binding, TRUE);
+    }
+
+    if (fb->depth_stencil)
+    {
+        if (swapchain->desc.flags & WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL
+                || fb->depth_stencil->flags & SFLAG_DISCARD)
+        {
+            surface_modify_ds_location(fb->depth_stencil, SFLAG_DISCARDED,
+                    fb->depth_stencil->resource.width,
+                    fb->depth_stencil->resource.height);
+            if (fb->depth_stencil == swapchain->device->onscreen_depth_stencil)
+            {
+                wined3d_surface_decref(swapchain->device->onscreen_depth_stencil);
+                swapchain->device->onscreen_depth_stencil = NULL;
+            }
+        }
+    }
+
+    context_release(context);
+}
+
+static const struct wined3d_swapchain_ops swapchain_gl_ops =
+{
+    swapchain_gl_present,
+};
+
+/* Helper function that blits the front buffer contents to the target window. */
+void x11_copy_to_screen(const struct wined3d_swapchain *swapchain, const RECT *rect)
+{
+    const struct wined3d_surface *front;
+    POINT offset = {0, 0};
+    HDC src_dc, dst_dc;
+    RECT draw_rect;
+    HWND window;
+
+    TRACE("swapchain %p, rect %s.\n", swapchain, wine_dbgstr_rect(rect));
+
+    front = swapchain->front_buffer;
+    if (!(front->resource.usage & WINED3DUSAGE_RENDERTARGET))
+        return;
+
+    if (front->resource.map_count)
+        ERR("Trying to blit a mapped surface.\n");
+
+    TRACE("Copying surface %p to screen.\n", front);
+
+    src_dc = front->hDC;
+    window = swapchain->win_handle;
+    dst_dc = GetDCEx(window, 0, DCX_CLIPSIBLINGS | DCX_CACHE);
+
+    /* Front buffer coordinates are screen coordinates. Map them to the
+     * destination window if not fullscreened. */
+    if (swapchain->desc.windowed)
+    {
+#ifndef VBOX_WITH_WINE_FIXES
+        ClientToScreen(window, &offset);
+#else
+        ERR("should not be here!");
+#endif
+    }
+
+    TRACE("offset %s.\n", wine_dbgstr_point(&offset));
+
+    draw_rect.left = 0;
+    draw_rect.right = front->resource.width;
+    draw_rect.top = 0;
+    draw_rect.bottom = front->resource.height;
+
+    if (rect)
+        IntersectRect(&draw_rect, &draw_rect, rect);
+
+    BitBlt(dst_dc, draw_rect.left - offset.x, draw_rect.top - offset.y,
+            draw_rect.right - draw_rect.left, draw_rect.bottom - draw_rect.top,
+            src_dc, draw_rect.left, draw_rect.top, SRCCOPY);
+    ReleaseDC(window, dst_dc);
+}
+
+static void swapchain_gdi_present(struct wined3d_swapchain *swapchain, const RECT *src_rect_in,
+        const RECT *dst_rect_in, const RGNDATA *dirty_region, DWORD flags)
+{
+    struct wined3d_surface *front, *back;
+
+    front = swapchain->front_buffer;
+    back = swapchain->back_buffers[0];
+
+    /* Flip the DC. */
+    {
+        HDC tmp;
+        tmp = front->hDC;
+        front->hDC = back->hDC;
+        back->hDC = tmp;
+    }
+
+    /* Flip the DIBsection. */
+    {
+        HBITMAP tmp;
+        tmp = front->dib.DIBsection;
+        front->dib.DIBsection = back->dib.DIBsection;
+        back->dib.DIBsection = tmp;
+    }
+
+    /* Flip the surface data. */
+    {
+        void *tmp;
+
+        tmp = front->dib.bitmap_data;
+        front->dib.bitmap_data = back->dib.bitmap_data;
+        back->dib.bitmap_data = tmp;
+
+        tmp = front->resource.allocatedMemory;
+        front->resource.allocatedMemory = back->resource.allocatedMemory;
+        back->resource.allocatedMemory = tmp;
+
+        if (front->resource.heapMemory)
+            ERR("GDI Surface %p has heap memory allocated.\n", front);
+
+        if (back->resource.heapMemory)
+            ERR("GDI Surface %p has heap memory allocated.\n", back);
+    }
+
+    /* FPS support */
+    if (TRACE_ON(fps))
+    {
+        static LONG prev_time, frames;
+        DWORD time = GetTickCount();
+
+        ++frames;
+
+        /* every 1.5 seconds */
+        if (time - prev_time > 1500)
+        {
+            TRACE_(fps)("@ approx %.2ffps\n", 1000.0 * frames / (time - prev_time));
+            prev_time = time;
+            frames = 0;
+        }
+    }
+
+    x11_copy_to_screen(swapchain, NULL);
+}
+
+static const struct wined3d_swapchain_ops swapchain_gdi_ops =
+{
+    swapchain_gdi_present,
+};
+
+void swapchain_update_render_to_fbo(struct wined3d_swapchain *swapchain)
+{
+    RECT client_rect;
+
+    if (wined3d_settings.offscreen_rendering_mode != ORM_FBO)
+        return;
+
+    if (!swapchain->desc.backbuffer_count)
+    {
+        TRACE("Single buffered rendering.\n");
+        swapchain->render_to_fbo = FALSE;
+        return;
+    }
+
+    GetClientRect(swapchain->win_handle, &client_rect);
+
+    TRACE("Backbuffer %ux%u, window %ux%u.\n",
+            swapchain->desc.backbuffer_width,
+            swapchain->desc.backbuffer_height,
+            client_rect.right, client_rect.bottom);
+    TRACE("Multisample type %#x, quality %#x.\n",
+            swapchain->desc.multisample_type,
+            swapchain->desc.multisample_quality);
+
+    if (!wined3d_settings.always_offscreen && !swapchain->desc.multisample_type
+            && swapchain->desc.backbuffer_width == client_rect.right
+            && swapchain->desc.backbuffer_height == client_rect.bottom)
+    {
+        TRACE("Backbuffer dimensions match window dimensions, rendering onscreen.\n");
+        swapchain->render_to_fbo = FALSE;
+        return;
+    }
+
+    TRACE("Rendering to FBO.\n");
+    swapchain->render_to_fbo = TRUE;
+}
+
+/* Do not call while under the GL lock. */
+static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3d_device *device,
+        struct wined3d_swapchain_desc *desc, void *parent, const struct wined3d_parent_ops *parent_ops)
+{
+    const struct wined3d_adapter *adapter = device->adapter;
+    struct wined3d_resource_desc surface_desc;
+    const struct wined3d_format *format;
+    struct wined3d_display_mode mode;
+#ifndef VBOX_WITH_WDDM
+    BOOL displaymode_set = FALSE;
+#endif
+    RECT client_rect;
+    HWND window;
+    HRESULT hr;
+    UINT i;
+#ifdef VBOX_WITH_WDDM
+    struct wined3d_swapchain *overriden_swapchain = NULL;
+    HDC hDC = NULL;
+#endif
+
+    if (desc->backbuffer_count > WINED3DPRESENT_BACK_BUFFER_MAX)
+    {
+        FIXME("The application requested %u back buffers, this is not supported.\n",
+                desc->backbuffer_count);
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    if (desc->backbuffer_count > 1)
+    {
+        FIXME("The application requested more than one back buffer, this is not properly supported.\n"
+                "Please configure the application to use double buffering (1 back buffer) if possible.\n");
+    }
+
+    if (device->wined3d->flags & WINED3D_NO3D)
+        swapchain->swapchain_ops = &swapchain_gdi_ops;
+    else
+        swapchain->swapchain_ops = &swapchain_gl_ops;
+
+#ifndef VBOX_WITH_WDDM
+    window = desc->device_window ? desc->device_window : device->create_parms.focus_window;
+#else
+    if (desc->device_window)
+    {
+        overriden_swapchain = swapchain_find(device, desc->device_window);
+        if (!overriden_swapchain)
+        {
+            ERR("invalid window handle supplied");
+            return E_FAIL;
+        }
+
+        window = overriden_swapchain->win_handle;
+        hDC = overriden_swapchain->hDC;
+    }
+    else
+    {
+        hr = VBoxExtWndCreate(desc->backbuffer_width, desc->backbuffer_height, &window, &hDC);
+        if (FAILED(hr))
+        {
+            ERR("VBoxExtWndCreate failed, hr 0x%x", hr);
+            return hr;
+        }
+    }
+    Assert(window);
+    Assert(hDC);
+    desc->device_window = window;
+#endif
+
+    swapchain->device = device;
+    swapchain->parent = parent;
+    swapchain->parent_ops = parent_ops;
+    swapchain->ref = 1;
+    swapchain->win_handle = window;
+#ifndef VBOX_WITH_WDDM
+    swapchain->device_window = window;
+# ifdef VBOX_WINE_WITH_SINGLE_CONTEXT
+    swapchain->hDC = VBoxExtGetDC(window);
+    if (!swapchain->hDC)
+    {
+        ERR("failed to get window DC");
+        return E_FAIL;
+    }
+# endif
+#else
+    Assert(window);
+    swapchain->hDC = hDC;
+#endif
+
+    wined3d_get_adapter_display_mode(device->wined3d, adapter->ordinal, &mode, NULL);
+#ifndef VBOX_WITH_WDDM
+    swapchain->orig_width = mode.width;
+    swapchain->orig_height = mode.height;
+    swapchain->orig_fmt = mode.format_id;
+#endif
+    format = wined3d_get_format(&adapter->gl_info, mode.format_id);
+
+    GetClientRect(window, &client_rect);
+    if (desc->windowed
+            && (!desc->backbuffer_width || !desc->backbuffer_height
+            || desc->backbuffer_format == WINED3DFMT_UNKNOWN))
+    {
+
+        if (!desc->backbuffer_width)
+        {
+            desc->backbuffer_width = client_rect.right;
+            TRACE("Updating width to %u.\n", desc->backbuffer_width);
+        }
+
+        if (!desc->backbuffer_height)
+        {
+            desc->backbuffer_height = client_rect.bottom;
+            TRACE("Updating height to %u.\n", desc->backbuffer_height);
+        }
+#ifndef VBOX_WITH_WDDM
+        if (desc->backbuffer_format == WINED3DFMT_UNKNOWN)
+        {
+            desc->backbuffer_format = swapchain->orig_fmt;
+            TRACE("Updating format to %s.\n", debug_d3dformat(swapchain->orig_fmt));
+        }
+#endif
+    }
+    swapchain->desc = *desc;
+    swapchain_update_render_to_fbo(swapchain);
+
+    TRACE("Creating front buffer.\n");
+
+    surface_desc.resource_type = WINED3D_RTYPE_SURFACE;
+    surface_desc.format = swapchain->desc.backbuffer_format;
+    surface_desc.multisample_type = swapchain->desc.multisample_type;
+    surface_desc.multisample_quality = swapchain->desc.multisample_quality;
+    surface_desc.usage = WINED3DUSAGE_RENDERTARGET;
+    surface_desc.pool = WINED3D_POOL_DEFAULT;
+    surface_desc.width = swapchain->desc.backbuffer_width;
+    surface_desc.height = swapchain->desc.backbuffer_height;
+    surface_desc.depth = 1;
+    surface_desc.size = 0;
+
+    if (FAILED(hr = device->device_parent->ops->create_swapchain_surface(device->device_parent,
+            parent, &surface_desc, &swapchain->front_buffer)))
+    {
+        WARN("Failed to create front buffer, hr %#x.\n", hr);
+        goto err;
+    }
+
+    surface_set_swapchain(swapchain->front_buffer, swapchain);
+    if (!(device->wined3d->flags & WINED3D_NO3D))
+        surface_modify_location(swapchain->front_buffer, SFLAG_INDRAWABLE, TRUE);
+
+    /* MSDN says we're only allowed a single fullscreen swapchain per device,
+     * so we should really check to see if there is a fullscreen swapchain
+     * already. Does a single head count as full screen? */
+
+#ifndef VBOX_WITH_WDDM
+    if (!desc->windowed)
+    {
+        struct wined3d_display_mode mode;
+
+        /* Change the display settings */
+        mode.width = desc->backbuffer_width;
+        mode.height = desc->backbuffer_height;
+        mode.format_id = desc->backbuffer_format;
+        mode.refresh_rate = desc->refresh_rate;
+        mode.scanline_ordering = WINED3D_SCANLINE_ORDERING_UNKNOWN;
+
+        if (FAILED(hr = wined3d_set_adapter_display_mode(device->wined3d, device->adapter->ordinal, &mode)))
+        {
+            WARN("Failed to set display mode, hr %#x.\n", hr);
+            goto err;
+        }
+        displaymode_set = TRUE;
+    }
+#endif
+
+    if (!(device->wined3d->flags & WINED3D_NO3D))
+    {
+#ifndef VBOX_WINE_WITH_SINGLE_CONTEXT
+        static const enum wined3d_format_id formats[] =
+        {
+            WINED3DFMT_D24_UNORM_S8_UINT,
+            WINED3DFMT_D32_UNORM,
+            WINED3DFMT_R24_UNORM_X8_TYPELESS,
+            WINED3DFMT_D16_UNORM,
+            WINED3DFMT_S1_UINT_D15_UNORM
+        };
+
+        const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+
+        swapchain->context = HeapAlloc(GetProcessHeap(), 0, sizeof(*swapchain->context));
+        if (!swapchain->context)
+        {
+            ERR("Failed to create the context array.\n");
+            hr = E_OUTOFMEMORY;
+            goto err;
+        }
+        swapchain->num_contexts = 1;
+
+        /* In WGL both color, depth and stencil are features of a pixel format. In case of D3D they are separate.
+         * You are able to add a depth + stencil surface at a later stage when you need it.
+         * In order to support this properly in WineD3D we need the ability to recreate the opengl context and
+         * drawable when this is required. This is very tricky as we need to reapply ALL opengl states for the new
+         * context, need torecreate shaders, textures and other resources.
+         *
+         * The context manager already takes care of the state problem and for the other tasks code from Reset
+         * can be used. These changes are way to risky during the 1.0 code freeze which is taking place right now.
+         * Likely a lot of other new bugs will be exposed. For that reason request a depth stencil surface all the
+         * time. It can cause a slight performance hit but fixes a lot of regressions. A fixme reminds of that this
+         * issue needs to be fixed. */
+        for (i = 0; i < (sizeof(formats) / sizeof(*formats)); i++)
+        {
+            swapchain->ds_format = wined3d_get_format(gl_info, formats[i]);
+            swapchain->context[0] = context_create(swapchain, swapchain->front_buffer, swapchain->ds_format);
+            if (swapchain->context[0]) break;
+            TRACE("Depth stencil format %s is not supported, trying next format\n",
+                  debug_d3dformat(formats[i]));
+        }
+
+        if (!swapchain->context[0])
+#else
+        struct wined3d_context * swapchain_context;
+        swapchain->ds_format = wined3d_get_format(&device->adapter->gl_info, WINED3DFMT_D24_UNORM_S8_UINT);
+        swapchain_context = context_find_create(device, swapchain, swapchain->ds_format);
+        if (!swapchain_context)
+#endif
+        {
+            WARN("Failed to create context.\n");
+            hr = WINED3DERR_NOTAVAILABLE;
+            goto err;
+        }
+
+        if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
+                && (!desc->enable_auto_depth_stencil
+                || swapchain->desc.auto_depth_stencil_format != swapchain->ds_format->id))
+        {
+            FIXME("Add OpenGL context recreation support to context_validate_onscreen_formats\n");
+        }
+#ifndef VBOX_WINE_WITH_SINGLE_CONTEXT
+        context_release(swapchain->context[0]);
+#else
+        context_release(swapchain_context);
+#endif
+    }
+
+    if (swapchain->desc.backbuffer_count > 0)
+    {
+        swapchain->back_buffers = HeapAlloc(GetProcessHeap(), 0,
+                sizeof(*swapchain->back_buffers) * swapchain->desc.backbuffer_count);
+        if (!swapchain->back_buffers)
+        {
+            ERR("Failed to allocate backbuffer array memory.\n");
+            hr = E_OUTOFMEMORY;
+            goto err;
+        }
+
+        for (i = 0; i < swapchain->desc.backbuffer_count; ++i)
+        {
+            TRACE("Creating back buffer %u.\n", i);
+            if (FAILED(hr = device->device_parent->ops->create_swapchain_surface(device->device_parent,
+                    parent, &surface_desc, &swapchain->back_buffers[i])))
+            {
+                WARN("Failed to create back buffer %u, hr %#x.\n", i, hr);
+                goto err;
+            }
+            surface_set_swapchain(swapchain->back_buffers[i], swapchain);
+        }
+    }
+
+    /* Swapchains share the depth/stencil buffer, so only create a single depthstencil surface. */
+    if (desc->enable_auto_depth_stencil && !(device->wined3d->flags & WINED3D_NO3D))
+    {
+        TRACE("Creating depth/stencil buffer.\n");
+        if (!device->auto_depth_stencil)
+        {
+            surface_desc.format = swapchain->desc.auto_depth_stencil_format;
+            surface_desc.usage = WINED3DUSAGE_DEPTHSTENCIL;
+
+            if (FAILED(hr = device->device_parent->ops->create_swapchain_surface(device->device_parent,
+                    device->device_parent, &surface_desc, &device->auto_depth_stencil)))
+            {
+                WARN("Failed to create the auto depth stencil, hr %#x.\n", hr);
+                goto err;
+            }
+        }
+    }
+
+#ifndef VBOX_WITH_WDDM
+    wined3d_swapchain_get_gamma_ramp(swapchain, &swapchain->orig_gamma);
+#else
+    if (overriden_swapchain)
+    {
+        swapchain_invalidate(overriden_swapchain);
+    }
+#endif
+
+    return WINED3D_OK;
+
+err:
+#ifndef VBOX_WITH_WDDM
+    if (displaymode_set)
+    {
+        DEVMODEW devmode;
+
+        ClipCursor(NULL);
+
+        /* Change the display settings */
+        memset(&devmode, 0, sizeof(devmode));
+        devmode.dmSize = sizeof(devmode);
+        devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
+        devmode.dmBitsPerPel = format->byte_count * CHAR_BIT;
+        devmode.dmPelsWidth = swapchain->orig_width;
+        devmode.dmPelsHeight = swapchain->orig_height;
+        ChangeDisplaySettingsExW(adapter->DeviceName, &devmode, NULL, CDS_FULLSCREEN, NULL);
+    }
+#endif
+    if (swapchain->back_buffers)
+    {
+        for (i = 0; i < swapchain->desc.backbuffer_count; ++i)
+        {
+            if (swapchain->back_buffers[i])
+            {
+                surface_set_swapchain(swapchain->back_buffers[i], NULL);
+                wined3d_surface_decref(swapchain->back_buffers[i]);
+            }
+        }
+        HeapFree(GetProcessHeap(), 0, swapchain->back_buffers);
+#ifdef VBOX_WITH_WINE_FIX_INITCLEAR
+        swapchain->back_buffers = NULL;
+#endif
+    }
+#ifdef VBOX_WITH_WINE_FIX_INITCLEAR
+    swapchain->desc.backbuffer_count = 0;
+#endif
+#ifndef VBOX_WINE_WITH_SINGLE_CONTEXT
+    if (swapchain->context)
+    {
+        if (swapchain->context[0])
+        {
+            context_release(swapchain->context[0]);
+            context_destroy(device, swapchain->context[0]);
+            swapchain->num_contexts = 0;
+        }
+        HeapFree(GetProcessHeap(), 0, swapchain->context);
+    }
+#else
+    if (!device->swapchain_count)
+    {
+        while (device->context_count)
+        {
+            context_destroy(device, device->contexts[0]);
+        }
+    }
+#endif
+    if (swapchain->front_buffer)
+    {
+        surface_set_swapchain(swapchain->front_buffer, NULL);
+        wined3d_surface_decref(swapchain->front_buffer);
+    }
+
+#ifdef VBOX_WITH_WDDM
+    if (!overriden_swapchain && swapchain->win_handle)
+    {
+        VBoxExtWndDestroy(swapchain->win_handle, swapchain->hDC);
+    }
+    swapchain_invalidate(swapchain);
+#endif
+
+    return hr;
+}
+
+/* Do not call while under the GL lock. */
+HRESULT CDECL wined3d_swapchain_create(struct wined3d_device *device, struct wined3d_swapchain_desc *desc,
+        void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_swapchain **swapchain)
+{
+    struct wined3d_swapchain *object;
+    HRESULT hr;
+
+    TRACE("device %p, desc %p, parent %p, parent_ops %p, swapchain %p.\n",
+            device, desc, parent, parent_ops, swapchain);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return E_OUTOFMEMORY;
+
+    hr = swapchain_init(object, device, desc, parent, parent_ops);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize swapchain, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created swapchain %p.\n", object);
+    *swapchain = object;
+
+    return WINED3D_OK;
+}
+
+#ifndef VBOX_WINE_WITH_SINGLE_CONTEXT
+/* Do not call while under the GL lock. */
+static struct wined3d_context *swapchain_create_context(struct wined3d_swapchain *swapchain)
+{
+    struct wined3d_context **newArray;
+    struct wined3d_context *ctx;
+
+    TRACE("Creating a new context for swapchain %p, thread %u.\n", swapchain, GetCurrentThreadId());
+
+    if (!(ctx = context_create(swapchain, swapchain->front_buffer, swapchain->ds_format)))
+    {
+        ERR("Failed to create a new context for the swapchain\n");
+        return NULL;
+    }
+    context_release(ctx);
+
+    newArray = HeapAlloc(GetProcessHeap(), 0, sizeof(*newArray) * (swapchain->num_contexts + 1));
+    if(!newArray) {
+        ERR("Out of memory when trying to allocate a new context array\n");
+        context_destroy(swapchain->device, ctx);
+        return NULL;
+    }
+    memcpy(newArray, swapchain->context, sizeof(*newArray) * swapchain->num_contexts);
+    HeapFree(GetProcessHeap(), 0, swapchain->context);
+    newArray[swapchain->num_contexts] = ctx;
+    swapchain->context = newArray;
+    swapchain->num_contexts++;
+
+    TRACE("Returning context %p\n", ctx);
+    return ctx;
+}
+
+void swapchain_destroy_contexts(struct wined3d_swapchain *swapchain)
+{
+    unsigned int i;
+
+    for (i = 0; i < swapchain->num_contexts; ++i)
+    {
+        context_destroy(swapchain->device, swapchain->context[i]);
+    }
+    swapchain->num_contexts = 0;
+}
+
+struct wined3d_context *swapchain_get_context(struct wined3d_swapchain *swapchain)
+{
+    DWORD tid = GetCurrentThreadId();
+    unsigned int i;
+
+    for (i = 0; i < swapchain->num_contexts; ++i)
+    {
+#  ifdef VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT
+        if (VBoxTlsRefIsFunctional(swapchain->context[i]))
+#  else
+        if (swapchain->context[i]->tid == tid)
+#endif
+            return swapchain->context[i];
+    }
+
+    /* Create a new context for the thread */
+    return swapchain_create_context(swapchain);
+}
+#else /* if defined VBOX_WINE_WITH_SINGLE_CONTEXT */
+struct wined3d_context *swapchain_get_context(struct wined3d_swapchain *swapchain)
+{
+    struct wined3d_context * context = swapchain->device->contexts[0];
+    return context;
+}
+#endif
+
+void get_drawable_size_swapchain(const struct wined3d_context *context, UINT *width, UINT *height)
+{
+    /* The drawable size of an onscreen drawable is the surface size.
+     * (Actually: The window size, but the surface is created in window size) */
+    *width = context->current_rt->resource.width;
+    *height = context->current_rt->resource.height;
+}
+
+#ifndef VBOX_WITH_WDDM
+HDC swapchain_get_backup_dc(struct wined3d_swapchain *swapchain)
+{
+    if (!swapchain->backup_dc)
+    {
+        TRACE("Creating the backup window for swapchain %p.\n", swapchain);
+
+        if (!(swapchain->backup_wnd = CreateWindowA(WINED3D_OPENGL_WINDOW_CLASS_NAME, "WineD3D fake window",
+                WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL)))
+        {
+            ERR("Failed to create a window.\n");
+            return NULL;
+        }
+
+        if (!(swapchain->backup_dc = GetDC(swapchain->backup_wnd)))
+        {
+            ERR("Failed to get a DC.\n");
+            DestroyWindow(swapchain->backup_wnd);
+            swapchain->backup_wnd = NULL;
+            return NULL;
+        }
+    }
+
+    return swapchain->backup_dc;
+}
+#endif
+void swapchain_update_draw_bindings(struct wined3d_swapchain *swapchain)
+{
+    UINT i;
+
+    surface_update_draw_binding(swapchain->front_buffer);
+
+    for (i = 0; i < swapchain->desc.backbuffer_count; ++i)
+    {
+        surface_update_draw_binding(swapchain->back_buffers[i]);
+    }
+}
+
+#ifdef VBOX_WITH_WDDM
+HRESULT CDECL wined3d_swapchain_present_rt(struct wined3d_swapchain *swapchain, struct wined3d_surface *rt)
+{
+    struct wined3d_surface *bb = swapchain->back_buffers[0];
+    HRESULT hr = wined3d_surface_blt(bb, NULL, rt, NULL, 0, NULL, 0);
+    if (FAILED(hr))
+    {
+        ERR("wined3d_surface_blt failed with hr(%d)", hr);
+        return hr;
+    }
+
+    hr =  wined3d_swapchain_present(swapchain, NULL, NULL, NULL, NULL, 0);
+    if (FAILED(hr))
+    {
+        ERR("wined3d_swapchain_present failed with hr(%d)", hr);
+        return hr;
+    }
+
+    return S_OK;
+}
+#endif
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/texture.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/texture.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/texture.c	(revision 46521)
@@ -0,0 +1,1774 @@
+/*
+ * Copyright 2002-2005 Jason Edmeades
+ * Copyright 2002-2005 Raphael Junqueira
+ * Copyright 2005 Oliver Stieber
+ * Copyright 2007-2009, 2013 Stefan Dösinger for CodeWeavers
+ * Copyright 2009-2011 Henri Verbeet for CodeWeavers
+ *
+ * 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 "wined3d_private.h"
+
+#ifdef VBOX_WITH_WDDM
+# include "../../common/VBoxVideoTools.h"
+#endif
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d_texture);
+
+static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struct wined3d_texture_ops *texture_ops,
+        UINT layer_count, UINT level_count, const struct wined3d_resource_desc *desc, struct wined3d_device *device,
+        void *parent, const struct wined3d_parent_ops *parent_ops, const struct wined3d_resource_ops *resource_ops
+#ifdef VBOX_WITH_WDDM
+        , HANDLE *shared_handle
+        , void **pavClientMem
+#endif
+        )
+{
+    const struct wined3d_format *format = wined3d_get_format(&device->adapter->gl_info, desc->format);
+    HRESULT hr;
+
+    TRACE("texture %p, texture_ops %p, layer_count %u, level_count %u, resource_type %s, format %s, "
+            "multisample_type %#x, multisample_quality %#x, usage %s, pool %s, width %u, height %u, depth %u, "
+            "device %p, parent %p, parent_ops %p, resource_ops %p.\n",
+            texture, texture_ops, layer_count, level_count, debug_d3dresourcetype(desc->resource_type),
+            debug_d3dformat(desc->format), desc->multisample_type, desc->multisample_quality,
+            debug_d3dusage(desc->usage), debug_d3dpool(desc->pool), desc->width, desc->height, desc->depth,
+            device, parent, parent_ops, resource_ops);
+
+#ifdef VBOX_WITH_WDDM
+    if (FAILED(hr = resource_init(&texture->resource, device, desc->resource_type, format,
+            desc->multisample_type, desc->multisample_quality, desc->usage, desc->pool,
+            desc->width, desc->height, desc->depth, 0, parent, parent_ops, resource_ops,
+            shared_handle, pavClientMem ? pavClientMem[0] : NULL)))
+#else
+    if (FAILED(hr = resource_init(&texture->resource, device, desc->resource_type, format,
+            desc->multisample_type, desc->multisample_quality, desc->usage, desc->pool,
+            desc->width, desc->height, desc->depth, 0, parent, parent_ops, resource_ops)))
+#endif
+    {
+        WARN("Failed to initialize resource, returning %#x\n", hr);
+        return hr;
+    }
+
+    texture->texture_ops = texture_ops;
+    texture->sub_resources = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+            level_count * layer_count * sizeof(*texture->sub_resources));
+    if (!texture->sub_resources)
+    {
+        ERR("Failed to allocate sub-resource array.\n");
+        resource_cleanup(&texture->resource);
+        return E_OUTOFMEMORY;
+    }
+
+    texture->layer_count = layer_count;
+    texture->level_count = level_count;
+    texture->filter_type = (desc->usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3D_TEXF_LINEAR : WINED3D_TEXF_NONE;
+    texture->lod = 0;
+    texture->texture_rgb.dirty = TRUE;
+    texture->texture_srgb.dirty = TRUE;
+    texture->flags = WINED3D_TEXTURE_POW2_MAT_IDENT;
+
+    if (texture->resource.format->flags & WINED3DFMT_FLAG_FILTERING)
+    {
+        texture->min_mip_lookup = minMipLookup;
+        texture->mag_lookup = magLookup;
+    }
+    else
+    {
+        texture->min_mip_lookup = minMipLookup_noFilter;
+        texture->mag_lookup = magLookup_noFilter;
+    }
+
+    return WINED3D_OK;
+}
+
+/* A GL context is provided by the caller */
+static void gltexture_delete(const struct wined3d_gl_info *gl_info, struct gl_texture *tex)
+{
+#ifdef VBOX_WITH_WDDM
+    texture_gl_delete(tex->name);
+#else
+    gl_info->gl_ops.gl.p_glDeleteTextures(1, &tex->name);
+#endif
+    tex->name = 0;
+}
+
+static void wined3d_texture_unload(struct wined3d_texture *texture)
+{
+    struct wined3d_device *device = texture->resource.device;
+    struct wined3d_context *context = NULL;
+
+    if (texture->texture_rgb.name || texture->texture_srgb.name)
+    {
+        context = context_acquire(device, NULL);
+    }
+
+    if (texture->texture_rgb.name)
+        gltexture_delete(context->gl_info, &texture->texture_rgb);
+
+    if (texture->texture_srgb.name)
+        gltexture_delete(context->gl_info, &texture->texture_srgb);
+
+    if (context) context_release(context);
+
+    wined3d_texture_set_dirty(texture, TRUE);
+
+    resource_unload(&texture->resource);
+}
+
+static void wined3d_texture_cleanup(struct wined3d_texture *texture)
+{
+    UINT sub_count = texture->level_count * texture->layer_count;
+    UINT i;
+
+    TRACE("texture %p.\n", texture);
+
+    for (i = 0; i < sub_count; ++i)
+    {
+        struct wined3d_resource *sub_resource = texture->sub_resources[i];
+
+        if (sub_resource)
+            texture->texture_ops->texture_sub_resource_cleanup(sub_resource);
+    }
+
+    wined3d_texture_unload(texture);
+    HeapFree(GetProcessHeap(), 0, texture->sub_resources);
+    resource_cleanup(&texture->resource);
+}
+
+void wined3d_texture_set_dirty(struct wined3d_texture *texture, BOOL dirty)
+{
+    texture->texture_rgb.dirty = dirty;
+    texture->texture_srgb.dirty = dirty;
+}
+
+/* Context activation is done by the caller. */
+static HRESULT wined3d_texture_bind(struct wined3d_texture *texture,
+        struct wined3d_context *context, BOOL srgb, BOOL *set_surface_desc)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    struct gl_texture *gl_tex;
+    BOOL new_texture = FALSE;
+    HRESULT hr = WINED3D_OK;
+    GLenum target;
+
+    TRACE("texture %p, context %p, srgb %#x, set_surface_desc %p.\n", texture, context, srgb, set_surface_desc);
+
+    /* sRGB mode cache for preload() calls outside drawprim. */
+    if (srgb)
+        texture->flags |= WINED3D_TEXTURE_IS_SRGB;
+    else
+        texture->flags &= ~WINED3D_TEXTURE_IS_SRGB;
+
+    gl_tex = wined3d_texture_get_gl_texture(texture, context->gl_info, srgb);
+    target = texture->target;
+
+    /* Generate a texture name if we don't already have one. */
+    if (!gl_tex->name)
+    {
+#ifdef VBOX_WITH_WDDM
+        if (VBOXSHRC_IS_SHARED_OPENED(texture))
+        {
+            ERR("should not be here!");
+            gl_tex->name = (GLuint)VBOXSHRC_GET_SHAREHANDLE(texture);
+            pglChromiumParameteriCR(GL_RCUSAGE_TEXTURE_SET_CR, gl_tex->name);
+            TRACE("Assigned shared texture %d\n", gl_tex->name);
+        }
+        else
+#endif
+        {
+#ifdef VBOX_WITH_WDDM
+            new_texture = TRUE;
+#endif
+            *set_surface_desc = TRUE;
+            gl_info->gl_ops.gl.p_glGenTextures(1, &gl_tex->name);
+            checkGLcall("glGenTextures");
+            TRACE("Generated texture %d.\n", gl_tex->name);
+#ifdef VBOX_WITH_WDDM
+            if (VBOXSHRC_IS_SHARED(texture))
+            {
+                VBOXSHRC_SET_SHAREHANDLE(texture, gl_tex->name);
+            }
+#endif
+        }
+#ifndef VBOX
+        if (texture->resource.pool == WINED3D_POOL_DEFAULT)
+        {
+            /* Tell OpenGL to try and keep this texture in video ram (well mostly). */
+            GLclampf tmp = 0.9f;
+            gl_info->gl_ops.gl.p_glPrioritizeTextures(1, &gl_tex->name, &tmp);
+        }
+#else
+        /* chromium code on host fails to resolve texture name to texture obj,
+         * most likely because the texture does not get created until it is bound
+         * @todo: investigate */
+#endif
+        /* Initialise the state of the texture object to the OpenGL defaults,
+         * not the D3D defaults. */
+        gl_tex->states[WINED3DTEXSTA_ADDRESSU] = WINED3D_TADDRESS_WRAP;
+        gl_tex->states[WINED3DTEXSTA_ADDRESSV] = WINED3D_TADDRESS_WRAP;
+        gl_tex->states[WINED3DTEXSTA_ADDRESSW] = WINED3D_TADDRESS_WRAP;
+        gl_tex->states[WINED3DTEXSTA_BORDERCOLOR] = 0;
+        gl_tex->states[WINED3DTEXSTA_MAGFILTER] = WINED3D_TEXF_LINEAR;
+        gl_tex->states[WINED3DTEXSTA_MINFILTER] = WINED3D_TEXF_POINT; /* GL_NEAREST_MIPMAP_LINEAR */
+        gl_tex->states[WINED3DTEXSTA_MIPFILTER] = WINED3D_TEXF_LINEAR; /* GL_NEAREST_MIPMAP_LINEAR */
+        gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL] = 0;
+        gl_tex->states[WINED3DTEXSTA_MAXANISOTROPY] = 1;
+        if (context->gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
+            gl_tex->states[WINED3DTEXSTA_SRGBTEXTURE] = TRUE;
+        else
+            gl_tex->states[WINED3DTEXSTA_SRGBTEXTURE] = srgb;
+        gl_tex->states[WINED3DTEXSTA_SHADOW] = FALSE;
+        wined3d_texture_set_dirty(texture, TRUE);
+#ifndef VBOX_WITH_WDDM
+        new_texture = TRUE;
+#endif
+
+#ifdef VBOX_WITH_WDDM
+        if (new_texture
+                && texture->resource.usage & WINED3DUSAGE_AUTOGENMIPMAP)
+#else
+        if (texture->resource.usage & WINED3DUSAGE_AUTOGENMIPMAP)
+#endif
+        {
+            /* This means double binding the texture at creation, but keeps
+             * the code simpler all in all, and the run-time path free from
+             * additional checks. */
+            context_bind_texture(context, target, gl_tex->name);
+            gl_info->gl_ops.gl.p_glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
+            checkGLcall("glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE)");
+        }
+    }
+    else
+    {
+        *set_surface_desc = FALSE;
+    }
+
+    if (gl_tex->name)
+    {
+        context_bind_texture(context, target, gl_tex->name);
+        if (new_texture)
+        {
+            /* For a new texture we have to set the texture levels after
+             * binding the texture. Beware that texture rectangles do not
+             * support mipmapping, but set the maxmiplevel if we're relying
+             * on the partial GL_ARB_texture_non_power_of_two emulation with
+             * texture rectangles. (I.e., do not care about cond_np2 here,
+             * just look for GL_TEXTURE_RECTANGLE_ARB.) */
+            if (target != GL_TEXTURE_RECTANGLE_ARB)
+            {
+                TRACE("Setting GL_TEXTURE_MAX_LEVEL to %u.\n", texture->level_count - 1);
+                gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, texture->level_count - 1);
+                checkGLcall("glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, texture->level_count)");
+            }
+            if (target == GL_TEXTURE_CUBE_MAP_ARB)
+            {
+                /* Cubemaps are always set to clamp, regardless of the sampler state. */
+                gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+                gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+                gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+            }
+        }
+    }
+    else
+    {
+        ERR("This texture doesn't have an OpenGL texture assigned to it.\n");
+        hr = WINED3DERR_INVALIDCALL;
+    }
+
+    return hr;
+}
+
+/* Context activation is done by the caller. */
+static void apply_wrap(const struct wined3d_gl_info *gl_info, GLenum target,
+        enum wined3d_texture_address d3d_wrap, GLenum param, BOOL cond_np2)
+{
+    GLint gl_wrap;
+
+    if (d3d_wrap < WINED3D_TADDRESS_WRAP || d3d_wrap > WINED3D_TADDRESS_MIRROR_ONCE)
+    {
+        FIXME("Unrecognized or unsupported texture address mode %#x.\n", d3d_wrap);
+        return;
+    }
+
+    /* Cubemaps are always set to clamp, regardless of the sampler state. */
+    if (target == GL_TEXTURE_CUBE_MAP_ARB
+            || (cond_np2 && d3d_wrap == WINED3D_TADDRESS_WRAP))
+        gl_wrap = GL_CLAMP_TO_EDGE;
+    else
+        gl_wrap = gl_info->wrap_lookup[d3d_wrap - WINED3D_TADDRESS_WRAP];
+
+    TRACE("Setting param %#x to %#x for target %#x.\n", param, gl_wrap, target);
+    gl_info->gl_ops.gl.p_glTexParameteri(target, param, gl_wrap);
+    checkGLcall("glTexParameteri(target, param, gl_wrap)");
+}
+
+/* Context activation is done by the caller (state handler). */
+void wined3d_texture_apply_state_changes(struct wined3d_texture *texture,
+        const DWORD sampler_states[WINED3D_HIGHEST_SAMPLER_STATE + 1],
+        const struct wined3d_gl_info *gl_info)
+{
+    BOOL cond_np2 = texture->flags & WINED3D_TEXTURE_COND_NP2;
+    GLenum target = texture->target;
+    struct gl_texture *gl_tex;
+    DWORD state;
+    DWORD aniso;
+
+    TRACE("texture %p, sampler_states %p.\n", texture, sampler_states);
+
+    gl_tex = wined3d_texture_get_gl_texture(texture, gl_info,
+            texture->flags & WINED3D_TEXTURE_IS_SRGB);
+
+    /* This function relies on the correct texture being bound and loaded. */
+
+    if (sampler_states[WINED3D_SAMP_ADDRESS_U] != gl_tex->states[WINED3DTEXSTA_ADDRESSU])
+    {
+        state = sampler_states[WINED3D_SAMP_ADDRESS_U];
+        apply_wrap(gl_info, target, state, GL_TEXTURE_WRAP_S, cond_np2);
+        gl_tex->states[WINED3DTEXSTA_ADDRESSU] = state;
+    }
+
+    if (sampler_states[WINED3D_SAMP_ADDRESS_V] != gl_tex->states[WINED3DTEXSTA_ADDRESSV])
+    {
+        state = sampler_states[WINED3D_SAMP_ADDRESS_V];
+        apply_wrap(gl_info, target, state, GL_TEXTURE_WRAP_T, cond_np2);
+        gl_tex->states[WINED3DTEXSTA_ADDRESSV] = state;
+    }
+
+    if (sampler_states[WINED3D_SAMP_ADDRESS_W] != gl_tex->states[WINED3DTEXSTA_ADDRESSW])
+    {
+        state = sampler_states[WINED3D_SAMP_ADDRESS_W];
+        apply_wrap(gl_info, target, state, GL_TEXTURE_WRAP_R, cond_np2);
+        gl_tex->states[WINED3DTEXSTA_ADDRESSW] = state;
+    }
+
+    if (sampler_states[WINED3D_SAMP_BORDER_COLOR] != gl_tex->states[WINED3DTEXSTA_BORDERCOLOR])
+    {
+        float col[4];
+
+        state = sampler_states[WINED3D_SAMP_BORDER_COLOR];
+        D3DCOLORTOGLFLOAT4(state, col);
+        TRACE("Setting border color for %#x to %#x.\n", target, state);
+        gl_info->gl_ops.gl.p_glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, &col[0]);
+        checkGLcall("glTexParameterfv(..., GL_TEXTURE_BORDER_COLOR, ...)");
+        gl_tex->states[WINED3DTEXSTA_BORDERCOLOR] = state;
+    }
+
+    if (sampler_states[WINED3D_SAMP_MAG_FILTER] != gl_tex->states[WINED3DTEXSTA_MAGFILTER])
+    {
+        GLint gl_value;
+
+        state = sampler_states[WINED3D_SAMP_MAG_FILTER];
+        if (state > WINED3D_TEXF_ANISOTROPIC)
+            FIXME("Unrecognized or unsupported MAGFILTER* value %d.\n", state);
+
+        gl_value = wined3d_gl_mag_filter(texture->mag_lookup,
+                min(max(state, WINED3D_TEXF_POINT), WINED3D_TEXF_LINEAR));
+        TRACE("ValueMAG=%#x setting MAGFILTER to %#x.\n", state, gl_value);
+        gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_MAG_FILTER, gl_value);
+
+        gl_tex->states[WINED3DTEXSTA_MAGFILTER] = state;
+    }
+
+    if ((sampler_states[WINED3D_SAMP_MIN_FILTER] != gl_tex->states[WINED3DTEXSTA_MINFILTER]
+            || sampler_states[WINED3D_SAMP_MIP_FILTER] != gl_tex->states[WINED3DTEXSTA_MIPFILTER]
+            || sampler_states[WINED3D_SAMP_MAX_MIP_LEVEL] != gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL]))
+    {
+        GLint gl_value;
+
+        gl_tex->states[WINED3DTEXSTA_MIPFILTER] = sampler_states[WINED3D_SAMP_MIP_FILTER];
+        gl_tex->states[WINED3DTEXSTA_MINFILTER] = sampler_states[WINED3D_SAMP_MIN_FILTER];
+        gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL] = sampler_states[WINED3D_SAMP_MAX_MIP_LEVEL];
+
+        if (gl_tex->states[WINED3DTEXSTA_MINFILTER] > WINED3D_TEXF_ANISOTROPIC
+            || gl_tex->states[WINED3DTEXSTA_MIPFILTER] > WINED3D_TEXF_ANISOTROPIC)
+        {
+            FIXME("Unrecognized or unsupported MIN_FILTER value %#x MIP_FILTER value %#x.\n",
+                  gl_tex->states[WINED3DTEXSTA_MINFILTER],
+                  gl_tex->states[WINED3DTEXSTA_MIPFILTER]);
+        }
+        gl_value = wined3d_gl_min_mip_filter(texture->min_mip_lookup,
+                min(max(sampler_states[WINED3D_SAMP_MIN_FILTER], WINED3D_TEXF_POINT), WINED3D_TEXF_LINEAR),
+                min(max(sampler_states[WINED3D_SAMP_MIP_FILTER], WINED3D_TEXF_NONE), WINED3D_TEXF_LINEAR));
+
+        TRACE("ValueMIN=%#x, ValueMIP=%#x, setting MINFILTER to %#x.\n",
+              sampler_states[WINED3D_SAMP_MIN_FILTER],
+              sampler_states[WINED3D_SAMP_MIP_FILTER], gl_value);
+        gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_MIN_FILTER, gl_value);
+        checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
+
+        if (!cond_np2)
+        {
+            if (gl_tex->states[WINED3DTEXSTA_MIPFILTER] == WINED3D_TEXF_NONE)
+                gl_value = texture->lod;
+            else if (gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL] >= texture->level_count)
+                gl_value = texture->level_count - 1;
+            else if (gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL] < texture->lod)
+                /* texture->lod is already clamped in the setter. */
+                gl_value = texture->lod;
+            else
+                gl_value = gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL];
+
+            /* Note that WINED3D_SAMP_MAX_MIP_LEVEL specifies the largest mipmap
+             * (default 0), while GL_TEXTURE_MAX_LEVEL specifies the smallest
+             * mimap used (default 1000). So WINED3D_SAMP_MAX_MIP_LEVEL
+             * corresponds to GL_TEXTURE_BASE_LEVEL. */
+            gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, gl_value);
+        }
+    }
+
+    if ((gl_tex->states[WINED3DTEXSTA_MAGFILTER] != WINED3D_TEXF_ANISOTROPIC
+            && gl_tex->states[WINED3DTEXSTA_MINFILTER] != WINED3D_TEXF_ANISOTROPIC
+            && gl_tex->states[WINED3DTEXSTA_MIPFILTER] != WINED3D_TEXF_ANISOTROPIC)
+            || cond_np2)
+        aniso = 1;
+    else
+        aniso = sampler_states[WINED3D_SAMP_MAX_ANISOTROPY];
+
+    if (gl_tex->states[WINED3DTEXSTA_MAXANISOTROPY] != aniso)
+    {
+        if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
+        {
+            gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso);
+            checkGLcall("glTexParameteri(GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso)");
+        }
+        else
+        {
+            WARN("Anisotropic filtering not supported.\n");
+        }
+        gl_tex->states[WINED3DTEXSTA_MAXANISOTROPY] = aniso;
+    }
+
+    /* These should always be the same unless EXT_texture_sRGB_decode is supported. */
+    if (sampler_states[WINED3D_SAMP_SRGB_TEXTURE] != gl_tex->states[WINED3DTEXSTA_SRGBTEXTURE])
+    {
+        gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_SRGB_DECODE_EXT,
+                sampler_states[WINED3D_SAMP_SRGB_TEXTURE] ? GL_DECODE_EXT : GL_SKIP_DECODE_EXT);
+        checkGLcall("glTexParameteri(GL_TEXTURE_SRGB_DECODE_EXT)");
+        gl_tex->states[WINED3DTEXSTA_SRGBTEXTURE] = sampler_states[WINED3D_SAMP_SRGB_TEXTURE];
+    }
+
+    if (!(texture->resource.format->flags & WINED3DFMT_FLAG_SHADOW)
+            != !gl_tex->states[WINED3DTEXSTA_SHADOW])
+    {
+        if (texture->resource.format->flags & WINED3DFMT_FLAG_SHADOW)
+        {
+            gl_info->gl_ops.gl.p_glTexParameteri(target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
+            gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
+            checkGLcall("glTexParameteri(target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB)");
+            gl_tex->states[WINED3DTEXSTA_SHADOW] = TRUE;
+        }
+        else
+        {
+            gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
+            checkGLcall("glTexParameteri(target, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE)");
+            gl_tex->states[WINED3DTEXSTA_SHADOW] = FALSE;
+        }
+    }
+}
+
+ULONG CDECL wined3d_texture_incref(struct wined3d_texture *texture)
+{
+    ULONG refcount = InterlockedIncrement(&texture->resource.ref);
+
+    TRACE("%p increasing refcount to %u.\n", texture, refcount);
+
+    return refcount;
+}
+
+/* Do not call while under the GL lock. */
+ULONG CDECL wined3d_texture_decref(struct wined3d_texture *texture)
+{
+    ULONG refcount = InterlockedDecrement(&texture->resource.ref);
+
+    TRACE("%p decreasing refcount to %u.\n", texture, refcount);
+
+    if (!refcount)
+    {
+        wined3d_texture_cleanup(texture);
+        texture->resource.parent_ops->wined3d_object_destroyed(texture->resource.parent);
+        HeapFree(GetProcessHeap(), 0, texture);
+    }
+
+    return refcount;
+}
+
+struct wined3d_resource * CDECL wined3d_texture_get_resource(struct wined3d_texture *texture)
+{
+    TRACE("texture %p.\n", texture);
+
+    return &texture->resource;
+}
+
+DWORD CDECL wined3d_texture_set_priority(struct wined3d_texture *texture, DWORD priority)
+{
+    return resource_set_priority(&texture->resource, priority);
+}
+
+DWORD CDECL wined3d_texture_get_priority(const struct wined3d_texture *texture)
+{
+    return resource_get_priority(&texture->resource);
+}
+
+/* Do not call while under the GL lock. */
+void CDECL wined3d_texture_preload(struct wined3d_texture *texture)
+{
+    texture->texture_ops->texture_preload(texture, SRGB_ANY);
+}
+
+void * CDECL wined3d_texture_get_parent(const struct wined3d_texture *texture)
+{
+    TRACE("texture %p.\n", texture);
+
+    return texture->resource.parent;
+}
+
+DWORD CDECL wined3d_texture_set_lod(struct wined3d_texture *texture, DWORD lod)
+{
+    DWORD old = texture->lod;
+
+    TRACE("texture %p, lod %u.\n", texture, lod);
+
+    /* The d3d9:texture test shows that SetLOD is ignored on non-managed
+     * textures. The call always returns 0, and GetLOD always returns 0. */
+    if (texture->resource.pool != WINED3D_POOL_MANAGED)
+    {
+        TRACE("Ignoring SetLOD on %s texture, returning 0.\n", debug_d3dpool(texture->resource.pool));
+        return 0;
+    }
+
+    if (lod >= texture->level_count)
+        lod = texture->level_count - 1;
+
+    if (texture->lod != lod)
+    {
+        texture->lod = lod;
+
+        texture->texture_rgb.states[WINED3DTEXSTA_MAXMIPLEVEL] = ~0U;
+        texture->texture_srgb.states[WINED3DTEXSTA_MAXMIPLEVEL] = ~0U;
+        if (texture->resource.bind_count)
+            device_invalidate_state(texture->resource.device, STATE_SAMPLER(texture->sampler));
+    }
+
+    return old;
+}
+
+DWORD CDECL wined3d_texture_get_lod(const struct wined3d_texture *texture)
+{
+    TRACE("texture %p, returning %u.\n", texture, texture->lod);
+
+    return texture->lod;
+}
+
+DWORD CDECL wined3d_texture_get_level_count(const struct wined3d_texture *texture)
+{
+    TRACE("texture %p, returning %u.\n", texture, texture->level_count);
+
+    return texture->level_count;
+}
+
+HRESULT CDECL wined3d_texture_set_autogen_filter_type(struct wined3d_texture *texture,
+        enum wined3d_texture_filter_type filter_type)
+{
+    FIXME("texture %p, filter_type %s stub!\n", texture, debug_d3dtexturefiltertype(filter_type));
+
+    if (!(texture->resource.usage & WINED3DUSAGE_AUTOGENMIPMAP))
+    {
+        WARN("Texture doesn't have AUTOGENMIPMAP usage.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    texture->filter_type = filter_type;
+
+    return WINED3D_OK;
+}
+
+enum wined3d_texture_filter_type CDECL wined3d_texture_get_autogen_filter_type(const struct wined3d_texture *texture)
+{
+    TRACE("texture %p.\n", texture);
+
+    return texture->filter_type;
+}
+
+void CDECL wined3d_texture_generate_mipmaps(struct wined3d_texture *texture)
+{
+    /* TODO: Implement filters using GL_SGI_generate_mipmaps. */
+    FIXME("texture %p stub!\n", texture);
+}
+
+struct wined3d_resource * CDECL wined3d_texture_get_sub_resource(struct wined3d_texture *texture,
+        UINT sub_resource_idx)
+{
+    UINT sub_count = texture->level_count * texture->layer_count;
+
+    TRACE("texture %p, sub_resource_idx %u.\n", texture, sub_resource_idx);
+
+    if (sub_resource_idx >= sub_count)
+    {
+        WARN("sub_resource_idx %u >= sub_count %u.\n", sub_resource_idx, sub_count);
+        return NULL;
+    }
+
+    return texture->sub_resources[sub_resource_idx];
+}
+
+HRESULT CDECL wined3d_texture_add_dirty_region(struct wined3d_texture *texture,
+        UINT layer, const struct wined3d_box *dirty_region)
+{
+    struct wined3d_resource *sub_resource;
+
+    TRACE("texture %p, layer %u, dirty_region %p.\n", texture, layer, dirty_region);
+
+    if (!(sub_resource = wined3d_texture_get_sub_resource(texture, layer * texture->level_count)))
+    {
+        WARN("Failed to get sub-resource.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    wined3d_texture_set_dirty(texture, TRUE);
+    texture->texture_ops->texture_sub_resource_add_dirty_region(sub_resource, dirty_region);
+
+    return WINED3D_OK;
+}
+
+/* Context activation is done by the caller. */
+static HRESULT texture2d_bind(struct wined3d_texture *texture,
+        struct wined3d_context *context, BOOL srgb)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    BOOL set_gl_texture_desc;
+    HRESULT hr;
+
+    TRACE("texture %p, context %p, srgb %#x.\n", texture, context, srgb);
+
+    hr = wined3d_texture_bind(texture, context, srgb, &set_gl_texture_desc);
+    if (set_gl_texture_desc && SUCCEEDED(hr))
+    {
+        UINT sub_count = texture->level_count * texture->layer_count;
+        BOOL srgb_tex = !context->gl_info->supported[EXT_TEXTURE_SRGB_DECODE]
+                && (texture->flags & WINED3D_TEXTURE_IS_SRGB);
+        struct gl_texture *gl_tex;
+        UINT i;
+
+        gl_tex = wined3d_texture_get_gl_texture(texture, context->gl_info, srgb_tex);
+
+        for (i = 0; i < sub_count; ++i)
+        {
+            struct wined3d_surface *surface = surface_from_resource(texture->sub_resources[i]);
+            surface_set_texture_name(surface, gl_tex->name, srgb_tex);
+        }
+
+        /* Conditinal non power of two textures use a different clamping
+         * default. If we're using the GL_WINE_normalized_texrect partial
+         * driver emulation, we're dealing with a GL_TEXTURE_2D texture which
+         * has the address mode set to repeat - something that prevents us
+         * from hitting the accelerated codepath. Thus manually set the GL
+         * state. The same applies to filtering. Even if the texture has only
+         * one mip level, the default LINEAR_MIPMAP_LINEAR filter causes a SW
+         * fallback on macos. */
+        if (texture->flags & WINED3D_TEXTURE_COND_NP2)
+        {
+#ifdef VBOX_WITH_WDDM
+            Assert(!VBOXSHRC_IS_SHARED_OPENED(texture));
+            if (!VBOXSHRC_IS_SHARED_OPENED(texture))
+#endif
+            {
+            GLenum target = texture->target;
+
+            gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+            checkGLcall("glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)");
+            gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+            checkGLcall("glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)");
+            gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+            checkGLcall("glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST)");
+            gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+            checkGLcall("glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST)");
+            }
+            gl_tex->states[WINED3DTEXSTA_ADDRESSU] = WINED3D_TADDRESS_CLAMP;
+            gl_tex->states[WINED3DTEXSTA_ADDRESSV] = WINED3D_TADDRESS_CLAMP;
+            gl_tex->states[WINED3DTEXSTA_MAGFILTER] = WINED3D_TEXF_POINT;
+            gl_tex->states[WINED3DTEXSTA_MINFILTER] = WINED3D_TEXF_POINT;
+            gl_tex->states[WINED3DTEXSTA_MIPFILTER] = WINED3D_TEXF_NONE;
+        }
+    }
+
+    return hr;
+}
+
+static BOOL texture_srgb_mode(const struct wined3d_texture *texture, enum WINED3DSRGB srgb)
+{
+    switch (srgb)
+    {
+        case SRGB_RGB:
+            return FALSE;
+
+        case SRGB_SRGB:
+            return TRUE;
+
+        default:
+            return texture->flags & WINED3D_TEXTURE_IS_SRGB;
+    }
+}
+
+/* Do not call while under the GL lock. */
+static void texture2d_preload(struct wined3d_texture *texture, enum WINED3DSRGB srgb)
+{
+    UINT sub_count = texture->level_count * texture->layer_count;
+    struct wined3d_device *device = texture->resource.device;
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    struct wined3d_context *context = NULL;
+    struct gl_texture *gl_tex;
+    BOOL srgb_mode;
+    UINT i;
+
+    TRACE("texture %p, srgb %#x.\n", texture, srgb);
+
+    srgb_mode = texture_srgb_mode(texture, srgb);
+    gl_tex = wined3d_texture_get_gl_texture(texture, gl_info, srgb_mode);
+
+    if (!device->isInDraw)
+    {
+        /* No danger of recursive calls, context_acquire() sets isInDraw to TRUE
+         * when loading offscreen render targets into the texture. */
+        context = context_acquire(device, NULL);
+    }
+
+    if (gl_tex->dirty)
+    {
+        /* Reload the surfaces if the texture is marked dirty. */
+        for (i = 0; i < sub_count; ++i)
+        {
+            surface_load(surface_from_resource(texture->sub_resources[i]), srgb_mode);
+        }
+    }
+    else
+    {
+        TRACE("Texture %p not dirty, nothing to do.\n", texture);
+    }
+
+    /* No longer dirty. */
+    gl_tex->dirty = FALSE;
+
+    if (context) context_release(context);
+}
+
+static void texture2d_sub_resource_add_dirty_region(struct wined3d_resource *sub_resource,
+        const struct wined3d_box *dirty_region)
+{
+    surface_add_dirty_rect(surface_from_resource(sub_resource), dirty_region);
+}
+
+static void texture2d_sub_resource_cleanup(struct wined3d_resource *sub_resource)
+{
+    struct wined3d_surface *surface = surface_from_resource(sub_resource);
+
+    /* Clean out the texture name we gave to the surface so that the
+     * surface doesn't try and release it. */
+    surface_set_texture_name(surface, 0, TRUE);
+    surface_set_texture_name(surface, 0, FALSE);
+    surface_set_texture_target(surface, 0, 0);
+    surface_set_container(surface, NULL);
+    wined3d_surface_decref(surface);
+}
+
+/* Do not call while under the GL lock. */
+static void texture2d_unload(struct wined3d_resource *resource)
+{
+    struct wined3d_texture *texture = wined3d_texture_from_resource(resource);
+    UINT sub_count = texture->level_count * texture->layer_count;
+    UINT i;
+
+    TRACE("texture %p.\n", texture);
+
+    for (i = 0; i < sub_count; ++i)
+    {
+        struct wined3d_resource *sub_resource = texture->sub_resources[i];
+        struct wined3d_surface *surface = surface_from_resource(sub_resource);
+
+        sub_resource->resource_ops->resource_unload(sub_resource);
+        surface_set_texture_name(surface, 0, FALSE); /* Delete RGB name */
+        surface_set_texture_name(surface, 0, TRUE); /* Delete sRGB name */
+    }
+
+    wined3d_texture_unload(texture);
+}
+
+static const struct wined3d_texture_ops texture2d_ops =
+{
+    texture2d_bind,
+    texture2d_preload,
+    texture2d_sub_resource_add_dirty_region,
+    texture2d_sub_resource_cleanup,
+};
+
+static const struct wined3d_resource_ops texture2d_resource_ops =
+{
+    texture2d_unload,
+};
+
+static HRESULT cubetexture_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc,
+        UINT levels, DWORD surface_flags, struct wined3d_device *device, void *parent,
+        const struct wined3d_parent_ops *parent_ops
+#ifdef VBOX_WITH_WDDM
+        , HANDLE *shared_handle
+        , void **pavClientMem
+#endif
+        )
+{
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    struct wined3d_resource_desc surface_desc;
+    unsigned int i, j;
+    HRESULT hr;
+
+    /* TODO: It should only be possible to create textures for formats
+     * that are reported as supported. */
+    if (WINED3DFMT_UNKNOWN >= desc->format)
+    {
+        WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture);
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    if (!gl_info->supported[ARB_TEXTURE_CUBE_MAP] && desc->pool != WINED3D_POOL_SCRATCH)
+    {
+        WARN("(%p) : Tried to create not supported cube texture.\n", texture);
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    /* Calculate levels for mip mapping */
+    if (desc->usage & WINED3DUSAGE_AUTOGENMIPMAP)
+    {
+        if (!gl_info->supported[SGIS_GENERATE_MIPMAP])
+        {
+            WARN("No mipmap generation support, returning D3DERR_INVALIDCALL.\n");
+            return WINED3DERR_INVALIDCALL;
+        }
+
+        if (levels > 1)
+        {
+            WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL.\n");
+            return WINED3DERR_INVALIDCALL;
+        }
+
+        levels = 1;
+    }
+    else if (!levels)
+    {
+        levels = wined3d_log2i(desc->width) + 1;
+        TRACE("Calculated levels = %u.\n", levels);
+    }
+
+    if (!gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
+    {
+        UINT pow2_edge_length = 1;
+        while (pow2_edge_length < desc->width)
+            pow2_edge_length <<= 1;
+
+        if (desc->width != pow2_edge_length)
+        {
+            if (desc->pool == WINED3D_POOL_SCRATCH)
+            {
+                /* SCRATCH textures cannot be used for texturing */
+                WARN("Creating a scratch NPOT cube texture despite lack of HW support.\n");
+            }
+            else
+            {
+                WARN("Attempted to create a NPOT cube texture (edge length %u) without GL support.\n", desc->width);
+                return WINED3DERR_INVALIDCALL;
+            }
+        }
+    }
+
+#ifdef VBOX_WITH_WDDM
+    if (FAILED(hr = wined3d_texture_init(texture, &texture2d_ops, 6, levels,
+            desc, device, parent, parent_ops, &texture2d_resource_ops,
+            shared_handle, pavClientMem)))
+#else
+    if (FAILED(hr = wined3d_texture_init(texture, &texture2d_ops, 6, levels,
+            desc, device, parent, parent_ops, &texture2d_resource_ops)))
+#endif
+    {
+        WARN("Failed to initialize texture, returning %#x\n", hr);
+        return hr;
+    }
+
+        texture->pow2_matrix[0] = 1.0f;
+        texture->pow2_matrix[5] = 1.0f;
+        texture->pow2_matrix[10] = 1.0f;
+        texture->pow2_matrix[15] = 1.0f;
+    texture->target = GL_TEXTURE_CUBE_MAP_ARB;
+
+    /* Generate all the surfaces. */
+    surface_desc = *desc;
+    surface_desc.resource_type = WINED3D_RTYPE_SURFACE;
+    for (i = 0; i < texture->level_count; ++i)
+    {
+        /* Create the 6 faces. */
+        for (j = 0; j < 6; ++j)
+        {
+            static const GLenum cube_targets[6] =
+            {
+                GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
+                GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
+                GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
+                GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
+                GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
+                GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,
+            };
+            UINT idx = j * texture->level_count + i;
+            struct wined3d_surface *surface;
+
+
+#ifdef VBOX_WITH_WDDM
+            if (FAILED(hr = device->device_parent->ops->create_texture_surface(device->device_parent,
+                    parent, &surface_desc, idx, surface_flags, &surface
+                    ,NULL, pavClientMem ? pavClientMem[i * 6 + j] : NULL
+                    )))
+#else
+            if (FAILED(hr = device->device_parent->ops->create_texture_surface(device->device_parent,
+                    parent, &surface_desc, idx, surface_flags, &surface)))
+#endif
+            {
+                FIXME("(%p) Failed to create surface, hr %#x.\n", texture, hr);
+                wined3d_texture_cleanup(texture);
+                return hr;
+            }
+
+            surface_set_container(surface, texture);
+            surface_set_texture_target(surface, cube_targets[j], i);
+            texture->sub_resources[idx] = &surface->resource;
+            TRACE("Created surface level %u @ %p.\n", i, surface);
+        }
+        surface_desc.width = max(1, surface_desc.width >> 1);
+        surface_desc.height = surface_desc.width;
+    }
+
+#ifdef VBOX_WITH_WDDM
+    if (VBOXSHRC_IS_SHARED(texture))
+    {
+        Assert(shared_handle);
+        for (i = 0; i < texture->level_count; ++i)
+        {
+            for (j = 0; j < 6; ++j)
+            {
+                UINT idx = j * texture->level_count + i;
+                VBOXSHRC_COPY_SHAREDATA(surface_from_resource(texture->sub_resources[idx]), texture);
+            }
+        }
+#ifdef DEBUG
+        for (i = 0; i < texture->level_count; ++i)
+        {
+            for (j = 0; j < 6; ++j)
+            {
+                UINT idx = j * texture->level_count + i;
+                Assert(!surface_from_resource(texture->sub_resources[idx])->texture_name);
+            }
+        }
+#endif
+
+        if (!VBOXSHRC_IS_SHARED_OPENED(texture))
+        {
+            for (i = 0; i < texture->level_count; ++i)
+            {
+                for (j = 0; j < 6; ++j)
+                {
+                    UINT idx = j * texture->level_count + i;
+                    struct wined3d_surface *surface = surface_from_resource(texture->sub_resources[idx]);
+                    surface_load_location(surface, SFLAG_INTEXTURE, NULL);
+                }
+            }
+
+            Assert(!(*shared_handle));
+            *shared_handle = VBOXSHRC_GET_SHAREHANDLE(texture);
+        }
+        else
+        {
+            struct wined3d_context *context = NULL;
+            const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+            struct gl_texture *gl_tex = wined3d_texture_get_gl_texture(texture, gl_info, FALSE);
+            texture->texture_rgb.name = (GLuint)VBOXSHRC_GET_SHAREHANDLE(texture);
+            gl_tex->states[WINED3DTEXSTA_ADDRESSU] = WINED3D_TADDRESS_WRAP;
+            gl_tex->states[WINED3DTEXSTA_ADDRESSV] = WINED3D_TADDRESS_WRAP;
+            gl_tex->states[WINED3DTEXSTA_ADDRESSW] = WINED3D_TADDRESS_WRAP;
+            gl_tex->states[WINED3DTEXSTA_BORDERCOLOR] = 0;
+            gl_tex->states[WINED3DTEXSTA_MAGFILTER] = WINED3D_TEXF_LINEAR;
+            gl_tex->states[WINED3DTEXSTA_MINFILTER] = WINED3D_TEXF_POINT; /* GL_NEAREST_MIPMAP_LINEAR */
+            gl_tex->states[WINED3DTEXSTA_MIPFILTER] = WINED3D_TEXF_LINEAR; /* GL_NEAREST_MIPMAP_LINEAR */
+            gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL] = 0;
+            gl_tex->states[WINED3DTEXSTA_MAXANISOTROPY] = 1;
+            if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
+                gl_tex->states[WINED3DTEXSTA_SRGBTEXTURE] = TRUE;
+            else
+                gl_tex->states[WINED3DTEXSTA_SRGBTEXTURE] = FALSE;
+            gl_tex->states[WINED3DTEXSTA_SHADOW] = FALSE;
+            wined3d_texture_set_dirty(texture, TRUE);
+
+            context = context_acquire(device, NULL);
+            pglChromiumParameteriCR(GL_RCUSAGE_TEXTURE_SET_CR, (GLuint)VBOXSHRC_GET_SHAREHANDLE(texture));
+            context_release(context);
+
+            for (i = 0; i < texture->level_count; ++i)
+            {
+                for (j = 0; j < 6; ++j)
+                {
+                    UINT idx = j * texture->level_count + i;
+                    struct wined3d_surface *surface = surface_from_resource(texture->sub_resources[idx]);
+                    surface_setup_location_onopen(surface);
+                    Assert(*shared_handle);
+                    Assert(*shared_handle == VBOXSHRC_GET_SHAREHANDLE(texture));
+                }
+            }
+        }
+#ifdef DEBUG
+        for (i = 0; i < texture->level_count; ++i)
+        {
+            for (j = 0; j < 6; ++j)
+            {
+                UINT idx = j * texture->level_count + i;
+                Assert((GLuint)(*shared_handle) == surface_from_resource(texture->sub_resources[idx])->texture_name);
+            }
+        }
+#endif
+
+#ifdef DEBUG
+        for (i = 0; i < texture->level_count; ++i)
+        {
+            for (j = 0; j < 6; ++j)
+            {
+                UINT idx = j * texture->level_count + i;
+                Assert((GLuint)(*shared_handle) == surface_from_resource(texture->sub_resources[idx])->texture_name);
+            }
+        }
+#endif
+
+        Assert(!device->isInDraw);
+
+        /* flush to ensure the texture is allocated/referenced before it is used/released by another
+         * process opening/creating it */
+        Assert(device->context_count == 1);
+        pVBoxFlushToHost(device->contexts[0]->glCtx);
+    }
+    else
+    {
+        Assert(!shared_handle);
+    }
+#endif
+
+    return WINED3D_OK;
+}
+
+static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc,
+        UINT levels, DWORD surface_flags, struct wined3d_device *device, void *parent,
+        const struct wined3d_parent_ops *parent_ops
+#ifdef VBOX_WITH_WDDM
+        , HANDLE *shared_handle
+        , void **pavClientMem
+#endif
+        )
+{
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    struct wined3d_resource_desc surface_desc;
+    UINT pow2_width, pow2_height;
+    unsigned int i;
+    HRESULT hr;
+
+    /* TODO: It should only be possible to create textures for formats
+     * that are reported as supported. */
+    if (WINED3DFMT_UNKNOWN >= desc->format)
+    {
+        WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture);
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    /* Non-power2 support. */
+    if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
+    {
+        pow2_width = desc->width;
+        pow2_height = desc->height;
+    }
+    else
+    {
+        /* Find the nearest pow2 match. */
+        pow2_width = pow2_height = 1;
+        while (pow2_width < desc->width)
+            pow2_width <<= 1;
+        while (pow2_height < desc->height)
+            pow2_height <<= 1;
+
+        if (pow2_width != desc->width || pow2_height != desc->height)
+        {
+            /* levels == 0 returns an error as well */
+            if (levels != 1)
+            {
+                if (desc->pool == WINED3D_POOL_SCRATCH)
+                {
+                    WARN("Creating a scratch mipmapped NPOT texture despite lack of HW support.\n");
+                }
+                else
+                {
+                    WARN("Attempted to create a mipmapped NPOT texture without unconditional NPOT support.\n");
+                return WINED3DERR_INVALIDCALL;
+            }
+            }
+        }
+    }
+
+    /* Calculate levels for mip mapping. */
+    if (desc->usage & WINED3DUSAGE_AUTOGENMIPMAP)
+    {
+        if (!gl_info->supported[SGIS_GENERATE_MIPMAP])
+        {
+            WARN("No mipmap generation support, returning WINED3DERR_INVALIDCALL.\n");
+            return WINED3DERR_INVALIDCALL;
+        }
+
+        if (levels > 1)
+        {
+            WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning WINED3DERR_INVALIDCALL.\n");
+            return WINED3DERR_INVALIDCALL;
+        }
+
+        levels = 1;
+    }
+    else if (!levels)
+    {
+        levels = wined3d_log2i(max(desc->width, desc->height)) + 1;
+        TRACE("Calculated levels = %u.\n", levels);
+    }
+
+#ifdef VBOX_WITH_WDDM
+    if (FAILED(hr = wined3d_texture_init(texture, &texture2d_ops, 1, levels,
+            desc, device, parent, parent_ops, &texture2d_resource_ops,
+            shared_handle, pavClientMem)))
+#else
+    if (FAILED(hr = wined3d_texture_init(texture, &texture2d_ops, 1, levels,
+            desc, device, parent, parent_ops, &texture2d_resource_ops)))
+#endif
+    {
+        WARN("Failed to initialize texture, returning %#x.\n", hr);
+        return hr;
+    }
+
+    /* Precalculated scaling for 'faked' non power of two texture coords.
+     * Second also don't use ARB_TEXTURE_RECTANGLE in case the surface format is P8 and EXT_PALETTED_TEXTURE
+     * is used in combination with texture uploads (RTL_READTEX). The reason is that EXT_PALETTED_TEXTURE
+     * doesn't work in combination with ARB_TEXTURE_RECTANGLE. */
+    if (gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT]
+            && (desc->width != pow2_width || desc->height != pow2_height))
+    {
+        texture->pow2_matrix[0] = 1.0f;
+        texture->pow2_matrix[5] = 1.0f;
+        texture->pow2_matrix[10] = 1.0f;
+        texture->pow2_matrix[15] = 1.0f;
+        texture->target = GL_TEXTURE_2D;
+        texture->flags |= WINED3D_TEXTURE_COND_NP2;
+        texture->min_mip_lookup = minMipLookup_noFilter;
+    }
+    else if (gl_info->supported[ARB_TEXTURE_RECTANGLE] && (desc->width != pow2_width || desc->height != pow2_height)
+            && !(desc->format == WINED3DFMT_P8_UINT && gl_info->supported[EXT_PALETTED_TEXTURE]
+            && wined3d_settings.rendertargetlock_mode == RTL_READTEX))
+    {
+        texture->pow2_matrix[0] = (float)desc->width;
+        texture->pow2_matrix[5] = (float)desc->height;
+        texture->pow2_matrix[10] = 1.0f;
+        texture->pow2_matrix[15] = 1.0f;
+        texture->target = GL_TEXTURE_RECTANGLE_ARB;
+        texture->flags |= WINED3D_TEXTURE_COND_NP2;
+        texture->flags &= ~WINED3D_TEXTURE_POW2_MAT_IDENT;
+
+        if (texture->resource.format->flags & WINED3DFMT_FLAG_FILTERING)
+            texture->min_mip_lookup = minMipLookup_noMip;
+        else
+            texture->min_mip_lookup = minMipLookup_noFilter;
+    }
+    else
+    {
+        if ((desc->width != pow2_width) || (desc->height != pow2_height))
+        {
+            texture->pow2_matrix[0] = (((float)desc->width) / ((float)pow2_width));
+            texture->pow2_matrix[5] = (((float)desc->height) / ((float)pow2_height));
+            texture->flags &= ~WINED3D_TEXTURE_POW2_MAT_IDENT;
+        }
+        else
+        {
+            texture->pow2_matrix[0] = 1.0f;
+            texture->pow2_matrix[5] = 1.0f;
+        }
+
+        texture->pow2_matrix[10] = 1.0f;
+        texture->pow2_matrix[15] = 1.0f;
+        texture->target = GL_TEXTURE_2D;
+    }
+    TRACE("xf(%f) yf(%f)\n", texture->pow2_matrix[0], texture->pow2_matrix[5]);
+
+    /* Generate all the surfaces. */
+    surface_desc = *desc;
+    surface_desc.resource_type = WINED3D_RTYPE_SURFACE;
+    for (i = 0; i < texture->level_count; ++i)
+    {
+        struct wined3d_surface *surface;
+
+        /* Use the callback to create the texture surface. */
+#ifdef VBOX_WITH_WDDM
+        if (FAILED(hr = device->device_parent->ops->create_texture_surface(device->device_parent,
+                parent, &surface_desc, i, surface_flags, &surface
+                , NULL /* <- we first create a surface in an average "non-shared" fashion and initialize its share properties later (see below)
+                     * this is done this way because the surface does not have its parent (texture) setup properly
+                     * thus we can not initialize texture at this stage */
+                , pavClientMem ? pavClientMem[i] : NULL
+                )))
+#else
+        if (FAILED(hr = device->device_parent->ops->create_texture_surface(device->device_parent,
+                parent, &surface_desc, i, surface_flags, &surface)))
+#endif
+        {
+            FIXME("Failed to create surface %p, hr %#x\n", texture, hr);
+            wined3d_texture_cleanup(texture);
+            return hr;
+        }
+
+        surface_set_container(surface, texture);
+        surface_set_texture_target(surface, texture->target, i);
+        texture->sub_resources[i] = &surface->resource;
+        TRACE("Created surface level %u @ %p.\n", i, surface);
+        /* Calculate the next mipmap level. */
+        surface_desc.width = max(1, surface_desc.width >> 1);
+        surface_desc.height = max(1, surface_desc.height >> 1);
+    }
+
+#ifdef VBOX_WITH_WDDM
+    if (VBOXSHRC_IS_SHARED(texture))
+    {
+        Assert(shared_handle);
+        for (i = 0; i < texture->level_count; ++i)
+        {
+            VBOXSHRC_COPY_SHAREDATA(surface_from_resource(texture->sub_resources[i]), texture);
+        }
+#ifdef DEBUG
+        for (i = 0; i < texture->level_count; ++i)
+        {
+            Assert(!surface_from_resource(texture->sub_resources[i])->texture_name);
+        }
+#endif
+        if (!VBOXSHRC_IS_SHARED_OPENED(texture))
+        {
+            for (i = 0; i < texture->level_count; ++i)
+            {
+                struct wined3d_surface *surface = surface_from_resource(texture->sub_resources[i]);
+                surface_load_location(surface, SFLAG_INTEXTURE, NULL);
+            }
+
+            Assert(!(*shared_handle));
+            *shared_handle = VBOXSHRC_GET_SHAREHANDLE(texture);
+        }
+        else
+        {
+            struct wined3d_context *context = NULL;
+            const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+            struct gl_texture *gl_tex = wined3d_texture_get_gl_texture(texture, gl_info, FALSE);
+            texture->texture_rgb.name = (GLuint)VBOXSHRC_GET_SHAREHANDLE(texture);
+            gl_tex->states[WINED3DTEXSTA_ADDRESSU] = WINED3D_TADDRESS_WRAP;
+            gl_tex->states[WINED3DTEXSTA_ADDRESSV] = WINED3D_TADDRESS_WRAP;
+            gl_tex->states[WINED3DTEXSTA_ADDRESSW] = WINED3D_TADDRESS_WRAP;
+            gl_tex->states[WINED3DTEXSTA_BORDERCOLOR] = 0;
+            gl_tex->states[WINED3DTEXSTA_MAGFILTER] = WINED3D_TEXF_LINEAR;
+            gl_tex->states[WINED3DTEXSTA_MINFILTER] = WINED3D_TEXF_POINT; /* GL_NEAREST_MIPMAP_LINEAR */
+            gl_tex->states[WINED3DTEXSTA_MIPFILTER] = WINED3D_TEXF_LINEAR; /* GL_NEAREST_MIPMAP_LINEAR */
+            gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL] = 0;
+            gl_tex->states[WINED3DTEXSTA_MAXANISOTROPY] = 1;
+            if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
+                gl_tex->states[WINED3DTEXSTA_SRGBTEXTURE] = TRUE;
+            else
+                gl_tex->states[WINED3DTEXSTA_SRGBTEXTURE] = FALSE;
+            gl_tex->states[WINED3DTEXSTA_SHADOW] = FALSE;
+            wined3d_texture_set_dirty(texture, TRUE);
+            if (texture->flags & WINED3D_TEXTURE_COND_NP2)
+            {
+                gl_tex->states[WINED3DTEXSTA_ADDRESSU] = WINED3D_TADDRESS_CLAMP;
+                gl_tex->states[WINED3DTEXSTA_ADDRESSV] = WINED3D_TADDRESS_CLAMP;
+                gl_tex->states[WINED3DTEXSTA_MAGFILTER] = WINED3D_TEXF_POINT;
+                gl_tex->states[WINED3DTEXSTA_MINFILTER] = WINED3D_TEXF_POINT;
+                gl_tex->states[WINED3DTEXSTA_MIPFILTER] = WINED3D_TEXF_NONE;
+            }
+
+            context = context_acquire(device, NULL);
+            pglChromiumParameteriCR(GL_RCUSAGE_TEXTURE_SET_CR, (GLuint)VBOXSHRC_GET_SHAREHANDLE(texture));
+            context_release(context);
+
+            for (i = 0; i < texture->level_count; ++i)
+            {
+                struct wined3d_surface *surface = surface_from_resource(texture->sub_resources[i]);
+                surface_setup_location_onopen(surface);
+                Assert(*shared_handle);
+                Assert(*shared_handle == VBOXSHRC_GET_SHAREHANDLE(texture));
+            }
+        }
+
+#ifdef DEBUG
+        for (i = 0; i < texture->level_count; ++i)
+        {
+            Assert((GLuint)(*shared_handle) == surface_from_resource(texture->sub_resources[i])->texture_name);
+        }
+#endif
+
+        Assert(!device->isInDraw);
+
+        /* flush to ensure the texture is allocated/referenced before it is used/released by another
+         * process opening/creating it */
+        Assert(device->context_count == 1);
+        pVBoxFlushToHost(device->contexts[0]->glCtx);
+    }
+    else
+    {
+        Assert(!shared_handle);
+    }
+#endif
+
+    return WINED3D_OK;
+}
+
+/* Context activation is done by the caller. */
+static HRESULT texture3d_bind(struct wined3d_texture *texture,
+        struct wined3d_context *context, BOOL srgb)
+{
+    BOOL dummy;
+
+    TRACE("texture %p, context %p, srgb %#x.\n", texture, context, srgb);
+
+    return wined3d_texture_bind(texture, context, srgb, &dummy);
+}
+
+/* Do not call while under the GL lock. */
+static void texture3d_preload(struct wined3d_texture *texture, enum WINED3DSRGB srgb)
+{
+    struct wined3d_device *device = texture->resource.device;
+    struct wined3d_context *context;
+    BOOL srgb_was_toggled = FALSE;
+    unsigned int i;
+
+    TRACE("texture %p, srgb %#x.\n", texture, srgb);
+
+    /* TODO: Use already acquired context when possible. */
+    context = context_acquire(device, NULL);
+    if (texture->resource.bind_count > 0)
+    {
+        BOOL texture_srgb = texture->flags & WINED3D_TEXTURE_IS_SRGB;
+        BOOL sampler_srgb = texture_srgb_mode(texture, srgb);
+        srgb_was_toggled = !texture_srgb != !sampler_srgb;
+
+        if (srgb_was_toggled)
+        {
+            if (sampler_srgb)
+                texture->flags |= WINED3D_TEXTURE_IS_SRGB;
+            else
+                texture->flags &= ~WINED3D_TEXTURE_IS_SRGB;
+        }
+    }
+
+    /* If the texture is marked dirty or the sRGB sampler setting has changed
+     * since the last load then reload the volumes. */
+    if (texture->texture_rgb.dirty)
+    {
+        for (i = 0; i < texture->level_count; ++i)
+        {
+            volume_load(volume_from_resource(texture->sub_resources[i]), context, i,
+                    texture->flags & WINED3D_TEXTURE_IS_SRGB);
+        }
+    }
+    else if (srgb_was_toggled)
+    {
+        for (i = 0; i < texture->level_count; ++i)
+        {
+            struct wined3d_volume *volume = volume_from_resource(texture->sub_resources[i]);
+            volume_add_dirty_box(volume, NULL);
+            volume_load(volume, context, i, texture->flags & WINED3D_TEXTURE_IS_SRGB);
+        }
+    }
+    else
+    {
+        TRACE("Texture %p not dirty, nothing to do.\n", texture);
+    }
+
+    context_release(context);
+
+    /* No longer dirty */
+    texture->texture_rgb.dirty = FALSE;
+}
+
+static void texture3d_sub_resource_add_dirty_region(struct wined3d_resource *sub_resource,
+        const struct wined3d_box *dirty_region)
+{
+    volume_add_dirty_box(volume_from_resource(sub_resource), dirty_region);
+}
+
+static void texture3d_sub_resource_cleanup(struct wined3d_resource *sub_resource)
+{
+    struct wined3d_volume *volume = volume_from_resource(sub_resource);
+
+    /* Cleanup the container. */
+    volume_set_container(volume, NULL);
+    wined3d_volume_decref(volume);
+}
+
+/* Do not call while under the GL lock. */
+static void texture3d_unload(struct wined3d_resource *resource)
+{
+    struct wined3d_texture *texture = wined3d_texture_from_resource(resource);
+    UINT i;
+
+    TRACE("texture %p.\n", texture);
+
+    for (i = 0; i < texture->level_count; ++i)
+    {
+        struct wined3d_resource *sub_resource = texture->sub_resources[i];
+        sub_resource->resource_ops->resource_unload(sub_resource);
+    }
+
+    wined3d_texture_unload(texture);
+}
+
+static const struct wined3d_texture_ops texture3d_ops =
+{
+    texture3d_bind,
+    texture3d_preload,
+    texture3d_sub_resource_add_dirty_region,
+    texture3d_sub_resource_cleanup,
+};
+
+static const struct wined3d_resource_ops texture3d_resource_ops =
+{
+    texture3d_unload,
+};
+
+
+static HRESULT volumetexture_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc,
+        UINT levels, struct wined3d_device *device, void *parent, const struct wined3d_parent_ops *parent_ops
+#ifdef VBOX_WITH_WDDM
+        , HANDLE *shared_handle
+        , void **pavClientMem
+#endif
+        )
+{
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    UINT tmp_w, tmp_h, tmp_d;
+    unsigned int i;
+    HRESULT hr;
+
+#ifdef VBOX_WITH_WDDM
+    if (shared_handle)
+    {
+        ERR("shared handle support for volume textures not impemented yet, ignoring!");
+    }
+#endif
+
+    /* TODO: It should only be possible to create textures for formats
+     * that are reported as supported. */
+    if (WINED3DFMT_UNKNOWN >= desc->format)
+    {
+        WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture);
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    if (!gl_info->supported[EXT_TEXTURE3D])
+    {
+        WARN("(%p) : Texture cannot be created - no volume texture support.\n", texture);
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    /* Calculate levels for mip mapping. */
+    if (desc->usage & WINED3DUSAGE_AUTOGENMIPMAP)
+    {
+        if (!gl_info->supported[SGIS_GENERATE_MIPMAP])
+        {
+            WARN("No mipmap generation support, returning D3DERR_INVALIDCALL.\n");
+            return WINED3DERR_INVALIDCALL;
+        }
+
+        if (levels > 1)
+        {
+            WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL.\n");
+            return WINED3DERR_INVALIDCALL;
+        }
+
+        levels = 1;
+    }
+    else if (!levels)
+    {
+        levels = wined3d_log2i(max(max(desc->width, desc->height), desc->depth)) + 1;
+        TRACE("Calculated levels = %u.\n", levels);
+    }
+
+    if (!gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
+    {
+        UINT pow2_w, pow2_h, pow2_d;
+        pow2_w = 1;
+        while (pow2_w < desc->width)
+            pow2_w <<= 1;
+        pow2_h = 1;
+        while (pow2_h < desc->height)
+            pow2_h <<= 1;
+        pow2_d = 1;
+        while (pow2_d < desc->depth)
+            pow2_d <<= 1;
+
+        if (pow2_w != desc->width || pow2_h != desc->height || pow2_d != desc->depth)
+        {
+            if (desc->pool == WINED3D_POOL_SCRATCH)
+            {
+                WARN("Creating a scratch NPOT volume texture despite lack of HW support.\n");
+            }
+            else
+            {
+                WARN("Attempted to create a NPOT volume texture (%u, %u, %u) without GL support.\n",
+                        desc->width, desc->height, desc->depth);
+                return WINED3DERR_INVALIDCALL;
+            }
+        }
+    }
+
+#ifdef VBOX_WITH_WDDM
+    if (FAILED(hr = wined3d_texture_init(texture, &texture3d_ops, 1, levels,
+            desc, device, parent, parent_ops, &texture3d_resource_ops
+            , shared_handle, pavClientMem)))
+#else
+    if (FAILED(hr = wined3d_texture_init(texture, &texture3d_ops, 1, levels,
+            desc, device, parent, parent_ops, &texture3d_resource_ops)))
+#endif
+    {
+        WARN("Failed to initialize texture, returning %#x.\n", hr);
+        return hr;
+    }
+
+    texture->pow2_matrix[0] = 1.0f;
+    texture->pow2_matrix[5] = 1.0f;
+    texture->pow2_matrix[10] = 1.0f;
+    texture->pow2_matrix[15] = 1.0f;
+    texture->target = GL_TEXTURE_3D;
+
+    /* Generate all the surfaces. */
+    tmp_w = desc->width;
+    tmp_h = desc->height;
+    tmp_d = desc->depth;
+
+    for (i = 0; i < texture->level_count; ++i)
+    {
+        struct wined3d_volume *volume;
+
+        /* Create the volume. */
+        hr = device->device_parent->ops->create_volume(device->device_parent, parent,
+                tmp_w, tmp_h, tmp_d, desc->format, desc->pool, desc->usage, &volume
+#ifdef VBOX_WITH_WDDM
+                , shared_handle
+                , pavClientMem
+#endif
+                );
+        if (FAILED(hr))
+        {
+            ERR("Creating a volume for the volume texture failed, hr %#x.\n", hr);
+            wined3d_texture_cleanup(texture);
+            return hr;
+        }
+
+        /* Set its container to this texture. */
+        volume_set_container(volume, texture);
+        texture->sub_resources[i] = &volume->resource;
+
+        /* Calculate the next mipmap level. */
+        tmp_w = max(1, tmp_w >> 1);
+        tmp_h = max(1, tmp_h >> 1);
+        tmp_d = max(1, tmp_d >> 1);
+    }
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_texture_create_2d(struct wined3d_device *device, const struct wined3d_resource_desc *desc,
+        UINT level_count, DWORD surface_flags, void *parent, const struct wined3d_parent_ops *parent_ops,
+        struct wined3d_texture **texture
+#ifdef VBOX_WITH_WDDM
+        , HANDLE *shared_handle
+        , void **pavClientMem
+#endif
+        )
+{
+    struct wined3d_texture *object;
+    HRESULT hr;
+
+    TRACE("device %p, desc %p, level_count %u, surface_flags %#x, parent %p, parent_ops %p, texture %p.\n",
+            device, desc, level_count, surface_flags, parent, parent_ops, texture);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+    {
+        *texture = NULL;
+        return WINED3DERR_OUTOFVIDEOMEMORY;
+    }
+
+#ifdef VBOX_WITH_WDDM
+    if (FAILED(hr = texture_init(object, desc, level_count, surface_flags, device, parent, parent_ops
+            , shared_handle, pavClientMem)))
+#else
+    if (FAILED(hr = texture_init(object, desc, level_count, surface_flags, device, parent, parent_ops)))
+#endif
+    {
+        WARN("Failed to initialize texture, returning %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        *texture = NULL;
+        return hr;
+    }
+
+    TRACE("Created texture %p.\n", object);
+    *texture = object;
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_texture_create_3d(struct wined3d_device *device, const struct wined3d_resource_desc *desc,
+        UINT level_count, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture
+#ifdef VBOX_WITH_WDDM
+        , HANDLE *shared_handle
+        , void **pavClientMem
+#endif
+		)
+{
+    struct wined3d_texture *object;
+    HRESULT hr;
+
+    TRACE("device %p, desc %p, level_count %u, parent %p, parent_ops %p, texture %p.\n",
+            device, desc, level_count, parent, parent_ops, texture);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+    {
+        *texture = NULL;
+        return WINED3DERR_OUTOFVIDEOMEMORY;
+    }
+
+#ifdef VBOX_WITH_WDDM
+    if (FAILED(hr = volumetexture_init(object, desc, level_count, device, parent, parent_ops
+            , shared_handle, pavClientMem)))
+#else
+    if (FAILED(hr = volumetexture_init(object, desc, level_count, device, parent, parent_ops)))
+#endif
+    {
+        WARN("Failed to initialize volumetexture, returning %#x\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        *texture = NULL;
+        return hr;
+    }
+
+    TRACE("Created texture %p.\n", object);
+    *texture = object;
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_texture_create_cube(struct wined3d_device *device, const struct wined3d_resource_desc *desc,
+        UINT level_count, DWORD surface_flags, void *parent, const struct wined3d_parent_ops *parent_ops,
+        struct wined3d_texture **texture
+#ifdef VBOX_WITH_WDDM
+        , HANDLE *shared_handle
+        , void **pavClientMem
+#endif
+        )
+{
+    struct wined3d_texture *object;
+    HRESULT hr;
+
+    TRACE("device %p, desc %p, level_count %u, surface_flags %#x, parent %p, parent_ops %p, texture %p.\n",
+            device, desc, level_count, surface_flags, parent, parent_ops, texture);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+    {
+        *texture = NULL;
+        return WINED3DERR_OUTOFVIDEOMEMORY;
+    }
+
+#ifdef VBOX_WITH_WDDM
+    if (FAILED(hr = cubetexture_init(object, desc, level_count, surface_flags, device, parent, parent_ops
+            , shared_handle, pavClientMem)))
+#else
+    if (FAILED(hr = cubetexture_init(object, desc, level_count, surface_flags, device, parent, parent_ops)))
+#endif
+    {
+        WARN("Failed to initialize cubetexture, returning %#x\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        *texture = NULL;
+        return hr;
+    }
+
+    TRACE("Created texture %p.\n", object);
+    *texture = object;
+
+    return WINED3D_OK;
+}
+
+#ifdef VBOX_WITH_WDDM
+HRESULT CDECL wined3d_device_blt_voltex(struct wined3d_device *device, struct wined3d_texture *src, struct wined3d_texture *dst,
+        const struct wined3d_box *pSrcBoxArg, const VBOXPOINT3D *pDstPoin3D)
+{
+    unsigned int level_count, i;
+    struct wined3d_volume *src_volume;
+    struct wined3d_volume *dst_volume;
+    HRESULT hr = S_OK;
+
+    level_count = src->level_count;
+    if (dst->level_count != level_count)
+    {
+        ERR("Source and destination have different level counts, returning WINED3DERR_INVALIDCALL.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    for (i = 0; i < level_count; ++i)
+    {
+        struct wined3d_box SrcBox, *pSrcBox;
+        VBOXPOINT3D DstPoint, *pDstPoint;
+
+        if (pSrcBoxArg)
+        {
+            vboxWddmBoxDivided((VBOXBOX3D*)&SrcBox, (VBOXBOX3D*)pSrcBoxArg, i + 1, true);
+            pSrcBox = &SrcBox;
+        }
+        else
+        {
+            pSrcBox = NULL;
+        }
+
+        if (pDstPoin3D)
+        {
+            vboxWddmPoint3DDivided(&DstPoint, pDstPoin3D, i + 1, true);
+            pDstPoint = &DstPoint;
+        }
+        else
+        {
+            pDstPoint = NULL;
+        }
+
+        src_volume = volume_from_resource(src->sub_resources[i]);
+        dst_volume = volume_from_resource(dst->sub_resources[i]);
+        hr = wined3d_device_blt_vol(device, src_volume, dst_volume, pSrcBox, pDstPoint);
+        if (FAILED(hr))
+        {
+            ERR("wined3d_device_blt_vol failed, hr %#x.\n", hr);
+            return hr;
+        }
+    }
+
+    return hr;
+}
+#endif
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/utils.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/utils.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/utils.c	(revision 46521)
@@ -0,0 +1,3709 @@
+/*
+ * Utility functions for the WineD3D Library
+ *
+ * Copyright 2002-2004 Jason Edmeades
+ * Copyright 2003-2004 Raphael Junqueira
+ * Copyright 2004 Christian Costa
+ * Copyright 2005 Oliver Stieber
+ * Copyright 2006-2008 Henri Verbeet
+ * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
+ * Copyright 2009-2010 Henri Verbeet for CodeWeavers
+ *
+ * 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 "wined3d_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d);
+
+struct wined3d_format_channels
+{
+    enum wined3d_format_id id;
+    DWORD red_size, green_size, blue_size, alpha_size;
+    DWORD red_offset, green_offset, blue_offset, alpha_offset;
+    UINT bpp;
+    BYTE depth_size, stencil_size;
+};
+
+static const struct wined3d_format_channels formats[] =
+{
+    /*                                          size            offset
+     *  format id                           r   g   b   a    r   g   b   a    bpp depth stencil */
+    {WINED3DFMT_UNKNOWN,                    0,  0,  0,  0,   0,  0,  0,  0,    0,   0,     0},
+    /* FourCC formats */
+    {WINED3DFMT_UYVY,                       0,  0,  0,  0,   0,  0,  0,  0,    2,   0,     0},
+    {WINED3DFMT_YUY2,                       0,  0,  0,  0,   0,  0,  0,  0,    2,   0,     0},
+    {WINED3DFMT_YV12,                       0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
+    {WINED3DFMT_DXT1,                       0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
+    {WINED3DFMT_DXT2,                       0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
+    {WINED3DFMT_DXT3,                       0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
+    {WINED3DFMT_DXT4,                       0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
+    {WINED3DFMT_DXT5,                       0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
+    {WINED3DFMT_MULTI2_ARGB8,               0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
+    {WINED3DFMT_G8R8_G8B8,                  0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
+    {WINED3DFMT_R8G8_B8G8,                  0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
+    /* IEEE formats */
+    {WINED3DFMT_R32_FLOAT,                 32,  0,  0,  0,   0,  0,  0,  0,    4,   0,     0},
+    {WINED3DFMT_R32G32_FLOAT,              32, 32,  0,  0,   0, 32,  0,  0,    8,   0,     0},
+    {WINED3DFMT_R32G32B32_FLOAT,           32, 32, 32,  0,   0, 32, 64,  0,   12,   0,     0},
+    {WINED3DFMT_R32G32B32A32_FLOAT,        32, 32, 32, 32,   0, 32, 64, 96,   16,   0,     0},
+    /* Hmm? */
+    {WINED3DFMT_R8G8_SNORM_Cx,              0,  0,  0,  0,   0,  0,  0,  0,    2,   0,     0},
+    /* Float */
+    {WINED3DFMT_R16_FLOAT,                 16,  0,  0,  0,   0,  0,  0,  0,    2,   0,     0},
+    {WINED3DFMT_R16G16_FLOAT,              16, 16,  0,  0,   0, 16,  0,  0,    4,   0,     0},
+    {WINED3DFMT_R16G16_SINT,               16, 16,  0,  0,   0, 16,  0,  0,    4,   0,     0},
+    {WINED3DFMT_R16G16B16A16_FLOAT,        16, 16, 16, 16,   0, 16, 32, 48,    8,   0,     0},
+    {WINED3DFMT_R16G16B16A16_SINT,         16, 16, 16, 16,   0, 16, 32, 48,    8,   0,     0},
+    /* Palettized formats */
+    {WINED3DFMT_P8_UINT_A8_UNORM,           0,  0,  0,  8,   0,  0,  0,  8,    2,   0,     0},
+    {WINED3DFMT_P8_UINT,                    0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
+    /* Standard ARGB formats. */
+    {WINED3DFMT_B8G8R8_UNORM,               8,  8,  8,  0,  16,  8,  0,  0,    3,   0,     0},
+    {WINED3DFMT_B8G8R8A8_UNORM,             8,  8,  8,  8,  16,  8,  0, 24,    4,   0,     0},
+    {WINED3DFMT_B8G8R8X8_UNORM,             8,  8,  8,  0,  16,  8,  0,  0,    4,   0,     0},
+    {WINED3DFMT_B5G6R5_UNORM,               5,  6,  5,  0,  11,  5,  0,  0,    2,   0,     0},
+    {WINED3DFMT_B5G5R5X1_UNORM,             5,  5,  5,  0,  10,  5,  0,  0,    2,   0,     0},
+    {WINED3DFMT_B5G5R5A1_UNORM,             5,  5,  5,  1,  10,  5,  0, 15,    2,   0,     0},
+    {WINED3DFMT_B4G4R4A4_UNORM,             4,  4,  4,  4,   8,  4,  0, 12,    2,   0,     0},
+    {WINED3DFMT_B2G3R3_UNORM,               3,  3,  2,  0,   5,  2,  0,  0,    1,   0,     0},
+    {WINED3DFMT_A8_UNORM,                   0,  0,  0,  8,   0,  0,  0,  0,    1,   0,     0},
+    {WINED3DFMT_B2G3R3A8_UNORM,             3,  3,  2,  8,   5,  2,  0,  8,    2,   0,     0},
+    {WINED3DFMT_B4G4R4X4_UNORM,             4,  4,  4,  0,   8,  4,  0,  0,    2,   0,     0},
+    {WINED3DFMT_R10G10B10A2_UNORM,         10, 10, 10,  2,   0, 10, 20, 30,    4,   0,     0},
+    {WINED3DFMT_R10G10B10A2_UINT,          10, 10, 10,  2,   0, 10, 20, 30,    4,   0,     0},
+    {WINED3DFMT_R10G10B10A2_SNORM,         10, 10, 10,  2,   0, 10, 20, 30,    4,   0,     0},
+    {WINED3DFMT_R8G8B8A8_UNORM,             8,  8,  8,  8,   0,  8, 16, 24,    4,   0,     0},
+    {WINED3DFMT_R8G8B8A8_UINT,              8,  8,  8,  8,   0,  8, 16, 24,    4,   0,     0},
+    {WINED3DFMT_R8G8B8X8_UNORM,             8,  8,  8,  0,   0,  8, 16,  0,    4,   0,     0},
+    {WINED3DFMT_R16G16_UNORM,              16, 16,  0,  0,   0, 16,  0,  0,    4,   0,     0},
+    {WINED3DFMT_B10G10R10A2_UNORM,         10, 10, 10,  2,  20, 10,  0, 30,    4,   0,     0},
+    {WINED3DFMT_R16G16B16A16_UNORM,        16, 16, 16, 16,   0, 16, 32, 48,    8,   0,     0},
+    /* Luminance */
+    {WINED3DFMT_L8_UNORM,                   0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
+    {WINED3DFMT_L8A8_UNORM,                 0,  0,  0,  8,   0,  0,  0,  8,    2,   0,     0},
+    {WINED3DFMT_L4A4_UNORM,                 0,  0,  0,  4,   0,  0,  0,  4,    1,   0,     0},
+    {WINED3DFMT_L16_UNORM,                  0,  0,  0,  0,   0,  0,  0,  0,    2,   0,     0},
+    /* Bump mapping stuff */
+    {WINED3DFMT_R8G8_SNORM,                 8,  8,  0,  0,   0,  8,  0,  0,    2,   0,     0},
+    {WINED3DFMT_R5G5_SNORM_L6_UNORM,        5,  5,  0,  0,   0,  5,  0,  0,    2,   0,     0},
+    {WINED3DFMT_R8G8_SNORM_L8X8_UNORM,      8,  8,  0,  0,   0,  8,  0,  0,    4,   0,     0},
+    {WINED3DFMT_R8G8B8A8_SNORM,             8,  8,  8,  8,   0,  8, 16, 24,    4,   0,     0},
+    {WINED3DFMT_R16G16_SNORM,              16, 16,  0,  0,   0, 16,  0,  0,    4,   0,     0},
+    {WINED3DFMT_R10G11B11_SNORM,           10, 11, 11,  0,   0, 10, 21,  0,    4,   0,     0},
+    {WINED3DFMT_R10G10B10_SNORM_A2_UNORM,  10, 10, 10,  2,   0, 10, 20, 30,    4,   0,     0},
+    /* Depth stencil formats */
+    {WINED3DFMT_D16_LOCKABLE,               0,  0,  0,  0,   0,  0,  0,  0,    2,  16,     0},
+    {WINED3DFMT_D32_UNORM,                  0,  0,  0,  0,   0,  0,  0,  0,    4,  32,     0},
+    {WINED3DFMT_S1_UINT_D15_UNORM,          0,  0,  0,  0,   0,  0,  0,  0,    2,  15,     1},
+    {WINED3DFMT_D24_UNORM_S8_UINT,          0,  0,  0,  0,   0,  0,  0,  0,    4,  24,     8},
+    {WINED3DFMT_X8D24_UNORM,                0,  0,  0,  0,   0,  0,  0,  0,    4,  24,     0},
+    {WINED3DFMT_S4X4_UINT_D24_UNORM,        0,  0,  0,  0,   0,  0,  0,  0,    4,  24,     4},
+    {WINED3DFMT_D16_UNORM,                  0,  0,  0,  0,   0,  0,  0,  0,    2,  16,     0},
+    {WINED3DFMT_D32_FLOAT,                  0,  0,  0,  0,   0,  0,  0,  0,    4,  32,     0},
+    {WINED3DFMT_S8_UINT_D24_FLOAT,          0,  0,  0,  0,   0,  0,  0,  0,    4,  24,     8},
+    {WINED3DFMT_VERTEXDATA,                 0,  0,  0,  0,   0,  0,  0,  0,    0,   0,     0},
+    {WINED3DFMT_R16_UINT,                  16,  0,  0,  0,   0,  0,  0,  0,    2,   0,     0},
+    {WINED3DFMT_R32_UINT,                  32,  0,  0,  0,   0,  0,  0,  0,    4,   0,     0},
+    {WINED3DFMT_R32G32_UINT,               32, 32,  0,  0,   0, 32,  0,  0,    8,   0,     0},
+    {WINED3DFMT_R32G32B32_UINT,            32, 32, 32,  0,   0, 32, 64,  0,   12,   0,     0},
+    {WINED3DFMT_R32G32B32A32_UINT,         32, 32, 32, 32,   0, 32, 64, 96,   16,   0,     0},
+    {WINED3DFMT_R16G16B16A16_SNORM,        16, 16, 16, 16,   0, 16, 32, 48,    8,   0,     0},
+    /* Vendor-specific formats */
+    {WINED3DFMT_ATI2N,                      0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
+    {WINED3DFMT_NVDB,                       0,  0,  0,  0,   0,  0,  0,  0,    0,   0,     0},
+    {WINED3DFMT_INST,                       0,  0,  0,  0,   0,  0,  0,  0,    0,   0,     0},
+    {WINED3DFMT_INTZ,                       0,  0,  0,  0,   0,  0,  0,  0,    4,  24,     8},
+    {WINED3DFMT_RESZ,                       0,  0,  0,  0,   0,  0,  0,  0,    0,   0,     0},
+    {WINED3DFMT_NVHU,                       0,  0,  0,  0,   0,  0,  0,  0,    2,   0,     0},
+    {WINED3DFMT_NVHS,                       0,  0,  0,  0,   0,  0,  0,  0,    2,   0,     0},
+    {WINED3DFMT_NULL,                       8,  8,  8,  8,   0,  8, 16, 24,    4,   0,     0},
+    /* Unsure about them, could not find a Windows driver that supports them */
+    {WINED3DFMT_R16,                       16,  0,  0,  0,   0,  0,  0,  0,    2,   0,     0},
+    {WINED3DFMT_AL16,                       0,  0,  0, 16,   0,  0,  0, 16,    4,   0,     0},
+    /* Typeless */
+    {WINED3DFMT_R8_TYPELESS,                8,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
+    {WINED3DFMT_R8G8_TYPELESS,              8,  8,  0,  0,   0,  8,  0,  0,    2,   0,     0},
+    {WINED3DFMT_R8G8B8A8_TYPELESS,          8,  8,  8,  8,   0,  8, 16, 24,    4,   0,     0},
+    {WINED3DFMT_R16_TYPELESS,              16,  0,  0,  0,   0,  0,  0,  0,    2,   0,     0},
+    {WINED3DFMT_R16G16_TYPELESS,           16, 16,  0,  0,   0, 16,  0,  0,    4,   0,     0},
+    {WINED3DFMT_R16G16B16A16_TYPELESS,     16, 16, 16, 16,   0, 16, 32, 48,    8,   0,     0},
+    {WINED3DFMT_R32_TYPELESS,              32,  0,  0,  0,   0,  0,  0,  0,    4,   0,     0},
+    {WINED3DFMT_R32G32_TYPELESS,           32, 32,  0,  0,   0, 32,  0,  0,    8,   0,     0},
+    {WINED3DFMT_R32G32B32_TYPELESS,        32, 32, 32,  0,   0, 32, 64,  0,   12,   0,     0},
+    {WINED3DFMT_R32G32B32A32_TYPELESS,     32, 32, 32, 32,   0, 32, 64, 96,   16,   0,     0},
+};
+
+struct wined3d_format_base_flags
+{
+    enum wined3d_format_id id;
+    DWORD flags;
+};
+
+/* The ATI2N format behaves like an uncompressed format in LockRect(), but
+ * still needs to use the correct block based calculation for e.g. the
+ * resource size. */
+static const struct wined3d_format_base_flags format_base_flags[] =
+{
+    {WINED3DFMT_P8_UINT,            WINED3DFMT_FLAG_GETDC},
+    {WINED3DFMT_B8G8R8_UNORM,       WINED3DFMT_FLAG_GETDC},
+    {WINED3DFMT_B8G8R8A8_UNORM,     WINED3DFMT_FLAG_GETDC},
+    {WINED3DFMT_B8G8R8X8_UNORM,     WINED3DFMT_FLAG_GETDC},
+    {WINED3DFMT_B5G6R5_UNORM,       WINED3DFMT_FLAG_GETDC},
+    {WINED3DFMT_B5G5R5X1_UNORM,     WINED3DFMT_FLAG_GETDC},
+    {WINED3DFMT_B5G5R5A1_UNORM,     WINED3DFMT_FLAG_GETDC},
+    {WINED3DFMT_B4G4R4A4_UNORM,     WINED3DFMT_FLAG_GETDC},
+    {WINED3DFMT_B4G4R4X4_UNORM,     WINED3DFMT_FLAG_GETDC},
+    {WINED3DFMT_R8G8B8A8_UNORM,     WINED3DFMT_FLAG_GETDC},
+    {WINED3DFMT_R8G8B8X8_UNORM,     WINED3DFMT_FLAG_GETDC},
+    {WINED3DFMT_ATI2N,              WINED3DFMT_FLAG_BROKEN_PITCH},
+    {WINED3DFMT_R32_FLOAT,          WINED3DFMT_FLAG_FLOAT},
+    {WINED3DFMT_R32G32_FLOAT,       WINED3DFMT_FLAG_FLOAT},
+    {WINED3DFMT_R32G32B32_FLOAT,    WINED3DFMT_FLAG_FLOAT},
+    {WINED3DFMT_R32G32B32A32_FLOAT, WINED3DFMT_FLAG_FLOAT},
+    {WINED3DFMT_R16_FLOAT,          WINED3DFMT_FLAG_FLOAT},
+    {WINED3DFMT_R16G16_FLOAT,       WINED3DFMT_FLAG_FLOAT},
+    {WINED3DFMT_R16G16B16A16_FLOAT, WINED3DFMT_FLAG_FLOAT},
+    {WINED3DFMT_D32_FLOAT,          WINED3DFMT_FLAG_FLOAT},
+    {WINED3DFMT_S8_UINT_D24_FLOAT,  WINED3DFMT_FLAG_FLOAT},
+};
+
+struct wined3d_format_block_info
+{
+    enum wined3d_format_id id;
+    UINT block_width;
+    UINT block_height;
+    UINT block_byte_count;
+};
+
+static const struct wined3d_format_block_info format_block_info[] =
+{
+    {WINED3DFMT_DXT1,   4,  4,  8},
+    {WINED3DFMT_DXT2,   4,  4,  16},
+    {WINED3DFMT_DXT3,   4,  4,  16},
+    {WINED3DFMT_DXT4,   4,  4,  16},
+    {WINED3DFMT_DXT5,   4,  4,  16},
+    {WINED3DFMT_ATI2N,  4,  4,  16},
+    {WINED3DFMT_YUY2,   2,  1,  4},
+    {WINED3DFMT_UYVY,   2,  1,  4},
+};
+
+struct wined3d_format_vertex_info
+{
+    enum wined3d_format_id id;
+    enum wined3d_ffp_emit_idx emit_idx;
+    GLint component_count;
+    GLenum gl_vtx_type;
+    GLint gl_vtx_format;
+    GLboolean gl_normalized;
+    unsigned int component_size;
+};
+
+static const struct wined3d_format_vertex_info format_vertex_info[] =
+{
+    {WINED3DFMT_R32_FLOAT,          WINED3D_FFP_EMIT_FLOAT1,    1, GL_FLOAT,          1, GL_FALSE, sizeof(float)},
+    {WINED3DFMT_R32G32_FLOAT,       WINED3D_FFP_EMIT_FLOAT2,    2, GL_FLOAT,          2, GL_FALSE, sizeof(float)},
+    {WINED3DFMT_R32G32B32_FLOAT,    WINED3D_FFP_EMIT_FLOAT3,    3, GL_FLOAT,          3, GL_FALSE, sizeof(float)},
+    {WINED3DFMT_R32G32B32A32_FLOAT, WINED3D_FFP_EMIT_FLOAT4,    4, GL_FLOAT,          4, GL_FALSE, sizeof(float)},
+    {WINED3DFMT_B8G8R8A8_UNORM,     WINED3D_FFP_EMIT_D3DCOLOR,  4, GL_UNSIGNED_BYTE,  4, GL_TRUE,  sizeof(BYTE)},
+    {WINED3DFMT_R8G8B8A8_UINT,      WINED3D_FFP_EMIT_UBYTE4,    4, GL_UNSIGNED_BYTE,  4, GL_FALSE, sizeof(BYTE)},
+    {WINED3DFMT_R16G16_SINT,        WINED3D_FFP_EMIT_SHORT2,    2, GL_SHORT,          2, GL_FALSE, sizeof(short int)},
+    {WINED3DFMT_R16G16B16A16_SINT,  WINED3D_FFP_EMIT_SHORT4,    4, GL_SHORT,          4, GL_FALSE, sizeof(short int)},
+    {WINED3DFMT_R8G8B8A8_UNORM,     WINED3D_FFP_EMIT_UBYTE4N,   4, GL_UNSIGNED_BYTE,  4, GL_TRUE,  sizeof(BYTE)},
+    {WINED3DFMT_R16G16_SNORM,       WINED3D_FFP_EMIT_SHORT2N,   2, GL_SHORT,          2, GL_TRUE,  sizeof(short int)},
+    {WINED3DFMT_R16G16B16A16_SNORM, WINED3D_FFP_EMIT_SHORT4N,   4, GL_SHORT,          4, GL_TRUE,  sizeof(short int)},
+    {WINED3DFMT_R16G16_UNORM,       WINED3D_FFP_EMIT_USHORT2N,  2, GL_UNSIGNED_SHORT, 2, GL_TRUE,  sizeof(short int)},
+    {WINED3DFMT_R16G16B16A16_UNORM, WINED3D_FFP_EMIT_USHORT4N,  4, GL_UNSIGNED_SHORT, 4, GL_TRUE,  sizeof(short int)},
+    {WINED3DFMT_R10G10B10A2_UINT,   WINED3D_FFP_EMIT_UDEC3,     3, GL_UNSIGNED_SHORT, 3, GL_FALSE, sizeof(short int)},
+    {WINED3DFMT_R10G10B10A2_SNORM,  WINED3D_FFP_EMIT_DEC3N,     3, GL_SHORT,          3, GL_TRUE,  sizeof(short int)},
+    {WINED3DFMT_R16G16_FLOAT,       WINED3D_FFP_EMIT_FLOAT16_2, 2, GL_FLOAT,          2, GL_FALSE, sizeof(GLhalfNV)},
+    {WINED3DFMT_R16G16B16A16_FLOAT, WINED3D_FFP_EMIT_FLOAT16_4, 4, GL_FLOAT,          4, GL_FALSE, sizeof(GLhalfNV)},
+    {WINED3DFMT_R32_UINT,           WINED3D_FFP_EMIT_INVALID,   1, GL_UNSIGNED_INT,   1, GL_FALSE, sizeof(UINT)},
+    {WINED3DFMT_R32G32_UINT,        WINED3D_FFP_EMIT_INVALID,   2, GL_UNSIGNED_INT,   2, GL_FALSE, sizeof(UINT)},
+    {WINED3DFMT_R32G32B32_UINT,     WINED3D_FFP_EMIT_INVALID,   3, GL_UNSIGNED_INT,   3, GL_FALSE, sizeof(UINT)},
+    {WINED3DFMT_R32G32B32A32_UINT,  WINED3D_FFP_EMIT_INVALID,   4, GL_UNSIGNED_INT,   4, GL_FALSE, sizeof(UINT)},
+};
+
+struct wined3d_format_texture_info
+{
+    enum wined3d_format_id id;
+    GLint gl_internal;
+    GLint gl_srgb_internal;
+    GLint gl_rt_internal;
+    GLint gl_format;
+    GLint gl_type;
+    unsigned int conv_byte_count;
+    unsigned int flags;
+    enum wined3d_gl_extension extension;
+    void (*convert)(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height);
+};
+
+static void convert_l4a4_unorm(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
+{
+    /* WINED3DFMT_L4A4_UNORM exists as an internal gl format, but for some reason there is not
+     * format+type combination to load it. Thus convert it to A8L8, then load it
+     * with A4L4 internal, but A8L8 format+type
+     */
+    unsigned int x, y;
+    const unsigned char *Source;
+    unsigned char *Dest;
+    UINT outpitch = pitch * 2;
+
+    for(y = 0; y < height; y++) {
+        Source = src + y * pitch;
+        Dest = dst + y * outpitch;
+        for (x = 0; x < width; x++ ) {
+            unsigned char color = (*Source++);
+            /* A */ Dest[1] = (color & 0xf0) << 0;
+            /* L */ Dest[0] = (color & 0x0f) << 4;
+            Dest += 2;
+        }
+    }
+}
+
+static void convert_r5g5_snorm_l6_unorm(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
+{
+    unsigned int x, y;
+    const WORD *Source;
+
+    for(y = 0; y < height; y++)
+    {
+        unsigned short *Dest_s = (unsigned short *) (dst + y * pitch);
+        Source = (const WORD *)(src + y * pitch);
+        for (x = 0; x < width; x++ )
+        {
+            short color = (*Source++);
+            unsigned char l = ((color >> 10) & 0xfc);
+                    short v = ((color >>  5) & 0x3e);
+                    short u = ((color      ) & 0x1f);
+            short v_conv = v + 16;
+            short u_conv = u + 16;
+
+            *Dest_s = ((v_conv << 11) & 0xf800) | ((l << 5) & 0x7e0) | (u_conv & 0x1f);
+            Dest_s += 1;
+        }
+    }
+}
+
+static void convert_r5g5_snorm_l6_unorm_nv(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
+{
+    unsigned int x, y;
+    const WORD *Source;
+    unsigned char *Dest;
+    UINT outpitch = (pitch * 3)/2;
+
+    /* This makes the gl surface bigger(24 bit instead of 16), but it works with
+     * fixed function and shaders without further conversion once the surface is
+     * loaded
+     */
+    for(y = 0; y < height; y++) {
+        Source = (const WORD *)(src + y * pitch);
+        Dest = dst + y * outpitch;
+        for (x = 0; x < width; x++ ) {
+            short color = (*Source++);
+            unsigned char l = ((color >> 10) & 0xfc);
+                     char v = ((color >>  5) & 0x3e);
+                     char u = ((color      ) & 0x1f);
+
+            /* 8 bits destination, 6 bits source, 8th bit is the sign. gl ignores the sign
+             * and doubles the positive range. Thus shift left only once, gl does the 2nd
+             * shift. GL reads a signed value and converts it into an unsigned value.
+             */
+            /* M */ Dest[2] = l << 1;
+
+            /* Those are read as signed, but kept signed. Just left-shift 3 times to scale
+             * from 5 bit values to 8 bit values.
+             */
+            /* V */ Dest[1] = v << 3;
+            /* U */ Dest[0] = u << 3;
+            Dest += 3;
+        }
+    }
+}
+
+static void convert_r8g8_snorm(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
+{
+    unsigned int x, y;
+    const short *Source;
+    unsigned char *Dest;
+    UINT outpitch = (pitch * 3)/2;
+
+    for(y = 0; y < height; y++)
+    {
+        Source = (const short *)(src + y * pitch);
+        Dest = dst + y * outpitch;
+        for (x = 0; x < width; x++ )
+        {
+            const short color = (*Source++);
+            /* B */ Dest[0] = 0xff;
+            /* G */ Dest[1] = (color >> 8) + 128; /* V */
+            /* R */ Dest[2] = (color & 0xff) + 128;      /* U */
+            Dest += 3;
+        }
+    }
+}
+
+static void convert_r8g8_snorm_l8x8_unorm(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
+{
+    unsigned int x, y;
+    const DWORD *Source;
+    unsigned char *Dest;
+
+    /* Doesn't work correctly with the fixed function pipeline, but can work in
+     * shaders if the shader is adjusted. (There's no use for this format in gl's
+     * standard fixed function pipeline anyway).
+     */
+    for(y = 0; y < height; y++)
+    {
+        Source = (const DWORD *)(src + y * pitch);
+        Dest = dst + y * pitch;
+        for (x = 0; x < width; x++ )
+        {
+            LONG color = (*Source++);
+            /* B */ Dest[0] = ((color >> 16) & 0xff);       /* L */
+            /* G */ Dest[1] = ((color >> 8 ) & 0xff) + 128; /* V */
+            /* R */ Dest[2] = (color         & 0xff) + 128; /* U */
+            Dest += 4;
+        }
+    }
+}
+
+static void convert_r8g8_snorm_l8x8_unorm_nv(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
+{
+    unsigned int x, y;
+    const DWORD *Source;
+    unsigned char *Dest;
+
+    /* This implementation works with the fixed function pipeline and shaders
+     * without further modification after converting the surface.
+     */
+    for(y = 0; y < height; y++)
+    {
+        Source = (const DWORD *)(src + y * pitch);
+        Dest = dst + y * pitch;
+        for (x = 0; x < width; x++ )
+        {
+            LONG color = (*Source++);
+            /* L */ Dest[2] = ((color >> 16) & 0xff);   /* L */
+            /* V */ Dest[1] = ((color >> 8 ) & 0xff);   /* V */
+            /* U */ Dest[0] = (color         & 0xff);   /* U */
+            /* I */ Dest[3] = 255;                      /* X */
+            Dest += 4;
+        }
+    }
+}
+
+static void convert_r8g8b8a8_snorm(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
+{
+    unsigned int x, y;
+    const DWORD *Source;
+    unsigned char *Dest;
+
+    for(y = 0; y < height; y++)
+    {
+        Source = (const DWORD *)(src + y * pitch);
+        Dest = dst + y * pitch;
+        for (x = 0; x < width; x++ )
+        {
+            LONG color = (*Source++);
+            /* B */ Dest[0] = ((color >> 16) & 0xff) + 128; /* W */
+            /* G */ Dest[1] = ((color >> 8 ) & 0xff) + 128; /* V */
+            /* R */ Dest[2] = (color         & 0xff) + 128; /* U */
+            /* A */ Dest[3] = ((color >> 24) & 0xff) + 128; /* Q */
+            Dest += 4;
+        }
+    }
+}
+
+static void convert_r16g16_snorm(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
+{
+    unsigned int x, y;
+    const DWORD *Source;
+    unsigned short *Dest;
+    UINT outpitch = (pitch * 3)/2;
+
+    for(y = 0; y < height; y++)
+    {
+        Source = (const DWORD *)(src + y * pitch);
+        Dest = (unsigned short *) (dst + y * outpitch);
+        for (x = 0; x < width; x++ )
+        {
+            const DWORD color = (*Source++);
+            /* B */ Dest[0] = 0xffff;
+            /* G */ Dest[1] = (color >> 16) + 32768; /* V */
+            /* R */ Dest[2] = (color & 0xffff) + 32768; /* U */
+            Dest += 3;
+        }
+    }
+}
+
+static void convert_r16g16(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
+{
+    unsigned int x, y;
+    const WORD *Source;
+    WORD *Dest;
+    UINT outpitch = (pitch * 3)/2;
+
+    for(y = 0; y < height; y++)
+    {
+        Source = (const WORD *)(src + y * pitch);
+        Dest = (WORD *) (dst + y * outpitch);
+        for (x = 0; x < width; x++ )
+        {
+            WORD green = (*Source++);
+            WORD red = (*Source++);
+            Dest[0] = green;
+            Dest[1] = red;
+            /* Strictly speaking not correct for R16G16F, but it doesn't matter because the
+             * shader overwrites it anyway
+             */
+            Dest[2] = 0xffff;
+            Dest += 3;
+        }
+    }
+}
+
+static void convert_r32g32_float(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
+{
+    unsigned int x, y;
+    const float *Source;
+    float *Dest;
+    UINT outpitch = (pitch * 3)/2;
+
+    for(y = 0; y < height; y++)
+    {
+        Source = (const float *)(src + y * pitch);
+        Dest = (float *) (dst + y * outpitch);
+        for (x = 0; x < width; x++ )
+        {
+            float green = (*Source++);
+            float red = (*Source++);
+            Dest[0] = green;
+            Dest[1] = red;
+            Dest[2] = 1.0f;
+            Dest += 3;
+        }
+    }
+}
+
+static void convert_s1_uint_d15_unorm(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
+{
+    unsigned int x, y;
+    UINT outpitch = pitch * 2;
+
+    for (y = 0; y < height; ++y)
+    {
+        const WORD *source = (const WORD *)(src + y * pitch);
+        DWORD *dest = (DWORD *)(dst + y * outpitch);
+
+        for (x = 0; x < width; ++x)
+        {
+            /* The depth data is normalized, so needs to be scaled,
+             * the stencil data isn't.  Scale depth data by
+             *      (2^24-1)/(2^15-1) ~~ (2^9 + 2^-6). */
+            WORD d15 = source[x] >> 1;
+            DWORD d24 = (d15 << 9) + (d15 >> 6);
+            dest[x] = (d24 << 8) | (source[x] & 0x1);
+        }
+    }
+}
+
+static void convert_s4x4_uint_d24_unorm(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
+{
+    unsigned int x, y;
+
+    for (y = 0; y < height; ++y)
+    {
+        const DWORD *source = (const DWORD *)(src + y * pitch);
+        DWORD *dest = (DWORD *)(dst + y * pitch);
+
+        for (x = 0; x < width; ++x)
+        {
+            /* Just need to clear out the X4 part. */
+            dest[x] = source[x] & ~0xf0;
+        }
+    }
+}
+
+static void convert_s8_uint_d24_float(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
+{
+    unsigned int x, y;
+    UINT outpitch = pitch * 2;
+
+    for (y = 0; y < height; ++y)
+    {
+        const DWORD *source = (const DWORD *)(src + y * pitch);
+        float *dest_f = (float *)(dst + y * outpitch);
+        DWORD *dest_s = (DWORD *)(dst + y * outpitch);
+
+        for (x = 0; x < width; ++x)
+        {
+            dest_f[x * 2] = float_24_to_32((source[x] & 0xffffff00) >> 8);
+            dest_s[x * 2 + 1] = source[x] & 0xff;
+        }
+    }
+}
+
+/* The following formats explicitly don't have WINED3DFMT_FLAG_TEXTURE set:
+ *
+ * These are never supported on native.
+ *     WINED3DFMT_B8G8R8_UNORM
+ *     WINED3DFMT_B2G3R3_UNORM
+ *     WINED3DFMT_L4A4_UNORM
+ *     WINED3DFMT_S1_UINT_D15_UNORM
+ *     WINED3DFMT_S4X4_UINT_D24_UNORM
+ *
+ * Only some Geforce/Voodoo3/G400 cards offer 8-bit textures in case of ddraw.
+ * Since it is not widely available, don't offer it. Further no Windows driver
+ * offers WINED3DFMT_P8_UINT_A8_NORM, so don't offer it either.
+ *     WINED3DFMT_P8_UINT
+ *     WINED3DFMT_P8_UINT_A8_UNORM
+ *
+ * These formats seem to be similar to the HILO formats in
+ * GL_NV_texture_shader. NVHU is said to be GL_UNSIGNED_HILO16,
+ * NVHS GL_SIGNED_HILO16. Rumours say that D3D computes a 3rd channel
+ * similarly to D3DFMT_CxV8U8 (So NVHS could be called D3DFMT_CxV16U16). ATI
+ * refused to support formats which can easily be emulated with pixel shaders,
+ * so applications have to deal with not having NVHS and NVHU.
+ *     WINED3DFMT_NVHU
+ *     WINED3DFMT_NVHS */
+static const struct wined3d_format_texture_info format_texture_info[] =
+{
+    /* format id                        gl_internal                       gl_srgb_internal                      gl_rt_internal
+            gl_format                   gl_type                           conv_byte_count
+            flags
+            extension                   convert */
+    /* FourCC formats */
+    /* GL_APPLE_ycbcr_422 claims that its '2YUV' format, which is supported via the UNSIGNED_SHORT_8_8_REV_APPLE type
+     * is equivalent to 'UYVY' format on Windows, and the 'YUVS' via UNSIGNED_SHORT_8_8_APPLE equates to 'YUY2'. The
+     * d3d9 test however shows that the opposite is true. Since the extension is from 2002, it predates the x86 based
+     * Macs, so probably the endianness differs. This could be tested as soon as we have a Windows and MacOS on a big
+     * endian machine
+     */
+    {WINED3DFMT_UYVY,                   GL_LUMINANCE_ALPHA,               GL_LUMINANCE_ALPHA,                     0,
+            GL_LUMINANCE_ALPHA,         GL_UNSIGNED_BYTE,                 0,
+            WINED3DFMT_FLAG_FILTERING,
+            WINED3D_GL_EXT_NONE,        NULL},
+    {WINED3DFMT_UYVY,                   GL_RGB,                           GL_RGB,                                 0,
+            GL_YCBCR_422_APPLE,         GL_UNSIGNED_SHORT_8_8_APPLE,      0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_FILTERING,
+            APPLE_YCBCR_422,            NULL},
+    {WINED3DFMT_YUY2,                   GL_LUMINANCE_ALPHA,               GL_LUMINANCE_ALPHA,                     0,
+            GL_LUMINANCE_ALPHA,         GL_UNSIGNED_BYTE,                 0,
+            WINED3DFMT_FLAG_FILTERING,
+            WINED3D_GL_EXT_NONE,        NULL},
+    {WINED3DFMT_YUY2,                   GL_RGB,                           GL_RGB,                                 0,
+            GL_YCBCR_422_APPLE,         GL_UNSIGNED_SHORT_8_8_REV_APPLE,  0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_FILTERING,
+            APPLE_YCBCR_422,            NULL},
+    {WINED3DFMT_YV12,                   GL_ALPHA,                         GL_ALPHA,                               0,
+            GL_ALPHA,                   GL_UNSIGNED_BYTE,                 0,
+            WINED3DFMT_FLAG_FILTERING,
+            WINED3D_GL_EXT_NONE,        NULL},
+    {WINED3DFMT_DXT1,                   GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 0,
+            GL_RGBA,                    GL_UNSIGNED_BYTE,                 0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_COMPRESSED,
+            EXT_TEXTURE_COMPRESSION_S3TC, NULL},
+    {WINED3DFMT_DXT2,                   GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 0,
+            GL_RGBA,                    GL_UNSIGNED_BYTE,                 0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_COMPRESSED,
+            EXT_TEXTURE_COMPRESSION_S3TC, NULL},
+    {WINED3DFMT_DXT3,                   GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 0,
+            GL_RGBA,                    GL_UNSIGNED_BYTE,                 0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_COMPRESSED,
+            EXT_TEXTURE_COMPRESSION_S3TC, NULL},
+    {WINED3DFMT_DXT4,                   GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 0,
+            GL_RGBA,                    GL_UNSIGNED_BYTE,                 0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_COMPRESSED,
+            EXT_TEXTURE_COMPRESSION_S3TC, NULL},
+    {WINED3DFMT_DXT5,                   GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 0,
+            GL_RGBA,                    GL_UNSIGNED_BYTE,                 0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_COMPRESSED,
+            EXT_TEXTURE_COMPRESSION_S3TC, NULL},
+    /* IEEE formats */
+    {WINED3DFMT_R32_FLOAT,              GL_RGB32F_ARB,                    GL_RGB32F_ARB,                          0,
+            GL_RED,                     GL_FLOAT,                         0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
+            ARB_TEXTURE_FLOAT,          NULL},
+    {WINED3DFMT_R32_FLOAT,              GL_R32F,                          GL_R32F,                                0,
+            GL_RED,                     GL_FLOAT,                         0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
+            ARB_TEXTURE_RG,             NULL},
+    {WINED3DFMT_R32G32_FLOAT,           GL_RGB32F_ARB,                    GL_RGB32F_ARB,                          0,
+            GL_RGB,                     GL_FLOAT,                         12,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
+            ARB_TEXTURE_FLOAT,          convert_r32g32_float},
+    {WINED3DFMT_R32G32_FLOAT,           GL_RG32F,                         GL_RG32F,                               0,
+            GL_RG,                      GL_FLOAT,                         0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
+            ARB_TEXTURE_RG,             NULL},
+    {WINED3DFMT_R32G32B32A32_FLOAT,     GL_RGBA32F_ARB,                   GL_RGBA32F_ARB,                         0,
+            GL_RGBA,                    GL_FLOAT,                         0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
+            ARB_TEXTURE_FLOAT,          NULL},
+    /* Float */
+    {WINED3DFMT_R16_FLOAT,              GL_RGB16F_ARB,                    GL_RGB16F_ARB,                          0,
+            GL_RED,                     GL_HALF_FLOAT_ARB,                0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
+            ARB_TEXTURE_FLOAT,          NULL},
+    {WINED3DFMT_R16_FLOAT,              GL_R16F,                          GL_R16F,                                0,
+            GL_RED,                     GL_HALF_FLOAT_ARB,                0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
+            ARB_TEXTURE_RG,             NULL},
+    {WINED3DFMT_R16G16_FLOAT,           GL_RGB16F_ARB,                    GL_RGB16F_ARB,                          0,
+            GL_RGB,                     GL_HALF_FLOAT_ARB,                6,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
+            ARB_TEXTURE_FLOAT,          convert_r16g16},
+    {WINED3DFMT_R16G16_FLOAT,           GL_RG16F,                         GL_RG16F,                               0,
+            GL_RG,                      GL_HALF_FLOAT_ARB,                0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
+            ARB_TEXTURE_RG,             NULL},
+    {WINED3DFMT_R16G16B16A16_FLOAT,     GL_RGBA16F_ARB,                   GL_RGBA16F_ARB,                         0,
+            GL_RGBA,                    GL_HALF_FLOAT_ARB,                0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_RENDERTARGET
+            | WINED3DFMT_FLAG_VTF,
+            ARB_TEXTURE_FLOAT,          NULL},
+    /* Palettized formats */
+    {WINED3DFMT_P8_UINT,                GL_RGBA,                          GL_RGBA,                                0,
+            GL_ALPHA,                   GL_UNSIGNED_BYTE,                 0,
+            0,
+            ARB_FRAGMENT_PROGRAM,       NULL},
+    {WINED3DFMT_P8_UINT,                GL_COLOR_INDEX8_EXT,              GL_COLOR_INDEX8_EXT,                    0,
+            GL_COLOR_INDEX,             GL_UNSIGNED_BYTE,                 0,
+            0,
+            EXT_PALETTED_TEXTURE,       NULL},
+    /* Standard ARGB formats */
+    {WINED3DFMT_B8G8R8_UNORM,           GL_RGB8,                          GL_RGB8,                                0,
+            GL_BGR,                     GL_UNSIGNED_BYTE,                 0,
+            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET,
+            WINED3D_GL_EXT_NONE,        NULL},
+    {WINED3DFMT_B8G8R8A8_UNORM,         GL_RGBA8,                         GL_SRGB8_ALPHA8_EXT,                    0,
+            GL_BGRA,                    GL_UNSIGNED_INT_8_8_8_8_REV,      0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_SRGB_WRITE
+            | WINED3DFMT_FLAG_VTF,
+            WINED3D_GL_EXT_NONE,        NULL},
+    {WINED3DFMT_B8G8R8X8_UNORM,         GL_RGB8,                          GL_SRGB8_EXT,                           0,
+            GL_BGRA,                    GL_UNSIGNED_INT_8_8_8_8_REV,      0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_SRGB_WRITE,
+            WINED3D_GL_EXT_NONE,        NULL},
+    {WINED3DFMT_B5G6R5_UNORM,           GL_RGB5,                          GL_RGB5,                          GL_RGB8,
+            GL_RGB,                     GL_UNSIGNED_SHORT_5_6_5,          0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_RENDERTARGET,
+            WINED3D_GL_EXT_NONE,        NULL},
+    {WINED3DFMT_B5G5R5X1_UNORM,         GL_RGB5,                          GL_RGB5_A1,                             0,
+            GL_BGRA,                    GL_UNSIGNED_SHORT_1_5_5_5_REV,    0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
+            WINED3D_GL_EXT_NONE,        NULL},
+    {WINED3DFMT_B5G5R5A1_UNORM,         GL_RGB5_A1,                       GL_RGB5_A1,                             0,
+            GL_BGRA,                    GL_UNSIGNED_SHORT_1_5_5_5_REV,    0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
+            WINED3D_GL_EXT_NONE,        NULL},
+    {WINED3DFMT_B4G4R4A4_UNORM,         GL_RGBA4,                         GL_SRGB8_ALPHA8_EXT,                    0,
+            GL_BGRA,                    GL_UNSIGNED_SHORT_4_4_4_4_REV,    0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_SRGB_READ,
+            WINED3D_GL_EXT_NONE,        NULL},
+    {WINED3DFMT_B2G3R3_UNORM,           GL_R3_G3_B2,                      GL_R3_G3_B2,                            0,
+            GL_RGB,                     GL_UNSIGNED_BYTE_3_3_2,           0,
+            WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
+            WINED3D_GL_EXT_NONE,        NULL},
+    {WINED3DFMT_A8_UNORM,               GL_ALPHA8,                        GL_ALPHA8,                              0,
+            GL_ALPHA,                   GL_UNSIGNED_BYTE,                 0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
+            WINED3D_GL_EXT_NONE,        NULL},
+    {WINED3DFMT_B4G4R4X4_UNORM,         GL_RGB4,                          GL_RGB4,                                0,
+            GL_BGRA,                    GL_UNSIGNED_SHORT_4_4_4_4_REV,    0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
+            WINED3D_GL_EXT_NONE,        NULL},
+    {WINED3DFMT_R10G10B10A2_UNORM,      GL_RGB10_A2,                      GL_RGB10_A2,                            0,
+            GL_RGBA,                    GL_UNSIGNED_INT_2_10_10_10_REV,   0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_RENDERTARGET,
+            WINED3D_GL_EXT_NONE,        NULL},
+    {WINED3DFMT_R8G8B8A8_UNORM,         GL_RGBA8,                         GL_RGBA8,                               0,
+            GL_RGBA,                    GL_UNSIGNED_INT_8_8_8_8_REV,      0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
+            WINED3D_GL_EXT_NONE,        NULL},
+    {WINED3DFMT_R8G8B8X8_UNORM,         GL_RGB8,                          GL_RGB8,                                0,
+            GL_RGBA,                    GL_UNSIGNED_INT_8_8_8_8_REV,      0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
+            WINED3D_GL_EXT_NONE,        NULL},
+    {WINED3DFMT_R16G16_UNORM,           GL_RGB16,                         GL_RGB16,                       GL_RGBA16,
+            GL_RGB,                     GL_UNSIGNED_SHORT,                6,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
+            WINED3D_GL_EXT_NONE,        convert_r16g16},
+    {WINED3DFMT_R16G16_UNORM,           GL_RG16,                          GL_RG16,                                0,
+            GL_RG,                      GL_UNSIGNED_SHORT,                0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_RENDERTARGET,
+            ARB_TEXTURE_RG,             NULL},
+    {WINED3DFMT_B10G10R10A2_UNORM,      GL_RGB10_A2,                      GL_RGB10_A2,                            0,
+            GL_BGRA,                    GL_UNSIGNED_INT_2_10_10_10_REV,   0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_RENDERTARGET,
+            WINED3D_GL_EXT_NONE,        NULL},
+    {WINED3DFMT_R16G16B16A16_UNORM,     GL_RGBA16,                        GL_RGBA16,                              0,
+            GL_RGBA,                    GL_UNSIGNED_SHORT,                0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_RENDERTARGET,
+            WINED3D_GL_EXT_NONE,        NULL},
+    /* Luminance */
+    {WINED3DFMT_L8_UNORM,               GL_LUMINANCE8,                    GL_SLUMINANCE8_EXT,                     0,
+            GL_LUMINANCE,               GL_UNSIGNED_BYTE,                 0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_SRGB_READ,
+            WINED3D_GL_EXT_NONE,        NULL},
+    {WINED3DFMT_L8A8_UNORM,             GL_LUMINANCE8_ALPHA8,             GL_SLUMINANCE8_ALPHA8_EXT,              0,
+            GL_LUMINANCE_ALPHA,         GL_UNSIGNED_BYTE,                 0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_SRGB_READ,
+            WINED3D_GL_EXT_NONE,        NULL},
+    {WINED3DFMT_L4A4_UNORM,             GL_LUMINANCE4_ALPHA4,             GL_LUMINANCE4_ALPHA4,                   0,
+            GL_LUMINANCE_ALPHA,         GL_UNSIGNED_BYTE,                 2,
+            WINED3DFMT_FLAG_FILTERING,
+            WINED3D_GL_EXT_NONE,        convert_l4a4_unorm},
+    /* Bump mapping stuff */
+    {WINED3DFMT_R8G8_SNORM,             GL_RGB8,                          GL_RGB8,                                0,
+            GL_BGR,                     GL_UNSIGNED_BYTE,                 3,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_BUMPMAP,
+            WINED3D_GL_EXT_NONE,        convert_r8g8_snorm},
+    {WINED3DFMT_R8G8_SNORM,             GL_DSDT8_NV,                      GL_DSDT8_NV,                            0,
+            GL_DSDT_NV,                 GL_BYTE,                          0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_BUMPMAP,
+            NV_TEXTURE_SHADER,          NULL},
+    {WINED3DFMT_R5G5_SNORM_L6_UNORM,    GL_RGB5,                          GL_RGB5,                                0,
+            GL_RGB,                     GL_UNSIGNED_SHORT_5_6_5,          2,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_BUMPMAP,
+            WINED3D_GL_EXT_NONE,        convert_r5g5_snorm_l6_unorm},
+    {WINED3DFMT_R5G5_SNORM_L6_UNORM,    GL_DSDT8_MAG8_NV,                 GL_DSDT8_MAG8_NV,                       0,
+            GL_DSDT_MAG_NV,             GL_BYTE,                          3,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_BUMPMAP,
+            NV_TEXTURE_SHADER,          convert_r5g5_snorm_l6_unorm_nv},
+    {WINED3DFMT_R8G8_SNORM_L8X8_UNORM,  GL_RGB8,                          GL_RGB8,                                0,
+            GL_BGRA,                    GL_UNSIGNED_INT_8_8_8_8_REV,      4,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_BUMPMAP,
+            WINED3D_GL_EXT_NONE,        convert_r8g8_snorm_l8x8_unorm},
+    {WINED3DFMT_R8G8_SNORM_L8X8_UNORM,  GL_DSDT8_MAG8_INTENSITY8_NV,      GL_DSDT8_MAG8_INTENSITY8_NV,            0,
+            GL_DSDT_MAG_VIB_NV,         GL_UNSIGNED_INT_8_8_S8_S8_REV_NV, 4,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_BUMPMAP,
+            NV_TEXTURE_SHADER,          convert_r8g8_snorm_l8x8_unorm_nv},
+    {WINED3DFMT_R8G8B8A8_SNORM,         GL_RGBA8,                         GL_RGBA8,                               0,
+            GL_BGRA,                    GL_UNSIGNED_BYTE,                 4,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_BUMPMAP,
+            WINED3D_GL_EXT_NONE,        convert_r8g8b8a8_snorm},
+    {WINED3DFMT_R8G8B8A8_SNORM,         GL_SIGNED_RGBA8_NV,               GL_SIGNED_RGBA8_NV,                     0,
+            GL_RGBA,                    GL_BYTE,                          0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_BUMPMAP,
+            NV_TEXTURE_SHADER,          NULL},
+    {WINED3DFMT_R16G16_SNORM,           GL_RGB16,                         GL_RGB16,                               0,
+            GL_BGR,                     GL_UNSIGNED_SHORT,                6,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_BUMPMAP,
+            WINED3D_GL_EXT_NONE,        convert_r16g16_snorm},
+    {WINED3DFMT_R16G16_SNORM,           GL_SIGNED_HILO16_NV,              GL_SIGNED_HILO16_NV,                    0,
+            GL_HILO_NV,                 GL_SHORT,                         0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_BUMPMAP,
+            NV_TEXTURE_SHADER,          NULL},
+    /* Depth stencil formats */
+    {WINED3DFMT_D16_LOCKABLE,           GL_DEPTH_COMPONENT24_ARB,         GL_DEPTH_COMPONENT24_ARB,               0,
+            GL_DEPTH_COMPONENT,         GL_UNSIGNED_SHORT,                0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW,
+            ARB_DEPTH_TEXTURE,          NULL},
+    {WINED3DFMT_D32_UNORM,              GL_DEPTH_COMPONENT32_ARB,         GL_DEPTH_COMPONENT32_ARB,               0,
+            GL_DEPTH_COMPONENT,         GL_UNSIGNED_INT,                  0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW,
+            ARB_DEPTH_TEXTURE,          NULL},
+    {WINED3DFMT_S1_UINT_D15_UNORM,      GL_DEPTH_COMPONENT24_ARB,         GL_DEPTH_COMPONENT24_ARB,               0,
+            GL_DEPTH_COMPONENT,         GL_UNSIGNED_SHORT,                0,
+            WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW,
+            ARB_DEPTH_TEXTURE,          NULL},
+    {WINED3DFMT_S1_UINT_D15_UNORM,      GL_DEPTH24_STENCIL8_EXT,          GL_DEPTH24_STENCIL8_EXT,                0,
+            GL_DEPTH_STENCIL_EXT,       GL_UNSIGNED_INT_24_8_EXT,         4,
+            WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
+            EXT_PACKED_DEPTH_STENCIL,   convert_s1_uint_d15_unorm},
+    {WINED3DFMT_S1_UINT_D15_UNORM,      GL_DEPTH24_STENCIL8,              GL_DEPTH24_STENCIL8,                    0,
+            GL_DEPTH_STENCIL,           GL_UNSIGNED_INT_24_8,             4,
+            WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
+            ARB_FRAMEBUFFER_OBJECT,     convert_s1_uint_d15_unorm},
+    {WINED3DFMT_D24_UNORM_S8_UINT,      GL_DEPTH_COMPONENT24_ARB,         GL_DEPTH_COMPONENT24_ARB,               0,
+            GL_DEPTH_COMPONENT,         GL_UNSIGNED_INT,                  0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW,
+            ARB_DEPTH_TEXTURE,          NULL},
+    {WINED3DFMT_D24_UNORM_S8_UINT,      GL_DEPTH24_STENCIL8_EXT,          GL_DEPTH24_STENCIL8_EXT,                0,
+            GL_DEPTH_STENCIL_EXT,       GL_UNSIGNED_INT_24_8_EXT,         0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
+            EXT_PACKED_DEPTH_STENCIL,   NULL},
+    {WINED3DFMT_D24_UNORM_S8_UINT,      GL_DEPTH24_STENCIL8,              GL_DEPTH24_STENCIL8,                    0,
+            GL_DEPTH_STENCIL,           GL_UNSIGNED_INT_24_8,             0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
+            ARB_FRAMEBUFFER_OBJECT,     NULL},
+    {WINED3DFMT_X8D24_UNORM,            GL_DEPTH_COMPONENT24_ARB,         GL_DEPTH_COMPONENT24_ARB,               0,
+            GL_DEPTH_COMPONENT,         GL_UNSIGNED_INT,                  0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW,
+            ARB_DEPTH_TEXTURE,          NULL},
+    {WINED3DFMT_S4X4_UINT_D24_UNORM,    GL_DEPTH_COMPONENT24_ARB,         GL_DEPTH_COMPONENT24_ARB,               0,
+            GL_DEPTH_COMPONENT,         GL_UNSIGNED_INT,                  0,
+            WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW,
+            ARB_DEPTH_TEXTURE,          NULL},
+    {WINED3DFMT_S4X4_UINT_D24_UNORM,    GL_DEPTH24_STENCIL8_EXT,          GL_DEPTH24_STENCIL8_EXT,                0,
+            GL_DEPTH_STENCIL_EXT,       GL_UNSIGNED_INT_24_8_EXT,         4,
+            WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
+            EXT_PACKED_DEPTH_STENCIL,   convert_s4x4_uint_d24_unorm},
+    {WINED3DFMT_S4X4_UINT_D24_UNORM,    GL_DEPTH24_STENCIL8,              GL_DEPTH24_STENCIL8,                    0,
+            GL_DEPTH_STENCIL,           GL_UNSIGNED_INT_24_8,             4,
+            WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
+            ARB_FRAMEBUFFER_OBJECT,     convert_s4x4_uint_d24_unorm},
+    {WINED3DFMT_D16_UNORM,              GL_DEPTH_COMPONENT24_ARB,         GL_DEPTH_COMPONENT24_ARB,               0,
+            GL_DEPTH_COMPONENT,         GL_UNSIGNED_SHORT,                0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW,
+            ARB_DEPTH_TEXTURE,          NULL},
+    {WINED3DFMT_L16_UNORM,              GL_LUMINANCE16,                   GL_LUMINANCE16,                         0,
+            GL_LUMINANCE,               GL_UNSIGNED_SHORT,                0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
+            WINED3D_GL_EXT_NONE,        NULL},
+    {WINED3DFMT_D32_FLOAT,              GL_DEPTH_COMPONENT32F,            GL_DEPTH_COMPONENT32F,                  0,
+            GL_DEPTH_COMPONENT,         GL_FLOAT,                         0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW,
+            ARB_DEPTH_BUFFER_FLOAT,     NULL},
+    {WINED3DFMT_S8_UINT_D24_FLOAT,      GL_DEPTH32F_STENCIL8,             GL_DEPTH32F_STENCIL8,                   0,
+            GL_DEPTH_STENCIL,           GL_FLOAT_32_UNSIGNED_INT_24_8_REV, 8,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
+            ARB_DEPTH_BUFFER_FLOAT,     convert_s8_uint_d24_float},
+    /* Vendor-specific formats */
+    {WINED3DFMT_ATI2N,                  GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI, GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI, 0,
+            GL_LUMINANCE_ALPHA,         GL_UNSIGNED_BYTE,                 0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_COMPRESSED,
+            ATI_TEXTURE_COMPRESSION_3DC, NULL},
+    {WINED3DFMT_ATI2N,                  GL_COMPRESSED_RG_RGTC2,           GL_COMPRESSED_RG_RGTC2,                 0,
+            GL_LUMINANCE_ALPHA,         GL_UNSIGNED_BYTE,                 0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_COMPRESSED,
+            ARB_TEXTURE_COMPRESSION_RGTC, NULL},
+    {WINED3DFMT_INTZ,                   GL_DEPTH24_STENCIL8_EXT,          GL_DEPTH24_STENCIL8_EXT,                0,
+            GL_DEPTH_STENCIL_EXT,       GL_UNSIGNED_INT_24_8_EXT,         0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL,
+            EXT_PACKED_DEPTH_STENCIL,   NULL},
+    {WINED3DFMT_INTZ,                   GL_DEPTH24_STENCIL8,              GL_DEPTH24_STENCIL8,                    0,
+            GL_DEPTH_STENCIL,           GL_UNSIGNED_INT_24_8,             0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
+            | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL,
+            ARB_FRAMEBUFFER_OBJECT,     NULL},
+    {WINED3DFMT_NULL,                   0,                                0,                                      0,
+            GL_RGBA,                    GL_UNSIGNED_INT_8_8_8_8_REV,      0,
+            WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET,
+            ARB_FRAMEBUFFER_OBJECT,     NULL},
+};
+
+static inline int getFmtIdx(enum wined3d_format_id format_id)
+{
+    /* First check if the format is at the position of its value.
+     * This will catch the argb formats before the loop is entered. */
+    if (format_id < (sizeof(formats) / sizeof(*formats))
+            && formats[format_id].id == format_id)
+    {
+        return format_id;
+    }
+    else
+    {
+        unsigned int i;
+
+        for (i = 0; i < (sizeof(formats) / sizeof(*formats)); ++i)
+        {
+            if (formats[i].id == format_id) return i;
+        }
+    }
+    return -1;
+}
+
+static BOOL init_format_base_info(struct wined3d_gl_info *gl_info)
+{
+    UINT format_count = sizeof(formats) / sizeof(*formats);
+    UINT i;
+
+    gl_info->formats = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, format_count * sizeof(*gl_info->formats));
+    if (!gl_info->formats)
+    {
+        ERR("Failed to allocate memory.\n");
+        return FALSE;
+    }
+
+    for (i = 0; i < format_count; ++i)
+    {
+        struct wined3d_format *format = &gl_info->formats[i];
+        format->id = formats[i].id;
+        format->red_size = formats[i].red_size;
+        format->green_size = formats[i].green_size;
+        format->blue_size = formats[i].blue_size;
+        format->alpha_size = formats[i].alpha_size;
+        format->red_offset = formats[i].red_offset;
+        format->green_offset = formats[i].green_offset;
+        format->blue_offset = formats[i].blue_offset;
+        format->alpha_offset = formats[i].alpha_offset;
+        format->byte_count = formats[i].bpp;
+        format->depth_size = formats[i].depth_size;
+        format->stencil_size = formats[i].stencil_size;
+        format->block_width = 1;
+        format->block_height = 1;
+        format->block_byte_count = formats[i].bpp;
+    }
+
+    for (i = 0; i < (sizeof(format_base_flags) / sizeof(*format_base_flags)); ++i)
+    {
+        int fmt_idx = getFmtIdx(format_base_flags[i].id);
+
+        if (fmt_idx == -1)
+        {
+            ERR("Format %s (%#x) not found.\n",
+                    debug_d3dformat(format_base_flags[i].id), format_base_flags[i].id);
+            HeapFree(GetProcessHeap(), 0, gl_info->formats);
+            return FALSE;
+        }
+
+        gl_info->formats[fmt_idx].flags |= format_base_flags[i].flags;
+    }
+
+    return TRUE;
+}
+
+static BOOL init_format_block_info(struct wined3d_gl_info *gl_info)
+{
+    unsigned int i;
+
+    for (i = 0; i < (sizeof(format_block_info) / sizeof(*format_block_info)); ++i)
+    {
+        struct wined3d_format *format;
+        int fmt_idx = getFmtIdx(format_block_info[i].id);
+
+        if (fmt_idx == -1)
+        {
+            ERR("Format %s (%#x) not found.\n",
+                    debug_d3dformat(format_block_info[i].id), format_block_info[i].id);
+            return FALSE;
+        }
+
+        format = &gl_info->formats[fmt_idx];
+        format->block_width = format_block_info[i].block_width;
+        format->block_height = format_block_info[i].block_height;
+        format->block_byte_count = format_block_info[i].block_byte_count;
+        format->flags |= WINED3DFMT_FLAG_BLOCKS;
+    }
+
+    return TRUE;
+}
+
+/* Context activation is done by the caller. */
+static void check_fbo_compat(const struct wined3d_gl_info *gl_info, struct wined3d_format *format)
+{
+    /* Check if the default internal format is supported as a frame buffer
+     * target, otherwise fall back to the render target internal.
+     *
+     * Try to stick to the standard format if possible, this limits precision differences. */
+    GLenum status;
+    GLuint tex;
+
+    while (gl_info->gl_ops.gl.p_glGetError());
+    gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
+
+    gl_info->gl_ops.gl.p_glGenTextures(1, &tex);
+    gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, tex);
+
+    gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, format->glInternal, 16, 16, 0,
+            format->glFormat, format->glType, NULL);
+    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+    gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
+
+    status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER);
+    checkGLcall("Framebuffer format check");
+
+    if (status == GL_FRAMEBUFFER_COMPLETE)
+    {
+        TRACE("Format %s is supported as FBO color attachment.\n", debug_d3dformat(format->id));
+        format->flags |= WINED3DFMT_FLAG_FBO_ATTACHABLE;
+        format->rtInternal = format->glInternal;
+    }
+    else
+    {
+        if (!format->rtInternal)
+        {
+            if (format->flags & WINED3DFMT_FLAG_RENDERTARGET)
+            {
+                FIXME("Format %s with rendertarget flag is not supported as FBO color attachment,"
+                        " and no fallback specified.\n", debug_d3dformat(format->id));
+                format->flags &= ~WINED3DFMT_FLAG_RENDERTARGET;
+            }
+            else
+            {
+                TRACE("Format %s is not supported as FBO color attachment.\n", debug_d3dformat(format->id));
+            }
+            format->rtInternal = format->glInternal;
+        }
+        else
+        {
+            TRACE("Format %s is not supported as FBO color attachment, trying rtInternal format as fallback.\n",
+                    debug_d3dformat(format->id));
+
+            while (gl_info->gl_ops.gl.p_glGetError());
+
+            gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
+
+            gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, format->rtInternal, 16, 16, 0,
+                    format->glFormat, format->glType, NULL);
+            gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+            gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+            gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
+
+            status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER);
+            checkGLcall("Framebuffer format check");
+
+            if (status == GL_FRAMEBUFFER_COMPLETE)
+            {
+                TRACE("Format %s rtInternal format is supported as FBO color attachment.\n",
+                        debug_d3dformat(format->id));
+            }
+            else
+            {
+                FIXME("Format %s rtInternal format is not supported as FBO color attachment.\n",
+                        debug_d3dformat(format->id));
+                format->flags &= ~WINED3DFMT_FLAG_RENDERTARGET;
+            }
+        }
+    }
+
+    if (status == GL_FRAMEBUFFER_COMPLETE && ((format->flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING)
+            || !(gl_info->quirks & WINED3D_QUIRK_LIMITED_TEX_FILTERING))
+            && format->id != WINED3DFMT_NULL && format->id != WINED3DFMT_P8_UINT
+            && format->glFormat != GL_LUMINANCE && format->glFormat != GL_LUMINANCE_ALPHA
+            && (format->red_size || format->alpha_size))
+    {
+        DWORD readback[16 * 16], color, r_range, a_range;
+        BYTE r, a;
+        BOOL match = TRUE;
+        GLuint rb;
+
+        if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT]
+                || gl_info->supported[EXT_PACKED_DEPTH_STENCIL])
+        {
+            gl_info->fbo_ops.glGenRenderbuffers(1, &rb);
+            gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, rb);
+            gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 16, 16);
+            gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rb);
+            gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rb);
+            checkGLcall("RB attachment");
+        }
+
+        gl_info->gl_ops.gl.p_glEnable(GL_BLEND);
+        gl_info->gl_ops.gl.p_glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+        gl_info->gl_ops.gl.p_glClear(GL_COLOR_BUFFER_BIT);
+        if (gl_info->gl_ops.gl.p_glGetError() == GL_INVALID_FRAMEBUFFER_OPERATION)
+        {
+            while (gl_info->gl_ops.gl.p_glGetError());
+            TRACE("Format doesn't support post-pixelshader blending.\n");
+            format->flags &= ~WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING;
+        }
+        else
+        {
+            gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
+            gl_info->gl_ops.gl.p_glViewport(0, 0, 16, 16);
+            gl_info->gl_ops.gl.p_glDisable(GL_LIGHTING);
+            gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
+            gl_info->gl_ops.gl.p_glLoadIdentity();
+            gl_info->gl_ops.gl.p_glMatrixMode(GL_PROJECTION);
+            gl_info->gl_ops.gl.p_glLoadIdentity();
+
+            gl_info->gl_ops.gl.p_glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+            /* Draw a full-black quad */
+            gl_info->gl_ops.gl.p_glBegin(GL_TRIANGLE_STRIP);
+            gl_info->gl_ops.gl.p_glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
+            gl_info->gl_ops.gl.p_glVertex3f(-1.0f, -1.0f, 0.0f);
+            gl_info->gl_ops.gl.p_glVertex3f(1.0f, -1.0f, 0.0f);
+            gl_info->gl_ops.gl.p_glVertex3f(-1.0f, 1.0f, 0.0f);
+            gl_info->gl_ops.gl.p_glVertex3f(1.0f, 1.0f, 0.0f);
+            gl_info->gl_ops.gl.p_glEnd();
+
+            gl_info->gl_ops.gl.p_glEnable(GL_BLEND);
+            /* Draw a half-transparent red quad */
+            gl_info->gl_ops.gl.p_glBegin(GL_TRIANGLE_STRIP);
+            gl_info->gl_ops.gl.p_glColor4f(1.0f, 0.0f, 0.0f, 0.5f);
+            gl_info->gl_ops.gl.p_glVertex3f(-1.0f, -1.0f, 0.0f);
+            gl_info->gl_ops.gl.p_glVertex3f(1.0f, -1.0f, 0.0f);
+            gl_info->gl_ops.gl.p_glVertex3f(-1.0f, 1.0f, 0.0f);
+            gl_info->gl_ops.gl.p_glVertex3f(1.0f, 1.0f, 0.0f);
+            gl_info->gl_ops.gl.p_glEnd();
+
+            gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
+
+            /* Rebinding texture to workaround a fglrx bug. */
+            gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, tex);
+            gl_info->gl_ops.gl.p_glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, readback);
+            checkGLcall("Post-pixelshader blending check");
+
+            color = readback[7 * 16 + 7];
+            a = color >> 24;
+            r = (color & 0x00ff0000) >> 16;
+
+            r_range = format->red_size < 8 ? 1 << (8 - format->red_size) : 1;
+            a_range = format->alpha_size < 8 ? 1 << (8 - format->alpha_size) : 1;
+            if (format->red_size && (r < 0x7f - r_range || r > 0x7f + r_range))
+                match = FALSE;
+            else if (format->alpha_size > 1 && (a < 0xbf - a_range || a > 0xbf + a_range))
+                match = FALSE;
+            if (!match)
+            {
+                TRACE("Format doesn't support post-pixelshader blending.\n");
+                TRACE("Color output: %#x\n", color);
+                format->flags &= ~WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING;
+            }
+            else
+            {
+                TRACE("Format supports post-pixelshader blending.\n");
+                TRACE("Color output: %#x\n", color);
+                format->flags |= WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING;
+            }
+        }
+
+        if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT]
+                || gl_info->supported[EXT_PACKED_DEPTH_STENCIL])
+        {
+            gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
+            gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
+            gl_info->fbo_ops.glDeleteRenderbuffers(1, &rb);
+            checkGLcall("RB cleanup");
+        }
+    }
+
+    if (format->glInternal != format->glGammaInternal)
+    {
+        gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, format->glGammaInternal, 16, 16, 0,
+                format->glFormat, format->glType, NULL);
+        gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
+
+        status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER);
+        checkGLcall("Framebuffer format check");
+
+        if (status == GL_FRAMEBUFFER_COMPLETE)
+        {
+            TRACE("Format %s's sRGB format is FBO attachable.\n", debug_d3dformat(format->id));
+            format->flags |= WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB;
+        }
+        else
+        {
+            WARN("Format %s's sRGB format is not FBO attachable.\n", debug_d3dformat(format->id));
+        }
+    }
+    else if (status == GL_FRAMEBUFFER_COMPLETE)
+        format->flags |= WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB;
+
+    gl_info->gl_ops.gl.p_glDeleteTextures(1, &tex);
+}
+
+static void query_format_flag(struct wined3d_gl_info *gl_info, struct wined3d_format *format,
+        GLint internal, GLenum pname, DWORD flag, const char *string)
+{
+    GLint value;
+
+    gl_info->gl_ops.ext.p_glGetInternalformativ(GL_TEXTURE_2D, internal, pname, 1, &value);
+    if (value == GL_FULL_SUPPORT)
+    {
+        TRACE("Format %s supports %s.\n", debug_d3dformat(format->id), string);
+        format->flags |= flag;
+    }
+    else
+    {
+        TRACE("Format %s doesn't support %s.\n", debug_d3dformat(format->id), string);
+        format->flags &= ~flag;
+    }
+}
+
+/* Context activation is done by the caller. */
+static void init_format_fbo_compat_info(struct wined3d_gl_info *gl_info)
+{
+    unsigned int i;
+    GLuint fbo;
+
+    if (gl_info->supported[ARB_INTERNALFORMAT_QUERY2])
+    {
+        for (i = 0; i < sizeof(formats) / sizeof(*formats); ++i)
+        {
+            GLint value;
+            struct wined3d_format *format = &gl_info->formats[i];
+
+            if (!format->glInternal)
+                continue;
+            if (format->flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))
+                continue;
+
+            gl_info->gl_ops.ext.p_glGetInternalformativ(GL_TEXTURE_2D, format->glInternal,
+                    GL_FRAMEBUFFER_RENDERABLE, 1, &value);
+            if (value == GL_FULL_SUPPORT)
+            {
+                TRACE("Format %s is supported as FBO color attachment.\n", debug_d3dformat(format->id));
+                format->flags |= WINED3DFMT_FLAG_FBO_ATTACHABLE;
+                format->rtInternal = format->glInternal;
+
+                query_format_flag(gl_info, format, format->glInternal, GL_FRAMEBUFFER_BLEND,
+                        WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING, "post-pixelshader blending");
+            }
+            else
+            {
+                if (!format->rtInternal)
+                {
+                    if (format->flags & WINED3DFMT_FLAG_RENDERTARGET)
+                    {
+                        WARN("Format %s with rendertarget flag is not supported as FBO color attachment"
+                                " and no fallback specified.\n", debug_d3dformat(format->id));
+                        format->flags &= ~WINED3DFMT_FLAG_RENDERTARGET;
+                    }
+                    else
+                        TRACE("Format %s is not supported as FBO color attachment.\n", debug_d3dformat(format->id));
+                    format->rtInternal = format->glInternal;
+                }
+                else
+                {
+                    gl_info->gl_ops.ext.p_glGetInternalformativ(GL_TEXTURE_2D, format->rtInternal,
+                            GL_FRAMEBUFFER_RENDERABLE, 1, &value);
+                    if (value == GL_FULL_SUPPORT)
+                    {
+                        TRACE("Format %s rtInternal format is supported as FBO color attachment.\n",
+                                debug_d3dformat(format->id));
+                    }
+                    else
+                    {
+                        WARN("Format %s rtInternal format is not supported as FBO color attachment.\n",
+                                debug_d3dformat(format->id));
+                        format->flags &= ~WINED3DFMT_FLAG_RENDERTARGET;
+                    }
+                }
+            }
+
+            if (format->glInternal != format->glGammaInternal)
+            {
+                gl_info->gl_ops.ext.p_glGetInternalformativ(GL_TEXTURE_2D, format->glGammaInternal,
+                        GL_FRAMEBUFFER_RENDERABLE, 1, &value);
+                if (value == GL_FULL_SUPPORT)
+                {
+                    TRACE("Format %s's sRGB format is FBO attachable.\n", debug_d3dformat(format->id));
+                    format->flags |= WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB;
+                }
+                else
+                {
+                    WARN("Format %s's sRGB format is not FBO attachable.\n", debug_d3dformat(format->id));
+                }
+            }
+            else if (format->flags & WINED3DFMT_FLAG_FBO_ATTACHABLE)
+                format->flags |= WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB;
+        }
+        return;
+    }
+
+    if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
+    {
+        gl_info->fbo_ops.glGenFramebuffers(1, &fbo);
+        gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+        gl_info->gl_ops.gl.p_glDrawBuffer(GL_COLOR_ATTACHMENT0);
+        gl_info->gl_ops.gl.p_glReadBuffer(GL_COLOR_ATTACHMENT0);
+    }
+
+    for (i = 0; i < sizeof(formats) / sizeof(*formats); ++i)
+    {
+        struct wined3d_format *format = &gl_info->formats[i];
+
+        if (!format->glInternal) continue;
+
+        if (format->flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))
+        {
+            TRACE("Skipping format %s because it's a depth/stencil format.\n",
+                    debug_d3dformat(format->id));
+            continue;
+        }
+
+        if (format->flags & WINED3DFMT_FLAG_COMPRESSED)
+        {
+            TRACE("Skipping format %s because it's a compressed format.\n",
+                    debug_d3dformat(format->id));
+            continue;
+        }
+
+        if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
+        {
+            TRACE("Checking if format %s is supported as FBO color attachment...\n", debug_d3dformat(format->id));
+            check_fbo_compat(gl_info, format);
+        }
+        else
+        {
+            format->rtInternal = format->glInternal;
+        }
+    }
+
+    if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
+        gl_info->fbo_ops.glDeleteFramebuffers(1, &fbo);
+}
+
+static BOOL init_format_texture_info(struct wined3d_adapter *adapter, struct wined3d_gl_info *gl_info)
+{
+    struct fragment_caps fragment_caps;
+    struct shader_caps shader_caps;
+    BOOL srgb_write;
+    unsigned int i;
+
+    adapter->fragment_pipe->get_caps(gl_info, &fragment_caps);
+    adapter->shader_backend->shader_get_caps(gl_info, &shader_caps);
+    srgb_write = (fragment_caps.wined3d_caps & WINED3D_FRAGMENT_CAP_SRGB_WRITE)
+            && (shader_caps.wined3d_caps & WINED3D_SHADER_CAP_SRGB_WRITE);
+
+    for (i = 0; i < sizeof(format_texture_info) / sizeof(*format_texture_info); ++i)
+    {
+        int fmt_idx = getFmtIdx(format_texture_info[i].id);
+        struct wined3d_format *format;
+
+        if (fmt_idx == -1)
+        {
+            ERR("Format %s (%#x) not found.\n",
+                    debug_d3dformat(format_texture_info[i].id), format_texture_info[i].id);
+            return FALSE;
+        }
+
+        if (!gl_info->supported[format_texture_info[i].extension]) continue;
+
+        format = &gl_info->formats[fmt_idx];
+
+        /* ARB_texture_rg defines floating point formats, but only if
+         * ARB_texture_float is also supported. */
+        if (!gl_info->supported[ARB_TEXTURE_FLOAT]
+                && (format->flags & WINED3DFMT_FLAG_FLOAT))
+            continue;
+
+        format->glInternal = format_texture_info[i].gl_internal;
+        format->glGammaInternal = format_texture_info[i].gl_srgb_internal;
+        format->rtInternal = format_texture_info[i].gl_rt_internal;
+        format->glFormat = format_texture_info[i].gl_format;
+        format->glType = format_texture_info[i].gl_type;
+        format->color_fixup = COLOR_FIXUP_IDENTITY;
+        format->flags |= format_texture_info[i].flags;
+        format->height_scale.numerator = 1;
+        format->height_scale.denominator = 1;
+
+        if (gl_info->supported[ARB_INTERNALFORMAT_QUERY2])
+        {
+            query_format_flag(gl_info, format, format->glInternal, GL_VERTEX_TEXTURE,
+                    WINED3DFMT_FLAG_VTF, "vertex texture usage");
+            query_format_flag(gl_info, format, format->glInternal, GL_FILTER,
+                    WINED3DFMT_FLAG_FILTERING, "filtering");
+
+            if (format->glGammaInternal != format->glInternal)
+            {
+                query_format_flag(gl_info, format, format->glGammaInternal, GL_SRGB_READ,
+                        WINED3DFMT_FLAG_SRGB_READ, "sRGB read");
+
+                if (srgb_write)
+                    query_format_flag(gl_info, format, format->glGammaInternal, GL_SRGB_WRITE,
+                            WINED3DFMT_FLAG_SRGB_WRITE, "sRGB write");
+                else
+                    format->flags &= ~WINED3DFMT_FLAG_SRGB_WRITE;
+
+                if (!(format->flags & (WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_SRGB_WRITE)))
+                    format->glGammaInternal = format->glInternal;
+                else if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
+                    format->glInternal = format->glGammaInternal;
+            }
+        }
+        else
+        {
+        if (!gl_info->limits.vertex_samplers)
+            format->flags &= ~WINED3DFMT_FLAG_VTF;
+
+        if (!(gl_info->quirks & WINED3D_QUIRK_LIMITED_TEX_FILTERING))
+            format->flags |= WINED3DFMT_FLAG_FILTERING;
+        else if (format->id != WINED3DFMT_R32G32B32A32_FLOAT && format->id != WINED3DFMT_R32_FLOAT)
+            format->flags &= ~WINED3DFMT_FLAG_VTF;
+
+        if (format->glGammaInternal != format->glInternal)
+        {
+            /* Filter sRGB capabilities if EXT_texture_sRGB is not supported. */
+            if (!gl_info->supported[EXT_TEXTURE_SRGB])
+            {
+                format->glGammaInternal = format->glInternal;
+                format->flags &= ~(WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_SRGB_WRITE);
+            }
+            else if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
+            {
+                format->glInternal = format->glGammaInternal;
+            }
+        }
+
+        if ((format->flags & WINED3DFMT_FLAG_SRGB_WRITE) && !srgb_write)
+            format->flags &= ~WINED3DFMT_FLAG_SRGB_WRITE;
+        }
+
+        /* Texture conversion stuff */
+        format->convert = format_texture_info[i].convert;
+        format->conv_byte_count = format_texture_info[i].conv_byte_count;
+    }
+
+    return TRUE;
+}
+
+static BOOL color_match(DWORD c1, DWORD c2, BYTE max_diff)
+{
+    if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
+    c1 >>= 8; c2 >>= 8;
+    if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
+    c1 >>= 8; c2 >>= 8;
+    if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
+    c1 >>= 8; c2 >>= 8;
+    if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
+    return TRUE;
+}
+
+/* A context is provided by the caller */
+static BOOL check_filter(const struct wined3d_gl_info *gl_info, GLenum internal)
+{
+    static const DWORD data[] = {0x00000000, 0xffffffff};
+    GLuint tex, fbo, buffer;
+    DWORD readback[16 * 1];
+    BOOL ret = FALSE;
+
+    /* Render a filtered texture and see what happens. This is intended to detect the lack of
+     * float16 filtering on ATI X1000 class cards. The drivers disable filtering instead of
+     * falling back to software. If this changes in the future this code will get fooled and
+     * apps might hit the software path due to incorrectly advertised caps.
+     *
+     * Its unlikely that this changes however. GL Games like Mass Effect depend on the filter
+     * disable fallback, if Apple or ATI ever change the driver behavior they will break more
+     * than Wine. The Linux binary <= r500 driver is not maintained any more anyway
+     */
+
+    while (gl_info->gl_ops.gl.p_glGetError());
+
+    gl_info->gl_ops.gl.p_glGenTextures(1, &buffer);
+    gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, buffer);
+    memset(readback, 0x7e, sizeof(readback));
+    gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 16, 1, 0,
+            GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, readback);
+    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+
+    gl_info->gl_ops.gl.p_glGenTextures(1, &tex);
+    gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, tex);
+    gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, internal, 2, 1, 0,
+            GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data);
+    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+    gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_2D);
+
+    gl_info->fbo_ops.glGenFramebuffers(1, &fbo);
+    gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+    gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, buffer, 0);
+    gl_info->gl_ops.gl.p_glDrawBuffer(GL_COLOR_ATTACHMENT0);
+
+    gl_info->gl_ops.gl.p_glViewport(0, 0, 16, 1);
+    gl_info->gl_ops.gl.p_glDisable(GL_LIGHTING);
+    gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
+    gl_info->gl_ops.gl.p_glLoadIdentity();
+    gl_info->gl_ops.gl.p_glMatrixMode(GL_PROJECTION);
+    gl_info->gl_ops.gl.p_glLoadIdentity();
+
+    gl_info->gl_ops.gl.p_glClearColor(0, 1, 0, 0);
+    gl_info->gl_ops.gl.p_glClear(GL_COLOR_BUFFER_BIT);
+
+    gl_info->gl_ops.gl.p_glBegin(GL_TRIANGLE_STRIP);
+    gl_info->gl_ops.gl.p_glTexCoord2f(0.0, 0.0);
+    gl_info->gl_ops.gl.p_glVertex2f(-1.0f, -1.0f);
+    gl_info->gl_ops.gl.p_glTexCoord2f(1.0, 0.0);
+    gl_info->gl_ops.gl.p_glVertex2f(1.0f, -1.0f);
+    gl_info->gl_ops.gl.p_glTexCoord2f(0.0, 1.0);
+    gl_info->gl_ops.gl.p_glVertex2f(-1.0f, 1.0f);
+    gl_info->gl_ops.gl.p_glTexCoord2f(1.0, 1.0);
+    gl_info->gl_ops.gl.p_glVertex2f(1.0f, 1.0f);
+    gl_info->gl_ops.gl.p_glEnd();
+
+    gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, buffer);
+    memset(readback, 0x7f, sizeof(readback));
+    gl_info->gl_ops.gl.p_glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, readback);
+    if (color_match(readback[6], 0xffffffff, 5) || color_match(readback[6], 0x00000000, 5)
+            || color_match(readback[9], 0xffffffff, 5) || color_match(readback[9], 0x00000000, 5))
+    {
+        TRACE("Read back colors 0x%08x and 0x%08x close to unfiltered color, assuming no filtering\n",
+              readback[6], readback[9]);
+        ret = FALSE;
+    }
+    else
+    {
+        TRACE("Read back colors are 0x%08x and 0x%08x, assuming texture is filtered\n",
+              readback[6], readback[9]);
+        ret = TRUE;
+    }
+
+    gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, 0);
+    gl_info->fbo_ops.glDeleteFramebuffers(1, &fbo);
+    gl_info->gl_ops.gl.p_glDeleteTextures(1, &tex);
+    gl_info->gl_ops.gl.p_glDeleteTextures(1, &buffer);
+
+    if (gl_info->gl_ops.gl.p_glGetError())
+    {
+        FIXME("Error during filtering test for format %x, returning no filtering\n", internal);
+        ret = FALSE;
+    }
+
+    return ret;
+}
+
+static void init_format_filter_info(struct wined3d_gl_info *gl_info, enum wined3d_pci_vendor vendor)
+{
+    struct wined3d_format *format;
+    unsigned int fmt_idx, i;
+    static const enum wined3d_format_id fmts16[] =
+    {
+        WINED3DFMT_R16_FLOAT,
+        WINED3DFMT_R16G16_FLOAT,
+        WINED3DFMT_R16G16B16A16_FLOAT,
+    };
+    BOOL filtered;
+
+    if (gl_info->supported[ARB_INTERNALFORMAT_QUERY2])
+        /* This was already handled by init_format_texture_info(). */
+        return;
+
+    if(wined3d_settings.offscreen_rendering_mode != ORM_FBO)
+    {
+        WARN("No FBO support, or no FBO ORM, guessing filter info from GL caps\n");
+        if (vendor == HW_VENDOR_NVIDIA && gl_info->supported[ARB_TEXTURE_FLOAT])
+        {
+            TRACE("Nvidia card with texture_float support: Assuming float16 blending\n");
+            filtered = TRUE;
+        }
+        else if (gl_info->limits.glsl_varyings > 44)
+        {
+            TRACE("More than 44 GLSL varyings - assuming d3d10 card with float16 blending\n");
+            filtered = TRUE;
+        }
+        else
+        {
+            TRACE("Assuming no float16 blending\n");
+            filtered = FALSE;
+        }
+
+        if(filtered)
+        {
+            for(i = 0; i < (sizeof(fmts16) / sizeof(*fmts16)); i++)
+            {
+                fmt_idx = getFmtIdx(fmts16[i]);
+                gl_info->formats[fmt_idx].flags |= WINED3DFMT_FLAG_FILTERING;
+            }
+        }
+        return;
+    }
+
+    for(i = 0; i < (sizeof(fmts16) / sizeof(*fmts16)); i++)
+    {
+        fmt_idx = getFmtIdx(fmts16[i]);
+        format = &gl_info->formats[fmt_idx];
+        if (!format->glInternal) continue; /* Not supported by GL */
+
+        filtered = check_filter(gl_info, gl_info->formats[fmt_idx].glInternal);
+        if(filtered)
+        {
+            TRACE("Format %s supports filtering\n", debug_d3dformat(fmts16[i]));
+            format->flags |= WINED3DFMT_FLAG_FILTERING;
+        }
+        else
+        {
+            TRACE("Format %s does not support filtering\n", debug_d3dformat(fmts16[i]));
+        }
+    }
+}
+
+static void apply_format_fixups(struct wined3d_adapter *adapter, struct wined3d_gl_info *gl_info)
+{
+    unsigned int i;
+    int idx;
+
+    idx = getFmtIdx(WINED3DFMT_R16_FLOAT);
+    gl_info->formats[idx].color_fixup = create_color_fixup_desc(
+            0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_W);
+
+    idx = getFmtIdx(WINED3DFMT_R32_FLOAT);
+    gl_info->formats[idx].color_fixup = create_color_fixup_desc(
+            0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_W);
+
+    idx = getFmtIdx(WINED3DFMT_R16G16_UNORM);
+    gl_info->formats[idx].color_fixup = create_color_fixup_desc(
+            0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_W);
+
+    idx = getFmtIdx(WINED3DFMT_R16G16_FLOAT);
+    gl_info->formats[idx].color_fixup = create_color_fixup_desc(
+            0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_W);
+
+    idx = getFmtIdx(WINED3DFMT_R32G32_FLOAT);
+    gl_info->formats[idx].color_fixup = create_color_fixup_desc(
+            0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_W);
+
+    /* V8U8 is supported natively by GL_ATI_envmap_bumpmap and GL_NV_texture_shader.
+     * V16U16 is only supported by GL_NV_texture_shader. The formats need fixup if
+     * their extensions are not available. GL_ATI_envmap_bumpmap is not used because
+     * the only driver that implements it(fglrx) has a buggy implementation.
+     *
+     * V8U8 and V16U16 need a fixup of the undefined blue channel. OpenGL
+     * returns 0.0 when sampling from it, DirectX 1.0. So we always have in-shader
+     * conversion for this format.
+     */
+    if (!gl_info->supported[NV_TEXTURE_SHADER])
+    {
+        idx = getFmtIdx(WINED3DFMT_R8G8_SNORM);
+        gl_info->formats[idx].color_fixup = create_color_fixup_desc(
+                1, CHANNEL_SOURCE_X, 1, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE);
+        idx = getFmtIdx(WINED3DFMT_R16G16_SNORM);
+        gl_info->formats[idx].color_fixup = create_color_fixup_desc(
+                1, CHANNEL_SOURCE_X, 1, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE);
+    }
+    else
+    {
+        idx = getFmtIdx(WINED3DFMT_R8G8_SNORM);
+        gl_info->formats[idx].color_fixup = create_color_fixup_desc(
+                0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE);
+
+        idx = getFmtIdx(WINED3DFMT_R16G16_SNORM);
+        gl_info->formats[idx].color_fixup = create_color_fixup_desc(
+                0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE);
+    }
+
+    if (!gl_info->supported[NV_TEXTURE_SHADER])
+    {
+        /* If GL_NV_texture_shader is not supported, those formats are converted, incompatibly
+         * with each other
+         */
+        idx = getFmtIdx(WINED3DFMT_R5G5_SNORM_L6_UNORM);
+        gl_info->formats[idx].color_fixup = create_color_fixup_desc(
+                1, CHANNEL_SOURCE_X, 1, CHANNEL_SOURCE_Z, 0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE);
+        idx = getFmtIdx(WINED3DFMT_R8G8_SNORM_L8X8_UNORM);
+        gl_info->formats[idx].color_fixup = create_color_fixup_desc(
+                1, CHANNEL_SOURCE_X, 1, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_Z, 0, CHANNEL_SOURCE_W);
+        idx = getFmtIdx(WINED3DFMT_R8G8B8A8_SNORM);
+        gl_info->formats[idx].color_fixup = create_color_fixup_desc(
+                1, CHANNEL_SOURCE_X, 1, CHANNEL_SOURCE_Y, 1, CHANNEL_SOURCE_Z, 1, CHANNEL_SOURCE_W);
+    }
+    else
+    {
+        /* If GL_NV_texture_shader is supported, WINED3DFMT_L6V5U5 and WINED3DFMT_X8L8V8U8
+         * are converted at surface loading time, but they do not need any modification in
+         * the shader, thus they are compatible with all WINED3DFMT_UNKNOWN group formats.
+         * WINED3DFMT_Q8W8V8U8 doesn't even need load-time conversion
+         */
+    }
+
+    if (gl_info->supported[EXT_TEXTURE_COMPRESSION_RGTC])
+    {
+        idx = getFmtIdx(WINED3DFMT_ATI2N);
+        gl_info->formats[idx].color_fixup = create_color_fixup_desc(
+                0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE);
+    }
+    else if (gl_info->supported[ATI_TEXTURE_COMPRESSION_3DC])
+    {
+        idx = getFmtIdx(WINED3DFMT_ATI2N);
+        gl_info->formats[idx].color_fixup= create_color_fixup_desc(
+                0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_W, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE);
+    }
+
+    if (!gl_info->supported[APPLE_YCBCR_422])
+    {
+        idx = getFmtIdx(WINED3DFMT_YUY2);
+        gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_YUY2);
+
+        idx = getFmtIdx(WINED3DFMT_UYVY);
+        gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_UYVY);
+    }
+
+    idx = getFmtIdx(WINED3DFMT_YV12);
+    gl_info->formats[idx].flags |= WINED3DFMT_FLAG_HEIGHT_SCALE;
+    gl_info->formats[idx].height_scale.numerator = 3;
+    gl_info->formats[idx].height_scale.denominator = 2;
+    gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_YV12);
+
+    if (gl_info->supported[EXT_PALETTED_TEXTURE] || gl_info->supported[ARB_FRAGMENT_PROGRAM])
+    {
+        idx = getFmtIdx(WINED3DFMT_P8_UINT);
+        gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_P8);
+    }
+
+    if (gl_info->supported[ARB_VERTEX_ARRAY_BGRA])
+    {
+        idx = getFmtIdx(WINED3DFMT_B8G8R8A8_UNORM);
+        gl_info->formats[idx].gl_vtx_format = GL_BGRA;
+    }
+
+    if (gl_info->supported[ARB_HALF_FLOAT_VERTEX])
+    {
+        /* Do not change the size of the type, it is CPU side. We have to change the GPU-side information though.
+         * It is the job of the vertex buffer code to make sure that the vbos have the right format */
+        idx = getFmtIdx(WINED3DFMT_R16G16_FLOAT);
+        gl_info->formats[idx].gl_vtx_type = GL_HALF_FLOAT; /* == GL_HALF_FLOAT_NV */
+
+        idx = getFmtIdx(WINED3DFMT_R16G16B16A16_FLOAT);
+        gl_info->formats[idx].gl_vtx_type = GL_HALF_FLOAT;
+    }
+
+    if (!gl_info->supported[ARB_HALF_FLOAT_PIXEL])
+    {
+        idx = getFmtIdx(WINED3DFMT_R16_FLOAT);
+        gl_info->formats[idx].flags &= ~WINED3DFMT_FLAG_TEXTURE;
+
+        idx = getFmtIdx(WINED3DFMT_R16G16_FLOAT);
+        gl_info->formats[idx].flags &= ~WINED3DFMT_FLAG_TEXTURE;
+
+        idx = getFmtIdx(WINED3DFMT_R16G16B16A16_FLOAT);
+        gl_info->formats[idx].flags &= ~WINED3DFMT_FLAG_TEXTURE;
+    }
+
+    if (gl_info->quirks & WINED3D_QUIRK_BROKEN_RGBA16)
+    {
+        idx = getFmtIdx(WINED3DFMT_R16G16B16A16_UNORM);
+        gl_info->formats[idx].flags &= ~WINED3DFMT_FLAG_TEXTURE;
+    }
+
+    /* ATI instancing hack: Although ATI cards do not support Shader Model
+     * 3.0, they support instancing. To query if the card supports instancing
+     * CheckDeviceFormat() with the special format MAKEFOURCC('I','N','S','T')
+     * is used. Should an application check for this, provide a proper return
+     * value. We can do instancing with all shader versions, but we need
+     * vertex shaders.
+     *
+     * Additionally applications have to set the D3DRS_POINTSIZE render state
+     * to MAKEFOURCC('I','N','S','T') once to enable instancing. Wined3d
+     * doesn't need that and just ignores it.
+     *
+     * With Shader Model 3.0 capable cards Instancing 'just works' in Windows. */
+    /* FIXME: This should just check the shader backend caps. */
+    if (gl_info->supported[ARB_VERTEX_PROGRAM] || gl_info->supported[ARB_VERTEX_SHADER])
+    {
+        idx = getFmtIdx(WINED3DFMT_INST);
+        gl_info->formats[idx].flags |= WINED3DFMT_FLAG_TEXTURE;
+    }
+
+    /* Depth bound test. To query if the card supports it CheckDeviceFormat()
+     * with the special format MAKEFOURCC('N','V','D','B') is used. It is
+     * enabled by setting D3DRS_ADAPTIVETESS_X render state to
+     * MAKEFOURCC('N','V','D','B') and then controlled by setting
+     * D3DRS_ADAPTIVETESS_Z (zMin) and D3DRS_ADAPTIVETESS_W (zMax) to test
+     * value. */
+    if (gl_info->supported[EXT_DEPTH_BOUNDS_TEST])
+    {
+        idx = getFmtIdx(WINED3DFMT_NVDB);
+        gl_info->formats[idx].flags |= WINED3DFMT_FLAG_TEXTURE;
+    }
+
+    /* RESZ aka AMD DX9-level hack for multisampled depth buffer resolve. You query for RESZ
+     * support by checking for availability of MAKEFOURCC('R','E','S','Z') surfaces with
+     * RENDERTARGET usage. */
+    if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT])
+    {
+        idx = getFmtIdx(WINED3DFMT_RESZ);
+        gl_info->formats[idx].flags |= WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET;
+    }
+
+    for (i = 0; i < sizeof(formats) / sizeof(*formats); ++i)
+    {
+        struct wined3d_format *format = &gl_info->formats[i];
+
+        if (!(format->flags & WINED3DFMT_FLAG_TEXTURE))
+            continue;
+
+        if (!adapter->shader_backend->shader_color_fixup_supported(format->color_fixup)
+                || !adapter->fragment_pipe->color_fixup_supported(format->color_fixup))
+            format->flags &= ~WINED3DFMT_FLAG_TEXTURE;
+    }
+}
+
+static BOOL init_format_vertex_info(struct wined3d_gl_info *gl_info)
+{
+    unsigned int i;
+
+    for (i = 0; i < (sizeof(format_vertex_info) / sizeof(*format_vertex_info)); ++i)
+    {
+        struct wined3d_format *format;
+        int fmt_idx = getFmtIdx(format_vertex_info[i].id);
+
+        if (fmt_idx == -1)
+        {
+            ERR("Format %s (%#x) not found.\n",
+                    debug_d3dformat(format_vertex_info[i].id), format_vertex_info[i].id);
+            return FALSE;
+        }
+
+        format = &gl_info->formats[fmt_idx];
+        format->emit_idx = format_vertex_info[i].emit_idx;
+        format->component_count = format_vertex_info[i].component_count;
+        format->gl_vtx_type = format_vertex_info[i].gl_vtx_type;
+        format->gl_vtx_format = format_vertex_info[i].gl_vtx_format;
+        format->gl_normalized = format_vertex_info[i].gl_normalized;
+        format->component_size = format_vertex_info[i].component_size;
+    }
+
+    return TRUE;
+}
+
+BOOL initPixelFormatsNoGL(struct wined3d_gl_info *gl_info)
+{
+    if (!init_format_base_info(gl_info)) return FALSE;
+
+    if (!init_format_block_info(gl_info))
+    {
+        HeapFree(GetProcessHeap(), 0, gl_info->formats);
+        gl_info->formats = NULL;
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+/* Context activation is done by the caller. */
+BOOL wined3d_adapter_init_format_info(struct wined3d_adapter *adapter)
+{
+    struct wined3d_gl_info *gl_info = &adapter->gl_info;
+
+    if (!init_format_base_info(gl_info)) return FALSE;
+
+    if (!init_format_block_info(gl_info)) goto fail;
+    if (!init_format_texture_info(adapter, gl_info)) goto fail;
+    if (!init_format_vertex_info(gl_info)) goto fail;
+
+    apply_format_fixups(adapter, gl_info);
+    init_format_fbo_compat_info(gl_info);
+    init_format_filter_info(gl_info, adapter->driver_info.vendor);
+
+    return TRUE;
+
+fail:
+    HeapFree(GetProcessHeap(), 0, gl_info->formats);
+    gl_info->formats = NULL;
+    return FALSE;
+}
+
+const struct wined3d_format *wined3d_get_format(const struct wined3d_gl_info *gl_info,
+        enum wined3d_format_id format_id)
+{
+    int idx = getFmtIdx(format_id);
+
+    if (idx == -1)
+    {
+        FIXME("Can't find format %s (%#x) in the format lookup table\n",
+                debug_d3dformat(format_id), format_id);
+        /* Get the caller a valid pointer */
+        idx = getFmtIdx(WINED3DFMT_UNKNOWN);
+    }
+
+    return &gl_info->formats[idx];
+}
+
+UINT wined3d_format_calculate_size(const struct wined3d_format *format, UINT alignment, UINT width, UINT height)
+{
+    UINT size;
+
+    if (format->id == WINED3DFMT_UNKNOWN)
+    {
+        size = 0;
+    }
+    else if (format->flags & WINED3DFMT_FLAG_BLOCKS)
+    {
+        UINT row_block_count = (width + format->block_width - 1) / format->block_width;
+        UINT row_count = (height + format->block_height - 1) / format->block_height;
+        size = row_count * (((row_block_count * format->block_byte_count) + alignment - 1) & ~(alignment - 1));
+    }
+    else
+    {
+        size = height * (((width * format->byte_count) + alignment - 1) & ~(alignment - 1));
+    }
+
+    if (format->flags & WINED3DFMT_FLAG_HEIGHT_SCALE)
+    {
+        /* The D3D format requirements make sure that the resulting format is an integer again */
+        size *= format->height_scale.numerator;
+        size /= format->height_scale.denominator;
+    }
+
+    return size;
+}
+
+/*****************************************************************************
+ * Trace formatting of useful values
+ */
+const char *debug_d3dformat(enum wined3d_format_id format_id)
+{
+    switch (format_id)
+    {
+#define FMT_TO_STR(format_id) case format_id: return #format_id
+        FMT_TO_STR(WINED3DFMT_UNKNOWN);
+        FMT_TO_STR(WINED3DFMT_B8G8R8_UNORM);
+        FMT_TO_STR(WINED3DFMT_B5G5R5X1_UNORM);
+        FMT_TO_STR(WINED3DFMT_B4G4R4A4_UNORM);
+        FMT_TO_STR(WINED3DFMT_B2G3R3_UNORM);
+        FMT_TO_STR(WINED3DFMT_B2G3R3A8_UNORM);
+        FMT_TO_STR(WINED3DFMT_B4G4R4X4_UNORM);
+        FMT_TO_STR(WINED3DFMT_R8G8B8X8_UNORM);
+        FMT_TO_STR(WINED3DFMT_B10G10R10A2_UNORM);
+        FMT_TO_STR(WINED3DFMT_P8_UINT_A8_UNORM);
+        FMT_TO_STR(WINED3DFMT_P8_UINT);
+        FMT_TO_STR(WINED3DFMT_L8_UNORM);
+        FMT_TO_STR(WINED3DFMT_L8A8_UNORM);
+        FMT_TO_STR(WINED3DFMT_L4A4_UNORM);
+        FMT_TO_STR(WINED3DFMT_R5G5_SNORM_L6_UNORM);
+        FMT_TO_STR(WINED3DFMT_R8G8_SNORM_L8X8_UNORM);
+        FMT_TO_STR(WINED3DFMT_R10G11B11_SNORM);
+        FMT_TO_STR(WINED3DFMT_R10G10B10_SNORM_A2_UNORM);
+        FMT_TO_STR(WINED3DFMT_UYVY);
+        FMT_TO_STR(WINED3DFMT_YUY2);
+        FMT_TO_STR(WINED3DFMT_YV12);
+        FMT_TO_STR(WINED3DFMT_DXT1);
+        FMT_TO_STR(WINED3DFMT_DXT2);
+        FMT_TO_STR(WINED3DFMT_DXT3);
+        FMT_TO_STR(WINED3DFMT_DXT4);
+        FMT_TO_STR(WINED3DFMT_DXT5);
+        FMT_TO_STR(WINED3DFMT_MULTI2_ARGB8);
+        FMT_TO_STR(WINED3DFMT_G8R8_G8B8);
+        FMT_TO_STR(WINED3DFMT_R8G8_B8G8);
+        FMT_TO_STR(WINED3DFMT_D16_LOCKABLE);
+        FMT_TO_STR(WINED3DFMT_D32_UNORM);
+        FMT_TO_STR(WINED3DFMT_S1_UINT_D15_UNORM);
+        FMT_TO_STR(WINED3DFMT_X8D24_UNORM);
+        FMT_TO_STR(WINED3DFMT_S4X4_UINT_D24_UNORM);
+        FMT_TO_STR(WINED3DFMT_L16_UNORM);
+        FMT_TO_STR(WINED3DFMT_S8_UINT_D24_FLOAT);
+        FMT_TO_STR(WINED3DFMT_VERTEXDATA);
+        FMT_TO_STR(WINED3DFMT_R8G8_SNORM_Cx);
+        FMT_TO_STR(WINED3DFMT_ATI2N);
+        FMT_TO_STR(WINED3DFMT_NVDB);
+        FMT_TO_STR(WINED3DFMT_NVHU);
+        FMT_TO_STR(WINED3DFMT_NVHS);
+        FMT_TO_STR(WINED3DFMT_R32G32B32A32_TYPELESS);
+        FMT_TO_STR(WINED3DFMT_R32G32B32A32_FLOAT);
+        FMT_TO_STR(WINED3DFMT_R32G32B32A32_UINT);
+        FMT_TO_STR(WINED3DFMT_R32G32B32A32_SINT);
+        FMT_TO_STR(WINED3DFMT_R32G32B32_TYPELESS);
+        FMT_TO_STR(WINED3DFMT_R32G32B32_FLOAT);
+        FMT_TO_STR(WINED3DFMT_R32G32B32_UINT);
+        FMT_TO_STR(WINED3DFMT_R32G32B32_SINT);
+        FMT_TO_STR(WINED3DFMT_R16G16B16A16_TYPELESS);
+        FMT_TO_STR(WINED3DFMT_R16G16B16A16_FLOAT);
+        FMT_TO_STR(WINED3DFMT_R16G16B16A16_UNORM);
+        FMT_TO_STR(WINED3DFMT_R16G16B16A16_UINT);
+        FMT_TO_STR(WINED3DFMT_R16G16B16A16_SNORM);
+        FMT_TO_STR(WINED3DFMT_R16G16B16A16_SINT);
+        FMT_TO_STR(WINED3DFMT_R32G32_TYPELESS);
+        FMT_TO_STR(WINED3DFMT_R32G32_FLOAT);
+        FMT_TO_STR(WINED3DFMT_R32G32_UINT);
+        FMT_TO_STR(WINED3DFMT_R32G32_SINT);
+        FMT_TO_STR(WINED3DFMT_R32G8X24_TYPELESS);
+        FMT_TO_STR(WINED3DFMT_D32_FLOAT_S8X24_UINT);
+        FMT_TO_STR(WINED3DFMT_R32_FLOAT_X8X24_TYPELESS);
+        FMT_TO_STR(WINED3DFMT_X32_TYPELESS_G8X24_UINT);
+        FMT_TO_STR(WINED3DFMT_R10G10B10A2_TYPELESS);
+        FMT_TO_STR(WINED3DFMT_R10G10B10A2_UNORM);
+        FMT_TO_STR(WINED3DFMT_R10G10B10A2_UINT);
+        FMT_TO_STR(WINED3DFMT_R10G10B10A2_SNORM);
+        FMT_TO_STR(WINED3DFMT_R11G11B10_FLOAT);
+        FMT_TO_STR(WINED3DFMT_R8G8B8A8_TYPELESS);
+        FMT_TO_STR(WINED3DFMT_R8G8B8A8_UNORM);
+        FMT_TO_STR(WINED3DFMT_R8G8B8A8_UNORM_SRGB);
+        FMT_TO_STR(WINED3DFMT_R8G8B8A8_UINT);
+        FMT_TO_STR(WINED3DFMT_R8G8B8A8_SNORM);
+        FMT_TO_STR(WINED3DFMT_R8G8B8A8_SINT);
+        FMT_TO_STR(WINED3DFMT_R16G16_TYPELESS);
+        FMT_TO_STR(WINED3DFMT_R16G16_FLOAT);
+        FMT_TO_STR(WINED3DFMT_R16G16_UNORM);
+        FMT_TO_STR(WINED3DFMT_R16G16_UINT);
+        FMT_TO_STR(WINED3DFMT_R16G16_SNORM);
+        FMT_TO_STR(WINED3DFMT_R16G16_SINT);
+        FMT_TO_STR(WINED3DFMT_R32_TYPELESS);
+        FMT_TO_STR(WINED3DFMT_D32_FLOAT);
+        FMT_TO_STR(WINED3DFMT_R32_FLOAT);
+        FMT_TO_STR(WINED3DFMT_R32_UINT);
+        FMT_TO_STR(WINED3DFMT_R32_SINT);
+        FMT_TO_STR(WINED3DFMT_R24G8_TYPELESS);
+        FMT_TO_STR(WINED3DFMT_D24_UNORM_S8_UINT);
+        FMT_TO_STR(WINED3DFMT_R24_UNORM_X8_TYPELESS);
+        FMT_TO_STR(WINED3DFMT_X24_TYPELESS_G8_UINT);
+        FMT_TO_STR(WINED3DFMT_R8G8_TYPELESS);
+        FMT_TO_STR(WINED3DFMT_R8G8_UNORM);
+        FMT_TO_STR(WINED3DFMT_R8G8_UINT);
+        FMT_TO_STR(WINED3DFMT_R8G8_SNORM);
+        FMT_TO_STR(WINED3DFMT_R8G8_SINT);
+        FMT_TO_STR(WINED3DFMT_R16_TYPELESS);
+        FMT_TO_STR(WINED3DFMT_R16_FLOAT);
+        FMT_TO_STR(WINED3DFMT_D16_UNORM);
+        FMT_TO_STR(WINED3DFMT_R16_UNORM);
+        FMT_TO_STR(WINED3DFMT_R16_UINT);
+        FMT_TO_STR(WINED3DFMT_R16_SNORM);
+        FMT_TO_STR(WINED3DFMT_R16_SINT);
+        FMT_TO_STR(WINED3DFMT_R8_TYPELESS);
+        FMT_TO_STR(WINED3DFMT_R8_UNORM);
+        FMT_TO_STR(WINED3DFMT_R8_UINT);
+        FMT_TO_STR(WINED3DFMT_R8_SNORM);
+        FMT_TO_STR(WINED3DFMT_R8_SINT);
+        FMT_TO_STR(WINED3DFMT_A8_UNORM);
+        FMT_TO_STR(WINED3DFMT_R1_UNORM);
+        FMT_TO_STR(WINED3DFMT_R9G9B9E5_SHAREDEXP);
+        FMT_TO_STR(WINED3DFMT_R8G8_B8G8_UNORM);
+        FMT_TO_STR(WINED3DFMT_G8R8_G8B8_UNORM);
+        FMT_TO_STR(WINED3DFMT_BC1_TYPELESS);
+        FMT_TO_STR(WINED3DFMT_BC1_UNORM);
+        FMT_TO_STR(WINED3DFMT_BC1_UNORM_SRGB);
+        FMT_TO_STR(WINED3DFMT_BC2_TYPELESS);
+        FMT_TO_STR(WINED3DFMT_BC2_UNORM);
+        FMT_TO_STR(WINED3DFMT_BC2_UNORM_SRGB);
+        FMT_TO_STR(WINED3DFMT_BC3_TYPELESS);
+        FMT_TO_STR(WINED3DFMT_BC3_UNORM);
+        FMT_TO_STR(WINED3DFMT_BC3_UNORM_SRGB);
+        FMT_TO_STR(WINED3DFMT_BC4_TYPELESS);
+        FMT_TO_STR(WINED3DFMT_BC4_UNORM);
+        FMT_TO_STR(WINED3DFMT_BC4_SNORM);
+        FMT_TO_STR(WINED3DFMT_BC5_TYPELESS);
+        FMT_TO_STR(WINED3DFMT_BC5_UNORM);
+        FMT_TO_STR(WINED3DFMT_BC5_SNORM);
+        FMT_TO_STR(WINED3DFMT_B5G6R5_UNORM);
+        FMT_TO_STR(WINED3DFMT_B5G5R5A1_UNORM);
+        FMT_TO_STR(WINED3DFMT_B8G8R8A8_UNORM);
+        FMT_TO_STR(WINED3DFMT_B8G8R8X8_UNORM);
+        FMT_TO_STR(WINED3DFMT_INTZ);
+        FMT_TO_STR(WINED3DFMT_RESZ);
+        FMT_TO_STR(WINED3DFMT_NULL);
+        FMT_TO_STR(WINED3DFMT_R16);
+        FMT_TO_STR(WINED3DFMT_AL16);
+#undef FMT_TO_STR
+        default:
+        {
+            char fourcc[5];
+            fourcc[0] = (char)(format_id);
+            fourcc[1] = (char)(format_id >> 8);
+            fourcc[2] = (char)(format_id >> 16);
+            fourcc[3] = (char)(format_id >> 24);
+            fourcc[4] = 0;
+            if (isprint(fourcc[0]) && isprint(fourcc[1]) && isprint(fourcc[2]) && isprint(fourcc[3]))
+                FIXME("Unrecognized %#x (as fourcc: %s) WINED3DFORMAT!\n", format_id, fourcc);
+            else
+                FIXME("Unrecognized %#x WINED3DFORMAT!\n", format_id);
+        }
+        return "unrecognized";
+    }
+}
+
+const char *debug_d3ddevicetype(enum wined3d_device_type device_type)
+{
+    switch (device_type)
+    {
+#define DEVTYPE_TO_STR(dev) case dev: return #dev
+        DEVTYPE_TO_STR(WINED3D_DEVICE_TYPE_HAL);
+        DEVTYPE_TO_STR(WINED3D_DEVICE_TYPE_REF);
+        DEVTYPE_TO_STR(WINED3D_DEVICE_TYPE_SW);
+#undef DEVTYPE_TO_STR
+        default:
+            FIXME("Unrecognized device type %#x.\n", device_type);
+            return "unrecognized";
+    }
+}
+
+const char *debug_d3dusage(DWORD usage)
+{
+    char buf[333];
+
+    buf[0] = '\0';
+#define WINED3DUSAGE_TO_STR(u) if (usage & u) { strcat(buf, " | "#u); usage &= ~u; }
+    WINED3DUSAGE_TO_STR(WINED3DUSAGE_RENDERTARGET);
+    WINED3DUSAGE_TO_STR(WINED3DUSAGE_DEPTHSTENCIL);
+    WINED3DUSAGE_TO_STR(WINED3DUSAGE_WRITEONLY);
+    WINED3DUSAGE_TO_STR(WINED3DUSAGE_SOFTWAREPROCESSING);
+    WINED3DUSAGE_TO_STR(WINED3DUSAGE_DONOTCLIP);
+    WINED3DUSAGE_TO_STR(WINED3DUSAGE_POINTS);
+    WINED3DUSAGE_TO_STR(WINED3DUSAGE_RTPATCHES);
+    WINED3DUSAGE_TO_STR(WINED3DUSAGE_NPATCHES);
+    WINED3DUSAGE_TO_STR(WINED3DUSAGE_DYNAMIC);
+    WINED3DUSAGE_TO_STR(WINED3DUSAGE_AUTOGENMIPMAP);
+    WINED3DUSAGE_TO_STR(WINED3DUSAGE_DMAP);
+    WINED3DUSAGE_TO_STR(WINED3DUSAGE_STATICDECL);
+    WINED3DUSAGE_TO_STR(WINED3DUSAGE_OVERLAY);
+#undef WINED3DUSAGE_TO_STR
+    if (usage) FIXME("Unrecognized usage flag(s) %#x\n", usage);
+
+    return buf[0] ? wine_dbg_sprintf("%s", &buf[3]) : "0";
+}
+
+const char *debug_d3dusagequery(DWORD usagequery)
+{
+    char buf[238];
+
+    buf[0] = '\0';
+#define WINED3DUSAGEQUERY_TO_STR(u) if (usagequery & u) { strcat(buf, " | "#u); usagequery &= ~u; }
+    WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_FILTER);
+    WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_LEGACYBUMPMAP);
+    WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING);
+    WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_SRGBREAD);
+    WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_SRGBWRITE);
+    WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_VERTEXTEXTURE);
+    WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_WRAPANDMIP);
+#undef WINED3DUSAGEQUERY_TO_STR
+    if (usagequery) FIXME("Unrecognized usage query flag(s) %#x\n", usagequery);
+
+    return buf[0] ? wine_dbg_sprintf("%s", &buf[3]) : "0";
+}
+
+const char *debug_d3ddeclmethod(enum wined3d_decl_method method)
+{
+    switch (method)
+    {
+#define WINED3DDECLMETHOD_TO_STR(u) case u: return #u
+        WINED3DDECLMETHOD_TO_STR(WINED3D_DECL_METHOD_DEFAULT);
+        WINED3DDECLMETHOD_TO_STR(WINED3D_DECL_METHOD_PARTIAL_U);
+        WINED3DDECLMETHOD_TO_STR(WINED3D_DECL_METHOD_PARTIAL_V);
+        WINED3DDECLMETHOD_TO_STR(WINED3D_DECL_METHOD_CROSS_UV);
+        WINED3DDECLMETHOD_TO_STR(WINED3D_DECL_METHOD_UV);
+        WINED3DDECLMETHOD_TO_STR(WINED3D_DECL_METHOD_LOOKUP);
+        WINED3DDECLMETHOD_TO_STR(WINED3D_DECL_METHOD_LOOKUP_PRESAMPLED);
+#undef WINED3DDECLMETHOD_TO_STR
+        default:
+            FIXME("Unrecognized declaration method %#x.\n", method);
+            return "unrecognized";
+    }
+}
+
+const char *debug_d3ddeclusage(enum wined3d_decl_usage usage)
+{
+    switch (usage)
+    {
+#define WINED3DDECLUSAGE_TO_STR(u) case u: return #u
+        WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_POSITION);
+        WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_BLEND_WEIGHT);
+        WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_BLEND_INDICES);
+        WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_NORMAL);
+        WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_PSIZE);
+        WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_TEXCOORD);
+        WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_TANGENT);
+        WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_BINORMAL);
+        WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_TESS_FACTOR);
+        WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_POSITIONT);
+        WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_COLOR);
+        WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_FOG);
+        WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_DEPTH);
+        WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_SAMPLE);
+#undef WINED3DDECLUSAGE_TO_STR
+        default:
+            FIXME("Unrecognized %u declaration usage!\n", usage);
+            return "unrecognized";
+    }
+}
+
+const char *debug_d3dresourcetype(enum wined3d_resource_type resource_type)
+{
+    switch (resource_type)
+    {
+#define RES_TO_STR(res) case res: return #res
+        RES_TO_STR(WINED3D_RTYPE_SURFACE);
+        RES_TO_STR(WINED3D_RTYPE_VOLUME);
+        RES_TO_STR(WINED3D_RTYPE_TEXTURE);
+        RES_TO_STR(WINED3D_RTYPE_VOLUME_TEXTURE);
+        RES_TO_STR(WINED3D_RTYPE_CUBE_TEXTURE);
+        RES_TO_STR(WINED3D_RTYPE_BUFFER);
+#undef  RES_TO_STR
+        default:
+            FIXME("Unrecognized resource type %#x.\n", resource_type);
+            return "unrecognized";
+    }
+}
+
+const char *debug_d3dprimitivetype(enum wined3d_primitive_type primitive_type)
+{
+    switch (primitive_type)
+    {
+#define PRIM_TO_STR(prim) case prim: return #prim
+        PRIM_TO_STR(WINED3D_PT_UNDEFINED);
+        PRIM_TO_STR(WINED3D_PT_POINTLIST);
+        PRIM_TO_STR(WINED3D_PT_LINELIST);
+        PRIM_TO_STR(WINED3D_PT_LINESTRIP);
+        PRIM_TO_STR(WINED3D_PT_TRIANGLELIST);
+        PRIM_TO_STR(WINED3D_PT_TRIANGLESTRIP);
+        PRIM_TO_STR(WINED3D_PT_TRIANGLEFAN);
+        PRIM_TO_STR(WINED3D_PT_LINELIST_ADJ);
+        PRIM_TO_STR(WINED3D_PT_LINESTRIP_ADJ);
+        PRIM_TO_STR(WINED3D_PT_TRIANGLELIST_ADJ);
+        PRIM_TO_STR(WINED3D_PT_TRIANGLESTRIP_ADJ);
+#undef  PRIM_TO_STR
+        default:
+            FIXME("Unrecognized %u primitive type!\n", primitive_type);
+            return "unrecognized";
+    }
+}
+
+const char *debug_d3drenderstate(enum wined3d_render_state state)
+{
+    switch (state)
+    {
+#define D3DSTATE_TO_STR(u) case u: return #u
+        D3DSTATE_TO_STR(WINED3D_RS_ANTIALIAS);
+        D3DSTATE_TO_STR(WINED3D_RS_TEXTUREPERSPECTIVE);
+        D3DSTATE_TO_STR(WINED3D_RS_WRAPU);
+        D3DSTATE_TO_STR(WINED3D_RS_WRAPV);
+        D3DSTATE_TO_STR(WINED3D_RS_ZENABLE);
+        D3DSTATE_TO_STR(WINED3D_RS_FILLMODE);
+        D3DSTATE_TO_STR(WINED3D_RS_SHADEMODE);
+        D3DSTATE_TO_STR(WINED3D_RS_LINEPATTERN);
+        D3DSTATE_TO_STR(WINED3D_RS_MONOENABLE);
+        D3DSTATE_TO_STR(WINED3D_RS_ROP2);
+        D3DSTATE_TO_STR(WINED3D_RS_PLANEMASK);
+        D3DSTATE_TO_STR(WINED3D_RS_ZWRITEENABLE);
+        D3DSTATE_TO_STR(WINED3D_RS_ALPHATESTENABLE);
+        D3DSTATE_TO_STR(WINED3D_RS_LASTPIXEL);
+        D3DSTATE_TO_STR(WINED3D_RS_SRCBLEND);
+        D3DSTATE_TO_STR(WINED3D_RS_DESTBLEND);
+        D3DSTATE_TO_STR(WINED3D_RS_CULLMODE);
+        D3DSTATE_TO_STR(WINED3D_RS_ZFUNC);
+        D3DSTATE_TO_STR(WINED3D_RS_ALPHAREF);
+        D3DSTATE_TO_STR(WINED3D_RS_ALPHAFUNC);
+        D3DSTATE_TO_STR(WINED3D_RS_DITHERENABLE);
+        D3DSTATE_TO_STR(WINED3D_RS_ALPHABLENDENABLE);
+        D3DSTATE_TO_STR(WINED3D_RS_FOGENABLE);
+        D3DSTATE_TO_STR(WINED3D_RS_SPECULARENABLE);
+        D3DSTATE_TO_STR(WINED3D_RS_ZVISIBLE);
+        D3DSTATE_TO_STR(WINED3D_RS_SUBPIXEL);
+        D3DSTATE_TO_STR(WINED3D_RS_SUBPIXELX);
+        D3DSTATE_TO_STR(WINED3D_RS_STIPPLEDALPHA);
+        D3DSTATE_TO_STR(WINED3D_RS_FOGCOLOR);
+        D3DSTATE_TO_STR(WINED3D_RS_FOGTABLEMODE);
+        D3DSTATE_TO_STR(WINED3D_RS_FOGSTART);
+        D3DSTATE_TO_STR(WINED3D_RS_FOGEND);
+        D3DSTATE_TO_STR(WINED3D_RS_FOGDENSITY);
+        D3DSTATE_TO_STR(WINED3D_RS_STIPPLEENABLE);
+        D3DSTATE_TO_STR(WINED3D_RS_EDGEANTIALIAS);
+        D3DSTATE_TO_STR(WINED3D_RS_COLORKEYENABLE);
+        D3DSTATE_TO_STR(WINED3D_RS_MIPMAPLODBIAS);
+        D3DSTATE_TO_STR(WINED3D_RS_RANGEFOGENABLE);
+        D3DSTATE_TO_STR(WINED3D_RS_ANISOTROPY);
+        D3DSTATE_TO_STR(WINED3D_RS_FLUSHBATCH);
+        D3DSTATE_TO_STR(WINED3D_RS_TRANSLUCENTSORTINDEPENDENT);
+        D3DSTATE_TO_STR(WINED3D_RS_STENCILENABLE);
+        D3DSTATE_TO_STR(WINED3D_RS_STENCILFAIL);
+        D3DSTATE_TO_STR(WINED3D_RS_STENCILZFAIL);
+        D3DSTATE_TO_STR(WINED3D_RS_STENCILPASS);
+        D3DSTATE_TO_STR(WINED3D_RS_STENCILFUNC);
+        D3DSTATE_TO_STR(WINED3D_RS_STENCILREF);
+        D3DSTATE_TO_STR(WINED3D_RS_STENCILMASK);
+        D3DSTATE_TO_STR(WINED3D_RS_STENCILWRITEMASK);
+        D3DSTATE_TO_STR(WINED3D_RS_TEXTUREFACTOR);
+        D3DSTATE_TO_STR(WINED3D_RS_WRAP0);
+        D3DSTATE_TO_STR(WINED3D_RS_WRAP1);
+        D3DSTATE_TO_STR(WINED3D_RS_WRAP2);
+        D3DSTATE_TO_STR(WINED3D_RS_WRAP3);
+        D3DSTATE_TO_STR(WINED3D_RS_WRAP4);
+        D3DSTATE_TO_STR(WINED3D_RS_WRAP5);
+        D3DSTATE_TO_STR(WINED3D_RS_WRAP6);
+        D3DSTATE_TO_STR(WINED3D_RS_WRAP7);
+        D3DSTATE_TO_STR(WINED3D_RS_CLIPPING);
+        D3DSTATE_TO_STR(WINED3D_RS_LIGHTING);
+        D3DSTATE_TO_STR(WINED3D_RS_EXTENTS);
+        D3DSTATE_TO_STR(WINED3D_RS_AMBIENT);
+        D3DSTATE_TO_STR(WINED3D_RS_FOGVERTEXMODE);
+        D3DSTATE_TO_STR(WINED3D_RS_COLORVERTEX);
+        D3DSTATE_TO_STR(WINED3D_RS_LOCALVIEWER);
+        D3DSTATE_TO_STR(WINED3D_RS_NORMALIZENORMALS);
+        D3DSTATE_TO_STR(WINED3D_RS_COLORKEYBLENDENABLE);
+        D3DSTATE_TO_STR(WINED3D_RS_DIFFUSEMATERIALSOURCE);
+        D3DSTATE_TO_STR(WINED3D_RS_SPECULARMATERIALSOURCE);
+        D3DSTATE_TO_STR(WINED3D_RS_AMBIENTMATERIALSOURCE);
+        D3DSTATE_TO_STR(WINED3D_RS_EMISSIVEMATERIALSOURCE);
+        D3DSTATE_TO_STR(WINED3D_RS_VERTEXBLEND);
+        D3DSTATE_TO_STR(WINED3D_RS_CLIPPLANEENABLE);
+        D3DSTATE_TO_STR(WINED3D_RS_SOFTWAREVERTEXPROCESSING);
+        D3DSTATE_TO_STR(WINED3D_RS_POINTSIZE);
+        D3DSTATE_TO_STR(WINED3D_RS_POINTSIZE_MIN);
+        D3DSTATE_TO_STR(WINED3D_RS_POINTSPRITEENABLE);
+        D3DSTATE_TO_STR(WINED3D_RS_POINTSCALEENABLE);
+        D3DSTATE_TO_STR(WINED3D_RS_POINTSCALE_A);
+        D3DSTATE_TO_STR(WINED3D_RS_POINTSCALE_B);
+        D3DSTATE_TO_STR(WINED3D_RS_POINTSCALE_C);
+        D3DSTATE_TO_STR(WINED3D_RS_MULTISAMPLEANTIALIAS);
+        D3DSTATE_TO_STR(WINED3D_RS_MULTISAMPLEMASK);
+        D3DSTATE_TO_STR(WINED3D_RS_PATCHEDGESTYLE);
+        D3DSTATE_TO_STR(WINED3D_RS_PATCHSEGMENTS);
+        D3DSTATE_TO_STR(WINED3D_RS_DEBUGMONITORTOKEN);
+        D3DSTATE_TO_STR(WINED3D_RS_POINTSIZE_MAX);
+        D3DSTATE_TO_STR(WINED3D_RS_INDEXEDVERTEXBLENDENABLE);
+        D3DSTATE_TO_STR(WINED3D_RS_COLORWRITEENABLE);
+        D3DSTATE_TO_STR(WINED3D_RS_TWEENFACTOR);
+        D3DSTATE_TO_STR(WINED3D_RS_BLENDOP);
+        D3DSTATE_TO_STR(WINED3D_RS_POSITIONDEGREE);
+        D3DSTATE_TO_STR(WINED3D_RS_NORMALDEGREE);
+        D3DSTATE_TO_STR(WINED3D_RS_SCISSORTESTENABLE);
+        D3DSTATE_TO_STR(WINED3D_RS_SLOPESCALEDEPTHBIAS);
+        D3DSTATE_TO_STR(WINED3D_RS_ANTIALIASEDLINEENABLE);
+        D3DSTATE_TO_STR(WINED3D_RS_MINTESSELLATIONLEVEL);
+        D3DSTATE_TO_STR(WINED3D_RS_MAXTESSELLATIONLEVEL);
+        D3DSTATE_TO_STR(WINED3D_RS_ADAPTIVETESS_X);
+        D3DSTATE_TO_STR(WINED3D_RS_ADAPTIVETESS_Y);
+        D3DSTATE_TO_STR(WINED3D_RS_ADAPTIVETESS_Z);
+        D3DSTATE_TO_STR(WINED3D_RS_ADAPTIVETESS_W);
+        D3DSTATE_TO_STR(WINED3D_RS_ENABLEADAPTIVETESSELLATION);
+        D3DSTATE_TO_STR(WINED3D_RS_TWOSIDEDSTENCILMODE);
+        D3DSTATE_TO_STR(WINED3D_RS_CCW_STENCILFAIL);
+        D3DSTATE_TO_STR(WINED3D_RS_CCW_STENCILZFAIL);
+        D3DSTATE_TO_STR(WINED3D_RS_CCW_STENCILPASS);
+        D3DSTATE_TO_STR(WINED3D_RS_CCW_STENCILFUNC);
+        D3DSTATE_TO_STR(WINED3D_RS_COLORWRITEENABLE1);
+        D3DSTATE_TO_STR(WINED3D_RS_COLORWRITEENABLE2);
+        D3DSTATE_TO_STR(WINED3D_RS_COLORWRITEENABLE3);
+        D3DSTATE_TO_STR(WINED3D_RS_BLENDFACTOR);
+        D3DSTATE_TO_STR(WINED3D_RS_SRGBWRITEENABLE);
+        D3DSTATE_TO_STR(WINED3D_RS_DEPTHBIAS);
+        D3DSTATE_TO_STR(WINED3D_RS_WRAP8);
+        D3DSTATE_TO_STR(WINED3D_RS_WRAP9);
+        D3DSTATE_TO_STR(WINED3D_RS_WRAP10);
+        D3DSTATE_TO_STR(WINED3D_RS_WRAP11);
+        D3DSTATE_TO_STR(WINED3D_RS_WRAP12);
+        D3DSTATE_TO_STR(WINED3D_RS_WRAP13);
+        D3DSTATE_TO_STR(WINED3D_RS_WRAP14);
+        D3DSTATE_TO_STR(WINED3D_RS_WRAP15);
+        D3DSTATE_TO_STR(WINED3D_RS_SEPARATEALPHABLENDENABLE);
+        D3DSTATE_TO_STR(WINED3D_RS_SRCBLENDALPHA);
+        D3DSTATE_TO_STR(WINED3D_RS_DESTBLENDALPHA);
+        D3DSTATE_TO_STR(WINED3D_RS_BLENDOPALPHA);
+#undef D3DSTATE_TO_STR
+        default:
+            FIXME("Unrecognized %u render state!\n", state);
+            return "unrecognized";
+    }
+}
+
+const char *debug_d3dsamplerstate(enum wined3d_sampler_state state)
+{
+    switch (state)
+    {
+#define D3DSTATE_TO_STR(u) case u: return #u
+        D3DSTATE_TO_STR(WINED3D_SAMP_BORDER_COLOR);
+        D3DSTATE_TO_STR(WINED3D_SAMP_ADDRESS_U);
+        D3DSTATE_TO_STR(WINED3D_SAMP_ADDRESS_V);
+        D3DSTATE_TO_STR(WINED3D_SAMP_ADDRESS_W);
+        D3DSTATE_TO_STR(WINED3D_SAMP_MAG_FILTER);
+        D3DSTATE_TO_STR(WINED3D_SAMP_MIN_FILTER);
+        D3DSTATE_TO_STR(WINED3D_SAMP_MIP_FILTER);
+        D3DSTATE_TO_STR(WINED3D_SAMP_MIPMAP_LOD_BIAS);
+        D3DSTATE_TO_STR(WINED3D_SAMP_MAX_MIP_LEVEL);
+        D3DSTATE_TO_STR(WINED3D_SAMP_MAX_ANISOTROPY);
+        D3DSTATE_TO_STR(WINED3D_SAMP_SRGB_TEXTURE);
+        D3DSTATE_TO_STR(WINED3D_SAMP_ELEMENT_INDEX);
+        D3DSTATE_TO_STR(WINED3D_SAMP_DMAP_OFFSET);
+#undef D3DSTATE_TO_STR
+        default:
+            FIXME("Unrecognized %u sampler state!\n", state);
+            return "unrecognized";
+    }
+}
+
+const char *debug_d3dtexturefiltertype(enum wined3d_texture_filter_type filter_type)
+{
+    switch (filter_type)
+    {
+#define D3DTEXTUREFILTERTYPE_TO_STR(u) case u: return #u
+        D3DTEXTUREFILTERTYPE_TO_STR(WINED3D_TEXF_NONE);
+        D3DTEXTUREFILTERTYPE_TO_STR(WINED3D_TEXF_POINT);
+        D3DTEXTUREFILTERTYPE_TO_STR(WINED3D_TEXF_LINEAR);
+        D3DTEXTUREFILTERTYPE_TO_STR(WINED3D_TEXF_ANISOTROPIC);
+        D3DTEXTUREFILTERTYPE_TO_STR(WINED3D_TEXF_FLAT_CUBIC);
+        D3DTEXTUREFILTERTYPE_TO_STR(WINED3D_TEXF_GAUSSIAN_CUBIC);
+        D3DTEXTUREFILTERTYPE_TO_STR(WINED3D_TEXF_PYRAMIDAL_QUAD);
+        D3DTEXTUREFILTERTYPE_TO_STR(WINED3D_TEXF_GAUSSIAN_QUAD);
+#undef D3DTEXTUREFILTERTYPE_TO_STR
+        default:
+            FIXME("Unrecognied texture filter type 0x%08x.\n", filter_type);
+            return "unrecognized";
+    }
+}
+
+const char *debug_d3dtexturestate(enum wined3d_texture_stage_state state)
+{
+    switch (state)
+    {
+#define D3DSTATE_TO_STR(u) case u: return #u
+        D3DSTATE_TO_STR(WINED3D_TSS_COLOR_OP);
+        D3DSTATE_TO_STR(WINED3D_TSS_COLOR_ARG1);
+        D3DSTATE_TO_STR(WINED3D_TSS_COLOR_ARG2);
+        D3DSTATE_TO_STR(WINED3D_TSS_ALPHA_OP);
+        D3DSTATE_TO_STR(WINED3D_TSS_ALPHA_ARG1);
+        D3DSTATE_TO_STR(WINED3D_TSS_ALPHA_ARG2);
+        D3DSTATE_TO_STR(WINED3D_TSS_BUMPENV_MAT00);
+        D3DSTATE_TO_STR(WINED3D_TSS_BUMPENV_MAT01);
+        D3DSTATE_TO_STR(WINED3D_TSS_BUMPENV_MAT10);
+        D3DSTATE_TO_STR(WINED3D_TSS_BUMPENV_MAT11);
+        D3DSTATE_TO_STR(WINED3D_TSS_TEXCOORD_INDEX);
+        D3DSTATE_TO_STR(WINED3D_TSS_BUMPENV_LSCALE);
+        D3DSTATE_TO_STR(WINED3D_TSS_BUMPENV_LOFFSET);
+        D3DSTATE_TO_STR(WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS);
+        D3DSTATE_TO_STR(WINED3D_TSS_COLOR_ARG0);
+        D3DSTATE_TO_STR(WINED3D_TSS_ALPHA_ARG0);
+        D3DSTATE_TO_STR(WINED3D_TSS_RESULT_ARG);
+        D3DSTATE_TO_STR(WINED3D_TSS_CONSTANT);
+#undef D3DSTATE_TO_STR
+        default:
+            FIXME("Unrecognized %u texture state!\n", state);
+            return "unrecognized";
+    }
+}
+
+const char *debug_d3dtop(enum wined3d_texture_op d3dtop)
+{
+    switch (d3dtop)
+    {
+#define D3DTOP_TO_STR(u) case u: return #u
+        D3DTOP_TO_STR(WINED3D_TOP_DISABLE);
+        D3DTOP_TO_STR(WINED3D_TOP_SELECT_ARG1);
+        D3DTOP_TO_STR(WINED3D_TOP_SELECT_ARG2);
+        D3DTOP_TO_STR(WINED3D_TOP_MODULATE);
+        D3DTOP_TO_STR(WINED3D_TOP_MODULATE_2X);
+        D3DTOP_TO_STR(WINED3D_TOP_MODULATE_4X);
+        D3DTOP_TO_STR(WINED3D_TOP_ADD);
+        D3DTOP_TO_STR(WINED3D_TOP_ADD_SIGNED);
+        D3DTOP_TO_STR(WINED3D_TOP_ADD_SIGNED_2X);
+        D3DTOP_TO_STR(WINED3D_TOP_SUBTRACT);
+        D3DTOP_TO_STR(WINED3D_TOP_ADD_SMOOTH);
+        D3DTOP_TO_STR(WINED3D_TOP_BLEND_DIFFUSE_ALPHA);
+        D3DTOP_TO_STR(WINED3D_TOP_BLEND_TEXTURE_ALPHA);
+        D3DTOP_TO_STR(WINED3D_TOP_BLEND_FACTOR_ALPHA);
+        D3DTOP_TO_STR(WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM);
+        D3DTOP_TO_STR(WINED3D_TOP_BLEND_CURRENT_ALPHA);
+        D3DTOP_TO_STR(WINED3D_TOP_PREMODULATE);
+        D3DTOP_TO_STR(WINED3D_TOP_MODULATE_ALPHA_ADD_COLOR);
+        D3DTOP_TO_STR(WINED3D_TOP_MODULATE_COLOR_ADD_ALPHA);
+        D3DTOP_TO_STR(WINED3D_TOP_MODULATE_INVALPHA_ADD_COLOR);
+        D3DTOP_TO_STR(WINED3D_TOP_MODULATE_INVCOLOR_ADD_ALPHA);
+        D3DTOP_TO_STR(WINED3D_TOP_BUMPENVMAP);
+        D3DTOP_TO_STR(WINED3D_TOP_BUMPENVMAP_LUMINANCE);
+        D3DTOP_TO_STR(WINED3D_TOP_DOTPRODUCT3);
+        D3DTOP_TO_STR(WINED3D_TOP_MULTIPLY_ADD);
+        D3DTOP_TO_STR(WINED3D_TOP_LERP);
+#undef D3DTOP_TO_STR
+        default:
+            FIXME("Unrecognized texture op %#x.\n", d3dtop);
+            return "unrecognized";
+    }
+}
+
+const char *debug_d3dtstype(enum wined3d_transform_state tstype)
+{
+    switch (tstype)
+    {
+#define TSTYPE_TO_STR(tstype) case tstype: return #tstype
+    TSTYPE_TO_STR(WINED3D_TS_VIEW);
+    TSTYPE_TO_STR(WINED3D_TS_PROJECTION);
+    TSTYPE_TO_STR(WINED3D_TS_TEXTURE0);
+    TSTYPE_TO_STR(WINED3D_TS_TEXTURE1);
+    TSTYPE_TO_STR(WINED3D_TS_TEXTURE2);
+    TSTYPE_TO_STR(WINED3D_TS_TEXTURE3);
+    TSTYPE_TO_STR(WINED3D_TS_TEXTURE4);
+    TSTYPE_TO_STR(WINED3D_TS_TEXTURE5);
+    TSTYPE_TO_STR(WINED3D_TS_TEXTURE6);
+    TSTYPE_TO_STR(WINED3D_TS_TEXTURE7);
+    TSTYPE_TO_STR(WINED3D_TS_WORLD_MATRIX(0));
+#undef TSTYPE_TO_STR
+    default:
+        if (tstype > 256 && tstype < 512)
+        {
+            FIXME("WINED3D_TS_WORLD_MATRIX(%u). 1..255 not currently supported.\n", tstype);
+            return ("WINED3D_TS_WORLD_MATRIX > 0");
+        }
+        FIXME("Unrecognized transform state %#x.\n", tstype);
+        return "unrecognized";
+    }
+}
+
+const char *debug_d3dstate(DWORD state)
+{
+    if (STATE_IS_RENDER(state))
+        return wine_dbg_sprintf("STATE_RENDER(%s)", debug_d3drenderstate(state - STATE_RENDER(0)));
+    if (STATE_IS_TEXTURESTAGE(state))
+    {
+        DWORD texture_stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
+        DWORD texture_state = state - STATE_TEXTURESTAGE(texture_stage, 0);
+        return wine_dbg_sprintf("STATE_TEXTURESTAGE(%#x, %s)",
+                texture_stage, debug_d3dtexturestate(texture_state));
+    }
+    if (STATE_IS_SAMPLER(state))
+        return wine_dbg_sprintf("STATE_SAMPLER(%#x)", state - STATE_SAMPLER(0));
+    if (STATE_IS_PIXELSHADER(state))
+        return "STATE_PIXELSHADER";
+    if (STATE_IS_TRANSFORM(state))
+        return wine_dbg_sprintf("STATE_TRANSFORM(%s)", debug_d3dtstype(state - STATE_TRANSFORM(0)));
+    if (STATE_IS_STREAMSRC(state))
+        return "STATE_STREAMSRC";
+    if (STATE_IS_INDEXBUFFER(state))
+        return "STATE_INDEXBUFFER";
+    if (STATE_IS_VDECL(state))
+        return "STATE_VDECL";
+    if (STATE_IS_VSHADER(state))
+        return "STATE_VSHADER";
+    if (STATE_IS_GEOMETRY_SHADER(state))
+        return "STATE_GEOMETRY_SHADER";
+    if (STATE_IS_VIEWPORT(state))
+        return "STATE_VIEWPORT";
+    if (STATE_IS_VERTEXSHADERCONSTANT(state))
+        return "STATE_VERTEXSHADERCONSTANT";
+    if (STATE_IS_PIXELSHADERCONSTANT(state))
+        return "STATE_PIXELSHADERCONSTANT";
+    if (STATE_IS_LIGHT_TYPE(state))
+        return "STATE_LIGHT_TYPE";
+    if (STATE_IS_ACTIVELIGHT(state))
+        return wine_dbg_sprintf("STATE_ACTIVELIGHT(%#x)", state - STATE_ACTIVELIGHT(0));
+    if (STATE_IS_SCISSORRECT(state))
+        return "STATE_SCISSORRECT";
+    if (STATE_IS_CLIPPLANE(state))
+        return wine_dbg_sprintf("STATE_CLIPPLANE(%#x)", state - STATE_CLIPPLANE(0));
+    if (STATE_IS_MATERIAL(state))
+        return "STATE_MATERIAL";
+    if (STATE_IS_FRONTFACE(state))
+        return "STATE_FRONTFACE";
+    if (STATE_IS_POINTSPRITECOORDORIGIN(state))
+        return "STATE_POINTSPRITECOORDORIGIN";
+    if (STATE_IS_BASEVERTEXINDEX(state))
+        return "STATE_BASEVERTEXINDEX";
+    if (STATE_IS_FRAMEBUFFER(state))
+        return "STATE_FRAMEBUFFER";
+    if (STATE_IS_POINT_SIZE_ENABLE(state))
+        return "STATE_POINT_SIZE_ENABLE";
+
+    return wine_dbg_sprintf("UNKNOWN_STATE(%#x)", state);
+}
+
+const char *debug_d3dpool(enum wined3d_pool pool)
+{
+    switch (pool)
+    {
+#define POOL_TO_STR(p) case p: return #p
+        POOL_TO_STR(WINED3D_POOL_DEFAULT);
+        POOL_TO_STR(WINED3D_POOL_MANAGED);
+        POOL_TO_STR(WINED3D_POOL_SYSTEM_MEM);
+        POOL_TO_STR(WINED3D_POOL_SCRATCH);
+#undef  POOL_TO_STR
+        default:
+            FIXME("Unrecognized pool %#x.\n", pool);
+            return "unrecognized";
+    }
+}
+
+const char *debug_fbostatus(GLenum status) {
+    switch(status) {
+#define FBOSTATUS_TO_STR(u) case u: return #u
+        FBOSTATUS_TO_STR(GL_FRAMEBUFFER_COMPLETE);
+        FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
+        FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT);
+        FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT);
+        FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT);
+        FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER);
+        FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER);
+        FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE);
+        FBOSTATUS_TO_STR(GL_FRAMEBUFFER_UNSUPPORTED);
+        FBOSTATUS_TO_STR(GL_FRAMEBUFFER_UNDEFINED);
+#undef FBOSTATUS_TO_STR
+        default:
+            FIXME("Unrecognied FBO status 0x%08x\n", status);
+            return "unrecognized";
+    }
+}
+
+const char *debug_glerror(GLenum error) {
+    switch(error) {
+#define GLERROR_TO_STR(u) case u: return #u
+        GLERROR_TO_STR(GL_NO_ERROR);
+        GLERROR_TO_STR(GL_INVALID_ENUM);
+        GLERROR_TO_STR(GL_INVALID_VALUE);
+        GLERROR_TO_STR(GL_INVALID_OPERATION);
+        GLERROR_TO_STR(GL_STACK_OVERFLOW);
+        GLERROR_TO_STR(GL_STACK_UNDERFLOW);
+        GLERROR_TO_STR(GL_OUT_OF_MEMORY);
+        GLERROR_TO_STR(GL_INVALID_FRAMEBUFFER_OPERATION);
+#undef GLERROR_TO_STR
+        default:
+            FIXME("Unrecognied GL error 0x%08x\n", error);
+            return "unrecognized";
+    }
+}
+
+static const char *debug_fixup_channel_source(enum fixup_channel_source source)
+{
+    switch(source)
+    {
+#define WINED3D_TO_STR(x) case x: return #x
+        WINED3D_TO_STR(CHANNEL_SOURCE_ZERO);
+        WINED3D_TO_STR(CHANNEL_SOURCE_ONE);
+        WINED3D_TO_STR(CHANNEL_SOURCE_X);
+        WINED3D_TO_STR(CHANNEL_SOURCE_Y);
+        WINED3D_TO_STR(CHANNEL_SOURCE_Z);
+        WINED3D_TO_STR(CHANNEL_SOURCE_W);
+        WINED3D_TO_STR(CHANNEL_SOURCE_COMPLEX0);
+        WINED3D_TO_STR(CHANNEL_SOURCE_COMPLEX1);
+#undef WINED3D_TO_STR
+        default:
+            FIXME("Unrecognized fixup_channel_source %#x\n", source);
+            return "unrecognized";
+    }
+}
+
+static const char *debug_complex_fixup(enum complex_fixup fixup)
+{
+    switch(fixup)
+    {
+#define WINED3D_TO_STR(x) case x: return #x
+        WINED3D_TO_STR(COMPLEX_FIXUP_YUY2);
+        WINED3D_TO_STR(COMPLEX_FIXUP_UYVY);
+        WINED3D_TO_STR(COMPLEX_FIXUP_YV12);
+        WINED3D_TO_STR(COMPLEX_FIXUP_P8);
+#undef WINED3D_TO_STR
+        default:
+            FIXME("Unrecognized complex fixup %#x\n", fixup);
+            return "unrecognized";
+    }
+}
+
+void dump_color_fixup_desc(struct color_fixup_desc fixup)
+{
+    if (is_complex_fixup(fixup))
+    {
+        TRACE("\tComplex: %s\n", debug_complex_fixup(get_complex_fixup(fixup)));
+        return;
+    }
+
+    TRACE("\tX: %s%s\n", debug_fixup_channel_source(fixup.x_source), fixup.x_sign_fixup ? ", SIGN_FIXUP" : "");
+    TRACE("\tY: %s%s\n", debug_fixup_channel_source(fixup.y_source), fixup.y_sign_fixup ? ", SIGN_FIXUP" : "");
+    TRACE("\tZ: %s%s\n", debug_fixup_channel_source(fixup.z_source), fixup.z_sign_fixup ? ", SIGN_FIXUP" : "");
+    TRACE("\tW: %s%s\n", debug_fixup_channel_source(fixup.w_source), fixup.w_sign_fixup ? ", SIGN_FIXUP" : "");
+}
+
+const char *debug_surflocation(DWORD flag) {
+    char buf[128];
+
+    buf[0] = 0;
+    if (flag & SFLAG_INSYSMEM) strcat(buf, " | SFLAG_INSYSMEM");                    /* 17 */
+    if (flag & SFLAG_INDRAWABLE) strcat(buf, " | SFLAG_INDRAWABLE");                /* 19 */
+    if (flag & SFLAG_INTEXTURE) strcat(buf, " | SFLAG_INTEXTURE");                  /* 18 */
+    if (flag & SFLAG_INSRGBTEX) strcat(buf, " | SFLAG_INSRGBTEX");                  /* 18 */
+    if (flag & SFLAG_INRB_MULTISAMPLE) strcat(buf, " | SFLAG_INRB_MULTISAMPLE");    /* 25 */
+    if (flag & SFLAG_INRB_RESOLVED) strcat(buf, " | SFLAG_INRB_RESOLVED");          /* 22 */
+    return wine_dbg_sprintf("%s", buf[0] ? buf + 3 : "0");
+}
+
+BOOL is_invalid_op(const struct wined3d_state *state, int stage,
+        enum wined3d_texture_op op, DWORD arg1, DWORD arg2, DWORD arg3)
+{
+    if (op == WINED3D_TOP_DISABLE)
+        return FALSE;
+    if (state->textures[stage])
+        return FALSE;
+
+    if ((arg1 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
+            && op != WINED3D_TOP_SELECT_ARG2)
+        return TRUE;
+    if ((arg2 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
+            && op != WINED3D_TOP_SELECT_ARG1)
+        return TRUE;
+    if ((arg3 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
+            && (op == WINED3D_TOP_MULTIPLY_ADD || op == WINED3D_TOP_LERP))
+        return TRUE;
+
+    return FALSE;
+}
+
+/* Setup this textures matrix according to the texture flags. */
+/* Context activation is done by the caller (state handler). */
+void set_texture_matrix(const struct wined3d_gl_info *gl_info, const float *smat, DWORD flags,
+        BOOL calculatedCoords, BOOL transformed, enum wined3d_format_id vtx_fmt, BOOL ffp_proj_control)
+{
+    float mat[16];
+
+    gl_info->gl_ops.gl.p_glMatrixMode(GL_TEXTURE);
+    checkGLcall("glMatrixMode(GL_TEXTURE)");
+
+    if (flags == WINED3D_TTFF_DISABLE || flags == WINED3D_TTFF_COUNT1 || transformed)
+    {
+        gl_info->gl_ops.gl.p_glLoadIdentity();
+        checkGLcall("glLoadIdentity()");
+        return;
+    }
+
+    if (flags == (WINED3D_TTFF_COUNT1 | WINED3D_TTFF_PROJECTED))
+    {
+        ERR("Invalid texture transform flags: WINED3D_TTFF_COUNT1 | WINED3D_TTFF_PROJECTED.\n");
+        return;
+    }
+
+    memcpy(mat, smat, 16 * sizeof(float));
+
+    if (flags & WINED3D_TTFF_PROJECTED)
+    {
+        if (!ffp_proj_control)
+        {
+            switch (flags & ~WINED3D_TTFF_PROJECTED)
+            {
+                case WINED3D_TTFF_COUNT2:
+                    mat[ 3] = mat[ 1];
+                    mat[ 7] = mat[ 5];
+                    mat[11] = mat[ 9];
+                    mat[15] = mat[13];
+                    mat[ 1] = mat[ 5] = mat[ 9] = mat[13] = 0.0f;
+                    break;
+                case WINED3D_TTFF_COUNT3:
+                    mat[ 3] = mat[ 2];
+                    mat[ 7] = mat[ 6];
+                    mat[11] = mat[10];
+                    mat[15] = mat[14];
+                    mat[ 2] = mat[ 6] = mat[10] = mat[14] = 0.0f;
+                    break;
+            }
+        }
+    } else { /* under directx the R/Z coord can be used for translation, under opengl we use the Q coord instead */
+        if(!calculatedCoords) {
+            switch(vtx_fmt)
+            {
+                case WINED3DFMT_R32_FLOAT:
+                    /* Direct3D passes the default 1.0 in the 2nd coord, while gl passes it in the 4th.
+                     * swap 2nd and 4th coord. No need to store the value of mat[12] in mat[4] because
+                     * the input value to the transformation will be 0, so the matrix value is irrelevant
+                     */
+                    mat[12] = mat[4];
+                    mat[13] = mat[5];
+                    mat[14] = mat[6];
+                    mat[15] = mat[7];
+                    break;
+                case WINED3DFMT_R32G32_FLOAT:
+                    /* See above, just 3rd and 4th coord
+                    */
+                    mat[12] = mat[8];
+                    mat[13] = mat[9];
+                    mat[14] = mat[10];
+                    mat[15] = mat[11];
+                    break;
+                case WINED3DFMT_R32G32B32_FLOAT: /* Opengl defaults match dx defaults */
+                case WINED3DFMT_R32G32B32A32_FLOAT: /* No defaults apply, all app defined */
+
+                /* This is to prevent swapping the matrix lines and put the default 4th coord = 1.0
+                 * into a bad place. The division elimination below will apply to make sure the
+                 * 1.0 doesn't do anything bad. The caller will set this value if the stride is 0
+                 */
+                case WINED3DFMT_UNKNOWN: /* No texture coords, 0/0/0/1 defaults are passed */
+                    break;
+                default:
+                    FIXME("Unexpected fixed function texture coord input\n");
+            }
+        }
+        if (!ffp_proj_control)
+        {
+            switch (flags & ~WINED3D_TTFF_PROJECTED)
+            {
+                /* case WINED3D_TTFF_COUNT1: Won't ever get here. */
+                case WINED3D_TTFF_COUNT2:
+                    mat[2] = mat[6] = mat[10] = mat[14] = 0;
+                /* OpenGL divides the first 3 vertex coord by the 4th by default,
+                * which is essentially the same as D3DTTFF_PROJECTED. Make sure that
+                * the 4th coord evaluates to 1.0 to eliminate that.
+                *
+                * If the fixed function pipeline is used, the 4th value remains unused,
+                * so there is no danger in doing this. With vertex shaders we have a
+                * problem. Should an app hit that problem, the code here would have to
+                * check for pixel shaders, and the shader has to undo the default gl divide.
+                *
+                * A more serious problem occurs if the app passes 4 coordinates in, and the
+                * 4th is != 1.0(opengl default). This would have to be fixed in drawStridedSlow
+                * or a replacement shader. */
+                default:
+                    mat[3] = mat[7] = mat[11] = 0; mat[15] = 1;
+            }
+        }
+    }
+
+    gl_info->gl_ops.gl.p_glLoadMatrixf(mat);
+    checkGLcall("glLoadMatrixf(mat)");
+}
+
+/* This small helper function is used to convert a bitmask into the number of masked bits */
+unsigned int count_bits(unsigned int mask)
+{
+    unsigned int count;
+    for (count = 0; mask; ++count)
+    {
+        mask &= mask - 1;
+    }
+    return count;
+}
+
+/* Helper function for retrieving color info for ChoosePixelFormat and wglChoosePixelFormatARB.
+ * The later function requires individual color components. */
+BOOL getColorBits(const struct wined3d_format *format,
+        BYTE *redSize, BYTE *greenSize, BYTE *blueSize, BYTE *alphaSize, BYTE *totalSize)
+{
+    TRACE("format %s.\n", debug_d3dformat(format->id));
+
+    switch (format->id)
+    {
+        case WINED3DFMT_B10G10R10A2_UNORM:
+        case WINED3DFMT_R10G10B10A2_UNORM:
+        case WINED3DFMT_B8G8R8X8_UNORM:
+        case WINED3DFMT_B8G8R8_UNORM:
+        case WINED3DFMT_B8G8R8A8_UNORM:
+        case WINED3DFMT_R8G8B8A8_UNORM:
+        case WINED3DFMT_B5G5R5X1_UNORM:
+        case WINED3DFMT_B5G5R5A1_UNORM:
+        case WINED3DFMT_B5G6R5_UNORM:
+        case WINED3DFMT_B4G4R4X4_UNORM:
+        case WINED3DFMT_B4G4R4A4_UNORM:
+        case WINED3DFMT_B2G3R3_UNORM:
+        case WINED3DFMT_P8_UINT_A8_UNORM:
+        case WINED3DFMT_P8_UINT:
+            break;
+        default:
+            FIXME("Unsupported format %s.\n", debug_d3dformat(format->id));
+            return FALSE;
+    }
+
+    *redSize = format->red_size;
+    *greenSize = format->green_size;
+    *blueSize = format->blue_size;
+    *alphaSize = format->alpha_size;
+    *totalSize = *redSize + *greenSize + *blueSize + *alphaSize;
+
+    TRACE("Returning red: %d, green: %d, blue: %d, alpha: %d, total: %d for format %s.\n",
+            *redSize, *greenSize, *blueSize, *alphaSize, *totalSize, debug_d3dformat(format->id));
+    return TRUE;
+}
+
+/* Helper function for retrieving depth/stencil info for ChoosePixelFormat and wglChoosePixelFormatARB */
+BOOL getDepthStencilBits(const struct wined3d_format *format, BYTE *depthSize, BYTE *stencilSize)
+{
+    TRACE("format %s.\n", debug_d3dformat(format->id));
+
+    switch (format->id)
+    {
+        case WINED3DFMT_D16_LOCKABLE:
+        case WINED3DFMT_D16_UNORM:
+        case WINED3DFMT_S1_UINT_D15_UNORM:
+        case WINED3DFMT_X8D24_UNORM:
+        case WINED3DFMT_S4X4_UINT_D24_UNORM:
+        case WINED3DFMT_D24_UNORM_S8_UINT:
+        case WINED3DFMT_S8_UINT_D24_FLOAT:
+        case WINED3DFMT_D32_UNORM:
+        case WINED3DFMT_D32_FLOAT:
+        case WINED3DFMT_INTZ:
+            break;
+        default:
+            FIXME("Unsupported depth/stencil format %s.\n", debug_d3dformat(format->id));
+            return FALSE;
+    }
+
+    *depthSize = format->depth_size;
+    *stencilSize = format->stencil_size;
+
+    TRACE("Returning depthSize: %d and stencilSize: %d for format %s.\n",
+            *depthSize, *stencilSize, debug_d3dformat(format->id));
+    return TRUE;
+}
+
+/* Note: It's the caller's responsibility to ensure values can be expressed
+ * in the requested format. UNORM formats for example can only express values
+ * in the range 0.0f -> 1.0f. */
+DWORD wined3d_format_convert_from_float(const struct wined3d_surface *surface, const struct wined3d_color *color)
+{
+    static const struct
+    {
+        enum wined3d_format_id format_id;
+        float r_mul;
+        float g_mul;
+        float b_mul;
+        float a_mul;
+        BYTE r_shift;
+        BYTE g_shift;
+        BYTE b_shift;
+        BYTE a_shift;
+    }
+    conv[] =
+    {
+        {WINED3DFMT_B8G8R8A8_UNORM,     255.0f,  255.0f,  255.0f,  255.0f, 16,  8,  0, 24},
+        {WINED3DFMT_B8G8R8X8_UNORM,     255.0f,  255.0f,  255.0f,  255.0f, 16,  8,  0, 24},
+        {WINED3DFMT_B8G8R8_UNORM,       255.0f,  255.0f,  255.0f,  255.0f, 16,  8,  0, 24},
+        {WINED3DFMT_B5G6R5_UNORM,        31.0f,   63.0f,   31.0f,    0.0f, 11,  5,  0,  0},
+        {WINED3DFMT_B5G5R5A1_UNORM,      31.0f,   31.0f,   31.0f,    1.0f, 10,  5,  0, 15},
+        {WINED3DFMT_B5G5R5X1_UNORM,      31.0f,   31.0f,   31.0f,    1.0f, 10,  5,  0, 15},
+        {WINED3DFMT_A8_UNORM,             0.0f,    0.0f,    0.0f,  255.0f,  0,  0,  0,  0},
+        {WINED3DFMT_B4G4R4A4_UNORM,      15.0f,   15.0f,   15.0f,   15.0f,  8,  4,  0, 12},
+        {WINED3DFMT_B4G4R4X4_UNORM,      15.0f,   15.0f,   15.0f,   15.0f,  8,  4,  0, 12},
+        {WINED3DFMT_B2G3R3_UNORM,         7.0f,    7.0f,    3.0f,    0.0f,  5,  2,  0,  0},
+        {WINED3DFMT_R8G8B8A8_UNORM,     255.0f,  255.0f,  255.0f,  255.0f,  0,  8, 16, 24},
+        {WINED3DFMT_R8G8B8X8_UNORM,     255.0f,  255.0f,  255.0f,  255.0f,  0,  8, 16, 24},
+        {WINED3DFMT_B10G10R10A2_UNORM, 1023.0f, 1023.0f, 1023.0f,    3.0f, 20, 10,  0, 30},
+        {WINED3DFMT_R10G10B10A2_UNORM, 1023.0f, 1023.0f, 1023.0f,    3.0f,  0, 10, 20, 30},
+    };
+    const struct wined3d_format *format = surface->resource.format;
+    unsigned int i;
+
+    TRACE("Converting color {%.8e %.8e %.8e %.8e} to format %s.\n",
+            color->r, color->g, color->b, color->a, debug_d3dformat(format->id));
+
+    for (i = 0; i < sizeof(conv) / sizeof(*conv); ++i)
+    {
+        DWORD ret;
+
+        if (format->id != conv[i].format_id) continue;
+
+        ret = ((DWORD)((color->r * conv[i].r_mul) + 0.5f)) << conv[i].r_shift;
+        ret |= ((DWORD)((color->g * conv[i].g_mul) + 0.5f)) << conv[i].g_shift;
+        ret |= ((DWORD)((color->b * conv[i].b_mul) + 0.5f)) << conv[i].b_shift;
+        ret |= ((DWORD)((color->a * conv[i].a_mul) + 0.5f)) << conv[i].a_shift;
+
+        TRACE("Returning 0x%08x.\n", ret);
+
+        return ret;
+    }
+
+    if (format->id == WINED3DFMT_P8_UINT)
+    {
+        PALETTEENTRY *e;
+        BYTE r, g, b, a;
+
+        if (!surface->palette)
+        {
+            WARN("Surface doesn't have a palette, returning 0.\n");
+            return 0;
+        }
+
+        r = (BYTE)((color->r * 255.0f) + 0.5f);
+        g = (BYTE)((color->g * 255.0f) + 0.5f);
+        b = (BYTE)((color->b * 255.0f) + 0.5f);
+        a = (BYTE)((color->a * 255.0f) + 0.5f);
+
+        e = &surface->palette->palents[a];
+        if (e->peRed == r && e->peGreen == g && e->peBlue == b)
+            return a;
+
+        WARN("Alpha didn't match index, searching full palette.\n");
+
+        for (i = 0; i < 256; ++i)
+        {
+            e = &surface->palette->palents[i];
+            if (e->peRed == r && e->peGreen == g && e->peBlue == b)
+                return i;
+        }
+
+        FIXME("Unable to convert color to palette index.\n");
+
+        return 0;
+    }
+
+    FIXME("Conversion for format %s not implemented.\n", debug_d3dformat(format->id));
+
+    return 0;
+}
+
+/* DirectDraw stuff */
+enum wined3d_format_id pixelformat_for_depth(DWORD depth)
+{
+    switch (depth)
+    {
+        case 8:  return WINED3DFMT_P8_UINT;
+        case 15: return WINED3DFMT_B5G5R5X1_UNORM;
+        case 16: return WINED3DFMT_B5G6R5_UNORM;
+        case 24: return WINED3DFMT_B8G8R8X8_UNORM; /* Robots needs 24bit to be WINED3DFMT_B8G8R8X8_UNORM */
+        case 32: return WINED3DFMT_B8G8R8X8_UNORM; /* EVE online and the Fur demo need 32bit AdapterDisplayMode to return WINED3DFMT_B8G8R8X8_UNORM */
+        default: return WINED3DFMT_UNKNOWN;
+    }
+}
+
+void multiply_matrix(struct wined3d_matrix *dest, const struct wined3d_matrix *src1,
+        const struct wined3d_matrix *src2)
+{
+    struct wined3d_matrix temp;
+
+    /* Now do the multiplication 'by hand'.
+       I know that all this could be optimised, but this will be done later :-) */
+    temp.u.s._11 = (src1->u.s._11 * src2->u.s._11) + (src1->u.s._21 * src2->u.s._12) + (src1->u.s._31 * src2->u.s._13) + (src1->u.s._41 * src2->u.s._14);
+    temp.u.s._21 = (src1->u.s._11 * src2->u.s._21) + (src1->u.s._21 * src2->u.s._22) + (src1->u.s._31 * src2->u.s._23) + (src1->u.s._41 * src2->u.s._24);
+    temp.u.s._31 = (src1->u.s._11 * src2->u.s._31) + (src1->u.s._21 * src2->u.s._32) + (src1->u.s._31 * src2->u.s._33) + (src1->u.s._41 * src2->u.s._34);
+    temp.u.s._41 = (src1->u.s._11 * src2->u.s._41) + (src1->u.s._21 * src2->u.s._42) + (src1->u.s._31 * src2->u.s._43) + (src1->u.s._41 * src2->u.s._44);
+
+    temp.u.s._12 = (src1->u.s._12 * src2->u.s._11) + (src1->u.s._22 * src2->u.s._12) + (src1->u.s._32 * src2->u.s._13) + (src1->u.s._42 * src2->u.s._14);
+    temp.u.s._22 = (src1->u.s._12 * src2->u.s._21) + (src1->u.s._22 * src2->u.s._22) + (src1->u.s._32 * src2->u.s._23) + (src1->u.s._42 * src2->u.s._24);
+    temp.u.s._32 = (src1->u.s._12 * src2->u.s._31) + (src1->u.s._22 * src2->u.s._32) + (src1->u.s._32 * src2->u.s._33) + (src1->u.s._42 * src2->u.s._34);
+    temp.u.s._42 = (src1->u.s._12 * src2->u.s._41) + (src1->u.s._22 * src2->u.s._42) + (src1->u.s._32 * src2->u.s._43) + (src1->u.s._42 * src2->u.s._44);
+
+    temp.u.s._13 = (src1->u.s._13 * src2->u.s._11) + (src1->u.s._23 * src2->u.s._12) + (src1->u.s._33 * src2->u.s._13) + (src1->u.s._43 * src2->u.s._14);
+    temp.u.s._23 = (src1->u.s._13 * src2->u.s._21) + (src1->u.s._23 * src2->u.s._22) + (src1->u.s._33 * src2->u.s._23) + (src1->u.s._43 * src2->u.s._24);
+    temp.u.s._33 = (src1->u.s._13 * src2->u.s._31) + (src1->u.s._23 * src2->u.s._32) + (src1->u.s._33 * src2->u.s._33) + (src1->u.s._43 * src2->u.s._34);
+    temp.u.s._43 = (src1->u.s._13 * src2->u.s._41) + (src1->u.s._23 * src2->u.s._42) + (src1->u.s._33 * src2->u.s._43) + (src1->u.s._43 * src2->u.s._44);
+
+    temp.u.s._14 = (src1->u.s._14 * src2->u.s._11) + (src1->u.s._24 * src2->u.s._12) + (src1->u.s._34 * src2->u.s._13) + (src1->u.s._44 * src2->u.s._14);
+    temp.u.s._24 = (src1->u.s._14 * src2->u.s._21) + (src1->u.s._24 * src2->u.s._22) + (src1->u.s._34 * src2->u.s._23) + (src1->u.s._44 * src2->u.s._24);
+    temp.u.s._34 = (src1->u.s._14 * src2->u.s._31) + (src1->u.s._24 * src2->u.s._32) + (src1->u.s._34 * src2->u.s._33) + (src1->u.s._44 * src2->u.s._34);
+    temp.u.s._44 = (src1->u.s._14 * src2->u.s._41) + (src1->u.s._24 * src2->u.s._42) + (src1->u.s._34 * src2->u.s._43) + (src1->u.s._44 * src2->u.s._44);
+
+    /* And copy the new matrix in the good storage.. */
+    memcpy(dest, &temp, 16 * sizeof(float));
+}
+
+DWORD get_flexible_vertex_size(DWORD d3dvtVertexType) {
+    DWORD size = 0;
+    int i;
+    int numTextures = (d3dvtVertexType & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
+
+    if (d3dvtVertexType & WINED3DFVF_NORMAL) size += 3 * sizeof(float);
+    if (d3dvtVertexType & WINED3DFVF_DIFFUSE) size += sizeof(DWORD);
+    if (d3dvtVertexType & WINED3DFVF_SPECULAR) size += sizeof(DWORD);
+    if (d3dvtVertexType & WINED3DFVF_PSIZE) size += sizeof(DWORD);
+    switch (d3dvtVertexType & WINED3DFVF_POSITION_MASK) {
+        case WINED3DFVF_XYZ:    size += 3 * sizeof(float); break;
+        case WINED3DFVF_XYZRHW: size += 4 * sizeof(float); break;
+        case WINED3DFVF_XYZB1:  size += 4 * sizeof(float); break;
+        case WINED3DFVF_XYZB2:  size += 5 * sizeof(float); break;
+        case WINED3DFVF_XYZB3:  size += 6 * sizeof(float); break;
+        case WINED3DFVF_XYZB4:  size += 7 * sizeof(float); break;
+        case WINED3DFVF_XYZB5:  size += 8 * sizeof(float); break;
+        case WINED3DFVF_XYZW:   size += 4 * sizeof(float); break;
+        default: ERR("Unexpected position mask\n");
+    }
+    for (i = 0; i < numTextures; i++) {
+        size += GET_TEXCOORD_SIZE_FROM_FVF(d3dvtVertexType, i) * sizeof(float);
+    }
+
+    return size;
+}
+
+void gen_ffp_frag_op(const struct wined3d_context *context, const struct wined3d_state *state,
+        struct ffp_frag_settings *settings, BOOL ignore_textype)
+{
+#define ARG1 0x01
+#define ARG2 0x02
+#define ARG0 0x04
+    static const unsigned char args[WINED3D_TOP_LERP + 1] =
+    {
+        /* undefined                        */  0,
+        /* D3DTOP_DISABLE                   */  0,
+        /* D3DTOP_SELECTARG1                */  ARG1,
+        /* D3DTOP_SELECTARG2                */  ARG2,
+        /* D3DTOP_MODULATE                  */  ARG1 | ARG2,
+        /* D3DTOP_MODULATE2X                */  ARG1 | ARG2,
+        /* D3DTOP_MODULATE4X                */  ARG1 | ARG2,
+        /* D3DTOP_ADD                       */  ARG1 | ARG2,
+        /* D3DTOP_ADDSIGNED                 */  ARG1 | ARG2,
+        /* D3DTOP_ADDSIGNED2X               */  ARG1 | ARG2,
+        /* D3DTOP_SUBTRACT                  */  ARG1 | ARG2,
+        /* D3DTOP_ADDSMOOTH                 */  ARG1 | ARG2,
+        /* D3DTOP_BLENDDIFFUSEALPHA         */  ARG1 | ARG2,
+        /* D3DTOP_BLENDTEXTUREALPHA         */  ARG1 | ARG2,
+        /* D3DTOP_BLENDFACTORALPHA          */  ARG1 | ARG2,
+        /* D3DTOP_BLENDTEXTUREALPHAPM       */  ARG1 | ARG2,
+        /* D3DTOP_BLENDCURRENTALPHA         */  ARG1 | ARG2,
+        /* D3DTOP_PREMODULATE               */  ARG1 | ARG2,
+        /* D3DTOP_MODULATEALPHA_ADDCOLOR    */  ARG1 | ARG2,
+        /* D3DTOP_MODULATECOLOR_ADDALPHA    */  ARG1 | ARG2,
+        /* D3DTOP_MODULATEINVALPHA_ADDCOLOR */  ARG1 | ARG2,
+        /* D3DTOP_MODULATEINVCOLOR_ADDALPHA */  ARG1 | ARG2,
+        /* D3DTOP_BUMPENVMAP                */  ARG1 | ARG2,
+        /* D3DTOP_BUMPENVMAPLUMINANCE       */  ARG1 | ARG2,
+        /* D3DTOP_DOTPRODUCT3               */  ARG1 | ARG2,
+        /* D3DTOP_MULTIPLYADD               */  ARG1 | ARG2 | ARG0,
+        /* D3DTOP_LERP                      */  ARG1 | ARG2 | ARG0
+    };
+    unsigned int i;
+    DWORD ttff;
+    DWORD cop, aop, carg0, carg1, carg2, aarg0, aarg1, aarg2;
+    const struct wined3d_surface *rt = state->fb->render_targets[0];
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    const struct wined3d_d3d_info *d3d_info = context->d3d_info;
+
+#ifdef VBOX_WITH_WINE_FIX_INITCLEAR
+    memset(settings, 0, sizeof(*settings));
+#endif
+
+    for (i = 0; i < d3d_info->limits.ffp_blend_stages; ++i)
+    {
+        const struct wined3d_texture *texture;
+
+        settings->op[i].padding = 0;
+        if (state->texture_states[i][WINED3D_TSS_COLOR_OP] == WINED3D_TOP_DISABLE)
+        {
+            settings->op[i].cop = WINED3D_TOP_DISABLE;
+            settings->op[i].aop = WINED3D_TOP_DISABLE;
+            settings->op[i].carg0 = settings->op[i].carg1 = settings->op[i].carg2 = ARG_UNUSED;
+            settings->op[i].aarg0 = settings->op[i].aarg1 = settings->op[i].aarg2 = ARG_UNUSED;
+            settings->op[i].color_fixup = COLOR_FIXUP_IDENTITY;
+            settings->op[i].dst = resultreg;
+            settings->op[i].tex_type = tex_1d;
+            settings->op[i].projected = proj_none;
+            i++;
+            break;
+        }
+
+        if ((texture = state->textures[i]))
+        {
+            settings->op[i].color_fixup = texture->resource.format->color_fixup;
+            if (ignore_textype)
+            {
+                settings->op[i].tex_type = tex_1d;
+            }
+            else
+            {
+                switch (texture->target)
+                {
+                    case GL_TEXTURE_1D:
+                        settings->op[i].tex_type = tex_1d;
+                        break;
+                    case GL_TEXTURE_2D:
+                        settings->op[i].tex_type = tex_2d;
+                        break;
+                    case GL_TEXTURE_3D:
+                        settings->op[i].tex_type = tex_3d;
+                        break;
+                    case GL_TEXTURE_CUBE_MAP_ARB:
+                        settings->op[i].tex_type = tex_cube;
+                        break;
+                    case GL_TEXTURE_RECTANGLE_ARB:
+                        settings->op[i].tex_type = tex_rect;
+                        break;
+                }
+            }
+        } else {
+            settings->op[i].color_fixup = COLOR_FIXUP_IDENTITY;
+            settings->op[i].tex_type = tex_1d;
+        }
+
+        cop = state->texture_states[i][WINED3D_TSS_COLOR_OP];
+        aop = state->texture_states[i][WINED3D_TSS_ALPHA_OP];
+
+        carg1 = (args[cop] & ARG1) ? state->texture_states[i][WINED3D_TSS_COLOR_ARG1] : ARG_UNUSED;
+        carg2 = (args[cop] & ARG2) ? state->texture_states[i][WINED3D_TSS_COLOR_ARG2] : ARG_UNUSED;
+        carg0 = (args[cop] & ARG0) ? state->texture_states[i][WINED3D_TSS_COLOR_ARG0] : ARG_UNUSED;
+
+        if (is_invalid_op(state, i, cop, carg1, carg2, carg0))
+        {
+            carg0 = ARG_UNUSED;
+            carg2 = ARG_UNUSED;
+            carg1 = WINED3DTA_CURRENT;
+            cop = WINED3D_TOP_SELECT_ARG1;
+        }
+
+        if (cop == WINED3D_TOP_DOTPRODUCT3)
+        {
+            /* A dotproduct3 on the colorop overwrites the alphaop operation and replicates
+             * the color result to the alpha component of the destination
+             */
+            aop = cop;
+            aarg1 = carg1;
+            aarg2 = carg2;
+            aarg0 = carg0;
+        }
+        else
+        {
+            aarg1 = (args[aop] & ARG1) ? state->texture_states[i][WINED3D_TSS_ALPHA_ARG1] : ARG_UNUSED;
+            aarg2 = (args[aop] & ARG2) ? state->texture_states[i][WINED3D_TSS_ALPHA_ARG2] : ARG_UNUSED;
+            aarg0 = (args[aop] & ARG0) ? state->texture_states[i][WINED3D_TSS_ALPHA_ARG0] : ARG_UNUSED;
+        }
+
+        if (!i && state->textures[0] && state->render_states[WINED3D_RS_COLORKEYENABLE])
+        {
+            GLenum texture_dimensions;
+
+            texture = state->textures[0];
+            texture_dimensions = texture->target;
+
+            if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB)
+            {
+                struct wined3d_surface *surf = surface_from_resource(texture->sub_resources[0]);
+
+                if (surf->CKeyFlags & WINEDDSD_CKSRCBLT && !surf->resource.format->alpha_size)
+                {
+                    if (aop == WINED3D_TOP_DISABLE)
+                    {
+                       aarg1 = WINED3DTA_TEXTURE;
+                       aop = WINED3D_TOP_SELECT_ARG1;
+                    }
+                    else if (aop == WINED3D_TOP_SELECT_ARG1 && aarg1 != WINED3DTA_TEXTURE)
+                    {
+                        if (state->render_states[WINED3D_RS_ALPHABLENDENABLE])
+                        {
+                            aarg2 = WINED3DTA_TEXTURE;
+                            aop = WINED3D_TOP_MODULATE;
+                        }
+                        else aarg1 = WINED3DTA_TEXTURE;
+                    }
+                    else if (aop == WINED3D_TOP_SELECT_ARG2 && aarg2 != WINED3DTA_TEXTURE)
+                    {
+                        if (state->render_states[WINED3D_RS_ALPHABLENDENABLE])
+                        {
+                            aarg1 = WINED3DTA_TEXTURE;
+                            aop = WINED3D_TOP_MODULATE;
+                        }
+                        else aarg2 = WINED3DTA_TEXTURE;
+                    }
+                }
+            }
+        }
+
+        if (is_invalid_op(state, i, aop, aarg1, aarg2, aarg0))
+        {
+               aarg0 = ARG_UNUSED;
+               aarg2 = ARG_UNUSED;
+               aarg1 = WINED3DTA_CURRENT;
+               aop = WINED3D_TOP_SELECT_ARG1;
+        }
+
+        if (carg1 == WINED3DTA_TEXTURE || carg2 == WINED3DTA_TEXTURE || carg0 == WINED3DTA_TEXTURE
+                || aarg1 == WINED3DTA_TEXTURE || aarg2 == WINED3DTA_TEXTURE || aarg0 == WINED3DTA_TEXTURE)
+        {
+            ttff = state->texture_states[i][WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS];
+            if (ttff == (WINED3D_TTFF_PROJECTED | WINED3D_TTFF_COUNT3))
+                settings->op[i].projected = proj_count3;
+            else if (ttff & WINED3D_TTFF_PROJECTED)
+                settings->op[i].projected = proj_count4;
+            else
+                settings->op[i].projected = proj_none;
+        }
+        else
+        {
+            settings->op[i].projected = proj_none;
+        }
+
+        settings->op[i].cop = cop;
+        settings->op[i].aop = aop;
+        settings->op[i].carg0 = carg0;
+        settings->op[i].carg1 = carg1;
+        settings->op[i].carg2 = carg2;
+        settings->op[i].aarg0 = aarg0;
+        settings->op[i].aarg1 = aarg1;
+        settings->op[i].aarg2 = aarg2;
+
+        if (state->texture_states[i][WINED3D_TSS_RESULT_ARG] == WINED3DTA_TEMP)
+            settings->op[i].dst = tempreg;
+        else
+            settings->op[i].dst = resultreg;
+    }
+
+    /* Clear unsupported stages */
+    for(; i < MAX_TEXTURES; i++) {
+        memset(&settings->op[i], 0xff, sizeof(settings->op[i]));
+    }
+
+    if (!state->render_states[WINED3D_RS_FOGENABLE])
+    {
+        settings->fog = WINED3D_FFP_PS_FOG_OFF;
+    }
+    else if (state->render_states[WINED3D_RS_FOGTABLEMODE] == WINED3D_FOG_NONE)
+    {
+        if (use_vs(state) || state->vertex_declaration->position_transformed)
+        {
+            settings->fog = WINED3D_FFP_PS_FOG_LINEAR;
+        }
+        else
+        {
+            switch (state->render_states[WINED3D_RS_FOGVERTEXMODE])
+            {
+                case WINED3D_FOG_NONE:
+                case WINED3D_FOG_LINEAR:
+                    settings->fog = WINED3D_FFP_PS_FOG_LINEAR;
+                    break;
+                case WINED3D_FOG_EXP:
+                    settings->fog = WINED3D_FFP_PS_FOG_EXP;
+                    break;
+                case WINED3D_FOG_EXP2:
+                    settings->fog = WINED3D_FFP_PS_FOG_EXP2;
+                    break;
+            }
+        }
+    }
+    else
+    {
+        switch (state->render_states[WINED3D_RS_FOGTABLEMODE])
+        {
+            case WINED3D_FOG_LINEAR:
+                settings->fog = WINED3D_FFP_PS_FOG_LINEAR;
+                break;
+            case WINED3D_FOG_EXP:
+                settings->fog = WINED3D_FFP_PS_FOG_EXP;
+                break;
+            case WINED3D_FOG_EXP2:
+                settings->fog = WINED3D_FFP_PS_FOG_EXP2;
+                break;
+        }
+    }
+    if (!gl_info->supported[ARB_FRAMEBUFFER_SRGB]
+            && state->render_states[WINED3D_RS_SRGBWRITEENABLE]
+            && rt->resource.format->flags & WINED3DFMT_FLAG_SRGB_WRITE)
+    {
+        settings->sRGB_write = 1;
+    } else {
+        settings->sRGB_write = 0;
+    }
+    if (d3d_info->vs_clipping || !use_vs(state) || !state->render_states[WINED3D_RS_CLIPPING]
+            || !state->render_states[WINED3D_RS_CLIPPLANEENABLE])
+    {
+        /* No need to emulate clipplanes if GL supports native vertex shader clipping or if
+         * the fixed function vertex pipeline is used(which always supports clipplanes), or
+         * if no clipplane is enabled
+         */
+        settings->emul_clipplanes = 0;
+    } else {
+        settings->emul_clipplanes = 1;
+    }
+}
+
+const struct ffp_frag_desc *find_ffp_frag_shader(const struct wine_rb_tree *fragment_shaders,
+        const struct ffp_frag_settings *settings)
+{
+    struct wine_rb_entry *entry = wine_rb_get(fragment_shaders, settings);
+    return entry ? WINE_RB_ENTRY_VALUE(entry, struct ffp_frag_desc, entry) : NULL;
+}
+
+void add_ffp_frag_shader(struct wine_rb_tree *shaders, struct ffp_frag_desc *desc)
+{
+    /* Note that the key is the implementation independent part of the ffp_frag_desc structure,
+     * whereas desc points to an extended structure with implementation specific parts. */
+    if (wine_rb_put(shaders, &desc->settings, &desc->entry) == -1)
+    {
+        ERR("Failed to insert ffp frag shader.\n");
+    }
+}
+
+/* Activates the texture dimension according to the bound D3D texture. Does
+ * not care for the colorop or correct gl texture unit (when using nvrc).
+ * Requires the caller to activate the correct unit. */
+/* Context activation is done by the caller (state handler). */
+void texture_activate_dimensions(const struct wined3d_texture *texture, const struct wined3d_gl_info *gl_info)
+{
+    if (texture)
+    {
+        switch (texture->target)
+        {
+            case GL_TEXTURE_2D:
+                gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
+                checkGLcall("glDisable(GL_TEXTURE_3D)");
+                if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
+                {
+                    gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB);
+                    checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
+                }
+                if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
+                {
+                    gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB);
+                    checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
+                }
+                gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_2D);
+                checkGLcall("glEnable(GL_TEXTURE_2D)");
+                break;
+            case GL_TEXTURE_RECTANGLE_ARB:
+                gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
+                checkGLcall("glDisable(GL_TEXTURE_2D)");
+                gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
+                checkGLcall("glDisable(GL_TEXTURE_3D)");
+                if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
+                {
+                    gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB);
+                    checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
+                }
+                gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_RECTANGLE_ARB);
+                checkGLcall("glEnable(GL_TEXTURE_RECTANGLE_ARB)");
+                break;
+            case GL_TEXTURE_3D:
+                if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
+                {
+                    gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB);
+                    checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
+                }
+                if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
+                {
+                    gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB);
+                    checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
+                }
+                gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
+                checkGLcall("glDisable(GL_TEXTURE_2D)");
+                gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_3D);
+                checkGLcall("glEnable(GL_TEXTURE_3D)");
+                break;
+            case GL_TEXTURE_CUBE_MAP_ARB:
+                gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
+                checkGLcall("glDisable(GL_TEXTURE_2D)");
+                gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
+                checkGLcall("glDisable(GL_TEXTURE_3D)");
+                if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
+                {
+                    gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB);
+                    checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
+                }
+                gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_CUBE_MAP_ARB);
+                checkGLcall("glEnable(GL_TEXTURE_CUBE_MAP_ARB)");
+              break;
+        }
+    }
+    else
+    {
+        gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_2D);
+        checkGLcall("glEnable(GL_TEXTURE_2D)");
+        gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
+        checkGLcall("glDisable(GL_TEXTURE_3D)");
+        if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
+        {
+            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB);
+            checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
+        }
+        if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
+        {
+            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB);
+            checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
+        }
+        /* Binding textures is done by samplers. A dummy texture will be bound */
+    }
+}
+
+/* Context activation is done by the caller (state handler). */
+void sampler_texdim(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    DWORD sampler = state_id - STATE_SAMPLER(0);
+    DWORD mapped_stage = context->swapchain->device->texUnitMap[sampler];
+
+    /* No need to enable / disable anything here for unused samplers. The
+     * tex_colorop handler takes care. Also no action is needed with pixel
+     * shaders, or if tex_colorop will take care of this business. */
+    if (mapped_stage == WINED3D_UNMAPPED_STAGE || mapped_stage >= context->gl_info->limits.textures)
+        return;
+    if (sampler >= state->lowest_disabled_stage)
+        return;
+    if (isStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3D_TSS_COLOR_OP)))
+        return;
+
+    texture_activate_dimensions(state->textures[sampler], context->gl_info);
+}
+
+void *wined3d_rb_alloc(size_t size)
+{
+    return HeapAlloc(GetProcessHeap(), 0, size);
+}
+
+void *wined3d_rb_realloc(void *ptr, size_t size)
+{
+    return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
+}
+
+void wined3d_rb_free(void *ptr)
+{
+    HeapFree(GetProcessHeap(), 0, ptr);
+}
+
+static int ffp_frag_program_key_compare(const void *key, const struct wine_rb_entry *entry)
+{
+    const struct ffp_frag_settings *ka = key;
+    const struct ffp_frag_settings *kb = &WINE_RB_ENTRY_VALUE(entry, const struct ffp_frag_desc, entry)->settings;
+
+    return memcmp(ka, kb, sizeof(*ka));
+}
+
+const struct wine_rb_functions wined3d_ffp_frag_program_rb_functions =
+{
+    wined3d_rb_alloc,
+    wined3d_rb_realloc,
+    wined3d_rb_free,
+    ffp_frag_program_key_compare,
+};
+
+void wined3d_ffp_get_vs_settings(const struct wined3d_state *state, const struct wined3d_stream_info *si,
+        struct wined3d_ffp_vs_settings *settings)
+{
+    unsigned int coord_idx, i;
+
+    if (si->position_transformed)
+    {
+        memset(settings, 0, sizeof(*settings));
+
+        settings->clipping = state->render_states[WINED3D_RS_CLIPPING]
+                && state->render_states[WINED3D_RS_CLIPPLANEENABLE];
+        settings->point_size = state->gl_primitive_type == GL_POINTS;
+        if (!state->render_states[WINED3D_RS_FOGENABLE])
+            settings->fog_mode = WINED3D_FFP_VS_FOG_OFF;
+        else if (state->render_states[WINED3D_RS_FOGTABLEMODE] != WINED3D_FOG_NONE)
+            settings->fog_mode = WINED3D_FFP_VS_FOG_DEPTH;
+        else
+            settings->fog_mode = WINED3D_FFP_VS_FOG_FOGCOORD;
+
+        for (i = 0; i < MAX_TEXTURES; ++i)
+        {
+            coord_idx = state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX];
+            if (coord_idx < MAX_TEXTURES && (si->use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coord_idx))))
+                settings->texcoords |= 1 << i;
+            settings->texgen[i] = (state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX] >> WINED3D_FFP_TCI_SHIFT)
+                    & WINED3D_FFP_TCI_MASK;
+        }
+        return;
+    }
+
+    settings->clipping = state->render_states[WINED3D_RS_CLIPPING]
+            && state->render_states[WINED3D_RS_CLIPPLANEENABLE];
+    settings->normal = !!(si->use_map & (1 << WINED3D_FFP_NORMAL));
+    settings->normalize = settings->normal && state->render_states[WINED3D_RS_NORMALIZENORMALS];
+    settings->lighting = !!state->render_states[WINED3D_RS_LIGHTING];
+    settings->localviewer = !!state->render_states[WINED3D_RS_LOCALVIEWER];
+    settings->point_size = state->gl_primitive_type == GL_POINTS;
+
+    if (state->render_states[WINED3D_RS_COLORVERTEX] && (si->use_map & (1 << WINED3D_FFP_DIFFUSE)))
+    {
+        settings->diffuse_source = state->render_states[WINED3D_RS_DIFFUSEMATERIALSOURCE];
+        settings->emission_source = state->render_states[WINED3D_RS_EMISSIVEMATERIALSOURCE];
+        settings->ambient_source = state->render_states[WINED3D_RS_AMBIENTMATERIALSOURCE];
+        settings->specular_source = state->render_states[WINED3D_RS_SPECULARMATERIALSOURCE];
+    }
+    else
+    {
+        settings->diffuse_source = WINED3D_MCS_MATERIAL;
+        settings->emission_source = WINED3D_MCS_MATERIAL;
+        settings->ambient_source = WINED3D_MCS_MATERIAL;
+        settings->specular_source = WINED3D_MCS_MATERIAL;
+    }
+
+    settings->texcoords = 0;
+    for (i = 0; i < MAX_TEXTURES; ++i)
+    {
+        coord_idx = state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX];
+        if (coord_idx < MAX_TEXTURES && (si->use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coord_idx))))
+            settings->texcoords |= 1 << i;
+        settings->texgen[i] = (state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX] >> WINED3D_FFP_TCI_SHIFT)
+                & WINED3D_FFP_TCI_MASK;
+    }
+
+    settings->light_type = 0;
+    for (i = 0; i < MAX_ACTIVE_LIGHTS; ++i)
+    {
+        if (state->lights[i])
+            settings->light_type |= (state->lights[i]->OriginalParms.type
+                    & WINED3D_FFP_LIGHT_TYPE_MASK) << WINED3D_FFP_LIGHT_TYPE_SHIFT(i);
+    }
+
+    if (!state->render_states[WINED3D_RS_FOGENABLE])
+        settings->fog_mode = WINED3D_FFP_VS_FOG_OFF;
+    else if (state->render_states[WINED3D_RS_FOGTABLEMODE] != WINED3D_FOG_NONE)
+        settings->fog_mode = WINED3D_FFP_VS_FOG_DEPTH;
+    else if (state->render_states[WINED3D_RS_FOGVERTEXMODE] == WINED3D_FOG_NONE)
+        settings->fog_mode = WINED3D_FFP_VS_FOG_FOGCOORD;
+    else if (state->render_states[WINED3D_RS_RANGEFOGENABLE])
+        settings->fog_mode = WINED3D_FFP_VS_FOG_RANGE;
+    else
+        settings->fog_mode = WINED3D_FFP_VS_FOG_DEPTH;
+
+    settings->padding = 0;
+}
+
+static int wined3d_ffp_vertex_program_key_compare(const void *key, const struct wine_rb_entry *entry)
+{
+    const struct wined3d_ffp_vs_settings *ka = key;
+    const struct wined3d_ffp_vs_settings *kb = &WINE_RB_ENTRY_VALUE(entry,
+            const struct wined3d_ffp_vs_desc, entry)->settings;
+
+    return memcmp(ka, kb, sizeof(*ka));
+}
+
+const struct wine_rb_functions wined3d_ffp_vertex_program_rb_functions =
+{
+    wined3d_rb_alloc,
+    wined3d_rb_realloc,
+    wined3d_rb_free,
+    wined3d_ffp_vertex_program_key_compare,
+};
+
+UINT wined3d_log2i(UINT32 x)
+{
+    static const UINT l[] =
+    {
+        ~0U, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
+          4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+          5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+          5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+          6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+          6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+          6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+          6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+    };
+    UINT32 i;
+
+    return (i = x >> 16) ? (x = i >> 8) ? l[x] + 24 : l[i] + 16 : (i = x >> 8) ? l[i] + 8 : l[x];
+}
+
+const struct blit_shader *wined3d_select_blitter(const struct wined3d_gl_info *gl_info, enum wined3d_blit_op blit_op,
+        const RECT *src_rect, DWORD src_usage, enum wined3d_pool src_pool, const struct wined3d_format *src_format,
+        const RECT *dst_rect, DWORD dst_usage, enum wined3d_pool dst_pool, const struct wined3d_format *dst_format)
+{
+    static const struct blit_shader * const blitters[] =
+    {
+        &arbfp_blit,
+        &ffp_blit,
+        &cpu_blit,
+    };
+    unsigned int i;
+
+    for (i = 0; i < sizeof(blitters) / sizeof(*blitters); ++i)
+    {
+        if (blitters[i]->blit_supported(gl_info, blit_op,
+                src_rect, src_usage, src_pool, src_format,
+                dst_rect, dst_usage, dst_pool, dst_format))
+            return blitters[i];
+    }
+
+    return NULL;
+}
+
+void wined3d_get_draw_rect(const struct wined3d_state *state, RECT *rect)
+{
+    const struct wined3d_viewport *vp = &state->viewport;
+
+    SetRect(rect, vp->x, vp->y, vp->x + vp->width, vp->y + vp->height);
+
+    if (state->render_states[WINED3D_RS_SCISSORTESTENABLE])
+        IntersectRect(rect, rect, &state->scissor_rect);
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/vboxext.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/vboxext.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/vboxext.c	(revision 46521)
@@ -0,0 +1,860 @@
+/* $Id$ */
+/** @file
+ *
+ * VBox extension to Wine D3D
+ *
+ * Copyright (C) 2011 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+#include "config.h"
+#include "wine/port.h"
+#include "wined3d_private.h"
+#include "vboxext.h"
+#ifdef VBOX_WITH_WDDM
+#include <VBox/VBoxCrHgsmi.h>
+#include <iprt/err.h>
+#endif
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d_vbox);
+
+typedef DECLCALLBACK(void) FNVBOXEXTWORKERCB(void *pvUser);
+typedef FNVBOXEXTWORKERCB *PFNVBOXEXTWORKERCB;
+
+HRESULT VBoxExtDwSubmitProcSync(PFNVBOXEXTWORKERCB pfnCb, void *pvCb);
+HRESULT VBoxExtDwSubmitProcAsync(PFNVBOXEXTWORKERCB pfnCb, void *pvCb);
+
+/*******************************/
+#ifdef VBOX_WITH_WDDM
+# if defined(VBOX_WDDM_WOW64)
+# define VBOXEXT_WINE_MODULE_NAME "wined3dwddm-x86.dll"
+# else
+# define VBOXEXT_WINE_MODULE_NAME "wined3dwddm.dll"
+# endif
+#else
+/* both 32bit and 64bit versions of xpdm wine libs are named identically */
+# define VBOXEXT_WINE_MODULE_NAME "wined3d.dll"
+#endif
+
+typedef struct VBOXEXT_WORKER
+{
+    CRITICAL_SECTION CritSect;
+
+    HANDLE hEvent;
+
+    HANDLE hThread;
+    DWORD  idThread;
+    /* wine does not seem to guarantie the dll is not unloaded in case FreeLibrary is used
+     * while d3d object is not terminated, keep an extra reference to ensure we're not unloaded
+     * while we are active */
+    HMODULE hSelf;
+} VBOXEXT_WORKER, *PVBOXEXT_WORKER;
+
+
+
+HRESULT VBoxExtWorkerCreate(PVBOXEXT_WORKER pWorker);
+HRESULT VBoxExtWorkerDestroy(PVBOXEXT_WORKER pWorker);
+HRESULT VBoxExtWorkerSubmitProc(PVBOXEXT_WORKER pWorker, PFNVBOXEXTWORKERCB pfnCb, void *pvCb);
+
+
+/*******************************/
+typedef struct VBOXEXT_GLOBAL
+{
+    VBOXEXT_WORKER Worker;
+} VBOXEXT_GLOBAL, *PVBOXEXT_GLOBAL;
+
+static VBOXEXT_GLOBAL g_VBoxExtGlobal;
+
+#define WM_VBOXEXT_CALLPROC  (WM_APP+1)
+#define WM_VBOXEXT_INIT_QUIT (WM_APP+2)
+
+typedef struct VBOXEXT_CALLPROC
+{
+    PFNVBOXEXTWORKERCB pfnCb;
+    void *pvCb;
+} VBOXEXT_CALLPROC, *PVBOXEXT_CALLPROC;
+
+static DWORD WINAPI vboxExtWorkerThread(void *pvUser)
+{
+    PVBOXEXT_WORKER pWorker = (PVBOXEXT_WORKER)pvUser;
+    MSG Msg;
+
+    PeekMessage(&Msg,
+        NULL /* HWND hWnd */,
+        WM_USER /* UINT wMsgFilterMin */,
+        WM_USER /* UINT wMsgFilterMax */,
+        PM_NOREMOVE);
+    SetEvent(pWorker->hEvent);
+
+    do
+    {
+        BOOL bResult = GetMessage(&Msg,
+            0 /*HWND hWnd*/,
+            0 /*UINT wMsgFilterMin*/,
+            0 /*UINT wMsgFilterMax*/
+            );
+
+        if(!bResult) /* WM_QUIT was posted */
+            break;
+
+        Assert(bResult != -1);
+        if(bResult == -1) /* error occurred */
+            break;
+
+        switch (Msg.message)
+        {
+            case WM_VBOXEXT_CALLPROC:
+            {
+                VBOXEXT_CALLPROC* pData = (VBOXEXT_CALLPROC*)Msg.lParam;
+                pData->pfnCb(pData->pvCb);
+                SetEvent(pWorker->hEvent);
+                break;
+            }
+            case WM_VBOXEXT_INIT_QUIT:
+            case WM_CLOSE:
+            {
+                PostQuitMessage(0);
+                break;
+            }
+            default:
+                TranslateMessage(&Msg);
+                DispatchMessage(&Msg);
+        }
+    } while (1);
+    return 0;
+}
+
+HRESULT VBoxExtWorkerCreate(PVBOXEXT_WORKER pWorker)
+{
+    if(!GetModuleHandleEx(0, VBOXEXT_WINE_MODULE_NAME, &pWorker->hSelf))
+    {
+        DWORD dwEr = GetLastError();
+        ERR("GetModuleHandleEx failed, %d", dwEr);
+        return E_FAIL;
+    }
+
+    InitializeCriticalSection(&pWorker->CritSect);
+    pWorker->hEvent = CreateEvent(NULL, /* LPSECURITY_ATTRIBUTES lpEventAttributes */
+            FALSE, /* BOOL bManualReset */
+            FALSE, /* BOOL bInitialState */
+            NULL /* LPCTSTR lpName */
+          );
+    if (pWorker->hEvent)
+    {
+        pWorker->hThread = CreateThread(
+                              NULL /* LPSECURITY_ATTRIBUTES lpThreadAttributes */,
+                              0 /* SIZE_T dwStackSize */,
+                              vboxExtWorkerThread,
+                              pWorker,
+                              0 /* DWORD dwCreationFlags */,
+                              &pWorker->idThread);
+        if (pWorker->hThread)
+        {
+            DWORD dwResult = WaitForSingleObject(pWorker->hEvent, INFINITE);
+            if (WAIT_OBJECT_0 == dwResult)
+                return S_OK;
+            ERR("WaitForSingleObject returned %d\n", dwResult);
+        }
+        else
+        {
+            DWORD winErr = GetLastError();
+            ERR("CreateThread failed, winErr = (%d)", winErr);
+        }
+
+        DeleteCriticalSection(&pWorker->CritSect);
+    }
+    else
+    {
+        DWORD winErr = GetLastError();
+        ERR("CreateEvent failed, winErr = (%d)", winErr);
+    }
+
+    FreeLibrary(pWorker->hSelf);
+
+    return E_FAIL;
+}
+
+HRESULT VBoxExtWorkerDestroy(PVBOXEXT_WORKER pWorker)
+{
+    BOOL bResult = PostThreadMessage(pWorker->idThread, WM_VBOXEXT_INIT_QUIT, 0, 0);
+    DWORD dwErr;
+    if (!bResult)
+    {
+        DWORD winErr = GetLastError();
+        ERR("PostThreadMessage failed, winErr = (%d)", winErr);
+        return E_FAIL;
+    }
+
+    dwErr = WaitForSingleObject(pWorker->hThread, INFINITE);
+    if (dwErr != WAIT_OBJECT_0)
+    {
+        ERR("WaitForSingleObject returned (%d)", dwErr);
+        return E_FAIL;
+    }
+
+    CloseHandle(pWorker->hEvent);
+    DeleteCriticalSection(&pWorker->CritSect);
+
+    FreeLibrary(pWorker->hSelf);
+
+    CloseHandle(pWorker->hThread);
+
+    return S_OK;
+}
+
+static HRESULT vboxExtWorkerSubmit(VBOXEXT_WORKER *pWorker, UINT Msg, LPARAM lParam, BOOL fSync)
+{
+    HRESULT hr = E_FAIL;
+    BOOL bResult;
+    /* need to serialize since vboxExtWorkerThread is using one pWorker->hEvent
+     * to signal job completion */
+    EnterCriticalSection(&pWorker->CritSect);
+    bResult = PostThreadMessage(pWorker->idThread, Msg, 0, lParam);
+    if (bResult)
+    {
+        if (fSync)
+        {
+            DWORD dwErr = WaitForSingleObject(pWorker->hEvent, INFINITE);
+            if (dwErr == WAIT_OBJECT_0)
+            {
+                hr = S_OK;
+            }
+            else
+            {
+                ERR("WaitForSingleObject returned (%d)", dwErr);
+            }
+        }
+        else
+            hr = S_OK;
+    }
+    else
+    {
+        DWORD winErr = GetLastError();
+        ERR("PostThreadMessage failed, winErr = (%d)", winErr);
+        return E_FAIL;
+    }
+    LeaveCriticalSection(&pWorker->CritSect);
+    return hr;
+}
+
+HRESULT VBoxExtWorkerSubmitProcSync(PVBOXEXT_WORKER pWorker, PFNVBOXEXTWORKERCB pfnCb, void *pvCb)
+{
+    VBOXEXT_CALLPROC Ctx;
+    Ctx.pfnCb = pfnCb;
+    Ctx.pvCb = pvCb;
+    return vboxExtWorkerSubmit(pWorker, WM_VBOXEXT_CALLPROC, (LPARAM)&Ctx, TRUE);
+}
+
+static DECLCALLBACK(void) vboxExtWorkerSubmitProcAsyncWorker(void *pvUser)
+{
+    PVBOXEXT_CALLPROC pCallInfo = (PVBOXEXT_CALLPROC)pvUser;
+    pCallInfo[1].pfnCb(pCallInfo[1].pvCb);
+    HeapFree(GetProcessHeap(), 0, pCallInfo);
+}
+
+HRESULT VBoxExtWorkerSubmitProcAsync(PVBOXEXT_WORKER pWorker, PFNVBOXEXTWORKERCB pfnCb, void *pvCb)
+{
+    HRESULT hr;
+    PVBOXEXT_CALLPROC pCallInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof (VBOXEXT_CALLPROC) * 2);
+    if (!pCallInfo)
+    {
+        ERR("HeapAlloc failed\n");
+        return E_OUTOFMEMORY;
+    }
+    pCallInfo[0].pfnCb = vboxExtWorkerSubmitProcAsyncWorker;
+    pCallInfo[0].pvCb = pCallInfo;
+    pCallInfo[1].pfnCb = pfnCb;
+    pCallInfo[1].pvCb = pvCb;
+    hr = vboxExtWorkerSubmit(pWorker, WM_VBOXEXT_CALLPROC, (LPARAM)pCallInfo, FALSE);
+    if (FAILED(hr))
+    {
+        ERR("vboxExtWorkerSubmit failed, hr 0x%x\n", hr);
+        HeapFree(GetProcessHeap(), 0, pCallInfo);
+        return hr;
+    }
+    return S_OK;
+}
+
+
+static HRESULT vboxExtInit()
+{
+    HRESULT hr = S_OK;
+#ifdef VBOX_WITH_WDDM
+    int rc = VBoxCrHgsmiInit();
+    if (!RT_SUCCESS(rc))
+    {
+        ERR("VBoxCrHgsmiInit failed rc %d", rc);
+        return E_FAIL;
+    }
+#endif
+    memset(&g_VBoxExtGlobal, 0, sizeof (g_VBoxExtGlobal));
+    hr = VBoxExtWorkerCreate(&g_VBoxExtGlobal.Worker);
+    if (SUCCEEDED(hr))
+        return S_OK;
+
+    /* failure branch */
+#ifdef VBOX_WITH_WDDM
+    VBoxCrHgsmiTerm();
+#endif
+    return hr;
+}
+
+
+static HRESULT vboxExtWndCleanup();
+
+static HRESULT vboxExtTerm()
+{
+    HRESULT hr = vboxExtWndCleanup();
+    if (!SUCCEEDED(hr))
+    {
+        ERR("vboxExtWndCleanup failed, hr %d", hr);
+        return hr;
+    }
+
+    hr = VBoxExtWorkerDestroy(&g_VBoxExtGlobal.Worker);
+    if (!SUCCEEDED(hr))
+    {
+        ERR("VBoxExtWorkerDestroy failed, hr %d", hr);
+        return hr;
+    }
+
+#ifdef VBOX_WITH_WDDM
+    VBoxCrHgsmiTerm();
+#endif
+
+    return S_OK;
+}
+
+/* wine serializes all calls to us, so no need for any synchronization here */
+static DWORD g_cVBoxExtInits = 0;
+
+static DWORD vboxExtAddRef()
+{
+    return ++g_cVBoxExtInits;
+}
+
+static DWORD vboxExtRelease()
+{
+    DWORD cVBoxExtInits = --g_cVBoxExtInits;
+    Assert(cVBoxExtInits < UINT32_MAX/2);
+    return cVBoxExtInits;
+}
+
+static DWORD vboxExtGetRef()
+{
+    return g_cVBoxExtInits;
+}
+
+HRESULT VBoxExtCheckInit()
+{
+    HRESULT hr = S_OK;
+    if (!vboxExtGetRef())
+    {
+        hr = vboxExtInit();
+        if (FAILED(hr))
+        {
+            ERR("vboxExtInit failed, hr (0x%x)", hr);
+            return hr;
+        }
+    }
+    vboxExtAddRef();
+    return S_OK;
+}
+
+HRESULT VBoxExtCheckTerm()
+{
+    HRESULT hr = S_OK;
+    if (vboxExtGetRef() == 1)
+    {
+        hr = vboxExtTerm();
+        if (FAILED(hr))
+        {
+            ERR("vboxExtTerm failed, hr (0x%x)", hr);
+            return hr;
+        }
+    }
+    vboxExtRelease();
+    return S_OK;
+}
+
+HRESULT VBoxExtDwSubmitProcSync(PFNVBOXEXTWORKERCB pfnCb, void *pvCb)
+{
+    return VBoxExtWorkerSubmitProcSync(&g_VBoxExtGlobal.Worker, pfnCb, pvCb);
+}
+
+HRESULT VBoxExtDwSubmitProcAsync(PFNVBOXEXTWORKERCB pfnCb, void *pvCb)
+{
+    return VBoxExtWorkerSubmitProcAsync(&g_VBoxExtGlobal.Worker, pfnCb, pvCb);
+}
+
+#if defined(VBOX_WINE_WITH_SINGLE_CONTEXT) || defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
+# ifndef VBOX_WITH_WDDM
+typedef struct VBOXEXT_GETDC_CB
+{
+    HWND hWnd;
+    HDC hDC;
+} VBOXEXT_GETDC_CB, *PVBOXEXT_GETDC_CB;
+
+static DECLCALLBACK(void) vboxExtGetDCWorker(void *pvUser)
+{
+    PVBOXEXT_GETDC_CB pData = (PVBOXEXT_GETDC_CB)pvUser;
+    pData->hDC = GetDC(pData->hWnd);
+}
+
+typedef struct VBOXEXT_RELEASEDC_CB
+{
+    HWND hWnd;
+    HDC hDC;
+    int ret;
+} VBOXEXT_RELEASEDC_CB, *PVBOXEXT_RELEASEDC_CB;
+
+static DECLCALLBACK(void) vboxExtReleaseDCWorker(void *pvUser)
+{
+    PVBOXEXT_RELEASEDC_CB pData = (PVBOXEXT_RELEASEDC_CB)pvUser;
+    pData->ret = ReleaseDC(pData->hWnd, pData->hDC);
+}
+
+HDC VBoxExtGetDC(HWND hWnd)
+{
+    HRESULT hr;
+    VBOXEXT_GETDC_CB Data = {0};
+    Data.hWnd = hWnd;
+    Data.hDC = NULL;
+
+    hr = VBoxExtDwSubmitProcSync(vboxExtGetDCWorker, &Data);
+    if (FAILED(hr))
+    {
+        ERR("VBoxExtDwSubmitProcSync feiled, hr (0x%x)\n", hr);
+        return NULL;
+    }
+
+    return Data.hDC;
+}
+
+int VBoxExtReleaseDC(HWND hWnd, HDC hDC)
+{
+    HRESULT hr;
+    VBOXEXT_RELEASEDC_CB Data = {0};
+    Data.hWnd = hWnd;
+    Data.hDC = hDC;
+    Data.ret = 0;
+
+    hr = VBoxExtDwSubmitProcSync(vboxExtReleaseDCWorker, &Data);
+    if (FAILED(hr))
+    {
+        ERR("VBoxExtDwSubmitProcSync feiled, hr (0x%x)\n", hr);
+        return -1;
+    }
+
+    return Data.ret;
+}
+# endif /* #ifndef VBOX_WITH_WDDM */
+
+static DECLCALLBACK(void) vboxExtReleaseContextWorker(void *pvUser)
+{
+    struct wined3d_context *context = (struct wined3d_context *)pvUser;
+    VBoxTlsRefRelease(context);
+}
+
+void VBoxExtReleaseContextAsync(struct wined3d_context *context)
+{
+    HRESULT hr;
+
+    hr = VBoxExtDwSubmitProcAsync(vboxExtReleaseContextWorker, context);
+    if (FAILED(hr))
+    {
+        ERR("VBoxExtDwSubmitProcAsync feiled, hr (0x%x)\n", hr);
+        return;
+    }
+}
+
+#endif /* #if defined(VBOX_WINE_WITH_SINGLE_CONTEXT) || defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT) */
+
+/* window creation API */
+static LRESULT CALLBACK vboxExtWndProc(HWND hwnd,
+    UINT uMsg,
+    WPARAM wParam,
+    LPARAM lParam
+)
+{
+    switch(uMsg)
+    {
+        case WM_CLOSE:
+            TRACE("got WM_CLOSE for hwnd(0x%x)", hwnd);
+            return 0;
+        case WM_DESTROY:
+            TRACE("got WM_DESTROY for hwnd(0x%x)", hwnd);
+            return 0;
+        case WM_NCHITTEST:
+            TRACE("got WM_NCHITTEST for hwnd(0x%x)\n", hwnd);
+            return HTNOWHERE;
+    }
+
+    return DefWindowProc(hwnd, uMsg, wParam, lParam);
+}
+
+#define VBOXEXTWND_NAME "VboxDispD3DWineWnd"
+
+static HRESULT vboxExtWndDoCleanup()
+{
+    HRESULT hr = S_OK;
+    HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);
+    WNDCLASS wc;
+    if (GetClassInfo(hInstance, VBOXEXTWND_NAME, &wc))
+    {
+        if (!UnregisterClass(VBOXEXTWND_NAME, hInstance))
+        {
+            DWORD winEr = GetLastError();
+            ERR("UnregisterClass failed, winErr(%d)\n", winEr);
+            hr = E_FAIL;
+        }
+    }
+    return hr;
+}
+
+static HRESULT vboxExtWndDoCreate(DWORD w, DWORD h, HWND *phWnd, HDC *phDC)
+{
+    HRESULT hr = S_OK;
+    HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);
+    /* Register the Window Class. */
+    WNDCLASS wc;
+    if (!GetClassInfo(hInstance, VBOXEXTWND_NAME, &wc))
+    {
+        wc.style = 0;//CS_OWNDC;
+        wc.lpfnWndProc = vboxExtWndProc;
+        wc.cbClsExtra = 0;
+        wc.cbWndExtra = 0;
+        wc.hInstance = hInstance;
+        wc.hIcon = NULL;
+        wc.hCursor = NULL;
+        wc.hbrBackground = NULL;
+        wc.lpszMenuName = NULL;
+        wc.lpszClassName = VBOXEXTWND_NAME;
+        if (!RegisterClass(&wc))
+        {
+            DWORD winErr = GetLastError();
+            ERR("RegisterClass failed, winErr(%d)\n", winErr);
+            hr = E_FAIL;
+        }
+    }
+
+    if (hr == S_OK)
+    {
+        HWND hWnd = CreateWindowEx (WS_EX_TOOLWINDOW,
+                                        VBOXEXTWND_NAME, VBOXEXTWND_NAME,
+                                        WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_DISABLED,
+                                        0, 0,
+                                        w, h,
+                                        NULL, //GetDesktopWindow() /* hWndParent */,
+                                        NULL /* hMenu */,
+                                        hInstance,
+                                        NULL /* lpParam */);
+        Assert(hWnd);
+        if (hWnd)
+        {
+            *phWnd = hWnd;
+            *phDC = GetDC(hWnd);
+            /* make sure we keep inited until the window is active */
+            vboxExtAddRef();
+        }
+        else
+        {
+            DWORD winErr = GetLastError();
+            ERR("CreateWindowEx failed, winErr(%d)\n", winErr);
+            hr = E_FAIL;
+        }
+    }
+
+    return hr;
+}
+
+static HRESULT vboxExtWndDoDestroy(HWND hWnd, HDC hDC)
+{
+    BOOL bResult;
+    DWORD winErr;
+    ReleaseDC(hWnd, hDC);
+    bResult = DestroyWindow(hWnd);
+    Assert(bResult);
+    if (bResult)
+    {
+        /* release the reference we previously acquired on window creation */
+        vboxExtRelease();
+        return S_OK;
+    }
+
+    winErr = GetLastError();
+    ERR("DestroyWindow failed, winErr(%d) for hWnd(0x%x)\n", winErr, hWnd);
+
+    return E_FAIL;
+}
+
+typedef struct VBOXEXTWND_CREATE_INFO
+{
+    int hr;
+    HWND hWnd;
+    HDC hDC;
+    DWORD width;
+    DWORD height;
+} VBOXEXTWND_CREATE_INFO;
+
+typedef struct VBOXEXTWND_DESTROY_INFO
+{
+    int hr;
+    HWND hWnd;
+    HDC hDC;
+} VBOXEXTWND_DESTROY_INFO;
+
+typedef struct VBOXEXTWND_CLEANUP_INFO
+{
+    int hr;
+} VBOXEXTWND_CLEANUP_INFO;
+
+static DECLCALLBACK(void) vboxExtWndDestroyWorker(void *pvUser)
+{
+    VBOXEXTWND_DESTROY_INFO *pInfo = (VBOXEXTWND_DESTROY_INFO*)pvUser;
+    pInfo->hr = vboxExtWndDoDestroy(pInfo->hWnd, pInfo->hDC);
+    Assert(pInfo->hr == S_OK);
+}
+
+static DECLCALLBACK(void) vboxExtWndCreateWorker(void *pvUser)
+{
+    VBOXEXTWND_CREATE_INFO *pInfo = (VBOXEXTWND_CREATE_INFO*)pvUser;
+    pInfo->hr = vboxExtWndDoCreate(pInfo->width, pInfo->height, &pInfo->hWnd, &pInfo->hDC);
+    Assert(pInfo->hr == S_OK);
+}
+
+static DECLCALLBACK(void) vboxExtWndCleanupWorker(void *pvUser)
+{
+    VBOXEXTWND_CLEANUP_INFO *pInfo = (VBOXEXTWND_CLEANUP_INFO*)pvUser;
+    pInfo-> hr = vboxExtWndDoCleanup();
+}
+
+HRESULT VBoxExtWndDestroy(HWND hWnd, HDC hDC)
+{
+    HRESULT hr;
+    VBOXEXTWND_DESTROY_INFO Info;
+    Info.hr = E_FAIL;
+    Info.hWnd = hWnd;
+    Info.hDC = hDC;
+    hr = VBoxExtDwSubmitProcSync(vboxExtWndDestroyWorker, &Info);
+    if (!SUCCEEDED(hr))
+    {
+        ERR("VBoxExtDwSubmitProcSync-vboxExtWndDestroyWorker failed hr %d", hr);
+        return hr;
+    }
+
+    if (!SUCCEEDED(Info.hr))
+    {
+        ERR("vboxExtWndDestroyWorker failed hr %d", Info.hr);
+        return Info.hr;
+    }
+
+    return S_OK;
+}
+
+HRESULT VBoxExtWndCreate(DWORD width, DWORD height, HWND *phWnd, HDC *phDC)
+{
+    HRESULT hr;
+    VBOXEXTWND_CREATE_INFO Info;
+    Info.hr = E_FAIL;
+    Info.width = width;
+    Info.height = height;
+    hr = VBoxExtDwSubmitProcSync(vboxExtWndCreateWorker, &Info);
+    if (!SUCCEEDED(hr))
+    {
+        ERR("VBoxExtDwSubmitProcSync-vboxExtWndCreateWorker failed hr %d", hr);
+        return hr;
+    }
+
+    Assert(Info.hr == S_OK);
+    if (!SUCCEEDED(Info.hr))
+    {
+        ERR("vboxExtWndCreateWorker failed hr %d", Info.hr);
+        return Info.hr;
+    }
+
+    *phWnd = Info.hWnd;
+    *phDC = Info.hDC;
+    return S_OK;
+}
+
+static HRESULT vboxExtWndCleanup()
+{
+    HRESULT hr;
+    VBOXEXTWND_CLEANUP_INFO Info;
+    Info.hr = E_FAIL;
+    hr = VBoxExtDwSubmitProcSync(vboxExtWndCleanupWorker, &Info);
+    if (!SUCCEEDED(hr))
+    {
+        ERR("VBoxExtDwSubmitProcSync-vboxExtWndCleanupWorker failed hr %d", hr);
+        return hr;
+    }
+
+    if (!SUCCEEDED(Info.hr))
+    {
+        ERR("vboxExtWndCleanupWorker failed hr %d", Info.hr);
+        return Info.hr;
+    }
+
+    return S_OK;
+}
+
+
+/* hash map impl */
+static void vboxExtHashInitEntries(PVBOXEXT_HASHMAP pMap)
+{
+    uint32_t i;
+    pMap->cEntries = 0;
+    for (i = 0; i < RT_ELEMENTS(pMap->aBuckets); ++i)
+    {
+        RTListInit(&pMap->aBuckets[i].EntryList);
+    }
+}
+
+void VBoxExtHashInit(PVBOXEXT_HASHMAP pMap, PFNVBOXEXT_HASHMAP_HASH pfnHash, PFNVBOXEXT_HASHMAP_EQUAL pfnEqual)
+{
+    pMap->pfnHash = pfnHash;
+    pMap->pfnEqual = pfnEqual;
+    vboxExtHashInitEntries(pMap);
+}
+
+static DECLINLINE(uint32_t) vboxExtHashIdx(uint32_t u32Hash)
+{
+    return u32Hash % VBOXEXT_HASHMAP_NUM_BUCKETS;
+}
+
+#define VBOXEXT_FOREACH_NODE(_pNode, _pList, _op) do { \
+        PRTLISTNODE _pNode; \
+        PRTLISTNODE __pNext; \
+        for (_pNode = (_pList)->pNext; \
+                _pNode != (_pList); \
+                _pNode = __pNext) \
+        { \
+            __pNext = _pNode->pNext; /* <- the _pNode should not be referenced after the _op */ \
+            _op \
+        } \
+    } while (0)
+
+DECLINLINE(PVBOXEXT_HASHMAP_ENTRY) vboxExtHashSearchEntry(PVBOXEXT_HASHMAP pMap, void *pvKey)
+{
+    uint32_t u32Hash = pMap->pfnHash(pvKey);
+    uint32_t u32HashIdx = vboxExtHashIdx(u32Hash);
+    PVBOXEXT_HASHMAP_BUCKET pBucket = &pMap->aBuckets[u32HashIdx];
+    PVBOXEXT_HASHMAP_ENTRY pEntry;
+    VBOXEXT_FOREACH_NODE(pNode, &pBucket->EntryList,
+        pEntry = RT_FROM_MEMBER(pNode, VBOXEXT_HASHMAP_ENTRY, ListNode);
+        if (pEntry->u32Hash != u32Hash)
+            continue;
+
+        if (!pMap->pfnEqual(pvKey, pEntry->pvKey))
+            continue;
+        return pEntry;
+    );
+    return NULL;
+}
+
+void* VBoxExtHashRemoveEntry(PVBOXEXT_HASHMAP pMap, PVBOXEXT_HASHMAP_ENTRY pEntry)
+{
+    RTListNodeRemove(&pEntry->ListNode);
+    --pMap->cEntries;
+    Assert(pMap->cEntries <= UINT32_MAX/2);
+    return pEntry->pvKey;
+}
+
+static void vboxExtHashPutEntry(PVBOXEXT_HASHMAP pMap, PVBOXEXT_HASHMAP_BUCKET pBucket, PVBOXEXT_HASHMAP_ENTRY pEntry)
+{
+    RTListNodeInsertAfter(&pBucket->EntryList, &pEntry->ListNode);
+    ++pMap->cEntries;
+}
+
+PVBOXEXT_HASHMAP_ENTRY VBoxExtHashRemove(PVBOXEXT_HASHMAP pMap, void *pvKey)
+{
+    PVBOXEXT_HASHMAP_ENTRY pEntry = vboxExtHashSearchEntry(pMap, pvKey);
+    if (!pEntry)
+        return NULL;
+
+    VBoxExtHashRemoveEntry(pMap, pEntry);
+    return pEntry;
+}
+
+PVBOXEXT_HASHMAP_ENTRY VBoxExtHashPut(PVBOXEXT_HASHMAP pMap, void *pvKey, PVBOXEXT_HASHMAP_ENTRY pEntry)
+{
+    PVBOXEXT_HASHMAP_ENTRY pOldEntry = VBoxExtHashRemove(pMap, pvKey);
+    uint32_t u32Hash = pMap->pfnHash(pvKey);
+    uint32_t u32HashIdx = vboxExtHashIdx(u32Hash);
+    pEntry->pvKey = pvKey;
+    pEntry->u32Hash = u32Hash;
+    vboxExtHashPutEntry(pMap, &pMap->aBuckets[u32HashIdx], pEntry);
+    return pOldEntry;
+}
+
+
+PVBOXEXT_HASHMAP_ENTRY VBoxExtHashGet(PVBOXEXT_HASHMAP pMap, void *pvKey)
+{
+    return vboxExtHashSearchEntry(pMap, pvKey);
+}
+
+void VBoxExtHashVisit(PVBOXEXT_HASHMAP pMap, PFNVBOXEXT_HASHMAP_VISITOR pfnVisitor, void *pvVisitor)
+{
+    uint32_t iBucket = 0, iEntry = 0;
+    uint32_t cEntries = pMap->cEntries;
+
+    if (!cEntries)
+        return;
+
+    for (; ; ++iBucket)
+    {
+        PVBOXEXT_HASHMAP_ENTRY pEntry;
+        PVBOXEXT_HASHMAP_BUCKET pBucket = &pMap->aBuckets[iBucket];
+        Assert(iBucket < RT_ELEMENTS(pMap->aBuckets));
+        VBOXEXT_FOREACH_NODE(pNode, &pBucket->EntryList,
+            pEntry = RT_FROM_MEMBER(pNode, VBOXEXT_HASHMAP_ENTRY, ListNode);
+            if (!pfnVisitor(pMap, pEntry->pvKey, pEntry, pvVisitor))
+                return;
+
+            if (++iEntry == cEntries)
+                return;
+        );
+    }
+
+    /* should not be here! */
+    AssertFailed();
+}
+
+void VBoxExtHashCleanup(PVBOXEXT_HASHMAP pMap, PFNVBOXEXT_HASHMAP_VISITOR pfnVisitor, void *pvVisitor)
+{
+    VBoxExtHashVisit(pMap, pfnVisitor, pvVisitor);
+    vboxExtHashInitEntries(pMap);
+}
+
+static DECLCALLBACK(bool) vboxExtCacheCleanupCb(struct VBOXEXT_HASHMAP *pMap, void *pvKey, struct VBOXEXT_HASHMAP_ENTRY *pValue, void *pvVisitor)
+{
+    PVBOXEXT_HASHCACHE pCache = VBOXEXT_HASHCACHE_FROM_MAP(pMap);
+    PVBOXEXT_HASHCACHE_ENTRY pCacheEntry = VBOXEXT_HASHCACHE_ENTRY_FROM_MAP(pValue);
+    pCache->pfnCleanupEntry(pvKey, pCacheEntry);
+    return TRUE;
+}
+
+void VBoxExtCacheCleanup(PVBOXEXT_HASHCACHE pCache)
+{
+    VBoxExtHashCleanup(&pCache->Map, vboxExtCacheCleanupCb, NULL);
+}
+
+#if defined(VBOXWINEDBG_SHADERS) || defined(VBOX_WINE_WITH_PROFILE)
+void vboxWDbgPrintF(char * szString, ...)
+{
+    char szBuffer[4096*2] = {0};
+    va_list pArgList;
+    va_start(pArgList, szString);
+    _vsnprintf(szBuffer, sizeof(szBuffer) / sizeof(szBuffer[0]), szString, pArgList);
+    va_end(pArgList);
+
+    OutputDebugStringA(szBuffer);
+}
+#endif
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/vboxext.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/vboxext.h	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/vboxext.h	(revision 46521)
@@ -0,0 +1,313 @@
+/* $Id$ */
+/** @file
+ *
+ * VBox extension to Wine D3D
+ *
+ * Copyright (C) 2011 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+#ifndef ___VBOXEXT_H__
+#define ___VBOXEXT_H__
+
+#ifdef VBOX_WINE_WITHOUT_LIBWINE
+# include <windows.h>
+#endif
+
+#include <iprt/list.h>
+
+HRESULT VBoxExtCheckInit();
+HRESULT VBoxExtCheckTerm();
+#if defined(VBOX_WINE_WITH_SINGLE_CONTEXT) || defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
+# ifndef VBOX_WITH_WDDM
+/* Windows destroys HDC created by a given thread when the thread is terminated
+ * this leads to a mess-up in Wine & Chromium code in some situations, e.g.
+ * D3D device is created in one thread, then the thread is terminated,
+ * then device is started to be used in another thread */
+HDC VBoxExtGetDC(HWND hWnd);
+int VBoxExtReleaseDC(HWND hWnd, HDC hDC);
+# endif
+/* We need to do a VBoxTlsRefRelease for the current thread context on thread exit to avoid memory leaking
+ * Calling VBoxTlsRefRelease may result in a call to context dtor callback, which is supposed to be run under wined3d lock.
+ * We can not acquire a wined3d lock in DllMain since this would result in a lock order violation, which may result in a deadlock.
+ * In other words, wined3d may internally call Win32 API functions which result in a DLL lock acquisition while holding wined3d lock.
+ * So lock order should always be "wined3d lock" -> "dll lock".
+ * To avoid possible deadlocks we make an asynchronous call to a worker thread to make a context release from there. */
+void VBoxExtReleaseContextAsync(struct wined3d_context *context);
+#endif
+
+/* API for creating & destroying windows */
+HRESULT VBoxExtWndDestroy(HWND hWnd, HDC hDC);
+HRESULT VBoxExtWndCreate(DWORD width, DWORD height, HWND *phWnd, HDC *phDC);
+
+
+/* hashmap */
+typedef DECLCALLBACK(uint32_t) FNVBOXEXT_HASHMAP_HASH(void *pvKey);
+typedef FNVBOXEXT_HASHMAP_HASH *PFNVBOXEXT_HASHMAP_HASH;
+
+typedef DECLCALLBACK(bool) FNVBOXEXT_HASHMAP_EQUAL(void *pvKey1, void *pvKey2);
+typedef FNVBOXEXT_HASHMAP_EQUAL *PFNVBOXEXT_HASHMAP_EQUAL;
+
+typedef DECLCALLBACK(bool) FNVBOXEXT_HASHMAP_VISITOR(struct VBOXEXT_HASHMAP *pMap, void *pvKey, struct VBOXEXT_HASHMAP_ENTRY *pValue, void *pvVisitor);
+typedef FNVBOXEXT_HASHMAP_VISITOR *PFNVBOXEXT_HASHMAP_VISITOR;
+
+typedef struct VBOXEXT_HASHMAP_ENTRY
+{
+    RTLISTNODE ListNode;
+    void *pvKey;
+    uint32_t u32Hash;
+} VBOXEXT_HASHMAP_ENTRY, *PVBOXEXT_HASHMAP_ENTRY;
+
+typedef struct VBOXEXT_HASHMAP_BUCKET
+{
+    RTLISTNODE EntryList;
+} VBOXEXT_HASHMAP_BUCKET, *PVBOXEXT_HASHMAP_BUCKET;
+
+#define VBOXEXT_HASHMAP_NUM_BUCKETS 29
+
+typedef struct VBOXEXT_HASHMAP
+{
+    PFNVBOXEXT_HASHMAP_HASH pfnHash;
+    PFNVBOXEXT_HASHMAP_EQUAL pfnEqual;
+    uint32_t cEntries;
+    VBOXEXT_HASHMAP_BUCKET aBuckets[VBOXEXT_HASHMAP_NUM_BUCKETS];
+} VBOXEXT_HASHMAP, *PVBOXEXT_HASHMAP;
+
+void VBoxExtHashInit(PVBOXEXT_HASHMAP pMap, PFNVBOXEXT_HASHMAP_HASH pfnHash, PFNVBOXEXT_HASHMAP_EQUAL pfnEqual);
+PVBOXEXT_HASHMAP_ENTRY VBoxExtHashPut(PVBOXEXT_HASHMAP pMap, void *pvKey, PVBOXEXT_HASHMAP_ENTRY pEntry);
+PVBOXEXT_HASHMAP_ENTRY VBoxExtHashGet(PVBOXEXT_HASHMAP pMap, void *pvKey);
+PVBOXEXT_HASHMAP_ENTRY VBoxExtHashRemove(PVBOXEXT_HASHMAP pMap, void *pvKey);
+void* VBoxExtHashRemoveEntry(PVBOXEXT_HASHMAP pMap, PVBOXEXT_HASHMAP_ENTRY pEntry);
+void VBoxExtHashVisit(PVBOXEXT_HASHMAP pMap, PFNVBOXEXT_HASHMAP_VISITOR pfnVisitor, void *pvVisitor);
+void VBoxExtHashCleanup(PVBOXEXT_HASHMAP pMap, PFNVBOXEXT_HASHMAP_VISITOR pfnVisitor, void *pvVisitor);
+
+DECLINLINE(uint32_t) VBoxExtHashSize(PVBOXEXT_HASHMAP pMap)
+{
+    return pMap->cEntries;
+}
+
+DECLINLINE(void*) VBoxExtHashEntryKey(PVBOXEXT_HASHMAP_ENTRY pEntry)
+{
+    return pEntry->pvKey;
+}
+
+typedef DECLCALLBACK(void) FNVBOXEXT_HASHCACHE_CLEANUP_ENTRY(void *pvKey, struct VBOXEXT_HASHCACHE_ENTRY *pEntry);
+typedef FNVBOXEXT_HASHCACHE_CLEANUP_ENTRY *PFNVBOXEXT_HASHCACHE_CLEANUP_ENTRY;
+
+typedef struct VBOXEXT_HASHCACHE_ENTRY
+{
+    VBOXEXT_HASHMAP_ENTRY MapEntry;
+    uint32_t u32Usage;
+} VBOXEXT_HASHCACHE_ENTRY, *PVBOXEXT_HASHCACHE_ENTRY;
+
+typedef struct VBOXEXT_HASHCACHE
+{
+    VBOXEXT_HASHMAP Map;
+    uint32_t cMaxElements;
+    PFNVBOXEXT_HASHCACHE_CLEANUP_ENTRY pfnCleanupEntry;
+} VBOXEXT_HASHCACHE, *PVBOXEXT_HASHCACHE;
+
+#define VBOXEXT_HASHCACHE_FROM_MAP(_pMap) RT_FROM_MEMBER((_pMap), VBOXEXT_HASHCACHE, Map)
+#define VBOXEXT_HASHCACHE_ENTRY_FROM_MAP(_pEntry) RT_FROM_MEMBER((_pEntry), VBOXEXT_HASHCACHE_ENTRY, MapEntry)
+
+DECLINLINE(void) VBoxExtCacheInit(PVBOXEXT_HASHCACHE pCache, uint32_t cMaxElements,
+        PFNVBOXEXT_HASHMAP_HASH pfnHash,
+        PFNVBOXEXT_HASHMAP_EQUAL pfnEqual,
+        PFNVBOXEXT_HASHCACHE_CLEANUP_ENTRY pfnCleanupEntry)
+{
+    VBoxExtHashInit(&pCache->Map, pfnHash, pfnEqual);
+    pCache->cMaxElements = cMaxElements;
+    pCache->pfnCleanupEntry = pfnCleanupEntry;
+}
+
+DECLINLINE(PVBOXEXT_HASHCACHE_ENTRY) VBoxExtCacheGet(PVBOXEXT_HASHCACHE pCache, void *pvKey)
+{
+    PVBOXEXT_HASHMAP_ENTRY pEntry = VBoxExtHashRemove(&pCache->Map, pvKey);
+    return VBOXEXT_HASHCACHE_ENTRY_FROM_MAP(pEntry);
+}
+
+DECLINLINE(void) VBoxExtCachePut(PVBOXEXT_HASHCACHE pCache, void *pvKey, PVBOXEXT_HASHCACHE_ENTRY pEntry)
+{
+    PVBOXEXT_HASHMAP_ENTRY pOldEntry = VBoxExtHashPut(&pCache->Map, pvKey, &pEntry->MapEntry);
+    PVBOXEXT_HASHCACHE_ENTRY pOld;
+    if (!pOldEntry)
+        return;
+    pOld = VBOXEXT_HASHCACHE_ENTRY_FROM_MAP(pOldEntry);
+    if (pOld != pEntry)
+        pCache->pfnCleanupEntry(pvKey, pOld);
+}
+
+void VBoxExtCacheCleanup(PVBOXEXT_HASHCACHE pCache);
+
+DECLINLINE(void) VBoxExtCacheTerm(PVBOXEXT_HASHCACHE pCache)
+{
+    VBoxExtCacheCleanup(pCache);
+}
+
+#ifdef VBOX_WINE_WITH_PROFILE
+
+#include <iprt/time.h>
+
+void vboxWDbgPrintF(char * szString, ...);
+
+#define VBOXWINEPROFILE_GET_TIME_NANO() RTTimeNanoTS()
+#define VBOXWINEPROFILE_GET_TIME_MILLI() RTTimeMilliTS()
+
+# define PRLOG(_m) do {\
+        vboxWDbgPrintF _m ; \
+    } while (0)
+
+typedef struct VBOXWINEPROFILE_ELEMENT
+{
+    uint64_t u64Time;
+    uint32_t cu32Calls;
+} VBOXWINEPROFILE_ELEMENT, *PVBOXWINEPROFILE_ELEMENT;
+
+typedef struct VBOXWINEPROFILE_HASHMAP_ELEMENT
+{
+    VBOXEXT_HASHMAP_ENTRY MapEntry;
+    VBOXWINEPROFILE_ELEMENT Data;
+} VBOXWINEPROFILE_HASHMAP_ELEMENT, *PVBOXWINEPROFILE_HASHMAP_ELEMENT;
+
+#define VBOXWINEPROFILE_HASHMAP_ELEMENT_FROMENTRY(_p) ((PVBOXWINEPROFILE_HASHMAP_ELEMENT)(((uint8_t*)(_p)) - RT_OFFSETOF(VBOXWINEPROFILE_HASHMAP_ELEMENT, MapEntry)))
+
+#define VBOXWINEPROFILE_ELEMENT_DUMP(_p, _pn) do { \
+        PRLOG(("%s: t(%u);c(%u)\n", \
+            (_pn), \
+            (uint32_t)((_p)->u64Time / 1000000), \
+            (_p)->cu32Calls \
+            )); \
+    } while (0)
+
+#define VBOXWINEPROFILE_ELEMENT_RESET(_p) do { \
+        memset(_p, 0, sizeof (*(_p))); \
+    } while (0)
+
+#define VBOXWINEPROFILE_ELEMENT_STEP(_p, _t) do { \
+        (_p)->u64Time += (_t); \
+        ++(_p)->cu32Calls; \
+    } while (0)
+
+#define VBOXWINEPROFILE_HASHMAP_ELEMENT_CREATE()  ( (PVBOXWINEPROFILE_HASHMAP_ELEMENT)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof (VBOXWINEPROFILE_HASHMAP_ELEMENT)) )
+
+#define VBOXWINEPROFILE_HASHMAP_ELEMENT_TERM(_pe) do { \
+        HeapFree(GetProcessHeap(), 0, (_pe)); \
+    } while (0)
+
+DECLINLINE(PVBOXWINEPROFILE_HASHMAP_ELEMENT) vboxWineProfileHashMapElementGet(PVBOXEXT_HASHMAP pMap, void *pvKey)
+{
+    PVBOXEXT_HASHMAP_ENTRY pEntry = VBoxExtHashGet(pMap, pvKey);
+    if (pEntry)
+    {
+        return VBOXWINEPROFILE_HASHMAP_ELEMENT_FROMENTRY(pEntry);
+    }
+    else
+    {
+        PVBOXWINEPROFILE_HASHMAP_ELEMENT pElement = VBOXWINEPROFILE_HASHMAP_ELEMENT_CREATE();
+        Assert(pElement);
+        if (pElement)
+            VBoxExtHashPut(pMap, pvKey, &pElement->MapEntry);
+        return pElement;
+    }
+}
+
+#define VBOXWINEPROFILE_HASHMAP_ELEMENT_STEP(_pm, _pk, _t) do { \
+        PVBOXWINEPROFILE_HASHMAP_ELEMENT pElement = vboxWineProfileHashMapElementGet(_pm, _pk); \
+        VBOXWINEPROFILE_ELEMENT_STEP(&pElement->Data, _t); \
+    } while (0)
+
+static DECLCALLBACK(bool) vboxWineProfileElementResetCb(struct VBOXEXT_HASHMAP *pMap, void *pvKey, struct VBOXEXT_HASHMAP_ENTRY *pValue, void *pvVisitor)
+{
+    PVBOXWINEPROFILE_HASHMAP_ELEMENT pElement = VBOXWINEPROFILE_HASHMAP_ELEMENT_FROMENTRY(pValue);
+    VBOXWINEPROFILE_ELEMENT_RESET(&pElement->Data);
+    return true;
+}
+
+static DECLCALLBACK(bool) vboxWineProfileElementDumpCb(struct VBOXEXT_HASHMAP *pMap, void *pvKey, struct VBOXEXT_HASHMAP_ENTRY *pValue, void *pvVisitor)
+{
+    PVBOXWINEPROFILE_HASHMAP_ELEMENT pElement = VBOXWINEPROFILE_HASHMAP_ELEMENT_FROMENTRY(pValue);
+    char *pName = (char*)pvVisitor;
+    PRLOG(("%s[%d]:", pName, (uint32_t)pvKey));
+    VBOXWINEPROFILE_ELEMENT_DUMP(&pElement->Data, "");
+    return true;
+}
+
+
+#define VBOXWINEPROFILE_HASHMAP_RESET(_pm) do { \
+        VBoxExtHashVisit((_pm), vboxWineProfileElementResetCb, NULL); \
+    } while (0)
+
+#define VBOXWINEPROFILE_HASHMAP_DUMP(_pm, _pn) do { \
+        VBoxExtHashVisit((_pm), vboxWineProfileElementDumpCb, (_pn)); \
+    } while (0)
+
+static DECLCALLBACK(bool) vboxWineProfileElementCleanupCb(struct VBOXEXT_HASHMAP *pMap, void *pvKey, struct VBOXEXT_HASHMAP_ENTRY *pValue, void *pvVisitor)
+{
+    PVBOXWINEPROFILE_HASHMAP_ELEMENT pElement = VBOXWINEPROFILE_HASHMAP_ELEMENT_FROMENTRY(pValue);
+    VBOXWINEPROFILE_HASHMAP_ELEMENT_TERM(pElement);
+    return true;
+}
+
+#define VBOXWINEPROFILE_HASHMAP_TERM(_pm) do { \
+        VBoxExtHashCleanup((_pm), vboxWineProfileElementCleanupCb, NULL); \
+        VBoxExtHashVisit((_pm), vboxWineProfileElementResetCb, NULL); \
+    } while (0)
+
+typedef struct VBOXWINEPROFILE_DRAWPRIM
+{
+    uint64_t u64LoadLocationTime;
+    uint64_t u64CtxAcquireTime;
+    uint64_t u64PostProcess;
+    VBOXEXT_HASHMAP MapDrawPrimSlowVs;
+    VBOXEXT_HASHMAP MapDrawPrimSlow;
+    VBOXEXT_HASHMAP MapDrawPrimStrided;
+    VBOXEXT_HASHMAP MapDrawPrimFast;
+    uint32_t cu32Calls;
+} VBOXWINEPROFILE_DRAWPRIM, *PVBOXWINEPROFILE_DRAWPRIM;
+
+#define VBOXWINEPROFILE_DRAWPRIM_RESET_NEXT(_p) do { \
+        (_p)->u64LoadLocationTime = 0; \
+        (_p)->u64CtxAcquireTime = 0; \
+        (_p)->u64PostProcess = 0; \
+        VBOXWINEPROFILE_HASHMAP_RESET(&(_p)->MapDrawPrimSlowVs); \
+        VBOXWINEPROFILE_HASHMAP_RESET(&(_p)->MapDrawPrimSlow); \
+        VBOXWINEPROFILE_HASHMAP_RESET(&(_p)->MapDrawPrimStrided); \
+        VBOXWINEPROFILE_HASHMAP_RESET(&(_p)->MapDrawPrimFast); \
+    } while (0)
+
+static DECLCALLBACK(uint32_t) vboxWineProfileDrawPrimHashMapHash(void *pvKey)
+{
+    return (uint32_t)pvKey;
+}
+
+static DECLCALLBACK(bool) vboxWineProfileDrawPrimHashMapEqual(void *pvKey1, void *pvKey2)
+{
+    return ((uint32_t)pvKey1) == ((uint32_t)pvKey2);
+}
+
+#define VBOXWINEPROFILE_DRAWPRIM_INIT(_p) do { \
+        memset((_p), 0, sizeof (*(_p))); \
+        VBoxExtHashInit(&(_p)->MapDrawPrimSlowVs, vboxWineProfileDrawPrimHashMapHash, vboxWineProfileDrawPrimHashMapEqual); \
+        VBoxExtHashInit(&(_p)->MapDrawPrimSlow, vboxWineProfileDrawPrimHashMapHash, vboxWineProfileDrawPrimHashMapEqual); \
+        VBoxExtHashInit(&(_p)->MapDrawPrimStrided, vboxWineProfileDrawPrimHashMapHash, vboxWineProfileDrawPrimHashMapEqual); \
+        VBoxExtHashInit(&(_p)->MapDrawPrimFast, vboxWineProfileDrawPrimHashMapHash, vboxWineProfileDrawPrimHashMapEqual); \
+    } while (0)
+
+#define VBOXWINEPROFILE_DRAWPRIM_TERM(_p) do { \
+        memset((_p), 0, sizeof (*(_p))); \
+        VBOXWINEPROFILE_HASHMAP_TERM(&(_p)->MapDrawPrimSlowVs); \
+        VBOXWINEPROFILE_HASHMAP_TERM(&(_p)->MapDrawPrimSlow); \
+        VBOXWINEPROFILE_HASHMAP_TERM(&(_p)->MapDrawPrimStrided); \
+        VBOXWINEPROFILE_HASHMAP_TERM(&(_p)->MapDrawPrimFast); \
+    } while (0)
+#else
+# define PRLOG(_m) do {} while (0)
+#endif
+
+#endif /* #ifndef ___VBOXEXT_H__*/
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/vboxsharedrc.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/vboxsharedrc.h	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/vboxsharedrc.h	(revision 46521)
@@ -0,0 +1,49 @@
+/* $Id$ */
+/** @file
+ *
+ * VBox extension to Wine D3D - shared resource
+ *
+ * Copyright (C) 2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+#ifndef ___vboxsharedrc_h___
+#define ___vboxsharedrc_h___
+
+#define VBOXSHRC_F_SHARED              0x00000001 /* shared rc */
+#define VBOXSHRC_F_SHARED_OPENED       0x00000002 /* if set shared rc is opened, otherwise it is created */
+
+#define VBOXSHRC_GET_SHAREFLAFS(_o) ((_o)->resource.sharerc_flags)
+#define VBOXSHRC_GET_SHAREHANDLE(_o) ((HANDLE)(_o)->resource.sharerc_handle)
+#define VBOXSHRC_SET_SHAREHANDLE(_o, _h) ((_o)->resource.sharerc_handle = (DWORD)(_h))
+#define VBOXSHRC_COPY_SHAREDATA(_oDst, _oSrc) do { \
+        VBOXSHRC_GET_SHAREFLAFS(_oDst) = VBOXSHRC_GET_SHAREFLAFS(_oSrc);   \
+        VBOXSHRC_SET_SHAREHANDLE(_oDst, VBOXSHRC_GET_SHAREHANDLE(_oSrc)); \
+    } while (0)
+#define VBOXSHRC_SET_SHARED(_o) (VBOXSHRC_GET_SHAREFLAFS(_o) |= VBOXSHRC_F_SHARED)
+#define VBOXSHRC_SET_SHARED_OPENED(_o) (VBOXSHRC_GET_SHAREFLAFS(_o) |= VBOXSHRC_F_SHARED_OPENED)
+
+#define VBOXSHRC_IS_SHARED(_o) (!!(VBOXSHRC_GET_SHAREFLAFS(_o) & VBOXSHRC_F_SHARED))
+#define VBOXSHRC_IS_SHARED_OPENED(_o) (!!(VBOXSHRC_GET_SHAREFLAFS(_o) & VBOXSHRC_F_SHARED_OPENED))
+#define VBOXSHRC_IS_SHARED_UNLOCKED(_o) (VBOXSHRC_IS_SHARED(_o) && !VBOXSHRC_IS_LOCKED(_o))
+
+#define VBOXSHRC_LOCK(_o) do{ \
+        Assert(VBOXSHRC_IS_SHARED(_o)); \
+        ++(_o)->resource.sharerc_locks; \
+    } while (0)
+#define VBOXSHRC_UNLOCK(_o) do{ \
+        Assert(VBOXSHRC_IS_SHARED(_o)); \
+        --(_o)->resource.sharerc_locks; \
+        Assert((_o)->resource.sharerc_locks < UINT32_MAX/2); \
+    } while (0)
+#define VBOXSHRC_IS_LOCKED(_o) ( \
+        !!((_o)->resource.sharerc_locks) \
+        )
+
+#endif /* #ifndef ___vboxsharedrc_h___ */
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/version.rc
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/version.rc	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/version.rc	(revision 46521)
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2009 Austin English
+ *
+ * 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" /* Needed to get PACKAGE_VERSION */
+
+#define WINE_FILEDESCRIPTION_STR "Wine D3D"
+#define WINE_FILENAME_STR "wined3d.dll"
+#define WINE_FILEVERSION_STR PACKAGE_VERSION
+#define WINE_PRODUCTVERSION_STR PACKAGE_VERSION
+#define WINE_PRODUCTNAME_STR "Wine D3D"
+
+#include "wine/wine_common_ver.rc"
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/vertexdeclaration.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/vertexdeclaration.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/vertexdeclaration.c	(revision 46521)
@@ -0,0 +1,420 @@
+/*
+ * vertex declaration implementation
+ *
+ * Copyright 2002-2005 Raphael Junqueira
+ * Copyright 2004 Jason Edmeades
+ * Copyright 2004 Christian Costa
+ * Copyright 2005 Oliver Stieber
+ * Copyright 2009 Henri Verbeet for CodeWeavers
+ *
+ * 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 "wined3d_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d_decl);
+
+static void dump_wined3d_vertex_element(const struct wined3d_vertex_element *element)
+{
+    TRACE("     format: %s (%#x)\n", debug_d3dformat(element->format), element->format);
+    TRACE(" input_slot: %u\n", element->input_slot);
+    TRACE("     offset: %u\n", element->offset);
+    TRACE("output_slot: %u\n", element->output_slot);
+    TRACE("     method: %s (%#x)\n", debug_d3ddeclmethod(element->method), element->method);
+    TRACE("      usage: %s (%#x)\n", debug_d3ddeclusage(element->usage), element->usage);
+    TRACE("  usage_idx: %u\n", element->usage_idx);
+}
+
+ULONG CDECL wined3d_vertex_declaration_incref(struct wined3d_vertex_declaration *declaration)
+{
+    ULONG refcount = InterlockedIncrement(&declaration->ref);
+
+    TRACE("%p increasing refcount to %u.\n", declaration, refcount);
+
+    return refcount;
+}
+
+ULONG CDECL wined3d_vertex_declaration_decref(struct wined3d_vertex_declaration *declaration)
+{
+    ULONG refcount = InterlockedDecrement(&declaration->ref);
+
+    TRACE("%p decreasing refcount to %u.\n", declaration, refcount);
+
+    if (!refcount)
+    {
+        HeapFree(GetProcessHeap(), 0, declaration->elements);
+        declaration->parent_ops->wined3d_object_destroyed(declaration->parent);
+        HeapFree(GetProcessHeap(), 0, declaration);
+    }
+
+    return refcount;
+}
+
+void * CDECL wined3d_vertex_declaration_get_parent(const struct wined3d_vertex_declaration *declaration)
+{
+    TRACE("declaration %p.\n", declaration);
+
+    return declaration->parent;
+}
+
+static BOOL declaration_element_valid_ffp(const struct wined3d_vertex_element *element)
+{
+    switch(element->usage)
+    {
+        case WINED3D_DECL_USAGE_POSITION:
+        case WINED3D_DECL_USAGE_POSITIONT:
+            switch(element->format)
+            {
+                case WINED3DFMT_R32G32_FLOAT:
+                case WINED3DFMT_R32G32B32_FLOAT:
+                case WINED3DFMT_R32G32B32A32_FLOAT:
+                case WINED3DFMT_R16G16_SINT:
+                case WINED3DFMT_R16G16B16A16_SINT:
+                case WINED3DFMT_R16G16_FLOAT:
+                case WINED3DFMT_R16G16B16A16_FLOAT:
+                    return TRUE;
+                default:
+                    return FALSE;
+            }
+
+        case WINED3D_DECL_USAGE_BLEND_WEIGHT:
+            switch(element->format)
+            {
+                case WINED3DFMT_R32_FLOAT:
+                case WINED3DFMT_R32G32_FLOAT:
+                case WINED3DFMT_R32G32B32_FLOAT:
+                case WINED3DFMT_R32G32B32A32_FLOAT:
+                case WINED3DFMT_B8G8R8A8_UNORM:
+                case WINED3DFMT_R8G8B8A8_UINT:
+                case WINED3DFMT_R16G16_SINT:
+                case WINED3DFMT_R16G16B16A16_SINT:
+                case WINED3DFMT_R16G16_FLOAT:
+                case WINED3DFMT_R16G16B16A16_FLOAT:
+                    return TRUE;
+                default:
+                    return FALSE;
+            }
+
+        case WINED3D_DECL_USAGE_NORMAL:
+            switch(element->format)
+            {
+                case WINED3DFMT_R32G32B32_FLOAT:
+                case WINED3DFMT_R32G32B32A32_FLOAT:
+                case WINED3DFMT_R16G16B16A16_SINT:
+                case WINED3DFMT_R16G16B16A16_FLOAT:
+                    return TRUE;
+                default:
+                    return FALSE;
+            }
+
+        case WINED3D_DECL_USAGE_TEXCOORD:
+            switch(element->format)
+            {
+                case WINED3DFMT_R32_FLOAT:
+                case WINED3DFMT_R32G32_FLOAT:
+                case WINED3DFMT_R32G32B32_FLOAT:
+                case WINED3DFMT_R32G32B32A32_FLOAT:
+                case WINED3DFMT_R16G16_SINT:
+                case WINED3DFMT_R16G16B16A16_SINT:
+                case WINED3DFMT_R16G16_FLOAT:
+                case WINED3DFMT_R16G16B16A16_FLOAT:
+                    return TRUE;
+                default:
+                    return FALSE;
+            }
+
+        case WINED3D_DECL_USAGE_COLOR:
+            switch(element->format)
+            {
+                case WINED3DFMT_R32G32B32_FLOAT:
+                case WINED3DFMT_R32G32B32A32_FLOAT:
+                case WINED3DFMT_B8G8R8A8_UNORM:
+                case WINED3DFMT_R8G8B8A8_UINT:
+                case WINED3DFMT_R16G16B16A16_SINT:
+                case WINED3DFMT_R8G8B8A8_UNORM:
+                case WINED3DFMT_R16G16B16A16_SNORM:
+                case WINED3DFMT_R16G16B16A16_UNORM:
+                case WINED3DFMT_R16G16B16A16_FLOAT:
+                    return TRUE;
+                default:
+                    return FALSE;
+            }
+
+        default:
+            return FALSE;
+    }
+}
+
+static HRESULT vertexdeclaration_init(struct wined3d_vertex_declaration *declaration,
+        struct wined3d_device *device, const struct wined3d_vertex_element *elements, UINT element_count,
+        void *parent, const struct wined3d_parent_ops *parent_ops)
+{
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    unsigned int i;
+
+    if (TRACE_ON(d3d_decl))
+    {
+        for (i = 0; i < element_count; ++i)
+        {
+            dump_wined3d_vertex_element(elements + i);
+        }
+    }
+
+    declaration->ref = 1;
+    declaration->parent = parent;
+    declaration->parent_ops = parent_ops;
+    declaration->device = device;
+    declaration->elements = HeapAlloc(GetProcessHeap(), 0, sizeof(*declaration->elements) * element_count);
+    if (!declaration->elements)
+    {
+        ERR("Failed to allocate elements memory.\n");
+        return E_OUTOFMEMORY;
+    }
+    declaration->element_count = element_count;
+
+    /* Do some static analysis on the elements to make reading the
+     * declaration more comfortable for the drawing code. */
+    for (i = 0; i < element_count; ++i)
+    {
+        struct wined3d_vertex_declaration_element *e = &declaration->elements[i];
+
+        e->format = wined3d_get_format(gl_info, elements[i].format);
+        e->ffp_valid = declaration_element_valid_ffp(&elements[i]);
+        e->input_slot = elements[i].input_slot;
+        e->offset = elements[i].offset;
+        e->output_slot = elements[i].output_slot;
+        e->method = elements[i].method;
+        e->usage = elements[i].usage;
+        e->usage_idx = elements[i].usage_idx;
+
+        if (e->usage == WINED3D_DECL_USAGE_POSITIONT)
+            declaration->position_transformed = TRUE;
+
+        /* Find the streams used in the declaration. The vertex buffers have
+         * to be loaded when drawing, but filter tesselation pseudo streams. */
+        if (e->input_slot >= MAX_STREAMS) continue;
+
+        if (!e->format->gl_vtx_format)
+        {
+            FIXME("The application tries to use an unsupported format (%s), returning E_FAIL.\n",
+                    debug_d3dformat(elements[i].format));
+            HeapFree(GetProcessHeap(), 0, declaration->elements);
+            return E_FAIL;
+        }
+
+        if (e->offset & 0x3)
+        {
+            WARN("Declaration element %u is not 4 byte aligned(%u), returning E_FAIL.\n", i, e->offset);
+            HeapFree(GetProcessHeap(), 0, declaration->elements);
+            return E_FAIL;
+        }
+
+        if (elements[i].format == WINED3DFMT_R16G16_FLOAT || elements[i].format == WINED3DFMT_R16G16B16A16_FLOAT)
+        {
+            if (!gl_info->supported[ARB_HALF_FLOAT_VERTEX]) declaration->half_float_conv_needed = TRUE;
+        }
+    }
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_vertex_declaration_create(struct wined3d_device *device,
+        const struct wined3d_vertex_element *elements, UINT element_count, void *parent,
+        const struct wined3d_parent_ops *parent_ops, struct wined3d_vertex_declaration **declaration)
+{
+    struct wined3d_vertex_declaration *object;
+    HRESULT hr;
+
+    TRACE("device %p, elements %p, element_count %u, parent %p, parent_ops %p, declaration %p.\n",
+            device, elements, element_count, parent, parent_ops, declaration);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if(!object)
+        return E_OUTOFMEMORY;
+
+    hr = vertexdeclaration_init(object, device, elements, element_count, parent, parent_ops);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize vertex declaration, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created vertex declaration %p.\n", object);
+    *declaration = object;
+
+    return WINED3D_OK;
+}
+
+struct wined3d_fvf_convert_state
+{
+    const struct wined3d_gl_info *gl_info;
+    struct wined3d_vertex_element *elements;
+    UINT offset;
+    UINT idx;
+};
+
+static void append_decl_element(struct wined3d_fvf_convert_state *state,
+        enum wined3d_format_id format_id, enum wined3d_decl_usage usage, UINT usage_idx)
+{
+    struct wined3d_vertex_element *elements = state->elements;
+    const struct wined3d_format *format;
+    UINT offset = state->offset;
+    UINT idx = state->idx;
+
+    elements[idx].format = format_id;
+    elements[idx].input_slot = 0;
+    elements[idx].offset = offset;
+    elements[idx].output_slot = 0;
+    elements[idx].method = WINED3D_DECL_METHOD_DEFAULT;
+    elements[idx].usage = usage;
+    elements[idx].usage_idx = usage_idx;
+
+    format = wined3d_get_format(state->gl_info, format_id);
+    state->offset += format->component_count * format->component_size;
+    ++state->idx;
+}
+
+static unsigned int convert_fvf_to_declaration(const struct wined3d_gl_info *gl_info,
+        DWORD fvf, struct wined3d_vertex_element **elements)
+{
+    BOOL has_pos = !!(fvf & WINED3DFVF_POSITION_MASK);
+    BOOL has_blend = (fvf & WINED3DFVF_XYZB5) > WINED3DFVF_XYZRHW;
+    BOOL has_blend_idx = has_blend &&
+       (((fvf & WINED3DFVF_XYZB5) == WINED3DFVF_XYZB5) ||
+        (fvf & WINED3DFVF_LASTBETA_D3DCOLOR) ||
+        (fvf & WINED3DFVF_LASTBETA_UBYTE4));
+    BOOL has_normal = !!(fvf & WINED3DFVF_NORMAL);
+    BOOL has_psize = !!(fvf & WINED3DFVF_PSIZE);
+    BOOL has_diffuse = !!(fvf & WINED3DFVF_DIFFUSE);
+    BOOL has_specular = !!(fvf & WINED3DFVF_SPECULAR);
+
+    DWORD num_textures = (fvf & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
+    DWORD texcoords = (fvf & 0xffff0000) >> 16;
+    struct wined3d_fvf_convert_state state;
+    unsigned int size;
+    unsigned int idx;
+    DWORD num_blends = 1 + (((fvf & WINED3DFVF_XYZB5) - WINED3DFVF_XYZB1) >> 1);
+    if (has_blend_idx) num_blends--;
+
+    /* Compute declaration size */
+    size = has_pos + (has_blend && num_blends > 0) + has_blend_idx + has_normal +
+           has_psize + has_diffuse + has_specular + num_textures;
+
+    state.gl_info = gl_info;
+    state.elements = HeapAlloc(GetProcessHeap(), 0, size * sizeof(*state.elements));
+    if (!state.elements) return ~0U;
+    state.offset = 0;
+    state.idx = 0;
+
+    if (has_pos)
+    {
+        if (!has_blend && (fvf & WINED3DFVF_XYZRHW))
+            append_decl_element(&state, WINED3DFMT_R32G32B32A32_FLOAT, WINED3D_DECL_USAGE_POSITIONT, 0);
+        else if ((fvf & WINED3DFVF_XYZW) == WINED3DFVF_XYZW)
+            append_decl_element(&state, WINED3DFMT_R32G32B32A32_FLOAT, WINED3D_DECL_USAGE_POSITION, 0);
+        else
+            append_decl_element(&state, WINED3DFMT_R32G32B32_FLOAT, WINED3D_DECL_USAGE_POSITION, 0);
+    }
+
+    if (has_blend && (num_blends > 0))
+    {
+        if ((fvf & WINED3DFVF_XYZB5) == WINED3DFVF_XYZB2 && (fvf & WINED3DFVF_LASTBETA_D3DCOLOR))
+            append_decl_element(&state, WINED3DFMT_B8G8R8A8_UNORM, WINED3D_DECL_USAGE_BLEND_WEIGHT, 0);
+        else
+        {
+            switch (num_blends)
+            {
+                case 1:
+                    append_decl_element(&state, WINED3DFMT_R32_FLOAT, WINED3D_DECL_USAGE_BLEND_WEIGHT, 0);
+                    break;
+                case 2:
+                    append_decl_element(&state, WINED3DFMT_R32G32_FLOAT, WINED3D_DECL_USAGE_BLEND_WEIGHT, 0);
+                    break;
+                case 3:
+                    append_decl_element(&state, WINED3DFMT_R32G32B32_FLOAT, WINED3D_DECL_USAGE_BLEND_WEIGHT, 0);
+                    break;
+                case 4:
+                    append_decl_element(&state, WINED3DFMT_R32G32B32A32_FLOAT, WINED3D_DECL_USAGE_BLEND_WEIGHT, 0);
+                    break;
+                default:
+                    ERR("Unexpected amount of blend values: %u\n", num_blends);
+            }
+        }
+    }
+
+    if (has_blend_idx)
+    {
+        if ((fvf & WINED3DFVF_LASTBETA_UBYTE4)
+                || ((fvf & WINED3DFVF_XYZB5) == WINED3DFVF_XYZB2 && (fvf & WINED3DFVF_LASTBETA_D3DCOLOR)))
+            append_decl_element(&state, WINED3DFMT_R8G8B8A8_UINT, WINED3D_DECL_USAGE_BLEND_INDICES, 0);
+        else if (fvf & WINED3DFVF_LASTBETA_D3DCOLOR)
+            append_decl_element(&state, WINED3DFMT_B8G8R8A8_UNORM, WINED3D_DECL_USAGE_BLEND_INDICES, 0);
+        else
+            append_decl_element(&state, WINED3DFMT_R32_FLOAT, WINED3D_DECL_USAGE_BLEND_INDICES, 0);
+    }
+
+    if (has_normal)
+        append_decl_element(&state, WINED3DFMT_R32G32B32_FLOAT, WINED3D_DECL_USAGE_NORMAL, 0);
+    if (has_psize)
+        append_decl_element(&state, WINED3DFMT_R32_FLOAT, WINED3D_DECL_USAGE_PSIZE, 0);
+    if (has_diffuse)
+        append_decl_element(&state, WINED3DFMT_B8G8R8A8_UNORM, WINED3D_DECL_USAGE_COLOR, 0);
+    if (has_specular)
+        append_decl_element(&state, WINED3DFMT_B8G8R8A8_UNORM, WINED3D_DECL_USAGE_COLOR, 1);
+
+    for (idx = 0; idx < num_textures; ++idx)
+    {
+        switch ((texcoords >> (idx * 2)) & 0x03)
+        {
+            case WINED3DFVF_TEXTUREFORMAT1:
+                append_decl_element(&state, WINED3DFMT_R32_FLOAT, WINED3D_DECL_USAGE_TEXCOORD, idx);
+                break;
+            case WINED3DFVF_TEXTUREFORMAT2:
+                append_decl_element(&state, WINED3DFMT_R32G32_FLOAT, WINED3D_DECL_USAGE_TEXCOORD, idx);
+                break;
+            case WINED3DFVF_TEXTUREFORMAT3:
+                append_decl_element(&state, WINED3DFMT_R32G32B32_FLOAT, WINED3D_DECL_USAGE_TEXCOORD, idx);
+                break;
+            case WINED3DFVF_TEXTUREFORMAT4:
+                append_decl_element(&state, WINED3DFMT_R32G32B32A32_FLOAT, WINED3D_DECL_USAGE_TEXCOORD, idx);
+                break;
+        }
+    }
+
+    *elements = state.elements;
+    return size;
+}
+
+HRESULT CDECL wined3d_vertex_declaration_create_from_fvf(struct wined3d_device *device,
+        DWORD fvf, void *parent, const struct wined3d_parent_ops *parent_ops,
+        struct wined3d_vertex_declaration **declaration)
+{
+    struct wined3d_vertex_element *elements;
+    unsigned int size;
+    DWORD hr;
+
+    TRACE("device %p, fvf %#x, parent %p, parent_ops %p, declaration %p.\n",
+            device, fvf, parent, parent_ops, declaration);
+
+    size = convert_fvf_to_declaration(&device->adapter->gl_info, fvf, &elements);
+    if (size == ~0U) return E_OUTOFMEMORY;
+
+    hr = wined3d_vertex_declaration_create(device, elements, size, parent, parent_ops, declaration);
+    HeapFree(GetProcessHeap(), 0, elements);
+    return hr;
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/view.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/view.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/view.c	(revision 46521)
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2009, 2011 Henri Verbeet for CodeWeavers
+ *
+ * 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 "wined3d_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d);
+
+ULONG CDECL wined3d_rendertarget_view_incref(struct wined3d_rendertarget_view *view)
+{
+    ULONG refcount = InterlockedIncrement(&view->refcount);
+
+    TRACE("%p increasing refcount to %u.\n", view, refcount);
+
+    return refcount;
+}
+
+ULONG CDECL wined3d_rendertarget_view_decref(struct wined3d_rendertarget_view *view)
+{
+    ULONG refcount = InterlockedDecrement(&view->refcount);
+
+    TRACE("%p decreasing refcount to %u.\n", view, refcount);
+
+    if (!refcount)
+        HeapFree(GetProcessHeap(), 0, view);
+
+    return refcount;
+}
+
+void * CDECL wined3d_rendertarget_view_get_parent(const struct wined3d_rendertarget_view *view)
+{
+    TRACE("view %p.\n", view);
+
+    return view->parent;
+}
+
+struct wined3d_resource * CDECL wined3d_rendertarget_view_get_resource(const struct wined3d_rendertarget_view *view)
+{
+    TRACE("view %p.\n", view);
+
+    return view->resource;
+}
+
+static void wined3d_rendertarget_view_init(struct wined3d_rendertarget_view *view,
+        struct wined3d_resource *resource, void *parent)
+{
+    view->refcount = 1;
+    view->resource = resource;
+    view->parent = parent;
+}
+
+HRESULT CDECL wined3d_rendertarget_view_create(struct wined3d_resource *resource,
+        void *parent, struct wined3d_rendertarget_view **rendertarget_view)
+{
+    struct wined3d_rendertarget_view *object;
+
+    TRACE("resource %p, parent %p, rendertarget_view %p.\n",
+            resource, parent, rendertarget_view);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return E_OUTOFMEMORY;
+
+    wined3d_rendertarget_view_init(object, resource, parent);
+
+    TRACE("Created render target view %p.\n", object);
+    *rendertarget_view = object;
+
+    return WINED3D_OK;
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/volume.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/volume.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/volume.c	(revision 46521)
@@ -0,0 +1,465 @@
+/*
+ * Copyright 2002-2005 Jason Edmeades
+ * Copyright 2002-2005 Raphael Junqueira
+ * Copyright 2005 Oliver Stieber
+ * Copyright 2009-2011 Henri Verbeet for CodeWeavers
+ *
+ * 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 "wined3d_private.h"
+
+#ifdef VBOX_WITH_WDDM
+# include "../../common/VBoxVideoTools.h"
+#endif
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface);
+
+/* Context activation is done by the caller. */
+static void volume_bind_and_dirtify(const struct wined3d_volume *volume, struct wined3d_context *context)
+{
+    struct wined3d_texture *container = volume->container;
+    DWORD active_sampler;
+
+    /* We don't need a specific texture unit, but after binding the texture the current unit is dirty.
+     * Read the unit back instead of switching to 0, this avoids messing around with the state manager's
+     * gl states. The current texture unit should always be a valid one.
+     *
+     * To be more specific, this is tricky because we can implicitly be called
+     * from sampler() in state.c. This means we can't touch anything other than
+     * whatever happens to be the currently active texture, or we would risk
+     * marking already applied sampler states dirty again. */
+    active_sampler = volume->resource.device->rev_tex_unit_map[context->active_texture];
+
+    if (active_sampler != WINED3D_UNMAPPED_STAGE)
+        device_invalidate_state(volume->resource.device, STATE_SAMPLER(active_sampler));
+
+    container->texture_ops->texture_bind(container, context, FALSE);
+}
+
+void volume_add_dirty_box(struct wined3d_volume *volume, const struct wined3d_box *dirty_box)
+{
+    volume->dirty = TRUE;
+    if (dirty_box)
+    {
+        volume->lockedBox.left = min(volume->lockedBox.left, dirty_box->left);
+        volume->lockedBox.top = min(volume->lockedBox.top, dirty_box->top);
+        volume->lockedBox.front = min(volume->lockedBox.front, dirty_box->front);
+        volume->lockedBox.right = max(volume->lockedBox.right, dirty_box->right);
+        volume->lockedBox.bottom = max(volume->lockedBox.bottom, dirty_box->bottom);
+        volume->lockedBox.back = max(volume->lockedBox.back, dirty_box->back);
+    }
+    else
+    {
+        volume->lockedBox.left = 0;
+        volume->lockedBox.top = 0;
+        volume->lockedBox.front = 0;
+        volume->lockedBox.right = volume->resource.width;
+        volume->lockedBox.bottom = volume->resource.height;
+        volume->lockedBox.back = volume->resource.depth;
+    }
+}
+
+void volume_set_container(struct wined3d_volume *volume, struct wined3d_texture *container)
+{
+    TRACE("volume %p, container %p.\n", volume, container);
+
+    volume->container = container;
+}
+
+/* Context activation is done by the caller. */
+void volume_load(const struct wined3d_volume *volume, struct wined3d_context *context, UINT level, BOOL srgb_mode)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    const struct wined3d_format *format = volume->resource.format;
+
+    TRACE("volume %p, context %p, level %u, srgb %#x, format %s (%#x).\n",
+            volume, context, level, srgb_mode, debug_d3dformat(format->id), format->id);
+
+    volume_bind_and_dirtify(volume, context);
+
+    GL_EXTCALL(glTexImage3DEXT(GL_TEXTURE_3D, level, format->glInternal,
+            volume->resource.width, volume->resource.height, volume->resource.depth,
+            0, format->glFormat, format->glType, volume->resource.allocatedMemory));
+    checkGLcall("glTexImage3D");
+
+    /* When adding code releasing volume->resource.allocatedMemory to save
+     * data keep in mind that GL_UNPACK_CLIENT_STORAGE_APPLE is enabled by
+     * default if supported(GL_APPLE_client_storage). Thus do not release
+     * volume->resource.allocatedMemory if GL_APPLE_client_storage is
+     * supported. */
+}
+
+/* Do not call while under the GL lock. */
+static void volume_unload(struct wined3d_resource *resource)
+{
+    TRACE("texture %p.\n", resource);
+
+    /* The whole content is shadowed on This->resource.allocatedMemory, and
+     * the texture name is managed by the VolumeTexture container. */
+
+    resource_unload(resource);
+}
+
+ULONG CDECL wined3d_volume_incref(struct wined3d_volume *volume)
+{
+    ULONG refcount;
+
+    if (volume->container)
+    {
+        TRACE("Forwarding to container %p.\n", volume->container);
+        return wined3d_texture_incref(volume->container);
+    }
+
+    refcount = InterlockedIncrement(&volume->resource.ref);
+
+    TRACE("%p increasing refcount to %u.\n", volume, refcount);
+
+    return refcount;
+}
+
+/* Do not call while under the GL lock. */
+ULONG CDECL wined3d_volume_decref(struct wined3d_volume *volume)
+{
+    ULONG refcount;
+
+    if (volume->container)
+    {
+        TRACE("Forwarding to container %p.\n", volume->container);
+        return wined3d_texture_decref(volume->container);
+    }
+
+    refcount = InterlockedDecrement(&volume->resource.ref);
+
+    TRACE("%p decreasing refcount to %u.\n", volume, refcount);
+
+    if (!refcount)
+    {
+        resource_cleanup(&volume->resource);
+        volume->resource.parent_ops->wined3d_object_destroyed(volume->resource.parent);
+        HeapFree(GetProcessHeap(), 0, volume);
+    }
+
+    return refcount;
+}
+
+void * CDECL wined3d_volume_get_parent(const struct wined3d_volume *volume)
+{
+    TRACE("volume %p.\n", volume);
+
+    return volume->resource.parent;
+}
+
+DWORD CDECL wined3d_volume_set_priority(struct wined3d_volume *volume, DWORD priority)
+{
+    return resource_set_priority(&volume->resource, priority);
+}
+
+DWORD CDECL wined3d_volume_get_priority(const struct wined3d_volume *volume)
+{
+    return resource_get_priority(&volume->resource);
+}
+
+/* Do not call while under the GL lock. */
+void CDECL wined3d_volume_preload(struct wined3d_volume *volume)
+{
+    FIXME("volume %p stub!\n", volume);
+}
+
+struct wined3d_resource * CDECL wined3d_volume_get_resource(struct wined3d_volume *volume)
+{
+    TRACE("volume %p.\n", volume);
+
+    return &volume->resource;
+}
+
+HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume,
+        struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags)
+{
+    TRACE("volume %p, map_desc %p, box %p, flags %#x.\n",
+            volume, map_desc, box, flags);
+
+    if (!volume->resource.allocatedMemory)
+        volume->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, volume->resource.size);
+
+    TRACE("allocatedMemory %p.\n", volume->resource.allocatedMemory);
+
+    map_desc->row_pitch = volume->resource.format->byte_count * volume->resource.width; /* Bytes / row */
+    map_desc->slice_pitch = volume->resource.format->byte_count
+            * volume->resource.width * volume->resource.height; /* Bytes / slice */
+    if (!box)
+    {
+        TRACE("No box supplied - all is ok\n");
+        map_desc->data = volume->resource.allocatedMemory;
+        volume->lockedBox.left   = 0;
+        volume->lockedBox.top    = 0;
+        volume->lockedBox.front  = 0;
+        volume->lockedBox.right  = volume->resource.width;
+        volume->lockedBox.bottom = volume->resource.height;
+        volume->lockedBox.back   = volume->resource.depth;
+    }
+    else
+    {
+#ifdef VBOX_WITH_WDDM
+        if (box->right <= box->left
+                || box->right > volume->resource.width
+                || box->bottom <= box->top
+                || box->bottom > volume->resource.height
+                || box->back <= box->front
+                || box->back > volume->resource.depth
+                )
+        {
+            ERR("invalid dimensions!");
+            return WINED3DERR_INVALIDCALL;
+        }
+#endif
+        TRACE("Lock Box (%p) = l %u, t %u, r %u, b %u, fr %u, ba %u\n",
+                box, box->left, box->top, box->right, box->bottom, box->front, box->back);
+        map_desc->data = volume->resource.allocatedMemory
+                + (map_desc->slice_pitch * box->front)     /* FIXME: is front < back or vica versa? */
+                + (map_desc->row_pitch * box->top)
+                + (box->left * volume->resource.format->byte_count);
+        volume->lockedBox.left   = box->left;
+        volume->lockedBox.top    = box->top;
+        volume->lockedBox.front  = box->front;
+        volume->lockedBox.right  = box->right;
+        volume->lockedBox.bottom = box->bottom;
+        volume->lockedBox.back   = box->back;
+    }
+
+    if (!(flags & (WINED3D_MAP_NO_DIRTY_UPDATE | WINED3D_MAP_READONLY)))
+    {
+        volume_add_dirty_box(volume, &volume->lockedBox);
+        wined3d_texture_set_dirty(volume->container, TRUE);
+    }
+
+    volume->locked = TRUE;
+
+    TRACE("Returning memory %p, row pitch %d, slice pitch %d.\n",
+            map_desc->data, map_desc->row_pitch, map_desc->slice_pitch);
+
+    return WINED3D_OK;
+}
+
+struct wined3d_volume * CDECL wined3d_volume_from_resource(struct wined3d_resource *resource)
+{
+    return volume_from_resource(resource);
+}
+
+HRESULT CDECL wined3d_volume_unmap(struct wined3d_volume *volume)
+{
+    TRACE("volume %p.\n", volume);
+
+    if (!volume->locked)
+    {
+        WARN("Trying to unlock unlocked volume %p.\n", volume);
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    volume->locked = FALSE;
+    memset(&volume->lockedBox, 0, sizeof(volume->lockedBox));
+
+    return WINED3D_OK;
+}
+
+static const struct wined3d_resource_ops volume_resource_ops =
+{
+    volume_unload,
+};
+
+static HRESULT volume_init(struct wined3d_volume *volume, struct wined3d_device *device, UINT width,
+        UINT height, UINT depth, DWORD usage, enum wined3d_format_id format_id, enum wined3d_pool pool,
+        void *parent, const struct wined3d_parent_ops *parent_ops
+#ifdef VBOX_WITH_WDDM
+        , HANDLE *shared_handle
+        , void *pvClientMem
+#endif
+        )
+{
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    const struct wined3d_format *format = wined3d_get_format(gl_info, format_id);
+    HRESULT hr;
+
+    if (!gl_info->supported[EXT_TEXTURE3D])
+    {
+        WARN("Volume cannot be created - no volume texture support.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    hr = resource_init(&volume->resource, device, WINED3D_RTYPE_VOLUME, format,
+            WINED3D_MULTISAMPLE_NONE, 0, usage, pool, width, height, depth,
+            width * height * depth * format->byte_count, parent, parent_ops,
+            &volume_resource_ops
+#ifdef VBOX_WITH_WDDM
+            , shared_handle, pvClientMem
+#endif
+            );
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize resource, returning %#x.\n", hr);
+        return hr;
+    }
+
+    volume->lockable = TRUE;
+    volume->locked = FALSE;
+    memset(&volume->lockedBox, 0, sizeof(volume->lockedBox));
+    volume->dirty = TRUE;
+
+    volume_add_dirty_box(volume, NULL);
+
+    return WINED3D_OK;
+}
+
+HRESULT CDECL wined3d_volume_create(struct wined3d_device *device, UINT width, UINT height,
+        UINT depth, DWORD usage, enum wined3d_format_id format_id, enum wined3d_pool pool, void *parent,
+        const struct wined3d_parent_ops *parent_ops, struct wined3d_volume **volume
+#ifdef VBOX_WITH_WDDM
+        , HANDLE *shared_handle
+        , void *pvClientMem
+#endif
+        )
+{
+    struct wined3d_volume *object;
+    HRESULT hr;
+
+    TRACE("device %p, width %u, height %u, depth %u, usage %#x, format %s, pool %s\n",
+            device, width, height, depth, usage, debug_d3dformat(format_id), debug_d3dpool(pool));
+    TRACE("parent %p, parent_ops %p, volume %p.\n", parent, parent_ops, volume);
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+    {
+        *volume = NULL;
+        return WINED3DERR_OUTOFVIDEOMEMORY;
+    }
+
+    hr = volume_init(object, device, width, height, depth, usage, format_id, pool, parent, parent_ops
+#ifdef VBOX_WITH_WDDM
+            , shared_handle
+            , pvClientMem
+#endif
+            );
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize volume, returning %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
+
+    TRACE("Created volume %p.\n", object);
+    *volume = object;
+
+    return WINED3D_OK;
+}
+
+#ifdef VBOX_WITH_WDDM
+HRESULT CDECL wined3d_device_blt_vol(struct wined3d_device *device, struct wined3d_volume *src, struct wined3d_volume *dst,
+        const struct wined3d_box *pSrcBoxArg,
+        const VBOXPOINT3D *pDstPoin3D)
+{
+    struct wined3d_map_desc src_desc, dst_desc;
+    HRESULT hr;
+    struct wined3d_box DstBox, SrcBox;
+    const struct wined3d_box *pDstBox;
+    const struct wined3d_box *pSrcBox;
+    int dstW, dstH, dstD, srcW, srcH, srcD;
+    int j, k;
+    uint8_t * pDstBits;
+    uint8_t * pSrcBits;
+
+
+    TRACE("device %p, src_volume %p, dst_volume %p.\n",
+            device, src, dst);
+
+    pSrcBox = pSrcBoxArg;
+    if (!pSrcBox)
+    {
+        SrcBox.left   = 0;
+        SrcBox.top    = 0;
+        SrcBox.front  = 0;
+        SrcBox.right  = src->resource.width;
+        SrcBox.bottom = src->resource.height;
+        SrcBox.back   = src->resource.depth;
+        pSrcBox = &SrcBox;
+    }
+
+    if (!pDstPoin3D)
+        pDstBox = pSrcBox;
+    else
+    {
+        vboxWddmBoxTranslated((VBOXBOX3D*)&DstBox, (const VBOXBOX3D *)pSrcBox, pDstPoin3D->x, pDstPoin3D->y, pDstPoin3D->z);
+        pDstBox = &DstBox;
+    }
+
+    dstW = pDstBox->right - pDstBox->left;
+    dstH = pDstBox->bottom - pDstBox->top;
+    dstD = pDstBox->back - pDstBox->front;
+
+    srcW = pSrcBox->right - pSrcBox->left;
+    srcH = pSrcBox->bottom - pSrcBox->top;
+    srcD = pSrcBox->back - pSrcBox->front;
+
+    if (srcW != dstW || srcH != dstH || srcD != dstD)
+    {
+        ERR("dimensions do not match, stretching not supported for volumes!");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    /* TODO: Implement direct loading into the gl volume instead of using memcpy and
+     * dirtification to improve loading performance.
+     */
+    hr = wined3d_volume_map(src, &src_desc, pSrcBox, WINED3D_MAP_READONLY);
+    if(FAILED(hr))
+    {
+        ERR("wined3d_volume_map src failed");
+        return hr;
+    }
+
+    hr = wined3d_volume_map(dst, &dst_desc, pDstBox, WINED3D_MAP_DISCARD);
+    if(FAILED(hr))
+    {
+        ERR("wined3d_volume_map dst failed");
+        wined3d_volume_unmap(src);
+        return hr;
+    }
+
+    pDstBits = dst_desc.data;
+    pSrcBits = src_desc.data;
+    for (k = 0; k < srcD; ++k)
+    {
+        uint8_t * pRowDstBits = pDstBits;
+        uint8_t * pRowSrcBits = pSrcBits;
+
+        for (j = 0; j < srcH; ++j)
+        {
+            memcpy(pRowDstBits, pRowSrcBits, srcW * dst->resource.format->byte_count);
+            pRowDstBits += dst_desc.row_pitch;
+            pRowSrcBits += src_desc.row_pitch;
+        }
+        pDstBits += dst_desc.slice_pitch;
+        pSrcBits += src_desc.slice_pitch;
+    }
+
+    hr = wined3d_volume_unmap(dst);
+    if(FAILED(hr)) {
+        wined3d_volume_unmap(src);
+    } else {
+        hr = wined3d_volume_unmap(src);
+    }
+    return hr;
+}
+#endif
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/wined3d.def
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/wined3d.def	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/wined3d.def	(revision 46521)
@@ -0,0 +1,255 @@
+; File generated automatically from ./dlls/wined3d/wined3d.spec; do not edit!
+
+EXPORTS
+  wined3d_mutex_lock
+  wined3d_mutex_unlock
+  wined3d_check_depth_stencil_match
+  wined3d_check_device_format
+  wined3d_check_device_format_conversion
+  wined3d_check_device_multisample_type
+  wined3d_check_device_type
+  wined3d_create
+  wined3d_decref
+  wined3d_enum_adapter_modes
+  wined3d_get_adapter_count
+  wined3d_get_adapter_display_mode
+  wined3d_get_adapter_identifier
+  wined3d_get_adapter_mode_count
+  wined3d_get_adapter_monitor
+  wined3d_get_adapter_raster_status
+  wined3d_get_device_caps
+  wined3d_incref
+  wined3d_register_software_device
+  wined3d_set_adapter_display_mode
+  wined3d_buffer_create
+  wined3d_buffer_create_ib
+  wined3d_buffer_create_vb
+  wined3d_buffer_decref
+  wined3d_buffer_get_parent
+  wined3d_buffer_get_priority
+  wined3d_buffer_get_resource
+  wined3d_buffer_incref
+  wined3d_buffer_map
+  wined3d_buffer_preload
+  wined3d_buffer_set_priority
+  wined3d_buffer_unmap
+  wined3d_device_acquire_focus_window
+  wined3d_device_begin_scene
+  wined3d_device_begin_stateblock
+  wined3d_device_clear
+  wined3d_device_clear_rendertarget_view
+  wined3d_device_color_fill
+  wined3d_device_create
+  wined3d_device_decref
+  wined3d_device_draw_indexed_primitive
+  wined3d_device_draw_primitive
+  wined3d_device_end_scene
+  wined3d_device_end_stateblock
+  wined3d_device_evict_managed_resources
+  wined3d_device_get_available_texture_mem
+  wined3d_device_get_back_buffer
+  wined3d_device_get_base_vertex_index
+  wined3d_device_get_clip_plane
+  wined3d_device_get_clip_status
+  wined3d_device_get_creation_parameters
+  wined3d_device_get_depth_stencil
+  wined3d_device_get_device_caps
+  wined3d_device_get_display_mode
+  wined3d_device_get_front_buffer_data
+  wined3d_device_get_gamma_ramp
+  wined3d_device_get_index_buffer
+  wined3d_device_get_light
+  wined3d_device_get_light_enable
+  wined3d_device_get_material
+  wined3d_device_get_npatch_mode
+  wined3d_device_get_pixel_shader
+  wined3d_device_get_primitive_type
+  wined3d_device_get_ps_consts_b
+  wined3d_device_get_ps_consts_f
+  wined3d_device_get_ps_consts_i
+  wined3d_device_get_raster_status
+  wined3d_device_get_render_state
+  wined3d_device_get_render_target
+  wined3d_device_get_sampler_state
+  wined3d_device_get_scissor_rect
+  wined3d_device_get_software_vertex_processing
+  wined3d_device_get_stream_source
+  wined3d_device_get_stream_source_freq
+  wined3d_device_get_surface_from_dc
+  wined3d_device_get_swapchain
+  wined3d_device_get_swapchain_count
+  wined3d_device_get_texture
+  wined3d_device_get_texture_stage_state
+  wined3d_device_get_transform
+  wined3d_device_get_vertex_declaration
+  wined3d_device_get_vertex_shader
+  wined3d_device_get_viewport
+  wined3d_device_get_vs_consts_b
+  wined3d_device_get_vs_consts_f
+  wined3d_device_get_vs_consts_i
+  wined3d_device_incref
+  wined3d_device_init_3d
+  wined3d_device_init_gdi
+  wined3d_device_multiply_transform
+  wined3d_device_present
+  wined3d_device_process_vertices
+  wined3d_device_release_focus_window
+  wined3d_device_reset
+  wined3d_device_restore_fullscreen_window
+  wined3d_device_set_base_vertex_index
+  wined3d_device_set_clip_plane
+  wined3d_device_set_clip_status
+  wined3d_device_set_cursor_position
+  wined3d_device_set_cursor_properties
+  wined3d_device_set_depth_stencil
+  wined3d_device_set_dialog_box_mode
+  wined3d_device_set_gamma_ramp
+  wined3d_device_set_index_buffer
+  wined3d_device_set_light
+  wined3d_device_set_light_enable
+  wined3d_device_set_material
+  wined3d_device_set_multithreaded
+  wined3d_device_set_npatch_mode
+  wined3d_device_set_pixel_shader
+  wined3d_device_set_primitive_type
+  wined3d_device_set_ps_consts_b
+  wined3d_device_set_ps_consts_f
+  wined3d_device_set_ps_consts_i
+  wined3d_device_set_render_state
+  wined3d_device_set_render_target
+  wined3d_device_set_sampler_state
+  wined3d_device_set_scissor_rect
+  wined3d_device_set_software_vertex_processing
+  wined3d_device_set_stream_source
+  wined3d_device_set_stream_source_freq
+  wined3d_device_set_texture
+  wined3d_device_set_texture_stage_state
+  wined3d_device_set_transform
+  wined3d_device_set_vertex_declaration
+  wined3d_device_set_vertex_shader
+  wined3d_device_set_viewport
+  wined3d_device_set_vs_consts_b
+  wined3d_device_set_vs_consts_f
+  wined3d_device_set_vs_consts_i
+  wined3d_device_setup_fullscreen_window
+  wined3d_device_show_cursor
+  wined3d_device_uninit_3d
+  wined3d_device_uninit_gdi
+  wined3d_device_update_surface
+  wined3d_device_update_texture
+  wined3d_device_validate_device
+  wined3d_palette_create
+  wined3d_palette_decref
+  wined3d_palette_get_entries
+  wined3d_palette_get_flags
+  wined3d_palette_get_parent
+  wined3d_palette_incref
+  wined3d_palette_set_entries
+  wined3d_query_create
+  wined3d_query_decref
+  wined3d_query_get_data
+  wined3d_query_get_data_size
+  wined3d_query_get_type
+  wined3d_query_incref
+  wined3d_query_issue
+  wined3d_resource_free_private_data
+  wined3d_resource_get_desc
+  wined3d_resource_get_parent
+  wined3d_resource_get_private_data
+  wined3d_resource_set_private_data
+  wined3d_rendertarget_view_create
+  wined3d_rendertarget_view_decref
+  wined3d_rendertarget_view_get_parent
+  wined3d_rendertarget_view_get_resource
+  wined3d_rendertarget_view_incref
+  wined3d_shader_create_gs
+  wined3d_shader_create_ps
+  wined3d_shader_create_vs
+  wined3d_shader_decref
+  wined3d_shader_get_byte_code
+  wined3d_shader_get_parent
+  wined3d_shader_incref
+  wined3d_shader_set_local_constants_float
+  wined3d_stateblock_apply
+  wined3d_stateblock_capture
+  wined3d_stateblock_create
+  wined3d_stateblock_decref
+  wined3d_stateblock_incref
+  wined3d_surface_blt
+  wined3d_surface_create
+  wined3d_surface_decref
+  wined3d_surface_flip
+  wined3d_surface_from_resource
+  wined3d_surface_get_blt_status
+  wined3d_surface_get_flip_status
+  wined3d_surface_get_overlay_position
+  wined3d_surface_get_palette
+  wined3d_surface_get_parent
+  wined3d_surface_get_pitch
+  wined3d_surface_get_priority
+  wined3d_surface_get_render_target_data
+  wined3d_surface_get_resource
+  wined3d_surface_getdc
+  wined3d_surface_incref
+  wined3d_surface_is_lost
+  wined3d_surface_map
+  wined3d_surface_preload
+  wined3d_surface_releasedc
+  wined3d_surface_restore
+  wined3d_surface_set_color_key
+  wined3d_surface_set_mem
+  wined3d_surface_set_overlay_position
+  wined3d_surface_set_palette
+  wined3d_surface_set_priority
+  wined3d_surface_unmap
+  wined3d_surface_update_desc
+  wined3d_surface_update_overlay
+  wined3d_surface_update_overlay_z_order
+  wined3d_swapchain_create
+  wined3d_swapchain_decref
+  wined3d_swapchain_get_back_buffer
+  wined3d_swapchain_get_device
+  wined3d_swapchain_get_display_mode
+  wined3d_swapchain_get_front_buffer_data
+  wined3d_swapchain_get_gamma_ramp
+  wined3d_swapchain_get_parent
+  wined3d_swapchain_get_desc
+  wined3d_swapchain_get_raster_status
+  wined3d_swapchain_incref
+  wined3d_swapchain_present
+  wined3d_swapchain_set_gamma_ramp
+  wined3d_swapchain_set_window
+  wined3d_texture_add_dirty_region
+  wined3d_texture_create_2d
+  wined3d_texture_create_3d
+  wined3d_texture_create_cube
+  wined3d_texture_decref
+  wined3d_texture_generate_mipmaps
+  wined3d_texture_get_autogen_filter_type
+  wined3d_texture_get_level_count
+  wined3d_texture_get_lod
+  wined3d_texture_get_parent
+  wined3d_texture_get_priority
+  wined3d_texture_get_resource
+  wined3d_texture_get_sub_resource
+  wined3d_texture_incref
+  wined3d_texture_preload
+  wined3d_texture_set_autogen_filter_type
+  wined3d_texture_set_lod
+  wined3d_texture_set_priority
+  wined3d_vertex_declaration_create
+  wined3d_vertex_declaration_create_from_fvf
+  wined3d_vertex_declaration_decref
+  wined3d_vertex_declaration_get_parent
+  wined3d_vertex_declaration_incref
+  wined3d_volume_create
+  wined3d_volume_decref
+  wined3d_volume_from_resource
+  wined3d_volume_get_parent
+  wined3d_volume_get_priority
+  wined3d_volume_get_resource
+  wined3d_volume_incref
+  wined3d_volume_map
+  wined3d_volume_preload
+  wined3d_volume_set_priority
+  wined3d_volume_unmap
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/wined3d.spec
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/wined3d.spec	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/wined3d.spec	(revision 46521)
@@ -0,0 +1,288 @@
+@ stdcall wined3d_mutex_lock()
+@ stdcall wined3d_mutex_unlock()
+
+@ cdecl wined3d_check_depth_stencil_match(ptr long long long long long)
+@ cdecl wined3d_check_device_format(ptr long long long long long long)
+@ cdecl wined3d_check_device_format_conversion(ptr long long long long)
+@ cdecl wined3d_check_device_multisample_type(ptr long long long long long ptr)
+@ cdecl wined3d_check_device_type(ptr long long long long long)
+@ cdecl wined3d_create(long long)
+@ cdecl wined3d_decref(ptr)
+@ cdecl wined3d_enum_adapter_modes(ptr long long long long ptr)
+@ cdecl wined3d_get_adapter_count(ptr)
+@ cdecl wined3d_get_adapter_display_mode(ptr long ptr ptr)
+@ cdecl wined3d_get_adapter_identifier(ptr long long ptr)
+@ cdecl wined3d_get_adapter_mode_count(ptr long long long)
+@ cdecl wined3d_get_adapter_monitor(ptr long)
+@ cdecl wined3d_get_adapter_raster_status(ptr long ptr)
+@ cdecl wined3d_get_device_caps(ptr long long ptr)
+@ cdecl wined3d_incref(ptr)
+@ cdecl wined3d_register_software_device(ptr ptr)
+@ cdecl wined3d_set_adapter_display_mode(ptr long ptr)
+
+@ cdecl wined3d_buffer_create(ptr ptr ptr ptr ptr ptr)
+@ cdecl wined3d_buffer_create_ib(ptr long long long ptr ptr ptr)
+@ cdecl wined3d_buffer_create_vb(ptr long long long ptr ptr ptr)
+@ cdecl wined3d_buffer_decref(ptr)
+@ cdecl wined3d_buffer_get_parent(ptr)
+@ cdecl wined3d_buffer_get_priority(ptr)
+@ cdecl wined3d_buffer_get_resource(ptr)
+@ cdecl wined3d_buffer_incref(ptr)
+@ cdecl wined3d_buffer_map(ptr long long ptr long)
+@ cdecl wined3d_buffer_preload(ptr)
+@ cdecl wined3d_buffer_set_priority(ptr long)
+@ cdecl wined3d_buffer_unmap(ptr)
+
+@ cdecl wined3d_device_acquire_focus_window(ptr ptr)
+@ cdecl wined3d_device_begin_scene(ptr)
+@ cdecl wined3d_device_begin_stateblock(ptr)
+@ cdecl wined3d_device_clear(ptr long ptr long ptr float long)
+@ cdecl wined3d_device_clear_rendertarget_view(ptr ptr ptr)
+@ cdecl wined3d_device_color_fill(ptr ptr ptr ptr)
+@ cdecl wined3d_device_create(ptr long long ptr long long ptr ptr)
+@ cdecl wined3d_device_decref(ptr)
+@ cdecl wined3d_device_draw_indexed_primitive(ptr long long)
+@ cdecl wined3d_device_draw_indexed_primitive_instanced(ptr long long long long)
+@ cdecl wined3d_device_draw_primitive(ptr long long)
+@ cdecl wined3d_device_end_scene(ptr)
+@ cdecl wined3d_device_end_stateblock(ptr ptr)
+@ cdecl wined3d_device_evict_managed_resources(ptr)
+@ cdecl wined3d_device_get_available_texture_mem(ptr)
+@ cdecl wined3d_device_get_back_buffer(ptr long long long ptr)
+@ cdecl wined3d_device_get_base_vertex_index(ptr)
+@ cdecl wined3d_device_get_clip_plane(ptr long ptr)
+@ cdecl wined3d_device_get_clip_status(ptr ptr)
+@ cdecl wined3d_device_get_creation_parameters(ptr ptr)
+@ cdecl wined3d_device_get_depth_stencil(ptr)
+@ cdecl wined3d_device_get_device_caps(ptr ptr)
+@ cdecl wined3d_device_get_display_mode(ptr long ptr ptr)
+@ cdecl wined3d_device_get_front_buffer_data(ptr long ptr)
+@ cdecl wined3d_device_get_gamma_ramp(ptr long ptr)
+@ cdecl wined3d_device_get_geometry_shader(ptr)
+@ cdecl wined3d_device_get_gs_cb(ptr long)
+@ cdecl wined3d_device_get_gs_sampler(ptr long)
+@ cdecl wined3d_device_get_index_buffer(ptr ptr)
+@ cdecl wined3d_device_get_light(ptr long ptr)
+@ cdecl wined3d_device_get_light_enable(ptr long ptr)
+@ cdecl wined3d_device_get_material(ptr ptr)
+@ cdecl wined3d_device_get_npatch_mode(ptr)
+@ cdecl wined3d_device_get_pixel_shader(ptr)
+@ cdecl wined3d_device_get_primitive_type(ptr ptr)
+@ cdecl wined3d_device_get_ps_cb(ptr long)
+@ cdecl wined3d_device_get_ps_consts_b(ptr long ptr long)
+@ cdecl wined3d_device_get_ps_consts_f(ptr long ptr long)
+@ cdecl wined3d_device_get_ps_consts_i(ptr long ptr long)
+@ cdecl wined3d_device_get_ps_sampler(ptr long)
+@ cdecl wined3d_device_get_raster_status(ptr long ptr)
+@ cdecl wined3d_device_get_render_state(ptr long)
+@ cdecl wined3d_device_get_render_target(ptr long)
+@ cdecl wined3d_device_get_sampler_state(ptr long long)
+@ cdecl wined3d_device_get_scissor_rect(ptr ptr)
+@ cdecl wined3d_device_get_software_vertex_processing(ptr)
+@ cdecl wined3d_device_get_stream_output(ptr long ptr)
+@ cdecl wined3d_device_get_stream_source(ptr long ptr ptr ptr)
+@ cdecl wined3d_device_get_stream_source_freq(ptr long ptr)
+@ cdecl wined3d_device_get_surface_from_dc(ptr ptr)
+@ cdecl wined3d_device_get_swapchain(ptr long)
+@ cdecl wined3d_device_get_swapchain_count(ptr)
+@ cdecl wined3d_device_get_texture(ptr long)
+@ cdecl wined3d_device_get_texture_stage_state(ptr long long)
+@ cdecl wined3d_device_get_transform(ptr long ptr)
+@ cdecl wined3d_device_get_vertex_declaration(ptr)
+@ cdecl wined3d_device_get_vertex_shader(ptr)
+@ cdecl wined3d_device_get_viewport(ptr ptr)
+@ cdecl wined3d_device_get_vs_cb(ptr long)
+@ cdecl wined3d_device_get_vs_consts_b(ptr long ptr long)
+@ cdecl wined3d_device_get_vs_consts_f(ptr long ptr long)
+@ cdecl wined3d_device_get_vs_consts_i(ptr long ptr long)
+@ cdecl wined3d_device_get_vs_sampler(ptr long)
+@ cdecl wined3d_device_incref(ptr)
+@ cdecl wined3d_device_init_3d(ptr ptr)
+@ cdecl wined3d_device_init_gdi(ptr ptr)
+@ cdecl wined3d_device_multiply_transform(ptr long ptr)
+@ cdecl wined3d_device_present(ptr ptr ptr ptr ptr long)
+@ cdecl wined3d_device_process_vertices(ptr long long long ptr ptr long long)
+@ cdecl wined3d_device_release_focus_window(ptr)
+@ cdecl wined3d_device_reset(ptr ptr ptr ptr long)
+@ cdecl wined3d_device_restore_fullscreen_window(ptr ptr)
+@ cdecl wined3d_device_set_base_vertex_index(ptr long)
+@ cdecl wined3d_device_set_clip_plane(ptr long ptr)
+@ cdecl wined3d_device_set_clip_status(ptr ptr)
+@ cdecl wined3d_device_set_cursor_position(ptr long long long)
+@ cdecl wined3d_device_set_cursor_properties(ptr long long ptr)
+@ cdecl wined3d_device_set_depth_stencil(ptr ptr)
+@ cdecl wined3d_device_set_dialog_box_mode(ptr long)
+@ cdecl wined3d_device_set_gamma_ramp(ptr long long ptr)
+@ cdecl wined3d_device_set_geometry_shader(ptr ptr)
+@ cdecl wined3d_device_set_gs_cb(ptr long ptr)
+@ cdecl wined3d_device_set_gs_sampler(ptr long ptr)
+@ cdecl wined3d_device_set_index_buffer(ptr ptr long)
+@ cdecl wined3d_device_set_light(ptr long ptr)
+@ cdecl wined3d_device_set_light_enable(ptr long long)
+@ cdecl wined3d_device_set_material(ptr ptr)
+@ cdecl wined3d_device_set_multithreaded(ptr)
+@ cdecl wined3d_device_set_npatch_mode(ptr float)
+@ cdecl wined3d_device_set_pixel_shader(ptr ptr)
+@ cdecl wined3d_device_set_primitive_type(ptr long)
+@ cdecl wined3d_device_set_ps_cb(ptr long ptr)
+@ cdecl wined3d_device_set_ps_consts_b(ptr long ptr long)
+@ cdecl wined3d_device_set_ps_consts_f(ptr long ptr long)
+@ cdecl wined3d_device_set_ps_consts_i(ptr long ptr long)
+@ cdecl wined3d_device_set_ps_sampler(ptr long ptr)
+@ cdecl wined3d_device_set_render_state(ptr long long)
+@ cdecl wined3d_device_set_render_target(ptr long ptr long)
+@ cdecl wined3d_device_set_sampler_state(ptr long long long)
+@ cdecl wined3d_device_set_scissor_rect(ptr ptr)
+@ cdecl wined3d_device_set_software_vertex_processing(ptr long)
+@ cdecl wined3d_device_set_stream_output(ptr long ptr long)
+@ cdecl wined3d_device_set_stream_source(ptr long ptr long long)
+@ cdecl wined3d_device_set_stream_source_freq(ptr long long)
+@ cdecl wined3d_device_set_texture(ptr long ptr)
+@ cdecl wined3d_device_set_texture_stage_state(ptr long long long)
+@ cdecl wined3d_device_set_transform(ptr long ptr)
+@ cdecl wined3d_device_set_vertex_declaration(ptr ptr)
+@ cdecl wined3d_device_set_vertex_shader(ptr ptr)
+@ cdecl wined3d_device_set_viewport(ptr ptr)
+@ cdecl wined3d_device_set_vs_cb(ptr long ptr)
+@ cdecl wined3d_device_set_vs_consts_b(ptr long ptr long)
+@ cdecl wined3d_device_set_vs_consts_f(ptr long ptr long)
+@ cdecl wined3d_device_set_vs_consts_i(ptr long ptr long)
+@ cdecl wined3d_device_set_vs_sampler(ptr long ptr)
+@ cdecl wined3d_device_setup_fullscreen_window(ptr ptr long long)
+@ cdecl wined3d_device_show_cursor(ptr long)
+@ cdecl wined3d_device_uninit_3d(ptr)
+@ cdecl wined3d_device_uninit_gdi(ptr)
+@ cdecl wined3d_device_update_surface(ptr ptr ptr ptr ptr)
+@ cdecl wined3d_device_update_texture(ptr ptr ptr)
+@ cdecl wined3d_device_validate_device(ptr ptr)
+
+@ cdecl wined3d_palette_create(ptr long ptr ptr ptr)
+@ cdecl wined3d_palette_decref(ptr)
+@ cdecl wined3d_palette_get_entries(ptr long long long ptr)
+@ cdecl wined3d_palette_get_flags(ptr)
+@ cdecl wined3d_palette_get_parent(ptr)
+@ cdecl wined3d_palette_incref(ptr)
+@ cdecl wined3d_palette_set_entries(ptr long long long ptr)
+
+@ cdecl wined3d_query_create(ptr long ptr)
+@ cdecl wined3d_query_decref(ptr)
+@ cdecl wined3d_query_get_data(ptr ptr long long)
+@ cdecl wined3d_query_get_data_size(ptr)
+@ cdecl wined3d_query_get_type(ptr)
+@ cdecl wined3d_query_incref(ptr)
+@ cdecl wined3d_query_issue(ptr long)
+
+@ cdecl wined3d_resource_free_private_data(ptr ptr)
+@ cdecl wined3d_resource_get_desc(ptr ptr)
+@ cdecl wined3d_resource_get_parent(ptr)
+@ cdecl wined3d_resource_get_private_data(ptr ptr ptr ptr)
+@ cdecl wined3d_resource_set_private_data(ptr ptr ptr long long)
+
+@ cdecl wined3d_rendertarget_view_create(ptr ptr ptr)
+@ cdecl wined3d_rendertarget_view_decref(ptr)
+@ cdecl wined3d_rendertarget_view_get_parent(ptr)
+@ cdecl wined3d_rendertarget_view_get_resource(ptr)
+@ cdecl wined3d_rendertarget_view_incref(ptr)
+
+@ cdecl wined3d_sampler_create(ptr ptr)
+@ cdecl wined3d_sampler_decref(ptr)
+@ cdecl wined3d_sampler_get_parent(ptr)
+@ cdecl wined3d_sampler_incref(ptr)
+
+@ cdecl wined3d_shader_create_gs(ptr ptr ptr ptr ptr ptr long)
+@ cdecl wined3d_shader_create_ps(ptr ptr ptr ptr ptr ptr long)
+@ cdecl wined3d_shader_create_vs(ptr ptr ptr ptr ptr ptr long)
+@ cdecl wined3d_shader_decref(ptr)
+@ cdecl wined3d_shader_get_byte_code(ptr ptr ptr)
+@ cdecl wined3d_shader_get_parent(ptr)
+@ cdecl wined3d_shader_incref(ptr)
+@ cdecl wined3d_shader_set_local_constants_float(ptr long ptr long)
+
+@ cdecl wined3d_stateblock_apply(ptr)
+@ cdecl wined3d_stateblock_capture(ptr)
+@ cdecl wined3d_stateblock_create(ptr long ptr)
+@ cdecl wined3d_stateblock_decref(ptr)
+@ cdecl wined3d_stateblock_incref(ptr)
+
+@ cdecl wined3d_surface_blt(ptr ptr ptr ptr long ptr long)
+@ cdecl wined3d_surface_create(ptr long long long long long long long long ptr ptr ptr)
+@ cdecl wined3d_surface_decref(ptr)
+@ cdecl wined3d_surface_flip(ptr ptr long)
+@ cdecl wined3d_surface_from_resource(ptr)
+@ cdecl wined3d_surface_get_blt_status(ptr long)
+@ cdecl wined3d_surface_get_flip_status(ptr long)
+@ cdecl wined3d_surface_get_overlay_position(ptr ptr ptr)
+@ cdecl wined3d_surface_get_palette(ptr)
+@ cdecl wined3d_surface_get_parent(ptr)
+@ cdecl wined3d_surface_get_pitch(ptr)
+@ cdecl wined3d_surface_get_priority(ptr)
+@ cdecl wined3d_surface_get_render_target_data(ptr ptr)
+@ cdecl wined3d_surface_get_resource(ptr)
+@ cdecl wined3d_surface_getdc(ptr ptr)
+@ cdecl wined3d_surface_incref(ptr)
+@ cdecl wined3d_surface_is_lost(ptr)
+@ cdecl wined3d_surface_map(ptr ptr ptr long)
+@ cdecl wined3d_surface_preload(ptr)
+@ cdecl wined3d_surface_releasedc(ptr ptr)
+@ cdecl wined3d_surface_restore(ptr)
+@ cdecl wined3d_surface_set_color_key(ptr long ptr)
+@ cdecl wined3d_surface_set_mem(ptr ptr)
+@ cdecl wined3d_surface_set_overlay_position(ptr long long)
+@ cdecl wined3d_surface_set_palette(ptr ptr)
+@ cdecl wined3d_surface_set_priority(ptr long)
+@ cdecl wined3d_surface_unmap(ptr)
+@ cdecl wined3d_surface_update_desc(ptr long long long long long)
+@ cdecl wined3d_surface_update_overlay(ptr ptr ptr ptr long ptr)
+@ cdecl wined3d_surface_update_overlay_z_order(ptr long ptr)
+
+@ cdecl wined3d_swapchain_create(ptr ptr ptr ptr ptr)
+@ cdecl wined3d_swapchain_decref(ptr)
+@ cdecl wined3d_swapchain_get_back_buffer(ptr long long)
+@ cdecl wined3d_swapchain_get_device(ptr)
+@ cdecl wined3d_swapchain_get_display_mode(ptr ptr ptr)
+@ cdecl wined3d_swapchain_get_front_buffer_data(ptr ptr)
+@ cdecl wined3d_swapchain_get_gamma_ramp(ptr ptr)
+@ cdecl wined3d_swapchain_get_parent(ptr)
+@ cdecl wined3d_swapchain_get_desc(ptr ptr)
+@ cdecl wined3d_swapchain_get_raster_status(ptr ptr)
+@ cdecl wined3d_swapchain_incref(ptr)
+@ cdecl wined3d_swapchain_present(ptr ptr ptr ptr ptr long)
+@ cdecl wined3d_swapchain_set_gamma_ramp(ptr long ptr)
+@ cdecl wined3d_swapchain_set_window(ptr ptr)
+
+@ cdecl wined3d_texture_add_dirty_region(ptr long ptr)
+@ cdecl wined3d_texture_create_2d(ptr ptr long long ptr ptr ptr)
+@ cdecl wined3d_texture_create_3d(ptr ptr long ptr ptr ptr)
+@ cdecl wined3d_texture_create_cube(ptr ptr long long ptr ptr ptr)
+@ cdecl wined3d_texture_decref(ptr)
+@ cdecl wined3d_texture_generate_mipmaps(ptr)
+@ cdecl wined3d_texture_get_autogen_filter_type(ptr)
+@ cdecl wined3d_texture_get_level_count(ptr)
+@ cdecl wined3d_texture_get_lod(ptr)
+@ cdecl wined3d_texture_get_parent(ptr)
+@ cdecl wined3d_texture_get_priority(ptr)
+@ cdecl wined3d_texture_get_resource(ptr)
+@ cdecl wined3d_texture_get_sub_resource(ptr long)
+@ cdecl wined3d_texture_incref(ptr)
+@ cdecl wined3d_texture_preload(ptr)
+@ cdecl wined3d_texture_set_autogen_filter_type(ptr long)
+@ cdecl wined3d_texture_set_lod(ptr long)
+@ cdecl wined3d_texture_set_priority(ptr long)
+
+@ cdecl wined3d_vertex_declaration_create(ptr ptr long ptr ptr ptr)
+@ cdecl wined3d_vertex_declaration_create_from_fvf(ptr long ptr ptr ptr)
+@ cdecl wined3d_vertex_declaration_decref(ptr)
+@ cdecl wined3d_vertex_declaration_get_parent(ptr)
+@ cdecl wined3d_vertex_declaration_incref(ptr)
+
+@ cdecl wined3d_volume_create(ptr long long long long long long ptr ptr ptr)
+@ cdecl wined3d_volume_decref(ptr)
+@ cdecl wined3d_volume_from_resource(ptr)
+@ cdecl wined3d_volume_get_parent(ptr)
+@ cdecl wined3d_volume_get_priority(ptr)
+@ cdecl wined3d_volume_get_resource(ptr)
+@ cdecl wined3d_volume_incref(ptr)
+@ cdecl wined3d_volume_map(ptr ptr ptr long)
+@ cdecl wined3d_volume_preload(ptr)
+@ cdecl wined3d_volume_set_priority(ptr long)
+@ cdecl wined3d_volume_unmap(ptr)
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/wined3d_gl.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/wined3d_gl.h	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/wined3d_gl.h	(revision 46521)
@@ -0,0 +1,619 @@
+/*
+ * Direct3D wine OpenGL include file
+ *
+ * Copyright 2002-2003 The wine-d3d team
+ * Copyright 2002-2004 Jason Edmeades
+ *                     Raphael Junqueira
+ * Copyright 2007 Roderick Colenbrander
+ *
+ * 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_WINED3D_GL_H
+#define __WINE_WINED3D_GL_H
+
+#include "wine/wgl.h"
+
+#define GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI 0x8837  /* not in the gl spec */
+
+void (WINE_GLAPI *glDisableWINE)(GLenum cap) DECLSPEC_HIDDEN;
+void (WINE_GLAPI *glEnableWINE)(GLenum cap) DECLSPEC_HIDDEN;
+
+/* OpenGL extensions. */
+enum wined3d_gl_extension
+{
+    WINED3D_GL_EXT_NONE,
+
+    /* APPLE */
+    APPLE_CLIENT_STORAGE,
+    APPLE_FENCE,
+    APPLE_FLOAT_PIXELS,
+    APPLE_FLUSH_BUFFER_RANGE,
+    APPLE_YCBCR_422,
+    /* ARB */
+    ARB_COLOR_BUFFER_FLOAT,
+    ARB_DEBUG_OUTPUT,
+    ARB_DEPTH_BUFFER_FLOAT,
+    ARB_DEPTH_CLAMP,
+    ARB_DEPTH_TEXTURE,
+    ARB_DRAW_BUFFERS,
+    ARB_DRAW_ELEMENTS_BASE_VERTEX,
+    ARB_DRAW_INSTANCED,
+    ARB_FRAGMENT_PROGRAM,
+    ARB_FRAGMENT_SHADER,
+    ARB_FRAMEBUFFER_OBJECT,
+    ARB_FRAMEBUFFER_SRGB,
+    ARB_GEOMETRY_SHADER4,
+    ARB_HALF_FLOAT_PIXEL,
+    ARB_HALF_FLOAT_VERTEX,
+    ARB_INSTANCED_ARRAYS,
+    ARB_INTERNALFORMAT_QUERY2,
+    ARB_MAP_BUFFER_ALIGNMENT,
+    ARB_MAP_BUFFER_RANGE,
+    ARB_MULTISAMPLE,
+    ARB_MULTITEXTURE,
+    ARB_OCCLUSION_QUERY,
+    ARB_PIXEL_BUFFER_OBJECT,
+    ARB_POINT_PARAMETERS,
+    ARB_POINT_SPRITE,
+    ARB_PROVOKING_VERTEX,
+    ARB_SHADER_BIT_ENCODING,
+    ARB_SHADER_OBJECTS,
+    ARB_SHADER_TEXTURE_LOD,
+    ARB_SHADING_LANGUAGE_100,
+    ARB_SHADOW,
+    ARB_SYNC,
+    ARB_TEXTURE_BORDER_CLAMP,
+    ARB_TEXTURE_COMPRESSION,
+    ARB_TEXTURE_COMPRESSION_RGTC,
+    ARB_TEXTURE_CUBE_MAP,
+    ARB_TEXTURE_ENV_ADD,
+    ARB_TEXTURE_ENV_COMBINE,
+    ARB_TEXTURE_ENV_DOT3,
+    ARB_TEXTURE_FLOAT,
+    ARB_TEXTURE_MIRRORED_REPEAT,
+    ARB_TEXTURE_NON_POWER_OF_TWO,
+    ARB_TEXTURE_RECTANGLE,
+    ARB_TEXTURE_RG,
+    ARB_VERTEX_ARRAY_BGRA,
+    ARB_VERTEX_BLEND,
+    ARB_VERTEX_BUFFER_OBJECT,
+    ARB_VERTEX_PROGRAM,
+    ARB_VERTEX_SHADER,
+    /* ATI */
+    ATI_FRAGMENT_SHADER,
+    ATI_SEPARATE_STENCIL,
+    ATI_TEXTURE_COMPRESSION_3DC,
+    ATI_TEXTURE_ENV_COMBINE3,
+    ATI_TEXTURE_MIRROR_ONCE,
+    /* EXT */
+    EXT_BLEND_COLOR,
+    EXT_BLEND_EQUATION_SEPARATE,
+    EXT_BLEND_FUNC_SEPARATE,
+    EXT_BLEND_MINMAX,
+    EXT_BLEND_SUBTRACT,
+    EXT_DRAW_BUFFERS2,
+    EXT_DEPTH_BOUNDS_TEST,
+    EXT_FOG_COORD,
+    EXT_FRAMEBUFFER_BLIT,
+    EXT_FRAMEBUFFER_MULTISAMPLE,
+    EXT_FRAMEBUFFER_OBJECT,
+    EXT_GPU_PROGRAM_PARAMETERS,
+    EXT_GPU_SHADER4,
+    EXT_PACKED_DEPTH_STENCIL,
+    EXT_PALETTED_TEXTURE,
+    EXT_POINT_PARAMETERS,
+    EXT_PROVOKING_VERTEX,
+    EXT_SECONDARY_COLOR,
+    EXT_STENCIL_TWO_SIDE,
+    EXT_STENCIL_WRAP,
+    EXT_TEXTURE3D,
+    EXT_TEXTURE_COMPRESSION_RGTC,
+    EXT_TEXTURE_COMPRESSION_S3TC,
+    EXT_TEXTURE_ENV_ADD,
+    EXT_TEXTURE_ENV_COMBINE,
+    EXT_TEXTURE_ENV_DOT3,
+    EXT_TEXTURE_FILTER_ANISOTROPIC,
+    EXT_TEXTURE_LOD_BIAS,
+    EXT_TEXTURE_SRGB,
+    EXT_TEXTURE_SRGB_DECODE,
+    EXT_VERTEX_ARRAY_BGRA,
+    /* NVIDIA */
+    NV_DEPTH_CLAMP,
+    NV_FENCE,
+    NV_FOG_DISTANCE,
+    NV_FRAGMENT_PROGRAM,
+    NV_FRAGMENT_PROGRAM2,
+    NV_FRAGMENT_PROGRAM_OPTION,
+    NV_HALF_FLOAT,
+    NV_LIGHT_MAX_EXPONENT,
+    NV_POINT_SPRITE,
+    NV_REGISTER_COMBINERS,
+    NV_REGISTER_COMBINERS2,
+    NV_TEXGEN_REFLECTION,
+    NV_TEXTURE_ENV_COMBINE4,
+    NV_TEXTURE_SHADER,
+    NV_TEXTURE_SHADER2,
+    NV_VERTEX_PROGRAM,
+    NV_VERTEX_PROGRAM1_1,
+    NV_VERTEX_PROGRAM2,
+    NV_VERTEX_PROGRAM2_OPTION,
+    NV_VERTEX_PROGRAM3,
+    /* SGI */
+    SGIS_GENERATE_MIPMAP,
+    /* WGL extensions */
+    WGL_ARB_PIXEL_FORMAT,
+    WGL_EXT_SWAP_CONTROL,
+    WGL_WINE_PIXEL_FORMAT_PASSTHROUGH,
+    /* Internally used */
+    WINED3D_GL_NORMALIZED_TEXRECT,
+    WINED3D_GL_VERSION_2_0,
+
+    WINED3D_GL_EXT_COUNT,
+};
+
+#include "wine/wglext.h"
+
+#ifdef VBOX
+/*Global resource ids sharing*/
+#define GL_SHARE_CONTEXT_RESOURCES_CR 0x8B27
+/*do flush for the command buffer of a thread the context was previusly current for*/
+#define GL_FLUSH_ON_THREAD_SWITCH_CR  0x8B28
+/*report that the shared resource is used by this context, the parameter value is a texture name*/
+#define GL_RCUSAGE_TEXTURE_SET_CR     0x8B29
+/*report that the shared resource is no longer used by this context, the parameter value is a texture name*/
+#define GL_RCUSAGE_TEXTURE_CLEAR_CR   0x8B2A
+/*configures host to create windows initially hidden*/
+#define GL_HOST_WND_CREATED_HIDDEN    0x8B2B
+
+typedef void (WINE_GLAPI *PGLFNCHROMIUMPARAMETERUCR)(GLenum param, GLint value);
+PGLFNCHROMIUMPARAMETERUCR pglChromiumParameteriCR;
+
+HGLRC (WINAPI *pVBoxCreateContext)(HDC, struct VBOXUHGSMI*) DECLSPEC_HIDDEN;
+void (WINAPI *pVBoxFlushToHost)(HGLRC) DECLSPEC_HIDDEN;
+
+
+#define VBOX_USE_GL_FUNC(pfn) p##pfn = (void *)wglGetProcAddress(#pfn);
+
+# define VBOX_GL_FUNCS_GEN \
+        VBOX_USE_FUNC(VBoxCreateContext) \
+        VBOX_USE_FUNC(VBoxFlushToHost)
+
+# define VBOX_GL_EXT_FUNCS_GEN \
+        VBOX_USE_GL_FUNC(glChromiumParameteriCR)
+
+#endif
+
+#define GL_EXT_FUNCS_GEN \
+    /* GL_APPLE_fence */ \
+    USE_GL_FUNC(glDeleteFencesAPPLE) \
+    USE_GL_FUNC(glFinishFenceAPPLE) \
+    USE_GL_FUNC(glFinishObjectAPPLE) \
+    USE_GL_FUNC(glGenFencesAPPLE) \
+    USE_GL_FUNC(glIsFenceAPPLE) \
+    USE_GL_FUNC(glSetFenceAPPLE) \
+    USE_GL_FUNC(glTestFenceAPPLE) \
+    USE_GL_FUNC(glTestObjectAPPLE) \
+    /* GL_APPLE_flush_buffer_range */ \
+    USE_GL_FUNC(glBufferParameteriAPPLE) \
+    USE_GL_FUNC(glFlushMappedBufferRangeAPPLE) \
+    /* GL_ARB_color_buffer_float */ \
+    USE_GL_FUNC(glClampColorARB) \
+    /* GL_ARB_debug_output */ \
+    USE_GL_FUNC(glDebugMessageCallbackARB) \
+    USE_GL_FUNC(glDebugMessageControlARB) \
+    USE_GL_FUNC(glDebugMessageInsertARB) \
+    USE_GL_FUNC(glGetDebugMessageLogARB) \
+    /* GL_ARB_draw_buffers */ \
+    USE_GL_FUNC(glDrawBuffersARB) \
+    /* GL_ARB_draw_elements_base_vertex */ \
+    USE_GL_FUNC(glDrawElementsBaseVertex) \
+    USE_GL_FUNC(glDrawElementsInstancedBaseVertex) \
+    USE_GL_FUNC(glDrawRangeElementsBaseVertex) \
+    USE_GL_FUNC(glMultiDrawElementsBaseVertex) \
+    /* GL_ARB_draw_instanced */ \
+    USE_GL_FUNC(glDrawArraysInstancedARB) \
+    USE_GL_FUNC(glDrawElementsInstancedARB) \
+    /* GL_ARB_framebuffer_object */ \
+    USE_GL_FUNC(glBindFramebuffer) \
+    USE_GL_FUNC(glBindRenderbuffer) \
+    USE_GL_FUNC(glBlitFramebuffer) \
+    USE_GL_FUNC(glCheckFramebufferStatus) \
+    USE_GL_FUNC(glDeleteFramebuffers) \
+    USE_GL_FUNC(glDeleteRenderbuffers) \
+    USE_GL_FUNC(glFramebufferRenderbuffer) \
+    USE_GL_FUNC(glFramebufferTexture1D) \
+    USE_GL_FUNC(glFramebufferTexture2D) \
+    USE_GL_FUNC(glFramebufferTexture3D) \
+    USE_GL_FUNC(glFramebufferTextureLayer) \
+    USE_GL_FUNC(glGenFramebuffers) \
+    USE_GL_FUNC(glGenRenderbuffers) \
+    USE_GL_FUNC(glGenerateMipmap) \
+    USE_GL_FUNC(glGetFramebufferAttachmentParameteriv) \
+    USE_GL_FUNC(glGetRenderbufferParameteriv) \
+    USE_GL_FUNC(glIsFramebuffer) \
+    USE_GL_FUNC(glIsRenderbuffer) \
+    USE_GL_FUNC(glRenderbufferStorage) \
+    USE_GL_FUNC(glRenderbufferStorageMultisample) \
+    /* GL_ARB_geometry_shader4 */ \
+    USE_GL_FUNC(glFramebufferTextureARB) \
+    USE_GL_FUNC(glFramebufferTextureFaceARB) \
+    USE_GL_FUNC(glFramebufferTextureLayerARB) \
+    USE_GL_FUNC(glProgramParameteriARB) \
+    /* GL_ARB_instanced_arrays */ \
+    USE_GL_FUNC(glVertexAttribDivisorARB) \
+    /* GL_ARB_internalformat_query */ \
+    USE_GL_FUNC(glGetInternalformativ) \
+    /* GL_ARB_internalformat_query2 */ \
+    USE_GL_FUNC(glGetInternalformati64v) \
+    /* GL_ARB_map_buffer_range */ \
+    USE_GL_FUNC(glFlushMappedBufferRange) \
+    USE_GL_FUNC(glMapBufferRange) \
+    /* GL_ARB_multisample */ \
+    USE_GL_FUNC(glSampleCoverageARB) \
+    /* GL_ARB_multitexture */ \
+    USE_GL_FUNC(glActiveTextureARB) \
+    USE_GL_FUNC(glClientActiveTextureARB) \
+    USE_GL_FUNC(glMultiTexCoord1fARB) \
+    USE_GL_FUNC(glMultiTexCoord1fvARB) \
+    USE_GL_FUNC(glMultiTexCoord2fARB) \
+    USE_GL_FUNC(glMultiTexCoord2fvARB) \
+    USE_GL_FUNC(glMultiTexCoord2svARB) \
+    USE_GL_FUNC(glMultiTexCoord3fARB) \
+    USE_GL_FUNC(glMultiTexCoord3fvARB) \
+    USE_GL_FUNC(glMultiTexCoord4fARB) \
+    USE_GL_FUNC(glMultiTexCoord4fvARB) \
+    USE_GL_FUNC(glMultiTexCoord4svARB) \
+    /* GL_ARB_occlusion_query */ \
+    USE_GL_FUNC(glBeginQueryARB) \
+    USE_GL_FUNC(glDeleteQueriesARB) \
+    USE_GL_FUNC(glEndQueryARB) \
+    USE_GL_FUNC(glGenQueriesARB) \
+    USE_GL_FUNC(glGetQueryivARB) \
+    USE_GL_FUNC(glGetQueryObjectivARB) \
+    USE_GL_FUNC(glGetQueryObjectuivARB) \
+    USE_GL_FUNC(glIsQueryARB) \
+    /* GL_ARB_point_parameters */ \
+    USE_GL_FUNC(glPointParameterfARB) \
+    USE_GL_FUNC(glPointParameterfvARB) \
+    /* GL_ARB_provoking_vertex */ \
+    USE_GL_FUNC(glProvokingVertex) \
+    /* GL_ARB_shader_objects */ \
+    USE_GL_FUNC(glAttachObjectARB) \
+    USE_GL_FUNC(glBindAttribLocationARB) \
+    USE_GL_FUNC(glCompileShaderARB) \
+    USE_GL_FUNC(glCreateProgramObjectARB) \
+    USE_GL_FUNC(glCreateShaderObjectARB) \
+    USE_GL_FUNC(glDeleteObjectARB) \
+    USE_GL_FUNC(glDetachObjectARB) \
+    USE_GL_FUNC(glGetActiveUniformARB) \
+    USE_GL_FUNC(glGetAttachedObjectsARB) \
+    USE_GL_FUNC(glGetAttribLocationARB) \
+    USE_GL_FUNC(glGetHandleARB) \
+    USE_GL_FUNC(glGetInfoLogARB) \
+    USE_GL_FUNC(glGetObjectParameterfvARB) \
+    USE_GL_FUNC(glGetObjectParameterivARB) \
+    USE_GL_FUNC(glGetShaderSourceARB) \
+    USE_GL_FUNC(glGetUniformLocationARB) \
+    USE_GL_FUNC(glGetUniformfvARB) \
+    USE_GL_FUNC(glGetUniformivARB) \
+    USE_GL_FUNC(glLinkProgramARB) \
+    USE_GL_FUNC(glShaderSourceARB) \
+    USE_GL_FUNC(glUniform1fARB) \
+    USE_GL_FUNC(glUniform1fvARB) \
+    USE_GL_FUNC(glUniform1iARB) \
+    USE_GL_FUNC(glUniform1ivARB) \
+    USE_GL_FUNC(glUniform2fARB) \
+    USE_GL_FUNC(glUniform2fvARB) \
+    USE_GL_FUNC(glUniform2iARB) \
+    USE_GL_FUNC(glUniform2ivARB) \
+    USE_GL_FUNC(glUniform3fARB) \
+    USE_GL_FUNC(glUniform3fvARB) \
+    USE_GL_FUNC(glUniform3iARB) \
+    USE_GL_FUNC(glUniform3ivARB) \
+    USE_GL_FUNC(glUniform4fARB) \
+    USE_GL_FUNC(glUniform4fvARB) \
+    USE_GL_FUNC(glUniform4iARB) \
+    USE_GL_FUNC(glUniform4ivARB) \
+    USE_GL_FUNC(glUniformMatrix2fvARB) \
+    USE_GL_FUNC(glUniformMatrix3fvARB) \
+    USE_GL_FUNC(glUniformMatrix4fvARB) \
+    USE_GL_FUNC(glUseProgramObjectARB) \
+    USE_GL_FUNC(glValidateProgramARB) \
+    /* GL_ARB_sync */ \
+    USE_GL_FUNC(glClientWaitSync) \
+    USE_GL_FUNC(glDeleteSync) \
+    USE_GL_FUNC(glFenceSync) \
+    USE_GL_FUNC(glGetInteger64v) \
+    USE_GL_FUNC(glGetSynciv) \
+    USE_GL_FUNC(glIsSync) \
+    USE_GL_FUNC(glWaitSync) \
+    /* GL_ARB_texture_compression */ \
+    USE_GL_FUNC(glCompressedTexImage2DARB) \
+    USE_GL_FUNC(glCompressedTexImage3DARB) \
+    USE_GL_FUNC(glCompressedTexSubImage2DARB) \
+    USE_GL_FUNC(glCompressedTexSubImage3DARB) \
+    USE_GL_FUNC(glGetCompressedTexImageARB) \
+    /* GL_ARB_vertex_blend */ \
+    USE_GL_FUNC(glVertexBlendARB) \
+    USE_GL_FUNC(glWeightPointerARB) \
+    USE_GL_FUNC(glWeightbvARB) \
+    USE_GL_FUNC(glWeightdvARB) \
+    USE_GL_FUNC(glWeightfvARB) \
+    USE_GL_FUNC(glWeightivARB) \
+    USE_GL_FUNC(glWeightsvARB) \
+    USE_GL_FUNC(glWeightubvARB) \
+    USE_GL_FUNC(glWeightuivARB) \
+    USE_GL_FUNC(glWeightusvARB) \
+    /* GL_ARB_vertex_buffer_object */ \
+    USE_GL_FUNC(glBindBufferARB) \
+    USE_GL_FUNC(glBufferDataARB) \
+    USE_GL_FUNC(glBufferSubDataARB) \
+    USE_GL_FUNC(glDeleteBuffersARB) \
+    USE_GL_FUNC(glGenBuffersARB) \
+    USE_GL_FUNC(glGetBufferParameterivARB) \
+    USE_GL_FUNC(glGetBufferPointervARB) \
+    USE_GL_FUNC(glGetBufferSubDataARB) \
+    USE_GL_FUNC(glIsBufferARB) \
+    USE_GL_FUNC(glMapBufferARB) \
+    USE_GL_FUNC(glUnmapBufferARB) \
+    /* GL_ARB_vertex_program */ \
+    USE_GL_FUNC(glBindProgramARB) \
+    USE_GL_FUNC(glDeleteProgramsARB) \
+    USE_GL_FUNC(glDisableVertexAttribArrayARB) \
+    USE_GL_FUNC(glEnableVertexAttribArrayARB) \
+    USE_GL_FUNC(glGenProgramsARB) \
+    USE_GL_FUNC(glGetProgramivARB) \
+    USE_GL_FUNC(glProgramEnvParameter4fvARB) \
+    USE_GL_FUNC(glProgramLocalParameter4fvARB) \
+    USE_GL_FUNC(glProgramStringARB) \
+    USE_GL_FUNC(glVertexAttrib1dARB) \
+    USE_GL_FUNC(glVertexAttrib1dvARB) \
+    USE_GL_FUNC(glVertexAttrib1fARB) \
+    USE_GL_FUNC(glVertexAttrib1fvARB) \
+    USE_GL_FUNC(glVertexAttrib1sARB) \
+    USE_GL_FUNC(glVertexAttrib1svARB) \
+    USE_GL_FUNC(glVertexAttrib2dARB) \
+    USE_GL_FUNC(glVertexAttrib2dvARB) \
+    USE_GL_FUNC(glVertexAttrib2fARB) \
+    USE_GL_FUNC(glVertexAttrib2fvARB) \
+    USE_GL_FUNC(glVertexAttrib2sARB) \
+    USE_GL_FUNC(glVertexAttrib2svARB) \
+    USE_GL_FUNC(glVertexAttrib3dARB) \
+    USE_GL_FUNC(glVertexAttrib3dvARB) \
+    USE_GL_FUNC(glVertexAttrib3fARB) \
+    USE_GL_FUNC(glVertexAttrib3fvARB) \
+    USE_GL_FUNC(glVertexAttrib3sARB) \
+    USE_GL_FUNC(glVertexAttrib3svARB) \
+    USE_GL_FUNC(glVertexAttrib4NbvARB) \
+    USE_GL_FUNC(glVertexAttrib4NivARB) \
+    USE_GL_FUNC(glVertexAttrib4NsvARB) \
+    USE_GL_FUNC(glVertexAttrib4NubARB) \
+    USE_GL_FUNC(glVertexAttrib4NubvARB) \
+    USE_GL_FUNC(glVertexAttrib4NuivARB) \
+    USE_GL_FUNC(glVertexAttrib4NusvARB) \
+    USE_GL_FUNC(glVertexAttrib4bvARB) \
+    USE_GL_FUNC(glVertexAttrib4dARB) \
+    USE_GL_FUNC(glVertexAttrib4dvARB) \
+    USE_GL_FUNC(glVertexAttrib4fARB) \
+    USE_GL_FUNC(glVertexAttrib4fvARB) \
+    USE_GL_FUNC(glVertexAttrib4ivARB) \
+    USE_GL_FUNC(glVertexAttrib4sARB) \
+    USE_GL_FUNC(glVertexAttrib4svARB) \
+    USE_GL_FUNC(glVertexAttrib4ubvARB) \
+    USE_GL_FUNC(glVertexAttrib4uivARB) \
+    USE_GL_FUNC(glVertexAttrib4usvARB) \
+    USE_GL_FUNC(glVertexAttribPointerARB) \
+    /* GL_ATI_fragment_shader */ \
+    USE_GL_FUNC(glAlphaFragmentOp1ATI) \
+    USE_GL_FUNC(glAlphaFragmentOp2ATI) \
+    USE_GL_FUNC(glAlphaFragmentOp3ATI) \
+    USE_GL_FUNC(glBeginFragmentShaderATI) \
+    USE_GL_FUNC(glBindFragmentShaderATI) \
+    USE_GL_FUNC(glColorFragmentOp1ATI) \
+    USE_GL_FUNC(glColorFragmentOp2ATI) \
+    USE_GL_FUNC(glColorFragmentOp3ATI) \
+    USE_GL_FUNC(glDeleteFragmentShaderATI) \
+    USE_GL_FUNC(glEndFragmentShaderATI) \
+    USE_GL_FUNC(glGenFragmentShadersATI) \
+    USE_GL_FUNC(glPassTexCoordATI) \
+    USE_GL_FUNC(glSampleMapATI) \
+    USE_GL_FUNC(glSetFragmentShaderConstantATI) \
+    /* GL_ATI_separate_stencil */ \
+    USE_GL_FUNC(glStencilOpSeparateATI) \
+    USE_GL_FUNC(glStencilFuncSeparateATI) \
+    /* GL_EXT_blend_color */ \
+    USE_GL_FUNC(glBlendColorEXT) \
+    /* GL_EXT_blend_equation_separate */ \
+    USE_GL_FUNC(glBlendFuncSeparateEXT) \
+    /* GL_EXT_blend_func_separate */ \
+    USE_GL_FUNC(glBlendEquationSeparateEXT) \
+    /* GL_EXT_blend_minmax */ \
+    USE_GL_FUNC(glBlendEquationEXT) \
+    /* GL_EXT_depth_bounds_test */ \
+    USE_GL_FUNC(glDepthBoundsEXT) \
+    /* GL_EXT_draw_buffers2 */ \
+    USE_GL_FUNC(glColorMaskIndexedEXT) \
+    USE_GL_FUNC(glDisableIndexedEXT) \
+    USE_GL_FUNC(glEnableIndexedEXT) \
+    USE_GL_FUNC(glGetBooleanIndexedvEXT) \
+    USE_GL_FUNC(glGetIntegerIndexedvEXT) \
+    USE_GL_FUNC(glIsEnabledIndexedEXT) \
+    /* GL_EXT_fog_coord */ \
+    USE_GL_FUNC(glFogCoordPointerEXT) \
+    USE_GL_FUNC(glFogCoorddEXT) \
+    USE_GL_FUNC(glFogCoorddvEXT) \
+    USE_GL_FUNC(glFogCoordfEXT) \
+    USE_GL_FUNC(glFogCoordfvEXT) \
+    /* GL_EXT_framebuffer_blit */ \
+    USE_GL_FUNC(glBlitFramebufferEXT) \
+    /* GL_EXT_framebuffer_multisample */ \
+    USE_GL_FUNC(glRenderbufferStorageMultisampleEXT) \
+    /* GL_EXT_framebuffer_object */ \
+    USE_GL_FUNC(glBindFramebufferEXT) \
+    USE_GL_FUNC(glBindRenderbufferEXT) \
+    USE_GL_FUNC(glCheckFramebufferStatusEXT) \
+    USE_GL_FUNC(glDeleteFramebuffersEXT) \
+    USE_GL_FUNC(glDeleteRenderbuffersEXT) \
+    USE_GL_FUNC(glFramebufferRenderbufferEXT) \
+    USE_GL_FUNC(glFramebufferTexture1DEXT) \
+    USE_GL_FUNC(glFramebufferTexture2DEXT) \
+    USE_GL_FUNC(glFramebufferTexture3DEXT) \
+    USE_GL_FUNC(glGenFramebuffersEXT) \
+    USE_GL_FUNC(glGenRenderbuffersEXT) \
+    USE_GL_FUNC(glGenerateMipmapEXT) \
+    USE_GL_FUNC(glGetFramebufferAttachmentParameterivEXT) \
+    USE_GL_FUNC(glGetRenderbufferParameterivEXT) \
+    USE_GL_FUNC(glIsFramebufferEXT) \
+    USE_GL_FUNC(glIsRenderbufferEXT) \
+    USE_GL_FUNC(glRenderbufferStorageEXT) \
+    /* GL_EXT_gpu_program_parameters */ \
+    USE_GL_FUNC(glProgramEnvParameters4fvEXT) \
+    USE_GL_FUNC(glProgramLocalParameters4fvEXT) \
+    /* GL_EXT_gpu_shader4 */\
+    USE_GL_FUNC(glBindFragDataLocationEXT) \
+    USE_GL_FUNC(glGetFragDataLocationEXT) \
+    USE_GL_FUNC(glGetUniformuivEXT) \
+    USE_GL_FUNC(glGetVertexAttribIivEXT) \
+    USE_GL_FUNC(glGetVertexAttribIuivEXT) \
+    USE_GL_FUNC(glUniform1uiEXT) \
+    USE_GL_FUNC(glUniform1uivEXT) \
+    USE_GL_FUNC(glUniform2uiEXT) \
+    USE_GL_FUNC(glUniform2uivEXT) \
+    USE_GL_FUNC(glUniform3uiEXT) \
+    USE_GL_FUNC(glUniform3uivEXT) \
+    USE_GL_FUNC(glUniform4uiEXT) \
+    USE_GL_FUNC(glUniform4uivEXT) \
+    USE_GL_FUNC(glVertexAttribI1iEXT) \
+    USE_GL_FUNC(glVertexAttribI1ivEXT) \
+    USE_GL_FUNC(glVertexAttribI1uiEXT) \
+    USE_GL_FUNC(glVertexAttribI1uivEXT) \
+    USE_GL_FUNC(glVertexAttribI2iEXT) \
+    USE_GL_FUNC(glVertexAttribI2ivEXT) \
+    USE_GL_FUNC(glVertexAttribI2uiEXT) \
+    USE_GL_FUNC(glVertexAttribI2uivEXT) \
+    USE_GL_FUNC(glVertexAttribI3iEXT) \
+    USE_GL_FUNC(glVertexAttribI3ivEXT) \
+    USE_GL_FUNC(glVertexAttribI3uiEXT) \
+    USE_GL_FUNC(glVertexAttribI3uivEXT) \
+    USE_GL_FUNC(glVertexAttribI4bvEXT) \
+    USE_GL_FUNC(glVertexAttribI4iEXT) \
+    USE_GL_FUNC(glVertexAttribI4ivEXT) \
+    USE_GL_FUNC(glVertexAttribI4svEXT) \
+    USE_GL_FUNC(glVertexAttribI4ubvEXT) \
+    USE_GL_FUNC(glVertexAttribI4uiEXT) \
+    USE_GL_FUNC(glVertexAttribI4uivEXT) \
+    USE_GL_FUNC(glVertexAttribI4usvEXT) \
+    USE_GL_FUNC(glVertexAttribIPointerEXT) \
+    /* GL_EXT_paletted_texture */ \
+    USE_GL_FUNC(glColorTableEXT) \
+    /* GL_EXT_point_parameters */ \
+    USE_GL_FUNC(glPointParameterfEXT) \
+    USE_GL_FUNC(glPointParameterfvEXT) \
+    /* GL_EXT_provoking_vertex */ \
+    USE_GL_FUNC(glProvokingVertexEXT) \
+    /* GL_EXT_secondary_color */ \
+    USE_GL_FUNC(glSecondaryColor3fEXT) \
+    USE_GL_FUNC(glSecondaryColor3fvEXT) \
+    USE_GL_FUNC(glSecondaryColor3ubEXT) \
+    USE_GL_FUNC(glSecondaryColor3ubvEXT) \
+    USE_GL_FUNC(glSecondaryColorPointerEXT) \
+    /* GL_EXT_stencil_two_side */ \
+    USE_GL_FUNC(glActiveStencilFaceEXT) \
+    /* GL_EXT_texture3D */ \
+    USE_GL_FUNC(glTexImage3D) \
+    USE_GL_FUNC(glTexImage3DEXT) \
+    USE_GL_FUNC(glTexSubImage3D) \
+    USE_GL_FUNC(glTexSubImage3DEXT) \
+    /* GL_NV_fence */ \
+    USE_GL_FUNC(glDeleteFencesNV) \
+    USE_GL_FUNC(glFinishFenceNV) \
+    USE_GL_FUNC(glGenFencesNV) \
+    USE_GL_FUNC(glGetFenceivNV) \
+    USE_GL_FUNC(glIsFenceNV) \
+    USE_GL_FUNC(glSetFenceNV) \
+    USE_GL_FUNC(glTestFenceNV) \
+    /* GL_NV_half_float */ \
+    USE_GL_FUNC(glColor3hNV) \
+    USE_GL_FUNC(glColor3hvNV) \
+    USE_GL_FUNC(glColor4hNV) \
+    USE_GL_FUNC(glColor4hvNV) \
+    USE_GL_FUNC(glFogCoordhNV) \
+    USE_GL_FUNC(glFogCoordhvNV) \
+    USE_GL_FUNC(glMultiTexCoord1hNV) \
+    USE_GL_FUNC(glMultiTexCoord1hvNV) \
+    USE_GL_FUNC(glMultiTexCoord2hNV) \
+    USE_GL_FUNC(glMultiTexCoord2hvNV) \
+    USE_GL_FUNC(glMultiTexCoord3hNV) \
+    USE_GL_FUNC(glMultiTexCoord3hvNV) \
+    USE_GL_FUNC(glMultiTexCoord4hNV) \
+    USE_GL_FUNC(glMultiTexCoord4hvNV) \
+    USE_GL_FUNC(glNormal3hNV) \
+    USE_GL_FUNC(glNormal3hvNV) \
+    USE_GL_FUNC(glSecondaryColor3hNV) \
+    USE_GL_FUNC(glSecondaryColor3hvNV) \
+    USE_GL_FUNC(glTexCoord1hNV) \
+    USE_GL_FUNC(glTexCoord1hvNV) \
+    USE_GL_FUNC(glTexCoord2hNV) \
+    USE_GL_FUNC(glTexCoord2hvNV) \
+    USE_GL_FUNC(glTexCoord3hNV) \
+    USE_GL_FUNC(glTexCoord3hvNV) \
+    USE_GL_FUNC(glTexCoord4hNV) \
+    USE_GL_FUNC(glTexCoord4hvNV) \
+    USE_GL_FUNC(glVertex2hNV) \
+    USE_GL_FUNC(glVertex2hvNV) \
+    USE_GL_FUNC(glVertex3hNV) \
+    USE_GL_FUNC(glVertex3hvNV) \
+    USE_GL_FUNC(glVertex4hNV) \
+    USE_GL_FUNC(glVertex4hvNV) \
+    USE_GL_FUNC(glVertexAttrib1hNV) \
+    USE_GL_FUNC(glVertexAttrib1hvNV) \
+    USE_GL_FUNC(glVertexAttrib2hNV) \
+    USE_GL_FUNC(glVertexAttrib2hvNV) \
+    USE_GL_FUNC(glVertexAttrib3hNV) \
+    USE_GL_FUNC(glVertexAttrib3hvNV) \
+    USE_GL_FUNC(glVertexAttrib4hNV) \
+    USE_GL_FUNC(glVertexAttrib4hvNV) \
+    USE_GL_FUNC(glVertexAttribs1hvNV) \
+    USE_GL_FUNC(glVertexAttribs2hvNV) \
+    USE_GL_FUNC(glVertexAttribs3hvNV) \
+    USE_GL_FUNC(glVertexAttribs4hvNV) \
+    USE_GL_FUNC(glVertexWeighthNV) \
+    USE_GL_FUNC(glVertexWeighthvNV) \
+    /* GL_NV_point_sprite */ \
+    USE_GL_FUNC(glPointParameteri) \
+    USE_GL_FUNC(glPointParameteriNV) \
+    USE_GL_FUNC(glPointParameteriv) \
+    USE_GL_FUNC(glPointParameterivNV) \
+    /* GL_NV_register_combiners */ \
+    USE_GL_FUNC(glCombinerInputNV) \
+    USE_GL_FUNC(glCombinerOutputNV) \
+    USE_GL_FUNC(glCombinerParameterfNV) \
+    USE_GL_FUNC(glCombinerParameterfvNV) \
+    USE_GL_FUNC(glCombinerParameteriNV) \
+    USE_GL_FUNC(glCombinerParameterivNV) \
+    USE_GL_FUNC(glFinalCombinerInputNV) \
+    /* WGL extensions */ \
+    USE_GL_FUNC(wglChoosePixelFormatARB) \
+    USE_GL_FUNC(wglGetExtensionsStringARB) \
+    USE_GL_FUNC(wglGetPixelFormatAttribfvARB) \
+    USE_GL_FUNC(wglGetPixelFormatAttribivARB) \
+    USE_GL_FUNC(wglSetPixelFormatWINE) \
+    USE_GL_FUNC(wglSwapIntervalEXT) \
+    /* #ifdef VBOX */ \
+    VBOX_GL_EXT_FUNCS_GEN \
+    /* #endif */
+
+#endif /* __WINE_WINED3D_GL */
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/wined3d_main.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/wined3d_main.c	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/wined3d_main.c	(revision 46521)
@@ -0,0 +1,575 @@
+/*
+ * Direct3D wine internal interface main
+ *
+ * Copyright 2002-2003 The wine-d3d team
+ * Copyright 2002-2003 Raphael Junqueira
+ * Copyright 2004      Jason Edmeades
+ * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
+ * Copyright 2009 Henri Verbeet for CodeWeavers
+ *
+ * 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 "initguid.h"
+#include "wined3d_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d);
+WINE_DECLARE_DEBUG_CHANNEL(winediag);
+
+#ifndef VBOX_WITH_WDDM
+struct wined3d_wndproc
+{
+    HWND window;
+    BOOL unicode;
+    WNDPROC proc;
+    struct wined3d_device *device;
+};
+
+struct wined3d_wndproc_table
+{
+    struct wined3d_wndproc *entries;
+    unsigned int count;
+    unsigned int size;
+};
+
+static struct wined3d_wndproc_table wndproc_table;
+
+static CRITICAL_SECTION wined3d_cs;
+static CRITICAL_SECTION_DEBUG wined3d_cs_debug =
+{
+    0, 0, &wined3d_cs,
+    {&wined3d_cs_debug.ProcessLocksList,
+    &wined3d_cs_debug.ProcessLocksList},
+    0, 0, {(DWORD_PTR)(__FILE__ ": wined3d_cs")}
+};
+static CRITICAL_SECTION wined3d_cs = {&wined3d_cs_debug, -1, 0, 0, 0, 0};
+
+static CRITICAL_SECTION wined3d_wndproc_cs;
+static CRITICAL_SECTION_DEBUG wined3d_wndproc_cs_debug =
+{
+    0, 0, &wined3d_wndproc_cs,
+    {&wined3d_wndproc_cs_debug.ProcessLocksList,
+    &wined3d_wndproc_cs_debug.ProcessLocksList},
+    0, 0, {(DWORD_PTR)(__FILE__ ": wined3d_wndproc_cs")}
+};
+static CRITICAL_SECTION wined3d_wndproc_cs = {&wined3d_wndproc_cs_debug, -1, 0, 0, 0, 0};
+#endif
+
+/* When updating default value here, make sure to update winecfg as well,
+ * where appropriate. */
+struct wined3d_settings wined3d_settings =
+{
+    TRUE,           /* Use of GLSL enabled by default */
+    ORM_FBO,        /* Use FBOs to do offscreen rendering */
+    RTL_READTEX,    /* Default render target locking method */
+    PCI_VENDOR_NONE,/* PCI Vendor ID */
+    PCI_DEVICE_NONE,/* PCI Device ID */
+    0,              /* The default of memory is set in init_driver_info */
+    NULL,           /* No wine logo by default */
+    TRUE,           /* Multisampling enabled by default. */
+    FALSE,          /* No strict draw ordering. */
+    TRUE,           /* Don't try to render onscreen by default. */
+    ~0U,            /* No VS shader model limit by default. */
+    ~0U,            /* No GS shader model limit by default. */
+    ~0U,            /* No PS shader model limit by default. */
+    FALSE,          /* 3D support enabled by default. */
+};
+
+/* Do not call while under the GL lock. */
+struct wined3d * CDECL wined3d_create(UINT version, DWORD flags)
+{
+    struct wined3d *object;
+    HRESULT hr;
+
+#ifdef VBOX
+    hr = VBoxExtCheckInit();
+    if (FAILED(hr))
+    {
+        ERR("VBoxExtCheckInit failed, hr (0x%x)\n", hr);
+        return NULL;
+    }
+#endif
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, FIELD_OFFSET(struct wined3d, adapters[1]));
+    if (!object)
+    {
+        ERR("Failed to allocate wined3d object memory.\n");
+#ifdef VBOX
+        VBoxExtCheckTerm();
+#endif
+        return NULL;
+    }
+
+    if (version == 7 && wined3d_settings.no_3d)
+        flags |= WINED3D_NO3D;
+
+    hr = wined3d_init(object, version, flags);
+    if (FAILED(hr))
+    {
+        WARN("Failed to initialize wined3d object, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+#ifdef VBOX
+        VBoxExtCheckTerm();
+#endif
+        return NULL;
+    }
+
+    TRACE("Created wined3d object %p for d3d%d support.\n", object, version);
+
+    return object;
+}
+
+static DWORD get_config_key(HKEY defkey, HKEY appkey, const char *name, char *buffer, DWORD size)
+{
+    if (appkey && !RegQueryValueExA(appkey, name, 0, NULL, (BYTE *)buffer, &size)) return 0;
+    if (defkey && !RegQueryValueExA(defkey, name, 0, NULL, (BYTE *)buffer, &size)) return 0;
+    return ERROR_FILE_NOT_FOUND;
+}
+
+static DWORD get_config_key_dword(HKEY defkey, HKEY appkey, const char *name, DWORD *data)
+{
+    DWORD type;
+    DWORD size = sizeof(DWORD);
+    if (appkey && !RegQueryValueExA(appkey, name, 0, &type, (BYTE *)data, &size) && (type == REG_DWORD)) return 0;
+    if (defkey && !RegQueryValueExA(defkey, name, 0, &type, (BYTE *)data, &size) && (type == REG_DWORD)) return 0;
+    return ERROR_FILE_NOT_FOUND;
+}
+
+static BOOL wined3d_dll_init(HINSTANCE hInstDLL)
+{
+    DWORD wined3d_context_tls_idx;
+    char buffer[MAX_PATH+10];
+    DWORD size = sizeof(buffer);
+    HKEY hkey = 0;
+    HKEY appkey = 0;
+    DWORD len, tmpvalue;
+    WNDCLASSA wc;
+#ifdef VBOX
+# ifndef VBOX_WITH_WDDM
+    InitializeCriticalSection(&wined3d_cs);
+    InitializeCriticalSection(&wined3d_wndproc_cs);
+# endif
+#endif
+
+    wined3d_context_tls_idx = TlsAlloc();
+    if (wined3d_context_tls_idx == TLS_OUT_OF_INDEXES)
+    {
+        DWORD err = GetLastError();
+        ERR("Failed to allocate context TLS index, err %#x.\n", err);
+        return FALSE;
+    }
+    context_set_tls_idx(wined3d_context_tls_idx);
+
+    /* We need our own window class for a fake window which we use to retrieve GL capabilities */
+    /* We might need CS_OWNDC in the future if we notice strange things on Windows.
+     * Various articles/posts about OpenGL problems on Windows recommend this. */
+    wc.style                = CS_HREDRAW | CS_VREDRAW;
+    wc.lpfnWndProc          = DefWindowProcA;
+    wc.cbClsExtra           = 0;
+    wc.cbWndExtra           = 0;
+    wc.hInstance            = hInstDLL;
+    wc.hIcon                = LoadIconA(NULL, (LPCSTR)IDI_WINLOGO);
+    wc.hCursor              = LoadCursorA(NULL, (LPCSTR)IDC_ARROW);
+    wc.hbrBackground        = NULL;
+    wc.lpszMenuName         = NULL;
+    wc.lpszClassName        = WINED3D_OPENGL_WINDOW_CLASS_NAME;
+
+    if (!RegisterClassA(&wc))
+    {
+        ERR("Failed to register window class 'WineD3D_OpenGL'!\n");
+        if (!TlsFree(wined3d_context_tls_idx))
+        {
+            DWORD err = GetLastError();
+            ERR("Failed to free context TLS index, err %#x.\n", err);
+        }
+        return FALSE;
+    }
+
+    DisableThreadLibraryCalls(hInstDLL);
+
+    /* @@ Wine registry key: HKCU\Software\Wine\Direct3D */
+    if ( RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Direct3D", &hkey ) ) hkey = 0;
+
+    len = GetModuleFileNameA( 0, buffer, MAX_PATH );
+    if (len && len < MAX_PATH)
+    {
+        HKEY tmpkey;
+        /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\Direct3D */
+        if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
+        {
+            char *p, *appname = buffer;
+            if ((p = strrchr( appname, '/' ))) appname = p + 1;
+            if ((p = strrchr( appname, '\\' ))) appname = p + 1;
+            strcat( appname, "\\Direct3D" );
+            TRACE("appname = [%s]\n", appname);
+            if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
+            RegCloseKey( tmpkey );
+        }
+    }
+
+    if (hkey || appkey)
+    {
+        if ( !get_config_key( hkey, appkey, "UseGLSL", buffer, size) )
+        {
+            if (!strcmp(buffer,"disabled"))
+            {
+                ERR_(winediag)("The GLSL shader backend has been disabled. You get to keep all the pieces if it breaks.\n");
+                TRACE("Use of GL Shading Language disabled\n");
+                wined3d_settings.glslRequested = FALSE;
+            }
+        }
+        if ( !get_config_key( hkey, appkey, "OffscreenRenderingMode", buffer, size) )
+        {
+            if (!strcmp(buffer,"backbuffer"))
+            {
+                TRACE("Using the backbuffer for offscreen rendering\n");
+                wined3d_settings.offscreen_rendering_mode = ORM_BACKBUFFER;
+            }
+            else if (!strcmp(buffer,"fbo"))
+            {
+                TRACE("Using FBOs for offscreen rendering\n");
+                wined3d_settings.offscreen_rendering_mode = ORM_FBO;
+            }
+        }
+        if ( !get_config_key( hkey, appkey, "RenderTargetLockMode", buffer, size) )
+        {
+            if (!strcmp(buffer,"readdraw"))
+            {
+                TRACE("Using glReadPixels for render target reading and glDrawPixels for writing\n");
+                wined3d_settings.rendertargetlock_mode = RTL_READDRAW;
+            }
+            else if (!strcmp(buffer,"readtex"))
+            {
+                TRACE("Using glReadPixels for render target reading and textures for writing\n");
+                wined3d_settings.rendertargetlock_mode = RTL_READTEX;
+            }
+        }
+        if ( !get_config_key_dword( hkey, appkey, "VideoPciDeviceID", &tmpvalue) )
+        {
+            int pci_device_id = tmpvalue;
+
+            /* A pci device id is 16-bit */
+            if(pci_device_id > 0xffff)
+            {
+                ERR("Invalid value for VideoPciDeviceID. The value should be smaller or equal to 65535 or 0xffff\n");
+            }
+            else
+            {
+                TRACE("Using PCI Device ID %04x\n", pci_device_id);
+                wined3d_settings.pci_device_id = pci_device_id;
+            }
+        }
+        if ( !get_config_key_dword( hkey, appkey, "VideoPciVendorID", &tmpvalue) )
+        {
+            int pci_vendor_id = tmpvalue;
+
+            /* A pci device id is 16-bit */
+            if(pci_vendor_id > 0xffff)
+            {
+                ERR("Invalid value for VideoPciVendorID. The value should be smaller or equal to 65535 or 0xffff\n");
+            }
+            else
+            {
+                TRACE("Using PCI Vendor ID %04x\n", pci_vendor_id);
+                wined3d_settings.pci_vendor_id = pci_vendor_id;
+            }
+        }
+        if ( !get_config_key( hkey, appkey, "VideoMemorySize", buffer, size) )
+        {
+            int TmpVideoMemorySize = atoi(buffer);
+            if(TmpVideoMemorySize > 0)
+            {
+                wined3d_settings.emulated_textureram = TmpVideoMemorySize *1024*1024;
+                TRACE("Use %iMB = %d byte for emulated_textureram\n",
+                        TmpVideoMemorySize,
+                        wined3d_settings.emulated_textureram);
+            }
+            else
+                ERR("VideoMemorySize is %i but must be >0\n", TmpVideoMemorySize);
+        }
+        if ( !get_config_key( hkey, appkey, "WineLogo", buffer, size) )
+        {
+            size_t len = strlen(buffer) + 1;
+
+            wined3d_settings.logo = HeapAlloc(GetProcessHeap(), 0, len);
+            if (!wined3d_settings.logo) ERR("Failed to allocate logo path memory.\n");
+            else memcpy(wined3d_settings.logo, buffer, len);
+        }
+        if ( !get_config_key( hkey, appkey, "Multisampling", buffer, size) )
+        {
+            if (!strcmp(buffer, "disabled"))
+            {
+                TRACE("Multisampling disabled.\n");
+                wined3d_settings.allow_multisampling = FALSE;
+            }
+        }
+        if (!get_config_key(hkey, appkey, "StrictDrawOrdering", buffer, size)
+                && !strcmp(buffer,"enabled"))
+        {
+            TRACE("Enforcing strict draw ordering.\n");
+            wined3d_settings.strict_draw_ordering = TRUE;
+        }
+        if (!get_config_key(hkey, appkey, "AlwaysOffscreen", buffer, size)
+                && !strcmp(buffer,"disabled"))
+        {
+            TRACE("Not always rendering backbuffers offscreen.\n");
+            wined3d_settings.always_offscreen = FALSE;
+        }
+        if (!get_config_key_dword(hkey, appkey, "MaxShaderModelVS", &wined3d_settings.max_sm_vs))
+            TRACE("Limiting VS shader model to %u.\n", wined3d_settings.max_sm_vs);
+        if (!get_config_key_dword(hkey, appkey, "MaxShaderModelGS", &wined3d_settings.max_sm_gs))
+            TRACE("Limiting GS shader model to %u.\n", wined3d_settings.max_sm_gs);
+        if (!get_config_key_dword(hkey, appkey, "MaxShaderModelPS", &wined3d_settings.max_sm_ps))
+            TRACE("Limiting PS shader model to %u.\n", wined3d_settings.max_sm_ps);
+        if (!get_config_key(hkey, appkey, "DirectDrawRenderer", buffer, size)
+                && !strcmp(buffer, "gdi"))
+        {
+            TRACE("Disabling 3D support.\n");
+            wined3d_settings.no_3d = TRUE;
+        }
+    }
+
+    if (appkey) RegCloseKey( appkey );
+    if (hkey) RegCloseKey( hkey );
+
+    return TRUE;
+}
+
+static BOOL wined3d_dll_destroy(HINSTANCE hInstDLL)
+{
+    DWORD wined3d_context_tls_idx = context_get_tls_idx();
+#ifndef VBOX_WITH_WDDM
+    unsigned int i;
+#endif
+
+    if (!TlsFree(wined3d_context_tls_idx))
+    {
+        DWORD err = GetLastError();
+        ERR("Failed to free context TLS index, err %#x.\n", err);
+    }
+
+#ifndef VBOX_WITH_WDDM
+    for (i = 0; i < wndproc_table.count; ++i)
+    {
+        /* Trying to unregister these would be futile. These entries can only
+         * exist if either we skipped them in wined3d_unregister_window() due
+         * to the application replacing the wndproc after the entry was
+         * registered, or if the application still has an active wined3d
+         * device. In the latter case the application has bigger problems than
+         * these entries. */
+        WARN("Leftover wndproc table entry %p.\n", &wndproc_table.entries[i]);
+    }
+    HeapFree(GetProcessHeap(), 0, wndproc_table.entries);
+#endif
+
+    HeapFree(GetProcessHeap(), 0, wined3d_settings.logo);
+    UnregisterClassA(WINED3D_OPENGL_WINDOW_CLASS_NAME, hInstDLL);
+
+#ifndef VBOX_WITH_WDDM
+    DeleteCriticalSection(&wined3d_wndproc_cs);
+    DeleteCriticalSection(&wined3d_cs);
+#endif
+    return TRUE;
+}
+
+#ifndef VBOX_WITH_WDDM
+void WINAPI wined3d_mutex_lock(void)
+{
+    EnterCriticalSection(&wined3d_cs);
+}
+
+void WINAPI wined3d_mutex_unlock(void)
+{
+    LeaveCriticalSection(&wined3d_cs);
+}
+
+static void wined3d_wndproc_mutex_lock(void)
+{
+    EnterCriticalSection(&wined3d_wndproc_cs);
+}
+
+static void wined3d_wndproc_mutex_unlock(void)
+{
+    LeaveCriticalSection(&wined3d_wndproc_cs);
+}
+
+static struct wined3d_wndproc *wined3d_find_wndproc(HWND window)
+{
+    unsigned int i;
+
+    for (i = 0; i < wndproc_table.count; ++i)
+    {
+        if (wndproc_table.entries[i].window == window)
+        {
+            return &wndproc_table.entries[i];
+        }
+    }
+
+    return NULL;
+}
+
+static LRESULT CALLBACK wined3d_wndproc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
+{
+    struct wined3d_wndproc *entry;
+    struct wined3d_device *device;
+    BOOL unicode;
+    WNDPROC proc;
+
+    wined3d_wndproc_mutex_lock();
+    entry = wined3d_find_wndproc(window);
+
+    if (!entry)
+    {
+        wined3d_wndproc_mutex_unlock();
+        ERR("Window %p is not registered with wined3d.\n", window);
+        return DefWindowProcW(window, message, wparam, lparam);
+    }
+
+    device = entry->device;
+    unicode = entry->unicode;
+    proc = entry->proc;
+    wined3d_wndproc_mutex_unlock();
+
+    if (device)
+        return device_process_message(device, window, unicode, message, wparam, lparam, proc);
+    if (unicode)
+        return CallWindowProcW(proc, window, message, wparam, lparam);
+    return CallWindowProcA(proc, window, message, wparam, lparam);
+}
+
+BOOL wined3d_register_window(HWND window, struct wined3d_device *device)
+{
+    struct wined3d_wndproc *entry;
+
+    wined3d_wndproc_mutex_lock();
+
+    if (wined3d_find_wndproc(window))
+    {
+        wined3d_wndproc_mutex_unlock();
+        WARN("Window %p is already registered with wined3d.\n", window);
+        return TRUE;
+    }
+
+    if (wndproc_table.size == wndproc_table.count)
+    {
+        unsigned int new_size = max(1, wndproc_table.size * 2);
+        struct wined3d_wndproc *new_entries;
+
+        if (!wndproc_table.entries) new_entries = HeapAlloc(GetProcessHeap(), 0, new_size * sizeof(*new_entries));
+        else new_entries = HeapReAlloc(GetProcessHeap(), 0, wndproc_table.entries, new_size * sizeof(*new_entries));
+
+        if (!new_entries)
+        {
+            wined3d_wndproc_mutex_unlock();
+            ERR("Failed to grow table.\n");
+            return FALSE;
+        }
+
+        wndproc_table.entries = new_entries;
+        wndproc_table.size = new_size;
+    }
+
+    entry = &wndproc_table.entries[wndproc_table.count++];
+    entry->window = window;
+    entry->unicode = IsWindowUnicode(window);
+    /* Set a window proc that matches the window. Some applications (e.g. NoX)
+     * replace the window proc after we've set ours, and expect to be able to
+     * call the previous one (ours) directly, without using CallWindowProc(). */
+    if (entry->unicode)
+        entry->proc = (WNDPROC)SetWindowLongPtrW(window, GWLP_WNDPROC, (LONG_PTR)wined3d_wndproc);
+    else
+        entry->proc = (WNDPROC)SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)wined3d_wndproc);
+    entry->device = device;
+
+    wined3d_wndproc_mutex_unlock();
+
+    return TRUE;
+}
+
+void wined3d_unregister_window(HWND window)
+{
+    struct wined3d_wndproc *entry, *last;
+    LONG_PTR proc;
+
+    wined3d_wndproc_mutex_lock();
+
+    if (!(entry = wined3d_find_wndproc(window)))
+    {
+        wined3d_wndproc_mutex_unlock();
+        ERR("Window %p is not registered with wined3d.\n", window);
+        return;
+    }
+
+    if (entry->unicode)
+    {
+        proc = GetWindowLongPtrW(window, GWLP_WNDPROC);
+        if (proc != (LONG_PTR)wined3d_wndproc)
+        {
+            entry->device = NULL;
+            wined3d_wndproc_mutex_unlock();
+            WARN("Not unregistering window %p, window proc %#lx doesn't match wined3d window proc %p.\n",
+                    window, proc, wined3d_wndproc);
+            return;
+        }
+
+        SetWindowLongPtrW(window, GWLP_WNDPROC, (LONG_PTR)entry->proc);
+    }
+    else
+    {
+        proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
+        if (proc != (LONG_PTR)wined3d_wndproc)
+        {
+            entry->device = NULL;
+            wined3d_wndproc_mutex_unlock();
+            WARN("Not unregistering window %p, window proc %#lx doesn't match wined3d window proc %p.\n",
+                    window, proc, wined3d_wndproc);
+            return;
+        }
+
+        SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)entry->proc);
+    }
+
+    last = &wndproc_table.entries[--wndproc_table.count];
+    if (entry != last) *entry = *last;
+
+    wined3d_wndproc_mutex_unlock();
+}
+#endif
+/* At process attach */
+BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
+{
+    TRACE("WineD3D DLLMain Reason=%u\n", fdwReason);
+
+    switch (fdwReason)
+    {
+        case DLL_PROCESS_ATTACH:
+            return wined3d_dll_init(hInstDLL);
+
+        case DLL_PROCESS_DETACH:
+            if (lpv) break;
+            return wined3d_dll_destroy(hInstDLL);
+
+        case DLL_THREAD_DETACH:
+            if (!context_set_current(NULL))
+            {
+                ERR("Failed to clear current context.\n");
+            }
+            return TRUE;
+        }
+            return TRUE;
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/wined3d_private.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/wined3d_private.h	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/wined3d_private.h	(revision 46521)
@@ -0,0 +1,3147 @@
+/*
+ * Direct3D wine internal private include file
+ *
+ * Copyright 2002-2003 The wine-d3d team
+ * Copyright 2002-2003 Raphael Junqueira
+ * Copyright 2002-2003, 2004 Jason Edmeades
+ * Copyright 2005 Oliver Stieber
+ * Copyright 2006-2011, 2013 Stefan Dösinger for CodeWeavers
+ *
+ * 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_WINED3D_PRIVATE_H
+#define __WINE_WINED3D_PRIVATE_H
+
+#ifdef USE_WIN32_OPENGL
+#define WINE_GLAPI __stdcall
+#else
+#define WINE_GLAPI
+#endif
+
+#include <stdarg.h>
+#include <math.h>
+#include <limits.h>
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+#define COBJMACROS
+#ifndef VBOX_WINE_WITHOUT_LIBWINE
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "wingdi.h"
+#include "winuser.h"
+#else
+#include <windows.h>
+#ifndef DUMMYUNIONNAME1
+# define DUMMYUNIONNAME1 u1
+#endif
+#endif
+#include "wine/debug.h"
+#include "wine/unicode.h"
+
+#ifndef VBOX_WINE_WITHOUT_LIBWINE
+#include "objbase.h"
+#endif
+#include "wine/wined3d.h"
+#include "wined3d_gl.h"
+#include "wine/list.h"
+#include "wine/rbtree.h"
+#include "wine/wgl_driver.h"
+
+#ifdef VBOX
+#include "vboxext.h"
+#endif
+
+#ifdef VBOX_WITH_WDDM
+# include "vboxsharedrc.h"
+#endif
+
+#if defined(VBOX_WINE_WITH_SINGLE_CONTEXT) || defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
+# define VBoxTlsRefGetImpl(_tls) (TlsGetValue((DWORD)(_tls)))
+# define VBoxTlsRefSetImpl(_tls, _val) (TlsSetValue((DWORD)(_tls), (_val)))
+# define VBoxTlsRefAssertImpl Assert
+# include <VBox/VBoxVideo3D.h>
+#endif
+
+/* Driver quirks */
+#define WINED3D_QUIRK_ARB_VS_OFFSET_LIMIT       0x00000001
+#define WINED3D_QUIRK_SET_TEXCOORD_W            0x00000002
+#define WINED3D_QUIRK_GLSL_CLIP_VARYING         0x00000004
+#define WINED3D_QUIRK_ALLOWS_SPECULAR_ALPHA     0x00000008
+#define WINED3D_QUIRK_NV_CLIP_BROKEN            0x00000010
+#define WINED3D_QUIRK_FBO_TEX_UPDATE            0x00000020
+#define WINED3D_QUIRK_BROKEN_RGBA16             0x00000040
+#define WINED3D_QUIRK_INFO_LOG_SPAM             0x00000080
+#define WINED3D_QUIRK_LIMITED_TEX_FILTERING     0x00000100
+#ifdef VBOX_WITH_WINE_FIX_QUIRKS
+#define WINED3D_QUIRK_FULLSIZE_BLIT             0x02000000
+#define WINED3D_QUIRK_FORCE_BLIT                0x04000000
+#define WINED3D_QUIRK_NO_SHADER_V3              0x08000000
+#endif
+
+/* Texture format fixups */
+
+enum fixup_channel_source
+{
+    CHANNEL_SOURCE_ZERO = 0,
+    CHANNEL_SOURCE_ONE = 1,
+    CHANNEL_SOURCE_X = 2,
+    CHANNEL_SOURCE_Y = 3,
+    CHANNEL_SOURCE_Z = 4,
+    CHANNEL_SOURCE_W = 5,
+    CHANNEL_SOURCE_COMPLEX0 = 6,
+    CHANNEL_SOURCE_COMPLEX1 = 7,
+};
+
+enum complex_fixup
+{
+    COMPLEX_FIXUP_NONE = 0,
+    COMPLEX_FIXUP_YUY2 = 1,
+    COMPLEX_FIXUP_UYVY = 2,
+    COMPLEX_FIXUP_YV12 = 3,
+    COMPLEX_FIXUP_P8   = 4,
+};
+
+#include <pshpack2.h>
+struct color_fixup_desc
+{
+    unsigned x_sign_fixup : 1;
+    unsigned x_source : 3;
+    unsigned y_sign_fixup : 1;
+    unsigned y_source : 3;
+    unsigned z_sign_fixup : 1;
+    unsigned z_source : 3;
+    unsigned w_sign_fixup : 1;
+    unsigned w_source : 3;
+};
+#include <poppack.h>
+
+static const struct color_fixup_desc COLOR_FIXUP_IDENTITY =
+        {0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_Z, 0, CHANNEL_SOURCE_W};
+
+static inline struct color_fixup_desc create_color_fixup_desc(
+        int sign0, enum fixup_channel_source src0, int sign1, enum fixup_channel_source src1,
+        int sign2, enum fixup_channel_source src2, int sign3, enum fixup_channel_source src3)
+{
+    struct color_fixup_desc fixup =
+    {
+        sign0, src0,
+        sign1, src1,
+        sign2, src2,
+        sign3, src3,
+    };
+    return fixup;
+}
+
+static inline struct color_fixup_desc create_complex_fixup_desc(enum complex_fixup complex_fixup)
+{
+    struct color_fixup_desc fixup =
+    {
+        0, complex_fixup & (1 << 0) ? CHANNEL_SOURCE_COMPLEX1 : CHANNEL_SOURCE_COMPLEX0,
+        0, complex_fixup & (1 << 1) ? CHANNEL_SOURCE_COMPLEX1 : CHANNEL_SOURCE_COMPLEX0,
+        0, complex_fixup & (1 << 2) ? CHANNEL_SOURCE_COMPLEX1 : CHANNEL_SOURCE_COMPLEX0,
+        0, complex_fixup & (1 << 3) ? CHANNEL_SOURCE_COMPLEX1 : CHANNEL_SOURCE_COMPLEX0,
+    };
+    return fixup;
+}
+
+static inline BOOL is_identity_fixup(struct color_fixup_desc fixup)
+{
+    return !memcmp(&fixup, &COLOR_FIXUP_IDENTITY, sizeof(fixup));
+}
+
+static inline BOOL is_complex_fixup(struct color_fixup_desc fixup)
+{
+    return fixup.x_source == CHANNEL_SOURCE_COMPLEX0 || fixup.x_source == CHANNEL_SOURCE_COMPLEX1;
+}
+
+static inline enum complex_fixup get_complex_fixup(struct color_fixup_desc fixup)
+{
+    enum complex_fixup complex_fixup = 0;
+    if (fixup.x_source == CHANNEL_SOURCE_COMPLEX1) complex_fixup |= (1 << 0);
+    if (fixup.y_source == CHANNEL_SOURCE_COMPLEX1) complex_fixup |= (1 << 1);
+    if (fixup.z_source == CHANNEL_SOURCE_COMPLEX1) complex_fixup |= (1 << 2);
+    if (fixup.w_source == CHANNEL_SOURCE_COMPLEX1) complex_fixup |= (1 << 3);
+    return complex_fixup;
+}
+
+void *wined3d_rb_alloc(size_t size) DECLSPEC_HIDDEN;
+void *wined3d_rb_realloc(void *ptr, size_t size) DECLSPEC_HIDDEN;
+void wined3d_rb_free(void *ptr) DECLSPEC_HIDDEN;
+
+/* Device caps */
+#define MAX_PALETTES            65536
+#define MAX_STREAM_OUT          4
+#define MAX_STREAMS             16
+#define MAX_TEXTURES            8
+#define MAX_FRAGMENT_SAMPLERS   16
+#define MAX_VERTEX_SAMPLERS     4
+#define MAX_COMBINED_SAMPLERS   (MAX_FRAGMENT_SAMPLERS + MAX_VERTEX_SAMPLERS)
+#define MAX_ACTIVE_LIGHTS       8
+#define MAX_CLIPPLANES          WINED3DMAXUSERCLIPPLANES
+#define MAX_CONSTANT_BUFFERS    15
+#define MAX_SAMPLER_OBJECTS     16
+
+struct min_lookup
+{
+    GLenum mip[WINED3D_TEXF_LINEAR + 1];
+};
+
+extern const struct min_lookup minMipLookup[WINED3D_TEXF_LINEAR + 1] DECLSPEC_HIDDEN;
+extern const struct min_lookup minMipLookup_noFilter[WINED3D_TEXF_LINEAR + 1] DECLSPEC_HIDDEN;
+extern const struct min_lookup minMipLookup_noMip[WINED3D_TEXF_LINEAR + 1] DECLSPEC_HIDDEN;
+extern const GLenum magLookup[WINED3D_TEXF_LINEAR + 1] DECLSPEC_HIDDEN;
+extern const GLenum magLookup_noFilter[WINED3D_TEXF_LINEAR + 1] DECLSPEC_HIDDEN;
+
+static inline GLenum wined3d_gl_mag_filter(const GLenum mag_lookup[], enum wined3d_texture_filter_type mag_filter)
+{
+    return mag_lookup[mag_filter];
+}
+
+static inline GLenum wined3d_gl_min_mip_filter(const struct min_lookup min_mip_lookup[],
+        enum wined3d_texture_filter_type min_filter, enum wined3d_texture_filter_type mip_filter)
+{
+    return min_mip_lookup[min_filter].mip[mip_filter];
+}
+
+/* float_16_to_32() and float_32_to_16() (see implementation in
+ * surface_base.c) convert 16 bit floats in the FLOAT16 data type
+ * to standard C floats and vice versa. They do not depend on the encoding
+ * of the C float, so they are platform independent, but slow. On x86 and
+ * other IEEE 754 compliant platforms the conversion can be accelerated by
+ * bit shifting the exponent and mantissa. There are also some SSE-based
+ * assembly routines out there.
+ *
+ * See GL_NV_half_float for a reference of the FLOAT16 / GL_HALF format
+ */
+static inline float float_16_to_32(const unsigned short *in)
+{
+    const unsigned short s = ((*in) & 0x8000);
+    const unsigned short e = ((*in) & 0x7c00) >> 10;
+    const unsigned short m = (*in) & 0x3ff;
+    const float sgn = (s ? -1.0f : 1.0f);
+
+    if(e == 0) {
+        if(m == 0) return sgn * 0.0f; /* +0.0 or -0.0 */
+        else return sgn * powf(2, -14.0f) * ((float)m / 1024.0f);
+    } else if(e < 31) {
+        return sgn * powf(2, (float)e - 15.0f) * (1.0f + ((float)m / 1024.0f));
+    } else {
+        if(m == 0) return sgn * INFINITY;
+        else return NAN;
+    }
+}
+
+static inline float float_24_to_32(DWORD in)
+{
+    const float sgn = in & 0x800000 ? -1.0f : 1.0f;
+    const unsigned short e = (in & 0x780000) >> 19;
+    const unsigned int m = in & 0x7ffff;
+
+    if (e == 0)
+    {
+        if (m == 0) return sgn * 0.0f; /* +0.0 or -0.0 */
+        else return sgn * powf(2, -6.0f) * ((float)m / 524288.0f);
+    }
+    else if (e < 15)
+    {
+        return sgn * powf(2, (float)e - 7.0f) * (1.0f + ((float)m / 524288.0f));
+    }
+    else
+    {
+        if (m == 0) return sgn * INFINITY;
+        else return NAN;
+    }
+}
+
+#define ORM_BACKBUFFER  0
+#define ORM_FBO         1
+
+#define RTL_READDRAW   1
+#define RTL_READTEX    2
+
+#define PCI_VENDOR_NONE 0xffff /* e.g. 0x8086 for Intel and 0x10de for Nvidia */
+#define PCI_DEVICE_NONE 0xffff /* e.g. 0x14f for a Geforce6200 */
+
+/* NOTE: When adding fields to this structure, make sure to update the default
+ * values in wined3d_main.c as well. */
+struct wined3d_settings
+{
+    /* Ideally, we don't want the user to have to request GLSL. If the
+     * hardware supports GLSL, we should use it. However, until it's fully
+     * implemented, we'll leave it as a registry setting for developers. */
+    BOOL glslRequested;
+    int offscreen_rendering_mode;
+    int rendertargetlock_mode;
+    unsigned short pci_vendor_id;
+    unsigned short pci_device_id;
+    /* Memory tracking and object counting. */
+    unsigned int emulated_textureram;
+    char *logo;
+    int allow_multisampling;
+    BOOL strict_draw_ordering;
+    BOOL always_offscreen;
+    unsigned int max_sm_vs;
+    unsigned int max_sm_gs;
+    unsigned int max_sm_ps;
+    BOOL no_3d;
+};
+
+extern struct wined3d_settings wined3d_settings DECLSPEC_HIDDEN;
+
+enum wined3d_sampler_texture_type
+{
+    WINED3DSTT_UNKNOWN = 0,
+    WINED3DSTT_1D = 1,
+    WINED3DSTT_2D = 2,
+    WINED3DSTT_CUBE = 3,
+    WINED3DSTT_VOLUME = 4,
+};
+
+enum wined3d_shader_register_type
+{
+    WINED3DSPR_TEMP = 0,
+    WINED3DSPR_INPUT = 1,
+    WINED3DSPR_CONST = 2,
+    WINED3DSPR_ADDR = 3,
+    WINED3DSPR_TEXTURE = 3,
+    WINED3DSPR_RASTOUT = 4,
+    WINED3DSPR_ATTROUT = 5,
+    WINED3DSPR_TEXCRDOUT = 6,
+    WINED3DSPR_OUTPUT = 6,
+    WINED3DSPR_CONSTINT = 7,
+    WINED3DSPR_COLOROUT = 8,
+    WINED3DSPR_DEPTHOUT = 9,
+    WINED3DSPR_SAMPLER = 10,
+    WINED3DSPR_CONST2 = 11,
+    WINED3DSPR_CONST3 = 12,
+    WINED3DSPR_CONST4 = 13,
+    WINED3DSPR_CONSTBOOL = 14,
+    WINED3DSPR_LOOP = 15,
+    WINED3DSPR_TEMPFLOAT16 = 16,
+    WINED3DSPR_MISCTYPE = 17,
+    WINED3DSPR_LABEL = 18,
+    WINED3DSPR_PREDICATE = 19,
+    WINED3DSPR_IMMCONST,
+    WINED3DSPR_CONSTBUFFER,
+    WINED3DSPR_PRIMID,
+    WINED3DSPR_NULL,
+    WINED3DSPR_RESOURCE,
+};
+
+enum wined3d_data_type
+{
+    WINED3D_DATA_FLOAT,
+    WINED3D_DATA_INT,
+    WINED3D_DATA_RESOURCE,
+    WINED3D_DATA_SAMPLER,
+    WINED3D_DATA_UINT,
+};
+
+enum wined3d_immconst_type
+{
+    WINED3D_IMMCONST_SCALAR,
+    WINED3D_IMMCONST_VEC4,
+};
+
+#define WINED3DSP_NOSWIZZLE (0 | (1 << 2) | (2 << 4) | (3 << 6))
+
+enum wined3d_shader_src_modifier
+{
+    WINED3DSPSM_NONE = 0,
+    WINED3DSPSM_NEG = 1,
+    WINED3DSPSM_BIAS = 2,
+    WINED3DSPSM_BIASNEG = 3,
+    WINED3DSPSM_SIGN = 4,
+    WINED3DSPSM_SIGNNEG = 5,
+    WINED3DSPSM_COMP = 6,
+    WINED3DSPSM_X2 = 7,
+    WINED3DSPSM_X2NEG = 8,
+    WINED3DSPSM_DZ = 9,
+    WINED3DSPSM_DW = 10,
+    WINED3DSPSM_ABS = 11,
+    WINED3DSPSM_ABSNEG = 12,
+    WINED3DSPSM_NOT = 13,
+};
+
+#define WINED3DSP_WRITEMASK_0   0x1 /* .x r */
+#define WINED3DSP_WRITEMASK_1   0x2 /* .y g */
+#define WINED3DSP_WRITEMASK_2   0x4 /* .z b */
+#define WINED3DSP_WRITEMASK_3   0x8 /* .w a */
+#define WINED3DSP_WRITEMASK_ALL 0xf /* all */
+
+enum wined3d_shader_dst_modifier
+{
+    WINED3DSPDM_NONE = 0,
+    WINED3DSPDM_SATURATE = 1,
+    WINED3DSPDM_PARTIALPRECISION = 2,
+    WINED3DSPDM_MSAMPCENTROID = 4,
+};
+
+/* Undocumented opcode control to identify projective texture lookups in ps 2.0 and later */
+#define WINED3DSI_TEXLD_PROJECT     0x1
+#define WINED3DSI_TEXLD_BIAS        0x2
+#define WINED3DSI_INDEXED_DYNAMIC   0x4
+
+enum wined3d_shader_rel_op
+{
+    WINED3D_SHADER_REL_OP_GT = 1,
+    WINED3D_SHADER_REL_OP_EQ = 2,
+    WINED3D_SHADER_REL_OP_GE = 3,
+    WINED3D_SHADER_REL_OP_LT = 4,
+    WINED3D_SHADER_REL_OP_NE = 5,
+    WINED3D_SHADER_REL_OP_LE = 6,
+};
+
+#define WINED3D_SM1_VS  0xfffe
+#define WINED3D_SM1_PS  0xffff
+#define WINED3D_SM4_PS  0x0000
+#define WINED3D_SM4_VS  0x0001
+#define WINED3D_SM4_GS  0x0002
+
+/* Shader version tokens, and shader end tokens */
+#define WINED3DPS_VERSION(major, minor) ((WINED3D_SM1_PS << 16) | ((major) << 8) | (minor))
+#define WINED3DVS_VERSION(major, minor) ((WINED3D_SM1_VS << 16) | ((major) << 8) | (minor))
+
+/* Shader backends */
+
+/* TODO: Make this dynamic, based on shader limits ? */
+#define MAX_ATTRIBS 16
+#define MAX_REG_ADDR 1
+#define MAX_REG_TEMP 32
+#define MAX_REG_TEXCRD 8
+#define MAX_REG_INPUT 32
+#define MAX_REG_OUTPUT 32
+#define MAX_CONST_I 16
+#define MAX_CONST_B 16
+#define WINED3D_MAX_CBS 15
+
+/* FIXME: This needs to go up to 2048 for
+ * Shader model 3 according to msdn (and for software shaders) */
+#define MAX_LABELS 16
+
+#define SHADER_PGMSIZE 16384
+
+struct wined3d_shader_buffer
+{
+    char *buffer;
+    unsigned int buffer_size;
+    unsigned int content_size;
+    unsigned int lineNo;
+    BOOL newline;
+};
+
+enum WINED3D_SHADER_INSTRUCTION_HANDLER
+{
+    WINED3DSIH_ABS,
+    WINED3DSIH_ADD,
+    WINED3DSIH_AND,
+    WINED3DSIH_BEM,
+    WINED3DSIH_BREAK,
+    WINED3DSIH_BREAKC,
+    WINED3DSIH_BREAKP,
+    WINED3DSIH_CALL,
+    WINED3DSIH_CALLNZ,
+    WINED3DSIH_CMP,
+    WINED3DSIH_CND,
+    WINED3DSIH_CRS,
+    WINED3DSIH_CUT,
+    WINED3DSIH_DCL,
+    WINED3DSIH_DCL_CONSTANT_BUFFER,
+    WINED3DSIH_DCL_INPUT_PRIMITIVE,
+    WINED3DSIH_DCL_OUTPUT_TOPOLOGY,
+    WINED3DSIH_DCL_VERTICES_OUT,
+    WINED3DSIH_DEF,
+    WINED3DSIH_DEFB,
+    WINED3DSIH_DEFI,
+    WINED3DSIH_DIV,
+    WINED3DSIH_DP2ADD,
+    WINED3DSIH_DP3,
+    WINED3DSIH_DP4,
+    WINED3DSIH_DST,
+    WINED3DSIH_DSX,
+    WINED3DSIH_DSY,
+    WINED3DSIH_ELSE,
+    WINED3DSIH_EMIT,
+    WINED3DSIH_ENDIF,
+    WINED3DSIH_ENDLOOP,
+    WINED3DSIH_ENDREP,
+    WINED3DSIH_EQ,
+    WINED3DSIH_EXP,
+    WINED3DSIH_EXPP,
+    WINED3DSIH_FRC,
+    WINED3DSIH_FTOI,
+    WINED3DSIH_GE,
+    WINED3DSIH_IADD,
+    WINED3DSIH_IEQ,
+    WINED3DSIH_IF,
+    WINED3DSIH_IFC,
+    WINED3DSIH_IGE,
+    WINED3DSIH_IMUL,
+    WINED3DSIH_ITOF,
+    WINED3DSIH_LABEL,
+    WINED3DSIH_LD,
+    WINED3DSIH_LIT,
+    WINED3DSIH_LOG,
+    WINED3DSIH_LOGP,
+    WINED3DSIH_LOOP,
+    WINED3DSIH_LRP,
+    WINED3DSIH_LT,
+    WINED3DSIH_M3x2,
+    WINED3DSIH_M3x3,
+    WINED3DSIH_M3x4,
+    WINED3DSIH_M4x3,
+    WINED3DSIH_M4x4,
+    WINED3DSIH_MAD,
+    WINED3DSIH_MAX,
+    WINED3DSIH_MIN,
+    WINED3DSIH_MOV,
+    WINED3DSIH_MOVA,
+    WINED3DSIH_MOVC,
+    WINED3DSIH_MUL,
+    WINED3DSIH_NOP,
+    WINED3DSIH_NRM,
+    WINED3DSIH_PHASE,
+    WINED3DSIH_POW,
+    WINED3DSIH_RCP,
+    WINED3DSIH_REP,
+    WINED3DSIH_RET,
+    WINED3DSIH_ROUND_NI,
+    WINED3DSIH_RSQ,
+    WINED3DSIH_SAMPLE,
+    WINED3DSIH_SAMPLE_GRAD,
+    WINED3DSIH_SAMPLE_LOD,
+    WINED3DSIH_SETP,
+    WINED3DSIH_SGE,
+    WINED3DSIH_SGN,
+    WINED3DSIH_SINCOS,
+    WINED3DSIH_SLT,
+    WINED3DSIH_SQRT,
+    WINED3DSIH_SUB,
+    WINED3DSIH_TEX,
+    WINED3DSIH_TEXBEM,
+    WINED3DSIH_TEXBEML,
+    WINED3DSIH_TEXCOORD,
+    WINED3DSIH_TEXDEPTH,
+    WINED3DSIH_TEXDP3,
+    WINED3DSIH_TEXDP3TEX,
+    WINED3DSIH_TEXKILL,
+    WINED3DSIH_TEXLDD,
+    WINED3DSIH_TEXLDL,
+    WINED3DSIH_TEXM3x2DEPTH,
+    WINED3DSIH_TEXM3x2PAD,
+    WINED3DSIH_TEXM3x2TEX,
+    WINED3DSIH_TEXM3x3,
+    WINED3DSIH_TEXM3x3DIFF,
+    WINED3DSIH_TEXM3x3PAD,
+    WINED3DSIH_TEXM3x3SPEC,
+    WINED3DSIH_TEXM3x3TEX,
+    WINED3DSIH_TEXM3x3VSPEC,
+    WINED3DSIH_TEXREG2AR,
+    WINED3DSIH_TEXREG2GB,
+    WINED3DSIH_TEXREG2RGB,
+    WINED3DSIH_UDIV,
+    WINED3DSIH_USHR,
+    WINED3DSIH_UTOF,
+    WINED3DSIH_XOR,
+    WINED3DSIH_TABLE_SIZE
+};
+
+enum wined3d_shader_type
+{
+    WINED3D_SHADER_TYPE_PIXEL,
+    WINED3D_SHADER_TYPE_VERTEX,
+    WINED3D_SHADER_TYPE_GEOMETRY,
+};
+
+struct wined3d_shader_version
+{
+    enum wined3d_shader_type type;
+    BYTE major;
+    BYTE minor;
+};
+
+#define WINED3D_SHADER_VERSION(major, minor) (((major) << 8) | (minor))
+
+struct wined3d_shader_reg_maps
+{
+    struct wined3d_shader_version shader_version;
+    BYTE texcoord;                          /* MAX_REG_TEXCRD, 8 */
+    BYTE address;                           /* MAX_REG_ADDR, 1 */
+    WORD labels;                            /* MAX_LABELS, 16 */
+    DWORD temporary;                        /* MAX_REG_TEMP, 32 */
+    DWORD *constf;                          /* pixel, vertex */
+    DWORD texcoord_mask[MAX_REG_TEXCRD];    /* vertex < 3.0 */
+    DWORD input_registers;                  /* max(MAX_REG_INPUT, MAX_ATTRIBS), 32 */
+    DWORD output_registers;                 /* MAX_REG_OUTPUT, 32 */
+    WORD integer_constants;                 /* MAX_CONST_I, 16 */
+    WORD boolean_constants;                 /* MAX_CONST_B, 16 */
+    WORD local_int_consts;                  /* MAX_CONST_I, 16 */
+    WORD local_bool_consts;                 /* MAX_CONST_B, 16 */
+    UINT cb_sizes[WINED3D_MAX_CBS];
+
+    enum wined3d_sampler_texture_type sampler_type[max(MAX_FRAGMENT_SAMPLERS, MAX_VERTEX_SAMPLERS)];
+    BYTE bumpmat;                           /* MAX_TEXTURES, 8 */
+    BYTE luminanceparams;                   /* MAX_TEXTURES, 8 */
+
+    WORD usesnrm        : 1;
+    WORD vpos           : 1;
+    WORD usesdsx        : 1;
+    WORD usesdsy        : 1;
+    WORD usestexldd     : 1;
+    WORD usesmova       : 1;
+    WORD usesfacing     : 1;
+    WORD usesrelconstF  : 1;
+    WORD fog            : 1;
+    WORD usestexldl     : 1;
+    WORD usesifc        : 1;
+    WORD usescall       : 1;
+    WORD usespow        : 1;
+    WORD padding        : 3;
+
+    DWORD rt_mask; /* Used render targets, 32 max. */
+
+    /* Whether or not loops are used in this shader, and nesting depth */
+    unsigned loop_depth;
+    UINT min_rel_offset, max_rel_offset;
+};
+
+/* Keeps track of details for TEX_M#x# instructions which need to maintain
+ * state information between multiple instructions. */
+struct wined3d_shader_tex_mx
+{
+    unsigned int current_row;
+    DWORD texcoord_w[2];
+};
+
+struct wined3d_shader_loop_state
+{
+    UINT current_depth;
+    UINT current_reg;
+};
+
+struct wined3d_shader_context
+{
+    const struct wined3d_shader *shader;
+    const struct wined3d_gl_info *gl_info;
+    const struct wined3d_shader_reg_maps *reg_maps;
+    struct wined3d_shader_buffer *buffer;
+    struct wined3d_shader_tex_mx *tex_mx;
+    struct wined3d_shader_loop_state *loop_state;
+    void *backend_data;
+};
+
+struct wined3d_shader_register_index
+{
+    const struct wined3d_shader_src_param *rel_addr;
+    unsigned int offset;
+};
+
+struct wined3d_shader_register
+{
+    enum wined3d_shader_register_type type;
+    enum wined3d_data_type data_type;
+    struct wined3d_shader_register_index idx[2];
+    enum wined3d_immconst_type immconst_type;
+    DWORD immconst_data[4];
+};
+
+struct wined3d_shader_dst_param
+{
+    struct wined3d_shader_register reg;
+    DWORD write_mask;
+    DWORD modifiers;
+    DWORD shift;
+};
+
+struct wined3d_shader_src_param
+{
+    struct wined3d_shader_register reg;
+    DWORD swizzle;
+    enum wined3d_shader_src_modifier modifiers;
+};
+
+struct wined3d_shader_semantic
+{
+    enum wined3d_decl_usage usage;
+    UINT usage_idx;
+    enum wined3d_sampler_texture_type sampler_type;
+    struct wined3d_shader_dst_param reg;
+};
+
+struct wined3d_shader_instruction
+{
+    const struct wined3d_shader_context *ctx;
+    enum WINED3D_SHADER_INSTRUCTION_HANDLER handler_idx;
+    DWORD flags;
+    BOOL coissue;
+    const struct wined3d_shader_src_param *predicate;
+    UINT dst_count;
+    const struct wined3d_shader_dst_param *dst;
+    UINT src_count;
+    const struct wined3d_shader_src_param *src;
+    union
+    {
+        struct wined3d_shader_semantic semantic;
+        enum wined3d_primitive_type primitive_type;
+        struct wined3d_shader_src_param src;
+        UINT count;
+    } declaration;
+};
+
+struct wined3d_shader_attribute
+{
+    enum wined3d_decl_usage usage;
+    UINT usage_idx;
+};
+
+struct wined3d_shader_loop_control
+{
+    unsigned int count;
+    unsigned int start;
+    int step;
+};
+
+struct wined3d_shader_frontend
+{
+    void *(*shader_init)(const DWORD *ptr, const struct wined3d_shader_signature *output_signature);
+    void (*shader_free)(void *data);
+    void (*shader_read_header)(void *data, const DWORD **ptr, struct wined3d_shader_version *shader_version);
+    void (*shader_read_instruction)(void *data, const DWORD **ptr, struct wined3d_shader_instruction *ins);
+    BOOL (*shader_is_end)(void *data, const DWORD **ptr);
+};
+
+extern const struct wined3d_shader_frontend sm1_shader_frontend DECLSPEC_HIDDEN;
+extern const struct wined3d_shader_frontend sm4_shader_frontend DECLSPEC_HIDDEN;
+
+typedef void (*SHADER_HANDLER)(const struct wined3d_shader_instruction *);
+
+#define WINED3D_SHADER_CAP_VS_CLIPPING      0x00000001
+#define WINED3D_SHADER_CAP_SRGB_WRITE       0x00000002
+
+struct shader_caps
+{
+    UINT vs_version;
+    UINT gs_version;
+    UINT ps_version;
+
+    DWORD vs_uniform_count;
+    DWORD ps_uniform_count;
+    float ps_1x_max_value;
+
+    DWORD wined3d_caps;
+};
+
+enum tex_types
+{
+    tex_1d       = 0,
+    tex_2d       = 1,
+    tex_3d       = 2,
+    tex_cube     = 3,
+    tex_rect     = 4,
+    tex_type_count = 5,
+};
+
+enum vertexprocessing_mode {
+    fixedfunction,
+    vertexshader,
+    pretransformed
+};
+
+#define WINED3D_CONST_NUM_UNUSED ~0U
+
+enum wined3d_ffp_ps_fog_mode
+{
+    WINED3D_FFP_PS_FOG_OFF,
+    WINED3D_FFP_PS_FOG_LINEAR,
+    WINED3D_FFP_PS_FOG_EXP,
+    WINED3D_FFP_PS_FOG_EXP2,
+};
+
+/* Stateblock dependent parameters which have to be hardcoded
+ * into the shader code
+ */
+
+#define WINED3D_PSARGS_PROJECTED (1 << 3)
+#define WINED3D_PSARGS_TEXTRANSFORM_SHIFT 4
+#define WINED3D_PSARGS_TEXTRANSFORM_MASK 0xf
+#define WINED3D_PSARGS_TEXTYPE_SHIFT 2
+#define WINED3D_PSARGS_TEXTYPE_MASK 0x3
+
+/* Similar to tex_types, except that it doesn't have 1d textures
+ * (can't be bound), rect textures (handled via np2_fixup) and
+ * none / unknown (treated as 2d and handled via dummy textures). */
+enum wined3d_shader_tex_types
+{
+    WINED3D_SHADER_TEX_2D   = 0,
+    WINED3D_SHADER_TEX_3D   = 1,
+    WINED3D_SHADER_TEX_CUBE = 2,
+};
+
+struct ps_compile_args {
+    struct color_fixup_desc     color_fixup[MAX_FRAGMENT_SAMPLERS];
+    enum vertexprocessing_mode  vp_mode;
+    enum wined3d_ffp_ps_fog_mode fog;
+    WORD                        tex_transform; /* ps 1.0-1.3, 4 textures */
+    WORD                        tex_types; /* ps 1.0 - 1.4, 6 textures */
+    WORD                        srgb_correction;
+    WORD                        np2_fixup;
+    /* Bitmap for NP2 texcoord fixups (16 samplers max currently).
+       D3D9 has a limit of 16 samplers and the fixup is superfluous
+       in D3D10 (unconditional NP2 support mandatory). */
+    WORD shadow; /* MAX_FRAGMENT_SAMPLERS, 16 */
+};
+
+enum fog_src_type {
+    VS_FOG_Z        = 0,
+    VS_FOG_COORD    = 1
+};
+
+struct vs_compile_args {
+    BYTE                        fog_src;
+    BYTE                        clip_enabled;
+    WORD                        swizzle_map;   /* MAX_ATTRIBS, 16 */
+};
+
+struct wined3d_context;
+struct wined3d_state;
+struct fragment_pipeline;
+struct wined3d_vertex_pipe_ops;
+
+struct wined3d_shader_backend_ops
+{
+    void (*shader_handle_instruction)(const struct wined3d_shader_instruction *);
+    void (*shader_select)(void *shader_priv, const struct wined3d_context *context,
+            const struct wined3d_state *state);
+    void (*shader_disable)(void *shader_priv, const struct wined3d_context *context);
+    void (*shader_select_depth_blt)(void *shader_priv, const struct wined3d_gl_info *gl_info,
+            enum tex_types tex_type, const SIZE *ds_mask_size);
+    void (*shader_deselect_depth_blt)(void *shader_priv, const struct wined3d_gl_info *gl_info);
+    void (*shader_update_float_vertex_constants)(struct wined3d_device *device, UINT start, UINT count);
+    void (*shader_update_float_pixel_constants)(struct wined3d_device *device, UINT start, UINT count);
+    void (*shader_load_constants)(void *shader_priv, const struct wined3d_context *context,
+            const struct wined3d_state *state);
+    void (*shader_load_np2fixup_constants)(void *shader_priv, const struct wined3d_gl_info *gl_info,
+            const struct wined3d_state *state);
+    void (*shader_destroy)(struct wined3d_shader *shader);
+    HRESULT (*shader_alloc_private)(struct wined3d_device *device, const struct wined3d_vertex_pipe_ops *vertex_pipe,
+            const struct fragment_pipeline *fragment_pipe);
+    void (*shader_free_private)(struct wined3d_device *device);
+    void (*shader_context_destroyed)(void *shader_priv, const struct wined3d_context *context);
+    void (*shader_get_caps)(const struct wined3d_gl_info *gl_info, struct shader_caps *caps);
+    BOOL (*shader_color_fixup_supported)(struct color_fixup_desc fixup);
+    BOOL (*shader_has_ffp_proj_control)(void *shader_priv);
+};
+
+extern const struct wined3d_shader_backend_ops glsl_shader_backend DECLSPEC_HIDDEN;
+extern const struct wined3d_shader_backend_ops arb_program_shader_backend DECLSPEC_HIDDEN;
+extern const struct wined3d_shader_backend_ops none_shader_backend DECLSPEC_HIDDEN;
+
+#define GL_EXTCALL(f) (gl_info->gl_ops.ext.p_##f)
+
+#define D3DCOLOR_B_R(dw) (((dw) >> 16) & 0xff)
+#define D3DCOLOR_B_G(dw) (((dw) >>  8) & 0xff)
+#define D3DCOLOR_B_B(dw) (((dw) >>  0) & 0xff)
+#define D3DCOLOR_B_A(dw) (((dw) >> 24) & 0xff)
+
+#define D3DCOLOR_R(dw) (((float) (((dw) >> 16) & 0xff)) / 255.0f)
+#define D3DCOLOR_G(dw) (((float) (((dw) >>  8) & 0xff)) / 255.0f)
+#define D3DCOLOR_B(dw) (((float) (((dw) >>  0) & 0xff)) / 255.0f)
+#define D3DCOLOR_A(dw) (((float) (((dw) >> 24) & 0xff)) / 255.0f)
+
+#define D3DCOLORTOGLFLOAT4(dw, vec) do { \
+  (vec)[0] = D3DCOLOR_R(dw); \
+  (vec)[1] = D3DCOLOR_G(dw); \
+  (vec)[2] = D3DCOLOR_B(dw); \
+  (vec)[3] = D3DCOLOR_A(dw); \
+} while(0)
+
+#define HIGHEST_TRANSFORMSTATE WINED3D_TS_WORLD_MATRIX(255) /* Highest value in wined3d_transform_state. */
+
+/* Checking of API calls */
+/* --------------------- */
+#ifndef WINE_NO_DEBUG_MSGS
+#define checkGLcall(A)                                              \
+do {                                                                \
+    GLint err;                                                      \
+    if (!__WINE_IS_DEBUG_ON(_ERR, __wine_dbch___default)) break;    \
+    err = gl_info->gl_ops.gl.p_glGetError();                        \
+    /* #ifdef VBOX */                                               \
+    if (!wglGetCurrentContext())                                    \
+    {                                                               \
+        ERR(">>>>>>>>>>>>>>>>> NULL ctx issuing %s @ %s / %d\n",    \
+            A, __FILE__, __LINE__);                                 \
+        break;                                                      \
+    }                                                               \
+    /*#endif*/                                                      \
+    if (err == GL_NO_ERROR) {                                       \
+       TRACE("%s call ok %s / %d\n", A, __FILE__, __LINE__);        \
+                                                                    \
+    } else do {                                                     \
+        ERR(">>>>>>>>>>>>>>>>> %s (%#x) from %s @ %s / %d\n",       \
+            debug_glerror(err), err, A, __FILE__, __LINE__);        \
+       err = gl_info->gl_ops.gl.p_glGetError();                     \
+    } while (err != GL_NO_ERROR);                                   \
+} while(0)
+#else
+#define checkGLcall(A) do {} while(0)
+#endif
+
+enum wined3d_ffp_idx
+{
+    WINED3D_FFP_POSITION = 0,
+    WINED3D_FFP_BLENDWEIGHT = 1,
+    WINED3D_FFP_BLENDINDICES = 2,
+    WINED3D_FFP_NORMAL = 3,
+    WINED3D_FFP_PSIZE = 4,
+    WINED3D_FFP_DIFFUSE = 5,
+    WINED3D_FFP_SPECULAR = 6,
+    WINED3D_FFP_TEXCOORD0 = 7,
+    WINED3D_FFP_TEXCOORD1 = 8,
+    WINED3D_FFP_TEXCOORD2 = 9,
+    WINED3D_FFP_TEXCOORD3 = 10,
+    WINED3D_FFP_TEXCOORD4 = 11,
+    WINED3D_FFP_TEXCOORD5 = 12,
+    WINED3D_FFP_TEXCOORD6 = 13,
+    WINED3D_FFP_TEXCOORD7 = 14,
+};
+
+enum wined3d_ffp_emit_idx
+{
+    WINED3D_FFP_EMIT_FLOAT1 = 0,
+    WINED3D_FFP_EMIT_FLOAT2 = 1,
+    WINED3D_FFP_EMIT_FLOAT3 = 2,
+    WINED3D_FFP_EMIT_FLOAT4 = 3,
+    WINED3D_FFP_EMIT_D3DCOLOR = 4,
+    WINED3D_FFP_EMIT_UBYTE4 = 5,
+    WINED3D_FFP_EMIT_SHORT2 = 6,
+    WINED3D_FFP_EMIT_SHORT4 = 7,
+    WINED3D_FFP_EMIT_UBYTE4N = 8,
+    WINED3D_FFP_EMIT_SHORT2N = 9,
+    WINED3D_FFP_EMIT_SHORT4N = 10,
+    WINED3D_FFP_EMIT_USHORT2N = 11,
+    WINED3D_FFP_EMIT_USHORT4N = 12,
+    WINED3D_FFP_EMIT_UDEC3 = 13,
+    WINED3D_FFP_EMIT_DEC3N = 14,
+    WINED3D_FFP_EMIT_FLOAT16_2 = 15,
+    WINED3D_FFP_EMIT_FLOAT16_4 = 16,
+    WINED3D_FFP_EMIT_INVALID = 17,
+    WINED3D_FFP_EMIT_COUNT = 18
+};
+
+struct wined3d_bo_address
+{
+    GLuint buffer_object;
+    const BYTE *addr;
+};
+
+struct wined3d_stream_info_element
+{
+    const struct wined3d_format *format;
+    struct wined3d_bo_address data;
+#ifdef VBOX_WITH_WINE_FIX_BUFOFFSET
+    UINT offset;
+#endif
+    GLsizei stride;
+    UINT stream_idx;
+};
+
+struct wined3d_stream_info
+{
+    struct wined3d_stream_info_element elements[MAX_ATTRIBS];
+    DWORD position_transformed : 1;
+    DWORD all_vbo : 1;
+    WORD swizzle_map; /* MAX_ATTRIBS, 16 */
+    WORD use_map; /* MAX_ATTRIBS, 16 */
+};
+
+void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_count,
+        UINT start_instance, UINT instance_count, BOOL indexed) DECLSPEC_HIDDEN;
+DWORD get_flexible_vertex_size(DWORD d3dvtVertexType) DECLSPEC_HIDDEN;
+
+typedef void (WINE_GLAPI *glAttribFunc)(const void *data);
+typedef void (WINE_GLAPI *glMultiTexCoordFunc)(GLenum unit, const void *data);
+extern glAttribFunc position_funcs[WINED3D_FFP_EMIT_COUNT] DECLSPEC_HIDDEN;
+extern glAttribFunc diffuse_funcs[WINED3D_FFP_EMIT_COUNT] DECLSPEC_HIDDEN;
+extern glAttribFunc specular_func_3ubv DECLSPEC_HIDDEN;
+extern glAttribFunc specular_funcs[WINED3D_FFP_EMIT_COUNT] DECLSPEC_HIDDEN;
+extern glAttribFunc normal_funcs[WINED3D_FFP_EMIT_COUNT] DECLSPEC_HIDDEN;
+extern glMultiTexCoordFunc multi_texcoord_funcs[WINED3D_FFP_EMIT_COUNT] DECLSPEC_HIDDEN;
+
+#define eps 1e-8
+
+#define GET_TEXCOORD_SIZE_FROM_FVF(d3dvtVertexType, tex_num) \
+    (((((d3dvtVertexType) >> (16 + (2 * (tex_num)))) + 1) & 0x03) + 1)
+
+/* Routines and structures related to state management */
+
+#define STATE_RENDER(a) (a)
+#define STATE_IS_RENDER(a) ((a) >= STATE_RENDER(1) && (a) <= STATE_RENDER(WINEHIGHEST_RENDER_STATE))
+
+#define STATE_TEXTURESTAGE(stage, num) (STATE_RENDER(WINEHIGHEST_RENDER_STATE) + 1 + (stage) * (WINED3D_HIGHEST_TEXTURE_STATE + 1) + (num))
+#define STATE_IS_TEXTURESTAGE(a) ((a) >= STATE_TEXTURESTAGE(0, 1) && (a) <= STATE_TEXTURESTAGE(MAX_TEXTURES - 1, WINED3D_HIGHEST_TEXTURE_STATE))
+
+/* + 1 because samplers start with 0 */
+#define STATE_SAMPLER(num) (STATE_TEXTURESTAGE(MAX_TEXTURES - 1, WINED3D_HIGHEST_TEXTURE_STATE) + 1 + (num))
+#define STATE_IS_SAMPLER(num) ((num) >= STATE_SAMPLER(0) && (num) <= STATE_SAMPLER(MAX_COMBINED_SAMPLERS - 1))
+
+#define STATE_PIXELSHADER (STATE_SAMPLER(MAX_COMBINED_SAMPLERS - 1) + 1)
+#define STATE_IS_PIXELSHADER(a) ((a) == STATE_PIXELSHADER)
+
+#define STATE_TRANSFORM(a) (STATE_PIXELSHADER + (a))
+#define STATE_IS_TRANSFORM(a) ((a) >= STATE_TRANSFORM(1) && (a) <= STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(255)))
+
+#define STATE_STREAMSRC (STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(255)) + 1)
+#define STATE_IS_STREAMSRC(a) ((a) == STATE_STREAMSRC)
+#define STATE_INDEXBUFFER (STATE_STREAMSRC + 1)
+#define STATE_IS_INDEXBUFFER(a) ((a) == STATE_INDEXBUFFER)
+
+#define STATE_VDECL (STATE_INDEXBUFFER + 1)
+#define STATE_IS_VDECL(a) ((a) == STATE_VDECL)
+
+#define STATE_VSHADER (STATE_VDECL + 1)
+#define STATE_IS_VSHADER(a) ((a) == STATE_VSHADER)
+
+#define STATE_GEOMETRY_SHADER (STATE_VSHADER + 1)
+#define STATE_IS_GEOMETRY_SHADER(a) ((a) == STATE_GEOMETRY_SHADER)
+
+#define STATE_VIEWPORT (STATE_GEOMETRY_SHADER + 1)
+#define STATE_IS_VIEWPORT(a) ((a) == STATE_VIEWPORT)
+
+#define STATE_VERTEXSHADERCONSTANT (STATE_VIEWPORT + 1)
+#define STATE_PIXELSHADERCONSTANT (STATE_VERTEXSHADERCONSTANT + 1)
+#define STATE_IS_VERTEXSHADERCONSTANT(a) ((a) == STATE_VERTEXSHADERCONSTANT)
+#define STATE_IS_PIXELSHADERCONSTANT(a) ((a) == STATE_PIXELSHADERCONSTANT)
+
+#define STATE_LIGHT_TYPE (STATE_PIXELSHADERCONSTANT + 1)
+#define STATE_IS_LIGHT_TYPE(a) ((a) == STATE_LIGHT_TYPE)
+#define STATE_ACTIVELIGHT(a) (STATE_LIGHT_TYPE + 1 + (a))
+#define STATE_IS_ACTIVELIGHT(a) ((a) >= STATE_ACTIVELIGHT(0) && (a) < STATE_ACTIVELIGHT(MAX_ACTIVE_LIGHTS))
+
+#define STATE_SCISSORRECT (STATE_ACTIVELIGHT(MAX_ACTIVE_LIGHTS - 1) + 1)
+#define STATE_IS_SCISSORRECT(a) ((a) == STATE_SCISSORRECT)
+
+#define STATE_CLIPPLANE(a) (STATE_SCISSORRECT + 1 + (a))
+#define STATE_IS_CLIPPLANE(a) ((a) >= STATE_CLIPPLANE(0) && (a) <= STATE_CLIPPLANE(MAX_CLIPPLANES - 1))
+
+#define STATE_MATERIAL (STATE_CLIPPLANE(MAX_CLIPPLANES))
+#define STATE_IS_MATERIAL(a) ((a) == STATE_MATERIAL)
+
+#define STATE_FRONTFACE (STATE_MATERIAL + 1)
+#define STATE_IS_FRONTFACE(a) ((a) == STATE_FRONTFACE)
+
+#define STATE_POINTSPRITECOORDORIGIN  (STATE_FRONTFACE + 1)
+#define STATE_IS_POINTSPRITECOORDORIGIN(a) ((a) == STATE_POINTSPRITECOORDORIGIN)
+
+#define STATE_BASEVERTEXINDEX  (STATE_POINTSPRITECOORDORIGIN + 1)
+#define STATE_IS_BASEVERTEXINDEX(a) ((a) == STATE_BASEVERTEXINDEX)
+
+#define STATE_FRAMEBUFFER (STATE_BASEVERTEXINDEX + 1)
+#define STATE_IS_FRAMEBUFFER(a) ((a) == STATE_FRAMEBUFFER)
+
+#define STATE_POINT_SIZE_ENABLE (STATE_FRAMEBUFFER + 1)
+#define STATE_IS_POINT_SIZE_ENABLE(a) ((a) == STATE_POINT_SIZE_ENABLE)
+
+#define STATE_HIGHEST (STATE_POINT_SIZE_ENABLE)
+
+enum fogsource {
+    FOGSOURCE_FFP,
+    FOGSOURCE_VS,
+    FOGSOURCE_COORD,
+};
+
+#define WINED3D_MAX_FBO_ENTRIES 64
+
+struct wined3d_occlusion_query
+{
+    struct list entry;
+    GLuint id;
+    struct wined3d_context *context;
+};
+
+union wined3d_gl_query_object
+{
+    GLuint id;
+    GLsync sync;
+};
+
+struct wined3d_event_query
+{
+    struct list entry;
+    union wined3d_gl_query_object object;
+    struct wined3d_context *context;
+};
+
+enum wined3d_event_query_result
+{
+    WINED3D_EVENT_QUERY_OK,
+    WINED3D_EVENT_QUERY_WAITING,
+    WINED3D_EVENT_QUERY_NOT_STARTED,
+    WINED3D_EVENT_QUERY_WRONG_THREAD,
+    WINED3D_EVENT_QUERY_ERROR
+};
+
+void wined3d_event_query_destroy(struct wined3d_event_query *query) DECLSPEC_HIDDEN;
+enum wined3d_event_query_result wined3d_event_query_finish(const struct wined3d_event_query *query,
+        const struct wined3d_device *device) DECLSPEC_HIDDEN;
+void wined3d_event_query_issue(struct wined3d_event_query *query, const struct wined3d_device *device) DECLSPEC_HIDDEN;
+BOOL wined3d_event_query_supported(const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN;
+
+struct wined3d_context
+{
+    const struct wined3d_gl_info *gl_info;
+    const struct wined3d_d3d_info *d3d_info;
+    const struct StateEntry *state_table;
+    /* State dirtification
+     * dirtyArray is an array that contains markers for dirty states. numDirtyEntries states are dirty, their numbers are in indices
+     * 0...numDirtyEntries - 1. isStateDirty is a redundant copy of the dirtyArray. Technically only one of them would be needed,
+     * but with the help of both it is easy to find out if a state is dirty(just check the array index), and for applying dirty states
+     * only numDirtyEntries array elements have to be checked, not STATE_HIGHEST states.
+     */
+    DWORD                   dirtyArray[STATE_HIGHEST + 1]; /* Won't get bigger than that, a state is never marked dirty 2 times */
+    DWORD                   numDirtyEntries;
+    DWORD isStateDirty[STATE_HIGHEST / (sizeof(DWORD) * CHAR_BIT) + 1]; /* Bitmap to find out quickly if a state is dirty */
+
+    struct wined3d_swapchain *swapchain;
+
+    struct wined3d_surface *current_rt;
+    DWORD                   tid;    /* Thread ID which owns this context at the moment */
+
+    /* Stores some information about the context state for optimization */
+    DWORD render_offscreen : 1;
+    DWORD last_was_rhw : 1;             /* true iff last draw_primitive was in xyzrhw mode */
+    DWORD last_was_pshader : 1;
+    DWORD last_was_vshader : 1;
+    DWORD namedArraysLoaded : 1;
+    DWORD numberedArraysLoaded : 1;
+    DWORD last_was_blit : 1;
+    DWORD last_was_ckey : 1;
+    DWORD fog_coord : 1;
+    DWORD fog_enabled : 1;
+    DWORD num_untracked_materials : 2;  /* Max value 2 */
+    DWORD current : 1;
+#if !defined(VBOX_WINE_WITH_SINGLE_CONTEXT) && !defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
+    DWORD destroyed : 1;
+#endif
+    DWORD valid : 1;
+    DWORD select_shader : 1;
+    DWORD load_constants : 1;
+#if !defined(VBOX_WINE_WITH_SINGLE_CONTEXT) && !defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
+    DWORD padding : 15;
+#else
+    DWORD padding : 16;
+#endif
+
+    BYTE texShaderBumpMap;              /* MAX_TEXTURES, 8 */
+    BYTE lastWasPow2Texture;            /* MAX_TEXTURES, 8 */
+    DWORD                   numbered_array_mask;
+    GLenum                  tracking_parm;     /* Which source is tracking current colour         */
+    GLenum                  untracked_materials[2];
+    UINT                    blit_w, blit_h;
+    enum fogsource          fog_source;
+    DWORD active_texture;
+    DWORD texture_type[MAX_COMBINED_SAMPLERS];
+
+    /* The actual opengl context */
+    UINT level;
+    HGLRC restore_ctx;
+    HDC restore_dc;
+    int restore_pf;
+    HGLRC                   glCtx;
+#ifndef VBOX_WINE_WITH_SINGLE_CONTEXT
+    HWND                    win_handle;
+    HDC                     hdc;
+#else
+    struct wined3d_device *device;
+#endif
+
+#if defined(VBOX_WINE_WITH_SINGLE_CONTEXT) || defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
+    VBOXTLSREFDATA
+#endif
+
+    int pixel_format;
+    GLint                   aux_buffers;
+
+    /* FBOs */
+    UINT                    fbo_entry_count;
+    struct list             fbo_list;
+    struct list             fbo_destroy_list;
+    struct fbo_entry        *current_fbo;
+    GLuint                  fbo_read_binding;
+    GLuint                  fbo_draw_binding;
+    BOOL rebind_fbo;
+    struct wined3d_surface **blit_targets;
+    GLenum *draw_buffers;
+    DWORD draw_buffers_mask; /* Enabled draw buffers, 31 max. */
+
+    /* Queries */
+    GLuint *free_occlusion_queries;
+    UINT free_occlusion_query_size;
+    UINT free_occlusion_query_count;
+    struct list occlusion_queries;
+
+    union wined3d_gl_query_object *free_event_queries;
+    UINT free_event_query_size;
+    UINT free_event_query_count;
+    struct list event_queries;
+
+    /* Extension emulation */
+    GLint                   gl_fog_source;
+    GLfloat                 fog_coord_value;
+    GLfloat                 color[4], fogstart, fogend, fogcolor[4];
+    GLuint                  dummy_arbfp_prog;
+};
+
+struct wined3d_fb_state
+{
+    struct wined3d_surface **render_targets;
+    struct wined3d_surface *depth_stencil;
+};
+
+typedef void (*APPLYSTATEFUNC)(struct wined3d_context *ctx, const struct wined3d_state *state, DWORD state_id);
+
+struct StateEntry
+{
+    DWORD representative;
+    APPLYSTATEFUNC apply;
+};
+
+struct StateEntryTemplate
+{
+    DWORD state;
+    struct StateEntry content;
+    enum wined3d_gl_extension extension;
+};
+
+#define WINED3D_FRAGMENT_CAP_PROJ_CONTROL   0x00000001
+#define WINED3D_FRAGMENT_CAP_SRGB_WRITE     0x00000002
+
+struct fragment_caps
+{
+    DWORD wined3d_caps;
+    DWORD PrimitiveMiscCaps;
+    DWORD TextureOpCaps;
+    DWORD MaxTextureBlendStages;
+    DWORD MaxSimultaneousTextures;
+};
+
+struct fragment_pipeline
+{
+    void (*enable_extension)(const struct wined3d_gl_info *gl_info, BOOL enable);
+    void (*get_caps)(const struct wined3d_gl_info *gl_info, struct fragment_caps *caps);
+    void *(*alloc_private)(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv);
+    void (*free_private)(struct wined3d_device *device);
+    BOOL (*color_fixup_supported)(struct color_fixup_desc fixup);
+    const struct StateEntryTemplate *states;
+};
+
+struct wined3d_vertex_caps
+{
+    DWORD max_active_lights;
+    DWORD max_vertex_blend_matrices;
+    DWORD max_vertex_blend_matrix_index;
+    DWORD vertex_processing_caps;
+    DWORD fvf_caps;
+    DWORD max_user_clip_planes;
+    DWORD raster_caps;
+};
+
+struct wined3d_vertex_pipe_ops
+{
+    void (*vp_enable)(const struct wined3d_gl_info *gl_info, BOOL enable);
+    void (*vp_get_caps)(const struct wined3d_gl_info *gl_info, struct wined3d_vertex_caps *caps);
+    void *(*vp_alloc)(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv);
+    void (*vp_free)(struct wined3d_device *device);
+    const struct StateEntryTemplate *vp_states;
+};
+
+extern const struct StateEntryTemplate misc_state_template[] DECLSPEC_HIDDEN;
+extern const struct fragment_pipeline none_fragment_pipe DECLSPEC_HIDDEN;
+extern const struct fragment_pipeline ffp_fragment_pipeline DECLSPEC_HIDDEN;
+extern const struct fragment_pipeline atifs_fragment_pipeline DECLSPEC_HIDDEN;
+extern const struct fragment_pipeline arbfp_fragment_pipeline DECLSPEC_HIDDEN;
+extern const struct fragment_pipeline nvts_fragment_pipeline DECLSPEC_HIDDEN;
+extern const struct fragment_pipeline nvrc_fragment_pipeline DECLSPEC_HIDDEN;
+extern const struct fragment_pipeline glsl_fragment_pipe DECLSPEC_HIDDEN;
+
+extern const struct wined3d_vertex_pipe_ops none_vertex_pipe DECLSPEC_HIDDEN;
+extern const struct wined3d_vertex_pipe_ops ffp_vertex_pipe DECLSPEC_HIDDEN;
+extern const struct wined3d_vertex_pipe_ops glsl_vertex_pipe DECLSPEC_HIDDEN;
+
+/* "Base" state table */
+HRESULT compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_multistate_funcs,
+        const struct wined3d_gl_info *gl_info, const struct wined3d_d3d_info *d3d_info,
+        const struct wined3d_vertex_pipe_ops *vertex, const struct fragment_pipeline *fragment,
+        const struct StateEntryTemplate *misc) DECLSPEC_HIDDEN;
+
+enum wined3d_blit_op
+{
+    WINED3D_BLIT_OP_COLOR_BLIT,
+    WINED3D_BLIT_OP_COLOR_FILL,
+    WINED3D_BLIT_OP_DEPTH_FILL,
+    WINED3D_BLIT_OP_DEPTH_BLIT,
+};
+
+/* Shaders for color conversions in blits. Do not do blit operations while
+ * already under the GL lock. */
+struct blit_shader
+{
+    HRESULT (*alloc_private)(struct wined3d_device *device);
+    void (*free_private)(struct wined3d_device *device);
+    HRESULT (*set_shader)(void *blit_priv, struct wined3d_context *context, const struct wined3d_surface *surface);
+    void (*unset_shader)(const struct wined3d_gl_info *gl_info);
+    BOOL (*blit_supported)(const struct wined3d_gl_info *gl_info, enum wined3d_blit_op blit_op,
+            const RECT *src_rect, DWORD src_usage, enum wined3d_pool src_pool, const struct wined3d_format *src_format,
+            const RECT *dst_rect, DWORD dst_usage, enum wined3d_pool dst_pool, const struct wined3d_format *dst_format);
+    HRESULT (*color_fill)(struct wined3d_device *device, struct wined3d_surface *dst_surface,
+            const RECT *dst_rect, const struct wined3d_color *color);
+    HRESULT (*depth_fill)(struct wined3d_device *device,
+            struct wined3d_surface *surface, const RECT *rect, float depth);
+};
+
+extern const struct blit_shader ffp_blit DECLSPEC_HIDDEN;
+extern const struct blit_shader arbfp_blit DECLSPEC_HIDDEN;
+extern const struct blit_shader cpu_blit DECLSPEC_HIDDEN;
+
+const struct blit_shader *wined3d_select_blitter(const struct wined3d_gl_info *gl_info, enum wined3d_blit_op blit_op,
+        const RECT *src_rect, DWORD src_usage, enum wined3d_pool src_pool, const struct wined3d_format *src_format,
+        const RECT *dst_rect, DWORD dst_usage, enum wined3d_pool dst_pool, const struct wined3d_format *dst_format)
+        DECLSPEC_HIDDEN;
+
+/* Temporary blit_shader helper functions */
+HRESULT arbfp_blit_surface(struct wined3d_device *device, DWORD filter,
+        struct wined3d_surface *src_surface, const RECT *src_rect,
+        struct wined3d_surface *dst_surface, const RECT *dst_rect) DECLSPEC_HIDDEN;
+
+struct wined3d_context *context_acquire(const struct wined3d_device *device,
+        struct wined3d_surface *target) DECLSPEC_HIDDEN;
+void context_alloc_event_query(struct wined3d_context *context,
+        struct wined3d_event_query *query) DECLSPEC_HIDDEN;
+void context_alloc_occlusion_query(struct wined3d_context *context,
+        struct wined3d_occlusion_query *query) DECLSPEC_HIDDEN;
+void context_apply_blit_state(struct wined3d_context *context, const struct wined3d_device *device) DECLSPEC_HIDDEN;
+BOOL context_apply_clear_state(struct wined3d_context *context, const struct wined3d_device *device,
+        UINT rt_count, const struct wined3d_fb_state *fb) DECLSPEC_HIDDEN;
+BOOL context_apply_draw_state(struct wined3d_context *context, struct wined3d_device *device) DECLSPEC_HIDDEN;
+void context_apply_fbo_state_blit(struct wined3d_context *context, GLenum target,
+        struct wined3d_surface *render_target, struct wined3d_surface *depth_stencil, DWORD location) DECLSPEC_HIDDEN;
+void context_active_texture(struct wined3d_context *context, const struct wined3d_gl_info *gl_info,
+        unsigned int unit) DECLSPEC_HIDDEN;
+void context_bind_texture(struct wined3d_context *context, GLenum target, GLuint name) DECLSPEC_HIDDEN;
+void context_check_fbo_status(const struct wined3d_context *context, GLenum target) DECLSPEC_HIDDEN;
+struct wined3d_context *context_create(struct wined3d_swapchain *swapchain, struct wined3d_surface *target,
+        const struct wined3d_format *ds_format
+#ifdef VBOX_WITH_WDDM
+                , struct VBOXUHGSMI *pHgsmi
+#endif
+        ) DECLSPEC_HIDDEN;
+BOOL context_debug_output_enabled(const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN;
+void context_destroy(struct wined3d_device *device, struct wined3d_context *context) DECLSPEC_HIDDEN;
+void context_free_event_query(struct wined3d_event_query *query) DECLSPEC_HIDDEN;
+void context_free_occlusion_query(struct wined3d_occlusion_query *query) DECLSPEC_HIDDEN;
+struct wined3d_context *context_get_current(void) DECLSPEC_HIDDEN;
+DWORD context_get_tls_idx(void) DECLSPEC_HIDDEN;
+void context_invalidate_state(struct wined3d_context *context, DWORD state_id) DECLSPEC_HIDDEN;
+void context_release(struct wined3d_context *context) DECLSPEC_HIDDEN;
+void context_resource_released(const struct wined3d_device *device,
+        struct wined3d_resource *resource, enum wined3d_resource_type type) DECLSPEC_HIDDEN;
+void context_resource_unloaded(const struct wined3d_device *device,
+        struct wined3d_resource *resource, enum wined3d_resource_type type) DECLSPEC_HIDDEN;
+BOOL context_set_current(struct wined3d_context *ctx) DECLSPEC_HIDDEN;
+void context_set_draw_buffer(struct wined3d_context *context, GLenum buffer) DECLSPEC_HIDDEN;
+void context_set_tls_idx(DWORD idx) DECLSPEC_HIDDEN;
+void context_state_drawbuf(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void context_state_fb(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void context_surface_update(struct wined3d_context *context, const struct wined3d_surface *surface) DECLSPEC_HIDDEN;
+
+#if defined(VBOX_WINE_WITH_SINGLE_CONTEXT) || defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
+void context_clear_on_thread_detach();
+#endif
+#if defined(VBOX_WINE_WITH_SINGLE_CONTEXT)
+struct wined3d_context *context_find_create(struct wined3d_device *device,
+        struct wined3d_swapchain *swapchain,
+        const struct wined3d_format *ds_format);
+#endif
+
+/*****************************************************************************
+ * Internal representation of a light
+ */
+struct wined3d_light_info
+{
+    struct wined3d_light OriginalParms; /* Note D3D8LIGHT == D3D9LIGHT */
+    DWORD        OriginalIndex;
+    LONG         glIndex;
+    BOOL         enabled;
+
+    /* Converted parms to speed up swapping lights */
+    float                         lightPosn[4];
+    float                         lightDirn[4];
+    float                         exponent;
+    float                         cutoff;
+
+    struct list entry;
+};
+
+/* The default light parameters */
+extern const struct wined3d_light WINED3D_default_light DECLSPEC_HIDDEN;
+
+struct wined3d_pixel_format
+{
+    int iPixelFormat; /* WGL pixel format */
+    int iPixelType; /* WGL pixel type e.g. WGL_TYPE_RGBA_ARB, WGL_TYPE_RGBA_FLOAT_ARB or WGL_TYPE_COLORINDEX_ARB */
+    int redSize, greenSize, blueSize, alphaSize, colorSize;
+    int depthSize, stencilSize;
+    BOOL windowDrawable;
+    BOOL doubleBuffer;
+    int auxBuffers;
+    int numSamples;
+};
+
+enum wined3d_pci_vendor
+{
+    HW_VENDOR_SOFTWARE                 = 0x0000,
+    HW_VENDOR_AMD                      = 0x1002,
+    HW_VENDOR_NVIDIA                   = 0x10de,
+    HW_VENDOR_INTEL                    = 0x8086,
+};
+
+enum wined3d_pci_device
+{
+    CARD_WINE                       = 0x0000,
+
+    CARD_AMD_RAGE_128PRO            = 0x5246,
+    CARD_AMD_RADEON_7200            = 0x5144,
+    CARD_AMD_RADEON_8500            = 0x514c,
+    CARD_AMD_RADEON_9500            = 0x4144,
+    CARD_AMD_RADEON_XPRESS_200M     = 0x5955,
+    CARD_AMD_RADEON_X700            = 0x5e4c,
+    CARD_AMD_RADEON_X1600           = 0x71c2,
+    CARD_AMD_RADEON_HD2350          = 0x94c7,
+    CARD_AMD_RADEON_HD2600          = 0x9581,
+    CARD_AMD_RADEON_HD2900          = 0x9400,
+    CARD_AMD_RADEON_HD3200          = 0x9620,
+    CARD_AMD_RADEON_HD4200M         = 0x9712,
+    CARD_AMD_RADEON_HD4350          = 0x954f,
+    CARD_AMD_RADEON_HD4600          = 0x9495,
+    CARD_AMD_RADEON_HD4700          = 0x944e,
+    CARD_AMD_RADEON_HD4800          = 0x944c,
+    CARD_AMD_RADEON_HD5400          = 0x68f9,
+    CARD_AMD_RADEON_HD5600          = 0x68d8,
+    CARD_AMD_RADEON_HD5700          = 0x68be,
+    CARD_AMD_RADEON_HD5800          = 0x6898,
+    CARD_AMD_RADEON_HD5900          = 0x689c,
+    CARD_AMD_RADEON_HD6300          = 0x9803,
+    CARD_AMD_RADEON_HD6400          = 0x6770,
+    CARD_AMD_RADEON_HD6410D         = 0x9644,
+    CARD_AMD_RADEON_HD6550D         = 0x9640,
+    CARD_AMD_RADEON_HD6600          = 0x6758,
+    CARD_AMD_RADEON_HD6600M         = 0x6741,
+    CARD_AMD_RADEON_HD6700          = 0x68ba,
+    CARD_AMD_RADEON_HD6800          = 0x6739,
+    CARD_AMD_RADEON_HD6900          = 0x6719,
+    CARD_AMD_RADEON_HD7700          = 0x683d,
+    CARD_AMD_RADEON_HD7800          = 0x6819,
+    CARD_AMD_RADEON_HD7900          = 0x679a,
+
+    CARD_NVIDIA_RIVA_128            = 0x0018,
+    CARD_NVIDIA_RIVA_TNT            = 0x0020,
+    CARD_NVIDIA_RIVA_TNT2           = 0x0028,
+    CARD_NVIDIA_GEFORCE             = 0x0100,
+    CARD_NVIDIA_GEFORCE2_MX         = 0x0110,
+    CARD_NVIDIA_GEFORCE2            = 0x0150,
+    CARD_NVIDIA_GEFORCE3            = 0x0200,
+    CARD_NVIDIA_GEFORCE4_MX         = 0x0170,
+    CARD_NVIDIA_GEFORCE4_TI4200     = 0x0253,
+    CARD_NVIDIA_GEFORCEFX_5200      = 0x0320,
+    CARD_NVIDIA_GEFORCEFX_5600      = 0x0312,
+    CARD_NVIDIA_GEFORCEFX_5800      = 0x0302,
+    CARD_NVIDIA_GEFORCE_6200        = 0x014f,
+    CARD_NVIDIA_GEFORCE_6600GT      = 0x0140,
+    CARD_NVIDIA_GEFORCE_6800        = 0x0041,
+    CARD_NVIDIA_GEFORCE_7400        = 0x01d8,
+    CARD_NVIDIA_GEFORCE_7300        = 0x01d7, /* GeForce Go 7300 */
+    CARD_NVIDIA_GEFORCE_7600        = 0x0391,
+    CARD_NVIDIA_GEFORCE_7800GT      = 0x0092,
+    CARD_NVIDIA_GEFORCE_8200        = 0x0849, /* Other PCI ID 0x084b */
+    CARD_NVIDIA_GEFORCE_8300GS      = 0x0423,
+    CARD_NVIDIA_GEFORCE_8400GS      = 0x0404,
+    CARD_NVIDIA_GEFORCE_8500GT      = 0x0421,
+    CARD_NVIDIA_GEFORCE_8600GT      = 0x0402,
+    CARD_NVIDIA_GEFORCE_8600MGT     = 0x0407,
+    CARD_NVIDIA_GEFORCE_8800GTS     = 0x0193,
+    CARD_NVIDIA_GEFORCE_8800GTX     = 0x0191,
+    CARD_NVIDIA_GEFORCE_9200        = 0x086d,
+    CARD_NVIDIA_GEFORCE_9300        = 0x086c,
+    CARD_NVIDIA_GEFORCE_9400M       = 0x0863,
+    CARD_NVIDIA_GEFORCE_9400GT      = 0x042c,
+    CARD_NVIDIA_GEFORCE_9500GT      = 0x0640,
+    CARD_NVIDIA_GEFORCE_9600GT      = 0x0622,
+    CARD_NVIDIA_GEFORCE_9800GT      = 0x0614,
+    CARD_NVIDIA_GEFORCE_210         = 0x0a23,
+    CARD_NVIDIA_GEFORCE_GT220       = 0x0a20,
+    CARD_NVIDIA_GEFORCE_GT240       = 0x0ca3,
+    CARD_NVIDIA_GEFORCE_GTX260      = 0x05e2,
+    CARD_NVIDIA_GEFORCE_GTX275      = 0x05e6,
+    CARD_NVIDIA_GEFORCE_GTX280      = 0x05e1,
+    CARD_NVIDIA_GEFORCE_315M        = 0x0a7a,
+    CARD_NVIDIA_GEFORCE_320M        = 0x08a3,
+    CARD_NVIDIA_GEFORCE_GT320M      = 0x0a2d,
+    CARD_NVIDIA_GEFORCE_GT325M      = 0x0a35,
+    CARD_NVIDIA_GEFORCE_GT330       = 0x0ca0,
+    CARD_NVIDIA_GEFORCE_GTS350M     = 0x0cb0,
+    CARD_NVIDIA_GEFORCE_410M        = 0x1055,
+    CARD_NVIDIA_GEFORCE_GT420       = 0x0de2,
+    CARD_NVIDIA_GEFORCE_GT430       = 0x0de1,
+    CARD_NVIDIA_GEFORCE_GT440       = 0x0de0,
+    CARD_NVIDIA_GEFORCE_GTS450      = 0x0dc4,
+    CARD_NVIDIA_GEFORCE_GTX460      = 0x0e22,
+    CARD_NVIDIA_GEFORCE_GTX460M     = 0x0dd1,
+    CARD_NVIDIA_GEFORCE_GTX465      = 0x06c4,
+    CARD_NVIDIA_GEFORCE_GTX470      = 0x06cd,
+    CARD_NVIDIA_GEFORCE_GTX480      = 0x06c0,
+    CARD_NVIDIA_GEFORCE_GT520       = 0x1040,
+    CARD_NVIDIA_GEFORCE_GT540M      = 0x0df4,
+    CARD_NVIDIA_GEFORCE_GTX550      = 0x1244,
+    CARD_NVIDIA_GEFORCE_GT555M      = 0x04b8,
+    CARD_NVIDIA_GEFORCE_GTX560TI    = 0x1200,
+    CARD_NVIDIA_GEFORCE_GTX560      = 0x1201,
+    CARD_NVIDIA_GEFORCE_GTX570      = 0x1081,
+    CARD_NVIDIA_GEFORCE_GTX580      = 0x1080,
+    CARD_NVIDIA_GEFORCE_GT610       = 0x104a,
+    CARD_NVIDIA_GEFORCE_GT630       = 0x0f00,
+    CARD_NVIDIA_GEFORCE_GT630M      = 0x0de9,
+    CARD_NVIDIA_GEFORCE_GT640M      = 0x0fd2,
+    CARD_NVIDIA_GEFORCE_GT650M      = 0x0fd1,
+    CARD_NVIDIA_GEFORCE_GTX650      = 0x0fc6,
+    CARD_NVIDIA_GEFORCE_GTX650TI    = 0x11c6,
+    CARD_NVIDIA_GEFORCE_GTX660      = 0x11c0,
+    CARD_NVIDIA_GEFORCE_GTX660TI    = 0x1183,
+    CARD_NVIDIA_GEFORCE_GTX670      = 0x1189,
+    CARD_NVIDIA_GEFORCE_GTX680      = 0x1180,
+
+    CARD_INTEL_830M                 = 0x3577,
+    CARD_INTEL_855GM                = 0x3582,
+    CARD_INTEL_845G                 = 0x2562,
+    CARD_INTEL_865G                 = 0x2572,
+    CARD_INTEL_915G                 = 0x2582,
+    CARD_INTEL_E7221G               = 0x258a,
+    CARD_INTEL_915GM                = 0x2592,
+    CARD_INTEL_945G                 = 0x2772,
+    CARD_INTEL_945GM                = 0x27a2,
+    CARD_INTEL_945GME               = 0x27ae,
+    CARD_INTEL_Q35                  = 0x29b2,
+    CARD_INTEL_G33                  = 0x29c2,
+    CARD_INTEL_Q33                  = 0x29d2,
+    CARD_INTEL_PNVG                 = 0xa001,
+    CARD_INTEL_PNVM                 = 0xa011,
+    CARD_INTEL_965Q                 = 0x2992,
+    CARD_INTEL_965G                 = 0x2982,
+    CARD_INTEL_946GZ                = 0x2972,
+    CARD_INTEL_965GM                = 0x2a02,
+    CARD_INTEL_965GME               = 0x2a12,
+    CARD_INTEL_GM45                 = 0x2a42,
+    CARD_INTEL_IGD                  = 0x2e02,
+    CARD_INTEL_Q45                  = 0x2e12,
+    CARD_INTEL_G45                  = 0x2e22,
+    CARD_INTEL_G41                  = 0x2e32,
+    CARD_INTEL_B43                  = 0x2e92,
+    CARD_INTEL_ILKD                 = 0x0042,
+    CARD_INTEL_ILKM                 = 0x0046,
+    CARD_INTEL_SNBD                 = 0x0122,
+    CARD_INTEL_SNBM                 = 0x0126,
+    CARD_INTEL_SNBS                 = 0x010a,
+    CARD_INTEL_IVBD                 = 0x0162,
+    CARD_INTEL_IVBM                 = 0x0166,
+    CARD_INTEL_IVBS                 = 0x015a,
+};
+
+struct wined3d_fbo_ops
+{
+    GLboolean (WINE_GLAPI *glIsRenderbuffer)(GLuint renderbuffer);
+    void (WINE_GLAPI *glBindRenderbuffer)(GLenum target, GLuint renderbuffer);
+    void (WINE_GLAPI *glDeleteRenderbuffers)(GLsizei n, const GLuint *renderbuffers);
+    void (WINE_GLAPI *glGenRenderbuffers)(GLsizei n, GLuint *renderbuffers);
+    void (WINE_GLAPI *glRenderbufferStorage)(GLenum target, GLenum internalformat,
+            GLsizei width, GLsizei height);
+    void (WINE_GLAPI *glRenderbufferStorageMultisample)(GLenum target, GLsizei samples,
+            GLenum internalformat, GLsizei width, GLsizei height);
+    void (WINE_GLAPI *glGetRenderbufferParameteriv)(GLenum target, GLenum pname, GLint *params);
+    GLboolean (WINE_GLAPI *glIsFramebuffer)(GLuint framebuffer);
+    void (WINE_GLAPI *glBindFramebuffer)(GLenum target, GLuint framebuffer);
+    void (WINE_GLAPI *glDeleteFramebuffers)(GLsizei n, const GLuint *framebuffers);
+    void (WINE_GLAPI *glGenFramebuffers)(GLsizei n, GLuint *framebuffers);
+    GLenum (WINE_GLAPI *glCheckFramebufferStatus)(GLenum target);
+    void (WINE_GLAPI *glFramebufferTexture1D)(GLenum target, GLenum attachment,
+            GLenum textarget, GLuint texture, GLint level);
+    void (WINE_GLAPI *glFramebufferTexture2D)(GLenum target, GLenum attachment,
+            GLenum textarget, GLuint texture, GLint level);
+    void (WINE_GLAPI *glFramebufferTexture3D)(GLenum target, GLenum attachment,
+            GLenum textarget, GLuint texture, GLint level, GLint layer);
+    void (WINE_GLAPI *glFramebufferRenderbuffer)(GLenum target, GLenum attachment,
+            GLenum renderbuffertarget, GLuint renderbuffer);
+    void (WINE_GLAPI *glGetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment,
+            GLenum pname, GLint *params);
+    void (WINE_GLAPI *glBlitFramebuffer)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+            GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+    void (WINE_GLAPI *glGenerateMipmap)(GLenum target);
+};
+
+struct wined3d_gl_limits
+{
+    UINT buffers;
+    UINT lights;
+    UINT textures;
+    UINT texture_coords;
+    UINT fragment_samplers;
+    UINT vertex_samplers;
+    UINT combined_samplers;
+    UINT general_combiners;
+    UINT clipplanes;
+    UINT texture_size;
+    UINT texture3d_size;
+    float pointsize_max;
+    float pointsize_min;
+    UINT blends;
+    UINT anisotropy;
+    float shininess;
+    UINT samples;
+    UINT vertex_attribs;
+
+    UINT glsl_varyings;
+    UINT glsl_vs_float_constants;
+    UINT glsl_ps_float_constants;
+
+    UINT arb_vs_float_constants;
+    UINT arb_vs_native_constants;
+    UINT arb_vs_instructions;
+    UINT arb_vs_temps;
+    UINT arb_ps_float_constants;
+    UINT arb_ps_local_constants;
+    UINT arb_ps_native_constants;
+    UINT arb_ps_instructions;
+    UINT arb_ps_temps;
+};
+
+struct wined3d_gl_info
+{
+    DWORD glsl_version;
+    struct wined3d_gl_limits limits;
+    DWORD reserved_glsl_constants, reserved_arb_constants;
+    DWORD quirks;
+    BOOL supported[WINED3D_GL_EXT_COUNT];
+    GLint wrap_lookup[WINED3D_TADDRESS_MIRROR_ONCE - WINED3D_TADDRESS_WRAP + 1];
+
+    HGLRC (WINAPI *p_wglCreateContextAttribsARB)(HDC dc, HGLRC share, const GLint *attribs);
+    struct opengl_funcs gl_ops;
+    struct wined3d_fbo_ops fbo_ops;
+
+    struct wined3d_format *formats;
+};
+
+struct wined3d_driver_info
+{
+    enum wined3d_pci_vendor vendor;
+    enum wined3d_pci_device device;
+    const char *name;
+    const char *description;
+    unsigned int vidmem;
+    DWORD version_high;
+    DWORD version_low;
+};
+
+struct wined3d_d3d_limits
+{
+    UINT vs_version, gs_version, ps_version;
+    DWORD vs_uniform_count;
+    DWORD ps_uniform_count;
+    UINT ffp_textures;
+    UINT ffp_blend_stages;
+};
+
+struct wined3d_d3d_info
+{
+    struct wined3d_d3d_limits limits;
+    BOOL vs_clipping;
+    DWORD valid_rt_mask;
+};
+
+/* The adapter structure */
+struct wined3d_adapter
+{
+    UINT ordinal;
+    POINT monitorPoint;
+    enum wined3d_format_id screen_format;
+
+    struct wined3d_gl_info  gl_info;
+    struct wined3d_d3d_info d3d_info;
+    struct wined3d_driver_info driver_info;
+    WCHAR                   DeviceName[CCHDEVICENAME]; /* DeviceName for use with e.g. ChangeDisplaySettings */
+    unsigned int cfg_count;
+    struct wined3d_pixel_format *cfgs;
+#ifndef VBOX_WITH_WDDM
+    unsigned int            TextureRam; /* Amount of texture memory both video ram + AGP/TurboCache/HyperMemory/.. */
+    unsigned int            UsedTextureRam;
+#endif
+    LUID luid;
+
+    const struct wined3d_vertex_pipe_ops *vertex_pipe;
+    const struct fragment_pipeline *fragment_pipe;
+    const struct wined3d_shader_backend_ops *shader_backend;
+    const struct blit_shader *blitter;
+};
+
+BOOL wined3d_adapter_init_format_info(struct wined3d_adapter *adapter) DECLSPEC_HIDDEN;
+
+#ifndef VBOX_WITH_WDDM
+unsigned int adapter_adjust_memory(struct wined3d_adapter *adapter, int amount) DECLSPEC_HIDDEN;
+#endif
+
+BOOL initPixelFormatsNoGL(struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN;
+extern void add_gl_compat_wrappers(struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN;
+
+enum projection_types
+{
+    proj_none    = 0,
+    proj_count3  = 1,
+    proj_count4  = 2
+};
+
+enum dst_arg
+{
+    resultreg    = 0,
+    tempreg      = 1
+};
+
+/*****************************************************************************
+ * Fixed function pipeline replacements
+ */
+#define ARG_UNUSED          0xff
+struct texture_stage_op
+{
+    unsigned                cop : 8;
+    unsigned                carg1 : 8;
+    unsigned                carg2 : 8;
+    unsigned                carg0 : 8;
+
+    unsigned                aop : 8;
+    unsigned                aarg1 : 8;
+    unsigned                aarg2 : 8;
+    unsigned                aarg0 : 8;
+
+    struct color_fixup_desc color_fixup;
+    unsigned                tex_type : 3;
+    unsigned                dst : 1;
+    unsigned                projected : 2;
+    unsigned                padding : 10;
+};
+
+struct ffp_frag_settings
+{
+    struct texture_stage_op     op[MAX_TEXTURES];
+    enum wined3d_ffp_ps_fog_mode fog;
+    /* Use shorts instead of chars to get dword alignment */
+    unsigned short sRGB_write;
+    unsigned short emul_clipplanes;
+};
+
+struct ffp_frag_desc
+{
+    struct wine_rb_entry entry;
+    struct ffp_frag_settings    settings;
+};
+
+extern const struct wine_rb_functions wined3d_ffp_frag_program_rb_functions DECLSPEC_HIDDEN;
+extern const struct wine_rb_functions wined3d_ffp_vertex_program_rb_functions DECLSPEC_HIDDEN;
+extern const struct wined3d_parent_ops wined3d_null_parent_ops DECLSPEC_HIDDEN;
+
+void gen_ffp_frag_op(const struct wined3d_context *context, const struct wined3d_state *state,
+        struct ffp_frag_settings *settings, BOOL ignore_textype) DECLSPEC_HIDDEN;
+const struct ffp_frag_desc *find_ffp_frag_shader(const struct wine_rb_tree *fragment_shaders,
+        const struct ffp_frag_settings *settings) DECLSPEC_HIDDEN;
+void add_ffp_frag_shader(struct wine_rb_tree *shaders, struct ffp_frag_desc *desc) DECLSPEC_HIDDEN;
+void wined3d_get_draw_rect(const struct wined3d_state *state, RECT *rect) DECLSPEC_HIDDEN;
+
+enum wined3d_ffp_vs_fog_mode
+{
+    WINED3D_FFP_VS_FOG_OFF      = 0,
+    WINED3D_FFP_VS_FOG_FOGCOORD = 1,
+    WINED3D_FFP_VS_FOG_DEPTH    = 2,
+    WINED3D_FFP_VS_FOG_RANGE    = 3,
+};
+
+#define WINED3D_FFP_TCI_SHIFT               16
+#define WINED3D_FFP_TCI_MASK                0xff
+
+#define WINED3D_FFP_LIGHT_TYPE_SHIFT(idx)   (3 * (idx))
+#define WINED3D_FFP_LIGHT_TYPE_MASK         0x7
+
+struct wined3d_ffp_vs_settings
+{
+    DWORD light_type      : 24; /* MAX_ACTIVE_LIGHTS, 8 * 3 */
+    DWORD diffuse_source  : 2;
+    DWORD emission_source : 2;
+    DWORD ambient_source  : 2;
+    DWORD specular_source : 2;
+
+    DWORD clipping        : 1;
+    DWORD normal          : 1;
+    DWORD normalize       : 1;
+    DWORD lighting        : 1;
+    DWORD localviewer     : 1;
+    DWORD point_size      : 1;
+    DWORD fog_mode        : 2;
+    DWORD texcoords       : 8;  /* MAX_TEXTURES */
+    DWORD padding         : 16;
+
+    BYTE texgen[MAX_TEXTURES];
+};
+
+struct wined3d_ffp_vs_desc
+{
+    struct wine_rb_entry entry;
+    struct wined3d_ffp_vs_settings settings;
+};
+
+void wined3d_ffp_get_vs_settings(const struct wined3d_state *state, const struct wined3d_stream_info *si,
+        struct wined3d_ffp_vs_settings *settings) DECLSPEC_HIDDEN;
+
+struct wined3d
+{
+    LONG ref;
+    DWORD flags;
+    UINT dxVersion;
+    UINT adapter_count;
+    struct wined3d_adapter adapters[1];
+};
+
+HRESULT wined3d_init(struct wined3d *wined3d, UINT version, DWORD flags) DECLSPEC_HIDDEN;
+#ifndef VBOX_WITH_WDDM
+BOOL wined3d_register_window(HWND window, struct wined3d_device *device) DECLSPEC_HIDDEN;
+void wined3d_unregister_window(HWND window) DECLSPEC_HIDDEN;
+#endif
+
+/*****************************************************************************
+ * IWineD3DDevice implementation structure
+ */
+#define WINED3D_UNMAPPED_STAGE ~0U
+
+/* Multithreaded flag. Removed from the public header to signal that IWineD3D::CreateDevice ignores it */
+#define WINED3DCREATE_MULTITHREADED 0x00000004
+
+struct wined3d_device
+{
+    LONG ref;
+
+    /* WineD3D Information  */
+    struct wined3d_device_parent *device_parent;
+    struct wined3d *wined3d;
+    struct wined3d_adapter *adapter;
+
+    /* Window styles to restore when switching fullscreen mode */
+    LONG                    style;
+    LONG                    exStyle;
+
+    /* X and GL Information */
+    GLenum                  offscreenBuffer;
+
+    const struct wined3d_shader_backend_ops *shader_backend;
+    void *shader_priv;
+    void *fragment_priv;
+    void *vertex_priv;
+    void *blit_priv;
+    struct StateEntry StateTable[STATE_HIGHEST + 1];
+    /* Array of functions for states which are handled by more than one pipeline part */
+    APPLYSTATEFUNC *multistate_funcs[STATE_HIGHEST + 1];
+    const struct blit_shader *blitter;
+
+    UINT instance_count;
+
+    WORD vertexBlendUsed : 1;           /* To avoid needless setting of the blend matrices */
+    WORD isRecordingState : 1;
+    WORD isInDraw : 1;
+    WORD bCursorVisible : 1;
+    WORD d3d_initialized : 1;
+    WORD inScene : 1;                   /* A flag to check for proper BeginScene / EndScene call pairs */
+    WORD softwareVertexProcessing : 1;  /* process vertex shaders using software or hardware */
+    WORD useDrawStridedSlow : 1;
+    WORD filter_messages : 1;
+    WORD padding : 7;
+
+    BYTE fixed_function_usage_map;      /* MAX_TEXTURES, 8 */
+
+#define DDRAW_PITCH_ALIGNMENT 8
+#define D3D8_PITCH_ALIGNMENT 4
+    unsigned char           surface_alignment; /* Line Alignment of surfaces                      */
+
+    /* State block related */
+    struct wined3d_stateblock *stateBlock;
+    struct wined3d_stateblock *updateStateBlock;
+
+    /* Internal use fields  */
+    struct wined3d_device_creation_parameters create_parms;
+#ifndef VBOX_WITH_WDDM
+    HWND focus_window;
+#endif
+
+    struct wined3d_swapchain **swapchains;
+    UINT swapchain_count;
+
+    struct list             resources; /* a linked list to track resources created by the device */
+    struct list             shaders;   /* a linked list to track shaders (pixel and vertex)      */
+
+    /* Render Target Support */
+    struct wined3d_fb_state fb;
+    struct wined3d_surface *onscreen_depth_stencil;
+    struct wined3d_surface *auto_depth_stencil;
+
+    /* For rendering to a texture using glCopyTexImage */
+    GLuint                  depth_blt_texture;
+
+    /* Cursor management */
+    UINT                    xHotSpot;
+    UINT                    yHotSpot;
+    UINT                    xScreenSpace;
+    UINT                    yScreenSpace;
+    UINT                    cursorWidth, cursorHeight;
+    GLuint                  cursorTexture;
+    HCURSOR                 hardwareCursor;
+
+    /* The Wine logo surface */
+    struct wined3d_surface *logo_surface;
+
+    /* Textures for when no other textures are mapped */
+    UINT dummy_texture_2d[MAX_COMBINED_SAMPLERS];
+    UINT dummy_texture_rect[MAX_COMBINED_SAMPLERS];
+    UINT dummy_texture_3d[MAX_COMBINED_SAMPLERS];
+    UINT dummy_texture_cube[MAX_COMBINED_SAMPLERS];
+
+    /* With register combiners we can skip junk texture stages */
+    DWORD                     texUnitMap[MAX_COMBINED_SAMPLERS];
+    DWORD                     rev_tex_unit_map[MAX_COMBINED_SAMPLERS];
+
+    /* Stream source management */
+    struct wined3d_stream_info stream_info;
+    struct wined3d_event_query *buffer_queries[MAX_ATTRIBS];
+    unsigned int num_buffer_queries;
+
+    /* Context management */
+    struct wined3d_context **contexts;
+    UINT context_count;
+
+#ifdef VBOX_WITH_WDDM
+    struct VBOXUHGSMI *pHgsmi;
+#endif
+
+#ifdef VBOX_WINE_WITH_SHADER_CACHE
+    VBOXEXT_HASHCACHE vshaderCache;
+    VBOXEXT_HASHCACHE pshaderCache;
+#endif
+
+#ifdef VBOX_WINE_WITH_PROFILE
+    VBOXWINEPROFILE_DRAWPRIM DrawPrimProfile;
+#endif
+};
+
+void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, const struct wined3d_fb_state *fb,
+        UINT rect_count, const RECT *rects, const RECT *draw_rect, DWORD flags,
+        const struct wined3d_color *color, float depth, DWORD stencil) DECLSPEC_HIDDEN;
+BOOL device_context_add(struct wined3d_device *device, struct wined3d_context *context) DECLSPEC_HIDDEN;
+void device_context_remove(struct wined3d_device *device, struct wined3d_context *context) DECLSPEC_HIDDEN;
+HRESULT device_init(struct wined3d_device *device, struct wined3d *wined3d,
+        UINT adapter_idx, enum wined3d_device_type device_type, HWND focus_window, DWORD flags,
+        BYTE surface_alignment, struct wined3d_device_parent *device_parent) DECLSPEC_HIDDEN;
+void device_preload_textures(const struct wined3d_device *device) DECLSPEC_HIDDEN;
+#ifndef VBOX_WITH_WDDM
+LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL unicode,
+        UINT message, WPARAM wparam, LPARAM lparam, WNDPROC proc) DECLSPEC_HIDDEN;
+#else
+void surface_setup_location_onopen(struct wined3d_surface *surface);
+#endif
+void device_resource_add(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN;
+void device_resource_released(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN;
+void device_switch_onscreen_ds(struct wined3d_device *device, struct wined3d_context *context,
+        struct wined3d_surface *depth_stencil) DECLSPEC_HIDDEN;
+void device_update_stream_info(struct wined3d_device *device, const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN;
+void device_update_tex_unit_map(struct wined3d_device *device) DECLSPEC_HIDDEN;
+void device_invalidate_state(const struct wined3d_device *device, DWORD state) DECLSPEC_HIDDEN;
+
+static inline BOOL isStateDirty(const struct wined3d_context *context, DWORD state)
+{
+    DWORD idx = state / (sizeof(*context->isStateDirty) * CHAR_BIT);
+    BYTE shift = state & ((sizeof(*context->isStateDirty) * CHAR_BIT) - 1);
+    return context->isStateDirty[idx] & (1 << shift);
+}
+
+static inline void invalidate_active_texture(const struct wined3d_device *device, struct wined3d_context *context)
+{
+    DWORD sampler = device->rev_tex_unit_map[context->active_texture];
+    if (sampler != WINED3D_UNMAPPED_STAGE)
+        context_invalidate_state(context, STATE_SAMPLER(sampler));
+}
+
+#define WINED3D_RESOURCE_ACCESS_GPU     0x1
+#define WINED3D_RESOURCE_ACCESS_CPU     0x2
+/* SCRATCH is mostly the same as CPU, but can't be used by the GPU at all,
+ * not even for resource uploads. */
+#define WINED3D_RESOURCE_ACCESS_SCRATCH 0x4
+
+struct wined3d_resource_ops
+{
+    void (*resource_unload)(struct wined3d_resource *resource);
+};
+
+struct wined3d_resource
+{
+    LONG ref;
+    LONG bind_count;
+    LONG map_count;
+    struct wined3d_device *device;
+    enum wined3d_resource_type type;
+    const struct wined3d_format *format;
+    enum wined3d_multisample_type multisample_type;
+    UINT                    multisample_quality;
+    DWORD                   usage;
+    enum wined3d_pool pool;
+    DWORD access_flags;
+    UINT width;
+    UINT height;
+    UINT depth;
+    UINT                    size;
+    DWORD                   priority;
+    BYTE                   *allocatedMemory; /* Pointer to the real data location */
+    BYTE                   *heapMemory; /* Pointer to the HeapAlloced block of memory */
+#ifdef VBOX_WITH_WDDM
+    DWORD                   sharerc_flags; /* shared resource flags */
+    DWORD                   sharerc_handle; /* shared resource handle */
+    DWORD                   sharerc_locks; /* lock count */
+#endif
+    struct list             privateData;
+    struct list             resource_list_entry;
+
+    void *parent;
+    const struct wined3d_parent_ops *parent_ops;
+    const struct wined3d_resource_ops *resource_ops;
+};
+
+void resource_cleanup(struct wined3d_resource *resource) DECLSPEC_HIDDEN;
+DWORD resource_get_priority(const struct wined3d_resource *resource) DECLSPEC_HIDDEN;
+HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device *device,
+        enum wined3d_resource_type type, const struct wined3d_format *format,
+        enum wined3d_multisample_type multisample_type, UINT multisample_quality,
+        DWORD usage, enum wined3d_pool pool, UINT width, UINT height, UINT depth, UINT size,
+        void *parent, const struct wined3d_parent_ops *parent_ops,
+        const struct wined3d_resource_ops *resource_ops
+#ifdef VBOX_WITH_WDDM
+        , HANDLE *shared_handle
+        , void *pvClientMem
+#endif
+        ) DECLSPEC_HIDDEN;
+DWORD resource_set_priority(struct wined3d_resource *resource, DWORD priority) DECLSPEC_HIDDEN;
+void resource_unload(struct wined3d_resource *resource) DECLSPEC_HIDDEN;
+
+/* Tests show that the start address of resources is 32 byte aligned */
+#define RESOURCE_ALIGNMENT 16
+
+enum wined3d_texture_state
+{
+    WINED3DTEXSTA_ADDRESSU       = 0,
+    WINED3DTEXSTA_ADDRESSV       = 1,
+    WINED3DTEXSTA_ADDRESSW       = 2,
+    WINED3DTEXSTA_BORDERCOLOR    = 3,
+    WINED3DTEXSTA_MAGFILTER      = 4,
+    WINED3DTEXSTA_MINFILTER      = 5,
+    WINED3DTEXSTA_MIPFILTER      = 6,
+    WINED3DTEXSTA_MAXMIPLEVEL    = 7,
+    WINED3DTEXSTA_MAXANISOTROPY  = 8,
+    WINED3DTEXSTA_SRGBTEXTURE    = 9,
+    WINED3DTEXSTA_SHADOW         = 10,
+    MAX_WINETEXTURESTATES        = 11,
+};
+
+enum WINED3DSRGB
+{
+    SRGB_ANY                                = 0,    /* Uses the cached value(e.g. external calls) */
+    SRGB_RGB                                = 1,    /* Loads the rgb texture */
+    SRGB_SRGB                               = 2,    /* Loads the srgb texture */
+};
+
+struct gl_texture
+{
+    DWORD                   states[MAX_WINETEXTURESTATES];
+    BOOL                    dirty;
+    GLuint                  name;
+};
+
+struct wined3d_texture_ops
+{
+    HRESULT (*texture_bind)(struct wined3d_texture *texture,
+            struct wined3d_context *context, BOOL srgb);
+    void (*texture_preload)(struct wined3d_texture *texture, enum WINED3DSRGB srgb);
+    void (*texture_sub_resource_add_dirty_region)(struct wined3d_resource *sub_resource,
+            const struct wined3d_box *dirty_region);
+    void (*texture_sub_resource_cleanup)(struct wined3d_resource *sub_resource);
+};
+
+#define WINED3D_TEXTURE_COND_NP2            0x1
+#define WINED3D_TEXTURE_POW2_MAT_IDENT      0x2
+#define WINED3D_TEXTURE_IS_SRGB             0x4
+
+struct wined3d_texture
+{
+    struct wined3d_resource resource;
+    const struct wined3d_texture_ops *texture_ops;
+    struct gl_texture texture_rgb, texture_srgb;
+    struct wined3d_resource **sub_resources;
+    UINT layer_count;
+    UINT level_count;
+    float pow2_matrix[16];
+    UINT lod;
+    enum wined3d_texture_filter_type filter_type;
+    DWORD sampler;
+    DWORD flags;
+    const struct min_lookup *min_mip_lookup;
+    const GLenum *mag_lookup;
+    GLenum target;
+};
+
+#ifdef VBOX
+# ifdef VBOX_WITH_WDDM
+#define texture_gl_delete(_t) do { \
+        pglChromiumParameteriCR(GL_RCUSAGE_TEXTURE_CLEAR_CR, _t); \
+    } while (0)
+# else
+#define texture_gl_delete(_t) do { \
+        gl_info->gl_ops.gl.p_glDeleteTextures(1, &_t);  \
+    } while (0)
+
+# endif
+#endif
+
+static inline struct wined3d_texture *wined3d_texture_from_resource(struct wined3d_resource *resource)
+{
+    return CONTAINING_RECORD(resource, struct wined3d_texture, resource);
+}
+
+static inline struct gl_texture *wined3d_texture_get_gl_texture(struct wined3d_texture *texture,
+        const struct wined3d_gl_info *gl_info, BOOL srgb)
+{
+    return srgb && !gl_info->supported[EXT_TEXTURE_SRGB_DECODE]
+            ? &texture->texture_srgb : &texture->texture_rgb;
+}
+
+void wined3d_texture_apply_state_changes(struct wined3d_texture *texture,
+        const DWORD samplerStates[WINED3D_HIGHEST_SAMPLER_STATE + 1],
+        const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN;
+void wined3d_texture_set_dirty(struct wined3d_texture *texture, BOOL dirty) DECLSPEC_HIDDEN;
+
+struct wined3d_volume
+{
+    struct wined3d_resource resource;
+    struct wined3d_texture *container;
+    BOOL                    lockable;
+    BOOL                    locked;
+    struct wined3d_box lockedBox;
+    struct wined3d_box dirtyBox;
+    BOOL                    dirty;
+};
+
+static inline struct wined3d_volume *volume_from_resource(struct wined3d_resource *resource)
+{
+    return CONTAINING_RECORD(resource, struct wined3d_volume, resource);
+}
+
+void volume_add_dirty_box(struct wined3d_volume *volume, const struct wined3d_box *dirty_box) DECLSPEC_HIDDEN;
+void volume_load(const struct wined3d_volume *volume, struct wined3d_context *context, UINT level, BOOL srgb_mode) DECLSPEC_HIDDEN;
+void volume_set_container(struct wined3d_volume *volume, struct wined3d_texture *container) DECLSPEC_HIDDEN;
+
+struct wined3d_surface_dib
+{
+    HBITMAP DIBsection;
+    void *bitmap_data;
+    UINT bitmap_size;
+};
+
+struct wined3d_renderbuffer_entry
+{
+    struct list entry;
+    GLuint id;
+    UINT width;
+    UINT height;
+};
+
+struct fbo_entry
+{
+    struct list entry;
+    struct wined3d_surface **render_targets;
+    struct wined3d_surface *depth_stencil;
+    DWORD location;
+    DWORD rt_mask;
+    BOOL attached;
+    GLuint id;
+};
+
+struct wined3d_surface_ops
+{
+    HRESULT (*surface_private_setup)(struct wined3d_surface *surface);
+    void (*surface_realize_palette)(struct wined3d_surface *surface);
+    void (*surface_map)(struct wined3d_surface *surface, const RECT *rect, DWORD flags);
+    void (*surface_unmap)(struct wined3d_surface *surface);
+};
+
+struct wined3d_surface
+{
+    struct wined3d_resource resource;
+    const struct wined3d_surface_ops *surface_ops;
+    struct wined3d_texture *container;
+    struct wined3d_swapchain *swapchain;
+    struct wined3d_palette *palette; /* D3D7 style palette handling */
+    DWORD draw_binding;
+
+    DWORD flags;
+
+    UINT                      pow2Width;
+    UINT                      pow2Height;
+
+    /* A method to retrieve the drawable size. Not in the Vtable to make it changeable */
+    void (*get_drawable_size)(const struct wined3d_context *context, UINT *width, UINT *height);
+
+    /* PBO */
+    GLuint                    pbo;
+    GLuint rb_multisample;
+    GLuint rb_resolved;
+    GLuint texture_name;
+    GLuint texture_name_srgb;
+    GLint texture_level;
+    GLenum texture_target;
+
+    RECT                      lockedRect;
+    RECT                      dirtyRect;
+    int                       lockCount;
+#define MAXLOCKCOUNT          50 /* After this amount of locks do not free the sysmem copy */
+
+    /* For GetDC */
+    struct wined3d_surface_dib dib;
+    HDC                       hDC;
+
+    /* Color keys for DDraw */
+    struct wined3d_color_key dst_blt_color_key;
+    struct wined3d_color_key src_blt_color_key;
+    struct wined3d_color_key dst_overlay_color_key;
+    struct wined3d_color_key src_overlay_color_key;
+    DWORD                     CKeyFlags;
+
+    struct wined3d_color_key gl_color_key;
+
+    struct list               renderbuffers;
+    const struct wined3d_renderbuffer_entry *current_renderbuffer;
+    SIZE ds_current_size;
+
+    /* DirectDraw Overlay handling */
+    RECT                      overlay_srcrect;
+    RECT                      overlay_destrect;
+    struct wined3d_surface *overlay_dest;
+    struct list               overlays;
+    struct list               overlay_entry;
+};
+
+static inline struct wined3d_surface *surface_from_resource(struct wined3d_resource *resource)
+{
+    return CONTAINING_RECORD(resource, struct wined3d_surface, resource);
+}
+
+static inline GLuint surface_get_texture_name(const struct wined3d_surface *surface,
+        const struct wined3d_gl_info *gl_info, BOOL srgb)
+{
+    return srgb && !gl_info->supported[EXT_TEXTURE_SRGB_DECODE]
+            ? surface->texture_name_srgb : surface->texture_name;
+}
+
+void surface_add_dirty_rect(struct wined3d_surface *surface, const struct wined3d_box *dirty_rect) DECLSPEC_HIDDEN;
+HRESULT surface_color_fill(struct wined3d_surface *s,
+        const RECT *rect, const struct wined3d_color *color) DECLSPEC_HIDDEN;
+GLenum surface_get_gl_buffer(const struct wined3d_surface *surface) DECLSPEC_HIDDEN;
+void surface_internal_preload(struct wined3d_surface *surface, enum WINED3DSRGB srgb) DECLSPEC_HIDDEN;
+BOOL surface_is_offscreen(const struct wined3d_surface *surface) DECLSPEC_HIDDEN;
+HRESULT surface_load(struct wined3d_surface *surface, BOOL srgb) DECLSPEC_HIDDEN;
+void surface_load_ds_location(struct wined3d_surface *surface,
+        struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN;
+void surface_load_fb_texture(struct wined3d_surface *surface, BOOL srgb) DECLSPEC_HIDDEN;
+HRESULT surface_load_location(struct wined3d_surface *surface, DWORD location, const RECT *rect) DECLSPEC_HIDDEN;
+void surface_modify_ds_location(struct wined3d_surface *surface, DWORD location, UINT w, UINT h) DECLSPEC_HIDDEN;
+void surface_modify_location(struct wined3d_surface *surface, DWORD location, BOOL persistent) DECLSPEC_HIDDEN;
+void surface_prepare_rb(struct wined3d_surface *surface,
+        const struct wined3d_gl_info *gl_info, BOOL multisample) DECLSPEC_HIDDEN;
+void surface_prepare_texture(struct wined3d_surface *surface,
+        struct wined3d_context *context, BOOL srgb) DECLSPEC_HIDDEN;
+void surface_set_compatible_renderbuffer(struct wined3d_surface *surface,
+        const struct wined3d_surface *rt) DECLSPEC_HIDDEN;
+void surface_set_container(struct wined3d_surface *surface, struct wined3d_texture *container) DECLSPEC_HIDDEN;
+void surface_set_swapchain(struct wined3d_surface *surface, struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
+void surface_set_texture_name(struct wined3d_surface *surface, GLuint name, BOOL srgb_name) DECLSPEC_HIDDEN;
+void surface_set_texture_target(struct wined3d_surface *surface, GLenum target, GLint level) DECLSPEC_HIDDEN;
+void surface_translate_drawable_coords(const struct wined3d_surface *surface, HWND window, RECT *rect) DECLSPEC_HIDDEN;
+void surface_update_draw_binding(struct wined3d_surface *surface) DECLSPEC_HIDDEN;
+HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const POINT *dst_point,
+        struct wined3d_surface *src_surface, const RECT *src_rect) DECLSPEC_HIDDEN;
+
+void get_drawable_size_swapchain(const struct wined3d_context *context, UINT *width, UINT *height) DECLSPEC_HIDDEN;
+void get_drawable_size_backbuffer(const struct wined3d_context *context, UINT *width, UINT *height) DECLSPEC_HIDDEN;
+void get_drawable_size_fbo(const struct wined3d_context *context, UINT *width, UINT *height) DECLSPEC_HIDDEN;
+
+void draw_textured_quad(const struct wined3d_surface *src_surface, struct wined3d_context *context,
+        const RECT *src_rect, const RECT *dst_rect, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN;
+void flip_surface(struct wined3d_surface *front, struct wined3d_surface *back) DECLSPEC_HIDDEN;
+
+/* Surface flags: */
+#define SFLAG_CONVERTED         0x00000001 /* Converted for color keying or palettized. */
+#define SFLAG_DISCARD           0x00000002 /* ??? */
+#define SFLAG_NONPOW2           0x00000004 /* Surface sizes are not a power of 2 */
+#define SFLAG_NORMCOORD         0x00000008 /* Set if GL texture coordinates are normalized (non-texture rectangle). */
+#define SFLAG_LOCKABLE          0x00000010 /* Surface can be locked. */
+#define SFLAG_DYNLOCK           0x00000020 /* Surface is often locked by the application. */
+#define SFLAG_PIN_SYSMEM        0x00000040 /* Keep the surface in sysmem, at the same address. */
+#define SFLAG_DCINUSE           0x00000080 /* Set between GetDC and ReleaseDC calls. */
+#define SFLAG_LOST              0x00000100 /* Surface lost flag for ddraw. */
+#define SFLAG_GLCKEY            0x00000200 /* The GL texture was created with a color key. */
+#define SFLAG_CLIENT            0x00000400 /* GL_APPLE_client_storage is used with this surface. */
+#define SFLAG_INOVERLAYDRAW     0x00000800 /* Overlay drawing is in progress. Recursion prevention. */
+#define SFLAG_DIBSECTION        0x00001000 /* Has a DIB section attached for GetDC. */
+#define SFLAG_USERPTR           0x00002000 /* The application allocated the memory for this surface. */
+#define SFLAG_ALLOCATED         0x00004000 /* A GL texture is allocated for this surface. */
+#define SFLAG_SRGBALLOCATED     0x00008000 /* A sRGB GL texture is allocated for this surface. */
+#define SFLAG_PBO               0x00010000 /* The surface has a PBO. */
+#define SFLAG_INSYSMEM          0x00020000 /* The system memory copy is current. */
+#define SFLAG_INTEXTURE         0x00040000 /* The GL texture is current. */
+#define SFLAG_INSRGBTEX         0x00080000 /* The GL sRGB texture is current. */
+#define SFLAG_INDRAWABLE        0x00100000 /* The GL drawable is current. */
+#define SFLAG_INRB_MULTISAMPLE  0x00200000 /* The multisample renderbuffer is current. */
+#define SFLAG_INRB_RESOLVED     0x00400000 /* The resolved renderbuffer is current. */
+#define SFLAG_DISCARDED         0x00800000 /* Surface was discarded, allocating new location is enough. */
+
+#ifdef VBOX_WITH_WDDM
+# define SFLAG_CLIENTMEM        0x10000000 /* SYSMEM surface using client-supplied memory buffer */
+# define SFLAG_DONOTFREE_VBOXWDDM SFLAG_CLIENTMEM
+#else
+# define SFLAG_DONOTFREE_VBOXWDDM 0
+#endif
+
+/* In some conditions the surface memory must not be freed:
+ * SFLAG_CONVERTED: Converting the data back would take too long
+ * SFLAG_DIBSECTION: The dib code manages the memory
+ * SFLAG_DYNLOCK: Avoid freeing the data for performance
+ * SFLAG_PBO: PBOs don't use 'normal' memory. It is either allocated by the driver or must be NULL.
+ * SFLAG_CLIENT: OpenGL uses our memory as backup
+ */
+#define SFLAG_DONOTFREE     (SFLAG_CONVERTED        | \
+                             SFLAG_DYNLOCK          | \
+                             SFLAG_CLIENT           | \
+                             SFLAG_DIBSECTION       | \
+                             SFLAG_USERPTR          | \
+                             SFLAG_PBO              | \
+                             SFLAG_PIN_SYSMEM       | \
+                             /* #ifdef VBOX */        \
+                             SFLAG_DONOTFREE_VBOXWDDM \
+                             /* #endif */             \
+                             )
+
+#define SFLAG_LOCATIONS     (SFLAG_INSYSMEM         | \
+                             SFLAG_INTEXTURE        | \
+                             SFLAG_INSRGBTEX        | \
+                             SFLAG_INDRAWABLE       | \
+                             SFLAG_INRB_MULTISAMPLE | \
+                             SFLAG_INRB_RESOLVED)
+
+enum wined3d_conversion_type
+{
+    WINED3D_CT_NONE,
+    WINED3D_CT_PALETTED,
+    WINED3D_CT_PALETTED_CK,
+    WINED3D_CT_CK_565,
+    WINED3D_CT_CK_5551,
+    WINED3D_CT_CK_RGB24,
+    WINED3D_CT_RGB32_888,
+    WINED3D_CT_CK_ARGB32,
+};
+
+void d3dfmt_p8_init_palette(const struct wined3d_surface *surface, BYTE table[256][4], BOOL colorkey) DECLSPEC_HIDDEN;
+
+struct wined3d_sampler
+{
+    LONG refcount;
+    void *parent;
+};
+
+struct wined3d_vertex_declaration_element
+{
+    const struct wined3d_format *format;
+    BOOL ffp_valid;
+    WORD input_slot;
+    WORD offset;
+    UINT output_slot;
+    BYTE method;
+    BYTE usage;
+    BYTE usage_idx;
+};
+
+struct wined3d_vertex_declaration
+{
+    LONG ref;
+    void *parent;
+    const struct wined3d_parent_ops *parent_ops;
+    struct wined3d_device *device;
+
+    struct wined3d_vertex_declaration_element *elements;
+    UINT element_count;
+
+    BOOL                    position_transformed;
+    BOOL                    half_float_conv_needed;
+};
+
+struct wined3d_saved_states
+{
+    DWORD transform[(HIGHEST_TRANSFORMSTATE >> 5) + 1];
+    WORD streamSource;                          /* MAX_STREAMS, 16 */
+    WORD streamFreq;                            /* MAX_STREAMS, 16 */
+    DWORD renderState[(WINEHIGHEST_RENDER_STATE >> 5) + 1];
+    DWORD textureState[MAX_TEXTURES];           /* WINED3D_HIGHEST_TEXTURE_STATE + 1, 18 */
+    WORD samplerState[MAX_COMBINED_SAMPLERS];   /* WINED3D_HIGHEST_SAMPLER_STATE + 1, 14 */
+    DWORD clipplane;                            /* WINED3DMAXUSERCLIPPLANES, 32 */
+    WORD pixelShaderConstantsB;                 /* MAX_CONST_B, 16 */
+    WORD pixelShaderConstantsI;                 /* MAX_CONST_I, 16 */
+    BOOL *pixelShaderConstantsF;
+    WORD vertexShaderConstantsB;                /* MAX_CONST_B, 16 */
+    WORD vertexShaderConstantsI;                /* MAX_CONST_I, 16 */
+    BOOL *vertexShaderConstantsF;
+    DWORD textures : 20;                        /* MAX_COMBINED_SAMPLERS, 20 */
+    DWORD primitive_type : 1;
+    DWORD indices : 1;
+    DWORD material : 1;
+    DWORD viewport : 1;
+    DWORD vertexDecl : 1;
+    DWORD pixelShader : 1;
+    DWORD vertexShader : 1;
+    DWORD scissorRect : 1;
+    DWORD padding : 4;
+};
+
+struct StageState {
+    DWORD stage;
+    DWORD state;
+};
+
+struct wined3d_stream_output
+{
+    struct wined3d_buffer *buffer;
+    UINT offset;
+};
+
+struct wined3d_stream_state
+{
+    struct wined3d_buffer *buffer;
+    UINT offset;
+    UINT stride;
+    UINT frequency;
+    UINT flags;
+};
+
+struct wined3d_state
+{
+    const struct wined3d_fb_state *fb;
+
+    struct wined3d_vertex_declaration *vertex_declaration;
+    struct wined3d_stream_output stream_output[MAX_STREAM_OUT];
+    struct wined3d_stream_state streams[MAX_STREAMS + 1 /* tesselated pseudo-stream */];
+    struct wined3d_buffer *index_buffer;
+    enum wined3d_format_id index_format;
+    INT base_vertex_index;
+    INT load_base_vertex_index; /* Non-indexed drawing needs 0 here, indexed needs base_vertex_index. */
+    GLenum gl_primitive_type;
+
+    struct wined3d_shader *vertex_shader;
+    struct wined3d_buffer *vs_cb[MAX_CONSTANT_BUFFERS];
+    struct wined3d_sampler *vs_sampler[MAX_SAMPLER_OBJECTS];
+    BOOL vs_consts_b[MAX_CONST_B];
+    INT vs_consts_i[MAX_CONST_I * 4];
+    float *vs_consts_f;
+
+    struct wined3d_shader *geometry_shader;
+    struct wined3d_buffer *gs_cb[MAX_CONSTANT_BUFFERS];
+    struct wined3d_sampler *gs_sampler[MAX_SAMPLER_OBJECTS];
+
+    struct wined3d_shader *pixel_shader;
+    struct wined3d_buffer *ps_cb[MAX_CONSTANT_BUFFERS];
+    struct wined3d_sampler *ps_sampler[MAX_SAMPLER_OBJECTS];
+    BOOL ps_consts_b[MAX_CONST_B];
+    INT ps_consts_i[MAX_CONST_I * 4];
+    float *ps_consts_f;
+
+    struct wined3d_texture *textures[MAX_COMBINED_SAMPLERS];
+    DWORD sampler_states[MAX_COMBINED_SAMPLERS][WINED3D_HIGHEST_SAMPLER_STATE + 1];
+    DWORD texture_states[MAX_TEXTURES][WINED3D_HIGHEST_TEXTURE_STATE + 1];
+    DWORD lowest_disabled_stage;
+
+    struct wined3d_matrix transforms[HIGHEST_TRANSFORMSTATE + 1];
+    struct wined3d_vec4 clip_planes[MAX_CLIPPLANES];
+    struct wined3d_material material;
+    struct wined3d_viewport viewport;
+    RECT scissor_rect;
+
+    /* Light hashmap . Collisions are handled using standard wine double linked lists */
+#define LIGHTMAP_SIZE 43 /* Use of a prime number recommended. Set to 1 for a linked list! */
+#define LIGHTMAP_HASHFUNC(x) ((x) % LIGHTMAP_SIZE) /* Primitive and simple function */
+    struct list light_map[LIGHTMAP_SIZE]; /* Hash map containing the lights */
+    const struct wined3d_light_info *lights[MAX_ACTIVE_LIGHTS]; /* Map of opengl lights to d3d lights */
+
+    DWORD render_states[WINEHIGHEST_RENDER_STATE + 1];
+};
+
+struct wined3d_stateblock
+{
+    LONG                      ref;     /* Note: Ref counting not required */
+    struct wined3d_device *device;
+
+    /* Array indicating whether things have been set or changed */
+    struct wined3d_saved_states changed;
+    struct wined3d_state state;
+
+    /* Contained state management */
+    DWORD                     contained_render_states[WINEHIGHEST_RENDER_STATE + 1];
+    unsigned int              num_contained_render_states;
+    DWORD                     contained_transform_states[HIGHEST_TRANSFORMSTATE + 1];
+    unsigned int              num_contained_transform_states;
+    DWORD                     contained_vs_consts_i[MAX_CONST_I];
+    unsigned int              num_contained_vs_consts_i;
+    DWORD                     contained_vs_consts_b[MAX_CONST_B];
+    unsigned int              num_contained_vs_consts_b;
+    DWORD                     *contained_vs_consts_f;
+    unsigned int              num_contained_vs_consts_f;
+    DWORD                     contained_ps_consts_i[MAX_CONST_I];
+    unsigned int              num_contained_ps_consts_i;
+    DWORD                     contained_ps_consts_b[MAX_CONST_B];
+    unsigned int              num_contained_ps_consts_b;
+    DWORD                     *contained_ps_consts_f;
+    unsigned int              num_contained_ps_consts_f;
+    struct StageState         contained_tss_states[MAX_TEXTURES * (WINED3D_HIGHEST_TEXTURE_STATE + 1)];
+    unsigned int              num_contained_tss_states;
+    struct StageState         contained_sampler_states[MAX_COMBINED_SAMPLERS * WINED3D_HIGHEST_SAMPLER_STATE];
+    unsigned int              num_contained_sampler_states;
+};
+
+void stateblock_init_contained_states(struct wined3d_stateblock *stateblock) DECLSPEC_HIDDEN;
+void stateblock_init_default_state(struct wined3d_stateblock *stateblock) DECLSPEC_HIDDEN;
+void stateblock_unbind_resources(struct wined3d_stateblock *stateblock) DECLSPEC_HIDDEN;
+
+/* Direct3D terminology with little modifications. We do not have an issued state
+ * because only the driver knows about it, but we have a created state because d3d
+ * allows GetData on a created issue, but opengl doesn't
+ */
+enum query_state {
+    QUERY_CREATED,
+    QUERY_SIGNALLED,
+    QUERY_BUILDING
+};
+
+struct wined3d_query_ops
+{
+    HRESULT (*query_get_data)(struct wined3d_query *query, void *data, DWORD data_size, DWORD flags);
+    HRESULT (*query_issue)(struct wined3d_query *query, DWORD flags);
+};
+
+struct wined3d_query
+{
+    LONG ref;
+    const struct wined3d_query_ops *query_ops;
+    struct wined3d_device *device;
+    enum query_state         state;
+    enum wined3d_query_type type;
+    DWORD data_size;
+    void                     *extendedData;
+};
+
+/* TODO: Add tests and support for FLOAT16_4 POSITIONT, D3DCOLOR position, other
+ * fixed function semantics as D3DCOLOR or FLOAT16 */
+enum wined3d_buffer_conversion_type
+{
+    CONV_NONE,
+    CONV_D3DCOLOR,
+    CONV_POSITIONT,
+};
+
+struct wined3d_map_range
+{
+    UINT offset;
+    UINT size;
+};
+
+#define WINED3D_BUFFER_OPTIMIZED    0x01    /* Optimize has been called for the buffer */
+#define WINED3D_BUFFER_HASDESC      0x02    /* A vertex description has been found */
+#define WINED3D_BUFFER_CREATEBO     0x04    /* Attempt to create a buffer object next PreLoad */
+#define WINED3D_BUFFER_DOUBLEBUFFER 0x08    /* Use a vbo and local allocated memory */
+#define WINED3D_BUFFER_FLUSH        0x10    /* Manual unmap flushing */
+#define WINED3D_BUFFER_DISCARD      0x20    /* A DISCARD lock has occurred since the last PreLoad */
+#define WINED3D_BUFFER_NOSYNC       0x40    /* All locks since the last PreLoad had NOOVERWRITE set */
+#define WINED3D_BUFFER_APPLESYNC    0x80    /* Using sync as in GL_APPLE_flush_buffer_range */
+
+struct wined3d_buffer
+{
+    struct wined3d_resource resource;
+
+    struct wined3d_buffer_desc desc;
+
+    GLuint buffer_object;
+    GLenum buffer_object_usage;
+    GLenum buffer_type_hint;
+    UINT buffer_object_size;
+    DWORD flags;
+
+    struct wined3d_map_range *maps;
+    ULONG maps_size, modified_areas;
+    struct wined3d_event_query *query;
+
+    /* conversion stuff */
+    UINT decl_change_count, full_conversion_count;
+    UINT draw_count;
+    UINT stride;                                            /* 0 if no conversion */
+#ifdef VBOX_WITH_WINE_FIX_BUFOFFSET
+    UINT offset;
+#endif
+    UINT conversion_stride;                                 /* 0 if no shifted conversion */
+    enum wined3d_buffer_conversion_type *conversion_map;    /* NULL if no conversion */
+};
+
+static inline struct wined3d_buffer *buffer_from_resource(struct wined3d_resource *resource)
+{
+    return CONTAINING_RECORD(resource, struct wined3d_buffer, resource);
+}
+
+void buffer_get_memory(struct wined3d_buffer *buffer, const struct wined3d_gl_info *gl_info,
+        struct wined3d_bo_address *data) DECLSPEC_HIDDEN;
+BYTE *buffer_get_sysmem(struct wined3d_buffer *This, const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN;
+
+struct wined3d_rendertarget_view
+{
+    LONG refcount;
+
+    struct wined3d_resource *resource;
+    void *parent;
+};
+
+struct wined3d_swapchain_ops
+{
+    void (*swapchain_present)(struct wined3d_swapchain *swapchain, const RECT *src_rect,
+            const RECT *dst_rect, const RGNDATA *dirty_region, DWORD flags);
+};
+
+struct wined3d_swapchain
+{
+    LONG ref;
+    void *parent;
+    const struct wined3d_parent_ops *parent_ops;
+    const struct wined3d_swapchain_ops *swapchain_ops;
+    struct wined3d_device *device;
+
+    struct wined3d_surface **back_buffers;
+    struct wined3d_surface *front_buffer;
+    struct wined3d_swapchain_desc desc;
+#ifndef VBOX_WITH_WDDM
+    DWORD orig_width, orig_height;
+    enum wined3d_format_id orig_fmt;
+    struct wined3d_gamma_ramp orig_gamma;
+#endif
+    BOOL render_to_fbo;
+    const struct wined3d_format *ds_format;
+
+    LONG prev_time, frames;   /* Performance tracking */
+
+#ifndef VBOX_WINE_WITH_SINGLE_CONTEXT
+    struct wined3d_context **context;
+    unsigned int num_contexts;
+#else
+    HDC hDC;
+#endif
+    HWND win_handle;
+#ifndef VBOX_WITH_WDDM
+    HWND device_window;
+
+    HDC backup_dc;
+    HWND backup_wnd;
+#endif
+};
+
+void x11_copy_to_screen(const struct wined3d_swapchain *swapchain, const RECT *rect) DECLSPEC_HIDDEN;
+
+struct wined3d_context *swapchain_get_context(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
+void swapchain_destroy_contexts(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
+HDC swapchain_get_backup_dc(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
+void swapchain_update_draw_bindings(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
+void swapchain_update_render_to_fbo(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
+
+#define DEFAULT_REFRESH_RATE 0
+
+/*****************************************************************************
+ * Utility function prototypes
+ */
+
+/* Trace routines */
+const char *debug_d3dformat(enum wined3d_format_id format_id) DECLSPEC_HIDDEN;
+const char *debug_d3ddevicetype(enum wined3d_device_type device_type) DECLSPEC_HIDDEN;
+const char *debug_d3dresourcetype(enum wined3d_resource_type resource_type) DECLSPEC_HIDDEN;
+const char *debug_d3dusage(DWORD usage) DECLSPEC_HIDDEN;
+const char *debug_d3dusagequery(DWORD usagequery) DECLSPEC_HIDDEN;
+const char *debug_d3ddeclmethod(enum wined3d_decl_method method) DECLSPEC_HIDDEN;
+const char *debug_d3ddeclusage(enum wined3d_decl_usage usage) DECLSPEC_HIDDEN;
+const char *debug_d3dprimitivetype(enum wined3d_primitive_type primitive_type) DECLSPEC_HIDDEN;
+const char *debug_d3drenderstate(enum wined3d_render_state state) DECLSPEC_HIDDEN;
+const char *debug_d3dsamplerstate(enum wined3d_sampler_state state) DECLSPEC_HIDDEN;
+const char *debug_d3dstate(DWORD state) DECLSPEC_HIDDEN;
+const char *debug_d3dtexturefiltertype(enum wined3d_texture_filter_type filter_type) DECLSPEC_HIDDEN;
+const char *debug_d3dtexturestate(enum wined3d_texture_stage_state state) DECLSPEC_HIDDEN;
+const char *debug_d3dtstype(enum wined3d_transform_state tstype) DECLSPEC_HIDDEN;
+const char *debug_d3dpool(enum wined3d_pool pool) DECLSPEC_HIDDEN;
+const char *debug_fbostatus(GLenum status) DECLSPEC_HIDDEN;
+const char *debug_glerror(GLenum error) DECLSPEC_HIDDEN;
+const char *debug_d3dtop(enum wined3d_texture_op d3dtop) DECLSPEC_HIDDEN;
+void dump_color_fixup_desc(struct color_fixup_desc fixup) DECLSPEC_HIDDEN;
+const char *debug_surflocation(DWORD flag) DECLSPEC_HIDDEN;
+
+BOOL is_invalid_op(const struct wined3d_state *state, int stage,
+        enum wined3d_texture_op op, DWORD arg1, DWORD arg2, DWORD arg3) DECLSPEC_HIDDEN;
+void set_tex_op_nvrc(const struct wined3d_gl_info *gl_info, const struct wined3d_state *state,
+        BOOL is_alpha, int stage, enum wined3d_texture_op op, DWORD arg1, DWORD arg2, DWORD arg3,
+        INT texture_idx, DWORD dst) DECLSPEC_HIDDEN;
+void set_texture_matrix(const struct wined3d_gl_info *gl_info, const float *smat, DWORD flags,
+        BOOL calculatedCoords, BOOL transformed, enum wined3d_format_id coordtype,
+        BOOL ffp_can_disable_proj) DECLSPEC_HIDDEN;
+void texture_activate_dimensions(const struct wined3d_texture *texture,
+        const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN;
+void sampler_texdim(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void tex_alphaop(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void apply_pixelshader(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void state_fogcolor(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void state_fogdensity(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void state_fogstartend(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void state_fog_fragpart(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void state_srgbwrite(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+
+void sampler_texmatrix(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void state_specularenable(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void transform_world(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void transform_view(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void transform_projection(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void transform_texture(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void state_ambient(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void viewport_vertexpart(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void state_clipping(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void light(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void vertexdeclaration(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void clipplane(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void state_psizemin_w(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void state_psizemin_ext(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void state_psizemin_arb(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void state_pointsprite_w(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void state_pointsprite(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void state_pscale(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+
+BOOL getColorBits(const struct wined3d_format *format,
+        BYTE *redSize, BYTE *greenSize, BYTE *blueSize, BYTE *alphaSize, BYTE *totalSize) DECLSPEC_HIDDEN;
+BOOL getDepthStencilBits(const struct wined3d_format *format,
+        BYTE *depthSize, BYTE *stencilSize) DECLSPEC_HIDDEN;
+GLenum gl_primitive_type_from_d3d(enum wined3d_primitive_type primitive_type) DECLSPEC_HIDDEN;
+
+/* Math utils */
+void multiply_matrix(struct wined3d_matrix *dest, const struct wined3d_matrix *src1,
+        const struct wined3d_matrix *src2) DECLSPEC_HIDDEN;
+UINT wined3d_log2i(UINT32 x) DECLSPEC_HIDDEN;
+unsigned int count_bits(unsigned int mask) DECLSPEC_HIDDEN;
+
+struct wined3d_shader_lconst
+{
+    struct list entry;
+    unsigned int idx;
+    DWORD value[4];
+};
+
+struct wined3d_shader_limits
+{
+    unsigned int sampler;
+    unsigned int constant_int;
+    unsigned int constant_float;
+    unsigned int constant_bool;
+    unsigned int packed_output;
+    unsigned int packed_input;
+};
+
+#ifdef __GNUC__
+#define PRINTF_ATTR(fmt,args) __attribute__((format (printf,fmt,args)))
+#else
+#define PRINTF_ATTR(fmt,args)
+#endif
+
+/* Base Shader utility functions. */
+int shader_addline(struct wined3d_shader_buffer *buffer, const char *fmt, ...) PRINTF_ATTR(2,3) DECLSPEC_HIDDEN;
+int shader_vaddline(struct wined3d_shader_buffer *buffer, const char *fmt, va_list args) DECLSPEC_HIDDEN;
+
+/* Vertex shader utility functions */
+BOOL vshader_get_input(const struct wined3d_shader *shader,
+        BYTE usage_req, BYTE usage_idx_req, unsigned int *regnum) DECLSPEC_HIDDEN;
+
+struct wined3d_vertex_shader
+{
+    struct wined3d_shader_attribute attributes[MAX_ATTRIBS];
+};
+
+struct wined3d_geometry_shader
+{
+    enum wined3d_primitive_type input_type;
+    enum wined3d_primitive_type output_type;
+    UINT vertices_out;
+};
+
+struct wined3d_pixel_shader
+{
+    /* Pixel shader input semantics */
+    DWORD input_reg_map[MAX_REG_INPUT];
+    BOOL input_reg_used[MAX_REG_INPUT];
+    unsigned int declared_in_count;
+
+    /* Some information about the shader behavior */
+    BOOL color0_mov;
+    DWORD color0_reg;
+};
+
+struct wined3d_shader
+{
+    LONG ref;
+    struct wined3d_shader_limits limits;
+    DWORD *function;
+    UINT functionLength;
+    BOOL load_local_constsF;
+    const struct wined3d_shader_frontend *frontend;
+    void *frontend_data;
+    void *backend_data;
+
+    void *parent;
+    const struct wined3d_parent_ops *parent_ops;
+
+    /* Programs this shader is linked with */
+    struct list linked_programs;
+
+    /* Immediate constants (override global ones) */
+    struct list constantsB;
+    struct list constantsF;
+    struct list constantsI;
+    struct wined3d_shader_reg_maps reg_maps;
+    BOOL lconst_inf_or_nan;
+
+    struct wined3d_shader_signature_element input_signature[max(MAX_ATTRIBS, MAX_REG_INPUT)];
+    struct wined3d_shader_signature_element output_signature[MAX_REG_OUTPUT];
+
+    /* Pointer to the parent device */
+    struct wined3d_device *device;
+    struct list shader_list_entry;
+
+    union
+    {
+        struct wined3d_vertex_shader vs;
+        struct wined3d_geometry_shader gs;
+        struct wined3d_pixel_shader ps;
+    } u;
+
+#ifdef VBOX_WINE_WITH_SHADER_CACHE
+    VBOXEXT_HASHCACHE_ENTRY CacheEntry;
+    uint32_t u32CacheDataInited;
+    uint32_t u32Hash;
+    PVBOXEXT_HASHCACHE shaderCache;
+#endif
+};
+
+void pixelshader_update_samplers(struct wined3d_shader *shader, WORD tex_types) DECLSPEC_HIDDEN;
+void find_ps_compile_args(const struct wined3d_state *state,
+        const struct wined3d_shader *shader, struct ps_compile_args *args) DECLSPEC_HIDDEN;
+
+void find_vs_compile_args(const struct wined3d_state *state,
+        const struct wined3d_shader *shader, struct vs_compile_args *args) DECLSPEC_HIDDEN;
+
+void shader_buffer_clear(struct wined3d_shader_buffer *buffer) DECLSPEC_HIDDEN;
+BOOL shader_buffer_init(struct wined3d_shader_buffer *buffer) DECLSPEC_HIDDEN;
+void shader_buffer_free(struct wined3d_shader_buffer *buffer) DECLSPEC_HIDDEN;
+void shader_dump_src_param(const struct wined3d_shader_src_param *param,
+        const struct wined3d_shader_version *shader_version) DECLSPEC_HIDDEN;
+void shader_dump_dst_param(const struct wined3d_shader_dst_param *param,
+        const struct wined3d_shader_version *shader_version) DECLSPEC_HIDDEN;
+unsigned int shader_find_free_input_register(const struct wined3d_shader_reg_maps *reg_maps,
+        unsigned int max) DECLSPEC_HIDDEN;
+void shader_generate_main(const struct wined3d_shader *shader, struct wined3d_shader_buffer *buffer,
+        const struct wined3d_shader_reg_maps *reg_maps, const DWORD *byte_code, void *backend_ctx) DECLSPEC_HIDDEN;
+BOOL shader_match_semantic(const char *semantic_name, enum wined3d_decl_usage usage) DECLSPEC_HIDDEN;
+
+static inline BOOL shader_is_scalar(const struct wined3d_shader_register *reg)
+{
+    switch (reg->type)
+    {
+        case WINED3DSPR_RASTOUT:
+            /* oFog & oPts */
+            if (reg->idx[0].offset)
+                return TRUE;
+            /* oPos */
+            return FALSE;
+
+        case WINED3DSPR_DEPTHOUT:   /* oDepth */
+        case WINED3DSPR_CONSTBOOL:  /* b# */
+        case WINED3DSPR_LOOP:       /* aL */
+        case WINED3DSPR_PREDICATE:  /* p0 */
+        case WINED3DSPR_PRIMID:     /* primID */
+            return TRUE;
+
+        case WINED3DSPR_MISCTYPE:
+            switch (reg->idx[0].offset)
+            {
+                case 0: /* vPos */
+                    return FALSE;
+                case 1: /* vFace */
+                    return TRUE;
+                default:
+                    return FALSE;
+            }
+
+        case WINED3DSPR_IMMCONST:
+            return reg->immconst_type == WINED3D_IMMCONST_SCALAR;
+
+        default:
+            return FALSE;
+    }
+}
+
+static inline void shader_get_position_fixup(const struct wined3d_context *context,
+        const struct wined3d_state *state, float *position_fixup)
+{
+    position_fixup[0] = 1.0f;
+    position_fixup[1] = 1.0f;
+    position_fixup[2] = (63.0f / 64.0f) / state->viewport.width;
+    position_fixup[3] = -(63.0f / 64.0f) / state->viewport.height;
+
+    if (context->render_offscreen)
+    {
+        position_fixup[1] *= -1.0f;
+        position_fixup[3] *= -1.0f;
+    }
+}
+
+static inline BOOL shader_constant_is_local(const struct wined3d_shader *shader, DWORD reg)
+{
+    struct wined3d_shader_lconst *lconst;
+
+    if (shader->load_local_constsF)
+        return FALSE;
+
+    LIST_FOR_EACH_ENTRY(lconst, &shader->constantsF, struct wined3d_shader_lconst, entry)
+    {
+        if (lconst->idx == reg)
+            return TRUE;
+    }
+
+    return FALSE;
+}
+
+/* Using additional shader constants (uniforms in GLSL / program environment
+ * or local parameters in ARB) is costly:
+ * ARB only knows float4 parameters and GLSL compiler are not really smart
+ * when it comes to efficiently pack float2 uniforms, so no space is wasted
+ * (in fact most compilers map a float2 to a full float4 uniform).
+ *
+ * For NP2 texcoord fixup we only need 2 floats (width and height) for each
+ * 2D texture used in the shader. We therefore pack fixup info for 2 textures
+ * into a single shader constant (uniform / program parameter).
+ *
+ * This structure is shared between the GLSL and the ARB backend.*/
+struct ps_np2fixup_info {
+    unsigned char     idx[MAX_FRAGMENT_SAMPLERS]; /* indices to the real constant */
+    WORD              active; /* bitfield indicating if we can apply the fixup */
+    WORD              num_consts;
+};
+
+#ifdef VBOX_WINE_WITH_SHADER_CACHE
+struct wined3d_shader * vertexshader_check_cached(struct wined3d_device *device, struct wined3d_shader *object) DECLSPEC_HIDDEN;
+struct wined3d_shader * pixelshader_check_cached(struct wined3d_device *device, struct wined3d_shader *object) DECLSPEC_HIDDEN;
+void shader_chaches_init(struct wined3d_device *device) DECLSPEC_HIDDEN;
+void shader_chaches_term(struct wined3d_device *device) DECLSPEC_HIDDEN;
+#endif
+
+/* sRGB correction constants */
+static const float srgb_cmp = 0.0031308f;
+static const float srgb_mul_low = 12.92f;
+static const float srgb_pow = 0.41666f;
+static const float srgb_mul_high = 1.055f;
+static const float srgb_sub_high = 0.055f;
+
+struct wined3d_palette
+{
+    LONG ref;
+    void *parent;
+    struct wined3d_device *device;
+
+    HPALETTE                   hpal;
+    WORD                       palVersion;     /*|               */
+    WORD                       palNumEntries;  /*|  LOGPALETTE   */
+    PALETTEENTRY               palents[256];   /*|               */
+    /* This is to store the palette in 'screen format' */
+    int                        screen_palents[256];
+    DWORD flags;
+};
+
+/* DirectDraw utility functions */
+extern enum wined3d_format_id pixelformat_for_depth(DWORD depth) DECLSPEC_HIDDEN;
+
+/*****************************************************************************
+ * Pixel format management
+ */
+
+/* WineD3D pixel format flags */
+#define WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING    0x00000001
+#define WINED3DFMT_FLAG_FILTERING                   0x00000002
+#define WINED3DFMT_FLAG_DEPTH                       0x00000004
+#define WINED3DFMT_FLAG_STENCIL                     0x00000008
+#define WINED3DFMT_FLAG_RENDERTARGET                0x00000010
+#define WINED3DFMT_FLAG_FBO_ATTACHABLE              0x00000040
+#define WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB         0x00000080
+#define WINED3DFMT_FLAG_GETDC                       0x00000100
+#define WINED3DFMT_FLAG_FLOAT                       0x00000200
+#define WINED3DFMT_FLAG_BUMPMAP                     0x00000400
+#define WINED3DFMT_FLAG_SRGB_READ                   0x00000800
+#define WINED3DFMT_FLAG_SRGB_WRITE                  0x00001000
+#define WINED3DFMT_FLAG_VTF                         0x00002000
+#define WINED3DFMT_FLAG_SHADOW                      0x00004000
+#define WINED3DFMT_FLAG_COMPRESSED                  0x00008000
+#define WINED3DFMT_FLAG_BROKEN_PITCH                0x00010000
+#define WINED3DFMT_FLAG_BLOCKS                      0x00020000
+#define WINED3DFMT_FLAG_HEIGHT_SCALE                0x00040000
+#define WINED3DFMT_FLAG_TEXTURE                     0x00080000
+
+struct wined3d_rational
+{
+    UINT numerator;
+    UINT denominator;
+};
+
+struct wined3d_format
+{
+    enum wined3d_format_id id;
+
+    DWORD red_size;
+    DWORD green_size;
+    DWORD blue_size;
+    DWORD alpha_size;
+    DWORD red_offset;
+    DWORD green_offset;
+    DWORD blue_offset;
+    DWORD alpha_offset;
+    UINT byte_count;
+    BYTE depth_size;
+    BYTE stencil_size;
+
+    UINT block_width;
+    UINT block_height;
+    UINT block_byte_count;
+
+    enum wined3d_ffp_emit_idx emit_idx;
+    GLint component_count;
+    GLenum gl_vtx_type;
+    GLint gl_vtx_format;
+    GLboolean gl_normalized;
+    unsigned int component_size;
+
+    GLint glInternal;
+    GLint glGammaInternal;
+    GLint rtInternal;
+    GLint glFormat;
+    GLint glType;
+    UINT  conv_byte_count;
+    unsigned int flags;
+    struct wined3d_rational height_scale;
+    struct color_fixup_desc color_fixup;
+    void (*convert)(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height);
+};
+
+const struct wined3d_format *wined3d_get_format(const struct wined3d_gl_info *gl_info,
+        enum wined3d_format_id format_id) DECLSPEC_HIDDEN;
+UINT wined3d_format_calculate_size(const struct wined3d_format *format,
+        UINT alignment, UINT width, UINT height) DECLSPEC_HIDDEN;
+DWORD wined3d_format_convert_from_float(const struct wined3d_surface *surface,
+        const struct wined3d_color *color) DECLSPEC_HIDDEN;
+
+static inline BOOL use_vs(const struct wined3d_state *state)
+{
+    /* Check stateblock->vertexDecl to allow this to be used from
+     * IWineD3DDeviceImpl_FindTexUnitMap(). This is safe because
+     * stateblock->vertexShader implies a vertex declaration instead of ddraw
+     * style strided data. */
+    return state->vertex_shader && !state->vertex_declaration->position_transformed;
+}
+
+static inline BOOL use_ps(const struct wined3d_state *state)
+{
+    return !!state->pixel_shader;
+}
+
+static inline void context_apply_state(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id)
+{
+    const struct StateEntry *state_table = context->state_table;
+    DWORD rep = state_table[state_id].representative;
+    state_table[rep].apply(context, state, rep);
+}
+
+/* The WNDCLASS-Name for the fake window which we use to retrieve the GL capabilities */
+#define WINED3D_OPENGL_WINDOW_CLASS_NAME "WineD3D_OpenGL"
+
+#define MAKEDWORD_VERSION(maj, min) (((maj & 0xffff) << 16) | (min & 0xffff))
+
+#ifdef VBOX_WINE_WITHOUT_LIBWINE
+#include <float.h>
+
+# define isnan(_a) (_isnan(_a))
+# define isinf(_a) (!_finite(_a))
+#endif
+
+#endif
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/wined3dwddm.def
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/wined3dwddm.def	(revision 46521)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/wined3dwddm.def	(revision 46521)
@@ -0,0 +1,260 @@
+; File generated automatically from ./dlls/wined3d/wined3d.spec; do not edit!
+
+EXPORTS
+  wined3d_check_depth_stencil_match
+  wined3d_check_device_format
+  wined3d_check_device_format_conversion
+  wined3d_check_device_multisample_type
+  wined3d_check_device_type
+  wined3d_create
+  wined3d_decref
+  wined3d_enum_adapter_modes
+  wined3d_get_adapter_count
+  wined3d_get_adapter_display_mode
+  wined3d_get_adapter_identifier
+  wined3d_get_adapter_mode_count
+  wined3d_get_adapter_monitor
+  wined3d_get_adapter_raster_status
+  wined3d_get_device_caps
+  wined3d_incref
+  wined3d_register_software_device
+  wined3d_set_adapter_display_mode
+  wined3d_buffer_create
+  wined3d_buffer_create_ib
+  wined3d_buffer_create_vb
+  wined3d_buffer_decref
+  wined3d_buffer_get_parent
+  wined3d_buffer_get_priority
+  wined3d_buffer_get_resource
+  wined3d_buffer_incref
+  wined3d_buffer_map
+  wined3d_buffer_preload
+  wined3d_buffer_set_priority
+  wined3d_buffer_unmap
+  wined3d_device_acquire_focus_window
+  wined3d_device_begin_scene
+  wined3d_device_begin_stateblock
+  wined3d_device_clear
+  wined3d_device_clear_rendertarget_view
+  wined3d_device_color_fill
+  wined3d_device_create
+  wined3d_device_decref
+  wined3d_device_draw_indexed_primitive
+  wined3d_device_draw_primitive
+  wined3d_device_end_scene
+  wined3d_device_end_stateblock
+  wined3d_device_evict_managed_resources
+  wined3d_device_get_available_texture_mem
+  wined3d_device_get_back_buffer
+  wined3d_device_get_base_vertex_index
+  wined3d_device_get_clip_plane
+  wined3d_device_get_clip_status
+  wined3d_device_get_creation_parameters
+  wined3d_device_get_depth_stencil
+  wined3d_device_get_device_caps
+  wined3d_device_get_display_mode
+  wined3d_device_get_front_buffer_data
+  wined3d_device_get_gamma_ramp
+  wined3d_device_get_index_buffer
+  wined3d_device_get_light
+  wined3d_device_get_light_enable
+  wined3d_device_get_material
+  wined3d_device_get_npatch_mode
+  wined3d_device_get_pixel_shader
+  wined3d_device_get_primitive_type
+  wined3d_device_get_ps_consts_b
+  wined3d_device_get_ps_consts_f
+  wined3d_device_get_ps_consts_i
+  wined3d_device_get_raster_status
+  wined3d_device_get_render_state
+  wined3d_device_get_render_target
+  wined3d_device_get_sampler_state
+  wined3d_device_get_scissor_rect
+  wined3d_device_get_software_vertex_processing
+  wined3d_device_get_stream_source
+  wined3d_device_get_stream_source_freq
+  wined3d_device_get_surface_from_dc
+  wined3d_device_get_swapchain
+  wined3d_device_get_swapchain_count
+  wined3d_device_get_texture
+  wined3d_device_get_texture_stage_state
+  wined3d_device_get_transform
+  wined3d_device_get_vertex_declaration
+  wined3d_device_get_vertex_shader
+  wined3d_device_get_viewport
+  wined3d_device_get_vs_consts_b
+  wined3d_device_get_vs_consts_f
+  wined3d_device_get_vs_consts_i
+  wined3d_device_incref
+  wined3d_device_init_3d
+  wined3d_device_init_gdi
+  wined3d_device_multiply_transform
+  wined3d_device_present
+  wined3d_device_process_vertices
+  wined3d_device_release_focus_window
+  wined3d_device_reset
+  wined3d_device_restore_fullscreen_window
+  wined3d_device_set_base_vertex_index
+  wined3d_device_set_clip_plane
+  wined3d_device_set_clip_status
+  wined3d_device_set_cursor_position
+  wined3d_device_set_cursor_properties
+  wined3d_device_set_depth_stencil
+  wined3d_device_set_dialog_box_mode
+  wined3d_device_set_gamma_ramp
+  wined3d_device_set_index_buffer
+  wined3d_device_set_light
+  wined3d_device_set_light_enable
+  wined3d_device_set_material
+  wined3d_device_set_multithreaded
+  wined3d_device_set_npatch_mode
+  wined3d_device_set_pixel_shader
+  wined3d_device_set_primitive_type
+  wined3d_device_set_ps_consts_b
+  wined3d_device_set_ps_consts_f
+  wined3d_device_set_ps_consts_i
+  wined3d_device_set_render_state
+  wined3d_device_set_render_target
+  wined3d_device_set_sampler_state
+  wined3d_device_set_scissor_rect
+  wined3d_device_set_software_vertex_processing
+  wined3d_device_set_stream_source
+  wined3d_device_set_stream_source_freq
+  wined3d_device_set_texture
+  wined3d_device_set_texture_stage_state
+  wined3d_device_set_transform
+  wined3d_device_set_vertex_declaration
+  wined3d_device_set_vertex_shader
+  wined3d_device_set_viewport
+  wined3d_device_set_vs_consts_b
+  wined3d_device_set_vs_consts_f
+  wined3d_device_set_vs_consts_i
+  wined3d_device_setup_fullscreen_window
+  wined3d_device_show_cursor
+  wined3d_device_uninit_3d
+  wined3d_device_uninit_gdi
+  wined3d_device_update_surface
+  wined3d_device_update_texture
+  wined3d_device_validate_device
+  wined3d_palette_create
+  wined3d_palette_decref
+  wined3d_palette_get_entries
+  wined3d_palette_get_flags
+  wined3d_palette_get_parent
+  wined3d_palette_incref
+  wined3d_palette_set_entries
+  wined3d_query_create
+  wined3d_query_decref
+  wined3d_query_get_data
+  wined3d_query_get_data_size
+  wined3d_query_get_type
+  wined3d_query_incref
+  wined3d_query_issue
+  wined3d_resource_free_private_data
+  wined3d_resource_get_desc
+  wined3d_resource_get_parent
+  wined3d_resource_get_private_data
+  wined3d_resource_set_private_data
+  wined3d_rendertarget_view_create
+  wined3d_rendertarget_view_decref
+  wined3d_rendertarget_view_get_parent
+  wined3d_rendertarget_view_get_resource
+  wined3d_rendertarget_view_incref
+  wined3d_shader_create_gs
+  wined3d_shader_create_ps
+  wined3d_shader_create_vs
+  wined3d_shader_decref
+  wined3d_shader_get_byte_code
+  wined3d_shader_get_parent
+  wined3d_shader_incref
+  wined3d_shader_set_local_constants_float
+  wined3d_stateblock_apply
+  wined3d_stateblock_capture
+  wined3d_stateblock_create
+  wined3d_stateblock_decref
+  wined3d_stateblock_incref
+  wined3d_surface_blt
+  wined3d_surface_create
+  wined3d_surface_decref
+  wined3d_surface_flip
+  wined3d_surface_from_resource
+  wined3d_surface_get_blt_status
+  wined3d_surface_get_flip_status
+  wined3d_surface_get_overlay_position
+  wined3d_surface_get_palette
+  wined3d_surface_get_parent
+  wined3d_surface_get_pitch
+  wined3d_surface_get_priority
+  wined3d_surface_get_render_target_data
+  wined3d_surface_get_resource
+  wined3d_surface_getdc
+  wined3d_surface_incref
+  wined3d_surface_is_lost
+  wined3d_surface_map
+  wined3d_surface_preload
+  wined3d_surface_releasedc
+  wined3d_surface_restore
+  wined3d_surface_set_color_key
+  wined3d_surface_set_mem
+  wined3d_surface_set_overlay_position
+  wined3d_surface_set_palette
+  wined3d_surface_set_priority
+  wined3d_surface_unmap
+  wined3d_surface_update_desc
+  wined3d_surface_update_overlay
+  wined3d_surface_update_overlay_z_order
+  wined3d_swapchain_create
+  wined3d_swapchain_decref
+  wined3d_swapchain_get_back_buffer
+  wined3d_swapchain_get_device
+  wined3d_swapchain_get_display_mode
+  wined3d_swapchain_get_front_buffer_data
+  wined3d_swapchain_get_gamma_ramp
+  wined3d_swapchain_get_parent
+  wined3d_swapchain_get_desc
+  wined3d_swapchain_get_raster_status
+  wined3d_swapchain_incref
+  wined3d_swapchain_present
+  wined3d_swapchain_set_gamma_ramp
+  wined3d_swapchain_set_window
+  wined3d_texture_add_dirty_region
+  wined3d_texture_create_2d
+  wined3d_texture_create_3d
+  wined3d_texture_create_cube
+  wined3d_texture_decref
+  wined3d_texture_generate_mipmaps
+  wined3d_texture_get_autogen_filter_type
+  wined3d_texture_get_level_count
+  wined3d_texture_get_lod
+  wined3d_texture_get_parent
+  wined3d_texture_get_priority
+  wined3d_texture_get_resource
+  wined3d_texture_get_sub_resource
+  wined3d_texture_incref
+  wined3d_texture_preload
+  wined3d_texture_set_autogen_filter_type
+  wined3d_texture_set_lod
+  wined3d_texture_set_priority
+  wined3d_vertex_declaration_create
+  wined3d_vertex_declaration_create_from_fvf
+  wined3d_vertex_declaration_decref
+  wined3d_vertex_declaration_get_parent
+  wined3d_vertex_declaration_incref
+  wined3d_volume_create
+  wined3d_volume_decref
+  wined3d_volume_from_resource
+  wined3d_volume_get_parent
+  wined3d_volume_get_priority
+  wined3d_volume_get_resource
+  wined3d_volume_incref
+  wined3d_volume_map
+  wined3d_volume_preload
+  wined3d_volume_set_priority
+  wined3d_volume_unmap
+  wined3d_device_flush
+  wined3d_device_flush_to_host
+  wined3d_device_finish
+  wined3d_device_blt_vol
+  wined3d_device_blt_voltex
+  wined3d_swapchain_present_rt
+  
