- sync wined3d, d3d8, d3d9, ddraw with Wine 1.1.21
authorKamil Hornicek <kamil.hornicek@reactos.org>
Fri, 15 May 2009 09:33:59 +0000 (09:33 +0000)
committerKamil Hornicek <kamil.hornicek@reactos.org>
Fri, 15 May 2009 09:33:59 +0000 (09:33 +0000)
svn path=/trunk/; revision=40924

41 files changed:
reactos/dll/directx/wine/d3d8/d3d8_private.h
reactos/dll/directx/wine/d3d8/device.c
reactos/dll/directx/wine/d3d8/directx.c
reactos/dll/directx/wine/d3d9/cubetexture.c
reactos/dll/directx/wine/d3d9/d3d9_private.h
reactos/dll/directx/wine/d3d9/device.c
reactos/dll/directx/wine/d3d9/directx.c
reactos/dll/directx/wine/d3d9/indexbuffer.c
reactos/dll/directx/wine/d3d9/pixelshader.c
reactos/dll/directx/wine/d3d9/texture.c
reactos/dll/directx/wine/d3d9/vertexbuffer.c
reactos/dll/directx/wine/d3d9/vertexshader.c
reactos/dll/directx/wine/d3d9/volumetexture.c
reactos/dll/directx/wine/ddraw/ddcomimpl.h [deleted file]
reactos/dll/directx/wine/ddraw/ddraw.c
reactos/dll/directx/wine/ddraw/device.c
reactos/dll/directx/wine/ddraw/direct3d.c
reactos/dll/directx/wine/ddraw/viewport.c
reactos/dll/directx/wine/wined3d/arb_program_shader.c
reactos/dll/directx/wine/wined3d/baseshader.c
reactos/dll/directx/wine/wined3d/buffer.c
reactos/dll/directx/wine/wined3d/context.c
reactos/dll/directx/wine/wined3d/device.c
reactos/dll/directx/wine/wined3d/directx.c
reactos/dll/directx/wine/wined3d/drawprim.c
reactos/dll/directx/wine/wined3d/glsl_shader.c
reactos/dll/directx/wine/wined3d/pixelshader.c
reactos/dll/directx/wine/wined3d/shader_sm1.c [new file with mode: 0644]
reactos/dll/directx/wine/wined3d/shader_sm4.c [new file with mode: 0644]
reactos/dll/directx/wine/wined3d/state.c
reactos/dll/directx/wine/wined3d/surface.c
reactos/dll/directx/wine/wined3d/surface_base.c
reactos/dll/directx/wine/wined3d/surface_gdi.c
reactos/dll/directx/wine/wined3d/utils.c
reactos/dll/directx/wine/wined3d/vertexdeclaration.c
reactos/dll/directx/wine/wined3d/vertexshader.c
reactos/dll/directx/wine/wined3d/wined3d.rbuild
reactos/dll/directx/wine/wined3d/wined3d_gl.h
reactos/dll/directx/wine/wined3d/wined3d_private.h
reactos/dll/directx/wine/wined3d/wined3d_private_types.h [deleted file]
reactos/include/reactos/wine/wined3d.idl

index c9afe17..c38d8cc 100644 (file)
@@ -601,6 +601,8 @@ struct IDirect3DVertexShader8Impl {
   IWineD3DVertexShader             *wineD3DVertexShader;
 };
 
+#define D3D8_MAX_VERTEX_SHADER_CONSTANTF 256
+
 
 /* ------------------------ */
 /* IDirect3DPixelShaderImpl */
index 985557c..206697d 100644 (file)
@@ -359,6 +359,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetDeviceCaps(LPDIRECT3DDEVICE8 iface
     if(pCaps->VertexShaderVersion > D3DVS_VERSION(1,1)){
         pCaps->VertexShaderVersion = D3DVS_VERSION(1,1);
     }
+    pCaps->MaxVertexShaderConst = min(D3D8_MAX_VERTEX_SHADER_CONSTANTF, pCaps->MaxVertexShaderConst);
 
     TRACE("Returning %p %p\n", This, pCaps);
     return hrc;
@@ -620,7 +621,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateTexture(LPDIRECT3DDEVICE8 iface
     object->ref = 1;
     EnterCriticalSection(&d3d8_cs);
     hrc = IWineD3DDevice_CreateTexture(This->WineD3DDevice, Width, Height, Levels, Usage & WINED3DUSAGE_MASK,
-            wined3dformat_from_d3dformat(Format), Pool, &object->wineD3DTexture, NULL, (IUnknown *)object);
+            wined3dformat_from_d3dformat(Format), Pool, &object->wineD3DTexture, (IUnknown *)object);
     LeaveCriticalSection(&d3d8_cs);
 
     if (FAILED(hrc)) {
@@ -660,8 +661,8 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateVolumeTexture(LPDIRECT3DDEVICE8
     object->ref = 1;
     EnterCriticalSection(&d3d8_cs);
     hrc = IWineD3DDevice_CreateVolumeTexture(This->WineD3DDevice, Width, Height, Depth, Levels,
-            Usage & WINED3DUSAGE_MASK, wined3dformat_from_d3dformat(Format), Pool,
-            &object->wineD3DVolumeTexture, NULL, (IUnknown *)object);
+            Usage & WINED3DUSAGE_MASK, wined3dformat_from_d3dformat(Format),
+            Pool, &object->wineD3DVolumeTexture, (IUnknown *)object);
     LeaveCriticalSection(&d3d8_cs);
 
     if (hrc != D3D_OK) {
@@ -701,7 +702,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateCubeTexture(LPDIRECT3DDEVICE8 i
     object->ref = 1;
     EnterCriticalSection(&d3d8_cs);
     hr = IWineD3DDevice_CreateCubeTexture(This->WineD3DDevice, EdgeLength, Levels, Usage & WINED3DUSAGE_MASK,
-            wined3dformat_from_d3dformat(Format), Pool, &object->wineD3DCubeTexture, NULL, (IUnknown *)object);
+            wined3dformat_from_d3dformat(Format), Pool, &object->wineD3DCubeTexture, (IUnknown *)object);
     LeaveCriticalSection(&d3d8_cs);
 
     if (hr != D3D_OK){
@@ -738,8 +739,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexBuffer(LPDIRECT3DDEVICE8
     object->ref = 1;
     EnterCriticalSection(&d3d8_cs);
     hrc = IWineD3DDevice_CreateVertexBuffer(This->WineD3DDevice, Size, Usage & WINED3DUSAGE_MASK,
-            0 /* fvf for ddraw only */, (WINED3DPOOL) Pool, &(object->wineD3DVertexBuffer), NULL,
-            (IUnknown *)object);
+            0 /* fvf for ddraw only */, (WINED3DPOOL)Pool, &object->wineD3DVertexBuffer, (IUnknown *)object);
     LeaveCriticalSection(&d3d8_cs);
     object->fvf = FVF;
 
@@ -777,8 +777,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateIndexBuffer(LPDIRECT3DDEVICE8 i
     TRACE("Calling wined3d create index buffer\n");
     EnterCriticalSection(&d3d8_cs);
     hrc = IWineD3DDevice_CreateIndexBuffer(This->WineD3DDevice, Length, Usage & WINED3DUSAGE_MASK,
-            (WINED3DPOOL) Pool, &object->wineD3DIndexBuffer,
-            NULL, (IUnknown *)object);
+            (WINED3DPOOL)Pool, &object->wineD3DIndexBuffer, (IUnknown *)object);
     LeaveCriticalSection(&d3d8_cs);
 
     if (D3D_OK != hrc) {
@@ -827,7 +826,7 @@ static HRESULT IDirect3DDevice8Impl_CreateSurface(LPDIRECT3DDEVICE8 iface, UINT
     EnterCriticalSection(&d3d8_cs);
     hrc = IWineD3DDevice_CreateSurface(This->WineD3DDevice, Width, Height, wined3dformat_from_d3dformat(Format),
             Lockable, Discard, Level,  &object->wineD3DSurface, Type, Usage & WINED3DUSAGE_MASK,
-            (WINED3DPOOL)Pool, MultiSample,MultisampleQuality, NULL, SURFACE_OPENGL, (IUnknown *)object);
+            (WINED3DPOOL)Pool, MultiSample, MultisampleQuality, SURFACE_OPENGL, (IUnknown *)object);
     LeaveCriticalSection(&d3d8_cs);
     if (hrc != D3D_OK || NULL == object->wineD3DSurface) {
        /* free up object */
@@ -2000,6 +1999,12 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEV
     HRESULT hr;
     TRACE("(%p) : Relay\n", This);
 
+    if(Register + ConstantCount > D3D8_MAX_VERTEX_SHADER_CONSTANTF) {
+        WARN("Trying to access %u constants, but d3d8 only supports %u\n",
+             Register + ConstantCount, D3D8_MAX_VERTEX_SHADER_CONSTANTF);
+        return D3DERR_INVALIDCALL;
+    }
+
     EnterCriticalSection(&d3d8_cs);
     hr = IWineD3DDevice_SetVertexShaderConstantF(This->WineD3DDevice, Register, pConstantData, ConstantCount);
     LeaveCriticalSection(&d3d8_cs);
@@ -2011,6 +2016,12 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEV
     HRESULT hr;
     TRACE("(%p) : Relay\n", This);
 
+    if(Register + ConstantCount > D3D8_MAX_VERTEX_SHADER_CONSTANTF) {
+        WARN("Trying to access %u constants, but d3d8 only supports %u\n",
+             Register + ConstantCount, D3D8_MAX_VERTEX_SHADER_CONSTANTF);
+        return D3DERR_INVALIDCALL;
+    }
+
     EnterCriticalSection(&d3d8_cs);
     hr = IWineD3DDevice_GetVertexShaderConstantF(This->WineD3DDevice, Register, pConstantData, ConstantCount);
     LeaveCriticalSection(&d3d8_cs);
@@ -2155,7 +2166,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 i
 
     EnterCriticalSection(&d3d8_cs);
     hr = IWineD3DDevice_CreatePixelShader(This->WineD3DDevice, pFunction,
-            &object->wineD3DPixelShader, (IUnknown *)object);
+            NULL, &object->wineD3DPixelShader, (IUnknown *)object);
     if (FAILED(hr))
     {
         LeaveCriticalSection(&d3d8_cs);
@@ -2651,7 +2662,7 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateVolume(IWineD3DDeviceParent
     object->lpVtbl = &Direct3DVolume8_Vtbl;
     object->ref = 1;
     hr = IWineD3DDevice_CreateVolume(This->WineD3DDevice, width, height, depth, usage,
-            format, pool, &object->wineD3DVolume, NULL, (IUnknown *)object);
+            format, pool, &object->wineD3DVolume, (IUnknown *)object);
     if (FAILED(hr))
     {
         ERR("(%p) CreateVolume failed, returning %#x\n", iface, hr);
index 64fc360..d39d3d6 100644 (file)
@@ -265,6 +265,7 @@ static HRESULT  WINAPI  IDirect3D8Impl_GetDeviceCaps(LPDIRECT3D8 iface, UINT Ada
     if(pCaps->VertexShaderVersion > D3DVS_VERSION(1,1)){
         pCaps->VertexShaderVersion = D3DVS_VERSION(1,1);
     }
+    pCaps->MaxVertexShaderConst = min(D3D8_MAX_VERTEX_SHADER_CONSTANTF, pCaps->MaxVertexShaderConst);
 
     TRACE("(%p) returning %p\n", This, pCaps);
     return hrc;
index c4b4860..bbd171e 100644 (file)
@@ -365,8 +365,7 @@ HRESULT  WINAPI  IDirect3DDevice9Impl_CreateCubeTexture(LPDIRECT3DDEVICE9EX ifac
     object->ref = 1;
     EnterCriticalSection(&d3d9_cs);
     hr = IWineD3DDevice_CreateCubeTexture(This->WineD3DDevice, EdgeLength, Levels, Usage,
-            wined3dformat_from_d3dformat(Format), Pool, &object->wineD3DCubeTexture,
-            pSharedHandle, (IUnknown*)object);
+            wined3dformat_from_d3dformat(Format), Pool, &object->wineD3DCubeTexture, (IUnknown *)object);
     LeaveCriticalSection(&d3d9_cs);
 
     if (hr != D3D_OK){
index 25b6ae2..7e43974 100644 (file)
@@ -497,6 +497,8 @@ typedef struct IDirect3DVertexShader9Impl {
   LPDIRECT3DDEVICE9EX parentDevice;
 } IDirect3DVertexShader9Impl;
 
+#define D3D9_MAX_VERTEX_SHADER_CONSTANTF 256
+
 /* --------------------- */
 /* IDirect3DPixelShader9 */
 /* --------------------- */
index 8d88e52..e5ca4c4 100644 (file)
@@ -678,8 +678,8 @@ static HRESULT IDirect3DDevice9Impl_CreateSurface(LPDIRECT3DDEVICE9EX iface, UIN
 
     EnterCriticalSection(&d3d9_cs);
     hrc = IWineD3DDevice_CreateSurface(This->WineD3DDevice, Width, Height, wined3dformat_from_d3dformat(Format),
-            Lockable, Discard, Level, &object->wineD3DSurface, Type, Usage & WINED3DUSAGE_MASK, (WINED3DPOOL)Pool,
-            MultiSample, MultisampleQuality, pSharedHandle, SURFACE_OPENGL, (IUnknown *)object);
+            Lockable, Discard, Level, &object->wineD3DSurface, Type, Usage & WINED3DUSAGE_MASK,
+            (WINED3DPOOL)Pool, MultiSample, MultisampleQuality, SURFACE_OPENGL, (IUnknown *)object);
     LeaveCriticalSection(&d3d9_cs);
 
     if (hrc != D3D_OK || NULL == object->wineD3DSurface) {
@@ -2099,7 +2099,7 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateVolume(IWineD3DDeviceParent
     object->lpVtbl = &Direct3DVolume9_Vtbl;
     object->ref = 1;
     hr = IWineD3DDevice_CreateVolume(This->WineD3DDevice, width, height, depth, usage & WINED3DUSAGE_MASK,
-            format, pool, &object->wineD3DVolume, NULL, (IUnknown *)object);
+            format, pool, &object->wineD3DVolume, (IUnknown *)object);
     if (FAILED(hr))
     {
         ERR("(%p) CreateVolume failed, returning %#x\n", iface, hr);
index 229368a..e9547a7 100644 (file)
@@ -311,6 +311,8 @@ void filter_caps(D3DCAPS9* pCaps)
         D3DPTEXTURECAPS_PROJECTED      | D3DPTEXTURECAPS_CUBEMAP       | D3DPTEXTURECAPS_VOLUMEMAP       |
         D3DPTEXTURECAPS_MIPMAP         | D3DPTEXTURECAPS_MIPVOLUMEMAP  | D3DPTEXTURECAPS_MIPCUBEMAP      |
         D3DPTEXTURECAPS_CUBEMAP_POW2   | D3DPTEXTURECAPS_VOLUMEMAP_POW2| D3DPTEXTURECAPS_NOPROJECTEDBUMPENV;
+
+    pCaps->MaxVertexShaderConst = min(D3D9_MAX_VERTEX_SHADER_CONSTANTF, pCaps->MaxVertexShaderConst);
 }
 
 static HRESULT WINAPI IDirect3D9Impl_GetDeviceCaps(LPDIRECT3D9EX iface, UINT Adapter, D3DDEVTYPE DeviceType, D3DCAPS9* pCaps) {
index 161ff64..8802bd1 100644 (file)
@@ -245,8 +245,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_CreateIndexBuffer(LPDIRECT3DDEVICE9EX iface,
     TRACE("Calling wined3d create index buffer\n");
     EnterCriticalSection(&d3d9_cs);
     hrc = IWineD3DDevice_CreateIndexBuffer(This->WineD3DDevice, Length, Usage & WINED3DUSAGE_MASK,
-            (WINED3DPOOL)Pool, &object->wineD3DIndexBuffer,
-            pSharedHandle, (IUnknown *)object);
+            (WINED3DPOOL)Pool, &object->wineD3DIndexBuffer, (IUnknown *)object);
     LeaveCriticalSection(&d3d9_cs);
     if (hrc != D3D_OK) {
 
index 9c528d9..3939f59 100644 (file)
@@ -128,7 +128,8 @@ HRESULT WINAPI IDirect3DDevice9Impl_CreatePixelShader(LPDIRECT3DDEVICE9EX iface,
     object->ref    = 1;
     object->lpVtbl = &Direct3DPixelShader9_Vtbl;
     EnterCriticalSection(&d3d9_cs);
-    hrc = IWineD3DDevice_CreatePixelShader(This->WineD3DDevice, pFunction, &object->wineD3DPixelShader , (IUnknown *)object);
+    hrc = IWineD3DDevice_CreatePixelShader(This->WineD3DDevice, pFunction, NULL,
+            &object->wineD3DPixelShader, (IUnknown *)object);
     LeaveCriticalSection(&d3d9_cs);
     if (hrc != D3D_OK) {
 
index e128350..f0a9c38 100644 (file)
@@ -358,7 +358,7 @@ HRESULT  WINAPI  IDirect3DDevice9Impl_CreateTexture(LPDIRECT3DDEVICE9EX iface, U
     object->ref = 1;
     EnterCriticalSection(&d3d9_cs);
     hrc = IWineD3DDevice_CreateTexture(This->WineD3DDevice, Width, Height, Levels, Usage & WINED3DUSAGE_MASK,
-            wined3dformat_from_d3dformat(Format), Pool, &object->wineD3DTexture, pSharedHandle, (IUnknown *)object);
+            wined3dformat_from_d3dformat(Format), Pool, &object->wineD3DTexture, (IUnknown *)object);
     LeaveCriticalSection(&d3d9_cs);
     if (FAILED(hrc)) {
 
index 8c65a88..501db41 100644 (file)
@@ -248,8 +248,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_CreateVertexBuffer(LPDIRECT3DDEVICE9EX iface
     object->fvf = FVF;
     EnterCriticalSection(&d3d9_cs);
     hrc = IWineD3DDevice_CreateVertexBuffer(This->WineD3DDevice, Size, Usage & WINED3DUSAGE_MASK,
-            0 /* fvf for ddraw only */, (WINED3DPOOL) Pool, &(object->wineD3DVertexBuffer),
-            pSharedHandle, (IUnknown *)object);
+            0 /* fvf for ddraw only */, (WINED3DPOOL) Pool, &(object->wineD3DVertexBuffer), (IUnknown *)object);
     LeaveCriticalSection(&d3d9_cs);
     
     if (hrc != D3D_OK) {
index 6478b68..fd2837d 100644 (file)
@@ -192,6 +192,12 @@ HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShaderConstantF(LPDIRECT3DDEVICE9EX
     HRESULT hr;
     TRACE("(%p) : Relay\n", This);
 
+    if(Register + Vector4fCount > D3D9_MAX_VERTEX_SHADER_CONSTANTF) {
+        WARN("Trying to access %u constants, but d3d9 only supports %u\n",
+             Register + Vector4fCount, D3D9_MAX_VERTEX_SHADER_CONSTANTF);
+        return D3DERR_INVALIDCALL;
+    }
+
     EnterCriticalSection(&d3d9_cs);
     hr = IWineD3DDevice_SetVertexShaderConstantF(This->WineD3DDevice, Register, pConstantData, Vector4fCount);
     LeaveCriticalSection(&d3d9_cs);
@@ -202,6 +208,12 @@ HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShaderConstantF(LPDIRECT3DDEVICE9EX
     IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface;
     HRESULT hr;
 
+    if(Register + Vector4fCount > D3D9_MAX_VERTEX_SHADER_CONSTANTF) {
+        WARN("Trying to access %u constants, but d3d9 only supports %u\n",
+             Register + Vector4fCount, D3D9_MAX_VERTEX_SHADER_CONSTANTF);
+        return D3DERR_INVALIDCALL;
+    }
+
     TRACE("(%p) : Relay\n", This);
     EnterCriticalSection(&d3d9_cs);
     hr = IWineD3DDevice_GetVertexShaderConstantF(This->WineD3DDevice, Register, pConstantData, Vector4fCount);
index 81327cd..07b686f 100644 (file)
@@ -431,8 +431,8 @@ HRESULT  WINAPI  IDirect3DDevice9Impl_CreateVolumeTexture(LPDIRECT3DDEVICE9EX if
     EnterCriticalSection(&d3d9_cs);
 
     hrc = IWineD3DDevice_CreateVolumeTexture(This->WineD3DDevice, Width, Height, Depth, Levels,
-            Usage & WINED3DUSAGE_MASK, wined3dformat_from_d3dformat(Format), Pool,
-            &object->wineD3DVolumeTexture, pSharedHandle, (IUnknown *)object);
+            Usage & WINED3DUSAGE_MASK, wined3dformat_from_d3dformat(Format),
+            Pool, &object->wineD3DVolumeTexture, (IUnknown *)object);
 
     LeaveCriticalSection(&d3d9_cs);
 
diff --git a/reactos/dll/directx/wine/ddraw/ddcomimpl.h b/reactos/dll/directx/wine/ddraw/ddcomimpl.h
deleted file mode 100644 (file)
index 553d29f..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/* A few helpful macros for implementing COM objects.
- *
- * Copyright 2000 TransGaming Technologies Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#ifndef _DDCOMIMPL_H_
-#define _DDCOMIMPL_H_
-
-#include <stddef.h>
-
-/* Generates the name for a vtable pointer for a given interface. */
-/* The canonical name for a single interface is "lpVtbl". */
-#define ICOM_VFIELD_MULTI_NAME2(iface) ITF_##iface
-#define ICOM_VFIELD_MULTI_NAME(iface) ICOM_VFIELD_MULTI_NAME2(iface)
-
-/* Declares a vtable pointer field in an implementation. */
-#define ICOM_VFIELD_MULTI(iface) \
-       iface ICOM_VFIELD_MULTI_NAME(iface)
-
-/* Returns the offset of a vtable pointer within an implementation object. */
-#define ICOM_VFIELD_OFFSET(impltype, iface) \
-       offsetof(impltype, ICOM_VFIELD_MULTI_NAME(iface))
-
-/* Given an interface pointer, returns the implementation pointer. */
-#define ICOM_OBJECT(impltype, ifacename, ifaceptr)             \
-       (impltype*)((ifaceptr) == NULL ? NULL                   \
-                 : (char*)(ifaceptr) - ICOM_VFIELD_OFFSET(impltype,ifacename))
-
-#define ICOM_THIS_FROM(impltype, ifacename, ifaceptr) \
-       impltype* This = ICOM_OBJECT(impltype, ifacename, ifaceptr)
-
-/* Given an object and interface name, returns a pointer to that interface. */
-#define ICOM_INTERFACE(implobj, iface) \
-       (implobj == NULL ? NULL :&((implobj)->ICOM_VFIELD_MULTI_NAME(iface)))
-
-#define ICOM_INIT_INTERFACE(implobj, ifacename, vtblname) \
-       do { \
-         (implobj)->ICOM_VFIELD_MULTI_NAME(ifacename).lpVtbl = &(vtblname); \
-       } while (0)
-
-#define COM_INTERFACE_CAST(impltype, ifnamefrom, ifnameto, ifaceptr)   \
-       ICOM_INTERFACE(ICOM_OBJECT(impltype, ifnamefrom, ifaceptr), ifnameto)
-
-#endif /* _DDCOMIMPL_H_ */
index 5e2717e..7011afa 100644 (file)
@@ -1727,20 +1727,9 @@ IDirectDrawImpl_RecreateSurfacesCallback(IDirectDrawSurface7 *surf,
     }
 
     /* Create the new surface */
-    hr = IWineD3DDevice_CreateSurface(This->wineD3DDevice,
-                                      Width, Height, Format,
-                                      TRUE /* Lockable */,
-                                      FALSE /* Discard */,
-                                      surfImpl->mipmap_level,
-                                      &surfImpl->WineD3DSurface,
-                                      Type,
-                                      Usage,
-                                      Pool,
-                                      MultiSampleType,
-                                      MultiSampleQuality,
-                                      0 /* SharedHandle */,
-                                      This->ImplType,
-                                      Parent);
+    hr = IWineD3DDevice_CreateSurface(This->wineD3DDevice, Width, Height, Format,
+            TRUE /* Lockable */, FALSE /* Discard */, surfImpl->mipmap_level, &surfImpl->WineD3DSurface,
+            Type, Usage, Pool, MultiSampleType, MultiSampleQuality, This->ImplType, Parent);
 
     if(hr != D3D_OK)
         return hr;
@@ -2036,21 +2025,9 @@ IDirectDrawImpl_CreateNewSurface(IDirectDrawImpl *This,
     }
 
     /* Now create the WineD3D Surface */
-    hr = IWineD3DDevice_CreateSurface(This->wineD3DDevice,
-                                      pDDSD->dwWidth,
-                                      pDDSD->dwHeight,
-                                      Format,
-                                      TRUE /* Lockable */,
-                                      FALSE /* Discard */,
-                                      level,
-                                      &(*ppSurf)->WineD3DSurface,
-                                      ResType, Usage,
-                                      Pool,
-                                      WINED3DMULTISAMPLE_NONE,
-                                      0 /* MultiSampleQuality */,
-                                      0 /* SharedHandle */,
-                                      ImplType,
-                                      Parent);
+    hr = IWineD3DDevice_CreateSurface(This->wineD3DDevice, pDDSD->dwWidth, pDDSD->dwHeight, Format,
+            TRUE /* Lockable */, FALSE /* Discard */, level, &(*ppSurf)->WineD3DSurface, ResType, Usage,
+            Pool, WINED3DMULTISAMPLE_NONE, 0 /* MultiSampleQuality */, ImplType, Parent);
 
     if(hr != D3D_OK)
     {
@@ -2725,15 +2702,13 @@ IDirectDrawImpl_CreateSurface(IDirectDraw7 *iface,
          */
         if(desc2.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
         {
-            hr = IWineD3DDevice_CreateCubeTexture(This->wineD3DDevice, DDSD->dwWidth /* Edgelength */,
-                    levels, 0 /* usage */, Format, Pool, (IWineD3DCubeTexture **)&object->wineD3DTexture,
-                    0 /* SharedHandle */, (IUnknown *)object);
+            hr = IWineD3DDevice_CreateCubeTexture(This->wineD3DDevice, DDSD->dwWidth /* Edgelength */, levels,
+                    0 /* usage */, Format, Pool, (IWineD3DCubeTexture **)&object->wineD3DTexture, (IUnknown *)object);
         }
         else
         {
             hr = IWineD3DDevice_CreateTexture(This->wineD3DDevice, DDSD->dwWidth, DDSD->dwHeight, levels,
-                    0 /* usage */, Format, Pool, (IWineD3DTexture **) &object->wineD3DTexture,
-                    0 /* SharedHandle */, (IUnknown *)object);
+                    0 /* usage */, Format, Pool, (IWineD3DTexture **)&object->wineD3DTexture, (IUnknown *)object);
         }
         This->tex_root = NULL;
     }
index 7c8e222..3b7778f 100644 (file)
@@ -4356,8 +4356,6 @@ Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
  * The return value consist of a combination of D3DCLIP_* flags, or it's
  * 0 if the sphere is completely visible(according to the SDK, not checked)
  *
- * Sounds like an overdose of math ;)
- *
  * Version 3 and 7
  *
  * Params:
@@ -4368,7 +4366,7 @@ Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
  *  ReturnValues: Array to write the results to
  *
  * Returns:
- *  D3D_OK because it's a stub
+ *  D3D_OK
  *  (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
  *  (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
  *  is singular)
index aeba55b..9ce0d36 100644 (file)
@@ -824,8 +824,7 @@ IDirect3DImpl_7_CreateDevice(IDirect3D7 *iface,
      * takes the pointer and avoids the memcpy
      */
     hr = IWineD3DDevice_CreateIndexBuffer(This->wineD3DDevice, 0x40000 /* Length. Don't know how long it should be */,
-            WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT,
-            &object->indexbuffer, 0 /* Handle */, (IUnknown *)IndexBufferParent);
+            WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, &object->indexbuffer, (IUnknown *)IndexBufferParent);
 
     if(FAILED(hr))
     {
@@ -1021,13 +1020,10 @@ IDirect3DImpl_7_CreateVertexBuffer(IDirect3D7 *iface,
 
     EnterCriticalSection(&ddraw_cs);
     hr = IWineD3DDevice_CreateVertexBuffer(This->wineD3DDevice,
-                                           get_flexible_vertex_size(Desc->dwFVF) * Desc->dwNumVertices,
-                                           Desc->dwCaps & D3DVBCAPS_WRITEONLY ? WINED3DUSAGE_WRITEONLY : 0,
-                                           Desc->dwFVF,
-                                           Desc->dwCaps & D3DVBCAPS_SYSTEMMEMORY ? WINED3DPOOL_SYSTEMMEM : WINED3DPOOL_DEFAULT,
-                                           &object->wineD3DVertexBuffer,
-                                           0 /* SharedHandle */,
-                                           (IUnknown *)object);
+            get_flexible_vertex_size(Desc->dwFVF) * Desc->dwNumVertices,
+            Desc->dwCaps & D3DVBCAPS_WRITEONLY ? WINED3DUSAGE_WRITEONLY : 0, Desc->dwFVF,
+            Desc->dwCaps & D3DVBCAPS_SYSTEMMEMORY ? WINED3DPOOL_SYSTEMMEM : WINED3DPOOL_DEFAULT,
+            &object->wineD3DVertexBuffer, (IUnknown *)object);
     if(hr != D3D_OK)
     {
         ERR("(%p) IWineD3DDevice::CreateVertexBuffer failed with hr=%08x\n", This, hr);
index 30d5e18..c6e346e 100644 (file)
@@ -751,6 +751,7 @@ IDirect3DViewportImpl_AddLight(IDirect3DViewport3 *iface,
     /* Add the light in the 'linked' chain */
     lpDirect3DLightImpl->next = This->lights;
     This->lights = lpDirect3DLightImpl;
+    IDirect3DLight_AddRef(lpDirect3DLight);
 
     /* Attach the light to the viewport */
     lpDirect3DLightImpl->active_viewport = This;
@@ -796,6 +797,7 @@ IDirect3DViewportImpl_DeleteLight(IDirect3DViewport3 *iface,
            else prev_light->next = cur_light->next;
            /* Detach the light to the viewport */
            cur_light->active_viewport = NULL;
+           IDirect3DLight_Release( (IDirect3DLight *)cur_light );
            This->num_lights--;
            This->map_lights &= ~(1<<lpDirect3DLightImpl->dwLightIndex);
             LeaveCriticalSection(&ddraw_cs);
@@ -871,6 +873,9 @@ IDirect3DViewportImpl_NextLight(IDirect3DViewport3 *iface,
             break;
     }
 
+    if (*lplpDirect3DLight)
+        IDirect3DLight_AddRef(*lplpDirect3DLight);
+
     LeaveCriticalSection(&ddraw_cs);
 
     return *lplpDirect3DLight ? D3D_OK : DDERR_INVALIDPARAMS;
index b5b5ad4..56ee162 100644 (file)
@@ -10,6 +10,7 @@
  * Copyright 2006 Jason Green
  * Copyright 2006 Henri Verbeet
  * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
+ * Copyright 2009 Henri Verbeet for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -80,7 +81,6 @@ struct shader_arb_priv {
 static unsigned int shader_arb_load_constantsF(IWineD3DBaseShaderImpl* This, const WineD3D_GL_Info *gl_info,
         GLuint target_type, unsigned int max_constants, const float *constants, char *dirty_consts)
 {
-    DWORD shader_version = This->baseShader.reg_maps.shader_version;
     local_constant* lconst;
     DWORD i, j;
     unsigned int ret;
@@ -94,7 +94,7 @@ static unsigned int shader_arb_load_constantsF(IWineD3DBaseShaderImpl* This, con
         }
     }
     /* In 1.X pixel shaders constants are implicitly clamped in the range [-1;1] */
-    if (target_type == GL_FRAGMENT_PROGRAM_ARB && WINED3DSHADER_VERSION_MAJOR(shader_version) == 1)
+    if (target_type == GL_FRAGMENT_PROGRAM_ARB && This->baseShader.reg_maps.shader_version.major == 1)
     {
         float lcl_const[4];
         for(i = 0; i < max_constants; i++) {
@@ -269,14 +269,34 @@ static void shader_arb_update_float_pixel_constants(IWineD3DDevice *iface, UINT
     This->highest_dirty_ps_const = max(This->highest_dirty_ps_const, start + count + 1);
 }
 
+static DWORD *local_const_mapping(IWineD3DBaseShaderImpl *This)
+{
+    DWORD *ret;
+    DWORD idx = 0;
+    const local_constant *lconst;
+
+    if(This->baseShader.load_local_constsF || list_empty(&This->baseShader.constantsF)) return NULL;
+
+    ret = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD) * This->baseShader.limits.temporary);
+    if(!ret) {
+        ERR("Out of memory\n");
+        return NULL;
+    }
+
+    LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) {
+        ret[lconst->idx] = idx++;
+    }
+    return ret;
+}
+
 /* Generate the variable & register declarations for the ARB_vertex_program output target */
 static void shader_generate_arb_declarations(IWineD3DBaseShader *iface, const shader_reg_maps *reg_maps,
-        SHADER_BUFFER *buffer, const WineD3D_GL_Info *gl_info)
+        SHADER_BUFFER *buffer, const WineD3D_GL_Info *gl_info, DWORD *lconst_map)
 {
     IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface;
     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device;
     DWORD i, cur;
-    char pshader = shader_is_pshader_version(reg_maps->shader_version);
+    char pshader = shader_is_pshader_version(reg_maps->shader_version.type);
     unsigned max_constantsF = min(This->baseShader.limits.constant_float, 
             (pshader ? GL_LIMITS(pshader_constantsF) - ARB_SHADER_RESERVED_PS_CONSTS :
                        GL_LIMITS(vshader_constantsF) - ARB_SHADER_RESERVED_VS_CONSTS));
@@ -343,25 +363,19 @@ static void shader_generate_arb_declarations(IWineD3DBaseShader *iface, const sh
     }
 
     if(device->stateBlock->renderState[WINED3DRS_SRGBWRITEENABLE] && pshader) {
-        shader_addline(buffer, "PARAM srgb_mul_low = {%f, %f, %f, 1.0};\n",
-                        srgb_mul_low, srgb_mul_low, srgb_mul_low);
-        shader_addline(buffer, "PARAM srgb_comparison =  {%f, %f, %f, %f};\n",
-                        srgb_cmp, srgb_cmp, srgb_cmp, srgb_cmp);
-        shader_addline(buffer, "PARAM srgb_pow =  {%f, %f, %f, 1.0};\n",
-                       srgb_pow, srgb_pow, srgb_pow);
-        shader_addline(buffer, "PARAM srgb_mul_hi =  {%f, %f, %f, 1.0};\n",
-                       srgb_mul_high, srgb_mul_high, srgb_mul_high);
-        shader_addline(buffer, "PARAM srgb_sub_hi =  {%f, %f, %f, 0.0};\n",
-                       srgb_sub_high, srgb_sub_high, srgb_sub_high);
+        shader_addline(buffer, "PARAM srgb_consts1 = {%f, %f, %f, %f};\n",
+                       srgb_mul_low, srgb_cmp, srgb_pow, srgb_mul_high);
+        shader_addline(buffer, "PARAM srgb_consts2 = {%f, %f, %f, %f};\n",
+                       srgb_sub_high, 0.0, 0.0, 0.0);
     }
 
     /* Load local constants using the program-local space,
      * this avoids reloading them each time the shader is used
      */
-    if(!This->baseShader.load_local_constsF) {
+    if(lconst_map) {
         LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) {
             shader_addline(buffer, "PARAM C%u = program.local[%u];\n", lconst->idx,
-                           lconst->idx);
+                           lconst_map[lconst->idx]);
         }
     }
 
@@ -371,13 +385,16 @@ static void shader_generate_arb_declarations(IWineD3DBaseShader *iface, const sh
      * local constants do not declare the loaded constants as an array because ARB compilers usually
      * do not optimize unused constants away
      */
-    if(This->baseShader.load_local_constsF || list_empty(&This->baseShader.constantsF)) {
+    if(This->baseShader.reg_maps.usesrelconstF) {
         /* Need to PARAM the environment parameters (constants) so we can use relative addressing */
         shader_addline(buffer, "PARAM C[%d] = { program.env[0..%d] };\n",
                     max_constantsF, max_constantsF - 1);
     } else {
         for(i = 0; i < max_constantsF; i++) {
-            if(!shader_constant_is_local(This, i)) {
+            DWORD idx, mask;
+            idx = i >> 5;
+            mask = 1 << (i & 0x1f);
+            if(!shader_constant_is_local(This, i) && (This->baseShader.reg_maps.constf[idx] & mask)) {
                 shader_addline(buffer, "PARAM C%d = program.env[%d];\n",i, i);
             }
         }
@@ -407,9 +424,9 @@ static void shader_arb_get_write_mask(const struct wined3d_shader_instruction *i
         const struct wined3d_shader_dst_param *dst, char *write_mask)
 {
     char *ptr = write_mask;
-    char vshader = shader_is_vshader_version(ins->reg_maps->shader_version);
+    char vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type);
 
-    if (vshader && dst->register_type == WINED3DSPR_ADDR)
+    if (vshader && dst->reg.type == WINED3DSPR_ADDR)
     {
         *ptr++ = '.';
         *ptr++ = 'x';
@@ -426,7 +443,8 @@ static void shader_arb_get_write_mask(const struct wined3d_shader_instruction *i
     *ptr = '\0';
 }
 
-static void shader_arb_get_swizzle(const DWORD param, BOOL fixup, char *swizzle_str) {
+static void shader_arb_get_swizzle(const struct wined3d_shader_src_param *param, BOOL fixup, char *swizzle_str)
+{
     /* For registers of type WINED3DDECLTYPE_D3DCOLOR, data is stored as "bgra",
      * but addressed as "rgba". To fix this we need to swap the register's x
      * and z components. */
@@ -434,7 +452,7 @@ static void shader_arb_get_swizzle(const DWORD param, BOOL fixup, char *swizzle_
     char *ptr = swizzle_str;
 
     /* swizzle bits fields: wwzzyyxx */
-    DWORD swizzle = (param & WINED3DSP_SWIZZLE_MASK) >> WINED3DSP_SWIZZLE_SHIFT;
+    DWORD swizzle = param->swizzle;
     DWORD swizzle_x = swizzle & 0x03;
     DWORD swizzle_y = (swizzle >> 2) & 0x03;
     DWORD swizzle_z = (swizzle >> 4) & 0x03;
@@ -442,7 +460,8 @@ static void shader_arb_get_swizzle(const DWORD param, BOOL fixup, char *swizzle_
 
     /* If the swizzle is the default swizzle (ie, "xyzw"), we don't need to
      * generate a swizzle string. Unless we need to our own swizzling. */
-    if ((WINED3DSP_NOSWIZZLE >> WINED3DSP_SWIZZLE_SHIFT) != swizzle || fixup) {
+    if (swizzle != WINED3DSP_NOSWIZZLE || fixup)
+    {
         *ptr++ = '.';
         if (swizzle_x == swizzle_y && swizzle_x == swizzle_z && swizzle_x == swizzle_w) {
             *ptr++ = swizzle_chars[swizzle_x];
@@ -463,8 +482,7 @@ static void shader_arb_get_register_name(IWineD3DBaseShader *iface, WINED3DSHADE
     /* oPos, oFog and oPts in D3D */
     static const char * const rastout_reg_names[] = {"TMP_OUT", "result.fogcoord", "result.pointsize"};
     IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)iface;
-    DWORD shader_version = This->baseShader.reg_maps.shader_version;
-    BOOL pshader = shader_is_pshader_version(shader_version);
+    BOOL pshader = shader_is_pshader_version(This->baseShader.reg_maps.shader_version.type);
 
     *is_color = FALSE;
 
@@ -498,7 +516,7 @@ static void shader_arb_get_register_name(IWineD3DBaseShader *iface, WINED3DSHADE
             }
             else
             {
-                if (This->baseShader.load_local_constsF || list_empty(&This->baseShader.constantsF))
+                if (This->baseShader.reg_maps.usesrelconstF)
                     sprintf(register_name, "C[%u]", register_idx);
                 else
                     sprintf(register_name, "C%u", register_idx);
@@ -549,36 +567,16 @@ static void shader_arb_get_register_name(IWineD3DBaseShader *iface, WINED3DSHADE
     }
 }
 
-static void shader_arb_add_src_param(const struct wined3d_shader_instruction *ins,
-        DWORD param, char *str)
-{
-    char register_name[255];
-    char swizzle[6];
-    BOOL is_color;
-
-    if ((param & WINED3DSP_SRCMOD_MASK) == WINED3DSPSM_NEG) strcat(str, " -");
-    else strcat(str, " ");
-
-    shader_arb_get_register_name(ins->shader, shader_get_regtype(param), param & WINED3DSP_REGNUM_MASK,
-            param & WINED3DSHADER_ADDRMODE_RELATIVE, register_name, &is_color);
-    strcat(str, register_name);
-
-    shader_arb_get_swizzle(param, is_color, swizzle);
-    strcat(str, swizzle);
-}
-
-static void shader_arb_add_dst_param(const struct wined3d_shader_instruction *ins,
+static void shader_arb_get_dst_param(const struct wined3d_shader_instruction *ins,
         const struct wined3d_shader_dst_param *wined3d_dst, char *str)
 {
     char register_name[255];
     char write_mask[6];
     BOOL is_color;
 
-    strcat(str, " ");
-
-    shader_arb_get_register_name(ins->shader, wined3d_dst->register_type,
-            wined3d_dst->register_idx, wined3d_dst->has_rel_addr, register_name, &is_color);
-    strcat(str, register_name);
+    shader_arb_get_register_name(ins->ctx->shader, wined3d_dst->reg.type,
+            wined3d_dst->reg.idx, !!wined3d_dst->reg.rel_addr, register_name, &is_color);
+    strcpy(str, register_name);
 
     shader_arb_get_write_mask(ins, wined3d_dst, write_mask);
     strcat(str, write_mask);
@@ -655,10 +653,10 @@ static void gen_color_correction(SHADER_BUFFER *buffer, const char *reg, DWORD d
 static void shader_hw_sample(const struct wined3d_shader_instruction *ins, DWORD sampler_idx,
         const char *dst_str, const char *coord_reg, BOOL projected, BOOL bias)
 {
-    SHADER_BUFFER *buffer = ins->buffer;
-    DWORD sampler_type = ins->reg_maps->samplers[sampler_idx] & WINED3DSP_TEXTURETYPE_MASK;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
+    DWORD sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx];
     const char *tex_type;
-    IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)ins->shader;
+    IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)ins->ctx->shader;
     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device;
 
     switch(sampler_type) {
@@ -673,7 +671,8 @@ static void shader_hw_sample(const struct wined3d_shader_instruction *ins, DWORD
             } else {
                 tex_type = "2D";
             }
-            if(shader_is_pshader_version(ins->reg_maps->shader_version)) {
+            if (shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type))
+            {
                const IWineD3DPixelShaderImpl* const ps = (const IWineD3DPixelShaderImpl*)This;
                if(ps->cur_args->np2_fixup & (1 << sampler_idx)) {
                    FIXME("NP2 texcoord fixup is currently not implemented in ARB mode (use GLSL instead).\n");
@@ -705,36 +704,34 @@ static void shader_hw_sample(const struct wined3d_shader_instruction *ins, DWORD
         shader_addline(buffer, "TEX %s, %s, texture[%u], %s;\n", dst_str, coord_reg, sampler_idx, tex_type);
     }
 
-    if (shader_is_pshader_version(ins->reg_maps->shader_version))
+    if (shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type))
     {
-        IWineD3DPixelShaderImpl *ps = (IWineD3DPixelShaderImpl *)ins->shader;
+        IWineD3DPixelShaderImpl *ps = (IWineD3DPixelShaderImpl *)ins->ctx->shader;
         gen_color_correction(buffer, dst_str, ins->dst[0].write_mask,
                 "one", "coefmul.x", ps->cur_args->color_fixup[sampler_idx]);
     }
 }
 
-static void pshader_gen_input_modifier_line (
-    IWineD3DBaseShader *iface,
-    SHADER_BUFFER* buffer,
-    const DWORD instr,
-    int tmpreg,
-    char *outregstr) {
-
+static void shader_arb_get_src_param(const struct wined3d_shader_instruction *ins,
+        const struct wined3d_shader_src_param *src, unsigned int tmpreg, char *outregstr)
+{
     /* Generate a line that does the input modifier computation and return the input register to use */
     BOOL is_color = FALSE;
     char regstr[256];
     char swzstr[20];
     int insert_line;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
 
     /* Assume a new line will be added */
     insert_line = 1;
 
     /* Get register name */
-    shader_arb_get_register_name(iface, shader_get_regtype(instr), instr & WINED3DSP_REGNUM_MASK,
-            instr & WINED3DSHADER_ADDRMODE_RELATIVE, regstr, &is_color);
-    shader_arb_get_swizzle(instr, is_color, swzstr);
+    shader_arb_get_register_name(ins->ctx->shader, src->reg.type,
+            src->reg.idx, !!src->reg.rel_addr, regstr, &is_color);
+    shader_arb_get_swizzle(src, is_color, swzstr);
 
-    switch (instr & WINED3DSP_SRCMOD_MASK) {
+    switch (src->modifiers)
+    {
     case WINED3DSPSM_NONE:
         sprintf(outregstr, "%s%s", regstr, swzstr);
         insert_line = 0;
@@ -782,23 +779,15 @@ static void pshader_gen_input_modifier_line (
         sprintf(outregstr, "T%c%s", 'A' + tmpreg, swzstr);
 }
 
-static inline void pshader_gen_output_modifier_line(SHADER_BUFFER *buffer, int saturate, const char *write_mask,
-        int shift, const char *regstr)
-{
-    /* Generate a line that does the output modifier computation */
-    shader_addline(buffer, "MUL%s %s%s, %s, %s;\n", saturate ? "_SAT" : "",
-        regstr, write_mask, regstr, shift_tab[shift]);
-}
-
 static void pshader_hw_bem(const struct wined3d_shader_instruction *ins)
 {
-    IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->shader;
+    IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->ctx->shader;
     const struct wined3d_shader_dst_param *dst = &ins->dst[0];
-    SHADER_BUFFER *buffer = ins->buffer;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
     char dst_name[50];
     char src_name[2][50];
     char dst_wmask[20];
-    DWORD sampler_code = dst->register_idx;
+    DWORD sampler_code = dst->reg.idx;
     BOOL has_bumpmat = FALSE;
     BOOL is_color;
     int i;
@@ -812,13 +801,13 @@ static void pshader_hw_bem(const struct wined3d_shader_instruction *ins)
         }
     }
 
-    shader_arb_get_register_name(ins->shader, dst->register_type,
-            dst->register_idx, dst->has_rel_addr, dst_name, &is_color);
+    shader_arb_get_register_name(ins->ctx->shader, dst->reg.type,
+            dst->reg.idx, !!dst->reg.rel_addr, dst_name, &is_color);
     shader_arb_get_write_mask(ins, dst, dst_wmask);
     strcat(dst_name, dst_wmask);
 
-    pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[0], 0, src_name[0]);
-    pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[1], 1, src_name[1]);
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src_name[0]);
+    shader_arb_get_src_param(ins, &ins->src[1], 1, src_name[1]);
 
     if(has_bumpmat) {
         /* Sampling the perturbation map in Tsrc was done already, including the signedness correction if needed */
@@ -836,28 +825,29 @@ static void pshader_hw_bem(const struct wined3d_shader_instruction *ins)
 static void pshader_hw_cnd(const struct wined3d_shader_instruction *ins)
 {
     const struct wined3d_shader_dst_param *dst = &ins->dst[0];
-    SHADER_BUFFER *buffer = ins->buffer;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
     char dst_wmask[20];
     char dst_name[50];
     char src_name[3][50];
     BOOL sat = dst->modifiers & WINED3DSPDM_SATURATE;
-    DWORD shift = dst->shift;
     BOOL is_color;
+    DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major,
+            ins->ctx->reg_maps->shader_version.minor);
 
     /* FIXME: support output modifiers */
 
     /* Handle output register */
-    shader_arb_get_register_name(ins->shader, dst->register_type,
-            dst->register_idx, dst->has_rel_addr, dst_name, &is_color);
+    shader_arb_get_register_name(ins->ctx->shader, dst->reg.type,
+            dst->reg.idx, !!dst->reg.rel_addr, dst_name, &is_color);
     shader_arb_get_write_mask(ins, dst, dst_wmask);
 
     /* Generate input register names (with modifiers) */
-    pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[0], 0, src_name[0]);
-    pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[1], 1, src_name[1]);
-    pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[2], 2, src_name[2]);
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src_name[0]);
+    shader_arb_get_src_param(ins, &ins->src[1], 1, src_name[1]);
+    shader_arb_get_src_param(ins, &ins->src[2], 2, src_name[2]);
 
     /* The coissue flag changes the semantic of the cnd instruction in <= 1.3 shaders */
-    if (ins->reg_maps->shader_version <= WINED3DPS_VERSION(1, 3) && ins->coissue)
+    if (shader_version <= WINED3D_SHADER_VERSION(1, 3) && ins->coissue)
     {
         shader_addline(buffer, "MOV%s %s%s, %s;\n", sat ? "_SAT" : "", dst_name, dst_wmask, src_name[1]);
     } else {
@@ -865,38 +855,32 @@ static void pshader_hw_cnd(const struct wined3d_shader_instruction *ins)
         shader_addline(buffer, "CMP%s %s%s, TMP, %s, %s;\n",
                                 sat ? "_SAT" : "", dst_name, dst_wmask, src_name[1], src_name[2]);
     }
-    if (shift != 0)
-        pshader_gen_output_modifier_line(buffer, FALSE, dst_wmask, shift, dst_name);
 }
 
 static void pshader_hw_cmp(const struct wined3d_shader_instruction *ins)
 {
     const struct wined3d_shader_dst_param *dst = &ins->dst[0];
-    SHADER_BUFFER *buffer = ins->buffer;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
     char dst_wmask[20];
     char dst_name[50];
     char src_name[3][50];
-    DWORD shift = dst->shift;
     BOOL sat = dst->modifiers & WINED3DSPDM_SATURATE;
     BOOL is_color;
 
     /* FIXME: support output modifiers */
 
     /* Handle output register */
-    shader_arb_get_register_name(ins->shader, dst->register_type,
-            dst->register_idx, dst->has_rel_addr, dst_name, &is_color);
+    shader_arb_get_register_name(ins->ctx->shader, dst->reg.type,
+            dst->reg.idx, !!dst->reg.rel_addr, dst_name, &is_color);
     shader_arb_get_write_mask(ins, dst, dst_wmask);
 
     /* Generate input register names (with modifiers) */
-    pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[0], 0, src_name[0]);
-    pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[1], 1, src_name[1]);
-    pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[2], 2, src_name[2]);
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src_name[0]);
+    shader_arb_get_src_param(ins, &ins->src[1], 1, src_name[1]);
+    shader_arb_get_src_param(ins, &ins->src[2], 2, src_name[2]);
 
     shader_addline(buffer, "CMP%s %s%s, %s, %s, %s;\n", sat ? "_SAT" : "", dst_name, dst_wmask,
                    src_name[0], src_name[2], src_name[1]);
-
-    if (shift != 0)
-        pshader_gen_output_modifier_line(buffer, FALSE, dst_wmask, shift, dst_name);
 }
 
 /** Process the WINED3DSIO_DP2ADD instruction in ARB.
@@ -904,40 +888,37 @@ static void pshader_hw_cmp(const struct wined3d_shader_instruction *ins)
 static void pshader_hw_dp2add(const struct wined3d_shader_instruction *ins)
 {
     const struct wined3d_shader_dst_param *dst = &ins->dst[0];
-    SHADER_BUFFER *buffer = ins->buffer;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
     char dst_wmask[20];
     char dst_name[50];
     char src_name[3][50];
-    DWORD shift = dst->shift;
     BOOL sat = dst->modifiers & WINED3DSPDM_SATURATE;
     BOOL is_color;
 
-    shader_arb_get_register_name(ins->shader, dst->register_type,
-            dst->register_idx, dst->has_rel_addr, dst_name, &is_color);
+    shader_arb_get_register_name(ins->ctx->shader, dst->reg.type,
+            dst->reg.idx, !!dst->reg.rel_addr, dst_name, &is_color);
     shader_arb_get_write_mask(ins, dst, dst_wmask);
 
-    pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[0], 0, src_name[0]);
-    pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[1], 1, src_name[1]);
-    pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[2], 2, src_name[2]);
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src_name[0]);
+    shader_arb_get_src_param(ins, &ins->src[1], 1, src_name[1]);
+    shader_arb_get_src_param(ins, &ins->src[2], 2, src_name[2]);
 
     /* Emulate a DP2 with a DP3 and 0.0 */
     shader_addline(buffer, "MOV TMP, %s;\n", src_name[0]);
     shader_addline(buffer, "MOV TMP.z, 0.0;\n");
     shader_addline(buffer, "DP3 TMP2, TMP, %s;\n", src_name[1]);
     shader_addline(buffer, "ADD%s %s%s, TMP2, %s;\n", sat ? "_SAT" : "", dst_name, dst_wmask, src_name[2]);
-
-    if (shift != 0)
-        pshader_gen_output_modifier_line(buffer, FALSE, dst_wmask, shift, dst_name);
 }
 
 /* Map the opcode 1-to-1 to the GL code */
 static void shader_hw_map2gl(const struct wined3d_shader_instruction *ins)
 {
-    SHADER_BUFFER *buffer = ins->buffer;
-    const DWORD *src = ins->src;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
     const char *instruction;
-    char arguments[256];
+    char arguments[256], dst_str[50];
     unsigned int i;
+    const struct wined3d_shader_dst_param *dst = &ins->dst[0];
+    const char *modifier;
 
     switch (ins->handler_idx)
     {
@@ -959,7 +940,6 @@ static void shader_hw_map2gl(const struct wined3d_shader_instruction *ins)
         case WINED3DSIH_MIN: instruction = "MIN"; break;
         case WINED3DSIH_MOV: instruction = "MOV"; break;
         case WINED3DSIH_MUL: instruction = "MUL"; break;
-        case WINED3DSIH_NOP: instruction = "NOP"; break;
         case WINED3DSIH_POW: instruction = "POW"; break;
         case WINED3DSIH_SGE: instruction = "SGE"; break;
         case WINED3DSIH_SLT: instruction = "SLT"; break;
@@ -969,96 +949,39 @@ static void shader_hw_map2gl(const struct wined3d_shader_instruction *ins)
             break;
     }
 
-    if (shader_is_pshader_version(ins->reg_maps->shader_version))
-    {
-        /* Output token related */
-        const struct wined3d_shader_dst_param *dst;
-        char output_rname[256];
-        char output_wmask[20];
-        char operands[4][100];
-        BOOL saturate = FALSE;
-        BOOL centroid = FALSE;
-        BOOL partialprecision = FALSE;
-        const char *modifier;
-        BOOL is_color;
-        DWORD shift;
-
-        if (!(ins->dst_count + ins->src_count))
-        {
-            ERR("Opcode \"%#x\" has no parameters\n", ins->handler_idx);
-            return;
-        }
-        dst = &ins->dst[0];
-
-        /* Process modifiers */
-        if (dst->modifiers)
-        {
-            DWORD mask = dst->modifiers;
-
-            saturate = mask & WINED3DSPDM_SATURATE;
-            centroid = mask & WINED3DSPDM_MSAMPCENTROID;
-            partialprecision = mask & WINED3DSPDM_PARTIALPRECISION;
-            mask &= ~(WINED3DSPDM_MSAMPCENTROID | WINED3DSPDM_PARTIALPRECISION | WINED3DSPDM_SATURATE);
-            if (mask)
-                FIXME("Unrecognized modifier(%#x)\n", mask >> WINED3DSP_DSTMOD_SHIFT);
-
-            if (centroid)
-                FIXME("Unhandled modifier(%#x)\n", mask >> WINED3DSP_DSTMOD_SHIFT);
-        }
-        shift = dst->shift;
-        modifier = (saturate && !shift) ? "_SAT" : "";
-
-        /* Generate input register names (with modifiers) */
-        for (i = 0; i < ins->src_count; ++i)
-        {
-            pshader_gen_input_modifier_line(ins->shader, buffer, src[i], i, operands[i + 1]);
-        }
-
-        /* Handle output register */
-        shader_arb_get_register_name(ins->shader, dst->register_type,
-                dst->register_idx, dst->has_rel_addr, output_rname, &is_color);
-        strcpy(operands[0], output_rname);
-        shader_arb_get_write_mask(ins, dst, output_wmask);
-        strcat(operands[0], output_wmask);
+    /* All instructions handled by this function have a destination parameter */
+    if(dst->modifiers & WINED3DSPDM_SATURATE) modifier = "_SAT";
+    else modifier = "";
 
-        arguments[0] = '\0';
-        strcat(arguments, operands[0]);
-        for (i = 0; i < ins->src_count; ++i)
-        {
-            strcat(arguments, ", ");
-            strcat(arguments, operands[i + 1]);
-        }
-        shader_addline(buffer, "%s%s %s;\n", instruction, modifier, arguments);
-
-        /* A shift requires another line. */
-        if (shift) pshader_gen_output_modifier_line(buffer, saturate, output_wmask, shift, output_rname);
-    } else {
-        /* Note that shader_arb_add_*_param() adds spaces. */
-
-        arguments[0] = '\0';
-        if (ins->dst_count)
-        {
-            shader_arb_add_dst_param(ins, &ins->dst[0], arguments);
-            for (i = 0; i < ins->src_count; ++i)
-            {
-                strcat(arguments, ",");
-                shader_arb_add_src_param(ins, src[i], arguments);
-            }
-        }
-        shader_addline(buffer, "%s%s;\n", instruction, arguments);
+    /* Note that shader_arb_add_dst_param() adds spaces. */
+    arguments[0] = '\0';
+    shader_arb_get_dst_param(ins, dst, dst_str);
+    for (i = 0; i < ins->src_count; ++i)
+    {
+        char operand[100];
+        strcat(arguments, ", ");
+        shader_arb_get_src_param(ins, &ins->src[i], i, operand);
+        strcat(arguments, operand);
     }
+    shader_addline(buffer, "%s%s %s%s;\n", instruction, modifier, dst_str, arguments);
+}
+
+static void shader_hw_nop(const struct wined3d_shader_instruction *ins)
+{
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
+    shader_addline(buffer, "NOP;\n");
 }
 
 static void shader_hw_mov(const struct wined3d_shader_instruction *ins)
 {
-    IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->shader;
+    IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->ctx->shader;
 
-    if ((WINED3DSHADER_VERSION_MAJOR(ins->reg_maps->shader_version) == 1
-            && !shader_is_pshader_version(ins->reg_maps->shader_version)
-            && ins->dst[0].register_type == WINED3DSPR_ADDR)
+    if ((ins->ctx->reg_maps->shader_version.major == 1
+            && !shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type)
+            && ins->dst[0].reg.type == WINED3DSPR_ADDR)
             || ins->handler_idx == WINED3DSIH_MOVA)
     {
-        SHADER_BUFFER *buffer = ins->buffer;
+        SHADER_BUFFER *buffer = ins->ctx->buffer;
         char src0_param[256];
 
         if (ins->handler_idx == WINED3DSIH_MOVA)
@@ -1067,7 +990,7 @@ static void shader_hw_mov(const struct wined3d_shader_instruction *ins)
         src0_param[0] = '\0';
         if (((IWineD3DVertexShaderImpl *)shader)->rel_offset)
         {
-            shader_arb_add_src_param(ins, ins->src[0], src0_param);
+            shader_arb_get_src_param(ins, &ins->src[0], 0, src0_param);
             shader_addline(buffer, "ADD TMP.x, %s, helper_const.z;\n", src0_param);
             shader_addline(buffer, "ARL A0.x, TMP.x;\n");
         }
@@ -1075,18 +998,10 @@ static void shader_hw_mov(const struct wined3d_shader_instruction *ins)
         {
             /* Apple's ARB_vertex_program implementation does not accept an ARL source argument
              * with more than one component. Thus replicate the first source argument over all
-             * 4 components. For example, .xyzw -> .x (or better: .xxxx), .zwxy -> .z, etc)
-             */
-            DWORD parm = ins->src[0] & ~(WINED3DVS_SWIZZLE_MASK);
-            if((ins->src[0] & WINED3DVS_X_W) == WINED3DVS_X_W)
-                parm |= WINED3DVS_X_W | WINED3DVS_Y_W | WINED3DVS_Z_W | WINED3DVS_W_W;
-            else if((ins->src[0] & WINED3DVS_X_Z) == WINED3DVS_X_Z)
-                parm |= WINED3DVS_X_Z | WINED3DVS_Y_Z | WINED3DVS_Z_Z | WINED3DVS_W_Z;
-            else if((ins->src[0] & WINED3DVS_X_Y) == WINED3DVS_X_Y)
-                parm |= WINED3DVS_X_Y | WINED3DVS_Y_Y | WINED3DVS_Z_Y | WINED3DVS_W_Y;
-            else if((ins->src[0] & WINED3DVS_X_X) == WINED3DVS_X_X)
-                parm |= WINED3DVS_X_X | WINED3DVS_Y_X | WINED3DVS_Z_X | WINED3DVS_W_X;
-            shader_arb_add_src_param(ins, parm, src0_param);
+             * 4 components. For example, .xyzw -> .x (or better: .xxxx), .zwxy -> .z, etc) */
+            struct wined3d_shader_src_param tmp_src = ins->src[0];
+            tmp_src.swizzle = (tmp_src.swizzle & 0x3) * 0x55;
+            shader_arb_get_src_param(ins, &tmp_src, 0, src0_param);
             shader_addline(buffer, "ARL A0.x, %s;\n", src0_param);
         }
     }
@@ -1099,18 +1014,15 @@ static void shader_hw_mov(const struct wined3d_shader_instruction *ins)
 static void pshader_hw_texkill(const struct wined3d_shader_instruction *ins)
 {
     const struct wined3d_shader_dst_param *dst = &ins->dst[0];
-    DWORD shader_version = ins->reg_maps->shader_version;
-    SHADER_BUFFER *buffer = ins->buffer;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
     char reg_dest[40];
-    BOOL is_color;
 
     /* No swizzles are allowed in d3d's texkill. PS 1.x ignores the 4th component as documented,
      * but >= 2.0 honors it(undocumented, but tested by the d3d9 testsuit)
      */
-    shader_arb_get_register_name(ins->shader, dst->register_type,
-            dst->register_idx, dst->has_rel_addr, reg_dest, &is_color);
+    shader_arb_get_dst_param(ins, dst, reg_dest);
 
-    if (shader_version >= WINED3DPS_VERSION(2,0))
+    if (ins->ctx->reg_maps->shader_version.major >= 2)
     {
         /* The arb backend doesn't claim ps 2.0 support, but try to eat what the app feeds to us */
         shader_addline(buffer, "KIL %s;\n", reg_dest);
@@ -1118,22 +1030,19 @@ static void pshader_hw_texkill(const struct wined3d_shader_instruction *ins)
         /* ARB fp doesn't like swizzles on the parameter of the KIL instruction. To mask the 4th component,
          * copy the register into our general purpose TMP variable, overwrite .w and pass TMP to KIL
          */
-        shader_addline(buffer, "MOV TMP, %s;\n", reg_dest);
-        shader_addline(buffer, "MOV TMP.w, one.w;\n");
+        shader_addline(buffer, "SWZ TMP, %s, x, y, z, 1;\n", reg_dest);
         shader_addline(buffer, "KIL TMP;\n");
     }
 }
 
 static void pshader_hw_tex(const struct wined3d_shader_instruction *ins)
 {
-    IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->shader;
+    IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->ctx->shader;
     IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device;
     const struct wined3d_shader_dst_param *dst = &ins->dst[0];
     BOOL is_color;
-
-    const DWORD *src = ins->src;
-    SHADER_BUFFER* buffer = ins->buffer;
-    DWORD shader_version = ins->reg_maps->shader_version;
+    DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major,
+            ins->ctx->reg_maps->shader_version.minor);
     BOOL projected = FALSE, bias = FALSE;
 
     char reg_dest[40];
@@ -1141,29 +1050,29 @@ static void pshader_hw_tex(const struct wined3d_shader_instruction *ins)
     DWORD reg_sampler_code;
 
     /* All versions have a destination register */
-    shader_arb_get_register_name(ins->shader, dst->register_type,
-            dst->register_idx, dst->has_rel_addr, reg_dest, &is_color);
+    shader_arb_get_register_name(ins->ctx->shader, dst->reg.type,
+            dst->reg.idx, !!dst->reg.rel_addr, reg_dest, &is_color);
 
     /* 1.0-1.3: Use destination register as coordinate source.
        1.4+: Use provided coordinate source register. */
-   if (shader_version < WINED3DPS_VERSION(1,4))
+   if (shader_version < WINED3D_SHADER_VERSION(1,4))
       strcpy(reg_coord, reg_dest);
    else
-      pshader_gen_input_modifier_line(ins->shader, buffer, src[0], 0, reg_coord);
+      shader_arb_get_src_param(ins, &ins->src[0], 0, reg_coord);
 
   /* 1.0-1.4: Use destination register number as texture code.
      2.0+: Use provided sampler number as texure code. */
-  if (shader_version < WINED3DPS_VERSION(2,0))
-     reg_sampler_code = dst->register_idx;
+  if (shader_version < WINED3D_SHADER_VERSION(2,0))
+     reg_sampler_code = dst->reg.idx;
   else
-     reg_sampler_code = src[1] & WINED3DSP_REGNUM_MASK;
+     reg_sampler_code = ins->src[1].reg.idx;
 
   /* projection flag:
    * 1.1, 1.2, 1.3: Use WINED3DTSS_TEXTURETRANSFORMFLAGS
    * 1.4: Use WINED3DSPSM_DZ or WINED3DSPSM_DW on src[0]
    * 2.0+: Use WINED3DSI_TEXLD_PROJECT on the opcode
    */
-  if (shader_version < WINED3DPS_VERSION(1,4))
+  if (shader_version < WINED3D_SHADER_VERSION(1,4))
   {
       DWORD flags = 0;
       if(reg_sampler_code < MAX_TEXTURES) {
@@ -1173,9 +1082,9 @@ static void pshader_hw_tex(const struct wined3d_shader_instruction *ins)
           projected = TRUE;
       }
   }
-  else if (shader_version < WINED3DPS_VERSION(2,0))
+  else if (shader_version < WINED3D_SHADER_VERSION(2,0))
   {
-      DWORD src_mod = ins->src[0] & WINED3DSP_SRCMOD_MASK;
+      DWORD src_mod = ins->src[0].modifiers;
       if (src_mod == WINED3DSPSM_DZ) {
           projected = TRUE;
       } else if(src_mod == WINED3DSPSM_DW) {
@@ -1191,35 +1100,37 @@ static void pshader_hw_tex(const struct wined3d_shader_instruction *ins)
 static void pshader_hw_texcoord(const struct wined3d_shader_instruction *ins)
 {
     const struct wined3d_shader_dst_param *dst = &ins->dst[0];
-    SHADER_BUFFER *buffer = ins->buffer;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
+    DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major,
+            ins->ctx->reg_maps->shader_version.minor);
 
     char tmp[20];
     shader_arb_get_write_mask(ins, dst, tmp);
-    if (ins->reg_maps->shader_version != WINED3DPS_VERSION(1,4))
+    if (shader_version != WINED3D_SHADER_VERSION(1,4))
     {
-        DWORD reg = dst->register_idx;
+        DWORD reg = dst->reg.idx;
         shader_addline(buffer, "MOV_SAT T%u%s, fragment.texcoord[%u];\n", reg, tmp, reg);
     } else {
         char reg_src[40];
 
-        pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[0], 0, reg_src);
-        shader_addline(buffer, "MOV R%u%s, %s;\n", dst->register_idx, tmp, reg_src);
+        shader_arb_get_src_param(ins, &ins->src[0], 0, reg_src);
+        shader_addline(buffer, "MOV R%u%s, %s;\n", dst->reg.idx, tmp, reg_src);
    }
 }
 
 static void pshader_hw_texreg2ar(const struct wined3d_shader_instruction *ins)
 {
-     SHADER_BUFFER *buffer = ins->buffer;
-     IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->shader;
+     SHADER_BUFFER *buffer = ins->ctx->buffer;
+     IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->ctx->shader;
      IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device;
      DWORD flags;
 
-     DWORD reg1 = ins->dst[0].register_idx;
+     DWORD reg1 = ins->dst[0].reg.idx;
      char dst_str[8];
      char src_str[50];
 
      sprintf(dst_str, "T%u", reg1);
-     pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[0], 0, src_str);
+     shader_arb_get_src_param(ins, &ins->src[0], 0, src_str);
      shader_addline(buffer, "MOV TMP.x, %s.w;\n", src_str);
      shader_addline(buffer, "MOV TMP.y, %s.x;\n", src_str);
      flags = reg1 < MAX_TEXTURES ? deviceImpl->stateBlock->textureState[reg1][WINED3DTSS_TEXTURETRANSFORMFLAGS] : 0;
@@ -1228,14 +1139,14 @@ static void pshader_hw_texreg2ar(const struct wined3d_shader_instruction *ins)
 
 static void pshader_hw_texreg2gb(const struct wined3d_shader_instruction *ins)
 {
-     SHADER_BUFFER *buffer = ins->buffer;
+     SHADER_BUFFER *buffer = ins->ctx->buffer;
 
-     DWORD reg1 = ins->dst[0].register_idx;
+     DWORD reg1 = ins->dst[0].reg.idx;
      char dst_str[8];
      char src_str[50];
 
      sprintf(dst_str, "T%u", reg1);
-     pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[0], 0, src_str);
+     shader_arb_get_src_param(ins, &ins->src[0], 0, src_str);
      shader_addline(buffer, "MOV TMP.x, %s.y;\n", src_str);
      shader_addline(buffer, "MOV TMP.y, %s.z;\n", src_str);
      shader_hw_sample(ins, reg1, dst_str, "TMP", FALSE, FALSE);
@@ -1243,36 +1154,34 @@ static void pshader_hw_texreg2gb(const struct wined3d_shader_instruction *ins)
 
 static void pshader_hw_texreg2rgb(const struct wined3d_shader_instruction *ins)
 {
-    SHADER_BUFFER *buffer = ins->buffer;
-    DWORD reg1 = ins->dst[0].register_idx;
+    DWORD reg1 = ins->dst[0].reg.idx;
     char dst_str[8];
     char src_str[50];
 
     sprintf(dst_str, "T%u", reg1);
-    pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[0], 0, src_str);
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src_str);
     shader_hw_sample(ins, reg1, dst_str, src_str, FALSE, FALSE);
 }
 
 static void pshader_hw_texbem(const struct wined3d_shader_instruction *ins)
 {
-    IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->shader;
+    IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->ctx->shader;
     const struct wined3d_shader_dst_param *dst = &ins->dst[0];
     BOOL has_bumpmat = FALSE;
     BOOL has_luminance = FALSE;
     BOOL is_color;
     int i;
 
-    DWORD src = ins->src[0] & WINED3DSP_REGNUM_MASK;
-    SHADER_BUFFER* buffer = ins->buffer;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
 
     char reg_coord[40];
     DWORD reg_dest_code;
 
     /* All versions have a destination register */
-    reg_dest_code = dst->register_idx;
+    reg_dest_code = dst->reg.idx;
     /* Can directly use the name because texbem is only valid for <= 1.3 shaders */
-    shader_arb_get_register_name(ins->shader, dst->register_type,
-            dst->register_idx, dst->has_rel_addr, reg_coord, &is_color);
+    shader_arb_get_register_name(ins->ctx->shader, dst->reg.type,
+            dst->reg.idx, !!dst->reg.rel_addr, reg_coord, &is_color);
 
     for(i = 0; i < This->numbumpenvmatconsts; i++) {
         if (This->bumpenvmatconst[i].const_num != WINED3D_CONST_NUM_UNUSED
@@ -1292,6 +1201,8 @@ static void pshader_hw_texbem(const struct wined3d_shader_instruction *ins)
     }
 
     if(has_bumpmat) {
+        DWORD src = ins->src[0].reg.idx;
+
         /* Sampling the perturbation map in Tsrc was done already, including the signedness correction if needed */
 
         shader_addline(buffer, "SWZ TMP2, bumpenvmat%d, x, z, 0, 0;\n", reg_dest_code);
@@ -1334,26 +1245,26 @@ static void pshader_hw_texbem(const struct wined3d_shader_instruction *ins)
 
 static void pshader_hw_texm3x2pad(const struct wined3d_shader_instruction *ins)
 {
-    DWORD reg = ins->dst[0].register_idx;
-    SHADER_BUFFER *buffer = ins->buffer;
+    DWORD reg = ins->dst[0].reg.idx;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
     char src0_name[50];
 
-    pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[0], 0, src0_name);
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src0_name);
     shader_addline(buffer, "DP3 TMP.x, T%u, %s;\n", reg, src0_name);
 }
 
 static void pshader_hw_texm3x2tex(const struct wined3d_shader_instruction *ins)
 {
-    IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->shader;
+    IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->ctx->shader;
     IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device;
     DWORD flags;
-    DWORD reg = ins->dst[0].register_idx;
-    SHADER_BUFFER *buffer = ins->buffer;
+    DWORD reg = ins->dst[0].reg.idx;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
     char dst_str[8];
     char src0_name[50];
 
     sprintf(dst_str, "T%u", reg);
-    pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[0], 0, src0_name);
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src0_name);
     shader_addline(buffer, "DP3 TMP.y, T%u, %s;\n", reg, src0_name);
     flags = reg < MAX_TEXTURES ? deviceImpl->stateBlock->textureState[reg][WINED3DTSS_TEXTURETRANSFORMFLAGS] : 0;
     shader_hw_sample(ins, reg, dst_str, "TMP", flags & WINED3DTTFF_PROJECTED, FALSE);
@@ -1361,29 +1272,29 @@ static void pshader_hw_texm3x2tex(const struct wined3d_shader_instruction *ins)
 
 static void pshader_hw_texm3x3pad(const struct wined3d_shader_instruction *ins)
 {
-    IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->shader;
-    DWORD reg = ins->dst[0].register_idx;
-    SHADER_BUFFER *buffer = ins->buffer;
+    IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->ctx->shader;
+    DWORD reg = ins->dst[0].reg.idx;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
     SHADER_PARSE_STATE* current_state = &This->baseShader.parse_state;
     char src0_name[50];
 
-    pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[0], 0, src0_name);
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src0_name);
     shader_addline(buffer, "DP3 TMP.%c, T%u, %s;\n", 'x' + current_state->current_row, reg, src0_name);
     current_state->texcoord_w[current_state->current_row++] = reg;
 }
 
 static void pshader_hw_texm3x3tex(const struct wined3d_shader_instruction *ins)
 {
-    IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->shader;
+    IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->ctx->shader;
     IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device;
     DWORD flags;
-    DWORD reg = ins->dst[0].register_idx;
-    SHADER_BUFFER *buffer = ins->buffer;
+    DWORD reg = ins->dst[0].reg.idx;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
     SHADER_PARSE_STATE* current_state = &This->baseShader.parse_state;
     char dst_str[8];
     char src0_name[50];
 
-    pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[0], 0, src0_name);
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src0_name);
     shader_addline(buffer, "DP3 TMP.z, T%u, %s;\n", reg, src0_name);
 
     /* Sample the texture using the calculated coordinates */
@@ -1395,16 +1306,16 @@ static void pshader_hw_texm3x3tex(const struct wined3d_shader_instruction *ins)
 
 static void pshader_hw_texm3x3vspec(const struct wined3d_shader_instruction *ins)
 {
-    IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->shader;
+    IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->ctx->shader;
     IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device;
     DWORD flags;
-    DWORD reg = ins->dst[0].register_idx;
-    SHADER_BUFFER *buffer = ins->buffer;
+    DWORD reg = ins->dst[0].reg.idx;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
     SHADER_PARSE_STATE* current_state = &This->baseShader.parse_state;
     char dst_str[8];
     char src0_name[50];
 
-    pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[0], 0, src0_name);
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src0_name);
     shader_addline(buffer, "DP3 TMP.z, T%u, %s;\n", reg, src0_name);
 
     /* Construct the eye-ray vector from w coordinates */
@@ -1431,17 +1342,18 @@ static void pshader_hw_texm3x3vspec(const struct wined3d_shader_instruction *ins
 
 static void pshader_hw_texm3x3spec(const struct wined3d_shader_instruction *ins)
 {
-    IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->shader;
+    IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->ctx->shader;
     IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device;
     DWORD flags;
-    DWORD reg = ins->dst[0].register_idx;
-    DWORD reg3 = ins->src[1] & WINED3DSP_REGNUM_MASK;
+    DWORD reg = ins->dst[0].reg.idx;
     SHADER_PARSE_STATE* current_state = &This->baseShader.parse_state;
-    SHADER_BUFFER *buffer = ins->buffer;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
     char dst_str[8];
     char src0_name[50];
+    char src1_name[50];
 
-    pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[0], 0, src0_name);
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src0_name);
+    shader_arb_get_src_param(ins, &ins->src[0], 1, src1_name);
     shader_addline(buffer, "DP3 TMP.z, T%u, %s;\n", reg, src0_name);
 
     /* Calculate reflection vector.
@@ -1452,12 +1364,12 @@ static void pshader_hw_texm3x3spec(const struct wined3d_shader_instruction *ins)
      *
      * Which normalizes the normal vector
      */
-    shader_addline(buffer, "DP3 TMP.w, TMP, C[%u];\n", reg3);
+    shader_addline(buffer, "DP3 TMP.w, TMP, %s;\n", src1_name);
     shader_addline(buffer, "DP3 TMP2.w, TMP, TMP;\n");
     shader_addline(buffer, "RCP TMP2.w, TMP2.w;\n");
     shader_addline(buffer, "MUL TMP.w, TMP.w, TMP2.w;\n");
     shader_addline(buffer, "MUL TMP, TMP.w, TMP;\n");
-    shader_addline(buffer, "MAD TMP, coefmul.x, TMP, -C[%u];\n", reg3);
+    shader_addline(buffer, "MAD TMP, coefmul.x, TMP, -%s;\n", src1_name);
 
     /* Sample the texture using the calculated coordinates */
     sprintf(dst_str, "T%u", reg);
@@ -1469,7 +1381,7 @@ static void pshader_hw_texm3x3spec(const struct wined3d_shader_instruction *ins)
 static void pshader_hw_texdepth(const struct wined3d_shader_instruction *ins)
 {
     const struct wined3d_shader_dst_param *dst = &ins->dst[0];
-    SHADER_BUFFER *buffer = ins->buffer;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
     char dst_name[50];
     BOOL is_color;
 
@@ -1478,8 +1390,8 @@ static void pshader_hw_texdepth(const struct wined3d_shader_instruction *ins)
      * parameter. According to the msdn, this must be register r5, but let's keep it more flexible
      * here
      */
-    shader_arb_get_register_name(ins->shader, dst->register_type,
-            dst->register_idx, dst->has_rel_addr, dst_name, &is_color);
+    shader_arb_get_register_name(ins->ctx->shader, dst->reg.type,
+            dst->reg.idx, !!dst->reg.rel_addr, dst_name, &is_color);
 
     /* According to the msdn, the source register(must be r5) is unusable after
      * the texdepth instruction, so we're free to modify it
@@ -1501,12 +1413,12 @@ static void pshader_hw_texdepth(const struct wined3d_shader_instruction *ins)
  * then perform a 1D texture lookup from stage dstregnum, place into dst. */
 static void pshader_hw_texdp3tex(const struct wined3d_shader_instruction *ins)
 {
-    SHADER_BUFFER *buffer = ins->buffer;
-    DWORD sampler_idx = ins->dst[0].register_idx;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
+    DWORD sampler_idx = ins->dst[0].reg.idx;
     char src0[50];
     char dst_str[8];
 
-    pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[0], 0, src0);
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src0);
     shader_addline(buffer, "MOV TMP, 0.0;\n");
     shader_addline(buffer, "DP3 TMP.x, T%u, %s;\n", sampler_idx, src0);
 
@@ -1522,16 +1434,16 @@ static void pshader_hw_texdp3(const struct wined3d_shader_instruction *ins)
     char src0[50];
     char dst_str[50];
     char dst_mask[6];
-    SHADER_BUFFER *buffer = ins->buffer;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
     BOOL is_color;
 
     /* Handle output register */
-    shader_arb_get_register_name(ins->shader, dst->register_type,
-            dst->register_idx, dst->has_rel_addr, dst_str, &is_color);
+    shader_arb_get_register_name(ins->ctx->shader, dst->reg.type,
+            dst->reg.idx, !!dst->reg.rel_addr, dst_str, &is_color);
     shader_arb_get_write_mask(ins, dst, dst_mask);
 
-    pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[0], 0, src0);
-    shader_addline(buffer, "DP3 %s%s, T%u, %s;\n", dst_str, dst_mask, dst->register_idx, src0);
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src0);
+    shader_addline(buffer, "DP3 %s%s, T%u, %s;\n", dst_str, dst_mask, dst->reg.idx, src0);
 
     /* TODO: Handle output modifiers */
 }
@@ -1541,18 +1453,18 @@ static void pshader_hw_texdp3(const struct wined3d_shader_instruction *ins)
 static void pshader_hw_texm3x3(const struct wined3d_shader_instruction *ins)
 {
     const struct wined3d_shader_dst_param *dst = &ins->dst[0];
-    SHADER_BUFFER *buffer = ins->buffer;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
     char dst_str[50];
     char dst_mask[6];
     char src0[50];
     BOOL is_color;
 
-    shader_arb_get_register_name(ins->shader, dst->register_type,
-            dst->register_idx, dst->has_rel_addr, dst_str, &is_color);
+    shader_arb_get_register_name(ins->ctx->shader, dst->reg.type,
+            dst->reg.idx, !!dst->reg.rel_addr, dst_str, &is_color);
     shader_arb_get_write_mask(ins, dst, dst_mask);
 
-    pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[0], 0, src0);
-    shader_addline(buffer, "DP3 TMP.z, T%u, %s;\n", dst->register_idx, src0);
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src0);
+    shader_addline(buffer, "DP3 TMP.z, T%u, %s;\n", dst->reg.idx, src0);
     shader_addline(buffer, "MOV %s%s, TMP;\n", dst_str, dst_mask);
 
     /* TODO: Handle output modifiers */
@@ -1565,11 +1477,11 @@ static void pshader_hw_texm3x3(const struct wined3d_shader_instruction *ins)
  */
 static void pshader_hw_texm3x2depth(const struct wined3d_shader_instruction *ins)
 {
-    SHADER_BUFFER *buffer = ins->buffer;
-    DWORD dst_reg = ins->dst[0].register_idx;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
+    DWORD dst_reg = ins->dst[0].reg.idx;
     char src0[50];
 
-    pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[0], 0, src0);
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src0);
     shader_addline(buffer, "DP3 TMP.y, T%u, %s;\n", dst_reg, src0);
 
     /* How to deal with the special case dst_name.g == 0? if r != 0, then
@@ -1588,21 +1500,18 @@ static void shader_hw_mnxn(const struct wined3d_shader_instruction *ins)
 {
     int i;
     int nComponents = 0;
-    struct wined3d_shader_dst_param tmp_dst = {0};
+    struct wined3d_shader_dst_param tmp_dst = {{0}};
+    struct wined3d_shader_src_param tmp_src[2] = {{{0}}};
     struct wined3d_shader_instruction tmp_ins;
 
     memset(&tmp_ins, 0, sizeof(tmp_ins));
 
     /* Set constants for the temporary argument */
-    tmp_ins.shader      = ins->shader;
-    tmp_ins.buffer      = ins->buffer;
-    tmp_ins.src[0]      = ins->src[0];
-    tmp_ins.src_addr[0] = ins->src_addr[0];
-    tmp_ins.src_addr[1] = ins->src_addr[1];
-    tmp_ins.reg_maps = ins->reg_maps;
+    tmp_ins.ctx = ins->ctx;
     tmp_ins.dst_count = 1;
     tmp_ins.dst = &tmp_dst;
     tmp_ins.src_count = 2;
+    tmp_ins.src = tmp_src;
 
     switch(ins->handler_idx)
     {
@@ -1632,21 +1541,22 @@ static void shader_hw_mnxn(const struct wined3d_shader_instruction *ins)
     }
 
     tmp_dst = ins->dst[0];
+    tmp_src[0] = ins->src[0];
+    tmp_src[1] = ins->src[1];
     for (i = 0; i < nComponents; i++) {
         tmp_dst.write_mask = WINED3DSP_WRITEMASK_0 << i;
-        tmp_ins.src[1] = ins->src[1]+i;
         shader_hw_map2gl(&tmp_ins);
+        ++tmp_src[1].reg.idx;
     }
 }
 
-static void vshader_hw_rsq_rcp(const struct wined3d_shader_instruction *ins)
+static void shader_hw_rsq_rcp(const struct wined3d_shader_instruction *ins)
 {
-    SHADER_BUFFER *buffer = ins->buffer;
-    DWORD src = ins->src[0];
-    DWORD swizzle = (src & WINED3DSP_SWIZZLE_MASK) >> WINED3DSP_SWIZZLE_SHIFT;
-    const char *instruction;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
+    const char *instruction, *sat;
 
-    char tmpLine[256];
+    char dst[50];
+    char src[50];
 
     switch(ins->handler_idx)
     {
@@ -1657,44 +1567,42 @@ static void vshader_hw_rsq_rcp(const struct wined3d_shader_instruction *ins)
             break;
     }
 
-    strcpy(tmpLine, instruction);
-    shader_arb_add_dst_param(ins, &ins->dst[0], tmpLine); /* Destination */
-    strcat(tmpLine, ",");
-    shader_arb_add_src_param(ins, src, tmpLine);
-    if ((WINED3DSP_NOSWIZZLE >> WINED3DSP_SWIZZLE_SHIFT) == swizzle) {
+    if(ins->dst[0].modifiers & WINED3DSPDM_SATURATE) sat = "_SAT";
+    else sat = "";
+
+    shader_arb_get_dst_param(ins, &ins->dst[0], dst); /* Destination */
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src);
+    if (ins->src[0].swizzle == WINED3DSP_NOSWIZZLE)
+    {
         /* Dx sdk says .x is used if no swizzle is given, but our test shows that
          * .w is used
          */
-        strcat(tmpLine, ".w");
+        strcat(src, ".w");
     }
 
-    shader_addline(buffer, "%s;\n", tmpLine);
+    shader_addline(buffer, "%s%s %s, %s;\n", instruction, sat, dst, src);
 }
 
 static void shader_hw_nrm(const struct wined3d_shader_instruction *ins)
 {
     const struct wined3d_shader_dst_param *dst = &ins->dst[0];
-    SHADER_BUFFER *buffer = ins->buffer;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
     char dst_name[50];
     char src_name[50];
     char dst_wmask[20];
-    DWORD shift = dst->shift;
     BOOL sat = dst->modifiers & WINED3DSPDM_SATURATE;
     BOOL is_color;
 
-    shader_arb_get_register_name(ins->shader, dst->register_type,
-            dst->register_idx, dst->has_rel_addr, dst_name, &is_color);
+    shader_arb_get_register_name(ins->ctx->shader, dst->reg.type,
+            dst->reg.idx, !!dst->reg.rel_addr, dst_name, &is_color);
     shader_arb_get_write_mask(ins, dst, dst_wmask);
 
-    pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[0], 0, src_name);
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src_name);
     shader_addline(buffer, "DP3 TMP, %s, %s;\n", src_name, src_name);
     shader_addline(buffer, "RSQ TMP, TMP.x;\n");
     /* dst.w = src[0].w * 1 / (src.x^2 + src.y^2 + src.z^2)^(1/2) according to msdn*/
     shader_addline(buffer, "MUL%s %s%s, %s, TMP;\n", sat ? "_SAT" : "", dst_name, dst_wmask,
                    src_name);
-
-    if (shift != 0)
-        pshader_gen_output_modifier_line(buffer, FALSE, dst_wmask, shift, dst_name);
 }
 
 static void shader_hw_sincos(const struct wined3d_shader_instruction *ins)
@@ -1704,25 +1612,20 @@ static void shader_hw_sincos(const struct wined3d_shader_instruction *ins)
      * can't use map2gl
      */
     const struct wined3d_shader_dst_param *dst = &ins->dst[0];
-    SHADER_BUFFER *buffer = ins->buffer;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
     char dst_name[50];
     char src_name[50];
     char dst_wmask[20];
-    DWORD shift = dst->shift;
     BOOL sat = dst->modifiers & WINED3DSPDM_SATURATE;
     BOOL is_color;
 
-    shader_arb_get_register_name(ins->shader, dst->register_type,
-            dst->register_idx, dst->has_rel_addr, dst_name, &is_color);
+    shader_arb_get_register_name(ins->ctx->shader, dst->reg.type,
+            dst->reg.idx, !!dst->reg.rel_addr, dst_name, &is_color);
     shader_arb_get_write_mask(ins, dst, dst_wmask);
 
-    pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[0], 0, src_name);
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src_name);
     shader_addline(buffer, "SCS%s %s%s, %s;\n", sat ? "_SAT" : "", dst_name, dst_wmask,
                    src_name);
-
-    if (shift != 0)
-        pshader_gen_output_modifier_line(buffer, FALSE, dst_wmask, shift, dst_name);
-
 }
 
 static GLuint create_arb_blt_vertex_program(const WineD3D_GL_Info *gl_info)
@@ -1904,7 +1807,7 @@ static void shader_arb_destroy(IWineD3DBaseShader *iface) {
     IWineD3DBaseShaderImpl *baseShader = (IWineD3DBaseShaderImpl *) iface;
     const WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)baseShader->baseShader.device)->adapter->gl_info;
 
-    if (shader_is_pshader_version(baseShader->baseShader.reg_maps.shader_version))
+    if (shader_is_pshader_version(baseShader->baseShader.reg_maps.shader_version.type))
     {
         IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *) iface;
         UINT i;
@@ -1969,16 +1872,16 @@ static void arbfp_add_sRGB_correction(SHADER_BUFFER *buffer, const char *fragcol
     /* Perform sRGB write correction. See GLX_EXT_framebuffer_sRGB */
 
     /* Calculate the > 0.0031308 case */
-    shader_addline(buffer, "POW %s.x, %s.x, srgb_pow.x;\n", tmp1, fragcolor);
-    shader_addline(buffer, "POW %s.y, %s.y, srgb_pow.y;\n", tmp1, fragcolor);
-    shader_addline(buffer, "POW %s.z, %s.z, srgb_pow.z;\n", tmp1, fragcolor);
-    shader_addline(buffer, "MUL %s, %s, srgb_mul_hi;\n", tmp1, tmp1);
-    shader_addline(buffer, "SUB %s, %s, srgb_sub_hi;\n", tmp1, tmp1);
+    shader_addline(buffer, "POW %s.x, %s.x, srgb_consts1.z;\n", tmp1, fragcolor);
+    shader_addline(buffer, "POW %s.y, %s.y, srgb_consts1.z;\n", tmp1, fragcolor);
+    shader_addline(buffer, "POW %s.z, %s.z, srgb_consts1.z;\n", tmp1, fragcolor);
+    shader_addline(buffer, "MUL %s, %s, srgb_consts1.w;\n", tmp1, tmp1);
+    shader_addline(buffer, "SUB %s, %s, srgb_consts2.x;\n", tmp1, tmp1);
     /* Calculate the < case */
-    shader_addline(buffer, "MUL %s, srgb_mul_low, %s;\n", tmp2, fragcolor);
+    shader_addline(buffer, "MUL %s, srgb_consts1.x, %s;\n", tmp2, fragcolor);
     /* Get 1.0 / 0.0 masks for > 0.0031308 and < 0.0031308 */
-    shader_addline(buffer, "SLT %s, srgb_comparison, %s;\n", tmp3, fragcolor);
-    shader_addline(buffer, "SGE %s, srgb_comparison, %s;\n", tmp4, fragcolor);
+    shader_addline(buffer, "SLT %s, srgb_consts1.y, %s;\n", tmp3, fragcolor);
+    shader_addline(buffer, "SGE %s, srgb_consts1.y, %s;\n", tmp4, fragcolor);
     /* Store the components > 0.0031308 in the destination */
     shader_addline(buffer, "MUL %s, %s, %s;\n", fragcolor, tmp1, tmp3);
     /* Add the components that are < 0.0031308 */
@@ -1986,20 +1889,23 @@ static void arbfp_add_sRGB_correction(SHADER_BUFFER *buffer, const char *fragcol
     /* [0.0;1.0] clamping. Not needed, this is done implicitly */
 }
 
-static GLuint shader_arb_generate_pshader(IWineD3DPixelShader *iface, SHADER_BUFFER *buffer, const struct ps_compile_args *args) {
+static GLuint shader_arb_generate_pshader(IWineD3DPixelShader *iface,
+        SHADER_BUFFER *buffer, const struct ps_compile_args *args)
+{
     IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
     const shader_reg_maps* reg_maps = &This->baseShader.reg_maps;
     CONST DWORD *function = This->baseShader.function;
-    DWORD shader_version = reg_maps->shader_version;
     const WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)This->baseShader.device)->adapter->gl_info;
     const local_constant *lconst;
     GLuint retval;
     const char *fragcolor;
+    DWORD *lconst_map = local_const_mapping((IWineD3DBaseShaderImpl *) This);
 
     /*  Create the hw ARB shader */
     shader_addline(buffer, "!!ARBfp1.0\n");
 
-    if (shader_version < WINED3DPS_VERSION(3,0)) {
+    if (reg_maps->shader_version.major < 3)
+    {
         switch(args->fog) {
             case FOG_OFF:
                 break;
@@ -2024,7 +1930,8 @@ static GLuint shader_arb_generate_pshader(IWineD3DPixelShader *iface, SHADER_BUF
     shader_addline(buffer, "PARAM coefmul = { 2, 4, 8, 16 };\n");
     shader_addline(buffer, "PARAM one = { 1.0, 1.0, 1.0, 1.0 };\n");
 
-    if (shader_version < WINED3DPS_VERSION(2,0)) {
+    if (reg_maps->shader_version.major < 2)
+    {
         fragcolor = "R0";
     } else {
         shader_addline(buffer, "TEMP TMP_COLOR;\n");
@@ -2032,10 +1939,10 @@ static GLuint shader_arb_generate_pshader(IWineD3DPixelShader *iface, SHADER_BUF
     }
 
     /* Base Declarations */
-    shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION);
+    shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION, lconst_map);
 
     /* Base Shader Body */
-    shader_generate_main( (IWineD3DBaseShader*) This, buffer, reg_maps, function);
+    shader_generate_main((IWineD3DBaseShader *)This, buffer, reg_maps, function);
 
     if(args->srgb_correction) {
         arbfp_add_sRGB_correction(buffer, fragcolor, "TMP", "TMP2", "TA", "TB");
@@ -2063,18 +1970,21 @@ static GLuint shader_arb_generate_pshader(IWineD3DPixelShader *iface, SHADER_BUF
     }
 
     /* Load immediate constants */
-    if(!This->baseShader.load_local_constsF) {
+    if(lconst_map) {
         LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) {
             const float *value = (const float *)lconst->value;
-            GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, lconst->idx, value));
+            GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, lconst_map[lconst->idx], value));
             checkGLcall("glProgramLocalParameter4fvARB");
         }
+        HeapFree(GetProcessHeap(), 0, lconst_map);
     }
 
     return retval;
 }
 
-static GLuint shader_arb_generate_vshader(IWineD3DVertexShader *iface, SHADER_BUFFER *buffer, const struct vs_compile_args *args) {
+static GLuint shader_arb_generate_vshader(IWineD3DVertexShader *iface,
+        SHADER_BUFFER *buffer, const struct vs_compile_args *args)
+{
     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
     const shader_reg_maps *reg_maps = &This->baseShader.reg_maps;
     CONST DWORD *function = This->baseShader.function;
@@ -2082,6 +1992,7 @@ static GLuint shader_arb_generate_vshader(IWineD3DVertexShader *iface, SHADER_BU
     const WineD3D_GL_Info *gl_info = &device->adapter->gl_info;
     const local_constant *lconst;
     GLuint ret;
+    DWORD *lconst_map = local_const_mapping((IWineD3DBaseShaderImpl *) This);
 
     /*  Create the hw ARB shader */
     shader_addline(buffer, "!!ARBvp1.0\n");
@@ -2095,7 +2006,7 @@ static GLuint shader_arb_generate_vshader(IWineD3DVertexShader *iface, SHADER_BU
     shader_addline(buffer, "TEMP TMP;\n");
 
     /* Base Declarations */
-    shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION);
+    shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION, lconst_map);
 
     /* We need a constant to fixup the final position */
     shader_addline(buffer, "PARAM posFixup = program.env[%d];\n", ARB_SHADER_PRIVCONST_POS);
@@ -2126,7 +2037,7 @@ static GLuint shader_arb_generate_vshader(IWineD3DVertexShader *iface, SHADER_BU
     }
 
     /* Base Shader Body */
-    shader_generate_main( (IWineD3DBaseShader*) This, buffer, reg_maps, function);
+    shader_generate_main((IWineD3DBaseShader *)This, buffer, reg_maps, function);
 
     /* The D3DRS_FOGTABLEMODE render state defines if the shader-generated fog coord is used
      * or if the fragment depth is used. If the fragment depth is used(FOGTABLEMODE != NONE),
@@ -2136,7 +2047,7 @@ static GLuint shader_arb_generate_vshader(IWineD3DVertexShader *iface, SHADER_BU
     if(args->fog_src == VS_FOG_Z) {
         shader_addline(buffer, "MOV result.fogcoord, TMP_OUT.z;\n");
     } else if (!reg_maps->fog) {
-        shader_addline(buffer, "MOV result.fogcoord, 0.0;\n");
+        shader_addline(buffer, "MOV result.fogcoord, helper_const.w;\n");
     }
 
     /* Write the final position.
@@ -2178,13 +2089,15 @@ static GLuint shader_arb_generate_vshader(IWineD3DVertexShader *iface, SHADER_BU
         ret = -1;
     } else {
         /* Load immediate constants */
-        if(!This->baseShader.load_local_constsF) {
+        if(lconst_map) {
             LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) {
                 const float *value = (const float *)lconst->value;
-                GL_EXTCALL(glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, lconst->idx, value));
+                GL_EXTCALL(glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, lconst_map[lconst->idx], value));
             }
         }
     }
+    HeapFree(GetProcessHeap(), 0, lconst_map);
+
     return ret;
 }
 
@@ -2228,6 +2141,30 @@ static BOOL shader_arb_color_fixup_supported(struct color_fixup_desc fixup)
     return FALSE;
 }
 
+static void shader_arb_add_instruction_modifiers(const struct wined3d_shader_instruction *ins) {
+    BOOL saturate;
+    DWORD shift;
+    char write_mask[20], regstr[50];
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
+    BOOL is_color = FALSE;
+    const struct wined3d_shader_dst_param *dst;
+
+    if (!ins->dst_count) return;
+
+    dst = &ins->dst[0];
+    shift = dst->shift;
+    if(shift == 0) return; /* Saturate alone is handled by the instructions */
+    saturate = dst->modifiers & WINED3DSPDM_SATURATE;
+
+    shader_arb_get_write_mask(ins, dst, write_mask);
+    shader_arb_get_register_name(ins->ctx->shader, dst->reg.type,
+                                 dst->reg.idx, !!dst->reg.rel_addr, regstr, &is_color);
+
+    /* Generate a line that does the output modifier computation */
+    shader_addline(buffer, "MUL%s %s%s, %s, %s;\n", saturate ? "_SAT" : "",
+                   regstr, write_mask, regstr, shift_tab[shift]);
+}
+
 static const SHADER_HANDLER shader_arb_instruction_handler_table[WINED3DSIH_TABLE_SIZE] =
 {
     /* WINED3DSIH_ABS           */ shader_hw_map2gl,
@@ -2277,14 +2214,14 @@ static const SHADER_HANDLER shader_arb_instruction_handler_table[WINED3DSIH_TABL
     /* WINED3DSIH_MOV           */ shader_hw_mov,
     /* WINED3DSIH_MOVA          */ shader_hw_mov,
     /* WINED3DSIH_MUL           */ shader_hw_map2gl,
-    /* WINED3DSIH_NOP           */ shader_hw_map2gl,
+    /* WINED3DSIH_NOP           */ shader_hw_nop,
     /* WINED3DSIH_NRM           */ shader_hw_nrm,
     /* WINED3DSIH_PHASE         */ NULL,
     /* WINED3DSIH_POW           */ shader_hw_map2gl,
-    /* WINED3DSIH_RCP           */ vshader_hw_rsq_rcp,
+    /* WINED3DSIH_RCP           */ shader_hw_rsq_rcp,
     /* WINED3DSIH_REP           */ NULL,
     /* WINED3DSIH_RET           */ NULL,
-    /* WINED3DSIH_RSQ           */ vshader_hw_rsq_rcp,
+    /* WINED3DSIH_RSQ           */ shader_hw_rsq_rcp,
     /* WINED3DSIH_SETP          */ NULL,
     /* WINED3DSIH_SGE           */ shader_hw_map2gl,
     /* WINED3DSIH_SGN           */ NULL,
@@ -2332,6 +2269,7 @@ const shader_backend_t arb_program_shader_backend = {
     shader_arb_generate_vshader,
     shader_arb_get_caps,
     shader_arb_color_fixup_supported,
+    shader_arb_add_instruction_modifiers,
 };
 
 /* ARB_fragment_program fixed function pipeline replacement definitions */
@@ -2865,16 +2803,10 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, IWi
         shader_addline(&buffer, "PARAM specular_enable = program.env[%u];\n", ARB_FFP_CONST_SPECULAR_ENABLE);
 
     if(settings->sRGB_write) {
-        shader_addline(&buffer, "PARAM srgb_mul_low = {%f, %f, %f, 1.0};\n",
-                       srgb_mul_low, srgb_mul_low, srgb_mul_low);
-        shader_addline(&buffer, "PARAM srgb_comparison =  {%f, %f, %f, %f};\n",
-                       srgb_cmp, srgb_cmp, srgb_cmp, srgb_cmp);
-        shader_addline(&buffer, "PARAM srgb_pow =  {%f, %f, %f, 1.0};\n",
-                       srgb_pow, srgb_pow, srgb_pow);
-        shader_addline(&buffer, "PARAM srgb_mul_hi =  {%f, %f, %f, 1.0};\n",
-                       srgb_mul_high, srgb_mul_high, srgb_mul_high);
-        shader_addline(&buffer, "PARAM srgb_sub_hi =  {%f, %f, %f, 0.0};\n",
-                       srgb_sub_high, srgb_sub_high, srgb_sub_high);
+        shader_addline(&buffer, "PARAM srgb_consts1 = {%f, %f, %f, %f};\n",
+                       srgb_mul_low, srgb_cmp, srgb_pow, srgb_mul_high);
+        shader_addline(&buffer, "PARAM srgb_consts2 = {%f, %f, %f, %f};\n",
+                       srgb_sub_high, 0.0, 0.0, 0.0);
     }
 
     /* Generate texture sampling instructions) */
index 08415c2..8b8aef4 100644 (file)
@@ -7,6 +7,7 @@
  * Copyright 2005 Oliver Stieber
  * Copyright 2006 Ivan Gyurdiev
  * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
+ * Copyright 2009 Henri Verbeet for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
 WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
 WINE_DECLARE_DEBUG_CHANNEL(d3d);
 
-static void shader_dump_param(const DWORD param, const DWORD addr_token, int input, DWORD shader_version);
+static const char *shader_opcode_names[] =
+{
+    /* WINED3DSIH_ABS           */ "abs",
+    /* WINED3DSIH_ADD           */ "add",
+    /* WINED3DSIH_BEM           */ "bem",
+    /* WINED3DSIH_BREAK         */ "break",
+    /* WINED3DSIH_BREAKC        */ "breakc",
+    /* WINED3DSIH_BREAKP        */ "breakp",
+    /* WINED3DSIH_CALL          */ "call",
+    /* WINED3DSIH_CALLNZ        */ "callnz",
+    /* WINED3DSIH_CMP           */ "cmp",
+    /* WINED3DSIH_CND           */ "cnd",
+    /* WINED3DSIH_CRS           */ "crs",
+    /* WINED3DSIH_DCL           */ "dcl",
+    /* WINED3DSIH_DEF           */ "def",
+    /* WINED3DSIH_DEFB          */ "defb",
+    /* WINED3DSIH_DEFI          */ "defi",
+    /* WINED3DSIH_DP2ADD        */ "dp2add",
+    /* WINED3DSIH_DP3           */ "dp3",
+    /* WINED3DSIH_DP4           */ "dp4",
+    /* WINED3DSIH_DST           */ "dst",
+    /* WINED3DSIH_DSX           */ "dsx",
+    /* WINED3DSIH_DSY           */ "dsy",
+    /* WINED3DSIH_ELSE          */ "else",
+    /* WINED3DSIH_ENDIF         */ "endif",
+    /* WINED3DSIH_ENDLOOP       */ "endloop",
+    /* WINED3DSIH_ENDREP        */ "endrep",
+    /* WINED3DSIH_EXP           */ "exp",
+    /* WINED3DSIH_EXPP          */ "expp",
+    /* WINED3DSIH_FRC           */ "frc",
+    /* WINED3DSIH_IF            */ "if",
+    /* WINED3DSIH_IFC           */ "ifc",
+    /* WINED3DSIH_LABEL         */ "label",
+    /* WINED3DSIH_LIT           */ "lit",
+    /* WINED3DSIH_LOG           */ "log",
+    /* WINED3DSIH_LOGP          */ "logp",
+    /* WINED3DSIH_LOOP          */ "loop",
+    /* WINED3DSIH_LRP           */ "lrp",
+    /* WINED3DSIH_M3x2          */ "m3x2",
+    /* WINED3DSIH_M3x3          */ "m3x3",
+    /* WINED3DSIH_M3x4          */ "m3x4",
+    /* WINED3DSIH_M4x3          */ "m4x3",
+    /* WINED3DSIH_M4x4          */ "m4x4",
+    /* WINED3DSIH_MAD           */ "mad",
+    /* WINED3DSIH_MAX           */ "max",
+    /* WINED3DSIH_MIN           */ "min",
+    /* WINED3DSIH_MOV           */ "mov",
+    /* WINED3DSIH_MOVA          */ "mova",
+    /* WINED3DSIH_MUL           */ "mul",
+    /* WINED3DSIH_NOP           */ "nop",
+    /* WINED3DSIH_NRM           */ "nrm",
+    /* WINED3DSIH_PHASE         */ "phase",
+    /* WINED3DSIH_POW           */ "pow",
+    /* WINED3DSIH_RCP           */ "rcp",
+    /* WINED3DSIH_REP           */ "rep",
+    /* WINED3DSIH_RET           */ "ret",
+    /* WINED3DSIH_RSQ           */ "rsq",
+    /* WINED3DSIH_SETP          */ "setp",
+    /* WINED3DSIH_SGE           */ "sge",
+    /* WINED3DSIH_SGN           */ "sgn",
+    /* WINED3DSIH_SINCOS        */ "sincos",
+    /* WINED3DSIH_SLT           */ "slt",
+    /* WINED3DSIH_SUB           */ "sub",
+    /* WINED3DSIH_TEX           */ "texld",
+    /* WINED3DSIH_TEXBEM        */ "texbem",
+    /* WINED3DSIH_TEXBEML       */ "texbeml",
+    /* WINED3DSIH_TEXCOORD      */ "texcrd",
+    /* WINED3DSIH_TEXDEPTH      */ "texdepth",
+    /* WINED3DSIH_TEXDP3        */ "texdp3",
+    /* WINED3DSIH_TEXDP3TEX     */ "texdp3tex",
+    /* WINED3DSIH_TEXKILL       */ "texkill",
+    /* WINED3DSIH_TEXLDD        */ "texldd",
+    /* WINED3DSIH_TEXLDL        */ "texldl",
+    /* WINED3DSIH_TEXM3x2DEPTH  */ "texm3x2depth",
+    /* WINED3DSIH_TEXM3x2PAD    */ "texm3x2pad",
+    /* WINED3DSIH_TEXM3x2TEX    */ "texm3x2tex",
+    /* WINED3DSIH_TEXM3x3       */ "texm3x3",
+    /* WINED3DSIH_TEXM3x3DIFF   */ "texm3x3diff",
+    /* WINED3DSIH_TEXM3x3PAD    */ "texm3x3pad",
+    /* WINED3DSIH_TEXM3x3SPEC   */ "texm3x3spec",
+    /* WINED3DSIH_TEXM3x3TEX    */ "texm3x3tex",
+    /* WINED3DSIH_TEXM3x3VSPEC  */ "texm3x3vspec",
+    /* WINED3DSIH_TEXREG2AR     */ "texreg2ar",
+    /* WINED3DSIH_TEXREG2GB     */ "texreg2gb",
+    /* WINED3DSIH_TEXREG2RGB    */ "texreg2rgb",
+};
+
+const struct wined3d_shader_frontend *shader_select_frontend(DWORD version_token)
+{
+    switch (version_token >> 16)
+    {
+        case WINED3D_SM1_VS:
+        case WINED3D_SM1_PS:
+            return &sm1_shader_frontend;
+
+        case WINED3D_SM4_PS:
+        case WINED3D_SM4_VS:
+        case WINED3D_SM4_GS:
+            return &sm4_shader_frontend;
+
+        default:
+            FIXME("Unrecognised version token %#x\n", version_token);
+            return NULL;
+    }
+}
 
 static inline BOOL shader_is_version_token(DWORD token) {
     return shader_is_pshader_version(token) ||
@@ -95,153 +200,164 @@ int shader_addline(SHADER_BUFFER* buffer, const char *format, ...)
     return ret;
 }
 
-void shader_init(struct IWineD3DBaseShaderClass *shader,
-        IWineD3DDevice *device, const SHADER_OPCODE *instruction_table)
+void shader_init(struct IWineD3DBaseShaderClass *shader, IWineD3DDevice *device)
 {
     shader->ref = 1;
     shader->device = device;
-    shader->shader_ins = instruction_table;
     list_init(&shader->linked_programs);
 }
 
-const SHADER_OPCODE *shader_get_opcode(const SHADER_OPCODE *opcode_table, DWORD shader_version, DWORD code)
+/* Convert floating point offset relative
+ * to a register file to an absolute offset for float constants */
+static unsigned int shader_get_float_offset(WINED3DSHADER_PARAM_REGISTER_TYPE register_type, UINT register_idx)
 {
-    DWORD i = 0;
-
-    /** TODO: use dichotomic search */
-    while (opcode_table[i].name)
+    switch (register_type)
     {
-        if ((code & WINED3DSI_OPCODE_MASK) == opcode_table[i].opcode
-                && shader_version >= opcode_table[i].min_version
-                && (!opcode_table[i].max_version || shader_version <= opcode_table[i].max_version))
-        {
-            return &opcode_table[i];
-        }
-        ++i;
+        case WINED3DSPR_CONST: return register_idx;
+        case WINED3DSPR_CONST2: return 2048 + register_idx;
+        case WINED3DSPR_CONST3: return 4096 + register_idx;
+        case WINED3DSPR_CONST4: return 6144 + register_idx;
+        default:
+            FIXME("Unsupported register type: %d\n", register_type);
+            return register_idx;
     }
-
-    FIXME("Unsupported opcode %#x(%d) masked %#x, shader version %#x\n",
-            code, code, code & WINED3DSI_OPCODE_MASK, shader_version);
-
-    return NULL;
 }
 
-/* Read a parameter opcode from the input stream,
- * and possibly a relative addressing token.
- * Return the number of tokens read */
-static int shader_get_param(const DWORD *pToken, DWORD shader_version, DWORD *param, DWORD *addr_token)
-{
-    /* PS >= 3.0 have relative addressing (with token)
-     * VS >= 2.0 have relative addressing (with token)
-     * VS >= 1.0 < 2.0 have relative addressing (without token)
-     * The version check below should work in general */
+static void shader_delete_constant_list(struct list* clist) {
 
-    char rel_token = WINED3DSHADER_VERSION_MAJOR(shader_version) >= 2 &&
-        ((*pToken & WINED3DSHADER_ADDRESSMODE_MASK) == WINED3DSHADER_ADDRMODE_RELATIVE);
+    struct list *ptr;
+    struct local_constant* constant;
 
-    *param = *pToken;
-    *addr_token = rel_token? *(pToken + 1): 0;
-    return rel_token? 2:1;
+    ptr = list_head(clist);
+    while (ptr) {
+        constant = LIST_ENTRY(ptr, struct local_constant, entry);
+        ptr = list_next(clist, ptr);
+        HeapFree(GetProcessHeap(), 0, constant);
+    }
+    list_init(clist);
 }
 
-/* Return the number of parameters to skip for an opcode */
-static inline int shader_skip_opcode(const SHADER_OPCODE *curOpcode, DWORD opcode_token, DWORD shader_version)
+static inline void set_bitmap_bit(DWORD *bitmap, DWORD bit)
 {
-   /* Shaders >= 2.0 may contain address tokens, but fortunately they
-    * have a useful length mask - use it here. Shaders 1.0 contain no such tokens */
-    return (WINED3DSHADER_VERSION_MAJOR(shader_version) >= 2)
-            ? ((opcode_token & WINED3DSI_INSTLENGTH_MASK) >> WINED3DSI_INSTLENGTH_SHIFT) : curOpcode->num_params;
+    DWORD idx, shift;
+    idx = bit >> 5;
+    shift = bit & 0x1f;
+    bitmap[idx] |= (1 << shift);
 }
 
-/* Read the parameters of an unrecognized opcode from the input stream
- * Return the number of tokens read. 
- * 
- * Note: This function assumes source or destination token format.
- * It will not work with specially-formatted tokens like DEF or DCL, 
- * but hopefully those would be recognized */
-static int shader_skip_unrecognized(const DWORD *pToken, DWORD shader_version)
+static void shader_record_register_usage(IWineD3DBaseShaderImpl *This, struct shader_reg_maps *reg_maps,
+        DWORD register_type, UINT register_idx, BOOL has_rel_addr, BOOL pshader)
 {
-    int tokens_read = 0;
-    int i = 0;
+    switch (register_type)
+    {
+        case WINED3DSPR_TEXTURE: /* WINED3DSPR_ADDR */
+            if (pshader) reg_maps->texcoord[register_idx] = 1;
+            else reg_maps->address[register_idx] = 1;
+            break;
+
+        case WINED3DSPR_TEMP:
+            reg_maps->temporary[register_idx] = 1;
+            break;
+
+        case WINED3DSPR_INPUT:
+            if (!pshader) reg_maps->attributes[register_idx] = 1;
+            else
+            {
+                if (has_rel_addr)
+                {
+                    /* If relative addressing is used, we must assume that all registers
+                     * are used. Even if it is a construct like v3[aL], we can't assume
+                     * that v0, v1 and v2 aren't read because aL can be negative */
+                    unsigned int i;
+                    for (i = 0; i < MAX_REG_INPUT; ++i)
+                    {
+                        ((IWineD3DPixelShaderImpl *)This)->input_reg_used[i] = TRUE;
+                    }
+                }
+                else
+                {
+                    ((IWineD3DPixelShaderImpl *)This)->input_reg_used[register_idx] = TRUE;
+                }
+            }
+            break;
+
+        case WINED3DSPR_RASTOUT:
+            if (register_idx == 1) reg_maps->fog = 1;
+            break;
+
+        case WINED3DSPR_MISCTYPE:
+            if (pshader && register_idx == 0) reg_maps->vpos = 1;
+            break;
+
+        case WINED3DSPR_CONST:
+            if (has_rel_addr)
+            {
+                if (!pshader)
+                {
+                    if (register_idx <= ((IWineD3DVertexShaderImpl *)This)->min_rel_offset)
+                        ((IWineD3DVertexShaderImpl *)This)->min_rel_offset = register_idx;
+                    else if (register_idx >= ((IWineD3DVertexShaderImpl *)This)->max_rel_offset)
+                        ((IWineD3DVertexShaderImpl *)This)->max_rel_offset = register_idx;
+                }
+                reg_maps->usesrelconstF = TRUE;
+            }
+            else
+            {
+                set_bitmap_bit(reg_maps->constf, register_idx);
+            }
+            break;
 
-    /* TODO: Think of a good name for 0x80000000 and replace it with a constant */
-    while (*pToken & 0x80000000) {
+        case WINED3DSPR_CONSTINT:
+            reg_maps->integer_constants |= (1 << register_idx);
+            break;
 
-        DWORD param, addr_token;
-        tokens_read += shader_get_param(pToken, shader_version, &param, &addr_token);
-        pToken += tokens_read;
+        case WINED3DSPR_CONSTBOOL:
+            reg_maps->boolean_constants |= (1 << register_idx);
+            break;
 
-        FIXME("Unrecognized opcode param: token=0x%08x "
-            "addr_token=0x%08x name=", param, addr_token);
-        shader_dump_param(param, addr_token, i, shader_version);
-        FIXME("\n");
-        ++i;
+        default:
+            TRACE("Not recording register of type %#x and idx %u\n", register_type, register_idx);
+            break;
     }
-    return tokens_read;
 }
 
-/* Convert floating point offset relative
- * to a register file to an absolute offset for float constants */
-static unsigned int shader_get_float_offset(const DWORD reg)
+static unsigned char get_instr_regcount(enum WINED3D_SHADER_INSTRUCTION_HANDLER instr, int param)
 {
-     unsigned int regnum = reg & WINED3DSP_REGNUM_MASK;
-     int regtype = shader_get_regtype(reg);
-
-     switch (regtype) {
-        case WINED3DSPR_CONST: return regnum;
-        case WINED3DSPR_CONST2: return 2048 + regnum;
-        case WINED3DSPR_CONST3: return 4096 + regnum;
-        case WINED3DSPR_CONST4: return 6144 + regnum;
-        default:
-            FIXME("Unsupported register type: %d\n", regtype);
-            return regnum;
-     }
-}
+    switch(instr)
+    {
+        case WINED3DSIH_M4x4:
+        case WINED3DSIH_M3x4:
+            return param == 1 ? 4 : 1;
 
-static void shader_delete_constant_list(struct list* clist) {
+        case WINED3DSIH_M4x3:
+        case WINED3DSIH_M3x3:
+            return param == 1 ? 3 : 1;
 
-    struct list *ptr;
-    struct local_constant* constant;
+        case WINED3DSIH_M3x2:
+            return param == 1 ? 2 : 1;
 
-    ptr = list_head(clist);
-    while (ptr) {
-        constant = LIST_ENTRY(ptr, struct local_constant, entry);
-        ptr = list_next(clist, ptr);
-        HeapFree(GetProcessHeap(), 0, constant);
+        default:
+            return 1;
     }
-    list_init(clist);
-}
-
-static void shader_parse_dst_param(DWORD param, DWORD addr_param, struct wined3d_shader_dst_param *dst)
-{
-    dst->register_type = ((param & WINED3DSP_REGTYPE_MASK) >> WINED3DSP_REGTYPE_SHIFT)
-            | ((param & WINED3DSP_REGTYPE_MASK2) >> WINED3DSP_REGTYPE_SHIFT2);
-    dst->register_idx = param & WINED3DSP_REGNUM_MASK;
-    dst->write_mask = param & WINED3DSP_WRITEMASK_ALL;
-    dst->modifiers = param & WINED3DSP_DSTMOD_MASK;
-    dst->shift = (param & WINED3DSP_DSTSHIFT_MASK) >> WINED3DSP_DSTSHIFT_SHIFT;
-    dst->has_rel_addr = param & WINED3DSHADER_ADDRMODE_RELATIVE;
-    dst->addr_token = addr_param;
 }
 
 /* Note that this does not count the loop register
  * as an address register. */
 
-HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, struct shader_reg_maps *reg_maps,
-        struct wined3d_shader_semantic *semantics_in, struct wined3d_shader_semantic *semantics_out,
-        const DWORD *byte_code)
+HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, const struct wined3d_shader_frontend *fe,
+        struct shader_reg_maps *reg_maps, struct wined3d_shader_semantic *semantics_in,
+        struct wined3d_shader_semantic *semantics_out, const DWORD *byte_code, DWORD constf_size)
 {
     IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface;
-    const SHADER_OPCODE *shader_ins = This->baseShader.shader_ins;
-    DWORD shader_version;
+    void *fe_data = This->baseShader.frontend_data;
+    struct wined3d_shader_version shader_version;
     unsigned int cur_loop_depth = 0, max_loop_depth = 0;
     const DWORD* pToken = byte_code;
     char pshader;
 
     /* There are some minor differences between pixel and vertex shaders */
 
-    memset(reg_maps->bumpmat, 0, sizeof(reg_maps->bumpmat));
-    memset(reg_maps->luminanceparams, 0, sizeof(reg_maps->luminanceparams));
+    memset(reg_maps, 0, sizeof(*reg_maps));
 
     /* get_registers_used is called on every compile on some 1.x shaders, which can result
      * in stacking up a collection of local constants. Delete the old constants if existing
@@ -250,83 +366,88 @@ HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, struct shader_reg_m
     shader_delete_constant_list(&This->baseShader.constantsB);
     shader_delete_constant_list(&This->baseShader.constantsI);
 
-    /* The version token is supposed to be the first token */
-    if (!shader_is_version_token(*pToken))
-    {
-        FIXME("First token is not a version token, invalid shader.\n");
-        return WINED3DERR_INVALIDCALL;
+    fe->shader_read_header(fe_data, &pToken, &shader_version);
+    reg_maps->shader_version = shader_version;
+    pshader = shader_is_pshader_version(shader_version.type);
+
+    reg_maps->constf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+                                 sizeof(*reg_maps->constf) * ((constf_size + 31) / 32));
+    if(!reg_maps->constf) {
+        ERR("Out of memory\n");
+        return E_OUTOFMEMORY;
     }
-    reg_maps->shader_version = shader_version = *pToken++;
-    pshader = shader_is_pshader_version(shader_version);
 
-    while (WINED3DVS_END() != *pToken) {
-        CONST SHADER_OPCODE* curOpcode;
-        DWORD opcode_token;
+    while (!fe->shader_is_end(fe_data, &pToken))
+    {
+        struct wined3d_shader_instruction ins;
+        const char *comment;
+        UINT param_size;
 
         /* Skip comments */
-        if (shader_is_comment(*pToken))
-        {
-             DWORD comment_len = (*pToken & WINED3DSI_COMMENTSIZE_MASK) >> WINED3DSI_COMMENTSIZE_SHIFT;
-             ++pToken;
-             pToken += comment_len;
-             continue;
-        }
+        fe->shader_read_comment(&pToken, &comment);
+        if (comment) continue;
 
         /* Fetch opcode */
-        opcode_token = *pToken++;
-        curOpcode = shader_get_opcode(shader_ins, shader_version, opcode_token);
+        fe->shader_read_opcode(fe_data, &pToken, &ins, &param_size);
 
         /* Unhandled opcode, and its parameters */
-        if (NULL == curOpcode) {
-           while (*pToken & 0x80000000)
-               ++pToken;
+        if (ins.handler_idx == WINED3DSIH_TABLE_SIZE)
+        {
+            TRACE("Skipping unrecognized instruction.\n");
+            pToken += param_size;
+            continue;
+        }
 
         /* Handle declarations */
-        } else if (WINED3DSIO_DCL == curOpcode->opcode) {
-
-            DWORD usage = *pToken++;
-            DWORD param = *pToken++;
-            DWORD regtype = shader_get_regtype(param);
-            unsigned int regnum = param & WINED3DSP_REGNUM_MASK;
-
-            /* Vshader: mark attributes used
-               Pshader: mark 3.0 input registers used, save token */
-            if (WINED3DSPR_INPUT == regtype) {
-
-                if (!pshader)
-                    reg_maps->attributes[regnum] = 1;
-                else
-                    reg_maps->packed_input[regnum] = 1;
-
-                semantics_in[regnum].usage = (usage & WINED3DSP_DCL_USAGE_MASK) >> WINED3DSP_DCL_USAGE_SHIFT;
-                semantics_in[regnum].usage_idx =
-                        (usage & WINED3DSP_DCL_USAGEINDEX_MASK) >> WINED3DSP_DCL_USAGEINDEX_SHIFT;
-                shader_parse_dst_param(param, 0, &semantics_in[regnum].reg);
-
-            /* Vshader: mark 3.0 output registers used, save token */
-            } else if (WINED3DSPR_OUTPUT == regtype) {
-                reg_maps->packed_output[regnum] = 1;
-                semantics_out[regnum].usage = (usage & WINED3DSP_DCL_USAGE_MASK) >> WINED3DSP_DCL_USAGE_SHIFT;
-                semantics_out[regnum].usage_idx =
-                        (usage & WINED3DSP_DCL_USAGEINDEX_MASK) >> WINED3DSP_DCL_USAGEINDEX_SHIFT;
-                shader_parse_dst_param(param, 0, &semantics_out[regnum].reg);
+        if (ins.handler_idx == WINED3DSIH_DCL)
+        {
+            struct wined3d_shader_semantic semantic;
 
-                if (usage & (WINED3DDECLUSAGE_FOG << WINED3DSP_DCL_USAGE_SHIFT))
-                    reg_maps->fog = 1;
+            fe->shader_read_semantic(&pToken, &semantic);
 
-            /* Save sampler usage token */
-            } else if (WINED3DSPR_SAMPLER == regtype)
-                reg_maps->samplers[regnum] = usage;
+            switch (semantic.reg.reg.type)
+            {
+                /* Vshader: mark attributes used
+                 * Pshader: mark 3.0 input registers used, save token */
+                case WINED3DSPR_INPUT:
+                    if (!pshader) reg_maps->attributes[semantic.reg.reg.idx] = 1;
+                    else reg_maps->packed_input[semantic.reg.reg.idx] = 1;
+                    semantics_in[semantic.reg.reg.idx] = semantic;
+                    break;
+
+                /* Vshader: mark 3.0 output registers used, save token */
+                case WINED3DSPR_OUTPUT:
+                    reg_maps->packed_output[semantic.reg.reg.idx] = 1;
+                    semantics_out[semantic.reg.reg.idx] = semantic;
+                    if (semantic.usage == WINED3DDECLUSAGE_FOG) reg_maps->fog = 1;
+                    break;
+
+                /* Save sampler usage token */
+                case WINED3DSPR_SAMPLER:
+                    reg_maps->sampler_type[semantic.reg.reg.idx] = semantic.sampler_type;
+                    break;
 
-        } else if (WINED3DSIO_DEF == curOpcode->opcode) {
+                default:
+                    TRACE("Not recording DCL register type %#x.\n", semantic.reg.reg.type);
+                    break;
+            }
+        }
+        else if (ins.handler_idx == WINED3DSIH_DEF)
+        {
+            struct wined3d_shader_dst_param dst;
+            struct wined3d_shader_src_param rel_addr;
 
             local_constant* lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(local_constant));
             if (!lconst) return E_OUTOFMEMORY;
-            lconst->idx = *pToken & WINED3DSP_REGNUM_MASK;
-            memcpy(lconst->value, pToken + 1, 4 * sizeof(DWORD));
+
+            fe->shader_read_dst_param(fe_data, &pToken, &dst, &rel_addr);
+            lconst->idx = dst.reg.idx;
+
+            memcpy(lconst->value, pToken, 4 * sizeof(DWORD));
+            pToken += 4;
 
             /* In pixel shader 1.X shaders, the constants are clamped between [-1;1] */
-            if (WINED3DSHADER_VERSION_MAJOR(shader_version) == 1 && pshader)
+            if (shader_version.major == 1 && pshader)
             {
                 float *value = (float *) lconst->value;
                 if(value[0] < -1.0) value[0] = -1.0;
@@ -340,176 +461,185 @@ HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, struct shader_reg_m
             }
 
             list_add_head(&This->baseShader.constantsF, &lconst->entry);
-            pToken += curOpcode->num_params;
-
-        } else if (WINED3DSIO_DEFI == curOpcode->opcode) {
+        }
+        else if (ins.handler_idx == WINED3DSIH_DEFI)
+        {
+            struct wined3d_shader_dst_param dst;
+            struct wined3d_shader_src_param rel_addr;
 
             local_constant* lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(local_constant));
             if (!lconst) return E_OUTOFMEMORY;
-            lconst->idx = *pToken & WINED3DSP_REGNUM_MASK;
-            memcpy(lconst->value, pToken + 1, 4 * sizeof(DWORD));
-            list_add_head(&This->baseShader.constantsI, &lconst->entry);
-            pToken += curOpcode->num_params;
 
-        } else if (WINED3DSIO_DEFB == curOpcode->opcode) {
+            fe->shader_read_dst_param(fe_data, &pToken, &dst, &rel_addr);
+            lconst->idx = dst.reg.idx;
+
+            memcpy(lconst->value, pToken, 4 * sizeof(DWORD));
+            pToken += 4;
+
+            list_add_head(&This->baseShader.constantsI, &lconst->entry);
+        }
+        else if (ins.handler_idx == WINED3DSIH_DEFB)
+        {
+            struct wined3d_shader_dst_param dst;
+            struct wined3d_shader_src_param rel_addr;
 
             local_constant* lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(local_constant));
             if (!lconst) return E_OUTOFMEMORY;
-            lconst->idx = *pToken & WINED3DSP_REGNUM_MASK;
-            memcpy(lconst->value, pToken + 1, 1 * sizeof(DWORD));
-            list_add_head(&This->baseShader.constantsB, &lconst->entry);
-            pToken += curOpcode->num_params;
 
+            fe->shader_read_dst_param(fe_data, &pToken, &dst, &rel_addr);
+            lconst->idx = dst.reg.idx;
+
+            memcpy(lconst->value, pToken, sizeof(DWORD));
+            ++pToken;
+
+            list_add_head(&This->baseShader.constantsB, &lconst->entry);
+        }
         /* If there's a loop in the shader */
-        } else if (WINED3DSIO_LOOP == curOpcode->opcode ||
-                   WINED3DSIO_REP == curOpcode->opcode) {
+        else if (ins.handler_idx == WINED3DSIH_LOOP
+                || ins.handler_idx == WINED3DSIH_REP)
+        {
+            struct wined3d_shader_src_param src, rel_addr;
+
+            fe->shader_read_src_param(fe_data, &pToken, &src, &rel_addr);
+
+            /* Rep and Loop always use an integer constant for the control parameters */
+            if (ins.handler_idx == WINED3DSIH_REP)
+            {
+                reg_maps->integer_constants |= 1 << src.reg.idx;
+            }
+            else
+            {
+                fe->shader_read_src_param(fe_data, &pToken, &src, &rel_addr);
+                reg_maps->integer_constants |= 1 << src.reg.idx;
+            }
+
             cur_loop_depth++;
             if(cur_loop_depth > max_loop_depth)
                 max_loop_depth = cur_loop_depth;
-            pToken += curOpcode->num_params;
-
-            /* Rep and Loop always use an integer constant for the control parameters */
-            This->baseShader.uses_int_consts = TRUE;
-        } else if (WINED3DSIO_ENDLOOP == curOpcode->opcode ||
-                   WINED3DSIO_ENDREP == curOpcode->opcode) {
+        }
+        else if (ins.handler_idx == WINED3DSIH_ENDLOOP
+                || ins.handler_idx == WINED3DSIH_ENDREP)
+        {
             cur_loop_depth--;
-
+        }
         /* For subroutine prototypes */
-        } else if (WINED3DSIO_LABEL == curOpcode->opcode) {
-
-            DWORD snum = *pToken & WINED3DSP_REGNUM_MASK; 
-            reg_maps->labels[snum] = 1;
-            pToken += curOpcode->num_params;
+        else if (ins.handler_idx == WINED3DSIH_LABEL)
+        {
+            struct wined3d_shader_src_param src, rel_addr;
 
+            fe->shader_read_src_param(fe_data, &pToken, &src, &rel_addr);
+            reg_maps->labels[src.reg.idx] = 1;
+        }
         /* Set texture, address, temporary registers */
-        } else {
+        else
+        {
             int i, limit;
 
-            /* Declare 1.X samplers implicitly, based on the destination reg. number */
-            if (WINED3DSHADER_VERSION_MAJOR(shader_version) == 1
-                    && pshader /* Filter different instructions with the same enum values in VS */
-                    && (WINED3DSIO_TEX == curOpcode->opcode
-                        || WINED3DSIO_TEXBEM == curOpcode->opcode
-                        || WINED3DSIO_TEXBEML == curOpcode->opcode
-                        || WINED3DSIO_TEXDP3TEX == curOpcode->opcode
-                        || WINED3DSIO_TEXM3x2TEX == curOpcode->opcode
-                        || WINED3DSIO_TEXM3x3SPEC == curOpcode->opcode
-                        || WINED3DSIO_TEXM3x3TEX == curOpcode->opcode
-                        || WINED3DSIO_TEXM3x3VSPEC == curOpcode->opcode
-                        || WINED3DSIO_TEXREG2AR == curOpcode->opcode
-                        || WINED3DSIO_TEXREG2GB == curOpcode->opcode
-                        || WINED3DSIO_TEXREG2RGB == curOpcode->opcode))
-            {
-                /* Fake sampler usage, only set reserved bit and ttype */
-                DWORD sampler_code = *pToken & WINED3DSP_REGNUM_MASK;
-
-                TRACE("Setting fake 2D sampler for 1.x pixelshader\n");
-                reg_maps->samplers[sampler_code] = (0x1 << 31) | WINED3DSTT_2D;
-
-                /* texbem is only valid with < 1.4 pixel shaders */
-                if(WINED3DSIO_TEXBEM  == curOpcode->opcode ||
-                    WINED3DSIO_TEXBEML == curOpcode->opcode) {
-                    reg_maps->bumpmat[sampler_code] = TRUE;
-                    if(WINED3DSIO_TEXBEML == curOpcode->opcode) {
-                        reg_maps->luminanceparams[sampler_code] = TRUE;
-                    }
-                }
-            }
-            if(WINED3DSIO_NRM  == curOpcode->opcode) {
-                reg_maps->usesnrm = 1;
-            } else if(WINED3DSIO_BEM == curOpcode->opcode && pshader) {
-                DWORD regnum = *pToken & WINED3DSP_REGNUM_MASK;
-                reg_maps->bumpmat[regnum] = TRUE;
-            } else if(WINED3DSIO_DSY  == curOpcode->opcode) {
-                reg_maps->usesdsy = 1;
-            }
-
             /* This will loop over all the registers and try to
-             * make a bitmask of the ones we're interested in. 
+             * make a bitmask of the ones we're interested in.
              *
-             * Relative addressing tokens are ignored, but that's 
-             * okay, since we'll catch any address registers when 
+             * Relative addressing tokens are ignored, but that's
+             * okay, since we'll catch any address registers when
              * they are initialized (required by spec) */
 
-            limit = (opcode_token & WINED3DSHADER_INSTRUCTION_PREDICATED)?
-                curOpcode->num_params + 1: curOpcode->num_params;
-
-            for (i = 0; i < limit; ++i) {
-
-                DWORD param, addr_token, reg, regtype;
-                pToken += shader_get_param(pToken, shader_version, &param, &addr_token);
-
-                regtype = shader_get_regtype(param);
-                reg = param & WINED3DSP_REGNUM_MASK;
+            if (ins.dst_count)
+            {
+                struct wined3d_shader_dst_param dst_param;
+                struct wined3d_shader_src_param dst_rel_addr;
 
-                if (WINED3DSPR_TEXTURE == regtype) { /* vs: WINED3DSPR_ADDR */
+                fe->shader_read_dst_param(fe_data, &pToken, &dst_param, &dst_rel_addr);
 
-                    if (pshader)
-                        reg_maps->texcoord[reg] = 1;
-                    else
-                        reg_maps->address[reg] = 1;
+                /* WINED3DSPR_TEXCRDOUT is the same as WINED3DSPR_OUTPUT. _OUTPUT can be > MAX_REG_TEXCRD and
+                 * is used in >= 3.0 shaders. Filter 3.0 shaders to prevent overflows, and also filter pixel
+                 * shaders because TECRDOUT isn't used in them, but future register types might cause issues */
+                if (!pshader && shader_version.major < 3 && dst_param.reg.type == WINED3DSPR_TEXCRDOUT)
+                {
+                    reg_maps->texcoord_mask[dst_param.reg.type] |= dst_param.write_mask;
                 }
-
-                else if (WINED3DSPR_TEMP == regtype)
-                    reg_maps->temporary[reg] = 1;
-
-                else if (WINED3DSPR_INPUT == regtype) {
-                    if( !pshader)
-                        reg_maps->attributes[reg] = 1;
-                    else {
-                        if(param & WINED3DSHADER_ADDRMODE_RELATIVE) {
-                            /* If relative addressing is used, we must assume that all registers
-                             * are used. Even if it is a construct like v3[aL], we can't assume
-                             * that v0, v1 and v2 aren't read because aL can be negative
-                             */
-                            unsigned int i;
-                            for(i = 0; i < MAX_REG_INPUT; i++) {
-                                ((IWineD3DPixelShaderImpl *) This)->input_reg_used[i] = TRUE;
-                            }
-                        } else {
-                            ((IWineD3DPixelShaderImpl *) This)->input_reg_used[reg] = TRUE;
-                        }
-                    }
+                else
+                {
+                    shader_record_register_usage(This, reg_maps, dst_param.reg.type,
+                            dst_param.reg.idx, !!dst_param.reg.rel_addr, pshader);
                 }
 
-                else if (WINED3DSPR_RASTOUT == regtype && reg == 1)
-                    reg_maps->fog = 1;
+                /* Declare 1.X samplers implicitly, based on the destination reg. number */
+                if (shader_version.major == 1
+                        && pshader /* Filter different instructions with the same enum values in VS */
+                        && (ins.handler_idx == WINED3DSIH_TEX
+                            || ins.handler_idx == WINED3DSIH_TEXBEM
+                            || ins.handler_idx == WINED3DSIH_TEXBEML
+                            || ins.handler_idx == WINED3DSIH_TEXDP3TEX
+                            || ins.handler_idx == WINED3DSIH_TEXM3x2TEX
+                            || ins.handler_idx == WINED3DSIH_TEXM3x3SPEC
+                            || ins.handler_idx == WINED3DSIH_TEXM3x3TEX
+                            || ins.handler_idx == WINED3DSIH_TEXM3x3VSPEC
+                            || ins.handler_idx == WINED3DSIH_TEXREG2AR
+                            || ins.handler_idx == WINED3DSIH_TEXREG2GB
+                            || ins.handler_idx == WINED3DSIH_TEXREG2RGB))
+                {
+                    /* Fake sampler usage, only set reserved bit and ttype */
+                    DWORD sampler_code = dst_param.reg.idx;
 
-                else if (WINED3DSPR_MISCTYPE == regtype && reg == 0 && pshader)
-                    reg_maps->vpos = 1;
+                    TRACE("Setting fake 2D sampler for 1.x pixelshader\n");
+                    reg_maps->sampler_type[sampler_code] = WINED3DSTT_2D;
 
-                else if(WINED3DSPR_CONST == regtype) {
-                    if(param & WINED3DSHADER_ADDRMODE_RELATIVE) {
-                        if(!pshader) {
-                            if(reg <= ((IWineD3DVertexShaderImpl *) This)->min_rel_offset) {
-                                ((IWineD3DVertexShaderImpl *) This)->min_rel_offset = reg;
-                            } else if(reg >= ((IWineD3DVertexShaderImpl *) This)->max_rel_offset) {
-                                ((IWineD3DVertexShaderImpl *) This)->max_rel_offset = reg;
-                            }
+                    /* texbem is only valid with < 1.4 pixel shaders */
+                    if (ins.handler_idx == WINED3DSIH_TEXBEM
+                            || ins.handler_idx == WINED3DSIH_TEXBEML)
+                    {
+                        reg_maps->bumpmat[sampler_code] = TRUE;
+                        if (ins.handler_idx == WINED3DSIH_TEXBEML)
+                        {
+                            reg_maps->luminanceparams[sampler_code] = TRUE;
                         }
-                        reg_maps->usesrelconstF = TRUE;
                     }
                 }
-                else if(WINED3DSPR_CONSTINT == regtype) {
-                    This->baseShader.uses_int_consts = TRUE;
-                }
-                else if(WINED3DSPR_CONSTBOOL == regtype) {
-                    This->baseShader.uses_bool_consts = TRUE;
+                else if (pshader && ins.handler_idx == WINED3DSIH_BEM)
+                {
+                    reg_maps->bumpmat[dst_param.reg.idx] = TRUE;
                 }
+            }
 
-                /* WINED3DSPR_TEXCRDOUT is the same as WINED3DSPR_OUTPUT. _OUTPUT can be > MAX_REG_TEXCRD and is used
-                 * in >= 3.0 shaders. Filter 3.0 shaders to prevent overflows, and also filter pixel shaders because TECRDOUT
-                 * isn't used in them, but future register types might cause issues
-                 */
-                else if (WINED3DSPR_TEXCRDOUT == regtype && i == 0 /* Only look at writes */
-                        && !pshader && WINED3DSHADER_VERSION_MAJOR(shader_version) < 3)
+            if (ins.handler_idx == WINED3DSIH_NRM)
+            {
+                reg_maps->usesnrm = 1;
+            }
+            else if (ins.handler_idx == WINED3DSIH_DSY)
+            {
+                reg_maps->usesdsy = 1;
+            }
+            else if(ins.handler_idx == WINED3DSIH_TEXLDD)
+            {
+                reg_maps->usestexldd = 1;
+            }
+
+            limit = ins.src_count + (ins.predicate ? 1 : 0);
+            for (i = 0; i < limit; ++i)
+            {
+                struct wined3d_shader_src_param src_param, src_rel_addr;
+
+                fe->shader_read_src_param(fe_data, &pToken, &src_param, &src_rel_addr);
+                switch(get_instr_regcount(ins.handler_idx, i))
                 {
-                    reg_maps->texcoord_mask[reg] |= shader_get_writemask(param);
+                    case 4:
+                        shader_record_register_usage(This, reg_maps, src_param.reg.type,
+                                src_param.reg.idx + 3, !!src_param.reg.rel_addr, pshader);
+                        /* drop through */
+                    case 3:
+                        shader_record_register_usage(This, reg_maps, src_param.reg.type,
+                                src_param.reg.idx + 2, !!src_param.reg.rel_addr, pshader);
+                        /* drop through */
+                    case 2:
+                        shader_record_register_usage(This, reg_maps, src_param.reg.type,
+                                src_param.reg.idx + 1, !!src_param.reg.rel_addr, pshader);
+                        /* drop through */
+                    case 1:
+                        shader_record_register_usage(This, reg_maps, src_param.reg.type,
+                                src_param.reg.idx, !!src_param.reg.rel_addr, pshader);
                 }
             }
         }
     }
-    ++pToken;
     reg_maps->loop_depth = max_loop_depth;
 
     This->baseShader.functionLength = ((char *)pToken - (char *)byte_code);
@@ -517,389 +647,395 @@ HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, struct shader_reg_m
     return WINED3D_OK;
 }
 
-static void shader_dump_decl_usage(DWORD decl, DWORD param, DWORD shader_version)
+static void shader_dump_decl_usage(const struct wined3d_shader_semantic *semantic,
+        const struct wined3d_shader_version *shader_version)
 {
-    DWORD regtype = shader_get_regtype(param);
-
     TRACE("dcl");
 
-    if (regtype == WINED3DSPR_SAMPLER) {
-        DWORD ttype = decl & WINED3DSP_TEXTURETYPE_MASK;
-
-        switch (ttype) {
+    if (semantic->reg.reg.type == WINED3DSPR_SAMPLER)
+    {
+        switch (semantic->sampler_type)
+        {
             case WINED3DSTT_2D: TRACE("_2d"); break;
             case WINED3DSTT_CUBE: TRACE("_cube"); break;
             case WINED3DSTT_VOLUME: TRACE("_volume"); break;
-            default: TRACE("_unknown_ttype(0x%08x)", ttype);
-       }
-
-    } else { 
-
-        DWORD usage = decl & WINED3DSP_DCL_USAGE_MASK;
-        DWORD idx = (decl & WINED3DSP_DCL_USAGEINDEX_MASK) >> WINED3DSP_DCL_USAGEINDEX_SHIFT;
-
+            default: TRACE("_unknown_ttype(0x%08x)", semantic->sampler_type);
+        }
+    }
+    else
+    {
         /* Pixel shaders 3.0 don't have usage semantics */
-        if (shader_is_pshader_version(shader_version) && shader_version < WINED3DPS_VERSION(3,0))
+        if (shader_is_pshader_version(shader_version->type) && shader_version->major < 3)
             return;
         else
             TRACE("_");
 
-        switch(usage) {
-        case WINED3DDECLUSAGE_POSITION:
-            TRACE("position%d", idx);
-            break;
-        case WINED3DDECLUSAGE_BLENDINDICES:
-            TRACE("blend");
-            break;
-        case WINED3DDECLUSAGE_BLENDWEIGHT:
-            TRACE("weight");
-            break;
-        case WINED3DDECLUSAGE_NORMAL:
-            TRACE("normal%d", idx);
-            break;
-        case WINED3DDECLUSAGE_PSIZE:
-            TRACE("psize");
-            break;
-        case WINED3DDECLUSAGE_COLOR:
-            if(idx == 0)  {
-                TRACE("color");
-            } else {
-                TRACE("specular%d", (idx - 1));
-            }
-            break;
-        case WINED3DDECLUSAGE_TEXCOORD:
-            TRACE("texture%d", idx);
-            break;
-        case WINED3DDECLUSAGE_TANGENT:
-            TRACE("tangent");
-            break;
-        case WINED3DDECLUSAGE_BINORMAL:
-            TRACE("binormal");
-            break;
-        case WINED3DDECLUSAGE_TESSFACTOR:
-            TRACE("tessfactor");
-            break;
-        case WINED3DDECLUSAGE_POSITIONT:
-            TRACE("positionT%d", idx);
-            break;
-        case WINED3DDECLUSAGE_FOG:
-            TRACE("fog");
-            break;
-        case WINED3DDECLUSAGE_DEPTH:
-            TRACE("depth");
-            break;
-        case WINED3DDECLUSAGE_SAMPLE:
-            TRACE("sample");
-            break;
-        default:
-            FIXME("unknown_semantics(0x%08x)", usage);
+        switch (semantic->usage)
+        {
+            case WINED3DDECLUSAGE_POSITION:
+                TRACE("position%d", semantic->usage_idx);
+                break;
+            case WINED3DDECLUSAGE_BLENDINDICES:
+                TRACE("blend");
+                break;
+            case WINED3DDECLUSAGE_BLENDWEIGHT:
+                TRACE("weight");
+                break;
+            case WINED3DDECLUSAGE_NORMAL:
+                TRACE("normal%d", semantic->usage_idx);
+                break;
+            case WINED3DDECLUSAGE_PSIZE:
+                TRACE("psize");
+                break;
+            case WINED3DDECLUSAGE_COLOR:
+                if (semantic->usage_idx == 0) TRACE("color");
+                else TRACE("specular%d", (semantic->usage_idx - 1));
+                break;
+            case WINED3DDECLUSAGE_TEXCOORD:
+                TRACE("texture%d", semantic->usage_idx);
+                break;
+            case WINED3DDECLUSAGE_TANGENT:
+                TRACE("tangent");
+                break;
+            case WINED3DDECLUSAGE_BINORMAL:
+                TRACE("binormal");
+                break;
+            case WINED3DDECLUSAGE_TESSFACTOR:
+                TRACE("tessfactor");
+                break;
+            case WINED3DDECLUSAGE_POSITIONT:
+                TRACE("positionT%d", semantic->usage_idx);
+                break;
+            case WINED3DDECLUSAGE_FOG:
+                TRACE("fog");
+                break;
+            case WINED3DDECLUSAGE_DEPTH:
+                TRACE("depth");
+                break;
+            case WINED3DDECLUSAGE_SAMPLE:
+                TRACE("sample");
+                break;
+            default:
+                FIXME("unknown_semantics(0x%08x)", semantic->usage);
         }
     }
 }
 
-static void shader_dump_arr_entry(const DWORD param, const DWORD addr_token,
-        unsigned int reg, int input, DWORD shader_version)
-{
-    char relative =
-        ((param & WINED3DSHADER_ADDRESSMODE_MASK) == WINED3DSHADER_ADDRMODE_RELATIVE);
-
-    if (relative) {
-        TRACE("[");
-        if (addr_token)
-            shader_dump_param(addr_token, 0, input, shader_version);
-        else
-            TRACE("a0.x");
-        TRACE(" + ");
-     }
-     TRACE("%u", reg);
-     if (relative)
-         TRACE("]");
-}
-
-static void shader_dump_param(const DWORD param, const DWORD addr_token, int input, DWORD shader_version)
+static void shader_dump_register(WINED3DSHADER_PARAM_REGISTER_TYPE register_type, UINT register_idx,
+        enum wined3d_immconst_type immconst_type, const DWORD *immconst_data,
+        const struct wined3d_shader_src_param *rel_addr, const struct wined3d_shader_version *shader_version)
 {
-    static const char * const rastout_reg_names[] = { "oPos", "oFog", "oPts" };
-    static const char * const misctype_reg_names[] = { "vPos", "vFace"};
-    const char *swizzle_reg_chars = "xyzw";
-
-    DWORD reg = param & WINED3DSP_REGNUM_MASK;
-    DWORD regtype = shader_get_regtype(param);
-    DWORD modifier = param & WINED3DSP_SRCMOD_MASK;
+    static const char * const rastout_reg_names[] = {"oPos", "oFog", "oPts"};
+    static const char * const misctype_reg_names[] = {"vPos", "vFace"};
+    UINT offset = register_idx;
 
-    /* There are some minor differences between pixel and vertex shaders */
-    char pshader = shader_is_pshader_version(shader_version);
-
-    if (input) {
-        if ( (modifier == WINED3DSPSM_NEG) ||
-             (modifier == WINED3DSPSM_BIASNEG) ||
-             (modifier == WINED3DSPSM_SIGNNEG) ||
-             (modifier == WINED3DSPSM_X2NEG) ||
-             (modifier == WINED3DSPSM_ABSNEG) )
-            TRACE("-");
-        else if (modifier == WINED3DSPSM_COMP)
-            TRACE("1-");
-        else if (modifier == WINED3DSPSM_NOT)
-            TRACE("!");
-
-        if (modifier == WINED3DSPSM_ABS || modifier == WINED3DSPSM_ABSNEG) 
-            TRACE("abs(");
-    }
-
-    switch (regtype) {
+    switch (register_type)
+    {
         case WINED3DSPR_TEMP:
-            TRACE("r%u", reg);
+            TRACE("r");
             break;
+
         case WINED3DSPR_INPUT:
             TRACE("v");
-            shader_dump_arr_entry(param, addr_token, reg, input, shader_version);
             break;
+
         case WINED3DSPR_CONST:
         case WINED3DSPR_CONST2:
         case WINED3DSPR_CONST3:
         case WINED3DSPR_CONST4:
             TRACE("c");
-            shader_dump_arr_entry(param, addr_token, shader_get_float_offset(param), input, shader_version);
+            offset = shader_get_float_offset(register_type, register_idx);
             break;
-        case WINED3DSPR_TEXTURE: /* vs: case D3DSPR_ADDR */
-            TRACE("%c%u", (pshader? 't':'a'), reg);
-            break;        
+
+        case WINED3DSPR_TEXTURE: /* vs: case WINED3DSPR_ADDR */
+            TRACE("%c", shader_is_pshader_version(shader_version->type) ? 't' : 'a');
+            break;
+
         case WINED3DSPR_RASTOUT:
-            TRACE("%s", rastout_reg_names[reg]);
+            TRACE("%s", rastout_reg_names[register_idx]);
             break;
+
         case WINED3DSPR_COLOROUT:
-            TRACE("oC%u", reg);
+            TRACE("oC");
             break;
+
         case WINED3DSPR_DEPTHOUT:
             TRACE("oDepth");
             break;
+
         case WINED3DSPR_ATTROUT:
-            TRACE("oD%u", reg);
+            TRACE("oD");
             break;
-        case WINED3DSPR_TEXCRDOUT: 
 
+        case WINED3DSPR_TEXCRDOUT:
             /* Vertex shaders >= 3.0 use general purpose output registers
              * (WINED3DSPR_OUTPUT), which can include an address token */
-
-            if (WINED3DSHADER_VERSION_MAJOR(shader_version) >= 3) {
-                TRACE("o");
-                shader_dump_arr_entry(param, addr_token, reg, input, shader_version);
-            }
-            else 
-               TRACE("oT%u", reg);
+            if (shader_version->major >= 3) TRACE("o");
+            else TRACE("oT");
             break;
+
         case WINED3DSPR_CONSTINT:
             TRACE("i");
-            shader_dump_arr_entry(param, addr_token, reg, input, shader_version);
             break;
+
         case WINED3DSPR_CONSTBOOL:
             TRACE("b");
-            shader_dump_arr_entry(param, addr_token, reg, input, shader_version);
             break;
+
         case WINED3DSPR_LABEL:
-            TRACE("l%u", reg);
+            TRACE("l");
             break;
+
         case WINED3DSPR_LOOP:
             TRACE("aL");
             break;
+
         case WINED3DSPR_SAMPLER:
-            TRACE("s%u", reg);
+            TRACE("s");
             break;
+
         case WINED3DSPR_MISCTYPE:
-            if (reg > 1) {
-                FIXME("Unhandled misctype register %d\n", reg);
-            } else {
-                TRACE("%s", misctype_reg_names[reg]);
-            }
+            if (register_idx > 1) FIXME("Unhandled misctype register %d\n", register_idx);
+            else TRACE("%s", misctype_reg_names[register_idx]);
             break;
+
         case WINED3DSPR_PREDICATE:
-            TRACE("p%u", reg);
+            TRACE("p");
             break;
+
+        case WINED3DSPR_IMMCONST:
+            TRACE("l");
+            break;
+
         default:
-            TRACE("unhandled_rtype(%#x)", regtype);
+            TRACE("unhandled_rtype(%#x)", register_type);
             break;
-   }
-
-   if (!input) {
-       /* operand output (for modifiers and shift, see dump_ins_modifiers) */
-
-       if ((param & WINED3DSP_WRITEMASK_ALL) != WINED3DSP_WRITEMASK_ALL) {
-           TRACE(".");
-           if (param & WINED3DSP_WRITEMASK_0) TRACE("%c", swizzle_reg_chars[0]);
-           if (param & WINED3DSP_WRITEMASK_1) TRACE("%c", swizzle_reg_chars[1]);
-           if (param & WINED3DSP_WRITEMASK_2) TRACE("%c", swizzle_reg_chars[2]);
-           if (param & WINED3DSP_WRITEMASK_3) TRACE("%c", swizzle_reg_chars[3]);
-       }
-
-   } else {
-        /** operand input */
-        DWORD swizzle = (param & WINED3DSP_SWIZZLE_MASK) >> WINED3DSP_SWIZZLE_SHIFT;
+    }
+
+    if (register_type == WINED3DSPR_IMMCONST)
+    {
+        TRACE("(");
+        switch (immconst_type)
+        {
+            case WINED3D_IMMCONST_FLOAT:
+                TRACE("%.8e", *(float *)immconst_data);
+                break;
+
+            case WINED3D_IMMCONST_FLOAT4:
+                TRACE("%.8e, %.8e, %.8e, %.8e",
+                        *(float *)&immconst_data[0], *(float *)&immconst_data[1],
+                        *(float *)&immconst_data[2], *(float *)&immconst_data[3]);
+                break;
+
+            default:
+                TRACE("<unhandled immconst_type %#x>", immconst_type);
+                break;
+        }
+        TRACE(")");
+    }
+    else if (register_type != WINED3DSPR_RASTOUT && register_type != WINED3DSPR_MISCTYPE)
+    {
+        if (rel_addr)
+        {
+            TRACE("[");
+            shader_dump_src_param(rel_addr, shader_version);
+            TRACE(" + ");
+        }
+        TRACE("%u", offset);
+        if (rel_addr) TRACE("]");
+    }
+}
+
+void shader_dump_dst_param(const struct wined3d_shader_dst_param *param,
+        const struct wined3d_shader_version *shader_version)
+{
+    DWORD write_mask = param->write_mask;
+
+    shader_dump_register(param->reg.type, param->reg.idx, 0, NULL, param->reg.rel_addr, shader_version);
+
+    if (write_mask != WINED3DSP_WRITEMASK_ALL)
+    {
+        static const char *write_mask_chars = "xyzw";
+
+        TRACE(".");
+        if (write_mask & WINED3DSP_WRITEMASK_0) TRACE("%c", write_mask_chars[0]);
+        if (write_mask & WINED3DSP_WRITEMASK_1) TRACE("%c", write_mask_chars[1]);
+        if (write_mask & WINED3DSP_WRITEMASK_2) TRACE("%c", write_mask_chars[2]);
+        if (write_mask & WINED3DSP_WRITEMASK_3) TRACE("%c", write_mask_chars[3]);
+    }
+}
+
+void shader_dump_src_param(const struct wined3d_shader_src_param *param,
+        const struct wined3d_shader_version *shader_version)
+{
+    DWORD src_modifier = param->modifiers;
+    DWORD swizzle = param->swizzle;
+
+    if (src_modifier == WINED3DSPSM_NEG
+            || src_modifier == WINED3DSPSM_BIASNEG
+            || src_modifier == WINED3DSPSM_SIGNNEG
+            || src_modifier == WINED3DSPSM_X2NEG
+            || src_modifier == WINED3DSPSM_ABSNEG)
+        TRACE("-");
+    else if (src_modifier == WINED3DSPSM_COMP)
+        TRACE("1-");
+    else if (src_modifier == WINED3DSPSM_NOT)
+        TRACE("!");
+
+    if (src_modifier == WINED3DSPSM_ABS || src_modifier == WINED3DSPSM_ABSNEG)
+        TRACE("abs(");
+
+    shader_dump_register(param->reg.type, param->reg.idx, param->reg.immconst_type,
+            param->reg.immconst_data, param->reg.rel_addr, shader_version);
+
+    if (src_modifier)
+    {
+        switch (src_modifier)
+        {
+            case WINED3DSPSM_NONE:    break;
+            case WINED3DSPSM_NEG:     break;
+            case WINED3DSPSM_NOT:     break;
+            case WINED3DSPSM_BIAS:    TRACE("_bias"); break;
+            case WINED3DSPSM_BIASNEG: TRACE("_bias"); break;
+            case WINED3DSPSM_SIGN:    TRACE("_bx2"); break;
+            case WINED3DSPSM_SIGNNEG: TRACE("_bx2"); break;
+            case WINED3DSPSM_COMP:    break;
+            case WINED3DSPSM_X2:      TRACE("_x2"); break;
+            case WINED3DSPSM_X2NEG:   TRACE("_x2"); break;
+            case WINED3DSPSM_DZ:      TRACE("_dz"); break;
+            case WINED3DSPSM_DW:      TRACE("_dw"); break;
+            case WINED3DSPSM_ABSNEG:  TRACE(")"); break;
+            case WINED3DSPSM_ABS:     TRACE(")"); break;
+            default:
+                                      TRACE("_unknown_modifier(%#x)", src_modifier);
+        }
+    }
+
+    if (swizzle != WINED3DSP_NOSWIZZLE)
+    {
+        static const char *swizzle_chars = "xyzw";
         DWORD swizzle_x = swizzle & 0x03;
         DWORD swizzle_y = (swizzle >> 2) & 0x03;
         DWORD swizzle_z = (swizzle >> 4) & 0x03;
         DWORD swizzle_w = (swizzle >> 6) & 0x03;
 
-        if (0 != modifier) {
-            switch (modifier) {
-                case WINED3DSPSM_NONE:    break;
-                case WINED3DSPSM_NEG:     break;
-                case WINED3DSPSM_NOT:     break;
-                case WINED3DSPSM_BIAS:    TRACE("_bias"); break;
-                case WINED3DSPSM_BIASNEG: TRACE("_bias"); break;
-                case WINED3DSPSM_SIGN:    TRACE("_bx2"); break;
-                case WINED3DSPSM_SIGNNEG: TRACE("_bx2"); break;
-                case WINED3DSPSM_COMP:    break;
-                case WINED3DSPSM_X2:      TRACE("_x2"); break;
-                case WINED3DSPSM_X2NEG:   TRACE("_x2"); break;
-                case WINED3DSPSM_DZ:      TRACE("_dz"); break;
-                case WINED3DSPSM_DW:      TRACE("_dw"); break;
-                case WINED3DSPSM_ABSNEG:  TRACE(")"); break;
-                case WINED3DSPSM_ABS:     TRACE(")"); break;
-                default:
-                    TRACE("_unknown_modifier(%#x)", modifier >> WINED3DSP_SRCMOD_SHIFT);
-            }
+        if (swizzle_x == swizzle_y
+                && swizzle_x == swizzle_z
+                && swizzle_x == swizzle_w)
+        {
+            TRACE(".%c", swizzle_chars[swizzle_x]);
         }
-
-        /**
-        * swizzle bits fields:
-        *  RRGGBBAA
-        */
-        if ((WINED3DVS_NOSWIZZLE >> WINED3DVS_SWIZZLE_SHIFT) != swizzle) {
-            if (swizzle_x == swizzle_y &&
-                swizzle_x == swizzle_z &&
-                swizzle_x == swizzle_w) {
-                    TRACE(".%c", swizzle_reg_chars[swizzle_x]);
-            } else {
-                TRACE(".%c%c%c%c",
-                swizzle_reg_chars[swizzle_x],
-                swizzle_reg_chars[swizzle_y],
-                swizzle_reg_chars[swizzle_z],
-                swizzle_reg_chars[swizzle_w]);
-            }
+        else
+        {
+            TRACE(".%c%c%c%c", swizzle_chars[swizzle_x], swizzle_chars[swizzle_y],
+                    swizzle_chars[swizzle_z], swizzle_chars[swizzle_w]);
         }
     }
 }
 
 /* Shared code in order to generate the bulk of the shader string.
  * NOTE: A description of how to parse tokens can be found on msdn */
-void shader_generate_main(IWineD3DBaseShader *iface, SHADER_BUFFERbuffer,
-        const shader_reg_maps* reg_maps, CONST DWORD* pFunction)
+void shader_generate_main(IWineD3DBaseShader *iface, SHADER_BUFFER *buffer,
+        const shader_reg_maps *reg_maps, const DWORD *pFunction)
 {
     IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface;
     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device; /* To access shader backend callbacks */
-    const SHADER_OPCODE *opcode_table = This->baseShader.shader_ins;
     const SHADER_HANDLER *handler_table = device->shader_backend->shader_instruction_handler_table;
-    DWORD shader_version = reg_maps->shader_version;
+    const struct wined3d_shader_frontend *fe = This->baseShader.frontend;
+    void *fe_data = This->baseShader.frontend_data;
+    struct wined3d_shader_src_param src_rel_addr[4];
+    struct wined3d_shader_src_param src_param[4];
+    struct wined3d_shader_version shader_version;
+    struct wined3d_shader_src_param dst_rel_addr;
     struct wined3d_shader_dst_param dst_param;
     struct wined3d_shader_instruction ins;
+    struct wined3d_shader_context ctx;
     const DWORD *pToken = pFunction;
-    const SHADER_OPCODE *curOpcode;
     SHADER_HANDLER hw_fct;
     DWORD i;
 
     /* Initialize current parsing state */
-    ins.shader = iface;
-    ins.buffer = buffer;
-    ins.reg_maps = reg_maps;
+    ctx.shader = iface;
+    ctx.reg_maps = reg_maps;
+    ctx.buffer = buffer;
+
+    ins.ctx = &ctx;
     ins.dst = &dst_param;
+    ins.src = src_param;
     This->baseShader.parse_state.current_row = 0;
 
-    while (WINED3DPS_END() != *pToken)
-    {
-        DWORD opcode_token;
+    fe->shader_read_header(fe_data, &pToken, &shader_version);
 
-        /* Skip version token */
-        if (shader_is_version_token(*pToken))
-        {
-            ++pToken;
-            continue;
-        }
+    while (!fe->shader_is_end(fe_data, &pToken))
+    {
+        const char *comment;
+        UINT param_size;
 
         /* Skip comment tokens */
-        if (shader_is_comment(*pToken))
-        {
-            pToken += (*pToken & WINED3DSI_COMMENTSIZE_MASK) >> WINED3DSI_COMMENTSIZE_SHIFT;
-            ++pToken;
-            continue;
-        }
+        fe->shader_read_comment(&pToken, &comment);
+        if (comment) continue;
 
         /* Read opcode */
-        opcode_token = *pToken++;
-        curOpcode = shader_get_opcode(opcode_table, shader_version, opcode_token);
+        fe->shader_read_opcode(fe_data, &pToken, &ins, &param_size);
 
         /* Unknown opcode and its parameters */
-        if (!curOpcode)
+        if (ins.handler_idx == WINED3DSIH_TABLE_SIZE)
         {
-            FIXME("Unrecognized opcode: token=0x%08x\n", opcode_token);
-            pToken += shader_skip_unrecognized(pToken, shader_version);
+            TRACE("Skipping unrecognized instruction.\n");
+            pToken += param_size;
             continue;
         }
 
         /* Nothing to do */
-        if (WINED3DSIO_DCL == curOpcode->opcode
-                || WINED3DSIO_NOP == curOpcode->opcode
-                || WINED3DSIO_DEF == curOpcode->opcode
-                || WINED3DSIO_DEFI == curOpcode->opcode
-                || WINED3DSIO_DEFB == curOpcode->opcode
-                || WINED3DSIO_PHASE == curOpcode->opcode
-                || WINED3DSIO_RET == curOpcode->opcode)
+        if (ins.handler_idx == WINED3DSIH_DCL
+                || ins.handler_idx == WINED3DSIH_NOP
+                || ins.handler_idx == WINED3DSIH_DEF
+                || ins.handler_idx == WINED3DSIH_DEFI
+                || ins.handler_idx == WINED3DSIH_DEFB
+                || ins.handler_idx == WINED3DSIH_PHASE
+                || ins.handler_idx == WINED3DSIH_RET)
         {
-            pToken += shader_skip_opcode(curOpcode, opcode_token, shader_version);
+            pToken += param_size;
             continue;
         }
 
         /* Select handler */
-        hw_fct = handler_table[curOpcode->handler_idx];
+        hw_fct = handler_table[ins.handler_idx];
 
         /* Unhandled opcode */
         if (!hw_fct)
         {
-            FIXME("Can't handle opcode %s in hwShader\n", curOpcode->name);
-            pToken += shader_skip_opcode(curOpcode, opcode_token, shader_version);
+            FIXME("Backend can't handle opcode %#x\n", ins.handler_idx);
+            pToken += param_size;
             continue;
         }
 
-        ins.handler_idx = curOpcode->handler_idx;
-        ins.flags = opcode_token & WINED3D_OPCODESPECIFICCONTROL_MASK;
-        ins.coissue = opcode_token & WINED3DSI_COISSUE;
-
         /* Destination token */
-        ins.dst_count = curOpcode->dst_token ? 1 : 0;
-        if (ins.dst_count)
-        {
-            DWORD param, addr_param = 0;
-            pToken += shader_get_param(pToken, shader_version, &param, &addr_param);
-            shader_parse_dst_param(param, addr_param, &dst_param);
-        }
+        if (ins.dst_count) fe->shader_read_dst_param(fe_data, &pToken, &dst_param, &dst_rel_addr);
 
         /* Predication token */
-        if (opcode_token & WINED3DSHADER_INSTRUCTION_PREDICATED) ins.predicate = *pToken++;
+        if (ins.predicate) ins.predicate = *pToken++;
 
         /* Other source tokens */
-        ins.src_count = curOpcode->num_params - curOpcode->dst_token;
         for (i = 0; i < ins.src_count; ++i)
         {
-            DWORD param, addr_token = 0;
-            pToken += shader_get_param(pToken, shader_version, &param, &addr_token);
-            ins.src[i] = param;
-            ins.src_addr[i] = addr_token;
+            fe->shader_read_src_param(fe_data, &pToken, &src_param[i], &src_rel_addr[i]);
         }
 
         /* Call appropriate function for output target */
         hw_fct(&ins);
 
         /* Process instruction modifiers for GLSL apps ( _sat, etc. ) */
-        /* FIXME: This should be internal to the shader backend.
-         * Also, right now this is the only reason "shader_mode" exists. */
-        if (This->baseShader.shader_mode == SHADER_GLSL) shader_glsl_add_instruction_modifiers(&ins);
+        device->shader_backend->shader_add_instruction_modifiers(&ins);
     }
 }
 
-static void shader_dump_ins_modifiers(const DWORD output)
+static void shader_dump_ins_modifiers(const struct wined3d_shader_dst_param *dst)
 {
-    DWORD shift = (output & WINED3DSP_DSTSHIFT_MASK) >> WINED3DSP_DSTSHIFT_SHIFT;
-    DWORD mmask = output & WINED3DSP_DSTMOD_MASK;
+    DWORD mmask = dst->modifiers;
 
-    switch (shift) {
+    switch (dst->shift)
+    {
         case 0: break;
         case 13: TRACE("_d8"); break;
         case 14: TRACE("_d4"); break;
@@ -907,7 +1043,7 @@ static void shader_dump_ins_modifiers(const DWORD output)
         case 1: TRACE("_x2"); break;
         case 2: TRACE("_x4"); break;
         case 3: TRACE("_x8"); break;
-        default: TRACE("_unhandled_shift(%d)", shift); break;
+        default: TRACE("_unhandled_shift(%d)", dst->shift); break;
     }
 
     if (mmask & WINED3DSPDM_SATURATE)         TRACE("_sat");
@@ -916,161 +1052,157 @@ static void shader_dump_ins_modifiers(const DWORD output)
 
     mmask &= ~(WINED3DSPDM_SATURATE | WINED3DSPDM_PARTIALPRECISION | WINED3DSPDM_MSAMPCENTROID);
     if (mmask)
-        FIXME("_unrecognized_modifier(%#x)", mmask >> WINED3DSP_DSTMOD_SHIFT);
+        FIXME("_unrecognized_modifier(%#x)", mmask);
 }
 
-void shader_trace_init(const DWORD *pFunction, const SHADER_OPCODE *opcode_table)
+void shader_trace_init(const struct wined3d_shader_frontend *fe, void *fe_data, const DWORD *pFunction)
 {
+    struct wined3d_shader_version shader_version;
     const DWORD* pToken = pFunction;
-    const SHADER_OPCODE* curOpcode = NULL;
-    DWORD shader_version;
-    DWORD opcode_token;
     DWORD i;
 
     TRACE("Parsing %p\n", pFunction);
 
-    /* The version token is supposed to be the first token */
-    if (!shader_is_version_token(*pToken))
-    {
-        FIXME("First token is not a version token, invalid shader.\n");
-        return;
-    }
-    shader_version = *pToken++;
-    TRACE("%s_%u_%u\n", shader_is_pshader_version(shader_version) ? "ps": "vs",
-            WINED3DSHADER_VERSION_MAJOR(shader_version), WINED3DSHADER_VERSION_MINOR(shader_version));
+    fe->shader_read_header(fe_data, &pToken, &shader_version);
+
+    TRACE("%s_%u_%u\n", shader_is_pshader_version(shader_version.type) ? "ps": "vs",
+            shader_version.major, shader_version.minor);
 
-    while (WINED3DVS_END() != *pToken)
+    while (!fe->shader_is_end(fe_data, &pToken))
     {
-        if (shader_is_comment(*pToken)) /* comment */
+        struct wined3d_shader_instruction ins;
+        const char *comment;
+        UINT param_size;
+
+        /* comment */
+        fe->shader_read_comment(&pToken, &comment);
+        if (comment)
         {
-            DWORD comment_len = (*pToken & WINED3DSI_COMMENTSIZE_MASK) >> WINED3DSI_COMMENTSIZE_SHIFT;
-            ++pToken;
-            TRACE("//%s\n", (const char*)pToken);
-            pToken += comment_len;
+            TRACE("//%s\n", comment);
+            continue;
+        }
+
+        fe->shader_read_opcode(fe_data, &pToken, &ins, &param_size);
+        if (ins.handler_idx == WINED3DSIH_TABLE_SIZE)
+        {
+            TRACE("Skipping unrecognized instruction.\n");
+            pToken += param_size;
             continue;
         }
-        opcode_token = *pToken++;
-        curOpcode = shader_get_opcode(opcode_table, shader_version, opcode_token);
 
-        if (!curOpcode)
+        if (ins.handler_idx == WINED3DSIH_DCL)
         {
-            int tokens_read;
-            FIXME("Unrecognized opcode: token=0x%08x\n", opcode_token);
-            tokens_read = shader_skip_unrecognized(pToken, shader_version);
-            pToken += tokens_read;
+            struct wined3d_shader_semantic semantic;
+
+            fe->shader_read_semantic(&pToken, &semantic);
+
+            shader_dump_decl_usage(&semantic, &shader_version);
+            shader_dump_ins_modifiers(&semantic.reg);
+            TRACE(" ");
+            shader_dump_dst_param(&semantic.reg, &shader_version);
+        }
+        else if (ins.handler_idx == WINED3DSIH_DEF)
+        {
+            struct wined3d_shader_dst_param dst;
+            struct wined3d_shader_src_param rel_addr;
+
+            fe->shader_read_dst_param(fe_data, &pToken, &dst, &rel_addr);
+
+            TRACE("def c%u = %f, %f, %f, %f", shader_get_float_offset(dst.reg.type, dst.reg.idx),
+                    *(const float *)(pToken),
+                    *(const float *)(pToken + 1),
+                    *(const float *)(pToken + 2),
+                    *(const float *)(pToken + 3));
+            pToken += 4;
+        }
+        else if (ins.handler_idx == WINED3DSIH_DEFI)
+        {
+            struct wined3d_shader_dst_param dst;
+            struct wined3d_shader_src_param rel_addr;
+
+            fe->shader_read_dst_param(fe_data, &pToken, &dst, &rel_addr);
+
+            TRACE("defi i%u = %d, %d, %d, %d", dst.reg.idx,
+                    *(pToken),
+                    *(pToken + 1),
+                    *(pToken + 2),
+                    *(pToken + 3));
+            pToken += 4;
+        }
+        else if (ins.handler_idx == WINED3DSIH_DEFB)
+        {
+            struct wined3d_shader_dst_param dst;
+            struct wined3d_shader_src_param rel_addr;
+
+            fe->shader_read_dst_param(fe_data, &pToken, &dst, &rel_addr);
+
+            TRACE("defb b%u = %s", dst.reg.idx, *pToken ? "true" : "false");
+            ++pToken;
         }
         else
         {
-            if (curOpcode->opcode == WINED3DSIO_DCL)
-            {
-                DWORD usage = *pToken;
-                DWORD param = *(pToken + 1);
+            struct wined3d_shader_src_param dst_rel_addr, src_rel_addr;
+            struct wined3d_shader_dst_param dst_param;
+            struct wined3d_shader_src_param src_param;
 
-                shader_dump_decl_usage(usage, param, shader_version);
-                shader_dump_ins_modifiers(param);
-                TRACE(" ");
-                shader_dump_param(param, 0, 0, shader_version);
-                pToken += 2;
-            }
-            else if (curOpcode->opcode == WINED3DSIO_DEF)
-            {
-                unsigned int offset = shader_get_float_offset(*pToken);
-
-                TRACE("def c%u = %f, %f, %f, %f", offset,
-                        *(const float *)(pToken + 1),
-                        *(const float *)(pToken + 2),
-                        *(const float *)(pToken + 3),
-                        *(const float *)(pToken + 4));
-                pToken += 5;
-            }
-            else if (curOpcode->opcode == WINED3DSIO_DEFI)
+            if (ins.dst_count)
             {
-                TRACE("defi i%u = %d, %d, %d, %d", *pToken & WINED3DSP_REGNUM_MASK,
-                        *(pToken + 1),
-                        *(pToken + 2),
-                        *(pToken + 3),
-                        *(pToken + 4));
-                pToken += 5;
+                fe->shader_read_dst_param(fe_data, &pToken, &dst_param, &dst_rel_addr);
             }
-            else if (curOpcode->opcode == WINED3DSIO_DEFB)
+
+            /* Print out predication source token first - it follows
+             * the destination token. */
+            if (ins.predicate)
             {
-                TRACE("defb b%u = %s", *pToken & WINED3DSP_REGNUM_MASK,
-                        *(pToken + 1)? "true": "false");
-                pToken += 2;
+                fe->shader_read_src_param(fe_data, &pToken, &src_param, &src_rel_addr);
+                TRACE("(");
+                shader_dump_src_param(&src_param, &shader_version);
+                TRACE(") ");
             }
-            else
-            {
-                DWORD param, addr_token;
-                int tokens_read;
 
-                /* Print out predication source token first - it follows
-                 * the destination token. */
-                if (opcode_token & WINED3DSHADER_INSTRUCTION_PREDICATED)
-                {
-                    TRACE("(");
-                    shader_dump_param(*(pToken + 2), 0, 1, shader_version);
-                    TRACE(") ");
-                }
-                if (opcode_token & WINED3DSI_COISSUE)
-                {
-                    /* PixWin marks instructions with the coissue flag with a '+' */
-                    TRACE("+");
-                }
+            /* PixWin marks instructions with the coissue flag with a '+' */
+            if (ins.coissue) TRACE("+");
 
-                TRACE("%s", curOpcode->name);
+            TRACE("%s", shader_opcode_names[ins.handler_idx]);
 
-                if (curOpcode->opcode == WINED3DSIO_IFC
-                        || curOpcode->opcode == WINED3DSIO_BREAKC)
-                {
-                    DWORD op = (opcode_token & INST_CONTROLS_MASK) >> INST_CONTROLS_SHIFT;
-
-                    switch (op)
-                    {
-                        case COMPARISON_GT: TRACE("_gt"); break;
-                        case COMPARISON_EQ: TRACE("_eq"); break;
-                        case COMPARISON_GE: TRACE("_ge"); break;
-                        case COMPARISON_LT: TRACE("_lt"); break;
-                        case COMPARISON_NE: TRACE("_ne"); break;
-                        case COMPARISON_LE: TRACE("_le"); break;
-                        default: TRACE("_(%u)", op);
-                    }
-                }
-                else if (curOpcode->opcode == WINED3DSIO_TEX
-                        && shader_version >= WINED3DPS_VERSION(2,0)
-                        && (opcode_token & WINED3DSI_TEXLD_PROJECT))
-                {
-                    TRACE("p");
-                }
-
-                /* Destination token */
-                if (curOpcode->dst_token)
-                {
-                    tokens_read = shader_get_param(pToken, shader_version, &param, &addr_token);
-                    pToken += tokens_read;
-
-                    shader_dump_ins_modifiers(param);
-                    TRACE(" ");
-                    shader_dump_param(param, addr_token, 0, shader_version);
-                }
-
-                /* Predication token - already printed out, just skip it */
-                if (opcode_token & WINED3DSHADER_INSTRUCTION_PREDICATED)
+            if (ins.handler_idx == WINED3DSIH_IFC
+                    || ins.handler_idx == WINED3DSIH_BREAKC)
+            {
+                switch (ins.flags)
                 {
-                    pToken++;
+                    case COMPARISON_GT: TRACE("_gt"); break;
+                    case COMPARISON_EQ: TRACE("_eq"); break;
+                    case COMPARISON_GE: TRACE("_ge"); break;
+                    case COMPARISON_LT: TRACE("_lt"); break;
+                    case COMPARISON_NE: TRACE("_ne"); break;
+                    case COMPARISON_LE: TRACE("_le"); break;
+                    default: TRACE("_(%u)", ins.flags);
                 }
+            }
+            else if (ins.handler_idx == WINED3DSIH_TEX
+                    && shader_version.major >= 2
+                    && (ins.flags & WINED3DSI_TEXLD_PROJECT))
+            {
+                TRACE("p");
+            }
 
-                /* Other source tokens */
-                for (i = curOpcode->dst_token; i < curOpcode->num_params; ++i)
-                {
-                    tokens_read = shader_get_param(pToken, shader_version, &param, &addr_token);
-                    pToken += tokens_read;
+            /* We already read the destination token, print it. */
+            if (ins.dst_count)
+            {
+                shader_dump_ins_modifiers(&dst_param);
+                TRACE(" ");
+                shader_dump_dst_param(&dst_param, &shader_version);
+            }
 
-                    TRACE((i == 0)? " " : ", ");
-                    shader_dump_param(param, addr_token, 1, shader_version);
-                }
+            /* Other source tokens */
+            for (i = ins.dst_count; i < (ins.dst_count + ins.src_count); ++i)
+            {
+                fe->shader_read_src_param(fe_data, &pToken, &src_param, &src_rel_addr);
+                TRACE(!i ? " " : ", ");
+                shader_dump_src_param(&src_param, &shader_version);
             }
-            TRACE("\n");
         }
+        TRACE("\n");
     }
 }
 
@@ -1079,11 +1211,17 @@ void shader_cleanup(IWineD3DBaseShader *iface)
     IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)iface;
 
     ((IWineD3DDeviceImpl *)This->baseShader.device)->shader_backend->shader_destroy(iface);
+    HeapFree(GetProcessHeap(), 0, This->baseShader.reg_maps.constf);
     HeapFree(GetProcessHeap(), 0, This->baseShader.function);
     shader_delete_constant_list(&This->baseShader.constantsF);
     shader_delete_constant_list(&This->baseShader.constantsB);
     shader_delete_constant_list(&This->baseShader.constantsI);
     list_remove(&This->baseShader.shader_list_entry);
+
+    if (This->baseShader.frontend && This->baseShader.frontend_data)
+    {
+        This->baseShader.frontend->shader_free(This->baseShader.frontend_data);
+    }
 }
 
 static const SHADER_HANDLER shader_none_instruction_handler_table[WINED3DSIH_TABLE_SIZE] = {0};
@@ -1098,14 +1236,19 @@ static void shader_none_destroy(IWineD3DBaseShader *iface) {}
 static HRESULT shader_none_alloc(IWineD3DDevice *iface) {return WINED3D_OK;}
 static void shader_none_free(IWineD3DDevice *iface) {}
 static BOOL shader_none_dirty_const(IWineD3DDevice *iface) {return FALSE;}
-static GLuint shader_none_generate_pshader(IWineD3DPixelShader *iface, SHADER_BUFFER *buffer, const struct ps_compile_args *args) {
+static GLuint shader_none_generate_pshader(IWineD3DPixelShader *iface,
+        SHADER_BUFFER *buffer, const struct ps_compile_args *args)
+{
     FIXME("NONE shader backend asked to generate a pixel shader\n");
     return 0;
 }
-static GLuint shader_none_generate_vshader(IWineD3DVertexShader *iface, SHADER_BUFFER *buffer, const struct vs_compile_args *args) {
+static GLuint shader_none_generate_vshader(IWineD3DVertexShader *iface,
+        SHADER_BUFFER *buffer, const struct vs_compile_args *args)
+{
     FIXME("NONE shader backend asked to generate a vertex shader\n");
     return 0;
 }
+static void shader_none_add_instruction_modifiers(const struct wined3d_shader_instruction *ins) {}
 
 #define GLINFO_LOCATION      (*gl_info)
 static void shader_none_get_caps(WINED3DDEVTYPE devtype, const WineD3D_GL_Info *gl_info, struct shader_caps *pCaps)
@@ -1152,4 +1295,5 @@ const shader_backend_t none_shader_backend = {
     shader_none_generate_vshader,
     shader_none_get_caps,
     shader_none_color_fixup_supported,
+    shader_none_add_instruction_modifiers,
 };
index b68dcf7..666de8e 100644 (file)
@@ -214,7 +214,7 @@ static BOOL buffer_check_attribute(struct wined3d_buffer *This,
 
     format = attrib->format_desc->format;
     /* Look for newly appeared conversion */
-    if (!GL_SUPPORT(NV_HALF_FLOAT) && (format == WINED3DFMT_R16G16_FLOAT || format == WINED3DFMT_R16G16B16A16_FLOAT))
+    if (!GL_SUPPORT(ARB_HALF_FLOAT_VERTEX) && (format == WINED3DFMT_R16G16_FLOAT || format == WINED3DFMT_R16G16B16A16_FLOAT))
     {
         ret = buffer_process_converted_attribute(This, CONV_FLOAT16_2, attrib, stride_this_run);
 
@@ -327,7 +327,7 @@ static BOOL buffer_find_decl(struct wined3d_buffer *This)
     /* Certain declaration types need some fixups before we can pass them to
      * opengl. This means D3DCOLOR attributes with fixed function vertex
      * processing, FLOAT4 POSITIONT with fixed function, and FLOAT16 if
-     * GL_NV_half_float is not supported.
+     * GL_ARB_half_float_vertex is not supported.
      *
      * Note for d3d8 and d3d9:
      * The vertex buffer FVF doesn't help with finding them, we have to use
@@ -590,7 +590,8 @@ static ULONG STDMETHODCALLTYPE buffer_AddRef(IWineD3DBuffer *iface)
 
 const BYTE *buffer_get_sysmem(struct wined3d_buffer *This)
 {
-    if(This->flags & WINED3D_BUFFER_DOUBLEBUFFER) return This->resource.allocatedMemory;
+    /* AllocatedMemory exists if the buffer is double buffered or has no buffer object at all */
+    if(This->resource.allocatedMemory) return This->resource.allocatedMemory;
 
     This->resource.heapMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->resource.size + RESOURCE_ALIGNMENT);
     This->resource.allocatedMemory = (BYTE *)(((ULONG_PTR)This->resource.heapMemory + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1));
@@ -951,12 +952,18 @@ static HRESULT STDMETHODCALLTYPE buffer_Map(IWineD3DBuffer *iface, UINT offset,
     {
         if(count == 1)
         {
+            IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
+
             if(This->buffer_type_hint == GL_ELEMENT_ARRAY_BUFFER_ARB)
             {
                 IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_INDEXBUFFER);
             }
+
+            ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
+            ENTER_GL();
             GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object));
             This->resource.allocatedMemory = GL_EXTCALL(glMapBufferARB(This->buffer_type_hint, GL_READ_WRITE_ARB));
+            LEAVE_GL();
         }
     }
     else
@@ -987,12 +994,19 @@ static HRESULT STDMETHODCALLTYPE buffer_Unmap(IWineD3DBuffer *iface)
 
     if(!(This->flags & WINED3D_BUFFER_DOUBLEBUFFER) && This->buffer_object)
     {
+        IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
+
         if(This->buffer_type_hint == GL_ELEMENT_ARRAY_BUFFER_ARB)
         {
             IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_INDEXBUFFER);
         }
+
+        ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
+        ENTER_GL();
         GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object));
         GL_EXTCALL(glUnmapBufferARB(This->buffer_type_hint));
+        LEAVE_GL();
+
         This->resource.allocatedMemory = NULL;
     }
     else if (This->flags & WINED3D_BUFFER_HASDESC)
index a510d2e..2c6703f 100644 (file)
@@ -895,12 +895,10 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar
         }
     }
 
-    if(GL_SUPPORT(ARB_POINT_SPRITE)) {
-        for(s = 0; s < GL_LIMITS(textures); s++) {
-            GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + s));
-            glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
-            checkGLcall("glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
-        }
+    for(s = 0; s < GL_LIMITS(point_sprite_units); s++) {
+        GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + s));
+        glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
+        checkGLcall("glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
     }
     LEAVE_GL();
 
index 1099872..ec6d3f0 100644 (file)
@@ -220,7 +220,7 @@ void device_stream_info_from_declaration(IWineD3DDeviceImpl *This,
             {
                 WARN("loadBaseVertexIndex is < 0 (%d), not using vbos\n", This->stateBlock->loadBaseVertexIndex);
                 buffer_object = 0;
-                data = ((struct wined3d_buffer *)This->stateBlock->streamSource[element->input_slot])->resource.allocatedMemory;
+                data = buffer_get_sysmem((struct wined3d_buffer *)This->stateBlock->streamSource[element->input_slot]);
                 if ((UINT_PTR)data < -This->stateBlock->loadBaseVertexIndex * stride)
                 {
                     FIXME("System memory vertex data load offset is negative!\n");
@@ -503,7 +503,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateBuffer(IWineD3DDevice *iface,
 }
 
 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
-        DWORD FVF, WINED3DPOOL Pool, IWineD3DBuffer **ppVertexBuffer, HANDLE *sharedHandle, IUnknown *parent)
+        DWORD FVF, WINED3DPOOL Pool, IWineD3DBuffer **ppVertexBuffer, IUnknown *parent)
 {
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
     /* Dummy format for now */
@@ -582,9 +582,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *ifac
     return WINED3D_OK;
 }
 
-static HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
-                                                    WINED3DPOOL Pool, IWineD3DBuffer** ppIndexBuffer,
-                                                    HANDLE *sharedHandle, IUnknown *parent) {
+static HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface,
+        UINT Length, DWORD Usage, WINED3DPOOL Pool, IWineD3DBuffer **ppIndexBuffer, IUnknown *parent)
+{
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
     const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(WINED3DFMT_UNKNOWN, &This->adapter->gl_info);
     struct wined3d_buffer *object;
@@ -897,8 +897,12 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface,
     return WINED3D_OK;
 }
 
-static HRESULT  WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height, WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface,WINED3DRESOURCETYPE Type, DWORD Usage, WINED3DPOOL Pool, WINED3DMULTISAMPLE_TYPE MultiSample ,DWORD MultisampleQuality, HANDLE* pSharedHandle, WINED3DSURFTYPE Impl, IUnknown *parent) {
-    IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;    
+static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface,
+        UINT Width, UINT Height, WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level,
+        IWineD3DSurface **ppSurface, WINED3DRESOURCETYPE Type, DWORD Usage, WINED3DPOOL Pool,
+        WINED3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, WINED3DSURFTYPE Impl, IUnknown *parent)
+{
+    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
     IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
     unsigned int Size       = 1;
     const struct GlPixelFormatDesc *glDesc = getFormatDescEntry(Format, &GLINFO_LOCATION);
@@ -1085,8 +1089,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateRendertargetView(IWineD3DDevice *
 }
 
 static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface,
-        UINT Width, UINT Height, UINT Levels, DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
-        IWineD3DTexture **ppTexture, HANDLE *pSharedHandle, IUnknown *parent)
+        UINT Width, UINT Height, UINT Levels, DWORD Usage, WINED3DFORMAT Format,
+        WINED3DPOOL Pool, IWineD3DTexture **ppTexture, IUnknown *parent)
 {
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
     const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(Format, &This->adapter->gl_info);
@@ -1099,8 +1103,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface,
     unsigned int pow2Height;
 
     TRACE("(%p) : Width %d, Height %d, Levels %d, Usage %#x\n", This, Width, Height, Levels, Usage);
-    TRACE("Format %#x (%s), Pool %#x, ppTexture %p, pSharedHandle %p, parent %p\n",
-            Format, debug_d3dformat(Format), Pool, ppTexture, pSharedHandle, parent);
+    TRACE("Format %#x (%s), Pool %#x, ppTexture %p, parent %p\n",
+            Format, debug_d3dformat(Format), Pool, ppTexture, parent);
 
     /* TODO: It should only be possible to create textures for formats
              that are reported as supported */
@@ -1269,8 +1273,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface,
 }
 
 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
-        UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
-        IWineD3DVolumeTexture **ppVolumeTexture, HANDLE *pSharedHandle, IUnknown *parent)
+        UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, WINED3DFORMAT Format,
+        WINED3DPOOL Pool, IWineD3DVolumeTexture **ppVolumeTexture, IUnknown *parent)
 {
     IWineD3DDeviceImpl        *This = (IWineD3DDeviceImpl *)iface;
     const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(Format, &This->adapter->gl_info);
@@ -1391,12 +1395,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *ifa
 }
 
 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
-                                               UINT Width, UINT Height, UINT Depth,
-                                               DWORD Usage,
-                                               WINED3DFORMAT Format, WINED3DPOOL Pool,
-                                               IWineD3DVolume** ppVolume,
-                                               HANDLE* pSharedHandle, IUnknown *parent) {
-
+        UINT Width, UINT Height, UINT Depth, DWORD Usage, WINED3DFORMAT Format,
+        WINED3DPOOL Pool, IWineD3DVolume **ppVolume, IUnknown *parent)
+{
     IWineD3DDeviceImpl        *This = (IWineD3DDeviceImpl *)iface;
     IWineD3DVolumeImpl        *object; /** NOTE: impl ref allowed since this is a create function **/
     const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(Format, &GLINFO_LOCATION);
@@ -1451,8 +1452,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
 }
 
 static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface,
-        UINT EdgeLength, UINT Levels, DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
-        IWineD3DCubeTexture **ppCubeTexture, HANDLE *pSharedHandle, IUnknown *parent)
+        UINT EdgeLength, UINT Levels, DWORD Usage, WINED3DFORMAT Format,
+        WINED3DPOOL Pool, IWineD3DCubeTexture **ppCubeTexture, IUnknown *parent)
 {
     IWineD3DDeviceImpl      *This = (IWineD3DDeviceImpl *)iface;
     const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(Format, &This->adapter->gl_info);
@@ -2343,7 +2344,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *ifac
 
     object->lpVtbl = &IWineD3DVertexShader_Vtbl;
     object->parent = parent;
-    shader_init(&object->baseShader, iface, IWineD3DVertexShaderImpl_shader_ins);
+    shader_init(&object->baseShader, iface);
     list_add_head(&This->shaders, &object->baseShader.shader_list_entry);
     *ppVertexShader = (IWineD3DVertexShader *)object;
 
@@ -2353,7 +2354,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *ifac
         IWineD3DVertexShader_FakeSemantics(*ppVertexShader, vertex_declaration);
     }
 
-    hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
+    hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction, NULL);
     if (FAILED(hr))
     {
         WARN("(%p) : Failed to set function, returning %#x\n", iface, hr);
@@ -2365,7 +2366,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *ifac
     return hr;
 }
 
-static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
+static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface,
+        const DWORD *pFunction, const struct wined3d_shader_signature *output_signature,
+        IWineD3DPixelShader **ppPixelShader, IUnknown *parent)
+{
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
     IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
     HRESULT hr = WINED3D_OK;
@@ -2382,13 +2386,13 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface
 
     object->lpVtbl = &IWineD3DPixelShader_Vtbl;
     object->parent = parent;
-    shader_init(&object->baseShader, iface, IWineD3DPixelShaderImpl_shader_ins);
+    shader_init(&object->baseShader, iface);
     list_add_head(&This->shaders, &object->baseShader.shader_list_entry);
     *ppPixelShader = (IWineD3DPixelShader *)object;
 
     TRACE("(%p) : Created pixel shader %p\n", This, *ppPixelShader);
 
-    hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
+    hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction, output_signature);
     if (FAILED(hr))
     {
         WARN("(%p) : Failed to set function, returning %#x\n", iface, hr);
@@ -2466,7 +2470,7 @@ static void IWineD3DDeviceImpl_LoadLogo(IWineD3DDeviceImpl *This, const char *fi
 
     hr = IWineD3DDevice_CreateSurface((IWineD3DDevice *) This, bm.bmWidth, bm.bmHeight, WINED3DFMT_R5G6B5,
                                       TRUE, FALSE, 0, &This->logo_surface, WINED3DRTYPE_SURFACE, 0,
-                                      WINED3DPOOL_DEFAULT, WINED3DMULTISAMPLE_NONE, 0, NULL, SURFACE_OPENGL, NULL);
+                                      WINED3DPOOL_DEFAULT, WINED3DMULTISAMPLE_NONE, 0, SURFACE_OPENGL, NULL);
     if(FAILED(hr)) {
         ERR("Wine logo requested, but failed to create surface\n");
         goto out;
@@ -4207,12 +4211,13 @@ static void device_map_fixed_function_samplers(IWineD3DDeviceImpl *This) {
 }
 
 static void device_map_psamplers(IWineD3DDeviceImpl *This) {
-    const DWORD *sampler_tokens =
-            ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.reg_maps.samplers;
+    const WINED3DSAMPLER_TEXTURE_TYPE *sampler_type =
+            ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.reg_maps.sampler_type;
     unsigned int i;
 
     for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i) {
-        if (sampler_tokens[i] && This->texUnitMap[i] != i) {
+        if (sampler_type[i] && This->texUnitMap[i] != i)
+        {
             device_map_stage(This, i, i);
             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
             if (i < MAX_TEXTURES) {
@@ -4249,9 +4254,9 @@ static BOOL device_unit_free_for_vs(IWineD3DDeviceImpl *This, const DWORD *pshad
 }
 
 static void device_map_vsamplers(IWineD3DDeviceImpl *This, BOOL ps) {
-    const DWORD *vshader_sampler_tokens =
-            ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.reg_maps.samplers;
-    const DWORD *pshader_sampler_tokens = NULL;
+    const WINED3DSAMPLER_TEXTURE_TYPE *vshader_sampler_type =
+            ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.reg_maps.sampler_type;
+    const WINED3DSAMPLER_TEXTURE_TYPE *pshader_sampler_type = NULL;
     int start = GL_LIMITS(combined_samplers) - 1;
     int i;
 
@@ -4260,12 +4265,13 @@ static void device_map_vsamplers(IWineD3DDeviceImpl *This, BOOL ps) {
 
         /* Note that we only care if a sampler is sampled or not, not the sampler's specific type.
          * Otherwise we'd need to call shader_update_samplers() here for 1.x pixelshaders. */
-        pshader_sampler_tokens = pshader->baseShader.reg_maps.samplers;
+        pshader_sampler_type = pshader->baseShader.reg_maps.sampler_type;
     }
 
     for (i = 0; i < MAX_VERTEX_SAMPLERS; ++i) {
         int vsampler_idx = i + MAX_FRAGMENT_SAMPLERS;
-        if (vshader_sampler_tokens[i]) {
+        if (vshader_sampler_type[i])
+        {
             if (This->texUnitMap[vsampler_idx] != WINED3D_UNMAPPED_STAGE)
             {
                 /* Already mapped somewhere */
@@ -4273,7 +4279,8 @@ static void device_map_vsamplers(IWineD3DDeviceImpl *This, BOOL ps) {
             }
 
             while (start >= 0) {
-                if (device_unit_free_for_vs(This, pshader_sampler_tokens, vshader_sampler_tokens, start)) {
+                if (device_unit_free_for_vs(This, pshader_sampler_type, vshader_sampler_type, start))
+                {
                     device_map_stage(This, vsampler_idx, start);
                     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(vsampler_idx));
 
@@ -4530,27 +4537,7 @@ static HRESULT process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIn
     ENTER_GL();
 
     if (dest->resource.allocatedMemory == NULL) {
-        /* This may happen if we do direct locking into a vbo. Unlikely,
-         * but theoretically possible(ddraw processvertices test)
-         */
-        dest->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, dest->resource.size);
-        if(!dest->resource.allocatedMemory) {
-            LEAVE_GL();
-            ERR("Out of memory\n");
-            return E_OUTOFMEMORY;
-        }
-        if (dest->buffer_object)
-        {
-            const void *src;
-            GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->buffer_object));
-            checkGLcall("glBindBufferARB");
-            src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
-            if(src) {
-                memcpy(dest->resource.allocatedMemory, src, dest->resource.size);
-            }
-            GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
-            checkGLcall("glUnmapBufferARB");
-        }
+        buffer_get_sysmem(dest);
     }
 
     /* Get a pointer into the destination vbo(create one if none exists) and
@@ -7611,8 +7598,25 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRE
         ERR("Cannot change the device window yet\n");
     }
     if (pPresentationParameters->EnableAutoDepthStencil && !This->auto_depth_stencil_buffer) {
-        WARN("Auto depth stencil enabled, but no auto depth stencil present, returning WINED3DERR_INVALIDCALL\n");
-        return WINED3DERR_INVALIDCALL;
+        HRESULT hrc;
+
+        TRACE("Creating the depth stencil buffer\n");
+
+        hrc = IWineD3DDeviceParent_CreateDepthStencilSurface(This->device_parent,
+                This->parent,
+                pPresentationParameters->BackBufferWidth,
+                pPresentationParameters->BackBufferHeight,
+                pPresentationParameters->AutoDepthStencilFormat,
+                pPresentationParameters->MultiSampleType,
+                pPresentationParameters->MultiSampleQuality,
+                FALSE,
+                &This->auto_depth_stencil_buffer);
+
+        if (FAILED(hrc)) {
+            ERR("Failed to create the depth stencil buffer\n");
+            IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
+            return WINED3DERR_INVALIDCALL;
+        }
     }
 
     /* Reset the depth stencil */
index 7c6cc3b..9a064bb 100644 (file)
@@ -91,6 +91,8 @@ static const struct {
     {"GL_ARB_vertex_program",               ARB_VERTEX_PROGRAM,             0                           },
     {"GL_ARB_vertex_shader",                ARB_VERTEX_SHADER,              0                           },
     {"GL_ARB_shader_objects",               ARB_SHADER_OBJECTS,             0                           },
+    {"GL_ARB_shader_texture_lod",           ARB_SHADER_TEXTURE_LOD,         0                           },
+    {"GL_ARB_half_float_vertex",            ARB_HALF_FLOAT_VERTEX,          0                           },
 
     /* EXT */
     {"GL_EXT_blend_color",                  EXT_BLEND_COLOR,                0                           },
@@ -232,8 +234,7 @@ static void WineD3D_ReleaseFakeGLContext(void) {
         if(!wined3d_fake_gl_context_foreign && glCtx) {
             TRACE_(d3d_caps)("destroying fake GL context\n");
             pwglMakeCurrent(NULL, NULL);
-            //ros hack, this line does destire the real icd interface in windows and reactos
-            // pwglDeleteContext(glCtx);
+            //pwglDeleteContext(glCtx);
         }
         if(wined3d_fake_gl_context_hdc)
             ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
@@ -1009,7 +1010,15 @@ static BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
             gl_info->supported[NV_TEXTURE_SHADER2] = FALSE;
             gl_info->supported[NV_TEXTURE_SHADER3] = FALSE;
         }
-
+        if(gl_info->supported[NV_HALF_FLOAT]) {
+            /* GL_ARB_half_float_vertex is a subset of GL_NV_half_float */
+            gl_info->supported[ARB_HALF_FLOAT_VERTEX] = TRUE;
+        }
+        if(gl_info->supported[ARB_POINT_SPRITE]) {
+            gl_info->max_point_sprite_units = gl_info->max_textures;
+        } else {
+            gl_info->max_point_sprite_units = 0;
+        }
     }
     checkGLcall("extension detection\n");
 
@@ -2392,6 +2401,7 @@ static BOOL CheckTextureCapability(struct WineD3DAdapter *adapter,
 
             /* Floating point formats */
         case WINED3DFMT_R16_FLOAT:
+        case WINED3DFMT_R16G16_FLOAT:
         case WINED3DFMT_R16G16B16A16_FLOAT:
             if(GL_SUPPORT(ARB_TEXTURE_FLOAT) && GL_SUPPORT(ARB_HALF_FLOAT_PIXEL)) {
                 TRACE_(d3d_caps)("[OK]\n");
@@ -2401,6 +2411,7 @@ static BOOL CheckTextureCapability(struct WineD3DAdapter *adapter,
             return FALSE;
 
         case WINED3DFMT_R32_FLOAT:
+        case WINED3DFMT_R32G32_FLOAT:
         case WINED3DFMT_R32G32B32A32_FLOAT:
             if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
                 TRACE_(d3d_caps)("[OK]\n");
@@ -2409,15 +2420,6 @@ static BOOL CheckTextureCapability(struct WineD3DAdapter *adapter,
             TRACE_(d3d_caps)("[FAILED]\n");
             return FALSE;
 
-        case WINED3DFMT_R16G16_FLOAT:
-        case WINED3DFMT_R32G32_FLOAT:
-            if(GL_SUPPORT(ARB_TEXTURE_RG)) {
-                TRACE_(d3d_caps)("[OK]\n");
-                return TRUE;
-            }
-            TRACE_(d3d_caps)("[FAILED]\n");
-            return FALSE;
-
         /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
          * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
          * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
@@ -3636,7 +3638,7 @@ static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter,
                            WINED3DDTCAPS_UBYTE4N   |
                            WINED3DDTCAPS_SHORT2N   |
                            WINED3DDTCAPS_SHORT4N;
-        if (GL_SUPPORT(NV_HALF_FLOAT)) {
+        if (GL_SUPPORT(ARB_HALF_FLOAT_VERTEX)) {
             pCaps->DeclTypes |= WINED3DDTCAPS_FLOAT16_2 |
                                 WINED3DDTCAPS_FLOAT16_4;
         }
@@ -3851,7 +3853,7 @@ ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
     return IUnknown_Release(volumeParent);
 }
 
-static BOOL implementation_is_apple(const WineD3D_GL_Info *gl_info)
+static BOOL match_apple(const WineD3D_GL_Info *gl_info)
 {
     /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
      * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
@@ -3908,6 +3910,8 @@ static void test_pbo_functionality(WineD3D_GL_Info *gl_info) {
     while(glGetError());
     glGenTextures(1, &texture);
     glBindTexture(GL_TEXTURE_2D, texture);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
     checkGLcall("Specifying the PBO test texture\n");
 
@@ -4003,46 +4007,80 @@ static const struct driver_version_information driver_version_table[] = {
     /* TODO: Add information about legacy ATI hardware, Intel and other cards */
 };
 
-static void fixup_extensions(WineD3D_GL_Info *gl_info) {
-    unsigned int i;
-    BOOL apple = implementation_is_apple(gl_info);
+static BOOL match_ati_r300_to_500(const WineD3D_GL_Info *gl_info) {
+    if(gl_info->gl_vendor != VENDOR_ATI) return FALSE;
+    if(gl_info->gl_card == CARD_ATI_RADEON_9500) return TRUE;
+    if(gl_info->gl_card == CARD_ATI_RADEON_X700) return TRUE;
+    if(gl_info->gl_card == CARD_ATI_RADEON_X1600) return TRUE;
+    return FALSE;
+}
 
-    if(apple) {
-        /* MacOS advertises more GLSL vertex shader uniforms than supported by the hardware, and if more are
-         * used it falls back to software. While the compiler can detect if the shader uses all declared
-         * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader
-         * using relative addressing falls back to software.
-         *
-         * ARB vp gives the correct amount of uniforms, so use it instead of GLSL
-         */
-        if(gl_info->vs_glsl_constantsF <= gl_info->vs_arb_constantsF) {
-            FIXME("GLSL doesn't advertise more vertex shader uniforms than ARB. Driver fixup outdated?\n");
-        } else {
-            TRACE("Driver claims %u GLSL vs uniforms, replacing with %u ARB vp uniforms\n",
-                  gl_info->vs_glsl_constantsF, gl_info->vs_arb_constantsF);
-            gl_info->vs_glsl_constantsF = gl_info->vs_arb_constantsF;
+static BOOL match_geforce5(const WineD3D_GL_Info *gl_info) {
+    if(gl_info->gl_vendor == VENDOR_NVIDIA) {
+        if(gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5800 || gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5600) {
+            return TRUE;
         }
+    }
+    return FALSE;
+}
 
-        /* The Intel GPUs on MacOS set the .w register of texcoords to 0.0 by default, which causes problems
-         * with fixed function fragment processing. Ideally this flag should be detected with a test shader
-         * and OpenGL feedback mode, but some GL implementations (MacOS ATI at least, probably all MacOS ones)
-         * do not like vertex shaders in feedback mode and return an error, even though it should be valid
-         * according to the spec.
-         *
-         * We don't want to enable this on all cards, as it adds an extra instruction per texcoord used. This
-         * makes the shader slower and eats instruction slots which should be available to the d3d app.
-         *
-         * ATI Radeon HD 2xxx cards on MacOS have the issue. Instead of checking for the buggy cards, blacklist
-         * all radeon cards on Macs and whitelist the good ones. That way we're prepared for the future. If
-         * this workaround is activated on cards that do not need it, it won't break things, just affect
-         * performance negatively.
-         */
-        if(gl_info->gl_vendor == VENDOR_INTEL ||
-           (gl_info->gl_vendor == VENDOR_ATI && gl_info->gl_card != CARD_ATI_RADEON_X1600)) {
-            TRACE("Enabling vertex texture coord fixes in vertex shaders\n");
-            gl_info->set_texcoord_w = TRUE;
-        }
+static BOOL match_apple_intel(const WineD3D_GL_Info *gl_info) {
+    return gl_info->gl_vendor == VENDOR_INTEL && match_apple(gl_info);
+}
+
+static BOOL match_apple_nonr500ati(const WineD3D_GL_Info *gl_info) {
+    if(!match_apple(gl_info)) return FALSE;
+    if(gl_info->gl_vendor != VENDOR_ATI) return FALSE;
+    if(gl_info->gl_card == CARD_ATI_RADEON_X1600) return FALSE;
+    return TRUE;
+}
+
+static BOOL match_fglrx(const WineD3D_GL_Info *gl_info) {
+    if(gl_info->gl_vendor != VENDOR_ATI) return FALSE;
+    if(match_apple(gl_info)) return FALSE;
+    if(strstr(gl_info->gl_renderer, "DRI")) return FALSE; /* Filter out Mesa DRI drivers */
+    return TRUE;
+}
+
+static void quirk_arb_constants(WineD3D_GL_Info *gl_info) {
+    TRACE_(d3d_caps)("Using ARB vs constant limit(=%u) for GLSL\n", gl_info->vs_arb_constantsF);
+    gl_info->vs_glsl_constantsF = gl_info->vs_arb_constantsF;
+    TRACE_(d3d_caps)("Using ARB ps constant limit(=%u) for GLSL\n", gl_info->ps_arb_constantsF);
+    gl_info->ps_glsl_constantsF = gl_info->ps_arb_constantsF;
+}
+
+static void quirk_apple_glsl_constants(WineD3D_GL_Info *gl_info) {
+    quirk_arb_constants(gl_info);
+    /* MacOS needs uniforms for relative addressing offsets. This can accumulate to quite a few uniforms.
+     * Beyond that the general uniform isn't optimal, so reserve a number of uniforms. 12 vec4's should
+     * allow 48 different offsets or other helper immediate values
+     */
+    TRACE_(d3d_caps)("Reserving 12 GLSL constants for compiler private use\n");
+    gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 12);
+}
+
+/* fglrx crashes with a very bad kernel panic if GL_POINT_SPRITE_ARB is set to GL_COORD_REPLACE_ARB
+ * on more than one texture unit. This means that the d3d9 visual point size test will cause a
+ * kernel panic on any machine running fglrx 9.3(latest that supports r300 to r500 cards). This
+ * quirk only enables point sprites on the first texture unit. This keeps point sprites working in
+ * most games, but avoids the crash
+ *
+ * A more sophisticated way would be to find all units that need texture coordinates and enable
+ * point sprites for one if only one is found, and software emulate point sprites in drawStridedSlow
+ * if more than one unit needs texture coordinates(This requires software ffp and vertex shaders though)
+ *
+ * Note that disabling the extension entirely does not gain predictability because there is no point
+ * sprite capability flag in d3d, so the potential rendering bugs are the same if we disable the extension.
+ */
+static void quirk_one_point_sprite(WineD3D_GL_Info *gl_info) {
+    if(gl_info->supported[ARB_POINT_SPRITE]) {
+        TRACE("Limiting point sprites to one texture unit\n");
+        gl_info->max_point_sprite_units = 1;
     }
+}
+
+static void quirk_ati_dx9(WineD3D_GL_Info *gl_info) {
+    quirk_arb_constants(gl_info);
 
     /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although
      * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL).
@@ -4056,16 +4094,18 @@ static void fixup_extensions(WineD3D_GL_Info *gl_info) {
      * has this extension promoted to core. The extension loading code sets this extension supported
      * due to that, so this code works on fglrx as well.
      */
-    if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] && gl_info->gl_vendor == VENDOR_ATI) {
-        if(gl_info->gl_card == CARD_ATI_RADEON_X700 || gl_info->gl_card == CARD_ATI_RADEON_X1600 ||
-            gl_info->gl_card == CARD_ATI_RADEON_9500 || gl_info->gl_card == CARD_ATI_RADEON_8500  ||
-            gl_info->gl_card == CARD_ATI_RADEON_7200 || gl_info->gl_card == CARD_ATI_RAGE_128PRO) {
-            TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing\n");
-            gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
-            gl_info->supported[WINE_NORMALIZED_TEXRECT] = TRUE;
-        }
-    }
+    TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing\n");
+    gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
+    gl_info->supported[WINE_NORMALIZED_TEXRECT] = TRUE;
+
+    /* fglrx has the same structural issues as the one described in quirk_apple_glsl_constants, although
+     * it is generally more efficient. Reserve just 8 constants
+     */
+    TRACE_(d3d_caps)("Reserving 8 GLSL constants for compiler private use\n");
+    gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 8);
+}
 
+static void quirk_no_np2(WineD3D_GL_Info *gl_info) {
     /*  The nVidia GeForceFX series reports OpenGL 2.0 capabilities with the latest drivers versions, but
      *  doesn't explicitly advertise the ARB_tex_npot extension in the GL extension string.
      *  This usually means that ARB_tex_npot is supported in hardware as long as the application is staying
@@ -4081,12 +4121,77 @@ static void fixup_extensions(WineD3D_GL_Info *gl_info) {
      *  post-processing effects in the game "Max Payne 2").
      *  The behaviour can be verified through a simple test app attached in bugreport #14724.
      */
-    if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] && gl_info->gl_vendor == VENDOR_NVIDIA) {
-        if(gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5800 || gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5600) {
-            TRACE("GL_ARB_texture_non_power_of_two advertised through OpenGL 2.0 on NV FX card, removing\n");
-            gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
-            gl_info->supported[ARB_TEXTURE_RECTANGLE] = TRUE;
-        }
+    TRACE("GL_ARB_texture_non_power_of_two advertised through OpenGL 2.0 on NV FX card, removing\n");
+    gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
+    gl_info->supported[ARB_TEXTURE_RECTANGLE] = TRUE;
+}
+
+static void quirk_texcoord_w(WineD3D_GL_Info *gl_info) {
+    /* The Intel GPUs on MacOS set the .w register of texcoords to 0.0 by default, which causes problems
+     * with fixed function fragment processing. Ideally this flag should be detected with a test shader
+     * and OpenGL feedback mode, but some GL implementations (MacOS ATI at least, probably all MacOS ones)
+     * do not like vertex shaders in feedback mode and return an error, even though it should be valid
+     * according to the spec.
+     *
+     * We don't want to enable this on all cards, as it adds an extra instruction per texcoord used. This
+     * makes the shader slower and eats instruction slots which should be available to the d3d app.
+     *
+     * ATI Radeon HD 2xxx cards on MacOS have the issue. Instead of checking for the buggy cards, blacklist
+     * all radeon cards on Macs and whitelist the good ones. That way we're prepared for the future. If
+     * this workaround is activated on cards that do not need it, it won't break things, just affect
+     * performance negatively.
+     */
+    TRACE("Enabling vertex texture coord fixes in vertex shaders\n");
+    gl_info->set_texcoord_w = TRUE;
+}
+
+struct driver_quirk quirk_table[] = {
+    {
+        match_ati_r300_to_500,
+        quirk_ati_dx9,
+        "ATI GLSL constant and normalized texrect quirk"
+    },
+    /* MacOS advertises more GLSL vertex shader uniforms than supported by the hardware, and if more are
+     * used it falls back to software. While the compiler can detect if the shader uses all declared
+     * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader
+     * using relative addressing falls back to software.
+     *
+     * ARB vp gives the correct amount of uniforms, so use it instead of GLSL
+     */
+    {
+        match_apple,
+        quirk_apple_glsl_constants,
+        "Apple GLSL uniform override"
+    },
+    {
+        match_geforce5,
+        quirk_no_np2,
+        "Geforce 5 NP2 disable"
+    },
+    {
+        match_apple_intel,
+        quirk_texcoord_w,
+        "Init texcoord .w for Apple Intel GPU driver"
+    },
+    {
+        match_apple_nonr500ati,
+        quirk_texcoord_w,
+        "Init texcoord .w for Apple ATI >= r600 GPU driver"
+    },
+    {
+        match_fglrx,
+        quirk_one_point_sprite,
+        "Fglrx point sprite crash workaround"
+    }
+};
+
+static void fixup_extensions(WineD3D_GL_Info *gl_info) {
+    unsigned int i;
+
+    for(i = 0; i < (sizeof(quirk_table) / sizeof(*quirk_table)); i++) {
+        if(!quirk_table[i].match(gl_info)) continue;
+        TRACE_(d3d_caps)("Applying driver quirk \"%s\"\n", quirk_table[i].description);
+        quirk_table[i].apply(gl_info);
     }
 
     /* Find out if PBOs work as they are supposed to */
@@ -4276,6 +4381,7 @@ static void fillGLAttribFuncs(const WineD3D_GL_Info *gl_info)
     multi_texcoord_funcs[WINED3D_FFP_EMIT_DEC3N]     = invalid_texcoord_func;
     if (GL_SUPPORT(NV_HALF_FLOAT))
     {
+        /* Not supported by ARB_HALF_FLOAT_VERTEX, so check for NV_HALF_FLOAT */
         multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2hvNV);
         multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4hvNV);
     } else {
index c96b975..68821b4 100644 (file)
@@ -370,6 +370,7 @@ static inline void send_attribute(IWineD3DDeviceImpl *This, WINED3DFORMAT format
              * byte float according to the IEEE standard
              */
             if (GL_SUPPORT(NV_HALF_FLOAT)) {
+                /* Not supported by GL_ARB_half_float_vertex */
                 GL_EXTCALL(glVertexAttrib2hvNV(index, ptr));
             } else {
                 float x = float_16_to_32(((const unsigned short *)ptr) + 0);
@@ -379,6 +380,7 @@ static inline void send_attribute(IWineD3DDeviceImpl *This, WINED3DFORMAT format
             break;
         case WINED3DFMT_R16G16B16A16_FLOAT:
             if (GL_SUPPORT(NV_HALF_FLOAT)) {
+                /* Not supported by GL_ARB_half_float_vertex */
                 GL_EXTCALL(glVertexAttrib4hvNV(index, ptr));
             } else {
                 float x = float_16_to_32(((const unsigned short *)ptr) + 0);
index 61c5701..ca50305 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright 2006 Jason Green 
  * Copyright 2006-2007 Henri Verbeet
  * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
+ * Copyright 2009 Henri Verbeet for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -43,6 +44,7 @@ WINE_DECLARE_DEBUG_CHANNEL(d3d);
 #define WINED3D_GLSL_SAMPLE_PROJECTED   0x1
 #define WINED3D_GLSL_SAMPLE_RECT        0x2
 #define WINED3D_GLSL_SAMPLE_LOD         0x4
+#define WINED3D_GLSL_SAMPLE_GRAD        0x8
 
 typedef struct {
     char reg_name[150];
@@ -51,7 +53,7 @@ typedef struct {
 
 typedef struct {
     char reg_name[150];
-    char param_str[100];
+    char param_str[200];
 } glsl_src_param_t;
 
 typedef struct {
@@ -367,8 +369,8 @@ static void shader_glsl_load_constantsF(IWineD3DBaseShaderImpl *This, const Wine
     const local_constant *lconst;
 
     /* 1.X pshaders have the constants clamped to [-1;1] implicitly. */
-    if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.reg_maps.shader_version) == 1
-            && shader_is_pshader_version(This->baseShader.reg_maps.shader_version))
+    if (This->baseShader.reg_maps.shader_version.major == 1
+            && shader_is_pshader_version(This->baseShader.reg_maps.shader_version.type))
         walk_constant_heap_clamped(gl_info, constants, constant_locations, heap, stack, version);
     else
         walk_constant_heap(gl_info, constants, constant_locations, heap, stack, version);
@@ -432,7 +434,7 @@ static void shader_glsl_load_constantsB(IWineD3DBaseShaderImpl *This, const Wine
     GLint tmp_loc;
     unsigned int i;
     char tmp_name[8];
-    char is_pshader = shader_is_pshader_version(This->baseShader.reg_maps.shader_version);
+    char is_pshader = shader_is_pshader_version(This->baseShader.reg_maps.shader_version.type);
     const char* prefix = is_pshader? "PB":"VB";
     struct list* ptr;
 
@@ -513,7 +515,7 @@ static void shader_glsl_load_np2fixup_constants(
             if (-1 != prog->np2Fixup_location[i]) {
                 const IWineD3DBaseTextureImpl* const tex = (const IWineD3DBaseTextureImpl*) stateBlock->textures[i];
                 if (!tex) {
-                    FIXME("Non-existant texture is flagged for NP2 texcoord fixup\n");
+                    FIXME("Nonexistent texture is flagged for NP2 texcoord fixup\n");
                     continue;
                 } else {
                     const float tex_dim[2] = {tex->baseTexture.pow2Matrix[0], tex->baseTexture.pow2Matrix[5]};
@@ -557,16 +559,12 @@ static void shader_glsl_load_constants(
                 prog->vuniformF_locations, &priv->vconst_heap, priv->stack, constant_version);
 
         /* Load DirectX 9 integer constants/uniforms for vertex shader */
-        if(vshader->baseShader.uses_int_consts) {
-            shader_glsl_load_constantsI(vshader, gl_info, prog->vuniformI_locations,
-                    stateBlock->vertexShaderConstantI, stateBlock->changed.vertexShaderConstantsI);
-        }
+        shader_glsl_load_constantsI(vshader, gl_info, prog->vuniformI_locations, stateBlock->vertexShaderConstantI,
+                stateBlock->changed.vertexShaderConstantsI & vshader->baseShader.reg_maps.integer_constants);
 
         /* Load DirectX 9 boolean constants/uniforms for vertex shader */
-        if(vshader->baseShader.uses_bool_consts) {
-            shader_glsl_load_constantsB(vshader, gl_info, programId,
-                    stateBlock->vertexShaderConstantB, stateBlock->changed.vertexShaderConstantsB);
-        }
+        shader_glsl_load_constantsB(vshader, gl_info, programId, stateBlock->vertexShaderConstantB,
+                stateBlock->changed.vertexShaderConstantsB & vshader->baseShader.reg_maps.boolean_constants);
 
         /* Upload the position fixup params */
         GL_EXTCALL(glUniform4fvARB(prog->posFixup_location, 1, &deviceImpl->posFixup[0]));
@@ -582,16 +580,12 @@ static void shader_glsl_load_constants(
                 prog->puniformF_locations, &priv->pconst_heap, priv->stack, constant_version);
 
         /* Load DirectX 9 integer constants/uniforms for pixel shader */
-        if(pshader->baseShader.uses_int_consts) {
-            shader_glsl_load_constantsI(pshader, gl_info, prog->puniformI_locations,
-                    stateBlock->pixelShaderConstantI, stateBlock->changed.pixelShaderConstantsI);
-        }
+        shader_glsl_load_constantsI(pshader, gl_info, prog->puniformI_locations, stateBlock->pixelShaderConstantI,
+                stateBlock->changed.pixelShaderConstantsI & pshader->baseShader.reg_maps.integer_constants);
 
         /* Load DirectX 9 boolean constants/uniforms for pixel shader */
-        if(pshader->baseShader.uses_bool_consts) {
-            shader_glsl_load_constantsB(pshader, gl_info, programId,
-                    stateBlock->pixelShaderConstantB, stateBlock->changed.pixelShaderConstantsB);
-        }
+        shader_glsl_load_constantsB(pshader, gl_info, programId, stateBlock->pixelShaderConstantB,
+                stateBlock->changed.pixelShaderConstantsB & pshader->baseShader.reg_maps.boolean_constants);
 
         /* Upload the environment bump map matrix if needed. The needsbumpmat member specifies the texture stage to load the matrix from.
          * It can't be 0 for a valid texbem instruction.
@@ -706,12 +700,11 @@ static void shader_generate_glsl_declarations(IWineD3DBaseShader *iface, const s
 {
     IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface;
     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device;
-    DWORD shader_version = reg_maps->shader_version;
     unsigned int i, extra_constants_needed = 0;
     const local_constant *lconst;
 
     /* There are some minor differences between pixel and vertex shaders */
-    char pshader = shader_is_pshader_version(shader_version);
+    char pshader = shader_is_pshader_version(reg_maps->shader_version.type);
     char prefix = pshader ? 'P' : 'V';
 
     /* Prototype the subroutines */
@@ -723,21 +716,53 @@ static void shader_generate_glsl_declarations(IWineD3DBaseShader *iface, const s
     /* Declare the constants (aka uniforms) */
     if (This->baseShader.limits.constant_float > 0) {
         unsigned max_constantsF;
+        /* Unless the shader uses indirect addressing, always declare the maximum array size and ignore that we need some
+         * uniforms privately. E.g. if GL supports 256 uniforms, and we need 2 for the pos fixup and immediate values, still
+         * declare VC[256]. If the shader needs more uniforms than we have it won't work in any case. If it uses less, the
+         * compiler will figure out which uniforms are really used and strip them out. This allows a shader to use c255 on
+         * a dx9 card, as long as it doesn't also use all the other constants.
+         *
+         * If the shader uses indirect addressing the compiler must assume that all declared uniforms are used. In this case,
+         * declare only the amount that we're assured to have.
+         *
+         * Thus we run into problems in these two cases:
+         * 1) The shader really uses more uniforms than supported
+         * 2) The shader uses indirect addressing, less constants than supported, but uses a constant index > #supported consts
+         */
         if(pshader) {
-            max_constantsF = GL_LIMITS(pshader_constantsF) - (MAX_CONST_B / 4) - MAX_CONST_I - 2;
-            max_constantsF = min(This->baseShader.limits.constant_float, max_constantsF);
+            /* No indirect addressing here */
+            max_constantsF = GL_LIMITS(pshader_constantsF);
         } else {
-            /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
-            max_constantsF = GL_LIMITS(vshader_constantsF) - (MAX_CONST_B / 4) - MAX_CONST_I - 1;
-            max_constantsF = min(This->baseShader.limits.constant_float, max_constantsF);
+            if(This->baseShader.reg_maps.usesrelconstF) {
+                /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix).
+                 * Subtract another uniform for immediate values, which have to be loaded via uniform by the driver as well.
+                 * The shader code only uses 0.5, 2.0, 1.0, 128 and -128 in vertex shader code, so one vec4 should be enough
+                 * (Unfortunately the Nvidia driver doesn't store 128 and -128 in one float
+                 */
+                max_constantsF = GL_LIMITS(vshader_constantsF) - 3;
+                max_constantsF -= count_bits(This->baseShader.reg_maps.integer_constants);
+                /* Strictly speaking a bool only uses one scalar, but the nvidia(Linux) compiler doesn't pack them properly,
+                 * so each scalar requires a full vec4. We could work around this by packing the booleans ourselves, but
+                 * for now take this into account when calculating the number of available constants
+                 */
+                max_constantsF -= count_bits(This->baseShader.reg_maps.boolean_constants);
+                /* Set by driver quirks in directx.c */
+                max_constantsF -= GLINFO_LOCATION.reserved_glsl_constants;
+            } else {
+                max_constantsF = GL_LIMITS(vshader_constantsF);
+            }
         }
+        max_constantsF = min(This->baseShader.limits.constant_float, max_constantsF);
         shader_addline(buffer, "uniform vec4 %cC[%u];\n", prefix, max_constantsF);
     }
 
-    if (This->baseShader.limits.constant_int > 0)
+    /* Always declare the full set of constants, the compiler can remove the unused ones because d3d doesn't(yet)
+     * support indirect int and bool constant addressing. This avoids problems if the app uses e.g. i0 and i9.
+     */
+    if (This->baseShader.limits.constant_int > 0 && This->baseShader.reg_maps.integer_constants)
         shader_addline(buffer, "uniform ivec4 %cI[%u];\n", prefix, This->baseShader.limits.constant_int);
 
-    if (This->baseShader.limits.constant_bool > 0)
+    if (This->baseShader.limits.constant_bool > 0 && This->baseShader.reg_maps.boolean_constants)
         shader_addline(buffer, "uniform bool %cB[%u];\n", prefix, This->baseShader.limits.constant_bool);
 
     if(!pshader) {
@@ -752,7 +777,7 @@ static void shader_generate_glsl_declarations(IWineD3DBaseShader *iface, const s
          * out. The nvidia driver only does that if the parameter is inout instead of out, hence the
          * inout.
          */
-        if (shader_version >= WINED3DVS_VERSION(3, 0))
+        if (reg_maps->shader_version.major >= 3)
         {
             shader_addline(buffer, "void order_ps_input(in vec4[%u]);\n", MAX_REG_OUTPUT);
         } else {
@@ -809,11 +834,10 @@ static void shader_generate_glsl_declarations(IWineD3DBaseShader *iface, const s
 
     /* Declare texture samplers */ 
     for (i = 0; i < This->baseShader.limits.sampler; i++) {
-        if (reg_maps->samplers[i]) {
-
-            DWORD stype = reg_maps->samplers[i] & WINED3DSP_TEXTURETYPE_MASK;
-            switch (stype) {
-
+        if (reg_maps->sampler_type[i])
+        {
+            switch (reg_maps->sampler_type[i])
+            {
                 case WINED3DSTT_1D:
                     shader_addline(buffer, "uniform sampler1D %csampler%u;\n", prefix, i);
                     break;
@@ -825,7 +849,8 @@ static void shader_generate_glsl_declarations(IWineD3DBaseShader *iface, const s
                         shader_addline(buffer, "uniform sampler2D %csampler%u;\n", prefix, i);
                     }
 
-                    if(ps_args->np2_fixup & (1 << i)) {
+                    if (pshader && ps_args->np2_fixup & (1 << i))
+                    {
                         /* NP2/RECT textures in OpenGL use texcoords in the range [0,width]x[0,height]
                          * while D3D has them in the (normalized) [0,1]x[0,1] range.
                          * samplerNP2Fixup stores texture dimensions and is updated through
@@ -841,7 +866,7 @@ static void shader_generate_glsl_declarations(IWineD3DBaseShader *iface, const s
                     break;
                 default:
                     shader_addline(buffer, "uniform unsupported_sampler %csampler%u;\n", prefix, i);
-                    FIXME("Unrecognized sampler type: %#x\n", stype);
+                    FIXME("Unrecognized sampler type: %#x\n", reg_maps->sampler_type[i]);
                     break;
             }
         }
@@ -862,7 +887,7 @@ static void shader_generate_glsl_declarations(IWineD3DBaseShader *iface, const s
     /* Declare input register varyings. Only pixel shader, vertex shaders have that declared in the
      * helper function shader that is linked in at link time
      */
-    if (pshader && shader_version >= WINED3DPS_VERSION(3, 0))
+    if (pshader && reg_maps->shader_version.major >= 3)
     {
         if (use_vs(device->stateBlock))
         {
@@ -941,8 +966,8 @@ static void shader_generate_glsl_declarations(IWineD3DBaseShader *iface, const s
  ****************************************************************************/
 
 /* Prototypes */
-static void shader_glsl_add_src_param(const struct wined3d_shader_instruction *ins, const DWORD param,
-        const DWORD addr_token, DWORD mask, glsl_src_param_t *src_param);
+static void shader_glsl_add_src_param(const struct wined3d_shader_instruction *ins,
+        const struct wined3d_shader_src_param *wined3d_src, DWORD mask, glsl_src_param_t *glsl_src);
 
 /** Used for opcode modifiers - They multiply the result by the specified amount */
 static const char * const shift_glsl_tab[] = {
@@ -965,15 +990,12 @@ static const char * const shift_glsl_tab[] = {
 };
 
 /* Generate a GLSL parameter that does the input modifier computation and return the input register/mask to use */
-static void shader_glsl_gen_modifier (
-    const DWORD instr,
-    const char *in_reg,
-    const char *in_regswizzle,
-    char *out_str) {
-
+static void shader_glsl_gen_modifier(DWORD src_modifier, const char *in_reg, const char *in_regswizzle, char *out_str)
+{
     out_str[0] = 0;
 
-    switch (instr & WINED3DSP_SRCMOD_MASK) {
+    switch (src_modifier)
+    {
     case WINED3DSPSM_DZ: /* Need to handle this in the instructions itself (texld & texcrd). */
     case WINED3DSPSM_DW:
     case WINED3DSPSM_NONE:
@@ -1013,207 +1035,214 @@ static void shader_glsl_gen_modifier (
         sprintf(out_str, "-abs(%s%s)", in_reg, in_regswizzle);
         break;
     default:
-        FIXME("Unhandled modifier %u\n", (instr & WINED3DSP_SRCMOD_MASK));
+        FIXME("Unhandled modifier %u\n", src_modifier);
         sprintf(out_str, "%s%s", in_reg, in_regswizzle);
     }
 }
 
 /** Writes the GLSL variable name that corresponds to the register that the
  * DX opcode parameter is trying to access */
-static void shader_glsl_get_register_name(WINED3DSHADER_PARAM_REGISTER_TYPE register_type, UINT register_idx,
-        BOOL rel_addr, const DWORD addr_token, char *register_name, BOOL *is_color,
-        const struct wined3d_shader_instruction *ins)
+static void shader_glsl_get_register_name(const struct wined3d_shader_register *reg,
+        char *register_name, BOOL *is_color, const struct wined3d_shader_instruction *ins)
 {
     /* oPos, oFog and oPts in D3D */
     static const char * const hwrastout_reg_names[] = { "gl_Position", "gl_FogFragCoord", "gl_PointSize" };
 
-    IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)ins->shader;
+    IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)ins->ctx->shader;
     IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device;
     const WineD3D_GL_Info* gl_info = &deviceImpl->adapter->gl_info;
-    DWORD shader_version = This->baseShader.reg_maps.shader_version;
-    char pshader = shader_is_pshader_version(shader_version);
+    char pshader = shader_is_pshader_version(This->baseShader.reg_maps.shader_version.type);
 
     *is_color = FALSE;
 
-    switch (register_type)
+    switch (reg->type)
     {
-    case WINED3DSPR_TEMP:
-        sprintf(register_name, "R%u", register_idx);
-    break;
-    case WINED3DSPR_INPUT:
-        if (pshader) {
-            /* Pixel shaders >= 3.0 */
-            if (WINED3DSHADER_VERSION_MAJOR(shader_version) >= 3)
+        case WINED3DSPR_TEMP:
+            sprintf(register_name, "R%u", reg->idx);
+            break;
+
+        case WINED3DSPR_INPUT:
+            /* vertex shaders */
+            if (!pshader)
+            {
+                if (((IWineD3DVertexShaderImpl *)This)->cur_args->swizzle_map & (1 << reg->idx)) *is_color = TRUE;
+                sprintf(register_name, "attrib%u", reg->idx);
+                break;
+            }
+
+            /* pixel shaders >= 3.0 */
+            if (This->baseShader.reg_maps.shader_version.major >= 3)
             {
+                DWORD idx = ((IWineD3DPixelShaderImpl *)This)->input_reg_map[reg->idx];
                 DWORD in_count = GL_LIMITS(glsl_varyings) / 4;
 
-                if (rel_addr)
+                if (reg->rel_addr)
                 {
                     glsl_src_param_t rel_param;
-                    shader_glsl_add_src_param(ins, addr_token, 0, WINED3DSP_WRITEMASK_0, &rel_param);
+
+                    shader_glsl_add_src_param(ins, reg->rel_addr, WINED3DSP_WRITEMASK_0, &rel_param);
 
                     /* Removing a + 0 would be an obvious optimization, but macos doesn't see the NOP
-                     * operation there
-                     */
-                    if (((IWineD3DPixelShaderImpl *)This)->input_reg_map[register_idx])
+                     * operation there */
+                    if (idx)
                     {
-                        if (((IWineD3DPixelShaderImpl *)This)->declared_in_count > in_count) {
-                            sprintf(register_name, "((%s + %u) > %d ? (%s + %u) > %d ? gl_SecondaryColor : gl_Color : IN[%s + %u])",
-                                    rel_param.param_str, ((IWineD3DPixelShaderImpl *)This)->input_reg_map[register_idx], in_count - 1,
-                                    rel_param.param_str, ((IWineD3DPixelShaderImpl *)This)->input_reg_map[register_idx], in_count,
-                                    rel_param.param_str, ((IWineD3DPixelShaderImpl *)This)->input_reg_map[register_idx]);
-                        } else {
-                            sprintf(register_name, "IN[%s + %u]", rel_param.param_str,
-                                    ((IWineD3DPixelShaderImpl *)This)->input_reg_map[register_idx]);
+                        if (((IWineD3DPixelShaderImpl *)This)->declared_in_count > in_count)
+                        {
+                            sprintf(register_name,
+                                    "((%s + %u) > %d ? (%s + %u) > %d ? gl_SecondaryColor : gl_Color : IN[%s + %u])",
+                                    rel_param.param_str, idx, in_count - 1, rel_param.param_str, idx, in_count,
+                                    rel_param.param_str, idx);
                         }
-                    } else {
-                        if (((IWineD3DPixelShaderImpl *)This)->declared_in_count > in_count) {
+                        else
+                        {
+                            sprintf(register_name, "IN[%s + %u]", rel_param.param_str, idx);
+                        }
+                    }
+                    else
+                    {
+                        if (((IWineD3DPixelShaderImpl *)This)->declared_in_count > in_count)
+                        {
                             sprintf(register_name, "((%s) > %d ? (%s) > %d ? gl_SecondaryColor : gl_Color : IN[%s])",
-                                    rel_param.param_str, in_count - 1,
-                                    rel_param.param_str, in_count,
+                                    rel_param.param_str, in_count - 1, rel_param.param_str, in_count,
                                     rel_param.param_str);
-                        } else {
+                        }
+                        else
+                        {
                             sprintf(register_name, "IN[%s]", rel_param.param_str);
                         }
                     }
-                } else {
-                    DWORD idx = ((IWineD3DPixelShaderImpl *) This)->input_reg_map[register_idx];
-                    if (idx == in_count) {
-                        sprintf(register_name, "gl_Color");
-                    } else if (idx == in_count + 1) {
-                        sprintf(register_name, "gl_SecondaryColor");
-                    } else {
-                        sprintf(register_name, "IN[%u]", idx);
-                    }
                 }
-            } else {
-                if (register_idx == 0)
-                    strcpy(register_name, "gl_Color");
                 else
-                    strcpy(register_name, "gl_SecondaryColor");
+                {
+                    if (idx == in_count) sprintf(register_name, "gl_Color");
+                    else if (idx == in_count + 1) sprintf(register_name, "gl_SecondaryColor");
+                    else sprintf(register_name, "IN[%u]", idx);
+                }
             }
-        } else {
-            if (((IWineD3DVertexShaderImpl *)This)->cur_args->swizzle_map & (1 << register_idx)) *is_color = TRUE;
-            sprintf(register_name, "attrib%u", register_idx);
-        }
-        break;
-    case WINED3DSPR_CONST:
-    {
-        const char prefix = pshader? 'P':'V';
+            else
+            {
+                if (reg->idx == 0) strcpy(register_name, "gl_Color");
+                else strcpy(register_name, "gl_SecondaryColor");
+                break;
+            }
+            break;
 
-        /* Relative addressing */
-        if (rel_addr)
-        {
-           /* Relative addressing on shaders 2.0+ have a relative address token, 
-            * prior to that, it was hard-coded as "A0.x" because there's only 1 register */
-           if (WINED3DSHADER_VERSION_MAJOR(shader_version) >= 2)
-           {
-               glsl_src_param_t rel_param;
-               shader_glsl_add_src_param(ins, addr_token, 0, WINED3DSP_WRITEMASK_0, &rel_param);
-               if (register_idx)
-               {
-                   sprintf(register_name, "%cC[%s + %u]", prefix, rel_param.param_str, register_idx);
-               } else {
-                   sprintf(register_name, "%cC[%s]", prefix, rel_param.param_str);
-               }
-           } else {
-               if (register_idx)
-               {
-                   sprintf(register_name, "%cC[A0.x + %u]", prefix, register_idx);
-               } else {
-                   sprintf(register_name, "%cC[A0.x]", prefix);
-               }
-           }
+        case WINED3DSPR_CONST:
+            {
+                const char prefix = pshader ? 'P' : 'V';
 
-        } else {
-            if (shader_constant_is_local(This, register_idx))
+                /* Relative addressing */
+                if (reg->rel_addr)
+                {
+                    glsl_src_param_t rel_param;
+                    shader_glsl_add_src_param(ins, reg->rel_addr, WINED3DSP_WRITEMASK_0, &rel_param);
+                    if (reg->idx) sprintf(register_name, "%cC[%s + %u]", prefix, rel_param.param_str, reg->idx);
+                    else sprintf(register_name, "%cC[%s]", prefix, rel_param.param_str);
+                }
+                else
+                {
+                    if (shader_constant_is_local(This, reg->idx))
+                        sprintf(register_name, "%cLC%u", prefix, reg->idx);
+                    else
+                        sprintf(register_name, "%cC[%u]", prefix, reg->idx);
+                }
+            }
+            break;
+
+        case WINED3DSPR_CONSTINT:
+            if (pshader) sprintf(register_name, "PI[%u]", reg->idx);
+            else sprintf(register_name, "VI[%u]", reg->idx);
+            break;
+
+        case WINED3DSPR_CONSTBOOL:
+            if (pshader) sprintf(register_name, "PB[%u]", reg->idx);
+            else sprintf(register_name, "VB[%u]", reg->idx);
+            break;
+
+        case WINED3DSPR_TEXTURE: /* case WINED3DSPR_ADDR: */
+            if (pshader) sprintf(register_name, "T%u", reg->idx);
+            else sprintf(register_name, "A%u", reg->idx);
+            break;
+
+        case WINED3DSPR_LOOP:
+            sprintf(register_name, "aL%u", This->baseShader.cur_loop_regno - 1);
+            break;
+
+        case WINED3DSPR_SAMPLER:
+            if (pshader) sprintf(register_name, "Psampler%u", reg->idx);
+            else sprintf(register_name, "Vsampler%u", reg->idx);
+            break;
+
+        case WINED3DSPR_COLOROUT:
+            if (reg->idx >= GL_LIMITS(buffers))
+                WARN("Write to render target %u, only %d supported\n", reg->idx, 4);
+
+            if (GL_SUPPORT(ARB_DRAW_BUFFERS)) sprintf(register_name, "gl_FragData[%u]", reg->idx);
+            /* On older cards with GLSL support like the GeforceFX there's only one buffer. */
+            else sprintf(register_name, "gl_FragColor");
+            break;
+
+        case WINED3DSPR_RASTOUT:
+            sprintf(register_name, "%s", hwrastout_reg_names[reg->idx]);
+            break;
+
+        case WINED3DSPR_DEPTHOUT:
+            sprintf(register_name, "gl_FragDepth");
+            break;
+
+        case WINED3DSPR_ATTROUT:
+            if (reg->idx == 0) sprintf(register_name, "gl_FrontColor");
+            else sprintf(register_name, "gl_FrontSecondaryColor");
+            break;
+
+        case WINED3DSPR_TEXCRDOUT:
+            /* Vertex shaders >= 3.0: WINED3DSPR_OUTPUT */
+            if (This->baseShader.reg_maps.shader_version.major >= 3) sprintf(register_name, "OUT[%u]", reg->idx);
+            else sprintf(register_name, "gl_TexCoord[%u]", reg->idx);
+            break;
+
+        case WINED3DSPR_MISCTYPE:
+            if (reg->idx == 0)
             {
-                sprintf(register_name, "%cLC%u", prefix, register_idx);
-            } else {
-                sprintf(register_name, "%cC[%u]", prefix, register_idx);
+                /* vPos */
+                sprintf(register_name, "vpos");
             }
-        }
+            else if (reg->idx == 1)
+            {
+                /* Note that gl_FrontFacing is a bool, while vFace is
+                 * a float for which the sign determines front/back */
+                sprintf(register_name, "(gl_FrontFacing ? 1.0 : -1.0)");
+            }
+            else
+            {
+                FIXME("Unhandled misctype register %d\n", reg->idx);
+                sprintf(register_name, "unrecognized_register");
+            }
+            break;
 
-        break;
-    }
-    case WINED3DSPR_CONSTINT:
-        if (pshader)
-            sprintf(register_name, "PI[%u]", register_idx);
-        else
-            sprintf(register_name, "VI[%u]", register_idx);
-        break;
-    case WINED3DSPR_CONSTBOOL:
-        if (pshader)
-            sprintf(register_name, "PB[%u]", register_idx);
-        else
-            sprintf(register_name, "VB[%u]", register_idx);
-        break;
-    case WINED3DSPR_TEXTURE: /* case WINED3DSPR_ADDR: */
-        if (pshader) {
-            sprintf(register_name, "T%u", register_idx);
-        } else {
-            sprintf(register_name, "A%u", register_idx);
-        }
-    break;
-    case WINED3DSPR_LOOP:
-        sprintf(register_name, "aL%u", This->baseShader.cur_loop_regno - 1);
-    break;
-    case WINED3DSPR_SAMPLER:
-        if (pshader)
-            sprintf(register_name, "Psampler%u", register_idx);
-        else
-            sprintf(register_name, "Vsampler%u", register_idx);
-    break;
-    case WINED3DSPR_COLOROUT:
-        if (register_idx >= GL_LIMITS(buffers))
-            WARN("Write to render target %u, only %d supported\n", register_idx, 4);
-
-        if (GL_SUPPORT(ARB_DRAW_BUFFERS)) {
-            sprintf(register_name, "gl_FragData[%u]", register_idx);
-        } else { /* On older cards with GLSL support like the GeforceFX there's only one buffer. */
-            sprintf(register_name, "gl_FragColor");
-        }
-    break;
-    case WINED3DSPR_RASTOUT:
-        sprintf(register_name, "%s", hwrastout_reg_names[register_idx]);
-    break;
-    case WINED3DSPR_DEPTHOUT:
-        sprintf(register_name, "gl_FragDepth");
-    break;
-    case WINED3DSPR_ATTROUT:
-        if (register_idx == 0)
-        {
-            sprintf(register_name, "gl_FrontColor");
-        } else {
-            sprintf(register_name, "gl_FrontSecondaryColor");
-        }
-    break;
-    case WINED3DSPR_TEXCRDOUT:
-        /* Vertex shaders >= 3.0: WINED3DSPR_OUTPUT */
-        if (WINED3DSHADER_VERSION_MAJOR(shader_version) >= 3) sprintf(register_name, "OUT[%u]", register_idx);
-        else sprintf(register_name, "gl_TexCoord[%u]", register_idx);
-    break;
-    case WINED3DSPR_MISCTYPE:
-        if (register_idx == 0)
-        {
-            /* vPos */
-            sprintf(register_name, "vpos");
-        }
-        else if (register_idx == 1)
-        {
-            /* Note that gl_FrontFacing is a bool, while vFace is
-             * a float for which the sign determines front/back
-             */
-            sprintf(register_name, "(gl_FrontFacing ? 1.0 : -1.0)");
-        } else {
-            FIXME("Unhandled misctype register %d\n", register_idx);
+        case WINED3DSPR_IMMCONST:
+            switch (reg->immconst_type)
+            {
+                case WINED3D_IMMCONST_FLOAT:
+                    sprintf(register_name, "%.8e", *(float *)reg->immconst_data);
+                    break;
+
+                case WINED3D_IMMCONST_FLOAT4:
+                    sprintf(register_name, "vec4(%.8e, %.8e, %.8e, %.8e)",
+                            *(float *)&reg->immconst_data[0], *(float *)&reg->immconst_data[1],
+                            *(float *)&reg->immconst_data[2], *(float *)&reg->immconst_data[3]);
+                    break;
+
+                default:
+                    FIXME("Unhandled immconst type %#x\n", reg->immconst_type);
+                    sprintf(register_name, "<unhandled_immconst_type %#x>", reg->immconst_type);
+            }
+            break;
+
+        default:
+            FIXME("Unhandled register name Type(%d)\n", reg->type);
             sprintf(register_name, "unrecognized_register");
-        }
-        break;
-    default:
-        FIXME("Unhandled register name Type(%d)\n", register_type);
-        sprintf(register_name, "unrecognized_register");
-    break;
+            break;
     }
 }
 
@@ -1232,7 +1261,7 @@ static DWORD shader_glsl_get_write_mask(const struct wined3d_shader_dst_param *p
 {
     DWORD mask = param->write_mask;
 
-    if (shader_is_scalar(param->register_type, param->register_idx))
+    if (shader_is_scalar(&param->reg))
     {
         mask = WINED3DSP_WRITEMASK_0;
         *write_mask = '\0';
@@ -1256,45 +1285,47 @@ static unsigned int shader_glsl_get_write_mask_size(DWORD write_mask) {
     return size;
 }
 
-static void shader_glsl_get_swizzle(const DWORD param, BOOL fixup, DWORD mask, char *swizzle_str) {
+static void shader_glsl_swizzle_to_str(const DWORD swizzle, BOOL fixup, DWORD mask, char *str)
+{
     /* For registers of type WINED3DDECLTYPE_D3DCOLOR, data is stored as "bgra",
      * but addressed as "rgba". To fix this we need to swap the register's x
      * and z components. */
-    DWORD swizzle = (param & WINED3DSP_SWIZZLE_MASK) >> WINED3DSP_SWIZZLE_SHIFT;
     const char *swizzle_chars = fixup ? "zyxw" : "xyzw";
-    char *ptr = swizzle_str;
 
-    if (!shader_is_scalar(shader_get_regtype(param), param & WINED3DSP_REGNUM_MASK))
-    {
-        *ptr++ = '.';
-        /* swizzle bits fields: wwzzyyxx */
-        if (mask & WINED3DSP_WRITEMASK_0) *ptr++ = swizzle_chars[swizzle & 0x03];
-        if (mask & WINED3DSP_WRITEMASK_1) *ptr++ = swizzle_chars[(swizzle >> 2) & 0x03];
-        if (mask & WINED3DSP_WRITEMASK_2) *ptr++ = swizzle_chars[(swizzle >> 4) & 0x03];
-        if (mask & WINED3DSP_WRITEMASK_3) *ptr++ = swizzle_chars[(swizzle >> 6) & 0x03];
-    }
+    *str++ = '.';
+    /* swizzle bits fields: wwzzyyxx */
+    if (mask & WINED3DSP_WRITEMASK_0) *str++ = swizzle_chars[swizzle & 0x03];
+    if (mask & WINED3DSP_WRITEMASK_1) *str++ = swizzle_chars[(swizzle >> 2) & 0x03];
+    if (mask & WINED3DSP_WRITEMASK_2) *str++ = swizzle_chars[(swizzle >> 4) & 0x03];
+    if (mask & WINED3DSP_WRITEMASK_3) *str++ = swizzle_chars[(swizzle >> 6) & 0x03];
+    *str = '\0';
+}
 
-    *ptr = '\0';
+static void shader_glsl_get_swizzle(const struct wined3d_shader_src_param *param,
+        BOOL fixup, DWORD mask, char *swizzle_str)
+{
+    if (shader_is_scalar(&param->reg))
+        *swizzle_str = '\0';
+    else
+        shader_glsl_swizzle_to_str(param->swizzle, fixup, mask, swizzle_str);
 }
 
 /* From a given parameter token, generate the corresponding GLSL string.
  * Also, return the actual register name and swizzle in case the
  * caller needs this information as well. */
 static void shader_glsl_add_src_param(const struct wined3d_shader_instruction *ins,
-        const DWORD param, const DWORD addr_token, DWORD mask, glsl_src_param_t *src_param)
+        const struct wined3d_shader_src_param *wined3d_src, DWORD mask, glsl_src_param_t *glsl_src)
 {
     BOOL is_color = FALSE;
     char swizzle_str[6];
 
-    src_param->reg_name[0] = '\0';
-    src_param->param_str[0] = '\0';
+    glsl_src->reg_name[0] = '\0';
+    glsl_src->param_str[0] = '\0';
     swizzle_str[0] = '\0';
 
-    shader_glsl_get_register_name(shader_get_regtype(param), param & WINED3DSP_REGNUM_MASK,
-            param & WINED3DSHADER_ADDRMODE_RELATIVE, addr_token, src_param->reg_name, &is_color, ins);
-
-    shader_glsl_get_swizzle(param, is_color, mask, swizzle_str);
-    shader_glsl_gen_modifier(param, src_param->reg_name, swizzle_str, src_param->param_str);
+    shader_glsl_get_register_name(&wined3d_src->reg, glsl_src->reg_name, &is_color, ins);
+    shader_glsl_get_swizzle(wined3d_src, is_color, mask, swizzle_str);
+    shader_glsl_gen_modifier(wined3d_src->modifiers, glsl_src->reg_name, swizzle_str, glsl_src->param_str);
 }
 
 /* From a given parameter token, generate the corresponding GLSL string.
@@ -1308,8 +1339,7 @@ static DWORD shader_glsl_add_dst_param(const struct wined3d_shader_instruction *
     glsl_dst->mask_str[0] = '\0';
     glsl_dst->reg_name[0] = '\0';
 
-    shader_glsl_get_register_name(wined3d_dst->register_type, wined3d_dst->register_idx,
-            wined3d_dst->has_rel_addr, wined3d_dst->addr_token, glsl_dst->reg_name, &is_color, ins);
+    shader_glsl_get_register_name(&wined3d_dst->reg, glsl_dst->reg_name, &is_color, ins);
     return shader_glsl_get_write_mask(wined3d_dst, glsl_dst->mask_str);
 }
 
@@ -1333,7 +1363,7 @@ static DWORD shader_glsl_append_dst(SHADER_BUFFER *buffer, const struct wined3d_
 }
 
 /** Process GLSL instruction modifiers */
-void shader_glsl_add_instruction_modifiers(const struct wined3d_shader_instruction *ins)
+static void shader_glsl_add_instruction_modifiers(const struct wined3d_shader_instruction *ins)
 {
     glsl_dst_param_t dst_param;
     DWORD modifiers;
@@ -1348,7 +1378,7 @@ void shader_glsl_add_instruction_modifiers(const struct wined3d_shader_instructi
     if (modifiers & WINED3DSPDM_SATURATE)
     {
         /* _SAT means to clamp the value of the register to between 0 and 1 */
-        shader_addline(ins->buffer, "%s%s = clamp(%s%s, 0.0, 1.0);\n", dst_param.reg_name,
+        shader_addline(ins->ctx->buffer, "%s%s = clamp(%s%s, 0.0, 1.0);\n", dst_param.reg_name,
                 dst_param.mask_str, dst_param.reg_name, dst_param.mask_str);
     }
 
@@ -1363,9 +1393,8 @@ void shader_glsl_add_instruction_modifiers(const struct wined3d_shader_instructi
     }
 }
 
-static inline const char *shader_get_comp_op(DWORD flags)
+static inline const char *shader_get_comp_op(DWORD op)
 {
-    DWORD op = (flags & INST_CONTROLS_MASK) >> INST_CONTROLS_SHIFT;
     switch (op) {
         case COMPARISON_GT: return ">";
         case COMPARISON_EQ: return "==";
@@ -1384,12 +1413,15 @@ static void shader_glsl_get_sample_function(DWORD sampler_type, DWORD flags, gls
     BOOL projected = flags & WINED3D_GLSL_SAMPLE_PROJECTED;
     BOOL texrect = flags & WINED3D_GLSL_SAMPLE_RECT;
     BOOL lod = flags & WINED3D_GLSL_SAMPLE_LOD;
+    BOOL grad = flags & WINED3D_GLSL_SAMPLE_GRAD;
 
     /* Note that there's no such thing as a projected cube texture. */
     switch(sampler_type) {
         case WINED3DSTT_1D:
             if(lod) {
                 sample_function->name = projected ? "texture1DProjLod" : "texture1DLod";
+            } else  if(grad) {
+                sample_function->name = projected ? "texture1DProjGradARB" : "texture1DGradARB";
             } else {
                 sample_function->name = projected ? "texture1DProj" : "texture1D";
             }
@@ -1399,12 +1431,19 @@ static void shader_glsl_get_sample_function(DWORD sampler_type, DWORD flags, gls
             if(texrect) {
                 if(lod) {
                     sample_function->name = projected ? "texture2DRectProjLod" : "texture2DRectLod";
+                } else  if(grad) {
+                    /* What good are texrect grad functions? I don't know, but GL_EXT_gpu_shader4 defines them.
+                    * There is no GL_ARB_shader_texture_lod spec yet, so I don't know if they're defined there
+                     */
+                    sample_function->name = projected ? "shadow2DRectProjGradARB" : "shadow2DRectGradARB";
                 } else {
                     sample_function->name = projected ? "texture2DRectProj" : "texture2DRect";
                 }
             } else {
                 if(lod) {
                     sample_function->name = projected ? "texture2DProjLod" : "texture2DLod";
+                } else  if(grad) {
+                    sample_function->name = projected ? "texture2DProjGradARB" : "texture2DGradARB";
                 } else {
                     sample_function->name = projected ? "texture2DProj" : "texture2D";
                 }
@@ -1414,6 +1453,8 @@ static void shader_glsl_get_sample_function(DWORD sampler_type, DWORD flags, gls
         case WINED3DSTT_CUBE:
             if(lod) {
                 sample_function->name = "textureCubeLod";
+            } else if(grad) {
+                sample_function->name = "textureCubeGradARB";
             } else {
                 sample_function->name = "textureCube";
             }
@@ -1422,6 +1463,8 @@ static void shader_glsl_get_sample_function(DWORD sampler_type, DWORD flags, gls
         case WINED3DSTT_VOLUME:
             if(lod) {
                 sample_function->name = projected ? "texture3DProjLod" : "texture3DLod";
+            } else  if(grad) {
+                sample_function->name = projected ? "texture3DProjGradARB" : "texture3DGradARB";
             } else {
                 sample_function->name = projected ? "texture3DProj" : "texture3D";
             }
@@ -1532,17 +1575,18 @@ static void shader_glsl_color_correction(const struct wined3d_shader_instruction
 
     if (mask_size > 1)
     {
-        shader_addline(ins->buffer, "%s%s = vec%u(%s);\n",
+        shader_addline(ins->ctx->buffer, "%s%s = vec%u(%s);\n",
                 dst_param.reg_name, dst_param.mask_str, mask_size, arguments);
     }
     else
     {
-        shader_addline(ins->buffer, "%s%s = %s;\n", dst_param.reg_name, dst_param.mask_str, arguments);
+        shader_addline(ins->ctx->buffer, "%s%s = %s;\n", dst_param.reg_name, dst_param.mask_str, arguments);
     }
 }
 
-static void PRINTF_ATTR(6, 7) shader_glsl_gen_sample_code(const struct wined3d_shader_instruction *ins,
+static void PRINTF_ATTR(8, 9) shader_glsl_gen_sample_code(const struct wined3d_shader_instruction *ins,
         DWORD sampler, const glsl_sample_function_t *sample_function, DWORD swizzle,
+        const char *dx, const char *dy,
         const char *bias, const char *coord_reg_fmt, ...)
 {
     const char *sampler_base;
@@ -1551,11 +1595,11 @@ static void PRINTF_ATTR(6, 7) shader_glsl_gen_sample_code(const struct wined3d_s
     BOOL np2_fixup = FALSE;
     va_list args;
 
-    shader_glsl_get_swizzle(swizzle, FALSE, ins->dst[0].write_mask, dst_swizzle);
+    shader_glsl_swizzle_to_str(swizzle, FALSE, ins->dst[0].write_mask, dst_swizzle);
 
-    if (shader_is_pshader_version(ins->reg_maps->shader_version))
+    if (shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type))
     {
-        IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->shader;
+        IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->ctx->shader;
         fixup = This->cur_args->color_fixup[sampler];
         sampler_base = "Psampler";
 
@@ -1571,21 +1615,23 @@ static void PRINTF_ATTR(6, 7) shader_glsl_gen_sample_code(const struct wined3d_s
         fixup = COLOR_FIXUP_IDENTITY; /* FIXME: Vshader color fixup */
     }
 
-    shader_glsl_append_dst(ins->buffer, ins);
+    shader_glsl_append_dst(ins->ctx->buffer, ins);
 
-    shader_addline(ins->buffer, "%s(%s%u, ", sample_function->name, sampler_base, sampler);
+    shader_addline(ins->ctx->buffer, "%s(%s%u, ", sample_function->name, sampler_base, sampler);
 
     va_start(args, coord_reg_fmt);
-    shader_vaddline(ins->buffer, coord_reg_fmt, args);
+    shader_vaddline(ins->ctx->buffer, coord_reg_fmt, args);
     va_end(args);
 
     if(bias) {
-        shader_addline(ins->buffer, ", %s)%s);\n", bias, dst_swizzle);
+        shader_addline(ins->ctx->buffer, ", %s)%s);\n", bias, dst_swizzle);
     } else {
         if (np2_fixup) {
-            shader_addline(ins->buffer, " * PsamplerNP2Fixup%u)%s);\n", sampler, dst_swizzle);
+            shader_addline(ins->ctx->buffer, " * PsamplerNP2Fixup%u)%s);\n", sampler, dst_swizzle);
+        } else if(dx && dy) {
+            shader_addline(ins->ctx->buffer, ", %s, %s)%s);\n", dx, dy, dst_swizzle);
         } else {
-            shader_addline(ins->buffer, ")%s);\n", dst_swizzle);
+            shader_addline(ins->ctx->buffer, ")%s);\n", dst_swizzle);
         }
     }
 
@@ -1603,7 +1649,7 @@ static void PRINTF_ATTR(6, 7) shader_glsl_gen_sample_code(const struct wined3d_s
 /* Generate GLSL arithmetic functions (dst = src1 + src2) */
 static void shader_glsl_arith(const struct wined3d_shader_instruction *ins)
 {
-    SHADER_BUFFER *buffer = ins->buffer;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
     glsl_src_param_t src0_param;
     glsl_src_param_t src1_param;
     DWORD write_mask;
@@ -1622,26 +1668,26 @@ static void shader_glsl_arith(const struct wined3d_shader_instruction *ins)
     }
 
     write_mask = shader_glsl_append_dst(buffer, ins);
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], write_mask, &src0_param);
-    shader_glsl_add_src_param(ins, ins->src[1], ins->src_addr[1], write_mask, &src1_param);
+    shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
     shader_addline(buffer, "%s %c %s);\n", src0_param.param_str, op, src1_param.param_str);
 }
 
 /* Process the WINED3DSIO_MOV opcode using GLSL (dst = src) */
 static void shader_glsl_mov(const struct wined3d_shader_instruction *ins)
 {
-    SHADER_BUFFER *buffer = ins->buffer;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
     glsl_src_param_t src0_param;
     DWORD write_mask;
 
     write_mask = shader_glsl_append_dst(buffer, ins);
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], write_mask, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
 
     /* In vs_1_1 WINED3DSIO_MOV can write to the address register. In later
      * shader versions WINED3DSIO_MOVA is used for this. */
-    if ((WINED3DSHADER_VERSION_MAJOR(ins->reg_maps->shader_version) == 1
-            && !shader_is_pshader_version(ins->reg_maps->shader_version)
-            && ins->dst[0].register_type == WINED3DSPR_ADDR))
+    if (ins->ctx->reg_maps->shader_version.major == 1
+            && !shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type)
+            && ins->dst[0].reg.type == WINED3DSPR_ADDR)
     {
         /* This is a simple floor() */
         unsigned int mask_size = shader_glsl_get_write_mask_size(write_mask);
@@ -1668,7 +1714,7 @@ static void shader_glsl_mov(const struct wined3d_shader_instruction *ins)
 /* Process the dot product operators DP3 and DP4 in GLSL (dst = dot(src0, src1)) */
 static void shader_glsl_dot(const struct wined3d_shader_instruction *ins)
 {
-    SHADER_BUFFER *buffer = ins->buffer;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
     glsl_src_param_t src0_param;
     glsl_src_param_t src1_param;
     DWORD dst_write_mask, src_write_mask;
@@ -1685,8 +1731,8 @@ static void shader_glsl_dot(const struct wined3d_shader_instruction *ins)
         src_write_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
     }
 
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], src_write_mask, &src0_param);
-    shader_glsl_add_src_param(ins, ins->src[1], ins->src_addr[1], src_write_mask, &src1_param);
+    shader_glsl_add_src_param(ins, &ins->src[0], src_write_mask, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[1], src_write_mask, &src1_param);
 
     if (dst_size > 1) {
         shader_addline(buffer, "vec%d(dot(%s, %s)));\n", dst_size, src0_param.param_str, src1_param.param_str);
@@ -1705,10 +1751,10 @@ static void shader_glsl_cross(const struct wined3d_shader_instruction *ins)
     char dst_mask[6];
 
     shader_glsl_get_write_mask(&ins->dst[0], dst_mask);
-    shader_glsl_append_dst(ins->buffer, ins);
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], src_mask, &src0_param);
-    shader_glsl_add_src_param(ins, ins->src[1], ins->src_addr[1], src_mask, &src1_param);
-    shader_addline(ins->buffer, "cross(%s, %s)%s);\n", src0_param.param_str, src1_param.param_str, dst_mask);
+    shader_glsl_append_dst(ins->ctx->buffer, ins);
+    shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[1], src_mask, &src1_param);
+    shader_addline(ins->ctx->buffer, "cross(%s, %s)%s);\n", src0_param.param_str, src1_param.param_str, dst_mask);
 }
 
 /* Process the WINED3DSIO_POW instruction in GLSL (dst = |src0|^src1)
@@ -1716,7 +1762,7 @@ static void shader_glsl_cross(const struct wined3d_shader_instruction *ins)
  * GLSL uses the value as-is. */
 static void shader_glsl_pow(const struct wined3d_shader_instruction *ins)
 {
-    SHADER_BUFFER *buffer = ins->buffer;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
     glsl_src_param_t src0_param;
     glsl_src_param_t src1_param;
     DWORD dst_write_mask;
@@ -1725,8 +1771,8 @@ static void shader_glsl_pow(const struct wined3d_shader_instruction *ins)
     dst_write_mask = shader_glsl_append_dst(buffer, ins);
     dst_size = shader_glsl_get_write_mask_size(dst_write_mask);
 
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], WINED3DSP_WRITEMASK_0, &src0_param);
-    shader_glsl_add_src_param(ins, ins->src[1], ins->src_addr[1], WINED3DSP_WRITEMASK_0, &src1_param);
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0, &src1_param);
 
     if (dst_size > 1) {
         shader_addline(buffer, "vec%d(pow(abs(%s), %s)));\n", dst_size, src0_param.param_str, src1_param.param_str);
@@ -1740,7 +1786,7 @@ static void shader_glsl_pow(const struct wined3d_shader_instruction *ins)
  * GLSL uses the value as-is. */
 static void shader_glsl_log(const struct wined3d_shader_instruction *ins)
 {
-    SHADER_BUFFER *buffer = ins->buffer;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
     glsl_src_param_t src0_param;
     DWORD dst_write_mask;
     unsigned int dst_size;
@@ -1748,7 +1794,7 @@ static void shader_glsl_log(const struct wined3d_shader_instruction *ins)
     dst_write_mask = shader_glsl_append_dst(buffer, ins);
     dst_size = shader_glsl_get_write_mask_size(dst_write_mask);
 
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], WINED3DSP_WRITEMASK_0, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param);
 
     if (dst_size > 1) {
         shader_addline(buffer, "vec%d(log2(abs(%s))));\n", dst_size, src0_param.param_str);
@@ -1760,7 +1806,7 @@ static void shader_glsl_log(const struct wined3d_shader_instruction *ins)
 /* Map the opcode 1-to-1 to the GL code (arg->dst = instruction(src0, src1, ...) */
 static void shader_glsl_map2gl(const struct wined3d_shader_instruction *ins)
 {
-    SHADER_BUFFER *buffer = ins->buffer;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
     glsl_src_param_t src_param;
     const char *instruction;
     DWORD write_mask;
@@ -1790,11 +1836,11 @@ static void shader_glsl_map2gl(const struct wined3d_shader_instruction *ins)
 
     if (ins->src_count)
     {
-        shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], write_mask, &src_param);
+        shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src_param);
         shader_addline(buffer, "%s", src_param.param_str);
         for (i = 1; i < ins->src_count; ++i)
         {
-            shader_glsl_add_src_param(ins, ins->src[i], ins->src_addr[i], write_mask, &src_param);
+            shader_glsl_add_src_param(ins, &ins->src[i], write_mask, &src_param);
             shader_addline(buffer, ", %s", src_param.param_str);
         }
     }
@@ -1815,31 +1861,31 @@ static void shader_glsl_expp(const struct wined3d_shader_instruction *ins)
 {
     glsl_src_param_t src_param;
 
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], WINED3DSP_WRITEMASK_0, &src_param);
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src_param);
 
-    if (ins->reg_maps->shader_version < WINED3DPS_VERSION(2,0))
+    if (ins->ctx->reg_maps->shader_version.major < 2)
     {
         char dst_mask[6];
 
-        shader_addline(ins->buffer, "tmp0.x = exp2(floor(%s));\n", src_param.param_str);
-        shader_addline(ins->buffer, "tmp0.y = %s - floor(%s);\n", src_param.param_str, src_param.param_str);
-        shader_addline(ins->buffer, "tmp0.z = exp2(%s);\n", src_param.param_str);
-        shader_addline(ins->buffer, "tmp0.w = 1.0;\n");
+        shader_addline(ins->ctx->buffer, "tmp0.x = exp2(floor(%s));\n", src_param.param_str);
+        shader_addline(ins->ctx->buffer, "tmp0.y = %s - floor(%s);\n", src_param.param_str, src_param.param_str);
+        shader_addline(ins->ctx->buffer, "tmp0.z = exp2(%s);\n", src_param.param_str);
+        shader_addline(ins->ctx->buffer, "tmp0.w = 1.0;\n");
 
-        shader_glsl_append_dst(ins->buffer, ins);
+        shader_glsl_append_dst(ins->ctx->buffer, ins);
         shader_glsl_get_write_mask(&ins->dst[0], dst_mask);
-        shader_addline(ins->buffer, "tmp0%s);\n", dst_mask);
+        shader_addline(ins->ctx->buffer, "tmp0%s);\n", dst_mask);
     } else {
         DWORD write_mask;
         unsigned int mask_size;
 
-        write_mask = shader_glsl_append_dst(ins->buffer, ins);
+        write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
         mask_size = shader_glsl_get_write_mask_size(write_mask);
 
         if (mask_size > 1) {
-            shader_addline(ins->buffer, "vec%d(exp2(%s)));\n", mask_size, src_param.param_str);
+            shader_addline(ins->ctx->buffer, "vec%d(exp2(%s)));\n", mask_size, src_param.param_str);
         } else {
-            shader_addline(ins->buffer, "exp2(%s));\n", src_param.param_str);
+            shader_addline(ins->ctx->buffer, "exp2(%s));\n", src_param.param_str);
         }
     }
 }
@@ -1851,20 +1897,20 @@ static void shader_glsl_rcp(const struct wined3d_shader_instruction *ins)
     DWORD write_mask;
     unsigned int mask_size;
 
-    write_mask = shader_glsl_append_dst(ins->buffer, ins);
+    write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
     mask_size = shader_glsl_get_write_mask_size(write_mask);
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], WINED3DSP_WRITEMASK_3, &src_param);
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &src_param);
 
     if (mask_size > 1) {
-        shader_addline(ins->buffer, "vec%d(1.0 / %s));\n", mask_size, src_param.param_str);
+        shader_addline(ins->ctx->buffer, "vec%d(1.0 / %s));\n", mask_size, src_param.param_str);
     } else {
-        shader_addline(ins->buffer, "1.0 / %s);\n", src_param.param_str);
+        shader_addline(ins->ctx->buffer, "1.0 / %s);\n", src_param.param_str);
     }
 }
 
 static void shader_glsl_rsq(const struct wined3d_shader_instruction *ins)
 {
-    SHADER_BUFFER *buffer = ins->buffer;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
     glsl_src_param_t src_param;
     DWORD write_mask;
     unsigned int mask_size;
@@ -1872,7 +1918,7 @@ static void shader_glsl_rsq(const struct wined3d_shader_instruction *ins)
     write_mask = shader_glsl_append_dst(buffer, ins);
     mask_size = shader_glsl_get_write_mask_size(write_mask);
 
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], WINED3DSP_WRITEMASK_3, &src_param);
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &src_param);
 
     if (mask_size > 1) {
         shader_addline(buffer, "vec%d(inversesqrt(%s)));\n", mask_size, src_param.param_str);
@@ -1889,10 +1935,10 @@ static void shader_glsl_compare(const struct wined3d_shader_instruction *ins)
     DWORD write_mask;
     unsigned int mask_size;
 
-    write_mask = shader_glsl_append_dst(ins->buffer, ins);
+    write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
     mask_size = shader_glsl_get_write_mask_size(write_mask);
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], write_mask, &src0_param);
-    shader_glsl_add_src_param(ins, ins->src[1], ins->src_addr[1], write_mask, &src1_param);
+    shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
 
     if (mask_size > 1) {
         const char *compare;
@@ -1905,7 +1951,7 @@ static void shader_glsl_compare(const struct wined3d_shader_instruction *ins)
                 FIXME("Can't handle opcode %#x\n", ins->handler_idx);
         }
 
-        shader_addline(ins->buffer, "vec%d(%s(%s, %s)));\n", mask_size, compare,
+        shader_addline(ins->ctx->buffer, "vec%d(%s(%s, %s)));\n", mask_size, compare,
                 src0_param.param_str, src1_param.param_str);
     } else {
         switch(ins->handler_idx)
@@ -1918,11 +1964,12 @@ static void shader_glsl_compare(const struct wined3d_shader_instruction *ins)
                  * issue. Playing with not() is not possible either because not() does not accept
                  * a scalar.
                  */
-                shader_addline(ins->buffer, "(%s < %s) ? 1.0 : 0.0);\n", src0_param.param_str, src1_param.param_str);
+                shader_addline(ins->ctx->buffer, "(%s < %s) ? 1.0 : 0.0);\n",
+                        src0_param.param_str, src1_param.param_str);
                 break;
             case WINED3DSIH_SGE:
                 /* Here we can use the step() function and safe a conditional */
-                shader_addline(ins->buffer, "step(%s, %s));\n", src1_param.param_str, src0_param.param_str);
+                shader_addline(ins->ctx->buffer, "step(%s, %s));\n", src1_param.param_str, src0_param.param_str);
                 break;
             default:
                 FIXME("Can't handle opcode %#x\n", ins->handler_idx);
@@ -1942,25 +1989,17 @@ static void shader_glsl_cmp(const struct wined3d_shader_instruction *ins)
     char mask_char[6];
     BOOL temp_destination = FALSE;
 
-    if (shader_is_scalar(shader_get_regtype(ins->src[0]), ins->src[0] & WINED3DSP_REGNUM_MASK))
+    if (shader_is_scalar(&ins->src[0].reg))
     {
-        write_mask = shader_glsl_append_dst(ins->buffer, ins);
+        write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
 
-        shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], WINED3DSP_WRITEMASK_ALL, &src0_param);
-        shader_glsl_add_src_param(ins, ins->src[1], ins->src_addr[1], write_mask, &src1_param);
-        shader_glsl_add_src_param(ins, ins->src[2], ins->src_addr[2], write_mask, &src2_param);
+        shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_ALL, &src0_param);
+        shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
+        shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param);
 
-        shader_addline(ins->buffer, "%s >= 0.0 ? %s : %s);\n",
+        shader_addline(ins->ctx->buffer, "%s >= 0.0 ? %s : %s);\n",
                        src0_param.param_str, src1_param.param_str, src2_param.param_str);
     } else {
-        DWORD src0reg = ins->src[0] & WINED3DSP_REGNUM_MASK;
-        DWORD src1reg = ins->src[1] & WINED3DSP_REGNUM_MASK;
-        DWORD src2reg = ins->src[2] & WINED3DSP_REGNUM_MASK;
-        DWORD src0regtype = shader_get_regtype(ins->src[0]);
-        DWORD src1regtype = shader_get_regtype(ins->src[1]);
-        DWORD src2regtype = shader_get_regtype(ins->src[2]);
-        DWORD dstreg = ins->dst[0].register_idx;
-        DWORD dstregtype = ins->dst[0].register_type;
         DWORD dst_mask = ins->dst[0].write_mask;
         struct wined3d_shader_dst_param dst = ins->dst[0];
 
@@ -1969,7 +2008,7 @@ static void shader_glsl_cmp(const struct wined3d_shader_instruction *ins)
             write_mask = 0;
             /* Find the destination channels which use the current source0 channel */
             for (j=0; j<4; j++) {
-                if (((ins->src[0] >> (WINED3DSP_SWIZZLE_SHIFT + 2 * j)) & 0x3) == i)
+                if (((ins->src[0].swizzle >> (2 * j)) & 0x3) == i)
                 {
                     write_mask |= WINED3DSP_WRITEMASK_0 << j;
                     cmp_channel = WINED3DSP_WRITEMASK_0 << j;
@@ -1981,31 +2020,34 @@ static void shader_glsl_cmp(const struct wined3d_shader_instruction *ins)
             * The first lines may overwrite source parameters of the following lines.
             * Deal with that by using a temporary destination register if needed
             */
-            if ((src0reg == dstreg && src0regtype == dstregtype)
-                    || (src1reg == dstreg && src1regtype == dstregtype)
-                    || (src2reg == dstreg && src2regtype == dstregtype))
+            if ((ins->src[0].reg.idx == ins->dst[0].reg.idx
+                    && ins->src[0].reg.type == ins->dst[0].reg.type)
+                    || (ins->src[1].reg.idx == ins->dst[0].reg.idx
+                    && ins->src[1].reg.type == ins->dst[0].reg.type)
+                    || (ins->src[2].reg.idx == ins->dst[0].reg.idx
+                    && ins->src[2].reg.type == ins->dst[0].reg.type))
             {
                 write_mask = shader_glsl_get_write_mask(&dst, mask_char);
                 if (!write_mask) continue;
-                shader_addline(ins->buffer, "tmp0%s = (", mask_char);
+                shader_addline(ins->ctx->buffer, "tmp0%s = (", mask_char);
                 temp_destination = TRUE;
             } else {
-                write_mask = shader_glsl_append_dst_ext(ins->buffer, ins, &dst);
+                write_mask = shader_glsl_append_dst_ext(ins->ctx->buffer, ins, &dst);
                 if (!write_mask) continue;
             }
 
-            shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], cmp_channel, &src0_param);
-            shader_glsl_add_src_param(ins, ins->src[1], ins->src_addr[1], write_mask, &src1_param);
-            shader_glsl_add_src_param(ins, ins->src[2], ins->src_addr[2], write_mask, &src2_param);
+            shader_glsl_add_src_param(ins, &ins->src[0], cmp_channel, &src0_param);
+            shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
+            shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param);
 
-            shader_addline(ins->buffer, "%s >= 0.0 ? %s : %s);\n",
+            shader_addline(ins->ctx->buffer, "%s >= 0.0 ? %s : %s);\n",
                         src0_param.param_str, src1_param.param_str, src2_param.param_str);
         }
 
         if(temp_destination) {
             shader_glsl_get_write_mask(&ins->dst[0], mask_char);
-            shader_glsl_append_dst(ins->buffer, ins);
-            shader_addline(ins->buffer, "tmp0%s);\n", mask_char);
+            shader_glsl_append_dst(ins->ctx->buffer, ins);
+            shader_addline(ins->ctx->buffer, "tmp0%s);\n", mask_char);
         }
     }
 
@@ -2023,20 +2065,22 @@ static void shader_glsl_cnd(const struct wined3d_shader_instruction *ins)
     DWORD write_mask, cmp_channel = 0;
     unsigned int i, j;
     DWORD dst_mask;
+    DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major,
+            ins->ctx->reg_maps->shader_version.minor);
 
-    if (ins->reg_maps->shader_version < WINED3DPS_VERSION(1, 4))
+    if (shader_version < WINED3D_SHADER_VERSION(1, 4))
     {
-        write_mask = shader_glsl_append_dst(ins->buffer, ins);
-        shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], WINED3DSP_WRITEMASK_0, &src0_param);
-        shader_glsl_add_src_param(ins, ins->src[1], ins->src_addr[1], write_mask, &src1_param);
-        shader_glsl_add_src_param(ins, ins->src[2], ins->src_addr[2], write_mask, &src2_param);
+        write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
+        shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param);
+        shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
+        shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param);
 
         /* Fun: The D3DSI_COISSUE flag changes the semantic of the cnd instruction for < 1.4 shaders */
         if (ins->coissue)
         {
-            shader_addline(ins->buffer, "%s /* COISSUE! */);\n", src1_param.param_str);
+            shader_addline(ins->ctx->buffer, "%s /* COISSUE! */);\n", src1_param.param_str);
         } else {
-            shader_addline(ins->buffer, "%s > 0.5 ? %s : %s);\n",
+            shader_addline(ins->ctx->buffer, "%s > 0.5 ? %s : %s);\n",
                     src0_param.param_str, src1_param.param_str, src2_param.param_str);
         }
         return;
@@ -2048,7 +2092,7 @@ static void shader_glsl_cnd(const struct wined3d_shader_instruction *ins)
         write_mask = 0;
         /* Find the destination channels which use the current source0 channel */
         for (j=0; j<4; j++) {
-            if (((ins->src[0] >> (WINED3DSP_SWIZZLE_SHIFT + 2 * j)) & 0x3) == i)
+            if (((ins->src[0].swizzle >> (2 * j)) & 0x3) == i)
             {
                 write_mask |= WINED3DSP_WRITEMASK_0 << j;
                 cmp_channel = WINED3DSP_WRITEMASK_0 << j;
@@ -2056,14 +2100,14 @@ static void shader_glsl_cnd(const struct wined3d_shader_instruction *ins)
         }
 
         dst.write_mask = dst_mask & write_mask;
-        write_mask = shader_glsl_append_dst_ext(ins->buffer, ins, &dst);
+        write_mask = shader_glsl_append_dst_ext(ins->ctx->buffer, ins, &dst);
         if (!write_mask) continue;
 
-        shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], cmp_channel, &src0_param);
-        shader_glsl_add_src_param(ins, ins->src[1], ins->src_addr[1], write_mask, &src1_param);
-        shader_glsl_add_src_param(ins, ins->src[2], ins->src_addr[2], write_mask, &src2_param);
+        shader_glsl_add_src_param(ins, &ins->src[0], cmp_channel, &src0_param);
+        shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
+        shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param);
 
-        shader_addline(ins->buffer, "%s > 0.5 ? %s : %s);\n",
+        shader_addline(ins->ctx->buffer, "%s > 0.5 ? %s : %s);\n",
                 src0_param.param_str, src1_param.param_str, src2_param.param_str);
     }
 }
@@ -2076,11 +2120,11 @@ static void shader_glsl_mad(const struct wined3d_shader_instruction *ins)
     glsl_src_param_t src2_param;
     DWORD write_mask;
 
-    write_mask = shader_glsl_append_dst(ins->buffer, ins);
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], write_mask, &src0_param);
-    shader_glsl_add_src_param(ins, ins->src[1], ins->src_addr[1], write_mask, &src1_param);
-    shader_glsl_add_src_param(ins, ins->src[2], ins->src_addr[2], write_mask, &src2_param);
-    shader_addline(ins->buffer, "(%s * %s) + %s);\n",
+    write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
+    shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
+    shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param);
+    shader_addline(ins->ctx->buffer, "(%s * %s) + %s);\n",
             src0_param.param_str, src1_param.param_str, src2_param.param_str);
 }
 
@@ -2090,21 +2134,18 @@ static void shader_glsl_mnxn(const struct wined3d_shader_instruction *ins)
 {
     int i;
     int nComponents = 0;
-    struct wined3d_shader_dst_param tmp_dst = {0};
+    struct wined3d_shader_dst_param tmp_dst = {{0}};
+    struct wined3d_shader_src_param tmp_src[2] = {{{0}}};
     struct wined3d_shader_instruction tmp_ins;
 
     memset(&tmp_ins, 0, sizeof(tmp_ins));
 
     /* Set constants for the temporary argument */
-    tmp_ins.shader      = ins->shader;
-    tmp_ins.buffer      = ins->buffer;
-    tmp_ins.src[0]      = ins->src[0];
-    tmp_ins.src_addr[0] = ins->src_addr[0];
-    tmp_ins.src_addr[1] = ins->src_addr[1];
-    tmp_ins.reg_maps = ins->reg_maps;
+    tmp_ins.ctx = ins->ctx;
     tmp_ins.dst_count = 1;
     tmp_ins.dst = &tmp_dst;
     tmp_ins.src_count = 2;
+    tmp_ins.src = tmp_src;
 
     switch(ins->handler_idx)
     {
@@ -2133,11 +2174,13 @@ static void shader_glsl_mnxn(const struct wined3d_shader_instruction *ins)
     }
 
     tmp_dst = ins->dst[0];
+    tmp_src[0] = ins->src[0];
+    tmp_src[1] = ins->src[1];
     for (i = 0; i < nComponents; ++i)
     {
         tmp_dst.write_mask = WINED3DSP_WRITEMASK_0 << i;
-        tmp_ins.src[1] = ins->src[1] + i;
         shader_glsl_dot(&tmp_ins);
+        ++tmp_src[1].reg.idx;
     }
 }
 
@@ -2154,13 +2197,13 @@ static void shader_glsl_lrp(const struct wined3d_shader_instruction *ins)
     glsl_src_param_t src2_param;
     DWORD write_mask;
 
-    write_mask = shader_glsl_append_dst(ins->buffer, ins);
+    write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
 
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], write_mask, &src0_param);
-    shader_glsl_add_src_param(ins, ins->src[1], ins->src_addr[1], write_mask, &src1_param);
-    shader_glsl_add_src_param(ins, ins->src[2], ins->src_addr[2], write_mask, &src2_param);
+    shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
+    shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param);
 
-    shader_addline(ins->buffer, "mix(%s, %s, %s));\n",
+    shader_addline(ins->ctx->buffer, "mix(%s, %s, %s));\n",
             src2_param.param_str, src1_param.param_str, src0_param.param_str);
 }
 
@@ -2177,12 +2220,12 @@ static void shader_glsl_lit(const struct wined3d_shader_instruction *ins)
     glsl_src_param_t src3_param;
     char dst_mask[6];
 
-    shader_glsl_append_dst(ins->buffer, ins);
+    shader_glsl_append_dst(ins->ctx->buffer, ins);
     shader_glsl_get_write_mask(&ins->dst[0], dst_mask);
 
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], WINED3DSP_WRITEMASK_0, &src0_param);
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], WINED3DSP_WRITEMASK_1, &src1_param);
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], WINED3DSP_WRITEMASK_3, &src3_param);
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_1, &src1_param);
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &src3_param);
 
     /* The sdk specifies the instruction like this
      * dst.x = 1.0;
@@ -2205,7 +2248,7 @@ static void shader_glsl_lit(const struct wined3d_shader_instruction *ins)
      * which sets dst.z to 0. If y > 0, but x = 0.0, we get pow(y * 0.0, power), which results in 0 too.
      * if both x and y are > 0, we get pow(y * 1.0, power), as it is supposed to
      */
-    shader_addline(ins->buffer,
+    shader_addline(ins->ctx->buffer,
             "vec4(1.0, max(%s, 0.0), pow(max(0.0, %s) * step(0.0, %s), clamp(%s, -128.0, 128.0)), 1.0)%s);\n",
             src0_param.param_str, src1_param.param_str, src0_param.param_str, src3_param.param_str, dst_mask);
 }
@@ -2224,15 +2267,15 @@ static void shader_glsl_dst(const struct wined3d_shader_instruction *ins)
     glsl_src_param_t src1w_param;
     char dst_mask[6];
 
-    shader_glsl_append_dst(ins->buffer, ins);
+    shader_glsl_append_dst(ins->ctx->buffer, ins);
     shader_glsl_get_write_mask(&ins->dst[0], dst_mask);
 
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], WINED3DSP_WRITEMASK_1, &src0y_param);
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], WINED3DSP_WRITEMASK_2, &src0z_param);
-    shader_glsl_add_src_param(ins, ins->src[1], ins->src_addr[1], WINED3DSP_WRITEMASK_1, &src1y_param);
-    shader_glsl_add_src_param(ins, ins->src[1], ins->src_addr[1], WINED3DSP_WRITEMASK_3, &src1w_param);
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_1, &src0y_param);
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_2, &src0z_param);
+    shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_1, &src1y_param);
+    shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_3, &src1w_param);
 
-    shader_addline(ins->buffer, "vec4(1.0, %s * %s, %s, %s))%s;\n",
+    shader_addline(ins->ctx->buffer, "vec4(1.0, %s * %s, %s, %s))%s;\n",
             src0y_param.param_str, src1y_param.param_str, src0z_param.param_str, src1w_param.param_str, dst_mask);
 }
 
@@ -2250,20 +2293,20 @@ static void shader_glsl_sincos(const struct wined3d_shader_instruction *ins)
     glsl_src_param_t src0_param;
     DWORD write_mask;
 
-    write_mask = shader_glsl_append_dst(ins->buffer, ins);
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], WINED3DSP_WRITEMASK_0, &src0_param);
+    write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param);
 
     switch (write_mask) {
         case WINED3DSP_WRITEMASK_0:
-            shader_addline(ins->buffer, "cos(%s));\n", src0_param.param_str);
+            shader_addline(ins->ctx->buffer, "cos(%s));\n", src0_param.param_str);
             break;
 
         case WINED3DSP_WRITEMASK_1:
-            shader_addline(ins->buffer, "sin(%s));\n", src0_param.param_str);
+            shader_addline(ins->ctx->buffer, "sin(%s));\n", src0_param.param_str);
             break;
 
         case (WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1):
-            shader_addline(ins->buffer, "vec2(cos(%s), sin(%s)));\n", src0_param.param_str, src0_param.param_str);
+            shader_addline(ins->ctx->buffer, "vec2(cos(%s), sin(%s)));\n", src0_param.param_str, src0_param.param_str);
             break;
 
         default:
@@ -2281,22 +2324,22 @@ static void shader_glsl_sincos(const struct wined3d_shader_instruction *ins)
 static void shader_glsl_loop(const struct wined3d_shader_instruction *ins)
 {
     glsl_src_param_t src1_param;
-    IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->shader;
-    DWORD regtype = shader_get_regtype(ins->src[1]);
-    DWORD reg = ins->src[1] & WINED3DSP_REGNUM_MASK;
+    IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->ctx->shader;
     const DWORD *control_values = NULL;
     const local_constant *constant;
 
-    shader_glsl_add_src_param(ins, ins->src[1], ins->src_addr[1], WINED3DSP_WRITEMASK_ALL, &src1_param);
+    shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_ALL, &src1_param);
 
     /* Try to hardcode the loop control parameters if possible. Direct3D 9 class hardware doesn't support real
      * varying indexing, but Microsoft designed this feature for Shader model 2.x+. If the loop control is
      * known at compile time, the GLSL compiler can unroll the loop, and replace indirect addressing with direct
      * addressing.
      */
-    if(regtype == WINED3DSPR_CONSTINT) {
+    if (ins->src[1].reg.type == WINED3DSPR_CONSTINT)
+    {
         LIST_FOR_EACH_ENTRY(constant, &shader->baseShader.constantsI, local_constant, entry) {
-            if(constant->idx == reg) {
+            if (constant->idx == ins->src[1].reg.idx)
+            {
                 control_values = constant->value;
                 break;
             }
@@ -2305,23 +2348,24 @@ static void shader_glsl_loop(const struct wined3d_shader_instruction *ins)
 
     if(control_values) {
         if(control_values[2] > 0) {
-            shader_addline(ins->buffer, "for (aL%u = %d; aL%u < (%d * %d + %d); aL%u += %d) {\n",
+            shader_addline(ins->ctx->buffer, "for (aL%u = %d; aL%u < (%d * %d + %d); aL%u += %d) {\n",
                     shader->baseShader.cur_loop_depth, control_values[1],
                     shader->baseShader.cur_loop_depth, control_values[0], control_values[2], control_values[1],
                     shader->baseShader.cur_loop_depth, control_values[2]);
         } else if(control_values[2] == 0) {
-            shader_addline(ins->buffer, "for (aL%u = %d, tmpInt%u = 0; tmpInt%u < %d; tmpInt%u++) {\n",
+            shader_addline(ins->ctx->buffer, "for (aL%u = %d, tmpInt%u = 0; tmpInt%u < %d; tmpInt%u++) {\n",
                     shader->baseShader.cur_loop_depth, control_values[1], shader->baseShader.cur_loop_depth,
                     shader->baseShader.cur_loop_depth, control_values[0],
                     shader->baseShader.cur_loop_depth);
         } else {
-            shader_addline(ins->buffer, "for (aL%u = %d; aL%u > (%d * %d + %d); aL%u += %d) {\n",
+            shader_addline(ins->ctx->buffer, "for (aL%u = %d; aL%u > (%d * %d + %d); aL%u += %d) {\n",
                     shader->baseShader.cur_loop_depth, control_values[1],
                     shader->baseShader.cur_loop_depth, control_values[0], control_values[2], control_values[1],
                     shader->baseShader.cur_loop_depth, control_values[2]);
         }
     } else {
-        shader_addline(ins->buffer, "for (tmpInt%u = 0, aL%u = %s.y; tmpInt%u < %s.x; tmpInt%u++, aL%u += %s.z) {\n",
+        shader_addline(ins->ctx->buffer,
+                "for (tmpInt%u = 0, aL%u = %s.y; tmpInt%u < %s.x; tmpInt%u++, aL%u += %s.z) {\n",
                 shader->baseShader.cur_loop_depth, shader->baseShader.cur_loop_regno,
                 src1_param.reg_name, shader->baseShader.cur_loop_depth, src1_param.reg_name,
                 shader->baseShader.cur_loop_depth, shader->baseShader.cur_loop_regno, src1_param.reg_name);
@@ -2333,9 +2377,9 @@ static void shader_glsl_loop(const struct wined3d_shader_instruction *ins)
 
 static void shader_glsl_end(const struct wined3d_shader_instruction *ins)
 {
-    IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->shader;
+    IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->ctx->shader;
 
-    shader_addline(ins->buffer, "}\n");
+    shader_addline(ins->ctx->buffer, "}\n");
 
     if (ins->handler_idx == WINED3DSIH_ENDLOOP)
     {
@@ -2351,13 +2395,34 @@ static void shader_glsl_end(const struct wined3d_shader_instruction *ins)
 
 static void shader_glsl_rep(const struct wined3d_shader_instruction *ins)
 {
-    IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->shader;
+    IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->ctx->shader;
     glsl_src_param_t src0_param;
+    const DWORD *control_values = NULL;
+    const local_constant *constant;
+
+    /* Try to hardcode local values to help the GLSL compiler to unroll and optimize the loop */
+    if (ins->src[0].reg.type == WINED3DSPR_CONSTINT)
+    {
+        LIST_FOR_EACH_ENTRY(constant, &shader->baseShader.constantsI, local_constant, entry)
+        {
+            if (constant->idx == ins->src[0].reg.idx)
+            {
+                control_values = constant->value;
+                break;
+            }
+        }
+    }
 
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], WINED3DSP_WRITEMASK_0, &src0_param);
-    shader_addline(ins->buffer, "for (tmpInt%d = 0; tmpInt%d < %s; tmpInt%d++) {\n",
-            shader->baseShader.cur_loop_depth, shader->baseShader.cur_loop_depth,
-            src0_param.param_str, shader->baseShader.cur_loop_depth);
+    if(control_values) {
+        shader_addline(ins->ctx->buffer, "for (tmpInt%d = 0; tmpInt%d < %d; tmpInt%d++) {\n",
+                       shader->baseShader.cur_loop_depth, shader->baseShader.cur_loop_depth,
+                       control_values[0], shader->baseShader.cur_loop_depth);
+    } else {
+        shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param);
+        shader_addline(ins->ctx->buffer, "for (tmpInt%d = 0; tmpInt%d < %s; tmpInt%d++) {\n",
+                shader->baseShader.cur_loop_depth, shader->baseShader.cur_loop_depth,
+                src0_param.param_str, shader->baseShader.cur_loop_depth);
+    }
     shader->baseShader.cur_loop_depth++;
 }
 
@@ -2365,8 +2430,8 @@ static void shader_glsl_if(const struct wined3d_shader_instruction *ins)
 {
     glsl_src_param_t src0_param;
 
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], WINED3DSP_WRITEMASK_0, &src0_param);
-    shader_addline(ins->buffer, "if (%s) {\n", src0_param.param_str);
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param);
+    shader_addline(ins->ctx->buffer, "if (%s) {\n", src0_param.param_str);
 }
 
 static void shader_glsl_ifc(const struct wined3d_shader_instruction *ins)
@@ -2374,21 +2439,21 @@ static void shader_glsl_ifc(const struct wined3d_shader_instruction *ins)
     glsl_src_param_t src0_param;
     glsl_src_param_t src1_param;
 
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], WINED3DSP_WRITEMASK_0, &src0_param);
-    shader_glsl_add_src_param(ins, ins->src[1], ins->src_addr[1], WINED3DSP_WRITEMASK_0, &src1_param);
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0, &src1_param);
 
-    shader_addline(ins->buffer, "if (%s %s %s) {\n",
+    shader_addline(ins->ctx->buffer, "if (%s %s %s) {\n",
             src0_param.param_str, shader_get_comp_op(ins->flags), src1_param.param_str);
 }
 
 static void shader_glsl_else(const struct wined3d_shader_instruction *ins)
 {
-    shader_addline(ins->buffer, "} else {\n");
+    shader_addline(ins->ctx->buffer, "} else {\n");
 }
 
 static void shader_glsl_break(const struct wined3d_shader_instruction *ins)
 {
-    shader_addline(ins->buffer, "break;\n");
+    shader_addline(ins->ctx->buffer, "break;\n");
 }
 
 /* FIXME: According to MSDN the compare is done per component. */
@@ -2397,34 +2462,30 @@ static void shader_glsl_breakc(const struct wined3d_shader_instruction *ins)
     glsl_src_param_t src0_param;
     glsl_src_param_t src1_param;
 
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], WINED3DSP_WRITEMASK_0, &src0_param);
-    shader_glsl_add_src_param(ins, ins->src[1], ins->src_addr[1], WINED3DSP_WRITEMASK_0, &src1_param);
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0, &src1_param);
 
-    shader_addline(ins->buffer, "if (%s %s %s) break;\n",
+    shader_addline(ins->ctx->buffer, "if (%s %s %s) break;\n",
             src0_param.param_str, shader_get_comp_op(ins->flags), src1_param.param_str);
 }
 
 static void shader_glsl_label(const struct wined3d_shader_instruction *ins)
 {
-
-    DWORD snum = (ins->src[0]) & WINED3DSP_REGNUM_MASK;
-    shader_addline(ins->buffer, "}\n");
-    shader_addline(ins->buffer, "void subroutine%u () {\n",  snum);
+    shader_addline(ins->ctx->buffer, "}\n");
+    shader_addline(ins->ctx->buffer, "void subroutine%u () {\n",  ins->src[0].reg.idx);
 }
 
 static void shader_glsl_call(const struct wined3d_shader_instruction *ins)
 {
-    DWORD snum = (ins->src[0]) & WINED3DSP_REGNUM_MASK;
-    shader_addline(ins->buffer, "subroutine%u();\n", snum);
+    shader_addline(ins->ctx->buffer, "subroutine%u();\n", ins->src[0].reg.idx);
 }
 
 static void shader_glsl_callnz(const struct wined3d_shader_instruction *ins)
 {
     glsl_src_param_t src1_param;
 
-    DWORD snum = (ins->src[0]) & WINED3DSP_REGNUM_MASK;
-    shader_glsl_add_src_param(ins, ins->src[1], ins->src_addr[1], WINED3DSP_WRITEMASK_0, &src1_param);
-    shader_addline(ins->buffer, "if (%s) subroutine%u();\n", src1_param.param_str, snum);
+    shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0, &src1_param);
+    shader_addline(ins->ctx->buffer, "if (%s) subroutine%u();\n", src1_param.param_str, ins->src[0].reg.idx);
 }
 
 /*********************************************
@@ -2432,22 +2493,23 @@ static void shader_glsl_callnz(const struct wined3d_shader_instruction *ins)
  ********************************************/
 static void pshader_glsl_tex(const struct wined3d_shader_instruction *ins)
 {
-    IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->shader;
+    IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->ctx->shader;
     IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device;
-    DWORD shader_version = ins->reg_maps->shader_version;
+    DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major,
+            ins->ctx->reg_maps->shader_version.minor);
     glsl_sample_function_t sample_function;
     DWORD sample_flags = 0;
-    DWORD sampler_type;
+    WINED3DSAMPLER_TEXTURE_TYPE sampler_type;
     DWORD sampler_idx;
     DWORD mask = 0, swizzle;
 
     /* 1.0-1.4: Use destination register as sampler source.
      * 2.0+: Use provided sampler source. */
-    if (shader_version < WINED3DPS_VERSION(2,0)) sampler_idx = ins->dst[0].register_idx;
-    else sampler_idx = ins->src[1] & WINED3DSP_REGNUM_MASK;
-    sampler_type = ins->reg_maps->samplers[sampler_idx] & WINED3DSP_TEXTURETYPE_MASK;
+    if (shader_version < WINED3D_SHADER_VERSION(2,0)) sampler_idx = ins->dst[0].reg.idx;
+    else sampler_idx = ins->src[1].reg.idx;
+    sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx];
 
-    if (shader_version < WINED3DPS_VERSION(1,4))
+    if (shader_version < WINED3D_SHADER_VERSION(1,4))
     {
         DWORD flags = deviceImpl->stateBlock->textureState[sampler_idx][WINED3DTSS_TEXTURETRANSFORMFLAGS];
 
@@ -2463,9 +2525,9 @@ static void pshader_glsl_tex(const struct wined3d_shader_instruction *ins)
             }
         }
     }
-    else if (shader_version < WINED3DPS_VERSION(2,0))
+    else if (shader_version < WINED3D_SHADER_VERSION(2,0))
     {
-        DWORD src_mod = ins->src[0] & WINED3DSP_SRCMOD_MASK;
+        DWORD src_mod = ins->src[0].modifiers;
 
         if (src_mod == WINED3DSPSM_DZ) {
             sample_flags |= WINED3D_GLSL_SAMPLE_PROJECTED;
@@ -2491,89 +2553,122 @@ static void pshader_glsl_tex(const struct wined3d_shader_instruction *ins)
     shader_glsl_get_sample_function(sampler_type, sample_flags, &sample_function);
     mask |= sample_function.coord_mask;
 
-    if (shader_version < WINED3DPS_VERSION(2,0)) swizzle = WINED3DVS_NOSWIZZLE;
-    else swizzle = ins->src[1] & WINED3DSP_SWIZZLE_MASK;
+    if (shader_version < WINED3D_SHADER_VERSION(2,0)) swizzle = WINED3DSP_NOSWIZZLE;
+    else swizzle = ins->src[1].swizzle;
 
     /* 1.0-1.3: Use destination register as coordinate source.
        1.4+: Use provided coordinate source register. */
-    if (shader_version < WINED3DPS_VERSION(1,4))
+    if (shader_version < WINED3D_SHADER_VERSION(1,4))
     {
         char coord_mask[6];
         shader_glsl_write_mask_to_str(mask, coord_mask);
-        shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, swizzle, NULL,
+        shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, swizzle, NULL, NULL, NULL,
                 "T%u%s", sampler_idx, coord_mask);
     } else {
         glsl_src_param_t coord_param;
-        shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], mask, &coord_param);
+        shader_glsl_add_src_param(ins, &ins->src[0], mask, &coord_param);
         if (ins->flags & WINED3DSI_TEXLD_BIAS)
         {
             glsl_src_param_t bias;
-            shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], WINED3DSP_WRITEMASK_3, &bias);
-            shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, swizzle, bias.param_str,
+            shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &bias);
+            shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, swizzle, NULL, NULL, bias.param_str,
                     "%s", coord_param.param_str);
         } else {
-            shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, swizzle, NULL,
+            shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, swizzle, NULL, NULL, NULL,
                     "%s", coord_param.param_str);
         }
     }
 }
 
+static void shader_glsl_texldd(const struct wined3d_shader_instruction *ins)
+{
+    IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)ins->ctx->shader;
+    IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device;
+    const WineD3D_GL_Info* gl_info = &deviceImpl->adapter->gl_info;
+    glsl_sample_function_t sample_function;
+    glsl_src_param_t coord_param, dx_param, dy_param;
+    DWORD sample_flags = WINED3D_GLSL_SAMPLE_GRAD;
+    DWORD sampler_type;
+    DWORD sampler_idx;
+    DWORD swizzle = ins->src[1].swizzle;
+
+    if(!GL_SUPPORT(ARB_SHADER_TEXTURE_LOD)) {
+        FIXME("texldd used, but not supported by hardware. Falling back to regular tex\n");
+        return pshader_glsl_tex(ins);
+    }
+
+    sampler_idx = ins->src[1].reg.idx;
+    sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx];
+    if(deviceImpl->stateBlock->textures[sampler_idx] &&
+       IWineD3DBaseTexture_GetTextureDimensions(deviceImpl->stateBlock->textures[sampler_idx]) == GL_TEXTURE_RECTANGLE_ARB) {
+        sample_flags |= WINED3D_GLSL_SAMPLE_RECT;
+    }
+
+    shader_glsl_get_sample_function(sampler_type, sample_flags, &sample_function);
+    shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &coord_param);
+    shader_glsl_add_src_param(ins, &ins->src[2], sample_function.coord_mask, &dx_param);
+    shader_glsl_add_src_param(ins, &ins->src[3], sample_function.coord_mask, &dy_param);
+
+    shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, swizzle, dx_param.param_str, dy_param.param_str, NULL,
+                                "%s", coord_param.param_str);
+}
+
 static void shader_glsl_texldl(const struct wined3d_shader_instruction *ins)
 {
-    IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)ins->shader;
+    IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)ins->ctx->shader;
     IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device;
     glsl_sample_function_t sample_function;
     glsl_src_param_t coord_param, lod_param;
     DWORD sample_flags = WINED3D_GLSL_SAMPLE_LOD;
     DWORD sampler_type;
     DWORD sampler_idx;
-    DWORD swizzle = ins->src[1] & WINED3DSP_SWIZZLE_MASK;
+    DWORD swizzle = ins->src[1].swizzle;
 
-    sampler_idx = ins->src[1] & WINED3DSP_REGNUM_MASK;
-    sampler_type = ins->reg_maps->samplers[sampler_idx] & WINED3DSP_TEXTURETYPE_MASK;
+    sampler_idx = ins->src[1].reg.idx;
+    sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx];
     if(deviceImpl->stateBlock->textures[sampler_idx] &&
        IWineD3DBaseTexture_GetTextureDimensions(deviceImpl->stateBlock->textures[sampler_idx]) == GL_TEXTURE_RECTANGLE_ARB) {
         sample_flags |= WINED3D_GLSL_SAMPLE_RECT;
     }
     shader_glsl_get_sample_function(sampler_type, sample_flags, &sample_function);
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], sample_function.coord_mask, &coord_param);
+    shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &coord_param);
 
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], WINED3DSP_WRITEMASK_3, &lod_param);
+    shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &lod_param);
 
-    if (shader_is_pshader_version(ins->reg_maps->shader_version))
+    if (shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type))
     {
         /* The GLSL spec claims the Lod sampling functions are only supported in vertex shaders.
          * However, they seem to work just fine in fragment shaders as well. */
         WARN("Using %s in fragment shader.\n", sample_function.name);
     }
-    shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, swizzle, lod_param.param_str,
+    shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, swizzle, NULL, NULL, lod_param.param_str,
             "%s", coord_param.param_str);
 }
 
 static void pshader_glsl_texcoord(const struct wined3d_shader_instruction *ins)
 {
     /* FIXME: Make this work for more than just 2D textures */
-    SHADER_BUFFER *buffer = ins->buffer;
-    DWORD write_mask = shader_glsl_append_dst(ins->buffer, ins);
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
+    DWORD write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
 
-    if (ins->reg_maps->shader_version != WINED3DPS_VERSION(1,4))
+    if (!(ins->ctx->reg_maps->shader_version.major == 1 && ins->ctx->reg_maps->shader_version.minor == 4))
     {
         char dst_mask[6];
 
         shader_glsl_get_write_mask(&ins->dst[0], dst_mask);
         shader_addline(buffer, "clamp(gl_TexCoord[%u], 0.0, 1.0)%s);\n",
-                ins->dst[0].register_idx, dst_mask);
+                ins->dst[0].reg.idx, dst_mask);
     } else {
-        DWORD reg = ins->src[0] & WINED3DSP_REGNUM_MASK;
-        DWORD src_mod = ins->src[0] & WINED3DSP_SRCMOD_MASK;
+        DWORD reg = ins->src[0].reg.idx;
+        DWORD src_mod = ins->src[0].modifiers;
         char dst_swizzle[6];
 
-        shader_glsl_get_swizzle(ins->src[0], FALSE, write_mask, dst_swizzle);
+        shader_glsl_get_swizzle(&ins->src[0], FALSE, write_mask, dst_swizzle);
 
         if (src_mod == WINED3DSPSM_DZ) {
             glsl_src_param_t div_param;
             unsigned int mask_size = shader_glsl_get_write_mask_size(write_mask);
-            shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], WINED3DSP_WRITEMASK_2, &div_param);
+            shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_2, &div_param);
 
             if (mask_size > 1) {
                 shader_addline(buffer, "gl_TexCoord[%u]%s / vec%d(%s));\n", reg, dst_swizzle, mask_size, div_param.param_str);
@@ -2583,7 +2678,7 @@ static void pshader_glsl_texcoord(const struct wined3d_shader_instruction *ins)
         } else if (src_mod == WINED3DSPSM_DW) {
             glsl_src_param_t div_param;
             unsigned int mask_size = shader_glsl_get_write_mask_size(write_mask);
-            shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], WINED3DSP_WRITEMASK_3, &div_param);
+            shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &div_param);
 
             if (mask_size > 1) {
                 shader_addline(buffer, "gl_TexCoord[%u]%s / vec%d(%s));\n", reg, dst_swizzle, mask_size, div_param.param_str);
@@ -2603,12 +2698,12 @@ static void pshader_glsl_texdp3tex(const struct wined3d_shader_instruction *ins)
 {
     glsl_src_param_t src0_param;
     glsl_sample_function_t sample_function;
-    DWORD sampler_idx = ins->dst[0].register_idx;
+    DWORD sampler_idx = ins->dst[0].reg.idx;
     DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
-    DWORD sampler_type = ins->reg_maps->samplers[sampler_idx] & WINED3DSP_TEXTURETYPE_MASK;
+    WINED3DSAMPLER_TEXTURE_TYPE sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx];
     UINT mask_size;
 
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], src_mask, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
 
     /* Do I have to take care about the projected bit? I don't think so, since the dp3 returns only one
      * scalar, and projected sampling would require 4.
@@ -2621,17 +2716,17 @@ static void pshader_glsl_texdp3tex(const struct wined3d_shader_instruction *ins)
     switch(mask_size)
     {
         case 1:
-            shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DVS_NOSWIZZLE, NULL,
+            shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL,
                     "dot(gl_TexCoord[%u].xyz, %s)", sampler_idx, src0_param.param_str);
             break;
 
         case 2:
-            shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DVS_NOSWIZZLE, NULL,
+            shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL,
                     "vec2(dot(gl_TexCoord[%u].xyz, %s), 0.0)", sampler_idx, src0_param.param_str);
             break;
 
         case 3:
-            shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DVS_NOSWIZZLE, NULL,
+            shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL,
                     "vec3(dot(gl_TexCoord[%u].xyz, %s), 0.0, 0.0)", sampler_idx, src0_param.param_str);
             break;
 
@@ -2646,19 +2741,19 @@ static void pshader_glsl_texdp3tex(const struct wined3d_shader_instruction *ins)
 static void pshader_glsl_texdp3(const struct wined3d_shader_instruction *ins)
 {
     glsl_src_param_t src0_param;
-    DWORD dstreg = ins->dst[0].register_idx;
+    DWORD dstreg = ins->dst[0].reg.idx;
     DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
     DWORD dst_mask;
     unsigned int mask_size;
 
-    dst_mask = shader_glsl_append_dst(ins->buffer, ins);
+    dst_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
     mask_size = shader_glsl_get_write_mask_size(dst_mask);
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], src_mask, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
 
     if (mask_size > 1) {
-        shader_addline(ins->buffer, "vec%d(dot(T%u.xyz, %s)));\n", mask_size, dstreg, src0_param.param_str);
+        shader_addline(ins->ctx->buffer, "vec%d(dot(T%u.xyz, %s)));\n", mask_size, dstreg, src0_param.param_str);
     } else {
-        shader_addline(ins->buffer, "dot(T%u.xyz, %s));\n", dstreg, src0_param.param_str);
+        shader_addline(ins->ctx->buffer, "dot(T%u.xyz, %s));\n", dstreg, src0_param.param_str);
     }
 }
 
@@ -2676,7 +2771,7 @@ static void pshader_glsl_texdepth(const struct wined3d_shader_instruction *ins)
      * too is irrelevant, since if x = 0, any y value < 1.0 (and > 1.0 is not allowed) results in a result
      * >= 1.0 or < 0.0
      */
-    shader_addline(ins->buffer, "gl_FragDepth = clamp((%s.x / min(%s.y, 1.0)), 0.0, 1.0);\n",
+    shader_addline(ins->ctx->buffer, "gl_FragDepth = clamp((%s.x / min(%s.y, 1.0)), 0.0, 1.0);\n",
             dst_param.reg_name, dst_param.reg_name);
 }
 
@@ -2688,13 +2783,13 @@ static void pshader_glsl_texdepth(const struct wined3d_shader_instruction *ins)
 static void pshader_glsl_texm3x2depth(const struct wined3d_shader_instruction *ins)
 {
     DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
-    DWORD dstreg = ins->dst[0].register_idx;
+    DWORD dstreg = ins->dst[0].reg.idx;
     glsl_src_param_t src0_param;
 
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], src_mask, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
 
-    shader_addline(ins->buffer, "tmp0.y = dot(T%u.xyz, %s);\n", dstreg, src0_param.param_str);
-    shader_addline(ins->buffer, "gl_FragDepth = (tmp0.y == 0.0) ? 1.0 : clamp(tmp0.x / tmp0.y, 0.0, 1.0);\n");
+    shader_addline(ins->ctx->buffer, "tmp0.y = dot(T%u.xyz, %s);\n", dstreg, src0_param.param_str);
+    shader_addline(ins->ctx->buffer, "gl_FragDepth = (tmp0.y == 0.0) ? 1.0 : clamp(tmp0.x / tmp0.y, 0.0, 1.0);\n");
 }
 
 /** Process the WINED3DSIO_TEXM3X2PAD instruction in GLSL
@@ -2702,11 +2797,11 @@ static void pshader_glsl_texm3x2depth(const struct wined3d_shader_instruction *i
 static void pshader_glsl_texm3x2pad(const struct wined3d_shader_instruction *ins)
 {
     DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
-    DWORD reg = ins->dst[0].register_idx;
-    SHADER_BUFFER *buffer = ins->buffer;
+    DWORD reg = ins->dst[0].reg.idx;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
     glsl_src_param_t src0_param;
 
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], src_mask, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
     shader_addline(buffer, "tmp0.x = dot(T%u.xyz, %s);\n", reg, src0_param.param_str);
 }
 
@@ -2714,14 +2809,14 @@ static void pshader_glsl_texm3x2pad(const struct wined3d_shader_instruction *ins
  * Calculate the 1st or 2nd row of a 3-row matrix multiplication. */
 static void pshader_glsl_texm3x3pad(const struct wined3d_shader_instruction *ins)
 {
-    IWineD3DPixelShaderImpl *shader = (IWineD3DPixelShaderImpl *)ins->shader;
+    IWineD3DPixelShaderImpl *shader = (IWineD3DPixelShaderImpl *)ins->ctx->shader;
     DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
-    DWORD reg = ins->dst[0].register_idx;
-    SHADER_BUFFER *buffer = ins->buffer;
+    DWORD reg = ins->dst[0].reg.idx;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
     SHADER_PARSE_STATE* current_state = &shader->baseShader.parse_state;
     glsl_src_param_t src0_param;
 
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], src_mask, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
     shader_addline(buffer, "tmp0.%c = dot(T%u.xyz, %s);\n", 'x' + current_state->current_row, reg, src0_param.param_str);
     current_state->texcoord_w[current_state->current_row++] = reg;
 }
@@ -2729,19 +2824,19 @@ static void pshader_glsl_texm3x3pad(const struct wined3d_shader_instruction *ins
 static void pshader_glsl_texm3x2tex(const struct wined3d_shader_instruction *ins)
 {
     DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
-    DWORD reg = ins->dst[0].register_idx;
-    SHADER_BUFFER *buffer = ins->buffer;
+    DWORD reg = ins->dst[0].reg.idx;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
     glsl_src_param_t src0_param;
-    DWORD sampler_type = ins->reg_maps->samplers[reg] & WINED3DSP_TEXTURETYPE_MASK;
+    WINED3DSAMPLER_TEXTURE_TYPE sampler_type = ins->ctx->reg_maps->sampler_type[reg];
     glsl_sample_function_t sample_function;
 
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], src_mask, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
     shader_addline(buffer, "tmp0.y = dot(T%u.xyz, %s);\n", reg, src0_param.param_str);
 
     shader_glsl_get_sample_function(sampler_type, 0, &sample_function);
 
     /* Sample the texture using the calculated coordinates */
-    shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DVS_NOSWIZZLE, NULL, "tmp0.xy");
+    shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, "tmp0.xy");
 }
 
 /** Process the WINED3DSIO_TEXM3X3TEX instruction in GLSL
@@ -2750,20 +2845,20 @@ static void pshader_glsl_texm3x3tex(const struct wined3d_shader_instruction *ins
 {
     DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
     glsl_src_param_t src0_param;
-    DWORD reg = ins->dst[0].register_idx;
-    IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->shader;
+    DWORD reg = ins->dst[0].reg.idx;
+    IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->ctx->shader;
     SHADER_PARSE_STATE* current_state = &This->baseShader.parse_state;
-    DWORD sampler_type = ins->reg_maps->samplers[reg] & WINED3DSP_TEXTURETYPE_MASK;
+    WINED3DSAMPLER_TEXTURE_TYPE sampler_type = ins->ctx->reg_maps->sampler_type[reg];
     glsl_sample_function_t sample_function;
 
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], src_mask, &src0_param);
-    shader_addline(ins->buffer, "tmp0.z = dot(T%u.xyz, %s);\n", reg, src0_param.param_str);
+    shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
+    shader_addline(ins->ctx->buffer, "tmp0.z = dot(T%u.xyz, %s);\n", reg, src0_param.param_str);
 
     /* Dependent read, not valid with conditional NP2 */
     shader_glsl_get_sample_function(sampler_type, 0, &sample_function);
 
     /* Sample the texture using the calculated coordinates */
-    shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DVS_NOSWIZZLE, NULL, "tmp0.xyz");
+    shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, "tmp0.xyz");
 
     current_state->current_row = 0;
 }
@@ -2775,15 +2870,15 @@ static void pshader_glsl_texm3x3(const struct wined3d_shader_instruction *ins)
     DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
     glsl_src_param_t src0_param;
     char dst_mask[6];
-    DWORD reg = ins->dst[0].register_idx;
-    IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->shader;
+    DWORD reg = ins->dst[0].reg.idx;
+    IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->ctx->shader;
     SHADER_PARSE_STATE* current_state = &This->baseShader.parse_state;
 
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], src_mask, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
 
-    shader_glsl_append_dst(ins->buffer, ins);
+    shader_glsl_append_dst(ins->ctx->buffer, ins);
     shader_glsl_get_write_mask(&ins->dst[0], dst_mask);
-    shader_addline(ins->buffer, "vec4(tmp0.xy, dot(T%u.xyz, %s), 1.0)%s);\n", reg, src0_param.param_str, dst_mask);
+    shader_addline(ins->ctx->buffer, "vec4(tmp0.xy, dot(T%u.xyz, %s), 1.0)%s);\n", reg, src0_param.param_str, dst_mask);
 
     current_state->current_row = 0;
 }
@@ -2792,18 +2887,18 @@ static void pshader_glsl_texm3x3(const struct wined3d_shader_instruction *ins)
  * Perform the final texture lookup based on the previous 2 3x3 matrix multiplies */
 static void pshader_glsl_texm3x3spec(const struct wined3d_shader_instruction *ins)
 {
-    IWineD3DPixelShaderImpl *shader = (IWineD3DPixelShaderImpl *)ins->shader;
-    DWORD reg = ins->dst[0].register_idx;
+    IWineD3DPixelShaderImpl *shader = (IWineD3DPixelShaderImpl *)ins->ctx->shader;
+    DWORD reg = ins->dst[0].reg.idx;
     glsl_src_param_t src0_param;
     glsl_src_param_t src1_param;
-    SHADER_BUFFER *buffer = ins->buffer;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
     SHADER_PARSE_STATE* current_state = &shader->baseShader.parse_state;
-    DWORD stype = ins->reg_maps->samplers[reg] & WINED3DSP_TEXTURETYPE_MASK;
+    WINED3DSAMPLER_TEXTURE_TYPE stype = ins->ctx->reg_maps->sampler_type[reg];
     DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
     glsl_sample_function_t sample_function;
 
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], src_mask, &src0_param);
-    shader_glsl_add_src_param(ins, ins->src[1], ins->src_addr[1], src_mask, &src1_param);
+    shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[1], src_mask, &src1_param);
 
     /* Perform the last matrix multiply operation */
     shader_addline(buffer, "tmp0.z = dot(T%u.xyz, %s);\n", reg, src0_param.param_str);
@@ -2814,7 +2909,7 @@ static void pshader_glsl_texm3x3spec(const struct wined3d_shader_instruction *in
     shader_glsl_get_sample_function(stype, 0, &sample_function);
 
     /* Sample the texture */
-    shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DVS_NOSWIZZLE, NULL, "tmp0.xyz");
+    shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, "tmp0.xyz");
 
     current_state->current_row = 0;
 }
@@ -2823,16 +2918,16 @@ static void pshader_glsl_texm3x3spec(const struct wined3d_shader_instruction *in
  * Perform the final texture lookup based on the previous 2 3x3 matrix multiplies */
 static void pshader_glsl_texm3x3vspec(const struct wined3d_shader_instruction *ins)
 {
-    IWineD3DPixelShaderImpl *shader = (IWineD3DPixelShaderImpl *)ins->shader;
-    DWORD reg = ins->dst[0].register_idx;
-    SHADER_BUFFER *buffer = ins->buffer;
+    IWineD3DPixelShaderImpl *shader = (IWineD3DPixelShaderImpl *)ins->ctx->shader;
+    DWORD reg = ins->dst[0].reg.idx;
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
     SHADER_PARSE_STATE* current_state = &shader->baseShader.parse_state;
     glsl_src_param_t src0_param;
     DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
-    DWORD sampler_type = ins->reg_maps->samplers[reg] & WINED3DSP_TEXTURETYPE_MASK;
+    WINED3DSAMPLER_TEXTURE_TYPE sampler_type = ins->ctx->reg_maps->sampler_type[reg];
     glsl_sample_function_t sample_function;
 
-    shader_glsl_add_src_param(ins, ins->src[0], ins->src_addr[0], src_mask, &src0_param);
+    shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
 
     /* Perform the last matrix multiply operation */
     shader_addline(buffer, "tmp0.z = dot(vec3(T%u), vec3(%s));\n", reg, src0_param.param_str);
@@ -2846,7 +2941,7 @@ static void pshader_glsl_texm3x3vspec(const struct wined3d_shader_instruction *i
     shader_glsl_get_sample_function(sampler_type, 0, &sample_function);
 
     /* Sample the texture using the calculated coordinates */
-    shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DVS_NOSWIZZLE, NULL, "tmp0.xyz");
+    shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, "tmp0.xyz");
 
     current_state->current_row = 0;
 }
@@ -2857,20 +2952,20 @@ static void pshader_glsl_texm3x3vspec(const struct wined3d_shader_instruction *i
  */
 static void pshader_glsl_texbem(const struct wined3d_shader_instruction *ins)
 {
-    IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->shader;
+    IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)ins->ctx->shader;
     IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device;
     glsl_sample_function_t sample_function;
     glsl_src_param_t coord_param;
-    DWORD sampler_type;
+    WIN