aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gallium/Makefile.am4
-rw-r--r--src/gallium/auxiliary/target-helpers/inline_sw_helper.h28
-rw-r--r--src/gallium/state_trackers/nine/Makefile.am13
-rw-r--r--src/gallium/state_trackers/nine/Makefile.sources71
-rw-r--r--src/gallium/state_trackers/nine/README78
-rw-r--r--src/gallium/state_trackers/nine/adapter9.c1091
-rw-r--r--src/gallium/state_trackers/nine/adapter9.h137
-rw-r--r--src/gallium/state_trackers/nine/authenticatedchannel9.c78
-rw-r--r--src/gallium/state_trackers/nine/authenticatedchannel9.h65
-rw-r--r--src/gallium/state_trackers/nine/basetexture9.c504
-rw-r--r--src/gallium/state_trackers/nine/basetexture9.h138
-rw-r--r--src/gallium/state_trackers/nine/cryptosession9.c115
-rw-r--r--src/gallium/state_trackers/nine/cryptosession9.h86
-rw-r--r--src/gallium/state_trackers/nine/cubetexture9.c274
-rw-r--r--src/gallium/state_trackers/nine/cubetexture9.h79
-rw-r--r--src/gallium/state_trackers/nine/device9.c3458
-rw-r--r--src/gallium/state_trackers/nine/device9.h801
-rw-r--r--src/gallium/state_trackers/nine/device9ex.c400
-rw-r--r--src/gallium/state_trackers/nine/device9ex.h149
-rw-r--r--src/gallium/state_trackers/nine/device9video.c62
-rw-r--r--src/gallium/state_trackers/nine/device9video.h57
-rw-r--r--src/gallium/state_trackers/nine/guid.c66
-rw-r--r--src/gallium/state_trackers/nine/guid.h36
-rw-r--r--src/gallium/state_trackers/nine/indexbuffer9.c218
-rw-r--r--src/gallium/state_trackers/nine/indexbuffer9.h88
-rw-r--r--src/gallium/state_trackers/nine/iunknown.c126
-rw-r--r--src/gallium/state_trackers/nine/iunknown.h153
-rw-r--r--src/gallium/state_trackers/nine/nine_debug.c104
-rw-r--r--src/gallium/state_trackers/nine/nine_debug.h135
-rw-r--r--src/gallium/state_trackers/nine/nine_defines.h55
-rw-r--r--src/gallium/state_trackers/nine/nine_dump.c813
-rw-r--r--src/gallium/state_trackers/nine/nine_dump.h52
-rw-r--r--src/gallium/state_trackers/nine/nine_ff.c2257
-rw-r--r--src/gallium/state_trackers/nine/nine_ff.h32
-rw-r--r--src/gallium/state_trackers/nine/nine_helpers.c100
-rw-r--r--src/gallium/state_trackers/nine/nine_helpers.h176
-rw-r--r--src/gallium/state_trackers/nine/nine_lock.c3319
-rw-r--r--src/gallium/state_trackers/nine/nine_lock.h51
-rw-r--r--src/gallium/state_trackers/nine/nine_pdata.h45
-rw-r--r--src/gallium/state_trackers/nine/nine_pipe.c410
-rw-r--r--src/gallium/state_trackers/nine/nine_pipe.h568
-rw-r--r--src/gallium/state_trackers/nine/nine_quirk.c49
-rw-r--r--src/gallium/state_trackers/nine/nine_quirk.h36
-rw-r--r--src/gallium/state_trackers/nine/nine_shader.c2959
-rw-r--r--src/gallium/state_trackers/nine/nine_shader.h142
-rw-r--r--src/gallium/state_trackers/nine/nine_state.c1489
-rw-r--r--src/gallium/state_trackers/nine/nine_state.h234
-rw-r--r--src/gallium/state_trackers/nine/nineexoverlayextension.c46
-rw-r--r--src/gallium/state_trackers/nine/nineexoverlayextension.h49
-rw-r--r--src/gallium/state_trackers/nine/pixelshader9.c172
-rw-r--r--src/gallium/state_trackers/nine/pixelshader9.h82
-rw-r--r--src/gallium/state_trackers/nine/query9.c358
-rw-r--r--src/gallium/state_trackers/nine/query9.h83
-rw-r--r--src/gallium/state_trackers/nine/resource9.c230
-rw-r--r--src/gallium/state_trackers/nine/resource9.h107
-rw-r--r--src/gallium/state_trackers/nine/stateblock9.c533
-rw-r--r--src/gallium/state_trackers/nine/stateblock9.h71
-rw-r--r--src/gallium/state_trackers/nine/surface9.c711
-rw-r--r--src/gallium/state_trackers/nine/surface9.h181
-rw-r--r--src/gallium/state_trackers/nine/swapchain9.c871
-rw-r--r--src/gallium/state_trackers/nine/swapchain9.h135
-rw-r--r--src/gallium/state_trackers/nine/swapchain9ex.c113
-rw-r--r--src/gallium/state_trackers/nine/swapchain9ex.h61
-rw-r--r--src/gallium/state_trackers/nine/texture9.c342
-rw-r--r--src/gallium/state_trackers/nine/texture9.h75
-rw-r--r--src/gallium/state_trackers/nine/vertexbuffer9.c223
-rw-r--r--src/gallium/state_trackers/nine/vertexbuffer9.h76
-rw-r--r--src/gallium/state_trackers/nine/vertexdeclaration9.c518
-rw-r--r--src/gallium/state_trackers/nine/vertexdeclaration9.h89
-rw-r--r--src/gallium/state_trackers/nine/vertexshader9.c177
-rw-r--r--src/gallium/state_trackers/nine/vertexshader9.h89
-rw-r--r--src/gallium/state_trackers/nine/volume9.c604
-rw-r--r--src/gallium/state_trackers/nine/volume9.h141
-rw-r--r--src/gallium/state_trackers/nine/volumetexture9.c253
-rw-r--r--src/gallium/state_trackers/nine/volumetexture9.h75
-rw-r--r--src/gallium/targets/d3dadapter9/Makefile.am131
-rw-r--r--src/gallium/targets/d3dadapter9/d3d.pc.in11
-rw-r--r--src/gallium/targets/d3dadapter9/d3dadapter9.sym6
-rw-r--r--src/gallium/targets/d3dadapter9/drm.c327
-rw-r--r--src/gallium/targets/d3dadapter9/getproc.c47
80 files changed, 28388 insertions, 0 deletions
diff --git a/src/gallium/Makefile.am b/src/gallium/Makefile.am
index c9b60d62730..81840b2081b 100644
--- a/src/gallium/Makefile.am
+++ b/src/gallium/Makefile.am
@@ -166,6 +166,10 @@ if HAVE_ST_XVMC
SUBDIRS += state_trackers/xvmc targets/xvmc
endif
+if HAVE_ST_NINE
+SUBDIRS += state_trackers/nine targets/d3dadapter9
+endif
+
##
## Don't forget to bundle the remaining (non autotools) state-trackers/targets
##
diff --git a/src/gallium/auxiliary/target-helpers/inline_sw_helper.h b/src/gallium/auxiliary/target-helpers/inline_sw_helper.h
index 8a144db09c3..d8cee2b2917 100644
--- a/src/gallium/auxiliary/target-helpers/inline_sw_helper.h
+++ b/src/gallium/auxiliary/target-helpers/inline_sw_helper.h
@@ -91,6 +91,34 @@ drisw_create_screen(struct drisw_loader_funcs *lf)
return screen;
}
#endif // DRI_TARGET
+
+#if defined(NINE_TARGET)
+#include "sw/wrapper/wrapper_sw_winsys.h"
+#include "target-helpers/inline_debug_helper.h"
+
+extern struct pipe_screen *ninesw_create_screen(struct pipe_screen *screen);
+
+INLINE struct pipe_screen *
+ninesw_create_screen(struct pipe_screen *pscreen)
+{
+ struct sw_winsys *winsys = NULL;
+ struct pipe_screen *screen = NULL;
+
+ winsys = wrapper_sw_winsys_wrap_pipe_screen(pscreen);
+ if (winsys == NULL)
+ return NULL;
+
+ screen = sw_screen_create(winsys);
+ if (screen == NULL) {
+ winsys->destroy(winsys);
+ return NULL;
+ }
+
+ screen = debug_screen_wrap(screen);
+ return screen;
+}
+#endif // NINE_TARGET
+
#endif // GALLIUM_SOFTPIPE
diff --git a/src/gallium/state_trackers/nine/Makefile.am b/src/gallium/state_trackers/nine/Makefile.am
new file mode 100644
index 00000000000..c0c75b34c59
--- /dev/null
+++ b/src/gallium/state_trackers/nine/Makefile.am
@@ -0,0 +1,13 @@
+include Makefile.sources
+include $(top_srcdir)/src/gallium/Automake.inc
+
+AM_CFLAGS = \
+ -I$(top_srcdir)/include/D3D9 \
+ $(GALLIUM_CFLAGS) \
+ $(VISIBILITY_CFLAGS)
+
+noinst_LTLIBRARIES = libninetracker.la
+
+libninetracker_la_SOURCES = $(C_SOURCES)
+
+EXTRA_DIST = README
diff --git a/src/gallium/state_trackers/nine/Makefile.sources b/src/gallium/state_trackers/nine/Makefile.sources
new file mode 100644
index 00000000000..b8219613f6c
--- /dev/null
+++ b/src/gallium/state_trackers/nine/Makefile.sources
@@ -0,0 +1,71 @@
+C_SOURCES := \
+ adapter9.c \
+ adapter9.h \
+ authenticatedchannel9.c \
+ authenticatedchannel9.h \
+ basetexture9.c \
+ basetexture9.h \
+ cryptosession9.c \
+ cryptosession9.h \
+ cubetexture9.c \
+ cubetexture9.h \
+ device9.c \
+ device9.h \
+ device9ex.c \
+ device9ex.h \
+ device9video.c \
+ device9video.h \
+ guid.c \
+ guid.h \
+ indexbuffer9.c \
+ indexbuffer9.h \
+ iunknown.c \
+ iunknown.h \
+ nine_debug.c \
+ nine_debug.h \
+ nine_defines.h \
+ nine_dump.c \
+ nine_dump.h \
+ nineexoverlayextension.c \
+ nineexoverlayextension.h \
+ nine_ff.c \
+ nine_ff.h \
+ nine_helpers.c \
+ nine_helpers.h \
+ nine_lock.c \
+ nine_lock.h \
+ nine_pdata.h \
+ nine_pipe.c \
+ nine_pipe.h \
+ nine_quirk.c \
+ nine_quirk.h \
+ nine_shader.c \
+ nine_shader.h \
+ nine_state.c \
+ nine_state.h \
+ pixelshader9.c \
+ pixelshader9.h \
+ query9.c \
+ query9.h \
+ resource9.c \
+ resource9.h \
+ stateblock9.c \
+ stateblock9.h \
+ surface9.c \
+ surface9.h \
+ swapchain9.c \
+ swapchain9ex.c \
+ swapchain9ex.h \
+ swapchain9.h \
+ texture9.c \
+ texture9.h \
+ vertexbuffer9.c \
+ vertexbuffer9.h \
+ vertexdeclaration9.c \
+ vertexdeclaration9.h \
+ vertexshader9.c \
+ vertexshader9.h \
+ volume9.c \
+ volume9.h \
+ volumetexture9.c \
+ volumetexture9.h
diff --git a/src/gallium/state_trackers/nine/README b/src/gallium/state_trackers/nine/README
new file mode 100644
index 00000000000..f10045c0deb
--- /dev/null
+++ b/src/gallium/state_trackers/nine/README
@@ -0,0 +1,78 @@
+Quickstart Guide
+
+*** Configure and build mesa
+CFLAGS="-m32" CXXFLAGS="-m32" ./autogen.sh --prefix=/usr \
+ --with-gallium-drivers=nouveau,r600,swrast --enable-nine \
+ --with-gallium-driver-dir="`pwd`/src/gallium/targets/pipe-loader/.libs" \
+ --enable-debug --enable-texture-float --with-dri-drivers= --disable-dri \
+ --disable-opengl --disable-egl --disable-vdpau --disable-xvmc --disable-gbm \
+ --disable-gallium-llvm
+make
+
+*** Then we create some symlinks to mesa:
+ln -s "`pwd`/lib/gallium/libd3dadapter9.so.0.0.0" /usr/lib/
+ln -s "`pwd`/lib/gallium/libd3dadapter9.so.0" /usr/lib/
+ln -s "`pwd`/lib/gallium/libd3dadapter9.so" /usr/lib/
+ln -s "`pwd`/include/d3dadapter" /usr/include/
+
+*** Clone and build a patched wine
+git clone [email protected]:iXit/wine.git
+./configure
+make
+
+*** And finally we create some symlinks to our patched wine files:
+for f in d3d9.dll gdi32.dll user32.dll wineps.drv winex11.drv;
+do
+ mv /usr/lib/wine/$f.so /usr/lib/wine/$f.so.old
+ ln -s "`pwd`/dlls/`basename -s .dll $f`/$f.so" /usr/lib/wine/
+done
+
+*** Activating it within wine
+regedit
+Navigate to HKCU\Software\Wine\Direct3D
+If it's not there, create it
+Create a new DWORD value called UseNative
+Set its value to 1
+
+Every Direct3D9 program will now try using nine before wined3d
+
+If you want to selectively enable it per-exe instead, use the key:
+HKCU\Software\Wine\AppDefaults\app.exe\Direct3D\UseNative
+where app.exe is the name of your .exe file
+
+
+*** HOW IT WORKS ***
+
+Nine implements the full IDirect3DDevice9 COM interface and a custom COM
+interface called ID3DAdapter9 which is used to implement a final IDirect3D9Ex
+COM interface.
+ID3DAdapter9 is completely devoid of window system code, meaning this can be
+provided by wine, Xlib, Wayland, etc. It's inadvisible to write a non-Windows
+backend though, as we don't want to encourage linux developers to use this API.
+
+The state tracker is compiled, along with pipe-loader, into a library called
+libd3dadapter9.so. This library loads pipe_[driver].so drivers on demand and
+exports a single symbol for getting a subsystem driver. Currently only DRM is
+supported.
+This library is then linked to the library implementing the IDirect3D9[Ex]
+interface and the actual Direct3D9 entry points (Direct3DCreate9[Ex])
+
+The implementation of IDirect3D9[Ex] lies within wine and coexists with
+wined3d. It's loaded on demand and so if it's not there, it doesn't have any
+drivers or something else is wrong, d3d9.dll will automatically revert to using
+wined3d.
+Whether or not it's even tried is determined by 2 DWORD registry keys.
+> HKCU\Software\Wine\Direct3D\UseNative
+> HKCU\Software\Wine\AppDefaults\app.exe\Direct3D\UseNative
+The former is the global on-switch. The latter is per-exe.
+
+The driver search path can be set at configure time with
+--with-gallium-driver-dir and overridden at runtime with D3D9_DRIVERS_PATH.
+Debugging information can be gotten with the WINEDEBUG channels d3d9 and
+d3dadapter, and state_tracker debug information can be gotten with NINE_DEBUG.
+Help on NINE_DEBUG is shown through NINE_DEBUG=help
+
+Finally, the ID3DPresent[Group] and ID3DAdapter9 interfaces are not set in
+stone, so feel free to hack on those as well as st/nine.
+
+Happy Hacking!
diff --git a/src/gallium/state_trackers/nine/adapter9.c b/src/gallium/state_trackers/nine/adapter9.c
new file mode 100644
index 00000000000..8d574deeca3
--- /dev/null
+++ b/src/gallium/state_trackers/nine/adapter9.c
@@ -0,0 +1,1091 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "adapter9.h"
+#include "device9ex.h"
+#include "nine_helpers.h"
+#include "nine_defines.h"
+#include "nine_pipe.h"
+#include "nine_dump.h"
+#include "util/u_math.h"
+#include "util/u_format.h"
+#include "util/u_dump.h"
+
+#include "pipe/p_screen.h"
+
+#define DBG_CHANNEL DBG_ADAPTER
+
+HRESULT
+NineAdapter9_ctor( struct NineAdapter9 *This,
+ struct NineUnknownParams *pParams,
+ struct d3dadapter9_context *pCTX )
+{
+ HRESULT hr = NineUnknown_ctor(&This->base, pParams);
+ if (FAILED(hr)) { return hr; }
+
+ DBG("This=%p pParams=%p pCTX=%p\n", This, pParams, pCTX);
+ nine_dump_D3DADAPTER_IDENTIFIER9(DBG_CHANNEL, &pCTX->identifier);
+
+ This->ctx = pCTX;
+ if (!This->ctx->hal->get_param(This->ctx->hal, PIPE_CAP_CLIP_HALFZ)) {
+ ERR("Driver doesn't support d3d9 coordinates\n");
+ return D3DERR_DRIVERINTERNALERROR;
+ }
+ if (This->ctx->ref &&
+ !This->ctx->ref->get_param(This->ctx->ref, PIPE_CAP_CLIP_HALFZ)) {
+ ERR("Warning: Sotware rendering driver doesn't support d3d9 coordinates\n");
+ }
+
+ return D3D_OK;
+}
+
+void
+NineAdapter9_dtor( struct NineAdapter9 *This )
+{
+ struct d3dadapter9_context *ctx = This->ctx;
+
+ DBG("This=%p\n", This);
+
+ NineUnknown_dtor(&This->base);
+
+ /* special case, call backend-specific dtor AFTER destroying this object
+ * completely. */
+ if (ctx) {
+ if (ctx->destroy) { ctx->destroy(ctx); }
+ }
+}
+
+static HRESULT
+NineAdapter9_GetScreen( struct NineAdapter9 *This,
+ D3DDEVTYPE DevType,
+ struct pipe_screen **ppScreen )
+{
+ const char *force_sw = getenv("D3D_ALWAYS_SOFTWARE");
+ switch (DevType) {
+ case D3DDEVTYPE_HAL:
+ if (force_sw && !strcmp(force_sw, "1") && This->ctx->ref) {
+ *ppScreen = This->ctx->ref;
+ break;
+ }
+ *ppScreen = This->ctx->hal;
+ break;
+
+ case D3DDEVTYPE_REF:
+ case D3DDEVTYPE_NULLREF:
+ case D3DDEVTYPE_SW:
+ if (force_sw && !strcmp(force_sw, "0")) {
+ *ppScreen = This->ctx->hal;
+ break;
+ }
+ *ppScreen = This->ctx->ref;
+ break;
+
+ default:
+ user_assert(!"Invalid device type", D3DERR_INVALIDCALL);
+ }
+
+ if (!*ppScreen) { return D3DERR_NOTAVAILABLE; }
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineAdapter9_GetAdapterIdentifier( struct NineAdapter9 *This,
+ DWORD Flags,
+ D3DADAPTER_IDENTIFIER9 *pIdentifier )
+{
+ DBG("This=%p Flags=%x pIdentifier=%p\n", This, Flags, pIdentifier);
+
+ /* regarding flags, MSDN has this to say:
+ * Flags sets the WHQLLevel member of D3DADAPTER_IDENTIFIER9. Flags can be
+ * set to either 0 or D3DENUM_WHQL_LEVEL. If D3DENUM_WHQL_LEVEL is
+ * specified, this call can connect to the Internet to download new
+ * Microsoft Windows Hardware Quality Labs (WHQL) certificates.
+ * so let's just ignore it. */
+ *pIdentifier = This->ctx->identifier;
+ return D3D_OK;
+}
+
+static INLINE boolean
+backbuffer_format( D3DFORMAT dfmt,
+ D3DFORMAT bfmt,
+ boolean win )
+{
+ if (dfmt == D3DFMT_A2R10G10B10 && win) { return FALSE; }
+
+ if ((dfmt == D3DFMT_A2R10G10B10 && bfmt == dfmt) ||
+ (dfmt == D3DFMT_X8R8G8B8 && (bfmt == dfmt ||
+ bfmt == D3DFMT_A8R8G8B8)) ||
+ (dfmt == D3DFMT_X1R5G5B5 && (bfmt == dfmt ||
+ bfmt == D3DFMT_A1R5G5B5)) ||
+ (dfmt == D3DFMT_R5G6B5 && bfmt == dfmt)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+HRESULT WINAPI
+NineAdapter9_CheckDeviceType( struct NineAdapter9 *This,
+ D3DDEVTYPE DevType,
+ D3DFORMAT AdapterFormat,
+ D3DFORMAT BackBufferFormat,
+ BOOL bWindowed )
+{
+ struct pipe_screen *screen;
+ enum pipe_format dfmt, bfmt;
+ HRESULT hr;
+
+ DBG("This=%p DevType=%s AdapterFormat=%s BackBufferFormat=%s "
+ "bWindowed=%i\n", This, nine_D3DDEVTYPE_to_str(DevType),
+ d3dformat_to_string(AdapterFormat),
+ d3dformat_to_string(BackBufferFormat), bWindowed);
+
+ user_assert(backbuffer_format(AdapterFormat, BackBufferFormat, bWindowed),
+ D3DERR_NOTAVAILABLE);
+
+ hr = NineAdapter9_GetScreen(This, DevType, &screen);
+ if (FAILED(hr)) { return hr; }
+
+ dfmt = d3d9_to_pipe_format(AdapterFormat);
+ bfmt = d3d9_to_pipe_format(BackBufferFormat);
+ if (dfmt == PIPE_FORMAT_NONE || bfmt == PIPE_FORMAT_NONE) {
+ DBG("Invalid Adapter/BackBufferFormat.\n");
+ return D3DERR_NOTAVAILABLE;
+ }
+
+ if (!screen->is_format_supported(screen, dfmt, PIPE_TEXTURE_2D, 1,
+ PIPE_BIND_DISPLAY_TARGET |
+ PIPE_BIND_SHARED) ||
+ !screen->is_format_supported(screen, bfmt, PIPE_TEXTURE_2D, 1,
+ PIPE_BIND_DISPLAY_TARGET |
+ PIPE_BIND_SHARED)) {
+ DBG("Unsupported Adapter/BackBufferFormat.\n");
+ return D3DERR_NOTAVAILABLE;
+ }
+
+ return D3D_OK;
+}
+
+static INLINE boolean
+display_format( D3DFORMAT fmt,
+ boolean win )
+{
+ /* http://msdn.microsoft.com/en-us/library/bb172558(v=VS.85).aspx#BackBuffer_or_Display_Formats */
+ static const D3DFORMAT allowed[] = {
+ D3DFMT_A2R10G10B10,
+ D3DFMT_X8R8G8B8,
+ D3DFMT_X1R5G5B5,
+ D3DFMT_R5G6B5,
+ };
+ unsigned i;
+
+ if (fmt == D3DFMT_A2R10G10B10 && win) { return FALSE; }
+
+ for (i = 0; i < sizeof(allowed)/sizeof(D3DFORMAT); i++) {
+ if (fmt == allowed[i]) { return TRUE; }
+ }
+ return FALSE;
+}
+
+HRESULT WINAPI
+NineAdapter9_CheckDeviceFormat( struct NineAdapter9 *This,
+ D3DDEVTYPE DeviceType,
+ D3DFORMAT AdapterFormat,
+ DWORD Usage,
+ D3DRESOURCETYPE RType,
+ D3DFORMAT CheckFormat )
+{
+ struct pipe_screen *screen;
+ HRESULT hr;
+ enum pipe_format pf;
+ enum pipe_texture_target target;
+ unsigned bind = 0;
+
+ /* Check adapter format. */
+
+ /* Nicer output if we only have the line at the end. */
+#if 1
+ DBG("This=%p DeviceType=%s AdapterFormat=%s\n", This,
+ nine_D3DDEVTYPE_to_str(DeviceType), d3dformat_to_string(AdapterFormat));
+#endif
+ user_assert(display_format(AdapterFormat, FALSE), D3DERR_INVALIDCALL);
+
+ hr = NineAdapter9_GetScreen(This, DeviceType, &screen);
+ if (FAILED(hr))
+ return hr;
+ pf = d3d9_to_pipe_format(AdapterFormat);
+ if (pf == PIPE_FORMAT_NONE ||
+ !screen->is_format_supported(screen, pf, PIPE_TEXTURE_2D, 0,
+ PIPE_BIND_DISPLAY_TARGET |
+ PIPE_BIND_SHARED)) {
+ DBG("AdapterFormat %s not available.\n",
+ d3dformat_to_string(AdapterFormat));
+ return D3DERR_NOTAVAILABLE;
+ }
+
+ /* Check actual format. */
+
+ switch (RType) {
+ case D3DRTYPE_SURFACE: target = PIPE_TEXTURE_2D; break;
+ case D3DRTYPE_TEXTURE: target = PIPE_TEXTURE_2D; break;
+ case D3DRTYPE_CUBETEXTURE: target = PIPE_TEXTURE_CUBE; break;
+ case D3DRTYPE_VOLUME: target = PIPE_TEXTURE_3D; break;
+ case D3DRTYPE_VOLUMETEXTURE: target = PIPE_TEXTURE_3D; break;
+ case D3DRTYPE_VERTEXBUFFER: target = PIPE_BUFFER; break;
+ case D3DRTYPE_INDEXBUFFER: target = PIPE_BUFFER; break;
+ default:
+ user_assert(0, D3DERR_INVALIDCALL);
+ }
+
+ bind = 0;
+ if (Usage & D3DUSAGE_RENDERTARGET) bind |= PIPE_BIND_RENDER_TARGET;
+ if (Usage & D3DUSAGE_DEPTHSTENCIL) bind |= PIPE_BIND_DEPTH_STENCIL;
+
+ /* API hack because setting RT[0] to NULL is forbidden */
+ if (CheckFormat == D3DFMT_NULL && bind == PIPE_BIND_RENDER_TARGET &&
+ (RType == D3DRTYPE_SURFACE ||
+ RType == D3DRTYPE_TEXTURE))
+ return D3D_OK;
+
+ if (Usage & D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING)
+ bind |= PIPE_BIND_BLENDABLE;
+
+ if (Usage & D3DUSAGE_DMAP) {
+ DBG("D3DUSAGE_DMAP not available\n");
+ return D3DERR_NOTAVAILABLE; /* TODO: displacement mapping */
+ }
+
+ switch (RType) {
+ case D3DRTYPE_TEXTURE: bind |= PIPE_BIND_SAMPLER_VIEW; break;
+ case D3DRTYPE_CUBETEXTURE: bind |= PIPE_BIND_SAMPLER_VIEW; break;
+ case D3DRTYPE_VOLUMETEXTURE: bind |= PIPE_BIND_SAMPLER_VIEW; break;
+ case D3DRTYPE_VERTEXBUFFER: bind |= PIPE_BIND_VERTEX_BUFFER; break;
+ case D3DRTYPE_INDEXBUFFER: bind |= PIPE_BIND_INDEX_BUFFER; break;
+ default:
+ break;
+ }
+
+
+ pf = d3d9_to_pipe_format(CheckFormat);
+ if (Usage & (D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_SRGBWRITE))
+ pf = util_format_srgb(pf);
+
+ DBG("Format=%s/%s Usage/Bind=%x/%d RType/Target=%u/%s\n", // replace %d to %s
+ d3dformat_to_string(CheckFormat), util_format_name(pf),
+ Usage, bind, // temporary simplified for merge, FIXME
+ /* Usage, util_dump_bind_flags(bind), */
+ RType, util_dump_tex_target(target, TRUE));
+
+ if (pf == PIPE_FORMAT_NONE ||
+ !screen->is_format_supported(screen, pf, target, 0, bind)) {
+ DBG("NOT AVAILABLE\n");
+ return D3DERR_NOTAVAILABLE;
+ }
+
+ /* if (Usage & D3DUSAGE_NONSECURE) { don't know the implications of this } */
+ /* if (Usage & D3DUSAGE_SOFTWAREPROCESSING) { we can always support this } */
+
+ if ((Usage & D3DUSAGE_AUTOGENMIPMAP) && !(bind & PIPE_BIND_SAMPLER_VIEW))
+ return D3DOK_NOAUTOGEN;
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineAdapter9_CheckDeviceMultiSampleType( struct NineAdapter9 *This,
+ D3DDEVTYPE DeviceType,
+ D3DFORMAT SurfaceFormat,
+ BOOL Windowed,
+ D3DMULTISAMPLE_TYPE MultiSampleType,
+ DWORD *pQualityLevels )
+{
+ struct pipe_screen *screen;
+ HRESULT hr;
+ enum pipe_format pf;
+ unsigned bind;
+
+ DBG("This=%p DeviceType=%s SurfaceFormat=%s Windowed=%i MultiSampleType=%u "
+ "pQualityLevels=%p\n", This, nine_D3DDEVTYPE_to_str(DeviceType),
+ d3dformat_to_string(SurfaceFormat), Windowed, MultiSampleType,
+ pQualityLevels);
+
+ hr = NineAdapter9_GetScreen(This, DeviceType, &screen);
+ if (FAILED(hr))
+ return hr;
+
+ pf = d3d9_to_pipe_format(SurfaceFormat);
+ bind = util_format_is_depth_or_stencil(pf) ?
+ PIPE_BIND_DEPTH_STENCIL : PIPE_BIND_RENDER_TARGET;
+
+ if (pf == PIPE_FORMAT_NONE ||
+ !screen->is_format_supported(screen, pf, PIPE_TEXTURE_2D,
+ MultiSampleType, bind)) {
+ DBG("%s with %u samples not available.\n",
+ d3dformat_to_string(SurfaceFormat), MultiSampleType);
+ return D3DERR_NOTAVAILABLE;
+ }
+
+ if (pQualityLevels)
+ *pQualityLevels = 1; /* gallium doesn't have quality levels */
+
+ return D3D_OK;
+}
+
+static INLINE boolean
+depth_stencil_format( D3DFORMAT fmt )
+{
+ static D3DFORMAT allowed[] = {
+ D3DFMT_D16_LOCKABLE,
+ D3DFMT_D32,
+ D3DFMT_D15S1,
+ D3DFMT_D24S8,
+ D3DFMT_D24X8,
+ D3DFMT_D24X4S4,
+ D3DFMT_D16,
+ D3DFMT_D32F_LOCKABLE,
+ D3DFMT_D24FS8,
+ D3DFMT_D32_LOCKABLE
+ };
+ unsigned i;
+
+ for (i = 0; i < sizeof(allowed)/sizeof(D3DFORMAT); i++) {
+ if (fmt == allowed[i]) { return TRUE; }
+ }
+ return FALSE;
+}
+
+HRESULT WINAPI
+NineAdapter9_CheckDepthStencilMatch( struct NineAdapter9 *This,
+ D3DDEVTYPE DeviceType,
+ D3DFORMAT AdapterFormat,
+ D3DFORMAT RenderTargetFormat,
+ D3DFORMAT DepthStencilFormat )
+{
+ struct pipe_screen *screen;
+ enum pipe_format dfmt, bfmt, zsfmt;
+ HRESULT hr;
+
+ DBG("This=%p DeviceType=%s AdapterFormat=%s "
+ "RenderTargetFormat=%s DepthStencilFormat=%s\n", This,
+ nine_D3DDEVTYPE_to_str(DeviceType), d3dformat_to_string(AdapterFormat),
+ d3dformat_to_string(RenderTargetFormat),
+ d3dformat_to_string(DepthStencilFormat));
+
+ user_assert(display_format(AdapterFormat, FALSE), D3DERR_NOTAVAILABLE);
+ user_assert(depth_stencil_format(DepthStencilFormat), D3DERR_NOTAVAILABLE);
+
+ hr = NineAdapter9_GetScreen(This, DeviceType, &screen);
+ if (FAILED(hr)) { return hr; }
+
+ dfmt = d3d9_to_pipe_format(AdapterFormat);
+ bfmt = d3d9_to_pipe_format(RenderTargetFormat);
+ if (RenderTargetFormat == D3DFMT_NULL)
+ bfmt = dfmt;
+ zsfmt = d3d9_to_pipe_format(DepthStencilFormat);
+ if (dfmt == PIPE_FORMAT_NONE ||
+ bfmt == PIPE_FORMAT_NONE ||
+ zsfmt == PIPE_FORMAT_NONE) {
+ return D3DERR_NOTAVAILABLE;
+ }
+
+ if (!screen->is_format_supported(screen, dfmt, PIPE_TEXTURE_2D, 0,
+ PIPE_BIND_DISPLAY_TARGET |
+ PIPE_BIND_SHARED) ||
+ !screen->is_format_supported(screen, bfmt, PIPE_TEXTURE_2D, 0,
+ PIPE_BIND_RENDER_TARGET) ||
+ !screen->is_format_supported(screen, zsfmt, PIPE_TEXTURE_2D, 0,
+ PIPE_BIND_DEPTH_STENCIL)) {
+ return D3DERR_NOTAVAILABLE;
+ }
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineAdapter9_CheckDeviceFormatConversion( struct NineAdapter9 *This,
+ D3DDEVTYPE DeviceType,
+ D3DFORMAT SourceFormat,
+ D3DFORMAT TargetFormat )
+{
+ /* MSDN says this tests whether a certain backbuffer format can be used in
+ * conjunction with a certain front buffer format. It's a little confusing
+ * but some one wiser might be able to figure this one out. XXX */
+ struct pipe_screen *screen;
+ enum pipe_format dfmt, bfmt;
+ HRESULT hr;
+
+ DBG("This=%p DeviceType=%s SourceFormat=%s TargetFormat=%s\n", This,
+ nine_D3DDEVTYPE_to_str(DeviceType),
+ d3dformat_to_string(SourceFormat), d3dformat_to_string(TargetFormat));
+
+ user_assert(backbuffer_format(TargetFormat, SourceFormat, FALSE),
+ D3DERR_NOTAVAILABLE);
+
+ hr = NineAdapter9_GetScreen(This, DeviceType, &screen);
+ if (FAILED(hr)) { return hr; }
+
+ dfmt = d3d9_to_pipe_format(TargetFormat);
+ bfmt = d3d9_to_pipe_format(SourceFormat);
+ if (dfmt == PIPE_FORMAT_NONE || bfmt == PIPE_FORMAT_NONE) {
+ return D3DERR_NOTAVAILABLE;
+ }
+ if (!screen->is_format_supported(screen, dfmt, PIPE_TEXTURE_2D, 1,
+ PIPE_BIND_DISPLAY_TARGET |
+ PIPE_BIND_SHARED) ||
+ !screen->is_format_supported(screen, bfmt, PIPE_TEXTURE_2D, 1,
+ PIPE_BIND_DISPLAY_TARGET |
+ PIPE_BIND_SHARED)) {
+ DBG("%s to %s not supported.\n",
+ d3dformat_to_string(SourceFormat),
+ d3dformat_to_string(TargetFormat));
+ return D3DERR_NOTAVAILABLE;
+ }
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineAdapter9_GetDeviceCaps( struct NineAdapter9 *This,
+ D3DDEVTYPE DeviceType,
+ D3DCAPS9 *pCaps )
+{
+ struct pipe_screen *screen;
+ boolean sm3, vs;
+ HRESULT hr;
+
+ DBG("This=%p DeviceType=%s pCaps=%p\n", This,
+ nine_D3DDEVTYPE_to_str(DeviceType), pCaps);
+
+ user_assert(pCaps, D3DERR_INVALIDCALL);
+
+ hr = NineAdapter9_GetScreen(This, DeviceType, &screen);
+ if (FAILED(hr)) {
+ DBG("Failed to get pipe_screen.\n");
+ return hr;
+ }
+
+#define D3DPIPECAP(pcap, d3dcap) \
+ (screen->get_param(screen, PIPE_CAP_##pcap) ? (d3dcap) : 0)
+
+#define D3DNPIPECAP(pcap, d3dcap) \
+ (screen->get_param(screen, PIPE_CAP_##pcap) ? 0 : (d3dcap))
+
+ sm3 = screen->get_param(screen, PIPE_CAP_SM3);
+ vs = !!(screen->get_shader_param(screen, PIPE_SHADER_VERTEX,
+ PIPE_SHADER_CAP_MAX_INSTRUCTIONS));
+
+ pCaps->DeviceType = DeviceType;
+
+ pCaps->AdapterOrdinal = 0;
+
+ pCaps->Caps = 0;
+
+ pCaps->Caps2 = D3DCAPS2_CANMANAGERESOURCE |
+ /* D3DCAPS2_CANSHARERESOURCE | */
+ /* D3DCAPS2_CANCALIBRATEGAMMA | */
+ D3DCAPS2_DYNAMICTEXTURES |
+ D3DCAPS2_FULLSCREENGAMMA |
+ D3DCAPS2_CANAUTOGENMIPMAP;
+
+ /* Note: D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD just means the
+ * backbuffer can be ARGB (instead of only XRGB) when we are fullscreen
+ * and in discard mode. */
+ pCaps->Caps3 = D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD |
+ D3DCAPS3_COPY_TO_VIDMEM |
+ D3DCAPS3_COPY_TO_SYSTEMMEM |
+ D3DCAPS3_LINEAR_TO_SRGB_PRESENTATION;
+
+ pCaps->PresentationIntervals = D3DPRESENT_INTERVAL_DEFAULT |
+ D3DPRESENT_INTERVAL_ONE |
+ D3DPRESENT_INTERVAL_TWO |
+ D3DPRESENT_INTERVAL_THREE |
+ D3DPRESENT_INTERVAL_FOUR |
+ D3DPRESENT_INTERVAL_IMMEDIATE;
+ pCaps->CursorCaps = D3DCURSORCAPS_COLOR | D3DCURSORCAPS_LOWRES;
+
+ pCaps->DevCaps = D3DDEVCAPS_CANBLTSYSTONONLOCAL |
+ D3DDEVCAPS_CANRENDERAFTERFLIP |
+ D3DDEVCAPS_DRAWPRIMITIVES2 |
+ D3DDEVCAPS_DRAWPRIMITIVES2EX |
+ D3DDEVCAPS_DRAWPRIMTLVERTEX |
+ D3DDEVCAPS_EXECUTESYSTEMMEMORY |
+ D3DDEVCAPS_EXECUTEVIDEOMEMORY |
+ D3DDEVCAPS_HWRASTERIZATION |
+ D3DDEVCAPS_HWTRANSFORMANDLIGHT |
+ /*D3DDEVCAPS_NPATCHES |*/
+ D3DDEVCAPS_PUREDEVICE |
+ /*D3DDEVCAPS_QUINTICRTPATCHES |*/
+ /*D3DDEVCAPS_RTPATCHES |*/
+ /*D3DDEVCAPS_RTPATCHHANDLEZERO |*/
+ /*D3DDEVCAPS_SEPARATETEXTUREMEMORIES |*/
+ /*D3DDEVCAPS_TEXTURENONLOCALVIDMEM |*/
+ D3DDEVCAPS_TEXTURESYSTEMMEMORY |
+ D3DDEVCAPS_TEXTUREVIDEOMEMORY |
+ D3DDEVCAPS_TLVERTEXSYSTEMMEMORY |
+ D3DDEVCAPS_TLVERTEXVIDEOMEMORY;
+
+ pCaps->PrimitiveMiscCaps = D3DPMISCCAPS_MASKZ |
+ D3DPMISCCAPS_CULLNONE | /* XXX */
+ D3DPMISCCAPS_CULLCW |
+ D3DPMISCCAPS_CULLCCW |
+ D3DPMISCCAPS_COLORWRITEENABLE |
+ D3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
+ D3DPMISCCAPS_CLIPTLVERTS |
+ D3DPMISCCAPS_TSSARGTEMP |
+ D3DPMISCCAPS_BLENDOP |
+ D3DPIPECAP(INDEP_BLEND_ENABLE, D3DPMISCCAPS_INDEPENDENTWRITEMASKS) |
+ /*D3DPMISCCAPS_PERSTAGECONSTANT |*/
+ /*D3DPMISCCAPS_POSTBLENDSRGBCONVERT |*/ /* TODO */
+ D3DPMISCCAPS_FOGANDSPECULARALPHA |
+ D3DPIPECAP(BLEND_EQUATION_SEPARATE, D3DPMISCCAPS_SEPARATEALPHABLEND) |
+ D3DPIPECAP(MIXED_COLORBUFFER_FORMATS, D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS) |
+ D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING |
+ /*D3DPMISCCAPS_FOGVERTEXCLAMPED*/0;
+
+ pCaps->RasterCaps =
+ D3DPIPECAP(ANISOTROPIC_FILTER, D3DPRASTERCAPS_ANISOTROPY) |
+ /*D3DPRASTERCAPS_COLORPERSPECTIVE |*/
+ D3DPRASTERCAPS_DITHER |
+ D3DPRASTERCAPS_DEPTHBIAS |
+ /*D3DPRASTERCAPS_FOGRANGE |*/
+ /*D3DPRASTERCAPS_FOGTABLE |*/
+ /*D3DPRASTERCAPS_FOGVERTEX |*/
+ D3DPRASTERCAPS_MIPMAPLODBIAS |
+ D3DPRASTERCAPS_MULTISAMPLE_TOGGLE |
+ D3DPRASTERCAPS_SCISSORTEST |
+ D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
+ /*D3DPRASTERCAPS_WBUFFER |*/
+ /*D3DPRASTERCAPS_WFOG |*/
+ /*D3DPRASTERCAPS_ZBUFFERLESSHSR |*/
+ /*D3DPRASTERCAPS_ZFOG |*/
+ D3DPRASTERCAPS_ZTEST;
+
+ pCaps->ZCmpCaps = D3DPCMPCAPS_NEVER |
+ D3DPCMPCAPS_LESS |
+ D3DPCMPCAPS_EQUAL |
+ D3DPCMPCAPS_LESSEQUAL |
+ D3DPCMPCAPS_GREATER |
+ D3DPCMPCAPS_NOTEQUAL |
+ D3DPCMPCAPS_GREATEREQUAL |
+ D3DPCMPCAPS_ALWAYS;
+
+ pCaps->SrcBlendCaps = D3DPBLENDCAPS_ZERO |
+ D3DPBLENDCAPS_ONE |
+ D3DPBLENDCAPS_SRCCOLOR |
+ D3DPBLENDCAPS_INVSRCCOLOR |
+ D3DPBLENDCAPS_SRCALPHA |
+ D3DPBLENDCAPS_INVSRCALPHA |
+ D3DPBLENDCAPS_DESTALPHA |
+ D3DPBLENDCAPS_INVDESTALPHA |
+ D3DPBLENDCAPS_DESTCOLOR |
+ D3DPBLENDCAPS_INVDESTCOLOR |
+ D3DPBLENDCAPS_SRCALPHASAT |
+ D3DPBLENDCAPS_BOTHSRCALPHA |
+ D3DPBLENDCAPS_BOTHINVSRCALPHA |
+ D3DPBLENDCAPS_BLENDFACTOR |
+ D3DPIPECAP(MAX_DUAL_SOURCE_RENDER_TARGETS,
+ D3DPBLENDCAPS_INVSRCCOLOR2 |
+ D3DPBLENDCAPS_SRCCOLOR2);
+
+ pCaps->DestBlendCaps = pCaps->SrcBlendCaps;
+
+ pCaps->AlphaCmpCaps = D3DPCMPCAPS_LESS |
+ D3DPCMPCAPS_EQUAL |
+ D3DPCMPCAPS_LESSEQUAL |
+ D3DPCMPCAPS_GREATER |
+ D3DPCMPCAPS_NOTEQUAL |
+ D3DPCMPCAPS_GREATEREQUAL |
+ D3DPCMPCAPS_ALWAYS;
+
+ /* FLAT caps not legal for D3D9. */
+ pCaps->ShadeCaps = D3DPSHADECAPS_COLORGOURAUDRGB |
+ D3DPSHADECAPS_SPECULARGOURAUDRGB |
+ D3DPSHADECAPS_ALPHAGOURAUDBLEND |
+ D3DPSHADECAPS_FOGGOURAUD;
+
+ pCaps->TextureCaps =
+ D3DPTEXTURECAPS_ALPHA |
+ D3DPTEXTURECAPS_ALPHAPALETTE |
+ D3DPTEXTURECAPS_PERSPECTIVE |
+ D3DPTEXTURECAPS_PROJECTED |
+ /*D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE |*/
+ D3DPTEXTURECAPS_CUBEMAP |
+ D3DPTEXTURECAPS_VOLUMEMAP |
+ D3DNPIPECAP(NPOT_TEXTURES, D3DPTEXTURECAPS_POW2) |
+ D3DNPIPECAP(NPOT_TEXTURES, D3DPTEXTURECAPS_NONPOW2CONDITIONAL) |
+ D3DNPIPECAP(NPOT_TEXTURES, D3DPTEXTURECAPS_CUBEMAP_POW2) |
+ D3DNPIPECAP(NPOT_TEXTURES, D3DPTEXTURECAPS_VOLUMEMAP_POW2) |
+ D3DPIPECAP(MAX_TEXTURE_2D_LEVELS, D3DPTEXTURECAPS_MIPMAP) |
+ D3DPIPECAP(MAX_TEXTURE_3D_LEVELS, D3DPTEXTURECAPS_MIPVOLUMEMAP) |
+ D3DPIPECAP(MAX_TEXTURE_CUBE_LEVELS, D3DPTEXTURECAPS_MIPCUBEMAP);
+
+ pCaps->TextureFilterCaps =
+ D3DPTFILTERCAPS_MINFPOINT |
+ D3DPTFILTERCAPS_MINFLINEAR |
+ D3DPIPECAP(ANISOTROPIC_FILTER, D3DPTFILTERCAPS_MINFANISOTROPIC) |
+ /*D3DPTFILTERCAPS_MINFPYRAMIDALQUAD |*/
+ /*D3DPTFILTERCAPS_MINFGAUSSIANQUAD |*/
+ D3DPTFILTERCAPS_MIPFPOINT |
+ D3DPTFILTERCAPS_MIPFLINEAR |
+ D3DPTFILTERCAPS_MAGFPOINT |
+ D3DPTFILTERCAPS_MAGFLINEAR |
+ D3DPIPECAP(ANISOTROPIC_FILTER, D3DPTFILTERCAPS_MAGFANISOTROPIC) |
+ /*D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD |*/
+ /*D3DPTFILTERCAPS_MAGFGAUSSIANQUAD*/0;
+
+ pCaps->CubeTextureFilterCaps = pCaps->TextureFilterCaps;
+ pCaps->VolumeTextureFilterCaps = pCaps->TextureFilterCaps;
+
+ pCaps->TextureAddressCaps =
+ D3DPTADDRESSCAPS_BORDER |
+ D3DPTADDRESSCAPS_INDEPENDENTUV |
+ D3DPTADDRESSCAPS_WRAP |
+ D3DPTADDRESSCAPS_MIRROR |
+ D3DPTADDRESSCAPS_CLAMP |
+ D3DPIPECAP(TEXTURE_MIRROR_CLAMP, D3DPTADDRESSCAPS_MIRRORONCE);
+
+ pCaps->VolumeTextureAddressCaps = pCaps->TextureAddressCaps;
+
+ pCaps->LineCaps =
+ D3DLINECAPS_ALPHACMP |
+ D3DLINECAPS_BLEND |
+ D3DLINECAPS_TEXTURE |
+ D3DLINECAPS_ZTEST |
+ D3DLINECAPS_FOG;
+ if (screen->get_paramf(screen, PIPE_CAPF_MAX_LINE_WIDTH_AA) > 0.0) {
+ pCaps->LineCaps |= D3DLINECAPS_ANTIALIAS;
+ }
+
+ pCaps->MaxTextureWidth =
+ 1 << (screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1);
+ pCaps->MaxTextureHeight = pCaps->MaxTextureWidth;
+ pCaps->MaxVolumeExtent =
+ 1 << (screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_3D_LEVELS) - 1);
+ /* XXX values from wine */
+ pCaps->MaxTextureRepeat = 32768;
+ pCaps->MaxTextureAspectRatio = pCaps->MaxTextureWidth;
+
+ pCaps->MaxAnisotropy =
+ (DWORD)screen->get_paramf(screen, PIPE_CAPF_MAX_TEXTURE_ANISOTROPY);
+
+ pCaps->MaxVertexW = 1.0f; /* XXX */
+ pCaps->GuardBandLeft = screen->get_paramf(screen,
+ PIPE_CAPF_GUARD_BAND_LEFT);
+ pCaps->GuardBandTop = screen->get_paramf(screen,
+ PIPE_CAPF_GUARD_BAND_TOP);
+ pCaps->GuardBandRight = screen->get_paramf(screen,
+ PIPE_CAPF_GUARD_BAND_RIGHT);
+ pCaps->GuardBandBottom = screen->get_paramf(screen,
+ PIPE_CAPF_GUARD_BAND_BOTTOM);
+ pCaps->ExtentsAdjust = 0.0f;
+
+ pCaps->StencilCaps =
+ D3DSTENCILCAPS_KEEP |
+ D3DSTENCILCAPS_ZERO |
+ D3DSTENCILCAPS_REPLACE |
+ D3DSTENCILCAPS_INCRSAT |
+ D3DSTENCILCAPS_DECRSAT |
+ D3DSTENCILCAPS_INVERT |
+ D3DSTENCILCAPS_INCR |
+ D3DSTENCILCAPS_DECR |
+ D3DPIPECAP(TWO_SIDED_STENCIL, D3DSTENCILCAPS_TWOSIDED);
+
+ pCaps->FVFCaps =
+ (D3DFVFCAPS_TEXCOORDCOUNTMASK & 0xff) |
+ /*D3DFVFCAPS_DONOTSTRIPELEMENTS |*/
+ D3DFVFCAPS_PSIZE;
+
+ /* XXX: Some of these are probably not in SM2.0 so cap them when I figure
+ * them out. For now leave them all enabled. */
+ pCaps->TextureOpCaps = D3DTEXOPCAPS_DISABLE |
+ D3DTEXOPCAPS_SELECTARG1 |
+ D3DTEXOPCAPS_SELECTARG2 |
+ D3DTEXOPCAPS_MODULATE |
+ D3DTEXOPCAPS_MODULATE2X |
+ D3DTEXOPCAPS_MODULATE4X |
+ D3DTEXOPCAPS_ADD |
+ D3DTEXOPCAPS_ADDSIGNED |
+ D3DTEXOPCAPS_ADDSIGNED2X |
+ D3DTEXOPCAPS_SUBTRACT |
+ D3DTEXOPCAPS_ADDSMOOTH |
+ D3DTEXOPCAPS_BLENDDIFFUSEALPHA |
+ D3DTEXOPCAPS_BLENDTEXTUREALPHA |
+ D3DTEXOPCAPS_BLENDFACTORALPHA |
+ D3DTEXOPCAPS_BLENDTEXTUREALPHAPM |
+ D3DTEXOPCAPS_BLENDCURRENTALPHA |
+ D3DTEXOPCAPS_PREMODULATE |
+ D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
+ D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
+ D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
+ D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA |
+ D3DTEXOPCAPS_BUMPENVMAP |
+ D3DTEXOPCAPS_BUMPENVMAPLUMINANCE |
+ D3DTEXOPCAPS_DOTPRODUCT3 |
+ D3DTEXOPCAPS_MULTIPLYADD |
+ D3DTEXOPCAPS_LERP;
+
+ pCaps->MaxTextureBlendStages = 8; /* XXX wine */
+ (DWORD)screen->get_param(screen, PIPE_CAP_BLEND_EQUATION_SEPARATE);
+ pCaps->MaxSimultaneousTextures = screen->get_shader_param(screen,
+ PIPE_SHADER_FRAGMENT, PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS);
+ if (pCaps->MaxSimultaneousTextures > NINE_MAX_SAMPLERS_PS)
+ pCaps->MaxSimultaneousTextures = NINE_MAX_SAMPLERS_PS;
+
+ pCaps->VertexProcessingCaps = D3DVTXPCAPS_TEXGEN |
+ /*D3DVTXPCAPS_TEXGEN_SPHEREMAP |*/
+ D3DVTXPCAPS_MATERIALSOURCE7 |
+ D3DVTXPCAPS_DIRECTIONALLIGHTS |
+ D3DVTXPCAPS_POSITIONALLIGHTS |
+ D3DVTXPCAPS_LOCALVIEWER |
+ D3DVTXPCAPS_TWEENING |
+ /*D3DVTXPCAPS_NO_TEXGEN_NONLOCALVIEWER*/0;
+
+ pCaps->MaxActiveLights = NINE_MAX_LIGHTS_ACTIVE; /* like GL_LIGHTi */
+ pCaps->MaxUserClipPlanes = PIPE_MAX_CLIP_PLANES;
+ pCaps->MaxVertexBlendMatrices = 4; /* 1 vec4 BLENDWEIGHT/INDICES input */
+ pCaps->MaxVertexBlendMatrixIndex = 7; /* D3DTS_WORLDMATRIX(0..7) */
+
+ pCaps->MaxPointSize = screen->get_paramf(screen, PIPE_CAPF_MAX_POINT_WIDTH);
+
+ pCaps->MaxPrimitiveCount = 0xFFFFF; /* <- wine, really 0xFFFFFFFF; */
+ pCaps->MaxVertexIndex = 0xFFFFF; /* <- wine, really 0xFFFFFFFF */
+ pCaps->MaxStreams =
+ _min(screen->get_shader_param(screen,
+ PIPE_SHADER_VERTEX, PIPE_SHADER_CAP_MAX_INPUTS),
+ 16);
+
+ pCaps->MaxStreamStride = screen->get_param(screen,
+ PIPE_CAP_MAX_VERTEX_ATTRIB_STRIDE);
+
+ pCaps->VertexShaderVersion = sm3 ? D3DVS_VERSION(3,0) : D3DVS_VERSION(2,0);
+ if (vs) {
+ /* VS 2 as well as 3.0 supports a minimum of 256 consts, no matter how
+ * much our architecture moans about it. The problem is that D3D9
+ * expects access to 16 int consts (i#), containing 3 components and
+ * 16 booleans (b#), containing only 1 component. This should be packed
+ * into 20 float vectors (16 for i# and 16/4 for b#), since gallium has
+ * removed support for the loop counter/boolean files. */
+ pCaps->MaxVertexShaderConst =
+ _min((screen->get_shader_param(screen, PIPE_SHADER_VERTEX,
+ PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) /
+ sizeof(float[4])) - 20,
+ NINE_MAX_CONST_F);
+ /* Fake the minimum cap for Windows. */
+ if (QUIRK(FAKE_CAPS)) {
+ pCaps->MaxVertexShaderConst = 256;
+ }
+ } else {
+ pCaps->MaxVertexShaderConst = 0;
+ }
+
+ pCaps->PixelShaderVersion = sm3 ? D3DPS_VERSION(3,0) : D3DPS_VERSION(2,0);
+ pCaps->PixelShader1xMaxValue = 8.0f; /* XXX: wine */
+
+ pCaps->DevCaps2 = D3DDEVCAPS2_STREAMOFFSET |
+ D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET |
+ D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES |
+ /*D3DDEVCAPS2_DMAPNPATCH |*/
+ /*D3DDEVCAPS2_ADAPTIVETESSRTPATCH |*/
+ /*D3DDEVCAPS2_ADAPTIVETESSNPATCH |*/
+ /*D3DDEVCAPS2_PRESAMPLEDDMAPNPATCH*/0;
+
+ pCaps->MasterAdapterOrdinal = 0;
+ pCaps->AdapterOrdinalInGroup = 0;
+ pCaps->NumberOfAdaptersInGroup = 1;
+
+ /* Undocumented ? */
+ pCaps->MaxNpatchTessellationLevel = 0.0f;
+ pCaps->Reserved5 = 0;
+
+ /* XXX: use is_format_supported */
+ pCaps->DeclTypes = D3DDTCAPS_UBYTE4 |
+ D3DDTCAPS_UBYTE4N |
+ D3DDTCAPS_SHORT2N |
+ D3DDTCAPS_SHORT4N |
+ D3DDTCAPS_USHORT2N |
+ D3DDTCAPS_USHORT4N |
+ D3DDTCAPS_UDEC3 |
+ D3DDTCAPS_DEC3N |
+ D3DDTCAPS_FLOAT16_2 |
+ D3DDTCAPS_FLOAT16_4;
+
+ pCaps->NumSimultaneousRTs =
+ screen->get_param(screen, PIPE_CAP_MAX_RENDER_TARGETS);
+ if (pCaps->NumSimultaneousRTs > NINE_MAX_SIMULTANEOUS_RENDERTARGETS)
+ pCaps->NumSimultaneousRTs = NINE_MAX_SIMULTANEOUS_RENDERTARGETS;
+
+ pCaps->StretchRectFilterCaps = D3DPTFILTERCAPS_MINFPOINT |
+ D3DPTFILTERCAPS_MINFLINEAR |
+ D3DPTFILTERCAPS_MAGFPOINT |
+ D3DPTFILTERCAPS_MAGFLINEAR;
+
+
+ pCaps->VS20Caps.Caps = D3DVS20CAPS_PREDICATION;
+ pCaps->VS20Caps.DynamicFlowControlDepth = /* XXX is this dynamic ? */
+ screen->get_shader_param(screen, PIPE_SHADER_VERTEX,
+ PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH);
+ pCaps->VS20Caps.NumTemps =
+ screen->get_shader_param(screen, PIPE_SHADER_VERTEX,
+ PIPE_SHADER_CAP_MAX_TEMPS);
+ pCaps->VS20Caps.StaticFlowControlDepth = /* XXX is this static ? */
+ screen->get_shader_param(screen, PIPE_SHADER_VERTEX,
+ PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH);
+
+ /* also check for values < 0, because get_shader_param may return unsigned */
+ if (pCaps->VS20Caps.DynamicFlowControlDepth > D3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH
+ || pCaps->VS20Caps.DynamicFlowControlDepth < 0)
+ pCaps->VS20Caps.DynamicFlowControlDepth = D3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH;
+ if (pCaps->VS20Caps.StaticFlowControlDepth > D3DVS20_MAX_STATICFLOWCONTROLDEPTH
+ || pCaps->VS20Caps.StaticFlowControlDepth < 0)
+ pCaps->VS20Caps.StaticFlowControlDepth = D3DVS20_MAX_STATICFLOWCONTROLDEPTH;
+ if (pCaps->VS20Caps.NumTemps > D3DVS20_MAX_NUMTEMPS)
+ pCaps->VS20Caps.NumTemps = D3DVS20_MAX_NUMTEMPS;
+ assert(pCaps->VS20Caps.DynamicFlowControlDepth >= D3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH);
+ assert(pCaps->VS20Caps.StaticFlowControlDepth >= D3DVS20_MIN_STATICFLOWCONTROLDEPTH);
+ assert(pCaps->VS20Caps.NumTemps >= D3DVS20_MIN_NUMTEMPS);
+
+
+ pCaps->PS20Caps.Caps = D3DPS20CAPS_ARBITRARYSWIZZLE |
+ D3DPS20CAPS_GRADIENTINSTRUCTIONS |
+ D3DPS20CAPS_PREDICATION;
+ if (screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
+ PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS) ==
+ screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
+ PIPE_SHADER_CAP_MAX_INSTRUCTIONS))
+ pCaps->PS20Caps.Caps |= D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
+ if (screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
+ PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS) ==
+ screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
+ PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS))
+ pCaps->PS20Caps.Caps |= D3DPS20CAPS_NODEPENDENTREADLIMIT;
+ pCaps->PS20Caps.DynamicFlowControlDepth = /* XXX is this dynamic ? */
+ screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
+ PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH);
+ pCaps->PS20Caps.NumTemps =
+ screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
+ PIPE_SHADER_CAP_MAX_TEMPS);
+ pCaps->PS20Caps.StaticFlowControlDepth = /* XXX is this static ? */
+ screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
+ PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH);
+ pCaps->PS20Caps.NumInstructionSlots =
+ screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
+ PIPE_SHADER_CAP_MAX_INSTRUCTIONS);
+
+ if (pCaps->PS20Caps.DynamicFlowControlDepth > D3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH
+ || pCaps->PS20Caps.DynamicFlowControlDepth < 0)
+ pCaps->PS20Caps.DynamicFlowControlDepth = D3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH;
+ if (pCaps->PS20Caps.StaticFlowControlDepth > D3DPS20_MAX_STATICFLOWCONTROLDEPTH
+ || pCaps->PS20Caps.StaticFlowControlDepth < 0)
+ pCaps->PS20Caps.StaticFlowControlDepth = D3DPS20_MAX_STATICFLOWCONTROLDEPTH;
+ if (pCaps->PS20Caps.NumTemps > D3DPS20_MAX_NUMTEMPS)
+ pCaps->PS20Caps.NumTemps = D3DPS20_MAX_NUMTEMPS;
+ if (pCaps->PS20Caps.NumInstructionSlots > D3DPS20_MAX_NUMINSTRUCTIONSLOTS)
+ pCaps->PS20Caps.NumInstructionSlots = D3DPS20_MAX_NUMINSTRUCTIONSLOTS;
+ assert(pCaps->PS20Caps.DynamicFlowControlDepth >= D3DPS20_MIN_DYNAMICFLOWCONTROLDEPTH);
+ assert(pCaps->PS20Caps.StaticFlowControlDepth >= D3DPS20_MIN_STATICFLOWCONTROLDEPTH);
+ assert(pCaps->PS20Caps.NumTemps >= D3DPS20_MIN_NUMTEMPS);
+ assert(pCaps->PS20Caps.NumInstructionSlots >= D3DPS20_MIN_NUMINSTRUCTIONSLOTS);
+
+
+ if (screen->get_shader_param(screen, PIPE_SHADER_VERTEX,
+ PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS))
+ pCaps->VertexTextureFilterCaps = pCaps->TextureFilterCaps &
+ ~(D3DPTFILTERCAPS_MIPFPOINT |
+ D3DPTFILTERCAPS_MIPFPOINT); /* XXX */
+ else
+ pCaps->VertexTextureFilterCaps = 0;
+
+ if (sm3) {
+ pCaps->MaxVertexShader30InstructionSlots =
+ screen->get_shader_param(screen, PIPE_SHADER_VERTEX,
+ PIPE_SHADER_CAP_MAX_INSTRUCTIONS);
+ pCaps->MaxPixelShader30InstructionSlots =
+ screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
+ PIPE_SHADER_CAP_MAX_INSTRUCTIONS);
+ if (pCaps->MaxVertexShader30InstructionSlots > D3DMAX30SHADERINSTRUCTIONS)
+ pCaps->MaxVertexShader30InstructionSlots = D3DMAX30SHADERINSTRUCTIONS;
+ if (pCaps->MaxPixelShader30InstructionSlots > D3DMAX30SHADERINSTRUCTIONS)
+ pCaps->MaxPixelShader30InstructionSlots = D3DMAX30SHADERINSTRUCTIONS;
+ assert(pCaps->MaxVertexShader30InstructionSlots >= D3DMIN30SHADERINSTRUCTIONS);
+ assert(pCaps->MaxPixelShader30InstructionSlots >= D3DMIN30SHADERINSTRUCTIONS);
+ } else {
+ pCaps->MaxVertexShader30InstructionSlots = 0;
+ pCaps->MaxPixelShader30InstructionSlots = 0;
+ }
+
+ /* 65535 is required, advertise more for GPUs with >= 2048 instruction slots */
+ pCaps->MaxVShaderInstructionsExecuted = MAX2(65535, pCaps->MaxVertexShader30InstructionSlots * 32);
+ pCaps->MaxPShaderInstructionsExecuted = MAX2(65535, pCaps->MaxPixelShader30InstructionSlots * 32);
+
+ if (debug_get_bool_option("NINE_DUMP_CAPS", FALSE))
+ nine_dump_D3DCAPS9(DBG_CHANNEL, pCaps);
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineAdapter9_CreateDevice( struct NineAdapter9 *This,
+ UINT RealAdapter,
+ D3DDEVTYPE DeviceType,
+ HWND hFocusWindow,
+ DWORD BehaviorFlags,
+ D3DPRESENT_PARAMETERS *pPresentationParameters,
+ IDirect3D9 *pD3D9,
+ ID3DPresentGroup *pPresentationGroup,
+ IDirect3DDevice9 **ppReturnedDeviceInterface )
+{
+ struct pipe_screen *screen;
+ D3DDEVICE_CREATION_PARAMETERS params;
+ D3DCAPS9 caps;
+ int major, minor;
+ HRESULT hr;
+
+ DBG("This=%p RealAdapter=%u DeviceType=%s hFocusWindow=%p "
+ "BehaviourFlags=%x " "pD3D9=%p pPresentationGroup=%p "
+ "ppReturnedDeviceInterface=%p\n", This,
+ RealAdapter, nine_D3DDEVTYPE_to_str(DeviceType), hFocusWindow,
+ BehaviorFlags, pD3D9, pPresentationGroup, ppReturnedDeviceInterface);
+
+ ID3DPresentGroup_GetVersion(pPresentationGroup, &major, &minor);
+ if (major != 1) {
+ ERR("Doesn't support the ID3DPresentGroup version %d %d. Expected 1\n",
+ major, minor);
+ return D3DERR_NOTAVAILABLE;
+ }
+
+ hr = NineAdapter9_GetScreen(This, DeviceType, &screen);
+ if (FAILED(hr)) {
+ DBG("Failed to get pipe_screen.\n");
+ return hr;
+ }
+
+ hr = NineAdapter9_GetDeviceCaps(This, DeviceType, &caps);
+ if (FAILED(hr)) {
+ DBG("Failed to get device caps.\n");
+ return hr;
+ }
+
+ params.AdapterOrdinal = RealAdapter;
+ params.DeviceType = DeviceType;
+ params.hFocusWindow = hFocusWindow;
+ params.BehaviorFlags = BehaviorFlags;
+
+ hr = NineDevice9_new(screen, &params, &caps, pPresentationParameters,
+ pD3D9, pPresentationGroup, This->ctx,
+ (struct NineDevice9 **)ppReturnedDeviceInterface);
+ if (FAILED(hr)) {
+ DBG("Failed to create device.\n");
+ return hr;
+ }
+ DBG("NineDevice9 created successfully.\n");
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineAdapter9_CreateDeviceEx( struct NineAdapter9 *This,
+ UINT RealAdapter,
+ D3DDEVTYPE DeviceType,
+ HWND hFocusWindow,
+ DWORD BehaviorFlags,
+ D3DPRESENT_PARAMETERS *pPresentationParameters,
+ D3DDISPLAYMODEEX *pFullscreenDisplayMode,
+ IDirect3D9Ex *pD3D9Ex,
+ ID3DPresentGroup *pPresentationGroup,
+ IDirect3DDevice9Ex **ppReturnedDeviceInterface )
+{
+ struct pipe_screen *screen;
+ D3DDEVICE_CREATION_PARAMETERS params;
+ D3DCAPS9 caps;
+ int major, minor;
+ HRESULT hr;
+
+ DBG("This=%p RealAdapter=%u DeviceType=%s hFocusWindow=%p "
+ "BehaviourFlags=%x " "pD3D9Ex=%p pPresentationGroup=%p "
+ "ppReturnedDeviceInterface=%p\n", This,
+ RealAdapter, nine_D3DDEVTYPE_to_str(DeviceType), hFocusWindow,
+ BehaviorFlags, pD3D9Ex, pPresentationGroup, ppReturnedDeviceInterface);
+
+ ID3DPresentGroup_GetVersion(pPresentationGroup, &major, &minor);
+ if (major != 1) {
+ ERR("Doesn't support the ID3DPresentGroup version %d %d. Expected 1\n",
+ major, minor);
+ return D3DERR_NOTAVAILABLE;
+ }
+
+ hr = NineAdapter9_GetScreen(This, DeviceType, &screen);
+ if (FAILED(hr)) {
+ DBG("Failed to get pipe_screen.\n");
+ return hr;
+ }
+
+ hr = NineAdapter9_GetDeviceCaps(This, DeviceType, &caps);
+ if (FAILED(hr)) {
+ DBG("Failed to get device caps.\n");
+ return hr;
+ }
+
+ params.AdapterOrdinal = RealAdapter;
+ params.DeviceType = DeviceType;
+ params.hFocusWindow = hFocusWindow;
+ params.BehaviorFlags = BehaviorFlags;
+
+ hr = NineDevice9Ex_new(screen, &params, &caps, pPresentationParameters,
+ pFullscreenDisplayMode,
+ pD3D9Ex, pPresentationGroup, This->ctx,
+ (struct NineDevice9Ex **)ppReturnedDeviceInterface);
+ if (FAILED(hr)) {
+ DBG("Failed to create device.\n");
+ return hr;
+ }
+ DBG("NineDevice9Ex created successfully.\n");
+
+ return D3D_OK;
+}
+
+ID3DAdapter9Vtbl NineAdapter9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)NineAdapter9_GetAdapterIdentifier,
+ (void *)NineAdapter9_CheckDeviceType,
+ (void *)NineAdapter9_CheckDeviceFormat,
+ (void *)NineAdapter9_CheckDeviceMultiSampleType,
+ (void *)NineAdapter9_CheckDepthStencilMatch,
+ (void *)NineAdapter9_CheckDeviceFormatConversion,
+ (void *)NineAdapter9_GetDeviceCaps,
+ (void *)NineAdapter9_CreateDevice,
+ (void *)NineAdapter9_CreateDeviceEx
+};
+
+static const GUID *NineAdapter9_IIDs[] = {
+ &IID_ID3D9Adapter,
+ &IID_IUnknown,
+ NULL
+};
+
+HRESULT
+NineAdapter9_new( struct d3dadapter9_context *pCTX,
+ struct NineAdapter9 **ppOut )
+{
+ NINE_NEW(Adapter9, ppOut, FALSE, /* args */ pCTX);
+}
diff --git a/src/gallium/state_trackers/nine/adapter9.h b/src/gallium/state_trackers/nine/adapter9.h
new file mode 100644
index 00000000000..c743347b6af
--- /dev/null
+++ b/src/gallium/state_trackers/nine/adapter9.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _NINE_ADAPTER9_H_
+#define _NINE_ADAPTER9_H_
+
+#include "iunknown.h"
+
+#include "d3dadapter/d3dadapter9.h"
+
+struct pipe_screen;
+struct pipe_resource;
+
+struct d3dadapter9_context
+{
+ struct pipe_screen *hal, *ref;
+ D3DADAPTER_IDENTIFIER9 identifier;
+ BOOL linear_framebuffer;
+ BOOL throttling;
+ int throttling_value;
+
+ void (*destroy)( struct d3dadapter9_context *ctx );
+};
+
+struct NineAdapter9
+{
+ struct NineUnknown base;
+
+ struct d3dadapter9_context *ctx;
+};
+static INLINE struct NineAdapter9 *
+NineAdapter9( void *data )
+{
+ return (struct NineAdapter9 *)data;
+}
+
+HRESULT
+NineAdapter9_new( struct d3dadapter9_context *pCTX,
+ struct NineAdapter9 **ppOut );
+
+HRESULT
+NineAdapter9_ctor( struct NineAdapter9 *This,
+ struct NineUnknownParams *pParams,
+ struct d3dadapter9_context *pCTX );
+
+void
+NineAdapter9_dtor( struct NineAdapter9 *This );
+
+HRESULT WINAPI
+NineAdapter9_GetAdapterIdentifier( struct NineAdapter9 *This,
+ DWORD Flags,
+ D3DADAPTER_IDENTIFIER9 *pIdentifier );
+
+HRESULT WINAPI
+NineAdapter9_CheckDeviceType( struct NineAdapter9 *This,
+ D3DDEVTYPE DevType,
+ D3DFORMAT AdapterFormat,
+ D3DFORMAT BackBufferFormat,
+ BOOL bWindowed );
+
+HRESULT WINAPI
+NineAdapter9_CheckDeviceFormat( struct NineAdapter9 *This,
+ D3DDEVTYPE DeviceType,
+ D3DFORMAT AdapterFormat,
+ DWORD Usage,
+ D3DRESOURCETYPE RType,
+ D3DFORMAT CheckFormat );
+
+HRESULT WINAPI
+NineAdapter9_CheckDeviceMultiSampleType( struct NineAdapter9 *This,
+ D3DDEVTYPE DeviceType,
+ D3DFORMAT SurfaceFormat,
+ BOOL Windowed,
+ D3DMULTISAMPLE_TYPE MultiSampleType,
+ DWORD *pQualityLevels );
+
+HRESULT WINAPI
+NineAdapter9_CheckDepthStencilMatch( struct NineAdapter9 *This,
+ D3DDEVTYPE DeviceType,
+ D3DFORMAT AdapterFormat,
+ D3DFORMAT RenderTargetFormat,
+ D3DFORMAT DepthStencilFormat );
+
+HRESULT WINAPI
+NineAdapter9_CheckDeviceFormatConversion( struct NineAdapter9 *This,
+ D3DDEVTYPE DeviceType,
+ D3DFORMAT SourceFormat,
+ D3DFORMAT TargetFormat );
+
+HRESULT WINAPI
+NineAdapter9_GetDeviceCaps( struct NineAdapter9 *This,
+ D3DDEVTYPE DeviceType,
+ D3DCAPS9 *pCaps );
+
+HRESULT WINAPI
+NineAdapter9_CreateDevice( struct NineAdapter9 *This,
+ UINT RealAdapter,
+ D3DDEVTYPE DeviceType,
+ HWND hFocusWindow,
+ DWORD BehaviorFlags,
+ D3DPRESENT_PARAMETERS *pPresentationParameters,
+ IDirect3D9 *pD3D9,
+ ID3DPresentGroup *pPresentationGroup,
+ IDirect3DDevice9 **ppReturnedDeviceInterface );
+
+HRESULT WINAPI
+NineAdapter9_CreateDeviceEx( struct NineAdapter9 *This,
+ UINT RealAdapter,
+ D3DDEVTYPE DeviceType,
+ HWND hFocusWindow,
+ DWORD BehaviorFlags,
+ D3DPRESENT_PARAMETERS *pPresentationParameters,
+ D3DDISPLAYMODEEX *pFullscreenDisplayMode,
+ IDirect3D9Ex *pD3D9Ex,
+ ID3DPresentGroup *pPresentationGroup,
+ IDirect3DDevice9Ex **ppReturnedDeviceInterface );
+
+#endif /* _NINE_ADAPTER9_H_ */
diff --git a/src/gallium/state_trackers/nine/authenticatedchannel9.c b/src/gallium/state_trackers/nine/authenticatedchannel9.c
new file mode 100644
index 00000000000..44ad87c956f
--- /dev/null
+++ b/src/gallium/state_trackers/nine/authenticatedchannel9.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "authenticatedchannel9.h"
+
+#define DBG_CHANNEL DBG_AUTHENTICATEDCHANNEL
+
+HRESULT WINAPI
+NineAuthenticatedChannel9_GetCertificateSize( struct NineAuthenticatedChannel9 *This,
+ UINT *pCertificateSize )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineAuthenticatedChannel9_GetCertificate( struct NineAuthenticatedChannel9 *This,
+ UINT CertifacteSize,
+ BYTE *ppCertificate )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineAuthenticatedChannel9_NegotiateKeyExchange( struct NineAuthenticatedChannel9 *This,
+ UINT DataSize,
+ void *pData )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineAuthenticatedChannel9_Query( struct NineAuthenticatedChannel9 *This,
+ UINT InputSize,
+ const void *pInput,
+ UINT OutputSize,
+ void *pOutput )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineAuthenticatedChannel9_Configure( struct NineAuthenticatedChannel9 *This,
+ UINT InputSize,
+ const void *pInput,
+ D3DAUTHENTICATEDCHANNEL_CONFIGURE_OUTPUT *pOutput )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+IDirect3DAuthenticatedChannel9Vtbl NineAuthenticatedChannel9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)NineAuthenticatedChannel9_GetCertificateSize,
+ (void *)NineAuthenticatedChannel9_GetCertificate,
+ (void *)NineAuthenticatedChannel9_NegotiateKeyExchange,
+ (void *)NineAuthenticatedChannel9_Query,
+ (void *)NineAuthenticatedChannel9_Configure
+};
diff --git a/src/gallium/state_trackers/nine/authenticatedchannel9.h b/src/gallium/state_trackers/nine/authenticatedchannel9.h
new file mode 100644
index 00000000000..7d374f67fca
--- /dev/null
+++ b/src/gallium/state_trackers/nine/authenticatedchannel9.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _NINE_AUTHENTICATEDCHANNEL9_H_
+#define _NINE_AUTHENTICATEDCHANNEL9_H_
+
+#include "iunknown.h"
+
+struct NineAuthenticatedChannel9
+{
+ struct NineUnknown base;
+};
+static INLINE struct NineAuthenticatedChannel9 *
+NineAuthenticatedChannel9( void *data )
+{
+ return (struct NineAuthenticatedChannel9 *)data;
+}
+
+HRESULT WINAPI
+NineAuthenticatedChannel9_GetCertificateSize( struct NineAuthenticatedChannel9 *This,
+ UINT *pCertificateSize );
+
+HRESULT WINAPI
+NineAuthenticatedChannel9_GetCertificate( struct NineAuthenticatedChannel9 *This,
+ UINT CertifacteSize,
+ BYTE *ppCertificate );
+
+HRESULT WINAPI
+NineAuthenticatedChannel9_NegotiateKeyExchange( struct NineAuthenticatedChannel9 *This,
+ UINT DataSize,
+ void *pData );
+
+HRESULT WINAPI
+NineAuthenticatedChannel9_Query( struct NineAuthenticatedChannel9 *This,
+ UINT InputSize,
+ const void *pInput,
+ UINT OutputSize,
+ void *pOutput );
+
+HRESULT WINAPI
+NineAuthenticatedChannel9_Configure( struct NineAuthenticatedChannel9 *This,
+ UINT InputSize,
+ const void *pInput,
+ D3DAUTHENTICATEDCHANNEL_CONFIGURE_OUTPUT *pOutput );
+
+#endif /* _NINE_AUTHENTICATEDCHANNEL9_H_ */
diff --git a/src/gallium/state_trackers/nine/basetexture9.c b/src/gallium/state_trackers/nine/basetexture9.c
new file mode 100644
index 00000000000..89f6269a742
--- /dev/null
+++ b/src/gallium/state_trackers/nine/basetexture9.c
@@ -0,0 +1,504 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "basetexture9.h"
+#include "device9.h"
+
+/* For UploadSelf: */
+#include "texture9.h"
+#include "cubetexture9.h"
+#include "volumetexture9.h"
+
+#ifdef DEBUG
+#include "nine_pipe.h"
+#include "nine_dump.h"
+#endif
+
+#include "util/u_format.h"
+#include "util/u_gen_mipmap.h"
+
+#define DBG_CHANNEL DBG_BASETEXTURE
+
+HRESULT
+NineBaseTexture9_ctor( struct NineBaseTexture9 *This,
+ struct NineUnknownParams *pParams,
+ D3DRESOURCETYPE Type,
+ D3DPOOL Pool )
+{
+ BOOL alloc = (Pool == D3DPOOL_DEFAULT) && !This->base.resource &&
+ (This->format != D3DFMT_NULL);
+ HRESULT hr;
+ DWORD usage = This->base.usage;
+
+ user_assert(!(usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)) ||
+ Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
+ user_assert(!(usage & D3DUSAGE_DYNAMIC) ||
+ Pool != D3DPOOL_MANAGED, D3DERR_INVALIDCALL);
+
+ hr = NineResource9_ctor(&This->base, pParams, alloc, Type, Pool);
+ if (FAILED(hr))
+ return hr;
+
+ This->pipe = pParams->device->pipe;
+ This->mipfilter = (This->base.usage & D3DUSAGE_AUTOGENMIPMAP) ?
+ D3DTEXF_LINEAR : D3DTEXF_NONE;
+ This->lod = 0;
+ This->lod_resident = -1;
+ This->shadow = This->format != D3DFMT_INTZ && util_format_has_depth(
+ util_format_description(This->base.info.format));
+
+ list_inithead(&This->list);
+
+ return D3D_OK;
+}
+
+void
+NineBaseTexture9_dtor( struct NineBaseTexture9 *This )
+{
+ DBG("This=%p\n", This);
+
+ pipe_sampler_view_reference(&This->view[0], NULL);
+ pipe_sampler_view_reference(&This->view[1], NULL);
+
+ list_del(&This->list),
+
+ NineResource9_dtor(&This->base);
+}
+
+DWORD WINAPI
+NineBaseTexture9_SetLOD( struct NineBaseTexture9 *This,
+ DWORD LODNew )
+{
+ DWORD old = This->lod;
+
+ user_assert(This->base.pool == D3DPOOL_MANAGED, 0);
+
+ This->lod = MIN2(LODNew, This->base.info.last_level);
+
+ if (This->lod != old && This->bind_count && LIST_IS_EMPTY(&This->list))
+ list_add(&This->list, &This->base.base.device->update_textures);
+
+ return old;
+}
+
+DWORD WINAPI
+NineBaseTexture9_GetLOD( struct NineBaseTexture9 *This )
+{
+ return This->lod;
+}
+
+DWORD WINAPI
+NineBaseTexture9_GetLevelCount( struct NineBaseTexture9 *This )
+{
+ if (This->base.usage & D3DUSAGE_AUTOGENMIPMAP)
+ return 1;
+ return This->base.info.last_level + 1;
+}
+
+HRESULT WINAPI
+NineBaseTexture9_SetAutoGenFilterType( struct NineBaseTexture9 *This,
+ D3DTEXTUREFILTERTYPE FilterType )
+{
+ if (!(This->base.usage & D3DUSAGE_AUTOGENMIPMAP))
+ return D3D_OK;
+ user_assert(FilterType != D3DTEXF_NONE, D3DERR_INVALIDCALL);
+
+ This->mipfilter = FilterType;
+
+ return D3D_OK;
+}
+
+D3DTEXTUREFILTERTYPE WINAPI
+NineBaseTexture9_GetAutoGenFilterType( struct NineBaseTexture9 *This )
+{
+ return This->mipfilter;
+}
+
+HRESULT
+NineBaseTexture9_UploadSelf( struct NineBaseTexture9 *This )
+{
+ HRESULT hr;
+ unsigned last_level = This->base.info.last_level;
+ unsigned l;
+
+ DBG("This=%p dirty=%i type=%s\n", This, This->dirty,
+ nine_D3DRTYPE_to_str(This->base.type));
+
+ assert(This->base.pool == D3DPOOL_MANAGED);
+
+ if (This->base.usage & D3DUSAGE_AUTOGENMIPMAP)
+ last_level = 0; /* TODO: What if level 0 is not resident ? */
+
+ if (This->lod_resident != This->lod) {
+ struct pipe_resource *res;
+
+ DBG("updating LOD from %u to %u ...\n", This->lod_resident, This->lod);
+
+ pipe_sampler_view_reference(&This->view[0], NULL);
+ pipe_sampler_view_reference(&This->view[1], NULL);
+
+ if (This->bind_count) {
+ /* mark state dirty */
+ struct nine_state *state = &This->base.base.device->state;
+ unsigned s;
+ for (s = 0; s < NINE_MAX_SAMPLERS; ++s)
+ if (state->texture[s] == This)
+ state->changed.texture |= 1 << s;
+ if (state->changed.texture)
+ state->changed.group |= NINE_STATE_TEXTURE;
+ }
+
+ hr = NineBaseTexture9_CreatePipeResource(This, This->lod_resident != -1);
+ if (FAILED(hr))
+ return hr;
+ res = This->base.resource;
+
+ if (This->lod_resident == -1) /* no levels were resident */
+ This->lod_resident = This->base.info.last_level + 1;
+
+ if (This->base.type == D3DRTYPE_TEXTURE) {
+ struct NineTexture9 *tex = NineTexture9(This);
+ struct pipe_box box;
+
+ /* Mark uninitialized levels as dirty. */
+ box.x = box.y = box.z = 0;
+ box.depth = 1;
+ for (l = This->lod; l < This->lod_resident; ++l) {
+ box.width = u_minify(This->base.info.width0, l);
+ box.height = u_minify(This->base.info.height0, l);
+ NineSurface9_AddDirtyRect(tex->surfaces[l], &box);
+ }
+ for (l = 0; l < This->lod; ++l)
+ NineSurface9_SetResource(tex->surfaces[l], NULL, -1);
+ for (; l <= This->base.info.last_level; ++l)
+ NineSurface9_SetResource(tex->surfaces[l], res, l - This->lod);
+ } else
+ if (This->base.type == D3DRTYPE_CUBETEXTURE) {
+ struct NineCubeTexture9 *tex = NineCubeTexture9(This);
+ struct pipe_box box;
+ unsigned z;
+
+ /* Mark uninitialized levels as dirty. */
+ box.x = box.y = box.z = 0;
+ box.depth = 1;
+ for (l = This->lod; l < This->lod_resident; ++l) {
+ box.width = u_minify(This->base.info.width0, l);
+ box.height = u_minify(This->base.info.height0, l);
+ for (z = 0; z < 6; ++z)
+ NineSurface9_AddDirtyRect(tex->surfaces[l * 6 + z], &box);
+ }
+ for (l = 0; l < This->lod; ++l) {
+ for (z = 0; z < 6; ++z)
+ NineSurface9_SetResource(tex->surfaces[l * 6 + z],
+ NULL, -1);
+ }
+ for (; l <= This->base.info.last_level; ++l) {
+ for (z = 0; z < 6; ++z)
+ NineSurface9_SetResource(tex->surfaces[l * 6 + z],
+ res, l - This->lod);
+ }
+ } else
+ if (This->base.type == D3DRTYPE_VOLUMETEXTURE) {
+ struct NineVolumeTexture9 *tex = NineVolumeTexture9(This);
+ struct pipe_box box;
+
+ /* Mark uninitialized levels as dirty. */
+ box.x = box.y = box.z = 0;
+ for (l = This->lod; l < This->lod_resident; ++l) {
+ box.width = u_minify(This->base.info.width0, l);
+ box.height = u_minify(This->base.info.height0, l);
+ box.depth = u_minify(This->base.info.depth0, l);
+ NineVolume9_AddDirtyRegion(tex->volumes[l], &box);
+ }
+ for (l = 0; l < This->lod; ++l)
+ NineVolume9_SetResource(tex->volumes[l], NULL, -1);
+ for (; l <= This->base.info.last_level; ++l)
+ NineVolume9_SetResource(tex->volumes[l], res, l - This->lod);
+ } else {
+ assert(!"invalid texture type");
+ }
+
+ if (This->lod < This->lod_resident)
+ This->dirty = TRUE;
+ This->lod_resident = This->lod;
+ }
+ if (!This->dirty)
+ return D3D_OK;
+
+ if (This->base.type == D3DRTYPE_TEXTURE) {
+ struct NineTexture9 *tex = NineTexture9(This);
+ struct pipe_box box;
+ box.z = 0;
+ box.depth = 1;
+
+ DBG("TEXTURE: dirty rect=(%u,%u) (%ux%u)\n",
+ tex->dirty_rect.x, tex->dirty_rect.y,
+ tex->dirty_rect.width, tex->dirty_rect.height);
+
+ if (tex->dirty_rect.width) {
+ for (l = 0; l <= last_level; ++l) {
+ u_box_minify_2d(&box, &tex->dirty_rect, l);
+ NineSurface9_AddDirtyRect(tex->surfaces[l], &box);
+ }
+ memset(&tex->dirty_rect, 0, sizeof(tex->dirty_rect));
+ tex->dirty_rect.depth = 1;
+ }
+ for (l = This->lod; l <= last_level; ++l)
+ NineSurface9_UploadSelf(tex->surfaces[l]);
+ } else
+ if (This->base.type == D3DRTYPE_CUBETEXTURE) {
+ struct NineCubeTexture9 *tex = NineCubeTexture9(This);
+ unsigned z;
+ struct pipe_box box;
+ box.z = 0;
+ box.depth = 1;
+
+ for (z = 0; z < 6; ++z) {
+ DBG("FACE[%u]: dirty rect=(%u,%u) (%ux%u)\n", z,
+ tex->dirty_rect[z].x, tex->dirty_rect[z].y,
+ tex->dirty_rect[z].width, tex->dirty_rect[z].height);
+
+ if (tex->dirty_rect[z].width) {
+ for (l = 0; l <= last_level; ++l) {
+ u_box_minify_2d(&box, &tex->dirty_rect[z], l);
+ NineSurface9_AddDirtyRect(tex->surfaces[l * 6 + z], &box);
+ }
+ memset(&tex->dirty_rect[z], 0, sizeof(tex->dirty_rect[z]));
+ tex->dirty_rect[z].depth = 1;
+ }
+ for (l = This->lod; l <= last_level; ++l)
+ NineSurface9_UploadSelf(tex->surfaces[l * 6 + z]);
+ }
+ } else
+ if (This->base.type == D3DRTYPE_VOLUMETEXTURE) {
+ struct NineVolumeTexture9 *tex = NineVolumeTexture9(This);
+ struct pipe_box box;
+
+ DBG("VOLUME: dirty_box=(%u,%u,%u) (%ux%ux%u)\n",
+ tex->dirty_box.x, tex->dirty_box.y, tex->dirty_box.y,
+ tex->dirty_box.width, tex->dirty_box.height, tex->dirty_box.depth);
+
+ if (tex->dirty_box.width) {
+ for (l = 0; l <= last_level; ++l) {
+ u_box_minify_2d(&box, &tex->dirty_box, l);
+ NineVolume9_AddDirtyRegion(tex->volumes[l], &tex->dirty_box);
+ }
+ memset(&tex->dirty_box, 0, sizeof(tex->dirty_box));
+ }
+ for (l = This->lod; l <= last_level; ++l)
+ NineVolume9_UploadSelf(tex->volumes[l]);
+ } else {
+ assert(!"invalid texture type");
+ }
+ This->dirty = FALSE;
+
+ if (This->base.usage & D3DUSAGE_AUTOGENMIPMAP)
+ This->dirty_mip = TRUE;
+ /* TODO: if dirty only because of lod change, only generate added levels */
+
+ DBG("DONE, generate mip maps = %i\n", This->dirty_mip);
+ return D3D_OK;
+}
+
+void WINAPI
+NineBaseTexture9_GenerateMipSubLevels( struct NineBaseTexture9 *This )
+{
+ struct pipe_resource *resource = This->base.resource;
+
+ unsigned base_level = 0;
+ unsigned last_level = This->base.info.last_level - This->lod;
+ unsigned first_layer = 0;
+ unsigned last_layer;
+ unsigned filter = This->mipfilter == D3DTEXF_POINT ? PIPE_TEX_FILTER_NEAREST
+ : PIPE_TEX_FILTER_LINEAR;
+ DBG("This=%p\n", This);
+
+ if (This->base.pool == D3DPOOL_MANAGED)
+ NineBaseTexture9_UploadSelf(This);
+ if (!This->dirty_mip)
+ return;
+ if (This->lod) {
+ ERR("AUTOGENMIPMAP if level 0 is not resident not supported yet !\n");
+ return;
+ }
+
+ if (!This->view[0])
+ NineBaseTexture9_UpdateSamplerView(This, 0);
+
+ last_layer = util_max_layer(This->view[0]->texture, base_level);
+
+ util_gen_mipmap(This->pipe, resource,
+ resource->format, base_level, last_level,
+ first_layer, last_layer, filter);
+
+ This->dirty_mip = FALSE;
+
+ NineDevice9_RestoreNonCSOState(This->base.base.device, ~0x3);
+}
+
+HRESULT
+NineBaseTexture9_CreatePipeResource( struct NineBaseTexture9 *This,
+ BOOL CopyData )
+{
+ struct pipe_context *pipe = This->pipe;
+ struct pipe_screen *screen = This->base.info.screen;
+ struct pipe_resource templ;
+ unsigned l, m;
+ struct pipe_resource *res;
+ struct pipe_resource *old = This->base.resource;
+
+ DBG("This=%p lod=%u last_level=%u\n", This,
+ This->lod, This->base.info.last_level);
+
+ assert(This->base.pool == D3DPOOL_MANAGED);
+
+ templ = This->base.info;
+
+ if (This->lod) {
+ templ.width0 = u_minify(templ.width0, This->lod);
+ templ.height0 = u_minify(templ.height0, This->lod);
+ templ.depth0 = u_minify(templ.depth0, This->lod);
+ }
+ templ.last_level = This->base.info.last_level - This->lod;
+
+ if (old) {
+ /* LOD might have changed. */
+ if (old->width0 == templ.width0 &&
+ old->height0 == templ.height0 &&
+ old->depth0 == templ.depth0)
+ return D3D_OK;
+ }
+
+ res = screen->resource_create(screen, &templ);
+ if (!res)
+ return D3DERR_OUTOFVIDEOMEMORY;
+ This->base.resource = res;
+
+ if (old && CopyData) { /* Don't return without releasing old ! */
+ struct pipe_box box;
+ box.x = 0;
+ box.y = 0;
+ box.z = 0;
+
+ l = (This->lod < This->lod_resident) ? This->lod_resident - This->lod : 0;
+ m = (This->lod < This->lod_resident) ? 0 : This->lod - This->lod_resident;
+
+ box.width = u_minify(templ.width0, l);
+ box.height = u_minify(templ.height0, l);
+ box.depth = u_minify(templ.depth0, l);
+
+ for (; l <= templ.last_level; ++l, ++m) {
+ pipe->resource_copy_region(pipe,
+ res, l, 0, 0, 0,
+ old, m, &box);
+ box.width = u_minify(box.width, 1);
+ box.height = u_minify(box.height, 1);
+ box.depth = u_minify(box.depth, 1);
+ }
+ }
+ pipe_resource_reference(&old, NULL);
+
+ return D3D_OK;
+}
+
+HRESULT
+NineBaseTexture9_UpdateSamplerView( struct NineBaseTexture9 *This,
+ const int sRGB )
+{
+ const struct util_format_description *desc;
+ struct pipe_context *pipe = This->pipe;
+ struct pipe_resource *resource = This->base.resource;
+ struct pipe_sampler_view templ;
+ uint8_t swizzle[4];
+
+ if (unlikely(!resource)) {
+ if (unlikely(This->format == D3DFMT_NULL))
+ return D3D_OK;
+ NineBaseTexture9_Dump(This);
+ }
+ assert(resource);
+
+ pipe_sampler_view_reference(&This->view[sRGB], NULL);
+
+ swizzle[0] = PIPE_SWIZZLE_RED;
+ swizzle[1] = PIPE_SWIZZLE_GREEN;
+ swizzle[2] = PIPE_SWIZZLE_BLUE;
+ swizzle[3] = PIPE_SWIZZLE_ALPHA;
+ desc = util_format_description(resource->format);
+ if (desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) {
+ /* ZZZ1 -> 0Z01 (see end of docs/source/tgsi.rst)
+ * XXX: but it's wrong
+ swizzle[0] = PIPE_SWIZZLE_ZERO;
+ swizzle[2] = PIPE_SWIZZLE_ZERO; */
+ } else
+ if (desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_X &&
+ desc->swizzle[3] == UTIL_FORMAT_SWIZZLE_1) {
+ /* R001/RG01 -> R111/RG11 */
+ if (desc->swizzle[1] == UTIL_FORMAT_SWIZZLE_0)
+ swizzle[1] = PIPE_SWIZZLE_ONE;
+ if (desc->swizzle[2] == UTIL_FORMAT_SWIZZLE_0)
+ swizzle[2] = PIPE_SWIZZLE_ONE;
+ }
+ /* but 000A remains unchanged */
+
+ templ.format = sRGB ? util_format_srgb(resource->format) : resource->format;
+ templ.u.tex.first_layer = 0;
+ templ.u.tex.last_layer = (resource->target == PIPE_TEXTURE_CUBE) ?
+ 5 : (This->base.info.depth0 - 1);
+ templ.u.tex.first_level = 0;
+ templ.u.tex.last_level = resource->last_level;
+ templ.swizzle_r = swizzle[0];
+ templ.swizzle_g = swizzle[1];
+ templ.swizzle_b = swizzle[2];
+ templ.swizzle_a = swizzle[3];
+ templ.target = resource->target;
+
+ This->view[sRGB] = pipe->create_sampler_view(pipe, resource, &templ);
+
+ DBG("sampler view = %p(resource = %p)\n", This->view[sRGB], resource);
+
+ return This->view ? D3D_OK : D3DERR_DRIVERINTERNALERROR;
+}
+
+void WINAPI
+NineBaseTexture9_PreLoad( struct NineBaseTexture9 *This )
+{
+ if (This->dirty && This->base.pool == D3DPOOL_MANAGED)
+ NineBaseTexture9_UploadSelf(This);
+}
+
+#ifdef DEBUG
+void
+NineBaseTexture9_Dump( struct NineBaseTexture9 *This )
+{
+ DBG("\nNineBaseTexture9(%p->%p/%p): Pool=%s Type=%s Usage=%s\n"
+ "Format=%s Dims=%ux%ux%u/%u LastLevel=%u Lod=%u(%u)\n", This,
+ This->base.resource, This->base.data,
+ nine_D3DPOOL_to_str(This->base.pool),
+ nine_D3DRTYPE_to_str(This->base.type),
+ nine_D3DUSAGE_to_str(This->base.usage),
+ d3dformat_to_string(This->format),
+ This->base.info.width0, This->base.info.height0, This->base.info.depth0,
+ This->base.info.array_size, This->base.info.last_level,
+ This->lod, This->lod_resident);
+}
+#endif /* DEBUG */
diff --git a/src/gallium/state_trackers/nine/basetexture9.h b/src/gallium/state_trackers/nine/basetexture9.h
new file mode 100644
index 00000000000..d615376f09b
--- /dev/null
+++ b/src/gallium/state_trackers/nine/basetexture9.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _NINE_BASETEXTURE9_H_
+#define _NINE_BASETEXTURE9_H_
+
+#include "resource9.h"
+#include "util/u_inlines.h"
+#include "util/u_double_list.h"
+
+struct NineBaseTexture9
+{
+ struct NineResource9 base;
+ struct list_head list;
+
+ /* g3d */
+ struct pipe_context *pipe;
+ struct pipe_sampler_view *view[2]; /* linear and sRGB */
+
+ D3DFORMAT format;
+
+ D3DTEXTUREFILTERTYPE mipfilter;
+ DWORD lod;
+ DWORD lod_resident;
+
+ int16_t bind_count; /* to Device9->state.texture */
+
+ boolean shadow;
+ uint8_t pstype; /* 0: 2D, 1: 1D, 2: CUBE, 3: 3D */
+
+ boolean dirty;
+ boolean dirty_mip;
+};
+static INLINE struct NineBaseTexture9 *
+NineBaseTexture9( void *data )
+{
+ return (struct NineBaseTexture9 *)data;
+}
+
+HRESULT
+NineBaseTexture9_ctor( struct NineBaseTexture9 *This,
+ struct NineUnknownParams *pParams,
+ D3DRESOURCETYPE Type,
+ D3DPOOL Pool );
+
+void
+NineBaseTexture9_dtor( struct NineBaseTexture9 *This );
+
+DWORD WINAPI
+NineBaseTexture9_SetLOD( struct NineBaseTexture9 *This,
+ DWORD LODNew );
+
+DWORD WINAPI
+NineBaseTexture9_GetLOD( struct NineBaseTexture9 *This );
+
+DWORD WINAPI
+NineBaseTexture9_GetLevelCount( struct NineBaseTexture9 *This );
+
+HRESULT WINAPI
+NineBaseTexture9_SetAutoGenFilterType( struct NineBaseTexture9 *This,
+ D3DTEXTUREFILTERTYPE FilterType );
+
+D3DTEXTUREFILTERTYPE WINAPI
+NineBaseTexture9_GetAutoGenFilterType( struct NineBaseTexture9 *This );
+
+void WINAPI
+NineBaseTexture9_GenerateMipSubLevels( struct NineBaseTexture9 *This );
+
+void WINAPI
+NineBaseTexture9_PreLoad( struct NineBaseTexture9 *This );
+
+/* For D3DPOOL_MANAGED only (after SetLOD change): */
+HRESULT
+NineBaseTexture9_CreatePipeResource( struct NineBaseTexture9 *This,
+ BOOL CopyData );
+
+/* For D3DPOOL_MANAGED only: */
+HRESULT
+NineBaseTexture9_UploadSelf( struct NineBaseTexture9 *This );
+
+HRESULT
+NineBaseTexture9_UpdateSamplerView( struct NineBaseTexture9 *This,
+ const int sRGB );
+
+static INLINE void
+NineBaseTexture9_Validate( struct NineBaseTexture9 *This )
+{
+ DBG_FLAG(DBG_BASETEXTURE, "This=%p dirty=%i dirty_mip=%i lod=%u/%u\n",
+ This, This->dirty, This->dirty_mip, This->lod, This->lod_resident);
+ if ((This->base.pool == D3DPOOL_MANAGED) &&
+ (This->dirty || This->lod != This->lod_resident))
+ NineBaseTexture9_UploadSelf(This);
+ if (This->dirty_mip)
+ NineBaseTexture9_GenerateMipSubLevels(This);
+}
+
+static INLINE struct pipe_sampler_view *
+NineBaseTexture9_GetSamplerView( struct NineBaseTexture9 *This, const int sRGB )
+{
+ if (!This->view[sRGB])
+ NineBaseTexture9_UpdateSamplerView(This, sRGB);
+ return This->view[sRGB];
+}
+
+#ifdef DEBUG
+void
+NineBaseTexture9_Dump( struct NineBaseTexture9 *This );
+#else
+static INLINE void
+NineBaseTexture9_Dump( struct NineBaseTexture9 *This ) { }
+#endif
+
+#define BASETEX_REGISTER_UPDATE(t) do { \
+ if (((t)->dirty | ((t)->dirty_mip)) && (t)->base.base.bind) \
+ if (LIST_IS_EMPTY(&(t)->list)) \
+ list_add(&(t)->list, &(t)->base.base.device->update_textures); \
+ } while(0)
+
+#endif /* _NINE_BASETEXTURE9_H_ */
diff --git a/src/gallium/state_trackers/nine/cryptosession9.c b/src/gallium/state_trackers/nine/cryptosession9.c
new file mode 100644
index 00000000000..2622f2b32e4
--- /dev/null
+++ b/src/gallium/state_trackers/nine/cryptosession9.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "cryptosession9.h"
+
+#define DBG_CHANNEL DBG_CRYPTOSESSION
+
+HRESULT WINAPI
+NineCryptoSession9_GetCertificateSize( struct NineCryptoSession9 *This,
+ UINT *pCertificateSize )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineCryptoSession9_GetCertificate( struct NineCryptoSession9 *This,
+ UINT CertifacteSize,
+ BYTE *ppCertificate )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineCryptoSession9_NegotiateKeyExchange( struct NineCryptoSession9 *This,
+ UINT DataSize,
+ void *pData )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineCryptoSession9_EncryptionBlt( struct NineCryptoSession9 *This,
+ IDirect3DSurface9 *pSrcSurface,
+ IDirect3DSurface9 *pDstSurface,
+ UINT DstSurfaceSize,
+ void *pIV )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineCryptoSession9_DecryptionBlt( struct NineCryptoSession9 *This,
+ IDirect3DSurface9 *pSrcSurface,
+ IDirect3DSurface9 *pDstSurface,
+ UINT SrcSurfaceSize,
+ D3DENCRYPTED_BLOCK_INFO *pEncryptedBlockInfo,
+ void *pContentKey,
+ void *pIV )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineCryptoSession9_GetSurfacePitch( struct NineCryptoSession9 *This,
+ IDirect3DSurface9 *pSrcSurface,
+ UINT *pSurfacePitch )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineCryptoSession9_StartSessionKeyRefresh( struct NineCryptoSession9 *This,
+ void *pRandomNumber,
+ UINT RandomNumberSize )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineCryptoSession9_FinishSessionKeyRefresh( struct NineCryptoSession9 *This )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineCryptoSession9_GetEncryptionBltKey( struct NineCryptoSession9 *This,
+ void *pReadbackKey,
+ UINT KeySize )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+IDirect3DCryptoSession9Vtbl NineCryptoSession9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)NineCryptoSession9_GetCertificateSize,
+ (void *)NineCryptoSession9_GetCertificate,
+ (void *)NineCryptoSession9_NegotiateKeyExchange,
+ (void *)NineCryptoSession9_EncryptionBlt,
+ (void *)NineCryptoSession9_DecryptionBlt,
+ (void *)NineCryptoSession9_GetSurfacePitch,
+ (void *)NineCryptoSession9_StartSessionKeyRefresh,
+ (void *)NineCryptoSession9_FinishSessionKeyRefresh,
+ (void *)NineCryptoSession9_GetEncryptionBltKey
+};
diff --git a/src/gallium/state_trackers/nine/cryptosession9.h b/src/gallium/state_trackers/nine/cryptosession9.h
new file mode 100644
index 00000000000..660d246bfa0
--- /dev/null
+++ b/src/gallium/state_trackers/nine/cryptosession9.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _NINE_CRYPTOSESSION9_H_
+#define _NINE_CRYPTOSESSION9_H_
+
+#include "iunknown.h"
+
+struct NineCryptoSession9
+{
+ struct NineUnknown base;
+};
+static INLINE struct NineCryptoSession9 *
+NineCryptoSession9( void *data )
+{
+ return (struct NineCryptoSession9 *)data;
+}
+
+HRESULT WINAPI
+NineCryptoSession9_GetCertificateSize( struct NineCryptoSession9 *This,
+ UINT *pCertificateSize );
+
+HRESULT WINAPI
+NineCryptoSession9_GetCertificate( struct NineCryptoSession9 *This,
+ UINT CertifacteSize,
+ BYTE *ppCertificate );
+
+HRESULT WINAPI
+NineCryptoSession9_NegotiateKeyExchange( struct NineCryptoSession9 *This,
+ UINT DataSize,
+ void *pData );
+
+HRESULT WINAPI
+NineCryptoSession9_EncryptionBlt( struct NineCryptoSession9 *This,
+ IDirect3DSurface9 *pSrcSurface,
+ IDirect3DSurface9 *pDstSurface,
+ UINT DstSurfaceSize,
+ void *pIV );
+
+HRESULT WINAPI
+NineCryptoSession9_DecryptionBlt( struct NineCryptoSession9 *This,
+ IDirect3DSurface9 *pSrcSurface,
+ IDirect3DSurface9 *pDstSurface,
+ UINT SrcSurfaceSize,
+ D3DENCRYPTED_BLOCK_INFO *pEncryptedBlockInfo,
+ void *pContentKey,
+ void *pIV );
+
+HRESULT WINAPI
+NineCryptoSession9_GetSurfacePitch( struct NineCryptoSession9 *This,
+ IDirect3DSurface9 *pSrcSurface,
+ UINT *pSurfacePitch );
+
+HRESULT WINAPI
+NineCryptoSession9_StartSessionKeyRefresh( struct NineCryptoSession9 *This,
+ void *pRandomNumber,
+ UINT RandomNumberSize );
+
+HRESULT WINAPI
+NineCryptoSession9_FinishSessionKeyRefresh( struct NineCryptoSession9 *This );
+
+HRESULT WINAPI
+NineCryptoSession9_GetEncryptionBltKey( struct NineCryptoSession9 *This,
+ void *pReadbackKey,
+ UINT KeySize );
+
+#endif /* _NINE_CRYPTOSESSION9_H_ */
diff --git a/src/gallium/state_trackers/nine/cubetexture9.c b/src/gallium/state_trackers/nine/cubetexture9.c
new file mode 100644
index 00000000000..77802e70220
--- /dev/null
+++ b/src/gallium/state_trackers/nine/cubetexture9.c
@@ -0,0 +1,274 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "device9.h"
+#include "cubetexture9.h"
+#include "nine_helpers.h"
+#include "nine_pipe.h"
+
+#define DBG_CHANNEL DBG_CUBETEXTURE
+
+
+static HRESULT
+NineCubeTexture9_ctor( struct NineCubeTexture9 *This,
+ struct NineUnknownParams *pParams,
+ UINT EdgeLength, UINT Levels,
+ DWORD Usage,
+ D3DFORMAT Format,
+ D3DPOOL Pool,
+ HANDLE *pSharedHandle )
+{
+ struct pipe_resource *info = &This->base.base.info;
+ unsigned i;
+ D3DSURFACE_DESC sfdesc;
+ HRESULT hr;
+
+ user_assert(!(Usage & D3DUSAGE_AUTOGENMIPMAP) ||
+ (Pool != D3DPOOL_SYSTEMMEM && Levels <= 1), D3DERR_INVALIDCALL);
+
+ user_assert(!pSharedHandle, D3DERR_INVALIDCALL); /* TODO */
+
+ if (Usage & D3DUSAGE_AUTOGENMIPMAP)
+ Levels = 0;
+
+ This->base.format = Format;
+ This->base.base.usage = Usage;
+
+ info->screen = pParams->device->screen;
+ info->target = PIPE_TEXTURE_CUBE;
+ info->format = d3d9_to_pipe_format(Format);
+ info->width0 = EdgeLength;
+ info->height0 = EdgeLength;
+ info->depth0 = 1;
+ if (Levels)
+ info->last_level = Levels - 1;
+ else
+ info->last_level = util_logbase2(EdgeLength);
+ info->array_size = 6;
+ info->nr_samples = 0;
+ info->bind = PIPE_BIND_SAMPLER_VIEW;
+ info->usage = PIPE_USAGE_DEFAULT;
+ info->flags = 0;
+
+ if (Usage & D3DUSAGE_RENDERTARGET)
+ info->bind |= PIPE_BIND_RENDER_TARGET;
+ if (Usage & D3DUSAGE_DEPTHSTENCIL)
+ info->bind |= PIPE_BIND_DEPTH_STENCIL;
+
+ if (Usage & D3DUSAGE_DYNAMIC) {
+ info->usage = PIPE_USAGE_DYNAMIC;
+ info->bind |=
+ PIPE_BIND_TRANSFER_READ |
+ PIPE_BIND_TRANSFER_WRITE;
+ }
+
+ This->surfaces = CALLOC(6 * (info->last_level + 1), sizeof(*This->surfaces));
+ if (!This->surfaces)
+ return E_OUTOFMEMORY;
+
+ hr = NineBaseTexture9_ctor(&This->base, pParams, D3DRTYPE_CUBETEXTURE,
+ Pool);
+ if (FAILED(hr))
+ return hr;
+ This->base.pstype = 2;
+
+ /* Create all the surfaces right away.
+ * They manage backing storage, and transfers (LockRect) are deferred
+ * to them.
+ */
+ sfdesc.Format = Format;
+ sfdesc.Type = D3DRTYPE_SURFACE;
+ sfdesc.Usage = Usage;
+ sfdesc.Pool = Pool;
+ sfdesc.MultiSampleType = D3DMULTISAMPLE_NONE;
+ sfdesc.MultiSampleQuality = 0;
+ for (i = 0; i < (info->last_level + 1) * 6; ++i) {
+ sfdesc.Width = sfdesc.Height = u_minify(EdgeLength, i / 6);
+
+ hr = NineSurface9_new(This->base.base.base.device, NineUnknown(This),
+ This->base.base.resource, D3DRTYPE_CUBETEXTURE,
+ i / 6, i % 6,
+ &sfdesc, &This->surfaces[i]);
+ if (FAILED(hr))
+ return hr;
+ }
+ for (i = 0; i < 6; ++i) /* width = 0 means empty, depth stays 1 */
+ This->dirty_rect[i].depth = 1;
+
+ return D3D_OK;
+}
+
+static void
+NineCubeTexture9_dtor( struct NineCubeTexture9 *This )
+{
+ unsigned i;
+
+ DBG("This=%p\n", This);
+
+ if (This->surfaces) {
+ for (i = 0; i < This->base.base.info.last_level * 6; ++i)
+ NineUnknown_Destroy(&This->surfaces[i]->base.base);
+ FREE(This->surfaces);
+ }
+
+ NineBaseTexture9_dtor(&This->base);
+}
+
+HRESULT WINAPI
+NineCubeTexture9_GetLevelDesc( struct NineCubeTexture9 *This,
+ UINT Level,
+ D3DSURFACE_DESC *pDesc )
+{
+ user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL);
+ user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP),
+ D3DERR_INVALIDCALL);
+
+ *pDesc = This->surfaces[Level]->desc;
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineCubeTexture9_GetCubeMapSurface( struct NineCubeTexture9 *This,
+ D3DCUBEMAP_FACES FaceType,
+ UINT Level,
+ IDirect3DSurface9 **ppCubeMapSurface )
+{
+ const unsigned s = Level * 6 + FaceType;
+
+ user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL);
+ user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP),
+ D3DERR_INVALIDCALL);
+ user_assert(FaceType < 6, D3DERR_INVALIDCALL);
+
+ NineUnknown_AddRef(NineUnknown(This->surfaces[s]));
+ *ppCubeMapSurface = (IDirect3DSurface9 *)This->surfaces[s];
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineCubeTexture9_LockRect( struct NineCubeTexture9 *This,
+ D3DCUBEMAP_FACES FaceType,
+ UINT Level,
+ D3DLOCKED_RECT *pLockedRect,
+ const RECT *pRect,
+ DWORD Flags )
+{
+ const unsigned s = Level * 6 + FaceType;
+
+ user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL);
+ user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP),
+ D3DERR_INVALIDCALL);
+ user_assert(FaceType < 6, D3DERR_INVALIDCALL);
+
+ return NineSurface9_LockRect(This->surfaces[s], pLockedRect, pRect, Flags);
+}
+
+HRESULT WINAPI
+NineCubeTexture9_UnlockRect( struct NineCubeTexture9 *This,
+ D3DCUBEMAP_FACES FaceType,
+ UINT Level )
+{
+ const unsigned s = Level * 6 + FaceType;
+
+ user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL);
+ user_assert(FaceType < 6, D3DERR_INVALIDCALL);
+
+ return NineSurface9_UnlockRect(This->surfaces[s]);
+}
+
+HRESULT WINAPI
+NineCubeTexture9_AddDirtyRect( struct NineCubeTexture9 *This,
+ D3DCUBEMAP_FACES FaceType,
+ const RECT *pDirtyRect )
+{
+ user_assert(FaceType < 6, D3DERR_INVALIDCALL);
+
+ if (This->base.base.pool != D3DPOOL_MANAGED) {
+ if (This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP)
+ This->base.dirty_mip = TRUE;
+ return D3D_OK;
+ }
+ This->base.dirty = TRUE;
+
+ BASETEX_REGISTER_UPDATE(&This->base);
+
+ if (!pDirtyRect) {
+ u_box_origin_2d(This->base.base.info.width0,
+ This->base.base.info.height0,
+ &This->dirty_rect[FaceType]);
+ } else {
+ struct pipe_box box;
+ rect_to_pipe_box_clamp(&box, pDirtyRect);
+ u_box_union_2d(&This->dirty_rect[FaceType], &This->dirty_rect[FaceType],
+ &box);
+ }
+ return D3D_OK;
+}
+
+IDirect3DCubeTexture9Vtbl NineCubeTexture9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */
+ (void *)NineResource9_SetPrivateData,
+ (void *)NineResource9_GetPrivateData,
+ (void *)NineResource9_FreePrivateData,
+ (void *)NineResource9_SetPriority,
+ (void *)NineResource9_GetPriority,
+ (void *)NineBaseTexture9_PreLoad,
+ (void *)NineResource9_GetType,
+ (void *)NineBaseTexture9_SetLOD,
+ (void *)NineBaseTexture9_GetLOD,
+ (void *)NineBaseTexture9_GetLevelCount,
+ (void *)NineBaseTexture9_SetAutoGenFilterType,
+ (void *)NineBaseTexture9_GetAutoGenFilterType,
+ (void *)NineBaseTexture9_GenerateMipSubLevels,
+ (void *)NineCubeTexture9_GetLevelDesc,
+ (void *)NineCubeTexture9_GetCubeMapSurface,
+ (void *)NineCubeTexture9_LockRect,
+ (void *)NineCubeTexture9_UnlockRect,
+ (void *)NineCubeTexture9_AddDirtyRect
+};
+
+static const GUID *NineCubeTexture9_IIDs[] = {
+ &IID_IDirect3DCubeTexture9,
+ &IID_IDirect3DBaseTexture9,
+ &IID_IDirect3DResource9,
+ &IID_IUnknown,
+ NULL
+};
+
+HRESULT
+NineCubeTexture9_new( struct NineDevice9 *pDevice,
+ UINT EdgeLength, UINT Levels,
+ DWORD Usage,
+ D3DFORMAT Format,
+ D3DPOOL Pool,
+ struct NineCubeTexture9 **ppOut,
+ HANDLE *pSharedHandle )
+{
+ NINE_DEVICE_CHILD_NEW(CubeTexture9, ppOut, pDevice,
+ EdgeLength, Levels,
+ Usage, Format, Pool, pSharedHandle);
+}
diff --git a/src/gallium/state_trackers/nine/cubetexture9.h b/src/gallium/state_trackers/nine/cubetexture9.h
new file mode 100644
index 00000000000..e8594d35bb4
--- /dev/null
+++ b/src/gallium/state_trackers/nine/cubetexture9.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _NINE_CUBETEXTURE9_H_
+#define _NINE_CUBETEXTURE9_H_
+
+#include "basetexture9.h"
+#include "surface9.h"
+
+struct NineCubeTexture9
+{
+ struct NineBaseTexture9 base;
+ struct NineSurface9 **surfaces;
+ struct pipe_box dirty_rect[6]; /* covers all mip levels */
+};
+static INLINE struct NineCubeTexture9 *
+NineCubeTexture9( void *data )
+{
+ return (struct NineCubeTexture9 *)data;
+}
+
+HRESULT
+NineCubeTexture9_new( struct NineDevice9 *pDevice,
+ UINT EdgeLength, UINT Levels,
+ DWORD Usage,
+ D3DFORMAT Format,
+ D3DPOOL Pool,
+ struct NineCubeTexture9 **ppOut,
+ HANDLE *pSharedHandle );
+
+HRESULT WINAPI
+NineCubeTexture9_GetLevelDesc( struct NineCubeTexture9 *This,
+ UINT Level,
+ D3DSURFACE_DESC *pDesc );
+
+HRESULT WINAPI
+NineCubeTexture9_GetCubeMapSurface( struct NineCubeTexture9 *This,
+ D3DCUBEMAP_FACES FaceType,
+ UINT Level,
+ IDirect3DSurface9 **ppCubeMapSurface );
+
+HRESULT WINAPI
+NineCubeTexture9_LockRect( struct NineCubeTexture9 *This,
+ D3DCUBEMAP_FACES FaceType,
+ UINT Level,
+ D3DLOCKED_RECT *pLockedRect,
+ const RECT *pRect,
+ DWORD Flags );
+
+HRESULT WINAPI
+NineCubeTexture9_UnlockRect( struct NineCubeTexture9 *This,
+ D3DCUBEMAP_FACES FaceType,
+ UINT Level );
+
+HRESULT WINAPI
+NineCubeTexture9_AddDirtyRect( struct NineCubeTexture9 *This,
+ D3DCUBEMAP_FACES FaceType,
+ const RECT *pDirtyRect );
+
+#endif /* _NINE_CUBETEXTURE9_H_ */
diff --git a/src/gallium/state_trackers/nine/device9.c b/src/gallium/state_trackers/nine/device9.c
new file mode 100644
index 00000000000..7d2142d03f1
--- /dev/null
+++ b/src/gallium/state_trackers/nine/device9.c
@@ -0,0 +1,3458 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "device9.h"
+#include "stateblock9.h"
+#include "surface9.h"
+#include "swapchain9.h"
+#include "swapchain9ex.h"
+#include "indexbuffer9.h"
+#include "vertexbuffer9.h"
+#include "vertexdeclaration9.h"
+#include "vertexshader9.h"
+#include "pixelshader9.h"
+#include "query9.h"
+#include "texture9.h"
+#include "cubetexture9.h"
+#include "volumetexture9.h"
+#include "nine_helpers.h"
+#include "nine_pipe.h"
+#include "nine_ff.h"
+#include "nine_dump.h"
+
+#include "pipe/p_screen.h"
+#include "pipe/p_context.h"
+#include "util/u_math.h"
+#include "util/u_inlines.h"
+#include "util/u_hash_table.h"
+#include "util/u_format.h"
+#include "util/u_surface.h"
+#include "util/u_upload_mgr.h"
+#include "hud/hud_context.h"
+
+#include "cso_cache/cso_context.h"
+
+#define DBG_CHANNEL DBG_DEVICE
+
+static void
+NineDevice9_SetDefaultState( struct NineDevice9 *This, boolean is_reset )
+{
+ struct NineSurface9 *refSurf = NULL;
+
+ assert(!This->is_recording);
+
+ nine_state_set_defaults(&This->state, &This->caps, is_reset);
+
+ This->state.viewport.X = 0;
+ This->state.viewport.Y = 0;
+ This->state.viewport.Width = 0;
+ This->state.viewport.Height = 0;
+
+ This->state.scissor.minx = 0;
+ This->state.scissor.miny = 0;
+ This->state.scissor.maxx = 0xffff;
+ This->state.scissor.maxy = 0xffff;
+
+ if (This->nswapchains && This->swapchains[0]->params.BackBufferCount)
+ refSurf = This->swapchains[0]->buffers[0];
+
+ if (refSurf) {
+ This->state.viewport.Width = refSurf->desc.Width;
+ This->state.viewport.Height = refSurf->desc.Height;
+ This->state.scissor.maxx = refSurf->desc.Width;
+ This->state.scissor.maxy = refSurf->desc.Height;
+ }
+
+ if (This->nswapchains && This->swapchains[0]->params.EnableAutoDepthStencil)
+ This->state.rs[D3DRS_ZENABLE] = TRUE;
+ if (This->state.rs[D3DRS_ZENABLE])
+ NineDevice9_SetDepthStencilSurface(
+ This, (IDirect3DSurface9 *)This->swapchains[0]->zsbuf);
+}
+
+void
+NineDevice9_RestoreNonCSOState( struct NineDevice9 *This, unsigned mask )
+{
+ struct pipe_context *pipe = This->pipe;
+
+ if (mask & 0x1) {
+ struct pipe_constant_buffer cb;
+ cb.buffer_offset = 0;
+
+ if (This->prefer_user_constbuf) {
+ cb.buffer = NULL;
+ cb.user_buffer = This->state.vs_const_f;
+ } else {
+ cb.buffer = This->constbuf_vs;
+ cb.user_buffer = NULL;
+ }
+ cb.buffer_size = This->constbuf_vs->width0;
+ pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &cb);
+
+ if (This->prefer_user_constbuf) {
+ cb.user_buffer = This->state.ps_const_f;
+ } else {
+ cb.buffer = This->constbuf_ps;
+ }
+ cb.buffer_size = This->constbuf_ps->width0;
+ pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &cb);
+ }
+
+ if (mask & 0x2) {
+ struct pipe_poly_stipple stipple;
+ memset(&stipple, ~0, sizeof(stipple));
+ pipe->set_polygon_stipple(pipe, &stipple);
+ }
+
+ This->state.changed.group = NINE_STATE_ALL;
+ This->state.changed.vtxbuf = (1ULL << This->caps.MaxStreams) - 1;
+ This->state.changed.ucp = (1 << PIPE_MAX_CLIP_PLANES) - 1;
+ This->state.changed.texture = NINE_PS_SAMPLERS_MASK | NINE_VS_SAMPLERS_MASK;
+}
+
+#define GET_PCAP(n) pScreen->get_param(pScreen, PIPE_CAP_##n)
+HRESULT
+NineDevice9_ctor( struct NineDevice9 *This,
+ struct NineUnknownParams *pParams,
+ struct pipe_screen *pScreen,
+ D3DDEVICE_CREATION_PARAMETERS *pCreationParameters,
+ D3DCAPS9 *pCaps,
+ D3DPRESENT_PARAMETERS *pPresentationParameters,
+ IDirect3D9 *pD3D9,
+ ID3DPresentGroup *pPresentationGroup,
+ struct d3dadapter9_context *pCTX )
+{
+ unsigned i;
+ HRESULT hr = NineUnknown_ctor(&This->base, pParams);
+ if (FAILED(hr)) { return hr; }
+
+ list_inithead(&This->update_textures);
+
+ This->screen = pScreen;
+ This->caps = *pCaps;
+ This->d3d9 = pD3D9;
+ This->params = *pCreationParameters;
+ This->present = pPresentationGroup;
+ IDirect3D9_AddRef(This->d3d9);
+ ID3DPresentGroup_AddRef(This->present);
+
+ This->pipe = This->screen->context_create(This->screen, NULL);
+ if (!This->pipe) { return E_OUTOFMEMORY; } /* guess */
+
+ This->cso = cso_create_context(This->pipe);
+ if (!This->cso) { return E_OUTOFMEMORY; } /* also a guess */
+
+ /* Create first, it messes up our state. */
+ This->hud = hud_create(This->pipe, This->cso); /* NULL result is fine */
+
+ /* create implicit swapchains */
+ This->nswapchains = ID3DPresentGroup_GetMultiheadCount(This->present);
+ This->swapchains = CALLOC(This->nswapchains,
+ sizeof(struct NineSwapChain9 *));
+ if (!This->swapchains) { return E_OUTOFMEMORY; }
+
+ for (i = 0; i < This->nswapchains; ++i) {
+ ID3DPresent *present;
+
+ hr = ID3DPresentGroup_GetPresent(This->present, i, &present);
+ if (FAILED(hr))
+ return hr;
+
+ if (This->ex) {
+ D3DDISPLAYMODEEX *mode = NULL;
+ struct NineSwapChain9Ex **ret =
+ (struct NineSwapChain9Ex **)&This->swapchains[i];
+
+ if (This->pFullscreenDisplayMode) mode = &(This->pFullscreenDisplayMode[i]);
+ /* when this is a Device9Ex, it should create SwapChain9Exs */
+ hr = NineSwapChain9Ex_new(This, TRUE, present,
+ &pPresentationParameters[i], pCTX,
+ This->params.hFocusWindow, mode, ret);
+ } else {
+ hr = NineSwapChain9_new(This, TRUE, present,
+ &pPresentationParameters[i], pCTX,
+ This->params.hFocusWindow,
+ &This->swapchains[i]);
+ }
+
+ ID3DPresent_Release(present);
+ if (FAILED(hr))
+ return hr;
+ NineUnknown_ConvertRefToBind(NineUnknown(This->swapchains[i]));
+
+ hr = NineSwapChain9_GetBackBuffer(This->swapchains[i], 0,
+ D3DBACKBUFFER_TYPE_MONO,
+ (IDirect3DSurface9 **)
+ &This->state.rt[i]);
+ if (FAILED(hr))
+ return hr;
+ NineUnknown_ConvertRefToBind(NineUnknown(This->state.rt[i]));
+ }
+
+ This->cursor.software = FALSE;
+ This->cursor.hotspot.x = -1;
+ This->cursor.hotspot.y = -1;
+ {
+ struct pipe_resource tmpl;
+ tmpl.target = PIPE_TEXTURE_2D;
+ tmpl.format = PIPE_FORMAT_R8G8B8A8_UNORM;
+ tmpl.width0 = 64;
+ tmpl.height0 = 64;
+ tmpl.depth0 = 1;
+ tmpl.array_size = 1;
+ tmpl.last_level = 0;
+ tmpl.nr_samples = 0;
+ tmpl.usage = PIPE_USAGE_DEFAULT;
+ tmpl.bind = PIPE_BIND_CURSOR | PIPE_BIND_SAMPLER_VIEW;
+ tmpl.flags = 0;
+
+ This->cursor.image = pScreen->resource_create(pScreen, &tmpl);
+ if (!This->cursor.image)
+ return D3DERR_OUTOFVIDEOMEMORY;
+ }
+
+ /* Create constant buffers. */
+ {
+ struct pipe_resource tmpl;
+ unsigned max_const_vs, max_const_ps;
+
+ max_const_vs = _min(pScreen->get_shader_param(pScreen, PIPE_SHADER_VERTEX,
+ PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) /
+ sizeof(float[4]),
+ NINE_MAX_CONST_ALL);
+ max_const_ps = _min(pScreen->get_shader_param(pScreen, PIPE_SHADER_FRAGMENT,
+ PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) /
+ sizeof(float[4]),
+ NINE_MAX_CONST_ALL);
+
+ This->max_vs_const_f = max_const_vs -
+ (NINE_MAX_CONST_I + NINE_MAX_CONST_B / 4);
+ This->max_ps_const_f = max_const_ps -
+ (NINE_MAX_CONST_I + NINE_MAX_CONST_B / 4);
+
+ /* Include space for I,B constants for user constbuf. */
+ This->state.vs_const_f = CALLOC(NINE_MAX_CONST_ALL, sizeof(float[4]));
+ This->state.ps_const_f = CALLOC(NINE_MAX_CONST_ALL, sizeof(float[4]));
+ if (!This->state.vs_const_f || !This->state.ps_const_f)
+ return E_OUTOFMEMORY;
+
+ if (strstr(pScreen->get_name(pScreen), "AMD") ||
+ strstr(pScreen->get_name(pScreen), "ATI"))
+ This->prefer_user_constbuf = TRUE;
+
+ tmpl.target = PIPE_BUFFER;
+ tmpl.format = PIPE_FORMAT_R8_UNORM;
+ tmpl.height0 = 1;
+ tmpl.depth0 = 1;
+ tmpl.array_size = 1;
+ tmpl.last_level = 0;
+ tmpl.nr_samples = 0;
+ tmpl.usage = PIPE_USAGE_DYNAMIC;
+ tmpl.bind = PIPE_BIND_CONSTANT_BUFFER;
+ tmpl.flags = 0;
+
+ tmpl.width0 = max_const_vs * sizeof(float[4]);
+ This->constbuf_vs = pScreen->resource_create(pScreen, &tmpl);
+
+ tmpl.width0 = max_const_ps * sizeof(float[4]);
+ This->constbuf_ps = pScreen->resource_create(pScreen, &tmpl);
+
+ if (!This->constbuf_vs || !This->constbuf_ps)
+ return E_OUTOFMEMORY;
+ }
+
+ This->vs_bool_true = pScreen->get_shader_param(pScreen,
+ PIPE_SHADER_VERTEX,
+ PIPE_SHADER_CAP_INTEGERS) ? 0xFFFFFFFF : fui(1.0f);
+ This->ps_bool_true = pScreen->get_shader_param(pScreen,
+ PIPE_SHADER_FRAGMENT,
+ PIPE_SHADER_CAP_INTEGERS) ? 0xFFFFFFFF : fui(1.0f);
+
+ /* Allocate upload helper for drivers that suck (from st pov ;). */
+ {
+ unsigned bind = 0;
+
+ This->driver_caps.user_vbufs = GET_PCAP(USER_VERTEX_BUFFERS);
+ This->driver_caps.user_ibufs = GET_PCAP(USER_INDEX_BUFFERS);
+
+ if (!This->driver_caps.user_vbufs) bind |= PIPE_BIND_VERTEX_BUFFER;
+ if (!This->driver_caps.user_ibufs) bind |= PIPE_BIND_INDEX_BUFFER;
+ if (bind)
+ This->upload = u_upload_create(This->pipe, 1 << 20, 4, bind);
+ }
+
+ This->driver_caps.window_space_position_support = GET_PCAP(TGSI_VS_WINDOW_SPACE_POSITION);
+
+ nine_ff_init(This); /* initialize fixed function code */
+
+ NineDevice9_SetDefaultState(This, FALSE);
+ NineDevice9_RestoreNonCSOState(This, ~0);
+
+ This->update = &This->state;
+ nine_update_state(This, ~0);
+
+ /* Is just used to pass the parameter from NineDevice9Ex_ctor */
+ This->pFullscreenDisplayMode = NULL;
+
+ ID3DPresentGroup_Release(This->present);
+
+ return D3D_OK;
+}
+#undef GET_PCAP
+
+void
+NineDevice9_dtor( struct NineDevice9 *This )
+{
+ unsigned i;
+
+ DBG("This=%p\n", This);
+
+ if (This->pipe && This->cso)
+ nine_pipe_context_clear(This);
+ nine_ff_fini(This);
+ nine_state_clear(&This->state, TRUE);
+
+ if (This->upload)
+ u_upload_destroy(This->upload);
+
+ nine_bind(&This->record, NULL);
+
+ pipe_resource_reference(&This->constbuf_vs, NULL);
+ pipe_resource_reference(&This->constbuf_ps, NULL);
+ FREE(This->state.vs_const_f);
+ FREE(This->state.ps_const_f);
+
+ if (This->swapchains) {
+ for (i = 0; i < This->nswapchains; ++i)
+ NineUnknown_Unbind(NineUnknown(This->swapchains[i]));
+ FREE(This->swapchains);
+ }
+
+ /* state stuff */
+ if (This->pipe) {
+ if (This->cso) {
+ cso_release_all(This->cso);
+ cso_destroy_context(This->cso);
+ }
+ if (This->pipe->destroy) { This->pipe->destroy(This->pipe); }
+ }
+
+ if (This->present) { ID3DPresentGroup_Release(This->present); }
+ if (This->d3d9) { IDirect3D9_Release(This->d3d9); }
+
+ NineUnknown_dtor(&This->base);
+}
+
+struct pipe_screen *
+NineDevice9_GetScreen( struct NineDevice9 *This )
+{
+ return This->screen;
+}
+
+struct pipe_context *
+NineDevice9_GetPipe( struct NineDevice9 *This )
+{
+ return This->pipe;
+}
+
+struct cso_context *
+NineDevice9_GetCSO( struct NineDevice9 *This )
+{
+ return This->cso;
+}
+
+const D3DCAPS9 *
+NineDevice9_GetCaps( struct NineDevice9 *This )
+{
+ return &This->caps;
+}
+
+static INLINE void
+NineDevice9_PauseRecording( struct NineDevice9 *This )
+{
+ if (This->record) {
+ This->update = &This->state;
+ This->is_recording = FALSE;
+ }
+}
+
+static INLINE void
+NineDevice9_ResumeRecording( struct NineDevice9 *This )
+{
+ if (This->record) {
+ This->update = &This->record->state;
+ This->is_recording = TRUE;
+ }
+}
+
+HRESULT WINAPI
+NineDevice9_TestCooperativeLevel( struct NineDevice9 *This )
+{
+ return D3D_OK; /* TODO */
+}
+
+UINT WINAPI
+NineDevice9_GetAvailableTextureMem( struct NineDevice9 *This )
+{
+ return This->screen->get_param(This->screen, PIPE_CAP_VIDEO_MEMORY);
+}
+
+HRESULT WINAPI
+NineDevice9_EvictManagedResources( struct NineDevice9 *This )
+{
+ /* We don't really need to do anything here, but might want to free up
+ * the GPU virtual address space by killing pipe_resources.
+ */
+ STUB(D3D_OK);
+}
+
+HRESULT WINAPI
+NineDevice9_GetDirect3D( struct NineDevice9 *This,
+ IDirect3D9 **ppD3D9 )
+{
+ user_assert(ppD3D9 != NULL, E_POINTER);
+ IDirect3D9_AddRef(This->d3d9);
+ *ppD3D9 = This->d3d9;
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_GetDeviceCaps( struct NineDevice9 *This,
+ D3DCAPS9 *pCaps )
+{
+ user_assert(pCaps != NULL, D3DERR_INVALIDCALL);
+ *pCaps = This->caps;
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_GetDisplayMode( struct NineDevice9 *This,
+ UINT iSwapChain,
+ D3DDISPLAYMODE *pMode )
+{
+ DBG("This=%p iSwapChain=%u pMode=%p\n", This, iSwapChain, pMode);
+
+ user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL);
+
+ return NineSwapChain9_GetDisplayMode(This->swapchains[iSwapChain], pMode);
+}
+
+HRESULT WINAPI
+NineDevice9_GetCreationParameters( struct NineDevice9 *This,
+ D3DDEVICE_CREATION_PARAMETERS *pParameters )
+{
+ user_assert(pParameters != NULL, D3DERR_INVALIDCALL);
+ *pParameters = This->params;
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_SetCursorProperties( struct NineDevice9 *This,
+ UINT XHotSpot,
+ UINT YHotSpot,
+ IDirect3DSurface9 *pCursorBitmap )
+{
+ /* TODO: hardware cursor */
+ struct NineSurface9 *surf = NineSurface9(pCursorBitmap);
+ struct pipe_context *pipe = This->pipe;
+ struct pipe_box box;
+ struct pipe_transfer *transfer;
+ void *ptr;
+
+ DBG_FLAG(DBG_SWAPCHAIN, "This=%p XHotSpot=%u YHotSpot=%u "
+ "pCursorBitmap=%p\n", This, XHotSpot, YHotSpot, pCursorBitmap);
+
+ user_assert(pCursorBitmap, D3DERR_INVALIDCALL);
+
+ This->cursor.w = MIN2(surf->desc.Width, This->cursor.image->width0);
+ This->cursor.h = MIN2(surf->desc.Height, This->cursor.image->height0);
+
+ u_box_origin_2d(This->cursor.w, This->cursor.h, &box);
+
+ ptr = pipe->transfer_map(pipe, This->cursor.image, 0,
+ PIPE_TRANSFER_WRITE |
+ PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE,
+ &box, &transfer);
+ if (!ptr)
+ ret_err("Failed to update cursor image.\n", D3DERR_DRIVERINTERNALERROR);
+
+ This->cursor.hotspot.x = XHotSpot;
+ This->cursor.hotspot.y = YHotSpot;
+
+ /* Copy cursor image to internal storage. */
+ {
+ D3DLOCKED_RECT lock;
+ HRESULT hr;
+ const struct util_format_description *sfmt =
+ util_format_description(surf->base.info.format);
+ assert(sfmt);
+
+ hr = NineSurface9_LockRect(surf, &lock, NULL, D3DLOCK_READONLY);
+ if (FAILED(hr))
+ ret_err("Failed to map cursor source image.\n",
+ D3DERR_DRIVERINTERNALERROR);
+
+ sfmt->unpack_rgba_8unorm(ptr, transfer->stride,
+ lock.pBits, lock.Pitch,
+ This->cursor.w, This->cursor.h);
+
+ if (!This->cursor.software &&
+ This->cursor.w == 32 && This->cursor.h == 32)
+ ID3DPresent_SetCursor(This->swapchains[0]->present,
+ lock.pBits, &This->cursor.hotspot,
+ This->cursor.visible);
+
+ NineSurface9_UnlockRect(surf);
+ }
+ pipe->transfer_unmap(pipe, transfer);
+
+ return D3D_OK;
+}
+
+void WINAPI
+NineDevice9_SetCursorPosition( struct NineDevice9 *This,
+ int X,
+ int Y,
+ DWORD Flags )
+{
+ struct NineSwapChain9 *swap = This->swapchains[0];
+
+ This->cursor.pos.x = X;
+ This->cursor.pos.y = Y;
+
+ if (!This->cursor.software)
+ ID3DPresent_SetCursorPos(swap->present, &This->cursor.pos);
+}
+
+BOOL WINAPI
+NineDevice9_ShowCursor( struct NineDevice9 *This,
+ BOOL bShow )
+{
+ BOOL old = This->cursor.visible;
+ This->cursor.visible = bShow && (This->cursor.hotspot.x != -1);
+ if (!This->cursor.software)
+ ID3DPresent_SetCursor(This->swapchains[0]->present, NULL, NULL, bShow);
+
+ return old;
+}
+
+HRESULT WINAPI
+NineDevice9_CreateAdditionalSwapChain( struct NineDevice9 *This,
+ D3DPRESENT_PARAMETERS *pPresentationParameters,
+ IDirect3DSwapChain9 **pSwapChain )
+{
+ struct NineSwapChain9 *swapchain, *tmplt = This->swapchains[0];
+ ID3DPresent *present;
+ HRESULT hr;
+
+ user_assert(pPresentationParameters, D3DERR_INVALIDCALL);
+
+ hr = ID3DPresentGroup_CreateAdditionalPresent(This->present, pPresentationParameters, &present);
+
+ if (FAILED(hr))
+ return hr;
+
+ hr = NineSwapChain9_new(This, FALSE, present, pPresentationParameters,
+ tmplt->actx,
+ tmplt->params.hDeviceWindow,
+ &swapchain);
+ if (FAILED(hr))
+ return hr;
+
+ *pSwapChain = (IDirect3DSwapChain9 *)swapchain;
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_GetSwapChain( struct NineDevice9 *This,
+ UINT iSwapChain,
+ IDirect3DSwapChain9 **pSwapChain )
+{
+ user_assert(pSwapChain != NULL, D3DERR_INVALIDCALL);
+
+ *pSwapChain = NULL;
+ user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL);
+
+ NineUnknown_AddRef(NineUnknown(This->swapchains[iSwapChain]));
+ *pSwapChain = (IDirect3DSwapChain9 *)This->swapchains[iSwapChain];
+
+ return D3D_OK;
+}
+
+UINT WINAPI
+NineDevice9_GetNumberOfSwapChains( struct NineDevice9 *This )
+{
+ return This->nswapchains;
+}
+
+HRESULT WINAPI
+NineDevice9_Reset( struct NineDevice9 *This,
+ D3DPRESENT_PARAMETERS *pPresentationParameters )
+{
+ HRESULT hr = D3D_OK;
+ unsigned i;
+
+ DBG("This=%p pPresentationParameters=%p\n", This, pPresentationParameters);
+
+ for (i = 0; i < This->nswapchains; ++i) {
+ D3DPRESENT_PARAMETERS *params = &pPresentationParameters[i];
+ hr = NineSwapChain9_Resize(This->swapchains[i], params, NULL);
+ if (FAILED(hr))
+ return (hr == D3DERR_OUTOFVIDEOMEMORY) ? hr : D3DERR_DEVICELOST;
+ }
+
+ nine_pipe_context_clear(This);
+ nine_state_clear(&This->state, TRUE);
+
+ NineDevice9_SetDefaultState(This, TRUE);
+ NineDevice9_SetRenderTarget(
+ This, 0, (IDirect3DSurface9 *)This->swapchains[0]->buffers[0]);
+ /* XXX: better use GetBackBuffer here ? */
+
+ return hr;
+}
+
+HRESULT WINAPI
+NineDevice9_Present( struct NineDevice9 *This,
+ const RECT *pSourceRect,
+ const RECT *pDestRect,
+ HWND hDestWindowOverride,
+ const RGNDATA *pDirtyRegion )
+{
+ unsigned i;
+ HRESULT hr;
+
+ /* XXX is this right? */
+ for (i = 0; i < This->nswapchains; ++i) {
+ hr = NineSwapChain9_Present(This->swapchains[i], pSourceRect, pDestRect,
+ hDestWindowOverride, pDirtyRegion, 0);
+ if (FAILED(hr)) { return hr; }
+ }
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_GetBackBuffer( struct NineDevice9 *This,
+ UINT iSwapChain,
+ UINT iBackBuffer,
+ D3DBACKBUFFER_TYPE Type,
+ IDirect3DSurface9 **ppBackBuffer )
+{
+ user_assert(ppBackBuffer != NULL, D3DERR_INVALIDCALL);
+ user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL);
+
+ return NineSwapChain9_GetBackBuffer(This->swapchains[iSwapChain],
+ iBackBuffer, Type, ppBackBuffer);
+}
+
+HRESULT WINAPI
+NineDevice9_GetRasterStatus( struct NineDevice9 *This,
+ UINT iSwapChain,
+ D3DRASTER_STATUS *pRasterStatus )
+{
+ user_assert(pRasterStatus != NULL, D3DERR_INVALIDCALL);
+ user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL);
+
+ return NineSwapChain9_GetRasterStatus(This->swapchains[iSwapChain],
+ pRasterStatus);
+}
+
+HRESULT WINAPI
+NineDevice9_SetDialogBoxMode( struct NineDevice9 *This,
+ BOOL bEnableDialogs )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+void WINAPI
+NineDevice9_SetGammaRamp( struct NineDevice9 *This,
+ UINT iSwapChain,
+ DWORD Flags,
+ const D3DGAMMARAMP *pRamp )
+{
+ DBG("This=%p iSwapChain=%u Flags=%x pRamp=%p\n", This,
+ iSwapChain, Flags, pRamp);
+
+ user_warn(iSwapChain >= This->nswapchains);
+ user_warn(!pRamp);
+
+ if (pRamp && (iSwapChain < This->nswapchains)) {
+ struct NineSwapChain9 *swap = This->swapchains[iSwapChain];
+ swap->gamma = *pRamp;
+ ID3DPresent_SetGammaRamp(swap->present, pRamp, swap->params.hDeviceWindow);
+ }
+}
+
+void WINAPI
+NineDevice9_GetGammaRamp( struct NineDevice9 *This,
+ UINT iSwapChain,
+ D3DGAMMARAMP *pRamp )
+{
+ DBG("This=%p iSwapChain=%u pRamp=%p\n", This, iSwapChain, pRamp);
+
+ user_warn(iSwapChain >= This->nswapchains);
+ user_warn(!pRamp);
+
+ if (pRamp && (iSwapChain < This->nswapchains))
+ *pRamp = This->swapchains[iSwapChain]->gamma;
+}
+
+HRESULT WINAPI
+NineDevice9_CreateTexture( struct NineDevice9 *This,
+ UINT Width,
+ UINT Height,
+ UINT Levels,
+ DWORD Usage,
+ D3DFORMAT Format,
+ D3DPOOL Pool,
+ IDirect3DTexture9 **ppTexture,
+ HANDLE *pSharedHandle )
+{
+ struct NineTexture9 *tex;
+ HRESULT hr;
+
+ DBG("This=%p Width=%u Height=%u Levels=%u Usage=%s Format=%s Pool=%s "
+ "ppOut=%p pSharedHandle=%p\n", This, Width, Height, Levels,
+ nine_D3DUSAGE_to_str(Usage), d3dformat_to_string(Format),
+ nine_D3DPOOL_to_str(Pool), ppTexture, pSharedHandle);
+
+ Usage &= D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_DMAP |
+ D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE | D3DUSAGE_RENDERTARGET |
+ D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_TEXTAPI;
+
+ user_assert(Width && Height, D3DERR_INVALIDCALL);
+ user_assert(!pSharedHandle || This->ex, D3DERR_INVALIDCALL);
+ /* When is used shared handle, Pool must be
+ * SYSTEMMEM with Levels 1 or DEFAULT with any Levels */
+ user_assert(!pSharedHandle || Pool != D3DPOOL_SYSTEMMEM || Levels == 1,
+ D3DERR_INVALIDCALL);
+ user_assert(!pSharedHandle || Pool == D3DPOOL_SYSTEMMEM || Pool == D3DPOOL_DEFAULT,
+ D3DERR_INVALIDCALL);
+ user_assert((Usage != D3DUSAGE_AUTOGENMIPMAP || Levels <= 1), D3DERR_INVALIDCALL);
+
+ hr = NineTexture9_new(This, Width, Height, Levels, Usage, Format, Pool,
+ &tex, pSharedHandle);
+ if (SUCCEEDED(hr))
+ *ppTexture = (IDirect3DTexture9 *)tex;
+
+ return hr;
+}
+
+HRESULT WINAPI
+NineDevice9_CreateVolumeTexture( struct NineDevice9 *This,
+ UINT Width,
+ UINT Height,
+ UINT Depth,
+ UINT Levels,
+ DWORD Usage,
+ D3DFORMAT Format,
+ D3DPOOL Pool,
+ IDirect3DVolumeTexture9 **ppVolumeTexture,
+ HANDLE *pSharedHandle )
+{
+ struct NineVolumeTexture9 *tex;
+ HRESULT hr;
+
+ DBG("This=%p Width=%u Height=%u Depth=%u Levels=%u Usage=%s Format=%s Pool=%s "
+ "ppOut=%p pSharedHandle=%p\n", This, Width, Height, Depth, Levels,
+ nine_D3DUSAGE_to_str(Usage), d3dformat_to_string(Format),
+ nine_D3DPOOL_to_str(Pool), ppVolumeTexture, pSharedHandle);
+
+ Usage &= D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE |
+ D3DUSAGE_SOFTWAREPROCESSING;
+
+ user_assert(Width && Height && Depth, D3DERR_INVALIDCALL);
+ user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
+
+ hr = NineVolumeTexture9_new(This, Width, Height, Depth, Levels,
+ Usage, Format, Pool, &tex, pSharedHandle);
+ if (SUCCEEDED(hr))
+ *ppVolumeTexture = (IDirect3DVolumeTexture9 *)tex;
+
+ return hr;
+}
+
+HRESULT WINAPI
+NineDevice9_CreateCubeTexture( struct NineDevice9 *This,
+ UINT EdgeLength,
+ UINT Levels,
+ DWORD Usage,
+ D3DFORMAT Format,
+ D3DPOOL Pool,
+ IDirect3DCubeTexture9 **ppCubeTexture,
+ HANDLE *pSharedHandle )
+{
+ struct NineCubeTexture9 *tex;
+ HRESULT hr;
+
+ DBG("This=%p EdgeLength=%u Levels=%u Usage=%s Format=%s Pool=%s ppOut=%p "
+ "pSharedHandle=%p\n", This, EdgeLength, Levels,
+ nine_D3DUSAGE_to_str(Usage), d3dformat_to_string(Format),
+ nine_D3DPOOL_to_str(Pool), ppCubeTexture, pSharedHandle);
+
+ Usage &= D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_DYNAMIC |
+ D3DUSAGE_NONSECURE | D3DUSAGE_RENDERTARGET |
+ D3DUSAGE_SOFTWAREPROCESSING;
+
+ user_assert(EdgeLength, D3DERR_INVALIDCALL);
+ user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
+
+ hr = NineCubeTexture9_new(This, EdgeLength, Levels, Usage, Format, Pool,
+ &tex, pSharedHandle);
+ if (SUCCEEDED(hr))
+ *ppCubeTexture = (IDirect3DCubeTexture9 *)tex;
+
+ return hr;
+}
+
+HRESULT WINAPI
+NineDevice9_CreateVertexBuffer( struct NineDevice9 *This,
+ UINT Length,
+ DWORD Usage,
+ DWORD FVF,
+ D3DPOOL Pool,
+ IDirect3DVertexBuffer9 **ppVertexBuffer,
+ HANDLE *pSharedHandle )
+{
+ struct NineVertexBuffer9 *buf;
+ HRESULT hr;
+ D3DVERTEXBUFFER_DESC desc;
+
+ DBG("This=%p Length=%u Usage=%x FVF=%x Pool=%u ppOut=%p pSharedHandle=%p\n",
+ This, Length, Usage, FVF, Pool, ppVertexBuffer, pSharedHandle);
+
+ user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_NOTAVAILABLE);
+
+ desc.Format = D3DFMT_VERTEXDATA;
+ desc.Type = D3DRTYPE_VERTEXBUFFER;
+ desc.Usage = Usage &
+ (D3DUSAGE_DONOTCLIP | D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE |
+ D3DUSAGE_NPATCHES | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES |
+ D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_TEXTAPI |
+ D3DUSAGE_WRITEONLY);
+ desc.Pool = Pool;
+ desc.Size = Length;
+ desc.FVF = FVF;
+
+ user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
+ user_assert(desc.Usage == Usage, D3DERR_INVALIDCALL);
+
+ hr = NineVertexBuffer9_new(This, &desc, &buf);
+ if (SUCCEEDED(hr))
+ *ppVertexBuffer = (IDirect3DVertexBuffer9 *)buf;
+ return hr;
+}
+
+HRESULT WINAPI
+NineDevice9_CreateIndexBuffer( struct NineDevice9 *This,
+ UINT Length,
+ DWORD Usage,
+ D3DFORMAT Format,
+ D3DPOOL Pool,
+ IDirect3DIndexBuffer9 **ppIndexBuffer,
+ HANDLE *pSharedHandle )
+{
+ struct NineIndexBuffer9 *buf;
+ HRESULT hr;
+ D3DINDEXBUFFER_DESC desc;
+
+ DBG("This=%p Length=%u Usage=%x Format=%s Pool=%u ppOut=%p "
+ "pSharedHandle=%p\n", This, Length, Usage,
+ d3dformat_to_string(Format), Pool, ppIndexBuffer, pSharedHandle);
+
+ user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_NOTAVAILABLE);
+
+ desc.Format = Format;
+ desc.Type = D3DRTYPE_INDEXBUFFER;
+ desc.Usage = Usage &
+ (D3DUSAGE_DONOTCLIP | D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE |
+ D3DUSAGE_NPATCHES | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES |
+ D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_WRITEONLY);
+ desc.Pool = Pool;
+ desc.Size = Length;
+
+ user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
+ user_assert(desc.Usage == Usage, D3DERR_INVALIDCALL);
+
+ hr = NineIndexBuffer9_new(This, &desc, &buf);
+ if (SUCCEEDED(hr))
+ *ppIndexBuffer = (IDirect3DIndexBuffer9 *)buf;
+ return hr;
+}
+
+static HRESULT
+create_zs_or_rt_surface(struct NineDevice9 *This,
+ unsigned type, /* 0 = RT, 1 = ZS, 2 = plain */
+ D3DPOOL Pool,
+ UINT Width, UINT Height,
+ D3DFORMAT Format,
+ D3DMULTISAMPLE_TYPE MultiSample,
+ DWORD MultisampleQuality,
+ BOOL Discard_or_Lockable,
+ IDirect3DSurface9 **ppSurface,
+ HANDLE *pSharedHandle)
+{
+ struct NineSurface9 *surface;
+ struct pipe_screen *screen = This->screen;
+ struct pipe_resource *resource = NULL;
+ HRESULT hr;
+ D3DSURFACE_DESC desc;
+ struct pipe_resource templ;
+
+ DBG("This=%p type=%u Pool=%s Width=%u Height=%u Format=%s MS=%u Quality=%u "
+ "Discard_or_Lockable=%i ppSurface=%p pSharedHandle=%p\n",
+ This, type, nine_D3DPOOL_to_str(Pool), Width, Height,
+ d3dformat_to_string(Format), MultiSample, MultisampleQuality,
+ Discard_or_Lockable, ppSurface, pSharedHandle);
+
+ if (pSharedHandle)
+ DBG("FIXME Used shared handle! This option isn't probably handled correctly!\n");
+
+ user_assert(Width && Height, D3DERR_INVALIDCALL);
+ user_assert(Pool != D3DPOOL_MANAGED, D3DERR_INVALIDCALL);
+
+ templ.target = PIPE_TEXTURE_2D;
+ templ.format = d3d9_to_pipe_format(Format);
+ templ.width0 = Width;
+ templ.height0 = Height;
+ templ.depth0 = 1;
+ templ.array_size = 1;
+ templ.last_level = 0;
+ templ.nr_samples = (unsigned)MultiSample;
+ templ.usage = PIPE_USAGE_DEFAULT;
+ templ.flags = 0;
+ templ.bind = PIPE_BIND_SAMPLER_VIEW; /* StretchRect */
+ switch (type) {
+ case 0: templ.bind |= PIPE_BIND_RENDER_TARGET; break;
+ case 1: templ.bind |= PIPE_BIND_DEPTH_STENCIL; break;
+ default:
+ assert(type == 2);
+ break;
+ }
+
+ desc.Format = Format;
+ desc.Type = D3DRTYPE_SURFACE;
+ desc.Usage = 0;
+ desc.Pool = Pool;
+ desc.MultiSampleType = MultiSample;
+ desc.MultiSampleQuality = MultisampleQuality;
+ desc.Width = Width;
+ desc.Height = Height;
+ switch (type) {
+ case 0: desc.Usage = D3DUSAGE_RENDERTARGET; break;
+ case 1: desc.Usage = D3DUSAGE_DEPTHSTENCIL; break;
+ default: break;
+ }
+
+ if (Pool == D3DPOOL_DEFAULT && Format != D3DFMT_NULL) {
+ /* resource_create doesn't return an error code, so check format here */
+ user_assert(CHECK_PIPE_RESOURCE_TEMPLATE(templ), D3DERR_INVALIDCALL);
+ resource = screen->resource_create(screen, &templ);
+ user_assert(resource, D3DERR_OUTOFVIDEOMEMORY);
+ if (Discard_or_Lockable && (desc.Usage & D3DUSAGE_RENDERTARGET))
+ resource->flags |= NINE_RESOURCE_FLAG_LOCKABLE;
+ } else {
+ resource = NULL;
+ }
+ hr = NineSurface9_new(This, NULL, resource, 0, 0, 0, &desc, &surface);
+ pipe_resource_reference(&resource, NULL);
+
+ if (SUCCEEDED(hr))
+ *ppSurface = (IDirect3DSurface9 *)surface;
+ return hr;
+}
+
+HRESULT WINAPI
+NineDevice9_CreateRenderTarget( struct NineDevice9 *This,
+ UINT Width,
+ UINT Height,
+ D3DFORMAT Format,
+ D3DMULTISAMPLE_TYPE MultiSample,
+ DWORD MultisampleQuality,
+ BOOL Lockable,
+ IDirect3DSurface9 **ppSurface,
+ HANDLE *pSharedHandle )
+{
+ return create_zs_or_rt_surface(This, 0, D3DPOOL_DEFAULT,
+ Width, Height, Format,
+ MultiSample, MultisampleQuality,
+ Lockable, ppSurface, pSharedHandle);
+}
+
+HRESULT WINAPI
+NineDevice9_CreateDepthStencilSurface( struct NineDevice9 *This,
+ UINT Width,
+ UINT Height,
+ D3DFORMAT Format,
+ D3DMULTISAMPLE_TYPE MultiSample,
+ DWORD MultisampleQuality,
+ BOOL Discard,
+ IDirect3DSurface9 **ppSurface,
+ HANDLE *pSharedHandle )
+{
+ return create_zs_or_rt_surface(This, 1, D3DPOOL_DEFAULT,
+ Width, Height, Format,
+ MultiSample, MultisampleQuality,
+ Discard, ppSurface, pSharedHandle);
+}
+
+HRESULT WINAPI
+NineDevice9_UpdateSurface( struct NineDevice9 *This,
+ IDirect3DSurface9 *pSourceSurface,
+ const RECT *pSourceRect,
+ IDirect3DSurface9 *pDestinationSurface,
+ const POINT *pDestPoint )
+{
+ struct NineSurface9 *dst = NineSurface9(pDestinationSurface);
+ struct NineSurface9 *src = NineSurface9(pSourceSurface);
+
+ DBG("This=%p pSourceSurface=%p pDestinationSurface=%p "
+ "pSourceRect=%p pDestPoint=%p\n", This,
+ pSourceSurface, pDestinationSurface, pSourceRect, pDestPoint);
+ if (pSourceRect)
+ DBG("pSourceRect = (%u,%u)-(%u,%u)\n",
+ pSourceRect->left, pSourceRect->top,
+ pSourceRect->right, pSourceRect->bottom);
+ if (pDestPoint)
+ DBG("pDestPoint = (%u,%u)\n", pDestPoint->x, pDestPoint->y);
+
+ user_assert(dst->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
+ user_assert(src->base.pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL);
+
+ user_assert(dst->desc.MultiSampleType == D3DMULTISAMPLE_NONE, D3DERR_INVALIDCALL);
+ user_assert(src->desc.MultiSampleType == D3DMULTISAMPLE_NONE, D3DERR_INVALIDCALL);
+
+ return NineSurface9_CopySurface(dst, src, pDestPoint, pSourceRect);
+}
+
+HRESULT WINAPI
+NineDevice9_UpdateTexture( struct NineDevice9 *This,
+ IDirect3DBaseTexture9 *pSourceTexture,
+ IDirect3DBaseTexture9 *pDestinationTexture )
+{
+ struct NineBaseTexture9 *dstb = NineBaseTexture9(pDestinationTexture);
+ struct NineBaseTexture9 *srcb = NineBaseTexture9(pSourceTexture);
+ unsigned l, m;
+ unsigned last_level = dstb->base.info.last_level;
+
+ DBG("This=%p pSourceTexture=%p pDestinationTexture=%p\n", This,
+ pSourceTexture, pDestinationTexture);
+
+ user_assert(pSourceTexture != pDestinationTexture, D3DERR_INVALIDCALL);
+
+ user_assert(dstb->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
+ user_assert(srcb->base.pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL);
+
+ if (dstb->base.usage & D3DUSAGE_AUTOGENMIPMAP) {
+ /* Only the first level is updated, the others regenerated. */
+ last_level = 0;
+ } else {
+ user_assert(!(srcb->base.usage & D3DUSAGE_AUTOGENMIPMAP), D3DERR_INVALIDCALL);
+ }
+
+ user_assert(dstb->base.type == srcb->base.type, D3DERR_INVALIDCALL);
+
+ /* TODO: We can restrict the update to the dirty portions of the source.
+ * Yes, this seems silly, but it's what MSDN says ...
+ */
+
+ /* Find src level that matches dst level 0: */
+ user_assert(srcb->base.info.width0 >= dstb->base.info.width0 &&
+ srcb->base.info.height0 >= dstb->base.info.height0 &&
+ srcb->base.info.depth0 >= dstb->base.info.depth0,
+ D3DERR_INVALIDCALL);
+ for (m = 0; m <= srcb->base.info.last_level; ++m) {
+ unsigned w = u_minify(srcb->base.info.width0, m);
+ unsigned h = u_minify(srcb->base.info.height0, m);
+ unsigned d = u_minify(srcb->base.info.depth0, m);
+
+ if (w == dstb->base.info.width0 &&
+ h == dstb->base.info.height0 &&
+ d == dstb->base.info.depth0)
+ break;
+ }
+ user_assert(m <= srcb->base.info.last_level, D3DERR_INVALIDCALL);
+
+ last_level = MIN2(last_level, srcb->base.info.last_level - m);
+
+ if (dstb->base.type == D3DRTYPE_TEXTURE) {
+ struct NineTexture9 *dst = NineTexture9(dstb);
+ struct NineTexture9 *src = NineTexture9(srcb);
+
+ for (l = 0; l <= last_level; ++l, ++m)
+ NineSurface9_CopySurface(dst->surfaces[l],
+ src->surfaces[m], NULL, NULL);
+ } else
+ if (dstb->base.type == D3DRTYPE_CUBETEXTURE) {
+ struct NineCubeTexture9 *dst = NineCubeTexture9(dstb);
+ struct NineCubeTexture9 *src = NineCubeTexture9(srcb);
+ unsigned z;
+
+ /* GPUs usually have them stored as arrays of mip-mapped 2D textures. */
+ for (z = 0; z < 6; ++z) {
+ for (l = 0; l <= last_level; ++l, ++m) {
+ NineSurface9_CopySurface(dst->surfaces[l * 6 + z],
+ src->surfaces[m * 6 + z], NULL, NULL);
+ }
+ m -= l;
+ }
+ } else
+ if (dstb->base.type == D3DRTYPE_VOLUMETEXTURE) {
+ struct NineVolumeTexture9 *dst = NineVolumeTexture9(dstb);
+ struct NineVolumeTexture9 *src = NineVolumeTexture9(srcb);
+
+ for (l = 0; l <= last_level; ++l, ++m)
+ NineVolume9_CopyVolume(dst->volumes[l],
+ src->volumes[m], 0, 0, 0, NULL);
+ } else{
+ assert(!"invalid texture type");
+ }
+
+ if (dstb->base.usage & D3DUSAGE_AUTOGENMIPMAP)
+ NineBaseTexture9_GenerateMipSubLevels(dstb);
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_GetRenderTargetData( struct NineDevice9 *This,
+ IDirect3DSurface9 *pRenderTarget,
+ IDirect3DSurface9 *pDestSurface )
+{
+ struct NineSurface9 *dst = NineSurface9(pDestSurface);
+ struct NineSurface9 *src = NineSurface9(pRenderTarget);
+
+ DBG("This=%p pRenderTarget=%p pDestSurface=%p\n",
+ This, pRenderTarget, pDestSurface);
+
+ user_assert(dst->desc.Pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL);
+ user_assert(src->desc.Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
+
+ user_assert(dst->desc.MultiSampleType < 2, D3DERR_INVALIDCALL);
+ user_assert(src->desc.MultiSampleType < 2, D3DERR_INVALIDCALL);
+
+ return NineSurface9_CopySurface(dst, src, NULL, NULL);
+}
+
+HRESULT WINAPI
+NineDevice9_GetFrontBufferData( struct NineDevice9 *This,
+ UINT iSwapChain,
+ IDirect3DSurface9 *pDestSurface )
+{
+ DBG("This=%p iSwapChain=%u pDestSurface=%p\n", This,
+ iSwapChain, pDestSurface);
+
+ user_assert(pDestSurface != NULL, D3DERR_INVALIDCALL);
+ user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL);
+
+ return NineSwapChain9_GetFrontBufferData(This->swapchains[iSwapChain],
+ pDestSurface);
+}
+
+HRESULT WINAPI
+NineDevice9_StretchRect( struct NineDevice9 *This,
+ IDirect3DSurface9 *pSourceSurface,
+ const RECT *pSourceRect,
+ IDirect3DSurface9 *pDestSurface,
+ const RECT *pDestRect,
+ D3DTEXTUREFILTERTYPE Filter )
+{
+ struct pipe_screen *screen = This->screen;
+ struct pipe_context *pipe = This->pipe;
+ struct NineSurface9 *dst = NineSurface9(pDestSurface);
+ struct NineSurface9 *src = NineSurface9(pSourceSurface);
+ struct pipe_resource *dst_res = NineSurface9_GetResource(dst);
+ struct pipe_resource *src_res = NineSurface9_GetResource(src);
+ const boolean zs = util_format_is_depth_or_stencil(dst_res->format);
+ struct pipe_blit_info blit;
+ boolean scaled, clamped, ms, flip_x = FALSE, flip_y = FALSE;
+
+ DBG("This=%p pSourceSurface=%p pSourceRect=%p pDestSurface=%p "
+ "pDestRect=%p Filter=%u\n",
+ This, pSourceSurface, pSourceRect, pDestSurface, pDestRect, Filter);
+ if (pSourceRect)
+ DBG("pSourceRect=(%u,%u)-(%u,%u)\n",
+ pSourceRect->left, pSourceRect->top,
+ pSourceRect->right, pSourceRect->bottom);
+ if (pDestRect)
+ DBG("pSourceRect=(%u,%u)-(%u,%u)\n", pDestRect->left, pDestRect->top,
+ pDestRect->right, pDestRect->bottom);
+
+ user_assert(!zs || !This->in_scene, D3DERR_INVALIDCALL);
+ user_assert(!zs || !pSourceRect ||
+ (pSourceRect->left == 0 &&
+ pSourceRect->top == 0 &&
+ pSourceRect->right == src->desc.Width &&
+ pSourceRect->bottom == src->desc.Height), D3DERR_INVALIDCALL);
+ user_assert(!zs || !pDestRect ||
+ (pDestRect->left == 0 &&
+ pDestRect->top == 0 &&
+ pDestRect->right == dst->desc.Width &&
+ pDestRect->bottom == dst->desc.Height), D3DERR_INVALIDCALL);
+ user_assert(!zs ||
+ (dst->desc.Width == src->desc.Width &&
+ dst->desc.Height == src->desc.Height), D3DERR_INVALIDCALL);
+ user_assert(zs || !util_format_is_depth_or_stencil(src_res->format),
+ D3DERR_INVALIDCALL);
+ user_assert(!zs || dst->desc.Format == src->desc.Format,
+ D3DERR_INVALIDCALL);
+ user_assert(screen->is_format_supported(screen, src_res->format,
+ src_res->target,
+ src_res->nr_samples,
+ PIPE_BIND_SAMPLER_VIEW),
+ D3DERR_INVALIDCALL);
+ user_assert(dst->base.pool == D3DPOOL_DEFAULT &&
+ src->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
+
+ /* We might want to permit these, but wine thinks we shouldn't. */
+ user_assert(!pDestRect ||
+ (pDestRect->left <= pDestRect->right &&
+ pDestRect->top <= pDestRect->bottom), D3DERR_INVALIDCALL);
+ user_assert(!pSourceRect ||
+ (pSourceRect->left <= pSourceRect->right &&
+ pSourceRect->top <= pSourceRect->bottom), D3DERR_INVALIDCALL);
+
+ blit.dst.resource = dst_res;
+ blit.dst.level = dst->level;
+ blit.dst.box.z = dst->layer;
+ blit.dst.box.depth = 1;
+ blit.dst.format = dst_res->format;
+ if (pDestRect) {
+ flip_x = pDestRect->left > pDestRect->right;
+ if (flip_x) {
+ blit.dst.box.x = pDestRect->right;
+ blit.dst.box.width = pDestRect->left - pDestRect->right;
+ } else {
+ blit.dst.box.x = pDestRect->left;
+ blit.dst.box.width = pDestRect->right - pDestRect->left;
+ }
+ flip_y = pDestRect->top > pDestRect->bottom;
+ if (flip_y) {
+ blit.dst.box.y = pDestRect->bottom;
+ blit.dst.box.height = pDestRect->top - pDestRect->bottom;
+ } else {
+ blit.dst.box.y = pDestRect->top;
+ blit.dst.box.height = pDestRect->bottom - pDestRect->top;
+ }
+ } else {
+ blit.dst.box.x = 0;
+ blit.dst.box.y = 0;
+ blit.dst.box.width = dst->desc.Width;
+ blit.dst.box.height = dst->desc.Height;
+ }
+ blit.src.resource = src_res;
+ blit.src.level = src->level;
+ blit.src.box.z = src->layer;
+ blit.src.box.depth = 1;
+ blit.src.format = src_res->format;
+ if (pSourceRect) {
+ if (flip_x ^ (pSourceRect->left > pSourceRect->right)) {
+ blit.src.box.x = pSourceRect->right;
+ blit.src.box.width = pSourceRect->left - pSourceRect->right;
+ } else {
+ blit.src.box.x = pSourceRect->left;
+ blit.src.box.width = pSourceRect->right - pSourceRect->left;
+ }
+ if (flip_y ^ (pSourceRect->top > pSourceRect->bottom)) {
+ blit.src.box.y = pSourceRect->bottom;
+ blit.src.box.height = pSourceRect->top - pSourceRect->bottom;
+ } else {
+ blit.src.box.y = pSourceRect->top;
+ blit.src.box.height = pSourceRect->bottom - pSourceRect->top;
+ }
+ } else {
+ blit.src.box.x = flip_x ? src->desc.Width : 0;
+ blit.src.box.y = flip_y ? src->desc.Height : 0;
+ blit.src.box.width = flip_x ? -src->desc.Width : src->desc.Width;
+ blit.src.box.height = flip_y ? -src->desc.Height : src->desc.Height;
+ }
+ blit.mask = zs ? PIPE_MASK_ZS : PIPE_MASK_RGBA;
+ blit.filter = Filter == D3DTEXF_LINEAR ?
+ PIPE_TEX_FILTER_LINEAR : PIPE_TEX_FILTER_NEAREST;
+ blit.scissor_enable = FALSE;
+
+ /* If both of a src and dst dimension are negative, flip them. */
+ if (blit.dst.box.width < 0 && blit.src.box.width < 0) {
+ blit.dst.box.width = -blit.dst.box.width;
+ blit.src.box.width = -blit.src.box.width;
+ }
+ if (blit.dst.box.height < 0 && blit.src.box.height < 0) {
+ blit.dst.box.height = -blit.dst.box.height;
+ blit.src.box.height = -blit.src.box.height;
+ }
+ scaled =
+ blit.dst.box.width != blit.src.box.width ||
+ blit.dst.box.height != blit.src.box.height;
+
+ user_assert(!scaled || dst != src, D3DERR_INVALIDCALL);
+ user_assert(!scaled ||
+ !NineSurface9_IsOffscreenPlain(dst) ||
+ NineSurface9_IsOffscreenPlain(src), D3DERR_INVALIDCALL);
+ user_assert(!scaled ||
+ (!util_format_is_compressed(dst->base.info.format) &&
+ !util_format_is_compressed(src->base.info.format)),
+ D3DERR_INVALIDCALL);
+
+ user_warn(src == dst &&
+ u_box_test_intersection_2d(&blit.src.box, &blit.dst.box));
+
+ /* Check for clipping/clamping: */
+ {
+ struct pipe_box box;
+ int xy;
+
+ xy = u_box_clip_2d(&box, &blit.dst.box,
+ dst->desc.Width, dst->desc.Height);
+ if (xy < 0)
+ return D3D_OK;
+ if (xy == 0)
+ xy = u_box_clip_2d(&box, &blit.src.box,
+ src->desc.Width, src->desc.Height);
+ clamped = !!xy;
+ }
+
+ ms = (dst->desc.MultiSampleType | 1) != (src->desc.MultiSampleType | 1);
+
+ if (clamped || scaled || (blit.dst.format != blit.src.format) || ms) {
+ DBG("using pipe->blit()\n");
+ /* TODO: software scaling */
+ user_assert(screen->is_format_supported(screen, dst_res->format,
+ dst_res->target,
+ dst_res->nr_samples,
+ zs ? PIPE_BIND_DEPTH_STENCIL :
+ PIPE_BIND_RENDER_TARGET),
+ D3DERR_INVALIDCALL);
+
+ pipe->blit(pipe, &blit);
+ } else {
+ assert(blit.dst.box.x >= 0 && blit.dst.box.y >= 0 &&
+ blit.src.box.x >= 0 && blit.src.box.y >= 0 &&
+ blit.dst.box.x + blit.dst.box.width <= dst->desc.Width &&
+ blit.src.box.x + blit.src.box.width <= src->desc.Width &&
+ blit.dst.box.y + blit.dst.box.height <= dst->desc.Height &&
+ blit.src.box.y + blit.src.box.height <= src->desc.Height);
+ /* Or drivers might crash ... */
+ DBG("Using resource_copy_region.\n");
+ pipe->resource_copy_region(pipe,
+ blit.dst.resource, blit.dst.level,
+ blit.dst.box.x, blit.dst.box.y, blit.dst.box.z,
+ blit.src.resource, blit.src.level,
+ &blit.src.box);
+ }
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_ColorFill( struct NineDevice9 *This,
+ IDirect3DSurface9 *pSurface,
+ const RECT *pRect,
+ D3DCOLOR color )
+{
+ struct pipe_context *pipe = This->pipe;
+ struct NineSurface9 *surf = NineSurface9(pSurface);
+ struct pipe_surface *psurf;
+ unsigned x, y, w, h;
+ union pipe_color_union rgba;
+ boolean fallback;
+
+ DBG("This=%p pSurface=%p pRect=%p color=%08x\n", This,
+ pSurface, pRect, color);
+ if (pRect)
+ DBG("pRect=(%u,%u)-(%u,%u)\n", pRect->left, pRect->top,
+ pRect->right, pRect->bottom);
+
+ user_assert(surf->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
+
+ user_assert((surf->base.usage & D3DUSAGE_RENDERTARGET) ||
+ NineSurface9_IsOffscreenPlain(surf), D3DERR_INVALIDCALL);
+
+ if (pRect) {
+ x = pRect->left;
+ y = pRect->top;
+ w = pRect->right - pRect->left;
+ h = pRect->bottom - pRect->top;
+ } else{
+ x = 0;
+ y = 0;
+ w = surf->desc.Width;
+ h = surf->desc.Height;
+ }
+ d3dcolor_to_pipe_color_union(&rgba, color);
+
+ fallback =
+ !This->screen->is_format_supported(This->screen, surf->base.info.format,
+ surf->base.info.target,
+ surf->base.info.nr_samples,
+ PIPE_BIND_RENDER_TARGET);
+ if (!fallback) {
+ psurf = NineSurface9_GetSurface(surf, 0);
+ if (!psurf)
+ fallback = TRUE;
+ }
+
+ if (!fallback) {
+ pipe->clear_render_target(pipe, psurf, &rgba, x, y, w, h);
+ } else {
+ D3DLOCKED_RECT lock;
+ union util_color uc;
+ HRESULT hr;
+ /* XXX: lock pRect and fix util_fill_rect */
+ hr = NineSurface9_LockRect(surf, &lock, NULL, 0);
+ if (FAILED(hr))
+ return hr;
+ util_pack_color_ub(color >> 16, color >> 8, color >> 0, color >> 24,
+ surf->base.info.format, &uc);
+ util_fill_rect(lock.pBits, surf->base.info.format,lock.Pitch,
+ x, y, w, h, &uc);
+ NineSurface9_UnlockRect(surf);
+ }
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_CreateOffscreenPlainSurface( struct NineDevice9 *This,
+ UINT Width,
+ UINT Height,
+ D3DFORMAT Format,
+ D3DPOOL Pool,
+ IDirect3DSurface9 **ppSurface,
+ HANDLE *pSharedHandle )
+{
+ HRESULT hr;
+
+ DBG("This=%p Width=%u Height=%u Format=%s(0x%x) Pool=%u "
+ "ppSurface=%p pSharedHandle=%p\n", This,
+ Width, Height, d3dformat_to_string(Format), Format, Pool,
+ ppSurface, pSharedHandle);
+
+ user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT
+ || Pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL);
+ user_assert(Pool != D3DPOOL_MANAGED, D3DERR_INVALIDCALL);
+
+ /* Can be used with StretchRect and ColorFill. It's also always lockable.
+ */
+ hr = create_zs_or_rt_surface(This, 2, Pool, Width, Height,
+ Format,
+ D3DMULTISAMPLE_NONE, 0,
+ TRUE,
+ ppSurface, pSharedHandle);
+ if (FAILED(hr))
+ DBG("Failed to create surface.\n");
+ return hr;
+}
+
+HRESULT WINAPI
+NineDevice9_SetRenderTarget( struct NineDevice9 *This,
+ DWORD RenderTargetIndex,
+ IDirect3DSurface9 *pRenderTarget )
+{
+ struct NineSurface9 *rt = NineSurface9(pRenderTarget);
+ const unsigned i = RenderTargetIndex;
+
+ DBG("This=%p RenderTargetIndex=%u pRenderTarget=%p\n", This,
+ RenderTargetIndex, pRenderTarget);
+
+ user_assert(i < This->caps.NumSimultaneousRTs, D3DERR_INVALIDCALL);
+ user_assert(i != 0 || pRenderTarget, D3DERR_INVALIDCALL);
+ user_assert(!pRenderTarget ||
+ rt->desc.Usage & D3DUSAGE_RENDERTARGET, D3DERR_INVALIDCALL);
+
+ if (i == 0) {
+ This->state.viewport.X = 0;
+ This->state.viewport.Y = 0;
+ This->state.viewport.Width = rt->desc.Width;
+ This->state.viewport.Height = rt->desc.Height;
+ This->state.viewport.MinZ = 0.0f;
+ This->state.viewport.MaxZ = 1.0f;
+
+ This->state.scissor.minx = 0;
+ This->state.scissor.miny = 0;
+ This->state.scissor.maxx = rt->desc.Width;
+ This->state.scissor.maxy = rt->desc.Height;
+
+ This->state.changed.group |= NINE_STATE_VIEWPORT | NINE_STATE_SCISSOR;
+ }
+
+ if (This->state.rt[i] != NineSurface9(pRenderTarget)) {
+ nine_bind(&This->state.rt[i], pRenderTarget);
+ This->state.changed.group |= NINE_STATE_FB;
+ }
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_GetRenderTarget( struct NineDevice9 *This,
+ DWORD RenderTargetIndex,
+ IDirect3DSurface9 **ppRenderTarget )
+{
+ const unsigned i = RenderTargetIndex;
+
+ user_assert(i < This->caps.NumSimultaneousRTs, D3DERR_INVALIDCALL);
+ user_assert(ppRenderTarget, D3DERR_INVALIDCALL);
+
+ *ppRenderTarget = (IDirect3DSurface9 *)This->state.rt[i];
+ if (!This->state.rt[i])
+ return D3DERR_NOTFOUND;
+
+ NineUnknown_AddRef(NineUnknown(This->state.rt[i]));
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_SetDepthStencilSurface( struct NineDevice9 *This,
+ IDirect3DSurface9 *pNewZStencil )
+{
+ DBG("This=%p pNewZStencil=%p\n", This, pNewZStencil);
+
+ if (This->state.ds != NineSurface9(pNewZStencil)) {
+ nine_bind(&This->state.ds, pNewZStencil);
+ This->state.changed.group |= NINE_STATE_FB;
+ }
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_GetDepthStencilSurface( struct NineDevice9 *This,
+ IDirect3DSurface9 **ppZStencilSurface )
+{
+ user_assert(ppZStencilSurface, D3DERR_INVALIDCALL);
+
+ *ppZStencilSurface = (IDirect3DSurface9 *)This->state.ds;
+ if (!This->state.ds)
+ return D3DERR_NOTFOUND;
+
+ NineUnknown_AddRef(NineUnknown(This->state.ds));
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_BeginScene( struct NineDevice9 *This )
+{
+ DBG("This=%p\n", This);
+ user_assert(!This->in_scene, D3DERR_INVALIDCALL);
+ This->in_scene = TRUE;
+ /* Do we want to do anything else here ? */
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_EndScene( struct NineDevice9 *This )
+{
+ DBG("This=%p\n", This);
+ user_assert(This->in_scene, D3DERR_INVALIDCALL);
+ This->in_scene = FALSE;
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_Clear( struct NineDevice9 *This,
+ DWORD Count,
+ const D3DRECT *pRects,
+ DWORD Flags,
+ D3DCOLOR Color,
+ float Z,
+ DWORD Stencil )
+{
+ struct pipe_context *pipe = This->pipe;
+ struct NineSurface9 *zsbuf = This->state.ds;
+ unsigned bufs = 0;
+ unsigned r, i;
+ union pipe_color_union rgba;
+ D3DRECT rect;
+
+ DBG("This=%p Count=%u pRects=%p Flags=%x Color=%08x Z=%f Stencil=%x\n",
+ This, Count, pRects, Flags, Color, Z, Stencil);
+
+ user_assert(This->state.ds || !(Flags & NINED3DCLEAR_DEPTHSTENCIL),
+ D3DERR_INVALIDCALL);
+ user_assert(!(Flags & D3DCLEAR_STENCIL) ||
+ (zsbuf &&
+ util_format_is_depth_and_stencil(zsbuf->base.info.format)),
+ D3DERR_INVALIDCALL);
+#ifdef NINE_STRICT
+ user_assert((Count && pRects) || (!Count && !pRects), D3DERR_INVALIDCALL);
+#else
+ user_warn((pRects && !Count) || (!pRects && Count));
+ if (pRects && !Count)
+ return D3D_OK;
+ if (!pRects)
+ Count = 0;
+#endif
+
+ if (Flags & D3DCLEAR_TARGET) bufs |= PIPE_CLEAR_COLOR;
+ if (Flags & D3DCLEAR_ZBUFFER) bufs |= PIPE_CLEAR_DEPTH;
+ if (Flags & D3DCLEAR_STENCIL) bufs |= PIPE_CLEAR_STENCIL;
+ if (!bufs)
+ return D3D_OK;
+ d3dcolor_to_pipe_color_union(&rgba, Color);
+
+ nine_update_state(This, NINE_STATE_FB);
+
+ rect.x1 = This->state.viewport.X;
+ rect.y1 = This->state.viewport.Y;
+ rect.x2 = This->state.viewport.Width + rect.x1;
+ rect.y2 = This->state.viewport.Height + rect.y1;
+
+ /* Both rectangles apply, which is weird, but that's D3D9. */
+ if (This->state.rs[D3DRS_SCISSORTESTENABLE]) {
+ rect.x1 = MAX2(rect.x1, This->state.scissor.minx);
+ rect.y1 = MAX2(rect.y1, This->state.scissor.miny);
+ rect.x2 = MIN2(rect.x2, This->state.scissor.maxx);
+ rect.y2 = MIN2(rect.y2, This->state.scissor.maxy);
+ }
+
+ if (Count) {
+ /* Maybe apps like to specify a large rect ? */
+ if (pRects[0].x1 <= rect.x1 && pRects[0].x2 >= rect.x2 &&
+ pRects[0].y1 <= rect.y1 && pRects[0].y2 >= rect.y2) {
+ DBG("First rect covers viewport.\n");
+ Count = 0;
+ pRects = NULL;
+ }
+ }
+
+ if (rect.x1 >= This->state.fb.width || rect.y1 >= This->state.fb.height)
+ return D3D_OK;
+ if (!Count &&
+ rect.x1 == 0 && rect.x2 >= This->state.fb.width &&
+ rect.y1 == 0 && rect.y2 >= This->state.fb.height) {
+ /* fast path, clears everything at once */
+ DBG("fast path\n");
+ pipe->clear(pipe, bufs, &rgba, Z, Stencil);
+ return D3D_OK;
+ }
+ rect.x2 = MIN2(rect.x2, This->state.fb.width);
+ rect.y2 = MIN2(rect.y2, This->state.fb.height);
+
+ if (!Count) {
+ Count = 1;
+ pRects = &rect;
+ }
+
+ for (i = 0; (i < This->state.fb.nr_cbufs); ++i) {
+ if (!This->state.fb.cbufs[i] || !(Flags & D3DCLEAR_TARGET))
+ continue; /* save space, compiler should hoist this */
+ for (r = 0; r < Count; ++r) {
+ /* Don't trust users to pass these in the right order. */
+ unsigned x1 = MIN2(pRects[r].x1, pRects[r].x2);
+ unsigned y1 = MIN2(pRects[r].y1, pRects[r].y2);
+ unsigned x2 = MAX2(pRects[r].x1, pRects[r].x2);
+ unsigned y2 = MAX2(pRects[r].y1, pRects[r].y2);
+#ifndef NINE_LAX
+ /* Drop negative rectangles (like wine expects). */
+ if (pRects[r].x1 > pRects[r].x2) continue;
+ if (pRects[r].y1 > pRects[r].y2) continue;
+#endif
+
+ x1 = MAX2(x1, rect.x1);
+ y1 = MAX2(y1, rect.y1);
+ x2 = MIN2(x2, rect.x2);
+ y2 = MIN2(y2, rect.y2);
+
+ DBG("Clearing (%u..%u)x(%u..%u)\n", x1, x2, y1, y2);
+ pipe->clear_render_target(pipe, This->state.fb.cbufs[i], &rgba,
+ x1, y1, x2 - x1, y2 - y1);
+ }
+ }
+ if (!(Flags & NINED3DCLEAR_DEPTHSTENCIL))
+ return D3D_OK;
+
+ bufs &= PIPE_CLEAR_DEPTHSTENCIL;
+
+ for (r = 0; r < Count; ++r) {
+ unsigned x1 = MIN2(pRects[r].x1, pRects[r].x2);
+ unsigned y1 = MIN2(pRects[r].y1, pRects[r].y2);
+ unsigned x2 = MAX2(pRects[r].x1, pRects[r].x2);
+ unsigned y2 = MAX2(pRects[r].y1, pRects[r].y2);
+#ifndef NINE_LAX
+ /* Drop negative rectangles. */
+ if (pRects[r].x1 > pRects[r].x2) continue;
+ if (pRects[r].y1 > pRects[r].y2) continue;
+#endif
+
+ x1 = MIN2(x1, rect.x1);
+ y1 = MIN2(y1, rect.y1);
+ x2 = MIN2(x2, rect.x2);
+ y2 = MIN2(y2, rect.y2);
+
+ pipe->clear_depth_stencil(pipe, This->state.fb.zsbuf, bufs, Z, Stencil,
+ x1, y1, x2 - x1, y2 - y1);
+ }
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_SetTransform( struct NineDevice9 *This,
+ D3DTRANSFORMSTATETYPE State,
+ const D3DMATRIX *pMatrix )
+{
+ struct nine_state *state = This->update;
+ D3DMATRIX *M = nine_state_access_transform(state, State, TRUE);
+ user_assert(M, D3DERR_INVALIDCALL);
+
+ *M = *pMatrix;
+ state->ff.changed.transform[State / 32] |= 1 << (State % 32);
+ state->changed.group |= NINE_STATE_FF;
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_GetTransform( struct NineDevice9 *This,
+ D3DTRANSFORMSTATETYPE State,
+ D3DMATRIX *pMatrix )
+{
+ D3DMATRIX *M = nine_state_access_transform(&This->state, State, FALSE);
+ user_assert(M, D3DERR_INVALIDCALL);
+ *pMatrix = *M;
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_MultiplyTransform( struct NineDevice9 *This,
+ D3DTRANSFORMSTATETYPE State,
+ const D3DMATRIX *pMatrix )
+{
+ struct nine_state *state = This->update;
+ D3DMATRIX T;
+ D3DMATRIX *M = nine_state_access_transform(state, State, TRUE);
+ user_assert(M, D3DERR_INVALIDCALL);
+
+ nine_d3d_matrix_matrix_mul(&T, pMatrix, M);
+ return NineDevice9_SetTransform(This, State, &T);
+}
+
+HRESULT WINAPI
+NineDevice9_SetViewport( struct NineDevice9 *This,
+ const D3DVIEWPORT9 *pViewport )
+{
+ struct nine_state *state = This->update;
+
+ DBG("X=%u Y=%u W=%u H=%u MinZ=%f MaxZ=%f\n",
+ pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height,
+ pViewport->MinZ, pViewport->MaxZ);
+
+ state->viewport = *pViewport;
+ state->changed.group |= NINE_STATE_VIEWPORT;
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_GetViewport( struct NineDevice9 *This,
+ D3DVIEWPORT9 *pViewport )
+{
+ *pViewport = This->state.viewport;
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_SetMaterial( struct NineDevice9 *This,
+ const D3DMATERIAL9 *pMaterial )
+{
+ struct nine_state *state = This->update;
+
+ DBG("This=%p pMaterial=%p\n", This, pMaterial);
+ if (pMaterial)
+ nine_dump_D3DMATERIAL9(DBG_FF, pMaterial);
+
+ user_assert(pMaterial, E_POINTER);
+
+ state->ff.material = *pMaterial;
+ state->changed.group |= NINE_STATE_FF_MATERIAL;
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_GetMaterial( struct NineDevice9 *This,
+ D3DMATERIAL9 *pMaterial )
+{
+ user_assert(pMaterial, E_POINTER);
+ *pMaterial = This->state.ff.material;
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_SetLight( struct NineDevice9 *This,
+ DWORD Index,
+ const D3DLIGHT9 *pLight )
+{
+ struct nine_state *state = This->update;
+
+ DBG("This=%p Index=%u pLight=%p\n", This, Index, pLight);
+ if (pLight)
+ nine_dump_D3DLIGHT9(DBG_FF, pLight);
+
+ user_assert(pLight, D3DERR_INVALIDCALL);
+ user_assert(pLight->Type < NINED3DLIGHT_INVALID, D3DERR_INVALIDCALL);
+
+ user_assert(Index < NINE_MAX_LIGHTS, D3DERR_INVALIDCALL); /* sanity */
+
+ if (Index >= state->ff.num_lights) {
+ unsigned n = state->ff.num_lights;
+ unsigned N = Index + 1;
+
+ state->ff.light = REALLOC(state->ff.light, n * sizeof(D3DLIGHT9),
+ N * sizeof(D3DLIGHT9));
+ if (!state->ff.light)
+ return E_OUTOFMEMORY;
+ state->ff.num_lights = N;
+
+ for (; n < Index; ++n)
+ state->ff.light[n].Type = (D3DLIGHTTYPE)NINED3DLIGHT_INVALID;
+ }
+ state->ff.light[Index] = *pLight;
+
+ if (pLight->Type == D3DLIGHT_SPOT && pLight->Theta >= pLight->Phi) {
+ DBG("Warning: clamping D3DLIGHT9.Theta\n");
+ state->ff.light[Index].Theta = state->ff.light[Index].Phi;
+ }
+ if (pLight->Type != D3DLIGHT_DIRECTIONAL &&
+ pLight->Attenuation0 == 0.0f &&
+ pLight->Attenuation1 == 0.0f &&
+ pLight->Attenuation2 == 0.0f) {
+ DBG("Warning: all D3DLIGHT9.Attenuation[i] are 0\n");
+ }
+
+ state->changed.group |= NINE_STATE_FF_LIGHTING;
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_GetLight( struct NineDevice9 *This,
+ DWORD Index,
+ D3DLIGHT9 *pLight )
+{
+ const struct nine_state *state = &This->state;
+
+ user_assert(pLight, D3DERR_INVALIDCALL);
+ user_assert(Index < state->ff.num_lights, D3DERR_INVALIDCALL);
+ user_assert(state->ff.light[Index].Type < NINED3DLIGHT_INVALID,
+ D3DERR_INVALIDCALL);
+
+ *pLight = state->ff.light[Index];
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_LightEnable( struct NineDevice9 *This,
+ DWORD Index,
+ BOOL Enable )
+{
+ struct nine_state *state = This->update;
+ unsigned i;
+
+ DBG("This=%p Index=%u Enable=%i\n", This, Index, Enable);
+
+ if (Index >= state->ff.num_lights ||
+ state->ff.light[Index].Type == NINED3DLIGHT_INVALID) {
+ /* This should create a default light. */
+ D3DLIGHT9 light;
+ memset(&light, 0, sizeof(light));
+ light.Type = D3DLIGHT_DIRECTIONAL;
+ light.Diffuse.r = 1.0f;
+ light.Diffuse.g = 1.0f;
+ light.Diffuse.b = 1.0f;
+ light.Direction.z = 1.0f;
+ NineDevice9_SetLight(This, Index, &light);
+ }
+ user_assert(Index < state->ff.num_lights, D3DERR_INVALIDCALL);
+
+ for (i = 0; i < state->ff.num_lights_active; ++i) {
+ if (state->ff.active_light[i] == Index)
+ break;
+ }
+
+ if (Enable) {
+ if (i < state->ff.num_lights_active)
+ return D3D_OK;
+ /* XXX wine thinks this should still succeed:
+ */
+ user_assert(i < NINE_MAX_LIGHTS_ACTIVE, D3DERR_INVALIDCALL);
+
+ state->ff.active_light[i] = Index;
+ state->ff.num_lights_active++;
+ } else {
+ if (i == state->ff.num_lights_active)
+ return D3D_OK;
+ --state->ff.num_lights_active;
+ for (; i < state->ff.num_lights_active; ++i)
+ state->ff.active_light[i] = state->ff.active_light[i + 1];
+ }
+ state->changed.group |= NINE_STATE_FF_LIGHTING;
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_GetLightEnable( struct NineDevice9 *This,
+ DWORD Index,
+ BOOL *pEnable )
+{
+ const struct nine_state *state = &This->state;
+ unsigned i;
+
+ user_assert(Index < state->ff.num_lights, D3DERR_INVALIDCALL);
+ user_assert(state->ff.light[Index].Type < NINED3DLIGHT_INVALID,
+ D3DERR_INVALIDCALL);
+
+ for (i = 0; i < state->ff.num_lights_active; ++i)
+ if (state->ff.active_light[i] == Index)
+ break;
+ *pEnable = i != state->ff.num_lights_active;
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_SetClipPlane( struct NineDevice9 *This,
+ DWORD Index,
+ const float *pPlane )
+{
+ struct nine_state *state = This->update;
+
+ DBG("This=%p Index=%u pPlane=%p(%f %f %f %f)\n", This, Index, pPlane,
+ pPlane ? pPlane[0] : 0.0f, pPlane ? pPlane[1] : 0.0f,
+ pPlane ? pPlane[2] : 0.0f, pPlane ? pPlane[3] : 0.0f);
+
+ user_assert(Index < PIPE_MAX_CLIP_PLANES, D3DERR_INVALIDCALL);
+
+ memcpy(&state->clip.ucp[Index][0], pPlane, sizeof(state->clip.ucp[0]));
+ state->changed.ucp |= 1 << Index;
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_GetClipPlane( struct NineDevice9 *This,
+ DWORD Index,
+ float *pPlane )
+{
+ const struct nine_state *state = &This->state;
+
+ user_assert(Index < PIPE_MAX_CLIP_PLANES, D3DERR_INVALIDCALL);
+
+ memcpy(pPlane, &state->clip.ucp[Index][0], sizeof(state->clip.ucp[0]));
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_SetRenderState( struct NineDevice9 *This,
+ D3DRENDERSTATETYPE State,
+ DWORD Value )
+{
+ struct nine_state *state = This->update;
+
+ DBG("This=%p State=%u(%s) Value=%08x\n", This,
+ State, nine_d3drs_to_string(State), Value);
+
+ user_assert(State < Elements(state->rs), D3DERR_INVALIDCALL);
+
+ if (likely(state->rs[State] != Value) || unlikely(This->is_recording)) {
+ state->rs[State] = Value;
+ state->changed.rs[State / 32] |= 1 << (State % 32);
+ state->changed.group |= nine_render_state_group[State];
+ }
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_GetRenderState( struct NineDevice9 *This,
+ D3DRENDERSTATETYPE State,
+ DWORD *pValue )
+{
+ user_assert(State < Elements(This->state.rs), D3DERR_INVALIDCALL);
+
+ *pValue = This->state.rs[State];
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_CreateStateBlock( struct NineDevice9 *This,
+ D3DSTATEBLOCKTYPE Type,
+ IDirect3DStateBlock9 **ppSB )
+{
+ struct NineStateBlock9 *nsb;
+ struct nine_state *dst;
+ HRESULT hr;
+ enum nine_stateblock_type type;
+ unsigned s;
+
+ DBG("This=%p Type=%u ppSB=%p\n", This, Type, ppSB);
+
+ user_assert(Type == D3DSBT_ALL ||
+ Type == D3DSBT_VERTEXSTATE ||
+ Type == D3DSBT_PIXELSTATE, D3DERR_INVALIDCALL);
+
+ switch (Type) {
+ case D3DSBT_VERTEXSTATE: type = NINESBT_VERTEXSTATE; break;
+ case D3DSBT_PIXELSTATE: type = NINESBT_PIXELSTATE; break;
+ default:
+ type = NINESBT_ALL;
+ break;
+ }
+
+ hr = NineStateBlock9_new(This, &nsb, type);
+ if (FAILED(hr))
+ return hr;
+ *ppSB = (IDirect3DStateBlock9 *)nsb;
+ dst = &nsb->state;
+
+ dst->changed.group =
+ NINE_STATE_TEXTURE |
+ NINE_STATE_SAMPLER;
+
+ if (Type == D3DSBT_ALL || Type == D3DSBT_VERTEXSTATE) {
+ dst->changed.group |=
+ NINE_STATE_FF_LIGHTING |
+ NINE_STATE_VS | NINE_STATE_VS_CONST |
+ NINE_STATE_VDECL;
+ /* TODO: texture/sampler state */
+ memcpy(dst->changed.rs,
+ nine_render_states_vertex, sizeof(dst->changed.rs));
+ nine_ranges_insert(&dst->changed.vs_const_f, 0, This->max_vs_const_f,
+ &This->range_pool);
+ dst->changed.vs_const_i = 0xffff;
+ dst->changed.vs_const_b = 0xffff;
+ for (s = 0; s < NINE_MAX_SAMPLERS; ++s)
+ dst->changed.sampler[s] |= 1 << D3DSAMP_DMAPOFFSET;
+ if (This->state.ff.num_lights) {
+ dst->ff.num_lights = This->state.ff.num_lights;
+ /* zero'd -> light type won't be NINED3DLIGHT_INVALID, so
+ * all currently existing lights will be captured
+ */
+ dst->ff.light = CALLOC(This->state.ff.num_lights,
+ sizeof(D3DLIGHT9));
+ if (!dst->ff.light) {
+ nine_bind(ppSB, NULL);
+ return E_OUTOFMEMORY;
+ }
+ }
+ }
+ if (Type == D3DSBT_ALL || Type == D3DSBT_PIXELSTATE) {
+ dst->changed.group |=
+ NINE_STATE_PS | NINE_STATE_PS_CONST;
+ /* TODO: texture/sampler state */
+ memcpy(dst->changed.rs,
+ nine_render_states_pixel, sizeof(dst->changed.rs));
+ nine_ranges_insert(&dst->changed.ps_const_f, 0, This->max_ps_const_f,
+ &This->range_pool);
+ dst->changed.ps_const_i = 0xffff;
+ dst->changed.ps_const_b = 0xffff;
+ for (s = 0; s < NINE_MAX_SAMPLERS; ++s)
+ dst->changed.sampler[s] |= 0x1ffe;
+ }
+ if (Type == D3DSBT_ALL) {
+ dst->changed.group |=
+ NINE_STATE_VIEWPORT |
+ NINE_STATE_SCISSOR |
+ NINE_STATE_RASTERIZER |
+ NINE_STATE_BLEND |
+ NINE_STATE_DSA |
+ NINE_STATE_IDXBUF |
+ NINE_STATE_MATERIAL |
+ NINE_STATE_BLEND_COLOR |
+ NINE_STATE_SAMPLE_MASK;
+ memset(dst->changed.rs, ~0, (D3DRS_COUNT / 32) * sizeof(uint32_t));
+ dst->changed.rs[D3DRS_LAST / 32] |= (1 << (D3DRS_COUNT % 32)) - 1;
+ dst->changed.vtxbuf = (1ULL << This->caps.MaxStreams) - 1;
+ dst->changed.stream_freq = dst->changed.vtxbuf;
+ dst->changed.ucp = (1 << PIPE_MAX_CLIP_PLANES) - 1;
+ dst->changed.texture = (1 << NINE_MAX_SAMPLERS) - 1;
+ }
+ NineStateBlock9_Capture(NineStateBlock9(*ppSB));
+
+ /* TODO: fixed function state */
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_BeginStateBlock( struct NineDevice9 *This )
+{
+ HRESULT hr;
+
+ DBG("This=%p\n", This);
+
+ user_assert(!This->record, D3DERR_INVALIDCALL);
+
+ hr = NineStateBlock9_new(This, &This->record, NINESBT_CUSTOM);
+ if (FAILED(hr))
+ return hr;
+ NineUnknown_ConvertRefToBind(NineUnknown(This->record));
+
+ This->update = &This->record->state;
+ This->is_recording = TRUE;
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_EndStateBlock( struct NineDevice9 *This,
+ IDirect3DStateBlock9 **ppSB )
+{
+ DBG("This=%p ppSB=%p\n", This, ppSB);
+
+ user_assert(This->record, D3DERR_INVALIDCALL);
+
+ This->update = &This->state;
+ This->is_recording = FALSE;
+
+ NineUnknown_AddRef(NineUnknown(This->record));
+ *ppSB = (IDirect3DStateBlock9 *)This->record;
+ NineUnknown_Unbind(NineUnknown(This->record));
+ This->record = NULL;
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_SetClipStatus( struct NineDevice9 *This,
+ const D3DCLIPSTATUS9 *pClipStatus )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineDevice9_GetClipStatus( struct NineDevice9 *This,
+ D3DCLIPSTATUS9 *pClipStatus )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineDevice9_GetTexture( struct NineDevice9 *This,
+ DWORD Stage,
+ IDirect3DBaseTexture9 **ppTexture )
+{
+ user_assert(Stage < This->caps.MaxSimultaneousTextures ||
+ Stage == D3DDMAPSAMPLER ||
+ (Stage >= D3DVERTEXTEXTURESAMPLER0 &&
+ Stage <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL);
+ user_assert(ppTexture, D3DERR_INVALIDCALL);
+
+ if (Stage >= D3DDMAPSAMPLER)
+ Stage = Stage - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS;
+
+ *ppTexture = (IDirect3DBaseTexture9 *)This->state.texture[Stage];
+
+ if (This->state.texture[Stage])
+ NineUnknown_AddRef(NineUnknown(This->state.texture[Stage]));
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_SetTexture( struct NineDevice9 *This,
+ DWORD Stage,
+ IDirect3DBaseTexture9 *pTexture )
+{
+ struct nine_state *state = This->update;
+
+ DBG("This=%p Stage=%u pTexture=%p\n", This, Stage, pTexture);
+
+ user_assert(Stage < This->caps.MaxSimultaneousTextures ||
+ Stage == D3DDMAPSAMPLER ||
+ (Stage >= D3DVERTEXTEXTURESAMPLER0 &&
+ Stage <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL);
+
+ if (Stage >= D3DDMAPSAMPLER)
+ Stage = Stage - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS;
+
+ if (!This->is_recording) {
+ struct NineBaseTexture9 *tex = NineBaseTexture9(pTexture);
+ struct NineBaseTexture9 *old = state->texture[Stage];
+ if (old == tex)
+ return D3D_OK;
+
+ state->samplers_shadow &= ~(1 << Stage);
+ if (tex) {
+ state->samplers_shadow |= tex->shadow << Stage;
+
+ if ((tex->dirty | tex->dirty_mip) && LIST_IS_EMPTY(&tex->list))
+ list_add(&tex->list, &This->update_textures);
+
+ tex->bind_count++;
+ }
+ if (old)
+ old->bind_count--;
+ }
+ nine_bind(&state->texture[Stage], pTexture);
+
+ state->changed.texture |= 1 << Stage;
+ state->changed.group |= NINE_STATE_TEXTURE;
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_GetTextureStageState( struct NineDevice9 *This,
+ DWORD Stage,
+ D3DTEXTURESTAGESTATETYPE Type,
+ DWORD *pValue )
+{
+ const struct nine_state *state = &This->state;
+
+ user_assert(Stage < Elements(state->ff.tex_stage), D3DERR_INVALIDCALL);
+ user_assert(Type < Elements(state->ff.tex_stage[0]), D3DERR_INVALIDCALL);
+
+ *pValue = state->ff.tex_stage[Stage][Type];
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_SetTextureStageState( struct NineDevice9 *This,
+ DWORD Stage,
+ D3DTEXTURESTAGESTATETYPE Type,
+ DWORD Value )
+{
+ struct nine_state *state = This->update;
+
+ DBG("Stage=%u Type=%u Value=%08x\n", Stage, Type, Value);
+ nine_dump_D3DTSS_value(DBG_FF, Type, Value);
+
+ user_assert(Stage < Elements(state->ff.tex_stage), D3DERR_INVALIDCALL);
+ user_assert(Type < Elements(state->ff.tex_stage[0]), D3DERR_INVALIDCALL);
+
+ state->ff.tex_stage[Stage][Type] = Value;
+
+ state->changed.group |= NINE_STATE_FF_PSSTAGES;
+ state->ff.changed.tex_stage[Stage][Type / 32] |= 1 << (Type % 32);
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_GetSamplerState( struct NineDevice9 *This,
+ DWORD Sampler,
+ D3DSAMPLERSTATETYPE Type,
+ DWORD *pValue )
+{
+ user_assert(Sampler < This->caps.MaxSimultaneousTextures ||
+ Sampler == D3DDMAPSAMPLER ||
+ (Sampler >= D3DVERTEXTEXTURESAMPLER0 &&
+ Sampler <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL);
+
+ if (Sampler >= D3DDMAPSAMPLER)
+ Sampler = Sampler - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS;
+
+ *pValue = This->state.samp[Sampler][Type];
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_SetSamplerState( struct NineDevice9 *This,
+ DWORD Sampler,
+ D3DSAMPLERSTATETYPE Type,
+ DWORD Value )
+{
+ struct nine_state *state = This->update;
+
+ DBG("This=%p Sampler=%u Type=%s Value=%08x\n", This,
+ Sampler, nine_D3DSAMP_to_str(Type), Value);
+
+ user_assert(Sampler < This->caps.MaxSimultaneousTextures ||
+ Sampler == D3DDMAPSAMPLER ||
+ (Sampler >= D3DVERTEXTEXTURESAMPLER0 &&
+ Sampler <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL);
+
+ if (Sampler >= D3DDMAPSAMPLER)
+ Sampler = Sampler - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS;
+
+ state->samp[Sampler][Type] = Value;
+ state->changed.group |= NINE_STATE_SAMPLER;
+ state->changed.sampler[Sampler] |= 1 << Type;
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_ValidateDevice( struct NineDevice9 *This,
+ DWORD *pNumPasses )
+{
+ const struct nine_state *state = &This->state;
+ unsigned i;
+ unsigned w = 0, h = 0;
+
+ DBG("This=%p pNumPasses=%p\n", This, pNumPasses);
+
+ for (i = 0; i < Elements(state->samp); ++i) {
+ if (state->samp[i][D3DSAMP_MINFILTER] == D3DTEXF_NONE ||
+ state->samp[i][D3DSAMP_MAGFILTER] == D3DTEXF_NONE)
+ return D3DERR_UNSUPPORTEDTEXTUREFILTER;
+ }
+
+ for (i = 0; i < This->caps.NumSimultaneousRTs; ++i) {
+ if (!state->rt[i])
+ continue;
+ if (w == 0) {
+ w = state->rt[i]->desc.Width;
+ h = state->rt[i]->desc.Height;
+ } else
+ if (state->rt[i]->desc.Width != w || state->rt[i]->desc.Height != h) {
+ return D3DERR_CONFLICTINGRENDERSTATE;
+ }
+ }
+ if (state->ds &&
+ (state->rs[D3DRS_ZENABLE] || state->rs[D3DRS_STENCILENABLE])) {
+ if (w != 0 &&
+ (state->ds->desc.Width != w || state->ds->desc.Height != h))
+ return D3DERR_CONFLICTINGRENDERSTATE;
+ }
+
+ if (pNumPasses)
+ *pNumPasses = 1;
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_SetPaletteEntries( struct NineDevice9 *This,
+ UINT PaletteNumber,
+ const PALETTEENTRY *pEntries )
+{
+ STUB(D3D_OK); /* like wine */
+}
+
+HRESULT WINAPI
+NineDevice9_GetPaletteEntries( struct NineDevice9 *This,
+ UINT PaletteNumber,
+ PALETTEENTRY *pEntries )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineDevice9_SetCurrentTexturePalette( struct NineDevice9 *This,
+ UINT PaletteNumber )
+{
+ STUB(D3D_OK); /* like wine */
+}
+
+HRESULT WINAPI
+NineDevice9_GetCurrentTexturePalette( struct NineDevice9 *This,
+ UINT *PaletteNumber )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineDevice9_SetScissorRect( struct NineDevice9 *This,
+ const RECT *pRect )
+{
+ struct nine_state *state = This->update;
+
+ DBG("x=(%u..%u) y=(%u..%u)\n",
+ pRect->left, pRect->top, pRect->right, pRect->bottom);
+
+ state->scissor.minx = pRect->left;
+ state->scissor.miny = pRect->top;
+ state->scissor.maxx = pRect->right;
+ state->scissor.maxy = pRect->bottom;
+
+ state->changed.group |= NINE_STATE_SCISSOR;
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_GetScissorRect( struct NineDevice9 *This,
+ RECT *pRect )
+{
+ pRect->left = This->state.scissor.minx;
+ pRect->top = This->state.scissor.miny;
+ pRect->right = This->state.scissor.maxx;
+ pRect->bottom = This->state.scissor.maxy;
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_SetSoftwareVertexProcessing( struct NineDevice9 *This,
+ BOOL bSoftware )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+BOOL WINAPI
+NineDevice9_GetSoftwareVertexProcessing( struct NineDevice9 *This )
+{
+ return !!(This->params.BehaviorFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING);
+}
+
+HRESULT WINAPI
+NineDevice9_SetNPatchMode( struct NineDevice9 *This,
+ float nSegments )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+float WINAPI
+NineDevice9_GetNPatchMode( struct NineDevice9 *This )
+{
+ STUB(0);
+}
+
+static INLINE void
+init_draw_info(struct pipe_draw_info *info,
+ struct NineDevice9 *dev, D3DPRIMITIVETYPE type, UINT count)
+{
+ info->mode = d3dprimitivetype_to_pipe_prim(type);
+ info->count = prim_count_to_vertex_count(type, count);
+ info->start_instance = 0;
+ info->instance_count = 1;
+ if (dev->state.stream_instancedata_mask & dev->state.stream_usage_mask)
+ info->instance_count = MAX2(dev->state.stream_freq[0] & 0x7FFFFF, 1);
+ info->primitive_restart = FALSE;
+ info->restart_index = 0;
+ info->count_from_stream_output = NULL;
+ info->indirect = NULL;
+}
+
+HRESULT WINAPI
+NineDevice9_DrawPrimitive( struct NineDevice9 *This,
+ D3DPRIMITIVETYPE PrimitiveType,
+ UINT StartVertex,
+ UINT PrimitiveCount )
+{
+ struct pipe_draw_info info;
+
+ DBG("iface %p, PrimitiveType %u, StartVertex %u, PrimitiveCount %u\n",
+ This, PrimitiveType, StartVertex, PrimitiveCount);
+
+ nine_update_state(This, ~0);
+
+ init_draw_info(&info, This, PrimitiveType, PrimitiveCount);
+ info.indexed = FALSE;
+ info.start = StartVertex;
+ info.index_bias = 0;
+ info.min_index = info.start;
+ info.max_index = info.count - 1;
+
+ This->pipe->draw_vbo(This->pipe, &info);
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_DrawIndexedPrimitive( struct NineDevice9 *This,
+ D3DPRIMITIVETYPE PrimitiveType,
+ INT BaseVertexIndex,
+ UINT MinVertexIndex,
+ UINT NumVertices,
+ UINT StartIndex,
+ UINT PrimitiveCount )
+{
+ struct pipe_draw_info info;
+
+ DBG("iface %p, PrimitiveType %u, BaseVertexIndex %u, MinVertexIndex %u "
+ "NumVertices %u, StartIndex %u, PrimitiveCount %u\n",
+ This, PrimitiveType, BaseVertexIndex, MinVertexIndex, NumVertices,
+ StartIndex, PrimitiveCount);
+
+ user_assert(This->state.idxbuf, D3DERR_INVALIDCALL);
+ user_assert(This->state.vdecl, D3DERR_INVALIDCALL);
+
+ nine_update_state(This, ~0);
+
+ init_draw_info(&info, This, PrimitiveType, PrimitiveCount);
+ info.indexed = TRUE;
+ info.start = StartIndex;
+ info.index_bias = BaseVertexIndex;
+ /* These don't include index bias: */
+ info.min_index = MinVertexIndex;
+ info.max_index = MinVertexIndex + NumVertices - 1;
+
+ This->pipe->draw_vbo(This->pipe, &info);
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_DrawPrimitiveUP( struct NineDevice9 *This,
+ D3DPRIMITIVETYPE PrimitiveType,
+ UINT PrimitiveCount,
+ const void *pVertexStreamZeroData,
+ UINT VertexStreamZeroStride )
+{
+ struct pipe_vertex_buffer vtxbuf;
+ struct pipe_draw_info info;
+
+ DBG("iface %p, PrimitiveType %u, PrimitiveCount %u, data %p, stride %u\n",
+ This, PrimitiveType, PrimitiveCount,
+ pVertexStreamZeroData, VertexStreamZeroStride);
+
+ user_assert(pVertexStreamZeroData && VertexStreamZeroStride,
+ D3DERR_INVALIDCALL);
+
+ nine_update_state(This, ~0);
+
+ init_draw_info(&info, This, PrimitiveType, PrimitiveCount);
+ info.indexed = FALSE;
+ info.start = 0;
+ info.index_bias = 0;
+ info.min_index = 0;
+ info.max_index = info.count - 1;
+
+ vtxbuf.stride = VertexStreamZeroStride;
+ vtxbuf.buffer_offset = 0;
+ vtxbuf.buffer = NULL;
+ vtxbuf.user_buffer = pVertexStreamZeroData;
+
+ if (!This->driver_caps.user_vbufs)
+ u_upload_data(This->upload,
+ 0,
+ (info.max_index + 1) * VertexStreamZeroStride, /* XXX */
+ vtxbuf.user_buffer,
+ &vtxbuf.buffer_offset,
+ &vtxbuf.buffer);
+
+ This->pipe->set_vertex_buffers(This->pipe, 0, 1, &vtxbuf);
+
+ This->pipe->draw_vbo(This->pipe, &info);
+
+ NineDevice9_PauseRecording(This);
+ NineDevice9_SetStreamSource(This, 0, NULL, 0, 0);
+ NineDevice9_ResumeRecording(This);
+
+ pipe_resource_reference(&vtxbuf.buffer, NULL);
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_DrawIndexedPrimitiveUP( struct NineDevice9 *This,
+ D3DPRIMITIVETYPE PrimitiveType,
+ UINT MinVertexIndex,
+ UINT NumVertices,
+ UINT PrimitiveCount,
+ const void *pIndexData,
+ D3DFORMAT IndexDataFormat,
+ const void *pVertexStreamZeroData,
+ UINT VertexStreamZeroStride )
+{
+ struct pipe_draw_info info;
+ struct pipe_vertex_buffer vbuf;
+ struct pipe_index_buffer ibuf;
+
+ DBG("iface %p, PrimitiveType %u, MinVertexIndex %u, NumVertices %u "
+ "PrimitiveCount %u, pIndexData %p, IndexDataFormat %u "
+ "pVertexStreamZeroData %p, VertexStreamZeroStride %u\n",
+ This, PrimitiveType, MinVertexIndex, NumVertices, PrimitiveCount,
+ pIndexData, IndexDataFormat,
+ pVertexStreamZeroData, VertexStreamZeroStride);
+
+ user_assert(pIndexData && pVertexStreamZeroData, D3DERR_INVALIDCALL);
+ user_assert(VertexStreamZeroStride, D3DERR_INVALIDCALL);
+ user_assert(IndexDataFormat == D3DFMT_INDEX16 ||
+ IndexDataFormat == D3DFMT_INDEX32, D3DERR_INVALIDCALL);
+
+ nine_update_state(This, ~0);
+
+ init_draw_info(&info, This, PrimitiveType, PrimitiveCount);
+ info.indexed = TRUE;
+ info.start = 0;
+ info.index_bias = 0;
+ info.min_index = MinVertexIndex;
+ info.max_index = MinVertexIndex + NumVertices - 1;
+
+ vbuf.stride = VertexStreamZeroStride;
+ vbuf.buffer_offset = 0;
+ vbuf.buffer = NULL;
+ vbuf.user_buffer = pVertexStreamZeroData;
+
+ ibuf.index_size = (IndexDataFormat == D3DFMT_INDEX16) ? 2 : 4;
+ ibuf.offset = 0;
+ ibuf.buffer = NULL;
+ ibuf.user_buffer = pIndexData;
+
+ if (!This->driver_caps.user_vbufs) {
+ const unsigned base = info.min_index * VertexStreamZeroStride;
+ u_upload_data(This->upload,
+ base,
+ (info.max_index -
+ info.min_index + 1) * VertexStreamZeroStride, /* XXX */
+ (const uint8_t *)vbuf.user_buffer + base,
+ &vbuf.buffer_offset,
+ &vbuf.buffer);
+ /* Won't be used: */
+ vbuf.buffer_offset -= base;
+ }
+ if (!This->driver_caps.user_ibufs)
+ u_upload_data(This->upload,
+ 0,
+ info.count * ibuf.index_size,
+ ibuf.user_buffer,
+ &ibuf.offset,
+ &ibuf.buffer);
+
+ This->pipe->set_vertex_buffers(This->pipe, 0, 1, &vbuf);
+ This->pipe->set_index_buffer(This->pipe, &ibuf);
+
+ This->pipe->draw_vbo(This->pipe, &info);
+
+ pipe_resource_reference(&vbuf.buffer, NULL);
+ pipe_resource_reference(&ibuf.buffer, NULL);
+
+ NineDevice9_PauseRecording(This);
+ NineDevice9_SetIndices(This, NULL);
+ NineDevice9_SetStreamSource(This, 0, NULL, 0, 0);
+ NineDevice9_ResumeRecording(This);
+
+ return D3D_OK;
+}
+
+/* TODO: Write to pDestBuffer directly if vertex declaration contains
+ * only f32 formats.
+ */
+HRESULT WINAPI
+NineDevice9_ProcessVertices( struct NineDevice9 *This,
+ UINT SrcStartIndex,
+ UINT DestIndex,
+ UINT VertexCount,
+ IDirect3DVertexBuffer9 *pDestBuffer,
+ IDirect3DVertexDeclaration9 *pVertexDecl,
+ DWORD Flags )
+{
+ struct pipe_screen *screen = This->screen;
+ struct NineVertexDeclaration9 *vdecl = NineVertexDeclaration9(pVertexDecl);
+ struct NineVertexShader9 *vs;
+ struct pipe_resource *resource;
+ struct pipe_stream_output_target *target;
+ struct pipe_draw_info draw;
+ HRESULT hr;
+ unsigned buffer_offset, buffer_size;
+
+ if (!screen->get_param(screen, PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS))
+ STUB(D3DERR_INVALIDCALL);
+
+ nine_update_state(This, ~0);
+
+ /* TODO: Create shader with stream output. */
+ STUB(D3DERR_INVALIDCALL);
+ struct NineVertexBuffer9 *dst = NineVertexBuffer9(pDestBuffer);
+
+ vs = This->state.vs ? This->state.vs : This->ff.vs;
+
+ buffer_size = VertexCount * vs->so->stride[0];
+ if (1) {
+ struct pipe_resource templ;
+
+ templ.target = PIPE_BUFFER;
+ templ.format = PIPE_FORMAT_R8_UNORM;
+ templ.width0 = buffer_size;
+ templ.flags = 0;
+ templ.bind = PIPE_BIND_STREAM_OUTPUT;
+ templ.usage = PIPE_USAGE_STREAM;
+ templ.height0 = templ.depth0 = templ.array_size = 1;
+ templ.last_level = templ.nr_samples = 0;
+
+ resource = This->screen->resource_create(This->screen, &templ);
+ if (!resource)
+ return E_OUTOFMEMORY;
+ buffer_offset = 0;
+ } else {
+ /* SO matches vertex declaration */
+ resource = dst->base.resource;
+ buffer_offset = DestIndex * vs->so->stride[0];
+ }
+ target = This->pipe->create_stream_output_target(This->pipe, resource,
+ buffer_offset,
+ buffer_size);
+ if (!target) {
+ pipe_resource_reference(&resource, NULL);
+ return D3DERR_DRIVERINTERNALERROR;
+ }
+
+ if (!vdecl) {
+ hr = NineVertexDeclaration9_new_from_fvf(This, dst->desc.FVF, &vdecl);
+ if (FAILED(hr))
+ goto out;
+ }
+
+ init_draw_info(&draw, This, D3DPT_POINTLIST, VertexCount);
+ draw.instance_count = 1;
+ draw.indexed = FALSE;
+ draw.start = SrcStartIndex;
+ draw.index_bias = 0;
+ draw.min_index = SrcStartIndex;
+ draw.max_index = SrcStartIndex + VertexCount - 1;
+
+ This->pipe->set_stream_output_targets(This->pipe, 1, &target, 0);
+ This->pipe->draw_vbo(This->pipe, &draw);
+ This->pipe->set_stream_output_targets(This->pipe, 0, NULL, 0);
+ This->pipe->stream_output_target_destroy(This->pipe, target);
+
+ hr = NineVertexDeclaration9_ConvertStreamOutput(vdecl,
+ dst, DestIndex, VertexCount,
+ resource, vs->so);
+out:
+ pipe_resource_reference(&resource, NULL);
+ if (!pVertexDecl)
+ NineUnknown_Release(NineUnknown(vdecl));
+ return hr;
+}
+
+HRESULT WINAPI
+NineDevice9_CreateVertexDeclaration( struct NineDevice9 *This,
+ const D3DVERTEXELEMENT9 *pVertexElements,
+ IDirect3DVertexDeclaration9 **ppDecl )
+{
+ struct NineVertexDeclaration9 *vdecl;
+
+ HRESULT hr = NineVertexDeclaration9_new(This, pVertexElements, &vdecl);
+ if (SUCCEEDED(hr))
+ *ppDecl = (IDirect3DVertexDeclaration9 *)vdecl;
+
+ return hr;
+}
+
+HRESULT WINAPI
+NineDevice9_SetVertexDeclaration( struct NineDevice9 *This,
+ IDirect3DVertexDeclaration9 *pDecl )
+{
+ struct nine_state *state = This->update;
+
+ DBG("This=%p pDecl=%p\n", This, pDecl);
+
+ if (likely(!This->is_recording) && state->vdecl == NineVertexDeclaration9(pDecl))
+ return D3D_OK;
+ nine_bind(&state->vdecl, pDecl);
+
+ state->changed.group |= NINE_STATE_VDECL;
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_GetVertexDeclaration( struct NineDevice9 *This,
+ IDirect3DVertexDeclaration9 **ppDecl )
+{
+ user_assert(ppDecl, D3DERR_INVALIDCALL);
+
+ *ppDecl = (IDirect3DVertexDeclaration9 *)This->state.vdecl;
+ if (*ppDecl)
+ NineUnknown_AddRef(NineUnknown(*ppDecl));
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_SetFVF( struct NineDevice9 *This,
+ DWORD FVF )
+{
+ struct NineVertexDeclaration9 *vdecl;
+ HRESULT hr;
+
+ DBG("FVF = %08x\n", FVF);
+ if (!FVF)
+ return D3D_OK; /* like wine */
+
+ vdecl = util_hash_table_get(This->ff.ht_fvf, &FVF);
+ if (!vdecl) {
+ hr = NineVertexDeclaration9_new_from_fvf(This, FVF, &vdecl);
+ if (FAILED(hr))
+ return hr;
+ vdecl->fvf = FVF;
+ util_hash_table_set(This->ff.ht_fvf, &vdecl->fvf, vdecl);
+ NineUnknown_ConvertRefToBind(NineUnknown(vdecl));
+ }
+ return NineDevice9_SetVertexDeclaration(
+ This, (IDirect3DVertexDeclaration9 *)vdecl);
+}
+
+HRESULT WINAPI
+NineDevice9_GetFVF( struct NineDevice9 *This,
+ DWORD *pFVF )
+{
+ *pFVF = This->state.vdecl ? This->state.vdecl->fvf : 0;
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_CreateVertexShader( struct NineDevice9 *This,
+ const DWORD *pFunction,
+ IDirect3DVertexShader9 **ppShader )
+{
+ struct NineVertexShader9 *vs;
+ HRESULT hr;
+
+ hr = NineVertexShader9_new(This, &vs, pFunction, NULL);
+ if (FAILED(hr))
+ return hr;
+ *ppShader = (IDirect3DVertexShader9 *)vs;
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_SetVertexShader( struct NineDevice9 *This,
+ IDirect3DVertexShader9 *pShader )
+{
+ struct nine_state *state = This->update;
+
+ DBG("This=%p pShader=%p\n", This, pShader);
+
+ nine_bind(&state->vs, pShader);
+
+ state->changed.group |= NINE_STATE_VS;
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_GetVertexShader( struct NineDevice9 *This,
+ IDirect3DVertexShader9 **ppShader )
+{
+ user_assert(ppShader, D3DERR_INVALIDCALL);
+ nine_reference_set(ppShader, This->state.vs);
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_SetVertexShaderConstantF( struct NineDevice9 *This,
+ UINT StartRegister,
+ const float *pConstantData,
+ UINT Vector4fCount )
+{
+ struct nine_state *state = This->update;
+
+ DBG("This=%p StartRegister=%u pConstantData=%p Vector4fCount=%u\n",
+ This, StartRegister, pConstantData, Vector4fCount);
+
+ user_assert(StartRegister < This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL);
+ user_assert(StartRegister + Vector4fCount <= This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL);
+
+ if (!Vector4fCount)
+ return D3D_OK;
+ user_assert(pConstantData, D3DERR_INVALIDCALL);
+
+ memcpy(&state->vs_const_f[StartRegister * 4],
+ pConstantData,
+ Vector4fCount * 4 * sizeof(state->vs_const_f[0]));
+
+ nine_ranges_insert(&state->changed.vs_const_f,
+ StartRegister, StartRegister + Vector4fCount,
+ &This->range_pool);
+
+ state->changed.group |= NINE_STATE_VS_CONST;
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_GetVertexShaderConstantF( struct NineDevice9 *This,
+ UINT StartRegister,
+ float *pConstantData,
+ UINT Vector4fCount )
+{
+ const struct nine_state *state = &This->state;
+
+ user_assert(StartRegister < This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL);
+ user_assert(StartRegister + Vector4fCount <= This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL);
+ user_assert(pConstantData, D3DERR_INVALIDCALL);
+
+ memcpy(pConstantData,
+ &state->vs_const_f[StartRegister * 4],
+ Vector4fCount * 4 * sizeof(state->vs_const_f[0]));
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_SetVertexShaderConstantI( struct NineDevice9 *This,
+ UINT StartRegister,
+ const int *pConstantData,
+ UINT Vector4iCount )
+{
+ struct nine_state *state = This->update;
+
+ DBG("This=%p StartRegister=%u pConstantData=%p Vector4iCount=%u\n",
+ This, StartRegister, pConstantData, Vector4iCount);
+
+ user_assert(StartRegister < NINE_MAX_CONST_I, D3DERR_INVALIDCALL);
+ user_assert(StartRegister + Vector4iCount <= NINE_MAX_CONST_I, D3DERR_INVALIDCALL);
+ user_assert(pConstantData, D3DERR_INVALIDCALL);
+
+ memcpy(&state->vs_const_i[StartRegister][0],
+ pConstantData,
+ Vector4iCount * sizeof(state->vs_const_i[0]));
+
+ state->changed.vs_const_i |= ((1 << Vector4iCount) - 1) << StartRegister;
+ state->changed.group |= NINE_STATE_VS_CONST;
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_GetVertexShaderConstantI( struct NineDevice9 *This,
+ UINT StartRegister,
+ int *pConstantData,
+ UINT Vector4iCount )
+{
+ const struct nine_state *state = &This->state;
+
+ user_assert(StartRegister < NINE_MAX_CONST_I, D3DERR_INVALIDCALL);
+ user_assert(StartRegister + Vector4iCount <= NINE_MAX_CONST_I, D3DERR_INVALIDCALL);
+ user_assert(pConstantData, D3DERR_INVALIDCALL);
+
+ memcpy(pConstantData,
+ &state->vs_const_i[StartRegister][0],
+ Vector4iCount * sizeof(state->vs_const_i[0]));
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_SetVertexShaderConstantB( struct NineDevice9 *This,
+ UINT StartRegister,
+ const BOOL *pConstantData,
+ UINT BoolCount )
+{
+ struct nine_state *state = This->update;
+
+ DBG("This=%p StartRegister=%u pConstantData=%p BoolCount=%u\n",
+ This, StartRegister, pConstantData, BoolCount);
+
+ user_assert(StartRegister < NINE_MAX_CONST_B, D3DERR_INVALIDCALL);
+ user_assert(StartRegister + BoolCount <= NINE_MAX_CONST_B, D3DERR_INVALIDCALL);
+ user_assert(pConstantData, D3DERR_INVALIDCALL);
+
+ memcpy(&state->vs_const_b[StartRegister],
+ pConstantData,
+ BoolCount * sizeof(state->vs_const_b[0]));
+
+ state->changed.vs_const_b |= ((1 << BoolCount) - 1) << StartRegister;
+ state->changed.group |= NINE_STATE_VS_CONST;
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_GetVertexShaderConstantB( struct NineDevice9 *This,
+ UINT StartRegister,
+ BOOL *pConstantData,
+ UINT BoolCount )
+{
+ const struct nine_state *state = &This->state;
+
+ user_assert(StartRegister < NINE_MAX_CONST_B, D3DERR_INVALIDCALL);
+ user_assert(StartRegister + BoolCount <= NINE_MAX_CONST_B, D3DERR_INVALIDCALL);
+ user_assert(pConstantData, D3DERR_INVALIDCALL);
+
+ memcpy(pConstantData,
+ &state->vs_const_b[StartRegister],
+ BoolCount * sizeof(state->vs_const_b[0]));
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_SetStreamSource( struct NineDevice9 *This,
+ UINT StreamNumber,
+ IDirect3DVertexBuffer9 *pStreamData,
+ UINT OffsetInBytes,
+ UINT Stride )
+{
+ struct nine_state *state = This->update;
+ struct NineVertexBuffer9 *pVBuf9 = NineVertexBuffer9(pStreamData);
+ const unsigned i = StreamNumber;
+
+ user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL);
+ user_assert(Stride <= This->caps.MaxStreamStride, D3DERR_INVALIDCALL);
+
+ if (likely(!This->is_recording)) {
+ if (state->stream[i] == NineVertexBuffer9(pStreamData) &&
+ state->vtxbuf[i].stride == Stride &&
+ state->vtxbuf[i].buffer_offset == OffsetInBytes)
+ return D3D_OK;
+ }
+ nine_bind(&state->stream[i], pStreamData);
+
+ state->changed.vtxbuf |= 1 << StreamNumber;
+
+ if (pStreamData) {
+ state->vtxbuf[i].stride = Stride;
+ state->vtxbuf[i].buffer_offset = OffsetInBytes;
+ }
+ state->vtxbuf[i].buffer = pStreamData ? pVBuf9->base.resource : NULL;
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_GetStreamSource( struct NineDevice9 *This,
+ UINT StreamNumber,
+ IDirect3DVertexBuffer9 **ppStreamData,
+ UINT *pOffsetInBytes,
+ UINT *pStride )
+{
+ const struct nine_state *state = &This->state;
+ const unsigned i = StreamNumber;
+
+ user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL);
+ user_assert(ppStreamData, D3DERR_INVALIDCALL);
+
+ nine_reference_set(ppStreamData, state->stream[i]);
+ *pStride = state->vtxbuf[i].stride;
+ *pOffsetInBytes = state->vtxbuf[i].buffer_offset;
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_SetStreamSourceFreq( struct NineDevice9 *This,
+ UINT StreamNumber,
+ UINT Setting )
+{
+ struct nine_state *state = This->update;
+ /* const UINT freq = Setting & 0x7FFFFF; */
+
+ DBG("This=%p StreamNumber=%u FrequencyParameter=0x%x\n", This,
+ StreamNumber, Setting);
+
+ user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL);
+ user_assert(StreamNumber != 0 || !(Setting & D3DSTREAMSOURCE_INSTANCEDATA),
+ D3DERR_INVALIDCALL);
+ user_assert(!((Setting & D3DSTREAMSOURCE_INSTANCEDATA) &&
+ (Setting & D3DSTREAMSOURCE_INDEXEDDATA)), D3DERR_INVALIDCALL);
+ user_assert(Setting, D3DERR_INVALIDCALL);
+
+ state->stream_freq[StreamNumber] = Setting;
+
+ if (Setting & D3DSTREAMSOURCE_INSTANCEDATA)
+ state->stream_instancedata_mask |= 1 << StreamNumber;
+ else
+ state->stream_instancedata_mask &= ~(1 << StreamNumber);
+
+ state->changed.stream_freq |= 1 << StreamNumber;
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_GetStreamSourceFreq( struct NineDevice9 *This,
+ UINT StreamNumber,
+ UINT *pSetting )
+{
+ user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL);
+ *pSetting = This->state.stream_freq[StreamNumber];
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_SetIndices( struct NineDevice9 *This,
+ IDirect3DIndexBuffer9 *pIndexData )
+{
+ struct nine_state *state = This->update;
+
+ if (likely(!This->is_recording))
+ if (state->idxbuf == NineIndexBuffer9(pIndexData))
+ return D3D_OK;
+ nine_bind(&state->idxbuf, pIndexData);
+
+ state->changed.group |= NINE_STATE_IDXBUF;
+
+ return D3D_OK;
+}
+
+/* XXX: wine/d3d9 doesn't have pBaseVertexIndex, and it doesn't make sense
+ * here because it's an argument passed to the Draw calls.
+ */
+HRESULT WINAPI
+NineDevice9_GetIndices( struct NineDevice9 *This,
+ IDirect3DIndexBuffer9 **ppIndexData /*,
+ UINT *pBaseVertexIndex */ )
+{
+ user_assert(ppIndexData, D3DERR_INVALIDCALL);
+ nine_reference_set(ppIndexData, This->state.idxbuf);
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_CreatePixelShader( struct NineDevice9 *This,
+ const DWORD *pFunction,
+ IDirect3DPixelShader9 **ppShader )
+{
+ struct NinePixelShader9 *ps;
+ HRESULT hr;
+
+ hr = NinePixelShader9_new(This, &ps, pFunction, NULL);
+ if (FAILED(hr))
+ return hr;
+ *ppShader = (IDirect3DPixelShader9 *)ps;
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_SetPixelShader( struct NineDevice9 *This,
+ IDirect3DPixelShader9 *pShader )
+{
+ struct nine_state *state = This->update;
+
+ DBG("This=%p pShader=%p\n", This, pShader);
+
+ nine_bind(&state->ps, pShader);
+
+ state->changed.group |= NINE_STATE_PS;
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_GetPixelShader( struct NineDevice9 *This,
+ IDirect3DPixelShader9 **ppShader )
+{
+ user_assert(ppShader, D3DERR_INVALIDCALL);
+ nine_reference_set(ppShader, This->state.ps);
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_SetPixelShaderConstantF( struct NineDevice9 *This,
+ UINT StartRegister,
+ const float *pConstantData,
+ UINT Vector4fCount )
+{
+ struct nine_state *state = This->update;
+
+ DBG("This=%p StartRegister=%u pConstantData=%p Vector4fCount=%u\n",
+ This, StartRegister, pConstantData, Vector4fCount);
+
+ user_assert(StartRegister < NINE_MAX_CONST_F, D3DERR_INVALIDCALL);
+ user_assert(StartRegister + Vector4fCount <= NINE_MAX_CONST_F, D3DERR_INVALIDCALL);
+
+ if (!Vector4fCount)
+ return D3D_OK;
+ user_assert(pConstantData, D3DERR_INVALIDCALL);
+
+ memcpy(&state->ps_const_f[StartRegister * 4],
+ pConstantData,
+ Vector4fCount * 4 * sizeof(state->ps_const_f[0]));
+
+ nine_ranges_insert(&state->changed.ps_const_f,
+ StartRegister, StartRegister + Vector4fCount,
+ &This->range_pool);
+
+ state->changed.group |= NINE_STATE_PS_CONST;
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_GetPixelShaderConstantF( struct NineDevice9 *This,
+ UINT StartRegister,
+ float *pConstantData,
+ UINT Vector4fCount )
+{
+ const struct nine_state *state = &This->state;
+
+ user_assert(StartRegister < NINE_MAX_CONST_F, D3DERR_INVALIDCALL);
+ user_assert(StartRegister + Vector4fCount <= NINE_MAX_CONST_F, D3DERR_INVALIDCALL);
+ user_assert(pConstantData, D3DERR_INVALIDCALL);
+
+ memcpy(pConstantData,
+ &state->ps_const_f[StartRegister * 4],
+ Vector4fCount * 4 * sizeof(state->ps_const_f[0]));
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_SetPixelShaderConstantI( struct NineDevice9 *This,
+ UINT StartRegister,
+ const int *pConstantData,
+ UINT Vector4iCount )
+{
+ struct nine_state *state = This->update;
+
+ DBG("This=%p StartRegister=%u pConstantData=%p Vector4iCount=%u\n",
+ This, StartRegister, pConstantData, Vector4iCount);
+
+ user_assert(StartRegister < NINE_MAX_CONST_I, D3DERR_INVALIDCALL);
+ user_assert(StartRegister + Vector4iCount <= NINE_MAX_CONST_I, D3DERR_INVALIDCALL);
+ user_assert(pConstantData, D3DERR_INVALIDCALL);
+
+ memcpy(&state->ps_const_i[StartRegister][0],
+ pConstantData,
+ Vector4iCount * sizeof(state->ps_const_i[0]));
+
+ state->changed.ps_const_i |= ((1 << Vector4iCount) - 1) << StartRegister;
+ state->changed.group |= NINE_STATE_PS_CONST;
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_GetPixelShaderConstantI( struct NineDevice9 *This,
+ UINT StartRegister,
+ int *pConstantData,
+ UINT Vector4iCount )
+{
+ const struct nine_state *state = &This->state;
+
+ user_assert(StartRegister < NINE_MAX_CONST_I, D3DERR_INVALIDCALL);
+ user_assert(StartRegister + Vector4iCount <= NINE_MAX_CONST_I, D3DERR_INVALIDCALL);
+ user_assert(pConstantData, D3DERR_INVALIDCALL);
+
+ memcpy(pConstantData,
+ &state->ps_const_i[StartRegister][0],
+ Vector4iCount * sizeof(state->ps_const_i[0]));
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_SetPixelShaderConstantB( struct NineDevice9 *This,
+ UINT StartRegister,
+ const BOOL *pConstantData,
+ UINT BoolCount )
+{
+ struct nine_state *state = This->update;
+
+ DBG("This=%p StartRegister=%u pConstantData=%p BoolCount=%u\n",
+ This, StartRegister, pConstantData, BoolCount);
+
+ user_assert(StartRegister < NINE_MAX_CONST_B, D3DERR_INVALIDCALL);
+ user_assert(StartRegister + BoolCount <= NINE_MAX_CONST_B, D3DERR_INVALIDCALL);
+ user_assert(pConstantData, D3DERR_INVALIDCALL);
+
+ memcpy(&state->ps_const_b[StartRegister],
+ pConstantData,
+ BoolCount * sizeof(state->ps_const_b[0]));
+
+ state->changed.ps_const_b |= ((1 << BoolCount) - 1) << StartRegister;
+ state->changed.group |= NINE_STATE_PS_CONST;
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_GetPixelShaderConstantB( struct NineDevice9 *This,
+ UINT StartRegister,
+ BOOL *pConstantData,
+ UINT BoolCount )
+{
+ const struct nine_state *state = &This->state;
+
+ user_assert(StartRegister < NINE_MAX_CONST_B, D3DERR_INVALIDCALL);
+ user_assert(StartRegister + BoolCount <= NINE_MAX_CONST_B, D3DERR_INVALIDCALL);
+ user_assert(pConstantData, D3DERR_INVALIDCALL);
+
+ memcpy(pConstantData,
+ &state->ps_const_b[StartRegister],
+ BoolCount * sizeof(state->ps_const_b[0]));
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9_DrawRectPatch( struct NineDevice9 *This,
+ UINT Handle,
+ const float *pNumSegs,
+ const D3DRECTPATCH_INFO *pRectPatchInfo )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineDevice9_DrawTriPatch( struct NineDevice9 *This,
+ UINT Handle,
+ const float *pNumSegs,
+ const D3DTRIPATCH_INFO *pTriPatchInfo )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineDevice9_DeletePatch( struct NineDevice9 *This,
+ UINT Handle )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineDevice9_CreateQuery( struct NineDevice9 *This,
+ D3DQUERYTYPE Type,
+ IDirect3DQuery9 **ppQuery )
+{
+ struct NineQuery9 *query;
+ HRESULT hr;
+
+ if (!ppQuery)
+ return nine_is_query_supported(Type);
+
+ hr = NineQuery9_new(This, &query, Type);
+ if (FAILED(hr))
+ return hr;
+ *ppQuery = (IDirect3DQuery9 *)query;
+ return D3D_OK;
+}
+
+IDirect3DDevice9Vtbl NineDevice9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)NineDevice9_TestCooperativeLevel,
+ (void *)NineDevice9_GetAvailableTextureMem,
+ (void *)NineDevice9_EvictManagedResources,
+ (void *)NineDevice9_GetDirect3D,
+ (void *)NineDevice9_GetDeviceCaps,
+ (void *)NineDevice9_GetDisplayMode,
+ (void *)NineDevice9_GetCreationParameters,
+ (void *)NineDevice9_SetCursorProperties,
+ (void *)NineDevice9_SetCursorPosition,
+ (void *)NineDevice9_ShowCursor,
+ (void *)NineDevice9_CreateAdditionalSwapChain,
+ (void *)NineDevice9_GetSwapChain,
+ (void *)NineDevice9_GetNumberOfSwapChains,
+ (void *)NineDevice9_Reset,
+ (void *)NineDevice9_Present,
+ (void *)NineDevice9_GetBackBuffer,
+ (void *)NineDevice9_GetRasterStatus,
+ (void *)NineDevice9_SetDialogBoxMode,
+ (void *)NineDevice9_SetGammaRamp,
+ (void *)NineDevice9_GetGammaRamp,
+ (void *)NineDevice9_CreateTexture,
+ (void *)NineDevice9_CreateVolumeTexture,
+ (void *)NineDevice9_CreateCubeTexture,
+ (void *)NineDevice9_CreateVertexBuffer,
+ (void *)NineDevice9_CreateIndexBuffer,
+ (void *)NineDevice9_CreateRenderTarget,
+ (void *)NineDevice9_CreateDepthStencilSurface,
+ (void *)NineDevice9_UpdateSurface,
+ (void *)NineDevice9_UpdateTexture,
+ (void *)NineDevice9_GetRenderTargetData,
+ (void *)NineDevice9_GetFrontBufferData,
+ (void *)NineDevice9_StretchRect,
+ (void *)NineDevice9_ColorFill,
+ (void *)NineDevice9_CreateOffscreenPlainSurface,
+ (void *)NineDevice9_SetRenderTarget,
+ (void *)NineDevice9_GetRenderTarget,
+ (void *)NineDevice9_SetDepthStencilSurface,
+ (void *)NineDevice9_GetDepthStencilSurface,
+ (void *)NineDevice9_BeginScene,
+ (void *)NineDevice9_EndScene,
+ (void *)NineDevice9_Clear,
+ (void *)NineDevice9_SetTransform,
+ (void *)NineDevice9_GetTransform,
+ (void *)NineDevice9_MultiplyTransform,
+ (void *)NineDevice9_SetViewport,
+ (void *)NineDevice9_GetViewport,
+ (void *)NineDevice9_SetMaterial,
+ (void *)NineDevice9_GetMaterial,
+ (void *)NineDevice9_SetLight,
+ (void *)NineDevice9_GetLight,
+ (void *)NineDevice9_LightEnable,
+ (void *)NineDevice9_GetLightEnable,
+ (void *)NineDevice9_SetClipPlane,
+ (void *)NineDevice9_GetClipPlane,
+ (void *)NineDevice9_SetRenderState,
+ (void *)NineDevice9_GetRenderState,
+ (void *)NineDevice9_CreateStateBlock,
+ (void *)NineDevice9_BeginStateBlock,
+ (void *)NineDevice9_EndStateBlock,
+ (void *)NineDevice9_SetClipStatus,
+ (void *)NineDevice9_GetClipStatus,
+ (void *)NineDevice9_GetTexture,
+ (void *)NineDevice9_SetTexture,
+ (void *)NineDevice9_GetTextureStageState,
+ (void *)NineDevice9_SetTextureStageState,
+ (void *)NineDevice9_GetSamplerState,
+ (void *)NineDevice9_SetSamplerState,
+ (void *)NineDevice9_ValidateDevice,
+ (void *)NineDevice9_SetPaletteEntries,
+ (void *)NineDevice9_GetPaletteEntries,
+ (void *)NineDevice9_SetCurrentTexturePalette,
+ (void *)NineDevice9_GetCurrentTexturePalette,
+ (void *)NineDevice9_SetScissorRect,
+ (void *)NineDevice9_GetScissorRect,
+ (void *)NineDevice9_SetSoftwareVertexProcessing,
+ (void *)NineDevice9_GetSoftwareVertexProcessing,
+ (void *)NineDevice9_SetNPatchMode,
+ (void *)NineDevice9_GetNPatchMode,
+ (void *)NineDevice9_DrawPrimitive,
+ (void *)NineDevice9_DrawIndexedPrimitive,
+ (void *)NineDevice9_DrawPrimitiveUP,
+ (void *)NineDevice9_DrawIndexedPrimitiveUP,
+ (void *)NineDevice9_ProcessVertices,
+ (void *)NineDevice9_CreateVertexDeclaration,
+ (void *)NineDevice9_SetVertexDeclaration,
+ (void *)NineDevice9_GetVertexDeclaration,
+ (void *)NineDevice9_SetFVF,
+ (void *)NineDevice9_GetFVF,
+ (void *)NineDevice9_CreateVertexShader,
+ (void *)NineDevice9_SetVertexShader,
+ (void *)NineDevice9_GetVertexShader,
+ (void *)NineDevice9_SetVertexShaderConstantF,
+ (void *)NineDevice9_GetVertexShaderConstantF,
+ (void *)NineDevice9_SetVertexShaderConstantI,
+ (void *)NineDevice9_GetVertexShaderConstantI,
+ (void *)NineDevice9_SetVertexShaderConstantB,
+ (void *)NineDevice9_GetVertexShaderConstantB,
+ (void *)NineDevice9_SetStreamSource,
+ (void *)NineDevice9_GetStreamSource,
+ (void *)NineDevice9_SetStreamSourceFreq,
+ (void *)NineDevice9_GetStreamSourceFreq,
+ (void *)NineDevice9_SetIndices,
+ (void *)NineDevice9_GetIndices,
+ (void *)NineDevice9_CreatePixelShader,
+ (void *)NineDevice9_SetPixelShader,
+ (void *)NineDevice9_GetPixelShader,
+ (void *)NineDevice9_SetPixelShaderConstantF,
+ (void *)NineDevice9_GetPixelShaderConstantF,
+ (void *)NineDevice9_SetPixelShaderConstantI,
+ (void *)NineDevice9_GetPixelShaderConstantI,
+ (void *)NineDevice9_SetPixelShaderConstantB,
+ (void *)NineDevice9_GetPixelShaderConstantB,
+ (void *)NineDevice9_DrawRectPatch,
+ (void *)NineDevice9_DrawTriPatch,
+ (void *)NineDevice9_DeletePatch,
+ (void *)NineDevice9_CreateQuery
+};
+
+static const GUID *NineDevice9_IIDs[] = {
+ &IID_IDirect3DDevice9,
+ &IID_IUnknown,
+ NULL
+};
+
+HRESULT
+NineDevice9_new( struct pipe_screen *pScreen,
+ D3DDEVICE_CREATION_PARAMETERS *pCreationParameters,
+ D3DCAPS9 *pCaps,
+ D3DPRESENT_PARAMETERS *pPresentationParameters,
+ IDirect3D9 *pD3D9,
+ ID3DPresentGroup *pPresentationGroup,
+ struct d3dadapter9_context *pCTX,
+ struct NineDevice9 **ppOut )
+{
+ BOOL lock;
+ lock = !!(pCreationParameters->BehaviorFlags & D3DCREATE_MULTITHREADED);
+
+ NINE_NEW(Device9, ppOut, lock, /* args */
+ pScreen, pCreationParameters, pCaps,
+ pPresentationParameters, pD3D9, pPresentationGroup, pCTX);
+}
diff --git a/src/gallium/state_trackers/nine/device9.h b/src/gallium/state_trackers/nine/device9.h
new file mode 100644
index 00000000000..9dc248e64fb
--- /dev/null
+++ b/src/gallium/state_trackers/nine/device9.h
@@ -0,0 +1,801 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _NINE_DEVICE9_H_
+#define _NINE_DEVICE9_H_
+
+#include "d3dadapter/d3dadapter9.h"
+
+#include "iunknown.h"
+#include "adapter9.h"
+
+#include "nine_helpers.h"
+#include "nine_state.h"
+
+struct gen_mipmap_state;
+struct util_hash_table;
+struct pipe_screen;
+struct pipe_context;
+struct cso_context;
+struct hud_context;
+struct u_upload_mgr;
+
+struct NineSwapChain9;
+struct NineStateBlock9;
+
+#include "util/u_double_list.h"
+
+struct NineDevice9
+{
+ struct NineUnknown base;
+ boolean ex;
+ D3DDISPLAYMODEEX *pFullscreenDisplayMode;
+
+ /* G3D context */
+ struct pipe_screen *screen;
+ struct pipe_context *pipe;
+ struct cso_context *cso;
+
+ /* creation parameters */
+ D3DCAPS9 caps;
+ D3DDEVICE_CREATION_PARAMETERS params;
+ IDirect3D9 *d3d9;
+
+ /* swapchain stuff */
+ ID3DPresentGroup *present;
+ struct NineSwapChain9 **swapchains;
+ unsigned nswapchains;
+
+ struct NineStateBlock9 *record;
+ struct nine_state *update; /* state to update (&state / &record->state) */
+ struct nine_state state; /* device state */
+
+ struct list_head update_textures;
+
+ boolean is_recording;
+ boolean in_scene;
+
+ boolean prefer_user_constbuf;
+
+ struct pipe_resource *constbuf_vs;
+ struct pipe_resource *constbuf_ps;
+ uint16_t max_vs_const_f;
+ uint16_t max_ps_const_f;
+ uint32_t vs_bool_true;
+ uint32_t ps_bool_true;
+
+ struct gen_mipmap_state *gen_mipmap;
+
+ struct {
+ struct util_hash_table *ht_vs;
+ struct util_hash_table *ht_ps;
+ struct NineVertexShader9 *vs;
+ struct NinePixelShader9 *ps;
+ unsigned num_vs;
+ unsigned num_ps;
+ float *vs_const;
+ float *ps_const;
+
+ struct util_hash_table *ht_fvf;
+ } ff;
+
+ struct {
+ struct pipe_resource *image;
+ unsigned w;
+ unsigned h;
+ POINT hotspot; /* -1, -1 if no cursor image set */
+ POINT pos;
+ BOOL visible;
+ boolean software;
+ } cursor;
+
+ struct {
+ boolean user_vbufs;
+ boolean user_ibufs;
+ boolean window_space_position_support;
+ } driver_caps;
+
+ struct u_upload_mgr *upload;
+
+ struct nine_range_pool range_pool;
+
+ struct hud_context *hud; /* NULL if hud is disabled */
+};
+static INLINE struct NineDevice9 *
+NineDevice9( void *data )
+{
+ return (struct NineDevice9 *)data;
+}
+
+HRESULT
+NineDevice9_new( struct pipe_screen *pScreen,
+ D3DDEVICE_CREATION_PARAMETERS *pCreationParameters,
+ D3DCAPS9 *pCaps,
+ D3DPRESENT_PARAMETERS *pPresentationParameters,
+ IDirect3D9 *pD3D9,
+ ID3DPresentGroup *pPresentationGroup,
+ struct d3dadapter9_context *pCTX,
+ struct NineDevice9 **ppOut );
+
+HRESULT
+NineDevice9_ctor( struct NineDevice9 *This,
+ struct NineUnknownParams *pParams,
+ struct pipe_screen *pScreen,
+ D3DDEVICE_CREATION_PARAMETERS *pCreationParameters,
+ D3DCAPS9 *pCaps,
+ D3DPRESENT_PARAMETERS *pPresentationParameters,
+ IDirect3D9 *pD3D9,
+ ID3DPresentGroup *pPresentationGroup,
+ struct d3dadapter9_context *pCTX );
+
+void
+NineDevice9_dtor( struct NineDevice9 *This );
+
+/*** Nine private ***/
+
+struct pipe_screen *
+NineDevice9_GetScreen( struct NineDevice9 *This );
+
+struct pipe_context *
+NineDevice9_GetPipe( struct NineDevice9 *This );
+
+struct cso_context *
+NineDevice9_GetCSO( struct NineDevice9 *This );
+
+const D3DCAPS9 *
+NineDevice9_GetCaps( struct NineDevice9 *This );
+
+/* Mask: 0x1 = constant buffers, 0x2 = stipple */
+void
+NineDevice9_RestoreNonCSOState( struct NineDevice9 *This, unsigned mask );
+
+/*** Direct3D public ***/
+
+HRESULT WINAPI
+NineDevice9_TestCooperativeLevel( struct NineDevice9 *This );
+
+UINT WINAPI
+NineDevice9_GetAvailableTextureMem( struct NineDevice9 *This );
+
+HRESULT WINAPI
+NineDevice9_EvictManagedResources( struct NineDevice9 *This );
+
+HRESULT WINAPI
+NineDevice9_GetDirect3D( struct NineDevice9 *This,
+ IDirect3D9 **ppD3D9 );
+
+HRESULT WINAPI
+NineDevice9_GetDeviceCaps( struct NineDevice9 *This,
+ D3DCAPS9 *pCaps );
+
+HRESULT WINAPI
+NineDevice9_GetDisplayMode( struct NineDevice9 *This,
+ UINT iSwapChain,
+ D3DDISPLAYMODE *pMode );
+
+HRESULT WINAPI
+NineDevice9_GetCreationParameters( struct NineDevice9 *This,
+ D3DDEVICE_CREATION_PARAMETERS *pParameters );
+
+HRESULT WINAPI
+NineDevice9_SetCursorProperties( struct NineDevice9 *This,
+ UINT XHotSpot,
+ UINT YHotSpot,
+ IDirect3DSurface9 *pCursorBitmap );
+
+void WINAPI
+NineDevice9_SetCursorPosition( struct NineDevice9 *This,
+ int X,
+ int Y,
+ DWORD Flags );
+
+BOOL WINAPI
+NineDevice9_ShowCursor( struct NineDevice9 *This,
+ BOOL bShow );
+
+HRESULT WINAPI
+NineDevice9_CreateAdditionalSwapChain( struct NineDevice9 *This,
+ D3DPRESENT_PARAMETERS *pPresentationParameters,
+ IDirect3DSwapChain9 **pSwapChain );
+
+HRESULT WINAPI
+NineDevice9_GetSwapChain( struct NineDevice9 *This,
+ UINT iSwapChain,
+ IDirect3DSwapChain9 **pSwapChain );
+
+UINT WINAPI
+NineDevice9_GetNumberOfSwapChains( struct NineDevice9 *This );
+
+HRESULT WINAPI
+NineDevice9_Reset( struct NineDevice9 *This,
+ D3DPRESENT_PARAMETERS *pPresentationParameters );
+
+HRESULT WINAPI
+NineDevice9_Present( struct NineDevice9 *This,
+ const RECT *pSourceRect,
+ const RECT *pDestRect,
+ HWND hDestWindowOverride,
+ const RGNDATA *pDirtyRegion );
+
+HRESULT WINAPI
+NineDevice9_GetBackBuffer( struct NineDevice9 *This,
+ UINT iSwapChain,
+ UINT iBackBuffer,
+ D3DBACKBUFFER_TYPE Type,
+ IDirect3DSurface9 **ppBackBuffer );
+
+HRESULT WINAPI
+NineDevice9_GetRasterStatus( struct NineDevice9 *This,
+ UINT iSwapChain,
+ D3DRASTER_STATUS *pRasterStatus );
+
+HRESULT WINAPI
+NineDevice9_SetDialogBoxMode( struct NineDevice9 *This,
+ BOOL bEnableDialogs );
+
+void WINAPI
+NineDevice9_SetGammaRamp( struct NineDevice9 *This,
+ UINT iSwapChain,
+ DWORD Flags,
+ const D3DGAMMARAMP *pRamp );
+
+void WINAPI
+NineDevice9_GetGammaRamp( struct NineDevice9 *This,
+ UINT iSwapChain,
+ D3DGAMMARAMP *pRamp );
+
+HRESULT WINAPI
+NineDevice9_CreateTexture( struct NineDevice9 *This,
+ UINT Width,
+ UINT Height,
+ UINT Levels,
+ DWORD Usage,
+ D3DFORMAT Format,
+ D3DPOOL Pool,
+ IDirect3DTexture9 **ppTexture,
+ HANDLE *pSharedHandle );
+
+HRESULT WINAPI
+NineDevice9_CreateVolumeTexture( struct NineDevice9 *This,
+ UINT Width,
+ UINT Height,
+ UINT Depth,
+ UINT Levels,
+ DWORD Usage,
+ D3DFORMAT Format,
+ D3DPOOL Pool,
+ IDirect3DVolumeTexture9 **ppVolumeTexture,
+ HANDLE *pSharedHandle );
+
+HRESULT WINAPI
+NineDevice9_CreateCubeTexture( struct NineDevice9 *This,
+ UINT EdgeLength,
+ UINT Levels,
+ DWORD Usage,
+ D3DFORMAT Format,
+ D3DPOOL Pool,
+ IDirect3DCubeTexture9 **ppCubeTexture,
+ HANDLE *pSharedHandle );
+
+HRESULT WINAPI
+NineDevice9_CreateVertexBuffer( struct NineDevice9 *This,
+ UINT Length,
+ DWORD Usage,
+ DWORD FVF,
+ D3DPOOL Pool,
+ IDirect3DVertexBuffer9 **ppVertexBuffer,
+ HANDLE *pSharedHandle );
+
+HRESULT WINAPI
+NineDevice9_CreateIndexBuffer( struct NineDevice9 *This,
+ UINT Length,
+ DWORD Usage,
+ D3DFORMAT Format,
+ D3DPOOL Pool,
+ IDirect3DIndexBuffer9 **ppIndexBuffer,
+ HANDLE *pSharedHandle );
+
+HRESULT WINAPI
+NineDevice9_CreateRenderTarget( struct NineDevice9 *This,
+ UINT Width,
+ UINT Height,
+ D3DFORMAT Format,
+ D3DMULTISAMPLE_TYPE MultiSample,
+ DWORD MultisampleQuality,
+ BOOL Lockable,
+ IDirect3DSurface9 **ppSurface,
+ HANDLE *pSharedHandle );
+
+HRESULT WINAPI
+NineDevice9_CreateDepthStencilSurface( struct NineDevice9 *This,
+ UINT Width,
+ UINT Height,
+ D3DFORMAT Format,
+ D3DMULTISAMPLE_TYPE MultiSample,
+ DWORD MultisampleQuality,
+ BOOL Discard,
+ IDirect3DSurface9 **ppSurface,
+ HANDLE *pSharedHandle );
+
+HRESULT WINAPI
+NineDevice9_UpdateSurface( struct NineDevice9 *This,
+ IDirect3DSurface9 *pSourceSurface,
+ const RECT *pSourceRect,
+ IDirect3DSurface9 *pDestinationSurface,
+ const POINT *pDestPoint );
+
+HRESULT WINAPI
+NineDevice9_UpdateTexture( struct NineDevice9 *This,
+ IDirect3DBaseTexture9 *pSourceTexture,
+ IDirect3DBaseTexture9 *pDestinationTexture );
+
+HRESULT WINAPI
+NineDevice9_GetRenderTargetData( struct NineDevice9 *This,
+ IDirect3DSurface9 *pRenderTarget,
+ IDirect3DSurface9 *pDestSurface );
+
+HRESULT WINAPI
+NineDevice9_GetFrontBufferData( struct NineDevice9 *This,
+ UINT iSwapChain,
+ IDirect3DSurface9 *pDestSurface );
+
+HRESULT WINAPI
+NineDevice9_StretchRect( struct NineDevice9 *This,
+ IDirect3DSurface9 *pSourceSurface,
+ const RECT *pSourceRect,
+ IDirect3DSurface9 *pDestSurface,
+ const RECT *pDestRect,
+ D3DTEXTUREFILTERTYPE Filter );
+
+HRESULT WINAPI
+NineDevice9_ColorFill( struct NineDevice9 *This,
+ IDirect3DSurface9 *pSurface,
+ const RECT *pRect,
+ D3DCOLOR color );
+
+HRESULT WINAPI
+NineDevice9_CreateOffscreenPlainSurface( struct NineDevice9 *This,
+ UINT Width,
+ UINT Height,
+ D3DFORMAT Format,
+ D3DPOOL Pool,
+ IDirect3DSurface9 **ppSurface,
+ HANDLE *pSharedHandle );
+
+HRESULT WINAPI
+NineDevice9_SetRenderTarget( struct NineDevice9 *This,
+ DWORD RenderTargetIndex,
+ IDirect3DSurface9 *pRenderTarget );
+
+HRESULT WINAPI
+NineDevice9_GetRenderTarget( struct NineDevice9 *This,
+ DWORD RenderTargetIndex,
+ IDirect3DSurface9 **ppRenderTarget );
+
+HRESULT WINAPI
+NineDevice9_SetDepthStencilSurface( struct NineDevice9 *This,
+ IDirect3DSurface9 *pNewZStencil );
+
+HRESULT WINAPI
+NineDevice9_GetDepthStencilSurface( struct NineDevice9 *This,
+ IDirect3DSurface9 **ppZStencilSurface );
+
+HRESULT WINAPI
+NineDevice9_BeginScene( struct NineDevice9 *This );
+
+HRESULT WINAPI
+NineDevice9_EndScene( struct NineDevice9 *This );
+
+HRESULT WINAPI
+NineDevice9_Clear( struct NineDevice9 *This,
+ DWORD Count,
+ const D3DRECT *pRects,
+ DWORD Flags,
+ D3DCOLOR Color,
+ float Z,
+ DWORD Stencil );
+
+HRESULT WINAPI
+NineDevice9_SetTransform( struct NineDevice9 *This,
+ D3DTRANSFORMSTATETYPE State,
+ const D3DMATRIX *pMatrix );
+
+HRESULT WINAPI
+NineDevice9_GetTransform( struct NineDevice9 *This,
+ D3DTRANSFORMSTATETYPE State,
+ D3DMATRIX *pMatrix );
+
+HRESULT WINAPI
+NineDevice9_MultiplyTransform( struct NineDevice9 *This,
+ D3DTRANSFORMSTATETYPE State,
+ const D3DMATRIX *pMatrix );
+
+HRESULT WINAPI
+NineDevice9_SetViewport( struct NineDevice9 *This,
+ const D3DVIEWPORT9 *pViewport );
+
+HRESULT WINAPI
+NineDevice9_GetViewport( struct NineDevice9 *This,
+ D3DVIEWPORT9 *pViewport );
+
+HRESULT WINAPI
+NineDevice9_SetMaterial( struct NineDevice9 *This,
+ const D3DMATERIAL9 *pMaterial );
+
+HRESULT WINAPI
+NineDevice9_GetMaterial( struct NineDevice9 *This,
+ D3DMATERIAL9 *pMaterial );
+
+HRESULT WINAPI
+NineDevice9_SetLight( struct NineDevice9 *This,
+ DWORD Index,
+ const D3DLIGHT9 *pLight );
+
+HRESULT WINAPI
+NineDevice9_GetLight( struct NineDevice9 *This,
+ DWORD Index,
+ D3DLIGHT9 *pLight );
+
+HRESULT WINAPI
+NineDevice9_LightEnable( struct NineDevice9 *This,
+ DWORD Index,
+ BOOL Enable );
+
+HRESULT WINAPI
+NineDevice9_GetLightEnable( struct NineDevice9 *This,
+ DWORD Index,
+ BOOL *pEnable );
+
+HRESULT WINAPI
+NineDevice9_SetClipPlane( struct NineDevice9 *This,
+ DWORD Index,
+ const float *pPlane );
+
+HRESULT WINAPI
+NineDevice9_GetClipPlane( struct NineDevice9 *This,
+ DWORD Index,
+ float *pPlane );
+
+HRESULT WINAPI
+NineDevice9_SetRenderState( struct NineDevice9 *This,
+ D3DRENDERSTATETYPE State,
+ DWORD Value );
+
+HRESULT WINAPI
+NineDevice9_GetRenderState( struct NineDevice9 *This,
+ D3DRENDERSTATETYPE State,
+ DWORD *pValue );
+
+HRESULT WINAPI
+NineDevice9_CreateStateBlock( struct NineDevice9 *This,
+ D3DSTATEBLOCKTYPE Type,
+ IDirect3DStateBlock9 **ppSB );
+
+HRESULT WINAPI
+NineDevice9_BeginStateBlock( struct NineDevice9 *This );
+
+HRESULT WINAPI
+NineDevice9_EndStateBlock( struct NineDevice9 *This,
+ IDirect3DStateBlock9 **ppSB );
+
+HRESULT WINAPI
+NineDevice9_SetClipStatus( struct NineDevice9 *This,
+ const D3DCLIPSTATUS9 *pClipStatus );
+
+HRESULT WINAPI
+NineDevice9_GetClipStatus( struct NineDevice9 *This,
+ D3DCLIPSTATUS9 *pClipStatus );
+
+HRESULT WINAPI
+NineDevice9_GetTexture( struct NineDevice9 *This,
+ DWORD Stage,
+ IDirect3DBaseTexture9 **ppTexture );
+
+HRESULT WINAPI
+NineDevice9_SetTexture( struct NineDevice9 *This,
+ DWORD Stage,
+ IDirect3DBaseTexture9 *pTexture );
+
+HRESULT WINAPI
+NineDevice9_GetTextureStageState( struct NineDevice9 *This,
+ DWORD Stage,
+ D3DTEXTURESTAGESTATETYPE Type,
+ DWORD *pValue );
+
+HRESULT WINAPI
+NineDevice9_SetTextureStageState( struct NineDevice9 *This,
+ DWORD Stage,
+ D3DTEXTURESTAGESTATETYPE Type,
+ DWORD Value );
+
+HRESULT WINAPI
+NineDevice9_GetSamplerState( struct NineDevice9 *This,
+ DWORD Sampler,
+ D3DSAMPLERSTATETYPE Type,
+ DWORD *pValue );
+
+HRESULT WINAPI
+NineDevice9_SetSamplerState( struct NineDevice9 *This,
+ DWORD Sampler,
+ D3DSAMPLERSTATETYPE Type,
+ DWORD Value );
+
+HRESULT WINAPI
+NineDevice9_ValidateDevice( struct NineDevice9 *This,
+ DWORD *pNumPasses );
+
+HRESULT WINAPI
+NineDevice9_SetPaletteEntries( struct NineDevice9 *This,
+ UINT PaletteNumber,
+ const PALETTEENTRY *pEntries );
+
+HRESULT WINAPI
+NineDevice9_GetPaletteEntries( struct NineDevice9 *This,
+ UINT PaletteNumber,
+ PALETTEENTRY *pEntries );
+
+HRESULT WINAPI
+NineDevice9_SetCurrentTexturePalette( struct NineDevice9 *This,
+ UINT PaletteNumber );
+
+HRESULT WINAPI
+NineDevice9_GetCurrentTexturePalette( struct NineDevice9 *This,
+ UINT *PaletteNumber );
+
+HRESULT WINAPI
+NineDevice9_SetScissorRect( struct NineDevice9 *This,
+ const RECT *pRect );
+
+HRESULT WINAPI
+NineDevice9_GetScissorRect( struct NineDevice9 *This,
+ RECT *pRect );
+
+HRESULT WINAPI
+NineDevice9_SetSoftwareVertexProcessing( struct NineDevice9 *This,
+ BOOL bSoftware );
+
+BOOL WINAPI
+NineDevice9_GetSoftwareVertexProcessing( struct NineDevice9 *This );
+
+HRESULT WINAPI
+NineDevice9_SetNPatchMode( struct NineDevice9 *This,
+ float nSegments );
+
+float WINAPI
+NineDevice9_GetNPatchMode( struct NineDevice9 *This );
+
+HRESULT WINAPI
+NineDevice9_DrawPrimitive( struct NineDevice9 *This,
+ D3DPRIMITIVETYPE PrimitiveType,
+ UINT StartVertex,
+ UINT PrimitiveCount );
+
+HRESULT WINAPI
+NineDevice9_DrawIndexedPrimitive( struct NineDevice9 *This,
+ D3DPRIMITIVETYPE PrimitiveType,
+ INT BaseVertexIndex,
+ UINT MinVertexIndex,
+ UINT NumVertices,
+ UINT startIndex,
+ UINT primCount );
+
+HRESULT WINAPI
+NineDevice9_DrawPrimitiveUP( struct NineDevice9 *This,
+ D3DPRIMITIVETYPE PrimitiveType,
+ UINT PrimitiveCount,
+ const void *pVertexStreamZeroData,
+ UINT VertexStreamZeroStride );
+
+HRESULT WINAPI
+NineDevice9_DrawIndexedPrimitiveUP( struct NineDevice9 *This,
+ D3DPRIMITIVETYPE PrimitiveType,
+ UINT MinVertexIndex,
+ UINT NumVertices,
+ UINT PrimitiveCount,
+ const void *pIndexData,
+ D3DFORMAT IndexDataFormat,
+ const void *pVertexStreamZeroData,
+ UINT VertexStreamZeroStride );
+
+HRESULT WINAPI
+NineDevice9_ProcessVertices( struct NineDevice9 *This,
+ UINT SrcStartIndex,
+ UINT DestIndex,
+ UINT VertexCount,
+ IDirect3DVertexBuffer9 *pDestBuffer,
+ IDirect3DVertexDeclaration9 *pVertexDecl,
+ DWORD Flags );
+
+HRESULT WINAPI
+NineDevice9_CreateVertexDeclaration( struct NineDevice9 *This,
+ const D3DVERTEXELEMENT9 *pVertexElements,
+ IDirect3DVertexDeclaration9 **ppDecl );
+
+HRESULT WINAPI
+NineDevice9_SetVertexDeclaration( struct NineDevice9 *This,
+ IDirect3DVertexDeclaration9 *pDecl );
+
+HRESULT WINAPI
+NineDevice9_GetVertexDeclaration( struct NineDevice9 *This,
+ IDirect3DVertexDeclaration9 **ppDecl );
+
+HRESULT WINAPI
+NineDevice9_SetFVF( struct NineDevice9 *This,
+ DWORD FVF );
+
+HRESULT WINAPI
+NineDevice9_GetFVF( struct NineDevice9 *This,
+ DWORD *pFVF );
+
+HRESULT WINAPI
+NineDevice9_CreateVertexShader( struct NineDevice9 *This,
+ const DWORD *pFunction,
+ IDirect3DVertexShader9 **ppShader );
+
+HRESULT WINAPI
+NineDevice9_SetVertexShader( struct NineDevice9 *This,
+ IDirect3DVertexShader9 *pShader );
+
+HRESULT WINAPI
+NineDevice9_GetVertexShader( struct NineDevice9 *This,
+ IDirect3DVertexShader9 **ppShader );
+
+HRESULT WINAPI
+NineDevice9_SetVertexShaderConstantF( struct NineDevice9 *This,
+ UINT StartRegister,
+ const float *pConstantData,
+ UINT Vector4fCount );
+
+HRESULT WINAPI
+NineDevice9_GetVertexShaderConstantF( struct NineDevice9 *This,
+ UINT StartRegister,
+ float *pConstantData,
+ UINT Vector4fCount );
+
+HRESULT WINAPI
+NineDevice9_SetVertexShaderConstantI( struct NineDevice9 *This,
+ UINT StartRegister,
+ const int *pConstantData,
+ UINT Vector4iCount );
+
+HRESULT WINAPI
+NineDevice9_GetVertexShaderConstantI( struct NineDevice9 *This,
+ UINT StartRegister,
+ int *pConstantData,
+ UINT Vector4iCount );
+
+HRESULT WINAPI
+NineDevice9_SetVertexShaderConstantB( struct NineDevice9 *This,
+ UINT StartRegister,
+ const BOOL *pConstantData,
+ UINT BoolCount );
+
+HRESULT WINAPI
+NineDevice9_GetVertexShaderConstantB( struct NineDevice9 *This,
+ UINT StartRegister,
+ BOOL *pConstantData,
+ UINT BoolCount );
+
+HRESULT WINAPI
+NineDevice9_SetStreamSource( struct NineDevice9 *This,
+ UINT StreamNumber,
+ IDirect3DVertexBuffer9 *pStreamData,
+ UINT OffsetInBytes,
+ UINT Stride );
+
+HRESULT WINAPI
+NineDevice9_GetStreamSource( struct NineDevice9 *This,
+ UINT StreamNumber,
+ IDirect3DVertexBuffer9 **ppStreamData,
+ UINT *pOffsetInBytes,
+ UINT *pStride );
+
+HRESULT WINAPI
+NineDevice9_SetStreamSourceFreq( struct NineDevice9 *This,
+ UINT StreamNumber,
+ UINT Setting );
+
+HRESULT WINAPI
+NineDevice9_GetStreamSourceFreq( struct NineDevice9 *This,
+ UINT StreamNumber,
+ UINT *pSetting );
+
+HRESULT WINAPI
+NineDevice9_SetIndices( struct NineDevice9 *This,
+ IDirect3DIndexBuffer9 *pIndexData );
+
+HRESULT WINAPI
+NineDevice9_GetIndices( struct NineDevice9 *This,
+ IDirect3DIndexBuffer9 **ppIndexData /*,
+ UINT *pBaseVertexIndex */ );
+
+HRESULT WINAPI
+NineDevice9_CreatePixelShader( struct NineDevice9 *This,
+ const DWORD *pFunction,
+ IDirect3DPixelShader9 **ppShader );
+
+HRESULT WINAPI
+NineDevice9_SetPixelShader( struct NineDevice9 *This,
+ IDirect3DPixelShader9 *pShader );
+
+HRESULT WINAPI
+NineDevice9_GetPixelShader( struct NineDevice9 *This,
+ IDirect3DPixelShader9 **ppShader );
+
+HRESULT WINAPI
+NineDevice9_SetPixelShaderConstantF( struct NineDevice9 *This,
+ UINT StartRegister,
+ const float *pConstantData,
+ UINT Vector4fCount );
+
+HRESULT WINAPI
+NineDevice9_GetPixelShaderConstantF( struct NineDevice9 *This,
+ UINT StartRegister,
+ float *pConstantData,
+ UINT Vector4fCount );
+
+HRESULT WINAPI
+NineDevice9_SetPixelShaderConstantI( struct NineDevice9 *This,
+ UINT StartRegister,
+ const int *pConstantData,
+ UINT Vector4iCount );
+
+HRESULT WINAPI
+NineDevice9_GetPixelShaderConstantI( struct NineDevice9 *This,
+ UINT StartRegister,
+ int *pConstantData,
+ UINT Vector4iCount );
+
+HRESULT WINAPI
+NineDevice9_SetPixelShaderConstantB( struct NineDevice9 *This,
+ UINT StartRegister,
+ const BOOL *pConstantData,
+ UINT BoolCount );
+
+HRESULT WINAPI
+NineDevice9_GetPixelShaderConstantB( struct NineDevice9 *This,
+ UINT StartRegister,
+ BOOL *pConstantData,
+ UINT BoolCount );
+
+HRESULT WINAPI
+NineDevice9_DrawRectPatch( struct NineDevice9 *This,
+ UINT Handle,
+ const float *pNumSegs,
+ const D3DRECTPATCH_INFO *pRectPatchInfo );
+
+HRESULT WINAPI
+NineDevice9_DrawTriPatch( struct NineDevice9 *This,
+ UINT Handle,
+ const float *pNumSegs,
+ const D3DTRIPATCH_INFO *pTriPatchInfo );
+
+HRESULT WINAPI
+NineDevice9_DeletePatch( struct NineDevice9 *This,
+ UINT Handle );
+
+HRESULT WINAPI
+NineDevice9_CreateQuery( struct NineDevice9 *This,
+ D3DQUERYTYPE Type,
+ IDirect3DQuery9 **ppQuery );
+
+#endif /* _NINE_DEVICE9_H_ */
diff --git a/src/gallium/state_trackers/nine/device9ex.c b/src/gallium/state_trackers/nine/device9ex.c
new file mode 100644
index 00000000000..00d460bdee4
--- /dev/null
+++ b/src/gallium/state_trackers/nine/device9ex.c
@@ -0,0 +1,400 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "device9ex.h"
+#include "swapchain9ex.h"
+
+#include "nine_helpers.h"
+
+#define DBG_CHANNEL DBG_DEVICE
+
+static HRESULT
+NineDevice9Ex_ctor( struct NineDevice9Ex *This,
+ struct NineUnknownParams *pParams,
+ struct pipe_screen *pScreen,
+ D3DDEVICE_CREATION_PARAMETERS *pCreationParameters,
+ D3DCAPS9 *pCaps,
+ D3DPRESENT_PARAMETERS *pPresentationParameters,
+ D3DDISPLAYMODEEX *pFullscreenDisplayMode,
+ IDirect3D9Ex *pD3D9Ex,
+ ID3DPresentGroup *pPresentationGroup,
+ struct d3dadapter9_context *pCTX )
+{
+ This->base.ex = TRUE;
+ This->base.pFullscreenDisplayMode = pFullscreenDisplayMode;
+
+ return NineDevice9_ctor(&This->base, pParams,
+ pScreen, pCreationParameters, pCaps,
+ pPresentationParameters,
+ (IDirect3D9 *)pD3D9Ex, pPresentationGroup, pCTX);
+}
+
+static void
+NineDevice9Ex_dtor( struct NineDevice9Ex *This )
+{
+ NineDevice9_dtor(&This->base);
+}
+
+HRESULT WINAPI
+NineDevice9Ex_SetConvolutionMonoKernel( struct NineDevice9Ex *This,
+ UINT width,
+ UINT height,
+ float *rows,
+ float *columns )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineDevice9Ex_ComposeRects( struct NineDevice9Ex *This,
+ IDirect3DSurface9 *pSrc,
+ IDirect3DSurface9 *pDst,
+ IDirect3DVertexBuffer9 *pSrcRectDescs,
+ UINT NumRects,
+ IDirect3DVertexBuffer9 *pDstRectDescs,
+ D3DCOMPOSERECTSOP Operation,
+ int Xoffset,
+ int Yoffset )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineDevice9Ex_PresentEx( struct NineDevice9Ex *This,
+ const RECT *pSourceRect,
+ const RECT *pDestRect,
+ HWND hDestWindowOverride,
+ const RGNDATA *pDirtyRegion,
+ DWORD dwFlags )
+{
+ unsigned i;
+ HRESULT hr;
+
+ for (i = 0; i < This->base.nswapchains; i++) {
+ hr = NineSwapChain9_Present(This->base.swapchains[i], pSourceRect, pDestRect,
+ hDestWindowOverride, pDirtyRegion, dwFlags);
+ if (FAILED(hr)) { return hr; }
+ }
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9Ex_GetGPUThreadPriority( struct NineDevice9Ex *This,
+ INT *pPriority )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineDevice9Ex_SetGPUThreadPriority( struct NineDevice9Ex *This,
+ INT Priority )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineDevice9Ex_WaitForVBlank( struct NineDevice9Ex *This,
+ UINT iSwapChain )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineDevice9Ex_CheckResourceResidency( struct NineDevice9Ex *This,
+ IDirect3DResource9 **pResourceArray,
+ UINT32 NumResources )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineDevice9Ex_SetMaximumFrameLatency( struct NineDevice9Ex *This,
+ UINT MaxLatency )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineDevice9Ex_GetMaximumFrameLatency( struct NineDevice9Ex *This,
+ UINT *pMaxLatency )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineDevice9Ex_CheckDeviceState( struct NineDevice9Ex *This,
+ HWND hDestinationWindow )
+{
+ DBG("This=%p hDestinationWindow=%p\n",
+ This, hDestinationWindow);
+
+ /* TODO: handle the other return values */
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineDevice9Ex_CreateRenderTargetEx( struct NineDevice9Ex *This,
+ UINT Width,
+ UINT Height,
+ D3DFORMAT Format,
+ D3DMULTISAMPLE_TYPE MultiSample,
+ DWORD MultisampleQuality,
+ BOOL Lockable,
+ IDirect3DSurface9 **ppSurface,
+ HANDLE *pSharedHandle,
+ DWORD Usage )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineDevice9Ex_CreateOffscreenPlainSurfaceEx( struct NineDevice9Ex *This,
+ UINT Width,
+ UINT Height,
+ D3DFORMAT Format,
+ D3DPOOL Pool,
+ IDirect3DSurface9 **ppSurface,
+ HANDLE *pSharedHandle,
+ DWORD Usage )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineDevice9Ex_CreateDepthStencilSurfaceEx( struct NineDevice9Ex *This,
+ UINT Width,
+ UINT Height,
+ D3DFORMAT Format,
+ D3DMULTISAMPLE_TYPE MultiSample,
+ DWORD MultisampleQuality,
+ BOOL Discard,
+ IDirect3DSurface9 **ppSurface,
+ HANDLE *pSharedHandle,
+ DWORD Usage )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineDevice9Ex_ResetEx( struct NineDevice9Ex *This,
+ D3DPRESENT_PARAMETERS *pPresentationParameters,
+ D3DDISPLAYMODEEX *pFullscreenDisplayMode )
+{
+ HRESULT hr = D3D_OK;
+ unsigned i;
+
+ DBG("This=%p pPresentationParameters=%p pFullscreenDisplayMode=%p\n", This, pPresentationParameters, pFullscreenDisplayMode);
+
+ for (i = 0; i < This->base.nswapchains; ++i) {
+ D3DDISPLAYMODEEX *mode = NULL;
+ D3DPRESENT_PARAMETERS *params = &pPresentationParameters[i];
+ if (pFullscreenDisplayMode) mode = &(pFullscreenDisplayMode[i]);
+ hr = NineSwapChain9_Resize(This->base.swapchains[i], params, mode);
+ if (FAILED(hr))
+ return (hr == D3DERR_OUTOFVIDEOMEMORY) ? hr : D3DERR_DEVICELOST;
+ }
+
+ NineDevice9_SetRenderTarget(
+ (struct NineDevice9 *)This, 0, (IDirect3DSurface9 *)This->base.swapchains[0]->buffers[0]);
+
+
+ return hr;
+}
+
+HRESULT WINAPI
+NineDevice9Ex_GetDisplayModeEx( struct NineDevice9Ex *This,
+ UINT iSwapChain,
+ D3DDISPLAYMODEEX *pMode,
+ D3DDISPLAYROTATION *pRotation )
+{
+ struct NineSwapChain9Ex *swapchain;
+
+ user_assert(iSwapChain < This->base.nswapchains, D3DERR_INVALIDCALL);
+
+ swapchain = NineSwapChain9Ex(This->base.swapchains[iSwapChain]);
+ return NineSwapChain9Ex_GetDisplayModeEx(swapchain, pMode, pRotation);
+}
+
+IDirect3DDevice9ExVtbl NineDevice9Ex_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)NineDevice9_TestCooperativeLevel,
+ (void *)NineDevice9_GetAvailableTextureMem,
+ (void *)NineDevice9_EvictManagedResources,
+ (void *)NineDevice9_GetDirect3D,
+ (void *)NineDevice9_GetDeviceCaps,
+ (void *)NineDevice9_GetDisplayMode,
+ (void *)NineDevice9_GetCreationParameters,
+ (void *)NineDevice9_SetCursorProperties,
+ (void *)NineDevice9_SetCursorPosition,
+ (void *)NineDevice9_ShowCursor,
+ (void *)NineDevice9_CreateAdditionalSwapChain,
+ (void *)NineDevice9_GetSwapChain,
+ (void *)NineDevice9_GetNumberOfSwapChains,
+ (void *)NineDevice9_Reset,
+ (void *)NineDevice9_Present,
+ (void *)NineDevice9_GetBackBuffer,
+ (void *)NineDevice9_GetRasterStatus,
+ (void *)NineDevice9_SetDialogBoxMode,
+ (void *)NineDevice9_SetGammaRamp,
+ (void *)NineDevice9_GetGammaRamp,
+ (void *)NineDevice9_CreateTexture,
+ (void *)NineDevice9_CreateVolumeTexture,
+ (void *)NineDevice9_CreateCubeTexture,
+ (void *)NineDevice9_CreateVertexBuffer,
+ (void *)NineDevice9_CreateIndexBuffer,
+ (void *)NineDevice9_CreateRenderTarget,
+ (void *)NineDevice9_CreateDepthStencilSurface,
+ (void *)NineDevice9_UpdateSurface,
+ (void *)NineDevice9_UpdateTexture,
+ (void *)NineDevice9_GetRenderTargetData,
+ (void *)NineDevice9_GetFrontBufferData,
+ (void *)NineDevice9_StretchRect,
+ (void *)NineDevice9_ColorFill,
+ (void *)NineDevice9_CreateOffscreenPlainSurface,
+ (void *)NineDevice9_SetRenderTarget,
+ (void *)NineDevice9_GetRenderTarget,
+ (void *)NineDevice9_SetDepthStencilSurface,
+ (void *)NineDevice9_GetDepthStencilSurface,
+ (void *)NineDevice9_BeginScene,
+ (void *)NineDevice9_EndScene,
+ (void *)NineDevice9_Clear,
+ (void *)NineDevice9_SetTransform,
+ (void *)NineDevice9_GetTransform,
+ (void *)NineDevice9_MultiplyTransform,
+ (void *)NineDevice9_SetViewport,
+ (void *)NineDevice9_GetViewport,
+ (void *)NineDevice9_SetMaterial,
+ (void *)NineDevice9_GetMaterial,
+ (void *)NineDevice9_SetLight,
+ (void *)NineDevice9_GetLight,
+ (void *)NineDevice9_LightEnable,
+ (void *)NineDevice9_GetLightEnable,
+ (void *)NineDevice9_SetClipPlane,
+ (void *)NineDevice9_GetClipPlane,
+ (void *)NineDevice9_SetRenderState,
+ (void *)NineDevice9_GetRenderState,
+ (void *)NineDevice9_CreateStateBlock,
+ (void *)NineDevice9_BeginStateBlock,
+ (void *)NineDevice9_EndStateBlock,
+ (void *)NineDevice9_SetClipStatus,
+ (void *)NineDevice9_GetClipStatus,
+ (void *)NineDevice9_GetTexture,
+ (void *)NineDevice9_SetTexture,
+ (void *)NineDevice9_GetTextureStageState,
+ (void *)NineDevice9_SetTextureStageState,
+ (void *)NineDevice9_GetSamplerState,
+ (void *)NineDevice9_SetSamplerState,
+ (void *)NineDevice9_ValidateDevice,
+ (void *)NineDevice9_SetPaletteEntries,
+ (void *)NineDevice9_GetPaletteEntries,
+ (void *)NineDevice9_SetCurrentTexturePalette,
+ (void *)NineDevice9_GetCurrentTexturePalette,
+ (void *)NineDevice9_SetScissorRect,
+ (void *)NineDevice9_GetScissorRect,
+ (void *)NineDevice9_SetSoftwareVertexProcessing,
+ (void *)NineDevice9_GetSoftwareVertexProcessing,
+ (void *)NineDevice9_SetNPatchMode,
+ (void *)NineDevice9_GetNPatchMode,
+ (void *)NineDevice9_DrawPrimitive,
+ (void *)NineDevice9_DrawIndexedPrimitive,
+ (void *)NineDevice9_DrawPrimitiveUP,
+ (void *)NineDevice9_DrawIndexedPrimitiveUP,
+ (void *)NineDevice9_ProcessVertices,
+ (void *)NineDevice9_CreateVertexDeclaration,
+ (void *)NineDevice9_SetVertexDeclaration,
+ (void *)NineDevice9_GetVertexDeclaration,
+ (void *)NineDevice9_SetFVF,
+ (void *)NineDevice9_GetFVF,
+ (void *)NineDevice9_CreateVertexShader,
+ (void *)NineDevice9_SetVertexShader,
+ (void *)NineDevice9_GetVertexShader,
+ (void *)NineDevice9_SetVertexShaderConstantF,
+ (void *)NineDevice9_GetVertexShaderConstantF,
+ (void *)NineDevice9_SetVertexShaderConstantI,
+ (void *)NineDevice9_GetVertexShaderConstantI,
+ (void *)NineDevice9_SetVertexShaderConstantB,
+ (void *)NineDevice9_GetVertexShaderConstantB,
+ (void *)NineDevice9_SetStreamSource,
+ (void *)NineDevice9_GetStreamSource,
+ (void *)NineDevice9_SetStreamSourceFreq,
+ (void *)NineDevice9_GetStreamSourceFreq,
+ (void *)NineDevice9_SetIndices,
+ (void *)NineDevice9_GetIndices,
+ (void *)NineDevice9_CreatePixelShader,
+ (void *)NineDevice9_SetPixelShader,
+ (void *)NineDevice9_GetPixelShader,
+ (void *)NineDevice9_SetPixelShaderConstantF,
+ (void *)NineDevice9_GetPixelShaderConstantF,
+ (void *)NineDevice9_SetPixelShaderConstantI,
+ (void *)NineDevice9_GetPixelShaderConstantI,
+ (void *)NineDevice9_SetPixelShaderConstantB,
+ (void *)NineDevice9_GetPixelShaderConstantB,
+ (void *)NineDevice9_DrawRectPatch,
+ (void *)NineDevice9_DrawTriPatch,
+ (void *)NineDevice9_DeletePatch,
+ (void *)NineDevice9_CreateQuery,
+ (void *)NineDevice9Ex_SetConvolutionMonoKernel,
+ (void *)NineDevice9Ex_ComposeRects,
+ (void *)NineDevice9Ex_PresentEx,
+ (void *)NineDevice9Ex_GetGPUThreadPriority,
+ (void *)NineDevice9Ex_SetGPUThreadPriority,
+ (void *)NineDevice9Ex_WaitForVBlank,
+ (void *)NineDevice9Ex_CheckResourceResidency,
+ (void *)NineDevice9Ex_SetMaximumFrameLatency,
+ (void *)NineDevice9Ex_GetMaximumFrameLatency,
+ (void *)NineDevice9Ex_CheckDeviceState,
+ (void *)NineDevice9Ex_CreateRenderTargetEx,
+ (void *)NineDevice9Ex_CreateOffscreenPlainSurfaceEx,
+ (void *)NineDevice9Ex_CreateDepthStencilSurfaceEx,
+ (void *)NineDevice9Ex_ResetEx,
+ (void *)NineDevice9Ex_GetDisplayModeEx
+};
+
+static const GUID *NineDevice9Ex_IIDs[] = {
+ &IID_IDirect3DDevice9Ex,
+ &IID_IDirect3DDevice9,
+ &IID_IUnknown,
+ NULL
+};
+
+HRESULT
+NineDevice9Ex_new( struct pipe_screen *pScreen,
+ D3DDEVICE_CREATION_PARAMETERS *pCreationParameters,
+ D3DCAPS9 *pCaps,
+ D3DPRESENT_PARAMETERS *pPresentationParameters,
+ D3DDISPLAYMODEEX *pFullscreenDisplayMode,
+ IDirect3D9Ex *pD3D9Ex,
+ ID3DPresentGroup *pPresentationGroup,
+ struct d3dadapter9_context *pCTX,
+ struct NineDevice9Ex **ppOut )
+{
+ BOOL lock;
+ lock = !!(pCreationParameters->BehaviorFlags & D3DCREATE_MULTITHREADED);
+
+ NINE_NEW(Device9Ex, ppOut, lock,
+ pScreen, pCreationParameters, pCaps, pPresentationParameters,
+ pFullscreenDisplayMode, pD3D9Ex, pPresentationGroup, pCTX);
+}
+
diff --git a/src/gallium/state_trackers/nine/device9ex.h b/src/gallium/state_trackers/nine/device9ex.h
new file mode 100644
index 00000000000..a31c720553a
--- /dev/null
+++ b/src/gallium/state_trackers/nine/device9ex.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _NINE_DEVICE9EX_H_
+#define _NINE_DEVICE9EX_H_
+
+#include "device9.h"
+
+struct NineDevice9Ex
+{
+ struct NineDevice9 base;
+};
+static INLINE struct NineDevice9Ex *
+NineDevice9Ex( void *data )
+{
+ return (struct NineDevice9Ex *)data;
+}
+
+HRESULT
+NineDevice9Ex_new( struct pipe_screen *pScreen,
+ D3DDEVICE_CREATION_PARAMETERS *pCreationParameters,
+ D3DCAPS9 *pCaps,
+ D3DPRESENT_PARAMETERS *pPresentationParameters,
+ D3DDISPLAYMODEEX *pFullscreenDisplayMode,
+ IDirect3D9Ex *pD3D9Ex,
+ ID3DPresentGroup *pPresentationGroup,
+ struct d3dadapter9_context *pCTX,
+ struct NineDevice9Ex **ppOut );
+
+HRESULT WINAPI
+NineDevice9Ex_SetConvolutionMonoKernel( struct NineDevice9Ex *This,
+ UINT width,
+ UINT height,
+ float *rows,
+ float *columns );
+
+HRESULT WINAPI
+NineDevice9Ex_ComposeRects( struct NineDevice9Ex *This,
+ IDirect3DSurface9 *pSrc,
+ IDirect3DSurface9 *pDst,
+ IDirect3DVertexBuffer9 *pSrcRectDescs,
+ UINT NumRects,
+ IDirect3DVertexBuffer9 *pDstRectDescs,
+ D3DCOMPOSERECTSOP Operation,
+ int Xoffset,
+ int Yoffset );
+
+HRESULT WINAPI
+NineDevice9Ex_PresentEx( struct NineDevice9Ex *This,
+ const RECT *pSourceRect,
+ const RECT *pDestRect,
+ HWND hDestWindowOverride,
+ const RGNDATA *pDirtyRegion,
+ DWORD dwFlags );
+
+HRESULT WINAPI
+NineDevice9Ex_GetGPUThreadPriority( struct NineDevice9Ex *This,
+ INT *pPriority );
+
+HRESULT WINAPI
+NineDevice9Ex_SetGPUThreadPriority( struct NineDevice9Ex *This,
+ INT Priority );
+
+HRESULT WINAPI
+NineDevice9Ex_WaitForVBlank( struct NineDevice9Ex *This,
+ UINT iSwapChain );
+
+HRESULT WINAPI
+NineDevice9Ex_CheckResourceResidency( struct NineDevice9Ex *This,
+ IDirect3DResource9 **pResourceArray,
+ UINT32 NumResources );
+
+HRESULT WINAPI
+NineDevice9Ex_SetMaximumFrameLatency( struct NineDevice9Ex *This,
+ UINT MaxLatency );
+
+HRESULT WINAPI
+NineDevice9Ex_GetMaximumFrameLatency( struct NineDevice9Ex *This,
+ UINT *pMaxLatency );
+
+HRESULT WINAPI
+NineDevice9Ex_CheckDeviceState( struct NineDevice9Ex *This,
+ HWND hDestinationWindow );
+
+HRESULT WINAPI
+NineDevice9Ex_CreateRenderTargetEx( struct NineDevice9Ex *This,
+ UINT Width,
+ UINT Height,
+ D3DFORMAT Format,
+ D3DMULTISAMPLE_TYPE MultiSample,
+ DWORD MultisampleQuality,
+ BOOL Lockable,
+ IDirect3DSurface9 **ppSurface,
+ HANDLE *pSharedHandle,
+ DWORD Usage );
+
+HRESULT WINAPI
+NineDevice9Ex_CreateOffscreenPlainSurfaceEx( struct NineDevice9Ex *This,
+ UINT Width,
+ UINT Height,
+ D3DFORMAT Format,
+ D3DPOOL Pool,
+ IDirect3DSurface9 **ppSurface,
+ HANDLE *pSharedHandle,
+ DWORD Usage );
+
+HRESULT WINAPI
+NineDevice9Ex_CreateDepthStencilSurfaceEx( struct NineDevice9Ex *This,
+ UINT Width,
+ UINT Height,
+ D3DFORMAT Format,
+ D3DMULTISAMPLE_TYPE MultiSample,
+ DWORD MultisampleQuality,
+ BOOL Discard,
+ IDirect3DSurface9 **ppSurface,
+ HANDLE *pSharedHandle,
+ DWORD Usage );
+
+HRESULT WINAPI
+NineDevice9Ex_ResetEx( struct NineDevice9Ex *This,
+ D3DPRESENT_PARAMETERS *pPresentationParameters,
+ D3DDISPLAYMODEEX *pFullscreenDisplayMode );
+
+HRESULT WINAPI
+NineDevice9Ex_GetDisplayModeEx( struct NineDevice9Ex *This,
+ UINT iSwapChain,
+ D3DDISPLAYMODEEX *pMode,
+ D3DDISPLAYROTATION *pRotation );
+
+#endif /* _NINE_DEVICE9EX_H_ */
diff --git a/src/gallium/state_trackers/nine/device9video.c b/src/gallium/state_trackers/nine/device9video.c
new file mode 100644
index 00000000000..65cc6a05c68
--- /dev/null
+++ b/src/gallium/state_trackers/nine/device9video.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "device9video.h"
+
+#define DBG_CHANNEL DBG_DEVICEVIDEO
+
+HRESULT WINAPI
+NineDevice9Video_GetContentProtectionCaps( struct NineDevice9Video *This,
+ const GUID *pCryptoType,
+ const GUID *pDecodeProfile,
+ D3DCONTENTPROTECTIONCAPS *pCaps )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineDevice9Video_CreateAuthenticatedChannel( struct NineDevice9Video *This,
+ D3DAUTHENTICATEDCHANNELTYPE ChannelType,
+ IDirect3DAuthenticatedChannel9 **ppAuthenticatedChannel,
+ HANDLE *pChannelHandle )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineDevice9Video_CreateCryptoSession( struct NineDevice9Video *This,
+ const GUID *pCryptoType,
+ const GUID *pDecodeProfile,
+ IDirect3DCryptoSession9 **ppCryptoSession,
+ HANDLE *pCryptoHandle )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+IDirect3DDevice9VideoVtbl NineDevice9Video_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)NineDevice9Video_GetContentProtectionCaps,
+ (void *)NineDevice9Video_CreateAuthenticatedChannel,
+ (void *)NineDevice9Video_CreateCryptoSession
+};
diff --git a/src/gallium/state_trackers/nine/device9video.h b/src/gallium/state_trackers/nine/device9video.h
new file mode 100644
index 00000000000..ca041e55fbc
--- /dev/null
+++ b/src/gallium/state_trackers/nine/device9video.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _NINE_DEVICE9VIDEO_H_
+#define _NINE_DEVICE9VIDEO_H_
+
+#include "iunknown.h"
+
+struct NineDevice9Video
+{
+ struct NineUnknown base;
+};
+static INLINE struct NineDevice9Video *
+NineDevice9Video( void *data )
+{
+ return (struct NineDevice9Video *)data;
+}
+
+HRESULT WINAPI
+NineDevice9Video_GetContentProtectionCaps( struct NineDevice9Video *This,
+ const GUID *pCryptoType,
+ const GUID *pDecodeProfile,
+ D3DCONTENTPROTECTIONCAPS *pCaps );
+
+HRESULT WINAPI
+NineDevice9Video_CreateAuthenticatedChannel( struct NineDevice9Video *This,
+ D3DAUTHENTICATEDCHANNELTYPE ChannelType,
+ IDirect3DAuthenticatedChannel9 **ppAuthenticatedChannel,
+ HANDLE *pChannelHandle );
+
+HRESULT WINAPI
+NineDevice9Video_CreateCryptoSession( struct NineDevice9Video *This,
+ const GUID *pCryptoType,
+ const GUID *pDecodeProfile,
+ IDirect3DCryptoSession9 **ppCryptoSession,
+ HANDLE *pCryptoHandle );
+
+#endif /* _NINE_DEVICE9VIDEO_H_ */
diff --git a/src/gallium/state_trackers/nine/guid.c b/src/gallium/state_trackers/nine/guid.c
new file mode 100644
index 00000000000..5034feb4d71
--- /dev/null
+++ b/src/gallium/state_trackers/nine/guid.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "guid.h"
+
+const GUID IID_IUnknown = { 0x00000000, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } };
+const GUID IID_ID3D9Adapter = { 0xBF6C7B9A, 0xF0BE, 0x11DF, { 0x81, 0xE3, 0x7F, 0x57, 0xDF, 0xD7, 0x20, 0x85 } };
+const GUID IID_IDirect3D9ExOverlayExtension = { 0x187AEB13, 0xAAF5, 0x4C59, { 0x87, 0x6D, 0xE0, 0x59, 0x08, 0x8C, 0x0D, 0xF8 } };
+const GUID IID_IDirect3DAuthenticatedChannel9 = { 0xFF24BEEE, 0xDA21, 0x4BEB, { 0x98, 0xB5, 0xD2, 0xF8, 0x99, 0xF9, 0x8A, 0xF9 } };
+const GUID IID_IDirect3DBaseTexture9 = { 0x580CA87E, 0x1D3C, 0x4D54, { 0x99, 0x1D, 0xB7, 0xD3, 0xE3, 0xC2, 0x98, 0xCE } };
+const GUID IID_IDirect3DCryptoSession9 = { 0xFA0AB799, 0x7A9C, 0x48CA, { 0x8C, 0x5B, 0x23, 0x7E, 0x71, 0xA5, 0x44, 0x34 } };
+const GUID IID_IDirect3DCubeTexture9 = { 0xFFF32F81, 0xD953, 0x473A, { 0x92, 0x23, 0x93, 0xD6, 0x52, 0xAB, 0xA9, 0x3F } };
+const GUID IID_IDirect3DDevice9 = { 0xD0223B96, 0xBF7A, 0x43FD, { 0x92, 0xBD, 0xA4, 0x3B, 0x0D, 0x82, 0xB9, 0xEB } };
+const GUID IID_IDirect3DDevice9Ex = { 0xB18B10CE, 0x2649, 0x405A, { 0x87, 0x0F, 0x95, 0xF7, 0x77, 0xD4, 0x31, 0x3A } };
+const GUID IID_IDirect3DDevice9Video = { 0x26DC4561, 0xA1EE, 0x4AE7, { 0x96, 0xDA, 0x11, 0x8A, 0x36, 0xC0, 0xEC, 0x95 } };
+const GUID IID_IDirect3DIndexBuffer9 = { 0x7C9DD65E, 0xD3F7, 0x4529, { 0xAC, 0xEE, 0x78, 0x58, 0x30, 0xAC, 0xDE, 0x35 } };
+const GUID IID_IDirect3DPixelShader9 = { 0x6D3BDBDC, 0x5B02, 0x4415, { 0xB8, 0x52, 0xCE, 0x5E, 0x8B, 0xCC, 0xB2, 0x89 } };
+const GUID IID_IDirect3DQuery9 = { 0xD9771460, 0xA695, 0x4F26, { 0xBB, 0xD3, 0x27, 0xB8, 0x40, 0xB5, 0x41, 0xCC } };
+const GUID IID_IDirect3DResource9 = { 0x05EEC05D, 0x8F7D, 0x4362, { 0xB9, 0x99, 0xD1, 0xBA, 0xF3, 0x57, 0xC7, 0x4 } };
+const GUID IID_IDirect3DStateBlock9 = { 0xB07C4FE5, 0x310D, 0x4BA8, { 0xA2, 0x3C, 0x4F, 0x0F, 0x20, 0x6F, 0x21, 0x8B } };
+const GUID IID_IDirect3DSurface9 = { 0x0CFBAF3A, 0x9FF6, 0x429A, { 0x99, 0xB3, 0xA2, 0x79, 0x6A, 0xF8, 0xB8, 0x9B } };
+const GUID IID_IDirect3DSwapChain9 = { 0x794950F2, 0xADFC, 0x458A, { 0x90, 0x5E, 0x10, 0xA1, 0x0B, 0x0B, 0x50, 0x3B } };
+const GUID IID_IDirect3DSwapChain9Ex = { 0x91886CAF, 0x1C3D, 0x4D2E, { 0xA0, 0xAB, 0x3E, 0x4C, 0x7D, 0x8D, 0x33, 0x3 } };
+const GUID IID_IDirect3DTexture9 = { 0x85C31227, 0x3DE5, 0x4F00, { 0x9B, 0x3A, 0xF1, 0x1A, 0xC3, 0x8C, 0x18, 0xB5 } };
+const GUID IID_IDirect3DVertexBuffer9 = { 0xB64BB1B5, 0xFD70, 0x4DF6, { 0xBF, 0x91, 0x19, 0xD0, 0xA1, 0x24, 0x55, 0xE3 } };
+const GUID IID_IDirect3DVertexDeclaration9 = { 0xDD13C59C, 0x36FA, 0x4098, { 0xA8, 0xFB, 0xC7, 0xED, 0x39, 0xDC, 0x85, 0x46 } };
+const GUID IID_IDirect3DVertexShader9 = { 0xEFC5557E, 0x6265, 0x4613, { 0x8A, 0x94, 0x43, 0x85, 0x78, 0x89, 0xEB, 0x36 } };
+const GUID IID_IDirect3DVolume9 = { 0x24F416E6, 0x1F67, 0x4AA7, { 0xB8, 0x8E, 0xD3, 0x3F, 0x6F, 0x31, 0x28, 0xA1 } };
+const GUID IID_IDirect3DVolumeTexture9 = { 0x2518526C, 0xE789, 0x4111, { 0xA7, 0xB9, 0x47, 0xEF, 0x32, 0x8D, 0x13, 0xE6 } };
+
+boolean
+GUID_equal( const GUID *a,
+ const GUID *b )
+{
+ unsigned i;
+
+ if (!a || !b)
+ return FALSE;
+
+ if (a->Data1 != b->Data1 ||
+ a->Data2 != b->Data2 ||
+ a->Data3 != b->Data3) { return FALSE; }
+ for (i = 0; i < 8; i++) {
+ if (a->Data4[i] != b->Data4[i]) { return FALSE; }
+ }
+ return TRUE;
+}
diff --git a/src/gallium/state_trackers/nine/guid.h b/src/gallium/state_trackers/nine/guid.h
new file mode 100644
index 00000000000..1f9ff009ad8
--- /dev/null
+++ b/src/gallium/state_trackers/nine/guid.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _NINE_GUID_H_
+#define _NINE_GUID_H_
+
+#include "pipe/p_compiler.h"
+
+#include "d3d9types.h"
+
+extern const GUID IID_ID3D9Adapter;
+
+boolean
+GUID_equal( const GUID *a,
+ const GUID *b );
+
+#endif /* _NINE_GUID_H_ */
diff --git a/src/gallium/state_trackers/nine/indexbuffer9.c b/src/gallium/state_trackers/nine/indexbuffer9.c
new file mode 100644
index 00000000000..c5606f1c757
--- /dev/null
+++ b/src/gallium/state_trackers/nine/indexbuffer9.c
@@ -0,0 +1,218 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "indexbuffer9.h"
+#include "device9.h"
+#include "nine_helpers.h"
+#include "nine_pipe.h"
+#include "nine_dump.h"
+
+#include "pipe/p_screen.h"
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_format.h"
+#include "util/u_box.h"
+
+#define DBG_CHANNEL DBG_INDEXBUFFER
+
+HRESULT
+NineIndexBuffer9_ctor( struct NineIndexBuffer9 *This,
+ struct NineUnknownParams *pParams,
+ D3DINDEXBUFFER_DESC *pDesc )
+{
+ struct pipe_resource *info = &This->base.info;
+ HRESULT hr;
+ DBG("This=%p pParams=%p pDesc=%p Usage=%s\n",
+ This, pParams, pDesc, nine_D3DUSAGE_to_str(pDesc->Usage));
+
+ This->pipe = pParams->device->pipe;
+
+ info->screen = pParams->device->screen;
+ info->target = PIPE_BUFFER;
+ info->format = PIPE_FORMAT_R8_UNORM;
+ info->width0 = pDesc->Size;
+ info->flags = 0;
+
+ info->bind = PIPE_BIND_INDEX_BUFFER | PIPE_BIND_TRANSFER_WRITE;
+ if (!(pDesc->Usage & D3DUSAGE_WRITEONLY))
+ info->bind |= PIPE_BIND_TRANSFER_READ;
+
+ info->usage = PIPE_USAGE_DEFAULT;
+ if (pDesc->Usage & D3DUSAGE_DYNAMIC)
+ info->usage = PIPE_USAGE_STREAM;
+ if (pDesc->Pool == D3DPOOL_SYSTEMMEM)
+ info->usage = PIPE_USAGE_STAGING;
+
+ /* if (This->desc.Usage & D3DUSAGE_DONOTCLIP) { } */
+ /* if (This->desc.Usage & D3DUSAGE_NONSECURE) { } */
+ /* if (This->desc.Usage & D3DUSAGE_NPATCHES) { } */
+ /* if (This->desc.Usage & D3DUSAGE_POINTS) { } */
+ /* if (This->desc.Usage & D3DUSAGE_RTPATCHES) { } */
+ /* if (This->desc.Usage & D3DUSAGE_SOFTWAREPROCESSING) { } */
+
+ info->height0 = 1;
+ info->depth0 = 1;
+ info->array_size = 1;
+ info->last_level = 0;
+ info->nr_samples = 0;
+
+ hr = NineResource9_ctor(&This->base, pParams, TRUE, D3DRTYPE_INDEXBUFFER,
+ pDesc->Pool);
+ if (FAILED(hr))
+ return hr;
+
+ This->buffer.buffer = This->base.resource;
+ This->buffer.offset = 0;
+ This->map_count = 0;
+
+ switch (pDesc->Format) {
+ case D3DFMT_INDEX16: This->buffer.index_size = 2; break;
+ case D3DFMT_INDEX32: This->buffer.index_size = 4; break;
+ default:
+ user_assert(!"Invalid index format.", D3DERR_INVALIDCALL);
+ break;
+ }
+ This->buffer.user_buffer = NULL;
+
+ pDesc->Type = D3DRTYPE_INDEXBUFFER;
+ This->desc = *pDesc;
+
+ return D3D_OK;
+}
+
+void
+NineIndexBuffer9_dtor( struct NineIndexBuffer9 *This )
+{
+ if (This->transfer) { NineIndexBuffer9_Unlock(This); }
+
+ NineResource9_dtor(&This->base);
+}
+
+const struct pipe_index_buffer *
+NineIndexBuffer9_GetBuffer( struct NineIndexBuffer9 *This )
+{
+ return &This->buffer;
+}
+
+HRESULT WINAPI
+NineIndexBuffer9_Lock( struct NineIndexBuffer9 *This,
+ UINT OffsetToLock,
+ UINT SizeToLock,
+ void **ppbData,
+ DWORD Flags )
+{
+ struct pipe_box box;
+ void *data;
+ UINT count;
+ const unsigned usage = d3dlock_buffer_to_pipe_transfer_usage(Flags);
+
+ DBG("This=%p OffsetToLock=%u SizeToLock=%u ppbData=%p Flags=%i "
+ "transfer=%p map_count=%u\n", This, OffsetToLock,
+ SizeToLock, ppbData, Flags, This->transfer, This->map_count);
+
+ count = ++This->map_count;
+
+ if (SizeToLock == 0) {
+ SizeToLock = This->desc.Size - OffsetToLock;
+ user_warn(OffsetToLock != 0);
+ }
+
+ u_box_1d(OffsetToLock, SizeToLock, &box);
+
+ if (unlikely(count != 1)) {
+ DBG("Lock has been called on already locked buffer."
+ "Unmapping before mapping again.");
+ This->pipe->transfer_unmap(This->pipe, This->transfer);
+ }
+ data = This->pipe->transfer_map(This->pipe, This->base.resource, 0,
+ usage, &box, &This->transfer);
+ if (!This->transfer) {
+ DBG("pipe::transfer_map failed\n"
+ " usage = %u\n"
+ " box.x = %u\n"
+ " box.width = %u\n",
+ usage, box.x, box.width);
+ }
+ *ppbData = data;
+ DBG("Returning memory at %p at address %p\n", *ppbData, ppbData);
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineIndexBuffer9_Unlock( struct NineIndexBuffer9 *This )
+{
+ DBG("This=%p\n", This);
+ if (!This->map_count) {
+ DBG("Unmap called without a previous map call.\n");
+ return D3D_OK;
+ }
+ if (--This->map_count) {
+ DBG("Ignoring unmap.\n");
+ return D3D_OK;
+ }
+ This->pipe->transfer_unmap(This->pipe, This->transfer);
+ This->transfer = NULL;
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineIndexBuffer9_GetDesc( struct NineIndexBuffer9 *This,
+ D3DINDEXBUFFER_DESC *pDesc )
+{
+ user_assert(pDesc, E_POINTER);
+ *pDesc = This->desc;
+ return D3D_OK;
+}
+
+IDirect3DIndexBuffer9Vtbl NineIndexBuffer9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */
+ (void *)NineResource9_SetPrivateData,
+ (void *)NineResource9_GetPrivateData,
+ (void *)NineResource9_FreePrivateData,
+ (void *)NineResource9_SetPriority,
+ (void *)NineResource9_GetPriority,
+ (void *)NineResource9_PreLoad,
+ (void *)NineResource9_GetType,
+ (void *)NineIndexBuffer9_Lock,
+ (void *)NineIndexBuffer9_Unlock,
+ (void *)NineIndexBuffer9_GetDesc
+};
+
+static const GUID *NineIndexBuffer9_IIDs[] = {
+ &IID_IDirect3DIndexBuffer9,
+ &IID_IDirect3DResource9,
+ &IID_IUnknown,
+ NULL
+};
+
+HRESULT
+NineIndexBuffer9_new( struct NineDevice9 *pDevice,
+ D3DINDEXBUFFER_DESC *pDesc,
+ struct NineIndexBuffer9 **ppOut )
+{
+ NINE_DEVICE_CHILD_NEW(IndexBuffer9, ppOut, /* args */ pDevice, pDesc);
+}
diff --git a/src/gallium/state_trackers/nine/indexbuffer9.h b/src/gallium/state_trackers/nine/indexbuffer9.h
new file mode 100644
index 00000000000..0982a93fbb1
--- /dev/null
+++ b/src/gallium/state_trackers/nine/indexbuffer9.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _NINE_INDEXBUFFER9_H_
+#define _NINE_INDEXBUFFER9_H_
+
+#include "resource9.h"
+
+#include "pipe/p_state.h"
+
+struct pipe_screen;
+struct pipe_context;
+struct pipe_index_buffer;
+struct pipe_transfer;
+struct NineDevice9;
+
+struct NineIndexBuffer9
+{
+ struct NineResource9 base;
+
+ /* g3d stuff */
+ struct pipe_context *pipe;
+ struct pipe_index_buffer buffer;
+ struct pipe_transfer *transfer;
+ UINT map_count;
+
+ D3DINDEXBUFFER_DESC desc;
+};
+static INLINE struct NineIndexBuffer9 *
+NineIndexBuffer9( void *data )
+{
+ return (struct NineIndexBuffer9 *)data;
+}
+
+HRESULT
+NineIndexBuffer9_new( struct NineDevice9 *pDevice,
+ D3DINDEXBUFFER_DESC *pDesc,
+ struct NineIndexBuffer9 **ppOut );
+
+HRESULT
+NineIndexBuffer9_ctor( struct NineIndexBuffer9 *This,
+ struct NineUnknownParams *pParams,
+ D3DINDEXBUFFER_DESC *pDesc );
+
+void
+NineIndexBuffer9_dtor( struct NineIndexBuffer9 *This );
+
+/*** Nine private ***/
+
+const struct pipe_index_buffer *
+NineIndexBuffer9_GetBuffer( struct NineIndexBuffer9 *This );
+
+/*** Direct3D public ***/
+
+HRESULT WINAPI
+NineIndexBuffer9_Lock( struct NineIndexBuffer9 *This,
+ UINT OffsetToLock,
+ UINT SizeToLock,
+ void **ppbData,
+ DWORD Flags );
+
+HRESULT WINAPI
+NineIndexBuffer9_Unlock( struct NineIndexBuffer9 *This );
+
+HRESULT WINAPI
+NineIndexBuffer9_GetDesc( struct NineIndexBuffer9 *This,
+ D3DINDEXBUFFER_DESC *pDesc );
+
+#endif /* _NINE_INDEXBUFFER9_H_ */
diff --git a/src/gallium/state_trackers/nine/iunknown.c b/src/gallium/state_trackers/nine/iunknown.c
new file mode 100644
index 00000000000..aff8041ec64
--- /dev/null
+++ b/src/gallium/state_trackers/nine/iunknown.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "iunknown.h"
+#include "util/u_atomic.h"
+#include "nine_helpers.h"
+
+#define DBG_CHANNEL DBG_UNKNOWN
+
+HRESULT
+NineUnknown_ctor( struct NineUnknown *This,
+ struct NineUnknownParams *pParams )
+{
+ This->refs = pParams->container ? 0 : 1;
+ This->bind = 0;
+ This->forward = !This->refs;
+ This->container = pParams->container;
+ This->device = pParams->device;
+ if (This->refs && This->device)
+ NineUnknown_AddRef(NineUnknown(This->device));
+
+ This->vtable = pParams->vtable;
+ This->guids = pParams->guids;
+ This->dtor = pParams->dtor;
+
+ return D3D_OK;
+}
+
+void
+NineUnknown_dtor( struct NineUnknown *This )
+{
+ FREE(This);
+}
+
+HRESULT WINAPI
+NineUnknown_QueryInterface( struct NineUnknown *This,
+ REFIID riid,
+ void **ppvObject )
+{
+ unsigned i = 0;
+
+ if (!ppvObject) return E_POINTER;
+
+ do {
+ if (GUID_equal(This->guids[i], riid)) {
+ *ppvObject = This;
+ assert(This->refs);
+ NineUnknown_AddRef(This);
+ return S_OK;
+ }
+ } while (This->guids[++i]);
+
+ *ppvObject = NULL;
+ return E_NOINTERFACE;
+}
+
+ULONG WINAPI
+NineUnknown_AddRef( struct NineUnknown *This )
+{
+ ULONG r;
+ if (This->forward)
+ return NineUnknown_AddRef(This->container);
+ else
+ r = p_atomic_inc_return(&This->refs);
+
+ if (r == 1) {
+ if (This->device)
+ NineUnknown_AddRef(NineUnknown(This->device));
+ /* This shouldn't be necessary:
+ if (This->container)
+ NineUnknown_Bind(NineUnknown(This->container)); */
+ }
+ return r;
+}
+
+ULONG WINAPI
+NineUnknown_Release( struct NineUnknown *This )
+{
+ if (This->forward)
+ return NineUnknown_Release(This->container);
+
+ ULONG r = p_atomic_dec_return(&This->refs);
+
+ if (r == 0) {
+ if (This->device) {
+ if (NineUnknown_Release(NineUnknown(This->device)) == 0)
+ return r; /* everything's gone */
+ }
+ if (This->container) {
+ /* NineUnknown_Unbind(NineUnknown(This->container)); */
+ } else
+ if (This->bind == 0) {
+ This->dtor(This);
+ }
+ }
+ return r;
+}
+
+HRESULT WINAPI
+NineUnknown_GetDevice( struct NineUnknown *This,
+ IDirect3DDevice9 **ppDevice )
+{
+ user_assert(ppDevice, E_POINTER);
+ NineUnknown_AddRef(NineUnknown(This->device));
+ *ppDevice = (IDirect3DDevice9 *)This->device;
+ return D3D_OK;
+}
diff --git a/src/gallium/state_trackers/nine/iunknown.h b/src/gallium/state_trackers/nine/iunknown.h
new file mode 100644
index 00000000000..4c83ddd8e4e
--- /dev/null
+++ b/src/gallium/state_trackers/nine/iunknown.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _NINE_IUNKNOWN_H_
+#define _NINE_IUNKNOWN_H_
+
+#include "pipe/p_compiler.h"
+
+#include "util/u_memory.h"
+
+#include "guid.h"
+#include "nine_debug.h"
+#include "nine_quirk.h"
+
+#include "d3d9.h"
+
+struct Nine9;
+struct NineDevice9;
+
+struct NineUnknown
+{
+ /* pointer to vtable */
+ void *vtable;
+
+ int32_t refs; /* external reference count */
+ int32_t bind; /* internal bind count */
+ boolean forward; /* whether to forward references to the container */
+
+ struct NineUnknown *container; /* referenced if (refs | bind) */
+ struct NineDevice9 *device; /* referenced if (refs) */
+
+ const GUID **guids; /* for QueryInterface */
+
+ void (*dtor)(void *data); /* top-level dtor */
+};
+static INLINE struct NineUnknown *
+NineUnknown( void *data )
+{
+ return (struct NineUnknown *)data;
+}
+
+/* Use this instead of a shitload of arguments: */
+struct NineUnknownParams
+{
+ void *vtable;
+ const GUID **guids;
+ void (*dtor)(void *data);
+ struct NineUnknown *container;
+ struct NineDevice9 *device;
+};
+
+HRESULT
+NineUnknown_ctor( struct NineUnknown *This,
+ struct NineUnknownParams *pParams );
+
+void
+NineUnknown_dtor( struct NineUnknown *This );
+
+/*** Direct3D public methods ***/
+
+HRESULT WINAPI
+NineUnknown_QueryInterface( struct NineUnknown *This,
+ REFIID riid,
+ void **ppvObject );
+
+ULONG WINAPI
+NineUnknown_AddRef( struct NineUnknown *This );
+
+ULONG WINAPI
+NineUnknown_Release( struct NineUnknown *This );
+
+HRESULT WINAPI
+NineUnknown_GetDevice( struct NineUnknown *This,
+ IDirect3DDevice9 **ppDevice );
+
+/*** Nine private methods ***/
+
+static INLINE void
+NineUnknown_Destroy( struct NineUnknown *This )
+{
+ assert(!(This->refs | This->bind));
+ This->dtor(This);
+}
+
+static INLINE UINT
+NineUnknown_Bind( struct NineUnknown *This )
+{
+ UINT b = ++This->bind;
+ assert(b);
+ if (b == 1 && This->container) {
+ if (This->container != NineUnknown(This->device))
+ NineUnknown_Bind(This->container);
+ }
+ return b;
+}
+
+static INLINE UINT
+NineUnknown_Unbind( struct NineUnknown *This )
+{
+ UINT b = --This->bind;
+ if (!b) {
+ if (This->container) {
+ if (This->container != NineUnknown(This->device))
+ NineUnknown_Unbind(This->container);
+ } else
+ if (This->refs == 0) {
+ This->dtor(This);
+ }
+ }
+ return b;
+}
+
+static INLINE void
+NineUnknown_ConvertRefToBind( struct NineUnknown *This )
+{
+ NineUnknown_Bind(This);
+ NineUnknown_Release(This);
+}
+
+/* Detach from container. */
+static INLINE void
+NineUnknown_Detach( struct NineUnknown *This )
+{
+ assert(This->container && !This->forward);
+ if (This->refs)
+ NineUnknown_Unbind(This->container);
+ if (This->bind)
+ NineUnknown_Unbind(This->container);
+ This->container = NULL;
+ if (!(This->refs | This->bind))
+ This->dtor(This);
+}
+
+#endif /* _NINE_IUNKNOWN_H_ */
diff --git a/src/gallium/state_trackers/nine/nine_debug.c b/src/gallium/state_trackers/nine/nine_debug.c
new file mode 100644
index 00000000000..4779192ecc3
--- /dev/null
+++ b/src/gallium/state_trackers/nine/nine_debug.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "nine_debug.h"
+
+#include <ctype.h>
+
+static const struct debug_named_value nine_debug_flags[] = {
+ { "unknown", DBG_UNKNOWN, "IUnknown implementation." },
+ { "adapter", DBG_ADAPTER, "ID3D9Adapter implementation." },
+ { "overlay", DBG_OVERLAYEXTENSION, "IDirect3D9ExOverlayExtension implementation." },
+ { "auth", DBG_AUTHENTICATEDCHANNEL, "IDirect3DAuthenticatedChannel9 implementation." },
+ { "basetex", DBG_BASETEXTURE, "IDirect3DBaseTexture9 implementation." },
+ { "crypto", DBG_CRYPTOSESSION, "IDirect3DCryptoSession9 implementation." },
+ { "cubetex", DBG_CUBETEXTURE, "IDirect3DCubeTexture9 implementation." },
+ { "device", DBG_DEVICE, "IDirect3DDevice9(Ex) implementation." },
+ { "video", DBG_DEVICEVIDEO, "IDirect3DDeviceVideo9 implementation." },
+ { "ibuf", DBG_INDEXBUFFER, "IDirect3DIndexBuffer9 implementation." },
+ { "ps", DBG_PIXELSHADER, "IDirect3DPixelShader9 implementation." },
+ { "query", DBG_QUERY, "IDirect3DQuery9 implementation." },
+ { "res", DBG_RESOURCE, "IDirect3DResource9 implementation." },
+ { "state", DBG_STATEBLOCK, "IDirect3DStateBlock9 implementation." },
+ { "surf", DBG_SURFACE, "IDirect3DSurface9 implementation." },
+ { "swap", DBG_SWAPCHAIN, "IDirect3DSwapChain9(Ex) implementation." },
+ { "tex", DBG_TEXTURE, "IDirect3DTexture9 implementation." },
+ { "vbuf", DBG_VERTEXBUFFER, "IDirect3DVertexBuffer9 implementation." },
+ { "vdecl", DBG_VERTEXDECLARATION, "IDirect3DVertexDeclaration9 implementation." },
+ { "vs", DBG_VERTEXSHADER, "IDirect3DVertexShader9 implementation." },
+ { "3dsurf", DBG_VOLUME, "IDirect3DVolume9 implementation." },
+ { "3dtex", DBG_VOLUMETEXTURE, "IDirect3DVolumeTexture9 implementation." },
+ { "shader", DBG_SHADER, "Shader token stream translator." },
+ { "ff", DBG_FF, "Fixed function emulation." },
+ { "user", DBG_USER, "User errors, both fixable and unfixable." },
+ { "error", DBG_ERROR, "Driver errors, always visible." },
+ { "warn", DBG_WARN, "Driver warnings, always visible in debug builds." },
+ DEBUG_NAMED_VALUE_END
+};
+
+void
+_nine_debug_printf( unsigned long flag,
+ const char *func,
+ const char *fmt,
+ ... )
+{
+ static boolean first = TRUE;
+ static unsigned long dbg_flags = DBG_ERROR | DBG_WARN;
+
+ if (first) {
+ first = FALSE;
+ dbg_flags |= debug_get_flags_option("NINE_DEBUG", nine_debug_flags, 0);
+ }
+ if (dbg_flags & flag) {
+ const char *f = func ? strrchr(func, '_') : NULL;
+ va_list ap;
+
+ /* inside a class this will print nine:classinlowercase:func: while
+ * outside a class (rarely used) it will just print nine:func:
+ * the reason for lower case is simply to match the filenames, as it
+ * will also strip off the "Nine" */
+ if (f && strncmp(func, "Nine", 4) == 0) {
+ char klass[96]; /* no class name is this long */
+ char *ptr = klass;
+ for (func += 4; func != f; ++func) { *ptr++ = tolower(*func); }
+ *ptr = '\0';
+
+ debug_printf("nine:%s:%s: ", klass, ++f);
+ } else if (func) {
+ debug_printf("nine:%s: ", func);
+ }
+
+ va_start(ap, fmt);
+ debug_vprintf(fmt, ap);
+ va_end(ap);
+ }
+}
+
+void
+_nine_stub( const char *file,
+ const char *func,
+ unsigned line )
+{
+ const char *r = strrchr(file, '/');
+ if (r == NULL) { r = strrchr(file, '\\'); }
+ debug_printf("nine:%s:%d: %s STUB!\n", r ? ++r : file, line, func);
+}
diff --git a/src/gallium/state_trackers/nine/nine_debug.h b/src/gallium/state_trackers/nine/nine_debug.h
new file mode 100644
index 00000000000..4c017eaac7e
--- /dev/null
+++ b/src/gallium/state_trackers/nine/nine_debug.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _NINE_DEBUG_H_
+#define _NINE_DEBUG_H_
+
+#include "util/u_debug.h"
+
+void
+_nine_debug_printf( unsigned long flag,
+ const char *func,
+ const char *fmt,
+ ... ) _util_printf_format(3,4);
+
+#define ERR(fmt, ...) _nine_debug_printf(DBG_ERROR, __FUNCTION__, fmt, ## __VA_ARGS__)
+
+#ifdef DEBUG
+#define WARN(fmt, ...) _nine_debug_printf(DBG_WARN, __FUNCTION__, fmt, ## __VA_ARGS__)
+#define WARN_ONCE(fmt, ...) \
+ do { \
+ static boolean once = TRUE; \
+ if (once) { \
+ once = FALSE; \
+ _nine_debug_printf(DBG_WARN, __FUNCTION__, fmt, ## __VA_ARGS__); \
+ } \
+ } while(0)
+#else
+#define WARN(fmt, ...)
+#define WARN_ONCE(fmt, ...)
+#endif
+
+#ifdef DEBUG
+#define DBG_FLAG(flag, fmt, ...) \
+ _nine_debug_printf(flag, __FUNCTION__, fmt, ## __VA_ARGS__)
+#else
+#define DBG_FLAG(flag, fmt, ...)
+#endif
+#define DBG(fmt, ...) DBG_FLAG(DBG_CHANNEL, fmt, ## __VA_ARGS__)
+
+#define DBG_UNKNOWN (1<< 0)
+#define DBG_ADAPTER (1<< 1)
+#define DBG_OVERLAYEXTENSION (1<< 2)
+#define DBG_AUTHENTICATEDCHANNEL (1<< 3)
+#define DBG_BASETEXTURE (1<< 4)
+#define DBG_CRYPTOSESSION (1<< 5)
+#define DBG_CUBETEXTURE (1<< 6)
+#define DBG_DEVICE (1<< 7)
+#define DBG_DEVICEVIDEO (1<< 8)
+#define DBG_INDEXBUFFER (1<< 9)
+#define DBG_PIXELSHADER (1<<10)
+#define DBG_QUERY (1<<11)
+#define DBG_RESOURCE (1<<12)
+#define DBG_STATEBLOCK (1<<13)
+#define DBG_SURFACE (1<<14)
+#define DBG_SWAPCHAIN (1<<15)
+#define DBG_TEXTURE (1<<16)
+#define DBG_VERTEXBUFFER (1<<17)
+#define DBG_VERTEXDECLARATION (1<<18)
+#define DBG_VERTEXSHADER (1<<19)
+#define DBG_VOLUME (1<<20)
+#define DBG_VOLUMETEXTURE (1<<21)
+#define DBG_SHADER (1<<22)
+#define DBG_FF (1<<23)
+#define DBG_USER (1<<24)
+#define DBG_ERROR (1<<25)
+#define DBG_WARN (1<<26)
+
+void
+_nine_stub( const char *file,
+ const char *func,
+ unsigned line );
+
+#ifdef DEBUG
+#define STUB(ret) \
+ do { \
+ _nine_stub(__FILE__, __FUNCTION__, __LINE__); \
+ return ret; \
+ } while (0)
+#else
+#define STUB(ret) do { return ret; } while (0)
+#endif
+
+/* the expression for this macro is equivalent of that to assert, however this
+ * macro is designed to be used in conditionals ala
+ * if (user_error(required condition)) { assertion failed }
+ * It also prints debug message if the assertion fails. */
+#ifdef DEBUG
+#define user_error(x) \
+ (!(x) ? (DBG_FLAG(DBG_USER, "User assertion failed: `%s'\n", #x), TRUE) \
+ : FALSE)
+#else
+#define user_error(x) (!(x) ? TRUE : FALSE)
+#endif
+
+#ifdef DEBUG
+#define user_warn(x) \
+ if ((x)) { DBG_FLAG(DBG_USER, "User warning: `%s'\n", #x); }
+#else
+#define user_warn(x)
+#endif
+
+/* nonfatal assert */
+#define user_assert(x, r) \
+ do { \
+ if (user_error(x)) { \
+ return r; \
+ } \
+ } while (0)
+
+#define ret_err(x, r) \
+ do { \
+ ERR(x); \
+ return r; \
+ } while(0)
+
+#endif /* _NINE_DEBUG_H_ */
diff --git a/src/gallium/state_trackers/nine/nine_defines.h b/src/gallium/state_trackers/nine/nine_defines.h
new file mode 100644
index 00000000000..aa3b257de09
--- /dev/null
+++ b/src/gallium/state_trackers/nine/nine_defines.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _NINE_DEFINES_H_
+#define _NINE_DEFINES_H_
+
+#include "pipe/p_defines.h"
+
+
+#define NINE_RESOURCE_FLAG_LOCKABLE (PIPE_RESOURCE_FLAG_ST_PRIV << 1)
+#define NINE_RESOURCE_FLAG_DUMMY (PIPE_RESOURCE_FLAG_ST_PRIV << 2)
+
+/* vertexdeclaration9.c */
+unsigned nine_d3d9_to_nine_declusage(unsigned usage, unsigned index);
+
+#define NINE_DECLUSAGE_POSITION(i) ( 0 + (i))
+#define NINE_DECLUSAGE_BLENDWEIGHT(i) ( 5 + (i))
+#define NINE_DECLUSAGE_BLENDINDICES(i) ( 9 + (i))
+#define NINE_DECLUSAGE_NORMAL(i) (13 + (i))
+#define NINE_DECLUSAGE_PSIZE 15
+#define NINE_DECLUSAGE_TEXCOORD(i) (16 + (i))
+#define NINE_DECLUSAGE_TANGENT(i) (32 + (i))
+#define NINE_DECLUSAGE_BINORMAL(i) (34 + (i))
+#define NINE_DECLUSAGE_TESSFACTOR 36
+#define NINE_DECLUSAGE_POSITIONT 37
+#define NINE_DECLUSAGE_COLOR(i) (38 + (i))
+#define NINE_DECLUSAGE_DEPTH 43
+#define NINE_DECLUSAGE_FOG 44
+#define NINE_DECLUSAGE_SAMPLE 45
+#define NINE_DECLUSAGE_NONE 46
+#define NINE_DECLUSAGE_LAST NINE_DECLUSAGE_NONE
+#define NINE_DECLUSAGE_COUNT (NINE_DECLUSAGE_LAST + 1)
+
+#define NINED3DCLEAR_DEPTHSTENCIL (D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL)
+
+#endif /* _NINE_DEFINES_H_ */
diff --git a/src/gallium/state_trackers/nine/nine_dump.c b/src/gallium/state_trackers/nine/nine_dump.c
new file mode 100644
index 00000000000..1ca550586e4
--- /dev/null
+++ b/src/gallium/state_trackers/nine/nine_dump.c
@@ -0,0 +1,813 @@
+
+#include "nine_debug.h"
+#include "nine_pipe.h"
+
+#include <stdio.h>
+#include "util/u_memory.h"
+#include "util/u_math.h"
+
+#include "nine_dump.h"
+
+#ifdef DEBUG
+
+static char __thread tls[128];
+
+const char *nine_D3DDEVTYPE_to_str(D3DDEVTYPE type)
+{
+ switch (type) {
+ case D3DDEVTYPE_HAL: return "HAL";
+ case D3DDEVTYPE_NULLREF: return "NULLREF";
+ case D3DDEVTYPE_REF: return "REF";
+ case D3DDEVTYPE_SW: return "SW";
+ default:
+ return "(D3DDEVTYPE_?)";
+ }
+}
+
+const char *nine_D3DPOOL_to_str(D3DPOOL pool)
+{
+ switch (pool) {
+ case D3DPOOL_DEFAULT: return "DEFAULT";
+ case D3DPOOL_MANAGED: return "MANAGED";
+ case D3DPOOL_SYSTEMMEM: return "SYSTEMMEM";
+ case D3DPOOL_SCRATCH: return "SCRATCH";
+ default:
+ return "(D3DPOOL_?)";
+ }
+}
+
+const char *nine_D3DSAMP_to_str(DWORD samp)
+{
+ switch (samp) {
+ case D3DSAMP_ADDRESSU: return "ADDRESSU";
+ case D3DSAMP_ADDRESSV: return "ADDRESSV";
+ case D3DSAMP_ADDRESSW: return "ADDRESSW";
+ case D3DSAMP_BORDERCOLOR: return "BORDERCOLOR";
+ case D3DSAMP_MAGFILTER: return "MAGFILTER";
+ case D3DSAMP_MINFILTER: return "MINFILTER";
+ case D3DSAMP_MIPFILTER: return "MIPFILTER";
+ case D3DSAMP_MIPMAPLODBIAS: return "MIPMAPLODBIAS";
+ case D3DSAMP_MAXMIPLEVEL: return "MAXMIPLEVEL";
+ case D3DSAMP_MAXANISOTROPY: return "MAXANISOTROPY";
+ case D3DSAMP_SRGBTEXTURE: return "SRGBTEXTURE";
+ case D3DSAMP_ELEMENTINDEX: return "ELEMENTINDEX";
+ case D3DSAMP_DMAPOFFSET: return "DMAPOFFSET";
+ default:
+ return "(D3DSAMP_?)";
+ }
+}
+
+#define C2S(n,s) \
+ do { \
+ if (usage & D3DUSAGE_##n) p += snprintf(&tls[p], sizeof(tls) - p, s); \
+ } while(0)
+const char *nine_D3DUSAGE_to_str(DWORD usage)
+{
+ int p = 0;
+ tls[0] = 0;
+ C2S(AUTOGENMIPMAP, "MIPGEN");
+ C2S(WRITEONLY, "WO");
+ C2S(DYNAMIC, "DYNAMIC");
+ C2S(DEPTHSTENCIL, "DS");
+ C2S(RENDERTARGET, "RT");
+ C2S(SOFTWAREPROCESSING, "SW");
+ C2S(DONOTCLIP, "NOCLIP");
+ C2S(POINTS, "POINTS");
+ C2S(DMAP, "DMAP");
+ C2S(NPATCHES, "NPATCHES");
+ C2S(RTPATCHES, "RTPATCHES");
+ C2S(TEXTAPI, "TEXTAPI");
+ C2S(NONSECURE, "NONSECURE");
+ C2S(RESTRICTED_CONTENT, "RESTRICTED_CONTENT");
+ C2S(RESTRICT_SHARED_RESOURCE, "RESTRICT_SHARED_RESOURCE");
+ C2S(RESTRICT_SHARED_RESOURCE_DRIVER, "RESTRICT_SHARED_RESOURCE_DRIVER");
+ return tls;
+}
+#undef C2S
+
+#define C2S(n) \
+ do { \
+ if (flags & D3DPRESENTFLAG_##n) \
+ p += snprintf(&tls[p], sizeof(tls) - p, #n); \
+ } while(0)
+const char *nine_D3DPRESENTFLAG_to_str(DWORD flags)
+{
+ int p = 0;
+ tls[0] = 0;
+ C2S(DEVICECLIP);
+ C2S(DISCARD_DEPTHSTENCIL);
+ C2S(LOCKABLE_BACKBUFFER);
+ C2S(NOAUTOROTATE);
+ C2S(UNPRUNEDMODE);
+ C2S(VIDEO);
+ C2S(OVERLAY_LIMITEDRGB);
+ C2S(OVERLAY_YCbCr_BT709);
+ C2S(OVERLAY_YCbCr_xvYCC);
+ C2S(RESTRICTED_CONTENT);
+ C2S(RESTRICT_SHARED_RESOURCE_DRIVER);
+ return tls;
+}
+#undef C2S
+
+#define C2S(n) \
+ do { \
+ if (lock & D3DLOCK_##n) p += snprintf(&tls[p], sizeof(tls) - p, #n"|"); \
+ } while(0)
+const char *nine_D3DLOCK_to_str(DWORD lock)
+{
+ int p = 0;
+ tls[0] = 0;
+ C2S(DISCARD);
+ C2S(DONOTWAIT);
+ C2S(NO_DIRTY_UPDATE);
+ C2S(NOOVERWRITE);
+ C2S(NOSYSLOCK);
+ C2S(READONLY);
+ return tls;
+}
+#undef C2S
+
+const char *nine_D3DRTYPE_to_str(D3DRESOURCETYPE type)
+{
+ switch (type) {
+ case D3DRTYPE_SURFACE: return "SURFACE";
+ case D3DRTYPE_VOLUME: return "VOLUME";
+ case D3DRTYPE_TEXTURE: return "TEXTURE";
+ case D3DRTYPE_VOLUMETEXTURE: return "VOLUMETEXTURE";
+ case D3DRTYPE_CUBETEXTURE: return "CUBETEXTURE";
+ case D3DRTYPE_VERTEXBUFFER: return "VERTEXBUFFER";
+ case D3DRTYPE_INDEXBUFFER: return "INDEXBUFFER";
+ default:
+ return "(D3DRTYPE_?)";
+ }
+}
+
+const char *nine_D3DQUERYTYPE_to_str(D3DQUERYTYPE type)
+{
+ switch (type) {
+ case D3DQUERYTYPE_VCACHE: return "VCACHE";
+ case D3DQUERYTYPE_RESOURCEMANAGER: return "RESOURCEMANAGER";
+ case D3DQUERYTYPE_VERTEXSTATS: return "VERTEXSTATS";
+ case D3DQUERYTYPE_EVENT: return "EVENT";
+ case D3DQUERYTYPE_OCCLUSION: return "OCCLUSION";
+ case D3DQUERYTYPE_TIMESTAMP: return "TIMESTAMP";
+ case D3DQUERYTYPE_TIMESTAMPDISJOINT: return "TIMESTAMPDISJOINT";
+ case D3DQUERYTYPE_TIMESTAMPFREQ: return "TIMESTAMPFREQ";
+ case D3DQUERYTYPE_PIPELINETIMINGS: return "PIPELINETIMINGS";
+ case D3DQUERYTYPE_INTERFACETIMINGS: return "INTERFACETIMINGS";
+ case D3DQUERYTYPE_VERTEXTIMINGS: return "VERTEXTIMINGS";
+ case D3DQUERYTYPE_PIXELTIMINGS: return "PIXELTIMINGS";
+ case D3DQUERYTYPE_BANDWIDTHTIMINGS: return "BANDWIDTHTIMINGS";
+ case D3DQUERYTYPE_CACHEUTILIZATION: return "CACHEUTILIZATION";
+ default:
+ return "(D3DQUERYTYPE_?)";
+ }
+}
+
+const char *nine_D3DTSS_to_str(D3DTEXTURESTAGESTATETYPE type)
+{
+ switch (type) {
+ case D3DTSS_COLOROP: return "COLOROP";
+ case D3DTSS_ALPHAOP: return "ALPHAOP";
+ case D3DTSS_COLORARG0: return "COLORARG0";
+ case D3DTSS_COLORARG1: return "COLORARG1";
+ case D3DTSS_COLORARG2: return "COLORARG2";
+ case D3DTSS_ALPHAARG0: return "ALPHAARG0";
+ case D3DTSS_ALPHAARG1: return "ALPHAARG1";
+ case D3DTSS_ALPHAARG2: return "ALPHAARG2";
+ case D3DTSS_RESULTARG: return "RESULTARG";
+ case D3DTSS_BUMPENVMAT00: return "BUMPENVMAT00";
+ case D3DTSS_BUMPENVMAT01: return "BUMPENVMAT01";
+ case D3DTSS_BUMPENVMAT10: return "BUMPENVMAT10";
+ case D3DTSS_BUMPENVMAT11: return "BUMPENVMAT11";
+ case D3DTSS_BUMPENVLSCALE: return "BUMPENVLSCALE";
+ case D3DTSS_BUMPENVLOFFSET: return "BUMPENVLOFFSET";
+ case D3DTSS_TEXCOORDINDEX: return "TEXCOORDINDEX";
+ case D3DTSS_TEXTURETRANSFORMFLAGS: return "TEXTURETRANSFORMFLAGS";
+ case D3DTSS_CONSTANT: return "CONSTANT";
+ default:
+ return "(D3DTSS_?)";
+ }
+}
+
+#define D3DTOP_TO_STR_CASE(n) case D3DTOP_##n: return #n
+const char *nine_D3DTOP_to_str(D3DTEXTUREOP top)
+{
+ switch (top) {
+ D3DTOP_TO_STR_CASE(DISABLE);
+ D3DTOP_TO_STR_CASE(SELECTARG1);
+ D3DTOP_TO_STR_CASE(SELECTARG2);
+ D3DTOP_TO_STR_CASE(MODULATE);
+ D3DTOP_TO_STR_CASE(MODULATE2X);
+ D3DTOP_TO_STR_CASE(MODULATE4X);
+ D3DTOP_TO_STR_CASE(ADD);
+ D3DTOP_TO_STR_CASE(ADDSIGNED);
+ D3DTOP_TO_STR_CASE(ADDSIGNED2X);
+ D3DTOP_TO_STR_CASE(SUBTRACT);
+ D3DTOP_TO_STR_CASE(ADDSMOOTH);
+ D3DTOP_TO_STR_CASE(BLENDDIFFUSEALPHA);
+ D3DTOP_TO_STR_CASE(BLENDTEXTUREALPHA);
+ D3DTOP_TO_STR_CASE(BLENDFACTORALPHA);
+ D3DTOP_TO_STR_CASE(BLENDTEXTUREALPHAPM);
+ D3DTOP_TO_STR_CASE(BLENDCURRENTALPHA);
+ D3DTOP_TO_STR_CASE(PREMODULATE);
+ D3DTOP_TO_STR_CASE(MODULATEALPHA_ADDCOLOR);
+ D3DTOP_TO_STR_CASE(MODULATECOLOR_ADDALPHA);
+ D3DTOP_TO_STR_CASE(MODULATEINVALPHA_ADDCOLOR);
+ D3DTOP_TO_STR_CASE(MODULATEINVCOLOR_ADDALPHA);
+ D3DTOP_TO_STR_CASE(BUMPENVMAP);
+ D3DTOP_TO_STR_CASE(BUMPENVMAPLUMINANCE);
+ D3DTOP_TO_STR_CASE(DOTPRODUCT3);
+ D3DTOP_TO_STR_CASE(MULTIPLYADD);
+ D3DTOP_TO_STR_CASE(LERP);
+ default:
+ return "(D3DTOP_?)";
+ }
+}
+
+static const char *
+nine_D3DLIGHTTYPE_to_str(D3DLIGHTTYPE type)
+{
+ switch (type) {
+ case D3DLIGHT_POINT: return "POINT";
+ case D3DLIGHT_SPOT: return "SPOT";
+ case D3DLIGHT_DIRECTIONAL: return "DIRECTIONAL";
+ default:
+ return "(D3DLIGHT_?)";
+ }
+}
+
+static const char *
+nine_D3DTA_to_str(DWORD value)
+{
+ switch (value & D3DTA_SELECTMASK) {
+ case D3DTA_DIFFUSE: return "DIFFUSE";
+ case D3DTA_CURRENT: return "CURRENT";
+ case D3DTA_TEXTURE: return "TEXTURE";
+ case D3DTA_TFACTOR: return "TFACTOR";
+ case D3DTA_SPECULAR: return "SPECULAR";
+ case D3DTA_TEMP: return "TEMP";
+ case D3DTA_CONSTANT: return "CONSTANT";
+ default:
+ return "(D3DTA_?)";
+ }
+}
+
+static const char *
+nine_D3DTSS_TCI_to_str(DWORD value)
+{
+ switch (value & 0xf0000) {
+ case D3DTSS_TCI_PASSTHRU: return "PASSTHRU";
+ case D3DTSS_TCI_CAMERASPACENORMAL: return "CAMERASPACENORMAL";
+ case D3DTSS_TCI_CAMERASPACEPOSITION: return "CAMERASPACEPOSITION";
+ case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
+ return "CAMERASPACEREFLECTIONVECTOR";
+ case D3DTSS_TCI_SPHEREMAP: return "SPHEREMAP";
+ default:
+ return "(D3DTSS_TCI_?)";
+ }
+}
+
+static const char *
+nine_D3DTTFF_to_str(DWORD value)
+{
+ switch (value) {
+ case D3DTTFF_DISABLE: return "DISABLE";
+ case D3DTTFF_COUNT1: return "COUNT1";
+ case D3DTTFF_COUNT2: return "COUNT2";
+ case D3DTTFF_COUNT3: return "COUNT3";
+ case D3DTTFF_COUNT4: return "COUNT4";
+ case D3DTTFF_PROJECTED: return "PROJECTED";
+ default:
+ return "(D3DTTFF_?)";
+ }
+}
+
+void
+nine_dump_D3DLIGHT9(unsigned ch, const D3DLIGHT9 *lit)
+{
+ DBG_FLAG(ch, "D3DLIGHT9(%p):\n"
+ "Type: %s\n"
+ "Diffuse: (%f %f %f %f)\n"
+ "Specular: (%f %f %f %f)\n"
+ "Ambient: (%f %f %f %f)\n"
+ "Position: (%f %f %f)\n"
+ "Direction: (%f %f %f)\n"
+ "Range: %f\n"
+ "Falloff: %f\n"
+ "Attenuation: %f + %f * d + %f * d^2\n"
+ "Theta: %f deg\n"
+ "Phi: %f deg\n", lit,
+ nine_D3DLIGHTTYPE_to_str(lit->Type),
+ lit->Diffuse.r,lit->Diffuse.r,lit->Diffuse.g,lit->Diffuse.a,
+ lit->Specular.r,lit->Specular.r,lit->Specular.g,lit->Specular.a,
+ lit->Ambient.r,lit->Ambient.r,lit->Ambient.g,lit->Ambient.a,
+ lit->Position.x,lit->Position.y,lit->Position.z,
+ lit->Direction.x,lit->Direction.y,lit->Direction.z,
+ lit->Range,lit->Falloff,
+ lit->Attenuation0,lit->Attenuation1,lit->Attenuation2,
+ lit->Theta * 360.0f / M_PI,lit->Phi * 360.0f / M_PI);
+}
+
+void
+nine_dump_D3DMATERIAL9(unsigned ch, const D3DMATERIAL9 *mat)
+{
+ DBG_FLAG(ch, "D3DMATERIAL9(%p):\n"
+ "Diffuse: (%f %f %f %f)\n"
+ "Specular: (%f %f %f %f)\n"
+ "Ambient: (%f %f %f %f)\n"
+ "Emissive: (%f %f %f %f)\n"
+ "Power: %f\n", mat,
+ mat->Diffuse.r,mat->Diffuse.r,mat->Diffuse.g,mat->Diffuse.a,
+ mat->Specular.r,mat->Specular.r,mat->Specular.g,mat->Specular.a,
+ mat->Ambient.r,mat->Ambient.r,mat->Ambient.g,mat->Ambient.a,
+ mat->Emissive.r,mat->Emissive.r,mat->Emissive.g,mat->Emissive.a,
+ mat->Power);
+}
+
+void
+nine_dump_D3DTSS_value(unsigned ch, D3DTEXTURESTAGESTATETYPE type, DWORD value)
+{
+ float rgba[4];
+
+ switch (type) {
+ case D3DTSS_COLOROP:
+ case D3DTSS_ALPHAOP:
+ DBG_FLAG(ch, "D3DTSS_%s = %s\n",
+ nine_D3DTSS_to_str(type), nine_D3DTOP_to_str(value));
+ break;
+ case D3DTSS_COLORARG0:
+ case D3DTSS_COLORARG1:
+ case D3DTSS_COLORARG2:
+ case D3DTSS_ALPHAARG0:
+ case D3DTSS_ALPHAARG1:
+ case D3DTSS_ALPHAARG2:
+ case D3DTSS_RESULTARG:
+ DBG_FLAG(ch, "D3DTSS_%s = %s%s%s\n",
+ nine_D3DTSS_to_str(type),
+ (value & D3DTA_COMPLEMENT) ? "COMPLEMENT " : "",
+ (value & D3DTA_ALPHAREPLICATE) ? "ALPHAREPLICATE " : "",
+ nine_D3DTA_to_str(value));
+ break;
+ case D3DTSS_BUMPENVMAT00:
+ case D3DTSS_BUMPENVMAT01:
+ case D3DTSS_BUMPENVMAT10:
+ case D3DTSS_BUMPENVMAT11:
+ case D3DTSS_BUMPENVLSCALE:
+ case D3DTSS_BUMPENVLOFFSET:
+ DBG_FLAG(ch, "D3DTSS_%s = %f\n",
+ nine_D3DTSS_to_str(type), asfloat(value));
+ break;
+ case D3DTSS_TEXCOORDINDEX:
+ DBG_FLAG(ch, "D3DTSS_TEXCOORDINDEX = %s %u\n",
+ nine_D3DTSS_TCI_to_str(value),
+ value & 0xffff);
+ break;
+ case D3DTSS_TEXTURETRANSFORMFLAGS:
+ DBG_FLAG(ch, "D3DTSS_TEXTURETRANSFORMFLAGS = %s\n",
+ nine_D3DTTFF_to_str(value));
+ break;
+ case D3DTSS_CONSTANT:
+ d3dcolor_to_rgba(rgba, value);
+ DBG_FLAG(ch, "D3DTSS_CONSTANT = %f %f %f %F\n",
+ rgba[0],rgba[1],rgba[2],rgba[3]);
+ break;
+ default:
+ DBG_FLAG(ch, "D3DTSS_? = 0x%08x\n", value);
+ break;
+ }
+}
+
+void
+nine_dump_D3DADAPTER_IDENTIFIER9(unsigned ch, const D3DADAPTER_IDENTIFIER9 *id)
+{
+ DBG_FLAG(ch, "D3DADAPTER_IDENTIFIER9(%p):\n"
+ "Driver: %s\n"
+ "Description: %s\n"
+ "DeviceName: %s\n"
+ "DriverVersion: %08x.%08x\n"
+ "VendorId: %x\n"
+ "DeviceId: %x\n"
+ "SubSysId: %x\n"
+ "Revision: %u\n"
+ "GUID: %08x.%04x.%04x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x\n"
+ "WHQLLevel: %u\n", id, id->Driver, id->Description,
+ id->DeviceName,
+ id->DriverVersionLowPart, id->DriverVersionHighPart,
+ id->VendorId, id->DeviceId, id->SubSysId,
+ id->Revision,
+ id->DeviceIdentifier.Data1,
+ id->DeviceIdentifier.Data2,
+ id->DeviceIdentifier.Data3,
+ id->DeviceIdentifier.Data4[0],
+ id->DeviceIdentifier.Data4[1],
+ id->DeviceIdentifier.Data4[2],
+ id->DeviceIdentifier.Data4[3],
+ id->DeviceIdentifier.Data4[4],
+ id->DeviceIdentifier.Data4[5],
+ id->DeviceIdentifier.Data4[6],
+ id->DeviceIdentifier.Data4[7],
+ id->WHQLLevel);
+}
+
+#define C2S(args...) p += snprintf(&s[p],c-p,args)
+
+#define CAP_CASE(m,p,n) \
+ do { \
+ if (caps->m & p##_##n) \
+ C2S(" "#n); \
+ else \
+ C2S(" ("#n")"); \
+ } while(0)
+
+void
+nine_dump_D3DCAPS9(unsigned ch, const D3DCAPS9 *caps)
+{
+ const int c = 1 << 17;
+ int p = 0;
+ char *s = (char *)MALLOC(c);
+
+ if (!s) {
+ DBG_FLAG(ch, "D3DCAPS9(%p): (out of memory)\n", caps);
+ return;
+ }
+
+ C2S("DeviceType: %s\n", nine_D3DDEVTYPE_to_str(caps->DeviceType));
+
+ C2S("AdapterOrdinal: %u\nCaps:", caps->AdapterOrdinal);
+ if (caps->Caps & 0x20000)
+ C2S(" READ_SCANLINE");
+ if (caps->Caps & ~0x20000)
+ C2S(" %x", caps->Caps & ~0x20000);
+
+ C2S("\nCaps2:");
+ CAP_CASE(Caps2, D3DCAPS2, CANAUTOGENMIPMAP);
+ CAP_CASE(Caps2, D3DCAPS2, CANCALIBRATEGAMMA);
+ CAP_CASE(Caps2, D3DCAPS2, CANSHARERESOURCE);
+ CAP_CASE(Caps2, D3DCAPS2, CANMANAGERESOURCE);
+ CAP_CASE(Caps2, D3DCAPS2, DYNAMICTEXTURES);
+ CAP_CASE(Caps2, D3DCAPS2, FULLSCREENGAMMA);
+
+ C2S("\nCaps3:");
+ CAP_CASE(Caps3, D3DCAPS3, ALPHA_FULLSCREEN_FLIP_OR_DISCARD);
+ CAP_CASE(Caps3, D3DCAPS3, COPY_TO_VIDMEM);
+ CAP_CASE(Caps3, D3DCAPS3, COPY_TO_SYSTEMMEM);
+ CAP_CASE(Caps3, D3DCAPS3, DXVAHD);
+ CAP_CASE(Caps3, D3DCAPS3, LINEAR_TO_SRGB_PRESENTATION);
+
+ C2S("\nPresentationIntervals:");
+ CAP_CASE(PresentationIntervals, D3DPRESENT_INTERVAL, ONE);
+ CAP_CASE(PresentationIntervals, D3DPRESENT_INTERVAL, TWO);
+ CAP_CASE(PresentationIntervals, D3DPRESENT_INTERVAL, THREE);
+ CAP_CASE(PresentationIntervals, D3DPRESENT_INTERVAL, FOUR);
+ CAP_CASE(PresentationIntervals, D3DPRESENT_INTERVAL, IMMEDIATE);
+
+ C2S("\nCursorCaps:");
+ CAP_CASE(CursorCaps, D3DCURSORCAPS, COLOR);
+ CAP_CASE(CursorCaps, D3DCURSORCAPS, LOWRES);
+
+ C2S("\nDevCaps:");
+ CAP_CASE(DevCaps, D3DDEVCAPS, CANBLTSYSTONONLOCAL);
+ CAP_CASE(DevCaps, D3DDEVCAPS, CANRENDERAFTERFLIP);
+ CAP_CASE(DevCaps, D3DDEVCAPS, DRAWPRIMITIVES2);
+ CAP_CASE(DevCaps, D3DDEVCAPS, DRAWPRIMITIVES2EX);
+ CAP_CASE(DevCaps, D3DDEVCAPS, DRAWPRIMTLVERTEX);
+ CAP_CASE(DevCaps, D3DDEVCAPS, EXECUTESYSTEMMEMORY);
+ CAP_CASE(DevCaps, D3DDEVCAPS, EXECUTEVIDEOMEMORY);
+ CAP_CASE(DevCaps, D3DDEVCAPS, HWRASTERIZATION);
+ CAP_CASE(DevCaps, D3DDEVCAPS, HWTRANSFORMANDLIGHT);
+ CAP_CASE(DevCaps, D3DDEVCAPS, NPATCHES);
+ CAP_CASE(DevCaps, D3DDEVCAPS, PUREDEVICE);
+ CAP_CASE(DevCaps, D3DDEVCAPS, QUINTICRTPATCHES);
+ CAP_CASE(DevCaps, D3DDEVCAPS, RTPATCHES);
+ CAP_CASE(DevCaps, D3DDEVCAPS, RTPATCHHANDLEZERO);
+ CAP_CASE(DevCaps, D3DDEVCAPS, SEPARATETEXTUREMEMORIES);
+ CAP_CASE(DevCaps, D3DDEVCAPS, TEXTURENONLOCALVIDMEM);
+ CAP_CASE(DevCaps, D3DDEVCAPS, TEXTURESYSTEMMEMORY);
+ CAP_CASE(DevCaps, D3DDEVCAPS, TEXTUREVIDEOMEMORY);
+ CAP_CASE(DevCaps, D3DDEVCAPS, TLVERTEXSYSTEMMEMORY);
+ CAP_CASE(DevCaps, D3DDEVCAPS, TLVERTEXVIDEOMEMORY);
+
+ C2S("\nPrimitiveMiscCaps:");
+ CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, MASKZ);
+ CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, CULLNONE);
+ CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, CULLCW);
+ CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, CULLCCW);
+ CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, COLORWRITEENABLE);
+ CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, CLIPPLANESCALEDPOINTS);
+ CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, CLIPTLVERTS);
+ CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, TSSARGTEMP);
+ CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, BLENDOP);
+ CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, NULLREFERENCE);
+ CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, INDEPENDENTWRITEMASKS);
+ CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, PERSTAGECONSTANT);
+ CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, POSTBLENDSRGBCONVERT);
+ CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, FOGANDSPECULARALPHA);
+ CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, SEPARATEALPHABLEND);
+ CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, MRTINDEPENDENTBITDEPTHS);
+ CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, MRTPOSTPIXELSHADERBLENDING);
+ CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, FOGVERTEXCLAMPED);
+
+ C2S("\nRasterCaps:");
+ CAP_CASE(RasterCaps, D3DPRASTERCAPS, ANISOTROPY);
+ CAP_CASE(RasterCaps, D3DPRASTERCAPS, COLORPERSPECTIVE);
+ CAP_CASE(RasterCaps, D3DPRASTERCAPS, DITHER);
+ CAP_CASE(RasterCaps, D3DPRASTERCAPS, DEPTHBIAS);
+ CAP_CASE(RasterCaps, D3DPRASTERCAPS, FOGRANGE);
+ CAP_CASE(RasterCaps, D3DPRASTERCAPS, FOGTABLE);
+ CAP_CASE(RasterCaps, D3DPRASTERCAPS, FOGVERTEX);
+ CAP_CASE(RasterCaps, D3DPRASTERCAPS, MIPMAPLODBIAS);
+ CAP_CASE(RasterCaps, D3DPRASTERCAPS, MULTISAMPLE_TOGGLE);
+ CAP_CASE(RasterCaps, D3DPRASTERCAPS, SCISSORTEST);
+ CAP_CASE(RasterCaps, D3DPRASTERCAPS, SLOPESCALEDEPTHBIAS);
+ CAP_CASE(RasterCaps, D3DPRASTERCAPS, WBUFFER);
+ CAP_CASE(RasterCaps, D3DPRASTERCAPS, WFOG);
+ CAP_CASE(RasterCaps, D3DPRASTERCAPS, ZBUFFERLESSHSR);
+ CAP_CASE(RasterCaps, D3DPRASTERCAPS, ZFOG);
+ CAP_CASE(RasterCaps, D3DPRASTERCAPS, ZTEST);
+
+ C2S("\nZCmpCaps:");
+ CAP_CASE(ZCmpCaps, D3DPCMPCAPS, ALWAYS);
+ CAP_CASE(ZCmpCaps, D3DPCMPCAPS, EQUAL);
+ CAP_CASE(ZCmpCaps, D3DPCMPCAPS, GREATER);
+ CAP_CASE(ZCmpCaps, D3DPCMPCAPS, GREATEREQUAL);
+ CAP_CASE(ZCmpCaps, D3DPCMPCAPS, LESS);
+ CAP_CASE(ZCmpCaps, D3DPCMPCAPS, LESSEQUAL);
+ CAP_CASE(ZCmpCaps, D3DPCMPCAPS, NEVER);
+ CAP_CASE(ZCmpCaps, D3DPCMPCAPS, NOTEQUAL);
+
+ C2S("\nSrcBlendCaps");
+ CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, BLENDFACTOR);
+ CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, BOTHINVSRCALPHA);
+ CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, BOTHSRCALPHA);
+ CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, DESTALPHA);
+ CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, DESTCOLOR);
+ CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, INVDESTALPHA);
+ CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, INVDESTCOLOR);
+ CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, INVSRCALPHA);
+ CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, INVSRCCOLOR);
+ CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, INVSRCCOLOR2);
+ CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, ONE);
+ CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, SRCALPHA);
+ CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, SRCALPHASAT);
+ CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, SRCCOLOR);
+ CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, SRCCOLOR2);
+ CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, ZERO);
+
+ C2S("\nDestBlendCaps");
+ CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, BLENDFACTOR);
+ CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, BOTHINVSRCALPHA);
+ CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, BOTHSRCALPHA);
+ CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, DESTALPHA);
+ CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, DESTCOLOR);
+ CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, INVDESTALPHA);
+ CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, INVDESTCOLOR);
+ CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, INVSRCALPHA);
+ CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, INVSRCCOLOR);
+ CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, INVSRCCOLOR2);
+ CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, ONE);
+ CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, SRCALPHA);
+ CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, SRCALPHASAT);
+ CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, SRCCOLOR);
+ CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, SRCCOLOR2);
+ CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, ZERO);
+
+ C2S("\nAlphaCmpCaps:");
+ CAP_CASE(AlphaCmpCaps, D3DPCMPCAPS, ALWAYS);
+ CAP_CASE(AlphaCmpCaps, D3DPCMPCAPS, EQUAL);
+ CAP_CASE(AlphaCmpCaps, D3DPCMPCAPS, GREATER);
+ CAP_CASE(AlphaCmpCaps, D3DPCMPCAPS, GREATEREQUAL);
+ CAP_CASE(AlphaCmpCaps, D3DPCMPCAPS, LESS);
+ CAP_CASE(AlphaCmpCaps, D3DPCMPCAPS, LESSEQUAL);
+ CAP_CASE(AlphaCmpCaps, D3DPCMPCAPS, NEVER);
+ CAP_CASE(AlphaCmpCaps, D3DPCMPCAPS, NOTEQUAL);
+
+ C2S("\nShadeCaps:");
+ CAP_CASE(ShadeCaps, D3DPSHADECAPS, ALPHAGOURAUDBLEND);
+ CAP_CASE(ShadeCaps, D3DPSHADECAPS, COLORGOURAUDRGB);
+ CAP_CASE(ShadeCaps, D3DPSHADECAPS, FOGGOURAUD);
+ CAP_CASE(ShadeCaps, D3DPSHADECAPS, SPECULARGOURAUDRGB);
+
+ C2S("\nTextureCaps:");
+ CAP_CASE(TextureCaps, D3DPTEXTURECAPS, ALPHA);
+ CAP_CASE(TextureCaps, D3DPTEXTURECAPS, ALPHAPALETTE);
+ CAP_CASE(TextureCaps, D3DPTEXTURECAPS, CUBEMAP);
+ CAP_CASE(TextureCaps, D3DPTEXTURECAPS, CUBEMAP_POW2);
+ CAP_CASE(TextureCaps, D3DPTEXTURECAPS, MIPCUBEMAP);
+ CAP_CASE(TextureCaps, D3DPTEXTURECAPS, MIPMAP);
+ CAP_CASE(TextureCaps, D3DPTEXTURECAPS, MIPVOLUMEMAP);
+ CAP_CASE(TextureCaps, D3DPTEXTURECAPS, NONPOW2CONDITIONAL);
+ CAP_CASE(TextureCaps, D3DPTEXTURECAPS, NOPROJECTEDBUMPENV);
+ CAP_CASE(TextureCaps, D3DPTEXTURECAPS, PERSPECTIVE);
+ CAP_CASE(TextureCaps, D3DPTEXTURECAPS, POW2);
+ CAP_CASE(TextureCaps, D3DPTEXTURECAPS, PROJECTED);
+ CAP_CASE(TextureCaps, D3DPTEXTURECAPS, SQUAREONLY);
+ CAP_CASE(TextureCaps, D3DPTEXTURECAPS, TEXREPEATNOTSCALEDBYSIZE);
+ CAP_CASE(TextureCaps, D3DPTEXTURECAPS, VOLUMEMAP);
+ CAP_CASE(TextureCaps, D3DPTEXTURECAPS, VOLUMEMAP_POW2);
+
+ C2S("\nTextureFilterCaps:");
+ /* CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, CONVOLUTIONMONO); */
+ CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MAGFPOINT);
+ CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MAGFLINEAR);
+ CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MAGFANISOTROPIC);
+ CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MAGFPYRAMIDALQUAD);
+ CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MAGFGAUSSIANQUAD);
+ CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MINFPOINT);
+ CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MINFLINEAR);
+ CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MINFANISOTROPIC);
+ CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MINFPYRAMIDALQUAD);
+ CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MINFGAUSSIANQUAD);
+ CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MIPFPOINT);
+ CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MIPFLINEAR);
+
+ C2S("\nCubeTextureFilterCaps:");
+ /* CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, CONVOLUTIONMONO); */
+ CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MAGFPOINT);
+ CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MAGFLINEAR);
+ CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MAGFANISOTROPIC);
+ CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MAGFPYRAMIDALQUAD);
+ CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MAGFGAUSSIANQUAD);
+ CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MINFPOINT);
+ CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MINFLINEAR);
+ CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MINFANISOTROPIC);
+ CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MINFPYRAMIDALQUAD);
+ CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MINFGAUSSIANQUAD);
+ CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MIPFPOINT);
+ CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MIPFLINEAR);
+
+ C2S("\nVolumeTextureFilterCaps:");
+ /* CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, CONVOLUTIONMONO); */
+ CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MAGFPOINT);
+ CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MAGFLINEAR);
+ CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MAGFANISOTROPIC);
+ CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MAGFPYRAMIDALQUAD);
+ CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MAGFGAUSSIANQUAD);
+ CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MINFPOINT);
+ CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MINFLINEAR);
+ CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MINFANISOTROPIC);
+ CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MINFPYRAMIDALQUAD);
+ CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MINFGAUSSIANQUAD);
+ CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MIPFPOINT);
+ CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MIPFLINEAR);
+
+ C2S("\nTextureAddressCaps:");
+ CAP_CASE(TextureAddressCaps, D3DPTADDRESSCAPS, BORDER);
+ CAP_CASE(TextureAddressCaps, D3DPTADDRESSCAPS, CLAMP);
+ CAP_CASE(TextureAddressCaps, D3DPTADDRESSCAPS, INDEPENDENTUV);
+ CAP_CASE(TextureAddressCaps, D3DPTADDRESSCAPS, MIRROR);
+ CAP_CASE(TextureAddressCaps, D3DPTADDRESSCAPS, MIRRORONCE);
+ CAP_CASE(TextureAddressCaps, D3DPTADDRESSCAPS, WRAP);
+
+ C2S("\nVolumeTextureAddressCaps:");
+ CAP_CASE(VolumeTextureAddressCaps, D3DPTADDRESSCAPS, BORDER);
+ CAP_CASE(VolumeTextureAddressCaps, D3DPTADDRESSCAPS, CLAMP);
+ CAP_CASE(VolumeTextureAddressCaps, D3DPTADDRESSCAPS, INDEPENDENTUV);
+ CAP_CASE(VolumeTextureAddressCaps, D3DPTADDRESSCAPS, MIRROR);
+ CAP_CASE(VolumeTextureAddressCaps, D3DPTADDRESSCAPS, MIRRORONCE);
+ CAP_CASE(VolumeTextureAddressCaps, D3DPTADDRESSCAPS, WRAP);
+
+ C2S("\nLineCaps:");
+ CAP_CASE(LineCaps, D3DLINECAPS, ALPHACMP);
+ CAP_CASE(LineCaps, D3DLINECAPS, ANTIALIAS);
+ CAP_CASE(LineCaps, D3DLINECAPS, BLEND);
+ CAP_CASE(LineCaps, D3DLINECAPS, FOG);
+ CAP_CASE(LineCaps, D3DLINECAPS, TEXTURE);
+ CAP_CASE(LineCaps, D3DLINECAPS, ZTEST);
+
+ C2S("\nMaxTextureWidth: %u", caps->MaxTextureWidth);
+ C2S("\nMaxTextureHeight: %u", caps->MaxTextureHeight);
+ C2S("\nMaxVolumeExtent: %u", caps->MaxVolumeExtent);
+ C2S("\nMaxTextureRepeat: %u", caps->MaxTextureRepeat);
+ C2S("\nMaxTextureAspectRatio: %u", caps->MaxTextureAspectRatio);
+ C2S("\nMaxAnisotropy: %u", caps->MaxAnisotropy);
+ C2S("\nMaxVertexW: %f", caps->MaxVertexW);
+
+ C2S("\nGuardBandLef,Top,Right,Bottom: %f %f %f %f",
+ caps->GuardBandLeft, caps->GuardBandTop,
+ caps->GuardBandRight, caps->GuardBandBottom);
+
+ C2S("\nExtentsAdjust: %f", caps->ExtentsAdjust);
+
+ C2S("\nStencilCaps:");
+ CAP_CASE(StencilCaps, D3DSTENCILCAPS, KEEP);
+ CAP_CASE(StencilCaps, D3DSTENCILCAPS, ZERO);
+ CAP_CASE(StencilCaps, D3DSTENCILCAPS, REPLACE);
+ CAP_CASE(StencilCaps, D3DSTENCILCAPS, INCRSAT);
+ CAP_CASE(StencilCaps, D3DSTENCILCAPS, DECRSAT);
+ CAP_CASE(StencilCaps, D3DSTENCILCAPS, INVERT);
+ CAP_CASE(StencilCaps, D3DSTENCILCAPS, INCR);
+ CAP_CASE(StencilCaps, D3DSTENCILCAPS, DECR);
+ CAP_CASE(StencilCaps, D3DSTENCILCAPS, TWOSIDED);
+
+ C2S("\nFVFCaps:");
+ CAP_CASE(FVFCaps, D3DFVFCAPS, DONOTSTRIPELEMENTS);
+ CAP_CASE(FVFCaps, D3DFVFCAPS, PSIZE);
+ CAP_CASE(FVFCaps, D3DFVFCAPS, TEXCOORDCOUNTMASK);
+
+ C2S("\nTextureOpCaps:");
+ CAP_CASE(TextureOpCaps, D3DTEXOPCAPS, ADD);
+ CAP_CASE(TextureOpCaps, D3DTEXOPCAPS, ADDSIGNED);
+ C2S(" ...");
+
+ C2S("\nMaxTextureBlendStages: %u", caps->MaxTextureBlendStages);
+ C2S("\nMaxSimultaneousTextures: %u", caps->MaxTextureBlendStages);
+
+ C2S("\nVertexProcessingCaps:");
+ CAP_CASE(VertexProcessingCaps, D3DVTXPCAPS, DIRECTIONALLIGHTS);
+ CAP_CASE(VertexProcessingCaps, D3DVTXPCAPS, LOCALVIEWER);
+ CAP_CASE(VertexProcessingCaps, D3DVTXPCAPS, MATERIALSOURCE7);
+ CAP_CASE(VertexProcessingCaps, D3DVTXPCAPS, NO_TEXGEN_NONLOCALVIEWER);
+ CAP_CASE(VertexProcessingCaps, D3DVTXPCAPS, POSITIONALLIGHTS);
+ CAP_CASE(VertexProcessingCaps, D3DVTXPCAPS, TEXGEN);
+ CAP_CASE(VertexProcessingCaps, D3DVTXPCAPS, TEXGEN_SPHEREMAP);
+ CAP_CASE(VertexProcessingCaps, D3DVTXPCAPS, TWEENING);
+
+ C2S("\nMaxActiveLights: %u", caps->MaxActiveLights);
+ C2S("\nMaxUserClipPlanes: %u", caps->MaxUserClipPlanes);
+ C2S("\nMaxVertexBlendMatrices: %u", caps->MaxVertexBlendMatrices);
+ C2S("\nMaxVertexBlendMatrixIndex: %u", caps->MaxVertexBlendMatrixIndex);
+ C2S("\nMaxPointSize: %f", caps->MaxPointSize);
+ C2S("\nMaxPrimitiveCount: 0x%x", caps->MaxPrimitiveCount);
+ C2S("\nMaxVertexIndex: 0x%x", caps->MaxVertexIndex);
+ C2S("\nMaxStreams: %u", caps->MaxStreams);
+ C2S("\nMaxStreamStride: 0x%x", caps->MaxStreamStride);
+
+ C2S("\nVertexShaderVersion: %08x", caps->VertexShaderVersion);
+ C2S("\nMaxVertexShaderConst: %u", caps->MaxVertexShaderConst);
+ C2S("\nPixelShaderVersion: %08x", caps->PixelShaderVersion);
+ C2S("\nPixelShader1xMaxValue: %f", caps->PixelShader1xMaxValue);
+
+ DBG_FLAG(ch, "D3DCAPS9(%p) part 1:\n%s\n", caps, s);
+ p = 0;
+
+ C2S("DevCaps2:");
+ CAP_CASE(DevCaps2, D3DDEVCAPS2, ADAPTIVETESSRTPATCH);
+ CAP_CASE(DevCaps2, D3DDEVCAPS2, ADAPTIVETESSNPATCH);
+ CAP_CASE(DevCaps2, D3DDEVCAPS2, CAN_STRETCHRECT_FROM_TEXTURES);
+ CAP_CASE(DevCaps2, D3DDEVCAPS2, DMAPNPATCH);
+ CAP_CASE(DevCaps2, D3DDEVCAPS2, PRESAMPLEDDMAPNPATCH);
+ CAP_CASE(DevCaps2, D3DDEVCAPS2, STREAMOFFSET);
+ CAP_CASE(DevCaps2, D3DDEVCAPS2, VERTEXELEMENTSCANSHARESTREAMOFFSET);
+
+ C2S("\nMasterAdapterOrdinal: %u", caps->MasterAdapterOrdinal);
+ C2S("\nAdapterOrdinalInGroup: %u", caps->AdapterOrdinalInGroup);
+ C2S("\nNumberOfAdaptersInGroup: %u", caps->NumberOfAdaptersInGroup);
+
+ C2S("\nDeclTypes:");
+ CAP_CASE(DeclTypes, D3DDTCAPS, UBYTE4);
+ CAP_CASE(DeclTypes, D3DDTCAPS, UBYTE4N);
+ CAP_CASE(DeclTypes, D3DDTCAPS, SHORT2N);
+ CAP_CASE(DeclTypes, D3DDTCAPS, SHORT4N);
+ CAP_CASE(DeclTypes, D3DDTCAPS, USHORT2N);
+ CAP_CASE(DeclTypes, D3DDTCAPS, USHORT4N);
+ CAP_CASE(DeclTypes, D3DDTCAPS, UDEC3);
+ CAP_CASE(DeclTypes, D3DDTCAPS, DEC3N);
+ CAP_CASE(DeclTypes, D3DDTCAPS, FLOAT16_2);
+ CAP_CASE(DeclTypes, D3DDTCAPS, FLOAT16_4);
+
+ C2S("\nNumSimultaneousRTs: %u", caps->NumSimultaneousRTs);
+
+ C2S("\nStretchRectFilterCaps:");
+ CAP_CASE(StretchRectFilterCaps, D3DPTFILTERCAPS, MINFPOINT);
+ CAP_CASE(StretchRectFilterCaps, D3DPTFILTERCAPS, MINFLINEAR);
+ CAP_CASE(StretchRectFilterCaps, D3DPTFILTERCAPS, MAGFPOINT);
+ CAP_CASE(StretchRectFilterCaps, D3DPTFILTERCAPS, MAGFLINEAR);
+
+ C2S("\nVS20Caps.Caps: Predication=%s", caps->VS20Caps.Caps ? "yes" : "no");
+ C2S("\nVS20Caps.DynamicFlowControlDepth: %u", caps->VS20Caps.DynamicFlowControlDepth);
+ C2S("\nVS20Caps.NumTemps: %u", caps->VS20Caps.NumTemps);
+ C2S("\nVS20Caps.StaticFlowControlDepth: %u", caps->VS20Caps.StaticFlowControlDepth);
+
+ C2S("\nPS20Caps.Caps: Predication=%s", caps->VS20Caps.Caps ? "yes" : "no");
+ C2S("\nPS20Caps.DynamicFlowControlDepth: %u", caps->PS20Caps.DynamicFlowControlDepth);
+ C2S("\nPS20Caps.NumTemps: %u", caps->PS20Caps.NumTemps);
+ C2S("\nPS20Caps.StaticFlowControlDepth: %u", caps->PS20Caps.StaticFlowControlDepth);
+ C2S("\nPS20Caps.NumInstructionSlots: %u", caps->PS20Caps.NumInstructionSlots);
+
+ C2S("\nVertexTextureFilterCaps");
+ /* CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, CONVOLUTIONMONO); */
+ CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MAGFPOINT);
+ CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MAGFLINEAR);
+ CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MAGFANISOTROPIC);
+ CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MAGFPYRAMIDALQUAD);
+ CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MAGFGAUSSIANQUAD);
+ CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MINFPOINT);
+ CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MINFLINEAR);
+ CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MINFANISOTROPIC);
+ CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MINFPYRAMIDALQUAD);
+ CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MINFGAUSSIANQUAD);
+ CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MIPFPOINT);
+ CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MIPFLINEAR);
+
+ C2S("\nMaxVShaderInstructionsExecuted: %u", caps->MaxVShaderInstructionsExecuted);
+ C2S("\nMaxPShaderInstructionsExecuted: %u", caps->MaxPShaderInstructionsExecuted);
+ C2S("\nMaxVertexShader30InstructionSlots: %u >= 512", caps->MaxVertexShader30InstructionSlots);
+ C2S("\nMaxPixelShader30InstructionSlots: %u >= 512", caps->MaxPixelShader30InstructionSlots);
+
+ DBG_FLAG(ch, "D3DCAPS9(%p) part 2:\n%s\n", caps, s);
+
+ FREE(s);
+}
+
+#endif /* DEBUG */
diff --git a/src/gallium/state_trackers/nine/nine_dump.h b/src/gallium/state_trackers/nine/nine_dump.h
new file mode 100644
index 00000000000..d0d4a9eb3aa
--- /dev/null
+++ b/src/gallium/state_trackers/nine/nine_dump.h
@@ -0,0 +1,52 @@
+
+#ifndef _NINE_DUMP_H_
+#define _NINE_DUMP_H_
+
+#include "d3d9types.h"
+#include "d3d9caps.h"
+
+const char *nine_D3DDEVTYPE_to_str(D3DDEVTYPE);
+const char *nine_D3DQUERYTYPE_to_str(D3DQUERYTYPE);
+const char *nine_D3DTSS_to_str(D3DTEXTURESTAGESTATETYPE);
+const char *nine_D3DTOP_to_str(D3DTEXTUREOP);
+const char *nine_D3DPOOL_to_str(D3DPOOL);
+const char *nine_D3DRTYPE_to_str(D3DRESOURCETYPE);
+const char *nine_D3DUSAGE_to_str(DWORD);
+const char *nine_D3DPRESENTFLAG_to_str(DWORD);
+const char *nine_D3DLOCK_to_str(DWORD);
+const char *nine_D3DSAMP_to_str(DWORD);
+
+#ifdef DEBUG
+
+void
+nine_dump_D3DADAPTER_IDENTIFIER9(unsigned, const D3DADAPTER_IDENTIFIER9 *);
+void
+nine_dump_D3DCAPS9(unsigned, const D3DCAPS9 *);
+void
+nine_dump_D3DLIGHT9(unsigned, const D3DLIGHT9 *);
+void
+nine_dump_D3DMATERIAL9(unsigned, const D3DMATERIAL9 *);
+void
+nine_dump_D3DTSS_value(unsigned, D3DTEXTURESTAGESTATETYPE, DWORD);
+
+#else /* !DEBUG */
+
+static INLINE void
+nine_dump_D3DADAPTER_IDENTIFIER9(unsigned ch, const D3DADAPTER_IDENTIFIER9 *id)
+{ }
+static INLINE void
+nine_dump_D3DCAPS9(unsigned ch, const D3DCAPS9 *caps)
+{ }
+static INLINE void
+nine_dump_D3DLIGHT9(unsigned ch, const D3DLIGHT9 *light)
+{ }
+static INLINE void
+nine_dump_D3DMATERIAL9(unsigned ch, const D3DMATERIAL9 *mat)
+{ }
+static INLINE void
+nine_dump_D3DTSS_value(unsigned ch, D3DTEXTURESTAGESTATETYPE tss, DWORD value)
+{ }
+
+#endif /* DEBUG */
+
+#endif /* _NINE_DUMP_H_H_ */
diff --git a/src/gallium/state_trackers/nine/nine_ff.c b/src/gallium/state_trackers/nine/nine_ff.c
new file mode 100644
index 00000000000..689093319a5
--- /dev/null
+++ b/src/gallium/state_trackers/nine/nine_ff.c
@@ -0,0 +1,2257 @@
+
+/* FF is big and ugly so feel free to write lines as long as you like.
+ * Aieeeeeeeee !
+ *
+ * Let me make that clearer:
+ * Aieeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee ! !! !!!
+ */
+
+#include "device9.h"
+#include "basetexture9.h"
+#include "vertexdeclaration9.h"
+#include "vertexshader9.h"
+#include "pixelshader9.h"
+#include "nine_ff.h"
+#include "nine_defines.h"
+#include "nine_helpers.h"
+#include "nine_pipe.h"
+#include "nine_dump.h"
+
+#include "pipe/p_context.h"
+#include "tgsi/tgsi_ureg.h"
+#include "tgsi/tgsi_dump.h"
+#include "util/u_box.h"
+#include "util/u_hash_table.h"
+
+#define NINE_TGSI_LAZY_DEVS 1
+
+#define DBG_CHANNEL DBG_FF
+
+#define NINE_FF_NUM_VS_CONST 256
+#define NINE_FF_NUM_PS_CONST 24
+
+#define NINED3DTSS_TCI_DISABLE 0
+#define NINED3DTSS_TCI_PASSTHRU 1
+#define NINED3DTSS_TCI_CAMERASPACENORMAL 2
+#define NINED3DTSS_TCI_CAMERASPACEPOSITION 3
+#define NINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR 4
+#define NINED3DTSS_TCI_SPHEREMAP 5
+
+struct fvec4
+{
+ float x, y, z, w;
+};
+
+struct nine_ff_vs_key
+{
+ union {
+ struct {
+ uint32_t position_t : 1;
+ uint32_t lighting : 1;
+ uint32_t darkness : 1; /* lighting enabled but no active lights */
+ uint32_t localviewer : 1;
+ uint32_t vertexpointsize : 1;
+ uint32_t pointscale : 1;
+ uint32_t vertexblend : 3;
+ uint32_t vertexblend_indexed : 1;
+ uint32_t vertextween : 1;
+ uint32_t mtl_diffuse : 2; /* 0 = material, 1 = color1, 2 = color2 */
+ uint32_t mtl_ambient : 2;
+ uint32_t mtl_specular : 2;
+ uint32_t mtl_emissive : 2;
+ uint32_t fog_mode : 2;
+ uint32_t fog_range : 1;
+ uint32_t color0in_one : 1;
+ uint32_t color1in_one : 1;
+ uint32_t pad1 : 8;
+ uint32_t tc_gen : 24; /* 8 * 3 bits */
+ uint32_t pad2 : 8;
+ uint32_t tc_idx : 24;
+ uint32_t pad3 : 8;
+ uint32_t tc_dim : 24; /* 8 * 3 bits */
+ uint32_t pad4 : 8;
+ };
+ uint64_t value64[2]; /* don't forget to resize VertexShader9.ff_key */
+ uint32_t value32[4];
+ };
+};
+
+/* Texture stage state:
+ *
+ * COLOROP D3DTOP 5 bit
+ * ALPHAOP D3DTOP 5 bit
+ * COLORARG0 D3DTA 3 bit
+ * COLORARG1 D3DTA 3 bit
+ * COLORARG2 D3DTA 3 bit
+ * ALPHAARG0 D3DTA 3 bit
+ * ALPHAARG1 D3DTA 3 bit
+ * ALPHAARG2 D3DTA 3 bit
+ * RESULTARG D3DTA 1 bit (CURRENT:0 or TEMP:1)
+ * TEXCOORDINDEX 0 - 7 3 bit
+ * ===========================
+ * 32 bit per stage
+ */
+struct nine_ff_ps_key
+{
+ union {
+ struct {
+ struct {
+ uint32_t colorop : 5;
+ uint32_t alphaop : 5;
+ uint32_t colorarg0 : 3;
+ uint32_t colorarg1 : 3;
+ uint32_t colorarg2 : 3;
+ uint32_t alphaarg0 : 3;
+ uint32_t alphaarg1 : 3;
+ uint32_t alphaarg2 : 3;
+ uint32_t resultarg : 1; /* CURRENT:0 or TEMP:1 */
+ uint32_t textarget : 2; /* 1D/2D/3D/CUBE */
+ uint32_t projected : 1;
+ /* that's 32 bit exactly */
+ } ts[8];
+ uint32_t fog : 1; /* for vFog with programmable VS */
+ uint32_t fog_mode : 2;
+ uint32_t specular : 1; /* 9 32-bit words with this */
+ uint8_t colorarg_b4[3];
+ uint8_t colorarg_b5[3];
+ uint8_t alphaarg_b4[3]; /* 11 32-bit words plus a byte */
+ };
+ uint64_t value64[6]; /* don't forget to resize PixelShader9.ff_key */
+ uint32_t value32[12];
+ };
+};
+
+static unsigned nine_ff_vs_key_hash(void *key)
+{
+ struct nine_ff_vs_key *vs = key;
+ unsigned i;
+ uint32_t hash = vs->value32[0];
+ for (i = 1; i < Elements(vs->value32); ++i)
+ hash ^= vs->value32[i];
+ return hash;
+}
+static int nine_ff_vs_key_comp(void *key1, void *key2)
+{
+ struct nine_ff_vs_key *a = (struct nine_ff_vs_key *)key1;
+ struct nine_ff_vs_key *b = (struct nine_ff_vs_key *)key2;
+
+ return memcmp(a->value64, b->value64, sizeof(a->value64));
+}
+static unsigned nine_ff_ps_key_hash(void *key)
+{
+ struct nine_ff_ps_key *ps = key;
+ unsigned i;
+ uint32_t hash = ps->value32[0];
+ for (i = 1; i < Elements(ps->value32); ++i)
+ hash ^= ps->value32[i];
+ return hash;
+}
+static int nine_ff_ps_key_comp(void *key1, void *key2)
+{
+ struct nine_ff_ps_key *a = (struct nine_ff_ps_key *)key1;
+ struct nine_ff_ps_key *b = (struct nine_ff_ps_key *)key2;
+
+ return memcmp(a->value64, b->value64, sizeof(a->value64));
+}
+static unsigned nine_ff_fvf_key_hash(void *key)
+{
+ return *(DWORD *)key;
+}
+static int nine_ff_fvf_key_comp(void *key1, void *key2)
+{
+ return *(DWORD *)key1 != *(DWORD *)key2;
+}
+
+static void nine_ff_prune_vs(struct NineDevice9 *);
+static void nine_ff_prune_ps(struct NineDevice9 *);
+
+static void nine_ureg_tgsi_dump(struct ureg_program *ureg, boolean override)
+{
+ if (debug_get_bool_option("NINE_FF_DUMP", FALSE) || override) {
+ unsigned count;
+ const struct tgsi_token *toks = ureg_get_tokens(ureg, &count);
+ tgsi_dump(toks, 0);
+ ureg_free_tokens(toks);
+ }
+}
+
+#define _X(r) ureg_scalar(ureg_src(r), TGSI_SWIZZLE_X)
+#define _Y(r) ureg_scalar(ureg_src(r), TGSI_SWIZZLE_Y)
+#define _Z(r) ureg_scalar(ureg_src(r), TGSI_SWIZZLE_Z)
+#define _W(r) ureg_scalar(ureg_src(r), TGSI_SWIZZLE_W)
+
+#define _XXXX(r) ureg_scalar(r, TGSI_SWIZZLE_X)
+#define _YYYY(r) ureg_scalar(r, TGSI_SWIZZLE_Y)
+#define _ZZZZ(r) ureg_scalar(r, TGSI_SWIZZLE_Z)
+#define _WWWW(r) ureg_scalar(r, TGSI_SWIZZLE_W)
+
+#define _XYZW(r) (r)
+
+/* AL should contain base address of lights table. */
+#define LIGHT_CONST(i) \
+ ureg_src_indirect(ureg_src_register(TGSI_FILE_CONSTANT, (i)), _X(AL))
+
+#define MATERIAL_CONST(i) \
+ ureg_src_register(TGSI_FILE_CONSTANT, 19 + (i))
+
+#define MISC_CONST(i) \
+ ureg_src_register(TGSI_FILE_CONSTANT, (i))
+
+#define _CONST(n) ureg_DECL_constant(ureg, n)
+
+/* VS FF constants layout:
+ *
+ * CONST[ 0.. 3] D3DTS_WORLD * D3DTS_VIEW * D3DTS_PROJECTION
+ * CONST[ 4.. 7] D3DTS_WORLD * D3DTS_VIEW
+ * CONST[ 8..11] D3DTS_VIEW * D3DTS_PROJECTION
+ * CONST[12..15] D3DTS_VIEW
+ * CONST[16..18] Normal matrix
+ *
+ * CONST[19] MATERIAL.Emissive + Material.Ambient * RS.Ambient
+ * CONST[20] MATERIAL.Diffuse
+ * CONST[21] MATERIAL.Ambient
+ * CONST[22] MATERIAL.Specular
+ * CONST[23].x___ MATERIAL.Power
+ * CONST[24] MATERIAL.Emissive
+ * CONST[25] RS.Ambient
+ *
+ * CONST[26].x___ RS.PointSizeMin
+ * CONST[26]._y__ RS.PointSizeMax
+ * CONST[26].__z_ RS.PointSize
+ * CONST[26].___w RS.PointScaleA
+ * CONST[27].x___ RS.PointScaleB
+ * CONST[27]._y__ RS.PointScaleC
+ *
+ * CONST[28].x___ RS.FogEnd
+ * CONST[28]._y__ 1.0f / (RS.FogEnd - RS.FogStart)
+ * CONST[28].__z_ RS.FogDensity
+ * CONST[29] RS.FogColor
+
+ * CONST[30].x___ TWEENFACTOR
+ *
+ * CONST[32].x___ LIGHT[0].Type
+ * CONST[32]._yzw LIGHT[0].Attenuation0,1,2
+ * CONST[33] LIGHT[0].Diffuse
+ * CONST[34] LIGHT[0].Specular
+ * CONST[35] LIGHT[0].Ambient
+ * CONST[36].xyz_ LIGHT[0].Position
+ * CONST[36].___w LIGHT[0].Range
+ * CONST[37].xyz_ LIGHT[0].Direction
+ * CONST[37].___w LIGHT[0].Falloff
+ * CONST[38].x___ cos(LIGHT[0].Theta / 2)
+ * CONST[38]._y__ cos(LIGHT[0].Phi / 2)
+ * CONST[38].__z_ 1.0f / (cos(LIGHT[0].Theta / 2) - cos(Light[0].Phi / 2))
+ * CONST[39].xyz_ LIGHT[0].HalfVector (for directional lights)
+ * CONST[39].___w 1 if this is the last active light, 0 if not
+ * CONST[40] LIGHT[1]
+ * CONST[48] LIGHT[2]
+ * CONST[56] LIGHT[3]
+ * CONST[64] LIGHT[4]
+ * CONST[72] LIGHT[5]
+ * CONST[80] LIGHT[6]
+ * CONST[88] LIGHT[7]
+ * NOTE: no lighting code is generated if there are no active lights
+ *
+ * CONST[100].x___ Viewport 2/width
+ * CONST[100]._y__ Viewport 2/height
+ * CONST[100].__z_ Viewport 1/(zmax - zmin)
+ * CONST[101].x___ Viewport x0
+ * CONST[101]._y__ Viewport y0
+ * CONST[101].__z_ Viewport z0
+ *
+ * CONST[128..131] D3DTS_TEXTURE0
+ * CONST[132..135] D3DTS_TEXTURE1
+ * CONST[136..139] D3DTS_TEXTURE2
+ * CONST[140..143] D3DTS_TEXTURE3
+ * CONST[144..147] D3DTS_TEXTURE4
+ * CONST[148..151] D3DTS_TEXTURE5
+ * CONST[152..155] D3DTS_TEXTURE6
+ * CONST[156..159] D3DTS_TEXTURE7
+ *
+ * CONST[224] D3DTS_WORLDMATRIX[0]
+ * CONST[228] D3DTS_WORLDMATRIX[1]
+ * ...
+ * CONST[252] D3DTS_WORLDMATRIX[7]
+ */
+struct vs_build_ctx
+{
+ struct ureg_program *ureg;
+ const struct nine_ff_vs_key *key;
+
+ unsigned input[PIPE_MAX_ATTRIBS];
+ unsigned num_inputs;
+
+ struct ureg_src aVtx;
+ struct ureg_src aNrm;
+ struct ureg_src aCol[2];
+ struct ureg_src aTex[8];
+ struct ureg_src aPsz;
+ struct ureg_src aInd;
+ struct ureg_src aWgt;
+
+ struct ureg_src aVtx1; /* tweening */
+ struct ureg_src aNrm1;
+
+ struct ureg_src mtlA;
+ struct ureg_src mtlD;
+ struct ureg_src mtlS;
+ struct ureg_src mtlE;
+};
+
+static INLINE unsigned
+get_texcoord_sn(struct pipe_screen *screen)
+{
+ if (screen->get_param(screen, PIPE_CAP_TGSI_TEXCOORD))
+ return TGSI_SEMANTIC_TEXCOORD;
+ return TGSI_SEMANTIC_GENERIC;
+}
+
+static INLINE struct ureg_src
+build_vs_add_input(struct vs_build_ctx *vs, unsigned ndecl)
+{
+ const unsigned i = vs->num_inputs++;
+ assert(i < PIPE_MAX_ATTRIBS);
+ vs->input[i] = ndecl;
+ return ureg_DECL_vs_input(vs->ureg, i);
+}
+
+/* NOTE: dst may alias src */
+static INLINE void
+ureg_normalize3(struct ureg_program *ureg,
+ struct ureg_dst dst, struct ureg_src src,
+ struct ureg_dst tmp)
+{
+#ifdef NINE_TGSI_LAZY_DEVS
+ struct ureg_dst tmp_x = ureg_writemask(tmp, TGSI_WRITEMASK_X);
+
+ ureg_DP3(ureg, tmp_x, src, src);
+ ureg_RSQ(ureg, tmp_x, _X(tmp));
+ ureg_MUL(ureg, dst, src, _X(tmp));
+#else
+ ureg_NRM(ureg, dst, src);
+#endif
+}
+
+static void *
+nine_ff_build_vs(struct NineDevice9 *device, struct vs_build_ctx *vs)
+{
+ const struct nine_ff_vs_key *key = vs->key;
+ struct ureg_program *ureg = ureg_create(TGSI_PROCESSOR_VERTEX);
+ struct ureg_dst oPos, oCol[2], oTex[8], oPsz, oFog;
+ struct ureg_dst rCol[2]; /* oCol if no fog, TEMP otherwise */
+ struct ureg_dst rVtx, rNrm;
+ struct ureg_dst r[8];
+ struct ureg_dst AR;
+ struct ureg_dst tmp, tmp_x, tmp_z;
+ unsigned i, c;
+ unsigned label[32], l = 0;
+ unsigned num_r = 8;
+ boolean need_rNrm = key->lighting || key->pointscale;
+ boolean need_rVtx = key->lighting || key->fog_mode;
+ const unsigned texcoord_sn = get_texcoord_sn(device->screen);
+
+ vs->ureg = ureg;
+
+ /* Check which inputs we should transform. */
+ for (i = 0; i < 8 * 3; i += 3) {
+ switch ((key->tc_gen >> i) & 0x3) {
+ case NINED3DTSS_TCI_CAMERASPACENORMAL:
+ need_rNrm = TRUE;
+ break;
+ case NINED3DTSS_TCI_CAMERASPACEPOSITION:
+ need_rVtx = TRUE;
+ break;
+ case NINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
+ need_rVtx = need_rNrm = TRUE;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* Declare and record used inputs (needed for linkage with vertex format):
+ * (texture coordinates handled later)
+ */
+ vs->aVtx = build_vs_add_input(vs,
+ key->position_t ? NINE_DECLUSAGE_POSITIONT : NINE_DECLUSAGE_POSITION(0));
+
+ if (need_rNrm)
+ vs->aNrm = build_vs_add_input(vs, NINE_DECLUSAGE_NORMAL(0));
+
+ vs->aCol[0] = ureg_imm1f(ureg, 1.0f);
+ vs->aCol[1] = ureg_imm1f(ureg, 1.0f);
+
+ if (key->lighting || key->darkness) {
+ const unsigned mask = key->mtl_diffuse | key->mtl_specular |
+ key->mtl_ambient | key->mtl_emissive;
+ if ((mask & 0x1) && !key->color0in_one)
+ vs->aCol[0] = build_vs_add_input(vs, NINE_DECLUSAGE_COLOR(0));
+ if ((mask & 0x2) && !key->color1in_one)
+ vs->aCol[1] = build_vs_add_input(vs, NINE_DECLUSAGE_COLOR(1));
+
+ vs->mtlD = MATERIAL_CONST(1);
+ vs->mtlA = MATERIAL_CONST(2);
+ vs->mtlS = MATERIAL_CONST(3);
+ vs->mtlE = MATERIAL_CONST(5);
+ if (key->mtl_diffuse == 1) vs->mtlD = vs->aCol[0]; else
+ if (key->mtl_diffuse == 2) vs->mtlD = vs->aCol[1];
+ if (key->mtl_ambient == 1) vs->mtlA = vs->aCol[0]; else
+ if (key->mtl_ambient == 2) vs->mtlA = vs->aCol[1];
+ if (key->mtl_specular == 1) vs->mtlS = vs->aCol[0]; else
+ if (key->mtl_specular == 2) vs->mtlS = vs->aCol[1];
+ if (key->mtl_emissive == 1) vs->mtlE = vs->aCol[0]; else
+ if (key->mtl_emissive == 2) vs->mtlE = vs->aCol[1];
+ } else {
+ if (!key->color0in_one) vs->aCol[0] = build_vs_add_input(vs, NINE_DECLUSAGE_COLOR(0));
+ if (!key->color1in_one) vs->aCol[1] = build_vs_add_input(vs, NINE_DECLUSAGE_COLOR(1));
+ }
+
+ if (key->vertexpointsize)
+ vs->aPsz = build_vs_add_input(vs, NINE_DECLUSAGE_PSIZE);
+
+ if (key->vertexblend_indexed)
+ vs->aInd = build_vs_add_input(vs, NINE_DECLUSAGE_BLENDINDICES(0));
+ if (key->vertexblend)
+ vs->aWgt = build_vs_add_input(vs, NINE_DECLUSAGE_BLENDWEIGHT(0));
+ if (key->vertextween) {
+ vs->aVtx1 = build_vs_add_input(vs, NINE_DECLUSAGE_POSITION(1));
+ vs->aNrm1 = build_vs_add_input(vs, NINE_DECLUSAGE_NORMAL(1));
+ }
+
+ /* Declare outputs:
+ */
+ oPos = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); /* HPOS */
+ oCol[0] = ureg_saturate(ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0));
+ oCol[1] = ureg_saturate(ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 1));
+
+ if (key->vertexpointsize || key->pointscale) {
+ oPsz = ureg_DECL_output_masked(ureg, TGSI_SEMANTIC_PSIZE, 0, TGSI_WRITEMASK_X);
+ oPsz = ureg_writemask(oPsz, TGSI_WRITEMASK_X);
+ }
+ if (key->fog_mode) {
+ /* We apply fog to the vertex colors, oFog is for programmable shaders only ?
+ */
+ oFog = ureg_DECL_output_masked(ureg, TGSI_SEMANTIC_FOG, 0, TGSI_WRITEMASK_X);
+ oFog = ureg_writemask(oFog, TGSI_WRITEMASK_X);
+ }
+
+ /* Declare TEMPs:
+ */
+ for (i = 0; i < num_r; ++i)
+ r[i] = ureg_DECL_local_temporary(ureg);
+ tmp = r[0];
+ tmp_x = ureg_writemask(tmp, TGSI_WRITEMASK_X);
+ tmp_z = ureg_writemask(tmp, TGSI_WRITEMASK_Z);
+ if (key->lighting || key->vertexblend)
+ AR = ureg_DECL_address(ureg);
+
+ if (key->fog_mode) {
+ rCol[0] = r[2];
+ rCol[1] = r[3];
+ } else {
+ rCol[0] = oCol[0];
+ rCol[1] = oCol[1];
+ }
+
+ rVtx = ureg_writemask(r[1], TGSI_WRITEMASK_XYZ);
+ rNrm = ureg_writemask(r[2], TGSI_WRITEMASK_XYZ);
+
+ /* === Vertex transformation / vertex blending:
+ */
+ if (key->vertextween) {
+ assert(!key->vertexblend);
+ ureg_LRP(ureg, r[2], _XXXX(_CONST(30)), vs->aVtx, vs->aVtx1);
+ if (need_rNrm)
+ ureg_LRP(ureg, r[3], _XXXX(_CONST(30)), vs->aNrm, vs->aNrm1);
+ vs->aVtx = ureg_src(r[2]);
+ vs->aNrm = ureg_src(r[3]);
+ }
+
+ if (key->vertexblend) {
+ struct ureg_src cWM[4];
+
+ for (i = 224; i <= 255; ++i)
+ ureg_DECL_constant(ureg, i);
+
+ /* translate world matrix index to constant file index */
+ if (key->vertexblend_indexed) {
+ ureg_MAD(ureg, tmp, vs->aInd, ureg_imm1f(ureg, 4.0f), ureg_imm1f(ureg, 224.0f));
+ ureg_ARL(ureg, AR, ureg_src(tmp));
+ }
+ for (i = 0; i < key->vertexblend; ++i) {
+ for (c = 0; c < 4; ++c) {
+ cWM[c] = ureg_src_register(TGSI_FILE_CONSTANT, (224 + i * 4) * !key->vertexblend_indexed + c);
+ if (key->vertexblend_indexed)
+ cWM[c] = ureg_src_indirect(cWM[c], ureg_scalar(ureg_src(AR), i));
+ }
+ /* multiply by WORLD(index) */
+ ureg_MUL(ureg, r[0], _XXXX(vs->aVtx), cWM[0]);
+ ureg_MAD(ureg, r[0], _YYYY(vs->aVtx), cWM[1], ureg_src(r[0]));
+ ureg_MAD(ureg, r[0], _ZZZZ(vs->aVtx), cWM[2], ureg_src(r[0]));
+ ureg_MAD(ureg, r[0], _WWWW(vs->aVtx), cWM[3], ureg_src(r[0]));
+
+ /* accumulate weighted position value */
+ if (i)
+ ureg_MAD(ureg, r[2], ureg_src(r[0]), ureg_scalar(vs->aWgt, i), ureg_src(r[2]));
+ else
+ ureg_MUL(ureg, r[2], ureg_src(r[0]), ureg_scalar(vs->aWgt, 0));
+ }
+ /* multiply by VIEW_PROJ */
+ ureg_MUL(ureg, r[0], _X(r[2]), _CONST(8));
+ ureg_MAD(ureg, r[0], _Y(r[2]), _CONST(9), ureg_src(r[0]));
+ ureg_MAD(ureg, r[0], _Z(r[2]), _CONST(10), ureg_src(r[0]));
+ ureg_MAD(ureg, oPos, _W(r[2]), _CONST(11), ureg_src(r[0]));
+
+ if (need_rVtx)
+ vs->aVtx = ureg_src(r[2]);
+ } else
+ if (key->position_t && device->driver_caps.window_space_position_support) {
+ ureg_MOV(ureg, oPos, vs->aVtx);
+ } else if (key->position_t) {
+ /* vs->aVtx contains the coordinates buffer wise.
+ * later in the pipeline, clipping, viewport and division
+ * by w (rhw = 1/w) are going to be applied, so do the reverse
+ * of these transformations (except clipping) to have the good
+ * position at the end.*/
+ ureg_MOV(ureg, tmp, vs->aVtx);
+ /* X from [X_min, X_min + width] to [-1, 1], same for Y. Z to [0, 1] */
+ ureg_SUB(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XYZ), ureg_src(tmp), _CONST(101));
+ ureg_MUL(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XYZ), ureg_src(tmp), _CONST(100));
+ ureg_SUB(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XY), ureg_src(tmp), ureg_imm1f(ureg, 1.0f));
+ /* Y needs to be reversed */
+ ureg_MOV(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Y), ureg_negate(ureg_src(tmp)));
+ /* inverse rhw */
+ ureg_RCP(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_W), _W(tmp));
+ /* multiply X, Y, Z by w */
+ ureg_MUL(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XYZ), ureg_src(tmp), _W(tmp));
+ ureg_MOV(ureg, oPos, ureg_src(tmp));
+ } else {
+ /* position = vertex * WORLD_VIEW_PROJ */
+ ureg_MUL(ureg, r[0], _XXXX(vs->aVtx), _CONST(0));
+ ureg_MAD(ureg, r[0], _YYYY(vs->aVtx), _CONST(1), ureg_src(r[0]));
+ ureg_MAD(ureg, r[0], _ZZZZ(vs->aVtx), _CONST(2), ureg_src(r[0]));
+ ureg_MAD(ureg, oPos, _WWWW(vs->aVtx), _CONST(3), ureg_src(r[0]));
+ }
+
+ if (need_rVtx) {
+ ureg_MUL(ureg, rVtx, _XXXX(vs->aVtx), _CONST(4));
+ ureg_MAD(ureg, rVtx, _YYYY(vs->aVtx), _CONST(5), ureg_src(rVtx));
+ ureg_MAD(ureg, rVtx, _ZZZZ(vs->aVtx), _CONST(6), ureg_src(rVtx));
+ ureg_MAD(ureg, rVtx, _WWWW(vs->aVtx), _CONST(7), ureg_src(rVtx));
+ }
+ if (need_rNrm) {
+ ureg_MUL(ureg, rNrm, _XXXX(vs->aNrm), _CONST(16));
+ ureg_MAD(ureg, rNrm, _YYYY(vs->aNrm), _CONST(17), ureg_src(rNrm));
+ ureg_MAD(ureg, rNrm, _ZZZZ(vs->aNrm), _CONST(18), ureg_src(rNrm));
+ ureg_normalize3(ureg, rNrm, ureg_src(rNrm), tmp);
+ }
+ /* NOTE: don't use vs->aVtx, vs->aNrm after this line */
+
+ /* === Process point size:
+ */
+ if (key->vertexpointsize) {
+ struct ureg_src cPsz1 = ureg_DECL_constant(ureg, 26);
+#ifdef NINE_TGSI_LAZY_DEVS
+ struct ureg_dst tmp_clamp = ureg_DECL_temporary(ureg);
+
+ ureg_MAX(ureg, tmp_clamp, vs->aPsz, _XXXX(cPsz1));
+ ureg_MIN(ureg, oPsz, ureg_src(tmp_clamp), _YYYY(cPsz1));
+ ureg_release_temporary(ureg, tmp_clamp);
+#else
+ ureg_CLAMP(ureg, oPsz, vs->aPsz, _XXXX(cPsz1), _YYYY(cPsz1));
+#endif
+ } else if (key->pointscale) {
+ struct ureg_dst tmp_x = ureg_writemask(tmp, TGSI_WRITEMASK_X);
+ struct ureg_dst tmp_y = ureg_writemask(tmp, TGSI_WRITEMASK_Y);
+ struct ureg_src cPsz1 = ureg_DECL_constant(ureg, 26);
+ struct ureg_src cPsz2 = ureg_DECL_constant(ureg, 27);
+
+ ureg_DP3(ureg, tmp_x, ureg_src(r[1]), ureg_src(r[1]));
+ ureg_SQRT(ureg, tmp_y, _X(tmp));
+ ureg_MAD(ureg, tmp_x, _Y(tmp), _YYYY(cPsz2), _XXXX(cPsz2));
+ ureg_MAD(ureg, tmp_x, _Y(tmp), _X(tmp), _WWWW(cPsz1));
+ ureg_RCP(ureg, tmp_x, ureg_src(tmp));
+ ureg_MUL(ureg, tmp_x, ureg_src(tmp), _ZZZZ(cPsz1));
+#ifdef NINE_TGSI_LAZY_DEVS
+ struct ureg_dst tmp_clamp = ureg_DECL_temporary(ureg);
+
+ ureg_MAX(ureg, tmp_clamp, _X(tmp), _XXXX(cPsz1));
+ ureg_MIN(ureg, oPsz, ureg_src(tmp_clamp), _YYYY(cPsz1));
+ ureg_release_temporary(ureg, tmp_clamp);
+#else
+ ureg_CLAMP(ureg, oPsz, _X(tmp), _XXXX(cPsz1), _YYYY(cPsz1));
+#endif
+ }
+
+ /* Texture coordinate generation:
+ * XXX: D3DTTFF_PROJECTED, transform matrix
+ */
+ for (i = 0; i < 8; ++i) {
+ struct ureg_dst dst[5];
+ struct ureg_src src;
+ unsigned c;
+ const unsigned tci = (key->tc_gen >> (i * 3)) & 0x7;
+ const unsigned idx = (key->tc_idx >> (i * 3)) & 0x7;
+ const unsigned dim = (key->tc_dim >> (i * 3)) & 0x7;
+
+ if (tci == NINED3DTSS_TCI_DISABLE)
+ continue;
+ oTex[i] = ureg_DECL_output(ureg, texcoord_sn, i);
+
+ if (tci == NINED3DTSS_TCI_PASSTHRU)
+ vs->aTex[idx] = build_vs_add_input(vs, NINE_DECLUSAGE_TEXCOORD(idx));
+
+ if (!dim) {
+ dst[c = 4] = oTex[i];
+ } else {
+ dst[4] = r[5];
+ src = ureg_src(dst[4]);
+ for (c = 0; c < (dim - 1); ++c)
+ dst[c] = ureg_writemask(tmp, (1 << dim) - 1);
+ dst[c] = ureg_writemask(oTex[i], (1 << dim) - 1);
+ }
+
+ switch (tci) {
+ case NINED3DTSS_TCI_PASSTHRU:
+ ureg_MOV(ureg, dst[4], vs->aTex[idx]);
+ break;
+ case NINED3DTSS_TCI_CAMERASPACENORMAL:
+ assert(dim <= 3);
+ ureg_MOV(ureg, ureg_writemask(dst[4], TGSI_WRITEMASK_XYZ), ureg_src(rNrm));
+ ureg_MOV(ureg, ureg_writemask(dst[4], TGSI_WRITEMASK_W), ureg_imm1f(ureg, 1.0f));
+ break;
+ case NINED3DTSS_TCI_CAMERASPACEPOSITION:
+ ureg_MOV(ureg, ureg_writemask(dst[4], TGSI_WRITEMASK_XYZ), ureg_src(rVtx));
+ ureg_MOV(ureg, ureg_writemask(dst[4], TGSI_WRITEMASK_W), ureg_imm1f(ureg, 1.0f));
+ break;
+ case NINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
+ tmp.WriteMask = TGSI_WRITEMASK_XYZ;
+ ureg_DP3(ureg, tmp_x, ureg_src(rVtx), ureg_src(rNrm));
+ ureg_MUL(ureg, tmp, ureg_src(rNrm), _X(tmp));
+ ureg_ADD(ureg, tmp, ureg_src(tmp), ureg_src(tmp));
+ ureg_SUB(ureg, ureg_writemask(dst[4], TGSI_WRITEMASK_XYZ), ureg_src(rVtx), ureg_src(tmp));
+ ureg_MOV(ureg, ureg_writemask(dst[4], TGSI_WRITEMASK_W), ureg_imm1f(ureg, 1.0f));
+ tmp.WriteMask = TGSI_WRITEMASK_XYZW;
+ break;
+ case NINED3DTSS_TCI_SPHEREMAP:
+ assert(!"TODO");
+ break;
+ default:
+ break;
+ }
+ if (!dim)
+ continue;
+ dst[c].WriteMask = ~dst[c].WriteMask;
+ if (dst[c].WriteMask)
+ ureg_MOV(ureg, dst[c], src); /* store untransformed components */
+ dst[c].WriteMask = ~dst[c].WriteMask;
+ if (dim > 0) ureg_MUL(ureg, dst[0], _XXXX(src), _CONST(128 + i * 4));
+ if (dim > 1) ureg_MAD(ureg, dst[1], _YYYY(src), _CONST(129 + i * 4), ureg_src(tmp));
+ if (dim > 2) ureg_MAD(ureg, dst[2], _ZZZZ(src), _CONST(130 + i * 4), ureg_src(tmp));
+ if (dim > 3) ureg_MAD(ureg, dst[3], _WWWW(src), _CONST(131 + i * 4), ureg_src(tmp));
+ }
+
+ /* === Lighting:
+ *
+ * DIRECTIONAL: Light at infinite distance, parallel rays, no attenuation.
+ * POINT: Finite distance to scene, divergent rays, isotropic, attenuation.
+ * SPOT: Finite distance, divergent rays, angular dependence, attenuation.
+ *
+ * vec3 normal = normalize(in.Normal * NormalMatrix);
+ * vec3 hitDir = light.direction;
+ * float atten = 1.0;
+ *
+ * if (light.type != DIRECTIONAL)
+ * {
+ * vec3 hitVec = light.position - eyeVertex;
+ * float d = length(hitVec);
+ * hitDir = hitVec / d;
+ * atten = 1 / ((light.atten2 * d + light.atten1) * d + light.atten0);
+ * }
+ *
+ * if (light.type == SPOTLIGHT)
+ * {
+ * float rho = dp3(-hitVec, light.direction);
+ * if (rho < cos(light.phi / 2))
+ * atten = 0;
+ * if (rho < cos(light.theta / 2))
+ * atten *= pow(some_func(rho), light.falloff);
+ * }
+ *
+ * float nDotHit = dp3_sat(normal, hitVec);
+ * float powFact = 0.0;
+ *
+ * if (nDotHit > 0.0)
+ * {
+ * vec3 midVec = normalize(hitDir + eye);
+ * float nDotMid = dp3_sat(normal, midVec);
+ * pFact = pow(nDotMid, material.power);
+ * }
+ *
+ * ambient += light.ambient * atten;
+ * diffuse += light.diffuse * atten * nDotHit;
+ * specular += light.specular * atten * powFact;
+ */
+ if (key->lighting) {
+ struct ureg_dst tmp_y = ureg_writemask(tmp, TGSI_WRITEMASK_Y);
+
+ struct ureg_dst rAtt = ureg_writemask(r[1], TGSI_WRITEMASK_W);
+ struct ureg_dst rHit = ureg_writemask(r[3], TGSI_WRITEMASK_XYZ);
+ struct ureg_dst rMid = ureg_writemask(r[4], TGSI_WRITEMASK_XYZ);
+
+ struct ureg_dst rCtr = ureg_writemask(r[2], TGSI_WRITEMASK_W);
+
+ struct ureg_dst AL = ureg_writemask(AR, TGSI_WRITEMASK_X);
+
+ /* Light.*.Alpha is not used. */
+ struct ureg_dst rD = ureg_writemask(r[5], TGSI_WRITEMASK_XYZ);
+ struct ureg_dst rA = ureg_writemask(r[6], TGSI_WRITEMASK_XYZ);
+ struct ureg_dst rS = ureg_writemask(r[7], TGSI_WRITEMASK_XYZ);
+
+ struct ureg_src mtlP = _XXXX(MATERIAL_CONST(4));
+
+ struct ureg_src cLKind = _XXXX(LIGHT_CONST(0));
+ struct ureg_src cLAtt0 = _YYYY(LIGHT_CONST(0));
+ struct ureg_src cLAtt1 = _ZZZZ(LIGHT_CONST(0));
+ struct ureg_src cLAtt2 = _WWWW(LIGHT_CONST(0));
+ struct ureg_src cLColD = _XYZW(LIGHT_CONST(1));
+ struct ureg_src cLColS = _XYZW(LIGHT_CONST(2));
+ struct ureg_src cLColA = _XYZW(LIGHT_CONST(3));
+ struct ureg_src cLPos = _XYZW(LIGHT_CONST(4));
+ struct ureg_src cLRng = _WWWW(LIGHT_CONST(4));
+ struct ureg_src cLDir = _XYZW(LIGHT_CONST(5));
+ struct ureg_src cLFOff = _WWWW(LIGHT_CONST(5));
+ struct ureg_src cLTht = _XXXX(LIGHT_CONST(6));
+ struct ureg_src cLPhi = _YYYY(LIGHT_CONST(6));
+ struct ureg_src cLSDiv = _ZZZZ(LIGHT_CONST(6));
+ struct ureg_src cLLast = _WWWW(LIGHT_CONST(7));
+
+ const unsigned loop_label = l++;
+
+ ureg_MOV(ureg, rCtr, ureg_imm1f(ureg, 32.0f)); /* &lightconst(0) */
+ ureg_MOV(ureg, rD, ureg_imm1f(ureg, 0.0f));
+ ureg_MOV(ureg, rA, ureg_imm1f(ureg, 0.0f));
+ ureg_MOV(ureg, rS, ureg_imm1f(ureg, 0.0f));
+ rD = ureg_saturate(rD);
+ rA = ureg_saturate(rA);
+ rS = ureg_saturate(rS);
+
+
+ /* loop management */
+ ureg_BGNLOOP(ureg, &label[loop_label]);
+ ureg_ARL(ureg, AL, _W(rCtr));
+
+ /* if (not DIRECTIONAL light): */
+ ureg_SNE(ureg, tmp_x, cLKind, ureg_imm1f(ureg, D3DLIGHT_DIRECTIONAL));
+ ureg_MOV(ureg, rHit, ureg_negate(cLDir));
+ ureg_MOV(ureg, rAtt, ureg_imm1f(ureg, 1.0f));
+ ureg_IF(ureg, _X(tmp), &label[l++]);
+ {
+ /* hitDir = light.position - eyeVtx
+ * d = length(hitDir)
+ * hitDir /= d
+ */
+ ureg_SUB(ureg, rHit, cLPos, ureg_src(rVtx));
+ ureg_DP3(ureg, tmp_x, ureg_src(rHit), ureg_src(rHit));
+ ureg_RSQ(ureg, tmp_y, _X(tmp));
+ ureg_MUL(ureg, rHit, ureg_src(rHit), _Y(tmp)); /* normalize */
+ ureg_MUL(ureg, tmp_x, _X(tmp), _Y(tmp)); /* length */
+
+ /* att = 1.0 / (light.att0 + (light.att1 + light.att2 * d) * d) */
+ ureg_MAD(ureg, rAtt, _X(tmp), cLAtt2, cLAtt1);
+ ureg_MAD(ureg, rAtt, _X(tmp), _W(rAtt), cLAtt0);
+ ureg_RCP(ureg, rAtt, _W(rAtt));
+ /* cut-off if distance exceeds Light.Range */
+ ureg_SLT(ureg, tmp_x, _X(tmp), cLRng);
+ ureg_MUL(ureg, rAtt, _W(rAtt), _X(tmp));
+ }
+ ureg_fixup_label(ureg, label[l-1], ureg_get_instruction_number(ureg));
+ ureg_ENDIF(ureg);
+
+ /* if (SPOT light) */
+ ureg_SEQ(ureg, tmp_x, cLKind, ureg_imm1f(ureg, D3DLIGHT_SPOT));
+ ureg_IF(ureg, _X(tmp), &label[l++]);
+ {
+ /* rho = dp3(-hitDir, light.spotDir)
+ *
+ * if (rho > light.ctht2) NOTE: 0 <= phi <= pi, 0 <= theta <= phi
+ * spotAtt = 1
+ * else
+ * if (rho <= light.cphi2)
+ * spotAtt = 0
+ * else
+ * spotAtt = (rho - light.cphi2) / (light.ctht2 - light.cphi2) ^ light.falloff
+ */
+ ureg_DP3(ureg, tmp_y, ureg_negate(ureg_src(rHit)), cLDir); /* rho */
+ ureg_SUB(ureg, tmp_x, _Y(tmp), cLPhi);
+ ureg_MUL(ureg, tmp_x, _X(tmp), cLSDiv);
+ ureg_POW(ureg, tmp_x, _X(tmp), cLFOff); /* spotAtten */
+ ureg_SGE(ureg, tmp_z, _Y(tmp), cLTht); /* if inside theta && phi */
+ ureg_SGE(ureg, tmp_y, _Y(tmp), cLPhi); /* if inside phi */
+ ureg_MAD(ureg, ureg_saturate(tmp_x), _X(tmp), _Y(tmp), _Z(tmp));
+ ureg_MUL(ureg, rAtt, _W(rAtt), _X(tmp));
+ }
+ ureg_fixup_label(ureg, label[l-1], ureg_get_instruction_number(ureg));
+ ureg_ENDIF(ureg);
+
+ /* directional factors, let's not use LIT because of clarity */
+ ureg_DP3(ureg, ureg_saturate(tmp_x), ureg_src(rNrm), ureg_src(rHit));
+ ureg_MOV(ureg, tmp_y, ureg_imm1f(ureg, 0.0f));
+ ureg_IF(ureg, _X(tmp), &label[l++]);
+ {
+ /* midVec = normalize(hitDir + eyeDir) */
+ if (key->localviewer) {
+ ureg_normalize3(ureg, rMid, ureg_src(rVtx), tmp);
+ ureg_ADD(ureg, rMid, ureg_src(rHit), ureg_negate(ureg_src(rMid)));
+ } else {
+ ureg_ADD(ureg, rMid, ureg_src(rHit), ureg_imm3f(ureg, 0.0f, 0.0f, 1.0f));
+ }
+ ureg_normalize3(ureg, rMid, ureg_src(rMid), tmp);
+ ureg_DP3(ureg, ureg_saturate(tmp_y), ureg_src(rNrm), ureg_src(rMid));
+ ureg_POW(ureg, tmp_y, _Y(tmp), mtlP);
+
+ ureg_MUL(ureg, tmp_x, _W(rAtt), _X(tmp)); /* dp3(normal,hitDir) * att */
+ ureg_MUL(ureg, tmp_y, _W(rAtt), _Y(tmp)); /* power factor * att */
+ ureg_MAD(ureg, rD, cLColD, _X(tmp), ureg_src(rD)); /* accumulate diffuse */
+ ureg_MAD(ureg, rS, cLColS, _Y(tmp), ureg_src(rS)); /* accumulate specular */
+ }
+ ureg_fixup_label(ureg, label[l-1], ureg_get_instruction_number(ureg));
+ ureg_ENDIF(ureg);
+
+ ureg_MAD(ureg, rA, cLColA, _W(rAtt), ureg_src(rA)); /* accumulate ambient */
+
+ /* break if this was the last light */
+ ureg_IF(ureg, cLLast, &label[l++]);
+ ureg_BRK(ureg);
+ ureg_ENDIF(ureg);
+ ureg_fixup_label(ureg, label[l-1], ureg_get_instruction_number(ureg));
+
+ ureg_ADD(ureg, rCtr, _W(rCtr), ureg_imm1f(ureg, 8.0f));
+ ureg_fixup_label(ureg, label[loop_label], ureg_get_instruction_number(ureg));
+ ureg_ENDLOOP(ureg, &label[loop_label]);
+
+ /* Set alpha factors of illumination to 1.0 for the multiplications. */
+ rD.WriteMask = TGSI_WRITEMASK_W; rD.Saturate = 0;
+ rS.WriteMask = TGSI_WRITEMASK_W; rS.Saturate = 0;
+ rA.WriteMask = TGSI_WRITEMASK_W; rA.Saturate = 0;
+ ureg_MOV(ureg, rD, ureg_imm1f(ureg, 1.0f));
+ ureg_MOV(ureg, rS, ureg_imm1f(ureg, 1.0f));
+
+ /* Apply to material:
+ *
+ * oCol[0] = (material.emissive + material.ambient * rs.ambient) +
+ * material.ambient * ambient +
+ * material.diffuse * diffuse +
+ * oCol[1] = material.specular * specular;
+ */
+ if (key->mtl_emissive == 0 && key->mtl_ambient == 0) {
+ ureg_MOV(ureg, rA, ureg_imm1f(ureg, 1.0f));
+ ureg_MAD(ureg, tmp, ureg_src(rA), vs->mtlA, _CONST(19));
+ } else {
+ ureg_ADD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XYZ), ureg_src(rA), _CONST(25));
+ ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XYZ), vs->mtlA, ureg_src(tmp), vs->mtlE);
+ ureg_ADD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_W ), vs->mtlA, vs->mtlE);
+ }
+ ureg_MAD(ureg, rCol[0], ureg_src(rD), vs->mtlD, ureg_src(tmp));
+ ureg_MUL(ureg, rCol[1], ureg_src(rS), vs->mtlS);
+ } else
+ /* COLOR */
+ if (key->darkness) {
+ if (key->mtl_emissive == 0 && key->mtl_ambient == 0) {
+ ureg_MAD(ureg, rCol[0], vs->mtlD, ureg_imm4f(ureg, 0.0f, 0.0f, 0.0f, 1.0f), _CONST(19));
+ } else {
+ ureg_MAD(ureg, ureg_writemask(rCol[0], TGSI_WRITEMASK_XYZ), vs->mtlA, _CONST(25), vs->mtlE);
+ ureg_ADD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_W), vs->mtlA, vs->mtlE);
+ ureg_ADD(ureg, ureg_writemask(rCol[0], TGSI_WRITEMASK_W), vs->mtlD, _W(tmp));
+ }
+ ureg_MUL(ureg, rCol[1], ureg_imm4f(ureg, 0.0f, 0.0f, 0.0f, 1.0f), vs->mtlS);
+ } else {
+ ureg_MOV(ureg, rCol[0], vs->aCol[0]);
+ ureg_MOV(ureg, rCol[1], vs->aCol[1]);
+ }
+
+ /* === Process fog.
+ *
+ * exp(x) = ex2(log2(e) * x)
+ */
+ if (key->fog_mode) {
+ /* Fog doesn't affect alpha, TODO: combine with light code output */
+ ureg_MOV(ureg, ureg_writemask(oCol[0], TGSI_WRITEMASK_W), _W(rCol[0]));
+ ureg_MOV(ureg, ureg_writemask(oCol[1], TGSI_WRITEMASK_W), _W(rCol[1]));
+
+ if (key->position_t) {
+ ureg_MOV(ureg, ureg_saturate(tmp_x), ureg_scalar(vs->aCol[1], TGSI_SWIZZLE_W));
+ } else
+ if (key->fog_range) {
+ ureg_DP3(ureg, tmp_x, ureg_src(rVtx), ureg_src(rVtx));
+ ureg_RSQ(ureg, tmp_z, _X(tmp));
+ ureg_MUL(ureg, tmp_z, _Z(tmp), _X(tmp));
+ } else {
+ ureg_MOV(ureg, tmp_z, ureg_abs(_Z(rVtx)));
+ }
+
+ if (key->fog_mode == D3DFOG_EXP) {
+ ureg_MUL(ureg, tmp_x, _Z(tmp), _ZZZZ(_CONST(28)));
+ ureg_MUL(ureg, tmp_x, _X(tmp), ureg_imm1f(ureg, -1.442695f));
+ ureg_EX2(ureg, tmp_x, _X(tmp));
+ } else
+ if (key->fog_mode == D3DFOG_EXP2) {
+ ureg_MUL(ureg, tmp_x, _Z(tmp), _ZZZZ(_CONST(28)));
+ ureg_MUL(ureg, tmp_x, _X(tmp), _X(tmp));
+ ureg_MUL(ureg, tmp_x, _X(tmp), ureg_imm1f(ureg, -1.442695f));
+ ureg_EX2(ureg, tmp_x, _X(tmp));
+ } else
+ if (key->fog_mode == D3DFOG_LINEAR && !key->position_t) {
+ ureg_SUB(ureg, tmp_x, _XXXX(_CONST(28)), _Z(tmp));
+ ureg_MUL(ureg, ureg_saturate(tmp_x), _X(tmp), _YYYY(_CONST(28)));
+ }
+ ureg_MOV(ureg, oFog, _X(tmp));
+ ureg_LRP(ureg, ureg_writemask(oCol[0], TGSI_WRITEMASK_XYZ), _X(tmp), ureg_src(rCol[0]), _CONST(29));
+ ureg_LRP(ureg, ureg_writemask(oCol[1], TGSI_WRITEMASK_XYZ), _X(tmp), ureg_src(rCol[1]), _CONST(29));
+ }
+
+ if (key->position_t && device->driver_caps.window_space_position_support)
+ ureg_property(ureg, TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION, TRUE);
+
+ ureg_END(ureg);
+ nine_ureg_tgsi_dump(ureg, FALSE);
+ return ureg_create_shader_and_destroy(ureg, device->pipe);
+}
+
+/* PS FF constants layout:
+ *
+ * CONST[ 0.. 7] stage[i].D3DTSS_CONSTANT
+ * CONST[ 8..15].x___ stage[i].D3DTSS_BUMPENVMAT00
+ * CONST[ 8..15]._y__ stage[i].D3DTSS_BUMPENVMAT01
+ * CONST[ 8..15].__z_ stage[i].D3DTSS_BUMPENVMAT10
+ * CONST[ 8..15].___w stage[i].D3DTSS_BUMPENVMAT11
+ * CONST[16..19].x_z_ stage[i].D3DTSS_BUMPENVLSCALE
+ * CONST[17..19]._y_w stage[i].D3DTSS_BUMPENVLOFFSET
+ *
+ * CONST[20] D3DRS_TEXTUREFACTOR
+ * CONST[21] D3DRS_FOGCOLOR
+ * CONST[22].x___ RS.FogEnd
+ * CONST[22]._y__ 1.0f / (RS.FogEnd - RS.FogStart)
+ * CONST[22].__z_ RS.FogDensity
+ */
+struct ps_build_ctx
+{
+ struct ureg_program *ureg;
+
+ struct ureg_src vC[2]; /* DIFFUSE, SPECULAR */
+ struct ureg_src vT[8]; /* TEXCOORD[i] */
+ struct ureg_dst r[6]; /* TEMPs */
+ struct ureg_dst rCur; /* D3DTA_CURRENT */
+ struct ureg_dst rMod;
+ struct ureg_src rCurSrc;
+ struct ureg_dst rTmp; /* D3DTA_TEMP */
+ struct ureg_src rTmpSrc;
+ struct ureg_dst rTex;
+ struct ureg_src rTexSrc;
+ struct ureg_src cBEM[8];
+ struct ureg_src s[8];
+
+ struct {
+ unsigned index;
+ unsigned index_pre_mod;
+ unsigned num_regs;
+ } stage;
+};
+
+static struct ureg_src
+ps_get_ts_arg(struct ps_build_ctx *ps, unsigned ta)
+{
+ struct ureg_src reg;
+
+ switch (ta & D3DTA_SELECTMASK) {
+ case D3DTA_CONSTANT:
+ reg = ureg_DECL_constant(ps->ureg, ps->stage.index);
+ break;
+ case D3DTA_CURRENT:
+ reg = (ps->stage.index == ps->stage.index_pre_mod) ? ureg_src(ps->rMod) : ps->rCurSrc;
+ break;
+ case D3DTA_DIFFUSE:
+ reg = ureg_DECL_fs_input(ps->ureg, TGSI_SEMANTIC_COLOR, 0, TGSI_INTERPOLATE_PERSPECTIVE);
+ break;
+ case D3DTA_SPECULAR:
+ reg = ureg_DECL_fs_input(ps->ureg, TGSI_SEMANTIC_COLOR, 1, TGSI_INTERPOLATE_PERSPECTIVE);
+ break;
+ case D3DTA_TEMP:
+ reg = ps->rTmpSrc;
+ break;
+ case D3DTA_TEXTURE:
+ reg = ps->rTexSrc;
+ break;
+ case D3DTA_TFACTOR:
+ reg = ureg_DECL_constant(ps->ureg, 20);
+ break;
+ default:
+ assert(0);
+ reg = ureg_src_undef();
+ break;
+ }
+ if (ta & D3DTA_COMPLEMENT) {
+ struct ureg_dst dst = ps->r[ps->stage.num_regs++];
+ ureg_SUB(ps->ureg, dst, ureg_imm1f(ps->ureg, 1.0f), reg);
+ reg = ureg_src(dst);
+ }
+ if (ta & D3DTA_ALPHAREPLICATE)
+ reg = _WWWW(reg);
+ return reg;
+}
+
+static struct ureg_dst
+ps_get_ts_dst(struct ps_build_ctx *ps, unsigned ta)
+{
+ assert(!(ta & (D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE)));
+
+ switch (ta & D3DTA_SELECTMASK) {
+ case D3DTA_CURRENT:
+ return ps->rCur;
+ case D3DTA_TEMP:
+ return ps->rTmp;
+ default:
+ assert(0);
+ return ureg_dst_undef();
+ }
+}
+
+static uint8_t ps_d3dtop_args_mask(D3DTEXTUREOP top)
+{
+ switch (top) {
+ case D3DTOP_DISABLE:
+ return 0x0;
+ case D3DTOP_SELECTARG1:
+ case D3DTOP_PREMODULATE:
+ return 0x2;
+ case D3DTOP_SELECTARG2:
+ return 0x4;
+ case D3DTOP_MULTIPLYADD:
+ case D3DTOP_LERP:
+ return 0x7;
+ default:
+ return 0x6;
+ }
+}
+
+static INLINE boolean
+is_MOV_no_op(struct ureg_dst dst, struct ureg_src src)
+{
+ return !dst.WriteMask ||
+ (dst.File == src.File &&
+ dst.Index == src.Index &&
+ !dst.Indirect &&
+ !dst.Saturate &&
+ !src.Indirect &&
+ !src.Negate &&
+ !src.Absolute &&
+ (!(dst.WriteMask & TGSI_WRITEMASK_X) || (src.SwizzleX == TGSI_SWIZZLE_X)) &&
+ (!(dst.WriteMask & TGSI_WRITEMASK_Y) || (src.SwizzleY == TGSI_SWIZZLE_Y)) &&
+ (!(dst.WriteMask & TGSI_WRITEMASK_Z) || (src.SwizzleZ == TGSI_SWIZZLE_Z)) &&
+ (!(dst.WriteMask & TGSI_WRITEMASK_W) || (src.SwizzleW == TGSI_SWIZZLE_W)));
+
+}
+
+static void
+ps_do_ts_op(struct ps_build_ctx *ps, unsigned top, struct ureg_dst dst, struct ureg_src *arg)
+{
+ struct ureg_program *ureg = ps->ureg;
+ struct ureg_dst tmp = ps->r[ps->stage.num_regs];
+ struct ureg_dst tmp2 = ps->r[ps->stage.num_regs+1];
+ struct ureg_dst tmp_x = ureg_writemask(tmp, TGSI_WRITEMASK_X);
+
+ tmp.WriteMask = dst.WriteMask;
+
+ if (top != D3DTOP_SELECTARG1 && top != D3DTOP_SELECTARG2 &&
+ top != D3DTOP_MODULATE && top != D3DTOP_PREMODULATE &&
+ top != D3DTOP_BLENDDIFFUSEALPHA && top != D3DTOP_BLENDTEXTUREALPHA &&
+ top != D3DTOP_BLENDFACTORALPHA && top != D3DTOP_BLENDCURRENTALPHA &&
+ top != D3DTOP_BUMPENVMAP && top != D3DTOP_BUMPENVMAPLUMINANCE &&
+ top != D3DTOP_LERP)
+ dst = ureg_saturate(dst);
+
+ switch (top) {
+ case D3DTOP_SELECTARG1:
+ if (!is_MOV_no_op(dst, arg[1]))
+ ureg_MOV(ureg, dst, arg[1]);
+ break;
+ case D3DTOP_SELECTARG2:
+ if (!is_MOV_no_op(dst, arg[2]))
+ ureg_MOV(ureg, dst, arg[2]);
+ break;
+ case D3DTOP_MODULATE:
+ ureg_MUL(ureg, dst, arg[1], arg[2]);
+ break;
+ case D3DTOP_MODULATE2X:
+ ureg_MUL(ureg, tmp, arg[1], arg[2]);
+ ureg_ADD(ureg, dst, ureg_src(tmp), ureg_src(tmp));
+ break;
+ case D3DTOP_MODULATE4X:
+ ureg_MUL(ureg, tmp, arg[1], arg[2]);
+ ureg_MUL(ureg, dst, ureg_src(tmp), ureg_imm1f(ureg, 4.0f));
+ break;
+ case D3DTOP_ADD:
+ ureg_ADD(ureg, dst, arg[1], arg[2]);
+ break;
+ case D3DTOP_ADDSIGNED:
+ ureg_ADD(ureg, tmp, arg[1], arg[2]);
+ ureg_SUB(ureg, dst, ureg_src(tmp), ureg_imm1f(ureg, 0.5f));
+ break;
+ case D3DTOP_ADDSIGNED2X:
+ ureg_ADD(ureg, tmp, arg[1], arg[2]);
+ ureg_MAD(ureg, dst, ureg_src(tmp), ureg_imm1f(ureg, 2.0f), ureg_imm1f(ureg, -1.0f));
+ break;
+ case D3DTOP_SUBTRACT:
+ ureg_SUB(ureg, dst, arg[1], arg[2]);
+ break;
+ case D3DTOP_ADDSMOOTH:
+ ureg_SUB(ureg, tmp, ureg_imm1f(ureg, 1.0f), arg[1]);
+ ureg_MAD(ureg, dst, ureg_src(tmp), arg[2], arg[1]);
+ break;
+ case D3DTOP_BLENDDIFFUSEALPHA:
+ ureg_LRP(ureg, dst, _WWWW(ps->vC[0]), arg[1], arg[2]);
+ break;
+ case D3DTOP_BLENDTEXTUREALPHA:
+ /* XXX: alpha taken from previous stage, texture or result ? */
+ ureg_LRP(ureg, dst, _W(ps->rTex), arg[1], arg[2]);
+ break;
+ case D3DTOP_BLENDFACTORALPHA:
+ ureg_LRP(ureg, dst, _WWWW(_CONST(20)), arg[1], arg[2]);
+ break;
+ case D3DTOP_BLENDTEXTUREALPHAPM:
+ ureg_SUB(ureg, tmp_x, ureg_imm1f(ureg, 1.0f), _W(ps->rTex));
+ ureg_MAD(ureg, dst, arg[2], _X(tmp), arg[1]);
+ break;
+ case D3DTOP_BLENDCURRENTALPHA:
+ ureg_LRP(ureg, dst, _WWWW(ps->rCurSrc), arg[1], arg[2]);
+ break;
+ case D3DTOP_PREMODULATE:
+ ureg_MOV(ureg, dst, arg[1]);
+ ps->stage.index_pre_mod = ps->stage.index + 1;
+ break;
+ case D3DTOP_MODULATEALPHA_ADDCOLOR:
+ ureg_MAD(ureg, dst, _WWWW(arg[1]), arg[2], arg[1]);
+ break;
+ case D3DTOP_MODULATECOLOR_ADDALPHA:
+ ureg_MAD(ureg, dst, arg[1], arg[2], _WWWW(arg[1]));
+ break;
+ case D3DTOP_MODULATEINVALPHA_ADDCOLOR:
+ ureg_SUB(ureg, tmp_x, ureg_imm1f(ureg, 1.0f), _WWWW(arg[1]));
+ ureg_MAD(ureg, dst, _X(tmp), arg[2], arg[1]);
+ break;
+ case D3DTOP_MODULATEINVCOLOR_ADDALPHA:
+ ureg_SUB(ureg, tmp, ureg_imm1f(ureg, 1.0f), arg[1]);
+ ureg_MAD(ureg, dst, ureg_src(tmp), arg[2], _WWWW(arg[1]));
+ break;
+ case D3DTOP_BUMPENVMAP:
+ break;
+ case D3DTOP_BUMPENVMAPLUMINANCE:
+ break;
+ case D3DTOP_DOTPRODUCT3:
+ ureg_SUB(ureg, tmp, arg[1], ureg_imm4f(ureg,0.5,0.5,0.5,0.5));
+ ureg_SUB(ureg, tmp2, arg[2] , ureg_imm4f(ureg,0.5,0.5,0.5,0.5));
+ ureg_DP3(ureg, tmp, ureg_src(tmp), ureg_src(tmp2));
+ ureg_MUL(ureg, ureg_saturate(dst), ureg_src(tmp), ureg_imm4f(ureg,4.0,4.0,4.0,4.0));
+ break;
+ case D3DTOP_MULTIPLYADD:
+ ureg_MAD(ureg, dst, arg[2], arg[0], arg[1]);
+ break;
+ case D3DTOP_LERP:
+ ureg_LRP(ureg, dst, arg[1], arg[2], arg[0]);
+ break;
+ case D3DTOP_DISABLE:
+ /* no-op ? */
+ break;
+ default:
+ assert(!"invalid D3DTOP");
+ break;
+ }
+}
+
+static void *
+nine_ff_build_ps(struct NineDevice9 *device, struct nine_ff_ps_key *key)
+{
+ struct ps_build_ctx ps;
+ struct ureg_program *ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
+ struct ureg_dst oCol;
+ unsigned i, s;
+ const unsigned texcoord_sn = get_texcoord_sn(device->screen);
+
+ memset(&ps, 0, sizeof(ps));
+ ps.ureg = ureg;
+ ps.stage.index_pre_mod = -1;
+
+ ps.vC[0] = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_COLOR, 0, TGSI_INTERPOLATE_PERSPECTIVE);
+
+ /* Declare all TEMPs we might need, serious drivers have a register allocator. */
+ for (i = 0; i < Elements(ps.r); ++i)
+ ps.r[i] = ureg_DECL_local_temporary(ureg);
+ ps.rCur = ps.r[0];
+ ps.rTmp = ps.r[1];
+ ps.rTex = ps.r[2];
+ ps.rCurSrc = ureg_src(ps.rCur);
+ ps.rTmpSrc = ureg_src(ps.rTmp);
+ ps.rTexSrc = ureg_src(ps.rTex);
+
+ for (s = 0; s < 8; ++s) {
+ ps.s[s] = ureg_src_undef();
+
+ if (key->ts[s].colorop != D3DTOP_DISABLE) {
+ if (key->ts[s].colorarg0 == D3DTA_SPECULAR ||
+ key->ts[s].colorarg1 == D3DTA_SPECULAR ||
+ key->ts[s].colorarg2 == D3DTA_SPECULAR)
+ ps.vC[1] = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_COLOR, 1, TGSI_INTERPOLATE_PERSPECTIVE);
+
+ if (key->ts[s].colorarg0 == D3DTA_TEXTURE ||
+ key->ts[s].colorarg1 == D3DTA_TEXTURE ||
+ key->ts[s].colorarg2 == D3DTA_TEXTURE) {
+ ps.s[s] = ureg_DECL_sampler(ureg, s);
+ ps.vT[s] = ureg_DECL_fs_input(ureg, texcoord_sn, s, TGSI_INTERPOLATE_PERSPECTIVE);
+ }
+ if (s && (key->ts[s - 1].colorop == D3DTOP_PREMODULATE ||
+ key->ts[s - 1].alphaop == D3DTOP_PREMODULATE))
+ ps.s[s] = ureg_DECL_sampler(ureg, s);
+ }
+
+ if (key->ts[s].alphaop != D3DTOP_DISABLE) {
+ if (key->ts[s].alphaarg0 == D3DTA_SPECULAR ||
+ key->ts[s].alphaarg1 == D3DTA_SPECULAR ||
+ key->ts[s].alphaarg2 == D3DTA_SPECULAR)
+ ps.vC[1] = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_COLOR, 1, TGSI_INTERPOLATE_PERSPECTIVE);
+
+ if (key->ts[s].alphaarg0 == D3DTA_TEXTURE ||
+ key->ts[s].alphaarg1 == D3DTA_TEXTURE ||
+ key->ts[s].alphaarg2 == D3DTA_TEXTURE) {
+ ps.s[s] = ureg_DECL_sampler(ureg, s);
+ ps.vT[s] = ureg_DECL_fs_input(ureg, texcoord_sn, s, TGSI_INTERPOLATE_PERSPECTIVE);
+ }
+ }
+ }
+ if (key->specular)
+ ps.vC[1] = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_COLOR, 1, TGSI_INTERPOLATE_PERSPECTIVE);
+
+ oCol = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
+
+ if (key->ts[0].colorop == D3DTOP_DISABLE &&
+ key->ts[0].alphaop == D3DTOP_DISABLE)
+ ureg_MOV(ureg, ps.rCur, ps.vC[0]);
+ /* Or is it undefined then ? */
+
+ /* Run stages.
+ */
+ for (s = 0; s < 8; ++s) {
+ unsigned colorarg[3];
+ unsigned alphaarg[3];
+ const uint8_t used_c = ps_d3dtop_args_mask(key->ts[s].colorop);
+ const uint8_t used_a = ps_d3dtop_args_mask(key->ts[s].alphaop);
+ struct ureg_dst dst;
+ struct ureg_src arg[3];
+
+ if (key->ts[s].colorop == D3DTOP_DISABLE &&
+ key->ts[s].alphaop == D3DTOP_DISABLE)
+ continue;
+ ps.stage.index = s;
+ ps.stage.num_regs = 3;
+
+ DBG("STAGE[%u]: colorop=%s alphaop=%s\n", s,
+ nine_D3DTOP_to_str(key->ts[s].colorop),
+ nine_D3DTOP_to_str(key->ts[s].alphaop));
+
+ if (!ureg_src_is_undef(ps.s[s])) {
+ unsigned target;
+ switch (key->ts[s].textarget) {
+ case 0: target = TGSI_TEXTURE_1D; break;
+ case 1: target = TGSI_TEXTURE_2D; break;
+ case 2: target = TGSI_TEXTURE_3D; break;
+ case 3: target = TGSI_TEXTURE_CUBE; break;
+ /* this is a 2 bit bitfield, do I really need a default case ? */
+ }
+
+ /* sample the texture */
+ if (key->ts[s].colorop == D3DTOP_BUMPENVMAP ||
+ key->ts[s].colorop == D3DTOP_BUMPENVMAPLUMINANCE) {
+ }
+ if (key->ts[s].projected)
+ ureg_TXP(ureg, ps.rTex, target, ps.vT[s], ps.s[s]);
+ else
+ ureg_TEX(ureg, ps.rTex, target, ps.vT[s], ps.s[s]);
+ }
+
+ if (s == 0 &&
+ (key->ts[0].resultarg != 0 /* not current */ ||
+ key->ts[0].colorop == D3DTOP_DISABLE ||
+ key->ts[0].alphaop == D3DTOP_DISABLE ||
+ key->ts[0].colorarg0 == D3DTA_CURRENT ||
+ key->ts[0].colorarg1 == D3DTA_CURRENT ||
+ key->ts[0].colorarg2 == D3DTA_CURRENT ||
+ key->ts[0].alphaarg0 == D3DTA_CURRENT ||
+ key->ts[0].alphaarg1 == D3DTA_CURRENT ||
+ key->ts[0].alphaarg2 == D3DTA_CURRENT)
+ ) {
+ /* Initialize D3DTA_CURRENT.
+ * (Yes we can do this before the loop but not until
+ * NVE4 has an instruction scheduling pass.)
+ */
+ ureg_MOV(ureg, ps.rCur, ps.vC[0]);
+ }
+
+ dst = ps_get_ts_dst(&ps, key->ts[s].resultarg ? D3DTA_TEMP : D3DTA_CURRENT);
+
+ if (ps.stage.index_pre_mod == ps.stage.index) {
+ ps.rMod = ps.r[ps.stage.num_regs++];
+ ureg_MUL(ureg, ps.rMod, ps.rCurSrc, ps.rTexSrc);
+ }
+
+ colorarg[0] = (key->ts[s].colorarg0 | ((key->colorarg_b4[0] >> s) << 4) | ((key->colorarg_b5[0] >> s) << 5)) & 0x3f;
+ colorarg[1] = (key->ts[s].colorarg1 | ((key->colorarg_b4[1] >> s) << 4) | ((key->colorarg_b5[1] >> s) << 5)) & 0x3f;
+ colorarg[2] = (key->ts[s].colorarg2 | ((key->colorarg_b4[2] >> s) << 4) | ((key->colorarg_b5[2] >> s) << 5)) & 0x3f;
+ alphaarg[0] = (key->ts[s].alphaarg0 | ((key->alphaarg_b4[0] >> s) << 4)) & 0x1f;
+ alphaarg[1] = (key->ts[s].alphaarg1 | ((key->alphaarg_b4[1] >> s) << 4)) & 0x1f;
+ alphaarg[2] = (key->ts[s].alphaarg2 | ((key->alphaarg_b4[2] >> s) << 4)) & 0x1f;
+
+ if (key->ts[s].colorop != key->ts[s].alphaop ||
+ colorarg[0] != alphaarg[0] ||
+ colorarg[1] != alphaarg[1] ||
+ colorarg[2] != alphaarg[2])
+ dst.WriteMask = TGSI_WRITEMASK_XYZ;
+
+ if (used_c & 0x1) arg[0] = ps_get_ts_arg(&ps, colorarg[0]);
+ if (used_c & 0x2) arg[1] = ps_get_ts_arg(&ps, colorarg[1]);
+ if (used_c & 0x4) arg[2] = ps_get_ts_arg(&ps, colorarg[2]);
+ ps_do_ts_op(&ps, key->ts[s].colorop, dst, arg);
+
+ if (dst.WriteMask != TGSI_WRITEMASK_XYZW) {
+ dst.WriteMask = TGSI_WRITEMASK_W;
+
+ if (used_a & 0x1) arg[0] = ps_get_ts_arg(&ps, alphaarg[0]);
+ if (used_a & 0x2) arg[1] = ps_get_ts_arg(&ps, alphaarg[1]);
+ if (used_a & 0x4) arg[2] = ps_get_ts_arg(&ps, alphaarg[2]);
+ ps_do_ts_op(&ps, key->ts[s].alphaop, dst, arg);
+ }
+ }
+
+ if (key->specular)
+ ureg_ADD(ureg, ps.rCur, ps.rCurSrc, ps.vC[1]);
+
+ /* Fog.
+ */
+ if (key->fog_mode) {
+ struct ureg_src vPos = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_POSITION, 0, TGSI_INTERPOLATE_LINEAR);
+ struct ureg_dst rFog = ureg_writemask(ps.rTmp, TGSI_WRITEMASK_X);
+ if (key->fog_mode == D3DFOG_EXP) {
+ ureg_MUL(ureg, rFog, _ZZZZ(vPos), _ZZZZ(_CONST(22)));
+ ureg_MUL(ureg, rFog, _X(rFog), ureg_imm1f(ureg, -1.442695f));
+ ureg_EX2(ureg, rFog, _X(rFog));
+ } else
+ if (key->fog_mode == D3DFOG_EXP2) {
+ ureg_MUL(ureg, rFog, _ZZZZ(vPos), _ZZZZ(_CONST(22)));
+ ureg_MUL(ureg, rFog, _X(rFog), _X(rFog));
+ ureg_MUL(ureg, rFog, _X(rFog), ureg_imm1f(ureg, -1.442695f));
+ ureg_EX2(ureg, rFog, _X(rFog));
+ } else
+ if (key->fog_mode == D3DFOG_LINEAR) {
+ ureg_SUB(ureg, rFog, _XXXX(_CONST(22)), _ZZZZ(vPos));
+ ureg_MUL(ureg, ureg_saturate(rFog), _X(rFog), _YYYY(_CONST(22)));
+ }
+ ureg_LRP(ureg, ureg_writemask(oCol, TGSI_WRITEMASK_XYZ), _X(rFog), ps.rCurSrc, _CONST(21));
+ ureg_MOV(ureg, ureg_writemask(oCol, TGSI_WRITEMASK_W), ps.rCurSrc);
+ } else
+ if (key->fog) {
+ struct ureg_src vFog = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_FOG, 0, TGSI_INTERPOLATE_PERSPECTIVE);
+ ureg_LRP(ureg, ureg_writemask(oCol, TGSI_WRITEMASK_XYZ), _XXXX(vFog), ps.rCurSrc, _CONST(21));
+ ureg_MOV(ureg, ureg_writemask(oCol, TGSI_WRITEMASK_W), ps.rCurSrc);
+ } else {
+ ureg_MOV(ureg, oCol, ps.rCurSrc);
+ }
+
+ ureg_END(ureg);
+ nine_ureg_tgsi_dump(ureg, FALSE);
+ return ureg_create_shader_and_destroy(ureg, device->pipe);
+}
+
+static struct NineVertexShader9 *
+nine_ff_get_vs(struct NineDevice9 *device)
+{
+ const struct nine_state *state = &device->state;
+ struct NineVertexShader9 *vs;
+ enum pipe_error err;
+ struct vs_build_ctx bld;
+ struct nine_ff_vs_key key;
+ unsigned s;
+
+ assert(sizeof(key) <= sizeof(key.value32));
+
+ memset(&key, 0, sizeof(key));
+ memset(&bld, 0, sizeof(bld));
+
+ bld.key = &key;
+
+ /* FIXME: this shouldn't be NULL, but it is on init */
+ if (state->vdecl) {
+ if (state->vdecl->usage_map[NINE_DECLUSAGE_POSITIONT] != 0xff)
+ key.position_t = 1;
+ if (state->vdecl->usage_map[NINE_DECLUSAGE_COLOR(0)] == 0xff)
+ key.color0in_one = 1;
+ if (state->vdecl->usage_map[NINE_DECLUSAGE_COLOR(1)] == 0xff)
+ key.color1in_one = 1;
+ if (state->vdecl->usage_map[NINE_DECLUSAGE_PSIZE] != 0xff)
+ key.vertexpointsize = 1;
+ }
+ if (!key.vertexpointsize)
+ key.pointscale = !!state->rs[D3DRS_POINTSCALEENABLE];
+
+ key.lighting = !!state->rs[D3DRS_LIGHTING] && state->ff.num_lights_active;
+ key.darkness = !!state->rs[D3DRS_LIGHTING] && !state->ff.num_lights_active;
+ if (key.position_t) {
+ key.darkness = 0; /* |= key.lighting; */ /* XXX ? */
+ key.lighting = 0;
+ }
+ if ((key.lighting | key.darkness) && state->rs[D3DRS_COLORVERTEX]) {
+ key.mtl_diffuse = state->rs[D3DRS_DIFFUSEMATERIALSOURCE];
+ key.mtl_ambient = state->rs[D3DRS_AMBIENTMATERIALSOURCE];
+ key.mtl_specular = state->rs[D3DRS_SPECULARMATERIALSOURCE];
+ key.mtl_emissive = state->rs[D3DRS_EMISSIVEMATERIALSOURCE];
+ }
+ key.fog_mode = state->rs[D3DRS_FOGENABLE] ? state->rs[D3DRS_FOGVERTEXMODE] : 0;
+ if (key.fog_mode)
+ key.fog_range = !key.position_t && state->rs[D3DRS_RANGEFOGENABLE];
+
+ if (state->rs[D3DRS_VERTEXBLEND] != D3DVBF_DISABLE) {
+ key.vertexblend_indexed = !!state->rs[D3DRS_INDEXEDVERTEXBLENDENABLE];
+
+ switch (state->rs[D3DRS_VERTEXBLEND]) {
+ case D3DVBF_0WEIGHTS: key.vertexblend = key.vertexblend_indexed; break;
+ case D3DVBF_1WEIGHTS: key.vertexblend = 2; break;
+ case D3DVBF_2WEIGHTS: key.vertexblend = 3; break;
+ case D3DVBF_3WEIGHTS: key.vertexblend = 4; break;
+ case D3DVBF_TWEENING: key.vertextween = 1; break;
+ default:
+ assert(!"invalid D3DVBF");
+ break;
+ }
+ }
+
+ for (s = 0; s < 8; ++s) {
+ if (state->ff.tex_stage[s][D3DTSS_COLOROP] == D3DTOP_DISABLE &&
+ state->ff.tex_stage[s][D3DTSS_ALPHAOP] == D3DTOP_DISABLE)
+ break;
+ key.tc_idx |= (state->ff.tex_stage[s][D3DTSS_TEXCOORDINDEX] & 7) << (s * 3);
+ if (!key.position_t) {
+ unsigned gen = (state->ff.tex_stage[s][D3DTSS_TEXCOORDINDEX] >> 16) + 1;
+ unsigned dim = MIN2(state->ff.tex_stage[s][D3DTSS_TEXTURETRANSFORMFLAGS] & 0x7, 4);
+ key.tc_gen |= gen << (s * 3);
+ key.tc_dim |= dim << (s * 3);
+ } else {
+ key.tc_gen |= NINED3DTSS_TCI_PASSTHRU << (s * 3);
+ }
+ }
+
+ vs = util_hash_table_get(device->ff.ht_vs, &key);
+ if (vs)
+ return vs;
+ NineVertexShader9_new(device, &vs, NULL, nine_ff_build_vs(device, &bld));
+
+ nine_ff_prune_vs(device);
+ if (vs) {
+ unsigned n;
+
+ memcpy(&vs->ff_key, &key, sizeof(vs->ff_key));
+
+ err = util_hash_table_set(device->ff.ht_vs, &vs->ff_key, vs);
+ assert(err == PIPE_OK);
+ device->ff.num_vs++;
+ NineUnknown_ConvertRefToBind(NineUnknown(vs));
+
+ vs->num_inputs = bld.num_inputs;
+ for (n = 0; n < bld.num_inputs; ++n)
+ vs->input_map[n].ndecl = bld.input[n];
+
+ vs->position_t = key.position_t;
+ vs->point_size = key.vertexpointsize | key.pointscale;
+ }
+ return vs;
+}
+
+static struct NinePixelShader9 *
+nine_ff_get_ps(struct NineDevice9 *device)
+{
+ struct nine_state *state = &device->state;
+ struct NinePixelShader9 *ps;
+ enum pipe_error err;
+ struct nine_ff_ps_key key;
+ unsigned s;
+
+ assert(sizeof(key) <= sizeof(key.value32));
+
+ memset(&key, 0, sizeof(key));
+ for (s = 0; s < 8; ++s) {
+ key.ts[s].colorop = state->ff.tex_stage[s][D3DTSS_COLOROP];
+ key.ts[s].alphaop = state->ff.tex_stage[s][D3DTSS_ALPHAOP];
+ /* MSDN says D3DTOP_DISABLE disables this and all subsequent stages. */
+ /* ALPHAOP cannot be disabled if COLOROP is enabled. */
+ if (key.ts[s].colorop == D3DTOP_DISABLE) {
+ key.ts[s].alphaop = D3DTOP_DISABLE; /* DISABLE == 1, avoid degenerate keys */
+ break;
+ }
+ if (!state->texture[s] &&
+ state->ff.tex_stage[s][D3DTSS_COLORARG1] == D3DTA_TEXTURE) {
+ /* This should also disable the stage. */
+ key.ts[s].colorop = key.ts[s].alphaop = D3DTOP_DISABLE;
+ break;
+ }
+ if (key.ts[s].colorop != D3DTOP_DISABLE) {
+ uint8_t used_c = ps_d3dtop_args_mask(key.ts[s].colorop);
+ if (used_c & 0x1) key.ts[s].colorarg0 = state->ff.tex_stage[s][D3DTSS_COLORARG0];
+ if (used_c & 0x2) key.ts[s].colorarg1 = state->ff.tex_stage[s][D3DTSS_COLORARG1];
+ if (used_c & 0x4) key.ts[s].colorarg2 = state->ff.tex_stage[s][D3DTSS_COLORARG2];
+ if (used_c & 0x1) key.colorarg_b4[0] |= (state->ff.tex_stage[s][D3DTSS_COLORARG0] >> 4) << s;
+ if (used_c & 0x1) key.colorarg_b5[0] |= (state->ff.tex_stage[s][D3DTSS_COLORARG0] >> 5) << s;
+ if (used_c & 0x2) key.colorarg_b4[1] |= (state->ff.tex_stage[s][D3DTSS_COLORARG1] >> 4) << s;
+ if (used_c & 0x2) key.colorarg_b5[1] |= (state->ff.tex_stage[s][D3DTSS_COLORARG1] >> 5) << s;
+ if (used_c & 0x4) key.colorarg_b4[2] |= (state->ff.tex_stage[s][D3DTSS_COLORARG2] >> 4) << s;
+ if (used_c & 0x4) key.colorarg_b5[2] |= (state->ff.tex_stage[s][D3DTSS_COLORARG2] >> 5) << s;
+ }
+ if (key.ts[s].alphaop != D3DTOP_DISABLE) {
+ uint8_t used_a = ps_d3dtop_args_mask(key.ts[s].alphaop);
+ if (used_a & 0x1) key.ts[s].alphaarg0 = state->ff.tex_stage[s][D3DTSS_ALPHAARG0];
+ if (used_a & 0x2) key.ts[s].alphaarg1 = state->ff.tex_stage[s][D3DTSS_ALPHAARG1];
+ if (used_a & 0x4) key.ts[s].alphaarg2 = state->ff.tex_stage[s][D3DTSS_ALPHAARG2];
+ if (used_a & 0x1) key.alphaarg_b4[0] |= (state->ff.tex_stage[s][D3DTSS_ALPHAARG0] >> 4) << s;
+ if (used_a & 0x2) key.alphaarg_b4[1] |= (state->ff.tex_stage[s][D3DTSS_ALPHAARG1] >> 4) << s;
+ if (used_a & 0x4) key.alphaarg_b4[2] |= (state->ff.tex_stage[s][D3DTSS_ALPHAARG2] >> 4) << s;
+ }
+ key.ts[s].resultarg = state->ff.tex_stage[s][D3DTSS_RESULTARG] == D3DTA_TEMP;
+
+ key.ts[s].projected = !!(state->ff.tex_stage[s][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
+
+ if (state->texture[s]) {
+ switch (state->texture[s]->base.type) {
+ case D3DRTYPE_TEXTURE: key.ts[s].textarget = 1; break;
+ case D3DRTYPE_VOLUMETEXTURE: key.ts[s].textarget = 2; break;
+ case D3DRTYPE_CUBETEXTURE: key.ts[s].textarget = 3; break;
+ default:
+ assert(!"unexpected texture type");
+ break;
+ }
+ } else {
+ key.ts[s].textarget = 1;
+ }
+ }
+ for (; s < 8; ++s)
+ key.ts[s].colorop = key.ts[s].alphaop = D3DTOP_DISABLE;
+ if (state->rs[D3DRS_FOGENABLE])
+ key.fog_mode = state->rs[D3DRS_FOGTABLEMODE];
+
+ ps = util_hash_table_get(device->ff.ht_ps, &key);
+ if (ps)
+ return ps;
+ NinePixelShader9_new(device, &ps, NULL, nine_ff_build_ps(device, &key));
+
+ nine_ff_prune_ps(device);
+ if (ps) {
+ memcpy(&ps->ff_key, &key, sizeof(ps->ff_key));
+
+ err = util_hash_table_set(device->ff.ht_ps, &ps->ff_key, ps);
+ assert(err == PIPE_OK);
+ device->ff.num_ps++;
+ NineUnknown_ConvertRefToBind(NineUnknown(ps));
+
+ ps->rt_mask = 0x1;
+ }
+ return ps;
+}
+
+#define GET_D3DTS(n) nine_state_access_transform(state, D3DTS_##n, FALSE)
+#define IS_D3DTS_DIRTY(s,n) ((s)->ff.changed.transform[(D3DTS_##n) / 32] & (1 << ((D3DTS_##n) % 32)))
+static void
+nine_ff_load_vs_transforms(struct NineDevice9 *device)
+{
+ struct nine_state *state = &device->state;
+ D3DMATRIX T;
+ D3DMATRIX *M = (D3DMATRIX *)device->ff.vs_const;
+ unsigned i;
+
+ /* TODO: make this nicer, and only upload the ones we need */
+ /* TODO: use ff.vs_const as storage of W, V, P matrices */
+
+ if (IS_D3DTS_DIRTY(state, WORLD) ||
+ IS_D3DTS_DIRTY(state, VIEW) ||
+ IS_D3DTS_DIRTY(state, PROJECTION)) {
+ /* WVP, WV matrices */
+ nine_d3d_matrix_matrix_mul(&M[1], GET_D3DTS(WORLD), GET_D3DTS(VIEW));
+ nine_d3d_matrix_matrix_mul(&M[0], &M[1], GET_D3DTS(PROJECTION));
+
+ /* normal matrix == transpose(inverse(WV)) */
+ nine_d3d_matrix_inverse_3x3(&T, &M[1]);
+ nine_d3d_matrix_transpose(&M[4], &T);
+
+ /* VP matrix */
+ nine_d3d_matrix_matrix_mul(&M[2], GET_D3DTS(VIEW), GET_D3DTS(PROJECTION));
+
+ /* V and W matrix */
+ M[3] = *GET_D3DTS(VIEW);
+ M[56] = *GET_D3DTS(WORLD);
+ }
+
+ if (state->rs[D3DRS_VERTEXBLEND] != D3DVBF_DISABLE) {
+ /* load other world matrices */
+ for (i = 1; i <= 7; ++i)
+ M[56 + i] = *GET_D3DTS(WORLDMATRIX(i));
+ }
+
+ device->ff.vs_const[30 * 4] = asfloat(state->rs[D3DRS_TWEENFACTOR]);
+}
+
+static void
+nine_ff_load_lights(struct NineDevice9 *device)
+{
+ struct nine_state *state = &device->state;
+ struct fvec4 *dst = (struct fvec4 *)device->ff.vs_const;
+ unsigned l;
+
+ if (state->changed.group & NINE_STATE_FF_MATERIAL) {
+ const D3DMATERIAL9 *mtl = &state->ff.material;
+
+ memcpy(&dst[20], &mtl->Diffuse, 4 * sizeof(float));
+ memcpy(&dst[21], &mtl->Ambient, 4 * sizeof(float));
+ memcpy(&dst[22], &mtl->Specular, 4 * sizeof(float));
+ dst[23].x = mtl->Power;
+ memcpy(&dst[24], &mtl->Emissive, 4 * sizeof(float));
+ d3dcolor_to_rgba(&dst[25].x, state->rs[D3DRS_AMBIENT]);
+ dst[19].x = dst[25].x * mtl->Ambient.r + mtl->Emissive.r;
+ dst[19].y = dst[25].y * mtl->Ambient.g + mtl->Emissive.g;
+ dst[19].z = dst[25].z * mtl->Ambient.b + mtl->Emissive.b;
+ dst[19].w = mtl->Ambient.a + mtl->Emissive.a;
+ }
+
+ if (!(state->changed.group & NINE_STATE_FF_LIGHTING))
+ return;
+
+ for (l = 0; l < state->ff.num_lights_active; ++l) {
+ const D3DLIGHT9 *light = &state->ff.light[state->ff.active_light[l]];
+
+ dst[32 + l * 8].x = light->Type;
+ dst[32 + l * 8].y = light->Attenuation0;
+ dst[32 + l * 8].z = light->Attenuation1;
+ dst[32 + l * 8].w = light->Attenuation2;
+ memcpy(&dst[33 + l * 8].x, &light->Diffuse, sizeof(light->Diffuse));
+ memcpy(&dst[34 + l * 8].x, &light->Specular, sizeof(light->Specular));
+ memcpy(&dst[35 + l * 8].x, &light->Ambient, sizeof(light->Ambient));
+ nine_d3d_vector4_matrix_mul((D3DVECTOR *)&dst[36 + l * 8].x, &light->Position, GET_D3DTS(VIEW));
+ nine_d3d_vector3_matrix_mul((D3DVECTOR *)&dst[37 + l * 8].x, &light->Direction, GET_D3DTS(VIEW));
+ dst[36 + l * 8].w = light->Type == D3DLIGHT_DIRECTIONAL ? 1e9f : light->Range;
+ dst[37 + l * 8].w = light->Falloff;
+ dst[38 + l * 8].x = cosf(light->Theta * 0.5f);
+ dst[38 + l * 8].y = cosf(light->Phi * 0.5f);
+ dst[38 + l * 8].z = 1.0f / (dst[38 + l * 8].x - dst[38 + l * 8].y);
+ dst[39 + l * 8].w = (l + 1) == state->ff.num_lights_active;
+ }
+}
+
+static void
+nine_ff_load_point_and_fog_params(struct NineDevice9 *device)
+{
+ const struct nine_state *state = &device->state;
+ struct fvec4 *dst = (struct fvec4 *)device->ff.vs_const;
+
+ if (!(state->changed.group & NINE_STATE_FF_OTHER))
+ return;
+ dst[26].x = asfloat(state->rs[D3DRS_POINTSIZE_MIN]);
+ dst[26].y = asfloat(state->rs[D3DRS_POINTSIZE_MAX]);
+ dst[26].z = asfloat(state->rs[D3DRS_POINTSIZE]);
+ dst[26].w = asfloat(state->rs[D3DRS_POINTSCALE_A]);
+ dst[27].x = asfloat(state->rs[D3DRS_POINTSCALE_B]);
+ dst[27].y = asfloat(state->rs[D3DRS_POINTSCALE_C]);
+ dst[28].x = asfloat(state->rs[D3DRS_FOGEND]);
+ dst[28].y = 1.0f / (asfloat(state->rs[D3DRS_FOGEND]) - asfloat(state->rs[D3DRS_FOGSTART]));
+ if (isinf(dst[28].y))
+ dst[28].y = 0.0f;
+ dst[28].z = asfloat(state->rs[D3DRS_FOGDENSITY]);
+ d3dcolor_to_rgba(&dst[29].x, state->rs[D3DRS_FOGCOLOR]);
+}
+
+static void
+nine_ff_load_tex_matrices(struct NineDevice9 *device)
+{
+ struct nine_state *state = &device->state;
+ D3DMATRIX *M = (D3DMATRIX *)device->ff.vs_const;
+ unsigned s;
+
+ if (!(state->ff.changed.transform[0] & 0xff0000))
+ return;
+ for (s = 0; s < 8; ++s) {
+ if (IS_D3DTS_DIRTY(state, TEXTURE0 + s))
+ M[32 + s] = *nine_state_access_transform(state, D3DTS_TEXTURE0 + s, FALSE);
+ }
+}
+
+static void
+nine_ff_load_ps_params(struct NineDevice9 *device)
+{
+ const struct nine_state *state = &device->state;
+ struct fvec4 *dst = (struct fvec4 *)device->ff.ps_const;
+ unsigned s;
+
+ if (!(state->changed.group & (NINE_STATE_FF_PSSTAGES | NINE_STATE_FF_OTHER)))
+ return;
+
+ for (s = 0; s < 8; ++s)
+ d3dcolor_to_rgba(&dst[s].x, state->ff.tex_stage[s][D3DTSS_CONSTANT]);
+
+ for (s = 0; s < 8; ++s) {
+ dst[8 + s].x = asfloat(state->ff.tex_stage[s][D3DTSS_BUMPENVMAT00]);
+ dst[8 + s].y = asfloat(state->ff.tex_stage[s][D3DTSS_BUMPENVMAT01]);
+ dst[8 + s].z = asfloat(state->ff.tex_stage[s][D3DTSS_BUMPENVMAT10]);
+ dst[8 + s].w = asfloat(state->ff.tex_stage[s][D3DTSS_BUMPENVMAT11]);
+ if (s & 1) {
+ dst[8 + s / 2].z = asfloat(state->ff.tex_stage[s][D3DTSS_BUMPENVLSCALE]);
+ dst[8 + s / 2].w = asfloat(state->ff.tex_stage[s][D3DTSS_BUMPENVLOFFSET]);
+ } else {
+ dst[8 + s / 2].x = asfloat(state->ff.tex_stage[s][D3DTSS_BUMPENVLSCALE]);
+ dst[8 + s / 2].y = asfloat(state->ff.tex_stage[s][D3DTSS_BUMPENVLOFFSET]);
+ }
+ }
+
+ d3dcolor_to_rgba(&dst[20].x, state->rs[D3DRS_TEXTUREFACTOR]);
+ d3dcolor_to_rgba(&dst[21].x, state->rs[D3DRS_FOGCOLOR]);
+ dst[22].x = asfloat(state->rs[D3DRS_FOGEND]);
+ dst[22].y = 1.0f / (asfloat(state->rs[D3DRS_FOGEND]) - asfloat(state->rs[D3DRS_FOGSTART]));
+ dst[22].z = asfloat(state->rs[D3DRS_FOGDENSITY]);
+}
+
+static void
+nine_ff_load_viewport_info(struct NineDevice9 *device)
+{
+ D3DVIEWPORT9 *viewport = &device->state.viewport;
+ struct fvec4 *dst = (struct fvec4 *)device->ff.vs_const;
+ float diffZ = viewport->MaxZ - viewport->MinZ;
+
+ /* Note: the other functions avoids to fill the const again if nothing changed.
+ * But we don't have much to fill, and adding code to allow that may be complex
+ * so just fill it always */
+ dst[100].x = 2.0f / (float)(viewport->Width);
+ dst[100].y = 2.0f / (float)(viewport->Height);
+ dst[100].z = (diffZ == 0.0f) ? 0.0f : (1.0f / diffZ);
+ dst[101].x = (float)(viewport->X);
+ dst[101].y = (float)(viewport->Y);
+ dst[101].z = (float)(viewport->MinZ);
+}
+
+void
+nine_ff_update(struct NineDevice9 *device)
+{
+ struct pipe_context *pipe = device->pipe;
+ struct nine_state *state = &device->state;
+
+ DBG("vs=%p ps=%p\n", device->state.vs, device->state.ps);
+
+ /* NOTE: the only reference belongs to the hash table */
+ if (!device->state.vs)
+ device->ff.vs = nine_ff_get_vs(device);
+ if (!device->state.ps)
+ device->ff.ps = nine_ff_get_ps(device);
+
+ if (!device->state.vs) {
+ if (device->state.ff.clobber.vs_const) {
+ device->state.ff.clobber.vs_const = FALSE;
+ device->state.changed.group |=
+ NINE_STATE_FF_VSTRANSF |
+ NINE_STATE_FF_MATERIAL |
+ NINE_STATE_FF_LIGHTING |
+ NINE_STATE_FF_OTHER;
+ device->state.ff.changed.transform[0] |= 0xff000c;
+ device->state.ff.changed.transform[8] |= 0xff;
+ }
+ nine_ff_load_vs_transforms(device);
+ nine_ff_load_tex_matrices(device);
+ nine_ff_load_lights(device);
+ nine_ff_load_point_and_fog_params(device);
+ nine_ff_load_viewport_info(device);
+
+ memset(state->ff.changed.transform, 0, sizeof(state->ff.changed.transform));
+
+ device->state.changed.group |= NINE_STATE_VS;
+ device->state.changed.group |= NINE_STATE_VS_CONST;
+
+ if (device->prefer_user_constbuf) {
+ struct pipe_context *pipe = device->pipe;
+ struct pipe_constant_buffer cb;
+ cb.buffer_offset = 0;
+ cb.buffer = NULL;
+ cb.user_buffer = device->ff.vs_const;
+ cb.buffer_size = NINE_FF_NUM_VS_CONST * 4 * sizeof(float);
+ pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &cb);
+ } else {
+ struct pipe_box box;
+ u_box_1d(0, NINE_FF_NUM_VS_CONST * 4 * sizeof(float), &box);
+ pipe->transfer_inline_write(pipe, device->constbuf_vs, 0,
+ 0, &box,
+ device->ff.vs_const, 0, 0);
+ nine_ranges_insert(&device->state.changed.vs_const_f, 0, NINE_FF_NUM_VS_CONST,
+ &device->range_pool);
+ }
+ }
+
+ if (!device->state.ps) {
+ if (device->state.ff.clobber.ps_const) {
+ device->state.ff.clobber.ps_const = FALSE;
+ device->state.changed.group |=
+ NINE_STATE_FF_PSSTAGES |
+ NINE_STATE_FF_OTHER;
+ }
+ nine_ff_load_ps_params(device);
+
+ device->state.changed.group |= NINE_STATE_PS;
+ device->state.changed.group |= NINE_STATE_PS_CONST;
+
+ if (device->prefer_user_constbuf) {
+ struct pipe_context *pipe = device->pipe;
+ struct pipe_constant_buffer cb;
+ cb.buffer_offset = 0;
+ cb.buffer = NULL;
+ cb.user_buffer = device->ff.ps_const;
+ cb.buffer_size = NINE_FF_NUM_PS_CONST * 4 * sizeof(float);
+ pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &cb);
+ } else {
+ struct pipe_box box;
+ u_box_1d(0, NINE_FF_NUM_PS_CONST * 4 * sizeof(float), &box);
+ pipe->transfer_inline_write(pipe, device->constbuf_ps, 0,
+ 0, &box,
+ device->ff.ps_const, 0, 0);
+ nine_ranges_insert(&device->state.changed.ps_const_f, 0, NINE_FF_NUM_PS_CONST,
+ &device->range_pool);
+ }
+ }
+
+ device->state.changed.group &= ~NINE_STATE_FF;
+}
+
+
+boolean
+nine_ff_init(struct NineDevice9 *device)
+{
+ device->ff.ht_vs = util_hash_table_create(nine_ff_vs_key_hash,
+ nine_ff_vs_key_comp);
+ device->ff.ht_ps = util_hash_table_create(nine_ff_ps_key_hash,
+ nine_ff_ps_key_comp);
+
+ device->ff.ht_fvf = util_hash_table_create(nine_ff_fvf_key_hash,
+ nine_ff_fvf_key_comp);
+
+ device->ff.vs_const = CALLOC(NINE_FF_NUM_VS_CONST, 4 * sizeof(float));
+ device->ff.ps_const = CALLOC(NINE_FF_NUM_PS_CONST, 4 * sizeof(float));
+
+ return device->ff.ht_vs && device->ff.ht_ps &&
+ device->ff.ht_fvf &&
+ device->ff.vs_const && device->ff.ps_const;
+}
+
+static enum pipe_error nine_ff_ht_delete_cb(void *key, void *value, void *data)
+{
+ NineUnknown_Unbind(NineUnknown(value));
+ return PIPE_OK;
+}
+
+void
+nine_ff_fini(struct NineDevice9 *device)
+{
+ if (device->ff.ht_vs) {
+ util_hash_table_foreach(device->ff.ht_vs, nine_ff_ht_delete_cb, NULL);
+ util_hash_table_destroy(device->ff.ht_vs);
+ }
+ if (device->ff.ht_ps) {
+ util_hash_table_foreach(device->ff.ht_ps, nine_ff_ht_delete_cb, NULL);
+ util_hash_table_destroy(device->ff.ht_ps);
+ }
+ if (device->ff.ht_fvf) {
+ util_hash_table_foreach(device->ff.ht_fvf, nine_ff_ht_delete_cb, NULL);
+ util_hash_table_destroy(device->ff.ht_fvf);
+ }
+ device->ff.vs = NULL; /* destroyed by unbinding from hash table */
+ device->ff.ps = NULL;
+
+ FREE(device->ff.vs_const);
+ FREE(device->ff.ps_const);
+}
+
+static void
+nine_ff_prune_vs(struct NineDevice9 *device)
+{
+ if (device->ff.num_vs > 100) {
+ /* could destroy the bound one here, so unbind */
+ device->pipe->bind_vs_state(device->pipe, NULL);
+ util_hash_table_foreach(device->ff.ht_vs, nine_ff_ht_delete_cb, NULL);
+ util_hash_table_clear(device->ff.ht_vs);
+ device->ff.num_vs = 0;
+ device->state.changed.group |= NINE_STATE_VS;
+ }
+}
+static void
+nine_ff_prune_ps(struct NineDevice9 *device)
+{
+ if (device->ff.num_ps > 100) {
+ /* could destroy the bound one here, so unbind */
+ device->pipe->bind_fs_state(device->pipe, NULL);
+ util_hash_table_foreach(device->ff.ht_ps, nine_ff_ht_delete_cb, NULL);
+ util_hash_table_clear(device->ff.ht_ps);
+ device->ff.num_ps = 0;
+ device->state.changed.group |= NINE_STATE_PS;
+ }
+}
+
+/* ========================================================================== */
+
+/* Matrix multiplication:
+ *
+ * in memory: 0 1 2 3 (row major)
+ * 4 5 6 7
+ * 8 9 a b
+ * c d e f
+ *
+ * cA cB cC cD
+ * r0 = (r0 * cA) (r0 * cB) . .
+ * r1 = (r1 * cA) (r1 * cB)
+ * r2 = (r2 * cA) .
+ * r3 = (r3 * cA) .
+ *
+ * r: (11) (12) (13) (14)
+ * (21) (22) (23) (24)
+ * (31) (32) (33) (34)
+ * (41) (42) (43) (44)
+ * l: (11 12 13 14)
+ * (21 22 23 24)
+ * (31 32 33 34)
+ * (41 42 43 44)
+ *
+ * v: (x y z 1 )
+ *
+ * t.xyzw = MUL(v.xxxx, r[0]);
+ * t.xyzw = MAD(v.yyyy, r[1], t.xyzw);
+ * t.xyzw = MAD(v.zzzz, r[2], t.xyzw);
+ * v.xyzw = MAD(v.wwww, r[3], t.xyzw);
+ *
+ * v.x = DP4(v, c[0]);
+ * v.y = DP4(v, c[1]);
+ * v.z = DP4(v, c[2]);
+ * v.w = DP4(v, c[3]) = 1
+ */
+
+/*
+static void
+nine_D3DMATRIX_print(const D3DMATRIX *M)
+{
+ DBG("\n(%f %f %f %f)\n"
+ "(%f %f %f %f)\n"
+ "(%f %f %f %f)\n"
+ "(%f %f %f %f)\n",
+ M->m[0][0], M->m[0][1], M->m[0][2], M->m[0][3],
+ M->m[1][0], M->m[1][1], M->m[1][2], M->m[1][3],
+ M->m[2][0], M->m[2][1], M->m[2][2], M->m[2][3],
+ M->m[3][0], M->m[3][1], M->m[3][2], M->m[3][3]);
+}
+*/
+
+static INLINE float
+nine_DP4_row_col(const D3DMATRIX *A, int r, const D3DMATRIX *B, int c)
+{
+ return A->m[r][0] * B->m[0][c] +
+ A->m[r][1] * B->m[1][c] +
+ A->m[r][2] * B->m[2][c] +
+ A->m[r][3] * B->m[3][c];
+}
+
+static INLINE float
+nine_DP4_vec_col(const D3DVECTOR *v, const D3DMATRIX *M, int c)
+{
+ return v->x * M->m[0][c] +
+ v->y * M->m[1][c] +
+ v->z * M->m[2][c] +
+ 1.0f * M->m[3][c];
+}
+
+static INLINE float
+nine_DP3_vec_col(const D3DVECTOR *v, const D3DMATRIX *M, int c)
+{
+ return v->x * M->m[0][c] +
+ v->y * M->m[1][c] +
+ v->z * M->m[2][c];
+}
+
+void
+nine_d3d_matrix_matrix_mul(D3DMATRIX *D, const D3DMATRIX *L, const D3DMATRIX *R)
+{
+ D->_11 = nine_DP4_row_col(L, 0, R, 0);
+ D->_12 = nine_DP4_row_col(L, 0, R, 1);
+ D->_13 = nine_DP4_row_col(L, 0, R, 2);
+ D->_14 = nine_DP4_row_col(L, 0, R, 3);
+
+ D->_21 = nine_DP4_row_col(L, 1, R, 0);
+ D->_22 = nine_DP4_row_col(L, 1, R, 1);
+ D->_23 = nine_DP4_row_col(L, 1, R, 2);
+ D->_24 = nine_DP4_row_col(L, 1, R, 3);
+
+ D->_31 = nine_DP4_row_col(L, 2, R, 0);
+ D->_32 = nine_DP4_row_col(L, 2, R, 1);
+ D->_33 = nine_DP4_row_col(L, 2, R, 2);
+ D->_34 = nine_DP4_row_col(L, 2, R, 3);
+
+ D->_41 = nine_DP4_row_col(L, 3, R, 0);
+ D->_42 = nine_DP4_row_col(L, 3, R, 1);
+ D->_43 = nine_DP4_row_col(L, 3, R, 2);
+ D->_44 = nine_DP4_row_col(L, 3, R, 3);
+}
+
+void
+nine_d3d_vector4_matrix_mul(D3DVECTOR *d, const D3DVECTOR *v, const D3DMATRIX *M)
+{
+ d->x = nine_DP4_vec_col(v, M, 0);
+ d->y = nine_DP4_vec_col(v, M, 1);
+ d->z = nine_DP4_vec_col(v, M, 2);
+}
+
+void
+nine_d3d_vector3_matrix_mul(D3DVECTOR *d, const D3DVECTOR *v, const D3DMATRIX *M)
+{
+ d->x = nine_DP3_vec_col(v, M, 0);
+ d->y = nine_DP3_vec_col(v, M, 1);
+ d->z = nine_DP3_vec_col(v, M, 2);
+}
+
+void
+nine_d3d_matrix_transpose(D3DMATRIX *D, const D3DMATRIX *M)
+{
+ unsigned i, j;
+ for (i = 0; i < 4; ++i)
+ for (j = 0; j < 4; ++j)
+ D->m[i][j] = M->m[j][i];
+}
+
+#define _M_ADD_PROD_1i_2j_3k_4l(i,j,k,l) do { \
+ float t = M->_1##i * M->_2##j * M->_3##k * M->_4##l; \
+ if (t > 0.0f) pos += t; else neg += t; } while(0)
+
+#define _M_SUB_PROD_1i_2j_3k_4l(i,j,k,l) do { \
+ float t = M->_1##i * M->_2##j * M->_3##k * M->_4##l; \
+ if (t > 0.0f) neg -= t; else pos -= t; } while(0)
+float
+nine_d3d_matrix_det(const D3DMATRIX *M)
+{
+ float pos = 0.0f;
+ float neg = 0.0f;
+
+ _M_ADD_PROD_1i_2j_3k_4l(1, 2, 3, 4);
+ _M_ADD_PROD_1i_2j_3k_4l(1, 3, 4, 2);
+ _M_ADD_PROD_1i_2j_3k_4l(1, 4, 2, 3);
+
+ _M_ADD_PROD_1i_2j_3k_4l(2, 1, 4, 3);
+ _M_ADD_PROD_1i_2j_3k_4l(2, 3, 1, 4);
+ _M_ADD_PROD_1i_2j_3k_4l(2, 4, 3, 1);
+
+ _M_ADD_PROD_1i_2j_3k_4l(3, 1, 2, 4);
+ _M_ADD_PROD_1i_2j_3k_4l(3, 2, 4, 1);
+ _M_ADD_PROD_1i_2j_3k_4l(3, 4, 1, 2);
+
+ _M_ADD_PROD_1i_2j_3k_4l(4, 1, 3, 2);
+ _M_ADD_PROD_1i_2j_3k_4l(4, 2, 1, 3);
+ _M_ADD_PROD_1i_2j_3k_4l(4, 3, 2, 1);
+
+ _M_SUB_PROD_1i_2j_3k_4l(1, 2, 4, 3);
+ _M_SUB_PROD_1i_2j_3k_4l(1, 3, 2, 4);
+ _M_SUB_PROD_1i_2j_3k_4l(1, 4, 3, 2);
+
+ _M_SUB_PROD_1i_2j_3k_4l(2, 1, 3, 4);
+ _M_SUB_PROD_1i_2j_3k_4l(2, 3, 4, 1);
+ _M_SUB_PROD_1i_2j_3k_4l(2, 4, 1, 3);
+
+ _M_SUB_PROD_1i_2j_3k_4l(3, 1, 4, 2);
+ _M_SUB_PROD_1i_2j_3k_4l(3, 2, 1, 4);
+ _M_SUB_PROD_1i_2j_3k_4l(3, 4, 2, 1);
+
+ _M_SUB_PROD_1i_2j_3k_4l(4, 1, 2, 3);
+ _M_SUB_PROD_1i_2j_3k_4l(4, 2, 3, 1);
+ _M_SUB_PROD_1i_2j_3k_4l(4, 3, 1, 2);
+
+ return pos + neg;
+}
+
+/* XXX: Probably better to just use src/mesa/math/m_matrix.c because
+ * I have no idea where this code came from.
+ */
+void
+nine_d3d_matrix_inverse(D3DMATRIX *D, const D3DMATRIX *M)
+{
+ int i, k;
+ float det;
+
+ D->m[0][0] =
+ M->m[1][1] * M->m[2][2] * M->m[3][3] -
+ M->m[1][1] * M->m[3][2] * M->m[2][3] -
+ M->m[1][2] * M->m[2][1] * M->m[3][3] +
+ M->m[1][2] * M->m[3][1] * M->m[2][3] +
+ M->m[1][3] * M->m[2][1] * M->m[3][2] -
+ M->m[1][3] * M->m[3][1] * M->m[2][2];
+
+ D->m[0][1] =
+ -M->m[0][1] * M->m[2][2] * M->m[3][3] +
+ M->m[0][1] * M->m[3][2] * M->m[2][3] +
+ M->m[0][2] * M->m[2][1] * M->m[3][3] -
+ M->m[0][2] * M->m[3][1] * M->m[2][3] -
+ M->m[0][3] * M->m[2][1] * M->m[3][2] +
+ M->m[0][3] * M->m[3][1] * M->m[2][2];
+
+ D->m[0][2] =
+ M->m[0][1] * M->m[1][2] * M->m[3][3] -
+ M->m[0][1] * M->m[3][2] * M->m[1][3] -
+ M->m[0][2] * M->m[1][1] * M->m[3][3] +
+ M->m[0][2] * M->m[3][1] * M->m[1][3] +
+ M->m[0][3] * M->m[1][1] * M->m[3][2] -
+ M->m[0][3] * M->m[3][1] * M->m[1][2];
+
+ D->m[0][3] =
+ -M->m[0][1] * M->m[1][2] * M->m[2][3] +
+ M->m[0][1] * M->m[2][2] * M->m[1][3] +
+ M->m[0][2] * M->m[1][1] * M->m[2][3] -
+ M->m[0][2] * M->m[2][1] * M->m[1][3] -
+ M->m[0][3] * M->m[1][1] * M->m[2][2] +
+ M->m[0][3] * M->m[2][1] * M->m[1][2];
+
+ D->m[1][0] =
+ -M->m[1][0] * M->m[2][2] * M->m[3][3] +
+ M->m[1][0] * M->m[3][2] * M->m[2][3] +
+ M->m[1][2] * M->m[2][0] * M->m[3][3] -
+ M->m[1][2] * M->m[3][0] * M->m[2][3] -
+ M->m[1][3] * M->m[2][0] * M->m[3][2] +
+ M->m[1][3] * M->m[3][0] * M->m[2][2];
+
+ D->m[1][1] =
+ M->m[0][0] * M->m[2][2] * M->m[3][3] -
+ M->m[0][0] * M->m[3][2] * M->m[2][3] -
+ M->m[0][2] * M->m[2][0] * M->m[3][3] +
+ M->m[0][2] * M->m[3][0] * M->m[2][3] +
+ M->m[0][3] * M->m[2][0] * M->m[3][2] -
+ M->m[0][3] * M->m[3][0] * M->m[2][2];
+
+ D->m[1][2] =
+ -M->m[0][0] * M->m[1][2] * M->m[3][3] +
+ M->m[0][0] * M->m[3][2] * M->m[1][3] +
+ M->m[0][2] * M->m[1][0] * M->m[3][3] -
+ M->m[0][2] * M->m[3][0] * M->m[1][3] -
+ M->m[0][3] * M->m[1][0] * M->m[3][2] +
+ M->m[0][3] * M->m[3][0] * M->m[1][2];
+
+ D->m[1][3] =
+ M->m[0][0] * M->m[1][2] * M->m[2][3] -
+ M->m[0][0] * M->m[2][2] * M->m[1][3] -
+ M->m[0][2] * M->m[1][0] * M->m[2][3] +
+ M->m[0][2] * M->m[2][0] * M->m[1][3] +
+ M->m[0][3] * M->m[1][0] * M->m[2][2] -
+ M->m[0][3] * M->m[2][0] * M->m[1][2];
+
+ D->m[2][0] =
+ M->m[1][0] * M->m[2][1] * M->m[3][3] -
+ M->m[1][0] * M->m[3][1] * M->m[2][3] -
+ M->m[1][1] * M->m[2][0] * M->m[3][3] +
+ M->m[1][1] * M->m[3][0] * M->m[2][3] +
+ M->m[1][3] * M->m[2][0] * M->m[3][1] -
+ M->m[1][3] * M->m[3][0] * M->m[2][1];
+
+ D->m[2][1] =
+ -M->m[0][0] * M->m[2][1] * M->m[3][3] +
+ M->m[0][0] * M->m[3][1] * M->m[2][3] +
+ M->m[0][1] * M->m[2][0] * M->m[3][3] -
+ M->m[0][1] * M->m[3][0] * M->m[2][3] -
+ M->m[0][3] * M->m[2][0] * M->m[3][1] +
+ M->m[0][3] * M->m[3][0] * M->m[2][1];
+
+ D->m[2][2] =
+ M->m[0][0] * M->m[1][1] * M->m[3][3] -
+ M->m[0][0] * M->m[3][1] * M->m[1][3] -
+ M->m[0][1] * M->m[1][0] * M->m[3][3] +
+ M->m[0][1] * M->m[3][0] * M->m[1][3] +
+ M->m[0][3] * M->m[1][0] * M->m[3][1] -
+ M->m[0][3] * M->m[3][0] * M->m[1][1];
+
+ D->m[2][3] =
+ -M->m[0][0] * M->m[1][1] * M->m[2][3] +
+ M->m[0][0] * M->m[2][1] * M->m[1][3] +
+ M->m[0][1] * M->m[1][0] * M->m[2][3] -
+ M->m[0][1] * M->m[2][0] * M->m[1][3] -
+ M->m[0][3] * M->m[1][0] * M->m[2][1] +
+ M->m[0][3] * M->m[2][0] * M->m[1][1];
+
+ D->m[3][0] =
+ -M->m[1][0] * M->m[2][1] * M->m[3][2] +
+ M->m[1][0] * M->m[3][1] * M->m[2][2] +
+ M->m[1][1] * M->m[2][0] * M->m[3][2] -
+ M->m[1][1] * M->m[3][0] * M->m[2][2] -
+ M->m[1][2] * M->m[2][0] * M->m[3][1] +
+ M->m[1][2] * M->m[3][0] * M->m[2][1];
+
+ D->m[3][1] =
+ M->m[0][0] * M->m[2][1] * M->m[3][2] -
+ M->m[0][0] * M->m[3][1] * M->m[2][2] -
+ M->m[0][1] * M->m[2][0] * M->m[3][2] +
+ M->m[0][1] * M->m[3][0] * M->m[2][2] +
+ M->m[0][2] * M->m[2][0] * M->m[3][1] -
+ M->m[0][2] * M->m[3][0] * M->m[2][1];
+
+ D->m[3][2] =
+ -M->m[0][0] * M->m[1][1] * M->m[3][2] +
+ M->m[0][0] * M->m[3][1] * M->m[1][2] +
+ M->m[0][1] * M->m[1][0] * M->m[3][2] -
+ M->m[0][1] * M->m[3][0] * M->m[1][2] -
+ M->m[0][2] * M->m[1][0] * M->m[3][1] +
+ M->m[0][2] * M->m[3][0] * M->m[1][1];
+
+ D->m[3][3] =
+ M->m[0][0] * M->m[1][1] * M->m[2][2] -
+ M->m[0][0] * M->m[2][1] * M->m[1][2] -
+ M->m[0][1] * M->m[1][0] * M->m[2][2] +
+ M->m[0][1] * M->m[2][0] * M->m[1][2] +
+ M->m[0][2] * M->m[1][0] * M->m[2][1] -
+ M->m[0][2] * M->m[2][0] * M->m[1][1];
+
+ det =
+ M->m[0][0] * D->m[0][0] +
+ M->m[1][0] * D->m[0][1] +
+ M->m[2][0] * D->m[0][2] +
+ M->m[3][0] * D->m[0][3];
+
+ det = 1.0 / det;
+
+ for (i = 0; i < 4; i++)
+ for (k = 0; k < 4; k++)
+ D->m[i][k] *= det;
+
+#ifdef DEBUG
+ {
+ D3DMATRIX I;
+
+ nine_d3d_matrix_matrix_mul(&I, D, M);
+
+ for (i = 0; i < 4; ++i)
+ for (k = 0; k < 4; ++k)
+ if (fabsf(I.m[i][k] - (float)(i == k)) > 1e-3)
+ DBG("Matrix inversion check FAILED !\n");
+ }
+#endif
+}
+
+/* TODO: don't use 4x4 inverse, unless this gets all nicely inlined ? */
+void
+nine_d3d_matrix_inverse_3x3(D3DMATRIX *D, const D3DMATRIX *M)
+{
+ D3DMATRIX T;
+ unsigned i, j;
+
+ for (i = 0; i < 3; ++i)
+ for (j = 0; j < 3; ++j)
+ T.m[i][j] = M->m[i][j];
+ for (i = 0; i < 3; ++i) {
+ T.m[i][3] = 0.0f;
+ T.m[3][i] = 0.0f;
+ }
+ T.m[3][3] = 1.0f;
+
+ nine_d3d_matrix_inverse(D, &T);
+}
diff --git a/src/gallium/state_trackers/nine/nine_ff.h b/src/gallium/state_trackers/nine/nine_ff.h
new file mode 100644
index 00000000000..7cefa65b1c4
--- /dev/null
+++ b/src/gallium/state_trackers/nine/nine_ff.h
@@ -0,0 +1,32 @@
+
+#ifndef _NINE_FF_H_
+#define _NINE_FF_H_
+
+#include "device9.h"
+
+boolean nine_ff_init(struct NineDevice9 *);
+void nine_ff_fini(struct NineDevice9 *);
+
+void nine_ff_update(struct NineDevice9 *);
+
+void
+nine_d3d_matrix_matrix_mul(D3DMATRIX *, const D3DMATRIX *, const D3DMATRIX *);
+
+void
+nine_d3d_vector4_matrix_mul(D3DVECTOR *, const D3DVECTOR *, const D3DMATRIX *);
+void
+nine_d3d_vector3_matrix_mul(D3DVECTOR *, const D3DVECTOR *, const D3DMATRIX *);
+
+float
+nine_d3d_matrix_det(const D3DMATRIX *);
+
+void
+nine_d3d_matrix_inverse(D3DMATRIX *, const D3DMATRIX *);
+
+void
+nine_d3d_matrix_inverse_3x3(D3DMATRIX *, const D3DMATRIX *);
+
+void
+nine_d3d_matrix_transpose(D3DMATRIX *, const D3DMATRIX *);
+
+#endif /* _NINE_FF_H_ */
diff --git a/src/gallium/state_trackers/nine/nine_helpers.c b/src/gallium/state_trackers/nine/nine_helpers.c
new file mode 100644
index 00000000000..ed179f9aedc
--- /dev/null
+++ b/src/gallium/state_trackers/nine/nine_helpers.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2013 Christoph Bumiller
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "nine_helpers.h"
+
+static struct nine_range *
+nine_range_pool_more(struct nine_range_pool *pool)
+{
+ struct nine_range *r = MALLOC(64 * sizeof(struct nine_range));
+ int i;
+ assert(!pool->free);
+
+ if (pool->num_slabs == pool->num_slabs_max) {
+ unsigned p = pool->num_slabs_max;
+ unsigned n = pool->num_slabs_max * 2;
+ if (!n)
+ n = 4;
+ pool->slabs = REALLOC(pool->slabs,
+ p * sizeof(struct nine_range *),
+ n * sizeof(struct nine_range *));
+ pool->num_slabs_max = n;
+ }
+ pool->free = pool->slabs[pool->num_slabs++] = r;
+
+ for (i = 0; i < 63; ++i, r = r->next)
+ r->next = (struct nine_range *)
+ ((uint8_t *)r + sizeof(struct nine_range));
+ r->next = NULL;
+
+ return pool->free;
+}
+
+static INLINE struct nine_range *
+nine_range_pool_get(struct nine_range_pool *pool, int16_t bgn, int16_t end)
+{
+ struct nine_range *r = pool->free;
+ if (!r)
+ r = nine_range_pool_more(pool);
+ assert(r);
+ pool->free = r->next;
+ r->bgn = bgn;
+ r->end = end;
+ return r;
+}
+
+static INLINE void
+nine_ranges_coalesce(struct nine_range *r, struct nine_range_pool *pool)
+{
+ struct nine_range *n;
+
+ while (r->next && r->end >= r->next->bgn) {
+ n = r->next->next;
+ r->end = (r->end >= r->next->end) ? r->end : r->next->end;
+ nine_range_pool_put(pool, r->next);
+ r->next = n;
+ }
+}
+
+void
+nine_ranges_insert(struct nine_range **head, int16_t bgn, int16_t end,
+ struct nine_range_pool *pool)
+{
+ struct nine_range *r, **pn = head;
+
+ for (r = *head; r && bgn > r->end; pn = &r->next, r = r->next);
+
+ if (!r || end < r->bgn) {
+ *pn = nine_range_pool_get(pool, bgn, end);
+ (*pn)->next = r;
+ } else
+ if (bgn < r->bgn) {
+ r->bgn = bgn;
+ if (end > r->end)
+ r->end = end;
+ nine_ranges_coalesce(r, pool);
+ } else
+ if (end > r->end) {
+ r->end = end;
+ nine_ranges_coalesce(r, pool);
+ }
+}
diff --git a/src/gallium/state_trackers/nine/nine_helpers.h b/src/gallium/state_trackers/nine/nine_helpers.h
new file mode 100644
index 00000000000..e81db79a4ae
--- /dev/null
+++ b/src/gallium/state_trackers/nine/nine_helpers.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _NINE_HELPERS_H_
+#define _NINE_HELPERS_H_
+
+#include "iunknown.h"
+#include "nine_lock.h"
+
+/*
+ * Note: we use these function rather than the MIN2, MAX2, CLAMP macros to
+ * avoid evaluating arguments (which are often function calls) more than once.
+ */
+
+static inline unsigned _min(unsigned a, unsigned b)
+{
+ return (a < b) ? a : b;
+}
+
+
+/* Sshhh ... */
+#define nine_reference(a, b) _nine_reference((void **)(a), (b))
+
+static inline void _nine_reference(void **ref, void *ptr)
+{
+ if (*ref != ptr) {
+ if (*ref)
+ NineUnknown_Release(*ref);
+ if (ptr)
+ NineUnknown_AddRef(ptr);
+ *ref = ptr;
+ }
+}
+
+#define nine_reference_set(a, b) _nine_reference_set((void **)(a), (b))
+
+static inline void _nine_reference_set(void **ref, void *ptr)
+{
+ *ref = ptr;
+ if (ptr)
+ NineUnknown_AddRef(ptr);
+}
+
+#define nine_bind(a, b) _nine_bind((void **)(a), (b))
+
+static inline void _nine_bind(void **dst, void *obj)
+{
+ if (*dst != obj) {
+ if (*dst)
+ NineUnknown_Unbind(*dst);
+ if (obj)
+ NineUnknown_Bind(obj);
+ *dst = obj;
+ }
+}
+
+#define NINE_DEVICE_CHILD_NEW(nine, out, dev, ...) \
+ { \
+ struct NineUnknownParams __params; \
+ struct Nine##nine *__data; \
+ \
+ __data = CALLOC_STRUCT(Nine##nine); \
+ if (!__data) { return E_OUTOFMEMORY; } \
+ \
+ __params.vtable = ((dev)->params.BehaviorFlags & D3DCREATE_MULTITHREADED) ? &Lock##nine##_vtable : &Nine##nine##_vtable; \
+ __params.guids = Nine##nine##_IIDs; \
+ __params.dtor = (void *)Nine##nine##_dtor; \
+ __params.container = NULL; \
+ __params.device = dev; \
+ { \
+ HRESULT __hr = Nine##nine##_ctor(__data, &__params, ## __VA_ARGS__); \
+ if (FAILED(__hr)) { \
+ Nine##nine##_dtor(__data); \
+ return __hr; \
+ } \
+ } \
+ \
+ *(out) = __data; \
+ } \
+ return D3D_OK
+
+#define NINE_NEW(nine, out, lock, ...) \
+ { \
+ struct NineUnknownParams __params; \
+ struct Nine##nine *__data; \
+ \
+ __data = CALLOC_STRUCT(Nine##nine); \
+ if (!__data) { return E_OUTOFMEMORY; } \
+ \
+ __params.vtable = (lock) ? &Lock##nine##_vtable : &Nine##nine##_vtable; \
+ __params.guids = Nine##nine##_IIDs; \
+ __params.dtor = (void *)Nine##nine##_dtor; \
+ __params.container = NULL; \
+ __params.device = NULL; \
+ { \
+ HRESULT __hr = Nine##nine##_ctor(__data, &__params, ## __VA_ARGS__); \
+ if (FAILED(__hr)) { \
+ Nine##nine##_dtor(__data); \
+ return __hr; \
+ } \
+ } \
+ \
+ *(out) = __data; \
+ } \
+ return D3D_OK
+
+static INLINE float asfloat(DWORD value)
+{
+ union {
+ float f;
+ DWORD w;
+ } u;
+ u.w = value;
+ return u.f;
+}
+
+#define CHECK_PIPE_RESOURCE_TEMPLATE(t) \
+ screen->is_format_supported(screen, (t).format, (t).target, (t).nr_samples, (t).bind)
+
+
+struct nine_range
+{
+ struct nine_range *next;
+ int16_t bgn; /* inclusive */
+ int16_t end; /* exclusive */
+};
+
+/* We won't ever need more than 256 ranges, so just allocate once. */
+struct nine_range_pool
+{
+ struct nine_range *free;
+ struct nine_range **slabs;
+ unsigned num_slabs;
+ unsigned num_slabs_max;
+};
+
+static INLINE void
+nine_range_pool_put(struct nine_range_pool *pool, struct nine_range *r)
+{
+ r->next = pool->free;
+ pool->free = r;
+}
+
+static INLINE void
+nine_range_pool_put_chain(struct nine_range_pool *pool,
+ struct nine_range *head,
+ struct nine_range *tail)
+{
+ tail->next = pool->free;
+ pool->free = head;
+}
+
+void
+nine_ranges_insert(struct nine_range **head, int16_t bgn, int16_t end,
+ struct nine_range_pool *pool);
+
+#endif /* _NINE_HELPERS_H_ */
diff --git a/src/gallium/state_trackers/nine/nine_lock.c b/src/gallium/state_trackers/nine/nine_lock.c
new file mode 100644
index 00000000000..42cbb0589c4
--- /dev/null
+++ b/src/gallium/state_trackers/nine/nine_lock.c
@@ -0,0 +1,3319 @@
+/*
+ * Copyright 2013 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "authenticatedchannel9.h"
+#include "basetexture9.h"
+#include "cryptosession9.h"
+#include "cubetexture9.h"
+#include "device9.h"
+#include "device9ex.h"
+#include "device9video.h"
+#include "indexbuffer9.h"
+#include "pixelshader9.h"
+#include "query9.h"
+#include "resource9.h"
+#include "stateblock9.h"
+#include "surface9.h"
+#include "swapchain9.h"
+#include "swapchain9ex.h"
+#include "texture9.h"
+#include "vertexbuffer9.h"
+#include "vertexdeclaration9.h"
+#include "vertexshader9.h"
+#include "volume9.h"
+#include "volumetexture9.h"
+
+#include "d3d9.h"
+
+#include "os/os_thread.h"
+
+/* Global mutex as described by MSDN */
+pipe_static_mutex(d3dlock_global);
+
+static HRESULT WINAPI
+LockAuthenticatedChannel9_GetCertificateSize( struct NineAuthenticatedChannel9 *This,
+ UINT *pCertificateSize )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineAuthenticatedChannel9_GetCertificateSize(This, pCertificateSize);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockAuthenticatedChannel9_GetCertificate( struct NineAuthenticatedChannel9 *This,
+ UINT CertifacteSize,
+ BYTE *ppCertificate )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineAuthenticatedChannel9_GetCertificate(This, CertifacteSize, ppCertificate);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockAuthenticatedChannel9_NegotiateKeyExchange( struct NineAuthenticatedChannel9 *This,
+ UINT DataSize,
+ void *pData )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineAuthenticatedChannel9_NegotiateKeyExchange(This, DataSize, pData);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockAuthenticatedChannel9_Query( struct NineAuthenticatedChannel9 *This,
+ UINT InputSize,
+ const void *pInput,
+ UINT OutputSize,
+ void *pOutput )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineAuthenticatedChannel9_Query(This, InputSize, pInput, OutputSize, pOutput);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockAuthenticatedChannel9_Configure( struct NineAuthenticatedChannel9 *This,
+ UINT InputSize,
+ const void *pInput,
+ D3DAUTHENTICATEDCHANNEL_CONFIGURE_OUTPUT *pOutput )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineAuthenticatedChannel9_Configure(This, InputSize, pInput, pOutput);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+IDirect3DAuthenticatedChannel9Vtbl LockAuthenticatedChannel9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)LockAuthenticatedChannel9_GetCertificateSize,
+ (void *)LockAuthenticatedChannel9_GetCertificate,
+ (void *)LockAuthenticatedChannel9_NegotiateKeyExchange,
+ (void *)LockAuthenticatedChannel9_Query,
+ (void *)LockAuthenticatedChannel9_Configure
+};
+
+#if 0
+static HRESULT WINAPI
+LockResource9_GetDevice( struct NineResource9 *This,
+ IDirect3DDevice9 **ppDevice )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineUnknown_GetDevice(NineUnknown(This), ppDevice);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+#endif
+
+static HRESULT WINAPI
+LockResource9_SetPrivateData( struct NineResource9 *This,
+ REFGUID refguid,
+ const void *pData,
+ DWORD SizeOfData,
+ DWORD Flags )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineResource9_SetPrivateData(This, refguid, pData, SizeOfData, Flags);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockResource9_GetPrivateData( struct NineResource9 *This,
+ REFGUID refguid,
+ void *pData,
+ DWORD *pSizeOfData )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineResource9_GetPrivateData(This, refguid, pData, pSizeOfData);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockResource9_FreePrivateData( struct NineResource9 *This,
+ REFGUID refguid )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineResource9_FreePrivateData(This, refguid);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static DWORD WINAPI
+LockResource9_SetPriority( struct NineResource9 *This,
+ DWORD PriorityNew )
+{
+ DWORD r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineResource9_SetPriority(This, PriorityNew);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static DWORD WINAPI
+LockResource9_GetPriority( struct NineResource9 *This )
+{
+ DWORD r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineResource9_GetPriority(This);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+#if 0
+static void WINAPI
+LockResource9_PreLoad( struct NineResource9 *This )
+{
+ pipe_mutex_lock(d3dlock_global);
+ NineResource9_PreLoad(This);
+ pipe_mutex_unlock(d3dlock_global);
+}
+#endif
+
+#if 0
+static D3DRESOURCETYPE WINAPI
+LockResource9_GetType( struct NineResource9 *This )
+{
+ D3DRESOURCETYPE r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineResource9_GetType(This);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+#endif
+
+static DWORD WINAPI
+LockBaseTexture9_SetLOD( struct NineBaseTexture9 *This,
+ DWORD LODNew )
+{
+ DWORD r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineBaseTexture9_SetLOD(This, LODNew);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static DWORD WINAPI
+LockBaseTexture9_GetLOD( struct NineBaseTexture9 *This )
+{
+ DWORD r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineBaseTexture9_GetLOD(This);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static DWORD WINAPI
+LockBaseTexture9_GetLevelCount( struct NineBaseTexture9 *This )
+{
+ DWORD r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineBaseTexture9_GetLevelCount(This);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockBaseTexture9_SetAutoGenFilterType( struct NineBaseTexture9 *This,
+ D3DTEXTUREFILTERTYPE FilterType )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineBaseTexture9_SetAutoGenFilterType(This, FilterType);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static D3DTEXTUREFILTERTYPE WINAPI
+LockBaseTexture9_GetAutoGenFilterType( struct NineBaseTexture9 *This )
+{
+ D3DTEXTUREFILTERTYPE r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineBaseTexture9_GetAutoGenFilterType(This);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static void WINAPI
+LockBaseTexture9_PreLoad( struct NineBaseTexture9 *This )
+{
+ pipe_mutex_lock(d3dlock_global);
+ NineBaseTexture9_PreLoad(This);
+ pipe_mutex_unlock(d3dlock_global);
+}
+
+static void WINAPI
+LockBaseTexture9_GenerateMipSubLevels( struct NineBaseTexture9 *This )
+{
+ pipe_mutex_lock(d3dlock_global);
+ NineBaseTexture9_GenerateMipSubLevels(This);
+ pipe_mutex_unlock(d3dlock_global);
+}
+
+static HRESULT WINAPI
+LockCryptoSession9_GetCertificateSize( struct NineCryptoSession9 *This,
+ UINT *pCertificateSize )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineCryptoSession9_GetCertificateSize(This, pCertificateSize);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockCryptoSession9_GetCertificate( struct NineCryptoSession9 *This,
+ UINT CertifacteSize,
+ BYTE *ppCertificate )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineCryptoSession9_GetCertificate(This, CertifacteSize, ppCertificate);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockCryptoSession9_NegotiateKeyExchange( struct NineCryptoSession9 *This,
+ UINT DataSize,
+ void *pData )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineCryptoSession9_NegotiateKeyExchange(This, DataSize, pData);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockCryptoSession9_EncryptionBlt( struct NineCryptoSession9 *This,
+ IDirect3DSurface9 *pSrcSurface,
+ IDirect3DSurface9 *pDstSurface,
+ UINT DstSurfaceSize,
+ void *pIV )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineCryptoSession9_EncryptionBlt(This, pSrcSurface, pDstSurface, DstSurfaceSize, pIV);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockCryptoSession9_DecryptionBlt( struct NineCryptoSession9 *This,
+ IDirect3DSurface9 *pSrcSurface,
+ IDirect3DSurface9 *pDstSurface,
+ UINT SrcSurfaceSize,
+ D3DENCRYPTED_BLOCK_INFO *pEncryptedBlockInfo,
+ void *pContentKey,
+ void *pIV )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineCryptoSession9_DecryptionBlt(This, pSrcSurface, pDstSurface, SrcSurfaceSize, pEncryptedBlockInfo, pContentKey, pIV);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockCryptoSession9_GetSurfacePitch( struct NineCryptoSession9 *This,
+ IDirect3DSurface9 *pSrcSurface,
+ UINT *pSurfacePitch )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineCryptoSession9_GetSurfacePitch(This, pSrcSurface, pSurfacePitch);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockCryptoSession9_StartSessionKeyRefresh( struct NineCryptoSession9 *This,
+ void *pRandomNumber,
+ UINT RandomNumberSize )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineCryptoSession9_StartSessionKeyRefresh(This, pRandomNumber, RandomNumberSize);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockCryptoSession9_FinishSessionKeyRefresh( struct NineCryptoSession9 *This )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineCryptoSession9_FinishSessionKeyRefresh(This);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockCryptoSession9_GetEncryptionBltKey( struct NineCryptoSession9 *This,
+ void *pReadbackKey,
+ UINT KeySize )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineCryptoSession9_GetEncryptionBltKey(This, pReadbackKey, KeySize);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+IDirect3DCryptoSession9Vtbl LockCryptoSession9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)LockCryptoSession9_GetCertificateSize,
+ (void *)LockCryptoSession9_GetCertificate,
+ (void *)LockCryptoSession9_NegotiateKeyExchange,
+ (void *)LockCryptoSession9_EncryptionBlt,
+ (void *)LockCryptoSession9_DecryptionBlt,
+ (void *)LockCryptoSession9_GetSurfacePitch,
+ (void *)LockCryptoSession9_StartSessionKeyRefresh,
+ (void *)LockCryptoSession9_FinishSessionKeyRefresh,
+ (void *)LockCryptoSession9_GetEncryptionBltKey
+};
+
+#if 0
+static HRESULT WINAPI
+LockCubeTexture9_GetLevelDesc( struct NineCubeTexture9 *This,
+ UINT Level,
+ D3DSURFACE_DESC *pDesc )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineCubeTexture9_GetLevelDesc(This, Level, pDesc);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+#endif
+
+#if 0
+static HRESULT WINAPI
+LockCubeTexture9_GetCubeMapSurface( struct NineCubeTexture9 *This,
+ D3DCUBEMAP_FACES FaceType,
+ UINT Level,
+ IDirect3DSurface9 **ppCubeMapSurface )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineCubeTexture9_GetCubeMapSurface(This, FaceType, Level, ppCubeMapSurface);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+#endif
+
+static HRESULT WINAPI
+LockCubeTexture9_LockRect( struct NineCubeTexture9 *This,
+ D3DCUBEMAP_FACES FaceType,
+ UINT Level,
+ D3DLOCKED_RECT *pLockedRect,
+ const RECT *pRect,
+ DWORD Flags )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineCubeTexture9_LockRect(This, FaceType, Level, pLockedRect, pRect, Flags);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockCubeTexture9_UnlockRect( struct NineCubeTexture9 *This,
+ D3DCUBEMAP_FACES FaceType,
+ UINT Level )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineCubeTexture9_UnlockRect(This, FaceType, Level);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockCubeTexture9_AddDirtyRect( struct NineCubeTexture9 *This,
+ D3DCUBEMAP_FACES FaceType,
+ const RECT *pDirtyRect )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineCubeTexture9_AddDirtyRect(This, FaceType, pDirtyRect);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+IDirect3DCubeTexture9Vtbl LockCubeTexture9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */
+ (void *)LockResource9_SetPrivateData,
+ (void *)LockResource9_GetPrivateData,
+ (void *)LockResource9_FreePrivateData,
+ (void *)LockResource9_SetPriority,
+ (void *)LockResource9_GetPriority,
+ (void *)LockBaseTexture9_PreLoad,
+ (void *)NineResource9_GetType, /* immutable */
+ (void *)LockBaseTexture9_SetLOD,
+ (void *)LockBaseTexture9_GetLOD,
+ (void *)LockBaseTexture9_GetLevelCount,
+ (void *)LockBaseTexture9_SetAutoGenFilterType,
+ (void *)LockBaseTexture9_GetAutoGenFilterType,
+ (void *)LockBaseTexture9_GenerateMipSubLevels,
+ (void *)NineCubeTexture9_GetLevelDesc, /* immutable */
+ (void *)NineCubeTexture9_GetCubeMapSurface, /* AddRef */
+ (void *)LockCubeTexture9_LockRect,
+ (void *)LockCubeTexture9_UnlockRect,
+ (void *)LockCubeTexture9_AddDirtyRect
+};
+
+static HRESULT WINAPI
+LockDevice9_TestCooperativeLevel( struct NineDevice9 *This )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_TestCooperativeLevel(This);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static UINT WINAPI
+LockDevice9_GetAvailableTextureMem( struct NineDevice9 *This )
+{
+ UINT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetAvailableTextureMem(This);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_EvictManagedResources( struct NineDevice9 *This )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_EvictManagedResources(This);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetDirect3D( struct NineDevice9 *This,
+ IDirect3D9 **ppD3D9 )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetDirect3D(This, ppD3D9);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+#if 0
+static HRESULT WINAPI
+LockDevice9_GetDeviceCaps( struct NineDevice9 *This,
+ D3DCAPS9 *pCaps )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetDeviceCaps(This, pCaps);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+#endif
+
+static HRESULT WINAPI
+LockDevice9_GetDisplayMode( struct NineDevice9 *This,
+ UINT iSwapChain,
+ D3DDISPLAYMODE *pMode )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetDisplayMode(This, iSwapChain, pMode);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+#if 0
+static HRESULT WINAPI
+LockDevice9_GetCreationParameters( struct NineDevice9 *This,
+ D3DDEVICE_CREATION_PARAMETERS *pParameters )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetCreationParameters(This, pParameters);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+#endif
+
+static HRESULT WINAPI
+LockDevice9_SetCursorProperties( struct NineDevice9 *This,
+ UINT XHotSpot,
+ UINT YHotSpot,
+ IDirect3DSurface9 *pCursorBitmap )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_SetCursorProperties(This, XHotSpot, YHotSpot, pCursorBitmap);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static void WINAPI
+LockDevice9_SetCursorPosition( struct NineDevice9 *This,
+ int X,
+ int Y,
+ DWORD Flags )
+{
+ pipe_mutex_lock(d3dlock_global);
+ NineDevice9_SetCursorPosition(This, X, Y, Flags);
+ pipe_mutex_unlock(d3dlock_global);
+}
+
+static BOOL WINAPI
+LockDevice9_ShowCursor( struct NineDevice9 *This,
+ BOOL bShow )
+{
+ BOOL r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_ShowCursor(This, bShow);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_CreateAdditionalSwapChain( struct NineDevice9 *This,
+ D3DPRESENT_PARAMETERS *pPresentationParameters,
+ IDirect3DSwapChain9 **pSwapChain )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_CreateAdditionalSwapChain(This, pPresentationParameters, pSwapChain);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetSwapChain( struct NineDevice9 *This,
+ UINT iSwapChain,
+ IDirect3DSwapChain9 **pSwapChain )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetSwapChain(This, iSwapChain, pSwapChain);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static UINT WINAPI
+LockDevice9_GetNumberOfSwapChains( struct NineDevice9 *This )
+{
+ UINT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetNumberOfSwapChains(This);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_Reset( struct NineDevice9 *This,
+ D3DPRESENT_PARAMETERS *pPresentationParameters )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_Reset(This, pPresentationParameters);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_Present( struct NineDevice9 *This,
+ const RECT *pSourceRect,
+ const RECT *pDestRect,
+ HWND hDestWindowOverride,
+ const RGNDATA *pDirtyRegion )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_Present(This, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetBackBuffer( struct NineDevice9 *This,
+ UINT iSwapChain,
+ UINT iBackBuffer,
+ D3DBACKBUFFER_TYPE Type,
+ IDirect3DSurface9 **ppBackBuffer )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetBackBuffer(This, iSwapChain, iBackBuffer, Type, ppBackBuffer);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetRasterStatus( struct NineDevice9 *This,
+ UINT iSwapChain,
+ D3DRASTER_STATUS *pRasterStatus )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetRasterStatus(This, iSwapChain, pRasterStatus);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_SetDialogBoxMode( struct NineDevice9 *This,
+ BOOL bEnableDialogs )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_SetDialogBoxMode(This, bEnableDialogs);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static void WINAPI
+LockDevice9_SetGammaRamp( struct NineDevice9 *This,
+ UINT iSwapChain,
+ DWORD Flags,
+ const D3DGAMMARAMP *pRamp )
+{
+ pipe_mutex_lock(d3dlock_global);
+ NineDevice9_SetGammaRamp(This, iSwapChain, Flags, pRamp);
+ pipe_mutex_unlock(d3dlock_global);
+}
+
+static void WINAPI
+LockDevice9_GetGammaRamp( struct NineDevice9 *This,
+ UINT iSwapChain,
+ D3DGAMMARAMP *pRamp )
+{
+ pipe_mutex_lock(d3dlock_global);
+ NineDevice9_GetGammaRamp(This, iSwapChain, pRamp);
+ pipe_mutex_unlock(d3dlock_global);
+}
+
+static HRESULT WINAPI
+LockDevice9_CreateTexture( struct NineDevice9 *This,
+ UINT Width,
+ UINT Height,
+ UINT Levels,
+ DWORD Usage,
+ D3DFORMAT Format,
+ D3DPOOL Pool,
+ IDirect3DTexture9 **ppTexture,
+ HANDLE *pSharedHandle )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_CreateTexture(This, Width, Height, Levels, Usage, Format, Pool, ppTexture, pSharedHandle);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_CreateVolumeTexture( struct NineDevice9 *This,
+ UINT Width,
+ UINT Height,
+ UINT Depth,
+ UINT Levels,
+ DWORD Usage,
+ D3DFORMAT Format,
+ D3DPOOL Pool,
+ IDirect3DVolumeTexture9 **ppVolumeTexture,
+ HANDLE *pSharedHandle )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_CreateVolumeTexture(This, Width, Height, Depth, Levels, Usage, Format, Pool, ppVolumeTexture, pSharedHandle);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_CreateCubeTexture( struct NineDevice9 *This,
+ UINT EdgeLength,
+ UINT Levels,
+ DWORD Usage,
+ D3DFORMAT Format,
+ D3DPOOL Pool,
+ IDirect3DCubeTexture9 **ppCubeTexture,
+ HANDLE *pSharedHandle )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_CreateCubeTexture(This, EdgeLength, Levels, Usage, Format, Pool, ppCubeTexture, pSharedHandle);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_CreateVertexBuffer( struct NineDevice9 *This,
+ UINT Length,
+ DWORD Usage,
+ DWORD FVF,
+ D3DPOOL Pool,
+ IDirect3DVertexBuffer9 **ppVertexBuffer,
+ HANDLE *pSharedHandle )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_CreateVertexBuffer(This, Length, Usage, FVF, Pool, ppVertexBuffer, pSharedHandle);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_CreateIndexBuffer( struct NineDevice9 *This,
+ UINT Length,
+ DWORD Usage,
+ D3DFORMAT Format,
+ D3DPOOL Pool,
+ IDirect3DIndexBuffer9 **ppIndexBuffer,
+ HANDLE *pSharedHandle )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_CreateIndexBuffer(This, Length, Usage, Format, Pool, ppIndexBuffer, pSharedHandle);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_CreateRenderTarget( struct NineDevice9 *This,
+ UINT Width,
+ UINT Height,
+ D3DFORMAT Format,
+ D3DMULTISAMPLE_TYPE MultiSample,
+ DWORD MultisampleQuality,
+ BOOL Lockable,
+ IDirect3DSurface9 **ppSurface,
+ HANDLE *pSharedHandle )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_CreateRenderTarget(This, Width, Height, Format, MultiSample, MultisampleQuality, Lockable, ppSurface, pSharedHandle);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_CreateDepthStencilSurface( struct NineDevice9 *This,
+ UINT Width,
+ UINT Height,
+ D3DFORMAT Format,
+ D3DMULTISAMPLE_TYPE MultiSample,
+ DWORD MultisampleQuality,
+ BOOL Discard,
+ IDirect3DSurface9 **ppSurface,
+ HANDLE *pSharedHandle )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_CreateDepthStencilSurface(This, Width, Height, Format, MultiSample, MultisampleQuality, Discard, ppSurface, pSharedHandle);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_UpdateSurface( struct NineDevice9 *This,
+ IDirect3DSurface9 *pSourceSurface,
+ const RECT *pSourceRect,
+ IDirect3DSurface9 *pDestinationSurface,
+ const POINT *pDestPoint )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_UpdateSurface(This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_UpdateTexture( struct NineDevice9 *This,
+ IDirect3DBaseTexture9 *pSourceTexture,
+ IDirect3DBaseTexture9 *pDestinationTexture )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_UpdateTexture(This, pSourceTexture, pDestinationTexture);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetRenderTargetData( struct NineDevice9 *This,
+ IDirect3DSurface9 *pRenderTarget,
+ IDirect3DSurface9 *pDestSurface )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetRenderTargetData(This, pRenderTarget, pDestSurface);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetFrontBufferData( struct NineDevice9 *This,
+ UINT iSwapChain,
+ IDirect3DSurface9 *pDestSurface )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetFrontBufferData(This, iSwapChain, pDestSurface);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_StretchRect( struct NineDevice9 *This,
+ IDirect3DSurface9 *pSourceSurface,
+ const RECT *pSourceRect,
+ IDirect3DSurface9 *pDestSurface,
+ const RECT *pDestRect,
+ D3DTEXTUREFILTERTYPE Filter )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_StretchRect(This, pSourceSurface, pSourceRect, pDestSurface, pDestRect, Filter);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_ColorFill( struct NineDevice9 *This,
+ IDirect3DSurface9 *pSurface,
+ const RECT *pRect,
+ D3DCOLOR color )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_ColorFill(This, pSurface, pRect, color);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_CreateOffscreenPlainSurface( struct NineDevice9 *This,
+ UINT Width,
+ UINT Height,
+ D3DFORMAT Format,
+ D3DPOOL Pool,
+ IDirect3DSurface9 **ppSurface,
+ HANDLE *pSharedHandle )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_CreateOffscreenPlainSurface(This, Width, Height, Format, Pool, ppSurface, pSharedHandle);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_SetRenderTarget( struct NineDevice9 *This,
+ DWORD RenderTargetIndex,
+ IDirect3DSurface9 *pRenderTarget )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_SetRenderTarget(This, RenderTargetIndex, pRenderTarget);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetRenderTarget( struct NineDevice9 *This,
+ DWORD RenderTargetIndex,
+ IDirect3DSurface9 **ppRenderTarget )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetRenderTarget(This, RenderTargetIndex, ppRenderTarget);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_SetDepthStencilSurface( struct NineDevice9 *This,
+ IDirect3DSurface9 *pNewZStencil )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_SetDepthStencilSurface(This, pNewZStencil);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetDepthStencilSurface( struct NineDevice9 *This,
+ IDirect3DSurface9 **ppZStencilSurface )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetDepthStencilSurface(This, ppZStencilSurface);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_BeginScene( struct NineDevice9 *This )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_BeginScene(This);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_EndScene( struct NineDevice9 *This )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_EndScene(This);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_Clear( struct NineDevice9 *This,
+ DWORD Count,
+ const D3DRECT *pRects,
+ DWORD Flags,
+ D3DCOLOR Color,
+ float Z,
+ DWORD Stencil )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_Clear(This, Count, pRects, Flags, Color, Z, Stencil);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_SetTransform( struct NineDevice9 *This,
+ D3DTRANSFORMSTATETYPE State,
+ const D3DMATRIX *pMatrix )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_SetTransform(This, State, pMatrix);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetTransform( struct NineDevice9 *This,
+ D3DTRANSFORMSTATETYPE State,
+ D3DMATRIX *pMatrix )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetTransform(This, State, pMatrix);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_MultiplyTransform( struct NineDevice9 *This,
+ D3DTRANSFORMSTATETYPE State,
+ const D3DMATRIX *pMatrix )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_MultiplyTransform(This, State, pMatrix);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_SetViewport( struct NineDevice9 *This,
+ const D3DVIEWPORT9 *pViewport )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_SetViewport(This, pViewport);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetViewport( struct NineDevice9 *This,
+ D3DVIEWPORT9 *pViewport )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetViewport(This, pViewport);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_SetMaterial( struct NineDevice9 *This,
+ const D3DMATERIAL9 *pMaterial )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_SetMaterial(This, pMaterial);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetMaterial( struct NineDevice9 *This,
+ D3DMATERIAL9 *pMaterial )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetMaterial(This, pMaterial);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_SetLight( struct NineDevice9 *This,
+ DWORD Index,
+ const D3DLIGHT9 *pLight )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_SetLight(This, Index, pLight);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetLight( struct NineDevice9 *This,
+ DWORD Index,
+ D3DLIGHT9 *pLight )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetLight(This, Index, pLight);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_LightEnable( struct NineDevice9 *This,
+ DWORD Index,
+ BOOL Enable )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_LightEnable(This, Index, Enable);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetLightEnable( struct NineDevice9 *This,
+ DWORD Index,
+ BOOL *pEnable )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetLightEnable(This, Index, pEnable);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_SetClipPlane( struct NineDevice9 *This,
+ DWORD Index,
+ const float *pPlane )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_SetClipPlane(This, Index, pPlane);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetClipPlane( struct NineDevice9 *This,
+ DWORD Index,
+ float *pPlane )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetClipPlane(This, Index, pPlane);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_SetRenderState( struct NineDevice9 *This,
+ D3DRENDERSTATETYPE State,
+ DWORD Value )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_SetRenderState(This, State, Value);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetRenderState( struct NineDevice9 *This,
+ D3DRENDERSTATETYPE State,
+ DWORD *pValue )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetRenderState(This, State, pValue);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_CreateStateBlock( struct NineDevice9 *This,
+ D3DSTATEBLOCKTYPE Type,
+ IDirect3DStateBlock9 **ppSB )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_CreateStateBlock(This, Type, ppSB);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_BeginStateBlock( struct NineDevice9 *This )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_BeginStateBlock(This);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_EndStateBlock( struct NineDevice9 *This,
+ IDirect3DStateBlock9 **ppSB )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_EndStateBlock(This, ppSB);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_SetClipStatus( struct NineDevice9 *This,
+ const D3DCLIPSTATUS9 *pClipStatus )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_SetClipStatus(This, pClipStatus);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetClipStatus( struct NineDevice9 *This,
+ D3DCLIPSTATUS9 *pClipStatus )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetClipStatus(This, pClipStatus);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetTexture( struct NineDevice9 *This,
+ DWORD Stage,
+ IDirect3DBaseTexture9 **ppTexture )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetTexture(This, Stage, ppTexture);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_SetTexture( struct NineDevice9 *This,
+ DWORD Stage,
+ IDirect3DBaseTexture9 *pTexture )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_SetTexture(This, Stage, pTexture);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetTextureStageState( struct NineDevice9 *This,
+ DWORD Stage,
+ D3DTEXTURESTAGESTATETYPE Type,
+ DWORD *pValue )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetTextureStageState(This, Stage, Type, pValue);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_SetTextureStageState( struct NineDevice9 *This,
+ DWORD Stage,
+ D3DTEXTURESTAGESTATETYPE Type,
+ DWORD Value )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_SetTextureStageState(This, Stage, Type, Value);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetSamplerState( struct NineDevice9 *This,
+ DWORD Sampler,
+ D3DSAMPLERSTATETYPE Type,
+ DWORD *pValue )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetSamplerState(This, Sampler, Type, pValue);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_SetSamplerState( struct NineDevice9 *This,
+ DWORD Sampler,
+ D3DSAMPLERSTATETYPE Type,
+ DWORD Value )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_SetSamplerState(This, Sampler, Type, Value);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_ValidateDevice( struct NineDevice9 *This,
+ DWORD *pNumPasses )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_ValidateDevice(This, pNumPasses);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_SetPaletteEntries( struct NineDevice9 *This,
+ UINT PaletteNumber,
+ const PALETTEENTRY *pEntries )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_SetPaletteEntries(This, PaletteNumber, pEntries);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetPaletteEntries( struct NineDevice9 *This,
+ UINT PaletteNumber,
+ PALETTEENTRY *pEntries )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetPaletteEntries(This, PaletteNumber, pEntries);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_SetCurrentTexturePalette( struct NineDevice9 *This,
+ UINT PaletteNumber )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_SetCurrentTexturePalette(This, PaletteNumber);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetCurrentTexturePalette( struct NineDevice9 *This,
+ UINT *PaletteNumber )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetCurrentTexturePalette(This, PaletteNumber);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_SetScissorRect( struct NineDevice9 *This,
+ const RECT *pRect )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_SetScissorRect(This, pRect);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetScissorRect( struct NineDevice9 *This,
+ RECT *pRect )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetScissorRect(This, pRect);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_SetSoftwareVertexProcessing( struct NineDevice9 *This,
+ BOOL bSoftware )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_SetSoftwareVertexProcessing(This, bSoftware);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static BOOL WINAPI
+LockDevice9_GetSoftwareVertexProcessing( struct NineDevice9 *This )
+{
+ BOOL r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetSoftwareVertexProcessing(This);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_SetNPatchMode( struct NineDevice9 *This,
+ float nSegments )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_SetNPatchMode(This, nSegments);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static float WINAPI
+LockDevice9_GetNPatchMode( struct NineDevice9 *This )
+{
+ float r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetNPatchMode(This);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_DrawPrimitive( struct NineDevice9 *This,
+ D3DPRIMITIVETYPE PrimitiveType,
+ UINT StartVertex,
+ UINT PrimitiveCount )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_DrawPrimitive(This, PrimitiveType, StartVertex, PrimitiveCount);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_DrawIndexedPrimitive( struct NineDevice9 *This,
+ D3DPRIMITIVETYPE PrimitiveType,
+ INT BaseVertexIndex,
+ UINT MinVertexIndex,
+ UINT NumVertices,
+ UINT startIndex,
+ UINT primCount )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_DrawIndexedPrimitive(This, PrimitiveType, BaseVertexIndex, MinVertexIndex, NumVertices, startIndex, primCount);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_DrawPrimitiveUP( struct NineDevice9 *This,
+ D3DPRIMITIVETYPE PrimitiveType,
+ UINT PrimitiveCount,
+ const void *pVertexStreamZeroData,
+ UINT VertexStreamZeroStride )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_DrawPrimitiveUP(This, PrimitiveType, PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_DrawIndexedPrimitiveUP( struct NineDevice9 *This,
+ D3DPRIMITIVETYPE PrimitiveType,
+ UINT MinVertexIndex,
+ UINT NumVertices,
+ UINT PrimitiveCount,
+ const void *pIndexData,
+ D3DFORMAT IndexDataFormat,
+ const void *pVertexStreamZeroData,
+ UINT VertexStreamZeroStride )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_DrawIndexedPrimitiveUP(This, PrimitiveType, MinVertexIndex, NumVertices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_ProcessVertices( struct NineDevice9 *This,
+ UINT SrcStartIndex,
+ UINT DestIndex,
+ UINT VertexCount,
+ IDirect3DVertexBuffer9 *pDestBuffer,
+ IDirect3DVertexDeclaration9 *pVertexDecl,
+ DWORD Flags )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_ProcessVertices(This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_CreateVertexDeclaration( struct NineDevice9 *This,
+ const D3DVERTEXELEMENT9 *pVertexElements,
+ IDirect3DVertexDeclaration9 **ppDecl )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_CreateVertexDeclaration(This, pVertexElements, ppDecl);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_SetVertexDeclaration( struct NineDevice9 *This,
+ IDirect3DVertexDeclaration9 *pDecl )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_SetVertexDeclaration(This, pDecl);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetVertexDeclaration( struct NineDevice9 *This,
+ IDirect3DVertexDeclaration9 **ppDecl )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetVertexDeclaration(This, ppDecl);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_SetFVF( struct NineDevice9 *This,
+ DWORD FVF )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_SetFVF(This, FVF);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetFVF( struct NineDevice9 *This,
+ DWORD *pFVF )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetFVF(This, pFVF);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_CreateVertexShader( struct NineDevice9 *This,
+ const DWORD *pFunction,
+ IDirect3DVertexShader9 **ppShader )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_CreateVertexShader(This, pFunction, ppShader);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_SetVertexShader( struct NineDevice9 *This,
+ IDirect3DVertexShader9 *pShader )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_SetVertexShader(This, pShader);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetVertexShader( struct NineDevice9 *This,
+ IDirect3DVertexShader9 **ppShader )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetVertexShader(This, ppShader);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_SetVertexShaderConstantF( struct NineDevice9 *This,
+ UINT StartRegister,
+ const float *pConstantData,
+ UINT Vector4fCount )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_SetVertexShaderConstantF(This, StartRegister, pConstantData, Vector4fCount);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetVertexShaderConstantF( struct NineDevice9 *This,
+ UINT StartRegister,
+ float *pConstantData,
+ UINT Vector4fCount )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetVertexShaderConstantF(This, StartRegister, pConstantData, Vector4fCount);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_SetVertexShaderConstantI( struct NineDevice9 *This,
+ UINT StartRegister,
+ const int *pConstantData,
+ UINT Vector4iCount )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_SetVertexShaderConstantI(This, StartRegister, pConstantData, Vector4iCount);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetVertexShaderConstantI( struct NineDevice9 *This,
+ UINT StartRegister,
+ int *pConstantData,
+ UINT Vector4iCount )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetVertexShaderConstantI(This, StartRegister, pConstantData, Vector4iCount);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_SetVertexShaderConstantB( struct NineDevice9 *This,
+ UINT StartRegister,
+ const BOOL *pConstantData,
+ UINT BoolCount )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_SetVertexShaderConstantB(This, StartRegister, pConstantData, BoolCount);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetVertexShaderConstantB( struct NineDevice9 *This,
+ UINT StartRegister,
+ BOOL *pConstantData,
+ UINT BoolCount )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetVertexShaderConstantB(This, StartRegister, pConstantData, BoolCount);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_SetStreamSource( struct NineDevice9 *This,
+ UINT StreamNumber,
+ IDirect3DVertexBuffer9 *pStreamData,
+ UINT OffsetInBytes,
+ UINT Stride )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_SetStreamSource(This, StreamNumber, pStreamData, OffsetInBytes, Stride);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetStreamSource( struct NineDevice9 *This,
+ UINT StreamNumber,
+ IDirect3DVertexBuffer9 **ppStreamData,
+ UINT *pOffsetInBytes,
+ UINT *pStride )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetStreamSource(This, StreamNumber, ppStreamData, pOffsetInBytes, pStride);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_SetStreamSourceFreq( struct NineDevice9 *This,
+ UINT StreamNumber,
+ UINT Setting )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_SetStreamSourceFreq(This, StreamNumber, Setting);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetStreamSourceFreq( struct NineDevice9 *This,
+ UINT StreamNumber,
+ UINT *pSetting )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetStreamSourceFreq(This, StreamNumber, pSetting);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_SetIndices( struct NineDevice9 *This,
+ IDirect3DIndexBuffer9 *pIndexData )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_SetIndices(This, pIndexData);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetIndices( struct NineDevice9 *This,
+ IDirect3DIndexBuffer9 **ppIndexData )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetIndices(This, ppIndexData);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_CreatePixelShader( struct NineDevice9 *This,
+ const DWORD *pFunction,
+ IDirect3DPixelShader9 **ppShader )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_CreatePixelShader(This, pFunction, ppShader);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_SetPixelShader( struct NineDevice9 *This,
+ IDirect3DPixelShader9 *pShader )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_SetPixelShader(This, pShader);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetPixelShader( struct NineDevice9 *This,
+ IDirect3DPixelShader9 **ppShader )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetPixelShader(This, ppShader);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_SetPixelShaderConstantF( struct NineDevice9 *This,
+ UINT StartRegister,
+ const float *pConstantData,
+ UINT Vector4fCount )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_SetPixelShaderConstantF(This, StartRegister, pConstantData, Vector4fCount);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetPixelShaderConstantF( struct NineDevice9 *This,
+ UINT StartRegister,
+ float *pConstantData,
+ UINT Vector4fCount )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetPixelShaderConstantF(This, StartRegister, pConstantData, Vector4fCount);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_SetPixelShaderConstantI( struct NineDevice9 *This,
+ UINT StartRegister,
+ const int *pConstantData,
+ UINT Vector4iCount )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_SetPixelShaderConstantI(This, StartRegister, pConstantData, Vector4iCount);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetPixelShaderConstantI( struct NineDevice9 *This,
+ UINT StartRegister,
+ int *pConstantData,
+ UINT Vector4iCount )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetPixelShaderConstantI(This, StartRegister, pConstantData, Vector4iCount);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_SetPixelShaderConstantB( struct NineDevice9 *This,
+ UINT StartRegister,
+ const BOOL *pConstantData,
+ UINT BoolCount )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_SetPixelShaderConstantB(This, StartRegister, pConstantData, BoolCount);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_GetPixelShaderConstantB( struct NineDevice9 *This,
+ UINT StartRegister,
+ BOOL *pConstantData,
+ UINT BoolCount )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_GetPixelShaderConstantB(This, StartRegister, pConstantData, BoolCount);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_DrawRectPatch( struct NineDevice9 *This,
+ UINT Handle,
+ const float *pNumSegs,
+ const D3DRECTPATCH_INFO *pRectPatchInfo )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_DrawRectPatch(This, Handle, pNumSegs, pRectPatchInfo);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_DrawTriPatch( struct NineDevice9 *This,
+ UINT Handle,
+ const float *pNumSegs,
+ const D3DTRIPATCH_INFO *pTriPatchInfo )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_DrawTriPatch(This, Handle, pNumSegs, pTriPatchInfo);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_DeletePatch( struct NineDevice9 *This,
+ UINT Handle )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_DeletePatch(This, Handle);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9_CreateQuery( struct NineDevice9 *This,
+ D3DQUERYTYPE Type,
+ IDirect3DQuery9 **ppQuery )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9_CreateQuery(This, Type, ppQuery);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+IDirect3DDevice9Vtbl LockDevice9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)LockDevice9_TestCooperativeLevel,
+ (void *)LockDevice9_GetAvailableTextureMem,
+ (void *)LockDevice9_EvictManagedResources,
+ (void *)LockDevice9_GetDirect3D,
+ (void *)NineDevice9_GetDeviceCaps, /* immutable */
+ (void *)LockDevice9_GetDisplayMode,
+ (void *)NineDevice9_GetCreationParameters, /* immutable */
+ (void *)LockDevice9_SetCursorProperties,
+ (void *)LockDevice9_SetCursorPosition,
+ (void *)LockDevice9_ShowCursor,
+ (void *)LockDevice9_CreateAdditionalSwapChain,
+ (void *)LockDevice9_GetSwapChain,
+ (void *)LockDevice9_GetNumberOfSwapChains,
+ (void *)LockDevice9_Reset,
+ (void *)LockDevice9_Present,
+ (void *)LockDevice9_GetBackBuffer,
+ (void *)LockDevice9_GetRasterStatus,
+ (void *)LockDevice9_SetDialogBoxMode,
+ (void *)LockDevice9_SetGammaRamp,
+ (void *)LockDevice9_GetGammaRamp,
+ (void *)LockDevice9_CreateTexture,
+ (void *)LockDevice9_CreateVolumeTexture,
+ (void *)LockDevice9_CreateCubeTexture,
+ (void *)LockDevice9_CreateVertexBuffer,
+ (void *)LockDevice9_CreateIndexBuffer,
+ (void *)LockDevice9_CreateRenderTarget,
+ (void *)LockDevice9_CreateDepthStencilSurface,
+ (void *)LockDevice9_UpdateSurface,
+ (void *)LockDevice9_UpdateTexture,
+ (void *)LockDevice9_GetRenderTargetData,
+ (void *)LockDevice9_GetFrontBufferData,
+ (void *)LockDevice9_StretchRect,
+ (void *)LockDevice9_ColorFill,
+ (void *)LockDevice9_CreateOffscreenPlainSurface,
+ (void *)LockDevice9_SetRenderTarget,
+ (void *)LockDevice9_GetRenderTarget,
+ (void *)LockDevice9_SetDepthStencilSurface,
+ (void *)LockDevice9_GetDepthStencilSurface,
+ (void *)LockDevice9_BeginScene,
+ (void *)LockDevice9_EndScene,
+ (void *)LockDevice9_Clear,
+ (void *)LockDevice9_SetTransform,
+ (void *)LockDevice9_GetTransform,
+ (void *)LockDevice9_MultiplyTransform,
+ (void *)LockDevice9_SetViewport,
+ (void *)LockDevice9_GetViewport,
+ (void *)LockDevice9_SetMaterial,
+ (void *)LockDevice9_GetMaterial,
+ (void *)LockDevice9_SetLight,
+ (void *)LockDevice9_GetLight,
+ (void *)LockDevice9_LightEnable,
+ (void *)LockDevice9_GetLightEnable,
+ (void *)LockDevice9_SetClipPlane,
+ (void *)LockDevice9_GetClipPlane,
+ (void *)LockDevice9_SetRenderState,
+ (void *)LockDevice9_GetRenderState,
+ (void *)LockDevice9_CreateStateBlock,
+ (void *)LockDevice9_BeginStateBlock,
+ (void *)LockDevice9_EndStateBlock,
+ (void *)LockDevice9_SetClipStatus,
+ (void *)LockDevice9_GetClipStatus,
+ (void *)LockDevice9_GetTexture,
+ (void *)LockDevice9_SetTexture,
+ (void *)LockDevice9_GetTextureStageState,
+ (void *)LockDevice9_SetTextureStageState,
+ (void *)LockDevice9_GetSamplerState,
+ (void *)LockDevice9_SetSamplerState,
+ (void *)LockDevice9_ValidateDevice,
+ (void *)LockDevice9_SetPaletteEntries,
+ (void *)LockDevice9_GetPaletteEntries,
+ (void *)LockDevice9_SetCurrentTexturePalette,
+ (void *)LockDevice9_GetCurrentTexturePalette,
+ (void *)LockDevice9_SetScissorRect,
+ (void *)LockDevice9_GetScissorRect,
+ (void *)LockDevice9_SetSoftwareVertexProcessing,
+ (void *)LockDevice9_GetSoftwareVertexProcessing,
+ (void *)LockDevice9_SetNPatchMode,
+ (void *)LockDevice9_GetNPatchMode,
+ (void *)LockDevice9_DrawPrimitive,
+ (void *)LockDevice9_DrawIndexedPrimitive,
+ (void *)LockDevice9_DrawPrimitiveUP,
+ (void *)LockDevice9_DrawIndexedPrimitiveUP,
+ (void *)LockDevice9_ProcessVertices,
+ (void *)LockDevice9_CreateVertexDeclaration,
+ (void *)LockDevice9_SetVertexDeclaration,
+ (void *)LockDevice9_GetVertexDeclaration,
+ (void *)LockDevice9_SetFVF,
+ (void *)LockDevice9_GetFVF,
+ (void *)LockDevice9_CreateVertexShader,
+ (void *)LockDevice9_SetVertexShader,
+ (void *)LockDevice9_GetVertexShader,
+ (void *)LockDevice9_SetVertexShaderConstantF,
+ (void *)LockDevice9_GetVertexShaderConstantF,
+ (void *)LockDevice9_SetVertexShaderConstantI,
+ (void *)LockDevice9_GetVertexShaderConstantI,
+ (void *)LockDevice9_SetVertexShaderConstantB,
+ (void *)LockDevice9_GetVertexShaderConstantB,
+ (void *)LockDevice9_SetStreamSource,
+ (void *)LockDevice9_GetStreamSource,
+ (void *)LockDevice9_SetStreamSourceFreq,
+ (void *)LockDevice9_GetStreamSourceFreq,
+ (void *)LockDevice9_SetIndices,
+ (void *)LockDevice9_GetIndices,
+ (void *)LockDevice9_CreatePixelShader,
+ (void *)LockDevice9_SetPixelShader,
+ (void *)LockDevice9_GetPixelShader,
+ (void *)LockDevice9_SetPixelShaderConstantF,
+ (void *)LockDevice9_GetPixelShaderConstantF,
+ (void *)LockDevice9_SetPixelShaderConstantI,
+ (void *)LockDevice9_GetPixelShaderConstantI,
+ (void *)LockDevice9_SetPixelShaderConstantB,
+ (void *)LockDevice9_GetPixelShaderConstantB,
+ (void *)LockDevice9_DrawRectPatch,
+ (void *)LockDevice9_DrawTriPatch,
+ (void *)LockDevice9_DeletePatch,
+ (void *)LockDevice9_CreateQuery
+};
+
+static HRESULT WINAPI
+LockDevice9Ex_SetConvolutionMonoKernel( struct NineDevice9Ex *This,
+ UINT width,
+ UINT height,
+ float *rows,
+ float *columns )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9Ex_SetConvolutionMonoKernel(This, width, height, rows, columns);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9Ex_ComposeRects( struct NineDevice9Ex *This,
+ IDirect3DSurface9 *pSrc,
+ IDirect3DSurface9 *pDst,
+ IDirect3DVertexBuffer9 *pSrcRectDescs,
+ UINT NumRects,
+ IDirect3DVertexBuffer9 *pDstRectDescs,
+ D3DCOMPOSERECTSOP Operation,
+ int Xoffset,
+ int Yoffset )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9Ex_ComposeRects(This, pSrc, pDst, pSrcRectDescs, NumRects, pDstRectDescs, Operation, Xoffset, Yoffset);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9Ex_PresentEx( struct NineDevice9Ex *This,
+ const RECT *pSourceRect,
+ const RECT *pDestRect,
+ HWND hDestWindowOverride,
+ const RGNDATA *pDirtyRegion,
+ DWORD dwFlags )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9Ex_PresentEx(This, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, dwFlags);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9Ex_GetGPUThreadPriority( struct NineDevice9Ex *This,
+ INT *pPriority )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9Ex_GetGPUThreadPriority(This, pPriority);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9Ex_SetGPUThreadPriority( struct NineDevice9Ex *This,
+ INT Priority )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9Ex_SetGPUThreadPriority(This, Priority);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9Ex_WaitForVBlank( struct NineDevice9Ex *This,
+ UINT iSwapChain )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9Ex_WaitForVBlank(This, iSwapChain);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9Ex_CheckResourceResidency( struct NineDevice9Ex *This,
+ IDirect3DResource9 **pResourceArray,
+ UINT32 NumResources )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9Ex_CheckResourceResidency(This, pResourceArray, NumResources);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9Ex_SetMaximumFrameLatency( struct NineDevice9Ex *This,
+ UINT MaxLatency )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9Ex_SetMaximumFrameLatency(This, MaxLatency);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9Ex_GetMaximumFrameLatency( struct NineDevice9Ex *This,
+ UINT *pMaxLatency )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9Ex_GetMaximumFrameLatency(This, pMaxLatency);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9Ex_CheckDeviceState( struct NineDevice9Ex *This,
+ HWND hDestinationWindow )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9Ex_CheckDeviceState(This, hDestinationWindow);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9Ex_CreateRenderTargetEx( struct NineDevice9Ex *This,
+ UINT Width,
+ UINT Height,
+ D3DFORMAT Format,
+ D3DMULTISAMPLE_TYPE MultiSample,
+ DWORD MultisampleQuality,
+ BOOL Lockable,
+ IDirect3DSurface9 **ppSurface,
+ HANDLE *pSharedHandle,
+ DWORD Usage )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9Ex_CreateRenderTargetEx(This, Width, Height, Format, MultiSample, MultisampleQuality, Lockable, ppSurface, pSharedHandle, Usage);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9Ex_CreateOffscreenPlainSurfaceEx( struct NineDevice9Ex *This,
+ UINT Width,
+ UINT Height,
+ D3DFORMAT Format,
+ D3DPOOL Pool,
+ IDirect3DSurface9 **ppSurface,
+ HANDLE *pSharedHandle,
+ DWORD Usage )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9Ex_CreateOffscreenPlainSurfaceEx(This, Width, Height, Format, Pool, ppSurface, pSharedHandle, Usage);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9Ex_CreateDepthStencilSurfaceEx( struct NineDevice9Ex *This,
+ UINT Width,
+ UINT Height,
+ D3DFORMAT Format,
+ D3DMULTISAMPLE_TYPE MultiSample,
+ DWORD MultisampleQuality,
+ BOOL Discard,
+ IDirect3DSurface9 **ppSurface,
+ HANDLE *pSharedHandle,
+ DWORD Usage )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9Ex_CreateDepthStencilSurfaceEx(This, Width, Height, Format, MultiSample, MultisampleQuality, Discard, ppSurface, pSharedHandle, Usage);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9Ex_ResetEx( struct NineDevice9Ex *This,
+ D3DPRESENT_PARAMETERS *pPresentationParameters,
+ D3DDISPLAYMODEEX *pFullscreenDisplayMode )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9Ex_ResetEx(This, pPresentationParameters, pFullscreenDisplayMode);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9Ex_GetDisplayModeEx( struct NineDevice9Ex *This,
+ UINT iSwapChain,
+ D3DDISPLAYMODEEX *pMode,
+ D3DDISPLAYROTATION *pRotation )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9Ex_GetDisplayModeEx(This, iSwapChain, pMode, pRotation);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+IDirect3DDevice9ExVtbl LockDevice9Ex_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)LockDevice9_TestCooperativeLevel,
+ (void *)LockDevice9_GetAvailableTextureMem,
+ (void *)LockDevice9_EvictManagedResources,
+ (void *)LockDevice9_GetDirect3D,
+ (void *)NineDevice9_GetDeviceCaps,
+ (void *)LockDevice9_GetDisplayMode,
+ (void *)NineDevice9_GetCreationParameters,
+ (void *)LockDevice9_SetCursorProperties,
+ (void *)LockDevice9_SetCursorPosition,
+ (void *)LockDevice9_ShowCursor,
+ (void *)LockDevice9_CreateAdditionalSwapChain,
+ (void *)LockDevice9_GetSwapChain,
+ (void *)LockDevice9_GetNumberOfSwapChains,
+ (void *)LockDevice9_Reset,
+ (void *)LockDevice9_Present,
+ (void *)LockDevice9_GetBackBuffer,
+ (void *)LockDevice9_GetRasterStatus,
+ (void *)LockDevice9_SetDialogBoxMode,
+ (void *)LockDevice9_SetGammaRamp,
+ (void *)LockDevice9_GetGammaRamp,
+ (void *)LockDevice9_CreateTexture,
+ (void *)LockDevice9_CreateVolumeTexture,
+ (void *)LockDevice9_CreateCubeTexture,
+ (void *)LockDevice9_CreateVertexBuffer,
+ (void *)LockDevice9_CreateIndexBuffer,
+ (void *)LockDevice9_CreateRenderTarget,
+ (void *)LockDevice9_CreateDepthStencilSurface,
+ (void *)LockDevice9_UpdateSurface,
+ (void *)LockDevice9_UpdateTexture,
+ (void *)LockDevice9_GetRenderTargetData,
+ (void *)LockDevice9_GetFrontBufferData,
+ (void *)LockDevice9_StretchRect,
+ (void *)LockDevice9_ColorFill,
+ (void *)LockDevice9_CreateOffscreenPlainSurface,
+ (void *)LockDevice9_SetRenderTarget,
+ (void *)LockDevice9_GetRenderTarget,
+ (void *)LockDevice9_SetDepthStencilSurface,
+ (void *)LockDevice9_GetDepthStencilSurface,
+ (void *)LockDevice9_BeginScene,
+ (void *)LockDevice9_EndScene,
+ (void *)LockDevice9_Clear,
+ (void *)LockDevice9_SetTransform,
+ (void *)LockDevice9_GetTransform,
+ (void *)LockDevice9_MultiplyTransform,
+ (void *)LockDevice9_SetViewport,
+ (void *)LockDevice9_GetViewport,
+ (void *)LockDevice9_SetMaterial,
+ (void *)LockDevice9_GetMaterial,
+ (void *)LockDevice9_SetLight,
+ (void *)LockDevice9_GetLight,
+ (void *)LockDevice9_LightEnable,
+ (void *)LockDevice9_GetLightEnable,
+ (void *)LockDevice9_SetClipPlane,
+ (void *)LockDevice9_GetClipPlane,
+ (void *)LockDevice9_SetRenderState,
+ (void *)LockDevice9_GetRenderState,
+ (void *)LockDevice9_CreateStateBlock,
+ (void *)LockDevice9_BeginStateBlock,
+ (void *)LockDevice9_EndStateBlock,
+ (void *)LockDevice9_SetClipStatus,
+ (void *)LockDevice9_GetClipStatus,
+ (void *)LockDevice9_GetTexture,
+ (void *)LockDevice9_SetTexture,
+ (void *)LockDevice9_GetTextureStageState,
+ (void *)LockDevice9_SetTextureStageState,
+ (void *)LockDevice9_GetSamplerState,
+ (void *)LockDevice9_SetSamplerState,
+ (void *)LockDevice9_ValidateDevice,
+ (void *)LockDevice9_SetPaletteEntries,
+ (void *)LockDevice9_GetPaletteEntries,
+ (void *)LockDevice9_SetCurrentTexturePalette,
+ (void *)LockDevice9_GetCurrentTexturePalette,
+ (void *)LockDevice9_SetScissorRect,
+ (void *)LockDevice9_GetScissorRect,
+ (void *)LockDevice9_SetSoftwareVertexProcessing,
+ (void *)LockDevice9_GetSoftwareVertexProcessing,
+ (void *)LockDevice9_SetNPatchMode,
+ (void *)LockDevice9_GetNPatchMode,
+ (void *)LockDevice9_DrawPrimitive,
+ (void *)LockDevice9_DrawIndexedPrimitive,
+ (void *)LockDevice9_DrawPrimitiveUP,
+ (void *)LockDevice9_DrawIndexedPrimitiveUP,
+ (void *)LockDevice9_ProcessVertices,
+ (void *)LockDevice9_CreateVertexDeclaration,
+ (void *)LockDevice9_SetVertexDeclaration,
+ (void *)LockDevice9_GetVertexDeclaration,
+ (void *)LockDevice9_SetFVF,
+ (void *)LockDevice9_GetFVF,
+ (void *)LockDevice9_CreateVertexShader,
+ (void *)LockDevice9_SetVertexShader,
+ (void *)LockDevice9_GetVertexShader,
+ (void *)LockDevice9_SetVertexShaderConstantF,
+ (void *)LockDevice9_GetVertexShaderConstantF,
+ (void *)LockDevice9_SetVertexShaderConstantI,
+ (void *)LockDevice9_GetVertexShaderConstantI,
+ (void *)LockDevice9_SetVertexShaderConstantB,
+ (void *)LockDevice9_GetVertexShaderConstantB,
+ (void *)LockDevice9_SetStreamSource,
+ (void *)LockDevice9_GetStreamSource,
+ (void *)LockDevice9_SetStreamSourceFreq,
+ (void *)LockDevice9_GetStreamSourceFreq,
+ (void *)LockDevice9_SetIndices,
+ (void *)LockDevice9_GetIndices,
+ (void *)LockDevice9_CreatePixelShader,
+ (void *)LockDevice9_SetPixelShader,
+ (void *)LockDevice9_GetPixelShader,
+ (void *)LockDevice9_SetPixelShaderConstantF,
+ (void *)LockDevice9_GetPixelShaderConstantF,
+ (void *)LockDevice9_SetPixelShaderConstantI,
+ (void *)LockDevice9_GetPixelShaderConstantI,
+ (void *)LockDevice9_SetPixelShaderConstantB,
+ (void *)LockDevice9_GetPixelShaderConstantB,
+ (void *)LockDevice9_DrawRectPatch,
+ (void *)LockDevice9_DrawTriPatch,
+ (void *)LockDevice9_DeletePatch,
+ (void *)LockDevice9_CreateQuery,
+ (void *)LockDevice9Ex_SetConvolutionMonoKernel,
+ (void *)LockDevice9Ex_ComposeRects,
+ (void *)LockDevice9Ex_PresentEx,
+ (void *)LockDevice9Ex_GetGPUThreadPriority,
+ (void *)LockDevice9Ex_SetGPUThreadPriority,
+ (void *)LockDevice9Ex_WaitForVBlank,
+ (void *)LockDevice9Ex_CheckResourceResidency,
+ (void *)LockDevice9Ex_SetMaximumFrameLatency,
+ (void *)LockDevice9Ex_GetMaximumFrameLatency,
+ (void *)LockDevice9Ex_CheckDeviceState,
+ (void *)LockDevice9Ex_CreateRenderTargetEx,
+ (void *)LockDevice9Ex_CreateOffscreenPlainSurfaceEx,
+ (void *)LockDevice9Ex_CreateDepthStencilSurfaceEx,
+ (void *)LockDevice9Ex_ResetEx,
+ (void *)LockDevice9Ex_GetDisplayModeEx
+};
+
+static HRESULT WINAPI
+LockDevice9Video_GetContentProtectionCaps( struct NineDevice9Video *This,
+ const GUID *pCryptoType,
+ const GUID *pDecodeProfile,
+ D3DCONTENTPROTECTIONCAPS *pCaps )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9Video_GetContentProtectionCaps(This, pCryptoType, pDecodeProfile, pCaps);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9Video_CreateAuthenticatedChannel( struct NineDevice9Video *This,
+ D3DAUTHENTICATEDCHANNELTYPE ChannelType,
+ IDirect3DAuthenticatedChannel9 **ppAuthenticatedChannel,
+ HANDLE *pChannelHandle )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9Video_CreateAuthenticatedChannel(This, ChannelType, ppAuthenticatedChannel, pChannelHandle);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockDevice9Video_CreateCryptoSession( struct NineDevice9Video *This,
+ const GUID *pCryptoType,
+ const GUID *pDecodeProfile,
+ IDirect3DCryptoSession9 **ppCryptoSession,
+ HANDLE *pCryptoHandle )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineDevice9Video_CreateCryptoSession(This, pCryptoType, pDecodeProfile, ppCryptoSession, pCryptoHandle);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+IDirect3DDevice9VideoVtbl LockDevice9Video_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)LockDevice9Video_GetContentProtectionCaps,
+ (void *)LockDevice9Video_CreateAuthenticatedChannel,
+ (void *)LockDevice9Video_CreateCryptoSession
+};
+
+static HRESULT WINAPI
+LockIndexBuffer9_Lock( struct NineIndexBuffer9 *This,
+ UINT OffsetToLock,
+ UINT SizeToLock,
+ void **ppbData,
+ DWORD Flags )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineIndexBuffer9_Lock(This, OffsetToLock, SizeToLock, ppbData, Flags);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockIndexBuffer9_Unlock( struct NineIndexBuffer9 *This )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineIndexBuffer9_Unlock(This);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+#if 0
+static HRESULT WINAPI
+LockIndexBuffer9_GetDesc( struct NineIndexBuffer9 *This,
+ D3DINDEXBUFFER_DESC *pDesc )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineIndexBuffer9_GetDesc(This, pDesc);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+#endif
+
+IDirect3DIndexBuffer9Vtbl LockIndexBuffer9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */
+ (void *)LockResource9_SetPrivateData,
+ (void *)LockResource9_GetPrivateData,
+ (void *)LockResource9_FreePrivateData,
+ (void *)LockResource9_SetPriority,
+ (void *)LockResource9_GetPriority,
+ (void *)NineResource9_PreLoad, /* nop */
+ (void *)NineResource9_GetType, /* immutable */
+ (void *)LockIndexBuffer9_Lock,
+ (void *)LockIndexBuffer9_Unlock,
+ (void *)NineIndexBuffer9_GetDesc /* immutable */
+};
+
+#if 0
+static HRESULT WINAPI
+LockPixelShader9_GetDevice( struct NinePixelShader9 *This,
+ IDirect3DDevice9 **ppDevice )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineUnknown_GetDevice(NineUnknown(This), ppDevice);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+#endif
+
+static HRESULT WINAPI
+LockPixelShader9_GetFunction( struct NinePixelShader9 *This,
+ void *pData,
+ UINT *pSizeOfData )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NinePixelShader9_GetFunction(This, pData, pSizeOfData);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+IDirect3DPixelShader9Vtbl LockPixelShader9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)NineUnknown_GetDevice,
+ (void *)LockPixelShader9_GetFunction
+};
+
+#if 0
+static HRESULT WINAPI
+LockQuery9_GetDevice( struct NineQuery9 *This,
+ IDirect3DDevice9 **ppDevice )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineUnknown_GetDevice(NineUnknown(This), ppDevice);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+#endif
+
+#if 0
+static D3DQUERYTYPE WINAPI
+LockQuery9_GetType( struct NineQuery9 *This )
+{
+ D3DQUERYTYPE r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineQuery9_GetType(This);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+#endif
+
+#if 0
+static DWORD WINAPI
+LockQuery9_GetDataSize( struct NineQuery9 *This )
+{
+ DWORD r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineQuery9_GetDataSize(This);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+#endif
+
+static HRESULT WINAPI
+LockQuery9_Issue( struct NineQuery9 *This,
+ DWORD dwIssueFlags )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineQuery9_Issue(This, dwIssueFlags);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockQuery9_GetData( struct NineQuery9 *This,
+ void *pData,
+ DWORD dwSize,
+ DWORD dwGetDataFlags )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineQuery9_GetData(This, pData, dwSize, dwGetDataFlags);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+IDirect3DQuery9Vtbl LockQuery9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)NineUnknown_GetDevice, /* actually part of Query9 iface */
+ (void *)NineQuery9_GetType, /* immutable */
+ (void *)NineQuery9_GetDataSize, /* immutable */
+ (void *)LockQuery9_Issue,
+ (void *)LockQuery9_GetData
+};
+
+#if 0
+static HRESULT WINAPI
+LockStateBlock9_GetDevice( struct NineStateBlock9 *This,
+ IDirect3DDevice9 **ppDevice )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineUnknown_GetDevice(NineUnknown(This), ppDevice);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+#endif
+
+static HRESULT WINAPI
+LockStateBlock9_Capture( struct NineStateBlock9 *This )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineStateBlock9_Capture(This);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockStateBlock9_Apply( struct NineStateBlock9 *This )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineStateBlock9_Apply(This);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+IDirect3DStateBlock9Vtbl LockStateBlock9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)NineUnknown_GetDevice, /* actually part of StateBlock9 iface */
+ (void *)LockStateBlock9_Capture,
+ (void *)LockStateBlock9_Apply
+};
+
+static HRESULT WINAPI
+LockSurface9_GetContainer( struct NineSurface9 *This,
+ REFIID riid,
+ void **ppContainer )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineSurface9_GetContainer(This, riid, ppContainer);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+#if 0
+static HRESULT WINAPI
+LockSurface9_GetDesc( struct NineSurface9 *This,
+ D3DSURFACE_DESC *pDesc )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineSurface9_GetDesc(This, pDesc);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+#endif
+
+static HRESULT WINAPI
+LockSurface9_LockRect( struct NineSurface9 *This,
+ D3DLOCKED_RECT *pLockedRect,
+ const RECT *pRect,
+ DWORD Flags )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineSurface9_LockRect(This, pLockedRect, pRect, Flags);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockSurface9_UnlockRect( struct NineSurface9 *This )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineSurface9_UnlockRect(This);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockSurface9_GetDC( struct NineSurface9 *This,
+ HDC *phdc )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineSurface9_GetDC(This, phdc);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockSurface9_ReleaseDC( struct NineSurface9 *This,
+ HDC hdc )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineSurface9_ReleaseDC(This, hdc);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+IDirect3DSurface9Vtbl LockSurface9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */
+ (void *)LockResource9_SetPrivateData,
+ (void *)LockResource9_GetPrivateData,
+ (void *)LockResource9_FreePrivateData,
+ (void *)LockResource9_SetPriority,
+ (void *)LockResource9_GetPriority,
+ (void *)NineResource9_PreLoad, /* nop */
+ (void *)NineResource9_GetType, /* immutable */
+ (void *)LockSurface9_GetContainer,
+ (void *)NineSurface9_GetDesc, /* immutable */
+ (void *)LockSurface9_LockRect,
+ (void *)LockSurface9_UnlockRect,
+ (void *)LockSurface9_GetDC,
+ (void *)LockSurface9_ReleaseDC
+};
+
+static HRESULT WINAPI
+LockSwapChain9_Present( struct NineSwapChain9 *This,
+ const RECT *pSourceRect,
+ const RECT *pDestRect,
+ HWND hDestWindowOverride,
+ const RGNDATA *pDirtyRegion,
+ DWORD dwFlags )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineSwapChain9_Present(This, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, dwFlags);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockSwapChain9_GetFrontBufferData( struct NineSwapChain9 *This,
+ IDirect3DSurface9 *pDestSurface )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineSwapChain9_GetFrontBufferData(This, pDestSurface);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockSwapChain9_GetBackBuffer( struct NineSwapChain9 *This,
+ UINT iBackBuffer,
+ D3DBACKBUFFER_TYPE Type,
+ IDirect3DSurface9 **ppBackBuffer )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineSwapChain9_GetBackBuffer(This, iBackBuffer, Type, ppBackBuffer);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockSwapChain9_GetRasterStatus( struct NineSwapChain9 *This,
+ D3DRASTER_STATUS *pRasterStatus )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineSwapChain9_GetRasterStatus(This, pRasterStatus);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockSwapChain9_GetDisplayMode( struct NineSwapChain9 *This,
+ D3DDISPLAYMODE *pMode )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineSwapChain9_GetDisplayMode(This, pMode);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+#if 0
+static HRESULT WINAPI
+LockSwapChain9_GetDevice( struct NineSwapChain9 *This,
+ IDirect3DDevice9 **ppDevice )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineUnknown_GetDevice(NineUnknown(This), ppDevice);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+#endif
+
+static HRESULT WINAPI
+LockSwapChain9_GetPresentParameters( struct NineSwapChain9 *This,
+ D3DPRESENT_PARAMETERS *pPresentationParameters )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineSwapChain9_GetPresentParameters(This, pPresentationParameters);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+IDirect3DSwapChain9Vtbl LockSwapChain9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)LockSwapChain9_Present,
+ (void *)LockSwapChain9_GetFrontBufferData,
+ (void *)LockSwapChain9_GetBackBuffer,
+ (void *)LockSwapChain9_GetRasterStatus,
+ (void *)LockSwapChain9_GetDisplayMode,
+ (void *)NineUnknown_GetDevice, /* actually part of SwapChain9 iface */
+ (void *)LockSwapChain9_GetPresentParameters
+};
+
+static HRESULT WINAPI
+LockSwapChain9Ex_GetLastPresentCount( struct NineSwapChain9Ex *This,
+ UINT *pLastPresentCount )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineSwapChain9Ex_GetLastPresentCount(This, pLastPresentCount);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockSwapChain9Ex_GetPresentStats( struct NineSwapChain9Ex *This,
+ D3DPRESENTSTATS *pPresentationStatistics )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineSwapChain9Ex_GetPresentStats(This, pPresentationStatistics);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockSwapChain9Ex_GetDisplayModeEx( struct NineSwapChain9Ex *This,
+ D3DDISPLAYMODEEX *pMode,
+ D3DDISPLAYROTATION *pRotation )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineSwapChain9Ex_GetDisplayModeEx(This, pMode, pRotation);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+IDirect3DSwapChain9ExVtbl LockSwapChain9Ex_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)LockSwapChain9_Present,
+ (void *)LockSwapChain9_GetFrontBufferData,
+ (void *)LockSwapChain9_GetBackBuffer,
+ (void *)LockSwapChain9_GetRasterStatus,
+ (void *)LockSwapChain9_GetDisplayMode,
+ (void *)NineUnknown_GetDevice, /* actually part of NineSwapChain9 iface */
+ (void *)LockSwapChain9_GetPresentParameters,
+ (void *)LockSwapChain9Ex_GetLastPresentCount,
+ (void *)LockSwapChain9Ex_GetPresentStats,
+ (void *)LockSwapChain9Ex_GetDisplayModeEx
+};
+
+#if 0
+static HRESULT WINAPI
+LockTexture9_GetLevelDesc( struct NineTexture9 *This,
+ UINT Level,
+ D3DSURFACE_DESC *pDesc )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineTexture9_GetLevelDesc(This, Level, pDesc);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+#endif
+
+#if 0
+static HRESULT WINAPI
+LockTexture9_GetSurfaceLevel( struct NineTexture9 *This,
+ UINT Level,
+ IDirect3DSurface9 **ppSurfaceLevel )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineTexture9_GetSurfaceLevel(This, Level, ppSurfaceLevel);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+#endif
+
+static HRESULT WINAPI
+LockTexture9_LockRect( struct NineTexture9 *This,
+ UINT Level,
+ D3DLOCKED_RECT *pLockedRect,
+ const RECT *pRect,
+ DWORD Flags )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineTexture9_LockRect(This, Level, pLockedRect, pRect, Flags);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockTexture9_UnlockRect( struct NineTexture9 *This,
+ UINT Level )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineTexture9_UnlockRect(This, Level);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockTexture9_AddDirtyRect( struct NineTexture9 *This,
+ const RECT *pDirtyRect )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineTexture9_AddDirtyRect(This, pDirtyRect);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+IDirect3DTexture9Vtbl LockTexture9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */
+ (void *)LockResource9_SetPrivateData,
+ (void *)LockResource9_GetPrivateData,
+ (void *)LockResource9_FreePrivateData,
+ (void *)LockResource9_SetPriority,
+ (void *)LockResource9_GetPriority,
+ (void *)LockBaseTexture9_PreLoad,
+ (void *)NineResource9_GetType, /* immutable */
+ (void *)LockBaseTexture9_SetLOD,
+ (void *)LockBaseTexture9_GetLOD,
+ (void *)LockBaseTexture9_GetLevelCount,
+ (void *)LockBaseTexture9_SetAutoGenFilterType,
+ (void *)LockBaseTexture9_GetAutoGenFilterType,
+ (void *)LockBaseTexture9_GenerateMipSubLevels,
+ (void *)NineTexture9_GetLevelDesc, /* immutable */
+ (void *)NineTexture9_GetSurfaceLevel, /* AddRef */
+ (void *)LockTexture9_LockRect,
+ (void *)LockTexture9_UnlockRect,
+ (void *)LockTexture9_AddDirtyRect
+};
+
+static HRESULT WINAPI
+LockVertexBuffer9_Lock( struct NineVertexBuffer9 *This,
+ UINT OffsetToLock,
+ UINT SizeToLock,
+ void **ppbData,
+ DWORD Flags )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineVertexBuffer9_Lock(This, OffsetToLock, SizeToLock, ppbData, Flags);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockVertexBuffer9_Unlock( struct NineVertexBuffer9 *This )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineVertexBuffer9_Unlock(This);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+#if 0
+static HRESULT WINAPI
+LockVertexBuffer9_GetDesc( struct NineVertexBuffer9 *This,
+ D3DVERTEXBUFFER_DESC *pDesc )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineVertexBuffer9_GetDesc(This, pDesc);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+#endif
+
+IDirect3DVertexBuffer9Vtbl LockVertexBuffer9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */
+ (void *)LockResource9_SetPrivateData,
+ (void *)LockResource9_GetPrivateData,
+ (void *)LockResource9_FreePrivateData,
+ (void *)LockResource9_SetPriority,
+ (void *)LockResource9_GetPriority,
+ (void *)NineResource9_PreLoad, /* nop */
+ (void *)NineResource9_GetType, /* immutable */
+ (void *)LockVertexBuffer9_Lock,
+ (void *)LockVertexBuffer9_Unlock,
+ (void *)NineVertexBuffer9_GetDesc /* immutable */
+};
+
+#if 0
+static HRESULT WINAPI
+LockVertexDeclaration9_GetDevice( struct NineVertexDeclaration9 *This,
+ IDirect3DDevice9 **ppDevice )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineUnknown_GetDevice(NineUnknown(This), ppDevice);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+#endif
+
+static HRESULT WINAPI
+LockVertexDeclaration9_GetDeclaration( struct NineVertexDeclaration9 *This,
+ D3DVERTEXELEMENT9 *pElement,
+ UINT *pNumElements )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineVertexDeclaration9_GetDeclaration(This, pElement, pNumElements);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+IDirect3DVertexDeclaration9Vtbl LockVertexDeclaration9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)NineUnknown_GetDevice, /* actually part of VertexDecl9 iface */
+ (void *)LockVertexDeclaration9_GetDeclaration
+};
+
+#if 0
+static HRESULT WINAPI
+LockVertexShader9_GetDevice( struct NineVertexShader9 *This,
+ IDirect3DDevice9 **ppDevice )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineUnknown_GetDevice(NineUnknown(This), ppDevice);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+#endif
+
+static HRESULT WINAPI
+LockVertexShader9_GetFunction( struct NineVertexShader9 *This,
+ void *pData,
+ UINT *pSizeOfData )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineVertexShader9_GetFunction(This, pData, pSizeOfData);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+IDirect3DVertexShader9Vtbl LockVertexShader9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)NineUnknown_GetDevice,
+ (void *)LockVertexShader9_GetFunction
+};
+
+#if 0
+static HRESULT WINAPI
+LockVolume9_GetDevice( struct NineVolume9 *This,
+ IDirect3DDevice9 **ppDevice )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineUnknown_GetDevice(NineUnknown(This), ppDevice);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+#endif
+
+static HRESULT WINAPI
+LockVolume9_SetPrivateData( struct NineVolume9 *This,
+ REFGUID refguid,
+ const void *pData,
+ DWORD SizeOfData,
+ DWORD Flags )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineVolume9_SetPrivateData(This, refguid, pData, SizeOfData, Flags);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockVolume9_GetPrivateData( struct NineVolume9 *This,
+ REFGUID refguid,
+ void *pData,
+ DWORD *pSizeOfData )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineVolume9_GetPrivateData(This, refguid, pData, pSizeOfData);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockVolume9_FreePrivateData( struct NineVolume9 *This,
+ REFGUID refguid )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineVolume9_FreePrivateData(This, refguid);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockVolume9_GetContainer( struct NineVolume9 *This,
+ REFIID riid,
+ void **ppContainer )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineVolume9_GetContainer(This, riid, ppContainer);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+#if 0
+static HRESULT WINAPI
+LockVolume9_GetDesc( struct NineVolume9 *This,
+ D3DVOLUME_DESC *pDesc )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineVolume9_GetDesc(This, pDesc);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+#endif
+
+static HRESULT WINAPI
+LockVolume9_LockBox( struct NineVolume9 *This,
+ D3DLOCKED_BOX *pLockedVolume,
+ const D3DBOX *pBox,
+ DWORD Flags )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineVolume9_LockBox(This, pLockedVolume, pBox, Flags);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockVolume9_UnlockBox( struct NineVolume9 *This )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineVolume9_UnlockBox(This);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+IDirect3DVolume9Vtbl LockVolume9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)NineUnknown_GetDevice, /* actually part of Volume9 iface */
+ (void *)LockVolume9_SetPrivateData,
+ (void *)LockVolume9_GetPrivateData,
+ (void *)LockVolume9_FreePrivateData,
+ (void *)LockVolume9_GetContainer,
+ (void *)NineVolume9_GetDesc, /* immutable */
+ (void *)LockVolume9_LockBox,
+ (void *)LockVolume9_UnlockBox
+};
+
+#if 0
+static HRESULT WINAPI
+LockVolumeTexture9_GetLevelDesc( struct NineVolumeTexture9 *This,
+ UINT Level,
+ D3DVOLUME_DESC *pDesc )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineVolumeTexture9_GetLevelDesc(This, Level, pDesc);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+#endif
+
+#if 0
+static HRESULT WINAPI
+LockVolumeTexture9_GetVolumeLevel( struct NineVolumeTexture9 *This,
+ UINT Level,
+ IDirect3DVolume9 **ppVolumeLevel )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineVolumeTexture9_GetVolumeLevel(This, Level, ppVolumeLevel);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+#endif
+
+static HRESULT WINAPI
+LockVolumeTexture9_LockBox( struct NineVolumeTexture9 *This,
+ UINT Level,
+ D3DLOCKED_BOX *pLockedVolume,
+ const D3DBOX *pBox,
+ DWORD Flags )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineVolumeTexture9_LockBox(This, Level, pLockedVolume, pBox, Flags);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockVolumeTexture9_UnlockBox( struct NineVolumeTexture9 *This,
+ UINT Level )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineVolumeTexture9_UnlockBox(This, Level);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+static HRESULT WINAPI
+LockVolumeTexture9_AddDirtyBox( struct NineVolumeTexture9 *This,
+ const D3DBOX *pDirtyBox )
+{
+ HRESULT r;
+ pipe_mutex_lock(d3dlock_global);
+ r = NineVolumeTexture9_AddDirtyBox(This, pDirtyBox);
+ pipe_mutex_unlock(d3dlock_global);
+ return r;
+}
+
+IDirect3DVolumeTexture9Vtbl LockVolumeTexture9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */
+ (void *)LockResource9_SetPrivateData,
+ (void *)LockResource9_GetPrivateData,
+ (void *)LockResource9_FreePrivateData,
+ (void *)LockResource9_SetPriority,
+ (void *)LockResource9_GetPriority,
+ (void *)LockBaseTexture9_PreLoad,
+ (void *)NineResource9_GetType, /* immutable */
+ (void *)LockBaseTexture9_SetLOD,
+ (void *)LockBaseTexture9_GetLOD,
+ (void *)LockBaseTexture9_GetLevelCount,
+ (void *)LockBaseTexture9_SetAutoGenFilterType,
+ (void *)LockBaseTexture9_GetAutoGenFilterType,
+ (void *)LockBaseTexture9_GenerateMipSubLevels,
+ (void *)NineVolumeTexture9_GetLevelDesc, /* immutable */
+ (void *)NineVolumeTexture9_GetVolumeLevel, /* AddRef */
+ (void *)LockVolumeTexture9_LockBox,
+ (void *)LockVolumeTexture9_UnlockBox,
+ (void *)LockVolumeTexture9_AddDirtyBox
+};
+
+ID3DAdapter9Vtbl LockAdapter9_vtable = { /* not used */
+ (void *)NULL,
+ (void *)NULL,
+ (void *)NULL,
+ (void *)NULL,
+ (void *)NULL,
+ (void *)NULL,
+ (void *)NULL,
+ (void *)NULL,
+ (void *)NULL,
+ (void *)NULL,
+ (void *)NULL,
+ (void *)NULL
+};
diff --git a/src/gallium/state_trackers/nine/nine_lock.h b/src/gallium/state_trackers/nine/nine_lock.h
new file mode 100644
index 00000000000..9738a203c14
--- /dev/null
+++ b/src/gallium/state_trackers/nine/nine_lock.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2013 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _NINE_LOCK_H_
+#define _NINE_LOCK_H_
+
+#include "d3d9.h"
+#include "d3dadapter/d3dadapter9.h"
+
+extern IDirect3DAuthenticatedChannel9Vtbl LockAuthenticatedChannel9_vtable;
+extern IDirect3DCryptoSession9Vtbl LockCryptoSession9_vtable;
+extern IDirect3DCubeTexture9Vtbl LockCubeTexture9_vtable;
+extern IDirect3DDevice9Vtbl LockDevice9_vtable;
+extern IDirect3DDevice9ExVtbl LockDevice9Ex_vtable;
+extern IDirect3DDevice9VideoVtbl LockDevice9Video_vtable;
+extern IDirect3DIndexBuffer9Vtbl LockIndexBuffer9_vtable;
+extern IDirect3DPixelShader9Vtbl LockPixelShader9_vtable;
+extern IDirect3DQuery9Vtbl LockQuery9_vtable;
+extern IDirect3DStateBlock9Vtbl LockStateBlock9_vtable;
+extern IDirect3DSurface9Vtbl LockSurface9_vtable;
+extern IDirect3DSwapChain9Vtbl LockSwapChain9_vtable;
+extern IDirect3DSwapChain9ExVtbl LockSwapChain9Ex_vtable;
+extern IDirect3DTexture9Vtbl LockTexture9_vtable;
+extern IDirect3DVertexBuffer9Vtbl LockVertexBuffer9_vtable;
+extern IDirect3DVertexDeclaration9Vtbl LockVertexDeclaration9_vtable;
+extern IDirect3DVertexShader9Vtbl LockVertexShader9_vtable;
+extern IDirect3DVolume9Vtbl LockVolume9_vtable;
+extern IDirect3DVolumeTexture9Vtbl LockVolumeTexture9_vtable;
+extern IDirect3DVolumeTexture9Vtbl LockVolumeTexture9_vtable;
+extern ID3DAdapter9Vtbl LockAdapter9_vtable;
+
+#endif /* _NINE_LOCK_H_ */
diff --git a/src/gallium/state_trackers/nine/nine_pdata.h b/src/gallium/state_trackers/nine/nine_pdata.h
new file mode 100644
index 00000000000..7bdd702cfbb
--- /dev/null
+++ b/src/gallium/state_trackers/nine/nine_pdata.h
@@ -0,0 +1,45 @@
+
+#ifndef _NINE_PDATA_H_
+#define _NINE_PDATA_H_
+
+struct pheader
+{
+ boolean unknown;
+ DWORD size;
+ char data[1];
+};
+
+static int
+ht_guid_compare( void *a,
+ void *b )
+{
+ return GUID_equal(a, b) ? 0 : 1;
+}
+
+static unsigned
+ht_guid_hash( void *key )
+{
+ unsigned i, hash = 0;
+ const unsigned char *str = key;
+
+ for (i = 0; i < sizeof(GUID); i++) {
+ hash = (unsigned)(str[i]) + (hash << 6) + (hash << 16) - hash;
+ }
+
+ return hash;
+}
+
+static enum pipe_error
+ht_guid_delete( void *key,
+ void *value,
+ void *data )
+{
+ struct pheader *header = value;
+
+ if (header->unknown) { IUnknown_Release(*(IUnknown **)header->data); }
+ FREE(header);
+
+ return PIPE_OK;
+}
+
+#endif /* _NINE_PDATA_H_ */
diff --git a/src/gallium/state_trackers/nine/nine_pipe.c b/src/gallium/state_trackers/nine/nine_pipe.c
new file mode 100644
index 00000000000..3a7bb90d222
--- /dev/null
+++ b/src/gallium/state_trackers/nine/nine_pipe.c
@@ -0,0 +1,410 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ * Copyright 2013 Christoph Bumiller
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "device9.h"
+#include "nine_pipe.h"
+
+#include "cso_cache/cso_context.h"
+
+void
+nine_convert_dsa_state(struct cso_context *ctx, const DWORD *rs)
+{
+ struct pipe_depth_stencil_alpha_state dsa;
+
+ memset(&dsa, 0, sizeof(dsa)); /* memcmp safety */
+
+ if (rs[D3DRS_ZENABLE]) {
+ dsa.depth.enabled = 1;
+ dsa.depth.writemask = !!rs[D3DRS_ZWRITEENABLE];
+ dsa.depth.func = d3dcmpfunc_to_pipe_func(rs[D3DRS_ZFUNC]);
+ }
+
+ if (rs[D3DRS_STENCILENABLE]) {
+ dsa.stencil[0].enabled = 1;
+ dsa.stencil[0].func = d3dcmpfunc_to_pipe_func(rs[D3DRS_STENCILFUNC]);
+ dsa.stencil[0].fail_op = d3dstencilop_to_pipe_stencil_op(rs[D3DRS_STENCILFAIL]);
+ dsa.stencil[0].zpass_op = d3dstencilop_to_pipe_stencil_op(rs[D3DRS_STENCILPASS]);
+ dsa.stencil[0].zfail_op = d3dstencilop_to_pipe_stencil_op(rs[D3DRS_STENCILZFAIL]);
+ dsa.stencil[0].valuemask = rs[D3DRS_STENCILMASK];
+ dsa.stencil[0].writemask = rs[D3DRS_STENCILWRITEMASK];
+
+ if (rs[D3DRS_TWOSIDEDSTENCILMODE]) {
+ dsa.stencil[1].enabled = 1;
+ dsa.stencil[1].func = d3dcmpfunc_to_pipe_func(rs[D3DRS_CCW_STENCILFUNC]);
+ dsa.stencil[1].fail_op = d3dstencilop_to_pipe_stencil_op(rs[D3DRS_CCW_STENCILFAIL]);
+ dsa.stencil[1].zpass_op = d3dstencilop_to_pipe_stencil_op(rs[D3DRS_CCW_STENCILPASS]);
+ dsa.stencil[1].zfail_op = d3dstencilop_to_pipe_stencil_op(rs[D3DRS_CCW_STENCILZFAIL]);
+ dsa.stencil[1].valuemask = dsa.stencil[0].valuemask;
+ dsa.stencil[1].writemask = dsa.stencil[0].writemask;
+ }
+ }
+
+ if (rs[D3DRS_ALPHATESTENABLE]) {
+ dsa.alpha.enabled = 1;
+ dsa.alpha.func = d3dcmpfunc_to_pipe_func(rs[D3DRS_ALPHAFUNC]);
+ dsa.alpha.ref_value = (float)rs[D3DRS_ALPHAREF] / 255.0f;
+ }
+
+ cso_set_depth_stencil_alpha(ctx, &dsa);
+}
+
+/* TODO: Keep a static copy in device so we don't have to memset every time ? */
+void
+nine_convert_rasterizer_state(struct cso_context *ctx, const DWORD *rs)
+{
+ struct pipe_rasterizer_state rast;
+
+ memset(&rast, 0, sizeof(rast)); /* memcmp safety */
+
+ rast.flatshade = rs[D3DRS_SHADEMODE] == D3DSHADE_FLAT;
+ /* rast.light_twoside = 0; */
+ /* rast.clamp_fragment_color = 0; */
+ /* rast.clamp_vertex_color = 0; */
+ /* rast.front_ccw = 0; */
+ rast.cull_face = d3dcull_to_pipe_face(rs[D3DRS_CULLMODE]);
+ rast.fill_front = d3dfillmode_to_pipe_polygon_mode(rs[D3DRS_FILLMODE]);
+ rast.fill_back = rast.fill_front;
+ rast.offset_tri = !!(rs[D3DRS_DEPTHBIAS] | rs[D3DRS_SLOPESCALEDEPTHBIAS]);
+ rast.offset_line = rast.offset_tri; /* triangles in wireframe mode */
+ rast.offset_point = 0; /* XXX ? */
+ rast.scissor = !!rs[D3DRS_SCISSORTESTENABLE];
+ /* rast.poly_smooth = 0; */
+ /* rast.poly_stipple_enable = 0; */
+ /* rast.point_smooth = 0; */
+ rast.sprite_coord_mode = PIPE_SPRITE_COORD_UPPER_LEFT;
+ rast.point_quad_rasterization = !!rs[D3DRS_POINTSPRITEENABLE];
+ rast.point_size_per_vertex = rs[NINED3DRS_VSPOINTSIZE];
+ rast.multisample = !!rs[D3DRS_MULTISAMPLEANTIALIAS];
+ rast.line_smooth = !!rs[D3DRS_ANTIALIASEDLINEENABLE];
+ /* rast.line_stipple_enable = 0; */
+ rast.line_last_pixel = !!rs[D3DRS_LASTPIXEL];
+ rast.flatshade_first = 1;
+ /* rast.half_pixel_center = 0; */
+ /* rast.lower_left_origin = 0; */
+ /* rast.bottom_edge_rule = 0; */
+ /* rast.rasterizer_discard = 0; */
+ rast.depth_clip = 1;
+ rast.clip_halfz = 1;
+ rast.clip_plane_enable = rs[D3DRS_CLIPPLANEENABLE];
+ /* rast.line_stipple_factor = 0; */
+ /* rast.line_stipple_pattern = 0; */
+ rast.sprite_coord_enable = rs[D3DRS_POINTSPRITEENABLE] ? 0xff : 0x00;
+ rast.line_width = 1.0f;
+ rast.point_size = rs[NINED3DRS_VSPOINTSIZE] ? 1.0f : asfloat(rs[D3DRS_POINTSIZE]); /* XXX: D3DRS_POINTSIZE_MIN/MAX */
+ rast.offset_units = asfloat(rs[D3DRS_DEPTHBIAS]) * asfloat(rs[NINED3DRS_ZBIASSCALE]);
+ rast.offset_scale = asfloat(rs[D3DRS_SLOPESCALEDEPTHBIAS]);
+ /* rast.offset_clamp = 0.0f; */
+
+ cso_set_rasterizer(ctx, &rast);
+}
+
+static INLINE void
+nine_convert_blend_state_fixup(struct pipe_blend_state *blend, const DWORD *rs)
+{
+ if (unlikely(rs[D3DRS_SRCBLEND] == D3DBLEND_BOTHSRCALPHA ||
+ rs[D3DRS_SRCBLEND] == D3DBLEND_BOTHINVSRCALPHA)) {
+ blend->rt[0].rgb_dst_factor = (rs[D3DRS_SRCBLEND] == D3DBLEND_BOTHSRCALPHA) ?
+ PIPE_BLENDFACTOR_INV_SRC_ALPHA : PIPE_BLENDFACTOR_SRC_ALPHA;
+ if (!rs[D3DRS_SEPARATEALPHABLENDENABLE])
+ blend->rt[0].alpha_dst_factor = blend->rt[0].rgb_dst_factor;
+ } else
+ if (unlikely(rs[D3DRS_SEPARATEALPHABLENDENABLE] &&
+ (rs[D3DRS_SRCBLENDALPHA] == D3DBLEND_BOTHSRCALPHA ||
+ rs[D3DRS_SRCBLENDALPHA] == D3DBLEND_BOTHINVSRCALPHA))) {
+ blend->rt[0].alpha_dst_factor = (rs[D3DRS_SRCBLENDALPHA] == D3DBLEND_BOTHSRCALPHA) ?
+ PIPE_BLENDFACTOR_INV_SRC_ALPHA : PIPE_BLENDFACTOR_SRC_ALPHA;
+ }
+}
+
+void
+nine_convert_blend_state(struct cso_context *ctx, const DWORD *rs)
+{
+ struct pipe_blend_state blend;
+
+ memset(&blend, 0, sizeof(blend)); /* memcmp safety */
+
+ blend.dither = !!rs[D3DRS_DITHERENABLE];
+
+ /* blend.alpha_to_one = 0; */
+ /* blend.alpha_to_coverage = 0; */ /* XXX */
+
+ blend.rt[0].blend_enable = !!rs[D3DRS_ALPHABLENDENABLE];
+ if (blend.rt[0].blend_enable) {
+ blend.rt[0].rgb_func = d3dblendop_to_pipe_blend(rs[D3DRS_BLENDOP]);
+ blend.rt[0].rgb_src_factor = d3dblend_color_to_pipe_blendfactor(rs[D3DRS_SRCBLEND]);
+ blend.rt[0].rgb_dst_factor = d3dblend_color_to_pipe_blendfactor(rs[D3DRS_DESTBLEND]);
+ if (rs[D3DRS_SEPARATEALPHABLENDENABLE]) {
+ blend.rt[0].alpha_func = d3dblendop_to_pipe_blend(rs[D3DRS_BLENDOPALPHA]);
+ blend.rt[0].alpha_src_factor = d3dblend_alpha_to_pipe_blendfactor(rs[D3DRS_SRCBLENDALPHA]);
+ blend.rt[0].alpha_dst_factor = d3dblend_alpha_to_pipe_blendfactor(rs[D3DRS_DESTBLENDALPHA]);
+ } else {
+ /* TODO: Just copy the rgb values ? SRC1_x may differ ... */
+ blend.rt[0].alpha_func = blend.rt[0].rgb_func;
+ blend.rt[0].alpha_src_factor = d3dblend_alpha_to_pipe_blendfactor(rs[D3DRS_SRCBLEND]);
+ blend.rt[0].alpha_dst_factor = d3dblend_alpha_to_pipe_blendfactor(rs[D3DRS_DESTBLEND]);
+ }
+ nine_convert_blend_state_fixup(&blend, rs); /* for BOTH[INV]SRCALPHA */
+ }
+ blend.rt[0].colormask = rs[D3DRS_COLORWRITEENABLE];
+
+ if (rs[D3DRS_COLORWRITEENABLE1] != rs[D3DRS_COLORWRITEENABLE] ||
+ rs[D3DRS_COLORWRITEENABLE2] != rs[D3DRS_COLORWRITEENABLE] ||
+ rs[D3DRS_COLORWRITEENABLE3] != rs[D3DRS_COLORWRITEENABLE]) {
+ unsigned i;
+ blend.independent_blend_enable = TRUE;
+ for (i = 1; i < 4; ++i)
+ blend.rt[i] = blend.rt[0];
+ blend.rt[1].colormask = rs[D3DRS_COLORWRITEENABLE1];
+ blend.rt[2].colormask = rs[D3DRS_COLORWRITEENABLE2];
+ blend.rt[3].colormask = rs[D3DRS_COLORWRITEENABLE3];
+ }
+
+ /* blend.force_srgb = !!rs[D3DRS_SRGBWRITEENABLE]; */
+
+ cso_set_blend(ctx, &blend);
+}
+
+void
+nine_convert_sampler_state(struct cso_context *ctx, int idx, const DWORD *ss)
+{
+ struct pipe_sampler_state samp;
+
+ assert(idx >= 0 &&
+ (idx < NINE_MAX_SAMPLERS_PS || idx >= NINE_SAMPLER_VS(0)) &&
+ (idx < NINE_MAX_SAMPLERS));
+
+ memset(&samp, 0, sizeof(samp)); /* memcmp safety */
+
+ if (ss[D3DSAMP_MIPFILTER] != D3DTEXF_NONE) {
+ samp.lod_bias = asfloat(ss[D3DSAMP_MIPMAPLODBIAS]);
+ samp.min_lod = ss[NINED3DSAMP_MINLOD];
+ samp.min_mip_filter = (ss[D3DSAMP_MIPFILTER] == D3DTEXF_POINT) ? PIPE_TEX_FILTER_NEAREST : PIPE_TEX_FILTER_LINEAR;
+ } else {
+ samp.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+ }
+ samp.max_lod = 15.0f;
+ samp.wrap_s = d3dtextureaddress_to_pipe_tex_wrap(ss[D3DSAMP_ADDRESSU]);
+ samp.wrap_t = d3dtextureaddress_to_pipe_tex_wrap(ss[D3DSAMP_ADDRESSV]);
+ samp.wrap_r = d3dtextureaddress_to_pipe_tex_wrap(ss[D3DSAMP_ADDRESSW]);
+ samp.min_img_filter = ss[D3DSAMP_MINFILTER] == D3DTEXF_POINT ? PIPE_TEX_FILTER_NEAREST : PIPE_TEX_FILTER_LINEAR;
+ samp.mag_img_filter = ss[D3DSAMP_MAGFILTER] == D3DTEXF_POINT ? PIPE_TEX_FILTER_NEAREST : PIPE_TEX_FILTER_LINEAR;
+ if (ss[D3DSAMP_MINFILTER] == D3DTEXF_ANISOTROPIC ||
+ ss[D3DSAMP_MAGFILTER] == D3DTEXF_ANISOTROPIC)
+ samp.max_anisotropy = ss[D3DSAMP_MAXANISOTROPY];
+ samp.compare_mode = ss[NINED3DSAMP_SHADOW] ? PIPE_TEX_COMPARE_R_TO_TEXTURE : PIPE_TEX_COMPARE_NONE;
+ samp.compare_func = PIPE_FUNC_LEQUAL;
+ samp.normalized_coords = 1;
+ samp.seamless_cube_map = 1;
+ d3dcolor_to_pipe_color_union(&samp.border_color, ss[D3DSAMP_BORDERCOLOR]);
+
+ /* see nine_state.h */
+ if (idx < NINE_MAX_SAMPLERS_PS)
+ cso_single_sampler(ctx, PIPE_SHADER_FRAGMENT, idx - NINE_SAMPLER_PS(0), &samp);
+ else
+ cso_single_sampler(ctx, PIPE_SHADER_VERTEX, idx - NINE_SAMPLER_VS(0), &samp);
+}
+
+void
+nine_pipe_context_clear(struct NineDevice9 *This)
+{
+ struct pipe_context *pipe = This->pipe;
+ struct cso_context *cso = This->cso;
+ pipe->bind_vs_state(pipe, NULL);
+ pipe->bind_fs_state(pipe, NULL);
+
+ /* Don't unbind constant buffers, they're device-private and
+ * do not change on Reset.
+ */
+
+ cso_set_samplers(cso, PIPE_SHADER_VERTEX, 0, NULL);
+ cso_set_samplers(cso, PIPE_SHADER_FRAGMENT, 0, NULL);
+
+ pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, 0, NULL);
+ pipe->set_sampler_views(pipe, PIPE_SHADER_VERTEX, 0, 0, NULL);
+
+ pipe->set_vertex_buffers(pipe, 0, This->caps.MaxStreams, NULL);
+ pipe->set_index_buffer(pipe, NULL);
+}
+
+const enum pipe_format nine_d3d9_to_pipe_format_map[120] =
+{
+ [D3DFMT_UNKNOWN] = PIPE_FORMAT_NONE,
+
+ [D3DFMT_A8R8G8B8] = PIPE_FORMAT_B8G8R8A8_UNORM,
+ [D3DFMT_X8R8G8B8] = PIPE_FORMAT_B8G8R8X8_UNORM,
+ [D3DFMT_R5G6B5] = PIPE_FORMAT_B5G6R5_UNORM,
+ [D3DFMT_X1R5G5B5] = PIPE_FORMAT_B5G5R5X1_UNORM,
+ [D3DFMT_A1R5G5B5] = PIPE_FORMAT_B5G5R5A1_UNORM,
+ [D3DFMT_A4R4G4B4] = PIPE_FORMAT_B4G4R4A4_UNORM,
+ [D3DFMT_A8] = PIPE_FORMAT_A8_UNORM,
+ [D3DFMT_X4R4G4B4] = PIPE_FORMAT_B4G4R4X4_UNORM,
+ [D3DFMT_R3G3B2] = PIPE_FORMAT_B2G3R3_UNORM,
+ [D3DFMT_A2B10G10R10] = PIPE_FORMAT_R10G10B10A2_UNORM,
+ [D3DFMT_A8B8G8R8] = PIPE_FORMAT_R8G8B8A8_UNORM,
+ [D3DFMT_X8B8G8R8] = PIPE_FORMAT_R8G8B8X8_UNORM,
+ [D3DFMT_G16R16] = PIPE_FORMAT_R16G16_UNORM,
+ [D3DFMT_A2R10G10B10] = PIPE_FORMAT_B10G10R10A2_UNORM,
+ [D3DFMT_A16B16G16R16] = PIPE_FORMAT_R16G16B16A16_UNORM,
+
+ /* palette texture formats not supported by gallium/hardware, TODO ? */
+ [D3DFMT_P8] = PIPE_FORMAT_NONE,
+ [D3DFMT_A8P8] = PIPE_FORMAT_NONE,
+
+ [D3DFMT_L8] = PIPE_FORMAT_L8_UNORM,
+ [D3DFMT_A8L8] = PIPE_FORMAT_L8A8_UNORM,
+ [D3DFMT_A4L4] = PIPE_FORMAT_L4A4_UNORM,
+
+ [D3DFMT_V8U8] = PIPE_FORMAT_R8G8_SNORM,
+ [D3DFMT_Q8W8V8U8] = PIPE_FORMAT_R8G8B8A8_SNORM,
+ [D3DFMT_V16U16] = PIPE_FORMAT_R16G16_SNORM,
+ [D3DFMT_A2W10V10U10] = PIPE_FORMAT_R10SG10SB10SA2U_NORM,
+
+ /* [D3DFMT_UYVY] = PIPE_FORMAT_YUYV, fourcc */
+ /* [D3DFMT_YUY2] = PIPE_FORMAT_NONE, fourcc */
+
+ /* XXX: DXT2, DXT4 */
+ /* fourcc
+ [D3DFMT_DXT1] = PIPE_FORMAT_DXT1_RGBA,
+ [D3DFMT_DXT2] = PIPE_FORMAT_DXT3_RGBA,
+ [D3DFMT_DXT3] = PIPE_FORMAT_DXT3_RGBA,
+ [D3DFMT_DXT4] = PIPE_FORMAT_DXT5_RGBA,
+ [D3DFMT_DXT5] = PIPE_FORMAT_DXT5_RGBA,
+ */
+
+ /* XXX: order ? */
+ /* fourcc
+ [D3DFMT_G8R8_G8B8] = PIPE_FORMAT_G8R8_G8B8_UNORM,
+ [D3DFMT_R8G8_B8G8] = PIPE_FORMAT_R8G8_B8G8_UNORM,
+ */
+
+ [D3DFMT_D16_LOCKABLE] = PIPE_FORMAT_Z16_UNORM,
+ [D3DFMT_D32] = PIPE_FORMAT_Z32_UNORM,
+ [D3DFMT_D24S8] = PIPE_FORMAT_S8_UINT_Z24_UNORM,
+ [D3DFMT_D24X8] = PIPE_FORMAT_X8Z24_UNORM,
+ [D3DFMT_D16] = PIPE_FORMAT_Z16_UNORM,
+ [D3DFMT_L16] = PIPE_FORMAT_L16_UNORM,
+ [D3DFMT_D32F_LOCKABLE] = PIPE_FORMAT_Z32_FLOAT,
+
+ [D3DFMT_INDEX16] = PIPE_FORMAT_R16_UINT,
+ [D3DFMT_INDEX32] = PIPE_FORMAT_R32_UINT,
+ [D3DFMT_Q16W16V16U16] = PIPE_FORMAT_R16G16B16A16_SNORM,
+
+ [D3DFMT_R16F] = PIPE_FORMAT_R16_FLOAT,
+ [D3DFMT_R32F] = PIPE_FORMAT_R32_FLOAT,
+ [D3DFMT_G16R16F] = PIPE_FORMAT_R16G16_FLOAT,
+ [D3DFMT_G32R32F] = PIPE_FORMAT_R32G32_FLOAT,
+ [D3DFMT_A16B16G16R16F] = PIPE_FORMAT_R16G16B16A16_FLOAT,
+ [D3DFMT_A32B32G32R32F] = PIPE_FORMAT_R32G32B32A32_FLOAT,
+
+ /* non-1:1 formats (don't support because we'd have to convert) */
+ [D3DFMT_R8G8B8] = PIPE_FORMAT_NONE, /* XXX order */
+ [D3DFMT_A8R3G3B2] = PIPE_FORMAT_NONE, /* XXX alpha */
+ /* This is ok because they're not lockable: */
+ [D3DFMT_D15S1] = PIPE_FORMAT_Z24_UNORM_S8_UINT,
+ [D3DFMT_D24X4S4] = PIPE_FORMAT_Z24_UNORM_S8_UINT,
+ [D3DFMT_D24FS8] = PIPE_FORMAT_Z32_FLOAT_S8X24_UINT,
+
+ /* not really formats */
+ [D3DFMT_VERTEXDATA] = PIPE_FORMAT_NONE,
+ /* [D3DFMT_BINARYBUFFER] = PIPE_FORMAT_NONE, too large */
+
+ /* unsupported formats */
+ [D3DFMT_L6V5U5] = PIPE_FORMAT_NONE,
+ [D3DFMT_X8L8V8U8] = PIPE_FORMAT_NONE,
+
+ /* [D3DFMT_MULTI2_ARGB8] = PIPE_FORMAT_NONE, fourcc, MET */
+
+ [D3DFMT_CxV8U8] = PIPE_FORMAT_NONE,
+ [D3DFMT_A1] = PIPE_FORMAT_NONE, /* XXX: add this ? */
+ [D3DFMT_A2B10G10R10_XR_BIAS] = PIPE_FORMAT_NONE, /* XXX ? */
+};
+
+const D3DFORMAT nine_pipe_to_d3d9_format_map[PIPE_FORMAT_COUNT] =
+{
+ [PIPE_FORMAT_NONE] = D3DFMT_UNKNOWN,
+
+/* [PIPE_FORMAT_B8G8R8_UNORM] = D3DFMT_R8G8B8, */
+ [PIPE_FORMAT_B8G8R8A8_UNORM] = D3DFMT_A8R8G8B8,
+ [PIPE_FORMAT_B8G8R8X8_UNORM] = D3DFMT_X8R8G8B8,
+ [PIPE_FORMAT_B5G6R5_UNORM] = D3DFMT_R5G6B5,
+ [PIPE_FORMAT_B5G5R5X1_UNORM] = D3DFMT_X1R5G5B5,
+ [PIPE_FORMAT_B5G5R5A1_UNORM] = D3DFMT_A1R5G5B5,
+ [PIPE_FORMAT_B4G4R4A4_UNORM] = D3DFMT_A4R4G4B4,
+ [PIPE_FORMAT_B2G3R3_UNORM] = D3DFMT_R3G3B2,
+ [PIPE_FORMAT_A8_UNORM] = D3DFMT_A8,
+/* [PIPE_FORMAT_B2G3R3A8_UNORM] = D3DFMT_A8R3G3B2, */
+ [PIPE_FORMAT_B4G4R4X4_UNORM] = D3DFMT_X4R4G4B4,
+ [PIPE_FORMAT_R10G10B10A2_UNORM] = D3DFMT_A2B10G10R10,
+ [PIPE_FORMAT_R8G8B8A8_UNORM] = D3DFMT_A8B8G8R8,
+ [PIPE_FORMAT_R8G8B8X8_UNORM] = D3DFMT_X8B8G8R8,
+ [PIPE_FORMAT_R16G16_UNORM] = D3DFMT_G16R16,
+ [PIPE_FORMAT_B10G10R10A2_UNORM] = D3DFMT_A2R10G10B10,
+ [PIPE_FORMAT_R16G16B16A16_UNORM] = D3DFMT_A16B16G16R16,
+
+ [PIPE_FORMAT_R8_UINT] = D3DFMT_P8,
+ [PIPE_FORMAT_R8A8_UINT] = D3DFMT_A8P8,
+
+ [PIPE_FORMAT_L8_UNORM] = D3DFMT_L8,
+ [PIPE_FORMAT_L8A8_UNORM] = D3DFMT_A8L8,
+ [PIPE_FORMAT_L4A4_UNORM] = D3DFMT_A4L4,
+
+ [PIPE_FORMAT_R8G8_SNORM] = D3DFMT_V8U8,
+/* [PIPE_FORMAT_?] = D3DFMT_L6V5U5, */
+/* [PIPE_FORMAT_?] = D3DFMT_X8L8V8U8, */
+ [PIPE_FORMAT_R8G8B8A8_SNORM] = D3DFMT_Q8W8V8U8,
+ [PIPE_FORMAT_R16G16_SNORM] = D3DFMT_V16U16,
+ [PIPE_FORMAT_R10SG10SB10SA2U_NORM] = D3DFMT_A2W10V10U10,
+
+ [PIPE_FORMAT_YUYV] = D3DFMT_UYVY,
+/* [PIPE_FORMAT_YUY2] = D3DFMT_YUY2, */
+ [PIPE_FORMAT_DXT1_RGBA] = D3DFMT_DXT1,
+/* [PIPE_FORMAT_DXT2_RGBA] = D3DFMT_DXT2, */
+ [PIPE_FORMAT_DXT3_RGBA] = D3DFMT_DXT3,
+/* [PIPE_FORMAT_DXT4_RGBA] = D3DFMT_DXT4, */
+ [PIPE_FORMAT_DXT5_RGBA] = D3DFMT_DXT5,
+/* [PIPE_FORMAT_?] = D3DFMT_MULTI2_ARGB8, (MET) */
+ [PIPE_FORMAT_R8G8_B8G8_UNORM] = D3DFMT_R8G8_B8G8, /* XXX: order */
+ [PIPE_FORMAT_G8R8_G8B8_UNORM] = D3DFMT_G8R8_G8B8,
+
+ [PIPE_FORMAT_Z16_UNORM] = D3DFMT_D16_LOCKABLE,
+ [PIPE_FORMAT_Z32_UNORM] = D3DFMT_D32,
+/* [PIPE_FORMAT_Z15_UNORM_S1_UINT] = D3DFMT_D15S1, */
+ [PIPE_FORMAT_S8_UINT_Z24_UNORM] = D3DFMT_D24S8,
+ [PIPE_FORMAT_X8Z24_UNORM] = D3DFMT_D24X8,
+ [PIPE_FORMAT_L16_UNORM] = D3DFMT_L16,
+ [PIPE_FORMAT_Z32_FLOAT] = D3DFMT_D32F_LOCKABLE,
+/* [PIPE_FORMAT_Z24_FLOAT_S8_UINT] = D3DFMT_D24FS8, */
+
+ [PIPE_FORMAT_R16_UINT] = D3DFMT_INDEX16,
+ [PIPE_FORMAT_R32_UINT] = D3DFMT_INDEX32,
+ [PIPE_FORMAT_R16G16B16A16_SNORM] = D3DFMT_Q16W16V16U16,
+
+ [PIPE_FORMAT_R16_FLOAT] = D3DFMT_R16F,
+ [PIPE_FORMAT_R32_FLOAT] = D3DFMT_R32F,
+ [PIPE_FORMAT_R16G16_FLOAT] = D3DFMT_G16R16F,
+ [PIPE_FORMAT_R32G32_FLOAT] = D3DFMT_G32R32F,
+ [PIPE_FORMAT_R16G16B16A16_FLOAT] = D3DFMT_A16B16G16R16F,
+ [PIPE_FORMAT_R32G32B32A32_FLOAT] = D3DFMT_A32B32G32R32F,
+
+/* [PIPE_FORMAT_?] = D3DFMT_CxV8U8, */
+};
diff --git a/src/gallium/state_trackers/nine/nine_pipe.h b/src/gallium/state_trackers/nine/nine_pipe.h
new file mode 100644
index 00000000000..1fd16944fd5
--- /dev/null
+++ b/src/gallium/state_trackers/nine/nine_pipe.h
@@ -0,0 +1,568 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _NINE_PIPE_H_
+#define _NINE_PIPE_H_
+
+#include "d3d9.h"
+#include "pipe/p_format.h"
+#include "pipe/p_state.h" /* pipe_box */
+#include "util/u_rect.h"
+#include "nine_helpers.h"
+
+struct cso_context;
+
+extern const enum pipe_format nine_d3d9_to_pipe_format_map[120];
+extern const D3DFORMAT nine_pipe_to_d3d9_format_map[PIPE_FORMAT_COUNT];
+
+void nine_convert_dsa_state(struct cso_context *, const DWORD *);
+void nine_convert_rasterizer_state(struct cso_context *, const DWORD *);
+void nine_convert_blend_state(struct cso_context *, const DWORD *);
+void nine_convert_sampler_state(struct cso_context *, int idx, const DWORD *);
+
+void nine_pipe_context_clear(struct NineDevice9 *);
+
+static INLINE unsigned d3dlock_buffer_to_pipe_transfer_usage(DWORD Flags)
+{
+ unsigned usage;
+
+ if (Flags & D3DLOCK_DISCARD)
+ usage = PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE;
+ else
+ if (Flags & D3DLOCK_READONLY)
+ usage = PIPE_TRANSFER_READ;
+ else
+ usage = PIPE_TRANSFER_READ_WRITE;
+
+ if (Flags & D3DLOCK_NOOVERWRITE)
+ usage = (PIPE_TRANSFER_UNSYNCHRONIZED |
+ PIPE_TRANSFER_DISCARD_RANGE | usage) & ~PIPE_TRANSFER_READ;
+ else
+ if (Flags & D3DLOCK_DONOTWAIT)
+ usage |= PIPE_TRANSFER_DONTBLOCK;
+
+ /*
+ if (Flags & D3DLOCK_NO_DIRTY_UPDATE)
+ usage |= PIPE_TRANSFER_FLUSH_EXPLICIT;
+ */
+
+ return usage;
+}
+
+static INLINE void
+rect_to_pipe_box(struct pipe_box *dst, const RECT *src)
+{
+ dst->x = src->left;
+ dst->y = src->top;
+ dst->z = 0;
+ dst->width = src->right - src->left;
+ dst->height = src->bottom - src->top;
+ dst->depth = 1;
+}
+
+static INLINE boolean
+rect_to_pipe_box_clamp(struct pipe_box *dst, const RECT *src)
+{
+ rect_to_pipe_box(dst, src);
+
+ if (dst->width <= 0 || dst->height <= 0) {
+ DBG_FLAG(DBG_UNKNOWN, "Warning: NULL box");
+ dst->width = MAX2(dst->width, 0);
+ dst->height = MAX2(dst->height, 0);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static INLINE boolean
+rect_to_pipe_box_flip(struct pipe_box *dst, const RECT *src)
+{
+ rect_to_pipe_box(dst, src);
+
+ if (dst->width >= 0 && dst->height >= 0)
+ return FALSE;
+ if (dst->width < 0) dst->width = -dst->width;
+ if (dst->height < 0) dst->height = -dst->height;
+ return TRUE;
+}
+
+static INLINE void
+nine_u_rect_to_pipe_box(struct pipe_box *dst, const struct u_rect *rect, int z)
+{
+ dst->x = rect->x0;
+ dst->y = rect->y0;
+ dst->z = z;
+ dst->width = rect->x1 - rect->x0;
+ dst->height = rect->y1 - rect->y0;
+ dst->depth = 1;
+}
+
+static INLINE void
+rect_to_pipe_box_xy_only(struct pipe_box *dst, const RECT *src)
+{
+ user_warn(src->left > src->right || src->top > src->bottom);
+
+ dst->x = src->left;
+ dst->y = src->top;
+ dst->width = src->right - src->left;
+ dst->height = src->bottom - src->top;
+}
+
+static INLINE boolean
+rect_to_pipe_box_xy_only_clamp(struct pipe_box *dst, const RECT *src)
+{
+ rect_to_pipe_box_xy_only(dst, src);
+
+ if (dst->width <= 0 || dst->height <= 0) {
+ DBG_FLAG(DBG_UNKNOWN, "Warning: NULL box");
+ dst->width = MAX2(dst->width, 0);
+ dst->height = MAX2(dst->height, 0);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static INLINE void
+rect_to_g3d_u_rect(struct u_rect *dst, const RECT *src)
+{
+ user_warn(src->left > src->right || src->top > src->bottom);
+
+ dst->x0 = src->left;
+ dst->x1 = src->right;
+ dst->y0 = src->top;
+ dst->y1 = src->bottom;
+}
+
+static INLINE void
+d3dbox_to_pipe_box(struct pipe_box *dst, const D3DBOX *src)
+{
+ user_warn(src->Left > src->Right);
+ user_warn(src->Top > src->Bottom);
+ user_warn(src->Front > src->Back);
+
+ dst->x = src->Left;
+ dst->y = src->Top;
+ dst->z = src->Front;
+ dst->width = src->Right - src->Left;
+ dst->height = src->Bottom - src->Top;
+ dst->depth = src->Back - src->Front;
+}
+
+static INLINE D3DFORMAT
+pipe_to_d3d9_format(enum pipe_format format)
+{
+ return nine_pipe_to_d3d9_format_map[format];
+}
+
+static INLINE enum pipe_format
+d3d9_to_pipe_format(D3DFORMAT format)
+{
+ if (format <= D3DFMT_A2B10G10R10_XR_BIAS)
+ return nine_d3d9_to_pipe_format_map[format];
+ switch (format) {
+ case D3DFMT_INTZ: return PIPE_FORMAT_Z24_UNORM_S8_UINT;
+ case D3DFMT_DXT1: return PIPE_FORMAT_DXT1_RGBA;
+ case D3DFMT_DXT2: return PIPE_FORMAT_DXT3_RGBA; /* XXX */
+ case D3DFMT_DXT3: return PIPE_FORMAT_DXT3_RGBA;
+ case D3DFMT_DXT4: return PIPE_FORMAT_DXT5_RGBA; /* XXX */
+ case D3DFMT_DXT5: return PIPE_FORMAT_DXT5_RGBA;
+ case D3DFMT_UYVY: return PIPE_FORMAT_UYVY;
+ case D3DFMT_YUY2: return PIPE_FORMAT_YUYV; /* XXX check */
+ case D3DFMT_NV12: return PIPE_FORMAT_NV12;
+ case D3DFMT_G8R8_G8B8: return PIPE_FORMAT_G8R8_G8B8_UNORM; /* XXX order ? */
+ case D3DFMT_R8G8_B8G8: return PIPE_FORMAT_R8G8_B8G8_UNORM; /* XXX order ? */
+ case D3DFMT_BINARYBUFFER: return PIPE_FORMAT_NONE; /* not a format */
+ case D3DFMT_MULTI2_ARGB8: return PIPE_FORMAT_NONE; /* not supported */
+ case D3DFMT_Y210: /* XXX */
+ case D3DFMT_Y216:
+ case D3DFMT_NV11:
+ case D3DFMT_DF16: /* useless, not supported by wine either */
+ case D3DFMT_DF24: /* useless, not supported by wine either */
+ case D3DFMT_NULL: /* special cased, only for surfaces */
+ return PIPE_FORMAT_NONE;
+ default:
+ DBG_FLAG(DBG_UNKNOWN, "unknown D3DFORMAT: 0x%x/%c%c%c%c\n",
+ format, (char)format, (char)(format >> 8),
+ (char)(format >> 16), (char)(format >> 24));
+ return PIPE_FORMAT_NONE;
+ }
+}
+
+static INLINE const char *
+d3dformat_to_string(D3DFORMAT fmt)
+{
+ switch (fmt) {
+ case D3DFMT_UNKNOWN: return "D3DFMT_UNKNOWN";
+ case D3DFMT_R8G8B8: return "D3DFMT_R8G8B8";
+ case D3DFMT_A8R8G8B8: return "D3DFMT_A8R8G8B8";
+ case D3DFMT_X8R8G8B8: return "D3DFMT_X8R8G8B8";
+ case D3DFMT_R5G6B5: return "D3DFMT_R5G6B5";
+ case D3DFMT_X1R5G5B5: return "D3DFMT_X1R5G5B5";
+ case D3DFMT_A1R5G5B5: return "D3DFMT_A1R5G5B5";
+ case D3DFMT_A4R4G4B4: return "D3DFMT_A4R4G4B4";
+ case D3DFMT_R3G3B2: return "D3DFMT_R3G3B2";
+ case D3DFMT_A8: return "D3DFMT_A8";
+ case D3DFMT_A8R3G3B2: return "D3DFMT_A8R3G3B2";
+ case D3DFMT_X4R4G4B4: return "D3DFMT_X4R4G4B4";
+ case D3DFMT_A2B10G10R10: return "D3DFMT_A2B10G10R10";
+ case D3DFMT_A8B8G8R8: return "D3DFMT_A8B8G8R8";
+ case D3DFMT_X8B8G8R8: return "D3DFMT_X8B8G8R8";
+ case D3DFMT_G16R16: return "D3DFMT_G16R16";
+ case D3DFMT_A2R10G10B10: return "D3DFMT_A2R10G10B10";
+ case D3DFMT_A16B16G16R16: return "D3DFMT_A16B16G16R16";
+ case D3DFMT_A8P8: return "D3DFMT_A8P8";
+ case D3DFMT_P8: return "D3DFMT_P8";
+ case D3DFMT_L8: return "D3DFMT_L8";
+ case D3DFMT_A8L8: return "D3DFMT_A8L8";
+ case D3DFMT_A4L4: return "D3DFMT_A4L4";
+ case D3DFMT_V8U8: return "D3DFMT_V8U8";
+ case D3DFMT_L6V5U5: return "D3DFMT_L6V5U5";
+ case D3DFMT_X8L8V8U8: return "D3DFMT_X8L8V8U8";
+ case D3DFMT_Q8W8V8U8: return "D3DFMT_Q8W8V8U8";
+ case D3DFMT_V16U16: return "D3DFMT_V16U16";
+ case D3DFMT_A2W10V10U10: return "D3DFMT_A2W10V10U10";
+ case D3DFMT_UYVY: return "D3DFMT_UYVY";
+ case D3DFMT_R8G8_B8G8: return "D3DFMT_R8G8_B8G8";
+ case D3DFMT_YUY2: return "D3DFMT_YUY2";
+ case D3DFMT_G8R8_G8B8: return "D3DFMT_G8R8_G8B8";
+ case D3DFMT_DXT1: return "D3DFMT_DXT1";
+ case D3DFMT_DXT2: return "D3DFMT_DXT2";
+ case D3DFMT_DXT3: return "D3DFMT_DXT3";
+ case D3DFMT_DXT4: return "D3DFMT_DXT4";
+ case D3DFMT_DXT5: return "D3DFMT_DXT5";
+ case D3DFMT_D16_LOCKABLE: return "D3DFMT_D16_LOCKABLE";
+ case D3DFMT_D32: return "D3DFMT_D32";
+ case D3DFMT_D15S1: return "D3DFMT_D15S1";
+ case D3DFMT_D24S8: return "D3DFMT_D24S8";
+ case D3DFMT_D24X8: return "D3DFMT_D24X8";
+ case D3DFMT_D24X4S4: return "D3DFMT_D24X4S4";
+ case D3DFMT_D16: return "D3DFMT_D16";
+ case D3DFMT_D32F_LOCKABLE: return "D3DFMT_D32F_LOCKABLE";
+ case D3DFMT_D24FS8: return "D3DFMT_D24FS8";
+ case D3DFMT_D32_LOCKABLE: return "D3DFMT_D32_LOCKABLE";
+ case D3DFMT_S8_LOCKABLE: return "D3DFMT_S8_LOCKABLE";
+ case D3DFMT_L16: return "D3DFMT_L16";
+ case D3DFMT_VERTEXDATA: return "D3DFMT_VERTEXDATA";
+ case D3DFMT_INDEX16: return "D3DFMT_INDEX16";
+ case D3DFMT_INDEX32: return "D3DFMT_INDEX32";
+ case D3DFMT_Q16W16V16U16: return "D3DFMT_Q16W16V16U16";
+ case D3DFMT_MULTI2_ARGB8: return "D3DFMT_MULTI2_ARGB8";
+ case D3DFMT_R16F: return "D3DFMT_R16F";
+ case D3DFMT_G16R16F: return "D3DFMT_G16R16F";
+ case D3DFMT_A16B16G16R16F: return "D3DFMT_A16B16G16R16F";
+ case D3DFMT_R32F: return "D3DFMT_R32F";
+ case D3DFMT_G32R32F: return "D3DFMT_G32R32F";
+ case D3DFMT_A32B32G32R32F: return "D3DFMT_A32B32G32R32F";
+ case D3DFMT_CxV8U8: return "D3DFMT_CxV8U8";
+ case D3DFMT_A1: return "D3DFMT_A1";
+ case D3DFMT_A2B10G10R10_XR_BIAS: return "D3DFMT_A2B10G10R10_XR_BIAS";
+ case D3DFMT_BINARYBUFFER: return "D3DFMT_BINARYBUFFER";
+ case D3DFMT_DF16: return "D3DFMT_DF16";
+ case D3DFMT_DF24: return "D3DFMT_DF24";
+ case D3DFMT_INTZ: return "D3DFMT_INTZ";
+ case D3DFMT_NULL: return "D3DFMT_NULL";
+ default:
+ break;
+ }
+ return "Unknown";
+}
+
+static INLINE unsigned
+nine_fvf_stride( DWORD fvf )
+{
+ unsigned texcount, i, size = 0;
+
+ switch (fvf & D3DFVF_POSITION_MASK) {
+ case D3DFVF_XYZ: size += 3*4; break;
+ case D3DFVF_XYZRHW: size += 4*4; break;
+ case D3DFVF_XYZB1: size += 4*4; break;
+ case D3DFVF_XYZB2: size += 5*4; break;
+ case D3DFVF_XYZB3: size += 6*4; break;
+ case D3DFVF_XYZB4: size += 7*4; break;
+ case D3DFVF_XYZB5: size += 8*4; break;
+ case D3DFVF_XYZW: size += 4*4; break;
+ default:
+ user_warn("Position doesn't match any known combination.");
+ break;
+ }
+
+ if (fvf & D3DFVF_NORMAL) { size += 3*4; }
+ if (fvf & D3DFVF_PSIZE) { size += 1*4; }
+ if (fvf & D3DFVF_DIFFUSE) { size += 1*4; }
+ if (fvf & D3DFVF_SPECULAR) { size += 1*4; }
+
+ texcount = (fvf >> D3DFVF_TEXCOUNT_SHIFT) & D3DFVF_TEXCOUNT_MASK;
+ if (user_error(texcount <= 8))
+ texcount = 8;
+
+ for (i = 0; i < texcount; ++i) {
+ unsigned texformat = (fvf>>(16+i*2))&0x3;
+ /* texformats are defined having been shifted around so 1=3,2=0,3=1,4=2
+ * meaning we can just do this instead of the switch below */
+ size += (((texformat+1)&0x3)+1)*4;
+
+ /*
+ switch (texformat) {
+ case D3DFVF_TEXTUREFORMAT1: size += 1*4;
+ case D3DFVF_TEXTUREFORMAT2: size += 2*4;
+ case D3DFVF_TEXTUREFORMAT3: size += 3*4;
+ case D3DFVF_TEXTUREFORMAT4: size += 4*4;
+ }
+ */
+ }
+
+ return size;
+}
+
+static INLINE void
+d3dcolor_to_rgba(float *rgba, D3DCOLOR color)
+{
+ rgba[0] = (float)((color >> 16) & 0xFF) / 0xFF;
+ rgba[1] = (float)((color >> 8) & 0xFF) / 0xFF;
+ rgba[2] = (float)((color >> 0) & 0xFF) / 0xFF;
+ rgba[3] = (float)((color >> 24) & 0xFF) / 0xFF;
+}
+
+static INLINE void
+d3dcolor_to_pipe_color_union(union pipe_color_union *rgba, D3DCOLOR color)
+{
+ d3dcolor_to_rgba(&rgba->f[0], color);
+}
+
+static INLINE unsigned
+d3dprimitivetype_to_pipe_prim(D3DPRIMITIVETYPE prim)
+{
+ switch (prim) {
+ case D3DPT_POINTLIST: return PIPE_PRIM_POINTS;
+ case D3DPT_LINELIST: return PIPE_PRIM_LINES;
+ case D3DPT_LINESTRIP: return PIPE_PRIM_LINE_STRIP;
+ case D3DPT_TRIANGLELIST: return PIPE_PRIM_TRIANGLES;
+ case D3DPT_TRIANGLESTRIP: return PIPE_PRIM_TRIANGLE_STRIP;
+ case D3DPT_TRIANGLEFAN: return PIPE_PRIM_TRIANGLE_FAN;
+ default:
+ assert(0);
+ return PIPE_PRIM_POINTS;
+ }
+}
+
+static INLINE unsigned
+prim_count_to_vertex_count(D3DPRIMITIVETYPE prim, UINT count)
+{
+ switch (prim) {
+ case D3DPT_POINTLIST: return count;
+ case D3DPT_LINELIST: return count * 2;
+ case D3DPT_LINESTRIP: return count + 1;
+ case D3DPT_TRIANGLELIST: return count * 3;
+ case D3DPT_TRIANGLESTRIP: return count + 2;
+ case D3DPT_TRIANGLEFAN: return count + 2;
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+static INLINE unsigned
+d3dcmpfunc_to_pipe_func(D3DCMPFUNC func)
+{
+ switch (func) {
+ case D3DCMP_NEVER: return PIPE_FUNC_NEVER;
+ case D3DCMP_LESS: return PIPE_FUNC_LESS;
+ case D3DCMP_EQUAL: return PIPE_FUNC_EQUAL;
+ case D3DCMP_LESSEQUAL: return PIPE_FUNC_LEQUAL;
+ case D3DCMP_GREATER: return PIPE_FUNC_GREATER;
+ case D3DCMP_NOTEQUAL: return PIPE_FUNC_NOTEQUAL;
+ case D3DCMP_GREATEREQUAL: return PIPE_FUNC_GEQUAL;
+ case D3DCMP_ALWAYS: return PIPE_FUNC_ALWAYS;
+ default:
+ assert(0);
+ return PIPE_FUNC_NEVER;
+ }
+}
+
+static INLINE unsigned
+d3dstencilop_to_pipe_stencil_op(D3DSTENCILOP op)
+{
+ switch (op) {
+ case D3DSTENCILOP_KEEP: return PIPE_STENCIL_OP_KEEP;
+ case D3DSTENCILOP_ZERO: return PIPE_STENCIL_OP_ZERO;
+ case D3DSTENCILOP_REPLACE: return PIPE_STENCIL_OP_REPLACE;
+ case D3DSTENCILOP_INCRSAT: return PIPE_STENCIL_OP_INCR;
+ case D3DSTENCILOP_DECRSAT: return PIPE_STENCIL_OP_DECR;
+ case D3DSTENCILOP_INVERT: return PIPE_STENCIL_OP_INVERT;
+ case D3DSTENCILOP_INCR: return PIPE_STENCIL_OP_INCR_WRAP;
+ case D3DSTENCILOP_DECR: return PIPE_STENCIL_OP_DECR_WRAP;
+ default:
+ return PIPE_STENCIL_OP_ZERO;
+ }
+}
+
+static INLINE unsigned
+d3dcull_to_pipe_face(D3DCULL cull)
+{
+ switch (cull) {
+ case D3DCULL_NONE: return PIPE_FACE_NONE;
+ case D3DCULL_CW: return PIPE_FACE_FRONT;
+ case D3DCULL_CCW: return PIPE_FACE_BACK;
+ default:
+ assert(0);
+ return PIPE_FACE_NONE;
+ }
+}
+
+static INLINE unsigned
+d3dfillmode_to_pipe_polygon_mode(D3DFILLMODE mode)
+{
+ switch (mode) {
+ case D3DFILL_POINT: return PIPE_POLYGON_MODE_POINT;
+ case D3DFILL_WIREFRAME: return PIPE_POLYGON_MODE_LINE;
+ case D3DFILL_SOLID: return PIPE_POLYGON_MODE_FILL;
+ default:
+ assert(0);
+ return PIPE_POLYGON_MODE_FILL;
+ }
+}
+
+static INLINE unsigned
+d3dblendop_to_pipe_blend(D3DBLENDOP op)
+{
+ switch (op) {
+ case D3DBLENDOP_ADD: return PIPE_BLEND_ADD;
+ case D3DBLENDOP_SUBTRACT: return PIPE_BLEND_SUBTRACT;
+ case D3DBLENDOP_REVSUBTRACT: return PIPE_BLEND_REVERSE_SUBTRACT;
+ case D3DBLENDOP_MIN: return PIPE_BLEND_MIN;
+ case D3DBLENDOP_MAX: return PIPE_BLEND_MAX;
+ default:
+ assert(0);
+ return PIPE_BLEND_ADD;
+ }
+}
+
+/* NOTE: The COLOR factors for are equal to the ALPHA ones for alpha.
+ * Drivers may check RGB and ALPHA factors for equality so we should not
+ * simply substitute the ALPHA variants.
+ */
+static INLINE unsigned
+d3dblend_alpha_to_pipe_blendfactor(D3DBLEND b)
+{
+ switch (b) {
+ case D3DBLEND_ZERO: return PIPE_BLENDFACTOR_ZERO;
+ case D3DBLEND_ONE: return PIPE_BLENDFACTOR_ONE;
+ case D3DBLEND_SRCCOLOR: return PIPE_BLENDFACTOR_SRC_COLOR/*ALPHA*/;
+ case D3DBLEND_INVSRCCOLOR: return PIPE_BLENDFACTOR_INV_SRC_COLOR/*ALPHA*/;
+ case D3DBLEND_SRCALPHA: return PIPE_BLENDFACTOR_SRC_ALPHA;
+ case D3DBLEND_INVSRCALPHA: return PIPE_BLENDFACTOR_INV_SRC_ALPHA;
+ case D3DBLEND_DESTALPHA: return PIPE_BLENDFACTOR_DST_ALPHA;
+ case D3DBLEND_INVDESTALPHA: return PIPE_BLENDFACTOR_INV_DST_ALPHA;
+ case D3DBLEND_DESTCOLOR: return PIPE_BLENDFACTOR_DST_COLOR/*ALPHA*/;
+ case D3DBLEND_INVDESTCOLOR: return PIPE_BLENDFACTOR_INV_DST_COLOR/*ALPHA*/;
+ case D3DBLEND_SRCALPHASAT: return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE;
+ case D3DBLEND_BOTHSRCALPHA: return PIPE_BLENDFACTOR_SRC_ALPHA;
+ case D3DBLEND_BOTHINVSRCALPHA: return PIPE_BLENDFACTOR_INV_SRC_ALPHA;
+ case D3DBLEND_BLENDFACTOR: return PIPE_BLENDFACTOR_CONST_COLOR/*ALPHA*/;
+ case D3DBLEND_INVBLENDFACTOR: return PIPE_BLENDFACTOR_INV_CONST_COLOR/*ALPHA*/;
+ case D3DBLEND_SRCCOLOR2: return PIPE_BLENDFACTOR_ONE; /* XXX */
+ case D3DBLEND_INVSRCCOLOR2: return PIPE_BLENDFACTOR_ZERO; /* XXX */
+ default:
+ DBG_FLAG(DBG_UNKNOWN, "Unhandled blend factor %d\n", b);
+ return PIPE_BLENDFACTOR_ZERO;
+ }
+}
+
+static INLINE unsigned
+d3dblend_color_to_pipe_blendfactor(D3DBLEND b)
+{
+ switch (b) {
+ case D3DBLEND_ZERO: return PIPE_BLENDFACTOR_ZERO;
+ case D3DBLEND_ONE: return PIPE_BLENDFACTOR_ONE;
+ case D3DBLEND_SRCCOLOR: return PIPE_BLENDFACTOR_SRC_COLOR;
+ case D3DBLEND_INVSRCCOLOR: return PIPE_BLENDFACTOR_INV_SRC_COLOR;
+ case D3DBLEND_SRCALPHA: return PIPE_BLENDFACTOR_SRC_ALPHA;
+ case D3DBLEND_INVSRCALPHA: return PIPE_BLENDFACTOR_INV_SRC_ALPHA;
+ case D3DBLEND_DESTALPHA: return PIPE_BLENDFACTOR_DST_ALPHA;
+ case D3DBLEND_INVDESTALPHA: return PIPE_BLENDFACTOR_INV_DST_ALPHA;
+ case D3DBLEND_DESTCOLOR: return PIPE_BLENDFACTOR_DST_COLOR;
+ case D3DBLEND_INVDESTCOLOR: return PIPE_BLENDFACTOR_INV_DST_COLOR;
+ case D3DBLEND_SRCALPHASAT: return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE;
+ case D3DBLEND_BOTHSRCALPHA: return PIPE_BLENDFACTOR_SRC_ALPHA;
+ case D3DBLEND_BOTHINVSRCALPHA: return PIPE_BLENDFACTOR_INV_SRC_ALPHA;
+ case D3DBLEND_BLENDFACTOR: return PIPE_BLENDFACTOR_CONST_COLOR;
+ case D3DBLEND_INVBLENDFACTOR: return PIPE_BLENDFACTOR_INV_CONST_COLOR;
+ case D3DBLEND_SRCCOLOR2: return PIPE_BLENDFACTOR_SRC1_COLOR;
+ case D3DBLEND_INVSRCCOLOR2: return PIPE_BLENDFACTOR_INV_SRC1_COLOR;
+ default:
+ DBG_FLAG(DBG_UNKNOWN, "Unhandled blend factor %d\n", b);
+ return PIPE_BLENDFACTOR_ZERO;
+ }
+}
+
+static INLINE unsigned
+d3dtextureaddress_to_pipe_tex_wrap(D3DTEXTUREADDRESS addr)
+{
+ switch (addr) {
+ case D3DTADDRESS_WRAP: return PIPE_TEX_WRAP_REPEAT;
+ case D3DTADDRESS_MIRROR: return PIPE_TEX_WRAP_MIRROR_REPEAT;
+ case D3DTADDRESS_CLAMP: return PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ case D3DTADDRESS_BORDER: return PIPE_TEX_WRAP_CLAMP_TO_BORDER;
+ case D3DTADDRESS_MIRRORONCE: return PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE;
+ default:
+ assert(0);
+ return PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ }
+}
+
+static INLINE unsigned
+d3dtexturefiltertype_to_pipe_tex_filter(D3DTEXTUREFILTERTYPE filter)
+{
+ switch (filter) {
+ case D3DTEXF_POINT: return PIPE_TEX_FILTER_NEAREST;
+ case D3DTEXF_LINEAR: return PIPE_TEX_FILTER_LINEAR;
+ case D3DTEXF_ANISOTROPIC: return PIPE_TEX_FILTER_LINEAR;
+
+ case D3DTEXF_NONE:
+ case D3DTEXF_PYRAMIDALQUAD:
+ case D3DTEXF_GAUSSIANQUAD:
+ case D3DTEXF_CONVOLUTIONMONO:
+ default:
+ assert(0);
+ return PIPE_TEX_FILTER_NEAREST;
+ }
+}
+
+static INLINE unsigned
+d3dtexturefiltertype_to_pipe_tex_mipfilter(D3DTEXTUREFILTERTYPE filter)
+{
+ switch (filter) {
+ case D3DTEXF_NONE: return PIPE_TEX_MIPFILTER_NONE;
+ case D3DTEXF_POINT: return PIPE_TEX_FILTER_NEAREST;
+ case D3DTEXF_LINEAR: return PIPE_TEX_FILTER_LINEAR;
+ case D3DTEXF_ANISOTROPIC: return PIPE_TEX_FILTER_LINEAR;
+
+ case D3DTEXF_PYRAMIDALQUAD:
+ case D3DTEXF_GAUSSIANQUAD:
+ case D3DTEXF_CONVOLUTIONMONO:
+ default:
+ assert(0);
+ return PIPE_TEX_MIPFILTER_NONE;
+ }
+}
+
+#endif /* _NINE_PIPE_H_ */
diff --git a/src/gallium/state_trackers/nine/nine_quirk.c b/src/gallium/state_trackers/nine/nine_quirk.c
new file mode 100644
index 00000000000..267436b14de
--- /dev/null
+++ b/src/gallium/state_trackers/nine/nine_quirk.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "nine_quirk.h"
+
+#include "util/u_debug.h"
+
+static const struct debug_named_value nine_quirk_table[] = {
+ { "fakecaps", QUIRK_FAKE_CAPS,
+ "Fake caps to emulate D3D specs regardless of hardware caps." },
+ { "lenientshader", QUIRK_LENIENT_SHADER,
+ "Be lenient when translating shaders." },
+ { "all", ~0U,
+ "Enable all quirks." },
+ DEBUG_NAMED_VALUE_END
+};
+
+boolean
+_nine_get_quirk( unsigned quirk )
+{
+ static boolean first = TRUE;
+ static unsigned long flags = 0;
+
+ if (first) {
+ first = FALSE;
+ flags = debug_get_flags_option("NINE_QUIRKS", nine_quirk_table, 0);
+ }
+
+ return !!(flags & quirk);
+}
diff --git a/src/gallium/state_trackers/nine/nine_quirk.h b/src/gallium/state_trackers/nine/nine_quirk.h
new file mode 100644
index 00000000000..9c082dd9f93
--- /dev/null
+++ b/src/gallium/state_trackers/nine/nine_quirk.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _NINE_QUIRK_H_
+#define _NINE_QUIRK_H_
+
+#include "pipe/p_compiler.h"
+
+boolean
+_nine_get_quirk( unsigned quirk );
+
+#define QUIRK(q) (_nine_get_quirk(QUIRK_##q))
+
+#define QUIRK_FAKE_CAPS 0x00000001
+#define QUIRK_LENIENT_SHADER 0x00000002
+
+#endif /* _NINE_QUIRK_H_ */
diff --git a/src/gallium/state_trackers/nine/nine_shader.c b/src/gallium/state_trackers/nine/nine_shader.c
new file mode 100644
index 00000000000..cc027b485b2
--- /dev/null
+++ b/src/gallium/state_trackers/nine/nine_shader.c
@@ -0,0 +1,2959 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ * Copyright 2013 Christoph Bumiller
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "nine_shader.h"
+
+#include "device9.h"
+#include "nine_debug.h"
+#include "nine_state.h"
+
+#include "util/u_memory.h"
+#include "util/u_inlines.h"
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_ureg.h"
+#include "tgsi/tgsi_dump.h"
+
+#define DBG_CHANNEL DBG_SHADER
+
+#if 1
+#define NINE_TGSI_LAZY_DEVS /* don't use TGSI_OPCODE_BREAKC */
+#endif
+#define NINE_TGSI_LAZY_R600 /* don't use TGSI_OPCODE_DP2A */
+
+#define DUMP(args...) _nine_debug_printf(DBG_CHANNEL, NULL, args)
+
+
+struct shader_translator;
+
+typedef HRESULT (*translate_instruction_func)(struct shader_translator *);
+
+static INLINE const char *d3dsio_to_string(unsigned opcode);
+
+
+#define NINED3D_SM1_VS 0xfffe
+#define NINED3D_SM1_PS 0xffff
+
+#define NINE_MAX_COND_DEPTH 64
+#define NINE_MAX_LOOP_DEPTH 64
+
+#define NINED3DSP_END 0x0000ffff
+
+#define NINED3DSPTYPE_FLOAT4 0
+#define NINED3DSPTYPE_INT4 1
+#define NINED3DSPTYPE_BOOL 2
+
+#define NINED3DSPR_IMMEDIATE (D3DSPR_PREDICATE + 1)
+
+#define NINED3DSP_WRITEMASK_MASK D3DSP_WRITEMASK_ALL
+#define NINED3DSP_WRITEMASK_SHIFT 16
+
+#define NINED3DSHADER_INST_PREDICATED (1 << 28)
+
+#define NINED3DSHADER_REL_OP_GT 1
+#define NINED3DSHADER_REL_OP_EQ 2
+#define NINED3DSHADER_REL_OP_GE 3
+#define NINED3DSHADER_REL_OP_LT 4
+#define NINED3DSHADER_REL_OP_NE 5
+#define NINED3DSHADER_REL_OP_LE 6
+
+#define NINED3DSIO_OPCODE_FLAGS_SHIFT 16
+#define NINED3DSIO_OPCODE_FLAGS_MASK (0xff << NINED3DSIO_OPCODE_FLAGS_SHIFT)
+
+#define NINED3DSI_TEXLD_PROJECT 0x1
+#define NINED3DSI_TEXLD_BIAS 0x2
+
+#define NINED3DSP_WRITEMASK_0 0x1
+#define NINED3DSP_WRITEMASK_1 0x2
+#define NINED3DSP_WRITEMASK_2 0x4
+#define NINED3DSP_WRITEMASK_3 0x8
+#define NINED3DSP_WRITEMASK_ALL 0xf
+
+#define NINED3DSP_NOSWIZZLE ((0 << 0) | (1 << 2) | (2 << 4) | (3 << 6))
+
+#define NINE_SWIZZLE4(x,y,z,w) \
+ TGSI_SWIZZLE_##x, TGSI_SWIZZLE_##y, TGSI_SWIZZLE_##z, TGSI_SWIZZLE_##w
+
+#define NINED3DSPDM_SATURATE (D3DSPDM_SATURATE >> D3DSP_DSTMOD_SHIFT)
+#define NINED3DSPDM_PARTIALP (D3DSPDM_PARTIALPRECISION >> D3DSP_DSTMOD_SHIFT)
+#define NINED3DSPDM_CENTROID (D3DSPDM_MSAMPCENTROID >> D3DSP_DSTMOD_SHIFT)
+
+/*
+ * NEG all, not ps: m3x2, m3x3, m3x4, m4x3, m4x4
+ * BIAS <= PS 1.4 (x-0.5)
+ * BIASNEG <= PS 1.4 (-(x-0.5))
+ * SIGN <= PS 1.4 (2(x-0.5))
+ * SIGNNEG <= PS 1.4 (-2(x-0.5))
+ * COMP <= PS 1.4 (1-x)
+ * X2 = PS 1.4 (2x)
+ * X2NEG = PS 1.4 (-2x)
+ * DZ <= PS 1.4, tex{ld,crd} (.xy/.z), z=0 => .11
+ * DW <= PS 1.4, tex{ld,crd} (.xy/.w), w=0 => .11
+ * ABS >= SM 3.0 (abs(x))
+ * ABSNEG >= SM 3.0 (-abs(x))
+ * NOT >= SM 2.0 pedication only
+ */
+#define NINED3DSPSM_NONE (D3DSPSM_NONE >> D3DSP_SRCMOD_SHIFT)
+#define NINED3DSPSM_NEG (D3DSPSM_NEG >> D3DSP_SRCMOD_SHIFT)
+#define NINED3DSPSM_BIAS (D3DSPSM_BIAS >> D3DSP_SRCMOD_SHIFT)
+#define NINED3DSPSM_BIASNEG (D3DSPSM_BIASNEG >> D3DSP_SRCMOD_SHIFT)
+#define NINED3DSPSM_SIGN (D3DSPSM_SIGN >> D3DSP_SRCMOD_SHIFT)
+#define NINED3DSPSM_SIGNNEG (D3DSPSM_SIGNNEG >> D3DSP_SRCMOD_SHIFT)
+#define NINED3DSPSM_COMP (D3DSPSM_COMP >> D3DSP_SRCMOD_SHIFT)
+#define NINED3DSPSM_X2 (D3DSPSM_X2 >> D3DSP_SRCMOD_SHIFT)
+#define NINED3DSPSM_X2NEG (D3DSPSM_X2NEG >> D3DSP_SRCMOD_SHIFT)
+#define NINED3DSPSM_DZ (D3DSPSM_DZ >> D3DSP_SRCMOD_SHIFT)
+#define NINED3DSPSM_DW (D3DSPSM_DW >> D3DSP_SRCMOD_SHIFT)
+#define NINED3DSPSM_ABS (D3DSPSM_ABS >> D3DSP_SRCMOD_SHIFT)
+#define NINED3DSPSM_ABSNEG (D3DSPSM_ABSNEG >> D3DSP_SRCMOD_SHIFT)
+#define NINED3DSPSM_NOT (D3DSPSM_NOT >> D3DSP_SRCMOD_SHIFT)
+
+static const char *sm1_mod_str[] =
+{
+ [NINED3DSPSM_NONE] = "",
+ [NINED3DSPSM_NEG] = "-",
+ [NINED3DSPSM_BIAS] = "bias",
+ [NINED3DSPSM_BIASNEG] = "biasneg",
+ [NINED3DSPSM_SIGN] = "sign",
+ [NINED3DSPSM_SIGNNEG] = "signneg",
+ [NINED3DSPSM_COMP] = "comp",
+ [NINED3DSPSM_X2] = "x2",
+ [NINED3DSPSM_X2NEG] = "x2neg",
+ [NINED3DSPSM_DZ] = "dz",
+ [NINED3DSPSM_DW] = "dw",
+ [NINED3DSPSM_ABS] = "abs",
+ [NINED3DSPSM_ABSNEG] = "-abs",
+ [NINED3DSPSM_NOT] = "not"
+};
+
+static void
+sm1_dump_writemask(BYTE mask)
+{
+ if (mask & 1) DUMP("x"); else DUMP("_");
+ if (mask & 2) DUMP("y"); else DUMP("_");
+ if (mask & 4) DUMP("z"); else DUMP("_");
+ if (mask & 8) DUMP("w"); else DUMP("_");
+}
+
+static void
+sm1_dump_swizzle(BYTE s)
+{
+ char c[4] = { 'x', 'y', 'z', 'w' };
+ DUMP("%c%c%c%c",
+ c[(s >> 0) & 3], c[(s >> 2) & 3], c[(s >> 4) & 3], c[(s >> 6) & 3]);
+}
+
+static const char sm1_file_char[] =
+{
+ [D3DSPR_TEMP] = 'r',
+ [D3DSPR_INPUT] = 'v',
+ [D3DSPR_CONST] = 'c',
+ [D3DSPR_ADDR] = 'A',
+ [D3DSPR_RASTOUT] = 'R',
+ [D3DSPR_ATTROUT] = 'D',
+ [D3DSPR_OUTPUT] = 'o',
+ [D3DSPR_CONSTINT] = 'I',
+ [D3DSPR_COLOROUT] = 'C',
+ [D3DSPR_DEPTHOUT] = 'D',
+ [D3DSPR_SAMPLER] = 's',
+ [D3DSPR_CONST2] = 'c',
+ [D3DSPR_CONST3] = 'c',
+ [D3DSPR_CONST4] = 'c',
+ [D3DSPR_CONSTBOOL] = 'B',
+ [D3DSPR_LOOP] = 'L',
+ [D3DSPR_TEMPFLOAT16] = 'h',
+ [D3DSPR_MISCTYPE] = 'M',
+ [D3DSPR_LABEL] = 'X',
+ [D3DSPR_PREDICATE] = 'p'
+};
+
+static void
+sm1_dump_reg(BYTE file, INT index)
+{
+ switch (file) {
+ case D3DSPR_LOOP:
+ DUMP("aL");
+ break;
+ case D3DSPR_COLOROUT:
+ DUMP("oC%i", index);
+ break;
+ case D3DSPR_DEPTHOUT:
+ DUMP("oDepth");
+ break;
+ case D3DSPR_RASTOUT:
+ DUMP("oRast%i", index);
+ break;
+ case D3DSPR_CONSTINT:
+ DUMP("iconst[%i]", index);
+ break;
+ case D3DSPR_CONSTBOOL:
+ DUMP("bconst[%i]", index);
+ break;
+ default:
+ DUMP("%c%i", sm1_file_char[file], index);
+ break;
+ }
+}
+
+struct sm1_src_param
+{
+ INT idx;
+ struct sm1_src_param *rel;
+ BYTE file;
+ BYTE swizzle;
+ BYTE mod;
+ BYTE type;
+ union {
+ DWORD d[4];
+ float f[4];
+ int i[4];
+ BOOL b;
+ } imm;
+};
+static void
+sm1_parse_immediate(struct shader_translator *, struct sm1_src_param *);
+
+struct sm1_dst_param
+{
+ INT idx;
+ struct sm1_src_param *rel;
+ BYTE file;
+ BYTE mask;
+ BYTE mod;
+ BYTE shift; /* sint4 */
+ BYTE type;
+};
+
+static INLINE void
+assert_replicate_swizzle(const struct ureg_src *reg)
+{
+ assert(reg->SwizzleY == reg->SwizzleX &&
+ reg->SwizzleZ == reg->SwizzleX &&
+ reg->SwizzleW == reg->SwizzleX);
+}
+
+static void
+sm1_dump_immediate(const struct sm1_src_param *param)
+{
+ switch (param->type) {
+ case NINED3DSPTYPE_FLOAT4:
+ DUMP("{ %f %f %f %f }",
+ param->imm.f[0], param->imm.f[1],
+ param->imm.f[2], param->imm.f[3]);
+ break;
+ case NINED3DSPTYPE_INT4:
+ DUMP("{ %i %i %i %i }",
+ param->imm.i[0], param->imm.i[1],
+ param->imm.i[2], param->imm.i[3]);
+ break;
+ case NINED3DSPTYPE_BOOL:
+ DUMP("%s", param->imm.b ? "TRUE" : "FALSE");
+ break;
+ default:
+ assert(0);
+ break;
+ }
+}
+
+static void
+sm1_dump_src_param(const struct sm1_src_param *param)
+{
+ if (param->file == NINED3DSPR_IMMEDIATE) {
+ assert(!param->mod &&
+ !param->rel &&
+ param->swizzle == NINED3DSP_NOSWIZZLE);
+ sm1_dump_immediate(param);
+ return;
+ }
+
+ if (param->mod)
+ DUMP("%s(", sm1_mod_str[param->mod]);
+ if (param->rel) {
+ DUMP("%c[", sm1_file_char[param->file]);
+ sm1_dump_src_param(param->rel);
+ DUMP("+%i]", param->idx);
+ } else {
+ sm1_dump_reg(param->file, param->idx);
+ }
+ if (param->mod)
+ DUMP(")");
+ if (param->swizzle != NINED3DSP_NOSWIZZLE) {
+ DUMP(".");
+ sm1_dump_swizzle(param->swizzle);
+ }
+}
+
+static void
+sm1_dump_dst_param(const struct sm1_dst_param *param)
+{
+ if (param->mod & NINED3DSPDM_SATURATE)
+ DUMP("sat ");
+ if (param->mod & NINED3DSPDM_PARTIALP)
+ DUMP("pp ");
+ if (param->mod & NINED3DSPDM_CENTROID)
+ DUMP("centroid ");
+ if (param->shift < 0)
+ DUMP("/%u ", 1 << -param->shift);
+ if (param->shift > 0)
+ DUMP("*%u ", 1 << param->shift);
+
+ if (param->rel) {
+ DUMP("%c[", sm1_file_char[param->file]);
+ sm1_dump_src_param(param->rel);
+ DUMP("+%i]", param->idx);
+ } else {
+ sm1_dump_reg(param->file, param->idx);
+ }
+ if (param->mask != NINED3DSP_WRITEMASK_ALL) {
+ DUMP(".");
+ sm1_dump_writemask(param->mask);
+ }
+}
+
+struct sm1_semantic
+{
+ struct sm1_dst_param reg;
+ BYTE sampler_type;
+ D3DDECLUSAGE usage;
+ BYTE usage_idx;
+};
+
+struct sm1_op_info
+{
+ /* NOTE: 0 is a valid TGSI opcode, but if handler is set, this parameter
+ * should be ignored completely */
+ unsigned sio;
+ unsigned opcode; /* TGSI_OPCODE_x */
+
+ /* versions are still set even handler is set */
+ struct {
+ unsigned min;
+ unsigned max;
+ } vert_version, frag_version;
+
+ /* number of regs parsed outside of special handler */
+ unsigned ndst;
+ unsigned nsrc;
+
+ /* some instructions don't map perfectly, so use a special handler */
+ translate_instruction_func handler;
+};
+
+struct sm1_instruction
+{
+ D3DSHADER_INSTRUCTION_OPCODE_TYPE opcode;
+ BYTE flags;
+ BOOL coissue;
+ BOOL predicated;
+ BYTE ndst;
+ BYTE nsrc;
+ struct sm1_src_param src[4];
+ struct sm1_src_param src_rel[4];
+ struct sm1_src_param pred;
+ struct sm1_src_param dst_rel[1];
+ struct sm1_dst_param dst[1];
+
+ struct sm1_op_info *info;
+};
+
+static void
+sm1_dump_instruction(struct sm1_instruction *insn, unsigned indent)
+{
+ unsigned i;
+
+ /* no info stored for these: */
+ if (insn->opcode == D3DSIO_DCL)
+ return;
+ for (i = 0; i < indent; ++i)
+ DUMP(" ");
+
+ if (insn->predicated) {
+ DUMP("@");
+ sm1_dump_src_param(&insn->pred);
+ DUMP(" ");
+ }
+ DUMP("%s", d3dsio_to_string(insn->opcode));
+ if (insn->flags) {
+ switch (insn->opcode) {
+ case D3DSIO_TEX:
+ DUMP(insn->flags == NINED3DSI_TEXLD_PROJECT ? "p" : "b");
+ break;
+ default:
+ DUMP("_%x", insn->flags);
+ break;
+ }
+ }
+ if (insn->coissue)
+ DUMP("_co");
+ DUMP(" ");
+
+ for (i = 0; i < insn->ndst && i < Elements(insn->dst); ++i) {
+ sm1_dump_dst_param(&insn->dst[i]);
+ DUMP(" ");
+ }
+
+ for (i = 0; i < insn->nsrc && i < Elements(insn->src); ++i) {
+ sm1_dump_src_param(&insn->src[i]);
+ DUMP(" ");
+ }
+ if (insn->opcode == D3DSIO_DEF ||
+ insn->opcode == D3DSIO_DEFI ||
+ insn->opcode == D3DSIO_DEFB)
+ sm1_dump_immediate(&insn->src[0]);
+
+ DUMP("\n");
+}
+
+struct sm1_local_const
+{
+ INT idx;
+ struct ureg_src reg;
+ union {
+ boolean b;
+ float f[4];
+ int32_t i[4];
+ } imm;
+};
+
+struct shader_translator
+{
+ const DWORD *byte_code;
+ const DWORD *parse;
+ const DWORD *parse_next;
+
+ struct ureg_program *ureg;
+
+ /* shader version */
+ struct {
+ BYTE major;
+ BYTE minor;
+ } version;
+ unsigned processor; /* TGSI_PROCESSOR_VERTEX/FRAMGENT */
+
+ boolean native_integers;
+ boolean inline_subroutines;
+ boolean lower_preds;
+ boolean want_texcoord;
+ boolean shift_wpos;
+ unsigned texcoord_sn;
+
+ struct sm1_instruction insn; /* current instruction */
+
+ struct {
+ struct ureg_dst *r;
+ struct ureg_dst oPos;
+ struct ureg_dst oFog;
+ struct ureg_dst oPts;
+ struct ureg_dst oCol[4];
+ struct ureg_dst o[PIPE_MAX_SHADER_OUTPUTS];
+ struct ureg_dst oDepth;
+ struct ureg_src v[PIPE_MAX_SHADER_INPUTS];
+ struct ureg_src vPos;
+ struct ureg_src vFace;
+ struct ureg_src s;
+ struct ureg_dst p;
+ struct ureg_dst a;
+ struct ureg_dst tS[8]; /* texture stage registers */
+ struct ureg_dst tdst; /* scratch dst if we need extra modifiers */
+ struct ureg_dst t[5]; /* scratch TEMPs */
+ struct ureg_src vC[2]; /* PS color in */
+ struct ureg_src vT[8]; /* PS texcoord in */
+ struct ureg_dst rL[NINE_MAX_LOOP_DEPTH]; /* loop ctr */
+ struct ureg_dst aL[NINE_MAX_LOOP_DEPTH]; /* loop ctr ADDR register */
+ } regs;
+ unsigned num_temp; /* Elements(regs.r) */
+ unsigned num_scratch;
+ unsigned loop_depth;
+ unsigned loop_depth_max;
+ unsigned cond_depth;
+ unsigned loop_labels[NINE_MAX_LOOP_DEPTH];
+ unsigned cond_labels[NINE_MAX_COND_DEPTH];
+
+ unsigned *inst_labels; /* LABEL op */
+ unsigned num_inst_labels;
+
+ unsigned sampler_targets[NINE_MAX_SAMPLERS]; /* TGSI_TEXTURE_x */
+
+ struct sm1_local_const *lconstf;
+ unsigned num_lconstf;
+ struct sm1_local_const lconsti[NINE_MAX_CONST_I];
+ struct sm1_local_const lconstb[NINE_MAX_CONST_B];
+
+ boolean indirect_const_access;
+
+ struct nine_shader_info *info;
+
+ int16_t op_info_map[D3DSIO_BREAKP + 1];
+};
+
+#define IS_VS (tx->processor == TGSI_PROCESSOR_VERTEX)
+#define IS_PS (tx->processor == TGSI_PROCESSOR_FRAGMENT)
+
+static void
+sm1_read_semantic(struct shader_translator *, struct sm1_semantic *);
+
+static void
+sm1_instruction_check(const struct sm1_instruction *insn)
+{
+ if (insn->opcode == D3DSIO_CRS)
+ {
+ if (insn->dst[0].mask & NINED3DSP_WRITEMASK_3)
+ {
+ DBG("CRS.mask.w\n");
+ }
+ }
+}
+
+static boolean
+tx_lconstf(struct shader_translator *tx, struct ureg_src *src, INT index)
+{
+ INT i;
+ assert(index >= 0 && index < (NINE_MAX_CONST_F * 2));
+ for (i = 0; i < tx->num_lconstf; ++i) {
+ if (tx->lconstf[i].idx == index) {
+ *src = tx->lconstf[i].reg;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+static boolean
+tx_lconsti(struct shader_translator *tx, struct ureg_src *src, INT index)
+{
+ assert(index >= 0 && index < NINE_MAX_CONST_I);
+ if (tx->lconsti[index].idx == index)
+ *src = tx->lconsti[index].reg;
+ return tx->lconsti[index].idx == index;
+}
+static boolean
+tx_lconstb(struct shader_translator *tx, struct ureg_src *src, INT index)
+{
+ assert(index >= 0 && index < NINE_MAX_CONST_B);
+ if (tx->lconstb[index].idx == index)
+ *src = tx->lconstb[index].reg;
+ return tx->lconstb[index].idx == index;
+}
+
+static void
+tx_set_lconstf(struct shader_translator *tx, INT index, float f[4])
+{
+ unsigned n;
+
+ /* Anno1404 sets out of range constants. */
+ assert(index >= 0 && index < (NINE_MAX_CONST_F * 2));
+ if (index >= NINE_MAX_CONST_F)
+ WARN("lconstf index %i too high, indirect access won't work\n", index);
+
+ for (n = 0; n < tx->num_lconstf; ++n)
+ if (tx->lconstf[n].idx == index)
+ break;
+ if (n == tx->num_lconstf) {
+ if ((n % 8) == 0) {
+ tx->lconstf = REALLOC(tx->lconstf,
+ (n + 0) * sizeof(tx->lconstf[0]),
+ (n + 8) * sizeof(tx->lconstf[0]));
+ assert(tx->lconstf);
+ }
+ tx->num_lconstf++;
+ }
+ tx->lconstf[n].idx = index;
+ tx->lconstf[n].reg = ureg_imm4f(tx->ureg, f[0], f[1], f[2], f[3]);
+
+ memcpy(tx->lconstf[n].imm.f, f, sizeof(tx->lconstf[n].imm.f));
+}
+static void
+tx_set_lconsti(struct shader_translator *tx, INT index, int i[4])
+{
+ assert(index >= 0 && index < NINE_MAX_CONST_I);
+ tx->lconsti[index].idx = index;
+ tx->lconsti[index].reg = tx->native_integers ?
+ ureg_imm4i(tx->ureg, i[0], i[1], i[2], i[3]) :
+ ureg_imm4f(tx->ureg, i[0], i[1], i[2], i[3]);
+}
+static void
+tx_set_lconstb(struct shader_translator *tx, INT index, BOOL b)
+{
+ assert(index >= 0 && index < NINE_MAX_CONST_B);
+ tx->lconstb[index].idx = index;
+ tx->lconstb[index].reg = tx->native_integers ?
+ ureg_imm1u(tx->ureg, b ? 0xffffffff : 0) :
+ ureg_imm1f(tx->ureg, b ? 1.0f : 0.0f);
+}
+
+static INLINE struct ureg_dst
+tx_scratch(struct shader_translator *tx)
+{
+ assert(tx->num_scratch < Elements(tx->regs.t));
+ if (ureg_dst_is_undef(tx->regs.t[tx->num_scratch]))
+ tx->regs.t[tx->num_scratch] = ureg_DECL_local_temporary(tx->ureg);
+ return tx->regs.t[tx->num_scratch++];
+}
+
+static INLINE struct ureg_dst
+tx_scratch_scalar(struct shader_translator *tx)
+{
+ return ureg_writemask(tx_scratch(tx), TGSI_WRITEMASK_X);
+}
+
+static INLINE struct ureg_src
+tx_src_scalar(struct ureg_dst dst)
+{
+ struct ureg_src src = ureg_src(dst);
+ int c = ffs(dst.WriteMask) - 1;
+ if (dst.WriteMask == (1 << c))
+ src = ureg_scalar(src, c);
+ return src;
+}
+
+/* Need to declare all constants if indirect addressing is used,
+ * otherwise we could scan the shader to determine the maximum.
+ * TODO: It doesn't really matter for nv50 so I won't do the scan,
+ * but radeon drivers might care, if they don't infer it from TGSI.
+ */
+static void
+tx_decl_constants(struct shader_translator *tx)
+{
+ unsigned i, n = 0;
+
+ for (i = 0; i < NINE_MAX_CONST_F; ++i)
+ ureg_DECL_constant(tx->ureg, n++);
+ for (i = 0; i < NINE_MAX_CONST_I; ++i)
+ ureg_DECL_constant(tx->ureg, n++);
+ for (i = 0; i < (NINE_MAX_CONST_B / 4); ++i)
+ ureg_DECL_constant(tx->ureg, n++);
+}
+
+static INLINE void
+tx_temp_alloc(struct shader_translator *tx, INT idx)
+{
+ assert(idx >= 0);
+ if (idx >= tx->num_temp) {
+ unsigned k = tx->num_temp;
+ unsigned n = idx + 1;
+ tx->regs.r = REALLOC(tx->regs.r,
+ k * sizeof(tx->regs.r[0]),
+ n * sizeof(tx->regs.r[0]));
+ for (; k < n; ++k)
+ tx->regs.r[k] = ureg_dst_undef();
+ tx->num_temp = n;
+ }
+ if (ureg_dst_is_undef(tx->regs.r[idx]))
+ tx->regs.r[idx] = ureg_DECL_temporary(tx->ureg);
+}
+
+static INLINE void
+tx_addr_alloc(struct shader_translator *tx, INT idx)
+{
+ assert(idx == 0);
+ if (ureg_dst_is_undef(tx->regs.a))
+ tx->regs.a = ureg_DECL_address(tx->ureg);
+}
+
+static INLINE void
+tx_pred_alloc(struct shader_translator *tx, INT idx)
+{
+ assert(idx == 0);
+ if (ureg_dst_is_undef(tx->regs.p))
+ tx->regs.p = ureg_DECL_predicate(tx->ureg);
+}
+
+static INLINE void
+tx_texcoord_alloc(struct shader_translator *tx, INT idx)
+{
+ assert(IS_PS);
+ assert(idx >= 0 && idx < Elements(tx->regs.vT));
+ if (ureg_src_is_undef(tx->regs.vT[idx]))
+ tx->regs.vT[idx] = ureg_DECL_fs_input(tx->ureg, tx->texcoord_sn, idx,
+ TGSI_INTERPOLATE_PERSPECTIVE);
+}
+
+static INLINE unsigned *
+tx_bgnloop(struct shader_translator *tx)
+{
+ tx->loop_depth++;
+ if (tx->loop_depth_max < tx->loop_depth)
+ tx->loop_depth_max = tx->loop_depth;
+ assert(tx->loop_depth < NINE_MAX_LOOP_DEPTH);
+ return &tx->loop_labels[tx->loop_depth - 1];
+}
+
+static INLINE unsigned *
+tx_endloop(struct shader_translator *tx)
+{
+ assert(tx->loop_depth);
+ tx->loop_depth--;
+ ureg_fixup_label(tx->ureg, tx->loop_labels[tx->loop_depth],
+ ureg_get_instruction_number(tx->ureg));
+ return &tx->loop_labels[tx->loop_depth];
+}
+
+static struct ureg_dst
+tx_get_loopctr(struct shader_translator *tx)
+{
+ const unsigned l = tx->loop_depth - 1;
+
+ if (!tx->loop_depth)
+ {
+ DBG("loop counter requested outside of loop\n");
+ return ureg_dst_undef();
+ }
+
+ if (ureg_dst_is_undef(tx->regs.aL[l]))
+ {
+ struct ureg_dst rreg = ureg_DECL_local_temporary(tx->ureg);
+ struct ureg_dst areg = ureg_DECL_address(tx->ureg);
+ unsigned c;
+
+ assert(l % 4 == 0);
+ for (c = l; c < (l + 4) && c < Elements(tx->regs.aL); ++c) {
+ tx->regs.rL[c] = ureg_writemask(rreg, 1 << (c & 3));
+ tx->regs.aL[c] = ureg_writemask(areg, 1 << (c & 3));
+ }
+ }
+ return tx->regs.rL[l];
+}
+static struct ureg_dst
+tx_get_aL(struct shader_translator *tx)
+{
+ if (!ureg_dst_is_undef(tx_get_loopctr(tx)))
+ return tx->regs.aL[tx->loop_depth - 1];
+ return ureg_dst_undef();
+}
+
+static INLINE unsigned *
+tx_cond(struct shader_translator *tx)
+{
+ assert(tx->cond_depth <= NINE_MAX_COND_DEPTH);
+ tx->cond_depth++;
+ return &tx->cond_labels[tx->cond_depth - 1];
+}
+
+static INLINE unsigned *
+tx_elsecond(struct shader_translator *tx)
+{
+ assert(tx->cond_depth);
+ return &tx->cond_labels[tx->cond_depth - 1];
+}
+
+static INLINE void
+tx_endcond(struct shader_translator *tx)
+{
+ assert(tx->cond_depth);
+ tx->cond_depth--;
+ ureg_fixup_label(tx->ureg, tx->cond_labels[tx->cond_depth],
+ ureg_get_instruction_number(tx->ureg));
+}
+
+static INLINE struct ureg_dst
+nine_ureg_dst_register(unsigned file, int index)
+{
+ return ureg_dst(ureg_src_register(file, index));
+}
+
+static struct ureg_src
+tx_src_param(struct shader_translator *tx, const struct sm1_src_param *param)
+{
+ struct ureg_program *ureg = tx->ureg;
+ struct ureg_src src;
+ struct ureg_dst tmp;
+
+ switch (param->file)
+ {
+ case D3DSPR_TEMP:
+ assert(!param->rel);
+ tx_temp_alloc(tx, param->idx);
+ src = ureg_src(tx->regs.r[param->idx]);
+ break;
+ /* case D3DSPR_TEXTURE: == D3DSPR_ADDR */
+ case D3DSPR_ADDR:
+ assert(!param->rel);
+ if (IS_VS) {
+ tx_addr_alloc(tx, param->idx);
+ src = ureg_src(tx->regs.a);
+ } else {
+ if (tx->version.major < 2 && tx->version.minor < 4) {
+ /* no subroutines, so should be defined */
+ src = ureg_src(tx->regs.tS[param->idx]);
+ } else {
+ tx_texcoord_alloc(tx, param->idx);
+ src = tx->regs.vT[param->idx];
+ }
+ }
+ break;
+ case D3DSPR_INPUT:
+ if (IS_VS) {
+ src = ureg_src_register(TGSI_FILE_INPUT, param->idx);
+ } else {
+ if (tx->version.major < 3) {
+ assert(!param->rel);
+ src = ureg_DECL_fs_input(tx->ureg, TGSI_SEMANTIC_COLOR,
+ param->idx,
+ TGSI_INTERPOLATE_PERSPECTIVE);
+ } else {
+ assert(!param->rel); /* TODO */
+ assert(param->idx < Elements(tx->regs.v));
+ src = tx->regs.v[param->idx];
+ }
+ }
+ break;
+ case D3DSPR_PREDICATE:
+ assert(!param->rel);
+ tx_pred_alloc(tx, param->idx);
+ src = ureg_src(tx->regs.p);
+ break;
+ case D3DSPR_SAMPLER:
+ assert(param->mod == NINED3DSPSM_NONE);
+ assert(param->swizzle == NINED3DSP_NOSWIZZLE);
+ assert(!param->rel);
+ src = ureg_src_register(TGSI_FILE_SAMPLER, param->idx);
+ break;
+ case D3DSPR_CONST:
+ if (param->rel)
+ tx->indirect_const_access = TRUE;
+ if (param->rel || !tx_lconstf(tx, &src, param->idx)) {
+ if (!param->rel)
+ nine_info_mark_const_f_used(tx->info, param->idx);
+ src = ureg_src_register(TGSI_FILE_CONSTANT, param->idx);
+ }
+ break;
+ case D3DSPR_CONST2:
+ case D3DSPR_CONST3:
+ case D3DSPR_CONST4:
+ DBG("CONST2/3/4 should have been collapsed into D3DSPR_CONST !\n");
+ assert(!"CONST2/3/4");
+ src = ureg_imm1f(ureg, 0.0f);
+ break;
+ case D3DSPR_CONSTINT:
+ if (param->rel || !tx_lconsti(tx, &src, param->idx)) {
+ if (!param->rel)
+ nine_info_mark_const_i_used(tx->info, param->idx);
+ src = ureg_src_register(TGSI_FILE_CONSTANT,
+ tx->info->const_i_base + param->idx);
+ }
+ break;
+ case D3DSPR_CONSTBOOL:
+ if (param->rel || !tx_lconstb(tx, &src, param->idx)) {
+ char r = param->idx / 4;
+ char s = param->idx & 3;
+ if (!param->rel)
+ nine_info_mark_const_b_used(tx->info, param->idx);
+ src = ureg_src_register(TGSI_FILE_CONSTANT,
+ tx->info->const_b_base + r);
+ src = ureg_swizzle(src, s, s, s, s);
+ }
+ break;
+ case D3DSPR_LOOP:
+ src = tx_src_scalar(tx_get_aL(tx));
+ break;
+ case D3DSPR_MISCTYPE:
+ switch (param->idx) {
+ case D3DSMO_POSITION:
+ if (ureg_src_is_undef(tx->regs.vPos))
+ tx->regs.vPos = ureg_DECL_fs_input(ureg,
+ TGSI_SEMANTIC_POSITION, 0,
+ TGSI_INTERPOLATE_LINEAR);
+ if (tx->shift_wpos) {
+ /* TODO: do this only once */
+ struct ureg_dst wpos = tx_scratch(tx);
+ ureg_SUB(ureg, wpos, tx->regs.vPos,
+ ureg_imm4f(ureg, 0.5f, 0.5f, 0.0f, 0.0f));
+ src = ureg_src(wpos);
+ } else {
+ src = tx->regs.vPos;
+ }
+ break;
+ case D3DSMO_FACE:
+ if (ureg_src_is_undef(tx->regs.vFace)) {
+ tx->regs.vFace = ureg_DECL_fs_input(ureg,
+ TGSI_SEMANTIC_FACE, 0,
+ TGSI_INTERPOLATE_CONSTANT);
+ tx->regs.vFace = ureg_scalar(tx->regs.vFace, TGSI_SWIZZLE_X);
+ }
+ src = tx->regs.vFace;
+ break;
+ default:
+ assert(!"invalid src D3DSMO");
+ break;
+ }
+ assert(!param->rel);
+ break;
+ case D3DSPR_TEMPFLOAT16:
+ break;
+ default:
+ assert(!"invalid src D3DSPR");
+ }
+ if (param->rel)
+ src = ureg_src_indirect(src, tx_src_param(tx, param->rel));
+
+ if (param->swizzle != NINED3DSP_NOSWIZZLE)
+ src = ureg_swizzle(src,
+ (param->swizzle >> 0) & 0x3,
+ (param->swizzle >> 2) & 0x3,
+ (param->swizzle >> 4) & 0x3,
+ (param->swizzle >> 6) & 0x3);
+
+ switch (param->mod) {
+ case NINED3DSPSM_ABS:
+ src = ureg_abs(src);
+ break;
+ case NINED3DSPSM_ABSNEG:
+ src = ureg_negate(ureg_abs(src));
+ break;
+ case NINED3DSPSM_NEG:
+ src = ureg_negate(src);
+ break;
+ case NINED3DSPSM_BIAS:
+ tmp = tx_scratch(tx);
+ ureg_SUB(ureg, tmp, src, ureg_imm1f(ureg, 0.5f));
+ src = ureg_src(tmp);
+ break;
+ case NINED3DSPSM_BIASNEG:
+ tmp = tx_scratch(tx);
+ ureg_SUB(ureg, tmp, ureg_imm1f(ureg, 0.5f), src);
+ src = ureg_src(tmp);
+ break;
+ case NINED3DSPSM_NOT:
+ if (tx->native_integers) {
+ tmp = tx_scratch(tx);
+ ureg_NOT(ureg, tmp, src);
+ src = ureg_src(tmp);
+ break;
+ }
+ /* fall through */
+ case NINED3DSPSM_COMP:
+ tmp = tx_scratch(tx);
+ ureg_SUB(ureg, tmp, ureg_imm1f(ureg, 1.0f), src);
+ src = ureg_src(tmp);
+ break;
+ case NINED3DSPSM_DZ:
+ case NINED3DSPSM_DW:
+ /* handled in instruction */
+ break;
+ case NINED3DSPSM_SIGN:
+ tmp = tx_scratch(tx);
+ ureg_MAD(ureg, tmp, src, ureg_imm1f(ureg, 2.0f), ureg_imm1f(ureg, -1.0f));
+ src = ureg_src(tmp);
+ break;
+ case NINED3DSPSM_SIGNNEG:
+ tmp = tx_scratch(tx);
+ ureg_MAD(ureg, tmp, src, ureg_imm1f(ureg, -2.0f), ureg_imm1f(ureg, 1.0f));
+ src = ureg_src(tmp);
+ break;
+ case NINED3DSPSM_X2:
+ tmp = tx_scratch(tx);
+ ureg_ADD(ureg, tmp, src, src);
+ src = ureg_src(tmp);
+ break;
+ case NINED3DSPSM_X2NEG:
+ tmp = tx_scratch(tx);
+ ureg_ADD(ureg, tmp, src, src);
+ src = ureg_negate(ureg_src(tmp));
+ break;
+ default:
+ assert(param->mod == NINED3DSPSM_NONE);
+ break;
+ }
+
+ return src;
+}
+
+static struct ureg_dst
+_tx_dst_param(struct shader_translator *tx, const struct sm1_dst_param *param)
+{
+ struct ureg_dst dst;
+
+ switch (param->file)
+ {
+ case D3DSPR_TEMP:
+ assert(!param->rel);
+ tx_temp_alloc(tx, param->idx);
+ dst = tx->regs.r[param->idx];
+ break;
+ /* case D3DSPR_TEXTURE: == D3DSPR_ADDR */
+ case D3DSPR_ADDR:
+ assert(!param->rel);
+ if (tx->version.major < 2 && !IS_VS) {
+ if (ureg_dst_is_undef(tx->regs.tS[param->idx]))
+ tx->regs.tS[param->idx] = ureg_DECL_temporary(tx->ureg);
+ dst = tx->regs.tS[param->idx];
+ } else
+ if (!IS_VS && tx->insn.opcode == D3DSIO_TEXKILL) { /* maybe others, too */
+ tx_texcoord_alloc(tx, param->idx);
+ dst = ureg_dst(tx->regs.vT[param->idx]);
+ } else {
+ tx_addr_alloc(tx, param->idx);
+ dst = tx->regs.a;
+ }
+ break;
+ case D3DSPR_RASTOUT:
+ assert(!param->rel);
+ switch (param->idx) {
+ case 0:
+ if (ureg_dst_is_undef(tx->regs.oPos))
+ tx->regs.oPos =
+ ureg_DECL_output(tx->ureg, TGSI_SEMANTIC_POSITION, 0);
+ dst = tx->regs.oPos;
+ break;
+ case 1:
+ if (ureg_dst_is_undef(tx->regs.oFog))
+ tx->regs.oFog =
+ ureg_DECL_output(tx->ureg, TGSI_SEMANTIC_FOG, 0);
+ dst = tx->regs.oFog;
+ break;
+ case 2:
+ if (ureg_dst_is_undef(tx->regs.oPts))
+ tx->regs.oPts =
+ ureg_DECL_output(tx->ureg, TGSI_SEMANTIC_PSIZE, 0);
+ dst = tx->regs.oPts;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ break;
+ /* case D3DSPR_TEXCRDOUT: == D3DSPR_OUTPUT */
+ case D3DSPR_OUTPUT:
+ if (tx->version.major < 3) {
+ assert(!param->rel);
+ dst = ureg_DECL_output(tx->ureg, tx->texcoord_sn, param->idx);
+ } else {
+ assert(!param->rel); /* TODO */
+ assert(param->idx < Elements(tx->regs.o));
+ dst = tx->regs.o[param->idx];
+ }
+ break;
+ case D3DSPR_ATTROUT: /* VS */
+ case D3DSPR_COLOROUT: /* PS */
+ assert(param->idx >= 0 && param->idx < 4);
+ assert(!param->rel);
+ tx->info->rt_mask |= 1 << param->idx;
+ if (ureg_dst_is_undef(tx->regs.oCol[param->idx]))
+ tx->regs.oCol[param->idx] =
+ ureg_DECL_output(tx->ureg, TGSI_SEMANTIC_COLOR, param->idx);
+ dst = tx->regs.oCol[param->idx];
+ if (IS_VS && tx->version.major < 3)
+ dst = ureg_saturate(dst);
+ break;
+ case D3DSPR_DEPTHOUT:
+ assert(!param->rel);
+ if (ureg_dst_is_undef(tx->regs.oDepth))
+ tx->regs.oDepth =
+ ureg_DECL_output_masked(tx->ureg, TGSI_SEMANTIC_POSITION, 0,
+ TGSI_WRITEMASK_Z);
+ dst = tx->regs.oDepth; /* XXX: must write .z component */
+ break;
+ case D3DSPR_PREDICATE:
+ assert(!param->rel);
+ tx_pred_alloc(tx, param->idx);
+ dst = tx->regs.p;
+ break;
+ case D3DSPR_TEMPFLOAT16:
+ DBG("unhandled D3DSPR: %u\n", param->file);
+ break;
+ default:
+ assert(!"invalid dst D3DSPR");
+ break;
+ }
+ if (param->rel)
+ dst = ureg_dst_indirect(dst, tx_src_param(tx, param->rel));
+
+ if (param->mask != NINED3DSP_WRITEMASK_ALL)
+ dst = ureg_writemask(dst, param->mask);
+ if (param->mod & NINED3DSPDM_SATURATE)
+ dst = ureg_saturate(dst);
+
+ return dst;
+}
+
+static struct ureg_dst
+tx_dst_param(struct shader_translator *tx, const struct sm1_dst_param *param)
+{
+ if (param->shift) {
+ tx->regs.tdst = ureg_writemask(tx_scratch(tx), param->mask);
+ return tx->regs.tdst;
+ }
+ return _tx_dst_param(tx, param);
+}
+
+static void
+tx_apply_dst0_modifiers(struct shader_translator *tx)
+{
+ struct ureg_dst rdst;
+ float f;
+
+ if (!tx->insn.ndst || !tx->insn.dst[0].shift || tx->insn.opcode == D3DSIO_TEXKILL)
+ return;
+ rdst = _tx_dst_param(tx, &tx->insn.dst[0]);
+
+ assert(rdst.File != TGSI_FILE_ADDRESS); /* this probably isn't possible */
+
+ if (tx->insn.dst[0].shift < 0)
+ f = 1.0f / (1 << -tx->insn.dst[0].shift);
+ else
+ f = 1 << tx->insn.dst[0].shift;
+
+ ureg_MUL(tx->ureg, rdst, ureg_src(tx->regs.tdst), ureg_imm1f(tx->ureg, f));
+}
+
+static struct ureg_src
+tx_dst_param_as_src(struct shader_translator *tx, const struct sm1_dst_param *param)
+{
+ struct ureg_src src;
+
+ assert(!param->shift);
+ assert(!(param->mod & NINED3DSPDM_SATURATE));
+
+ switch (param->file) {
+ case D3DSPR_INPUT:
+ if (IS_VS) {
+ src = ureg_src_register(TGSI_FILE_INPUT, param->idx);
+ } else {
+ assert(!param->rel);
+ assert(param->idx < Elements(tx->regs.v));
+ src = tx->regs.v[param->idx];
+ }
+ break;
+ default:
+ src = ureg_src(tx_dst_param(tx, param));
+ break;
+ }
+ if (param->rel)
+ src = ureg_src_indirect(src, tx_src_param(tx, param->rel));
+
+ if (!param->mask)
+ WARN("mask is 0, using identity swizzle\n");
+
+ if (param->mask && param->mask != NINED3DSP_WRITEMASK_ALL) {
+ char s[4];
+ int n;
+ int c;
+ for (n = 0, c = 0; c < 4; ++c)
+ if (param->mask & (1 << c))
+ s[n++] = c;
+ assert(n);
+ for (c = n; c < 4; ++c)
+ s[c] = s[n - 1];
+ src = ureg_swizzle(src, s[0], s[1], s[2], s[3]);
+ }
+ return src;
+}
+
+static HRESULT
+NineTranslateInstruction_Mkxn(struct shader_translator *tx, const unsigned k, const unsigned n)
+{
+ struct ureg_program *ureg = tx->ureg;
+ struct ureg_dst dst;
+ struct ureg_src src[2];
+ unsigned i;
+
+ dst = tx_dst_param(tx, &tx->insn.dst[0]);
+ src[0] = tx_src_param(tx, &tx->insn.src[0]);
+ src[1] = tx_src_param(tx, &tx->insn.src[1]);
+
+ for (i = 0; i < n; i++, src[1].Index++)
+ {
+ const unsigned m = (1 << i);
+
+ if (!(dst.WriteMask & m))
+ continue;
+
+ /* XXX: src == dst case ? */
+
+ switch (k) {
+ case 3:
+ ureg_DP3(ureg, ureg_writemask(dst, m), src[0], src[1]);
+ break;
+ case 4:
+ ureg_DP4(ureg, ureg_writemask(dst, m), src[0], src[1]);
+ break;
+ default:
+ DBG("invalid operation: M%ux%u\n", m, n);
+ break;
+ }
+ }
+
+ return D3D_OK;
+}
+
+#define VNOTSUPPORTED 0, 0
+#define V(maj, min) (((maj) << 8) | (min))
+
+static INLINE const char *
+d3dsio_to_string( unsigned opcode )
+{
+ static const char *names[] = {
+ "NOP",
+ "MOV",
+ "ADD",
+ "SUB",
+ "MAD",
+ "MUL",
+ "RCP",
+ "RSQ",
+ "DP3",
+ "DP4",
+ "MIN",
+ "MAX",
+ "SLT",
+ "SGE",
+ "EXP",
+ "LOG",
+ "LIT",
+ "DST",
+ "LRP",
+ "FRC",
+ "M4x4",
+ "M4x3",
+ "M3x4",
+ "M3x3",
+ "M3x2",
+ "CALL",
+ "CALLNZ",
+ "LOOP",
+ "RET",
+ "ENDLOOP",
+ "LABEL",
+ "DCL",
+ "POW",
+ "CRS",
+ "SGN",
+ "ABS",
+ "NRM",
+ "SINCOS",
+ "REP",
+ "ENDREP",
+ "IF",
+ "IFC",
+ "ELSE",
+ "ENDIF",
+ "BREAK",
+ "BREAKC",
+ "MOVA",
+ "DEFB",
+ "DEFI",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "TEXCOORD",
+ "TEXKILL",
+ "TEX",
+ "TEXBEM",
+ "TEXBEML",
+ "TEXREG2AR",
+ "TEXREG2GB",
+ "TEXM3x2PAD",
+ "TEXM3x2TEX",
+ "TEXM3x3PAD",
+ "TEXM3x3TEX",
+ NULL,
+ "TEXM3x3SPEC",
+ "TEXM3x3VSPEC",
+ "EXPP",
+ "LOGP",
+ "CND",
+ "DEF",
+ "TEXREG2RGB",
+ "TEXDP3TEX",
+ "TEXM3x2DEPTH",
+ "TEXDP3",
+ "TEXM3x3",
+ "TEXDEPTH",
+ "CMP",
+ "BEM",
+ "DP2ADD",
+ "DSX",
+ "DSY",
+ "TEXLDD",
+ "SETP",
+ "TEXLDL",
+ "BREAKP"
+ };
+
+ if (opcode < Elements(names)) return names[opcode];
+
+ switch (opcode) {
+ case D3DSIO_PHASE: return "PHASE";
+ case D3DSIO_COMMENT: return "COMMENT";
+ case D3DSIO_END: return "END";
+ default:
+ return NULL;
+ }
+}
+
+#define NULL_INSTRUCTION { 0, { 0, 0 }, { 0, 0 }, 0, 0, NULL }
+#define IS_VALID_INSTRUCTION(inst) ((inst).vert_version.min | \
+ (inst).vert_version.max | \
+ (inst).frag_version.min | \
+ (inst).frag_version.max)
+
+#define SPECIAL(name) \
+ NineTranslateInstruction_##name
+
+#define DECL_SPECIAL(name) \
+ static HRESULT \
+ NineTranslateInstruction_##name( struct shader_translator *tx )
+
+static HRESULT
+NineTranslateInstruction_Generic(struct shader_translator *);
+
+DECL_SPECIAL(M4x4)
+{
+ return NineTranslateInstruction_Mkxn(tx, 4, 3);
+}
+
+DECL_SPECIAL(M4x3)
+{
+ return NineTranslateInstruction_Mkxn(tx, 4, 3);
+}
+
+DECL_SPECIAL(M3x4)
+{
+ return NineTranslateInstruction_Mkxn(tx, 3, 4);
+}
+
+DECL_SPECIAL(M3x3)
+{
+ return NineTranslateInstruction_Mkxn(tx, 3, 3);
+}
+
+DECL_SPECIAL(M3x2)
+{
+ return NineTranslateInstruction_Mkxn(tx, 3, 2);
+}
+
+DECL_SPECIAL(CMP)
+{
+ ureg_CMP(tx->ureg, tx_dst_param(tx, &tx->insn.dst[0]),
+ tx_src_param(tx, &tx->insn.src[0]),
+ tx_src_param(tx, &tx->insn.src[2]),
+ tx_src_param(tx, &tx->insn.src[1]));
+ return D3D_OK;
+}
+
+DECL_SPECIAL(CND)
+{
+ struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]);
+ struct ureg_dst cgt;
+ struct ureg_src cnd;
+
+ if (tx->insn.coissue && tx->version.major == 1 && tx->version.minor < 4) {
+ ureg_MOV(tx->ureg,
+ dst, tx_src_param(tx, &tx->insn.src[1]));
+ return D3D_OK;
+ }
+
+ cnd = tx_src_param(tx, &tx->insn.src[0]);
+#ifdef NINE_TGSI_LAZY_R600
+ cgt = tx_scratch(tx);
+
+ if (tx->version.major == 1 && tx->version.minor < 4) {
+ cgt.WriteMask = TGSI_WRITEMASK_W;
+ ureg_SGT(tx->ureg, cgt, cnd, ureg_imm1f(tx->ureg, 0.5f));
+ cnd = ureg_scalar(cnd, TGSI_SWIZZLE_W);
+ } else {
+ ureg_SGT(tx->ureg, cgt, cnd, ureg_imm1f(tx->ureg, 0.5f));
+ }
+ ureg_CMP(tx->ureg, dst,
+ tx_src_param(tx, &tx->insn.src[1]),
+ tx_src_param(tx, &tx->insn.src[2]), ureg_negate(cnd));
+#else
+ if (tx->version.major == 1 && tx->version.minor < 4)
+ cnd = ureg_scalar(cnd, TGSI_SWIZZLE_W);
+ ureg_CND(tx->ureg, dst,
+ tx_src_param(tx, &tx->insn.src[1]),
+ tx_src_param(tx, &tx->insn.src[2]), cnd);
+#endif
+ return D3D_OK;
+}
+
+DECL_SPECIAL(CALL)
+{
+ assert(tx->insn.src[0].idx < tx->num_inst_labels);
+ ureg_CAL(tx->ureg, &tx->inst_labels[tx->insn.src[0].idx]);
+ return D3D_OK;
+}
+
+DECL_SPECIAL(CALLNZ)
+{
+ struct ureg_program *ureg = tx->ureg;
+ struct ureg_dst tmp = tx_scratch_scalar(tx);
+ struct ureg_src src = tx_src_param(tx, &tx->insn.src[1]);
+
+ /* NOTE: source should be const bool, so we can use NOT/SUB instead of [U]SNE 0 */
+ if (!tx->insn.flags) {
+ if (tx->native_integers)
+ ureg_NOT(ureg, tmp, src);
+ else
+ ureg_SUB(ureg, tmp, ureg_imm1f(ureg, 1.0f), src);
+ }
+ ureg_IF(ureg, tx->insn.flags ? src : tx_src_scalar(tmp), tx_cond(tx));
+ ureg_CAL(ureg, &tx->inst_labels[tx->insn.src[0].idx]);
+ tx_endcond(tx);
+ ureg_ENDIF(ureg);
+ return D3D_OK;
+}
+
+DECL_SPECIAL(MOV_vs1x)
+{
+ if (tx->insn.dst[0].file == D3DSPR_ADDR) {
+ ureg_ARL(tx->ureg,
+ tx_dst_param(tx, &tx->insn.dst[0]),
+ tx_src_param(tx, &tx->insn.src[0]));
+ return D3D_OK;
+ }
+ return NineTranslateInstruction_Generic(tx);
+}
+
+DECL_SPECIAL(LOOP)
+{
+ struct ureg_program *ureg = tx->ureg;
+ unsigned *label;
+ struct ureg_src src = tx_src_param(tx, &tx->insn.src[1]);
+ struct ureg_src iter = ureg_scalar(src, TGSI_SWIZZLE_X);
+ struct ureg_src init = ureg_scalar(src, TGSI_SWIZZLE_Y);
+ struct ureg_src step = ureg_scalar(src, TGSI_SWIZZLE_Z);
+ struct ureg_dst ctr;
+ struct ureg_dst tmp = tx_scratch_scalar(tx);
+
+ label = tx_bgnloop(tx);
+ ctr = tx_get_loopctr(tx);
+
+ ureg_MOV(tx->ureg, ctr, init);
+ ureg_BGNLOOP(tx->ureg, label);
+ if (tx->native_integers) {
+ /* we'll let the backend pull up that MAD ... */
+ ureg_UMAD(ureg, tmp, iter, step, init);
+ ureg_USEQ(ureg, tmp, ureg_src(ctr), tx_src_scalar(tmp));
+#ifdef NINE_TGSI_LAZY_DEVS
+ ureg_UIF(ureg, tx_src_scalar(tmp), tx_cond(tx));
+#endif
+ } else {
+ /* can't simply use SGE for precision because step might be negative */
+ ureg_MAD(ureg, tmp, iter, step, init);
+ ureg_SEQ(ureg, tmp, ureg_src(ctr), tx_src_scalar(tmp));
+#ifdef NINE_TGSI_LAZY_DEVS
+ ureg_IF(ureg, tx_src_scalar(tmp), tx_cond(tx));
+#endif
+ }
+#ifdef NINE_TGSI_LAZY_DEVS
+ ureg_BRK(ureg);
+ tx_endcond(tx);
+ ureg_ENDIF(ureg);
+#else
+ ureg_BREAKC(ureg, tx_src_scalar(tmp));
+#endif
+ if (tx->native_integers) {
+ ureg_UARL(ureg, tx_get_aL(tx), tx_src_scalar(ctr));
+ ureg_UADD(ureg, ctr, tx_src_scalar(ctr), step);
+ } else {
+ ureg_ARL(ureg, tx_get_aL(tx), tx_src_scalar(ctr));
+ ureg_ADD(ureg, ctr, tx_src_scalar(ctr), step);
+ }
+ return D3D_OK;
+}
+
+DECL_SPECIAL(RET)
+{
+ ureg_RET(tx->ureg);
+ return D3D_OK;
+}
+
+DECL_SPECIAL(ENDLOOP)
+{
+ ureg_ENDLOOP(tx->ureg, tx_endloop(tx));
+ return D3D_OK;
+}
+
+DECL_SPECIAL(LABEL)
+{
+ unsigned k = tx->num_inst_labels;
+ unsigned n = tx->insn.src[0].idx;
+ assert(n < 2048);
+ if (n >= k)
+ tx->inst_labels = REALLOC(tx->inst_labels,
+ k * sizeof(tx->inst_labels[0]),
+ n * sizeof(tx->inst_labels[0]));
+
+ tx->inst_labels[n] = ureg_get_instruction_number(tx->ureg);
+ return D3D_OK;
+}
+
+DECL_SPECIAL(SINCOS)
+{
+ struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]);
+ struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]);
+
+ assert(!(dst.WriteMask & 0xc));
+
+ dst.WriteMask &= TGSI_WRITEMASK_XY; /* z undefined, w untouched */
+ ureg_SCS(tx->ureg, dst, src);
+ return D3D_OK;
+}
+
+DECL_SPECIAL(SGN)
+{
+ ureg_SSG(tx->ureg,
+ tx_dst_param(tx, &tx->insn.dst[0]),
+ tx_src_param(tx, &tx->insn.src[0]));
+ return D3D_OK;
+}
+
+DECL_SPECIAL(REP)
+{
+ struct ureg_program *ureg = tx->ureg;
+ unsigned *label;
+ struct ureg_src rep = tx_src_param(tx, &tx->insn.src[0]);
+ struct ureg_dst ctr;
+ struct ureg_dst tmp = tx_scratch_scalar(tx);
+ struct ureg_src imm =
+ tx->native_integers ? ureg_imm1u(ureg, 0) : ureg_imm1f(ureg, 0.0f);
+
+ label = tx_bgnloop(tx);
+ ctr = tx_get_loopctr(tx);
+
+ /* NOTE: rep must be constant, so we don't have to save the count */
+ assert(rep.File == TGSI_FILE_CONSTANT || rep.File == TGSI_FILE_IMMEDIATE);
+
+ ureg_MOV(ureg, ctr, imm);
+ ureg_BGNLOOP(ureg, label);
+ if (tx->native_integers)
+ {
+ ureg_USGE(ureg, tmp, tx_src_scalar(ctr), rep);
+#ifdef NINE_TGSI_LAZY_DEVS
+ ureg_UIF(ureg, tx_src_scalar(tmp), tx_cond(tx));
+#endif
+ }
+ else
+ {
+ ureg_SGE(ureg, tmp, tx_src_scalar(ctr), rep);
+#ifdef NINE_TGSI_LAZY_DEVS
+ ureg_IF(ureg, tx_src_scalar(tmp), tx_cond(tx));
+#endif
+ }
+#ifdef NINE_TGSI_LAZY_DEVS
+ ureg_BRK(ureg);
+ tx_endcond(tx);
+ ureg_ENDIF(ureg);
+#else
+ ureg_BREAKC(ureg, tx_src_scalar(tmp));
+#endif
+
+ if (tx->native_integers) {
+ ureg_UADD(ureg, ctr, tx_src_scalar(ctr), ureg_imm1u(ureg, 1));
+ } else {
+ ureg_ADD(ureg, ctr, tx_src_scalar(ctr), ureg_imm1f(ureg, 1.0f));
+ }
+
+ return D3D_OK;
+}
+
+DECL_SPECIAL(ENDREP)
+{
+ ureg_ENDLOOP(tx->ureg, tx_endloop(tx));
+ return D3D_OK;
+}
+
+DECL_SPECIAL(ENDIF)
+{
+ tx_endcond(tx);
+ ureg_ENDIF(tx->ureg);
+ return D3D_OK;
+}
+
+DECL_SPECIAL(IF)
+{
+ struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]);
+
+ if (tx->native_integers && tx->insn.src[0].file == D3DSPR_CONSTBOOL)
+ ureg_UIF(tx->ureg, src, tx_cond(tx));
+ else
+ ureg_IF(tx->ureg, src, tx_cond(tx));
+
+ return D3D_OK;
+}
+
+static INLINE unsigned
+sm1_insn_flags_to_tgsi_setop(BYTE flags)
+{
+ switch (flags) {
+ case NINED3DSHADER_REL_OP_GT: return TGSI_OPCODE_SGT;
+ case NINED3DSHADER_REL_OP_EQ: return TGSI_OPCODE_SEQ;
+ case NINED3DSHADER_REL_OP_GE: return TGSI_OPCODE_SGE;
+ case NINED3DSHADER_REL_OP_LT: return TGSI_OPCODE_SLT;
+ case NINED3DSHADER_REL_OP_NE: return TGSI_OPCODE_SNE;
+ case NINED3DSHADER_REL_OP_LE: return TGSI_OPCODE_SLE;
+ default:
+ assert(!"invalid comparison flags");
+ return TGSI_OPCODE_SFL;
+ }
+}
+
+DECL_SPECIAL(IFC)
+{
+ const unsigned cmp_op = sm1_insn_flags_to_tgsi_setop(tx->insn.flags);
+ struct ureg_src src[2];
+ struct ureg_dst tmp = ureg_writemask(tx_scratch(tx), TGSI_WRITEMASK_X);
+ src[0] = tx_src_param(tx, &tx->insn.src[0]);
+ src[1] = tx_src_param(tx, &tx->insn.src[1]);
+ ureg_insn(tx->ureg, cmp_op, &tmp, 1, src, 2);
+ ureg_IF(tx->ureg, ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), tx_cond(tx));
+ return D3D_OK;
+}
+
+DECL_SPECIAL(ELSE)
+{
+ ureg_ELSE(tx->ureg, tx_elsecond(tx));
+ return D3D_OK;
+}
+
+DECL_SPECIAL(BREAKC)
+{
+ const unsigned cmp_op = sm1_insn_flags_to_tgsi_setop(tx->insn.flags);
+ struct ureg_src src[2];
+ struct ureg_dst tmp = ureg_writemask(tx_scratch(tx), TGSI_WRITEMASK_X);
+ src[0] = tx_src_param(tx, &tx->insn.src[0]);
+ src[1] = tx_src_param(tx, &tx->insn.src[1]);
+ ureg_insn(tx->ureg, cmp_op, &tmp, 1, src, 2);
+#ifdef NINE_TGSI_LAZY_DEVS
+ ureg_IF(tx->ureg, ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), tx_cond(tx));
+ ureg_BRK(tx->ureg);
+ tx_endcond(tx);
+ ureg_ENDIF(tx->ureg);
+#else
+ ureg_BREAKC(tx->ureg, ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X));
+#endif
+ return D3D_OK;
+}
+
+static const char *sm1_declusage_names[] =
+{
+ [D3DDECLUSAGE_POSITION] = "POSITION",
+ [D3DDECLUSAGE_BLENDWEIGHT] = "BLENDWEIGHT",
+ [D3DDECLUSAGE_BLENDINDICES] = "BLENDINDICES",
+ [D3DDECLUSAGE_NORMAL] = "NORMAL",
+ [D3DDECLUSAGE_PSIZE] = "PSIZE",
+ [D3DDECLUSAGE_TEXCOORD] = "TEXCOORD",
+ [D3DDECLUSAGE_TANGENT] = "TANGENT",
+ [D3DDECLUSAGE_BINORMAL] = "BINORMAL",
+ [D3DDECLUSAGE_TESSFACTOR] = "TESSFACTOR",
+ [D3DDECLUSAGE_POSITIONT] = "POSITIONT",
+ [D3DDECLUSAGE_COLOR] = "COLOR",
+ [D3DDECLUSAGE_FOG] = "FOG",
+ [D3DDECLUSAGE_DEPTH] = "DEPTH",
+ [D3DDECLUSAGE_SAMPLE] = "SAMPLE"
+};
+
+static INLINE unsigned
+sm1_to_nine_declusage(struct sm1_semantic *dcl)
+{
+ return nine_d3d9_to_nine_declusage(dcl->usage, dcl->usage_idx);
+}
+
+static void
+sm1_declusage_to_tgsi(struct tgsi_declaration_semantic *sem,
+ boolean tc,
+ struct sm1_semantic *dcl)
+{
+ const unsigned generic_base = tc ? 0 : 8; /* TEXCOORD[0..7] */
+
+ sem->Name = TGSI_SEMANTIC_GENERIC;
+ sem->Index = 0;
+
+ /* TGSI_SEMANTIC_GENERIC assignments (+8 if !PIPE_CAP_TGSI_TEXCOORD):
+ * Try to put frequently used semantics at low GENERIC indices.
+ *
+ * POSITION[1..4]: 17, 27, 28, 29
+ * COLOR[2..4]: 14, 15, 26
+ * TEXCOORD[8..15]: 10, 11, 18, 19, 20, 21, 22, 23
+ * BLENDWEIGHT[0..3]: 0, 4, 8, 12
+ * BLENDINDICES[0..3]: 1, 5, 9, 13
+ * NORMAL[0..1]: 2, 6
+ * TANGENT[0]: 3, 24
+ * BINORMAL[0]: 7, 25
+ * TESSFACTOR[0]: 16
+ */
+
+ switch (dcl->usage) {
+ case D3DDECLUSAGE_POSITION:
+ case D3DDECLUSAGE_POSITIONT:
+ case D3DDECLUSAGE_DEPTH:
+ sem->Name = TGSI_SEMANTIC_POSITION;
+ assert(dcl->usage_idx <= 4);
+ if (dcl->usage_idx == 1) {
+ sem->Name = TGSI_SEMANTIC_GENERIC;
+ sem->Index = generic_base + 17;
+ } else
+ if (dcl->usage_idx >= 2) {
+ sem->Name = TGSI_SEMANTIC_GENERIC;
+ sem->Index = generic_base + 27 + (dcl->usage_idx - 2);
+ }
+ break;
+ case D3DDECLUSAGE_COLOR:
+ assert(dcl->usage_idx <= 4);
+ if (dcl->usage_idx < 2) {
+ sem->Name = TGSI_SEMANTIC_COLOR;
+ sem->Index = dcl->usage_idx;
+ } else
+ if (dcl->usage_idx < 4) {
+ sem->Index = generic_base + 14 + (dcl->usage_idx - 2);
+ } else {
+ sem->Index = generic_base + 26;
+ }
+ break;
+ case D3DDECLUSAGE_FOG:
+ sem->Name = TGSI_SEMANTIC_FOG;
+ assert(dcl->usage_idx == 0);
+ break;
+ case D3DDECLUSAGE_PSIZE:
+ sem->Name = TGSI_SEMANTIC_PSIZE;
+ assert(dcl->usage_idx == 0);
+ break;
+ case D3DDECLUSAGE_TEXCOORD:
+ assert(dcl->usage_idx < 16);
+ if (dcl->usage_idx < 8) {
+ if (tc)
+ sem->Name = TGSI_SEMANTIC_TEXCOORD;
+ sem->Index = dcl->usage_idx;
+ } else
+ if (dcl->usage_idx < 10) {
+ sem->Index = generic_base + 10 + (dcl->usage_idx - 8);
+ } else {
+ sem->Index = generic_base + 18 + (dcl->usage_idx - 10);
+ }
+ break;
+ case D3DDECLUSAGE_BLENDWEIGHT: /* 0, 4, 8, 12 */
+ assert(dcl->usage_idx < 4);
+ sem->Index = generic_base + dcl->usage_idx * 4;
+ break;
+ case D3DDECLUSAGE_BLENDINDICES: /* 1, 5, 9, 13 */
+ assert(dcl->usage_idx < 4);
+ sem->Index = generic_base + dcl->usage_idx * 4 + 1;
+ break;
+ case D3DDECLUSAGE_NORMAL: /* 2, 3 */
+ assert(dcl->usage_idx < 2);
+ sem->Index = generic_base + 2 + dcl->usage_idx * 4;
+ break;
+ case D3DDECLUSAGE_TANGENT:
+ /* Yes these are weird, but we try to fit the more frequently used
+ * into lower slots. */
+ assert(dcl->usage_idx <= 1);
+ sem->Index = generic_base + (dcl->usage_idx ? 24 : 3);
+ break;
+ case D3DDECLUSAGE_BINORMAL:
+ assert(dcl->usage_idx <= 1);
+ sem->Index = generic_base + (dcl->usage_idx ? 25 : 7);
+ break;
+ case D3DDECLUSAGE_TESSFACTOR:
+ assert(dcl->usage_idx == 0);
+ sem->Index = generic_base + 16;
+ break;
+ case D3DDECLUSAGE_SAMPLE:
+ sem->Name = TGSI_SEMANTIC_COUNT;
+ break;
+ default:
+ assert(!"Invalid DECLUSAGE.");
+ break;
+ }
+}
+
+#define NINED3DSTT_1D (D3DSTT_1D >> D3DSP_TEXTURETYPE_SHIFT)
+#define NINED3DSTT_2D (D3DSTT_2D >> D3DSP_TEXTURETYPE_SHIFT)
+#define NINED3DSTT_VOLUME (D3DSTT_VOLUME >> D3DSP_TEXTURETYPE_SHIFT)
+#define NINED3DSTT_CUBE (D3DSTT_CUBE >> D3DSP_TEXTURETYPE_SHIFT)
+static INLINE unsigned
+d3dstt_to_tgsi_tex(BYTE sampler_type)
+{
+ switch (sampler_type) {
+ case NINED3DSTT_1D: return TGSI_TEXTURE_1D;
+ case NINED3DSTT_2D: return TGSI_TEXTURE_2D;
+ case NINED3DSTT_VOLUME: return TGSI_TEXTURE_3D;
+ case NINED3DSTT_CUBE: return TGSI_TEXTURE_CUBE;
+ default:
+ assert(0);
+ return TGSI_TEXTURE_UNKNOWN;
+ }
+}
+static INLINE unsigned
+d3dstt_to_tgsi_tex_shadow(BYTE sampler_type)
+{
+ switch (sampler_type) {
+ case NINED3DSTT_1D: return TGSI_TEXTURE_SHADOW1D;
+ case NINED3DSTT_2D: return TGSI_TEXTURE_SHADOW2D;
+ case NINED3DSTT_VOLUME:
+ case NINED3DSTT_CUBE:
+ default:
+ assert(0);
+ return TGSI_TEXTURE_UNKNOWN;
+ }
+}
+static INLINE unsigned
+ps1x_sampler_type(const struct nine_shader_info *info, unsigned stage)
+{
+ switch ((info->sampler_ps1xtypes >> (stage * 2)) & 0x3) {
+ case 1: return TGSI_TEXTURE_1D;
+ case 0: return TGSI_TEXTURE_2D;
+ case 3: return TGSI_TEXTURE_3D;
+ default:
+ return TGSI_TEXTURE_CUBE;
+ }
+}
+
+static const char *
+sm1_sampler_type_name(BYTE sampler_type)
+{
+ switch (sampler_type) {
+ case NINED3DSTT_1D: return "1D";
+ case NINED3DSTT_2D: return "2D";
+ case NINED3DSTT_VOLUME: return "VOLUME";
+ case NINED3DSTT_CUBE: return "CUBE";
+ default:
+ return "(D3DSTT_?)";
+ }
+}
+
+static INLINE unsigned
+nine_tgsi_to_interp_mode(struct tgsi_declaration_semantic *sem)
+{
+ switch (sem->Name) {
+ case TGSI_SEMANTIC_POSITION:
+ case TGSI_SEMANTIC_NORMAL:
+ return TGSI_INTERPOLATE_LINEAR;
+ case TGSI_SEMANTIC_BCOLOR:
+ case TGSI_SEMANTIC_COLOR:
+ case TGSI_SEMANTIC_FOG:
+ case TGSI_SEMANTIC_GENERIC:
+ case TGSI_SEMANTIC_TEXCOORD:
+ case TGSI_SEMANTIC_CLIPDIST:
+ case TGSI_SEMANTIC_CLIPVERTEX:
+ return TGSI_INTERPOLATE_PERSPECTIVE;
+ case TGSI_SEMANTIC_EDGEFLAG:
+ case TGSI_SEMANTIC_FACE:
+ case TGSI_SEMANTIC_INSTANCEID:
+ case TGSI_SEMANTIC_PCOORD:
+ case TGSI_SEMANTIC_PRIMID:
+ case TGSI_SEMANTIC_PSIZE:
+ case TGSI_SEMANTIC_VERTEXID:
+ return TGSI_INTERPOLATE_CONSTANT;
+ default:
+ assert(0);
+ return TGSI_INTERPOLATE_CONSTANT;
+ }
+}
+
+DECL_SPECIAL(DCL)
+{
+ struct ureg_program *ureg = tx->ureg;
+ boolean is_input;
+ boolean is_sampler;
+ struct tgsi_declaration_semantic tgsi;
+ struct sm1_semantic sem;
+ sm1_read_semantic(tx, &sem);
+
+ is_input = sem.reg.file == D3DSPR_INPUT;
+ is_sampler =
+ sem.usage == D3DDECLUSAGE_SAMPLE || sem.reg.file == D3DSPR_SAMPLER;
+
+ DUMP("DCL ");
+ sm1_dump_dst_param(&sem.reg);
+ if (is_sampler)
+ DUMP(" %s\n", sm1_sampler_type_name(sem.sampler_type));
+ else
+ if (tx->version.major >= 3)
+ DUMP(" %s%i\n", sm1_declusage_names[sem.usage], sem.usage_idx);
+ else
+ if (sem.usage | sem.usage_idx)
+ DUMP(" %u[%u]\n", sem.usage, sem.usage_idx);
+ else
+ DUMP("\n");
+
+ if (is_sampler) {
+ const unsigned m = 1 << sem.reg.idx;
+ ureg_DECL_sampler(ureg, sem.reg.idx);
+ tx->info->sampler_mask |= m;
+ tx->sampler_targets[sem.reg.idx] = (tx->info->sampler_mask_shadow & m) ?
+ d3dstt_to_tgsi_tex_shadow(sem.sampler_type) :
+ d3dstt_to_tgsi_tex(sem.sampler_type);
+ return D3D_OK;
+ }
+
+ sm1_declusage_to_tgsi(&tgsi, tx->want_texcoord, &sem);
+ if (IS_VS) {
+ if (is_input) {
+ /* linkage outside of shader with vertex declaration */
+ ureg_DECL_vs_input(ureg, sem.reg.idx);
+ assert(sem.reg.idx < Elements(tx->info->input_map));
+ tx->info->input_map[sem.reg.idx] = sm1_to_nine_declusage(&sem);
+ tx->info->num_inputs = sem.reg.idx + 1;
+ /* NOTE: preserving order in case of indirect access */
+ } else
+ if (tx->version.major >= 3) {
+ /* SM2 output semantic determined by file */
+ assert(sem.reg.mask != 0);
+ if (sem.usage == D3DDECLUSAGE_POSITIONT)
+ tx->info->position_t = TRUE;
+ assert(sem.reg.idx < Elements(tx->regs.o));
+ tx->regs.o[sem.reg.idx] = ureg_DECL_output_masked(
+ ureg, tgsi.Name, tgsi.Index, sem.reg.mask);
+
+ if (tgsi.Name == TGSI_SEMANTIC_PSIZE)
+ tx->regs.oPts = tx->regs.o[sem.reg.idx];
+ }
+ } else {
+ if (is_input && tx->version.major >= 3) {
+ /* SM3 only, SM2 input semantic determined by file */
+ assert(sem.reg.idx < Elements(tx->regs.v));
+ tx->regs.v[sem.reg.idx] = ureg_DECL_fs_input_cyl_centroid(
+ ureg, tgsi.Name, tgsi.Index,
+ nine_tgsi_to_interp_mode(&tgsi),
+ 0, /* cylwrap */
+ sem.reg.mod & NINED3DSPDM_CENTROID);
+ } else
+ if (!is_input && 0) { /* declare in COLOROUT/DEPTHOUT case */
+ /* FragColor or FragDepth */
+ assert(sem.reg.mask != 0);
+ ureg_DECL_output_masked(ureg, tgsi.Name, tgsi.Index, sem.reg.mask);
+ }
+ }
+ return D3D_OK;
+}
+
+DECL_SPECIAL(DEF)
+{
+ tx_set_lconstf(tx, tx->insn.dst[0].idx, tx->insn.src[0].imm.f);
+ return D3D_OK;
+}
+
+DECL_SPECIAL(DEFB)
+{
+ tx_set_lconstb(tx, tx->insn.dst[0].idx, tx->insn.src[0].imm.b);
+ return D3D_OK;
+}
+
+DECL_SPECIAL(DEFI)
+{
+ tx_set_lconsti(tx, tx->insn.dst[0].idx, tx->insn.src[0].imm.i);
+ return D3D_OK;
+}
+
+DECL_SPECIAL(NRM)
+{
+ struct ureg_program *ureg = tx->ureg;
+ struct ureg_dst tmp = tx_scratch_scalar(tx);
+ struct ureg_src nrm = tx_src_scalar(tmp);
+ struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]);
+ ureg_DP3(ureg, tmp, src, src);
+ ureg_RSQ(ureg, tmp, nrm);
+ ureg_MUL(ureg, tx_dst_param(tx, &tx->insn.dst[0]), src, nrm);
+ return D3D_OK;
+}
+
+DECL_SPECIAL(DP2ADD)
+{
+#ifdef NINE_TGSI_LAZY_R600
+ struct ureg_dst tmp = tx_scratch_scalar(tx);
+ struct ureg_src dp2 = tx_src_scalar(tmp);
+ struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]);
+ struct ureg_src src[3];
+ int i;
+ for (i = 0; i < 3; ++i)
+ src[i] = tx_src_param(tx, &tx->insn.src[i]);
+ assert_replicate_swizzle(&src[2]);
+
+ ureg_DP2(tx->ureg, tmp, src[0], src[1]);
+ ureg_ADD(tx->ureg, dst, src[2], dp2);
+
+ return D3D_OK;
+#else
+ return NineTranslateInstruction_Generic(tx);
+#endif
+}
+
+DECL_SPECIAL(TEXCOORD)
+{
+ struct ureg_program *ureg = tx->ureg;
+ const unsigned s = tx->insn.dst[0].idx;
+ struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]);
+
+ if (ureg_src_is_undef(tx->regs.vT[s]))
+ tx->regs.vT[s] = ureg_DECL_fs_input(ureg, tx->texcoord_sn, s, TGSI_INTERPOLATE_PERSPECTIVE);
+ ureg_MOV(ureg, dst, tx->regs.vT[s]); /* XXX is this sufficient ? */
+
+ return D3D_OK;
+}
+
+DECL_SPECIAL(TEXCOORD_ps14)
+{
+ struct ureg_program *ureg = tx->ureg;
+ const unsigned s = tx->insn.src[0].idx;
+ struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]);
+
+ if (ureg_src_is_undef(tx->regs.vT[s]))
+ tx->regs.vT[s] = ureg_DECL_fs_input(ureg, tx->texcoord_sn, s, TGSI_INTERPOLATE_PERSPECTIVE);
+ ureg_MOV(ureg, dst, tx->regs.vT[s]); /* XXX is this sufficient ? */
+
+ return D3D_OK;
+}
+
+DECL_SPECIAL(TEXKILL)
+{
+ struct ureg_src reg;
+
+ if (tx->version.major > 1 || tx->version.minor > 3) {
+ reg = tx_dst_param_as_src(tx, &tx->insn.dst[0]);
+ } else {
+ tx_texcoord_alloc(tx, tx->insn.dst[0].idx);
+ reg = tx->regs.vT[tx->insn.dst[0].idx];
+ }
+ if (tx->version.major < 2)
+ reg = ureg_swizzle(reg, NINE_SWIZZLE4(X,Y,Z,Z));
+ ureg_KILL_IF(tx->ureg, reg);
+
+ return D3D_OK;
+}
+
+DECL_SPECIAL(TEXBEM)
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+DECL_SPECIAL(TEXBEML)
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+DECL_SPECIAL(TEXREG2AR)
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+DECL_SPECIAL(TEXREG2GB)
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+DECL_SPECIAL(TEXM3x2PAD)
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+DECL_SPECIAL(TEXM3x2TEX)
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+DECL_SPECIAL(TEXM3x3PAD)
+{
+ return D3D_OK; /* this is just padding */
+}
+
+DECL_SPECIAL(TEXM3x3SPEC)
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+DECL_SPECIAL(TEXM3x3VSPEC)
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+DECL_SPECIAL(TEXREG2RGB)
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+DECL_SPECIAL(TEXDP3TEX)
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+DECL_SPECIAL(TEXM3x2DEPTH)
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+DECL_SPECIAL(TEXDP3)
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+DECL_SPECIAL(TEXM3x3)
+{
+ struct ureg_program *ureg = tx->ureg;
+ struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]);
+ struct ureg_src src[4];
+ int s;
+ const int m = tx->insn.dst[0].idx - 2;
+ const int n = tx->insn.src[0].idx;
+ assert(m >= 0 && m > n);
+
+ for (s = m; s <= (m + 2); ++s) {
+ if (ureg_src_is_undef(tx->regs.vT[s]))
+ tx->regs.vT[s] = ureg_DECL_fs_input(ureg, tx->texcoord_sn, s, TGSI_INTERPOLATE_PERSPECTIVE);
+ src[s] = tx->regs.vT[s];
+ }
+ ureg_DP3(ureg, ureg_writemask(dst, TGSI_WRITEMASK_X), src[0], ureg_src(tx->regs.tS[n]));
+ ureg_DP3(ureg, ureg_writemask(dst, TGSI_WRITEMASK_Y), src[1], ureg_src(tx->regs.tS[n]));
+ ureg_DP3(ureg, ureg_writemask(dst, TGSI_WRITEMASK_Z), src[2], ureg_src(tx->regs.tS[n]));
+
+ switch (tx->insn.opcode) {
+ case D3DSIO_TEXM3x3:
+ ureg_MOV(ureg, ureg_writemask(dst, TGSI_WRITEMASK_W), ureg_imm1f(ureg, 1.0f));
+ break;
+ case D3DSIO_TEXM3x3TEX:
+ src[3] = ureg_DECL_sampler(ureg, m + 2);
+ tx->info->sampler_mask |= 1 << (m + 2);
+ ureg_TEX(ureg, dst, ps1x_sampler_type(tx->info, m + 2), ureg_src(dst), src[3]);
+ break;
+ default:
+ return D3DERR_INVALIDCALL;
+ }
+ return D3D_OK;
+}
+
+DECL_SPECIAL(TEXDEPTH)
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+DECL_SPECIAL(BEM)
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+DECL_SPECIAL(TEXLD)
+{
+ struct ureg_program *ureg = tx->ureg;
+ unsigned target;
+ struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]);
+ struct ureg_src src[2] = {
+ tx_src_param(tx, &tx->insn.src[0]),
+ tx_src_param(tx, &tx->insn.src[1])
+ };
+ assert(tx->insn.src[1].idx >= 0 &&
+ tx->insn.src[1].idx < Elements(tx->sampler_targets));
+ target = tx->sampler_targets[tx->insn.src[1].idx];
+
+ switch (tx->insn.flags) {
+ case 0:
+ ureg_TEX(ureg, dst, target, src[0], src[1]);
+ break;
+ case NINED3DSI_TEXLD_PROJECT:
+ ureg_TXP(ureg, dst, target, src[0], src[1]);
+ break;
+ case NINED3DSI_TEXLD_BIAS:
+ ureg_TXB(ureg, dst, target, src[0], src[1]);
+ break;
+ default:
+ assert(0);
+ return D3DERR_INVALIDCALL;
+ }
+ return D3D_OK;
+}
+
+DECL_SPECIAL(TEXLD_14)
+{
+ struct ureg_program *ureg = tx->ureg;
+ struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]);
+ struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]);
+ const unsigned s = tx->insn.dst[0].idx;
+ const unsigned t = ps1x_sampler_type(tx->info, s);
+
+ tx->info->sampler_mask |= 1 << s;
+ ureg_TEX(ureg, dst, t, src, ureg_DECL_sampler(ureg, s));
+
+ return D3D_OK;
+}
+
+DECL_SPECIAL(TEX)
+{
+ struct ureg_program *ureg = tx->ureg;
+ const unsigned s = tx->insn.dst[0].idx;
+ const unsigned t = ps1x_sampler_type(tx->info, s);
+ struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]);
+ struct ureg_src src[2];
+
+ if (ureg_src_is_undef(tx->regs.vT[s]))
+ tx->regs.vT[s] = ureg_DECL_fs_input(ureg, tx->texcoord_sn, s, TGSI_INTERPOLATE_PERSPECTIVE);
+
+ src[0] = tx->regs.vT[s];
+ src[1] = ureg_DECL_sampler(ureg, s);
+ tx->info->sampler_mask |= 1 << s;
+
+ ureg_TEX(ureg, dst, t, src[0], src[1]);
+
+ return D3D_OK;
+}
+
+DECL_SPECIAL(TEXLDD)
+{
+ unsigned target;
+ struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]);
+ struct ureg_src src[4] = {
+ tx_src_param(tx, &tx->insn.src[0]),
+ tx_src_param(tx, &tx->insn.src[1]),
+ tx_src_param(tx, &tx->insn.src[2]),
+ tx_src_param(tx, &tx->insn.src[3])
+ };
+ assert(tx->insn.src[3].idx >= 0 &&
+ tx->insn.src[3].idx < Elements(tx->sampler_targets));
+ target = tx->sampler_targets[tx->insn.src[1].idx];
+
+ ureg_TXD(tx->ureg, dst, target, src[0], src[2], src[3], src[1]);
+ return D3D_OK;
+}
+
+DECL_SPECIAL(TEXLDL)
+{
+ unsigned target;
+ struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]);
+ struct ureg_src src[2] = {
+ tx_src_param(tx, &tx->insn.src[0]),
+ tx_src_param(tx, &tx->insn.src[1])
+ };
+ assert(tx->insn.src[3].idx >= 0 &&
+ tx->insn.src[3].idx < Elements(tx->sampler_targets));
+ target = tx->sampler_targets[tx->insn.src[1].idx];
+
+ ureg_TXL(tx->ureg, dst, target, src[0], src[1]);
+ return D3D_OK;
+}
+
+DECL_SPECIAL(SETP)
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+DECL_SPECIAL(BREAKP)
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+DECL_SPECIAL(PHASE)
+{
+ return D3D_OK; /* we don't care about phase */
+}
+
+DECL_SPECIAL(COMMENT)
+{
+ return D3D_OK; /* nothing to do */
+}
+
+
+#define _OPI(o,t,vv1,vv2,pv1,pv2,d,s,h) \
+ { D3DSIO_##o, TGSI_OPCODE_##t, { vv1, vv2 }, { pv1, pv2, }, d, s, h }
+
+struct sm1_op_info inst_table[] =
+{
+ _OPI(NOP, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 0, 0, NULL), /* 0 */
+ _OPI(MOV, MOV, V(0,0), V(1,1), V(0,0), V(0,0), 1, 1, SPECIAL(MOV_vs1x)),
+ _OPI(MOV, MOV, V(2,0), V(3,0), V(0,0), V(3,0), 1, 1, NULL),
+ _OPI(ADD, ADD, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, NULL), /* 2 */
+ _OPI(SUB, SUB, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, NULL), /* 3 */
+ _OPI(MAD, MAD, V(0,0), V(3,0), V(0,0), V(3,0), 1, 3, NULL), /* 4 */
+ _OPI(MUL, MUL, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, NULL), /* 5 */
+ _OPI(RCP, RCP, V(0,0), V(3,0), V(0,0), V(3,0), 1, 1, NULL), /* 6 */
+ _OPI(RSQ, RSQ, V(0,0), V(3,0), V(0,0), V(3,0), 1, 1, NULL), /* 7 */
+ _OPI(DP3, DP3, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, NULL), /* 8 */
+ _OPI(DP4, DP4, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, NULL), /* 9 */
+ _OPI(MIN, MIN, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, NULL), /* 10 */
+ _OPI(MAX, MAX, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, NULL), /* 11 */
+ _OPI(SLT, SLT, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, NULL), /* 12 */
+ _OPI(SGE, SGE, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, NULL), /* 13 */
+ _OPI(EXP, EX2, V(0,0), V(3,0), V(0,0), V(3,0), 1, 1, NULL), /* 14 */
+ _OPI(LOG, LG2, V(0,0), V(3,0), V(0,0), V(3,0), 1, 1, NULL), /* 15 */
+ _OPI(LIT, LIT, V(0,0), V(3,0), V(0,0), V(0,0), 1, 1, NULL), /* 16 */
+ _OPI(DST, DST, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, NULL), /* 17 */
+ _OPI(LRP, LRP, V(0,0), V(3,0), V(0,0), V(3,0), 1, 3, NULL), /* 18 */
+ _OPI(FRC, FRC, V(0,0), V(3,0), V(0,0), V(3,0), 1, 1, NULL), /* 19 */
+
+ _OPI(M4x4, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, SPECIAL(M4x4)),
+ _OPI(M4x3, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, SPECIAL(M4x3)),
+ _OPI(M3x4, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, SPECIAL(M3x4)),
+ _OPI(M3x3, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, SPECIAL(M3x3)),
+ _OPI(M3x2, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, SPECIAL(M3x2)),
+
+ _OPI(CALL, CAL, V(2,0), V(3,0), V(2,1), V(3,0), 0, 0, SPECIAL(CALL)),
+ _OPI(CALLNZ, CAL, V(2,0), V(3,0), V(2,1), V(3,0), 0, 0, SPECIAL(CALLNZ)),
+ _OPI(LOOP, BGNLOOP, V(2,0), V(3,0), V(3,0), V(3,0), 0, 2, SPECIAL(LOOP)),
+ _OPI(RET, RET, V(2,0), V(3,0), V(2,1), V(3,0), 0, 0, SPECIAL(RET)),
+ _OPI(ENDLOOP, ENDLOOP, V(2,0), V(3,0), V(3,0), V(3,0), 0, 0, SPECIAL(ENDLOOP)),
+ _OPI(LABEL, NOP, V(2,0), V(3,0), V(2,1), V(3,0), 0, 0, SPECIAL(LABEL)),
+
+ _OPI(DCL, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 0, 0, SPECIAL(DCL)),
+
+ _OPI(POW, POW, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, NULL),
+ _OPI(CRS, XPD, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, NULL), /* XXX: .w */
+ _OPI(SGN, SSG, V(2,0), V(3,0), V(0,0), V(0,0), 1, 3, SPECIAL(SGN)), /* ignore src1,2 */
+ _OPI(ABS, ABS, V(0,0), V(3,0), V(0,0), V(3,0), 1, 1, NULL),
+ _OPI(NRM, NRM, V(0,0), V(3,0), V(0,0), V(3,0), 1, 1, SPECIAL(NRM)), /* NRM doesn't fit */
+
+ _OPI(SINCOS, SCS, V(2,0), V(2,1), V(2,0), V(2,1), 1, 3, SPECIAL(SINCOS)),
+ _OPI(SINCOS, SCS, V(3,0), V(3,0), V(3,0), V(3,0), 1, 1, SPECIAL(SINCOS)),
+
+ /* More flow control */
+ _OPI(REP, NOP, V(2,0), V(3,0), V(2,1), V(3,0), 0, 1, SPECIAL(REP)),
+ _OPI(ENDREP, NOP, V(2,0), V(3,0), V(2,1), V(3,0), 0, 0, SPECIAL(ENDREP)),
+ _OPI(IF, IF, V(2,0), V(3,0), V(2,1), V(3,0), 0, 1, SPECIAL(IF)),
+ _OPI(IFC, IF, V(2,1), V(3,0), V(2,1), V(3,0), 0, 2, SPECIAL(IFC)),
+ _OPI(ELSE, ELSE, V(2,0), V(3,0), V(2,1), V(3,0), 0, 0, SPECIAL(ELSE)),
+ _OPI(ENDIF, ENDIF, V(2,0), V(3,0), V(2,1), V(3,0), 0, 0, SPECIAL(ENDIF)),
+ _OPI(BREAK, BRK, V(2,1), V(3,0), V(2,1), V(3,0), 0, 0, NULL),
+ _OPI(BREAKC, BREAKC, V(2,1), V(3,0), V(2,1), V(3,0), 0, 2, SPECIAL(BREAKC)),
+
+ _OPI(MOVA, ARR, V(2,0), V(3,0), V(0,0), V(0,0), 1, 1, NULL),
+
+ _OPI(DEFB, NOP, V(0,0), V(3,0) , V(0,0), V(3,0) , 1, 0, SPECIAL(DEFB)),
+ _OPI(DEFI, NOP, V(0,0), V(3,0) , V(0,0), V(3,0) , 1, 0, SPECIAL(DEFI)),
+
+ _OPI(TEXCOORD, NOP, V(0,0), V(0,0), V(0,0), V(1,3), 1, 0, SPECIAL(TEXCOORD)),
+ _OPI(TEXCOORD, MOV, V(0,0), V(0,0), V(1,4), V(1,4), 1, 1, SPECIAL(TEXCOORD_ps14)),
+ _OPI(TEXKILL, KILL_IF, V(0,0), V(0,0), V(0,0), V(3,0), 1, 0, SPECIAL(TEXKILL)),
+ _OPI(TEX, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 1, 0, SPECIAL(TEX)),
+ _OPI(TEX, TEX, V(0,0), V(0,0), V(1,4), V(1,4), 1, 1, SPECIAL(TEXLD_14)),
+ _OPI(TEX, TEX, V(0,0), V(0,0), V(2,0), V(3,0), 1, 2, SPECIAL(TEXLD)),
+ _OPI(TEXBEM, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 0, 0, SPECIAL(TEXBEM)),
+ _OPI(TEXBEML, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 0, 0, SPECIAL(TEXBEML)),
+ _OPI(TEXREG2AR, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 0, 0, SPECIAL(TEXREG2AR)),
+ _OPI(TEXREG2GB, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 0, 0, SPECIAL(TEXREG2GB)),
+ _OPI(TEXM3x2PAD, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 0, 0, SPECIAL(TEXM3x2PAD)),
+ _OPI(TEXM3x2TEX, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 0, 0, SPECIAL(TEXM3x2TEX)),
+ _OPI(TEXM3x3PAD, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 0, 0, SPECIAL(TEXM3x3PAD)),
+ _OPI(TEXM3x3TEX, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 0, 0, SPECIAL(TEXM3x3)),
+ _OPI(TEXM3x3SPEC, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 0, 0, SPECIAL(TEXM3x3SPEC)),
+ _OPI(TEXM3x3VSPEC, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 0, 0, SPECIAL(TEXM3x3VSPEC)),
+
+ _OPI(EXPP, EXP, V(0,0), V(1,1), V(0,0), V(0,0), 1, 1, NULL),
+ _OPI(EXPP, EX2, V(2,0), V(3,0), V(0,0), V(0,0), 1, 1, NULL),
+ _OPI(LOGP, LG2, V(0,0), V(3,0), V(0,0), V(0,0), 1, 1, NULL),
+ _OPI(CND, CND, V(0,0), V(0,0), V(0,0), V(1,4), 1, 3, SPECIAL(CND)),
+
+ _OPI(DEF, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 1, 0, SPECIAL(DEF)),
+
+ /* More tex stuff */
+ _OPI(TEXREG2RGB, TEX, V(0,0), V(0,0), V(1,2), V(1,3), 0, 0, SPECIAL(TEXREG2RGB)),
+ _OPI(TEXDP3TEX, TEX, V(0,0), V(0,0), V(1,2), V(1,3), 0, 0, SPECIAL(TEXDP3TEX)),
+ _OPI(TEXM3x2DEPTH, TEX, V(0,0), V(0,0), V(1,3), V(1,3), 0, 0, SPECIAL(TEXM3x2DEPTH)),
+ _OPI(TEXDP3, TEX, V(0,0), V(0,0), V(1,2), V(1,3), 0, 0, SPECIAL(TEXDP3)),
+ _OPI(TEXM3x3, TEX, V(0,0), V(0,0), V(1,2), V(1,3), 0, 0, SPECIAL(TEXM3x3)),
+ _OPI(TEXDEPTH, TEX, V(0,0), V(0,0), V(1,4), V(1,4), 0, 0, SPECIAL(TEXDEPTH)),
+
+ /* Misc */
+ _OPI(CMP, CMP, V(0,0), V(0,0), V(1,2), V(3,0), 1, 3, SPECIAL(CMP)), /* reversed */
+ _OPI(BEM, NOP, V(0,0), V(0,0), V(1,4), V(1,4), 0, 0, SPECIAL(BEM)),
+ _OPI(DP2ADD, DP2A, V(0,0), V(0,0), V(2,0), V(3,0), 1, 3, SPECIAL(DP2ADD)), /* for radeons */
+ _OPI(DSX, DDX, V(0,0), V(0,0), V(2,1), V(3,0), 1, 1, NULL),
+ _OPI(DSY, DDY, V(0,0), V(0,0), V(2,1), V(3,0), 1, 1, NULL),
+ _OPI(TEXLDD, TXD, V(0,0), V(0,0), V(2,1), V(3,0), 1, 4, SPECIAL(TEXLDD)),
+ _OPI(SETP, NOP, V(0,0), V(3,0), V(2,1), V(3,0), 0, 0, SPECIAL(SETP)),
+ _OPI(TEXLDL, TXL, V(3,0), V(3,0), V(3,0), V(3,0), 1, 2, SPECIAL(TEXLDL)),
+ _OPI(BREAKP, BRK, V(0,0), V(3,0), V(2,1), V(3,0), 0, 0, SPECIAL(BREAKP))
+};
+
+struct sm1_op_info inst_phase =
+ _OPI(PHASE, NOP, V(0,0), V(0,0), V(1,4), V(1,4), 0, 0, SPECIAL(PHASE));
+
+struct sm1_op_info inst_comment =
+ _OPI(COMMENT, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 0, 0, SPECIAL(COMMENT));
+
+static void
+create_op_info_map(struct shader_translator *tx)
+{
+ const unsigned version = (tx->version.major << 8) | tx->version.minor;
+ unsigned i;
+
+ for (i = 0; i < Elements(tx->op_info_map); ++i)
+ tx->op_info_map[i] = -1;
+
+ if (tx->processor == TGSI_PROCESSOR_VERTEX) {
+ for (i = 0; i < Elements(inst_table); ++i) {
+ assert(inst_table[i].sio < Elements(tx->op_info_map));
+ if (inst_table[i].vert_version.min <= version &&
+ inst_table[i].vert_version.max >= version)
+ tx->op_info_map[inst_table[i].sio] = i;
+ }
+ } else {
+ for (i = 0; i < Elements(inst_table); ++i) {
+ assert(inst_table[i].sio < Elements(tx->op_info_map));
+ if (inst_table[i].frag_version.min <= version &&
+ inst_table[i].frag_version.max >= version)
+ tx->op_info_map[inst_table[i].sio] = i;
+ }
+ }
+}
+
+static INLINE HRESULT
+NineTranslateInstruction_Generic(struct shader_translator *tx)
+{
+ struct ureg_dst dst[1];
+ struct ureg_src src[4];
+ unsigned i;
+
+ for (i = 0; i < tx->insn.ndst && i < Elements(dst); ++i)
+ dst[i] = tx_dst_param(tx, &tx->insn.dst[i]);
+ for (i = 0; i < tx->insn.nsrc && i < Elements(src); ++i)
+ src[i] = tx_src_param(tx, &tx->insn.src[i]);
+
+ ureg_insn(tx->ureg, tx->insn.info->opcode,
+ dst, tx->insn.ndst,
+ src, tx->insn.nsrc);
+ return D3D_OK;
+}
+
+static INLINE DWORD
+TOKEN_PEEK(struct shader_translator *tx)
+{
+ return *(tx->parse);
+}
+
+static INLINE DWORD
+TOKEN_NEXT(struct shader_translator *tx)
+{
+ return *(tx->parse)++;
+}
+
+static INLINE void
+TOKEN_JUMP(struct shader_translator *tx)
+{
+ if (tx->parse_next && tx->parse != tx->parse_next) {
+ WARN("parse(%p) != parse_next(%p) !\n", tx->parse, tx->parse_next);
+ tx->parse = tx->parse_next;
+ }
+}
+
+static INLINE boolean
+sm1_parse_eof(struct shader_translator *tx)
+{
+ return TOKEN_PEEK(tx) == NINED3DSP_END;
+}
+
+static void
+sm1_read_version(struct shader_translator *tx)
+{
+ const DWORD tok = TOKEN_NEXT(tx);
+
+ tx->version.major = D3DSHADER_VERSION_MAJOR(tok);
+ tx->version.minor = D3DSHADER_VERSION_MINOR(tok);
+
+ switch (tok >> 16) {
+ case NINED3D_SM1_VS: tx->processor = TGSI_PROCESSOR_VERTEX; break;
+ case NINED3D_SM1_PS: tx->processor = TGSI_PROCESSOR_FRAGMENT; break;
+ default:
+ DBG("Invalid shader type: %x\n", tok);
+ tx->processor = ~0;
+ break;
+ }
+}
+
+/* This is just to check if we parsed the instruction properly. */
+static void
+sm1_parse_get_skip(struct shader_translator *tx)
+{
+ const DWORD tok = TOKEN_PEEK(tx);
+
+ if (tx->version.major >= 2) {
+ tx->parse_next = tx->parse + 1 /* this */ +
+ ((tok & D3DSI_INSTLENGTH_MASK) >> D3DSI_INSTLENGTH_SHIFT);
+ } else {
+ tx->parse_next = NULL; /* TODO: determine from param count */
+ }
+}
+
+static void
+sm1_print_comment(const char *comment, UINT size)
+{
+ if (!size)
+ return;
+ /* TODO */
+}
+
+static void
+sm1_parse_comments(struct shader_translator *tx, BOOL print)
+{
+ DWORD tok = TOKEN_PEEK(tx);
+
+ while ((tok & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT)
+ {
+ const char *comment = "";
+ UINT size = (tok & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
+ tx->parse += size + 1;
+
+ if (print)
+ sm1_print_comment(comment, size);
+
+ tok = TOKEN_PEEK(tx);
+ }
+}
+
+static void
+sm1_parse_get_param(struct shader_translator *tx, DWORD *reg, DWORD *rel)
+{
+ *reg = TOKEN_NEXT(tx);
+
+ if (*reg & D3DSHADER_ADDRMODE_RELATIVE)
+ {
+ if (tx->version.major < 2)
+ *rel = (1 << 31) |
+ ((D3DSPR_ADDR << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2) |
+ ((D3DSPR_ADDR << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK) |
+ (D3DSP_NOSWIZZLE << D3DSP_SWIZZLE_SHIFT);
+ else
+ *rel = TOKEN_NEXT(tx);
+ }
+}
+
+static void
+sm1_parse_dst_param(struct sm1_dst_param *dst, DWORD tok)
+{
+ dst->file =
+ (tok & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT |
+ (tok & D3DSP_REGTYPE_MASK2) >> D3DSP_REGTYPE_SHIFT2;
+ dst->type = TGSI_RETURN_TYPE_FLOAT;
+ dst->idx = tok & D3DSP_REGNUM_MASK;
+ dst->rel = NULL;
+ dst->mask = (tok & NINED3DSP_WRITEMASK_MASK) >> NINED3DSP_WRITEMASK_SHIFT;
+ dst->mod = (tok & D3DSP_DSTMOD_MASK) >> D3DSP_DSTMOD_SHIFT;
+ dst->shift = (tok & D3DSP_DSTSHIFT_MASK) >> D3DSP_DSTSHIFT_SHIFT;
+}
+
+static void
+sm1_parse_src_param(struct sm1_src_param *src, DWORD tok)
+{
+ src->file =
+ ((tok & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT) |
+ ((tok & D3DSP_REGTYPE_MASK2) >> D3DSP_REGTYPE_SHIFT2);
+ src->type = TGSI_RETURN_TYPE_FLOAT;
+ src->idx = tok & D3DSP_REGNUM_MASK;
+ src->rel = NULL;
+ src->swizzle = (tok & D3DSP_SWIZZLE_MASK) >> D3DSP_SWIZZLE_SHIFT;
+ src->mod = (tok & D3DSP_SRCMOD_MASK) >> D3DSP_SRCMOD_SHIFT;
+
+ switch (src->file) {
+ case D3DSPR_CONST2: src->file = D3DSPR_CONST; src->idx += 2048; break;
+ case D3DSPR_CONST3: src->file = D3DSPR_CONST; src->idx += 4096; break;
+ case D3DSPR_CONST4: src->file = D3DSPR_CONST; src->idx += 6144; break;
+ default:
+ break;
+ }
+}
+
+static void
+sm1_parse_immediate(struct shader_translator *tx,
+ struct sm1_src_param *imm)
+{
+ imm->file = NINED3DSPR_IMMEDIATE;
+ imm->idx = INT_MIN;
+ imm->rel = NULL;
+ imm->swizzle = NINED3DSP_NOSWIZZLE;
+ imm->mod = 0;
+ switch (tx->insn.opcode) {
+ case D3DSIO_DEF:
+ imm->type = NINED3DSPTYPE_FLOAT4;
+ memcpy(&imm->imm.d[0], tx->parse, 4 * sizeof(DWORD));
+ tx->parse += 4;
+ break;
+ case D3DSIO_DEFI:
+ imm->type = NINED3DSPTYPE_INT4;
+ memcpy(&imm->imm.d[0], tx->parse, 4 * sizeof(DWORD));
+ tx->parse += 4;
+ break;
+ case D3DSIO_DEFB:
+ imm->type = NINED3DSPTYPE_BOOL;
+ memcpy(&imm->imm.d[0], tx->parse, 1 * sizeof(DWORD));
+ tx->parse += 1;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+}
+
+static void
+sm1_read_dst_param(struct shader_translator *tx,
+ struct sm1_dst_param *dst,
+ struct sm1_src_param *rel)
+{
+ DWORD tok_dst, tok_rel = 0;
+
+ sm1_parse_get_param(tx, &tok_dst, &tok_rel);
+ sm1_parse_dst_param(dst, tok_dst);
+ if (tok_dst & D3DSHADER_ADDRMODE_RELATIVE) {
+ sm1_parse_src_param(rel, tok_rel);
+ dst->rel = rel;
+ }
+}
+
+static void
+sm1_read_src_param(struct shader_translator *tx,
+ struct sm1_src_param *src,
+ struct sm1_src_param *rel)
+{
+ DWORD tok_src, tok_rel = 0;
+
+ sm1_parse_get_param(tx, &tok_src, &tok_rel);
+ sm1_parse_src_param(src, tok_src);
+ if (tok_src & D3DSHADER_ADDRMODE_RELATIVE) {
+ assert(rel);
+ sm1_parse_src_param(rel, tok_rel);
+ src->rel = rel;
+ }
+}
+
+static void
+sm1_read_semantic(struct shader_translator *tx,
+ struct sm1_semantic *sem)
+{
+ const DWORD tok_usg = TOKEN_NEXT(tx);
+ const DWORD tok_dst = TOKEN_NEXT(tx);
+
+ sem->sampler_type = (tok_usg & D3DSP_TEXTURETYPE_MASK) >> D3DSP_TEXTURETYPE_SHIFT;
+ sem->usage = (tok_usg & D3DSP_DCL_USAGE_MASK) >> D3DSP_DCL_USAGE_SHIFT;
+ sem->usage_idx = (tok_usg & D3DSP_DCL_USAGEINDEX_MASK) >> D3DSP_DCL_USAGEINDEX_SHIFT;
+
+ sm1_parse_dst_param(&sem->reg, tok_dst);
+}
+
+static void
+sm1_parse_instruction(struct shader_translator *tx)
+{
+ struct sm1_instruction *insn = &tx->insn;
+ DWORD tok;
+ struct sm1_op_info *info = NULL;
+ unsigned i;
+
+ sm1_parse_comments(tx, TRUE);
+ sm1_parse_get_skip(tx);
+
+ tok = TOKEN_NEXT(tx);
+
+ insn->opcode = tok & D3DSI_OPCODE_MASK;
+ insn->flags = (tok & NINED3DSIO_OPCODE_FLAGS_MASK) >> NINED3DSIO_OPCODE_FLAGS_SHIFT;
+ insn->coissue = !!(tok & D3DSI_COISSUE);
+ insn->predicated = !!(tok & NINED3DSHADER_INST_PREDICATED);
+
+ if (insn->opcode < Elements(tx->op_info_map)) {
+ int k = tx->op_info_map[insn->opcode];
+ if (k >= 0) {
+ assert(k < Elements(inst_table));
+ info = &inst_table[k];
+ }
+ } else {
+ if (insn->opcode == D3DSIO_PHASE) info = &inst_phase;
+ if (insn->opcode == D3DSIO_COMMENT) info = &inst_comment;
+ }
+ if (!info) {
+ DBG("illegal or unhandled opcode: %08x\n", insn->opcode);
+ TOKEN_JUMP(tx);
+ return;
+ }
+ insn->info = info;
+ insn->ndst = info->ndst;
+ insn->nsrc = info->nsrc;
+
+ assert(!insn->predicated && "TODO: predicated instructions");
+
+ /* check version */
+ {
+ unsigned min = IS_VS ? info->vert_version.min : info->frag_version.min;
+ unsigned max = IS_VS ? info->vert_version.max : info->frag_version.max;
+ unsigned ver = (tx->version.major << 8) | tx->version.minor;
+ if (ver < min || ver > max) {
+ DBG("opcode not supported in this shader version: %x <= %x <= %x\n",
+ min, ver, max);
+ return;
+ }
+ }
+
+ for (i = 0; i < insn->ndst; ++i)
+ sm1_read_dst_param(tx, &insn->dst[i], &insn->dst_rel[i]);
+ if (insn->predicated)
+ sm1_read_src_param(tx, &insn->pred, NULL);
+ for (i = 0; i < insn->nsrc; ++i)
+ sm1_read_src_param(tx, &insn->src[i], &insn->src_rel[i]);
+
+ /* parse here so we can dump them before processing */
+ if (insn->opcode == D3DSIO_DEF ||
+ insn->opcode == D3DSIO_DEFI ||
+ insn->opcode == D3DSIO_DEFB)
+ sm1_parse_immediate(tx, &tx->insn.src[0]);
+
+ sm1_dump_instruction(insn, tx->cond_depth + tx->loop_depth);
+ sm1_instruction_check(insn);
+
+ if (info->handler)
+ info->handler(tx);
+ else
+ NineTranslateInstruction_Generic(tx);
+ tx_apply_dst0_modifiers(tx);
+
+ tx->num_scratch = 0; /* reset */
+
+ TOKEN_JUMP(tx);
+}
+
+static void
+tx_ctor(struct shader_translator *tx, struct nine_shader_info *info)
+{
+ unsigned i;
+
+ tx->info = info;
+
+ tx->byte_code = info->byte_code;
+ tx->parse = info->byte_code;
+
+ for (i = 0; i < Elements(info->input_map); ++i)
+ info->input_map[i] = NINE_DECLUSAGE_NONE;
+ info->num_inputs = 0;
+
+ info->position_t = FALSE;
+ info->point_size = FALSE;
+
+ tx->info->const_used_size = 0;
+
+ info->sampler_mask = 0x0;
+ info->rt_mask = 0x0;
+
+ info->lconstf.data = NULL;
+ info->lconstf.ranges = NULL;
+
+ for (i = 0; i < Elements(tx->regs.aL); ++i) {
+ tx->regs.aL[i] = ureg_dst_undef();
+ tx->regs.rL[i] = ureg_dst_undef();
+ }
+ tx->regs.a = ureg_dst_undef();
+ tx->regs.p = ureg_dst_undef();
+ tx->regs.oDepth = ureg_dst_undef();
+ tx->regs.vPos = ureg_src_undef();
+ tx->regs.vFace = ureg_src_undef();
+ for (i = 0; i < Elements(tx->regs.o); ++i)
+ tx->regs.o[i] = ureg_dst_undef();
+ for (i = 0; i < Elements(tx->regs.oCol); ++i)
+ tx->regs.oCol[i] = ureg_dst_undef();
+ for (i = 0; i < Elements(tx->regs.vC); ++i)
+ tx->regs.vC[i] = ureg_src_undef();
+ for (i = 0; i < Elements(tx->regs.vT); ++i)
+ tx->regs.vT[i] = ureg_src_undef();
+
+ for (i = 0; i < Elements(tx->lconsti); ++i)
+ tx->lconsti[i].idx = -1;
+ for (i = 0; i < Elements(tx->lconstb); ++i)
+ tx->lconstb[i].idx = -1;
+
+ sm1_read_version(tx);
+
+ info->version = (tx->version.major << 4) | tx->version.minor;
+
+ create_op_info_map(tx);
+}
+
+static void
+tx_dtor(struct shader_translator *tx)
+{
+ if (tx->num_inst_labels)
+ FREE(tx->inst_labels);
+ if (tx->lconstf)
+ FREE(tx->lconstf);
+ if (tx->regs.r)
+ FREE(tx->regs.r);
+ FREE(tx);
+}
+
+static INLINE unsigned
+tgsi_processor_from_type(unsigned shader_type)
+{
+ switch (shader_type) {
+ case PIPE_SHADER_VERTEX: return TGSI_PROCESSOR_VERTEX;
+ case PIPE_SHADER_FRAGMENT: return TGSI_PROCESSOR_FRAGMENT;
+ default:
+ return ~0;
+ }
+}
+
+#define GET_CAP(n) device->screen->get_param( \
+ device->screen, PIPE_CAP_##n)
+#define GET_SHADER_CAP(n) device->screen->get_shader_param( \
+ device->screen, info->type, PIPE_SHADER_CAP_##n)
+
+HRESULT
+nine_translate_shader(struct NineDevice9 *device, struct nine_shader_info *info)
+{
+ struct shader_translator *tx;
+ HRESULT hr = D3D_OK;
+ const unsigned processor = tgsi_processor_from_type(info->type);
+
+ user_assert(processor != ~0, D3DERR_INVALIDCALL);
+
+ tx = CALLOC_STRUCT(shader_translator);
+ if (!tx)
+ return E_OUTOFMEMORY;
+ tx_ctor(tx, info);
+
+ if (((tx->version.major << 16) | tx->version.minor) > 0x00030000) {
+ hr = D3DERR_INVALIDCALL;
+ DBG("Unsupported shader version: %u.%u !\n",
+ tx->version.major, tx->version.minor);
+ goto out;
+ }
+ if (tx->processor != processor) {
+ hr = D3DERR_INVALIDCALL;
+ DBG("Shader type mismatch: %u / %u !\n", tx->processor, processor);
+ goto out;
+ }
+ DUMP("%s%u.%u\n", processor == TGSI_PROCESSOR_VERTEX ? "VS" : "PS",
+ tx->version.major, tx->version.minor);
+
+ tx->ureg = ureg_create(processor);
+ if (!tx->ureg) {
+ hr = E_OUTOFMEMORY;
+ goto out;
+ }
+ tx_decl_constants(tx);
+
+ tx->native_integers = GET_SHADER_CAP(INTEGERS);
+ tx->inline_subroutines = !GET_SHADER_CAP(SUBROUTINES);
+ tx->lower_preds = !GET_SHADER_CAP(MAX_PREDS);
+ tx->want_texcoord = GET_CAP(TGSI_TEXCOORD);
+ tx->shift_wpos = !GET_CAP(TGSI_FS_COORD_PIXEL_CENTER_INTEGER);
+ tx->texcoord_sn = tx->want_texcoord ?
+ TGSI_SEMANTIC_TEXCOORD : TGSI_SEMANTIC_GENERIC;
+
+ /* VS must always write position. Declare it here to make it the 1st output.
+ * (Some drivers like nv50 are buggy and rely on that.)
+ */
+ if (IS_VS) {
+ tx->regs.oPos = ureg_DECL_output(tx->ureg, TGSI_SEMANTIC_POSITION, 0);
+ } else {
+ ureg_property(tx->ureg, TGSI_PROPERTY_FS_COORD_ORIGIN, TGSI_FS_COORD_ORIGIN_UPPER_LEFT);
+ if (!tx->shift_wpos)
+ ureg_property(tx->ureg, TGSI_PROPERTY_FS_COORD_PIXEL_CENTER, TGSI_FS_COORD_PIXEL_CENTER_INTEGER);
+ }
+
+ if (!ureg_dst_is_undef(tx->regs.oPts))
+ info->point_size = TRUE;
+
+ while (!sm1_parse_eof(tx))
+ sm1_parse_instruction(tx);
+ tx->parse++; /* for byte_size */
+
+ if (IS_PS && (tx->version.major < 2) && tx->num_temp) {
+ ureg_MOV(tx->ureg, ureg_DECL_output(tx->ureg, TGSI_SEMANTIC_COLOR, 0),
+ ureg_src(tx->regs.r[0]));
+ info->rt_mask |= 0x1;
+ }
+
+ if (info->position_t)
+ ureg_property(tx->ureg, TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION, TRUE);
+
+ ureg_END(tx->ureg);
+
+ if (debug_get_bool_option("NINE_TGSI_DUMP", FALSE)) {
+ unsigned count;
+ const struct tgsi_token *toks = ureg_get_tokens(tx->ureg, &count);
+ tgsi_dump(toks, 0);
+ ureg_free_tokens(toks);
+ }
+
+ /* record local constants */
+ if (tx->num_lconstf && tx->indirect_const_access) {
+ struct nine_range *ranges;
+ float *data;
+ int *indices;
+ unsigned i, k, n;
+
+ hr = E_OUTOFMEMORY;
+
+ data = MALLOC(tx->num_lconstf * 4 * sizeof(float));
+ if (!data)
+ goto out;
+ info->lconstf.data = data;
+
+ indices = MALLOC(tx->num_lconstf * sizeof(indices[0]));
+ if (!indices)
+ goto out;
+
+ /* lazy sort, num_lconstf should be small */
+ for (n = 0; n < tx->num_lconstf; ++n) {
+ for (k = 0, i = 0; i < tx->num_lconstf; ++i) {
+ if (tx->lconstf[i].idx < tx->lconstf[k].idx)
+ k = i;
+ }
+ indices[n] = tx->lconstf[k].idx;
+ memcpy(&data[n * 4], &tx->lconstf[k].imm.f[0], 4 * sizeof(float));
+ tx->lconstf[k].idx = INT_MAX;
+ }
+
+ /* count ranges */
+ for (n = 1, i = 1; i < tx->num_lconstf; ++i)
+ if (indices[i] != indices[i - 1] + 1)
+ ++n;
+ ranges = MALLOC(n * sizeof(ranges[0]));
+ if (!ranges) {
+ FREE(indices);
+ goto out;
+ }
+ info->lconstf.ranges = ranges;
+
+ k = 0;
+ ranges[k].bgn = indices[0];
+ for (i = 1; i < tx->num_lconstf; ++i) {
+ if (indices[i] != indices[i - 1] + 1) {
+ ranges[k].next = &ranges[k + 1];
+ ranges[k].end = indices[i - 1] + 1;
+ ++k;
+ ranges[k].bgn = indices[i];
+ }
+ }
+ ranges[k].end = indices[i - 1] + 1;
+ ranges[k].next = NULL;
+ assert(n == (k + 1));
+
+ FREE(indices);
+ hr = D3D_OK;
+ }
+
+ if (tx->indirect_const_access)
+ info->const_used_size = ~0;
+
+ info->cso = ureg_create_shader_and_destroy(tx->ureg, device->pipe);
+ if (!info->cso) {
+ hr = D3DERR_DRIVERINTERNALERROR;
+ FREE(info->lconstf.data);
+ FREE(info->lconstf.ranges);
+ goto out;
+ }
+
+ info->byte_size = (tx->parse - tx->byte_code) * sizeof(DWORD);
+out:
+ tx_dtor(tx);
+ return hr;
+}
diff --git a/src/gallium/state_trackers/nine/nine_shader.h b/src/gallium/state_trackers/nine/nine_shader.h
new file mode 100644
index 00000000000..21824086490
--- /dev/null
+++ b/src/gallium/state_trackers/nine/nine_shader.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _NINE_SHADER_H_
+#define _NINE_SHADER_H_
+
+#include "d3d9types.h"
+#include "d3d9caps.h"
+#include "nine_defines.h"
+#include "pipe/p_state.h" /* PIPE_MAX_ATTRIBS */
+#include "util/u_memory.h"
+
+struct NineDevice9;
+
+struct nine_lconstf /* NOTE: both pointers should be FREE'd by the user */
+{
+ struct nine_range *ranges; /* single MALLOC, but next-pointers valid */
+ float *data;
+};
+
+struct nine_shader_info
+{
+ unsigned type; /* in, PIPE_SHADER_x */
+
+ uint8_t version; /* (major << 4) | minor */
+
+ const DWORD *byte_code; /* in, pointer to shader tokens */
+ DWORD byte_size; /* out, size of data at byte_code */
+
+ void *cso; /* out, pipe cso for bind_vs,fs_state */
+
+ uint8_t input_map[PIPE_MAX_ATTRIBS]; /* VS input -> NINE_DECLUSAGE_x */
+ uint8_t num_inputs; /* there may be unused inputs (NINE_DECLUSAGE_NONE) */
+
+ boolean position_t; /* out, true if VP writes pre-transformed position */
+ boolean point_size; /* out, true if VP writes point size */
+
+ uint32_t sampler_ps1xtypes; /* 2 bits per sampler */
+ uint16_t sampler_mask; /* out, which samplers are being used */
+ uint16_t sampler_mask_shadow; /* in, which samplers use depth compare */
+ uint8_t rt_mask; /* out, which render targets are being written */
+
+ unsigned const_i_base; /* in vec4 (16 byte) units */
+ unsigned const_b_base; /* in vec4 (16 byte) units */
+ unsigned const_used_size;
+
+ struct nine_lconstf lconstf; /* out, NOTE: members to be free'd by user */
+};
+
+static INLINE void
+nine_info_mark_const_f_used(struct nine_shader_info *info, int idx)
+{
+ unsigned size = (idx + 1) * 16;
+
+ if (info->const_used_size < size)
+ info->const_used_size = size;
+}
+static INLINE void
+nine_info_mark_const_i_used(struct nine_shader_info *info, int idx)
+{
+ unsigned size = (info->const_i_base + (idx + 1)) * 16;
+
+ if (info->const_used_size < size)
+ info->const_used_size = size;
+}
+static INLINE void
+nine_info_mark_const_b_used(struct nine_shader_info *info, int idx)
+{
+ unsigned size = (info->const_b_base + ((idx + 4) / 4)) * 16;
+
+ if (info->const_used_size < size)
+ info->const_used_size = size;
+}
+
+HRESULT
+nine_translate_shader(struct NineDevice9 *device, struct nine_shader_info *);
+
+
+struct nine_shader_variant
+{
+ struct nine_shader_variant *next;
+ void *cso;
+ uint32_t key;
+};
+
+static INLINE void *
+nine_shader_variant_get(struct nine_shader_variant *list, uint32_t key)
+{
+ while (list->key != key && list->next)
+ list = list->next;
+ if (list->key == key)
+ return list->cso;
+ return NULL;
+}
+
+static INLINE boolean
+nine_shader_variant_add(struct nine_shader_variant *list,
+ uint32_t key, void *cso)
+{
+ while (list->next) {
+ assert(list->key != key);
+ list = list->next;
+ }
+ list->next = MALLOC_STRUCT(nine_shader_variant);
+ if (!list->next)
+ return FALSE;
+ list->next->next = NULL;
+ list->next->key = key;
+ list->next->cso = cso;
+ return TRUE;
+}
+
+static INLINE void
+nine_shader_variants_free(struct nine_shader_variant *list)
+{
+ while (list->next) {
+ struct nine_shader_variant *ptr = list->next;
+ list->next = ptr->next;
+ FREE(ptr);
+ }
+}
+
+#endif /* _NINE_SHADER_H_ */
diff --git a/src/gallium/state_trackers/nine/nine_state.c b/src/gallium/state_trackers/nine/nine_state.c
new file mode 100644
index 00000000000..0215d080808
--- /dev/null
+++ b/src/gallium/state_trackers/nine/nine_state.c
@@ -0,0 +1,1489 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ * Copyright 2013 Christoph Bumiller
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "device9.h"
+#include "basetexture9.h"
+#include "indexbuffer9.h"
+#include "surface9.h"
+#include "vertexdeclaration9.h"
+#include "vertexshader9.h"
+#include "pixelshader9.h"
+#include "nine_pipe.h"
+#include "nine_ff.h"
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "cso_cache/cso_context.h"
+#include "util/u_math.h"
+
+#define DBG_CHANNEL DBG_DEVICE
+
+static uint32_t
+update_framebuffer(struct NineDevice9 *device)
+{
+ struct pipe_context *pipe = device->pipe;
+ struct nine_state *state = &device->state;
+ struct pipe_framebuffer_state *fb = &device->state.fb;
+ unsigned i;
+ unsigned w = 0, h = 0; /* no surface can have width or height 0 */
+
+ const int sRGB = state->rs[D3DRS_SRGBWRITEENABLE] ? 1 : 0;
+
+ DBG("\n");
+
+ state->rt_mask = 0x0;
+ fb->nr_cbufs = 0;
+
+ for (i = 0; i < device->caps.NumSimultaneousRTs; ++i) {
+ if (state->rt[i] && state->rt[i]->desc.Format != D3DFMT_NULL) {
+ struct NineSurface9 *rt = state->rt[i];
+ fb->cbufs[i] = NineSurface9_GetSurface(rt, sRGB);
+ state->rt_mask |= 1 << i;
+ fb->nr_cbufs = i + 1;
+ if (w) {
+ w = MIN2(w, rt->desc.Width);
+ h = MIN2(h, rt->desc.Height);
+ } else {
+ w = rt->desc.Width;
+ h = rt->desc.Height;
+ }
+ if (unlikely(rt->desc.Usage & D3DUSAGE_AUTOGENMIPMAP)) {
+ assert(rt->texture == D3DRTYPE_TEXTURE ||
+ rt->texture == D3DRTYPE_CUBETEXTURE);
+ NineBaseTexture9(rt->base.base.container)->dirty_mip = TRUE;
+ }
+ } else {
+ /* Color outputs must match RT slot,
+ * drivers will have to handle NULL entries for GL, too.
+ */
+ fb->cbufs[i] = NULL;
+ }
+ }
+
+ if (state->ds) {
+ fb->zsbuf = NineSurface9_GetSurface(state->ds, 0);
+ if (w) {
+ w = MIN2(w, state->ds->desc.Width);
+ h = MIN2(h, state->ds->desc.Height);
+ } else {
+ w = state->ds->desc.Width;
+ h = state->ds->desc.Height;
+ }
+ } else {
+ fb->zsbuf = NULL;
+ }
+
+ fb->width = w;
+ fb->height = h;
+
+ pipe->set_framebuffer_state(pipe, fb); /* XXX: cso ? */
+
+ if (fb->zsbuf) {
+ DWORD scale;
+ switch (fb->zsbuf->format) {
+ case PIPE_FORMAT_Z32_FLOAT:
+ case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
+ scale = fui(1.0f);
+ break;
+ case PIPE_FORMAT_Z16_UNORM:
+ scale = fui((float)(1 << 16));
+ break;
+ default:
+ scale = fui((float)(1 << 24));
+ break;
+ }
+ if (state->rs[NINED3DRS_ZBIASSCALE] != scale) {
+ state->rs[NINED3DRS_ZBIASSCALE] = scale;
+ state->changed.group |= NINE_STATE_RASTERIZER;
+ }
+ }
+
+#ifdef DEBUG
+ if (state->rt_mask & (state->ps ? ~state->ps->rt_mask : 0))
+ WARN_ONCE("FIXME: writing undefined values to cbufs 0x%x\n",
+ state->rt_mask & ~state->ps->rt_mask);
+#endif
+
+ return state->changed.group;
+}
+
+static void
+update_viewport(struct NineDevice9 *device)
+{
+ struct pipe_context *pipe = device->pipe;
+ const D3DVIEWPORT9 *vport = &device->state.viewport;
+ struct pipe_viewport_state pvport;
+
+ /* XXX:
+ * I hope D3D clip coordinates are still
+ * -1 .. +1 for X,Y and
+ * 0 .. +1 for Z (use pipe_rasterizer_state.clip_halfz)
+ */
+ pvport.scale[0] = (float)vport->Width * 0.5f;
+ pvport.scale[1] = (float)vport->Height * -0.5f;
+ pvport.scale[2] = vport->MaxZ - vport->MinZ;
+ pvport.scale[3] = 1.0f;
+ pvport.translate[0] = (float)vport->Width * 0.5f + (float)vport->X;
+ pvport.translate[1] = (float)vport->Height * 0.5f + (float)vport->Y;
+ pvport.translate[2] = vport->MinZ;
+ pvport.translate[3] = 0.0f;
+
+ pipe->set_viewport_states(pipe, 0, 1, &pvport);
+}
+
+static INLINE void
+update_scissor(struct NineDevice9 *device)
+{
+ struct pipe_context *pipe = device->pipe;
+
+ pipe->set_scissor_states(pipe, 0, 1, &device->state.scissor);
+}
+
+static INLINE void
+update_blend(struct NineDevice9 *device)
+{
+ nine_convert_blend_state(device->cso, device->state.rs);
+}
+
+static INLINE void
+update_dsa(struct NineDevice9 *device)
+{
+ nine_convert_dsa_state(device->cso, device->state.rs);
+}
+
+static INLINE void
+update_rasterizer(struct NineDevice9 *device)
+{
+ nine_convert_rasterizer_state(device->cso, device->state.rs);
+}
+
+/* Loop through VS inputs and pick the vertex elements with the declared
+ * usage from the vertex declaration, then insert the instance divisor from
+ * the stream source frequency setting.
+ */
+static void
+update_vertex_elements(struct NineDevice9 *device)
+{
+ struct nine_state *state = &device->state;
+ const struct NineVertexDeclaration9 *vdecl = device->state.vdecl;
+ const struct NineVertexShader9 *vs;
+ unsigned n, l, b;
+ struct pipe_vertex_element ve[PIPE_MAX_ATTRIBS];
+
+ state->stream_usage_mask = 0;
+
+ vs = device->state.vs ? device->state.vs : device->ff.vs;
+
+ if (!vdecl) /* no inputs */
+ return;
+ for (n = 0; n < vs->num_inputs; ++n) {
+ DBG("looking up input %u (usage %u) from vdecl(%p)\n",
+ n, vs->input_map[n].ndecl, vdecl);
+
+ assert(vs->input_map[n].ndecl < Elements(vdecl->usage_map));
+ l = vdecl->usage_map[vs->input_map[n].ndecl];
+
+ if (likely(l < vdecl->nelems)) {
+ ve[n] = vdecl->elems[l];
+ b = ve[n].vertex_buffer_index;
+ state->stream_usage_mask |= 1 << b;
+ /* XXX wine just uses 1 here: */
+ if (state->stream_freq[b] & D3DSTREAMSOURCE_INSTANCEDATA)
+ ve[n].instance_divisor = state->stream_freq[b] & 0x7FFFFF;
+ } else {
+ /* TODO:
+ * If drivers don't want to handle this, insert a dummy buffer.
+ * But on which stream ?
+ */
+ /* no data, disable */
+ ve[n].src_format = PIPE_FORMAT_NONE;
+ ve[n].src_offset = 0;
+ ve[n].instance_divisor = 0;
+ ve[n].vertex_buffer_index = 0;
+ }
+ }
+ cso_set_vertex_elements(device->cso, vs->num_inputs, ve);
+
+ state->changed.stream_freq = 0;
+}
+
+static INLINE uint32_t
+update_shader_variant_keys(struct NineDevice9 *device)
+{
+ struct nine_state *state = &device->state;
+ uint32_t mask = 0;
+ uint32_t vs_key = state->samplers_shadow;
+ uint32_t ps_key = state->samplers_shadow;
+
+ vs_key = (vs_key & NINE_VS_SAMPLERS_MASK) >> NINE_SAMPLER_VS(0);
+ ps_key = (ps_key & NINE_PS_SAMPLERS_MASK) >> NINE_SAMPLER_PS(0);
+
+ if (state->vs) vs_key &= state->vs->sampler_mask;
+ if (state->ps) {
+ if (unlikely(state->ps->byte_code.version < 0x20)) {
+ /* no depth textures, but variable targets */
+ uint32_t m = state->ps->sampler_mask;
+ ps_key = 0;
+ while (m) {
+ int s = ffs(m) - 1;
+ m &= ~(1 << s);
+ ps_key |= (state->texture[s] ? state->texture[s]->pstype : 1) << (s * 2);
+ }
+ } else {
+ ps_key &= state->ps->sampler_mask;
+ }
+ }
+
+ if (state->vs && state->vs_key != vs_key) {
+ state->vs_key = vs_key;
+ mask |= NINE_STATE_VS;
+ }
+ if (state->ps && state->ps_key != ps_key) {
+ state->ps_key = ps_key;
+ mask |= NINE_STATE_PS;
+ }
+ return mask;
+}
+
+static INLINE uint32_t
+update_vs(struct NineDevice9 *device)
+{
+ struct nine_state *state = &device->state;
+ struct NineVertexShader9 *vs = state->vs;
+
+ /* likely because we dislike FF */
+ if (likely(vs)) {
+ state->cso.vs = NineVertexShader9_GetVariant(vs, state->vs_key);
+ } else {
+ vs = device->ff.vs;
+ state->cso.vs = vs->variant.cso;
+ }
+ device->pipe->bind_vs_state(device->pipe, state->cso.vs);
+
+ if (state->rs[NINED3DRS_VSPOINTSIZE] != vs->point_size) {
+ state->rs[NINED3DRS_VSPOINTSIZE] = vs->point_size;
+ return NINE_STATE_RASTERIZER;
+ }
+#ifdef DEBUG
+ {
+ unsigned s, mask = vs->sampler_mask;
+ for (s = 0; mask; ++s, mask >>= 1)
+ if ((mask & 1) && !(device->state.texture[NINE_SAMPLER_VS(s)]))
+ WARN_ONCE("FIXME: unbound sampler should return alpha=1\n");
+ }
+#endif
+ return 0;
+}
+
+static INLINE uint32_t
+update_ps(struct NineDevice9 *device)
+{
+ struct nine_state *state = &device->state;
+ struct NinePixelShader9 *ps = state->ps;
+
+ if (likely(ps)) {
+ state->cso.ps = NinePixelShader9_GetVariant(ps, state->ps_key);
+ } else {
+ ps = device->ff.ps;
+ state->cso.ps = ps->variant.cso;
+ }
+ device->pipe->bind_fs_state(device->pipe, state->cso.ps);
+
+#ifdef DEBUG
+ {
+ unsigned s, mask = ps->sampler_mask;
+ for (s = 0; mask; ++s, mask >>= 1)
+ if ((mask & 1) && !(device->state.texture[NINE_SAMPLER_PS(s)]))
+ WARN_ONCE("FIXME: unbound sampler should return alpha=1\n");
+ if (device->state.rt_mask & ~ps->rt_mask)
+ WARN_ONCE("FIXME: writing undefined values to cbufs 0x%x\n",
+ device->state.rt_mask & ~ps->rt_mask);
+ }
+#endif
+ return 0;
+}
+
+#define DO_UPLOAD_CONST_F(buf,p,c,d) \
+ do { \
+ DBG("upload ConstantF [%u .. %u]\n", x, (x) + (c) - 1); \
+ box.x = (p) * 4 * sizeof(float); \
+ box.width = (c) * 4 * sizeof(float); \
+ pipe->transfer_inline_write(pipe, buf, 0, usage, &box, &((d)[p * 4]), \
+ 0, 0); \
+ } while(0)
+
+/* OK, this is a bit ugly ... */
+static void
+update_constants(struct NineDevice9 *device, unsigned shader_type)
+{
+ struct pipe_context *pipe = device->pipe;
+ struct pipe_resource *buf;
+ struct pipe_box box;
+ const void *data;
+ const float *const_f;
+ const int *const_i;
+ const BOOL *const_b;
+ uint32_t data_b[NINE_MAX_CONST_B];
+ uint32_t b_true;
+ uint16_t dirty_i;
+ uint16_t dirty_b;
+ const unsigned usage = PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE;
+ unsigned x = 0; /* silence warning */
+ unsigned i, c, n;
+ const struct nine_lconstf *lconstf;
+ struct nine_range *r, *p;
+
+ box.y = 0;
+ box.z = 0;
+ box.height = 1;
+ box.depth = 1;
+
+ if (shader_type == PIPE_SHADER_VERTEX) {
+ DBG("VS\n");
+ buf = device->constbuf_vs;
+
+ const_f = device->state.vs_const_f;
+ for (p = r = device->state.changed.vs_const_f; r; p = r, r = r->next)
+ DO_UPLOAD_CONST_F(buf, r->bgn, r->end - r->bgn, const_f);
+ if (p) {
+ nine_range_pool_put_chain(&device->range_pool,
+ device->state.changed.vs_const_f, p);
+ device->state.changed.vs_const_f = NULL;
+ }
+
+ dirty_i = device->state.changed.vs_const_i;
+ device->state.changed.vs_const_i = 0;
+ const_i = &device->state.vs_const_i[0][0];
+
+ dirty_b = device->state.changed.vs_const_b;
+ device->state.changed.vs_const_b = 0;
+ const_b = device->state.vs_const_b;
+ b_true = device->vs_bool_true;
+
+ lconstf = &device->state.vs->lconstf;
+ device->state.ff.clobber.vs_const = TRUE;
+ device->state.changed.group &= ~NINE_STATE_VS_CONST;
+ } else {
+ DBG("PS\n");
+ buf = device->constbuf_ps;
+
+ const_f = device->state.ps_const_f;
+ for (p = r = device->state.changed.ps_const_f; r; p = r, r = r->next)
+ DO_UPLOAD_CONST_F(buf, r->bgn, r->end - r->bgn, const_f);
+ if (p) {
+ nine_range_pool_put_chain(&device->range_pool,
+ device->state.changed.ps_const_f, p);
+ device->state.changed.ps_const_f = NULL;
+ }
+
+ dirty_i = device->state.changed.ps_const_i;
+ device->state.changed.ps_const_i = 0;
+ const_i = &device->state.ps_const_i[0][0];
+
+ dirty_b = device->state.changed.ps_const_b;
+ device->state.changed.vs_const_b = 0;
+ const_b = device->state.ps_const_b;
+ b_true = device->ps_bool_true;
+
+ lconstf = &device->state.ps->lconstf;
+ device->state.ff.clobber.ps_const = TRUE;
+ device->state.changed.group &= ~NINE_STATE_PS_CONST;
+ }
+
+ /* write range from min to max changed, it's not much data */
+ /* bool1 */
+ if (dirty_b) {
+ c = util_last_bit(dirty_b);
+ i = ffs(dirty_b) - 1;
+ x = buf->width0 - (NINE_MAX_CONST_B - i) * 4;
+ c -= i;
+ for (n = 0; n < c; ++n, ++i)
+ data_b[n] = const_b[i] ? b_true : 0;
+ box.x = x;
+ box.width = n * 4;
+ DBG("upload ConstantB [%u .. %u]\n", x, x + n - 1);
+ pipe->transfer_inline_write(pipe, buf, 0, usage, &box, data_b, 0, 0);
+ }
+
+ /* int4 */
+ for (c = 0, i = 0; dirty_i; i++, dirty_i >>= 1) {
+ if (dirty_i & 1) {
+ if (!c)
+ x = i;
+ ++c;
+ } else
+ if (c) {
+ DBG("upload ConstantI [%u .. %u]\n", x, x + c - 1);
+ data = &const_i[x * 4];
+ box.x = buf->width0 - (NINE_MAX_CONST_I * 4 + NINE_MAX_CONST_B) * 4;
+ box.x += x * 4 * sizeof(int);
+ box.width = c * 4 * sizeof(int);
+ c = 0;
+ pipe->transfer_inline_write(pipe, buf, 0, usage, &box, data, 0, 0);
+ }
+ }
+ if (c) {
+ DBG("upload ConstantI [%u .. %u]\n", x, x + c - 1);
+ data = &const_i[x * 4];
+ box.x = buf->width0 - (NINE_MAX_CONST_I * 4 + NINE_MAX_CONST_B) * 4;
+ box.x += x * 4 * sizeof(int);
+ box.width = c * 4 * sizeof(int);
+ pipe->transfer_inline_write(pipe, buf, 0, usage, &box, data, 0, 0);
+ }
+
+ /* TODO: only upload these when shader itself changes */
+ if (lconstf->ranges) {
+ unsigned n = 0;
+ struct nine_range *r = lconstf->ranges;
+ while (r) {
+ box.x = r->bgn * 4 * sizeof(float);
+ n += r->end - r->bgn;
+ box.width = (r->end - r->bgn) * 4 * sizeof(float);
+ data = &lconstf->data[4 * n];
+ pipe->transfer_inline_write(pipe, buf, 0, usage, &box, data, 0, 0);
+ r = r->next;
+ }
+ }
+}
+
+static void
+update_vs_constants_userbuf(struct NineDevice9 *device)
+{
+ struct nine_state *state = &device->state;
+ struct pipe_context *pipe = device->pipe;
+ struct pipe_constant_buffer cb;
+ cb.buffer = NULL;
+ cb.buffer_offset = 0;
+ cb.buffer_size = device->state.vs->const_used_size;
+ cb.user_buffer = device->state.vs_const_f;
+
+ if (!cb.buffer_size)
+ return;
+
+ if (state->changed.vs_const_i) {
+ int *idst = (int *)&state->vs_const_f[4 * device->max_vs_const_f];
+ memcpy(idst, state->vs_const_i, sizeof(state->vs_const_i));
+ state->changed.vs_const_i = 0;
+ }
+ if (state->changed.vs_const_b) {
+ int *idst = (int *)&state->vs_const_f[4 * device->max_vs_const_f];
+ uint32_t *bdst = (uint32_t *)&idst[4 * NINE_MAX_CONST_I];
+ int i;
+ for (i = 0; i < NINE_MAX_CONST_B; ++i)
+ bdst[i] = state->vs_const_b[i] ? device->vs_bool_true : 0;
+ state->changed.vs_const_b = 0;
+ }
+
+#ifdef DEBUG
+ if (device->state.vs->lconstf.ranges) {
+ /* TODO: Can we make it so that we don't have to copy everything ? */
+ const struct nine_lconstf *lconstf = &device->state.vs->lconstf;
+ const struct nine_range *r = lconstf->ranges;
+ unsigned n = 0;
+ float *dst = (float *)MALLOC(cb.buffer_size);
+ float *src = (float *)cb.user_buffer;
+ memcpy(dst, src, cb.buffer_size);
+ while (r) {
+ unsigned p = r->bgn;
+ unsigned c = r->end - r->bgn;
+ memcpy(&dst[p * 4], &lconstf->data[n * 4], c * 4 * sizeof(float));
+ n += c;
+ r = r->next;
+ }
+ cb.user_buffer = dst;
+ }
+#endif
+
+ pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &cb);
+
+#ifdef DEBUG
+ if (device->state.vs->lconstf.ranges)
+ FREE((void *)cb.user_buffer);
+#endif
+
+ if (device->state.changed.vs_const_f) {
+ struct nine_range *r = device->state.changed.vs_const_f;
+ struct nine_range *p = r;
+ while (p->next)
+ p = p->next;
+ nine_range_pool_put_chain(&device->range_pool, r, p);
+ device->state.changed.vs_const_f = NULL;
+ }
+ state->changed.group &= ~NINE_STATE_VS_CONST;
+}
+
+static void
+update_ps_constants_userbuf(struct NineDevice9 *device)
+{
+ struct nine_state *state = &device->state;
+ struct pipe_context *pipe = device->pipe;
+ struct pipe_constant_buffer cb;
+ cb.buffer = NULL;
+ cb.buffer_offset = 0;
+ cb.buffer_size = device->state.ps->const_used_size;
+ cb.user_buffer = device->state.ps_const_f;
+
+ if (!cb.buffer_size)
+ return;
+
+ if (state->changed.ps_const_i) {
+ int *idst = (int *)&state->ps_const_f[4 * device->max_ps_const_f];
+ memcpy(idst, state->ps_const_i, sizeof(state->ps_const_i));
+ state->changed.ps_const_i = 0;
+ }
+ if (state->changed.ps_const_b) {
+ int *idst = (int *)&state->ps_const_f[4 * device->max_ps_const_f];
+ uint32_t *bdst = (uint32_t *)&idst[4 * NINE_MAX_CONST_I];
+ int i;
+ for (i = 0; i < NINE_MAX_CONST_B; ++i)
+ bdst[i] = state->ps_const_b[i] ? device->ps_bool_true : 0;
+ state->changed.ps_const_b = 0;
+ }
+
+#ifdef DEBUG
+ if (device->state.ps->lconstf.ranges) {
+ /* TODO: Can we make it so that we don't have to copy everything ? */
+ const struct nine_lconstf *lconstf = &device->state.ps->lconstf;
+ const struct nine_range *r = lconstf->ranges;
+ unsigned n = 0;
+ float *dst = (float *)MALLOC(cb.buffer_size);
+ float *src = (float *)cb.user_buffer;
+ memcpy(dst, src, cb.buffer_size);
+ while (r) {
+ unsigned p = r->bgn;
+ unsigned c = r->end - r->bgn;
+ memcpy(&dst[p * 4], &lconstf->data[n * 4], c * 4 * sizeof(float));
+ n += c;
+ r = r->next;
+ }
+ cb.user_buffer = dst;
+ }
+#endif
+
+ pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &cb);
+
+#ifdef DEBUG
+ if (device->state.ps->lconstf.ranges)
+ FREE((void *)cb.user_buffer);
+#endif
+
+ if (device->state.changed.ps_const_f) {
+ struct nine_range *r = device->state.changed.ps_const_f;
+ struct nine_range *p = r;
+ while (p->next)
+ p = p->next;
+ nine_range_pool_put_chain(&device->range_pool, r, p);
+ device->state.changed.ps_const_f = NULL;
+ }
+ state->changed.group &= ~NINE_STATE_PS_CONST;
+}
+
+static void
+update_vertex_buffers(struct NineDevice9 *device)
+{
+ struct pipe_context *pipe = device->pipe;
+ struct nine_state *state = &device->state;
+ uint32_t mask = state->changed.vtxbuf;
+ unsigned i;
+ unsigned start;
+ unsigned count = 0;
+
+ DBG("mask=%x\n", mask);
+
+ for (i = 0; mask; mask >>= 1, ++i) {
+ if (mask & 1) {
+ if (!count)
+ start = i;
+ ++count;
+ } else {
+ if (count)
+ pipe->set_vertex_buffers(pipe,
+ start, count, &state->vtxbuf[start]);
+ count = 0;
+ }
+ }
+ if (count)
+ pipe->set_vertex_buffers(pipe, start, count, &state->vtxbuf[start]);
+
+ state->changed.vtxbuf = 0;
+}
+
+static INLINE void
+update_index_buffer(struct NineDevice9 *device)
+{
+ struct pipe_context *pipe = device->pipe;
+ if (device->state.idxbuf)
+ pipe->set_index_buffer(pipe, &device->state.idxbuf->buffer);
+ else
+ pipe->set_index_buffer(pipe, NULL);
+}
+
+/* TODO: only go through dirty textures */
+static void
+validate_textures(struct NineDevice9 *device)
+{
+ struct NineBaseTexture9 *tex, *ptr;
+ LIST_FOR_EACH_ENTRY_SAFE(tex, ptr, &device->update_textures, list) {
+ list_delinit(&tex->list);
+ NineBaseTexture9_Validate(tex);
+ }
+}
+
+static INLINE boolean
+update_sampler_derived(struct nine_state *state, unsigned s)
+{
+ boolean changed = FALSE;
+
+ if (state->samp[s][NINED3DSAMP_SHADOW] != state->texture[s]->shadow) {
+ changed = TRUE;
+ state->samp[s][NINED3DSAMP_SHADOW] = state->texture[s]->shadow;
+ }
+
+ if (state->samp[s][D3DSAMP_MIPFILTER] != D3DTEXF_NONE) {
+ int lod = state->samp[s][D3DSAMP_MAXMIPLEVEL] - state->texture[s]->lod;
+ if (lod < 0)
+ lod = 0;
+ if (state->samp[s][NINED3DSAMP_MINLOD] != lod) {
+ changed = TRUE;
+ state->samp[s][NINED3DSAMP_MINLOD] = lod;
+ }
+ } else {
+ state->changed.sampler[s] &= ~0x300; /* lod changes irrelevant */
+ }
+
+ return changed;
+}
+
+/* TODO: add sRGB override to pipe_sampler_state ? */
+static void
+update_textures_and_samplers(struct NineDevice9 *device)
+{
+ struct pipe_context *pipe = device->pipe;
+ struct nine_state *state = &device->state;
+ struct pipe_sampler_view *view[NINE_MAX_SAMPLERS];
+ unsigned num_textures;
+ unsigned i;
+ boolean commit_samplers;
+
+ /* TODO: Can we reduce iterations here ? */
+
+ commit_samplers = FALSE;
+ for (num_textures = 0, i = 0; i < NINE_MAX_SAMPLERS_PS; ++i) {
+ const unsigned s = NINE_SAMPLER_PS(i);
+ int sRGB;
+ if (!state->texture[s]) {
+ view[i] = NULL;
+#ifdef DEBUG
+ if (state->ps && state->ps->sampler_mask & (1 << i))
+ WARN_ONCE("FIXME: unbound sampler should return alpha=1\n");
+#endif
+ continue;
+ }
+ sRGB = state->samp[s][D3DSAMP_SRGBTEXTURE] ? 1 : 0;
+
+ view[i] = NineBaseTexture9_GetSamplerView(state->texture[s], sRGB);
+ num_textures = i + 1;
+
+ if (update_sampler_derived(state, s) || (state->changed.sampler[s] & 0x05fe)) {
+ state->changed.sampler[s] = 0;
+ commit_samplers = TRUE;
+ nine_convert_sampler_state(device->cso, s, state->samp[s]);
+ }
+ }
+ if (state->changed.texture & NINE_PS_SAMPLERS_MASK)
+ pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0,
+ num_textures, view);
+
+ if (commit_samplers)
+ cso_single_sampler_done(device->cso, PIPE_SHADER_FRAGMENT);
+
+ commit_samplers = FALSE;
+ for (num_textures = 0, i = 0; i < NINE_MAX_SAMPLERS_VS; ++i) {
+ const unsigned s = NINE_SAMPLER_VS(i);
+ int sRGB;
+ if (!state->texture[s]) {
+ view[i] = NULL;
+#ifdef DEBUG
+ if (state->vs && state->vs->sampler_mask & (1 << i))
+ WARN_ONCE("FIXME: unbound sampler should return alpha=1\n");
+#endif
+ continue;
+ }
+ sRGB = state->samp[s][D3DSAMP_SRGBTEXTURE] ? 1 : 0;
+
+ view[i] = NineBaseTexture9_GetSamplerView(state->texture[s], sRGB);
+ num_textures = i + 1;
+
+ if (update_sampler_derived(state, s) || (state->changed.sampler[s] & 0x05fe)) {
+ state->changed.sampler[s] = 0;
+ commit_samplers = TRUE;
+ nine_convert_sampler_state(device->cso, s, state->samp[s]);
+ }
+ }
+ if (state->changed.texture & NINE_VS_SAMPLERS_MASK)
+ pipe->set_sampler_views(pipe, PIPE_SHADER_VERTEX, 0,
+ num_textures, view);
+
+ if (commit_samplers)
+ cso_single_sampler_done(device->cso, PIPE_SHADER_VERTEX);
+
+ state->changed.texture = 0;
+}
+
+
+#define NINE_STATE_FREQ_GROUP_0 \
+ (NINE_STATE_FB | \
+ NINE_STATE_VIEWPORT | \
+ NINE_STATE_SCISSOR | \
+ NINE_STATE_BLEND | \
+ NINE_STATE_DSA | \
+ NINE_STATE_RASTERIZER | \
+ NINE_STATE_VS | \
+ NINE_STATE_PS | \
+ NINE_STATE_BLEND_COLOR | \
+ NINE_STATE_STENCIL_REF | \
+ NINE_STATE_SAMPLE_MASK)
+
+#define NINE_STATE_FREQ_GROUP_1 ~NINE_STATE_FREQ_GROUP_0
+
+#define NINE_STATE_SHADER_VARIANT_GROUP \
+ (NINE_STATE_TEXTURE | \
+ NINE_STATE_VS | \
+ NINE_STATE_PS)
+
+boolean
+nine_update_state(struct NineDevice9 *device, uint32_t mask)
+{
+ struct pipe_context *pipe = device->pipe;
+ struct nine_state *state = &device->state;
+ uint32_t group;
+
+ DBG("changed state groups: %x | %x\n",
+ state->changed.group & NINE_STATE_FREQ_GROUP_0,
+ state->changed.group & NINE_STATE_FREQ_GROUP_1);
+
+ /* NOTE: We may want to use the cso cache for everything, or let
+ * NineDevice9.RestoreNonCSOState actually set the states, then we wouldn't
+ * have to care about state being clobbered here and could merge this back
+ * into update_textures. Except, we also need to re-validate textures that
+ * may be dirty anyway, even if no texture bindings changed.
+ */
+ validate_textures(device); /* may clobber state */
+
+ /* ff_update may change VS/PS dirty bits */
+ if ((mask & NINE_STATE_FF) && unlikely(!state->vs || !state->ps))
+ nine_ff_update(device);
+ group = state->changed.group & mask;
+
+ if (group & NINE_STATE_SHADER_VARIANT_GROUP)
+ group |= update_shader_variant_keys(device);
+
+ if (group & NINE_STATE_FREQ_GROUP_0) {
+ if (group & NINE_STATE_FB)
+ group = update_framebuffer(device) & mask;
+ if (group & NINE_STATE_VIEWPORT)
+ update_viewport(device);
+ if (group & NINE_STATE_SCISSOR)
+ update_scissor(device);
+
+ if (group & NINE_STATE_DSA)
+ update_dsa(device);
+ if (group & NINE_STATE_BLEND)
+ update_blend(device);
+
+ if (group & NINE_STATE_VS)
+ group |= update_vs(device);
+
+ if (group & NINE_STATE_RASTERIZER)
+ update_rasterizer(device);
+
+ if (group & NINE_STATE_PS)
+ group |= update_ps(device);
+
+ if (group & NINE_STATE_BLEND_COLOR) {
+ struct pipe_blend_color color;
+ d3dcolor_to_rgba(&color.color[0], state->rs[D3DRS_BLENDFACTOR]);
+ pipe->set_blend_color(pipe, &color);
+ }
+ if (group & NINE_STATE_SAMPLE_MASK) {
+ pipe->set_sample_mask(pipe, state->rs[D3DRS_MULTISAMPLEMASK]);
+ }
+ if (group & NINE_STATE_STENCIL_REF) {
+ struct pipe_stencil_ref ref;
+ ref.ref_value[0] = state->rs[D3DRS_STENCILREF];
+ ref.ref_value[1] = ref.ref_value[0];
+ pipe->set_stencil_ref(pipe, &ref);
+ }
+ }
+
+ if (state->changed.ucp)
+ pipe->set_clip_state(pipe, &state->clip);
+
+ if (group & (NINE_STATE_FREQ_GROUP_1 | NINE_STATE_VS)) {
+ if (group & (NINE_STATE_TEXTURE | NINE_STATE_SAMPLER))
+ update_textures_and_samplers(device);
+
+ if (group & NINE_STATE_IDXBUF)
+ update_index_buffer(device);
+
+ if ((group & (NINE_STATE_VDECL | NINE_STATE_VS)) ||
+ state->changed.stream_freq & ~1)
+ update_vertex_elements(device);
+
+ if (device->prefer_user_constbuf) {
+ if ((group & (NINE_STATE_VS_CONST | NINE_STATE_VS)) && state->vs)
+ update_vs_constants_userbuf(device);
+ if ((group & (NINE_STATE_PS_CONST | NINE_STATE_PS)) && state->ps)
+ update_ps_constants_userbuf(device);
+ } else {
+ if ((group & NINE_STATE_VS_CONST) && state->vs)
+ update_constants(device, PIPE_SHADER_VERTEX);
+ if ((group & NINE_STATE_PS_CONST) && state->ps)
+ update_constants(device, PIPE_SHADER_FRAGMENT);
+ }
+ }
+ if (state->changed.vtxbuf)
+ update_vertex_buffers(device);
+
+ device->state.changed.group &= ~mask |
+ (NINE_STATE_FF | NINE_STATE_VS_CONST | NINE_STATE_PS_CONST);
+
+ DBG("finished\n");
+
+ return TRUE;
+}
+
+
+static const DWORD nine_render_state_defaults[NINED3DRS_LAST + 1] =
+{
+ /* [D3DRS_ZENABLE] = D3DZB_TRUE; wine: auto_depth_stencil */
+ [D3DRS_ZENABLE] = D3DZB_FALSE,
+ [D3DRS_FILLMODE] = D3DFILL_SOLID,
+ [D3DRS_SHADEMODE] = D3DSHADE_GOURAUD,
+/* [D3DRS_LINEPATTERN] = 0x00000000, */
+ [D3DRS_ZWRITEENABLE] = TRUE,
+ [D3DRS_ALPHATESTENABLE] = FALSE,
+ [D3DRS_LASTPIXEL] = TRUE,
+ [D3DRS_SRCBLEND] = D3DBLEND_ONE,
+ [D3DRS_DESTBLEND] = D3DBLEND_ZERO,
+ [D3DRS_CULLMODE] = D3DCULL_CCW,
+ [D3DRS_ZFUNC] = D3DCMP_LESSEQUAL,
+ [D3DRS_ALPHAFUNC] = D3DCMP_ALWAYS,
+ [D3DRS_ALPHAREF] = 0,
+ [D3DRS_DITHERENABLE] = FALSE,
+ [D3DRS_ALPHABLENDENABLE] = FALSE,
+ [D3DRS_FOGENABLE] = FALSE,
+ [D3DRS_SPECULARENABLE] = FALSE,
+/* [D3DRS_ZVISIBLE] = 0, */
+ [D3DRS_FOGCOLOR] = 0,
+ [D3DRS_FOGTABLEMODE] = D3DFOG_NONE,
+ [D3DRS_FOGSTART] = 0x00000000,
+ [D3DRS_FOGEND] = 0x3F800000,
+ [D3DRS_FOGDENSITY] = 0x3F800000,
+/* [D3DRS_EDGEANTIALIAS] = FALSE, */
+ [D3DRS_RANGEFOGENABLE] = FALSE,
+ [D3DRS_STENCILENABLE] = FALSE,
+ [D3DRS_STENCILFAIL] = D3DSTENCILOP_KEEP,
+ [D3DRS_STENCILZFAIL] = D3DSTENCILOP_KEEP,
+ [D3DRS_STENCILPASS] = D3DSTENCILOP_KEEP,
+ [D3DRS_STENCILREF] = 0,
+ [D3DRS_STENCILMASK] = 0xFFFFFFFF,
+ [D3DRS_STENCILFUNC] = D3DCMP_ALWAYS,
+ [D3DRS_STENCILWRITEMASK] = 0xFFFFFFFF,
+ [D3DRS_TEXTUREFACTOR] = 0xFFFFFFFF,
+ [D3DRS_WRAP0] = 0,
+ [D3DRS_WRAP1] = 0,
+ [D3DRS_WRAP2] = 0,
+ [D3DRS_WRAP3] = 0,
+ [D3DRS_WRAP4] = 0,
+ [D3DRS_WRAP5] = 0,
+ [D3DRS_WRAP6] = 0,
+ [D3DRS_WRAP7] = 0,
+ [D3DRS_CLIPPING] = TRUE,
+ [D3DRS_LIGHTING] = TRUE,
+ [D3DRS_AMBIENT] = 0,
+ [D3DRS_FOGVERTEXMODE] = D3DFOG_NONE,
+ [D3DRS_COLORVERTEX] = TRUE,
+ [D3DRS_LOCALVIEWER] = TRUE,
+ [D3DRS_NORMALIZENORMALS] = FALSE,
+ [D3DRS_DIFFUSEMATERIALSOURCE] = D3DMCS_COLOR1,
+ [D3DRS_SPECULARMATERIALSOURCE] = D3DMCS_COLOR2,
+ [D3DRS_AMBIENTMATERIALSOURCE] = D3DMCS_MATERIAL,
+ [D3DRS_EMISSIVEMATERIALSOURCE] = D3DMCS_MATERIAL,
+ [D3DRS_VERTEXBLEND] = D3DVBF_DISABLE,
+ [D3DRS_CLIPPLANEENABLE] = 0,
+/* [D3DRS_SOFTWAREVERTEXPROCESSING] = FALSE, */
+ [D3DRS_POINTSIZE] = 0x3F800000,
+ [D3DRS_POINTSIZE_MIN] = 0x3F800000,
+ [D3DRS_POINTSPRITEENABLE] = FALSE,
+ [D3DRS_POINTSCALEENABLE] = FALSE,
+ [D3DRS_POINTSCALE_A] = 0x3F800000,
+ [D3DRS_POINTSCALE_B] = 0x00000000,
+ [D3DRS_POINTSCALE_C] = 0x00000000,
+ [D3DRS_MULTISAMPLEANTIALIAS] = TRUE,
+ [D3DRS_MULTISAMPLEMASK] = 0xFFFFFFFF,
+ [D3DRS_PATCHEDGESTYLE] = D3DPATCHEDGE_DISCRETE,
+/* [D3DRS_PATCHSEGMENTS] = 0x3F800000, */
+ [D3DRS_DEBUGMONITORTOKEN] = 0xDEADCAFE,
+ [D3DRS_POINTSIZE_MAX] = 0x3F800000, /* depends on cap */
+ [D3DRS_INDEXEDVERTEXBLENDENABLE] = FALSE,
+ [D3DRS_COLORWRITEENABLE] = 0x0000000f,
+ [D3DRS_TWEENFACTOR] = 0x00000000,
+ [D3DRS_BLENDOP] = D3DBLENDOP_ADD,
+ [D3DRS_POSITIONDEGREE] = D3DDEGREE_CUBIC,
+ [D3DRS_NORMALDEGREE] = D3DDEGREE_LINEAR,
+ [D3DRS_SCISSORTESTENABLE] = FALSE,
+ [D3DRS_SLOPESCALEDEPTHBIAS] = 0,
+ [D3DRS_MINTESSELLATIONLEVEL] = 0x3F800000,
+ [D3DRS_MAXTESSELLATIONLEVEL] = 0x3F800000,
+ [D3DRS_ANTIALIASEDLINEENABLE] = FALSE,
+ [D3DRS_ADAPTIVETESS_X] = 0x00000000,
+ [D3DRS_ADAPTIVETESS_Y] = 0x00000000,
+ [D3DRS_ADAPTIVETESS_Z] = 0x3F800000,
+ [D3DRS_ADAPTIVETESS_W] = 0x00000000,
+ [D3DRS_ENABLEADAPTIVETESSELLATION] = FALSE,
+ [D3DRS_TWOSIDEDSTENCILMODE] = FALSE,
+ [D3DRS_CCW_STENCILFAIL] = D3DSTENCILOP_KEEP,
+ [D3DRS_CCW_STENCILZFAIL] = D3DSTENCILOP_KEEP,
+ [D3DRS_CCW_STENCILPASS] = D3DSTENCILOP_KEEP,
+ [D3DRS_CCW_STENCILFUNC] = D3DCMP_ALWAYS,
+ [D3DRS_COLORWRITEENABLE1] = 0x0000000F,
+ [D3DRS_COLORWRITEENABLE2] = 0x0000000F,
+ [D3DRS_COLORWRITEENABLE3] = 0x0000000F,
+ [D3DRS_BLENDFACTOR] = 0xFFFFFFFF,
+ [D3DRS_SRGBWRITEENABLE] = 0,
+ [D3DRS_DEPTHBIAS] = 0,
+ [D3DRS_WRAP8] = 0,
+ [D3DRS_WRAP9] = 0,
+ [D3DRS_WRAP10] = 0,
+ [D3DRS_WRAP11] = 0,
+ [D3DRS_WRAP12] = 0,
+ [D3DRS_WRAP13] = 0,
+ [D3DRS_WRAP14] = 0,
+ [D3DRS_WRAP15] = 0,
+ [D3DRS_SEPARATEALPHABLENDENABLE] = FALSE,
+ [D3DRS_SRCBLENDALPHA] = D3DBLEND_ONE,
+ [D3DRS_DESTBLENDALPHA] = D3DBLEND_ZERO,
+ [D3DRS_BLENDOPALPHA] = D3DBLENDOP_ADD,
+ [NINED3DRS_VSPOINTSIZE] = FALSE,
+ [NINED3DRS_RTMASK] = 0xf
+};
+static const DWORD nine_tex_stage_state_defaults[NINED3DTSS_LAST + 1] =
+{
+ [D3DTSS_COLOROP] = D3DTOP_DISABLE,
+ [D3DTSS_ALPHAOP] = D3DTOP_DISABLE,
+ [D3DTSS_COLORARG1] = D3DTA_TEXTURE,
+ [D3DTSS_COLORARG2] = D3DTA_CURRENT,
+ [D3DTSS_COLORARG0] = D3DTA_CURRENT,
+ [D3DTSS_ALPHAARG1] = D3DTA_TEXTURE,
+ [D3DTSS_ALPHAARG2] = D3DTA_CURRENT,
+ [D3DTSS_ALPHAARG0] = D3DTA_CURRENT,
+ [D3DTSS_RESULTARG] = D3DTA_CURRENT,
+ [D3DTSS_BUMPENVMAT00] = 0,
+ [D3DTSS_BUMPENVMAT01] = 0,
+ [D3DTSS_BUMPENVMAT10] = 0,
+ [D3DTSS_BUMPENVMAT11] = 0,
+ [D3DTSS_BUMPENVLSCALE] = 0,
+ [D3DTSS_BUMPENVLOFFSET] = 0,
+ [D3DTSS_TEXCOORDINDEX] = 0,
+ [D3DTSS_TEXTURETRANSFORMFLAGS] = D3DTTFF_DISABLE,
+};
+static const DWORD nine_samp_state_defaults[NINED3DSAMP_LAST + 1] =
+{
+ [D3DSAMP_ADDRESSU] = D3DTADDRESS_WRAP,
+ [D3DSAMP_ADDRESSV] = D3DTADDRESS_WRAP,
+ [D3DSAMP_ADDRESSW] = D3DTADDRESS_WRAP,
+ [D3DSAMP_BORDERCOLOR] = 0,
+ [D3DSAMP_MAGFILTER] = D3DTEXF_POINT,
+ [D3DSAMP_MINFILTER] = D3DTEXF_POINT,
+ [D3DSAMP_MIPFILTER] = D3DTEXF_NONE,
+ [D3DSAMP_MIPMAPLODBIAS] = 0,
+ [D3DSAMP_MAXMIPLEVEL] = 0,
+ [D3DSAMP_MAXANISOTROPY] = 1,
+ [D3DSAMP_SRGBTEXTURE] = 0,
+ [D3DSAMP_ELEMENTINDEX] = 0,
+ [D3DSAMP_DMAPOFFSET] = 0,
+ [NINED3DSAMP_MINLOD] = 0,
+ [NINED3DSAMP_SHADOW] = 0
+};
+void
+nine_state_set_defaults(struct nine_state *state, const D3DCAPS9 *caps,
+ boolean is_reset)
+{
+ unsigned s;
+
+ /* Initialize defaults.
+ */
+ memcpy(state->rs, nine_render_state_defaults, sizeof(state->rs));
+
+ for (s = 0; s < Elements(state->ff.tex_stage); ++s) {
+ memcpy(&state->ff.tex_stage[s], nine_tex_stage_state_defaults,
+ sizeof(state->ff.tex_stage[s]));
+ state->ff.tex_stage[s][D3DTSS_TEXCOORDINDEX] = s;
+ }
+ state->ff.tex_stage[0][D3DTSS_COLOROP] = D3DTOP_MODULATE;
+ state->ff.tex_stage[0][D3DTSS_ALPHAOP] = D3DTOP_SELECTARG1;
+
+ for (s = 0; s < Elements(state->samp); ++s) {
+ memcpy(&state->samp[s], nine_samp_state_defaults,
+ sizeof(state->samp[s]));
+ }
+
+ if (state->vs_const_f)
+ memset(state->vs_const_f, 0, NINE_MAX_CONST_F * 4 * sizeof(float));
+ if (state->ps_const_f)
+ memset(state->ps_const_f, 0, NINE_MAX_CONST_F * 4 * sizeof(float));
+
+ /* Cap dependent initial state:
+ */
+ state->rs[D3DRS_POINTSIZE_MAX] = fui(caps->MaxPointSize);
+
+ /* Set changed flags to initialize driver.
+ */
+ state->changed.group = NINE_STATE_ALL;
+
+ state->ff.changed.transform[0] = ~0;
+ state->ff.changed.transform[D3DTS_WORLD / 32] |= 1 << (D3DTS_WORLD % 32);
+
+ if (!is_reset) {
+ state->viewport.MinZ = 0.0f;
+ state->viewport.MaxZ = 1.0f;
+ }
+
+ for (s = 0; s < Elements(state->changed.sampler); ++s)
+ state->changed.sampler[s] = ~0;
+}
+
+void
+nine_state_clear(struct nine_state *state, const boolean device)
+{
+ unsigned i;
+
+ for (i = 0; i < Elements(state->rt); ++i)
+ nine_bind(&state->rt[i], NULL);
+ nine_bind(&state->ds, NULL);
+ nine_bind(&state->vs, NULL);
+ nine_bind(&state->ps, NULL);
+ nine_bind(&state->vdecl, NULL);
+ for (i = 0; i < PIPE_MAX_ATTRIBS; ++i)
+ nine_bind(&state->stream[i], NULL);
+ nine_bind(&state->idxbuf, NULL);
+ for (i = 0; i < NINE_MAX_SAMPLERS; ++i) {
+ if (device &&
+ state->texture[i] &&
+ --state->texture[i]->bind_count == 0)
+ list_delinit(&state->texture[i]->list);
+ nine_bind(&state->texture[i], NULL);
+ }
+}
+
+/*
+static const DWORD nine_render_states_pixel[] =
+{
+ D3DRS_ALPHABLENDENABLE,
+ D3DRS_ALPHAFUNC,
+ D3DRS_ALPHAREF,
+ D3DRS_ALPHATESTENABLE,
+ D3DRS_ANTIALIASEDLINEENABLE,
+ D3DRS_BLENDFACTOR,
+ D3DRS_BLENDOP,
+ D3DRS_BLENDOPALPHA,
+ D3DRS_CCW_STENCILFAIL,
+ D3DRS_CCW_STENCILPASS,
+ D3DRS_CCW_STENCILZFAIL,
+ D3DRS_COLORWRITEENABLE,
+ D3DRS_COLORWRITEENABLE1,
+ D3DRS_COLORWRITEENABLE2,
+ D3DRS_COLORWRITEENABLE3,
+ D3DRS_DEPTHBIAS,
+ D3DRS_DESTBLEND,
+ D3DRS_DESTBLENDALPHA,
+ D3DRS_DITHERENABLE,
+ D3DRS_FILLMODE,
+ D3DRS_FOGDENSITY,
+ D3DRS_FOGEND,
+ D3DRS_FOGSTART,
+ D3DRS_LASTPIXEL,
+ D3DRS_SCISSORTESTENABLE,
+ D3DRS_SEPARATEALPHABLENDENABLE,
+ D3DRS_SHADEMODE,
+ D3DRS_SLOPESCALEDEPTHBIAS,
+ D3DRS_SRCBLEND,
+ D3DRS_SRCBLENDALPHA,
+ D3DRS_SRGBWRITEENABLE,
+ D3DRS_STENCILENABLE,
+ D3DRS_STENCILFAIL,
+ D3DRS_STENCILFUNC,
+ D3DRS_STENCILMASK,
+ D3DRS_STENCILPASS,
+ D3DRS_STENCILREF,
+ D3DRS_STENCILWRITEMASK,
+ D3DRS_STENCILZFAIL,
+ D3DRS_TEXTUREFACTOR,
+ D3DRS_TWOSIDEDSTENCILMODE,
+ D3DRS_WRAP0,
+ D3DRS_WRAP1,
+ D3DRS_WRAP10,
+ D3DRS_WRAP11,
+ D3DRS_WRAP12,
+ D3DRS_WRAP13,
+ D3DRS_WRAP14,
+ D3DRS_WRAP15,
+ D3DRS_WRAP2,
+ D3DRS_WRAP3,
+ D3DRS_WRAP4,
+ D3DRS_WRAP5,
+ D3DRS_WRAP6,
+ D3DRS_WRAP7,
+ D3DRS_WRAP8,
+ D3DRS_WRAP9,
+ D3DRS_ZENABLE,
+ D3DRS_ZFUNC,
+ D3DRS_ZWRITEENABLE
+};
+*/
+const uint32_t nine_render_states_pixel[(NINED3DRS_LAST + 31) / 32] =
+{
+ 0x0f99c380, 0x1ff00070, 0x00000000, 0x00000000,
+ 0x000000ff, 0xde01c900, 0x0003ffcf
+};
+
+/*
+static const DWORD nine_render_states_vertex[] =
+{
+ D3DRS_ADAPTIVETESS_W,
+ D3DRS_ADAPTIVETESS_X,
+ D3DRS_ADAPTIVETESS_Y,
+ D3DRS_ADAPTIVETESS_Z,
+ D3DRS_AMBIENT,
+ D3DRS_AMBIENTMATERIALSOURCE,
+ D3DRS_CLIPPING,
+ D3DRS_CLIPPLANEENABLE,
+ D3DRS_COLORVERTEX,
+ D3DRS_CULLMODE,
+ D3DRS_DIFFUSEMATERIALSOURCE,
+ D3DRS_EMISSIVEMATERIALSOURCE,
+ D3DRS_ENABLEADAPTIVETESSELLATION,
+ D3DRS_FOGCOLOR,
+ D3DRS_FOGDENSITY,
+ D3DRS_FOGENABLE,
+ D3DRS_FOGEND,
+ D3DRS_FOGSTART,
+ D3DRS_FOGTABLEMODE,
+ D3DRS_FOGVERTEXMODE,
+ D3DRS_INDEXEDVERTEXBLENDENABLE,
+ D3DRS_LIGHTING,
+ D3DRS_LOCALVIEWER,
+ D3DRS_MAXTESSELLATIONLEVEL,
+ D3DRS_MINTESSELLATIONLEVEL,
+ D3DRS_MULTISAMPLEANTIALIAS,
+ D3DRS_MULTISAMPLEMASK,
+ D3DRS_NORMALDEGREE,
+ D3DRS_NORMALIZENORMALS,
+ D3DRS_PATCHEDGESTYLE,
+ D3DRS_POINTSCALE_A,
+ D3DRS_POINTSCALE_B,
+ D3DRS_POINTSCALE_C,
+ D3DRS_POINTSCALEENABLE,
+ D3DRS_POINTSIZE,
+ D3DRS_POINTSIZE_MAX,
+ D3DRS_POINTSIZE_MIN,
+ D3DRS_POINTSPRITEENABLE,
+ D3DRS_POSITIONDEGREE,
+ D3DRS_RANGEFOGENABLE,
+ D3DRS_SHADEMODE,
+ D3DRS_SPECULARENABLE,
+ D3DRS_SPECULARMATERIALSOURCE,
+ D3DRS_TWEENFACTOR,
+ D3DRS_VERTEXBLEND
+};
+*/
+const uint32_t nine_render_states_vertex[(NINED3DRS_LAST + 31) / 32] =
+{
+ 0x30400200, 0x0001007c, 0x00000000, 0x00000000,
+ 0xfd9efb00, 0x01fc34cf, 0x00000000
+};
+
+/* TODO: put in the right values */
+const uint32_t nine_render_state_group[NINED3DRS_LAST + 1] =
+{
+ [D3DRS_ZENABLE] = NINE_STATE_DSA,
+ [D3DRS_FILLMODE] = NINE_STATE_RASTERIZER,
+ [D3DRS_SHADEMODE] = NINE_STATE_RASTERIZER,
+ [D3DRS_ZWRITEENABLE] = NINE_STATE_DSA,
+ [D3DRS_ALPHATESTENABLE] = NINE_STATE_DSA,
+ [D3DRS_LASTPIXEL] = NINE_STATE_RASTERIZER,
+ [D3DRS_SRCBLEND] = NINE_STATE_BLEND,
+ [D3DRS_DESTBLEND] = NINE_STATE_BLEND,
+ [D3DRS_CULLMODE] = NINE_STATE_RASTERIZER,
+ [D3DRS_ZFUNC] = NINE_STATE_DSA,
+ [D3DRS_ALPHAREF] = NINE_STATE_DSA,
+ [D3DRS_ALPHAFUNC] = NINE_STATE_DSA,
+ [D3DRS_DITHERENABLE] = NINE_STATE_RASTERIZER,
+ [D3DRS_ALPHABLENDENABLE] = NINE_STATE_BLEND,
+ [D3DRS_FOGENABLE] = NINE_STATE_FF_OTHER,
+ [D3DRS_SPECULARENABLE] = NINE_STATE_FF_LIGHTING,
+ [D3DRS_FOGCOLOR] = NINE_STATE_FF_OTHER,
+ [D3DRS_FOGTABLEMODE] = NINE_STATE_FF_OTHER,
+ [D3DRS_FOGSTART] = NINE_STATE_FF_OTHER,
+ [D3DRS_FOGEND] = NINE_STATE_FF_OTHER,
+ [D3DRS_FOGDENSITY] = NINE_STATE_FF_OTHER,
+ [D3DRS_RANGEFOGENABLE] = NINE_STATE_FF_OTHER,
+ [D3DRS_STENCILENABLE] = NINE_STATE_DSA,
+ [D3DRS_STENCILFAIL] = NINE_STATE_DSA,
+ [D3DRS_STENCILZFAIL] = NINE_STATE_DSA,
+ [D3DRS_STENCILPASS] = NINE_STATE_DSA,
+ [D3DRS_STENCILFUNC] = NINE_STATE_DSA,
+ [D3DRS_STENCILREF] = NINE_STATE_STENCIL_REF,
+ [D3DRS_STENCILMASK] = NINE_STATE_DSA,
+ [D3DRS_STENCILWRITEMASK] = NINE_STATE_DSA,
+ [D3DRS_TEXTUREFACTOR] = NINE_STATE_FF_PSSTAGES,
+ [D3DRS_WRAP0] = NINE_STATE_UNHANDLED, /* cylindrical wrap is crazy */
+ [D3DRS_WRAP1] = NINE_STATE_UNHANDLED,
+ [D3DRS_WRAP2] = NINE_STATE_UNHANDLED,
+ [D3DRS_WRAP3] = NINE_STATE_UNHANDLED,
+ [D3DRS_WRAP4] = NINE_STATE_UNHANDLED,
+ [D3DRS_WRAP5] = NINE_STATE_UNHANDLED,
+ [D3DRS_WRAP6] = NINE_STATE_UNHANDLED,
+ [D3DRS_WRAP7] = NINE_STATE_UNHANDLED,
+ [D3DRS_CLIPPING] = 0, /* software vertex processing only */
+ [D3DRS_LIGHTING] = NINE_STATE_FF_LIGHTING,
+ [D3DRS_AMBIENT] = NINE_STATE_FF_LIGHTING | NINE_STATE_FF_MATERIAL,
+ [D3DRS_FOGVERTEXMODE] = NINE_STATE_FF_OTHER,
+ [D3DRS_COLORVERTEX] = NINE_STATE_FF_LIGHTING,
+ [D3DRS_LOCALVIEWER] = NINE_STATE_FF_LIGHTING,
+ [D3DRS_NORMALIZENORMALS] = NINE_STATE_FF_OTHER,
+ [D3DRS_DIFFUSEMATERIALSOURCE] = NINE_STATE_FF_LIGHTING,
+ [D3DRS_SPECULARMATERIALSOURCE] = NINE_STATE_FF_LIGHTING,
+ [D3DRS_AMBIENTMATERIALSOURCE] = NINE_STATE_FF_LIGHTING,
+ [D3DRS_EMISSIVEMATERIALSOURCE] = NINE_STATE_FF_LIGHTING,
+ [D3DRS_VERTEXBLEND] = NINE_STATE_FF_OTHER,
+ [D3DRS_CLIPPLANEENABLE] = NINE_STATE_RASTERIZER,
+ [D3DRS_POINTSIZE] = NINE_STATE_RASTERIZER,
+ [D3DRS_POINTSIZE_MIN] = NINE_STATE_MISC_CONST,
+ [D3DRS_POINTSPRITEENABLE] = NINE_STATE_RASTERIZER,
+ [D3DRS_POINTSCALEENABLE] = NINE_STATE_FF_OTHER,
+ [D3DRS_POINTSCALE_A] = NINE_STATE_FF_OTHER,
+ [D3DRS_POINTSCALE_B] = NINE_STATE_FF_OTHER,
+ [D3DRS_POINTSCALE_C] = NINE_STATE_FF_OTHER,
+ [D3DRS_MULTISAMPLEANTIALIAS] = NINE_STATE_RASTERIZER,
+ [D3DRS_MULTISAMPLEMASK] = NINE_STATE_SAMPLE_MASK,
+ [D3DRS_PATCHEDGESTYLE] = NINE_STATE_UNHANDLED,
+ [D3DRS_DEBUGMONITORTOKEN] = NINE_STATE_UNHANDLED,
+ [D3DRS_POINTSIZE_MAX] = NINE_STATE_MISC_CONST,
+ [D3DRS_INDEXEDVERTEXBLENDENABLE] = NINE_STATE_FF_OTHER,
+ [D3DRS_COLORWRITEENABLE] = NINE_STATE_BLEND,
+ [D3DRS_TWEENFACTOR] = NINE_STATE_FF_OTHER,
+ [D3DRS_BLENDOP] = NINE_STATE_BLEND,
+ [D3DRS_POSITIONDEGREE] = NINE_STATE_UNHANDLED,
+ [D3DRS_NORMALDEGREE] = NINE_STATE_UNHANDLED,
+ [D3DRS_SCISSORTESTENABLE] = NINE_STATE_RASTERIZER,
+ [D3DRS_SLOPESCALEDEPTHBIAS] = NINE_STATE_RASTERIZER,
+ [D3DRS_ANTIALIASEDLINEENABLE] = NINE_STATE_RASTERIZER,
+ [D3DRS_MINTESSELLATIONLEVEL] = NINE_STATE_UNHANDLED,
+ [D3DRS_MAXTESSELLATIONLEVEL] = NINE_STATE_UNHANDLED,
+ [D3DRS_ADAPTIVETESS_X] = NINE_STATE_UNHANDLED,
+ [D3DRS_ADAPTIVETESS_Y] = NINE_STATE_UNHANDLED,
+ [D3DRS_ADAPTIVETESS_Z] = NINE_STATE_UNHANDLED,
+ [D3DRS_ADAPTIVETESS_W] = NINE_STATE_UNHANDLED,
+ [D3DRS_ENABLEADAPTIVETESSELLATION] = NINE_STATE_UNHANDLED,
+ [D3DRS_TWOSIDEDSTENCILMODE] = NINE_STATE_DSA,
+ [D3DRS_CCW_STENCILFAIL] = NINE_STATE_DSA,
+ [D3DRS_CCW_STENCILZFAIL] = NINE_STATE_DSA,
+ [D3DRS_CCW_STENCILPASS] = NINE_STATE_DSA,
+ [D3DRS_CCW_STENCILFUNC] = NINE_STATE_DSA,
+ [D3DRS_COLORWRITEENABLE1] = NINE_STATE_BLEND,
+ [D3DRS_COLORWRITEENABLE2] = NINE_STATE_BLEND,
+ [D3DRS_COLORWRITEENABLE3] = NINE_STATE_BLEND,
+ [D3DRS_BLENDFACTOR] = NINE_STATE_BLEND_COLOR,
+ [D3DRS_SRGBWRITEENABLE] = NINE_STATE_FB,
+ [D3DRS_DEPTHBIAS] = NINE_STATE_RASTERIZER,
+ [D3DRS_WRAP8] = NINE_STATE_UNHANDLED, /* cylwrap has to be done via GP */
+ [D3DRS_WRAP9] = NINE_STATE_UNHANDLED,
+ [D3DRS_WRAP10] = NINE_STATE_UNHANDLED,
+ [D3DRS_WRAP11] = NINE_STATE_UNHANDLED,
+ [D3DRS_WRAP12] = NINE_STATE_UNHANDLED,
+ [D3DRS_WRAP13] = NINE_STATE_UNHANDLED,
+ [D3DRS_WRAP14] = NINE_STATE_UNHANDLED,
+ [D3DRS_WRAP15] = NINE_STATE_UNHANDLED,
+ [D3DRS_SEPARATEALPHABLENDENABLE] = NINE_STATE_BLEND,
+ [D3DRS_SRCBLENDALPHA] = NINE_STATE_BLEND,
+ [D3DRS_DESTBLENDALPHA] = NINE_STATE_BLEND,
+ [D3DRS_BLENDOPALPHA] = NINE_STATE_BLEND
+};
+
+D3DMATRIX *
+nine_state_access_transform(struct nine_state *state, D3DTRANSFORMSTATETYPE t,
+ boolean alloc)
+{
+ static D3DMATRIX Identity = { .m[0] = { 1, 0, 0, 0 },
+ .m[1] = { 0, 1, 0, 0 },
+ .m[2] = { 0, 0, 1, 0 },
+ .m[3] = { 0, 0, 0, 1 } };
+ unsigned index;
+
+ switch (t) {
+ case D3DTS_VIEW: index = 0; break;
+ case D3DTS_PROJECTION: index = 1; break;
+ case D3DTS_TEXTURE0: index = 2; break;
+ case D3DTS_TEXTURE1: index = 3; break;
+ case D3DTS_TEXTURE2: index = 4; break;
+ case D3DTS_TEXTURE3: index = 5; break;
+ case D3DTS_TEXTURE4: index = 6; break;
+ case D3DTS_TEXTURE5: index = 7; break;
+ case D3DTS_TEXTURE6: index = 8; break;
+ case D3DTS_TEXTURE7: index = 9; break;
+ default:
+ if (!(t >= D3DTS_WORLDMATRIX(0) && t <= D3DTS_WORLDMATRIX(255)))
+ return NULL;
+ index = 10 + (t - D3DTS_WORLDMATRIX(0));
+ break;
+ }
+
+ if (index >= state->ff.num_transforms) {
+ unsigned N = index + 1;
+ unsigned n = state->ff.num_transforms;
+
+ if (!alloc)
+ return &Identity;
+ state->ff.transform = REALLOC(state->ff.transform,
+ n * sizeof(D3DMATRIX),
+ N * sizeof(D3DMATRIX));
+ for (; n < N; ++n)
+ state->ff.transform[n] = Identity;
+ state->ff.num_transforms = N;
+ }
+ return &state->ff.transform[index];
+}
+
+#define D3DRS_TO_STRING_CASE(n) case D3DRS_##n: return "D3DRS_"#n
+const char *nine_d3drs_to_string(DWORD State)
+{
+ switch (State) {
+ D3DRS_TO_STRING_CASE(ZENABLE);
+ D3DRS_TO_STRING_CASE(FILLMODE);
+ D3DRS_TO_STRING_CASE(SHADEMODE);
+ D3DRS_TO_STRING_CASE(ZWRITEENABLE);
+ D3DRS_TO_STRING_CASE(ALPHATESTENABLE);
+ D3DRS_TO_STRING_CASE(LASTPIXEL);
+ D3DRS_TO_STRING_CASE(SRCBLEND);
+ D3DRS_TO_STRING_CASE(DESTBLEND);
+ D3DRS_TO_STRING_CASE(CULLMODE);
+ D3DRS_TO_STRING_CASE(ZFUNC);
+ D3DRS_TO_STRING_CASE(ALPHAREF);
+ D3DRS_TO_STRING_CASE(ALPHAFUNC);
+ D3DRS_TO_STRING_CASE(DITHERENABLE);
+ D3DRS_TO_STRING_CASE(ALPHABLENDENABLE);
+ D3DRS_TO_STRING_CASE(FOGENABLE);
+ D3DRS_TO_STRING_CASE(SPECULARENABLE);
+ D3DRS_TO_STRING_CASE(FOGCOLOR);
+ D3DRS_TO_STRING_CASE(FOGTABLEMODE);
+ D3DRS_TO_STRING_CASE(FOGSTART);
+ D3DRS_TO_STRING_CASE(FOGEND);
+ D3DRS_TO_STRING_CASE(FOGDENSITY);
+ D3DRS_TO_STRING_CASE(RANGEFOGENABLE);
+ D3DRS_TO_STRING_CASE(STENCILENABLE);
+ D3DRS_TO_STRING_CASE(STENCILFAIL);
+ D3DRS_TO_STRING_CASE(STENCILZFAIL);
+ D3DRS_TO_STRING_CASE(STENCILPASS);
+ D3DRS_TO_STRING_CASE(STENCILFUNC);
+ D3DRS_TO_STRING_CASE(STENCILREF);
+ D3DRS_TO_STRING_CASE(STENCILMASK);
+ D3DRS_TO_STRING_CASE(STENCILWRITEMASK);
+ D3DRS_TO_STRING_CASE(TEXTUREFACTOR);
+ D3DRS_TO_STRING_CASE(WRAP0);
+ D3DRS_TO_STRING_CASE(WRAP1);
+ D3DRS_TO_STRING_CASE(WRAP2);
+ D3DRS_TO_STRING_CASE(WRAP3);
+ D3DRS_TO_STRING_CASE(WRAP4);
+ D3DRS_TO_STRING_CASE(WRAP5);
+ D3DRS_TO_STRING_CASE(WRAP6);
+ D3DRS_TO_STRING_CASE(WRAP7);
+ D3DRS_TO_STRING_CASE(CLIPPING);
+ D3DRS_TO_STRING_CASE(LIGHTING);
+ D3DRS_TO_STRING_CASE(AMBIENT);
+ D3DRS_TO_STRING_CASE(FOGVERTEXMODE);
+ D3DRS_TO_STRING_CASE(COLORVERTEX);
+ D3DRS_TO_STRING_CASE(LOCALVIEWER);
+ D3DRS_TO_STRING_CASE(NORMALIZENORMALS);
+ D3DRS_TO_STRING_CASE(DIFFUSEMATERIALSOURCE);
+ D3DRS_TO_STRING_CASE(SPECULARMATERIALSOURCE);
+ D3DRS_TO_STRING_CASE(AMBIENTMATERIALSOURCE);
+ D3DRS_TO_STRING_CASE(EMISSIVEMATERIALSOURCE);
+ D3DRS_TO_STRING_CASE(VERTEXBLEND);
+ D3DRS_TO_STRING_CASE(CLIPPLANEENABLE);
+ D3DRS_TO_STRING_CASE(POINTSIZE);
+ D3DRS_TO_STRING_CASE(POINTSIZE_MIN);
+ D3DRS_TO_STRING_CASE(POINTSPRITEENABLE);
+ D3DRS_TO_STRING_CASE(POINTSCALEENABLE);
+ D3DRS_TO_STRING_CASE(POINTSCALE_A);
+ D3DRS_TO_STRING_CASE(POINTSCALE_B);
+ D3DRS_TO_STRING_CASE(POINTSCALE_C);
+ D3DRS_TO_STRING_CASE(MULTISAMPLEANTIALIAS);
+ D3DRS_TO_STRING_CASE(MULTISAMPLEMASK);
+ D3DRS_TO_STRING_CASE(PATCHEDGESTYLE);
+ D3DRS_TO_STRING_CASE(DEBUGMONITORTOKEN);
+ D3DRS_TO_STRING_CASE(POINTSIZE_MAX);
+ D3DRS_TO_STRING_CASE(INDEXEDVERTEXBLENDENABLE);
+ D3DRS_TO_STRING_CASE(COLORWRITEENABLE);
+ D3DRS_TO_STRING_CASE(TWEENFACTOR);
+ D3DRS_TO_STRING_CASE(BLENDOP);
+ D3DRS_TO_STRING_CASE(POSITIONDEGREE);
+ D3DRS_TO_STRING_CASE(NORMALDEGREE);
+ D3DRS_TO_STRING_CASE(SCISSORTESTENABLE);
+ D3DRS_TO_STRING_CASE(SLOPESCALEDEPTHBIAS);
+ D3DRS_TO_STRING_CASE(ANTIALIASEDLINEENABLE);
+ D3DRS_TO_STRING_CASE(MINTESSELLATIONLEVEL);
+ D3DRS_TO_STRING_CASE(MAXTESSELLATIONLEVEL);
+ D3DRS_TO_STRING_CASE(ADAPTIVETESS_X);
+ D3DRS_TO_STRING_CASE(ADAPTIVETESS_Y);
+ D3DRS_TO_STRING_CASE(ADAPTIVETESS_Z);
+ D3DRS_TO_STRING_CASE(ADAPTIVETESS_W);
+ D3DRS_TO_STRING_CASE(ENABLEADAPTIVETESSELLATION);
+ D3DRS_TO_STRING_CASE(TWOSIDEDSTENCILMODE);
+ D3DRS_TO_STRING_CASE(CCW_STENCILFAIL);
+ D3DRS_TO_STRING_CASE(CCW_STENCILZFAIL);
+ D3DRS_TO_STRING_CASE(CCW_STENCILPASS);
+ D3DRS_TO_STRING_CASE(CCW_STENCILFUNC);
+ D3DRS_TO_STRING_CASE(COLORWRITEENABLE1);
+ D3DRS_TO_STRING_CASE(COLORWRITEENABLE2);
+ D3DRS_TO_STRING_CASE(COLORWRITEENABLE3);
+ D3DRS_TO_STRING_CASE(BLENDFACTOR);
+ D3DRS_TO_STRING_CASE(SRGBWRITEENABLE);
+ D3DRS_TO_STRING_CASE(DEPTHBIAS);
+ D3DRS_TO_STRING_CASE(WRAP8);
+ D3DRS_TO_STRING_CASE(WRAP9);
+ D3DRS_TO_STRING_CASE(WRAP10);
+ D3DRS_TO_STRING_CASE(WRAP11);
+ D3DRS_TO_STRING_CASE(WRAP12);
+ D3DRS_TO_STRING_CASE(WRAP13);
+ D3DRS_TO_STRING_CASE(WRAP14);
+ D3DRS_TO_STRING_CASE(WRAP15);
+ D3DRS_TO_STRING_CASE(SEPARATEALPHABLENDENABLE);
+ D3DRS_TO_STRING_CASE(SRCBLENDALPHA);
+ D3DRS_TO_STRING_CASE(DESTBLENDALPHA);
+ D3DRS_TO_STRING_CASE(BLENDOPALPHA);
+ default:
+ return "(invalid)";
+ }
+}
+
diff --git a/src/gallium/state_trackers/nine/nine_state.h b/src/gallium/state_trackers/nine/nine_state.h
new file mode 100644
index 00000000000..3e0162c9dfc
--- /dev/null
+++ b/src/gallium/state_trackers/nine/nine_state.h
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _NINE_STATE_H_
+#define _NINE_STATE_H_
+
+#include "d3d9.h"
+#include "nine_defines.h"
+#include "pipe/p_state.h"
+#include "util/u_double_list.h"
+
+#define NINED3DSAMP_MINLOD (D3DSAMP_DMAPOFFSET + 1)
+#define NINED3DSAMP_SHADOW (D3DSAMP_DMAPOFFSET + 2)
+
+#define NINED3DRS_VSPOINTSIZE (D3DRS_BLENDOPALPHA + 1)
+#define NINED3DRS_RTMASK (D3DRS_BLENDOPALPHA + 2)
+#define NINED3DRS_ZBIASSCALE (D3DRS_BLENDOPALPHA + 3)
+
+#define D3DRS_LAST D3DRS_BLENDOPALPHA
+#define NINED3DRS_LAST NINED3DRS_ZBIASSCALE /* 212 */
+#define NINED3DSAMP_LAST NINED3DSAMP_SHADOW /* 15 */
+#define NINED3DTSS_LAST D3DTSS_CONSTANT
+#define NINED3DTS_LAST D3DTS_WORLDMATRIX(255)
+
+#define D3DRS_COUNT (D3DRS_LAST + 1)
+#define NINED3DRS_COUNT (NINED3DRS_LAST + 1)
+#define NINED3DSAMP_COUNT (NINED3DSAMP_LAST + 1)
+#define NINED3DTSS_COUNT (NINED3DTSS_LAST + 1)
+#define NINED3DTS_COUNT (NINED3DTS_LAST + 1)
+
+#define NINE_STATE_FB (1 << 0)
+#define NINE_STATE_VIEWPORT (1 << 1)
+#define NINE_STATE_SCISSOR (1 << 2)
+#define NINE_STATE_RASTERIZER (1 << 3)
+#define NINE_STATE_BLEND (1 << 4)
+#define NINE_STATE_DSA (1 << 5)
+#define NINE_STATE_VS (1 << 6)
+#define NINE_STATE_VS_CONST (1 << 7)
+#define NINE_STATE_PS (1 << 8)
+#define NINE_STATE_PS_CONST (1 << 9)
+#define NINE_STATE_TEXTURE (1 << 10)
+#define NINE_STATE_SAMPLER (1 << 11)
+#define NINE_STATE_VDECL (1 << 12)
+#define NINE_STATE_IDXBUF (1 << 13)
+#define NINE_STATE_PRIM (1 << 14)
+#define NINE_STATE_MATERIAL (1 << 15)
+#define NINE_STATE_BLEND_COLOR (1 << 16)
+#define NINE_STATE_STENCIL_REF (1 << 17)
+#define NINE_STATE_SAMPLE_MASK (1 << 18)
+#define NINE_STATE_MISC_CONST (1 << 19)
+#define NINE_STATE_FF (0x1f << 20)
+#define NINE_STATE_FF_VS (0x17 << 20)
+#define NINE_STATE_FF_PS (0x18 << 20)
+#define NINE_STATE_FF_LIGHTING (1 << 20)
+#define NINE_STATE_FF_MATERIAL (1 << 21)
+#define NINE_STATE_FF_VSTRANSF (1 << 22)
+#define NINE_STATE_FF_PSSTAGES (1 << 23)
+#define NINE_STATE_FF_OTHER (1 << 24)
+#define NINE_STATE_ALL 0x1ffffff
+#define NINE_STATE_UNHANDLED (1 << 25)
+
+
+#define NINE_MAX_SIMULTANEOUS_RENDERTARGETS 4
+#define NINE_MAX_CONST_F 256
+#define NINE_MAX_CONST_I 16
+#define NINE_MAX_CONST_B 16
+#define NINE_MAX_CONST_ALL 276 /* B consts count only 1/4 th */
+
+#define NINE_CONST_I_BASE(nconstf) \
+ ((nconstf) * 4 * sizeof(float))
+#define NINE_CONST_B_BASE(nconstf) \
+ ((nconstf) * 4 * sizeof(float) + \
+ NINE_MAX_CONST_I * 4 * sizeof(int))
+
+#define NINE_CONSTBUF_SIZE(nconstf) \
+ ((nconstf) * 4 * sizeof(float) + \
+ NINE_MAX_CONST_I * 4 * sizeof(int) + \
+ NINE_MAX_CONST_B * 1 * sizeof(float))
+
+
+#define NINE_MAX_LIGHTS 65536
+#define NINE_MAX_LIGHTS_ACTIVE 8
+
+#define NINED3DLIGHT_INVALID (D3DLIGHT_DIRECTIONAL + 1)
+
+#define NINE_MAX_SAMPLERS_PS 16
+#define NINE_MAX_SAMPLERS_VS 4
+#define NINE_MAX_SAMPLERS 21 /* PS + DMAP + VS */
+#define NINE_SAMPLER_PS(s) ( 0 + (s))
+#define NINE_SAMPLER_DMAP 16
+#define NINE_SAMPLER_VS(s) (17 + (s))
+#define NINE_PS_SAMPLERS_MASK 0x00ffff
+#define NINE_VS_SAMPLERS_MASK 0x1e0000
+
+struct nine_state
+{
+ struct {
+ uint32_t group;
+ uint32_t rs[(NINED3DRS_COUNT + 31) / 32];
+ uint32_t vtxbuf;
+ uint32_t stream_freq;
+ uint32_t texture;
+ uint16_t sampler[NINE_MAX_SAMPLERS];
+ struct nine_range *vs_const_f;
+ struct nine_range *ps_const_f;
+ uint16_t vs_const_i; /* NINE_MAX_CONST_I == 16 */
+ uint16_t ps_const_i;
+ uint16_t vs_const_b; /* NINE_MAX_CONST_B == 16 */
+ uint16_t ps_const_b;
+ uint8_t ucp;
+ } changed;
+
+ struct NineSurface9 *rt[NINE_MAX_SIMULTANEOUS_RENDERTARGETS];
+ struct NineSurface9 *ds;
+
+ D3DVIEWPORT9 viewport;
+
+ struct pipe_scissor_state scissor;
+
+ /* NOTE: vs, ps will be NULL for FF and are set in device->ff.vs,ps instead
+ * (XXX: or is it better to reference FF shaders here, too ?)
+ * NOTE: const_f contains extra space for const_i,b to use as user constbuf
+ */
+ struct NineVertexShader9 *vs;
+ float *vs_const_f;
+ int vs_const_i[NINE_MAX_CONST_I][4];
+ BOOL vs_const_b[NINE_MAX_CONST_B];
+ uint32_t vs_key;
+
+ struct NinePixelShader9 *ps;
+ float *ps_const_f;
+ int ps_const_i[NINE_MAX_CONST_I][4];
+ BOOL ps_const_b[NINE_MAX_CONST_B];
+ uint32_t ps_key;
+
+ struct {
+ void *vs;
+ void *ps;
+ } cso;
+
+ struct NineVertexDeclaration9 *vdecl;
+
+ struct NineIndexBuffer9 *idxbuf;
+ struct NineVertexBuffer9 *stream[PIPE_MAX_ATTRIBS];
+ struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS];
+ UINT stream_freq[PIPE_MAX_ATTRIBS];
+ uint32_t stream_instancedata_mask; /* derived from stream_freq */
+ uint32_t stream_usage_mask; /* derived from VS and vdecl */
+
+ struct pipe_clip_state clip;
+ struct pipe_framebuffer_state fb;
+ uint8_t rt_mask;
+
+ DWORD rs[NINED3DRS_COUNT];
+
+ struct NineBaseTexture9 *texture[NINE_MAX_SAMPLERS]; /* PS, DMAP, VS */
+
+ DWORD samp[NINE_MAX_SAMPLERS][NINED3DSAMP_COUNT];
+ uint32_t samplers_shadow;
+
+ struct {
+ struct {
+ uint32_t group;
+ uint32_t tex_stage[NINE_MAX_SAMPLERS][(NINED3DTSS_COUNT + 31) / 32];
+ uint32_t transform[(NINED3DTS_COUNT + 31) / 32];
+ } changed;
+ struct {
+ boolean vs_const;
+ boolean ps_const;
+ } clobber;
+
+ D3DMATRIX *transform; /* access only via nine_state_access_transform */
+ unsigned num_transforms;
+
+ /* XXX: Do state blocks just change the set of active lights or do we
+ * have to store which lights have been disabled, too ?
+ */
+ D3DLIGHT9 *light;
+ uint16_t active_light[NINE_MAX_LIGHTS_ACTIVE]; /* 8 */
+ unsigned num_lights;
+ unsigned num_lights_active;
+
+ D3DMATERIAL9 material;
+
+ DWORD tex_stage[NINE_MAX_SAMPLERS][NINED3DTSS_COUNT];
+ } ff;
+};
+
+/* map D3DRS -> NINE_STATE_x
+ */
+extern const uint32_t nine_render_state_group[NINED3DRS_COUNT];
+
+/* for D3DSBT_PIXEL/VERTEX:
+ */
+extern const uint32_t nine_render_states_pixel[(NINED3DRS_COUNT + 31) / 32];
+extern const uint32_t nine_render_states_vertex[(NINED3DRS_COUNT + 31) / 32];
+
+struct NineDevice9;
+
+boolean nine_update_state(struct NineDevice9 *, uint32_t group_mask);
+
+void nine_state_set_defaults(struct nine_state *, const D3DCAPS9 *,
+ boolean is_reset);
+void nine_state_clear(struct nine_state *, const boolean device);
+
+/* If @alloc is FALSE, the return value may be a const identity matrix.
+ * Therefore, do not modify if you set alloc to FALSE !
+ */
+D3DMATRIX *
+nine_state_access_transform(struct nine_state *, D3DTRANSFORMSTATETYPE,
+ boolean alloc);
+
+const char *nine_d3drs_to_string(DWORD State);
+
+#endif /* _NINE_STATE_H_ */
diff --git a/src/gallium/state_trackers/nine/nineexoverlayextension.c b/src/gallium/state_trackers/nine/nineexoverlayextension.c
new file mode 100644
index 00000000000..2253f8d9789
--- /dev/null
+++ b/src/gallium/state_trackers/nine/nineexoverlayextension.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "nineexoverlayextension.h"
+
+#define DBG_CHANNEL DBG_OVERLAYEXTENSION
+
+HRESULT WINAPI
+Nine9ExOverlayExtension_CheckDeviceOverlayType( struct Nine9ExOverlayExtension *This,
+ UINT Adapter,
+ D3DDEVTYPE DevType,
+ UINT OverlayWidth,
+ UINT OverlayHeight,
+ D3DFORMAT OverlayFormat,
+ D3DDISPLAYMODEEX *pDisplayMode,
+ D3DDISPLAYROTATION DisplayRotation,
+ D3DOVERLAYCAPS *pOverlayCaps )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+IDirect3D9ExOverlayExtensionVtbl Nine9ExOverlayExtension_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)Nine9ExOverlayExtension_CheckDeviceOverlayType
+};
diff --git a/src/gallium/state_trackers/nine/nineexoverlayextension.h b/src/gallium/state_trackers/nine/nineexoverlayextension.h
new file mode 100644
index 00000000000..a16d690dc8c
--- /dev/null
+++ b/src/gallium/state_trackers/nine/nineexoverlayextension.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _NINE_NINEEXOVERLAYEXTENSION_H_
+#define _NINE_NINEEXOVERLAYEXTENSION_H_
+
+#include "iunknown.h"
+
+struct Nine9ExOverlayExtension
+{
+ struct NineUnknown base;
+};
+static INLINE struct Nine9ExOverlayExtension *
+Nine9ExOverlayExtension( void *data )
+{
+ return (struct Nine9ExOverlayExtension *)data;
+}
+
+HRESULT WINAPI
+Nine9ExOverlayExtension_CheckDeviceOverlayType( struct Nine9ExOverlayExtension *This,
+ UINT Adapter,
+ D3DDEVTYPE DevType,
+ UINT OverlayWidth,
+ UINT OverlayHeight,
+ D3DFORMAT OverlayFormat,
+ D3DDISPLAYMODEEX *pDisplayMode,
+ D3DDISPLAYROTATION DisplayRotation,
+ D3DOVERLAYCAPS *pOverlayCaps );
+
+#endif /* _NINE_NINEEXOVERLAYEXTENSION_H_ */
diff --git a/src/gallium/state_trackers/nine/pixelshader9.c b/src/gallium/state_trackers/nine/pixelshader9.c
new file mode 100644
index 00000000000..3d68274aa01
--- /dev/null
+++ b/src/gallium/state_trackers/nine/pixelshader9.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "nine_helpers.h"
+#include "nine_shader.h"
+
+#include "pixelshader9.h"
+
+#include "device9.h"
+#include "pipe/p_context.h"
+
+#define DBG_CHANNEL DBG_PIXELSHADER
+
+HRESULT
+NinePixelShader9_ctor( struct NinePixelShader9 *This,
+ struct NineUnknownParams *pParams,
+ const DWORD *pFunction, void *cso )
+{
+ struct NineDevice9 *device;
+ struct nine_shader_info info;
+ HRESULT hr;
+
+ hr = NineUnknown_ctor(&This->base, pParams);
+ if (FAILED(hr))
+ return hr;
+
+ if (cso) {
+ This->variant.cso = cso;
+ return D3D_OK;
+ }
+ device = This->base.device;
+
+ info.type = PIPE_SHADER_FRAGMENT;
+ info.byte_code = pFunction;
+ info.const_i_base = NINE_CONST_I_BASE(device->max_ps_const_f) / 16;
+ info.const_b_base = NINE_CONST_B_BASE(device->max_ps_const_f) / 16;
+ info.sampler_mask_shadow = 0x0;
+ info.sampler_ps1xtypes = 0x0;
+
+ hr = nine_translate_shader(device, &info);
+ if (FAILED(hr))
+ return hr;
+ This->byte_code.version = info.version;
+
+ This->byte_code.tokens = mem_dup(pFunction, info.byte_size);
+ if (!This->byte_code.tokens)
+ return E_OUTOFMEMORY;
+ This->byte_code.size = info.byte_size;
+
+ This->variant.cso = info.cso;
+ This->sampler_mask = info.sampler_mask;
+ This->rt_mask = info.rt_mask;
+ This->const_used_size = info.const_used_size;
+ if (info.const_used_size == ~0)
+ This->const_used_size = NINE_CONSTBUF_SIZE(device->max_ps_const_f);
+ This->lconstf = info.lconstf;
+
+ return D3D_OK;
+}
+
+void
+NinePixelShader9_dtor( struct NinePixelShader9 *This )
+{
+ DBG("This=%p cso=%p\n", This, This->variant.cso);
+
+ if (This->base.device) {
+ struct pipe_context *pipe = This->base.device->pipe;
+ struct nine_shader_variant *var = &This->variant;
+ do {
+ if (var->cso) {
+ if (This->base.device->state.cso.ps == var->cso)
+ pipe->bind_fs_state(pipe, NULL);
+ pipe->delete_fs_state(pipe, var->cso);
+ }
+ var = var->next;
+ } while (var);
+ }
+ nine_shader_variants_free(&This->variant);
+
+ if (This->byte_code.tokens)
+ FREE((void *)This->byte_code.tokens); /* const_cast */
+
+ FREE(This->lconstf.data);
+ FREE(This->lconstf.ranges);
+
+ NineUnknown_dtor(&This->base);
+}
+
+HRESULT WINAPI
+NinePixelShader9_GetFunction( struct NinePixelShader9 *This,
+ void *pData,
+ UINT *pSizeOfData )
+{
+ user_assert(pSizeOfData, D3DERR_INVALIDCALL);
+
+ if (!pData) {
+ *pSizeOfData = This->byte_code.size;
+ return D3D_OK;
+ }
+ user_assert(*pSizeOfData >= This->byte_code.size, D3DERR_INVALIDCALL);
+
+ memcpy(pData, This->byte_code.tokens, This->byte_code.size);
+
+ return D3D_OK;
+}
+
+void *
+NinePixelShader9_GetVariant( struct NinePixelShader9 *This,
+ uint32_t key )
+{
+ void *cso = nine_shader_variant_get(&This->variant, key);
+ if (!cso) {
+ struct NineDevice9 *device = This->base.device;
+ struct nine_shader_info info;
+ HRESULT hr;
+
+ info.type = PIPE_SHADER_FRAGMENT;
+ info.const_i_base = NINE_CONST_I_BASE(device->max_ps_const_f) / 16;
+ info.const_b_base = NINE_CONST_B_BASE(device->max_ps_const_f) / 16;
+ info.byte_code = This->byte_code.tokens;
+ info.sampler_mask_shadow = key & 0xffff;
+ info.sampler_ps1xtypes = key;
+
+ hr = nine_translate_shader(This->base.device, &info);
+ if (FAILED(hr))
+ return NULL;
+ nine_shader_variant_add(&This->variant, key, info.cso);
+ cso = info.cso;
+ }
+ return cso;
+}
+
+IDirect3DPixelShader9Vtbl NinePixelShader9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)NineUnknown_GetDevice,
+ (void *)NinePixelShader9_GetFunction
+};
+
+static const GUID *NinePixelShader9_IIDs[] = {
+ &IID_IDirect3DPixelShader9,
+ &IID_IUnknown,
+ NULL
+};
+
+HRESULT
+NinePixelShader9_new( struct NineDevice9 *pDevice,
+ struct NinePixelShader9 **ppOut,
+ const DWORD *pFunction, void *cso )
+{
+ NINE_DEVICE_CHILD_NEW(PixelShader9, ppOut, pDevice, pFunction, cso);
+}
diff --git a/src/gallium/state_trackers/nine/pixelshader9.h b/src/gallium/state_trackers/nine/pixelshader9.h
new file mode 100644
index 00000000000..5e00b46e0c5
--- /dev/null
+++ b/src/gallium/state_trackers/nine/pixelshader9.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _NINE_PIXELSHADER9_H_
+#define _NINE_PIXELSHADER9_H_
+
+#include "iunknown.h"
+#include "nine_shader.h"
+
+struct nine_lconstf;
+
+struct NinePixelShader9
+{
+ struct NineUnknown base;
+ struct nine_shader_variant variant;
+
+ struct {
+ const DWORD *tokens;
+ DWORD size;
+ uint8_t version; /* (major << 4) | minor */
+ } byte_code;
+
+ unsigned const_used_size; /* in bytes */
+
+ struct nine_lconstf lconstf;
+
+ uint16_t sampler_mask;
+ uint16_t sampler_mask_shadow;
+ uint8_t rt_mask;
+
+ uint64_t ff_key[6];
+};
+static INLINE struct NinePixelShader9 *
+NinePixelShader9( void *data )
+{
+ return (struct NinePixelShader9 *)data;
+}
+
+void *
+NinePixelShader9_GetVariant( struct NinePixelShader9 *vs,
+ uint32_t key );
+
+/*** public ***/
+
+HRESULT
+NinePixelShader9_new( struct NineDevice9 *pDevice,
+ struct NinePixelShader9 **ppOut,
+ const DWORD *pFunction, void *cso );
+
+HRESULT
+NinePixelShader9_ctor( struct NinePixelShader9 *,
+ struct NineUnknownParams *pParams,
+ const DWORD *pFunction, void *cso );
+
+void
+NinePixelShader9_dtor( struct NinePixelShader9 * );
+
+HRESULT WINAPI
+NinePixelShader9_GetFunction( struct NinePixelShader9 *This,
+ void *pData,
+ UINT *pSizeOfData );
+
+#endif /* _NINE_PIXELSHADER9_H_ */
diff --git a/src/gallium/state_trackers/nine/query9.c b/src/gallium/state_trackers/nine/query9.c
new file mode 100644
index 00000000000..86762d2e697
--- /dev/null
+++ b/src/gallium/state_trackers/nine/query9.c
@@ -0,0 +1,358 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "device9.h"
+#include "query9.h"
+#include "nine_helpers.h"
+#include "pipe/p_context.h"
+#include "util/u_math.h"
+#include "nine_dump.h"
+
+#define DBG_CHANNEL DBG_QUERY
+
+#define QUERY_TYPE_MAP_CASE(a, b) case D3DQUERYTYPE_##a: return PIPE_QUERY_##b
+static inline unsigned
+d3dquerytype_to_pipe_query(D3DQUERYTYPE type)
+{
+ switch (type) {
+ QUERY_TYPE_MAP_CASE(EVENT, GPU_FINISHED);
+ QUERY_TYPE_MAP_CASE(OCCLUSION, OCCLUSION_COUNTER);
+ QUERY_TYPE_MAP_CASE(TIMESTAMP, TIMESTAMP);
+ QUERY_TYPE_MAP_CASE(TIMESTAMPDISJOINT, TIMESTAMP_DISJOINT);
+ QUERY_TYPE_MAP_CASE(TIMESTAMPFREQ, TIMESTAMP_DISJOINT);
+ QUERY_TYPE_MAP_CASE(VERTEXSTATS, PIPELINE_STATISTICS);
+ case D3DQUERYTYPE_VCACHE:
+ case D3DQUERYTYPE_RESOURCEMANAGER:
+ case D3DQUERYTYPE_PIPELINETIMINGS:
+ case D3DQUERYTYPE_INTERFACETIMINGS:
+ case D3DQUERYTYPE_VERTEXTIMINGS:
+ case D3DQUERYTYPE_PIXELTIMINGS:
+ case D3DQUERYTYPE_BANDWIDTHTIMINGS:
+ case D3DQUERYTYPE_CACHEUTILIZATION:
+ return PIPE_QUERY_TYPES;
+ default:
+ return ~0;
+ }
+}
+
+#define GET_DATA_SIZE_CASE9(a) case D3DQUERYTYPE_##a: return sizeof(D3DDEVINFO_D3D9##a)
+#define GET_DATA_SIZE_CASE1(a) case D3DQUERYTYPE_##a: return sizeof(D3DDEVINFO_##a)
+#define GET_DATA_SIZE_CASE2(a, b) case D3DQUERYTYPE_##a: return sizeof(D3DDEVINFO_##b)
+#define GET_DATA_SIZE_CASET(a, b) case D3DQUERYTYPE_##a: return sizeof(b)
+static INLINE DWORD
+nine_query_result_size(D3DQUERYTYPE type)
+{
+ switch (type) {
+ GET_DATA_SIZE_CASE1(VCACHE);
+ GET_DATA_SIZE_CASE1(RESOURCEMANAGER);
+ GET_DATA_SIZE_CASE2(VERTEXSTATS, D3DVERTEXSTATS);
+ GET_DATA_SIZE_CASET(EVENT, BOOL);
+ GET_DATA_SIZE_CASET(OCCLUSION, DWORD);
+ GET_DATA_SIZE_CASET(TIMESTAMP, UINT64);
+ GET_DATA_SIZE_CASET(TIMESTAMPDISJOINT, BOOL);
+ GET_DATA_SIZE_CASET(TIMESTAMPFREQ, UINT64);
+ GET_DATA_SIZE_CASE9(PIPELINETIMINGS);
+ GET_DATA_SIZE_CASE9(INTERFACETIMINGS);
+ GET_DATA_SIZE_CASE2(VERTEXTIMINGS, D3D9STAGETIMINGS);
+ GET_DATA_SIZE_CASE2(PIXELTIMINGS, D3D9STAGETIMINGS);
+ GET_DATA_SIZE_CASE9(BANDWIDTHTIMINGS);
+ GET_DATA_SIZE_CASE9(CACHEUTILIZATION);
+ /* GET_DATA_SIZE_CASE1(MEMORYPRESSURE); Win7 only */
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+HRESULT
+nine_is_query_supported(D3DQUERYTYPE type)
+{
+ const unsigned ptype = d3dquerytype_to_pipe_query(type);
+
+ user_assert(ptype != ~0, D3DERR_INVALIDCALL);
+
+ if (ptype == PIPE_QUERY_TYPES) {
+ DBG("Query type %u (%s) not supported.\n",
+ type, nine_D3DQUERYTYPE_to_str(type));
+ return D3DERR_NOTAVAILABLE;
+ }
+ return D3D_OK;
+}
+
+HRESULT
+NineQuery9_ctor( struct NineQuery9 *This,
+ struct NineUnknownParams *pParams,
+ D3DQUERYTYPE Type )
+{
+ struct pipe_context *pipe = pParams->device->pipe;
+ const unsigned ptype = d3dquerytype_to_pipe_query(Type);
+ HRESULT hr;
+
+ hr = NineUnknown_ctor(&This->base, pParams);
+ if (FAILED(hr))
+ return hr;
+
+ This->state = NINE_QUERY_STATE_FRESH;
+ This->type = Type;
+
+ user_assert(ptype != ~0, D3DERR_INVALIDCALL);
+
+ if (ptype < PIPE_QUERY_TYPES) {
+ This->pq = pipe->create_query(pipe, ptype, 0);
+ if (!This->pq)
+ return E_OUTOFMEMORY;
+ } else {
+ DBG("Returning dummy NineQuery9 for %s.\n",
+ nine_D3DQUERYTYPE_to_str(Type));
+ }
+
+ This->instant =
+ Type == D3DQUERYTYPE_EVENT ||
+ Type == D3DQUERYTYPE_RESOURCEMANAGER ||
+ Type == D3DQUERYTYPE_TIMESTAMP ||
+ Type == D3DQUERYTYPE_TIMESTAMPFREQ ||
+ Type == D3DQUERYTYPE_VCACHE ||
+ Type == D3DQUERYTYPE_VERTEXSTATS;
+
+ This->result_size = nine_query_result_size(Type);
+
+ return D3D_OK;
+}
+
+void
+NineQuery9_dtor( struct NineQuery9 *This )
+{
+ struct pipe_context *pipe = This->base.device->pipe;
+
+ if (This->pq) {
+ if (This->state == NINE_QUERY_STATE_RUNNING)
+ pipe->end_query(pipe, This->pq);
+ pipe->destroy_query(pipe, This->pq);
+ }
+
+ NineUnknown_dtor(&This->base);
+}
+
+D3DQUERYTYPE WINAPI
+NineQuery9_GetType( struct NineQuery9 *This )
+{
+ return This->type;
+}
+
+DWORD WINAPI
+NineQuery9_GetDataSize( struct NineQuery9 *This )
+{
+ return This->result_size;
+}
+
+HRESULT WINAPI
+NineQuery9_Issue( struct NineQuery9 *This,
+ DWORD dwIssueFlags )
+{
+ struct pipe_context *pipe = This->base.device->pipe;
+
+ user_assert((dwIssueFlags == D3DISSUE_BEGIN && !This->instant) ||
+ (dwIssueFlags == 0) ||
+ (dwIssueFlags == D3DISSUE_END), D3DERR_INVALIDCALL);
+
+ if (!This->pq) {
+ DBG("Issued dummy query.\n");
+ return D3D_OK;
+ }
+
+ if (dwIssueFlags == D3DISSUE_BEGIN) {
+ if (This->state == NINE_QUERY_STATE_RUNNING) {
+ pipe->end_query(pipe, This->pq);
+ }
+ pipe->begin_query(pipe, This->pq);
+ This->state = NINE_QUERY_STATE_RUNNING;
+ } else {
+ if (This->state == NINE_QUERY_STATE_RUNNING) {
+ pipe->end_query(pipe, This->pq);
+ This->state = NINE_QUERY_STATE_ENDED;
+ }
+ }
+ return D3D_OK;
+}
+
+union nine_query_result
+{
+ D3DDEVINFO_D3DVERTEXSTATS vertexstats;
+ D3DDEVINFO_D3D9BANDWIDTHTIMINGS bandwidth;
+ D3DDEVINFO_VCACHE vcache;
+ D3DDEVINFO_RESOURCEMANAGER rm;
+ D3DDEVINFO_D3D9PIPELINETIMINGS pipe;
+ D3DDEVINFO_D3D9STAGETIMINGS stage;
+ D3DDEVINFO_D3D9INTERFACETIMINGS iface;
+ D3DDEVINFO_D3D9CACHEUTILIZATION cacheu;
+ DWORD dw;
+ BOOL b;
+ UINT64 u64;
+};
+
+HRESULT WINAPI
+NineQuery9_GetData( struct NineQuery9 *This,
+ void *pData,
+ DWORD dwSize,
+ DWORD dwGetDataFlags )
+{
+ struct pipe_context *pipe = This->base.device->pipe;
+ boolean ok = !This->pq;
+ unsigned i;
+ union pipe_query_result presult;
+ union nine_query_result nresult;
+
+ user_assert(This->state != NINE_QUERY_STATE_RUNNING, D3DERR_INVALIDCALL);
+ user_assert(dwSize == 0 || pData, D3DERR_INVALIDCALL);
+ user_assert(dwGetDataFlags == 0 ||
+ dwGetDataFlags == D3DGETDATA_FLUSH, D3DERR_INVALIDCALL);
+
+ if (!This->pq) {
+ DBG("No pipe query available.\n");
+ if (!dwSize)
+ return S_OK;
+ }
+ if (This->state == NINE_QUERY_STATE_FRESH)
+ return S_OK;
+
+ if (!ok) {
+ ok = pipe->get_query_result(pipe, This->pq, FALSE, &presult);
+ if (!ok) {
+ if (dwGetDataFlags) {
+ if (This->state != NINE_QUERY_STATE_FLUSHED)
+ pipe->flush(pipe, NULL, 0);
+ This->state = NINE_QUERY_STATE_FLUSHED;
+ }
+ return S_FALSE;
+ }
+ }
+ if (!dwSize)
+ return S_OK;
+
+ switch (This->type) {
+ case D3DQUERYTYPE_EVENT:
+ nresult.b = presult.b;
+ break;
+ case D3DQUERYTYPE_OCCLUSION:
+ nresult.dw = presult.u64;
+ break;
+ case D3DQUERYTYPE_TIMESTAMP:
+ nresult.u64 = presult.u64;
+ break;
+ case D3DQUERYTYPE_TIMESTAMPDISJOINT:
+ nresult.b = presult.timestamp_disjoint.disjoint;
+ break;
+ case D3DQUERYTYPE_TIMESTAMPFREQ:
+ nresult.u64 = presult.timestamp_disjoint.frequency;
+ break;
+ case D3DQUERYTYPE_VERTEXSTATS:
+ nresult.vertexstats.NumRenderedTriangles =
+ presult.pipeline_statistics.c_invocations;
+ nresult.vertexstats.NumExtraClippingTriangles =
+ presult.pipeline_statistics.c_primitives;
+ break;
+ /* Thse might be doable with driver-specific queries; dummy for now. */
+ case D3DQUERYTYPE_BANDWIDTHTIMINGS:
+ nresult.bandwidth.MaxBandwidthUtilized = 1.0f;
+ nresult.bandwidth.FrontEndUploadMemoryUtilizedPercent = 0.5f;
+ nresult.bandwidth.VertexRateUtilizedPercent = 0.75f;
+ nresult.bandwidth.TriangleSetupRateUtilizedPercent = 0.75f;
+ nresult.bandwidth.FillRateUtilizedPercent = 1.0f;
+ break;
+ case D3DQUERYTYPE_VERTEXTIMINGS:
+ case D3DQUERYTYPE_PIXELTIMINGS:
+ nresult.stage.MemoryProcessingPercent = 0.5f;
+ nresult.stage.ComputationProcessingPercent = 0.5f;
+ break;
+ case D3DQUERYTYPE_VCACHE:
+ /* Are we supposed to fill this in ? */
+ nresult.vcache.Pattern = MAKEFOURCC('C', 'A', 'C', 'H');
+ nresult.vcache.OptMethod = 1;
+ nresult.vcache.CacheSize = 32 << 10;
+ nresult.vcache.MagicNumber = 0xdeadcafe;
+ break;
+ case D3DQUERYTYPE_RESOURCEMANAGER:
+ /* We could record some of these in the device ... */
+ for (i = 0; i < D3DRTYPECOUNT; ++i) {
+ nresult.rm.stats[i].bThrashing = FALSE;
+ nresult.rm.stats[i].ApproxBytesDownloaded = 0;
+ nresult.rm.stats[i].NumEvicts = 0;
+ nresult.rm.stats[i].NumVidCreates = 0;
+ nresult.rm.stats[i].LastPri = 0;
+ nresult.rm.stats[i].NumUsed = 1;
+ nresult.rm.stats[i].NumUsedInVidMem = 1;
+ nresult.rm.stats[i].WorkingSet = 1;
+ nresult.rm.stats[i].WorkingSetBytes = 1 << 20;
+ nresult.rm.stats[i].TotalManaged = 1;
+ nresult.rm.stats[i].TotalBytes = 1 << 20;
+ }
+ break;
+ case D3DQUERYTYPE_PIPELINETIMINGS:
+ nresult.pipe.VertexProcessingTimePercent = 0.4f;
+ nresult.pipe.PixelProcessingTimePercent = 0.4f;
+ nresult.pipe.OtherGPUProcessingTimePercent = 0.15f;
+ nresult.pipe.GPUIdleTimePercent = 0.05f;
+ break;
+ case D3DQUERYTYPE_INTERFACETIMINGS:
+ nresult.iface.WaitingForGPUToUseApplicationResourceTimePercent = 0.0f;
+ nresult.iface.WaitingForGPUToAcceptMoreCommandsTimePercent = 0.0f;
+ nresult.iface.WaitingForGPUToStayWithinLatencyTimePercent = 0.0f;
+ nresult.iface.WaitingForGPUExclusiveResourceTimePercent = 0.0f;
+ nresult.iface.WaitingForGPUOtherTimePercent = 0.0f;
+ break;
+ case D3DQUERYTYPE_CACHEUTILIZATION:
+ nresult.cacheu.TextureCacheHitRate = 0.9f;
+ nresult.cacheu.PostTransformVertexCacheHitRate = 0.3f;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ memcpy(pData, &nresult, MIN2(sizeof(nresult), dwSize));
+
+ return S_OK;
+}
+
+IDirect3DQuery9Vtbl NineQuery9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)NineUnknown_GetDevice, /* actually part of Query9 iface */
+ (void *)NineQuery9_GetType,
+ (void *)NineQuery9_GetDataSize,
+ (void *)NineQuery9_Issue,
+ (void *)NineQuery9_GetData
+};
+
+static const GUID *NineQuery9_IIDs[] = {
+ &IID_IDirect3DQuery9,
+ &IID_IUnknown,
+ NULL
+};
+
+HRESULT
+NineQuery9_new( struct NineDevice9 *pDevice,
+ struct NineQuery9 **ppOut,
+ D3DQUERYTYPE Type )
+{
+ NINE_DEVICE_CHILD_NEW(Query9, ppOut, pDevice, Type);
+}
diff --git a/src/gallium/state_trackers/nine/query9.h b/src/gallium/state_trackers/nine/query9.h
new file mode 100644
index 00000000000..f08393fcf34
--- /dev/null
+++ b/src/gallium/state_trackers/nine/query9.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _NINE_QUERY9_H_
+#define _NINE_QUERY9_H_
+
+#include "iunknown.h"
+
+enum nine_query_state
+{
+ NINE_QUERY_STATE_FRESH = 0,
+ NINE_QUERY_STATE_RUNNING,
+ NINE_QUERY_STATE_ENDED,
+ NINE_QUERY_STATE_FLUSHED
+};
+
+struct NineQuery9
+{
+ struct NineUnknown base;
+ struct pipe_query *pq;
+ DWORD result_size;
+ D3DQUERYTYPE type;
+ enum nine_query_state state;
+ boolean instant; /* true if D3DISSUE_BEGIN is not needed / invalid */
+};
+static INLINE struct NineQuery9 *
+NineQuery9( void *data )
+{
+ return (struct NineQuery9 *)data;
+}
+
+HRESULT
+nine_is_query_supported(D3DQUERYTYPE);
+
+HRESULT
+NineQuery9_new( struct NineDevice9 *Device,
+ struct NineQuery9 **ppOut,
+ D3DQUERYTYPE);
+
+HRESULT
+NineQuery9_ctor( struct NineQuery9 *,
+ struct NineUnknownParams *pParams,
+ D3DQUERYTYPE Type );
+
+void
+NineQuery9_dtor( struct NineQuery9 * );
+
+D3DQUERYTYPE WINAPI
+NineQuery9_GetType( struct NineQuery9 *This );
+
+DWORD WINAPI
+NineQuery9_GetDataSize( struct NineQuery9 *This );
+
+HRESULT WINAPI
+NineQuery9_Issue( struct NineQuery9 *This,
+ DWORD dwIssueFlags );
+
+HRESULT WINAPI
+NineQuery9_GetData( struct NineQuery9 *This,
+ void *pData,
+ DWORD dwSize,
+ DWORD dwGetDataFlags );
+
+#endif /* _NINE_QUERY9_H_ */
diff --git a/src/gallium/state_trackers/nine/resource9.c b/src/gallium/state_trackers/nine/resource9.c
new file mode 100644
index 00000000000..8f535580bbf
--- /dev/null
+++ b/src/gallium/state_trackers/nine/resource9.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "resource9.h"
+#include "device9.h"
+#include "nine_helpers.h"
+#include "nine_defines.h"
+
+#include "pipe/p_screen.h"
+
+#include "util/u_hash_table.h"
+#include "util/u_inlines.h"
+
+#include "nine_pdata.h"
+
+#define DBG_CHANNEL DBG_RESOURCE
+
+
+HRESULT
+NineResource9_ctor( struct NineResource9 *This,
+ struct NineUnknownParams *pParams,
+ BOOL Allocate,
+ D3DRESOURCETYPE Type,
+ D3DPOOL Pool )
+{
+ struct pipe_screen *screen;
+ HRESULT hr;
+
+ hr = NineUnknown_ctor(&This->base, pParams);
+ if (FAILED(hr))
+ return hr;
+
+ This->info.screen = screen = This->base.device->screen;
+
+ if (Allocate) {
+ DBG("(%p) Creating pipe_resource.\n", This);
+ This->resource = screen->resource_create(screen, &This->info);
+ if (!This->resource)
+ return D3DERR_OUTOFVIDEOMEMORY;
+ }
+
+ This->data = NULL; /* FIXME remove, rather set it to null in surface9.c*/
+ This->type = Type;
+ This->pool = Pool;
+ This->priority = 0;
+
+ This->pdata = util_hash_table_create(ht_guid_hash, ht_guid_compare);
+ if (!This->pdata)
+ return E_OUTOFMEMORY;
+
+ return D3D_OK;
+}
+
+void
+NineResource9_dtor( struct NineResource9 *This )
+{
+ if (This->pdata) {
+ util_hash_table_foreach(This->pdata, ht_guid_delete, NULL);
+ util_hash_table_destroy(This->pdata);
+ }
+
+ /* NOTE: We do have to use refcounting, the driver might
+ * still hold a reference. */
+ pipe_resource_reference(&This->resource, NULL);
+
+ /* release allocated system memory for non-D3DPOOL_DEFAULT resources */
+ if (This->data)
+ FREE(This->data);
+
+ NineUnknown_dtor(&This->base);
+}
+
+struct pipe_resource *
+NineResource9_GetResource( struct NineResource9 *This )
+{
+ return This->resource;
+}
+
+D3DPOOL
+NineResource9_GetPool( struct NineResource9 *This )
+{
+ return This->pool;
+}
+
+HRESULT WINAPI
+NineResource9_SetPrivateData( struct NineResource9 *This,
+ REFGUID refguid,
+ const void *pData,
+ DWORD SizeOfData,
+ DWORD Flags )
+{
+ enum pipe_error err;
+ struct pheader *header;
+ const void *user_data = pData;
+
+ DBG("This=%p refguid=%p pData=%p SizeOfData=%u Flags=%x\n",
+ This, refguid, pData, SizeOfData, Flags);
+
+ if (Flags & D3DSPD_IUNKNOWN)
+ user_assert(SizeOfData == sizeof(IUnknown *), D3DERR_INVALIDCALL);
+
+ /* data consists of a header and the actual data. avoiding 2 mallocs */
+ header = CALLOC_VARIANT_LENGTH_STRUCT(pheader, SizeOfData-1);
+ if (!header) { return E_OUTOFMEMORY; }
+ header->unknown = (Flags & D3DSPD_IUNKNOWN) ? TRUE : FALSE;
+
+ /* if the refguid already exists, delete it */
+ NineResource9_FreePrivateData(This, refguid);
+
+ /* IUnknown special case */
+ if (header->unknown) {
+ /* here the pointer doesn't point to the data we want, so point at the
+ * pointer making what we eventually copy is the pointer itself */
+ user_data = &pData;
+ }
+
+ header->size = SizeOfData;
+ memcpy(header->data, user_data, header->size);
+
+ err = util_hash_table_set(This->pdata, refguid, header);
+ if (err == PIPE_OK) {
+ if (header->unknown) { IUnknown_AddRef(*(IUnknown **)header->data); }
+ return D3D_OK;
+ }
+
+ FREE(header);
+ if (err == PIPE_ERROR_OUT_OF_MEMORY) { return E_OUTOFMEMORY; }
+
+ return D3DERR_DRIVERINTERNALERROR;
+}
+
+HRESULT WINAPI
+NineResource9_GetPrivateData( struct NineResource9 *This,
+ REFGUID refguid,
+ void *pData,
+ DWORD *pSizeOfData )
+{
+ struct pheader *header;
+
+ DBG("This=%p refguid=%p pData=%p pSizeOfData=%p\n",
+ This, refguid, pData, pSizeOfData);
+
+ user_assert(pSizeOfData, E_POINTER);
+
+ header = util_hash_table_get(This->pdata, refguid);
+ if (!header) { return D3DERR_NOTFOUND; }
+
+ if (!pData) {
+ *pSizeOfData = header->size;
+ return D3D_OK;
+ }
+ if (*pSizeOfData < header->size) {
+ return D3DERR_MOREDATA;
+ }
+
+ if (header->unknown) { IUnknown_AddRef(*(IUnknown **)header->data); }
+ memcpy(pData, header->data, header->size);
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineResource9_FreePrivateData( struct NineResource9 *This,
+ REFGUID refguid )
+{
+ struct pheader *header;
+
+ DBG("This=%p refguid=%p\n", This, refguid);
+
+ header = util_hash_table_get(This->pdata, refguid);
+ if (!header)
+ return D3DERR_NOTFOUND;
+
+ ht_guid_delete(NULL, header, NULL);
+ util_hash_table_remove(This->pdata, refguid);
+
+ return D3D_OK;
+}
+
+DWORD WINAPI
+NineResource9_SetPriority( struct NineResource9 *This,
+ DWORD PriorityNew )
+{
+ DWORD prev = This->priority;
+ This->priority = PriorityNew;
+ return prev;
+}
+
+DWORD WINAPI
+NineResource9_GetPriority( struct NineResource9 *This )
+{
+ return This->priority;
+}
+
+/* NOTE: Don't forget to adjust locked vtable if you change this ! */
+void WINAPI
+NineResource9_PreLoad( struct NineResource9 *This )
+{
+ if (This->pool != D3DPOOL_MANAGED)
+ return;
+ /* We don't treat managed vertex or index buffers different from
+ * default ones (are managed vertex buffers even allowed ?), and
+ * the PreLoad for textures is overridden by superclass.
+ */
+}
+
+D3DRESOURCETYPE WINAPI
+NineResource9_GetType( struct NineResource9 *This )
+{
+ return This->type;
+}
diff --git a/src/gallium/state_trackers/nine/resource9.h b/src/gallium/state_trackers/nine/resource9.h
new file mode 100644
index 00000000000..0451498a4bf
--- /dev/null
+++ b/src/gallium/state_trackers/nine/resource9.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _NINE_RESOURCE9_H_
+#define _NINE_RESOURCE9_H_
+
+#include "iunknown.h"
+#include "pipe/p_state.h"
+
+struct pipe_screen;
+struct util_hash_table;
+struct NineDevice9;
+
+struct NineResource9
+{
+ struct NineUnknown base;
+
+ struct pipe_resource *resource; /* device resource */
+
+ uint8_t *data; /* system memory backing */
+
+ D3DRESOURCETYPE type;
+ D3DPOOL pool;
+ DWORD priority;
+ DWORD usage;
+
+ struct pipe_resource info; /* resource configuration */
+
+ /* for [GS]etPrivateData/FreePrivateData */
+ struct util_hash_table *pdata;
+};
+static INLINE struct NineResource9 *
+NineResource9( void *data )
+{
+ return (struct NineResource9 *)data;
+}
+
+HRESULT
+NineResource9_ctor( struct NineResource9 *This,
+ struct NineUnknownParams *pParams,
+ BOOL Allocate,
+ D3DRESOURCETYPE Type,
+ D3DPOOL Pool );
+
+void
+NineResource9_dtor( struct NineResource9 *This );
+
+/*** Nine private methods ***/
+
+struct pipe_resource *
+NineResource9_GetResource( struct NineResource9 *This );
+
+D3DPOOL
+NineResource9_GetPool( struct NineResource9 *This );
+
+/*** Direct3D public methods ***/
+
+HRESULT WINAPI
+NineResource9_SetPrivateData( struct NineResource9 *This,
+ REFGUID refguid,
+ const void *pData,
+ DWORD SizeOfData,
+ DWORD Flags );
+
+HRESULT WINAPI
+NineResource9_GetPrivateData( struct NineResource9 *This,
+ REFGUID refguid,
+ void *pData,
+ DWORD *pSizeOfData );
+
+HRESULT WINAPI
+NineResource9_FreePrivateData( struct NineResource9 *This,
+ REFGUID refguid );
+
+DWORD WINAPI
+NineResource9_SetPriority( struct NineResource9 *This,
+ DWORD PriorityNew );
+
+DWORD WINAPI
+NineResource9_GetPriority( struct NineResource9 *This );
+
+void WINAPI
+NineResource9_PreLoad( struct NineResource9 *This );
+
+D3DRESOURCETYPE WINAPI
+NineResource9_GetType( struct NineResource9 *This );
+
+#endif /* _NINE_RESOURCE9_H_ */
diff --git a/src/gallium/state_trackers/nine/stateblock9.c b/src/gallium/state_trackers/nine/stateblock9.c
new file mode 100644
index 00000000000..ffe4ab2f196
--- /dev/null
+++ b/src/gallium/state_trackers/nine/stateblock9.c
@@ -0,0 +1,533 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "stateblock9.h"
+#include "device9.h"
+#include "basetexture9.h"
+#include "nine_helpers.h"
+
+#define DBG_CHANNEL DBG_STATEBLOCK
+
+/* XXX TODO: handling of lights is broken */
+
+HRESULT
+NineStateBlock9_ctor( struct NineStateBlock9 *This,
+ struct NineUnknownParams *pParams,
+ enum nine_stateblock_type type )
+{
+ HRESULT hr = NineUnknown_ctor(&This->base, pParams);
+ if (FAILED(hr))
+ return hr;
+
+ This->type = type;
+
+ This->state.vs_const_f = MALLOC(pParams->device->constbuf_vs->width0);
+ This->state.ps_const_f = MALLOC(pParams->device->constbuf_ps->width0);
+ if (!This->state.vs_const_f || !This->state.ps_const_f)
+ return E_OUTOFMEMORY;
+
+ return D3D_OK;
+}
+
+void
+NineStateBlock9_dtor( struct NineStateBlock9 *This )
+{
+ struct nine_state *state = &This->state;
+ struct nine_range *r;
+ struct nine_range_pool *pool = &This->base.device->range_pool;
+
+ nine_state_clear(state, FALSE);
+
+ if (state->vs_const_f) FREE(state->vs_const_f);
+ if (state->ps_const_f) FREE(state->ps_const_f);
+
+ if (state->ff.light) FREE(state->ff.light);
+
+ if (state->ff.transform) FREE(state->ff.transform);
+
+ if (This->state.changed.ps_const_f) {
+ for (r = This->state.changed.ps_const_f; r->next; r = r->next);
+ nine_range_pool_put_chain(pool, This->state.changed.ps_const_f, r);
+ }
+ if (This->state.changed.vs_const_f) {
+ for (r = This->state.changed.vs_const_f; r->next; r = r->next);
+ nine_range_pool_put_chain(pool, This->state.changed.vs_const_f, r);
+ }
+
+ NineUnknown_dtor(&This->base);
+}
+
+/* Copy state marked changed in @mask from @src to @dst.
+ * If @apply is false, updating dst->changed can be omitted.
+ * TODO: compare ?
+ */
+static void
+nine_state_copy_common(struct nine_state *dst,
+ const struct nine_state *src,
+ struct nine_state *mask, /* aliases either src or dst */
+ const boolean apply,
+ struct nine_range_pool *pool)
+{
+ unsigned i, s;
+
+ if (apply)
+ dst->changed.group |= mask->changed.group;
+
+ if (mask->changed.group & NINE_STATE_VIEWPORT)
+ dst->viewport = src->viewport;
+ if (mask->changed.group & NINE_STATE_SCISSOR)
+ dst->scissor = src->scissor;
+
+ if (mask->changed.group & NINE_STATE_VS)
+ nine_bind(&dst->vs, src->vs);
+ if (mask->changed.group & NINE_STATE_PS)
+ nine_bind(&dst->ps, src->ps);
+
+ /* Vertex constants.
+ *
+ * Various possibilities for optimization here, like creating a per-SB
+ * constant buffer, or memcmp'ing for changes.
+ * Will do that later depending on what works best for specific apps.
+ */
+ if (mask->changed.group & NINE_STATE_VS_CONST) {
+ struct nine_range *r;
+ for (r = mask->changed.vs_const_f; r; r = r->next) {
+ memcpy(&dst->vs_const_f[r->bgn * 4],
+ &src->vs_const_f[r->bgn * 4],
+ (r->end - r->bgn) * 4 * sizeof(float));
+ if (apply)
+ nine_ranges_insert(&dst->changed.vs_const_f, r->bgn, r->end,
+ pool);
+ }
+ if (mask->changed.vs_const_i) {
+ uint16_t m = mask->changed.vs_const_i;
+ for (i = ffs(m) - 1, m >>= i; m; ++i, m >>= 1)
+ if (m & 1)
+ memcpy(dst->vs_const_i[i], src->vs_const_i[i], 4 * sizeof(int));
+ if (apply)
+ dst->changed.vs_const_i |= mask->changed.vs_const_i;
+ }
+ if (mask->changed.vs_const_b) {
+ uint16_t m = mask->changed.vs_const_b;
+ for (i = ffs(m) - 1, m >>= i; m; ++i, m >>= 1)
+ if (m & 1)
+ dst->vs_const_b[i] = src->vs_const_b[i];
+ if (apply)
+ dst->changed.vs_const_b |= mask->changed.vs_const_b;
+ }
+ }
+
+ /* Pixel constants. */
+ if (mask->changed.group & NINE_STATE_PS_CONST) {
+ struct nine_range *r;
+ for (r = mask->changed.ps_const_f; r; r = r->next) {
+ memcpy(&dst->ps_const_f[r->bgn * 4],
+ &src->ps_const_f[r->bgn * 4],
+ (r->end - r->bgn) * 4 * sizeof(float));
+ if (apply)
+ nine_ranges_insert(&dst->changed.ps_const_f, r->bgn, r->end,
+ pool);
+ }
+ if (mask->changed.ps_const_i) {
+ uint16_t m = mask->changed.ps_const_i;
+ for (i = ffs(m) - 1, m >>= i; m; ++i, m >>= 1)
+ if (m & 1)
+ memcpy(dst->ps_const_i[i], src->ps_const_i[i], 4 * sizeof(int));
+ if (apply)
+ dst->changed.ps_const_i |= mask->changed.ps_const_i;
+ }
+ if (mask->changed.ps_const_b) {
+ uint16_t m = mask->changed.ps_const_b;
+ for (i = ffs(m) - 1, m >>= i; m; ++i, m >>= 1)
+ if (m & 1)
+ dst->ps_const_b[i] = src->ps_const_b[i];
+ if (apply)
+ dst->changed.ps_const_b |= mask->changed.ps_const_b;
+ }
+ }
+
+ /* Render states.
+ * TODO: Maybe build a list ?
+ */
+ for (i = 0; i < Elements(dst->changed.rs); ++i) {
+ uint32_t m = mask->changed.rs[i];
+ if (apply)
+ dst->changed.rs[i] |= m;
+ while (m) {
+ const int r = ffs(m) - 1;
+ m &= ~(1 << r);
+ dst->rs[i * 32 + r] = src->rs[i * 32 + r];
+ }
+ }
+
+
+ /* Clip planes. */
+ if (mask->changed.ucp) {
+ for (i = 0; i < PIPE_MAX_CLIP_PLANES; ++i)
+ if (mask->changed.ucp & (1 << i))
+ memcpy(dst->clip.ucp[i],
+ src->clip.ucp[i], sizeof(src->clip.ucp[0]));
+ if (apply)
+ dst->changed.ucp |= mask->changed.ucp;
+ }
+
+ /* Sampler state. */
+ if (mask->changed.group & NINE_STATE_SAMPLER) {
+ for (s = 0; s < NINE_MAX_SAMPLERS; ++s) {
+ if (mask->changed.sampler[s] == 0x3ffe) {
+ memcpy(&dst->samp[s], &src->samp[s], sizeof(dst->samp[s]));
+ } else {
+ uint32_t m = mask->changed.sampler[s];
+ while (m) {
+ const int i = ffs(m) - 1;
+ m &= ~(1 << i);
+ dst->samp[s][i] = src->samp[s][i];
+ }
+ }
+ if (apply)
+ dst->changed.sampler[s] |= mask->changed.sampler[s];
+ }
+ }
+
+ /* Index buffer. */
+ if (mask->changed.group & NINE_STATE_IDXBUF)
+ nine_bind(&dst->idxbuf, src->idxbuf);
+
+ /* Vertex streams. */
+ if (mask->changed.vtxbuf | mask->changed.stream_freq) {
+ uint32_t m = mask->changed.vtxbuf | mask->changed.stream_freq;
+ for (i = 0; m; ++i, m >>= 1) {
+ if (mask->changed.vtxbuf & (1 << i)) {
+ nine_bind(&dst->stream[i], src->stream[i]);
+ if (src->stream[i]) {
+ dst->vtxbuf[i].buffer_offset = src->vtxbuf[i].buffer_offset;
+ dst->vtxbuf[i].buffer = src->vtxbuf[i].buffer;
+ dst->vtxbuf[i].stride = src->vtxbuf[i].stride;
+ }
+ }
+ if (mask->changed.stream_freq & (1 << i))
+ dst->stream_freq[i] = src->stream_freq[i];
+ }
+ dst->stream_instancedata_mask &= ~mask->changed.stream_freq;
+ dst->stream_instancedata_mask |=
+ src->stream_instancedata_mask & mask->changed.stream_freq;
+ if (apply) {
+ dst->changed.vtxbuf |= mask->changed.vtxbuf;
+ dst->changed.stream_freq |= mask->changed.stream_freq;
+ }
+ }
+
+ if (!(mask->changed.group & NINE_STATE_FF))
+ return;
+ WARN_ONCE("Fixed function state not handled properly by StateBlocks.\n");
+
+ /* Fixed function state. */
+ if (apply)
+ dst->ff.changed.group |= src->ff.changed.group;
+
+ if (mask->changed.group & NINE_STATE_FF_MATERIAL)
+ dst->ff.material = src->ff.material;
+
+ if (mask->changed.group & NINE_STATE_FF_PSSTAGES) {
+ for (s = 0; s < NINE_MAX_SAMPLERS; ++s) {
+ for (i = 0; i < NINED3DTSS_COUNT; ++i)
+ if (mask->ff.changed.tex_stage[s][i / 32] & (1 << (i % 32)))
+ dst->ff.tex_stage[s][i] = src->ff.tex_stage[s][i];
+ if (apply) {
+ /* TODO: it's 32 exactly, just offset by 1 as 0 is unused */
+ dst->ff.changed.tex_stage[s][0] |=
+ mask->ff.changed.tex_stage[s][0];
+ dst->ff.changed.tex_stage[s][1] |=
+ mask->ff.changed.tex_stage[s][1];
+ }
+ }
+ }
+ if (mask->changed.group & NINE_STATE_FF_LIGHTING) {
+ if (dst->ff.num_lights < mask->ff.num_lights) {
+ dst->ff.light = REALLOC(dst->ff.light,
+ dst->ff.num_lights * sizeof(D3DLIGHT9),
+ mask->ff.num_lights * sizeof(D3DLIGHT9));
+ dst->ff.num_lights = mask->ff.num_lights;
+ }
+ for (i = 0; i < mask->ff.num_lights; ++i)
+ if (mask->ff.light[i].Type != NINED3DLIGHT_INVALID)
+ dst->ff.light[i] = src->ff.light[i];
+
+ DBG("TODO: active lights\n");
+ }
+ if (mask->changed.group & NINE_STATE_FF_VSTRANSF) {
+ for (i = 0; i < Elements(mask->ff.changed.transform); ++i) {
+ if (!mask->ff.changed.transform[i])
+ continue;
+ for (s = i * 32; s < (i * 32 + 32); ++s) {
+ if (!(mask->ff.changed.transform[i] & (1 << (s % 32))))
+ continue;
+ *nine_state_access_transform(dst, s, TRUE) =
+ *nine_state_access_transform( /* const because !alloc */
+ (struct nine_state *)src, s, FALSE);
+ }
+ if (apply)
+ dst->ff.changed.transform[i] |= mask->ff.changed.transform[i];
+ }
+ }
+}
+
+static void
+nine_state_copy_common_all(struct nine_state *dst,
+ const struct nine_state *src,
+ struct nine_state *help,
+ const boolean apply,
+ struct nine_range_pool *pool,
+ const int MaxStreams)
+{
+ unsigned i;
+
+ if (apply)
+ dst->changed.group |= src->changed.group;
+
+ dst->viewport = src->viewport;
+ dst->scissor = src->scissor;
+
+ nine_bind(&dst->vs, src->vs);
+ nine_bind(&dst->ps, src->ps);
+
+ /* Vertex constants.
+ *
+ * Various possibilities for optimization here, like creating a per-SB
+ * constant buffer, or memcmp'ing for changes.
+ * Will do that later depending on what works best for specific apps.
+ */
+ if (1) {
+ struct nine_range *r = help->changed.vs_const_f;
+ memcpy(&dst->vs_const_f[0],
+ &src->vs_const_f[0], (r->end - r->bgn) * 4 * sizeof(float));
+ if (apply)
+ nine_ranges_insert(&dst->changed.vs_const_f, r->bgn, r->end, pool);
+
+ memcpy(dst->vs_const_i, src->vs_const_i, sizeof(dst->vs_const_i));
+ memcpy(dst->vs_const_b, src->vs_const_b, sizeof(dst->vs_const_b));
+ if (apply) {
+ dst->changed.vs_const_i |= src->changed.vs_const_i;
+ dst->changed.vs_const_b |= src->changed.vs_const_b;
+ }
+ }
+
+ /* Pixel constants. */
+ if (1) {
+ struct nine_range *r = help->changed.ps_const_f;
+ memcpy(&dst->ps_const_f[0],
+ &src->ps_const_f[0], (r->end - r->bgn) * 4 * sizeof(float));
+ if (apply)
+ nine_ranges_insert(&dst->changed.ps_const_f, r->bgn, r->end, pool);
+
+ memcpy(dst->ps_const_i, src->ps_const_i, sizeof(dst->ps_const_i));
+ memcpy(dst->ps_const_b, src->ps_const_b, sizeof(dst->ps_const_b));
+ if (apply) {
+ dst->changed.ps_const_i |= src->changed.ps_const_i;
+ dst->changed.ps_const_b |= src->changed.ps_const_b;
+ }
+ }
+
+ /* Render states. */
+ memcpy(dst->rs, src->rs, sizeof(dst->rs));
+ if (apply)
+ memcpy(dst->changed.rs, src->changed.rs, sizeof(dst->changed.rs));
+
+
+ /* Clip planes. */
+ memcpy(&dst->clip, &src->clip, sizeof(dst->clip));
+ if (apply)
+ dst->changed.ucp = src->changed.ucp;
+
+ /* Sampler state. */
+ memcpy(dst->samp, src->samp, sizeof(dst->samp));
+ if (apply)
+ memcpy(dst->changed.sampler,
+ src->changed.sampler, sizeof(dst->changed.sampler));
+
+ /* Index buffer. */
+ nine_bind(&dst->idxbuf, src->idxbuf);
+
+ /* Vertex streams. */
+ if (1) {
+ for (i = 0; i < Elements(dst->stream); ++i) {
+ nine_bind(&dst->stream[i], src->stream[i]);
+ if (src->stream[i]) {
+ dst->vtxbuf[i].buffer_offset = src->vtxbuf[i].buffer_offset;
+ dst->vtxbuf[i].buffer = src->vtxbuf[i].buffer;
+ dst->vtxbuf[i].stride = src->vtxbuf[i].stride;
+ }
+ dst->stream_freq[i] = src->stream_freq[i];
+ }
+ dst->stream_instancedata_mask = src->stream_instancedata_mask;
+ if (apply) {
+ dst->changed.vtxbuf = (1ULL << MaxStreams) - 1;
+ dst->changed.stream_freq = (1ULL << MaxStreams) - 1;
+ }
+ }
+
+ /* keep this check in case we want to disable FF */
+ if (!(help->changed.group & NINE_STATE_FF))
+ return;
+ WARN_ONCE("Fixed function state not handled properly by StateBlocks.\n");
+
+ /* Fixed function state. */
+ if (apply)
+ dst->ff.changed.group = src->ff.changed.group;
+
+ dst->ff.material = src->ff.material;
+
+ memcpy(dst->ff.tex_stage, src->ff.tex_stage, sizeof(dst->ff.tex_stage));
+ if (apply) /* TODO: memset */
+ memcpy(dst->ff.changed.tex_stage,
+ src->ff.changed.tex_stage, sizeof(dst->ff.changed.tex_stage));
+
+ /* Lights. */
+ if (1) {
+ if (dst->ff.num_lights < src->ff.num_lights) {
+ dst->ff.light = REALLOC(dst->ff.light,
+ dst->ff.num_lights * sizeof(D3DLIGHT9),
+ src->ff.num_lights * sizeof(D3DLIGHT9));
+ dst->ff.num_lights = src->ff.num_lights;
+ }
+ memcpy(dst->ff.light,
+ src->ff.light, src->ff.num_lights * sizeof(dst->ff.light[0]));
+
+ DBG("TODO: active lights\n");
+ }
+
+ /* Transforms. */
+ if (1) {
+ if (dst->ff.num_transforms < src->ff.num_transforms) {
+ dst->ff.transform = REALLOC(dst->ff.transform,
+ dst->ff.num_transforms * sizeof(dst->ff.transform[0]),
+ src->ff.num_transforms * sizeof(src->ff.transform[0]));
+ dst->ff.num_transforms = src->ff.num_transforms;
+ }
+ memcpy(dst->ff.transform,
+ src->ff.transform, src->ff.num_transforms * sizeof(D3DMATRIX));
+ if (apply) /* TODO: memset */
+ memcpy(dst->ff.changed.transform,
+ src->ff.changed.transform, sizeof(dst->ff.changed.transform));
+ }
+}
+
+/* Capture those bits of current device state that have been changed between
+ * BeginStateBlock and EndStateBlock.
+ */
+HRESULT WINAPI
+NineStateBlock9_Capture( struct NineStateBlock9 *This )
+{
+ struct nine_state *dst = &This->state;
+ struct nine_state *src = &This->base.device->state;
+ const int MaxStreams = This->base.device->caps.MaxStreams;
+ unsigned s;
+
+ DBG("This=%p\n", This);
+
+ if (This->type == NINESBT_ALL)
+ nine_state_copy_common_all(dst, src, dst, FALSE, NULL, MaxStreams);
+ else
+ nine_state_copy_common(dst, src, dst, FALSE, NULL);
+
+ if (dst->changed.group & NINE_STATE_VDECL)
+ nine_bind(&dst->vdecl, src->vdecl);
+
+ /* Textures */
+ if (dst->changed.texture) {
+ uint32_t m = dst->changed.texture;
+ for (s = 0; m; ++s, m >>= 1)
+ if (m & 1)
+ nine_bind(&dst->texture[s], src->texture[s]);
+ }
+
+ return D3D_OK;
+}
+
+/* Set state managed by this StateBlock as current device state. */
+HRESULT WINAPI
+NineStateBlock9_Apply( struct NineStateBlock9 *This )
+{
+ struct nine_state *dst = &This->base.device->state;
+ struct nine_state *src = &This->state;
+ struct nine_range_pool *pool = &This->base.device->range_pool;
+ const int MaxStreams = This->base.device->caps.MaxStreams;
+ unsigned s;
+
+ DBG("This=%p\n", This);
+
+ if (This->type == NINESBT_ALL)
+ nine_state_copy_common_all(dst, src, src, TRUE, pool, MaxStreams);
+ else
+ nine_state_copy_common(dst, src, src, TRUE, pool);
+
+ if ((src->changed.group & NINE_STATE_VDECL) && src->vdecl)
+ nine_bind(&dst->vdecl, src->vdecl);
+
+ /* Textures */
+ if (src->changed.texture) {
+ uint32_t m = src->changed.texture;
+ dst->changed.texture |= m;
+
+ dst->samplers_shadow &= ~m;
+
+ for (s = 0; m; ++s, m >>= 1) {
+ struct NineBaseTexture9 *tex = src->texture[s];
+ if (!(m & 1))
+ continue;
+ if (tex) {
+ tex->bind_count++;
+ if ((tex->dirty | tex->dirty_mip) && LIST_IS_EMPTY(&tex->list))
+ list_add(&tex->list, &This->base.device->update_textures);
+ dst->samplers_shadow |= tex->shadow << s;
+ }
+ if (src->texture[s])
+ src->texture[s]->bind_count--;
+ nine_bind(&dst->texture[s], src->texture[s]);
+ }
+ }
+
+ return D3D_OK;
+}
+
+IDirect3DStateBlock9Vtbl NineStateBlock9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)NineUnknown_GetDevice, /* actually part of StateBlock9 iface */
+ (void *)NineStateBlock9_Capture,
+ (void *)NineStateBlock9_Apply
+};
+
+static const GUID *NineStateBlock9_IIDs[] = {
+ &IID_IDirect3DStateBlock9,
+ &IID_IUnknown,
+ NULL
+};
+
+HRESULT
+NineStateBlock9_new( struct NineDevice9 *pDevice,
+ struct NineStateBlock9 **ppOut,
+ enum nine_stateblock_type type)
+{
+ NINE_DEVICE_CHILD_NEW(StateBlock9, ppOut, pDevice, type);
+}
diff --git a/src/gallium/state_trackers/nine/stateblock9.h b/src/gallium/state_trackers/nine/stateblock9.h
new file mode 100644
index 00000000000..bcaf634d933
--- /dev/null
+++ b/src/gallium/state_trackers/nine/stateblock9.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _NINE_STATEBLOCK9_H_
+#define _NINE_STATEBLOCK9_H_
+
+#include "iunknown.h"
+
+#include "nine_state.h"
+
+enum nine_stateblock_type
+{
+ NINESBT_ALL,
+ NINESBT_VERTEXSTATE,
+ NINESBT_PIXELSTATE,
+ NINESBT_CUSTOM
+};
+
+struct NineStateBlock9
+{
+ struct NineUnknown base;
+
+ struct nine_state state;
+
+ enum nine_stateblock_type type;
+};
+static INLINE struct NineStateBlock9 *
+NineStateBlock9( void *data )
+{
+ return (struct NineStateBlock9 *)data;
+}
+
+HRESULT
+NineStateBlock9_new( struct NineDevice9 *,
+ struct NineStateBlock9 **ppOut,
+ enum nine_stateblock_type);
+
+HRESULT
+NineStateBlock9_ctor( struct NineStateBlock9 *,
+ struct NineUnknownParams *pParams,
+ enum nine_stateblock_type type );
+
+void
+NineStateBlock9_dtor( struct NineStateBlock9 * );
+
+HRESULT WINAPI
+NineStateBlock9_Capture( struct NineStateBlock9 *This );
+
+HRESULT WINAPI
+NineStateBlock9_Apply( struct NineStateBlock9 *This );
+
+#endif /* _NINE_STATEBLOCK9_H_ */
diff --git a/src/gallium/state_trackers/nine/surface9.c b/src/gallium/state_trackers/nine/surface9.c
new file mode 100644
index 00000000000..42a9e05dabd
--- /dev/null
+++ b/src/gallium/state_trackers/nine/surface9.c
@@ -0,0 +1,711 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "surface9.h"
+#include "device9.h"
+#include "basetexture9.h" /* for marking dirty */
+
+#include "nine_helpers.h"
+#include "nine_pipe.h"
+#include "nine_dump.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_screen.h"
+#include "pipe/p_state.h"
+
+#include "util/u_math.h"
+#include "util/u_inlines.h"
+#include "util/u_surface.h"
+
+#define DBG_CHANNEL DBG_SURFACE
+
+HRESULT
+NineSurface9_ctor( struct NineSurface9 *This,
+ struct NineUnknownParams *pParams,
+ struct NineUnknown *pContainer,
+ struct pipe_resource *pResource,
+ uint8_t TextureType,
+ unsigned Level,
+ unsigned Layer,
+ D3DSURFACE_DESC *pDesc )
+{
+ HRESULT hr;
+
+ DBG("This=%p pDevice=%p pResource=%p Level=%u Layer=%u pDesc=%p\n",
+ This, pParams->device, pResource, Level, Layer, pDesc);
+
+ /* Mark this as a special surface held by another internal resource. */
+ pParams->container = pContainer;
+
+ user_assert(!(pDesc->Usage & D3DUSAGE_DYNAMIC) ||
+ (pDesc->Pool != D3DPOOL_MANAGED), D3DERR_INVALIDCALL);
+
+ assert(pResource ||
+ pDesc->Pool != D3DPOOL_DEFAULT || pDesc->Format == D3DFMT_NULL);
+
+ This->base.info.screen = pParams->device->screen;
+ This->base.info.target = PIPE_TEXTURE_2D;
+ This->base.info.format = d3d9_to_pipe_format(pDesc->Format);
+ This->base.info.width0 = pDesc->Width;
+ This->base.info.height0 = pDesc->Height;
+ This->base.info.depth0 = 1;
+ This->base.info.last_level = 0;
+ This->base.info.array_size = 1;
+ This->base.info.nr_samples = pDesc->MultiSampleType;
+ This->base.info.usage = PIPE_USAGE_DEFAULT;
+ This->base.info.bind = PIPE_BIND_SAMPLER_VIEW;
+ This->base.info.flags = 0;
+
+ if (pDesc->Usage & D3DUSAGE_RENDERTARGET)
+ This->base.info.bind |= PIPE_BIND_RENDER_TARGET;
+ if (pDesc->Usage & D3DUSAGE_DEPTHSTENCIL)
+ This->base.info.bind |= PIPE_BIND_DEPTH_STENCIL;
+
+ if (pDesc->Pool == D3DPOOL_SYSTEMMEM) {
+ This->base.info.usage = PIPE_USAGE_STAGING;
+ if (pResource)
+ This->base.data = (uint8_t *)pResource; /* this is *pSharedHandle */
+ pResource = NULL;
+ } else {
+ if (pResource && (pDesc->Usage & D3DUSAGE_DYNAMIC))
+ pResource->flags |= NINE_RESOURCE_FLAG_LOCKABLE;
+ pipe_resource_reference(&This->base.resource, pResource);
+ }
+
+ hr = NineResource9_ctor(&This->base, pParams, FALSE, D3DRTYPE_SURFACE,
+ pDesc->Pool);
+ if (FAILED(hr))
+ return hr;
+ This->base.usage = pDesc->Usage;
+
+ This->pipe = This->base.base.device->pipe;
+ This->transfer = NULL;
+
+ This->texture = TextureType;
+ This->level = Level;
+ This->level_actual = Level;
+ This->layer = Layer;
+ This->desc = *pDesc;
+
+ This->stride = util_format_get_stride(This->base.info.format, pDesc->Width);
+ This->stride = align(This->stride, 4);
+
+ if (!pResource && !This->base.data) {
+ hr = NineSurface9_AllocateData(This);
+ if (FAILED(hr))
+ return hr;
+ } else {
+ if (pResource && NineSurface9_IsOffscreenPlain(This))
+ pResource->flags |= NINE_RESOURCE_FLAG_LOCKABLE;
+ }
+
+ NineSurface9_Dump(This);
+
+ return D3D_OK;
+}
+
+void
+NineSurface9_dtor( struct NineSurface9 *This )
+{
+ if (This->transfer)
+ NineSurface9_UnlockRect(This);
+ NineSurface9_ClearDirtyRects(This);
+
+ pipe_surface_reference(&This->surface[0], NULL);
+ pipe_surface_reference(&This->surface[1], NULL);
+
+ NineResource9_dtor(&This->base);
+}
+
+struct pipe_surface *
+NineSurface9_CreatePipeSurface( struct NineSurface9 *This, const int sRGB )
+{
+ struct pipe_context *pipe = This->pipe;
+ struct pipe_resource *resource = This->base.resource;
+ struct pipe_surface templ;
+
+ assert(This->desc.Pool == D3DPOOL_DEFAULT ||
+ This->desc.Pool == D3DPOOL_MANAGED);
+ assert(resource);
+
+ templ.format = sRGB ? util_format_srgb(resource->format) : resource->format;
+ templ.u.tex.level = This->level;
+ templ.u.tex.first_layer = This->layer;
+ templ.u.tex.last_layer = This->layer;
+
+ This->surface[sRGB] = pipe->create_surface(pipe, resource, &templ);
+ assert(This->surface[sRGB]);
+ return This->surface[sRGB];
+}
+
+#ifdef DEBUG
+void
+NineSurface9_Dump( struct NineSurface9 *This )
+{
+ struct NineBaseTexture9 *tex;
+ GUID id = IID_IDirect3DBaseTexture9;
+ REFIID ref = &id;
+
+ DBG("\nNineSurface9(%p->%p/%p): Pool=%s Type=%s Usage=%s\n"
+ "Dims=%ux%u Format=%s Stride=%u Lockable=%i\n"
+ "Level=%u(%u), Layer=%u\n", This, This->base.resource, This->base.data,
+ nine_D3DPOOL_to_str(This->desc.Pool),
+ nine_D3DRTYPE_to_str(This->desc.Type),
+ nine_D3DUSAGE_to_str(This->desc.Usage),
+ This->desc.Width, This->desc.Height,
+ d3dformat_to_string(This->desc.Format), This->stride,
+ This->base.resource &&
+ (This->base.resource->flags & NINE_RESOURCE_FLAG_LOCKABLE),
+ This->level, This->level_actual, This->layer);
+
+ if (!This->base.base.container)
+ return;
+ NineUnknown_QueryInterface(This->base.base.container, ref, (void **)&tex);
+ if (tex) {
+ NineBaseTexture9_Dump(tex);
+ NineUnknown_Release(NineUnknown(tex));
+ }
+}
+#endif /* DEBUG */
+
+HRESULT WINAPI
+NineSurface9_GetContainer( struct NineSurface9 *This,
+ REFIID riid,
+ void **ppContainer )
+{
+ HRESULT hr;
+ if (!NineUnknown(This)->container)
+ return E_NOINTERFACE;
+ hr = NineUnknown_QueryInterface(NineUnknown(This)->container, riid, ppContainer);
+ if (FAILED(hr))
+ DBG("QueryInterface FAILED!\n");
+ return hr;
+}
+
+static INLINE void
+NineSurface9_MarkContainerDirty( struct NineSurface9 *This )
+{
+ if (This->texture) {
+ struct NineBaseTexture9 *tex =
+ NineBaseTexture9(This->base.base.container);
+ assert(tex);
+ assert(This->texture == D3DRTYPE_TEXTURE ||
+ This->texture == D3DRTYPE_CUBETEXTURE);
+ if (This->base.pool == D3DPOOL_MANAGED)
+ tex->dirty = TRUE;
+ else
+ if (This->base.usage & D3DUSAGE_AUTOGENMIPMAP)
+ tex->dirty_mip = TRUE;
+
+ BASETEX_REGISTER_UPDATE(tex);
+ }
+}
+
+HRESULT WINAPI
+NineSurface9_GetDesc( struct NineSurface9 *This,
+ D3DSURFACE_DESC *pDesc )
+{
+ user_assert(pDesc != NULL, E_POINTER);
+ *pDesc = This->desc;
+ return D3D_OK;
+}
+
+/* Wine just keeps a single directy rect and expands it to cover all
+ * the dirty rects ever added.
+ * We'll keep 2, and expand the one that fits better, just for fun.
+ */
+INLINE void
+NineSurface9_AddDirtyRect( struct NineSurface9 *This,
+ const struct pipe_box *box )
+{
+ float area[2];
+ struct u_rect rect, cover_a, cover_b;
+
+ if (!box) {
+ This->dirty_rects[0].x0 = 0;
+ This->dirty_rects[0].y0 = 0;
+ This->dirty_rects[0].x1 = This->desc.Width;
+ This->dirty_rects[0].y1 = This->desc.Height;
+
+ memset(&This->dirty_rects[1], 0, sizeof(This->dirty_rects[1]));
+ return;
+ }
+ rect.x0 = box->x;
+ rect.y0 = box->y;
+ rect.x1 = box->x + box->width;
+ rect.y1 = box->y + box->height;
+
+ if (This->dirty_rects[0].x1 == 0) {
+ This->dirty_rects[0] = rect;
+ return;
+ }
+
+ u_rect_union(&cover_a, &This->dirty_rects[0], &rect);
+ area[0] = u_rect_area(&cover_a);
+
+ if (This->dirty_rects[1].x1 == 0) {
+ area[1] = u_rect_area(&This->dirty_rects[0]);
+ if (area[0] > (area[1] * 1.25f))
+ This->dirty_rects[1] = rect;
+ else
+ This->dirty_rects[0] = cover_a;
+ } else {
+ u_rect_union(&cover_b, &This->dirty_rects[1], &rect);
+ area[1] = u_rect_area(&cover_b);
+
+ if (area[0] > area[1])
+ This->dirty_rects[1] = cover_b;
+ else
+ This->dirty_rects[0] = cover_a;
+ }
+}
+
+static INLINE uint8_t *
+NineSurface9_GetSystemMemPointer(struct NineSurface9 *This, int x, int y)
+{
+ unsigned x_offset = util_format_get_stride(This->base.info.format, x);
+
+ y = util_format_get_nblocksy(This->base.info.format, y);
+
+ assert(This->base.data);
+ return This->base.data + (y * This->stride + x_offset);
+}
+
+HRESULT WINAPI
+NineSurface9_LockRect( struct NineSurface9 *This,
+ D3DLOCKED_RECT *pLockedRect,
+ const RECT *pRect,
+ DWORD Flags )
+{
+ struct pipe_resource *resource = This->base.resource;
+ struct pipe_box box;
+ unsigned usage;
+
+ DBG("This=%p pLockedRect=%p pRect=%p[%u..%u,%u..%u] Flags=%s\n", This,
+ pLockedRect, pRect,
+ pRect ? pRect->left : 0, pRect ? pRect->right : 0,
+ pRect ? pRect->top : 0, pRect ? pRect->bottom : 0,
+ nine_D3DLOCK_to_str(Flags));
+ NineSurface9_Dump(This);
+
+#ifdef NINE_STRICT
+ user_assert(This->base.pool != D3DPOOL_DEFAULT ||
+ (resource && (resource->flags & NINE_RESOURCE_FLAG_LOCKABLE)),
+ D3DERR_INVALIDCALL);
+#endif
+ user_assert(!(Flags & ~(D3DLOCK_DISCARD |
+ D3DLOCK_DONOTWAIT |
+ D3DLOCK_NO_DIRTY_UPDATE |
+ D3DLOCK_NOOVERWRITE |
+ D3DLOCK_NOSYSLOCK | /* ignored */
+ D3DLOCK_READONLY)), D3DERR_INVALIDCALL);
+ user_assert(!((Flags & D3DLOCK_DISCARD) && (Flags & D3DLOCK_READONLY)),
+ D3DERR_INVALIDCALL);
+
+ /* check if it's already locked */
+ user_assert(This->lock_count == 0, D3DERR_INVALIDCALL);
+ user_assert(pLockedRect, E_POINTER);
+
+ user_assert(This->desc.MultiSampleType == D3DMULTISAMPLE_NONE,
+ D3DERR_INVALIDCALL);
+
+ if (pRect && This->base.pool == D3DPOOL_DEFAULT &&
+ util_format_is_compressed(This->base.info.format)) {
+ const unsigned w = util_format_get_blockwidth(This->base.info.format);
+ const unsigned h = util_format_get_blockheight(This->base.info.format);
+ user_assert(!(pRect->left % w) && !(pRect->right % w) &&
+ !(pRect->top % h) && !(pRect->bottom % h),
+ D3DERR_INVALIDCALL);
+ }
+
+ if (Flags & D3DLOCK_DISCARD) {
+ usage = PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE;
+ } else {
+ usage = (Flags & D3DLOCK_READONLY) ?
+ PIPE_TRANSFER_READ : PIPE_TRANSFER_READ_WRITE;
+ }
+ if (Flags & D3DLOCK_DONOTWAIT)
+ usage |= PIPE_TRANSFER_DONTBLOCK;
+
+ if (pRect) {
+ rect_to_pipe_box(&box, pRect);
+ if (u_box_clip_2d(&box, &box, This->desc.Width,
+ This->desc.Height) < 0) {
+ DBG("pRect clipped by Width=%u Height=%u\n",
+ This->desc.Width, This->desc.Height);
+ return D3DERR_INVALIDCALL;
+ }
+ } else {
+ u_box_origin_2d(This->desc.Width, This->desc.Height, &box);
+ }
+
+ user_warn(This->desc.Format == D3DFMT_NULL);
+
+ if (This->base.data) {
+ DBG("returning system memory\n");
+
+ pLockedRect->Pitch = This->stride;
+ pLockedRect->pBits = NineSurface9_GetSystemMemPointer(This,
+ box.x, box.y);
+ } else {
+ DBG("mapping pipe_resource %p (level=%u usage=%x)\n",
+ resource, This->level, usage);
+
+ pLockedRect->pBits = This->pipe->transfer_map(This->pipe, resource,
+ This->level, usage, &box,
+ &This->transfer);
+ if (!This->transfer) {
+ DBG("transfer_map failed\n");
+ if (Flags & D3DLOCK_DONOTWAIT)
+ return D3DERR_WASSTILLDRAWING;
+ return D3DERR_INVALIDCALL;
+ }
+ pLockedRect->Pitch = This->transfer->stride;
+ }
+
+ if (!(Flags & (D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_READONLY))) {
+ NineSurface9_MarkContainerDirty(This);
+ if (This->base.pool == D3DPOOL_MANAGED)
+ NineSurface9_AddDirtyRect(This, &box);
+ }
+
+ ++This->lock_count;
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineSurface9_UnlockRect( struct NineSurface9 *This )
+{
+ DBG("This=%p lock_count=%u\n", This, This->lock_count);
+ user_assert(This->lock_count, D3DERR_INVALIDCALL);
+ if (This->transfer) {
+ This->pipe->transfer_unmap(This->pipe, This->transfer);
+ This->transfer = NULL;
+ }
+ --This->lock_count;
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineSurface9_GetDC( struct NineSurface9 *This,
+ HDC *phdc )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineSurface9_ReleaseDC( struct NineSurface9 *This,
+ HDC hdc )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+/* nine private */
+
+HRESULT
+NineSurface9_AllocateData( struct NineSurface9 *This )
+{
+#if 0
+ struct pipe_screen *screen = This->base.info.screen;
+ /* XXX: Can't use staging resource because apparently apps expect
+ * memory offsets to be the same across locks.
+ * NV50 doesn't support direct mapping yet so only enable this if
+ * everything else works.
+ */
+ if (This->base.pool == D3DPOOL_SYSTEMMEM) {
+ /* Allocate a staging resource to save a copy:
+ * user -> staging resource
+ * staging resource -> (blit) -> video memory
+ *
+ * Instead of:
+ * user -> system memory
+ * system memory -> transfer staging area
+ * transfer -> video memory
+ *
+ * Does this work if we "lose" the device ?
+ */
+ struct pipe_resource *resource;
+ struct pipe_resource templ;
+
+ templ.target = PIPE_TEXTURE_2D;
+ templ.format = This->base.info.format;
+ templ.width0 = This->desc.Width;
+ templ.height0 = This->desc.Height;
+ templ.depth0 = 1;
+ templ.array_size = 1;
+ templ.last_level = 0;
+ templ.nr_samples = 0;
+ templ.usage = PIPE_USAGE_STAGING;
+ templ.bind =
+ PIPE_BIND_SAMPLER_VIEW |
+ PIPE_BIND_TRANSFER_WRITE |
+ PIPE_BIND_TRANSFER_READ;
+ templ.flags = 0;
+
+ DBG("(%p(This=%p),level=%u) Allocating staging resource.\n",
+ This->base.base.container, This, This->level);
+
+ resource = screen->resource_create(screen, &templ);
+ if (!resource)
+ DBG("Failed to allocate staging resource.\n");
+
+ /* Also deallocate old staging resource. */
+ pipe_resource_reference(&This->base.resource, resource);
+ }
+#endif
+ if (!This->base.resource) {
+ const unsigned size = This->stride *
+ util_format_get_nblocksy(This->base.info.format, This->desc.Height);
+
+ DBG("(%p(This=%p),level=%u) Allocating 0x%x bytes of system memory.\n",
+ This->base.base.container, This, This->level, size);
+
+ This->base.data = (uint8_t *)MALLOC(size);
+ if (!This->base.data)
+ return E_OUTOFMEMORY;
+ }
+ return D3D_OK;
+}
+
+IDirect3DSurface9Vtbl NineSurface9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */
+ (void *)NineResource9_SetPrivateData,
+ (void *)NineResource9_GetPrivateData,
+ (void *)NineResource9_FreePrivateData,
+ (void *)NineResource9_SetPriority,
+ (void *)NineResource9_GetPriority,
+ (void *)NineResource9_PreLoad,
+ (void *)NineResource9_GetType,
+ (void *)NineSurface9_GetContainer,
+ (void *)NineSurface9_GetDesc,
+ (void *)NineSurface9_LockRect,
+ (void *)NineSurface9_UnlockRect,
+ (void *)NineSurface9_GetDC,
+ (void *)NineSurface9_ReleaseDC
+};
+
+
+static INLINE boolean
+NineSurface9_IsDirty(struct NineSurface9 *This)
+{
+ return This->dirty_rects[0].x1 != 0;
+}
+
+HRESULT
+NineSurface9_CopySurface( struct NineSurface9 *This,
+ struct NineSurface9 *From,
+ const POINT *pDestPoint,
+ const RECT *pSourceRect )
+{
+ struct pipe_context *pipe = This->pipe;
+ struct pipe_resource *r_dst = This->base.resource;
+ struct pipe_resource *r_src = From->base.resource;
+ struct pipe_transfer *transfer;
+ struct pipe_box src_box;
+ struct pipe_box dst_box;
+ uint8_t *p_dst;
+ const uint8_t *p_src;
+
+ user_assert(This->desc.Format == From->desc.Format, D3DERR_INVALIDCALL);
+
+ dst_box.x = pDestPoint ? pDestPoint->x : 0;
+ dst_box.y = pDestPoint ? pDestPoint->y : 0;
+
+ user_assert(dst_box.x >= 0 &&
+ dst_box.y >= 0, D3DERR_INVALIDCALL);
+
+ dst_box.z = This->layer;
+ src_box.z = From->layer;
+
+ dst_box.depth = 1;
+ src_box.depth = 1;
+
+ if (pSourceRect) {
+ /* make sure it doesn't range outside the source surface */
+ user_assert(pSourceRect->left >= 0 &&
+ pSourceRect->right <= From->desc.Width &&
+ pSourceRect->top >= 0 &&
+ pSourceRect->bottom <= From->desc.Height,
+ D3DERR_INVALIDCALL);
+ if (rect_to_pipe_box_xy_only_clamp(&src_box, pSourceRect))
+ return D3D_OK;
+ } else {
+ src_box.x = 0;
+ src_box.y = 0;
+ src_box.width = From->desc.Width;
+ src_box.height = From->desc.Height;
+ }
+
+ /* limits */
+ dst_box.width = This->desc.Width - dst_box.x;
+ dst_box.height = This->desc.Height - dst_box.y;
+
+ user_assert(src_box.width <= dst_box.width &&
+ src_box.height <= dst_box.height, D3DERR_INVALIDCALL);
+
+ dst_box.width = src_box.width;
+ dst_box.height = src_box.height;
+
+ /* Don't copy to device memory of managed resources.
+ * We don't want to download it back again later.
+ */
+ if (This->base.pool == D3DPOOL_MANAGED)
+ r_dst = NULL;
+
+ /* Don't copy from stale device memory of managed resources.
+ * Also, don't copy between system and device if we don't have to.
+ */
+ if (From->base.pool == D3DPOOL_MANAGED) {
+ if (!r_dst || NineSurface9_IsDirty(From))
+ r_src = NULL;
+ }
+
+ if (r_dst && r_src) {
+ pipe->resource_copy_region(pipe,
+ r_dst, This->level,
+ dst_box.x, dst_box.y, dst_box.z,
+ r_src, From->level,
+ &src_box);
+ } else
+ if (r_dst) {
+ p_src = NineSurface9_GetSystemMemPointer(From, src_box.x, src_box.y);
+
+ pipe->transfer_inline_write(pipe, r_dst, This->level,
+ 0, /* WRITE|DISCARD are implicit */
+ &dst_box, p_src, From->stride, 0);
+ } else
+ if (r_src) {
+ p_dst = NineSurface9_GetSystemMemPointer(This, 0, 0);
+
+ p_src = pipe->transfer_map(pipe, r_src, From->level,
+ PIPE_TRANSFER_READ,
+ &src_box, &transfer);
+ if (!p_src)
+ return D3DERR_DRIVERINTERNALERROR;
+
+ util_copy_rect(p_dst, This->base.info.format,
+ This->stride, dst_box.x, dst_box.y,
+ dst_box.width, dst_box.height,
+ p_src,
+ transfer->stride, src_box.x, src_box.y);
+
+ pipe->transfer_unmap(pipe, transfer);
+ } else {
+ p_dst = NineSurface9_GetSystemMemPointer(This, 0, 0);
+ p_src = NineSurface9_GetSystemMemPointer(From, 0, 0);
+
+ util_copy_rect(p_dst, This->base.info.format,
+ This->stride, dst_box.x, dst_box.y,
+ dst_box.width, dst_box.height,
+ p_src,
+ From->stride, src_box.x, src_box.y);
+ }
+
+ if (This->base.pool == D3DPOOL_DEFAULT ||
+ This->base.pool == D3DPOOL_MANAGED)
+ NineSurface9_MarkContainerDirty(This);
+ if (!r_dst && This->base.resource)
+ NineSurface9_AddDirtyRect(This, &dst_box);
+
+ return D3D_OK;
+}
+
+/* Gladly, rendering to a MANAGED surface is not permitted, so we will
+ * never have to do the reverse, i.e. download the surface.
+ */
+HRESULT
+NineSurface9_UploadSelf( struct NineSurface9 *This )
+{
+ struct pipe_context *pipe = This->pipe;
+ struct pipe_resource *res = This->base.resource;
+ uint8_t *ptr;
+ unsigned i;
+
+ assert(This->base.pool == D3DPOOL_MANAGED);
+
+ if (!NineSurface9_IsDirty(This))
+ return D3D_OK;
+
+ for (i = 0; i < Elements(This->dirty_rects); ++i) {
+ struct pipe_box box;
+ nine_u_rect_to_pipe_box(&box, &This->dirty_rects[i], This->layer);
+
+ if (box.width == 0)
+ break;
+ ptr = NineSurface9_GetSystemMemPointer(This, box.x, box.y);
+
+ pipe->transfer_inline_write(pipe, res, This->level,
+ 0,
+ &box, ptr, This->stride, 0);
+ }
+ NineSurface9_ClearDirtyRects(This);
+
+ return D3D_OK;
+}
+
+void
+NineSurface9_SetResourceResize( struct NineSurface9 *This,
+ struct pipe_resource *resource )
+{
+ assert(This->level == 0 && This->level_actual == 0);
+ assert(!This->lock_count);
+ assert(This->desc.Pool == D3DPOOL_DEFAULT);
+ assert(!This->texture);
+
+ pipe_resource_reference(&This->base.resource, resource);
+
+ This->desc.Width = This->base.info.width0 = resource->width0;
+ This->desc.Height = This->base.info.height0 = resource->height0;
+
+ This->stride = util_format_get_stride(This->base.info.format,
+ This->desc.Width);
+ This->stride = align(This->stride, 4);
+
+ pipe_surface_reference(&This->surface[0], NULL);
+ pipe_surface_reference(&This->surface[1], NULL);
+}
+
+
+static const GUID *NineSurface9_IIDs[] = {
+ &IID_IDirect3DSurface9,
+ &IID_IDirect3DResource9,
+ &IID_IUnknown,
+ NULL
+};
+
+HRESULT
+NineSurface9_new( struct NineDevice9 *pDevice,
+ struct NineUnknown *pContainer,
+ struct pipe_resource *pResource,
+ uint8_t TextureType,
+ unsigned Level,
+ unsigned Layer,
+ D3DSURFACE_DESC *pDesc,
+ struct NineSurface9 **ppOut )
+{
+ NINE_DEVICE_CHILD_NEW(Surface9, ppOut, pDevice, /* args */
+ pContainer, pResource,
+ TextureType, Level, Layer, pDesc);
+}
diff --git a/src/gallium/state_trackers/nine/surface9.h b/src/gallium/state_trackers/nine/surface9.h
new file mode 100644
index 00000000000..4a9db25237c
--- /dev/null
+++ b/src/gallium/state_trackers/nine/surface9.h
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _NINE_SURFACE9_H_
+#define _NINE_SURFACE9_H_
+
+#include "resource9.h"
+
+#include "pipe/p_state.h"
+#include "util/u_double_list.h"
+#include "util/u_rect.h"
+#include "util/u_inlines.h"
+
+struct NineSurface9
+{
+ struct NineResource9 base;
+
+ /* G3D state */
+ struct pipe_context *pipe;
+ struct pipe_transfer *transfer;
+ struct pipe_surface *surface[2]; /* created on-demand (linear, sRGB) */
+ int lock_count;
+ uint8_t texture; /* rtype of container BaseTex or 0 */
+
+ /* resource description */
+ unsigned level; /* refers to the pipe_resource (SetLOD !) */
+ unsigned level_actual; /* refers to the NineTexture */
+ unsigned layer;
+ D3DSURFACE_DESC desc;
+
+ unsigned stride; /* for system memory backing */
+
+ /* wine doesn't even use these, 2 will be enough */
+ struct u_rect dirty_rects[2];
+};
+static INLINE struct NineSurface9 *
+NineSurface9( void *data )
+{
+ return (struct NineSurface9 *)data;
+}
+
+HRESULT
+NineSurface9_new( struct NineDevice9 *pDevice,
+ struct NineUnknown *pContainer,
+ struct pipe_resource *pResource,
+ uint8_t TextureType, /* 0 if pContainer isn't BaseTexure9 */
+ unsigned Level,
+ unsigned Layer,
+ D3DSURFACE_DESC *pDesc,
+ struct NineSurface9 **ppOut );
+
+HRESULT
+NineSurface9_ctor( struct NineSurface9 *This,
+ struct NineUnknownParams *pParams,
+ struct NineUnknown *pContainer,
+ struct pipe_resource *pResource,
+ uint8_t TextureType,
+ unsigned Level,
+ unsigned Layer,
+ D3DSURFACE_DESC *pDesc );
+
+void
+NineSurface9_dtor( struct NineSurface9 *This );
+
+/*** Nine private ***/
+
+struct pipe_surface *
+NineSurface9_CreatePipeSurface( struct NineSurface9 *This, const int sRGB );
+
+static INLINE struct pipe_surface *
+NineSurface9_GetSurface( struct NineSurface9 *This, int sRGB )
+{
+ if (This->surface[sRGB])
+ return This->surface[sRGB];
+ return NineSurface9_CreatePipeSurface(This, sRGB);
+}
+
+static INLINE struct pipe_resource *
+NineSurface9_GetResource( struct NineSurface9 *This )
+{
+ return This->base.resource;
+}
+
+static INLINE void
+NineSurface9_SetResource( struct NineSurface9 *This,
+ struct pipe_resource *resource, unsigned level )
+{
+ This->level = level;
+ pipe_resource_reference(&This->base.resource, resource);
+ pipe_surface_reference(&This->surface[0], NULL);
+ pipe_surface_reference(&This->surface[1], NULL);
+}
+
+void
+NineSurface9_SetResourceResize( struct NineSurface9 *This,
+ struct pipe_resource *resource );
+
+void
+NineSurface9_AddDirtyRect( struct NineSurface9 *This,
+ const struct pipe_box *box );
+
+static INLINE void
+NineSurface9_ClearDirtyRects( struct NineSurface9 *This )
+{
+ memset(&This->dirty_rects, 0, sizeof(This->dirty_rects));
+}
+
+HRESULT
+NineSurface9_AllocateData( struct NineSurface9 *This );
+
+HRESULT
+NineSurface9_UploadSelf( struct NineSurface9 *This );
+
+HRESULT
+NineSurface9_CopySurface( struct NineSurface9 *This,
+ struct NineSurface9 *From,
+ const POINT *pDestPoint,
+ const RECT *pSourceRect );
+
+static INLINE boolean
+NineSurface9_IsOffscreenPlain (struct NineSurface9 *This )
+{
+ return This->base.usage == 0 && !This->texture;
+}
+
+#ifdef DEBUG
+void
+NineSurface9_Dump( struct NineSurface9 *This );
+#else
+static INLINE void
+NineSurface9_Dump( struct NineSurface9 *This ) { }
+#endif
+
+/*** Direct3D public ***/
+
+HRESULT WINAPI
+NineSurface9_GetContainer( struct NineSurface9 *This,
+ REFIID riid,
+ void **ppContainer );
+
+HRESULT WINAPI
+NineSurface9_GetDesc( struct NineSurface9 *This,
+ D3DSURFACE_DESC *pDesc );
+
+HRESULT WINAPI
+NineSurface9_LockRect( struct NineSurface9 *This,
+ D3DLOCKED_RECT *pLockedRect,
+ const RECT *pRect,
+ DWORD Flags );
+
+HRESULT WINAPI
+NineSurface9_UnlockRect( struct NineSurface9 *This );
+
+HRESULT WINAPI
+NineSurface9_GetDC( struct NineSurface9 *This,
+ HDC *phdc );
+
+HRESULT WINAPI
+NineSurface9_ReleaseDC( struct NineSurface9 *This,
+ HDC hdc );
+
+#endif /* _NINE_SURFACE9_H_ */
diff --git a/src/gallium/state_trackers/nine/swapchain9.c b/src/gallium/state_trackers/nine/swapchain9.c
new file mode 100644
index 00000000000..b6e81257aba
--- /dev/null
+++ b/src/gallium/state_trackers/nine/swapchain9.c
@@ -0,0 +1,871 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "swapchain9.h"
+#include "surface9.h"
+#include "device9.h"
+
+#include "nine_helpers.h"
+#include "nine_pipe.h"
+#include "nine_dump.h"
+
+#include "util/u_inlines.h"
+#include "util/u_surface.h"
+#include "hud/hud_context.h"
+#include "state_tracker/drm_driver.h"
+
+#define DBG_CHANNEL DBG_SWAPCHAIN
+
+#define UNTESTED(n) DBG("UNTESTED point %d. Please tell if it worked\n", n)
+
+HRESULT
+NineSwapChain9_ctor( struct NineSwapChain9 *This,
+ struct NineUnknownParams *pParams,
+ BOOL implicit,
+ ID3DPresent *pPresent,
+ D3DPRESENT_PARAMETERS *pPresentationParameters,
+ struct d3dadapter9_context *pCTX,
+ HWND hFocusWindow,
+ D3DDISPLAYMODEEX *mode )
+{
+ HRESULT hr;
+
+ DBG("This=%p pDevice=%p pPresent=%p pCTX=%p hFocusWindow=%p\n",
+ This, pParams->device, pPresent, pCTX, hFocusWindow);
+
+ hr = NineUnknown_ctor(&This->base, pParams);
+ if (FAILED(hr))
+ return hr;
+
+ This->screen = NineDevice9_GetScreen(This->base.device);
+ This->pipe = NineDevice9_GetPipe(This->base.device);
+ This->cso = NineDevice9_GetCSO(This->base.device);
+ This->implicit = implicit;
+ This->actx = pCTX;
+ This->present = pPresent;
+ This->mode = NULL;
+
+ ID3DPresent_AddRef(pPresent);
+
+ if (!pPresentationParameters->hDeviceWindow)
+ pPresentationParameters->hDeviceWindow = hFocusWindow;
+
+ This->rendering_done = FALSE;
+ return NineSwapChain9_Resize(This, pPresentationParameters, mode);
+}
+
+static D3DWindowBuffer *
+D3DWindowBuffer_create(struct NineSwapChain9 *This,
+ struct pipe_resource *resource,
+ int depth)
+{
+ D3DWindowBuffer *ret;
+ struct winsys_handle whandle;
+ int stride, dmaBufFd;
+
+ memset(&whandle, 0, sizeof(whandle));
+ whandle.type = DRM_API_HANDLE_TYPE_FD;
+ This->screen->resource_get_handle(This->screen, resource, &whandle);
+ stride = whandle.stride;
+ dmaBufFd = whandle.handle;
+ ID3DPresent_NewD3DWindowBufferFromDmaBuf(This->present,
+ dmaBufFd,
+ resource->width0,
+ resource->height0,
+ stride,
+ depth,
+ 32,
+ &ret);
+ return ret;
+}
+
+HRESULT
+NineSwapChain9_Resize( struct NineSwapChain9 *This,
+ D3DPRESENT_PARAMETERS *pParams,
+ D3DDISPLAYMODEEX *mode )
+{
+ struct NineDevice9 *pDevice = This->base.device;
+ struct NineSurface9 **bufs;
+ D3DSURFACE_DESC desc;
+ HRESULT hr;
+ struct pipe_resource *resource, tmplt;
+ enum pipe_format pf;
+ BOOL has_present_buffers = FALSE;
+ int depth;
+ unsigned i, oldBufferCount, newBufferCount;
+
+ DBG("This=%p pParams=%p\n", This, pParams);
+ user_assert(pParams != NULL, E_POINTER);
+
+ DBG("pParams(%p):\n"
+ "BackBufferWidth: %u\n"
+ "BackBufferHeight: %u\n"
+ "BackBufferFormat: %s\n"
+ "BackBufferCount: %u\n"
+ "MultiSampleType: %u\n"
+ "MultiSampleQuality: %u\n"
+ "SwapEffect: %u\n"
+ "hDeviceWindow: %p\n"
+ "Windowed: %i\n"
+ "EnableAutoDepthStencil: %i\n"
+ "AutoDepthStencilFormat: %s\n"
+ "Flags: %s\n"
+ "FullScreen_RefreshRateInHz: %u\n"
+ "PresentationInterval: %x\n", pParams,
+ pParams->BackBufferWidth, pParams->BackBufferHeight,
+ d3dformat_to_string(pParams->BackBufferFormat),
+ pParams->BackBufferCount,
+ pParams->MultiSampleType, pParams->MultiSampleQuality,
+ pParams->SwapEffect, pParams->hDeviceWindow, pParams->Windowed,
+ pParams->EnableAutoDepthStencil,
+ d3dformat_to_string(pParams->AutoDepthStencilFormat),
+ nine_D3DPRESENTFLAG_to_str(pParams->Flags),
+ pParams->FullScreen_RefreshRateInHz,
+ pParams->PresentationInterval);
+
+ if (pParams->SwapEffect == D3DSWAPEFFECT_COPY &&
+ pParams->BackBufferCount > 1) {
+ pParams->BackBufferCount = 1;
+ }
+
+ if (pParams->BackBufferCount > 3) {
+ pParams->BackBufferCount = 3;
+ }
+
+ if (pParams->BackBufferCount == 0) {
+ pParams->BackBufferCount = 1;
+ }
+
+ if (pParams->BackBufferFormat == D3DFMT_UNKNOWN) {
+ pParams->BackBufferFormat = D3DFMT_A8R8G8B8;
+ }
+
+ This->desired_fences = This->actx->throttling ? This->actx->throttling_value + 1 : 0;
+ /* +1 because we add the fence of the current buffer before popping an old one */
+ if (This->desired_fences > DRI_SWAP_FENCES_MAX)
+ This->desired_fences = DRI_SWAP_FENCES_MAX;
+
+ if (mode && This->mode) {
+ *(This->mode) = *mode;
+ } else if (mode) {
+ This->mode = malloc(sizeof(D3DDISPLAYMODEEX));
+ memcpy(This->mode, mode, sizeof(D3DDISPLAYMODEEX));
+ } else if (This->mode) {
+ free(This->mode);
+ This->mode = NULL;
+ }
+
+ /* Note: It is the role of the backend to fill if neccessary
+ * BackBufferWidth and BackBufferHeight */
+ ID3DPresent_SetPresentParameters(This->present, pParams, This->mode);
+
+ /* When we have flip behaviour, d3d9 expects we get back the screen buffer when we flip.
+ * Here we don't get back the initial content of the screen. To emulate the behaviour
+ * we allocate an additional buffer */
+ oldBufferCount = This->params.BackBufferCount ?
+ (This->params.BackBufferCount +
+ (This->params.SwapEffect != D3DSWAPEFFECT_COPY)) : 0;
+ newBufferCount = pParams->BackBufferCount +
+ (pParams->SwapEffect != D3DSWAPEFFECT_COPY);
+
+ pf = d3d9_to_pipe_format(pParams->BackBufferFormat);
+ if (This->actx->linear_framebuffer ||
+ (pf != PIPE_FORMAT_B8G8R8X8_UNORM &&
+ pf != PIPE_FORMAT_B8G8R8A8_UNORM) ||
+ pParams->SwapEffect != D3DSWAPEFFECT_DISCARD ||
+ pParams->MultiSampleType >= 2 ||
+ (This->actx->ref && This->actx->ref == This->screen))
+ has_present_buffers = TRUE;
+
+ /* Note: the buffer depth has to match the window depth.
+ * In practice, ARGB buffers can be used with windows
+ * of depth 24. Windows of depth 32 are extremely rare.
+ * So even if the buffer is ARGB, say it is depth 24.
+ * It is common practice, for example that's how
+ * glamor implements depth 24.
+ * TODO: handle windows with other depths. Not possible in the short term.
+ * For example 16 bits.*/
+ depth = 24;
+
+ tmplt.target = PIPE_TEXTURE_2D;
+ tmplt.width0 = pParams->BackBufferWidth;
+ tmplt.height0 = pParams->BackBufferHeight;
+ tmplt.depth0 = 1;
+ tmplt.last_level = 0;
+ tmplt.array_size = 1;
+ tmplt.usage = PIPE_USAGE_DEFAULT;
+ tmplt.flags = 0;
+
+ desc.Type = D3DRTYPE_SURFACE;
+ desc.Pool = D3DPOOL_DEFAULT;
+ desc.MultiSampleType = pParams->MultiSampleType;
+ desc.MultiSampleQuality = 0;
+ desc.Width = pParams->BackBufferWidth;
+ desc.Height = pParams->BackBufferHeight;
+
+ for (i = 0; i < oldBufferCount; i++) {
+ ID3DPresent_DestroyD3DWindowBuffer(This->present, This->present_handles[i]);
+ This->present_handles[i] = NULL;
+ if (This->present_buffers)
+ pipe_resource_reference(&(This->present_buffers[i]), NULL);
+ }
+
+ if (!has_present_buffers && This->present_buffers) {
+ FREE(This->present_buffers);
+ This->present_buffers = NULL;
+ }
+
+ if (newBufferCount != oldBufferCount) {
+ for (i = newBufferCount; i < oldBufferCount;
+ ++i)
+ NineUnknown_Detach(NineUnknown(This->buffers[i]));
+
+ bufs = REALLOC(This->buffers,
+ oldBufferCount * sizeof(This->buffers[0]),
+ newBufferCount * sizeof(This->buffers[0]));
+ if (!bufs)
+ return E_OUTOFMEMORY;
+ This->buffers = bufs;
+ if (has_present_buffers) {
+ This->present_buffers = REALLOC(This->present_buffers,
+ This->present_buffers == NULL ? 0 : oldBufferCount * sizeof(struct pipe_resource *),
+ newBufferCount * sizeof(struct pipe_resource *));
+ memset(This->present_buffers, 0, newBufferCount * sizeof(struct pipe_resource *));
+ }
+ This->present_handles = REALLOC(This->present_handles,
+ oldBufferCount * sizeof(D3DWindowBuffer *),
+ newBufferCount * sizeof(D3DWindowBuffer *));
+ for (i = oldBufferCount; i < newBufferCount; ++i) {
+ This->buffers[i] = NULL;
+ This->present_handles[i] = NULL;
+ }
+ }
+
+ for (i = 0; i < newBufferCount; ++i) {
+ tmplt.format = d3d9_to_pipe_format(pParams->BackBufferFormat);
+ tmplt.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_TRANSFER_READ |
+ PIPE_BIND_TRANSFER_WRITE | PIPE_BIND_RENDER_TARGET;
+ tmplt.nr_samples = pParams->MultiSampleType;
+ if (!has_present_buffers)
+ tmplt.bind |= PIPE_BIND_SHARED | PIPE_BIND_SCANOUT | PIPE_BIND_DISPLAY_TARGET;
+ resource = This->screen->resource_create(This->screen, &tmplt);
+ if (!resource) {
+ DBG("Failed to create pipe_resource.\n");
+ return D3DERR_OUTOFVIDEOMEMORY;
+ }
+ if (pParams->Flags & D3DPRESENTFLAG_LOCKABLE_BACKBUFFER)
+ resource->flags |= NINE_RESOURCE_FLAG_LOCKABLE;
+ if (This->buffers[i]) {
+ NineSurface9_SetResourceResize(This->buffers[i], resource);
+ if (has_present_buffers)
+ pipe_resource_reference(&resource, NULL);
+ } else {
+ desc.Format = pParams->BackBufferFormat;
+ desc.Usage = D3DUSAGE_RENDERTARGET;
+ hr = NineSurface9_new(pDevice, NineUnknown(This), resource, 0,
+ 0, 0, &desc, &This->buffers[i]);
+ if (has_present_buffers)
+ pipe_resource_reference(&resource, NULL);
+ if (FAILED(hr)) {
+ DBG("Failed to create RT surface.\n");
+ return hr;
+ }
+ This->buffers[i]->base.base.forward = FALSE;
+ }
+ if (has_present_buffers) {
+ tmplt.format = PIPE_FORMAT_B8G8R8X8_UNORM;
+ tmplt.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_SHARED | PIPE_BIND_SCANOUT | PIPE_BIND_DISPLAY_TARGET;
+ tmplt.nr_samples = 0;
+ if (This->actx->linear_framebuffer)
+ tmplt.bind |= PIPE_BIND_LINEAR;
+ if (pParams->SwapEffect != D3DSWAPEFFECT_DISCARD)
+ tmplt.bind |= PIPE_BIND_RENDER_TARGET;
+ resource = This->screen->resource_create(This->screen, &tmplt);
+ pipe_resource_reference(&(This->present_buffers[i]), resource);
+ }
+ This->present_handles[i] = D3DWindowBuffer_create(This, resource, depth);
+ if (!has_present_buffers)
+ pipe_resource_reference(&resource, NULL);
+ }
+ if (pParams->EnableAutoDepthStencil) {
+ tmplt.format = d3d9_to_pipe_format(pParams->AutoDepthStencilFormat);
+ tmplt.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_TRANSFER_READ |
+ PIPE_BIND_TRANSFER_WRITE | PIPE_BIND_DEPTH_STENCIL;
+ tmplt.nr_samples = pParams->MultiSampleType;
+
+ resource = This->screen->resource_create(This->screen, &tmplt);
+ if (!resource) {
+ DBG("Failed to create pipe_resource for depth buffer.\n");
+ return D3DERR_OUTOFVIDEOMEMORY;
+ }
+ if (This->zsbuf) {
+ NineSurface9_SetResourceResize(This->zsbuf, resource);
+ pipe_resource_reference(&resource, NULL);
+ } else {
+ /* XXX wine thinks the container of this should be the device */
+ desc.Format = pParams->AutoDepthStencilFormat;
+ desc.Usage = D3DUSAGE_DEPTHSTENCIL;
+ hr = NineSurface9_new(pDevice, NineUnknown(pDevice), resource, 0,
+ 0, 0, &desc, &This->zsbuf);
+ pipe_resource_reference(&resource, NULL);
+ if (FAILED(hr)) {
+ DBG("Failed to create ZS surface.\n");
+ return hr;
+ }
+ This->zsbuf->base.base.forward = FALSE;
+ }
+ }
+
+ This->params = *pParams;
+
+ return D3D_OK;
+}
+
+/* Throttling: code adapted from the dri state tracker */
+
+/**
+ * swap_fences_pop_front - pull a fence from the throttle queue
+ *
+ * If the throttle queue is filled to the desired number of fences,
+ * pull fences off the queue until the number is less than the desired
+ * number of fences, and return the last fence pulled.
+ */
+static struct pipe_fence_handle *
+swap_fences_pop_front(struct NineSwapChain9 *This)
+{
+ struct pipe_screen *screen = This->screen;
+ struct pipe_fence_handle *fence = NULL;
+
+ if (This->desired_fences == 0)
+ return NULL;
+
+ if (This->cur_fences >= This->desired_fences) {
+ screen->fence_reference(screen, &fence, This->swap_fences[This->tail]);
+ screen->fence_reference(screen, &This->swap_fences[This->tail++], NULL);
+ This->tail &= DRI_SWAP_FENCES_MASK;
+ --This->cur_fences;
+ }
+ return fence;
+}
+
+
+/**
+ * swap_fences_see_front - same than swap_fences_pop_front without
+ * pulling
+ *
+ */
+
+static struct pipe_fence_handle *
+swap_fences_see_front(struct NineSwapChain9 *This)
+{
+ struct pipe_screen *screen = This->screen;
+ struct pipe_fence_handle *fence = NULL;
+
+ if (This->desired_fences == 0)
+ return NULL;
+
+ if (This->cur_fences >= This->desired_fences) {
+ screen->fence_reference(screen, &fence, This->swap_fences[This->tail]);
+ }
+ return fence;
+}
+
+
+/**
+ * swap_fences_push_back - push a fence onto the throttle queue at the back
+ *
+ * push a fence onto the throttle queue and pull fences of the queue
+ * so that the desired number of fences are on the queue.
+ */
+static void
+swap_fences_push_back(struct NineSwapChain9 *This,
+ struct pipe_fence_handle *fence)
+{
+ struct pipe_screen *screen = This->screen;
+
+ if (!fence || This->desired_fences == 0)
+ return;
+
+ while(This->cur_fences == This->desired_fences)
+ swap_fences_pop_front(This);
+
+ This->cur_fences++;
+ screen->fence_reference(screen, &This->swap_fences[This->head++],
+ fence);
+ This->head &= DRI_SWAP_FENCES_MASK;
+}
+
+
+/**
+ * swap_fences_unref - empty the throttle queue
+ *
+ * pulls fences of the throttle queue until it is empty.
+ */
+static void
+swap_fences_unref(struct NineSwapChain9 *This)
+{
+ struct pipe_screen *screen = This->screen;
+
+ while(This->cur_fences) {
+ screen->fence_reference(screen, &This->swap_fences[This->tail++], NULL);
+ This->tail &= DRI_SWAP_FENCES_MASK;
+ --This->cur_fences;
+ }
+}
+
+void
+NineSwapChain9_dtor( struct NineSwapChain9 *This )
+{
+ unsigned i;
+
+ DBG("This=%p\n", This);
+
+ if (This->buffers) {
+ for (i = 0; i < This->params.BackBufferCount; i++) {
+ NineUnknown_Destroy(NineUnknown(This->buffers[i]));
+ ID3DPresent_DestroyD3DWindowBuffer(This->present, This->present_handles[i]);
+ if (This->present_buffers)
+ pipe_resource_reference(&(This->present_buffers[i]), NULL);
+ }
+ FREE(This->buffers);
+ FREE(This->present_buffers);
+ }
+ if (This->zsbuf)
+ NineUnknown_Destroy(NineUnknown(This->zsbuf));
+
+ if (This->present)
+ ID3DPresent_Release(This->present);
+
+ swap_fences_unref(This);
+ NineUnknown_dtor(&This->base);
+}
+
+static void
+create_present_buffer( struct NineSwapChain9 *This,
+ unsigned int width, unsigned int height,
+ struct pipe_resource **resource,
+ D3DWindowBuffer **present_handle)
+{
+ struct pipe_resource tmplt;
+
+ tmplt.target = PIPE_TEXTURE_2D;
+ tmplt.width0 = width;
+ tmplt.height0 = height;
+ tmplt.depth0 = 1;
+ tmplt.last_level = 0;
+ tmplt.array_size = 1;
+ tmplt.usage = PIPE_USAGE_DEFAULT;
+ tmplt.flags = 0;
+ tmplt.format = PIPE_FORMAT_B8G8R8X8_UNORM;
+ tmplt.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_TRANSFER_READ |
+ PIPE_BIND_TRANSFER_WRITE | PIPE_BIND_RENDER_TARGET |
+ PIPE_BIND_SHARED | PIPE_BIND_SCANOUT | PIPE_BIND_DISPLAY_TARGET;
+ tmplt.nr_samples = 0;
+ if (This->actx->linear_framebuffer)
+ tmplt.bind |= PIPE_BIND_LINEAR;
+ *resource = This->screen->resource_create(This->screen, &tmplt);
+
+ *present_handle = D3DWindowBuffer_create(This, *resource, 24);
+}
+
+static void
+handle_draw_cursor_and_hud( struct NineSwapChain9 *This, struct pipe_resource *resource)
+{
+ struct NineDevice9 *device = This->base.device;
+ struct pipe_blit_info blit;
+
+ if (device->cursor.software && device->cursor.visible && device->cursor.w) {
+ blit.src.resource = device->cursor.image;
+ blit.src.level = 0;
+ blit.src.format = device->cursor.image->format;
+ blit.src.box.x = 0;
+ blit.src.box.y = 0;
+ blit.src.box.z = 0;
+ blit.src.box.depth = 1;
+ blit.src.box.width = device->cursor.w;
+ blit.src.box.height = device->cursor.h;
+
+ blit.dst.resource = resource;
+ blit.dst.level = 0;
+ blit.dst.format = resource->format;
+ blit.dst.box.z = 0;
+ blit.dst.box.depth = 1;
+
+ blit.mask = PIPE_MASK_RGBA;
+ blit.filter = PIPE_TEX_FILTER_NEAREST;
+ blit.scissor_enable = FALSE;
+
+ ID3DPresent_GetCursorPos(This->present, &device->cursor.pos);
+
+ /* NOTE: blit messes up when box.x + box.width < 0, fix driver */
+ blit.dst.box.x = MAX2(device->cursor.pos.x, 0) - device->cursor.hotspot.x;
+ blit.dst.box.y = MAX2(device->cursor.pos.y, 0) - device->cursor.hotspot.y;
+ blit.dst.box.width = blit.src.box.width;
+ blit.dst.box.height = blit.src.box.height;
+
+ DBG("Blitting cursor(%ux%u) to (%i,%i).\n",
+ blit.src.box.width, blit.src.box.height,
+ blit.dst.box.x, blit.dst.box.y);
+
+ This->pipe->blit(This->pipe, &blit);
+ }
+
+ if (device->hud && resource) {
+ hud_draw(device->hud, resource); /* XXX: no offset */
+ /* HUD doesn't clobber stipple */
+ NineDevice9_RestoreNonCSOState(device, ~0x2);
+ }
+}
+
+static INLINE HRESULT
+present( struct NineSwapChain9 *This,
+ const RECT *pSourceRect,
+ const RECT *pDestRect,
+ HWND hDestWindowOverride,
+ const RGNDATA *pDirtyRegion,
+ DWORD dwFlags )
+{
+ struct pipe_resource *resource;
+ struct pipe_fence_handle *fence;
+ HRESULT hr;
+ struct pipe_blit_info blit;
+
+ DBG("present: This=%p pSourceRect=%p pDestRect=%p "
+ "pDirtyRegion=%p hDestWindowOverride=%p"
+ "dwFlags=%d resource=%p\n",
+ This, pSourceRect, pDestRect, pDirtyRegion,
+ hDestWindowOverride, (int)dwFlags, This->buffers[0]->base.resource);
+
+ if (pSourceRect)
+ DBG("pSourceRect = (%u..%u)x(%u..%u)\n",
+ pSourceRect->left, pSourceRect->right,
+ pSourceRect->top, pSourceRect->bottom);
+ if (pDestRect)
+ DBG("pDestRect = (%u..%u)x(%u..%u)\n",
+ pDestRect->left, pDestRect->right,
+ pDestRect->top, pDestRect->bottom);
+
+ /* TODO: in the case the source and destination rect have different size:
+ * We need to allocate a new buffer, and do a blit to it to resize.
+ * We can't use the present_buffer for that since when we created it,
+ * we couldn't guess which size would have been needed.
+ * If pDestRect or pSourceRect is null, we have to check the sizes
+ * from the source size, and the destination window size.
+ * In this case, either resize rngdata, or pass NULL instead
+ */
+ /* Note: This->buffers[0]->level should always be 0 */
+
+ if (This->rendering_done)
+ goto bypass_rendering;
+
+ resource = This->buffers[0]->base.resource;
+
+ if (This->params.SwapEffect == D3DSWAPEFFECT_DISCARD)
+ handle_draw_cursor_and_hud(This, resource);
+
+ if (This->present_buffers) {
+ blit.src.resource = resource;
+ blit.src.level = 0;
+ blit.src.format = resource->format;
+ blit.src.box.z = 0;
+ blit.src.box.depth = 1;
+ blit.src.box.x = 0;
+ blit.src.box.y = 0;
+ blit.src.box.width = resource->width0;
+ blit.src.box.height = resource->height0;
+
+ resource = This->present_buffers[0];
+
+ blit.dst.resource = resource;
+ blit.dst.level = 0;
+ blit.dst.format = resource->format;
+ blit.dst.box.z = 0;
+ blit.dst.box.depth = 1;
+ blit.dst.box.x = 0;
+ blit.dst.box.y = 0;
+ blit.dst.box.width = resource->width0;
+ blit.dst.box.height = resource->height0;
+
+ blit.mask = PIPE_MASK_RGBA;
+ blit.filter = PIPE_TEX_FILTER_NEAREST;
+ blit.scissor_enable = FALSE;
+
+ This->pipe->blit(This->pipe, &blit);
+ }
+
+ if (This->params.SwapEffect != D3DSWAPEFFECT_DISCARD)
+ handle_draw_cursor_and_hud(This, resource);
+
+ fence = NULL;
+ This->pipe->flush(This->pipe, &fence, PIPE_FLUSH_END_OF_FRAME);
+ if (fence) {
+ swap_fences_push_back(This, fence);
+ This->screen->fence_reference(This->screen, &fence, NULL);
+ }
+
+ This->rendering_done = TRUE;
+bypass_rendering:
+
+ if (dwFlags & D3DPRESENT_DONOTWAIT) {
+ UNTESTED(2);
+ BOOL still_draw = FALSE;
+ fence = swap_fences_see_front(This);
+ if (fence) {
+ still_draw = !This->screen->fence_signalled(This->screen, fence);
+ This->screen->fence_reference(This->screen, &fence, NULL);
+ }
+ if (still_draw)
+ return D3DERR_WASSTILLDRAWING;
+ }
+
+ fence = swap_fences_pop_front(This);
+ if (fence) {
+ (void) This->screen->fence_finish(This->screen, fence, PIPE_TIMEOUT_INFINITE);
+ This->screen->fence_reference(This->screen, &fence, NULL);
+ }
+
+ if (This->present_buffers)
+ resource = This->present_buffers[0];
+ else
+ resource = This->buffers[0]->base.resource;
+ This->pipe->flush_resource(This->pipe, resource);
+ hr = ID3DPresent_PresentBuffer(This->present, This->present_handles[0], hDestWindowOverride, pSourceRect, pDestRect, pDirtyRegion, dwFlags);
+
+ if (FAILED(hr)) { UNTESTED(3);return hr; }
+
+ This->rendering_done = FALSE;
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineSwapChain9_Present( struct NineSwapChain9 *This,
+ const RECT *pSourceRect,
+ const RECT *pDestRect,
+ HWND hDestWindowOverride,
+ const RGNDATA *pDirtyRegion,
+ DWORD dwFlags )
+{
+ struct pipe_resource *res = NULL;
+ D3DWindowBuffer *handle_temp;
+ int i;
+ BOOL released;
+ HRESULT hr = present(This, pSourceRect, pDestRect,
+ hDestWindowOverride, pDirtyRegion, dwFlags);
+
+ if (hr == D3DERR_WASSTILLDRAWING)
+ return hr;
+
+ switch (This->params.SwapEffect) {
+ case D3DSWAPEFFECT_FLIP:
+ UNTESTED(4);
+ case D3DSWAPEFFECT_DISCARD:
+ /* rotate the queue */;
+ pipe_resource_reference(&res, This->buffers[0]->base.resource);
+ for (i = 1; i <= This->params.BackBufferCount; i++) {
+ NineSurface9_SetResourceResize(This->buffers[i - 1],
+ This->buffers[i]->base.resource);
+ }
+ NineSurface9_SetResourceResize(
+ This->buffers[This->params.BackBufferCount], res);
+ pipe_resource_reference(&res, NULL);
+
+ if (This->present_buffers) {
+ pipe_resource_reference(&res, This->present_buffers[0]);
+ for (i = 1; i <= This->params.BackBufferCount; i++)
+ pipe_resource_reference(&(This->present_buffers[i-1]), This->present_buffers[i]);
+ pipe_resource_reference(&(This->present_buffers[This->params.BackBufferCount]), res);
+ pipe_resource_reference(&res, NULL);
+ }
+
+ handle_temp = This->present_handles[0];
+ for (i = 1; i <= This->params.BackBufferCount; i++) {
+ This->present_handles[i-1] = This->present_handles[i];
+ }
+ This->present_handles[This->params.BackBufferCount] = handle_temp;
+ break;
+
+ case D3DSWAPEFFECT_COPY:
+ UNTESTED(5);
+ /* do nothing */
+ break;
+
+ case D3DSWAPEFFECT_OVERLAY:
+ /* XXX not implemented */
+ break;
+
+ case D3DSWAPEFFECT_FLIPEX:
+ /* XXX not implemented */
+ break;
+ }
+
+ ID3DPresent_WaitBufferReleased(This->present, This->present_handles[0]);
+
+ This->base.device->state.changed.group |= NINE_STATE_FB;
+ nine_update_state(This->base.device, NINE_STATE_FB);
+
+ return hr;
+}
+
+HRESULT WINAPI
+NineSwapChain9_GetFrontBufferData( struct NineSwapChain9 *This,
+ IDirect3DSurface9 *pDestSurface )
+{
+ struct NineSurface9 *dest_surface = NineSurface9(pDestSurface);
+ struct NineDevice9 *pDevice = This->base.device;
+ unsigned int width, height;
+ struct pipe_resource *temp_resource;
+ struct NineSurface9 *temp_surface;
+ D3DWindowBuffer *temp_handle;
+ D3DSURFACE_DESC desc;
+ HRESULT hr;
+
+ DBG("GetFrontBufferData: This=%p pDestSurface=%p\n",
+ This, pDestSurface);
+
+ width = dest_surface->desc.Width;
+ height = dest_surface->desc.Height;
+
+ /* Note: front window size and destination size are supposed
+ * to match. However it's not very clear what should get taken in Windowed
+ * mode. It may need a fix */
+ create_present_buffer(This, width, height, &temp_resource, &temp_handle);
+
+ desc.Type = D3DRTYPE_SURFACE;
+ desc.Pool = D3DPOOL_DEFAULT;
+ desc.MultiSampleType = D3DMULTISAMPLE_NONE;
+ desc.MultiSampleQuality = 0;
+ desc.Width = width;
+ desc.Height = height;
+ /* NineSurface9_CopySurface needs same format. */
+ desc.Format = dest_surface->desc.Format;
+ desc.Usage = D3DUSAGE_RENDERTARGET;
+ hr = NineSurface9_new(pDevice, NineUnknown(This), temp_resource, 0,
+ 0, 0, &desc, &temp_surface);
+ pipe_resource_reference(&temp_resource, NULL);
+ if (FAILED(hr)) {
+ DBG("Failed to create temp FrontBuffer surface.\n");
+ return hr;
+ }
+
+ ID3DPresent_FrontBufferCopy(This->present, temp_handle);
+
+ NineSurface9_CopySurface(dest_surface, temp_surface, NULL, NULL);
+
+ ID3DPresent_DestroyD3DWindowBuffer(This->present, temp_handle);
+ NineUnknown_Destroy(NineUnknown(temp_surface));
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineSwapChain9_GetBackBuffer( struct NineSwapChain9 *This,
+ UINT iBackBuffer,
+ D3DBACKBUFFER_TYPE Type,
+ IDirect3DSurface9 **ppBackBuffer )
+{
+ DBG("GetBackBuffer: This=%p iBackBuffer=%d Type=%d ppBackBuffer=%p\n",
+ This, iBackBuffer, Type, ppBackBuffer);
+ (void)user_error(Type == D3DBACKBUFFER_TYPE_MONO);
+ user_assert(iBackBuffer < This->params.BackBufferCount, D3DERR_INVALIDCALL);
+ user_assert(ppBackBuffer != NULL, E_POINTER);
+
+ NineUnknown_AddRef(NineUnknown(This->buffers[iBackBuffer]));
+ *ppBackBuffer = (IDirect3DSurface9 *)This->buffers[iBackBuffer];
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineSwapChain9_GetRasterStatus( struct NineSwapChain9 *This,
+ D3DRASTER_STATUS *pRasterStatus )
+{
+ DBG("GetRasterStatus: This=%p pRasterStatus=%p\n",
+ This, pRasterStatus);
+ user_assert(pRasterStatus != NULL, E_POINTER);
+ return ID3DPresent_GetRasterStatus(This->present, pRasterStatus);
+}
+
+HRESULT WINAPI
+NineSwapChain9_GetDisplayMode( struct NineSwapChain9 *This,
+ D3DDISPLAYMODE *pMode )
+{
+ D3DDISPLAYMODEEX mode;
+ D3DDISPLAYROTATION rot;
+ HRESULT hr;
+
+ DBG("GetDisplayMode: This=%p pMode=%p\n",
+ This, pMode);
+ user_assert(pMode != NULL, E_POINTER);
+
+ hr = ID3DPresent_GetDisplayMode(This->present, &mode, &rot);
+ if (SUCCEEDED(hr)) {
+ pMode->Width = mode.Width;
+ pMode->Height = mode.Height;
+ pMode->RefreshRate = mode.RefreshRate;
+ pMode->Format = mode.Format;
+ }
+ return hr;
+}
+
+HRESULT WINAPI
+NineSwapChain9_GetPresentParameters( struct NineSwapChain9 *This,
+ D3DPRESENT_PARAMETERS *pPresentationParameters )
+{
+ DBG("GetPresentParameters: This=%p pPresentationParameters=%p\n",
+ This, pPresentationParameters);
+ user_assert(pPresentationParameters != NULL, E_POINTER);
+ *pPresentationParameters = This->params;
+ return D3D_OK;
+}
+
+IDirect3DSwapChain9Vtbl NineSwapChain9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)NineSwapChain9_Present,
+ (void *)NineSwapChain9_GetFrontBufferData,
+ (void *)NineSwapChain9_GetBackBuffer,
+ (void *)NineSwapChain9_GetRasterStatus,
+ (void *)NineSwapChain9_GetDisplayMode,
+ (void *)NineUnknown_GetDevice, /* actually part of SwapChain9 iface */
+ (void *)NineSwapChain9_GetPresentParameters
+};
+
+static const GUID *NineSwapChain9_IIDs[] = {
+ &IID_IDirect3DSwapChain9,
+ &IID_IUnknown,
+ NULL
+};
+
+HRESULT
+NineSwapChain9_new( struct NineDevice9 *pDevice,
+ BOOL implicit,
+ ID3DPresent *pPresent,
+ D3DPRESENT_PARAMETERS *pPresentationParameters,
+ struct d3dadapter9_context *pCTX,
+ HWND hFocusWindow,
+ struct NineSwapChain9 **ppOut )
+{
+ NINE_DEVICE_CHILD_NEW(SwapChain9, ppOut, pDevice, /* args */
+ implicit, pPresent, pPresentationParameters,
+ pCTX, hFocusWindow, NULL);
+}
diff --git a/src/gallium/state_trackers/nine/swapchain9.h b/src/gallium/state_trackers/nine/swapchain9.h
new file mode 100644
index 00000000000..566f78ab0ed
--- /dev/null
+++ b/src/gallium/state_trackers/nine/swapchain9.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _NINE_SWAPCHAIN9_H_
+#define _NINE_SWAPCHAIN9_H_
+
+#include "iunknown.h"
+#include "adapter9.h"
+
+#include "d3dadapter/d3dadapter9.h"
+
+struct NineDevice9;
+struct NineSurface9;
+struct nine_winsys_swapchain;
+struct blit_state;
+
+#define DRI_SWAP_FENCES_MAX 4
+#define DRI_SWAP_FENCES_MASK 3
+
+struct NineSwapChain9
+{
+ struct NineUnknown base;
+
+ /* G3D stuff */
+ struct pipe_screen *screen;
+ struct pipe_context *pipe;
+ struct cso_context *cso;
+
+ /* presentation backend */
+ ID3DPresent *present;
+ D3DPRESENT_PARAMETERS params;
+ D3DDISPLAYMODEEX *mode;
+ struct d3dadapter9_context *actx;
+ BOOL implicit;
+
+ /* buffer handles */
+ struct NineSurface9 **buffers; /* 0 to BackBufferCount-1 : the back buffers. BackBufferCount : additional buffer */
+ struct pipe_resource **present_buffers;
+ D3DWindowBuffer **present_handles;
+
+ struct pipe_fence_handle *swap_fences[DRI_SWAP_FENCES_MAX];
+ unsigned int cur_fences;
+ unsigned int head;
+ unsigned int tail;
+ unsigned int desired_fences;
+
+ BOOL rendering_done;
+
+ struct NineSurface9 *zsbuf;
+
+ D3DGAMMARAMP gamma;
+};
+static INLINE struct NineSwapChain9 *
+NineSwapChain9( void *data )
+{
+ return (struct NineSwapChain9 *)data;
+}
+
+HRESULT
+NineSwapChain9_new( struct NineDevice9 *pDevice,
+ BOOL implicit,
+ ID3DPresent *pPresent,
+ D3DPRESENT_PARAMETERS *pPresentationParameters,
+ struct d3dadapter9_context *pCTX,
+ HWND hFocusWindow,
+ struct NineSwapChain9 **ppOut );
+
+HRESULT
+NineSwapChain9_ctor( struct NineSwapChain9 *This,
+ struct NineUnknownParams *pParams,
+ BOOL implicit,
+ ID3DPresent *pPresent,
+ D3DPRESENT_PARAMETERS *pPresentationParameters,
+ struct d3dadapter9_context *pCTX,
+ HWND hFocusWindow,
+ D3DDISPLAYMODEEX *mode );
+
+void
+NineSwapChain9_dtor( struct NineSwapChain9 *This );
+
+HRESULT
+NineSwapChain9_Resize( struct NineSwapChain9 *This,
+ D3DPRESENT_PARAMETERS *pParams,
+ D3DDISPLAYMODEEX *mode );
+
+HRESULT WINAPI
+NineSwapChain9_Present( struct NineSwapChain9 *This,
+ const RECT *pSourceRect,
+ const RECT *pDestRect,
+ HWND hDestWindowOverride,
+ const RGNDATA *pDirtyRegion,
+ DWORD dwFlags );
+
+HRESULT WINAPI
+NineSwapChain9_GetFrontBufferData( struct NineSwapChain9 *This,
+ IDirect3DSurface9 *pDestSurface );
+
+HRESULT WINAPI
+NineSwapChain9_GetBackBuffer( struct NineSwapChain9 *This,
+ UINT iBackBuffer,
+ D3DBACKBUFFER_TYPE Type,
+ IDirect3DSurface9 **ppBackBuffer );
+
+HRESULT WINAPI
+NineSwapChain9_GetRasterStatus( struct NineSwapChain9 *This,
+ D3DRASTER_STATUS *pRasterStatus );
+
+HRESULT WINAPI
+NineSwapChain9_GetDisplayMode( struct NineSwapChain9 *This,
+ D3DDISPLAYMODE *pMode );
+
+HRESULT WINAPI
+NineSwapChain9_GetPresentParameters( struct NineSwapChain9 *This,
+ D3DPRESENT_PARAMETERS *pPresentationParameters );
+
+#endif /* _NINE_SWAPCHAIN9_H_ */
diff --git a/src/gallium/state_trackers/nine/swapchain9ex.c b/src/gallium/state_trackers/nine/swapchain9ex.c
new file mode 100644
index 00000000000..7207b585f08
--- /dev/null
+++ b/src/gallium/state_trackers/nine/swapchain9ex.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "swapchain9ex.h"
+#include "device9.h"
+
+#include "nine_helpers.h"
+
+#define DBG_CHANNEL DBG_SWAPCHAIN
+
+static HRESULT
+NineSwapChain9Ex_ctor( struct NineSwapChain9Ex *This,
+ struct NineUnknownParams *pParams,
+ BOOL implicit,
+ ID3DPresent *pPresent,
+ D3DPRESENT_PARAMETERS *pPresentationParameters,
+ struct d3dadapter9_context *pCTX,
+ HWND hFocusWindow,
+ D3DDISPLAYMODEEX *mode )
+{
+ return NineSwapChain9_ctor(&This->base, pParams, implicit, pPresent,
+ pPresentationParameters, pCTX, hFocusWindow, mode);
+}
+
+static void
+NineSwapChain9Ex_dtor( struct NineSwapChain9Ex *This )
+{
+ NineSwapChain9_dtor(&This->base);
+}
+
+HRESULT WINAPI
+NineSwapChain9Ex_GetLastPresentCount( struct NineSwapChain9Ex *This,
+ UINT *pLastPresentCount )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineSwapChain9Ex_GetPresentStats( struct NineSwapChain9Ex *This,
+ D3DPRESENTSTATS *pPresentationStatistics )
+{
+ STUB(D3DERR_INVALIDCALL);
+}
+
+HRESULT WINAPI
+NineSwapChain9Ex_GetDisplayModeEx( struct NineSwapChain9Ex *This,
+ D3DDISPLAYMODEEX *pMode,
+ D3DDISPLAYROTATION *pRotation )
+{
+ D3DDISPLAYROTATION rot;
+
+ user_assert(pMode != NULL, E_POINTER);
+ if (!pRotation) { pRotation = &rot; }
+
+ return ID3DPresent_GetDisplayMode(This->base.present, pMode, pRotation);
+}
+
+IDirect3DSwapChain9ExVtbl NineSwapChain9Ex_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)NineSwapChain9_Present,
+ (void *)NineSwapChain9_GetFrontBufferData,
+ (void *)NineSwapChain9_GetBackBuffer,
+ (void *)NineSwapChain9_GetRasterStatus,
+ (void *)NineSwapChain9_GetDisplayMode,
+ (void *)NineUnknown_GetDevice, /* actually part of NineSwapChain9 iface */
+ (void *)NineSwapChain9_GetPresentParameters,
+ (void *)NineSwapChain9Ex_GetLastPresentCount,
+ (void *)NineSwapChain9Ex_GetPresentStats,
+ (void *)NineSwapChain9Ex_GetDisplayModeEx
+};
+
+static const GUID *NineSwapChain9Ex_IIDs[] = {
+ &IID_IDirect3DSwapChain9Ex,
+ &IID_IDirect3DSwapChain9,
+ &IID_IUnknown,
+ NULL
+};
+
+HRESULT
+NineSwapChain9Ex_new( struct NineDevice9 *pDevice,
+ BOOL implicit,
+ ID3DPresent *pPresent,
+ D3DPRESENT_PARAMETERS *pPresentationParameters,
+ struct d3dadapter9_context *pCTX,
+ HWND hFocusWindow,
+ D3DDISPLAYMODEEX *mode,
+ struct NineSwapChain9Ex **ppOut )
+{
+ NINE_DEVICE_CHILD_NEW(SwapChain9Ex, ppOut, pDevice, /* args */
+ implicit, pPresent, pPresentationParameters,
+ pCTX, hFocusWindow, mode);
+}
diff --git a/src/gallium/state_trackers/nine/swapchain9ex.h b/src/gallium/state_trackers/nine/swapchain9ex.h
new file mode 100644
index 00000000000..bf407836099
--- /dev/null
+++ b/src/gallium/state_trackers/nine/swapchain9ex.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _NINE_SWAPCHAIN9EX_H_
+#define _NINE_SWAPCHAIN9EX_H_
+
+#include "swapchain9.h"
+
+struct NineSwapChain9Ex
+{
+ struct NineSwapChain9 base;
+};
+static INLINE struct NineSwapChain9Ex *
+NineSwapChain9Ex( void *data )
+{
+ return (struct NineSwapChain9Ex *)data;
+}
+
+HRESULT
+NineSwapChain9Ex_new( struct NineDevice9 *pDevice,
+ BOOL implicit,
+ ID3DPresent *pPresent,
+ D3DPRESENT_PARAMETERS *pPresentationParameters,
+ struct d3dadapter9_context *pCTX,
+ HWND hFocusWindow,
+ D3DDISPLAYMODEEX *mode,
+ struct NineSwapChain9Ex **ppOut );
+
+HRESULT WINAPI
+NineSwapChain9Ex_GetLastPresentCount( struct NineSwapChain9Ex *This,
+ UINT *pLastPresentCount );
+
+HRESULT WINAPI
+NineSwapChain9Ex_GetPresentStats( struct NineSwapChain9Ex *This,
+ D3DPRESENTSTATS *pPresentationStatistics );
+
+HRESULT WINAPI
+NineSwapChain9Ex_GetDisplayModeEx( struct NineSwapChain9Ex *This,
+ D3DDISPLAYMODEEX *pMode,
+ D3DDISPLAYROTATION *pRotation );
+
+#endif /* _NINE_SWAPCHAIN9EX_H_ */
diff --git a/src/gallium/state_trackers/nine/texture9.c b/src/gallium/state_trackers/nine/texture9.c
new file mode 100644
index 00000000000..c13268db9fd
--- /dev/null
+++ b/src/gallium/state_trackers/nine/texture9.c
@@ -0,0 +1,342 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "device9.h"
+#include "surface9.h"
+#include "texture9.h"
+#include "nine_helpers.h"
+#include "nine_pipe.h"
+#include "nine_dump.h"
+
+#include "pipe/p_state.h"
+#include "pipe/p_context.h"
+#include "pipe/p_screen.h"
+#include "util/u_inlines.h"
+#include "util/u_resource.h"
+
+#define DBG_CHANNEL DBG_TEXTURE
+
+static HRESULT
+NineTexture9_ctor( struct NineTexture9 *This,
+ struct NineUnknownParams *pParams,
+ UINT Width, UINT Height, UINT Levels,
+ DWORD Usage,
+ D3DFORMAT Format,
+ D3DPOOL Pool,
+ HANDLE *pSharedHandle )
+{
+ struct pipe_screen *screen = pParams->device->screen;
+ struct pipe_resource *info = &This->base.base.info;
+ unsigned l;
+ D3DSURFACE_DESC sfdesc;
+ HRESULT hr;
+ const boolean shared_create = pSharedHandle && !*pSharedHandle;
+
+ DBG("(%p) Width=%u Height=%u Levels=%u Usage=%s Format=%s Pool=%s "
+ "pSharedHandle=%p\n", This, Width, Height, Levels,
+ nine_D3DUSAGE_to_str(Usage),
+ d3dformat_to_string(Format), nine_D3DPOOL_to_str(Pool), pSharedHandle);
+
+ user_assert(!(Usage & D3DUSAGE_AUTOGENMIPMAP) ||
+ (Pool != D3DPOOL_SYSTEMMEM && Levels <= 1), D3DERR_INVALIDCALL);
+
+ /* TODO: implement buffer sharing (should work with cross process too)
+ *
+ * Gem names may have fit but they're depreciated and won't work on render-nodes.
+ * One solution is to use shm buffers. We would use a /dev/shm file, fill the first
+ * values to tell it is a nine buffer, the size, which function created it, etc,
+ * and then it would contain the data. The handle would be a number, corresponding to
+ * the file to read (/dev/shm/nine-share-4 for example would be 4).
+ *
+ * Wine just ignores the argument, which works only if the app creates the handle
+ * and won't use it. Instead of failing, we support that situation by putting an
+ * invalid handle, that we would fail to import. Please note that we don't advertise
+ * the flag indicating the support for that feature, but apps seem to not care.
+ */
+ user_assert(!pSharedHandle ||
+ Pool == D3DPOOL_SYSTEMMEM ||
+ Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
+
+ if (pSharedHandle && Pool == D3DPOOL_DEFAULT) {
+ /* Note: Below there is some implementation to support buffer sharing in
+ * this case, but it won't work for cross-process. Thus just ignore
+ * that code. */
+ if (shared_create) {
+ DBG("Creating Texture with invalid handle. Importing will fail\n.");
+ *pSharedHandle = (HANDLE)1; /* Wine would keep it NULL */
+ pSharedHandle = NULL;
+ } else {
+ ERR("Application tries to use cross-process sharing feature. Nine "
+ "doesn't support it");
+ return D3DERR_INVALIDCALL;
+ }
+ }
+
+ if (Usage & D3DUSAGE_AUTOGENMIPMAP)
+ Levels = 0;
+
+ This->base.format = Format;
+ This->base.base.usage = Usage;
+
+ info->screen = screen;
+ info->target = PIPE_TEXTURE_2D;
+ info->format = d3d9_to_pipe_format(Format);
+ info->width0 = Width;
+ info->height0 = Height;
+ info->depth0 = 1;
+ if (Levels)
+ info->last_level = Levels - 1;
+ else
+ info->last_level = util_logbase2(MAX2(Width, Height));
+ info->array_size = 1;
+ info->nr_samples = 0;
+ info->bind = PIPE_BIND_SAMPLER_VIEW;
+ info->usage = PIPE_USAGE_DEFAULT;
+ info->flags = 0;
+
+ if (Usage & D3DUSAGE_RENDERTARGET)
+ info->bind |= PIPE_BIND_RENDER_TARGET;
+ if (Usage & D3DUSAGE_DEPTHSTENCIL)
+ info->bind |= PIPE_BIND_DEPTH_STENCIL;
+
+ if (Usage & D3DUSAGE_DYNAMIC) {
+ info->usage = PIPE_USAGE_DYNAMIC;
+ info->bind |=
+ PIPE_BIND_TRANSFER_READ |
+ PIPE_BIND_TRANSFER_WRITE;
+ }
+ if (pSharedHandle)
+ info->bind |= PIPE_BIND_SHARED;
+
+ if (Pool == D3DPOOL_SYSTEMMEM)
+ info->usage = PIPE_USAGE_STAGING;
+
+ if (pSharedHandle && !shared_create) {
+ if (Pool == D3DPOOL_SYSTEMMEM) {
+ /* Hack for surface creation. */
+ This->base.base.resource = (struct pipe_resource *)*pSharedHandle;
+ } else {
+ struct pipe_resource *res;
+ res = screen->resource_from_handle(screen, info,
+ (struct winsys_handle *)pSharedHandle);
+ if (!res)
+ return D3DERR_NOTFOUND;
+ This->base.base.resource = res;
+ }
+ }
+
+ This->surfaces = CALLOC(info->last_level + 1, sizeof(*This->surfaces));
+ if (!This->surfaces)
+ return E_OUTOFMEMORY;
+
+ hr = NineBaseTexture9_ctor(&This->base, pParams, D3DRTYPE_TEXTURE, Pool);
+ if (FAILED(hr))
+ return hr;
+ This->base.pstype = (Height == 1) ? 1 : 0;
+
+ /* Create all the surfaces right away.
+ * They manage backing storage, and transfers (LockRect) are deferred
+ * to them.
+ */
+ sfdesc.Format = Format;
+ sfdesc.Type = D3DRTYPE_SURFACE;
+ sfdesc.Usage = Usage;
+ sfdesc.Pool = Pool;
+ sfdesc.MultiSampleType = D3DMULTISAMPLE_NONE;
+ sfdesc.MultiSampleQuality = 0;
+ for (l = 0; l <= info->last_level; ++l) {
+ sfdesc.Width = u_minify(Width, l);
+ sfdesc.Height = u_minify(Height, l);
+
+ hr = NineSurface9_new(This->base.base.base.device, NineUnknown(This),
+ This->base.base.resource, D3DRTYPE_TEXTURE, l, 0,
+ &sfdesc, &This->surfaces[l]);
+ if (FAILED(hr))
+ return hr;
+ }
+
+ This->dirty_rect.depth = 1; /* widht == 0 means empty, depth stays 1 */
+
+ if (pSharedHandle) {
+ if (Pool == D3DPOOL_SYSTEMMEM) {
+ This->base.base.resource = NULL;
+ if (shared_create)
+ *pSharedHandle = This->surfaces[0]->base.data;
+ } else
+ if (shared_create) {
+ boolean ok;
+ ok = screen->resource_get_handle(screen, This->base.base.resource,
+ (struct winsys_handle *)pSharedHandle);
+ if (!ok)
+ return D3DERR_DRIVERINTERNALERROR;
+ }
+ }
+
+ return D3D_OK;
+}
+
+static void
+NineTexture9_dtor( struct NineTexture9 *This )
+{
+ unsigned l;
+
+ if (This->surfaces) {
+ /* The surfaces should have 0 references and be unbound now. */
+ for (l = 0; l <= This->base.base.info.last_level; ++l)
+ NineUnknown_Destroy(&This->surfaces[l]->base.base);
+ FREE(This->surfaces);
+ }
+
+ NineBaseTexture9_dtor(&This->base);
+}
+
+HRESULT WINAPI
+NineTexture9_GetLevelDesc( struct NineTexture9 *This,
+ UINT Level,
+ D3DSURFACE_DESC *pDesc )
+{
+ user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL);
+ user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP),
+ D3DERR_INVALIDCALL);
+
+ *pDesc = This->surfaces[Level]->desc;
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineTexture9_GetSurfaceLevel( struct NineTexture9 *This,
+ UINT Level,
+ IDirect3DSurface9 **ppSurfaceLevel )
+{
+ user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL);
+ user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP),
+ D3DERR_INVALIDCALL);
+
+ NineUnknown_AddRef(NineUnknown(This->surfaces[Level]));
+ *ppSurfaceLevel = (IDirect3DSurface9 *)This->surfaces[Level];
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineTexture9_LockRect( struct NineTexture9 *This,
+ UINT Level,
+ D3DLOCKED_RECT *pLockedRect,
+ const RECT *pRect,
+ DWORD Flags )
+{
+ user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL);
+ user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP),
+ D3DERR_INVALIDCALL);
+
+ return NineSurface9_LockRect(This->surfaces[Level], pLockedRect,
+ pRect, Flags);
+}
+
+HRESULT WINAPI
+NineTexture9_UnlockRect( struct NineTexture9 *This,
+ UINT Level )
+{
+ user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL);
+
+ return NineSurface9_UnlockRect(This->surfaces[Level]);
+}
+
+HRESULT WINAPI
+NineTexture9_AddDirtyRect( struct NineTexture9 *This,
+ const RECT *pDirtyRect )
+{
+ DBG("This=%p pDirtyRect=%p[(%u,%u)-(%u,%u)]\n", This, pDirtyRect,
+ pDirtyRect ? pDirtyRect->left : 0, pDirtyRect ? pDirtyRect->top : 0,
+ pDirtyRect ? pDirtyRect->right : 0, pDirtyRect ? pDirtyRect->bottom : 0);
+
+ /* Tracking dirty regions on DEFAULT or SYSTEMMEM resources is pointless,
+ * because we always write to the final storage. Just marked it dirty in
+ * case we need to generate mip maps.
+ */
+ if (This->base.base.pool != D3DPOOL_MANAGED) {
+ if (This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP)
+ This->base.dirty_mip = TRUE;
+ return D3D_OK;
+ }
+ This->base.dirty = TRUE;
+
+ BASETEX_REGISTER_UPDATE(&This->base);
+
+ if (!pDirtyRect) {
+ u_box_origin_2d(This->base.base.info.width0,
+ This->base.base.info.height0, &This->dirty_rect);
+ } else {
+ struct pipe_box box;
+ rect_to_pipe_box_clamp(&box, pDirtyRect);
+ u_box_union_2d(&This->dirty_rect, &This->dirty_rect, &box);
+ }
+ return D3D_OK;
+}
+
+IDirect3DTexture9Vtbl NineTexture9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */
+ (void *)NineResource9_SetPrivateData,
+ (void *)NineResource9_GetPrivateData,
+ (void *)NineResource9_FreePrivateData,
+ (void *)NineResource9_SetPriority,
+ (void *)NineResource9_GetPriority,
+ (void *)NineBaseTexture9_PreLoad,
+ (void *)NineResource9_GetType,
+ (void *)NineBaseTexture9_SetLOD,
+ (void *)NineBaseTexture9_GetLOD,
+ (void *)NineBaseTexture9_GetLevelCount,
+ (void *)NineBaseTexture9_SetAutoGenFilterType,
+ (void *)NineBaseTexture9_GetAutoGenFilterType,
+ (void *)NineBaseTexture9_GenerateMipSubLevels,
+ (void *)NineTexture9_GetLevelDesc,
+ (void *)NineTexture9_GetSurfaceLevel,
+ (void *)NineTexture9_LockRect,
+ (void *)NineTexture9_UnlockRect,
+ (void *)NineTexture9_AddDirtyRect
+};
+
+static const GUID *NineTexture9_IIDs[] = {
+ &IID_IDirect3DTexture9,
+ &IID_IDirect3DBaseTexture9,
+ &IID_IDirect3DResource9,
+ &IID_IUnknown,
+ NULL
+};
+
+HRESULT
+NineTexture9_new( struct NineDevice9 *pDevice,
+ UINT Width, UINT Height, UINT Levels,
+ DWORD Usage,
+ D3DFORMAT Format,
+ D3DPOOL Pool,
+ struct NineTexture9 **ppOut,
+ HANDLE *pSharedHandle )
+{
+ NINE_DEVICE_CHILD_NEW(Texture9, ppOut, pDevice,
+ Width, Height, Levels,
+ Usage, Format, Pool, pSharedHandle);
+}
diff --git a/src/gallium/state_trackers/nine/texture9.h b/src/gallium/state_trackers/nine/texture9.h
new file mode 100644
index 00000000000..5e37a12cf4e
--- /dev/null
+++ b/src/gallium/state_trackers/nine/texture9.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _NINE_TEXTURE9_H_
+#define _NINE_TEXTURE9_H_
+
+#include "basetexture9.h"
+#include "surface9.h"
+
+struct NineTexture9
+{
+ struct NineBaseTexture9 base;
+ struct NineSurface9 **surfaces;
+ struct pipe_box dirty_rect; /* covers all mip levels */
+};
+static INLINE struct NineTexture9 *
+NineTexture9( void *data )
+{
+ return (struct NineTexture9 *)data;
+}
+
+HRESULT
+NineTexture9_new( struct NineDevice9 *pDevice,
+ UINT Width, UINT Height, UINT Levels,
+ DWORD Usage,
+ D3DFORMAT Format,
+ D3DPOOL Pool,
+ struct NineTexture9 **ppOut,
+ HANDLE *pSharedHandle );
+
+HRESULT WINAPI
+NineTexture9_GetLevelDesc( struct NineTexture9 *This,
+ UINT Level,
+ D3DSURFACE_DESC *pDesc );
+
+HRESULT WINAPI
+NineTexture9_GetSurfaceLevel( struct NineTexture9 *This,
+ UINT Level,
+ IDirect3DSurface9 **ppSurfaceLevel );
+
+HRESULT WINAPI
+NineTexture9_LockRect( struct NineTexture9 *This,
+ UINT Level,
+ D3DLOCKED_RECT *pLockedRect,
+ const RECT *pRect,
+ DWORD Flags );
+
+HRESULT WINAPI
+NineTexture9_UnlockRect( struct NineTexture9 *This,
+ UINT Level );
+
+HRESULT WINAPI
+NineTexture9_AddDirtyRect( struct NineTexture9 *This,
+ const RECT *pDirtyRect );
+
+#endif /* _NINE_TEXTURE9_H_ */
diff --git a/src/gallium/state_trackers/nine/vertexbuffer9.c b/src/gallium/state_trackers/nine/vertexbuffer9.c
new file mode 100644
index 00000000000..6a57349e0dd
--- /dev/null
+++ b/src/gallium/state_trackers/nine/vertexbuffer9.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "vertexbuffer9.h"
+#include "device9.h"
+#include "nine_helpers.h"
+#include "nine_pipe.h"
+
+#include "pipe/p_screen.h"
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_format.h"
+#include "util/u_box.h"
+
+#define DBG_CHANNEL DBG_VERTEXBUFFER
+
+HRESULT
+NineVertexBuffer9_ctor( struct NineVertexBuffer9 *This,
+ struct NineUnknownParams *pParams,
+ D3DVERTEXBUFFER_DESC *pDesc )
+{
+ struct pipe_resource *info = &This->base.info;
+ HRESULT hr;
+
+ DBG("This=%p Size=0x%x Usage=%x Pool=%u\n", This,
+ pDesc->Size, pDesc->Usage, pDesc->Pool);
+
+ user_assert(pDesc->Pool != D3DPOOL_SCRATCH, D3DERR_INVALIDCALL);
+
+ This->maps = MALLOC(sizeof(struct pipe_transfer *));
+ if (!This->maps)
+ return E_OUTOFMEMORY;
+ This->nmaps = 0;
+ This->maxmaps = 1;
+
+ This->pipe = pParams->device->pipe;
+
+ info->screen = pParams->device->screen;
+ info->target = PIPE_BUFFER;
+ info->format = PIPE_FORMAT_R8_UNORM;
+ info->width0 = pDesc->Size;
+ info->flags = 0;
+
+ info->bind = PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_TRANSFER_WRITE;
+ if (!(pDesc->Usage & D3DUSAGE_WRITEONLY))
+ info->bind |= PIPE_BIND_TRANSFER_READ;
+
+ info->usage = PIPE_USAGE_DEFAULT;
+ if (pDesc->Usage & D3DUSAGE_DYNAMIC)
+ info->usage = PIPE_USAGE_STREAM;
+ if (pDesc->Pool == D3DPOOL_SYSTEMMEM)
+ info->usage = PIPE_USAGE_STAGING;
+
+ /* if (pDesc->Usage & D3DUSAGE_DONOTCLIP) { } */
+ /* if (pDesc->Usage & D3DUSAGE_NONSECURE) { } */
+ /* if (pDesc->Usage & D3DUSAGE_NPATCHES) { } */
+ /* if (pDesc->Usage & D3DUSAGE_POINTS) { } */
+ /* if (pDesc->Usage & D3DUSAGE_RTPATCHES) { } */
+ /* if (pDesc->Usage & D3DUSAGE_SOFTWAREPROCESSING) { } */
+ /* if (pDesc->Usage & D3DUSAGE_TEXTAPI) { } */
+
+ info->height0 = 1;
+ info->depth0 = 1;
+ info->array_size = 1;
+ info->last_level = 0;
+ info->nr_samples = 0;
+
+ hr = NineResource9_ctor(&This->base, pParams, TRUE, D3DRTYPE_VERTEXBUFFER,
+ pDesc->Pool);
+ if (FAILED(hr))
+ return hr;
+
+ pDesc->Type = D3DRTYPE_VERTEXBUFFER;
+ pDesc->Format = D3DFMT_VERTEXDATA;
+ This->desc = *pDesc;
+
+ return D3D_OK;
+}
+
+void
+NineVertexBuffer9_dtor( struct NineVertexBuffer9 *This )
+{
+ if (This->maps) {
+ while (This->nmaps) {
+ NineVertexBuffer9_Unlock(This);
+ }
+ FREE(This->maps);
+ }
+
+ NineResource9_dtor(&This->base);
+}
+
+HRESULT WINAPI
+NineVertexBuffer9_Lock( struct NineVertexBuffer9 *This,
+ UINT OffsetToLock,
+ UINT SizeToLock,
+ void **ppbData,
+ DWORD Flags )
+{
+ struct pipe_box box;
+ void *data;
+ const unsigned usage = d3dlock_buffer_to_pipe_transfer_usage(Flags);
+
+ DBG("This=%p(pipe=%p) OffsetToLock=0x%x, SizeToLock=0x%x, Flags=0x%x\n",
+ This, This->base.resource,
+ OffsetToLock, SizeToLock, Flags);
+
+ user_assert(ppbData, E_POINTER);
+ user_assert(!(Flags & ~(D3DLOCK_DISCARD |
+ D3DLOCK_DONOTWAIT |
+ D3DLOCK_NO_DIRTY_UPDATE |
+ D3DLOCK_NOSYSLOCK |
+ D3DLOCK_READONLY |
+ D3DLOCK_NOOVERWRITE)), D3DERR_INVALIDCALL);
+
+ if (This->nmaps == This->maxmaps) {
+ struct pipe_transfer **newmaps =
+ REALLOC(This->maps, sizeof(struct pipe_transfer *)*This->maxmaps,
+ sizeof(struct pipe_transfer *)*(This->maxmaps << 1));
+ if (newmaps == NULL)
+ return E_OUTOFMEMORY;
+
+ This->maxmaps <<= 1;
+ This->maps = newmaps;
+ }
+
+ if (SizeToLock == 0) {
+ SizeToLock = This->desc.Size - OffsetToLock;
+ user_warn(OffsetToLock != 0);
+ }
+
+ u_box_1d(OffsetToLock, SizeToLock, &box);
+
+ data = This->pipe->transfer_map(This->pipe, This->base.resource, 0,
+ usage, &box, &This->maps[This->nmaps]);
+ if (!data) {
+ DBG("pipe::transfer_map failed\n"
+ " usage = %x\n"
+ " box.x = %u\n"
+ " box.width = %u\n",
+ usage, box.x, box.width);
+ /* not sure what to return, msdn suggests this */
+ if (Flags & D3DLOCK_DONOTWAIT)
+ return D3DERR_WASSTILLDRAWING;
+ return D3DERR_INVALIDCALL;
+ }
+
+ This->nmaps++;
+ *ppbData = data;
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineVertexBuffer9_Unlock( struct NineVertexBuffer9 *This )
+{
+ DBG("This=%p\n", This);
+
+ user_assert(This->nmaps > 0, D3DERR_INVALIDCALL);
+ This->pipe->transfer_unmap(This->pipe, This->maps[--(This->nmaps)]);
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineVertexBuffer9_GetDesc( struct NineVertexBuffer9 *This,
+ D3DVERTEXBUFFER_DESC *pDesc )
+{
+ user_assert(pDesc, E_POINTER);
+ *pDesc = This->desc;
+ return D3D_OK;
+}
+
+IDirect3DVertexBuffer9Vtbl NineVertexBuffer9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */
+ (void *)NineResource9_SetPrivateData,
+ (void *)NineResource9_GetPrivateData,
+ (void *)NineResource9_FreePrivateData,
+ (void *)NineResource9_SetPriority,
+ (void *)NineResource9_GetPriority,
+ (void *)NineResource9_PreLoad,
+ (void *)NineResource9_GetType,
+ (void *)NineVertexBuffer9_Lock,
+ (void *)NineVertexBuffer9_Unlock,
+ (void *)NineVertexBuffer9_GetDesc
+};
+
+static const GUID *NineVertexBuffer9_IIDs[] = {
+ &IID_IDirect3DVertexBuffer9,
+ &IID_IDirect3DResource9,
+ &IID_IUnknown,
+ NULL
+};
+
+HRESULT
+NineVertexBuffer9_new( struct NineDevice9 *pDevice,
+ D3DVERTEXBUFFER_DESC *pDesc,
+ struct NineVertexBuffer9 **ppOut )
+{
+ NINE_DEVICE_CHILD_NEW(VertexBuffer9, ppOut, /* args */ pDevice, pDesc);
+}
diff --git a/src/gallium/state_trackers/nine/vertexbuffer9.h b/src/gallium/state_trackers/nine/vertexbuffer9.h
new file mode 100644
index 00000000000..0d88b839cad
--- /dev/null
+++ b/src/gallium/state_trackers/nine/vertexbuffer9.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _NINE_VERTEXBUFFER9_H_
+#define _NINE_VERTEXBUFFER9_H_
+
+#include "resource9.h"
+
+struct pipe_screen;
+struct pipe_context;
+struct pipe_transfer;
+
+struct NineVertexBuffer9
+{
+ struct NineResource9 base;
+
+ /* G3D */
+ struct pipe_context *pipe;
+ struct pipe_transfer **maps;
+ int nmaps, maxmaps;
+
+ D3DVERTEXBUFFER_DESC desc;
+};
+static INLINE struct NineVertexBuffer9 *
+NineVertexBuffer9( void *data )
+{
+ return (struct NineVertexBuffer9 *)data;
+}
+
+HRESULT
+NineVertexBuffer9_new( struct NineDevice9 *pDevice,
+ D3DVERTEXBUFFER_DESC *pDesc,
+ struct NineVertexBuffer9 **ppOut );
+
+HRESULT
+NineVertexBuffer9_ctor( struct NineVertexBuffer9 *This,
+ struct NineUnknownParams *pParams,
+ D3DVERTEXBUFFER_DESC *pDesc );
+
+void
+NineVertexBuffer9_dtor( struct NineVertexBuffer9 *This );
+
+HRESULT WINAPI
+NineVertexBuffer9_Lock( struct NineVertexBuffer9 *This,
+ UINT OffsetToLock,
+ UINT SizeToLock,
+ void **ppbData,
+ DWORD Flags );
+
+HRESULT WINAPI
+NineVertexBuffer9_Unlock( struct NineVertexBuffer9 *This );
+
+HRESULT WINAPI
+NineVertexBuffer9_GetDesc( struct NineVertexBuffer9 *This,
+ D3DVERTEXBUFFER_DESC *pDesc );
+
+#endif /* _NINE_VERTEXBUFFER9_H_ */
diff --git a/src/gallium/state_trackers/nine/vertexdeclaration9.c b/src/gallium/state_trackers/nine/vertexdeclaration9.c
new file mode 100644
index 00000000000..1a33e9348c0
--- /dev/null
+++ b/src/gallium/state_trackers/nine/vertexdeclaration9.c
@@ -0,0 +1,518 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "vertexdeclaration9.h"
+#include "vertexbuffer9.h"
+#include "device9.h"
+#include "nine_helpers.h"
+
+#include "pipe/p_format.h"
+#include "pipe/p_context.h"
+#include "util/u_math.h"
+#include "util/u_format.h"
+#include "util/u_box.h"
+#include "translate/translate.h"
+
+#define DBG_CHANNEL DBG_VERTEXDECLARATION
+
+static INLINE enum pipe_format decltype_format(BYTE type)
+{
+ switch (type) {
+ case D3DDECLTYPE_FLOAT1: return PIPE_FORMAT_R32_FLOAT;
+ case D3DDECLTYPE_FLOAT2: return PIPE_FORMAT_R32G32_FLOAT;
+ case D3DDECLTYPE_FLOAT3: return PIPE_FORMAT_R32G32B32_FLOAT;
+ case D3DDECLTYPE_FLOAT4: return PIPE_FORMAT_R32G32B32A32_FLOAT;
+ case D3DDECLTYPE_D3DCOLOR: return PIPE_FORMAT_B8G8R8A8_UNORM;
+ case D3DDECLTYPE_UBYTE4: return PIPE_FORMAT_R8G8B8A8_USCALED;
+ case D3DDECLTYPE_SHORT2: return PIPE_FORMAT_R16G16_SSCALED;
+ case D3DDECLTYPE_SHORT4: return PIPE_FORMAT_R16G16B16A16_SSCALED;
+ case D3DDECLTYPE_UBYTE4N: return PIPE_FORMAT_R8G8B8A8_UNORM;
+ case D3DDECLTYPE_SHORT2N: return PIPE_FORMAT_R16G16_SNORM;
+ case D3DDECLTYPE_SHORT4N: return PIPE_FORMAT_R16G16B16A16_SNORM;
+ case D3DDECLTYPE_USHORT2N: return PIPE_FORMAT_R16G16_UNORM;
+ case D3DDECLTYPE_USHORT4N: return PIPE_FORMAT_R16G16B16A16_UNORM;
+ case D3DDECLTYPE_UDEC3: return PIPE_FORMAT_R10G10B10X2_USCALED;
+ case D3DDECLTYPE_DEC3N: return PIPE_FORMAT_R10G10B10X2_SNORM;
+ case D3DDECLTYPE_FLOAT16_2: return PIPE_FORMAT_R16G16_FLOAT;
+ case D3DDECLTYPE_FLOAT16_4: return PIPE_FORMAT_R16G16B16A16_FLOAT;
+ default:
+ assert(!"Implementation error !");
+ }
+ return PIPE_FORMAT_NONE;
+}
+
+static INLINE unsigned decltype_size(BYTE type)
+{
+ switch (type) {
+ case D3DDECLTYPE_FLOAT1: return 1 * sizeof(float);
+ case D3DDECLTYPE_FLOAT2: return 2 * sizeof(float);
+ case D3DDECLTYPE_FLOAT3: return 3 * sizeof(float);
+ case D3DDECLTYPE_FLOAT4: return 4 * sizeof(float);
+ case D3DDECLTYPE_D3DCOLOR: return 1 * sizeof(DWORD);
+ case D3DDECLTYPE_UBYTE4: return 4 * sizeof(BYTE);
+ case D3DDECLTYPE_SHORT2: return 2 * sizeof(short);
+ case D3DDECLTYPE_SHORT4: return 4 * sizeof(short);
+ case D3DDECLTYPE_UBYTE4N: return 4 * sizeof(BYTE);
+ case D3DDECLTYPE_SHORT2N: return 2 * sizeof(short);
+ case D3DDECLTYPE_SHORT4N: return 4 * sizeof(short);
+ case D3DDECLTYPE_USHORT2N: return 2 * sizeof(short);
+ case D3DDECLTYPE_USHORT4N: return 4 * sizeof(short);
+ case D3DDECLTYPE_UDEC3: return 4;
+ case D3DDECLTYPE_DEC3N: return 4;
+ case D3DDECLTYPE_FLOAT16_2: return 2 * 2;
+ case D3DDECLTYPE_FLOAT16_4: return 4 * 2;
+ default:
+ assert(!"Implementation error !");
+ }
+ return 0;
+}
+
+/* Actually, arbitrary usage index values are permitted, but a
+ * simple lookup table won't work in that case. Let's just wait
+ * with making this more generic until we need it.
+ */
+static INLINE boolean
+nine_d3ddeclusage_check(unsigned usage, unsigned usage_idx)
+{
+ switch (usage) {
+ case D3DDECLUSAGE_POSITIONT:
+ case D3DDECLUSAGE_PSIZE:
+ case D3DDECLUSAGE_TESSFACTOR:
+ case D3DDECLUSAGE_DEPTH:
+ case D3DDECLUSAGE_FOG:
+ case D3DDECLUSAGE_SAMPLE:
+ return usage_idx <= 0;
+ case D3DDECLUSAGE_NORMAL:
+ case D3DDECLUSAGE_TANGENT:
+ case D3DDECLUSAGE_BINORMAL:
+ return usage_idx <= 1;
+ case D3DDECLUSAGE_POSITION:
+ case D3DDECLUSAGE_BLENDWEIGHT:
+ case D3DDECLUSAGE_BLENDINDICES:
+ case D3DDECLUSAGE_COLOR:
+ return usage_idx <= 4;
+ case D3DDECLUSAGE_TEXCOORD:
+ return usage_idx <= 15;
+ default:
+ return FALSE;
+ }
+}
+
+#define NINE_DECLUSAGE_CASE0(n) case D3DDECLUSAGE_##n: return NINE_DECLUSAGE_##n
+#define NINE_DECLUSAGE_CASEi(n) case D3DDECLUSAGE_##n: return NINE_DECLUSAGE_##n(usage_idx)
+INLINE unsigned
+nine_d3d9_to_nine_declusage(unsigned usage, unsigned usage_idx)
+{
+ if (!nine_d3ddeclusage_check(usage, usage_idx))
+ ERR("D3DDECLUSAGE_%u[%u]\n",usage,usage_idx);
+ assert(nine_d3ddeclusage_check(usage, usage_idx));
+ switch (usage) {
+ NINE_DECLUSAGE_CASEi(POSITION);
+ NINE_DECLUSAGE_CASEi(BLENDWEIGHT);
+ NINE_DECLUSAGE_CASEi(BLENDINDICES);
+ NINE_DECLUSAGE_CASEi(NORMAL);
+ NINE_DECLUSAGE_CASE0(PSIZE);
+ NINE_DECLUSAGE_CASEi(TEXCOORD);
+ NINE_DECLUSAGE_CASEi(TANGENT);
+ NINE_DECLUSAGE_CASEi(BINORMAL);
+ NINE_DECLUSAGE_CASE0(TESSFACTOR);
+ NINE_DECLUSAGE_CASE0(POSITIONT);
+ NINE_DECLUSAGE_CASEi(COLOR);
+ NINE_DECLUSAGE_CASE0(DEPTH);
+ NINE_DECLUSAGE_CASE0(FOG);
+ NINE_DECLUSAGE_CASE0(SAMPLE);
+ default:
+ assert(!"Invalid DECLUSAGE.");
+ return NINE_DECLUSAGE_NONE;
+ }
+}
+
+static const char *nine_declusage_names[] =
+{
+ [NINE_DECLUSAGE_POSITION(0)] = "POSITION",
+ [NINE_DECLUSAGE_POSITION(1)] = "POSITION1",
+ [NINE_DECLUSAGE_POSITION(2)] = "POSITION2",
+ [NINE_DECLUSAGE_POSITION(3)] = "POSITION3",
+ [NINE_DECLUSAGE_POSITION(4)] = "POSITION4",
+ [NINE_DECLUSAGE_BLENDWEIGHT(0)] = "BLENDWEIGHT",
+ [NINE_DECLUSAGE_BLENDWEIGHT(1)] = "BLENDWEIGHT1",
+ [NINE_DECLUSAGE_BLENDWEIGHT(2)] = "BLENDWEIGHT2",
+ [NINE_DECLUSAGE_BLENDWEIGHT(3)] = "BLENDWEIGHT3",
+ [NINE_DECLUSAGE_BLENDINDICES(0)] = "BLENDINDICES",
+ [NINE_DECLUSAGE_BLENDINDICES(1)] = "BLENDINDICES1",
+ [NINE_DECLUSAGE_BLENDINDICES(2)] = "BLENDINDICES2",
+ [NINE_DECLUSAGE_BLENDINDICES(3)] = "BLENDINDICES3",
+ [NINE_DECLUSAGE_NORMAL(0)] = "NORMAL",
+ [NINE_DECLUSAGE_NORMAL(1)] = "NORMAL1",
+ [NINE_DECLUSAGE_PSIZE] = "PSIZE",
+ [NINE_DECLUSAGE_TEXCOORD(0)] = "TEXCOORD0",
+ [NINE_DECLUSAGE_TEXCOORD(1)] = "TEXCOORD1",
+ [NINE_DECLUSAGE_TEXCOORD(2)] = "TEXCOORD2",
+ [NINE_DECLUSAGE_TEXCOORD(3)] = "TEXCOORD3",
+ [NINE_DECLUSAGE_TEXCOORD(4)] = "TEXCOORD4",
+ [NINE_DECLUSAGE_TEXCOORD(5)] = "TEXCOORD5",
+ [NINE_DECLUSAGE_TEXCOORD(6)] = "TEXCOORD6",
+ [NINE_DECLUSAGE_TEXCOORD(7)] = "TEXCOORD7",
+ [NINE_DECLUSAGE_TEXCOORD(8)] = "TEXCOORD8",
+ [NINE_DECLUSAGE_TEXCOORD(9)] = "TEXCOORD9",
+ [NINE_DECLUSAGE_TEXCOORD(10)] = "TEXCOORD10",
+ [NINE_DECLUSAGE_TEXCOORD(11)] = "TEXCOORD11",
+ [NINE_DECLUSAGE_TEXCOORD(12)] = "TEXCOORD12",
+ [NINE_DECLUSAGE_TEXCOORD(13)] = "TEXCOORD13",
+ [NINE_DECLUSAGE_TEXCOORD(14)] = "TEXCOORD14",
+ [NINE_DECLUSAGE_TEXCOORD(15)] = "TEXCOORD15",
+ [NINE_DECLUSAGE_TANGENT(0)] = "TANGENT",
+ [NINE_DECLUSAGE_TANGENT(1)] = "TANGENT1",
+ [NINE_DECLUSAGE_BINORMAL(0)] = "BINORMAL",
+ [NINE_DECLUSAGE_BINORMAL(1)] = "BINORMAL1",
+ [NINE_DECLUSAGE_TESSFACTOR] = "TESSFACTOR",
+ [NINE_DECLUSAGE_POSITIONT] = "POSITIONT",
+ [NINE_DECLUSAGE_COLOR(0)] = "DIFFUSE",
+ [NINE_DECLUSAGE_COLOR(1)] = "SPECULAR",
+ [NINE_DECLUSAGE_COLOR(2)] = "COLOR2",
+ [NINE_DECLUSAGE_COLOR(3)] = "COLOR3",
+ [NINE_DECLUSAGE_COLOR(4)] = "COLOR4",
+ [NINE_DECLUSAGE_DEPTH] = "DEPTH",
+ [NINE_DECLUSAGE_FOG] = "FOG",
+ [NINE_DECLUSAGE_NONE] = "(NONE)",
+ [NINE_DECLUSAGE_COUNT] = "(OOB)"
+};
+static INLINE const char *
+nine_declusage_name(unsigned ndcl)
+{
+ return nine_declusage_names[MIN2(ndcl, Elements(nine_declusage_names) - 1)];
+}
+
+HRESULT
+NineVertexDeclaration9_ctor( struct NineVertexDeclaration9 *This,
+ struct NineUnknownParams *pParams,
+ const D3DVERTEXELEMENT9 *pElements )
+{
+ const D3DCAPS9 *caps;
+ unsigned i;
+
+ HRESULT hr = NineUnknown_ctor(&This->base, pParams);
+ if (FAILED(hr)) { return hr; }
+
+ for (This->nelems = 0;
+ pElements[This->nelems].Type != D3DDECLTYPE_UNUSED &&
+ pElements[This->nelems].Stream != 0xFF; /* wine */
+ ++This->nelems);
+
+ caps = NineDevice9_GetCaps(This->base.device);
+ user_assert(This->nelems <= caps->MaxStreams, D3DERR_INVALIDCALL);
+
+ This->decls = CALLOC(This->nelems+1, sizeof(D3DVERTEXELEMENT9));
+ This->elems = CALLOC(This->nelems, sizeof(struct pipe_vertex_element));
+ if (!This->decls || !This->elems) { return E_OUTOFMEMORY; }
+ memcpy(This->decls, pElements, sizeof(D3DVERTEXELEMENT9)*(This->nelems+1));
+
+ memset(This->usage_map, 0xff, sizeof(This->usage_map));
+
+ for (i = 0; i < This->nelems; ++i) {
+ uint8_t usage = nine_d3d9_to_nine_declusage(This->decls[i].Usage,
+ This->decls[i].UsageIndex);
+ This->usage_map[usage] = i;
+
+ This->elems[i].src_offset = This->decls[i].Offset;
+ This->elems[i].instance_divisor = 0;
+ This->elems[i].vertex_buffer_index = This->decls[i].Stream;
+ This->elems[i].src_format = decltype_format(This->decls[i].Type);
+ /* XXX Remember Method (tesselation), Usage, UsageIndex */
+
+ DBG("VERTEXELEMENT[%u]: Stream=%u Offset=%u Type=%s DeclUsage=%s\n", i,
+ This->decls[i].Stream,
+ This->decls[i].Offset,
+ util_format_name(This->elems[i].src_format),
+ nine_declusage_name(usage));
+ }
+
+ return D3D_OK;
+}
+
+void
+NineVertexDeclaration9_dtor( struct NineVertexDeclaration9 *This )
+{
+ if (This->decls)
+ FREE(This->decls);
+ if (This->elems)
+ FREE(This->elems);
+
+ NineUnknown_dtor(&This->base);
+}
+
+HRESULT WINAPI
+NineVertexDeclaration9_GetDeclaration( struct NineVertexDeclaration9 *This,
+ D3DVERTEXELEMENT9 *pElement,
+ UINT *pNumElements )
+{
+ if (!pElement) {
+ user_assert(pNumElements, D3DERR_INVALIDCALL);
+ *pNumElements = This->nelems+1;
+ return D3D_OK;
+ }
+ if (pNumElements) { *pNumElements = This->nelems+1; }
+ memcpy(pElement, This->decls, sizeof(D3DVERTEXELEMENT9)*(This->nelems+1));
+ return D3D_OK;
+}
+
+IDirect3DVertexDeclaration9Vtbl NineVertexDeclaration9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)NineUnknown_GetDevice, /* actually part of VertexDecl9 iface */
+ (void *)NineVertexDeclaration9_GetDeclaration
+};
+
+static const GUID *NineVertexDeclaration9_IIDs[] = {
+ &IID_IDirect3DVertexDeclaration9,
+ &IID_IUnknown,
+ NULL
+};
+
+HRESULT
+NineVertexDeclaration9_new( struct NineDevice9 *pDevice,
+ const D3DVERTEXELEMENT9 *pElements,
+ struct NineVertexDeclaration9 **ppOut )
+{
+ NINE_DEVICE_CHILD_NEW(VertexDeclaration9, ppOut, /* args */ pDevice, pElements);
+}
+
+HRESULT
+NineVertexDeclaration9_new_from_fvf( struct NineDevice9 *pDevice,
+ DWORD FVF,
+ struct NineVertexDeclaration9 **ppOut )
+{
+ D3DVERTEXELEMENT9 elems[16], decl_end = D3DDECL_END();
+ unsigned texcount, i, betas, nelems = 0;
+ BYTE beta_index = 0xFF;
+
+ switch (FVF & D3DFVF_POSITION_MASK) {
+ case D3DFVF_XYZ: /* simple XYZ */
+ case D3DFVF_XYZB1:
+ case D3DFVF_XYZB2:
+ case D3DFVF_XYZB3:
+ case D3DFVF_XYZB4:
+ case D3DFVF_XYZB5: /* XYZ with beta values */
+ elems[nelems].Type = D3DDECLTYPE_FLOAT3;
+ elems[nelems].Usage = D3DDECLUSAGE_POSITION;
+ elems[nelems].UsageIndex = 0;
+ ++nelems;
+ /* simple XYZ has no beta values. break. */
+ if ((FVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) { break; }
+
+ betas = (((FVF & D3DFVF_XYZB5)-D3DFVF_XYZB1)>>1)+1;
+ if (FVF & D3DFVF_LASTBETA_D3DCOLOR) {
+ beta_index = D3DDECLTYPE_D3DCOLOR;
+ } else if (FVF & D3DFVF_LASTBETA_UBYTE4) {
+ beta_index = D3DDECLTYPE_UBYTE4;
+ } else if ((FVF & D3DFVF_XYZB5) == D3DFVF_XYZB5) {
+ beta_index = D3DDECLTYPE_FLOAT1;
+ }
+ if (beta_index != 0xFF) { --betas; }
+
+ if (betas > 0) {
+ switch (betas) {
+ case 1: elems[nelems].Type = D3DDECLTYPE_FLOAT1; break;
+ case 2: elems[nelems].Type = D3DDECLTYPE_FLOAT2; break;
+ case 3: elems[nelems].Type = D3DDECLTYPE_FLOAT3; break;
+ case 4: elems[nelems].Type = D3DDECLTYPE_FLOAT4; break;
+ default:
+ assert(!"Implementation error!");
+ }
+ elems[nelems].Usage = D3DDECLUSAGE_BLENDWEIGHT;
+ elems[nelems].UsageIndex = 0;
+ ++nelems;
+ }
+
+ if (beta_index != 0xFF) {
+ elems[nelems].Type = beta_index;
+ elems[nelems].Usage = D3DDECLUSAGE_BLENDINDICES;
+ elems[nelems].UsageIndex = 0;
+ ++nelems;
+ }
+ break;
+
+ case D3DFVF_XYZW: /* simple XYZW */
+ case D3DFVF_XYZRHW: /* pretransformed XYZW */
+ elems[nelems].Type = D3DDECLTYPE_FLOAT4;
+ elems[nelems].Usage =
+ ((FVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZW) ?
+ D3DDECLUSAGE_POSITION : D3DDECLUSAGE_POSITIONT;
+ elems[nelems].UsageIndex = 0;
+ ++nelems;
+ break;
+
+ default:
+ (void)user_error(!"Position doesn't match any known combination");
+ }
+
+ /* normals, psize and colors */
+ if (FVF & D3DFVF_NORMAL) {
+ elems[nelems].Type = D3DDECLTYPE_FLOAT3;
+ elems[nelems].Usage = D3DDECLUSAGE_NORMAL;
+ elems[nelems].UsageIndex = 0;
+ ++nelems;
+ }
+ if (FVF & D3DFVF_PSIZE) {
+ elems[nelems].Type = D3DDECLTYPE_FLOAT1;
+ elems[nelems].Usage = D3DDECLUSAGE_PSIZE;
+ elems[nelems].UsageIndex = 0;
+ ++nelems;
+ }
+ if (FVF & D3DFVF_DIFFUSE) {
+ elems[nelems].Type = D3DDECLTYPE_D3DCOLOR;
+ elems[nelems].Usage = D3DDECLUSAGE_COLOR;
+ elems[nelems].UsageIndex = 0;
+ ++nelems;
+ }
+ if (FVF & D3DFVF_SPECULAR) {
+ elems[nelems].Type = D3DDECLTYPE_D3DCOLOR;
+ elems[nelems].Usage = D3DDECLUSAGE_COLOR;
+ elems[nelems].UsageIndex = 1;
+ ++nelems;
+ }
+
+ /* textures */
+ texcount = (FVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
+ if (user_error(texcount <= 8)) { texcount = 8; }
+
+ for (i = 0; i < texcount; ++i) {
+ switch ((FVF >> (16+i*2)) & 0x3) {
+ case D3DFVF_TEXTUREFORMAT1:
+ elems[nelems].Type = D3DDECLTYPE_FLOAT1;
+ break;
+
+ case D3DFVF_TEXTUREFORMAT2:
+ elems[nelems].Type = D3DDECLTYPE_FLOAT2;
+ break;
+
+ case D3DFVF_TEXTUREFORMAT3:
+ elems[nelems].Type = D3DDECLTYPE_FLOAT3;
+ break;
+
+ case D3DFVF_TEXTUREFORMAT4:
+ elems[nelems].Type = D3DDECLTYPE_FLOAT4;
+ break;
+
+ default:
+ assert(!"Implementation error!");
+ }
+ elems[nelems].Usage = D3DDECLUSAGE_TEXCOORD;
+ elems[nelems].UsageIndex = i;
+ ++nelems;
+ }
+
+ /* fill out remaining data */
+ for (i = 0; i < nelems; ++i) {
+ elems[i].Stream = 0;
+ elems[i].Offset = (i == 0) ? 0 : (elems[i-1].Offset +
+ decltype_size(elems[i-1].Type));
+ elems[i].Method = D3DDECLMETHOD_DEFAULT;
+ }
+ elems[nelems++] = decl_end;
+
+ NINE_DEVICE_CHILD_NEW(VertexDeclaration9, ppOut, /* args */ pDevice, elems);
+}
+
+/* ProcessVertices runs stream output into a temporary buffer to capture
+ * all outputs.
+ * Now we have to convert them to the format and order set by the vertex
+ * declaration, for which we use u_translate.
+ * This is necessary if the vertex declaration contains elements using a
+ * non float32 format, because stream output only supports f32/u32/s32.
+ */
+HRESULT
+NineVertexDeclaration9_ConvertStreamOutput(
+ struct NineVertexDeclaration9 *This,
+ struct NineVertexBuffer9 *pDstBuf,
+ UINT DestIndex,
+ UINT VertexCount,
+ struct pipe_resource *pSrcBuf,
+ const struct pipe_stream_output_info *so )
+{
+ struct pipe_context *pipe = This->base.device->pipe;
+ struct pipe_transfer *transfer = NULL;
+ struct translate *translate;
+ struct translate_key transkey;
+ struct pipe_box box;
+ HRESULT hr;
+ unsigned i;
+ void *src_map;
+ void *dst_map;
+
+ transkey.output_stride = 0;
+ for (i = 0; i < This->nelems; ++i) {
+ enum pipe_format format;
+
+ switch (so->output[i].num_components) {
+ case 1: format = PIPE_FORMAT_R32_FLOAT; break;
+ case 2: format = PIPE_FORMAT_R32G32_FLOAT; break;
+ case 3: format = PIPE_FORMAT_R32G32B32_FLOAT; break;
+ default:
+ assert(so->output[i].num_components == 4);
+ format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ break;
+ }
+ transkey.element[i].type = TRANSLATE_ELEMENT_NORMAL;
+ transkey.element[i].input_format = format;
+ transkey.element[i].input_buffer = 0;
+ transkey.element[i].input_offset = so->output[i].dst_offset * 4;
+ transkey.element[i].instance_divisor = 0;
+
+ transkey.element[i].output_format = This->elems[i].src_format;
+ transkey.element[i].output_offset = This->elems[i].src_offset;
+ transkey.output_stride +=
+ util_format_get_blocksize(This->elems[i].src_format);
+
+ assert(!(transkey.output_stride & 3));
+ }
+ transkey.nr_elements = This->nelems;
+
+ translate = translate_create(&transkey);
+ if (!translate)
+ return E_OUTOFMEMORY;
+
+ hr = NineVertexBuffer9_Lock(pDstBuf,
+ transkey.output_stride * DestIndex,
+ transkey.output_stride * VertexCount,
+ &dst_map, D3DLOCK_DISCARD);
+ if (FAILED(hr))
+ goto out;
+
+ src_map = pipe->transfer_map(pipe, pSrcBuf, 0, PIPE_TRANSFER_READ, &box,
+ &transfer);
+ if (!src_map) {
+ hr = D3DERR_DRIVERINTERNALERROR;
+ goto out;
+ }
+ translate->set_buffer(translate, 0, src_map, so->stride[0], ~0);
+
+ translate->run(translate, 0, VertexCount, 0, 0, dst_map);
+
+ NineVertexBuffer9_Unlock(pDstBuf);
+out:
+ if (transfer)
+ pipe->transfer_unmap(pipe, transfer);
+ translate->release(translate); /* TODO: cache these */
+ return hr;
+}
diff --git a/src/gallium/state_trackers/nine/vertexdeclaration9.h b/src/gallium/state_trackers/nine/vertexdeclaration9.h
new file mode 100644
index 00000000000..6590f460f67
--- /dev/null
+++ b/src/gallium/state_trackers/nine/vertexdeclaration9.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _NINE_VERTEXDECLARATION9_H_
+#define _NINE_VERTEXDECLARATION9_H_
+
+#include "nine_defines.h"
+#include "iunknown.h"
+
+struct pipe_resource;
+struct pipe_vertex_element;
+struct pipe_stream_output_info;
+struct NineDevice9;
+struct NineVertexBuffer9;
+
+struct NineVertexDeclaration9
+{
+ struct NineUnknown base;
+
+ /* G3D state */
+ struct pipe_vertex_element *elems;
+ unsigned nelems;
+
+ /* DECLUSAGE -> element index, for selecting the vertex element
+ * for each VS input */
+ uint8_t usage_map[NINE_DECLUSAGE_COUNT];
+
+ D3DVERTEXELEMENT9 *decls;
+ DWORD fvf;
+};
+static INLINE struct NineVertexDeclaration9 *
+NineVertexDeclaration9( void *data )
+{
+ return (struct NineVertexDeclaration9 *)data;
+}
+
+HRESULT
+NineVertexDeclaration9_new( struct NineDevice9 *pDevice,
+ const D3DVERTEXELEMENT9 *pElements,
+ struct NineVertexDeclaration9 **ppOut );
+
+HRESULT
+NineVertexDeclaration9_new_from_fvf( struct NineDevice9 *pDevice,
+ DWORD FVF,
+ struct NineVertexDeclaration9 **ppOut );
+
+HRESULT
+NineVertexDeclaration9_ctor( struct NineVertexDeclaration9 *This,
+ struct NineUnknownParams *pParams,
+ const D3DVERTEXELEMENT9 *pElements );
+
+void
+NineVertexDeclaration9_dtor( struct NineVertexDeclaration9 *This );
+
+HRESULT WINAPI
+NineVertexDeclaration9_GetDeclaration( struct NineVertexDeclaration9 *This,
+ D3DVERTEXELEMENT9 *pElement,
+ UINT *pNumElements );
+
+/* Convert stream output data to the vertex declaration's format. */
+HRESULT
+NineVertexDeclaration9_ConvertStreamOutput(
+ struct NineVertexDeclaration9 *This,
+ struct NineVertexBuffer9 *pDstBuf,
+ UINT DestIndex,
+ UINT VertexCount,
+ struct pipe_resource *pSrcBuf,
+ const struct pipe_stream_output_info *so );
+
+#endif /* _NINE_VERTEXDECLARATION9_H_ */
diff --git a/src/gallium/state_trackers/nine/vertexshader9.c b/src/gallium/state_trackers/nine/vertexshader9.c
new file mode 100644
index 00000000000..e04f3a5da9a
--- /dev/null
+++ b/src/gallium/state_trackers/nine/vertexshader9.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "nine_helpers.h"
+#include "nine_shader.h"
+
+#include "vertexshader9.h"
+
+#include "device9.h"
+#include "pipe/p_context.h"
+
+#define DBG_CHANNEL DBG_VERTEXSHADER
+
+HRESULT
+NineVertexShader9_ctor( struct NineVertexShader9 *This,
+ struct NineUnknownParams *pParams,
+ const DWORD *pFunction, void *cso )
+{
+ struct NineDevice9 *device;
+ struct nine_shader_info info;
+ HRESULT hr;
+ unsigned i;
+
+ hr = NineUnknown_ctor(&This->base, pParams);
+ if (FAILED(hr))
+ return hr;
+
+ if (cso) {
+ This->variant.cso = cso;
+ return D3D_OK;
+ }
+ device = This->base.device;
+
+ info.type = PIPE_SHADER_VERTEX;
+ info.byte_code = pFunction;
+ info.const_i_base = NINE_CONST_I_BASE(device->max_vs_const_f) / 16;
+ info.const_b_base = NINE_CONST_B_BASE(device->max_vs_const_f) / 16;
+ info.sampler_mask_shadow = 0x0;
+ info.sampler_ps1xtypes = 0x0;
+
+ hr = nine_translate_shader(device, &info);
+ if (FAILED(hr))
+ return hr;
+ This->byte_code.version = info.version;
+
+ This->byte_code.tokens = mem_dup(pFunction, info.byte_size);
+ if (!This->byte_code.tokens)
+ return E_OUTOFMEMORY;
+ This->byte_code.size = info.byte_size;
+
+ This->variant.cso = info.cso;
+ This->const_used_size = info.const_used_size;
+ if (info.const_used_size == ~0)
+ This->const_used_size = NINE_CONSTBUF_SIZE(device->max_vs_const_f);
+ This->lconstf = info.lconstf;
+ This->sampler_mask = info.sampler_mask;
+ This->position_t = info.position_t;
+ This->point_size = info.point_size;
+
+ for (i = 0; i < info.num_inputs && i < Elements(This->input_map); ++i)
+ This->input_map[i].ndecl = info.input_map[i];
+ This->num_inputs = i;
+
+ return D3D_OK;
+}
+
+void
+NineVertexShader9_dtor( struct NineVertexShader9 *This )
+{
+ DBG("This=%p cso=%p\n", This, This->variant.cso);
+
+ if (This->base.device) {
+ struct pipe_context *pipe = This->base.device->pipe;
+ struct nine_shader_variant *var = &This->variant;
+ do {
+ if (var->cso) {
+ if (This->base.device->state.cso.vs == var->cso)
+ pipe->bind_vs_state(pipe, NULL);
+ pipe->delete_vs_state(pipe, var->cso);
+ }
+ var = var->next;
+ } while (var);
+ }
+ nine_shader_variants_free(&This->variant);
+
+ if (This->byte_code.tokens)
+ FREE((void *)This->byte_code.tokens); /* const_cast */
+
+ FREE(This->lconstf.data);
+ FREE(This->lconstf.ranges);
+
+ NineUnknown_dtor(&This->base);
+}
+
+HRESULT WINAPI
+NineVertexShader9_GetFunction( struct NineVertexShader9 *This,
+ void *pData,
+ UINT *pSizeOfData )
+{
+ user_assert(pSizeOfData, D3DERR_INVALIDCALL);
+
+ if (!pData) {
+ *pSizeOfData = This->byte_code.size;
+ return D3D_OK;
+ }
+ user_assert(*pSizeOfData >= This->byte_code.size, D3DERR_INVALIDCALL);
+
+ memcpy(pData, This->byte_code.tokens, This->byte_code.size);
+
+ return D3D_OK;
+}
+
+void *
+NineVertexShader9_GetVariant( struct NineVertexShader9 *This,
+ uint32_t key )
+{
+ void *cso = nine_shader_variant_get(&This->variant, key);
+ if (!cso) {
+ struct NineDevice9 *device = This->base.device;
+ struct nine_shader_info info;
+ HRESULT hr;
+
+ info.type = PIPE_SHADER_VERTEX;
+ info.const_i_base = NINE_CONST_I_BASE(device->max_vs_const_f) / 16;
+ info.const_b_base = NINE_CONST_B_BASE(device->max_vs_const_f) / 16;
+ info.byte_code = This->byte_code.tokens;
+ info.sampler_mask_shadow = key & 0xf;
+
+ hr = nine_translate_shader(This->base.device, &info);
+ if (FAILED(hr))
+ return NULL;
+ nine_shader_variant_add(&This->variant, key, info.cso);
+ cso = info.cso;
+ }
+ return cso;
+}
+
+IDirect3DVertexShader9Vtbl NineVertexShader9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)NineUnknown_GetDevice,
+ (void *)NineVertexShader9_GetFunction
+};
+
+static const GUID *NineVertexShader9_IIDs[] = {
+ &IID_IDirect3DVertexShader9,
+ &IID_IUnknown,
+ NULL
+};
+
+HRESULT
+NineVertexShader9_new( struct NineDevice9 *pDevice,
+ struct NineVertexShader9 **ppOut,
+ const DWORD *pFunction, void *cso )
+{
+ NINE_DEVICE_CHILD_NEW(VertexShader9, ppOut, pDevice, pFunction, cso);
+}
diff --git a/src/gallium/state_trackers/nine/vertexshader9.h b/src/gallium/state_trackers/nine/vertexshader9.h
new file mode 100644
index 00000000000..a7d750d3efb
--- /dev/null
+++ b/src/gallium/state_trackers/nine/vertexshader9.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _NINE_VERTEXSHADER9_H_
+#define _NINE_VERTEXSHADER9_H_
+
+#include "iunknown.h"
+#include "nine_shader.h"
+
+struct NineVertexShader9
+{
+ struct NineUnknown base;
+ struct nine_shader_variant variant;
+
+ struct {
+ uint8_t ndecl; /* NINE_DECLUSAGE_x */
+ } input_map[PIPE_MAX_ATTRIBS];
+ unsigned num_inputs;
+
+ struct {
+ const DWORD *tokens;
+ DWORD size;
+ uint8_t version; /* (major << 4) | minor */
+ } byte_code;
+
+ uint8_t sampler_mask;
+ uint8_t sampler_mask_shadow;
+
+ boolean position_t; /* if true, disable vport transform */
+ boolean point_size; /* if true, set rasterizer.point_size_per_vertex to 1 */
+
+ unsigned const_used_size; /* in bytes */
+
+ struct nine_lconstf lconstf;
+
+ const struct pipe_stream_output_info *so;
+
+ uint64_t ff_key[2];
+};
+static INLINE struct NineVertexShader9 *
+NineVertexShader9( void *data )
+{
+ return (struct NineVertexShader9 *)data;
+}
+
+void *
+NineVertexShader9_GetVariant( struct NineVertexShader9 *vs,
+ uint32_t key );
+
+/*** public ***/
+
+HRESULT
+NineVertexShader9_new( struct NineDevice9 *pDevice,
+ struct NineVertexShader9 **ppOut,
+ const DWORD *pFunction, void *cso );
+
+HRESULT
+NineVertexShader9_ctor( struct NineVertexShader9 *,
+ struct NineUnknownParams *pParams,
+ const DWORD *pFunction, void *cso );
+
+void
+NineVertexShader9_dtor( struct NineVertexShader9 * );
+
+HRESULT WINAPI
+NineVertexShader9_GetFunction( struct NineVertexShader9 *This,
+ void *pData,
+ UINT *pSizeOfData );
+
+#endif /* _NINE_VERTEXSHADER9_H_ */
diff --git a/src/gallium/state_trackers/nine/volume9.c b/src/gallium/state_trackers/nine/volume9.c
new file mode 100644
index 00000000000..c46a9d1c2e0
--- /dev/null
+++ b/src/gallium/state_trackers/nine/volume9.c
@@ -0,0 +1,604 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "device9.h"
+#include "volume9.h"
+#include "basetexture9.h" /* for marking dirty */
+#include "nine_helpers.h"
+#include "nine_pipe.h"
+#include "nine_dump.h"
+
+#include "util/u_hash_table.h"
+#include "util/u_format.h"
+#include "util/u_surface.h"
+#include "nine_pdata.h"
+
+#define DBG_CHANNEL DBG_VOLUME
+
+
+static HRESULT
+NineVolume9_AllocateData( struct NineVolume9 *This )
+{
+ unsigned size = This->layer_stride * This->desc.Depth;
+
+ DBG("(%p(This=%p),level=%u) Allocating 0x%x bytes of system memory.\n",
+ This->base.container, This, This->level, size);
+
+ This->data = (uint8_t *)MALLOC(size);
+ if (!This->data)
+ return E_OUTOFMEMORY;
+ return D3D_OK;
+}
+
+static HRESULT
+NineVolume9_ctor( struct NineVolume9 *This,
+ struct NineUnknownParams *pParams,
+ struct NineUnknown *pContainer,
+ struct pipe_resource *pResource,
+ unsigned Level,
+ D3DVOLUME_DESC *pDesc )
+{
+ HRESULT hr;
+
+ assert(pContainer); /* stand-alone volumes can't be created */
+
+ DBG("This=%p pContainer=%p pDevice=%p pResource=%p Level=%u pDesc=%p\n",
+ This, pContainer, pParams->device, pResource, Level, pDesc);
+
+ /* Mark this as a special surface held by another internal resource. */
+ pParams->container = pContainer;
+
+ user_assert(!(pDesc->Usage & D3DUSAGE_DYNAMIC) ||
+ (pDesc->Pool != D3DPOOL_MANAGED), D3DERR_INVALIDCALL);
+
+ assert(pResource || pDesc->Pool != D3DPOOL_DEFAULT);
+
+ hr = NineUnknown_ctor(&This->base, pParams);
+ if (FAILED(hr))
+ return hr;
+
+ This->pdata = util_hash_table_create(ht_guid_hash, ht_guid_compare);
+ if (!This->pdata)
+ return E_OUTOFMEMORY;
+
+ pipe_resource_reference(&This->resource, pResource);
+
+ This->pipe = pParams->device->pipe;
+ This->transfer = NULL;
+ This->lock_count = 0;
+
+ This->level = Level;
+ This->level_actual = Level;
+ This->desc = *pDesc;
+
+ This->info.screen = pParams->device->screen;
+ This->info.target = PIPE_TEXTURE_3D;
+ This->info.format = d3d9_to_pipe_format(pDesc->Format);
+ This->info.width0 = pDesc->Width;
+ This->info.height0 = pDesc->Height;
+ This->info.depth0 = pDesc->Depth;
+ This->info.last_level = 0;
+ This->info.array_size = 1;
+ This->info.nr_samples = 0;
+ This->info.usage = PIPE_USAGE_DEFAULT;
+ This->info.bind = PIPE_BIND_SAMPLER_VIEW;
+ This->info.flags = 0;
+
+ This->stride = util_format_get_stride(This->info.format, pDesc->Width);
+ This->stride = align(This->stride, 4);
+ This->layer_stride = util_format_get_2d_size(This->info.format,
+ This->stride, pDesc->Height);
+
+ if (pDesc->Pool == D3DPOOL_SYSTEMMEM)
+ This->info.usage = PIPE_USAGE_STAGING;
+
+ if (!This->resource) {
+ hr = NineVolume9_AllocateData(This);
+ if (FAILED(hr))
+ return hr;
+ }
+ return D3D_OK;
+}
+
+static void
+NineVolume9_dtor( struct NineVolume9 *This )
+{
+ DBG("This=%p\n", This);
+
+ if (This->transfer)
+ NineVolume9_UnlockBox(This);
+
+ pipe_resource_reference(&This->resource, NULL);
+
+ NineUnknown_dtor(&This->base);
+}
+
+HRESULT WINAPI
+NineVolume9_GetContainer( struct NineVolume9 *This,
+ REFIID riid,
+ void **ppContainer )
+{
+ if (!NineUnknown(This)->container)
+ return E_NOINTERFACE;
+ return NineUnknown_QueryInterface(NineUnknown(This)->container, riid, ppContainer);
+}
+
+static INLINE void
+NineVolume9_MarkContainerDirty( struct NineVolume9 *This )
+{
+ struct NineBaseTexture9 *tex;
+#ifdef DEBUG
+ /* This is always contained by a NineVolumeTexture9. */
+ GUID id = IID_IDirect3DVolumeTexture9;
+ REFIID ref = &id;
+ assert(NineUnknown_QueryInterface(This->base.container, ref, (void **)&tex)
+ == S_OK);
+ assert(NineUnknown_Release(NineUnknown(tex)) != 0);
+#endif
+
+ tex = NineBaseTexture9(This->base.container);
+ assert(tex);
+ if (This->desc.Pool == D3DPOOL_MANAGED)
+ tex->dirty = TRUE;
+ else
+ if (This->desc.Usage & D3DUSAGE_AUTOGENMIPMAP)
+ tex->dirty_mip = TRUE;
+
+ BASETEX_REGISTER_UPDATE(tex);
+}
+
+HRESULT WINAPI
+NineVolume9_GetDesc( struct NineVolume9 *This,
+ D3DVOLUME_DESC *pDesc )
+{
+ user_assert(pDesc != NULL, E_POINTER);
+ *pDesc = This->desc;
+ return D3D_OK;
+}
+
+static INLINE boolean
+NineVolume9_IsDirty(struct NineVolume9 *This)
+{
+ return This->dirty_box[0].width != 0;
+}
+
+INLINE void
+NineVolume9_AddDirtyRegion( struct NineVolume9 *This,
+ const struct pipe_box *box )
+{
+ struct pipe_box cover_a, cover_b;
+ float vol[2];
+
+ if (!box) {
+ u_box_3d(0, 0, 0, This->desc.Width, This->desc.Height,
+ This->desc.Depth, &This->dirty_box[0]);
+ memset(&This->dirty_box[1], 0, sizeof(This->dirty_box[1]));
+ return;
+ }
+ if (!This->dirty_box[0].width) {
+ This->dirty_box[0] = *box;
+ return;
+ }
+
+ u_box_union_3d(&cover_a, &This->dirty_box[0], box);
+ vol[0] = u_box_volume_3d(&cover_a);
+
+ if (This->dirty_box[1].width == 0) {
+ vol[1] = u_box_volume_3d(&This->dirty_box[0]);
+ if (vol[0] > (vol[1] * 1.5f))
+ This->dirty_box[1] = *box;
+ else
+ This->dirty_box[0] = cover_a;
+ } else {
+ u_box_union_3d(&cover_b, &This->dirty_box[1], box);
+ vol[1] = u_box_volume_3d(&cover_b);
+
+ if (vol[0] > vol[1])
+ This->dirty_box[1] = cover_b;
+ else
+ This->dirty_box[0] = cover_a;
+ }
+}
+
+static INLINE uint8_t *
+NineVolume9_GetSystemMemPointer(struct NineVolume9 *This, int x, int y, int z)
+{
+ unsigned x_offset = util_format_get_stride(This->info.format, x);
+
+ y = util_format_get_nblocksy(This->info.format, y);
+
+ assert(This->data);
+ return This->data + (z * This->layer_stride + y * This->stride + x_offset);
+}
+
+HRESULT WINAPI
+NineVolume9_LockBox( struct NineVolume9 *This,
+ D3DLOCKED_BOX *pLockedVolume,
+ const D3DBOX *pBox,
+ DWORD Flags )
+{
+ struct pipe_resource *resource = This->resource;
+ struct pipe_box box;
+ unsigned usage;
+
+ DBG("This=%p(%p) pLockedVolume=%p pBox=%p[%u..%u,%u..%u,%u..%u] Flags=%s\n",
+ This, This->base.container, pLockedVolume, pBox,
+ pBox ? pBox->Left : 0, pBox ? pBox->Right : 0,
+ pBox ? pBox->Top : 0, pBox ? pBox->Bottom : 0,
+ pBox ? pBox->Front : 0, pBox ? pBox->Back : 0,
+ nine_D3DLOCK_to_str(Flags));
+
+ user_assert(This->desc.Pool != D3DPOOL_DEFAULT ||
+ (This->desc.Usage & D3DUSAGE_DYNAMIC), D3DERR_INVALIDCALL);
+
+ user_assert(!((Flags & D3DLOCK_DISCARD) && (Flags & D3DLOCK_READONLY)),
+ D3DERR_INVALIDCALL);
+
+ user_assert(This->lock_count == 0, D3DERR_INVALIDCALL);
+ user_assert(pLockedVolume, E_POINTER);
+
+ if (pBox && This->desc.Pool == D3DPOOL_DEFAULT &&
+ util_format_is_compressed(This->info.format)) {
+ const unsigned w = util_format_get_blockwidth(This->info.format);
+ const unsigned h = util_format_get_blockheight(This->info.format);
+ user_assert(!(pBox->Left % w) && !(pBox->Right % w) &&
+ !(pBox->Top % h) && !(pBox->Bottom % h),
+ D3DERR_INVALIDCALL);
+ }
+
+ if (Flags & D3DLOCK_DISCARD) {
+ usage = PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE;
+ } else {
+ usage = (Flags & D3DLOCK_READONLY) ?
+ PIPE_TRANSFER_READ : PIPE_TRANSFER_READ_WRITE;
+ }
+ if (Flags & D3DLOCK_DONOTWAIT)
+ usage |= PIPE_TRANSFER_DONTBLOCK;
+
+ if (pBox) {
+ d3dbox_to_pipe_box(&box, pBox);
+ if (u_box_clip_2d(&box, &box, This->desc.Width, This->desc.Height) < 0) {
+ DBG("Locked volume intersection empty.\n");
+ return D3DERR_INVALIDCALL;
+ }
+ } else {
+ u_box_3d(0, 0, 0, This->desc.Width, This->desc.Height, This->desc.Depth,
+ &box);
+ }
+
+ if (This->data) {
+ pLockedVolume->RowPitch = This->stride;
+ pLockedVolume->SlicePitch = This->layer_stride;
+ pLockedVolume->pBits =
+ NineVolume9_GetSystemMemPointer(This, box.x, box.y, box.z);
+ } else {
+ pLockedVolume->pBits =
+ This->pipe->transfer_map(This->pipe, resource, This->level, usage,
+ &box, &This->transfer);
+ if (!This->transfer) {
+ if (Flags & D3DLOCK_DONOTWAIT)
+ return D3DERR_WASSTILLDRAWING;
+ return D3DERR_DRIVERINTERNALERROR;
+ }
+ pLockedVolume->RowPitch = This->transfer->stride;
+ pLockedVolume->SlicePitch = This->transfer->layer_stride;
+ }
+
+ if (!(Flags & (D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_READONLY))) {
+ NineVolume9_MarkContainerDirty(This);
+ if (This->desc.Pool == D3DPOOL_MANAGED)
+ NineVolume9_AddDirtyRegion(This, &box);
+ }
+
+ ++This->lock_count;
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineVolume9_UnlockBox( struct NineVolume9 *This )
+{
+ DBG("This=%p lock_count=%u\n", This, This->lock_count);
+ user_assert(This->lock_count, D3DERR_INVALIDCALL);
+ if (This->transfer) {
+ This->pipe->transfer_unmap(This->pipe, This->transfer);
+ This->transfer = NULL;
+ }
+ --This->lock_count;
+ return D3D_OK;
+}
+
+
+HRESULT
+NineVolume9_CopyVolume( struct NineVolume9 *This,
+ struct NineVolume9 *From,
+ unsigned dstx, unsigned dsty, unsigned dstz,
+ struct pipe_box *pSrcBox )
+{
+ struct pipe_context *pipe = This->pipe;
+ struct pipe_resource *r_dst = This->resource;
+ struct pipe_resource *r_src = From->resource;
+ struct pipe_transfer *transfer;
+ struct pipe_box src_box;
+ struct pipe_box dst_box;
+ uint8_t *p_dst;
+ const uint8_t *p_src;
+
+ user_assert(This->desc.Format == From->desc.Format, D3DERR_INVALIDCALL);
+
+ dst_box.x = dstx;
+ dst_box.y = dsty;
+ dst_box.z = dstz;
+
+ if (pSrcBox) {
+ /* make sure it doesn't range outside the source volume */
+ user_assert(pSrcBox->x >= 0 &&
+ (pSrcBox->width - pSrcBox->x) <= From->desc.Width &&
+ pSrcBox->y >= 0 &&
+ (pSrcBox->height - pSrcBox->y) <= From->desc.Height &&
+ pSrcBox->z >= 0 &&
+ (pSrcBox->depth - pSrcBox->z) <= From->desc.Depth,
+ D3DERR_INVALIDCALL);
+ src_box = *pSrcBox;
+ } else {
+ src_box.x = 0;
+ src_box.y = 0;
+ src_box.z = 0;
+ src_box.width = From->desc.Width;
+ src_box.height = From->desc.Height;
+ src_box.depth = From->desc.Depth;
+ }
+ /* limits */
+ dst_box.width = This->desc.Width - dst_box.x;
+ dst_box.height = This->desc.Height - dst_box.y;
+ dst_box.depth = This->desc.Depth - dst_box.z;
+
+ user_assert(src_box.width <= dst_box.width &&
+ src_box.height <= dst_box.height &&
+ src_box.depth <= dst_box.depth, D3DERR_INVALIDCALL);
+
+ dst_box.width = src_box.width;
+ dst_box.height = src_box.height;
+ dst_box.depth = src_box.depth;
+
+ /* Don't copy to device memory of managed resources.
+ * We don't want to download it back again later.
+ */
+ if (This->desc.Pool == D3DPOOL_MANAGED)
+ r_dst = NULL;
+
+ /* Don't copy from stale device memory of managed resources.
+ * Also, don't copy between system and device if we don't have to.
+ */
+ if (From->desc.Pool == D3DPOOL_MANAGED) {
+ if (!r_dst || NineVolume9_IsDirty(From))
+ r_src = NULL;
+ }
+
+ if (r_dst && r_src) {
+ pipe->resource_copy_region(pipe,
+ r_dst, This->level,
+ dst_box.x, dst_box.y, dst_box.z,
+ r_src, From->level,
+ &src_box);
+ } else
+ if (r_dst) {
+ p_src = NineVolume9_GetSystemMemPointer(From,
+ src_box.x, src_box.y, src_box.z);
+
+ pipe->transfer_inline_write(pipe, r_dst, This->level,
+ 0, /* WRITE|DISCARD are implicit */
+ &dst_box, p_src,
+ From->stride, From->layer_stride);
+ } else
+ if (r_src) {
+ p_dst = NineVolume9_GetSystemMemPointer(This, 0, 0, 0);
+ p_src = pipe->transfer_map(pipe, r_src, From->level,
+ PIPE_TRANSFER_READ,
+ &src_box, &transfer);
+ if (!p_src)
+ return D3DERR_DRIVERINTERNALERROR;
+
+ util_copy_box(p_dst, This->info.format,
+ This->stride, This->layer_stride,
+ dst_box.x, dst_box.y, dst_box.z,
+ dst_box.width, dst_box.height, dst_box.depth,
+ p_src,
+ transfer->stride, transfer->layer_stride,
+ src_box.x, src_box.y, src_box.z);
+
+ pipe->transfer_unmap(pipe, transfer);
+ } else {
+ p_dst = NineVolume9_GetSystemMemPointer(This, 0, 0, 0);
+ p_src = NineVolume9_GetSystemMemPointer(From, 0, 0, 0);
+
+ util_copy_box(p_dst, This->info.format,
+ This->stride, This->layer_stride,
+ dst_box.x, dst_box.y, dst_box.z,
+ dst_box.width, dst_box.height, dst_box.depth,
+ p_src,
+ From->stride, From->layer_stride,
+ src_box.x, src_box.y, src_box.z);
+ }
+
+ if (This->desc.Pool == D3DPOOL_DEFAULT ||
+ This->desc.Pool == D3DPOOL_MANAGED)
+ NineVolume9_MarkContainerDirty(This);
+ if (!r_dst && This->resource)
+ NineVolume9_AddDirtyRegion(This, &dst_box);
+
+ return D3D_OK;
+}
+
+HRESULT
+NineVolume9_UploadSelf( struct NineVolume9 *This )
+{
+ struct pipe_context *pipe = This->pipe;
+ struct pipe_resource *res = This->resource;
+ uint8_t *ptr;
+ unsigned i;
+
+ DBG("This=%p dirty=%i data=%p res=%p\n", This, NineVolume9_IsDirty(This),
+ This->data, res);
+
+ assert(This->desc.Pool == D3DPOOL_MANAGED);
+
+ if (!NineVolume9_IsDirty(This))
+ return D3D_OK;
+ assert(res);
+
+ for (i = 0; i < Elements(This->dirty_box); ++i) {
+ const struct pipe_box *box = &This->dirty_box[i];
+ if (box->width == 0)
+ break;
+ ptr = NineVolume9_GetSystemMemPointer(This, box->x, box->y, box->z);
+
+ pipe->transfer_inline_write(pipe, res, This->level,
+ 0,
+ box, ptr, This->stride, This->layer_stride);
+ }
+ NineVolume9_ClearDirtyRegion(This);
+
+ return D3D_OK;
+}
+
+
+IDirect3DVolume9Vtbl NineVolume9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)NineUnknown_GetDevice, /* actually part of Volume9 iface */
+ (void *)NineVolume9_SetPrivateData,
+ (void *)NineVolume9_GetPrivateData,
+ (void *)NineVolume9_FreePrivateData,
+ (void *)NineVolume9_GetContainer,
+ (void *)NineVolume9_GetDesc,
+ (void *)NineVolume9_LockBox,
+ (void *)NineVolume9_UnlockBox
+};
+
+static const GUID *NineVolume9_IIDs[] = {
+ &IID_IDirect3DVolume9,
+ &IID_IUnknown,
+ NULL
+};
+
+HRESULT
+NineVolume9_new( struct NineDevice9 *pDevice,
+ struct NineUnknown *pContainer,
+ struct pipe_resource *pResource,
+ unsigned Level,
+ D3DVOLUME_DESC *pDesc,
+ struct NineVolume9 **ppOut )
+{
+ NINE_DEVICE_CHILD_NEW(Volume9, ppOut, pDevice, /* args */
+ pContainer, pResource, Level, pDesc);
+}
+
+
+/*** The boring stuff. TODO: Unify with Resource. ***/
+
+HRESULT WINAPI
+NineVolume9_SetPrivateData( struct NineVolume9 *This,
+ REFGUID refguid,
+ const void *pData,
+ DWORD SizeOfData,
+ DWORD Flags )
+{
+ enum pipe_error err;
+ struct pheader *header;
+ const void *user_data = pData;
+
+ if (Flags & D3DSPD_IUNKNOWN)
+ user_assert(SizeOfData == sizeof(IUnknown *), D3DERR_INVALIDCALL);
+
+ /* data consists of a header and the actual data. avoiding 2 mallocs */
+ header = CALLOC_VARIANT_LENGTH_STRUCT(pheader, SizeOfData-1);
+ if (!header) { return E_OUTOFMEMORY; }
+ header->unknown = (Flags & D3DSPD_IUNKNOWN) ? TRUE : FALSE;
+
+ /* if the refguid already exists, delete it */
+ NineVolume9_FreePrivateData(This, refguid);
+
+ /* IUnknown special case */
+ if (header->unknown) {
+ /* here the pointer doesn't point to the data we want, so point at the
+ * pointer making what we eventually copy is the pointer itself */
+ user_data = &pData;
+ }
+
+ header->size = SizeOfData;
+ memcpy(header->data, user_data, header->size);
+
+ err = util_hash_table_set(This->pdata, refguid, header);
+ if (err == PIPE_OK) {
+ if (header->unknown) { IUnknown_AddRef(*(IUnknown **)header->data); }
+ return D3D_OK;
+ }
+
+ FREE(header);
+ if (err == PIPE_ERROR_OUT_OF_MEMORY) { return E_OUTOFMEMORY; }
+
+ return D3DERR_DRIVERINTERNALERROR;
+}
+
+HRESULT WINAPI
+NineVolume9_GetPrivateData( struct NineVolume9 *This,
+ REFGUID refguid,
+ void *pData,
+ DWORD *pSizeOfData )
+{
+ struct pheader *header;
+
+ user_assert(pSizeOfData, E_POINTER);
+
+ header = util_hash_table_get(This->pdata, refguid);
+ if (!header) { return D3DERR_NOTFOUND; }
+
+ if (!pData) {
+ *pSizeOfData = header->size;
+ return D3D_OK;
+ }
+ if (*pSizeOfData < header->size) {
+ return D3DERR_MOREDATA;
+ }
+
+ if (header->unknown) { IUnknown_AddRef(*(IUnknown **)header->data); }
+ memcpy(pData, header->data, header->size);
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineVolume9_FreePrivateData( struct NineVolume9 *This,
+ REFGUID refguid )
+{
+ struct pheader *header;
+
+ header = util_hash_table_get(This->pdata, refguid);
+ if (!header) { return D3DERR_NOTFOUND; }
+
+ ht_guid_delete(NULL, header, NULL);
+ util_hash_table_remove(This->pdata, refguid);
+
+ return D3D_OK;
+}
+
diff --git a/src/gallium/state_trackers/nine/volume9.h b/src/gallium/state_trackers/nine/volume9.h
new file mode 100644
index 00000000000..802836659c2
--- /dev/null
+++ b/src/gallium/state_trackers/nine/volume9.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _NINE_VOLUME9_H_
+#define _NINE_VOLUME9_H_
+
+#include "iunknown.h"
+
+#include "pipe/p_state.h"
+#include "util/u_inlines.h"
+
+struct util_hash_table;
+
+struct NineDevice9;
+
+struct NineVolume9
+{
+ struct NineUnknown base;
+
+ struct pipe_resource *resource;
+ unsigned level;
+ unsigned level_actual;
+
+ uint8_t *data; /* system memory backing */
+
+ D3DVOLUME_DESC desc;
+ struct pipe_resource info;
+ unsigned stride;
+ unsigned layer_stride;
+
+ struct pipe_transfer *transfer;
+ unsigned lock_count;
+
+ struct pipe_box dirty_box[2];
+
+ struct pipe_context *pipe;
+
+ /* for [GS]etPrivateData/FreePrivateData */
+ struct util_hash_table *pdata;
+};
+static INLINE struct NineVolume9 *
+NineVolume9( void *data )
+{
+ return (struct NineVolume9 *)data;
+}
+
+HRESULT
+NineVolume9_new( struct NineDevice9 *pDevice,
+ struct NineUnknown *pContainer,
+ struct pipe_resource *pResource,
+ unsigned Level,
+ D3DVOLUME_DESC *pDesc,
+ struct NineVolume9 **ppOut );
+
+/*** Nine private ***/
+
+static INLINE void
+NineVolume9_SetResource( struct NineVolume9 *This,
+ struct pipe_resource *resource, unsigned level )
+{
+ This->level = level;
+ pipe_resource_reference(&This->resource, resource);
+}
+
+void
+NineVolume9_AddDirtyRegion( struct NineVolume9 *This,
+ const struct pipe_box *box );
+
+static INLINE void
+NineVolume9_ClearDirtyRegion( struct NineVolume9 *This )
+{
+ memset(&This->dirty_box, 0, sizeof(This->dirty_box));
+}
+
+HRESULT
+NineVolume9_CopyVolume( struct NineVolume9 *This,
+ struct NineVolume9 *From,
+ unsigned dstx, unsigned dsty, unsigned dstz,
+ struct pipe_box *pSrcBox );
+
+HRESULT
+NineVolume9_UploadSelf( struct NineVolume9 *This );
+
+
+/*** Direct3D public ***/
+
+HRESULT WINAPI
+NineVolume9_SetPrivateData( struct NineVolume9 *This,
+ REFGUID refguid,
+ const void *pData,
+ DWORD SizeOfData,
+ DWORD Flags );
+
+HRESULT WINAPI
+NineVolume9_GetPrivateData( struct NineVolume9 *This,
+ REFGUID refguid,
+ void *pData,
+ DWORD *pSizeOfData );
+
+HRESULT WINAPI
+NineVolume9_FreePrivateData( struct NineVolume9 *This,
+ REFGUID refguid );
+
+HRESULT WINAPI
+NineVolume9_GetContainer( struct NineVolume9 *This,
+ REFIID riid,
+ void **ppContainer );
+
+HRESULT WINAPI
+NineVolume9_GetDesc( struct NineVolume9 *This,
+ D3DVOLUME_DESC *pDesc );
+
+HRESULT WINAPI
+NineVolume9_LockBox( struct NineVolume9 *This,
+ D3DLOCKED_BOX *pLockedVolume,
+ const D3DBOX *pBox,
+ DWORD Flags );
+
+HRESULT WINAPI
+NineVolume9_UnlockBox( struct NineVolume9 *This );
+
+#endif /* _NINE_VOLUME9_H_ */
diff --git a/src/gallium/state_trackers/nine/volumetexture9.c b/src/gallium/state_trackers/nine/volumetexture9.c
new file mode 100644
index 00000000000..65d320c6645
--- /dev/null
+++ b/src/gallium/state_trackers/nine/volumetexture9.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "device9.h"
+#include "volumetexture9.h"
+#include "nine_helpers.h"
+#include "nine_pipe.h"
+
+#define DBG_CHANNEL DBG_VOLUMETEXTURE
+
+static HRESULT
+NineVolumeTexture9_ctor( struct NineVolumeTexture9 *This,
+ struct NineUnknownParams *pParams,
+ UINT Width, UINT Height, UINT Depth, UINT Levels,
+ DWORD Usage,
+ D3DFORMAT Format,
+ D3DPOOL Pool,
+ HANDLE *pSharedHandle )
+{
+ struct pipe_resource *info = &This->base.base.info;
+ unsigned l;
+ D3DVOLUME_DESC voldesc;
+ HRESULT hr;
+
+ /* An IDirect3DVolume9 cannot be bound as a render target can it ? */
+ user_assert(!(Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)),
+ D3DERR_INVALIDCALL);
+ user_assert(!(Usage & D3DUSAGE_AUTOGENMIPMAP) ||
+ (Pool != D3DPOOL_SYSTEMMEM && Levels <= 1), D3DERR_INVALIDCALL);
+
+ user_assert(!pSharedHandle, D3DERR_INVALIDCALL); /* TODO */
+
+ if (Usage & D3DUSAGE_AUTOGENMIPMAP)
+ Levels = 0;
+
+ This->base.format = Format;
+ This->base.base.usage = Usage;
+
+ info->screen = pParams->device->screen;
+ info->target = PIPE_TEXTURE_3D;
+ info->format = d3d9_to_pipe_format(Format);
+ info->width0 = Width;
+ info->height0 = Height;
+ info->depth0 = Depth;
+ if (Levels)
+ info->last_level = Levels - 1;
+ else
+ info->last_level = util_logbase2(MAX2(MAX2(Width, Height), Depth));
+ info->array_size = 1;
+ info->nr_samples = 0;
+ info->bind = PIPE_BIND_SAMPLER_VIEW;
+ info->usage = PIPE_USAGE_DEFAULT;
+ info->flags = 0;
+
+ if (Usage & D3DUSAGE_DYNAMIC) {
+ info->usage = PIPE_USAGE_DYNAMIC;
+ info->bind |=
+ PIPE_BIND_TRANSFER_READ |
+ PIPE_BIND_TRANSFER_WRITE;
+ }
+
+ This->volumes = CALLOC(info->last_level + 1, sizeof(*This->volumes));
+ if (!This->volumes)
+ return E_OUTOFMEMORY;
+ This->base.pstype = 3;
+
+ hr = NineBaseTexture9_ctor(&This->base, pParams,
+ D3DRTYPE_VOLUMETEXTURE, Pool);
+ if (FAILED(hr))
+ return hr;
+
+ voldesc.Format = Format;
+ voldesc.Type = D3DRTYPE_VOLUME;
+ voldesc.Usage = Usage;
+ voldesc.Pool = Pool;
+ for (l = 0; l <= info->last_level; ++l) {
+ voldesc.Width = u_minify(Width, l);
+ voldesc.Height = u_minify(Height, l);
+ voldesc.Depth = u_minify(Depth, l);
+
+ hr = NineVolume9_new(This->base.base.base.device, NineUnknown(This),
+ This->base.base.resource, l,
+ &voldesc, &This->volumes[l]);
+ if (FAILED(hr))
+ return hr;
+ }
+
+ return D3D_OK;
+}
+
+static void
+NineVolumeTexture9_dtor( struct NineVolumeTexture9 *This )
+{
+ unsigned l;
+
+ DBG("This=%p\n", This);
+
+ if (This->volumes) {
+ for (l = 0; l < This->base.base.info.last_level; ++l)
+ NineUnknown_Destroy(&This->volumes[l]->base);
+ FREE(This->volumes);
+ }
+
+ NineBaseTexture9_dtor(&This->base);
+}
+
+HRESULT WINAPI
+NineVolumeTexture9_GetLevelDesc( struct NineVolumeTexture9 *This,
+ UINT Level,
+ D3DVOLUME_DESC *pDesc )
+{
+ user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL);
+ user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP),
+ D3DERR_INVALIDCALL);
+
+ *pDesc = This->volumes[Level]->desc;
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineVolumeTexture9_GetVolumeLevel( struct NineVolumeTexture9 *This,
+ UINT Level,
+ IDirect3DVolume9 **ppVolumeLevel )
+{
+ user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL);
+ user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP),
+ D3DERR_INVALIDCALL);
+
+ NineUnknown_AddRef(NineUnknown(This->volumes[Level]));
+ *ppVolumeLevel = (IDirect3DVolume9 *)This->volumes[Level];
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+NineVolumeTexture9_LockBox( struct NineVolumeTexture9 *This,
+ UINT Level,
+ D3DLOCKED_BOX *pLockedVolume,
+ const D3DBOX *pBox,
+ DWORD Flags )
+{
+ user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL);
+ user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP),
+ D3DERR_INVALIDCALL);
+
+ return NineVolume9_LockBox(This->volumes[Level], pLockedVolume, pBox,
+ Flags);
+}
+
+HRESULT WINAPI
+NineVolumeTexture9_UnlockBox( struct NineVolumeTexture9 *This,
+ UINT Level )
+{
+ user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL);
+
+ return NineVolume9_UnlockBox(This->volumes[Level]);
+}
+
+HRESULT WINAPI
+NineVolumeTexture9_AddDirtyBox( struct NineVolumeTexture9 *This,
+ const D3DBOX *pDirtyBox )
+{
+ if (This->base.base.pool != D3DPOOL_MANAGED) {
+ if (This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP)
+ This->base.dirty_mip = TRUE;
+ return D3D_OK;
+ }
+ This->base.dirty = TRUE;
+
+ BASETEX_REGISTER_UPDATE(&This->base);
+
+ if (!pDirtyBox) {
+ This->dirty_box.x = 0;
+ This->dirty_box.y = 0;
+ This->dirty_box.z = 0;
+ This->dirty_box.width = This->base.base.info.width0;
+ This->dirty_box.height = This->base.base.info.height0;
+ This->dirty_box.depth = This->base.base.info.depth0;
+ } else {
+ struct pipe_box box;
+ d3dbox_to_pipe_box(&box, pDirtyBox);
+ u_box_union_3d(&This->dirty_box, &This->dirty_box, &box);
+ }
+ return D3D_OK;
+}
+
+IDirect3DVolumeTexture9Vtbl NineVolumeTexture9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */
+ (void *)NineResource9_SetPrivateData,
+ (void *)NineResource9_GetPrivateData,
+ (void *)NineResource9_FreePrivateData,
+ (void *)NineResource9_SetPriority,
+ (void *)NineResource9_GetPriority,
+ (void *)NineBaseTexture9_PreLoad,
+ (void *)NineResource9_GetType,
+ (void *)NineBaseTexture9_SetLOD,
+ (void *)NineBaseTexture9_GetLOD,
+ (void *)NineBaseTexture9_GetLevelCount,
+ (void *)NineBaseTexture9_SetAutoGenFilterType,
+ (void *)NineBaseTexture9_GetAutoGenFilterType,
+ (void *)NineBaseTexture9_GenerateMipSubLevels,
+ (void *)NineVolumeTexture9_GetLevelDesc,
+ (void *)NineVolumeTexture9_GetVolumeLevel,
+ (void *)NineVolumeTexture9_LockBox,
+ (void *)NineVolumeTexture9_UnlockBox,
+ (void *)NineVolumeTexture9_AddDirtyBox
+};
+
+static const GUID *NineVolumeTexture9_IIDs[] = {
+ &IID_IDirect3DVolumeTexture9,
+ &IID_IDirect3DBaseTexture9,
+ &IID_IDirect3DResource9,
+ &IID_IUnknown,
+ NULL
+};
+
+HRESULT
+NineVolumeTexture9_new( struct NineDevice9 *pDevice,
+ UINT Width, UINT Height, UINT Depth, UINT Levels,
+ DWORD Usage,
+ D3DFORMAT Format,
+ D3DPOOL Pool,
+ struct NineVolumeTexture9 **ppOut,
+ HANDLE *pSharedHandle )
+{
+ NINE_DEVICE_CHILD_NEW(VolumeTexture9, ppOut, pDevice,
+ Width, Height, Depth, Levels,
+ Usage, Format, Pool, pSharedHandle);
+}
+
diff --git a/src/gallium/state_trackers/nine/volumetexture9.h b/src/gallium/state_trackers/nine/volumetexture9.h
new file mode 100644
index 00000000000..313fa1a91fb
--- /dev/null
+++ b/src/gallium/state_trackers/nine/volumetexture9.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _NINE_VOLUMETEXTURE9_H_
+#define _NINE_VOLUMETEXTURE9_H_
+
+#include "basetexture9.h"
+#include "volume9.h"
+
+struct NineVolumeTexture9
+{
+ struct NineBaseTexture9 base;
+ struct NineVolume9 **volumes;
+ struct pipe_box dirty_box;
+};
+static INLINE struct NineVolumeTexture9 *
+NineVolumeTexture9( void *data )
+{
+ return (struct NineVolumeTexture9 *)data;
+}
+
+HRESULT
+NineVolumeTexture9_new( struct NineDevice9 *pDevice,
+ UINT Width, UINT Height, UINT Depth, UINT Levels,
+ DWORD Usage,
+ D3DFORMAT Format,
+ D3DPOOL Pool,
+ struct NineVolumeTexture9 **ppOut,
+ HANDLE *pSharedHandle );
+
+HRESULT WINAPI
+NineVolumeTexture9_GetLevelDesc( struct NineVolumeTexture9 *This,
+ UINT Level,
+ D3DVOLUME_DESC *pDesc );
+
+HRESULT WINAPI
+NineVolumeTexture9_GetVolumeLevel( struct NineVolumeTexture9 *This,
+ UINT Level,
+ IDirect3DVolume9 **ppVolumeLevel );
+
+HRESULT WINAPI
+NineVolumeTexture9_LockBox( struct NineVolumeTexture9 *This,
+ UINT Level,
+ D3DLOCKED_BOX *pLockedVolume,
+ const D3DBOX *pBox,
+ DWORD Flags );
+
+HRESULT WINAPI
+NineVolumeTexture9_UnlockBox( struct NineVolumeTexture9 *This,
+ UINT Level );
+
+HRESULT WINAPI
+NineVolumeTexture9_AddDirtyBox( struct NineVolumeTexture9 *This,
+ const D3DBOX *pDirtyBox );
+
+#endif /* _NINE_VOLUMETEXTURE9_H_ */
diff --git a/src/gallium/targets/d3dadapter9/Makefile.am b/src/gallium/targets/d3dadapter9/Makefile.am
new file mode 100644
index 00000000000..62312369adc
--- /dev/null
+++ b/src/gallium/targets/d3dadapter9/Makefile.am
@@ -0,0 +1,131 @@
+# Copyright © 2012 Intel Corporation
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+include $(top_srcdir)/src/gallium/Automake.inc
+
+AM_CFLAGS = \
+ -I$(top_srcdir)/include/D3D9 \
+ -I$(top_srcdir)/src/loader \
+ -I$(top_srcdir)/src/mapi/ \
+ -I$(top_srcdir)/src/mesa/ \
+ -I$(top_srcdir)/src/mesa/drivers/dri/common/ \
+ -I$(top_builddir)/src/mesa/drivers/dri/common/ \
+ -I$(top_srcdir)/src/gallium/winsys \
+ -I$(top_srcdir)/src/gallium/state_trackers/nine \
+ $(GALLIUM_TARGET_CFLAGS) \
+ $(VISIBILITY_CFLAGS)
+
+if HAVE_GALLIUM_STATIC_TARGETS
+AM_CPPFLAGS = \
+ -DNINE_TARGET \
+ -DGALLIUM_STATIC_TARGETS=1
+
+else
+
+AM_CPPFLAGS = \
+ -DPIPE_SEARCH_DIR=\"$(libdir)/gallium-pipe\" \
+ $(GALLIUM_PIPE_LOADER_DEFINES)
+
+endif
+
+ninedir = $(D3D_DRIVER_INSTALL_DIR)
+nine_LTLIBRARIES = d3dadapter9.la
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = d3d.pc
+
+d3dadapter9_la_SOURCES = \
+ getproc.c \
+ drm.c
+
+d3dadapter9_la_LDFLAGS = \
+ -shared \
+ -shrext .so \
+ -module \
+ -no-undefined \
+ -version-number $(NINE_MAJOR):$(NINE_MINOR) \
+ $(GC_SECTIONS) \
+ $(LD_NO_UNDEFINED)
+
+if HAVE_LD_VERSION_SCRIPT
+d3dadapter9_la_LDFLAGS += \
+ -Wl,--version-script=$(top_srcdir)/src/gallium/targets/d3dadapter9/d3dadapter9.sym
+endif # HAVE_LD_VERSION_SCRIPT
+
+d3dadapter9_la_LIBADD = \
+ $(top_builddir)/src/gallium/auxiliary/libgallium.la \
+ $(top_builddir)/src/gallium/state_trackers/nine/libninetracker.la \
+ $(top_builddir)/src/util/libmesautil.la \
+ $(top_builddir)/src/gallium/winsys/sw/wrapper/libwsw.la \
+ $(EXPAT_LIBS) \
+ $(GALLIUM_COMMON_LIB_DEPS)
+
+
+TARGET_DRIVERS =
+TARGET_CPPFLAGS =
+TARGET_LIB_DEPS = $(top_builddir)/src/loader/libloader.la
+
+include $(top_srcdir)/src/gallium/drivers/i915/Automake.inc
+
+include $(top_srcdir)/src/gallium/drivers/ilo/Automake.inc
+
+include $(top_srcdir)/src/gallium/drivers/nouveau/Automake.inc
+
+include $(top_srcdir)/src/gallium/drivers/r300/Automake.inc
+include $(top_srcdir)/src/gallium/drivers/r600/Automake.inc
+include $(top_srcdir)/src/gallium/drivers/radeonsi/Automake.inc
+
+include $(top_srcdir)/src/gallium/drivers/svga/Automake.inc
+
+include $(top_srcdir)/src/gallium/drivers/freedreno/Automake.inc
+
+include $(top_srcdir)/src/gallium/drivers/vc4/Automake.inc
+
+include $(top_srcdir)/src/gallium/drivers/softpipe/Automake.inc
+include $(top_srcdir)/src/gallium/drivers/llvmpipe/Automake.inc
+
+if HAVE_GALLIUM_STATIC_TARGETS
+
+d3dadapter9_la_CPPFLAGS = $(AM_CPPFLAGS) $(TARGET_CPPFLAGS)
+d3dadapter9_la_LIBADD += $(TARGET_LIB_DEPS) \
+ $(TARGET_RADEON_WINSYS) $(TARGET_RADEON_COMMON)
+
+else # HAVE_GALLIUM_STATIC_TARGETS
+
+d3dadapter9_la_LIBADD += \
+ $(top_builddir)/src/gallium/auxiliary/pipe-loader/libpipe_loader.la \
+ $(GALLIUM_PIPE_LOADER_WINSYS_LIBS) \
+ $(GALLIUM_PIPE_LOADER_LIBS)
+
+endif # HAVE_GALLIUM_STATIC_TARGETS
+
+if HAVE_MESA_LLVM
+nodist_EXTRA_d3dadapter9_la_SOURCES = dummy.cpp
+d3dadapter9_la_LDFLAGS += $(LLVM_LDFLAGS)
+d3dadapter9_la_LIBADD += $(LLVM_LIBS)
+endif
+
+d3dadapterdir = $(includedir)/d3dadapter
+d3dadapter_HEADERS = \
+ $(top_srcdir)/include/d3dadapter/d3dadapter9.h \
+ $(top_srcdir)/include/d3dadapter/drm.h \
+ $(top_srcdir)/include/d3dadapter/present.h
diff --git a/src/gallium/targets/d3dadapter9/d3d.pc.in b/src/gallium/targets/d3dadapter9/d3d.pc.in
new file mode 100644
index 00000000000..9a18a5c1b8e
--- /dev/null
+++ b/src/gallium/targets/d3dadapter9/d3d.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+moduledir=@D3D_DRIVER_INSTALL_DIR@
+
+Name: d3d
+Description: Native D3D driver modules
+Version: @VERSION@
+Requires.private: @DRI_PC_REQ_PRIV@
+Cflags: -I${includedir}
diff --git a/src/gallium/targets/d3dadapter9/d3dadapter9.sym b/src/gallium/targets/d3dadapter9/d3dadapter9.sym
new file mode 100644
index 00000000000..2290daea7a3
--- /dev/null
+++ b/src/gallium/targets/d3dadapter9/d3dadapter9.sym
@@ -0,0 +1,6 @@
+{
+ global:
+ D3DAdapter9GetProc;
+ local:
+ *;
+};
diff --git a/src/gallium/targets/d3dadapter9/drm.c b/src/gallium/targets/d3dadapter9/drm.c
new file mode 100644
index 00000000000..d0b72e07bc2
--- /dev/null
+++ b/src/gallium/targets/d3dadapter9/drm.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "loader.h"
+
+#include "adapter9.h"
+
+#include "pipe-loader/pipe_loader.h"
+
+#include "pipe/p_screen.h"
+#include "pipe/p_state.h"
+
+#include "target-helpers/inline_drm_helper.h"
+#include "target-helpers/inline_sw_helper.h"
+#include "state_tracker/drm_driver.h"
+
+#include "d3dadapter/d3dadapter9.h"
+#include "d3dadapter/drm.h"
+
+#include <libdrm/drm.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+#define DBG_CHANNEL DBG_ADAPTER
+
+#define VERSION_DWORD(hi, lo) \
+ ((DWORD)( \
+ ((DWORD)((hi) & 0xFFFF) << 16) | \
+ (DWORD)((lo) & 0xFFFF) \
+ ))
+
+/* Regarding os versions, we should not define our own as that would simply be
+ * weird. Defaulting to Win2k/XP seems sane considering the origin of D3D9. The
+ * driver also defaults to being a generic D3D9 driver, which of course only
+ * matters if you're actually using the DDI. */
+#define VERSION_HIGH VERSION_DWORD(0x0006, 0x000E) /* winxp, d3d9 */
+#define VERSION_LOW VERSION_DWORD(0x0000, 0x0001) /* version, build */
+
+struct d3dadapter9drm_context
+{
+ struct d3dadapter9_context base;
+ struct pipe_loader_device *dev, *swdev;
+};
+
+static void
+drm_destroy( struct d3dadapter9_context *ctx )
+{
+#if !GALLIUM_STATIC_TARGETS
+ struct d3dadapter9drm_context *drm = (struct d3dadapter9drm_context *)ctx;
+
+ /* pipe_loader_sw destroys the context */
+ if (drm->swdev)
+ pipe_loader_release(&drm->swdev, 1);
+ if (drm->dev)
+ pipe_loader_release(&drm->dev, 1);
+#endif
+
+ FREE(ctx);
+}
+
+/* read a DWORD in the form 0xnnnnnnnn, which is how sysfs pci id stuff is
+ * formatted. */
+static INLINE DWORD
+read_file_dword( const char *name )
+{
+ char buf[32];
+ int fd, r;
+
+ fd = open(name, O_RDONLY);
+ if (fd < 0) {
+ DBG("Unable to get PCI information from `%s'\n", name);
+ return 0;
+ }
+
+ r = read(fd, buf, 32);
+ close(fd);
+
+ return (r > 0) ? (DWORD)strtol(buf, NULL, 0) : 0;
+}
+
+/* sysfs doesn't expose the revision as its own file, so this function grabs a
+ * dword at an offset in the raw PCI header. The reason this isn't used for all
+ * data is that the kernel will make corrections but not expose them in the raw
+ * header bytes. */
+static INLINE DWORD
+read_config_dword( int fd,
+ unsigned offset )
+{
+ DWORD r = 0;
+
+ if (lseek(fd, offset, SEEK_SET) != offset) { return 0; }
+ if (read(fd, &r, 4) != 4) { return 0; }
+
+ return r;
+}
+
+static INLINE void
+get_bus_info( int fd,
+ DWORD *vendorid,
+ DWORD *deviceid,
+ DWORD *subsysid,
+ DWORD *revision )
+{
+ drm_unique_t u;
+
+ u.unique_len = 0;
+ u.unique = NULL;
+
+ if (ioctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) { return; }
+ u.unique = CALLOC(u.unique_len+1, 1);
+
+ if (ioctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) { return; }
+ u.unique[u.unique_len] = '\0';
+
+ DBG("DRM Device BusID: %s\n", u.unique);
+ if (strncmp("pci:", u.unique, 4) == 0) {
+ char fname[512]; /* this ought to be enough */
+ int l = snprintf(fname, 512, "/sys/bus/pci/devices/%s/", u.unique+4);
+
+ /* VendorId */
+ snprintf(fname+l, 512-l, "vendor");
+ *vendorid = read_file_dword(fname);
+ /* DeviceId */
+ snprintf(fname+l, 512-l, "device");
+ *deviceid = read_file_dword(fname);
+ /* SubSysId */
+ snprintf(fname+l, 512-l, "subsystem_device");
+ *subsysid = (read_file_dword(fname) << 16) & 0xFFFF0000;
+ snprintf(fname+l, 512-l, "subsystem_vendor");
+ *subsysid |= read_file_dword(fname) & 0x0000FFFF;
+ /* Revision */
+ {
+ int cfgfd;
+
+ snprintf(fname+l, 512-l, "config");
+ cfgfd = open(fname, O_RDONLY);
+ if (cfgfd >= 0) {
+ *revision = read_config_dword(cfgfd, 0x8) & 0x000000FF;
+ close(cfgfd);
+ } else {
+ DBG("Unable to get raw PCI information from `%s'\n", fname);
+ }
+ }
+ DBG("PCI info: vendor=0x%04x, device=0x%04x, subsys=0x%08x, rev=%d\n",
+ *vendorid, *deviceid, *subsysid, *revision);
+ } else {
+ DBG("Unsupported BusID type.\n");
+ }
+
+ FREE(u.unique);
+}
+
+static INLINE void
+read_descriptor( struct d3dadapter9_context *ctx,
+ int fd )
+{
+ D3DADAPTER_IDENTIFIER9 *drvid = &ctx->identifier;
+
+ memset(drvid, 0, sizeof(*drvid));
+ get_bus_info(fd, &drvid->VendorId, &drvid->DeviceId,
+ &drvid->SubSysId, &drvid->Revision);
+
+ strncpy(drvid->Driver, "libd3dadapter9.so", sizeof(drvid->Driver));
+ strncpy(drvid->DeviceName, ctx->hal->get_name(ctx->hal), 32);
+ snprintf(drvid->Description, sizeof(drvid->Description),
+ "Gallium 0.4 with %s", ctx->hal->get_vendor(ctx->hal));
+
+ drvid->DriverVersionLowPart = VERSION_LOW;
+ drvid->DriverVersionHighPart = VERSION_HIGH;
+
+ /* To make a pseudo-real GUID we use the PCI bus data and some string */
+ drvid->DeviceIdentifier.Data1 = drvid->VendorId;
+ drvid->DeviceIdentifier.Data2 = drvid->DeviceId;
+ drvid->DeviceIdentifier.Data3 = drvid->SubSysId;
+ memcpy(drvid->DeviceIdentifier.Data4, "Gallium3D", 8);
+
+ drvid->WHQLLevel = 1; /* This fakes WHQL validaion */
+
+ /* XXX Fake NVIDIA binary driver on Windows.
+ *
+ * OS version: 4=95/98/NT4, 5=2000, 6=2000/XP, 7=Vista, 8=Win7
+ */
+ strncpy(drvid->Driver, "nvd3dum.dll", sizeof(drvid->Driver));
+ strncpy(drvid->Description, "NVIDIA GeForce GTX 680", sizeof(drvid->Description));
+ drvid->DriverVersionLowPart = VERSION_DWORD(12, 6658); /* minor, build */
+ drvid->DriverVersionHighPart = VERSION_DWORD(6, 15); /* OS, major */
+ drvid->SubSysId = 0;
+ drvid->Revision = 0;
+ drvid->DeviceIdentifier.Data1 = 0xaeb2cdd4;
+ drvid->DeviceIdentifier.Data2 = 0x6e41;
+ drvid->DeviceIdentifier.Data3 = 0x43ea;
+ drvid->DeviceIdentifier.Data4[0] = 0x94;
+ drvid->DeviceIdentifier.Data4[1] = 0x1c;
+ drvid->DeviceIdentifier.Data4[2] = 0x83;
+ drvid->DeviceIdentifier.Data4[3] = 0x61;
+ drvid->DeviceIdentifier.Data4[4] = 0xcc;
+ drvid->DeviceIdentifier.Data4[5] = 0x76;
+ drvid->DeviceIdentifier.Data4[6] = 0x07;
+ drvid->DeviceIdentifier.Data4[7] = 0x81;
+ drvid->WHQLLevel = 0;
+}
+
+static HRESULT WINAPI
+drm_create_adapter( int fd,
+ ID3DAdapter9 **ppAdapter )
+{
+ struct d3dadapter9drm_context *ctx = CALLOC_STRUCT(d3dadapter9drm_context);
+ HRESULT hr;
+ int i, different_device;
+ const struct drm_conf_ret *throttle_ret = NULL;
+ const struct drm_conf_ret *dmabuf_ret = NULL;
+
+#if !GALLIUM_STATIC_TARGETS
+ const char *paths[] = {
+ getenv("D3D9_DRIVERS_PATH"),
+ getenv("D3D9_DRIVERS_DIR"),
+ PIPE_SEARCH_DIR
+ };
+#endif
+
+ if (!ctx) { return E_OUTOFMEMORY; }
+
+ ctx->base.destroy = drm_destroy;
+
+ fd = loader_get_user_preferred_fd(fd, &different_device);
+ ctx->base.linear_framebuffer = !!different_device;
+
+#if GALLIUM_STATIC_TARGETS
+ ctx->base.hal = dd_create_screen(fd);
+#else
+ /* use pipe-loader to dlopen appropriate drm driver */
+ if (!pipe_loader_drm_probe_fd(&ctx->dev, fd, FALSE)) {
+ ERR("Failed to probe drm fd %d.\n", fd);
+ FREE(ctx);
+ close(fd);
+ return D3DERR_DRIVERINTERNALERROR;
+ }
+
+ /* use pipe-loader to create a drm screen (hal) */
+ ctx->base.hal = NULL;
+ for (i = 0; !ctx->base.hal && i < Elements(paths); ++i) {
+ if (!paths[i]) { continue; }
+ ctx->base.hal = pipe_loader_create_screen(ctx->dev, paths[i]);
+ }
+#endif
+ if (!ctx->base.hal) {
+ ERR("Unable to load requested driver.\n");
+ drm_destroy(&ctx->base);
+ return D3DERR_DRIVERINTERNALERROR;
+ }
+
+#if GALLIUM_STATIC_TARGETS
+ dmabuf_ret = dd_configuration(DRM_CONF_SHARE_FD);
+ throttle_ret = dd_configuration(DRM_CONF_THROTTLE);
+#else
+ dmabuf_ret = pipe_loader_configuration(ctx->dev, DRM_CONF_SHARE_FD);
+ throttle_ret = pipe_loader_configuration(ctx->dev, DRM_CONF_THROTTLE);
+#endif // GALLIUM_STATIC_TARGETS
+ if (!dmabuf_ret || !dmabuf_ret->val.val_bool) {
+ ERR("The driver is not capable of dma-buf sharing."
+ "Abandon to load nine state tracker\n");
+ drm_destroy(&ctx->base);
+ return D3DERR_DRIVERINTERNALERROR;
+ }
+
+ if (throttle_ret && throttle_ret->val.val_int != -1) {
+ ctx->base.throttling = TRUE;
+ ctx->base.throttling_value = throttle_ret->val.val_int;
+ } else
+ ctx->base.throttling = FALSE;
+
+
+#if GALLIUM_STATIC_TARGETS
+ ctx->base.ref = ninesw_create_screen(ctx->base.hal);
+#else
+ /* wrap it to create a software screen that can share resources */
+ if (pipe_loader_sw_probe_wrapped(&ctx->swdev, ctx->base.hal)) {
+ ctx->base.ref = NULL;
+ for (i = 0; !ctx->base.ref && i < Elements(paths); ++i) {
+ if (!paths[i]) { continue; }
+ ctx->base.ref = pipe_loader_create_screen(ctx->swdev, paths[i]);
+ }
+ }
+#endif
+ if (!ctx->base.ref) {
+ ERR("Couldn't wrap drm screen to swrast screen. Software devices "
+ "will be unavailable.\n");
+ }
+
+ /* read out PCI info */
+ read_descriptor(&ctx->base, fd);
+
+ /* create and return new ID3DAdapter9 */
+ hr = NineAdapter9_new(&ctx->base, (struct NineAdapter9 **)ppAdapter);
+ if (FAILED(hr)) {
+ drm_destroy(&ctx->base);
+ return hr;
+ }
+
+ return D3D_OK;
+}
+
+const struct D3DAdapter9DRM drm9_desc = {
+ .major_version = D3DADAPTER9DRM_MAJOR,
+ .minor_version = D3DADAPTER9DRM_MINOR,
+ .create_adapter = drm_create_adapter
+};
diff --git a/src/gallium/targets/d3dadapter9/getproc.c b/src/gallium/targets/d3dadapter9/getproc.c
new file mode 100644
index 00000000000..2aa79a444ed
--- /dev/null
+++ b/src/gallium/targets/d3dadapter9/getproc.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2013 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <string.h>
+
+#include "util/u_memory.h"
+
+#include "d3dadapter/drm.h"
+extern const struct D3DAdapter9DRM drm9_desc;
+
+struct {
+ const char *name;
+ const void *desc;
+} drivers[] = {
+ { D3DADAPTER9DRM_NAME, &drm9_desc },
+};
+
+PUBLIC const void * WINAPI
+D3DAdapter9GetProc( const char *name )
+{
+ int i;
+ for (i = 0; i < Elements(drivers); ++i) {
+ if (strcmp(name, drivers[i].name) == 0) {
+ return drivers[i].desc;
+ }
+ }
+ return NULL;
+}