[DXGI][D3D8][D3D9][DDRAW][WINED3D]
authorAmine Khaldi <amine.khaldi@reactos.org>
Fri, 13 Sep 2013 23:50:10 +0000 (23:50 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Fri, 13 Sep 2013 23:50:10 +0000 (23:50 +0000)
* Sync with Wine 1.7.1.

svn path=/trunk/; revision=60090

51 files changed:
reactos/dll/directx/dxgi/device.c
reactos/dll/directx/dxgi/dxgi_main.c
reactos/dll/directx/wine/d3d8/CMakeLists.txt
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/d3d8/surface.c
reactos/dll/directx/wine/d3d8/texture.c
reactos/dll/directx/wine/d3d8/volume.c
reactos/dll/directx/wine/d3d9/CMakeLists.txt
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/surface.c
reactos/dll/directx/wine/d3d9/texture.c
reactos/dll/directx/wine/d3d9/volume.c
reactos/dll/directx/wine/ddraw/CMakeLists.txt
reactos/dll/directx/wine/ddraw/ddraw.c
reactos/dll/directx/wine/ddraw/ddraw_private.h
reactos/dll/directx/wine/ddraw/device.c
reactos/dll/directx/wine/ddraw/executebuffer.c
reactos/dll/directx/wine/ddraw/main.c
reactos/dll/directx/wine/ddraw/surface.c
reactos/dll/directx/wine/ddraw/utils.c
reactos/dll/directx/wine/ddraw/viewport.c
reactos/dll/directx/wine/wined3d/CMakeLists.txt
reactos/dll/directx/wine/wined3d/arb_program_shader.c
reactos/dll/directx/wine/wined3d/ati_fragment_shader.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/gl_compat.c
reactos/dll/directx/wine/wined3d/glsl_shader.c
reactos/dll/directx/wine/wined3d/resource.c
reactos/dll/directx/wine/wined3d/shader.c
reactos/dll/directx/wine/wined3d/state.c
reactos/dll/directx/wine/wined3d/stateblock.c
reactos/dll/directx/wine/wined3d/surface.c
reactos/dll/directx/wine/wined3d/swapchain.c
reactos/dll/directx/wine/wined3d/texture.c
reactos/dll/directx/wine/wined3d/utils.c
reactos/dll/directx/wine/wined3d/vertexdeclaration.c
reactos/dll/directx/wine/wined3d/volume.c
reactos/dll/directx/wine/wined3d/wined3d.spec
reactos/dll/directx/wine/wined3d/wined3d_gl.h
reactos/dll/directx/wine/wined3d/wined3d_main.c
reactos/dll/directx/wine/wined3d/wined3d_private.h
reactos/include/reactos/wine/wined3d.h
reactos/media/doc/README.WINE

index b8e6692..e98a2c0 100644 (file)
@@ -156,6 +156,7 @@ static HRESULT STDMETHODCALLTYPE dxgi_device_CreateSurface(IWineDXGIDevice *ifac
         const DXGI_SHARED_RESOURCE *shared_resource, IDXGISurface **surface)
 {
     struct wined3d_device_parent *device_parent;
+    struct wined3d_resource_desc surface_desc;
     IWineDXGIDeviceParent *dxgi_device_parent;
     HRESULT hr;
     UINT i;
@@ -174,6 +175,16 @@ static HRESULT STDMETHODCALLTYPE dxgi_device_CreateSurface(IWineDXGIDevice *ifac
     device_parent = IWineDXGIDeviceParent_get_wined3d_device_parent(dxgi_device_parent);
 
     FIXME("Implement DXGI<->wined3d usage conversion\n");
+    surface_desc.resource_type = WINED3D_RTYPE_SURFACE;
+    surface_desc.format = wined3dformat_from_dxgi_format(desc->Format);
+    surface_desc.multisample_type = desc->SampleDesc.Count > 1 ? desc->SampleDesc.Count : WINED3D_MULTISAMPLE_NONE;
+    surface_desc.multisample_quality = desc->SampleDesc.Quality;
+    surface_desc.usage = usage;
+    surface_desc.pool = WINED3D_POOL_DEFAULT;
+    surface_desc.width = desc->Width;
+    surface_desc.height = desc->Height;
+    surface_desc.depth = 1;
+    surface_desc.size = 0;
 
     memset(surface, 0, surface_count * sizeof(*surface));
     for (i = 0; i < surface_count; ++i)
@@ -181,13 +192,10 @@ static HRESULT STDMETHODCALLTYPE dxgi_device_CreateSurface(IWineDXGIDevice *ifac
         struct wined3d_surface *wined3d_surface;
         IUnknown *parent;
 
-        hr = device_parent->ops->create_swapchain_surface(device_parent, NULL,
-                desc->Width, desc->Height, wined3dformat_from_dxgi_format(desc->Format), usage,
-                desc->SampleDesc.Count > 1 ? desc->SampleDesc.Count : WINED3D_MULTISAMPLE_NONE,
-                desc->SampleDesc.Quality, &wined3d_surface);
-        if (FAILED(hr))
+        if (FAILED(hr = device_parent->ops->create_swapchain_surface(device_parent,
+                NULL, &surface_desc, &wined3d_surface)))
         {
-            ERR("CreateSurface failed, returning %#x\n", hr);
+            ERR("Failed to create surface, hr %#x.\n", hr);
             goto fail;
         }
 
index c9d6f2e..e9ed482 100644 (file)
@@ -44,16 +44,8 @@ static struct dxgi_main dxgi_main;
 
 static void dxgi_main_cleanup(void)
 {
-    EnterCriticalSection(&dxgi_cs);
-
     HeapFree(GetProcessHeap(), 0, dxgi_main.device_layers);
-    dxgi_main.device_layers = NULL;
-    dxgi_main.layer_count = 0;
-
     FreeLibrary(dxgi_main.d3d10core);
-    dxgi_main.d3d10core = NULL;
-
-    LeaveCriticalSection(&dxgi_cs);
     DeleteCriticalSection(&dxgi_cs);
 }
 
@@ -68,6 +60,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
             break;
 
         case DLL_PROCESS_DETACH:
+            if (lpv) break;
             dxgi_main_cleanup();
             break;
     }
index a54b23a..2dc5cf9 100644 (file)
@@ -23,17 +23,7 @@ list(APPEND SOURCE
 
 add_library(d3d8 SHARED ${SOURCE})
 set_module_type(d3d8 win32dll UNICODE)
-target_link_libraries(d3d8 uuid wine)
-
-add_importlibs(d3d8
-    user32
-    gdi32
-    advapi32
-    wined3d
-    msvcrt
-    kernel32
-    ntdll)
-
-add_dependencies(d3d8 wineheaders)
+target_link_libraries(d3d8 wine)
+add_importlibs(d3d8 wined3d msvcrt kernel32 ntdll)
 add_pch(d3d8 d3d8_private.h)
 add_cd_file(TARGET d3d8 DESTINATION reactos/system32 FOR all)
index 94482cc..4820b2b 100644 (file)
@@ -188,7 +188,8 @@ struct d3d8_volume
 };
 
 HRESULT volume_init(struct d3d8_volume *volume, struct d3d8_device *device, UINT width, UINT height,
-        UINT depth, DWORD usage, enum wined3d_format_id format, enum wined3d_pool pool) DECLSPEC_HIDDEN;
+        UINT depth, UINT level, DWORD usage, enum wined3d_format_id format,
+        enum wined3d_pool pool) DECLSPEC_HIDDEN;
 
 struct d3d8_swapchain
 {
@@ -216,8 +217,8 @@ struct d3d8_surface
 };
 
 HRESULT surface_init(struct d3d8_surface *surface, struct d3d8_device *device, UINT width, UINT height,
-        D3DFORMAT format, BOOL lockable, BOOL discard, DWORD usage, D3DPOOL pool,
-        D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality) DECLSPEC_HIDDEN;
+        D3DFORMAT format, DWORD flags, DWORD usage, D3DPOOL pool, D3DMULTISAMPLE_TYPE multisample_type,
+        DWORD multisample_quality) DECLSPEC_HIDDEN;
 struct d3d8_surface *unsafe_impl_from_IDirect3DSurface8(IDirect3DSurface8 *iface) DECLSPEC_HIDDEN;
 
 struct d3d8_vertexbuffer
index 2996b5a..dbf1f76 100644 (file)
 
 WINE_DEFAULT_DEBUG_CHANNEL(d3d8);
 
+static void STDMETHODCALLTYPE d3d8_null_wined3d_object_destroyed(void *parent) {}
+
+static const struct wined3d_parent_ops d3d8_null_wined3d_parent_ops =
+{
+    d3d8_null_wined3d_object_destroyed,
+};
+
 D3DFORMAT d3dformat_from_wined3dformat(enum wined3d_format_id format)
 {
     BYTE *c = (BYTE *)&format;
@@ -571,6 +578,21 @@ static HRESULT CDECL reset_enum_callback(struct wined3d_resource *resource)
     {
         struct d3d8_surface *surface;
 
+        if (desc.resource_type == WINED3D_RTYPE_TEXTURE)
+        {
+            IUnknown *parent = wined3d_resource_get_parent(resource);
+            IDirect3DBaseTexture8 *texture;
+
+            if (SUCCEEDED(IUnknown_QueryInterface(parent, &IID_IDirect3DBaseTexture8, (void **)&texture)))
+            {
+                IDirect3DBaseTexture8_Release(texture);
+                WARN("Texture %p (resource %p) in pool D3DPOOL_DEFAULT blocks the Reset call.\n", texture, resource);
+                return D3DERR_DEVICELOST;
+            }
+
+            return D3D_OK;
+        }
+
         if (desc.resource_type != WINED3D_RTYPE_SURFACE)
         {
             WARN("Resource %p in pool D3DPOOL_DEFAULT blocks the Reset call.\n", resource);
@@ -853,33 +875,50 @@ static HRESULT WINAPI d3d8_device_CreateIndexBuffer(IDirect3DDevice8 *iface, UIN
 }
 
 static HRESULT d3d8_device_create_surface(struct d3d8_device *device, UINT width, UINT height,
-        D3DFORMAT format, BOOL lockable, BOOL discard, IDirect3DSurface8 **surface, UINT usage,
-        D3DPOOL pool, D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality)
+        D3DFORMAT format, DWORD flags, IDirect3DSurface8 **surface, UINT usage, D3DPOOL pool,
+        D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality)
 {
-    struct d3d8_surface *object;
+    struct wined3d_resource *sub_resource;
+    struct wined3d_resource_desc desc;
+    struct d3d8_surface *surface_impl;
+    struct wined3d_texture *texture;
     HRESULT hr;
 
-    TRACE("device %p, width %u, height %u, format %#x, lockable %#x, discard %#x, surface %p,\n"
+    TRACE("device %p, width %u, height %u, format %#x, flags %#x, surface %p,\n"
             "\tusage %#x, pool %#x, multisample_type %#x, multisample_quality %u.\n",
-            device, width, height, format, lockable, discard, surface,
+            device, width, height, format, flags, surface,
             usage, pool, multisample_type, multisample_quality);
 
-    if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
-    {
-        FIXME("Failed to allocate surface memory.\n");
-        return D3DERR_OUTOFVIDEOMEMORY;
-    }
+    desc.resource_type = WINED3D_RTYPE_TEXTURE;
+    desc.format = wined3dformat_from_d3dformat(format);
+    desc.multisample_type = multisample_type;
+    desc.multisample_quality = multisample_quality;
+    desc.usage = usage & WINED3DUSAGE_MASK;
+    desc.pool = pool;
+    desc.width = width;
+    desc.height = height;
+    desc.depth = 1;
+    desc.size = 0;
+
+    wined3d_mutex_lock();
 
-    if (FAILED(hr = surface_init(object, device, width, height, format, lockable,
-            discard, usage, pool, multisample_type, multisample_quality)))
+    if (FAILED(hr = wined3d_texture_create_2d(device->wined3d_device, &desc,
+            1, flags, NULL, &d3d8_null_wined3d_parent_ops, &texture)))
     {
-        WARN("Failed to initialize surface, hr %#x.\n", hr);
-        HeapFree(GetProcessHeap(), 0, object);
+        wined3d_mutex_unlock();
+        WARN("Failed to create texture, hr %#x.\n", hr);
         return hr;
     }
 
-    TRACE("Created surface %p.\n", object);
-    *surface = &object->IDirect3DSurface8_iface;
+    sub_resource = wined3d_texture_get_sub_resource(texture, 0);
+    surface_impl = wined3d_resource_get_parent(sub_resource);
+    surface_impl->forwardReference = NULL;
+    surface_impl->parent_device = &device->IDirect3DDevice8_iface;
+    *surface = &surface_impl->IDirect3DSurface8_iface;
+    IDirect3DSurface8_AddRef(*surface);
+    wined3d_texture_decref(texture);
+
+    wined3d_mutex_unlock();
 
     return D3D_OK;
 }
@@ -889,12 +928,16 @@ static HRESULT WINAPI d3d8_device_CreateRenderTarget(IDirect3DDevice8 *iface, UI
         IDirect3DSurface8 **surface)
 {
     struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    DWORD flags = 0;
 
     TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, lockable %#x, surface %p.\n",
             iface, width, height, format, multisample_type, lockable, surface);
 
-    return d3d8_device_create_surface(device, width, height, format, lockable, FALSE,
-            surface, D3DUSAGE_RENDERTARGET, D3DPOOL_DEFAULT, multisample_type, 0);
+    if (lockable)
+        flags |= WINED3D_SURFACE_MAPPABLE;
+
+    return d3d8_device_create_surface(device, width, height, format, flags, surface,
+            D3DUSAGE_RENDERTARGET, D3DPOOL_DEFAULT, multisample_type, 0);
 }
 
 static HRESULT WINAPI d3d8_device_CreateDepthStencilSurface(IDirect3DDevice8 *iface,
@@ -907,7 +950,7 @@ static HRESULT WINAPI d3d8_device_CreateDepthStencilSurface(IDirect3DDevice8 *if
             iface, width, height, format, multisample_type, surface);
 
     /* TODO: Verify that Discard is false */
-    return d3d8_device_create_surface(device, width, height, format, TRUE, FALSE,
+    return d3d8_device_create_surface(device, width, height, format, WINED3D_SURFACE_MAPPABLE,
             surface, D3DUSAGE_DEPTHSTENCIL, D3DPOOL_DEFAULT, multisample_type, 0);
 }
 
@@ -920,7 +963,7 @@ static HRESULT WINAPI d3d8_device_CreateImageSurface(IDirect3DDevice8 *iface, UI
     TRACE("iface %p, width %u, height %u, format %#x, surface %p.\n",
             iface, width, height, format, surface);
 
-    return d3d8_device_create_surface(device, width, height, format, TRUE, FALSE,
+    return d3d8_device_create_surface(device, width, height, format, WINED3D_SURFACE_MAPPABLE,
             surface, 0, D3DPOOL_SYSTEMMEM, D3DMULTISAMPLE_NONE, 0);
 }
 
@@ -1891,13 +1934,6 @@ static HRESULT WINAPI d3d8_device_DrawIndexedPrimitive(IDirect3DDevice8 *iface,
     return hr;
 }
 
-static void STDMETHODCALLTYPE d3d8_null_wined3d_object_destroyed(void *parent) {}
-
-static const struct wined3d_parent_ops d3d8_null_wined3d_parent_ops =
-{
-    d3d8_null_wined3d_object_destroyed,
-};
-
 /* The caller is responsible for wined3d locking */
 static HRESULT d3d8_device_prepare_vertex_buffer(struct d3d8_device *device, UINT min_size)
 {
@@ -2878,29 +2914,33 @@ static void CDECL device_parent_mode_changed(struct wined3d_device_parent *devic
 }
 
 static HRESULT CDECL device_parent_create_texture_surface(struct wined3d_device_parent *device_parent,
-        void *container_parent, UINT width, UINT height, enum wined3d_format_id format, DWORD usage,
-        enum wined3d_pool pool, UINT sub_resource_idx, struct wined3d_surface **surface)
+        void *container_parent, const struct wined3d_resource_desc *desc, UINT sub_resource_idx,
+        DWORD flags, struct wined3d_surface **surface)
 {
     struct d3d8_device *device = device_from_device_parent(device_parent);
     struct d3d8_surface *d3d_surface;
-    BOOL lockable = TRUE;
     HRESULT hr;
 
-    TRACE("device_parent %p, container_parent %p, width %u, height %u, format %#x, usage %#x,\n"
-            "\tpool %#x, sub_resource_idx %u, surface %p.\n",
-            device_parent, container_parent, width, height, format, usage, pool, sub_resource_idx, surface);
-
+    TRACE("device_parent %p, container_parent %p, desc %p, sub_resource_idx %u, flags %#x, surface %p.\n",
+            device_parent, container_parent, desc, sub_resource_idx, flags, surface);
 
-    if (pool == WINED3D_POOL_DEFAULT && !(usage & WINED3DUSAGE_DYNAMIC))
-        lockable = FALSE;
+    if (!(d3d_surface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*d3d_surface))))
+    {
+        FIXME("Failed to allocate surface memory.\n");
+        return D3DERR_OUTOFVIDEOMEMORY;
+    }
 
-    if (FAILED(hr = d3d8_device_create_surface(device, width, height, d3dformat_from_wined3dformat(format),
-            lockable, FALSE, (IDirect3DSurface8 **)&d3d_surface, usage, pool, D3DMULTISAMPLE_NONE, 0)))
+    if (FAILED(hr = surface_init(d3d_surface, device, desc->width, desc->height,
+            d3dformat_from_wined3dformat(desc->format), flags, desc->usage, desc->pool,
+            desc->multisample_type, desc->multisample_quality)))
     {
-        WARN("Failed to create surface, hr %#x.\n", hr);
+        WARN("Failed to initialize surface, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, d3d_surface);
         return hr;
     }
 
+    TRACE("Created surface %p.\n", d3d_surface);
+
     *surface = d3d_surface->wined3d_surface;
     wined3d_surface_incref(*surface);
 
@@ -2915,39 +2955,40 @@ static HRESULT CDECL device_parent_create_texture_surface(struct wined3d_device_
 }
 
 static HRESULT CDECL device_parent_create_swapchain_surface(struct wined3d_device_parent *device_parent,
-        void *container_parent, UINT width, UINT height, enum wined3d_format_id format_id, DWORD usage,
-        enum wined3d_multisample_type multisample_type, DWORD multisample_quality, struct wined3d_surface **surface)
+        void *container_parent, const struct wined3d_resource_desc *desc, struct wined3d_surface **surface)
 {
     struct d3d8_device *device = device_from_device_parent(device_parent);
+    struct wined3d_resource_desc texture_desc;
     struct d3d8_surface *d3d_surface;
+    struct wined3d_texture *texture;
     HRESULT hr;
 
-    TRACE("device_parent %p, container_parent %p, width %u, height %u, format_id %#x, usage %#x,\n"
-            "\tmultisample_type %#x, multisample_quality %u, surface %p.\n",
-            device_parent, container_parent, width, height, format_id, usage,
-            multisample_type, multisample_quality, surface);
+    TRACE("device_parent %p, container_parent %p, desc %p, surface %p.\n",
+            device_parent, container_parent, desc, surface);
 
-    if (FAILED(hr = d3d8_device_create_surface(device, width, height, d3dformat_from_wined3dformat(format_id),
-            TRUE, FALSE, (IDirect3DSurface8 **)&d3d_surface, usage, D3DPOOL_DEFAULT, multisample_type,
-            multisample_quality)))
+    texture_desc = *desc;
+    texture_desc.resource_type = WINED3D_RTYPE_TEXTURE;
+    if (FAILED(hr = wined3d_texture_create_2d(device->wined3d_device, &texture_desc, 1,
+            WINED3D_SURFACE_MAPPABLE, &device->IDirect3DDevice8_iface, &d3d8_null_wined3d_parent_ops, &texture)))
     {
-        WARN("Failed to create surface, hr %#x.\n", hr);
+        WARN("Failed to create texture, hr %#x.\n", hr);
         return hr;
     }
 
-    *surface = d3d_surface->wined3d_surface;
+    *surface = wined3d_surface_from_resource(wined3d_texture_get_sub_resource(texture, 0));
     wined3d_surface_incref(*surface);
+    wined3d_texture_decref(texture);
 
-    d3d_surface->container = (IUnknown *)&device->IDirect3DDevice8_iface;
-    /* Implicit surfaces are created with an refcount of 0 */
-    IDirect3DSurface8_Release(&d3d_surface->IDirect3DSurface8_iface);
+    d3d_surface = wined3d_surface_get_parent(*surface);
+    d3d_surface->forwardReference = NULL;
+    d3d_surface->parent_device = &device->IDirect3DDevice8_iface;
 
     return hr;
 }
 
 static HRESULT CDECL device_parent_create_volume(struct wined3d_device_parent *device_parent,
-        void *container_parent, UINT width, UINT height, UINT depth, enum wined3d_format_id format,
-        enum wined3d_pool pool, DWORD usage, struct wined3d_volume **volume)
+        void *container_parent, UINT width, UINT height, UINT depth, UINT level,
+        enum wined3d_format_id format, enum wined3d_pool pool, DWORD usage, struct wined3d_volume **volume)
 {
     struct d3d8_device *device = device_from_device_parent(device_parent);
     struct d3d8_volume *object;
@@ -2967,7 +3008,7 @@ static HRESULT CDECL device_parent_create_volume(struct wined3d_device_parent *d
         return D3DERR_OUTOFVIDEOMEMORY;
     }
 
-    hr = volume_init(object, device, width, height, depth, usage, format, pool);
+    hr = volume_init(object, device, width, height, depth, level, usage, format, pool);
     if (FAILED(hr))
     {
         WARN("Failed to initialize volume, hr %#x.\n", hr);
index e5b3a80..dbe96e8 100644 (file)
@@ -404,11 +404,13 @@ static const struct IDirect3D8Vtbl d3d8_vtbl =
 
 BOOL d3d8_init(struct d3d8 *d3d8)
 {
+    DWORD flags = WINED3D_LEGACY_DEPTH_BIAS | WINED3D_VIDMEM_ACCOUNTING;
+
     d3d8->IDirect3D8_iface.lpVtbl = &d3d8_vtbl;
     d3d8->refcount = 1;
 
     wined3d_mutex_lock();
-    d3d8->wined3d = wined3d_create(8, WINED3D_LEGACY_DEPTH_BIAS);
+    d3d8->wined3d = wined3d_create(8, flags);
     wined3d_mutex_unlock();
     if (!d3d8->wined3d)
         return FALSE;
index ba56944..70eebf9 100644 (file)
@@ -326,10 +326,9 @@ static const struct wined3d_parent_ops d3d8_surface_wined3d_parent_ops =
 };
 
 HRESULT surface_init(struct d3d8_surface *surface, struct d3d8_device *device, UINT width, UINT height,
-        D3DFORMAT format, BOOL lockable, BOOL discard, DWORD usage, D3DPOOL pool,
-        D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality)
+        D3DFORMAT format, DWORD flags, DWORD usage, D3DPOOL pool, D3DMULTISAMPLE_TYPE multisample_type,
+        DWORD multisample_quality)
 {
-    DWORD flags = 0;
     HRESULT hr;
 
     surface->IDirect3DSurface8_iface.lpVtbl = &d3d8_surface_vtbl;
@@ -342,11 +341,6 @@ HRESULT surface_init(struct d3d8_surface *surface, struct d3d8_device *device, U
         multisample_quality = 0;
     }
 
-    if (lockable)
-        flags |= WINED3D_SURFACE_MAPPABLE;
-    if (discard)
-        flags |= WINED3D_SURFACE_DISCARD;
-
     wined3d_mutex_lock();
     hr = wined3d_surface_create(device->wined3d_device, width, height, wined3dformat_from_d3dformat(format),
             usage & WINED3DUSAGE_MASK, (enum wined3d_pool)pool, multisample_type, multisample_quality,
index c041ea7..f69c68b 100644 (file)
@@ -1155,9 +1155,20 @@ struct d3d8_texture *unsafe_impl_from_IDirect3DBaseTexture8(IDirect3DBaseTexture
 {
     if (!iface)
         return NULL;
-    assert(iface->lpVtbl == (const IDirect3DBaseTexture8Vtbl *)&Direct3DTexture8_Vtbl
-            || iface->lpVtbl == (const IDirect3DBaseTexture8Vtbl *)&Direct3DCubeTexture8_Vtbl
-            || iface->lpVtbl == (const IDirect3DBaseTexture8Vtbl *)&Direct3DVolumeTexture8_Vtbl);
+
+    /* SetTexture() in particular doesn't do a lot of validation on the pointer
+     * that gets passed in, and passing an invalid pointer works as long as the
+     * application doesn't try to actually render anything with it, so we print
+     * a WARN and return NULL instead of having the usual assert() here.
+     * One application affected by this is Fishdom 2. */
+    if (iface->lpVtbl != (const IDirect3DBaseTexture8Vtbl *)&Direct3DTexture8_Vtbl
+            && iface->lpVtbl != (const IDirect3DBaseTexture8Vtbl *)&Direct3DCubeTexture8_Vtbl
+            && iface->lpVtbl != (const IDirect3DBaseTexture8Vtbl *)&Direct3DVolumeTexture8_Vtbl)
+    {
+        WARN("%p is not a valid IDirect3DBaseTexture8 interface.\n", iface);
+        return NULL;
+    }
+
     return CONTAINING_RECORD(iface, struct d3d8_texture, IDirect3DBaseTexture8_iface);
 }
 
@@ -1174,14 +1185,29 @@ static const struct wined3d_parent_ops d3d8_texture_wined3d_parent_ops =
 HRESULT texture_init(struct d3d8_texture *texture, struct d3d8_device *device,
         UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool)
 {
+    struct wined3d_resource_desc desc;
+    DWORD surface_flags = 0;
     HRESULT hr;
 
     texture->IDirect3DBaseTexture8_iface.lpVtbl = (const IDirect3DBaseTexture8Vtbl *)&Direct3DTexture8_Vtbl;
     texture->refcount = 1;
 
+    desc.resource_type = WINED3D_RTYPE_TEXTURE;
+    desc.format = wined3dformat_from_d3dformat(format);
+    desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
+    desc.multisample_quality = 0;
+    desc.usage = usage & WINED3DUSAGE_MASK;
+    desc.pool = pool;
+    desc.width = width;
+    desc.height = height;
+    desc.depth = 1;
+    desc.size = 0;
+
+    if (pool != D3DPOOL_DEFAULT || (usage & D3DUSAGE_DYNAMIC))
+        surface_flags |= WINED3D_SURFACE_MAPPABLE;
+
     wined3d_mutex_lock();
-    hr = wined3d_texture_create_2d(device->wined3d_device, width, height, levels,
-            usage & WINED3DUSAGE_MASK, wined3dformat_from_d3dformat(format), pool,
+    hr = wined3d_texture_create_2d(device->wined3d_device, &desc, levels, surface_flags,
             texture, &d3d8_texture_wined3d_parent_ops, &texture->wined3d_texture);
     wined3d_mutex_unlock();
     if (FAILED(hr))
@@ -1199,15 +1225,30 @@ HRESULT texture_init(struct d3d8_texture *texture, struct d3d8_device *device,
 HRESULT cubetexture_init(struct d3d8_texture *texture, struct d3d8_device *device,
         UINT edge_length, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool)
 {
+    struct wined3d_resource_desc desc;
+    DWORD surface_flags = 0;
     HRESULT hr;
 
     texture->IDirect3DBaseTexture8_iface.lpVtbl = (const IDirect3DBaseTexture8Vtbl *)&Direct3DCubeTexture8_Vtbl;
     texture->refcount = 1;
 
+    desc.resource_type = WINED3D_RTYPE_CUBE_TEXTURE;
+    desc.format = wined3dformat_from_d3dformat(format);
+    desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
+    desc.multisample_quality = 0;
+    desc.usage = usage & WINED3DUSAGE_MASK;
+    desc.pool = pool;
+    desc.width = edge_length;
+    desc.height = edge_length;
+    desc.depth = 1;
+    desc.size = 0;
+
+    if (pool != D3DPOOL_DEFAULT || (usage & D3DUSAGE_DYNAMIC))
+        surface_flags |= WINED3D_SURFACE_MAPPABLE;
+
     wined3d_mutex_lock();
-    hr = wined3d_texture_create_cube(device->wined3d_device, edge_length, levels,
-            usage & WINED3DUSAGE_MASK, wined3dformat_from_d3dformat(format), pool, texture,
-            &d3d8_texture_wined3d_parent_ops, &texture->wined3d_texture);
+    hr = wined3d_texture_create_cube(device->wined3d_device, &desc, levels, surface_flags,
+            texture, &d3d8_texture_wined3d_parent_ops, &texture->wined3d_texture);
     wined3d_mutex_unlock();
     if (FAILED(hr))
     {
@@ -1224,15 +1265,26 @@ HRESULT cubetexture_init(struct d3d8_texture *texture, struct d3d8_device *devic
 HRESULT volumetexture_init(struct d3d8_texture *texture, struct d3d8_device *device,
         UINT width, UINT height, UINT depth, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool)
 {
+    struct wined3d_resource_desc desc;
     HRESULT hr;
 
     texture->IDirect3DBaseTexture8_iface.lpVtbl = (const IDirect3DBaseTexture8Vtbl *)&Direct3DVolumeTexture8_Vtbl;
     texture->refcount = 1;
 
+    desc.resource_type = WINED3D_RTYPE_VOLUME_TEXTURE;
+    desc.format = wined3dformat_from_d3dformat(format);
+    desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
+    desc.multisample_quality = 0;
+    desc.usage = usage & WINED3DUSAGE_MASK;
+    desc.pool = pool;
+    desc.width = width;
+    desc.height = height;
+    desc.depth = depth;
+    desc.size = 0;
+
     wined3d_mutex_lock();
-    hr = wined3d_texture_create_3d(device->wined3d_device, width, height, depth, levels,
-            usage & WINED3DUSAGE_MASK, wined3dformat_from_d3dformat(format), pool, texture,
-            &d3d8_texture_wined3d_parent_ops, &texture->wined3d_texture);
+    hr = wined3d_texture_create_3d(device->wined3d_device, &desc, levels,
+            texture, &d3d8_texture_wined3d_parent_ops, &texture->wined3d_texture);
     wined3d_mutex_unlock();
     if (FAILED(hr))
     {
index 4e8e88f..ee190ef 100644 (file)
@@ -284,14 +284,14 @@ static const struct wined3d_parent_ops d3d8_volume_wined3d_parent_ops =
 };
 
 HRESULT volume_init(struct d3d8_volume *volume, struct d3d8_device *device, UINT width, UINT height,
-        UINT depth, DWORD usage, enum wined3d_format_id format, enum wined3d_pool pool)
+        UINT depth, UINT level, DWORD usage, enum wined3d_format_id format, enum wined3d_pool pool)
 {
     HRESULT hr;
 
     volume->IDirect3DVolume8_iface.lpVtbl = &d3d8_volume_vtbl;
     volume->refcount = 1;
 
-    hr = wined3d_volume_create(device->wined3d_device, width, height, depth, usage,
+    hr = wined3d_volume_create(device->wined3d_device, width, height, depth, level, usage,
             format, pool, volume, &d3d8_volume_wined3d_parent_ops, &volume->wined3d_volume);
     if (FAILED(hr))
     {
index 52ee8b6..bdf9d7a 100644 (file)
@@ -26,17 +26,7 @@ list(APPEND SOURCE
 
 add_library(d3d9 SHARED ${SOURCE})
 set_module_type(d3d9 win32dll UNICODE)
-target_link_libraries(d3d9 uuid wine)
-
-add_importlibs(d3d9
-    user32
-    gdi32
-    advapi32
-    wined3d
-    msvcrt
-    kernel32
-    ntdll)
-
-add_dependencies(d3d9 wineheaders)
+target_link_libraries(d3d9 wine)
+add_importlibs(d3d9 wined3d msvcrt kernel32 ntdll)
 add_pch(d3d9 d3d9_private.h)
 add_cd_file(TARGET d3d9 DESTINATION reactos/system32 FOR all)
index 4e86556..3bd4f73 100644 (file)
@@ -180,7 +180,8 @@ struct d3d9_volume
 };
 
 HRESULT volume_init(struct d3d9_volume *volume, struct d3d9_device *device, UINT width, UINT height,
-        UINT depth, DWORD usage, enum wined3d_format_id format, enum wined3d_pool pool) DECLSPEC_HIDDEN;
+        UINT depth, UINT level, DWORD usage, enum wined3d_format_id format,
+        enum wined3d_pool pool) DECLSPEC_HIDDEN;
 
 struct d3d9_swapchain
 {
@@ -205,8 +206,8 @@ struct d3d9_surface
 };
 
 HRESULT surface_init(struct d3d9_surface *surface, struct d3d9_device *device, UINT width, UINT height,
-        D3DFORMAT format, BOOL lockable, BOOL discard, DWORD usage, D3DPOOL pool,
-        D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality) DECLSPEC_HIDDEN;
+        D3DFORMAT format, DWORD flags, DWORD usage, D3DPOOL pool, D3DMULTISAMPLE_TYPE multisample_type,
+        DWORD multisample_quality) DECLSPEC_HIDDEN;
 struct d3d9_surface *unsafe_impl_from_IDirect3DSurface9(IDirect3DSurface9 *iface) DECLSPEC_HIDDEN;
 
 struct d3d9_vertexbuffer
index 5a943df..7400a42 100644 (file)
 
 WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
 
+static void STDMETHODCALLTYPE d3d9_null_wined3d_object_destroyed(void *parent) {}
+
+static const struct wined3d_parent_ops d3d9_null_wined3d_parent_ops =
+{
+    d3d9_null_wined3d_object_destroyed,
+};
+
 D3DFORMAT d3dformat_from_wined3dformat(enum wined3d_format_id format)
 {
     BYTE *c = (BYTE *)&format;
@@ -557,6 +564,21 @@ static HRESULT CDECL reset_enum_callback(struct wined3d_resource *resource)
     {
         struct d3d9_surface *surface;
 
+        if (desc.resource_type == WINED3D_RTYPE_TEXTURE)
+        {
+            IUnknown *parent = wined3d_resource_get_parent(resource);
+            IDirect3DBaseTexture9 *texture;
+
+            if (SUCCEEDED(IUnknown_QueryInterface(parent, &IID_IDirect3DBaseTexture9, (void **)&texture)))
+            {
+                IDirect3DBaseTexture9_Release(texture);
+                WARN("Texture %p (resource %p) in pool D3DPOOL_DEFAULT blocks the Reset call.\n", texture, resource);
+                return D3DERR_INVALIDCALL;
+            }
+
+            return D3D_OK;
+        }
+
         if (desc.resource_type != WINED3D_RTYPE_SURFACE)
         {
             WARN("Resource %p in pool D3DPOOL_DEFAULT blocks the Reset call.\n", resource);
@@ -751,7 +773,7 @@ static HRESULT WINAPI d3d9_device_CreateTexture(IDirect3DDevice9Ex *iface,
 
         resource = wined3d_texture_get_sub_resource(object->wined3d_texture, 0);
         surface = wined3d_resource_get_parent(resource);
-        wined3d_surface_set_mem(surface->wined3d_surface, *shared_handle);
+        wined3d_surface_set_mem(surface->wined3d_surface, *shared_handle, 0);
     }
 
     TRACE("Created texture %p.\n", object);
@@ -891,33 +913,50 @@ static HRESULT WINAPI d3d9_device_CreateIndexBuffer(IDirect3DDevice9Ex *iface, U
 }
 
 static HRESULT d3d9_device_create_surface(struct d3d9_device *device, UINT width, UINT height,
-        D3DFORMAT format, BOOL lockable, BOOL discard, IDirect3DSurface9 **surface, UINT usage,
-        D3DPOOL pool, D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality)
+        D3DFORMAT format, DWORD flags, IDirect3DSurface9 **surface, UINT usage, D3DPOOL pool,
+        D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality)
 {
-    struct d3d9_surface *object;
+    struct wined3d_resource *sub_resource;
+    struct wined3d_resource_desc desc;
+    struct d3d9_surface *surface_impl;
+    struct wined3d_texture *texture;
     HRESULT hr;
 
-    TRACE("device %p, width %u, height %u, format %#x, lockable %#x, discard %#x, surface %p.\n"
+    TRACE("device %p, width %u, height %u, format %#x, flags %#x, surface %p.\n"
             "usage %#x, pool %#x, multisample_type %#x, multisample_quality %u.\n",
-            device, width, height, format, lockable, discard, surface, usage, pool,
+            device, width, height, format, flags, surface, usage, pool,
             multisample_type, multisample_quality);
 
-    if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
-    {
-        FIXME("Failed to allocate surface memory.\n");
-        return D3DERR_OUTOFVIDEOMEMORY;
-    }
+    desc.resource_type = WINED3D_RTYPE_TEXTURE;
+    desc.format = wined3dformat_from_d3dformat(format);
+    desc.multisample_type = multisample_type;
+    desc.multisample_quality = multisample_quality;
+    desc.usage = usage & WINED3DUSAGE_MASK;
+    desc.pool = pool;
+    desc.width = width;
+    desc.height = height;
+    desc.depth = 1;
+    desc.size = 0;
+
+    wined3d_mutex_lock();
 
-    if (FAILED(hr = surface_init(object, device, width, height, format, lockable,
-            discard, usage, pool, multisample_type, multisample_quality)))
+    if (FAILED(hr = wined3d_texture_create_2d(device->wined3d_device, &desc,
+            1, flags, NULL, &d3d9_null_wined3d_parent_ops, &texture)))
     {
-        WARN("Failed to initialize surface, hr %#x.\n", hr);
-        HeapFree(GetProcessHeap(), 0, object);
+        wined3d_mutex_unlock();
+        WARN("Failed to create texture, hr %#x.\n", hr);
         return hr;
     }
 
-    TRACE("Created surface %p.\n", object);
-    *surface = &object->IDirect3DSurface9_iface;
+    sub_resource = wined3d_texture_get_sub_resource(texture, 0);
+    surface_impl = wined3d_resource_get_parent(sub_resource);
+    surface_impl->forwardReference = NULL;
+    surface_impl->parent_device = &device->IDirect3DDevice9Ex_iface;
+    *surface = &surface_impl->IDirect3DSurface9_iface;
+    IDirect3DSurface9_AddRef(*surface);
+    wined3d_texture_decref(texture);
+
+    wined3d_mutex_unlock();
 
     return D3D_OK;
 }
@@ -927,6 +966,7 @@ static HRESULT WINAPI d3d9_device_CreateRenderTarget(IDirect3DDevice9Ex *iface,
         BOOL lockable, IDirect3DSurface9 **surface, HANDLE *shared_handle)
 {
     struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    DWORD flags = 0;
 
     TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, multisample_quality %u.\n"
             "lockable %#x, surface %p, shared_handle %p.\n",
@@ -936,7 +976,10 @@ static HRESULT WINAPI d3d9_device_CreateRenderTarget(IDirect3DDevice9Ex *iface,
     if (shared_handle)
         FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
 
-    return d3d9_device_create_surface(device, width, height, format, lockable, FALSE, surface,
+    if (lockable)
+        flags |= WINED3D_SURFACE_MAPPABLE;
+
+    return d3d9_device_create_surface(device, width, height, format, flags, surface,
             D3DUSAGE_RENDERTARGET, D3DPOOL_DEFAULT, multisample_type, multisample_quality);
 }
 
@@ -945,6 +988,7 @@ static HRESULT WINAPI d3d9_device_CreateDepthStencilSurface(IDirect3DDevice9Ex *
         BOOL discard, IDirect3DSurface9 **surface, HANDLE *shared_handle)
 {
     struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    DWORD flags = WINED3D_SURFACE_MAPPABLE;
 
     TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, multisample_quality %u.\n"
             "discard %#x, surface %p, shared_handle %p.\n",
@@ -954,7 +998,10 @@ static HRESULT WINAPI d3d9_device_CreateDepthStencilSurface(IDirect3DDevice9Ex *
     if (shared_handle)
         FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
 
-    return d3d9_device_create_surface(device, width, height, format, TRUE, discard, surface,
+    if (discard)
+        flags |= WINED3D_SURFACE_DISCARD;
+
+    return d3d9_device_create_surface(device, width, height, format, flags, surface,
             D3DUSAGE_DEPTHSTENCIL, D3DPOOL_DEFAULT, multisample_type, multisample_quality);
 }
 
@@ -1155,8 +1202,8 @@ static HRESULT WINAPI d3d9_device_CreateOffscreenPlainSurface(IDirect3DDevice9Ex
     /* FIXME: Offscreen surfaces are supposed to be always lockable,
      * regardless of the pool they're created in. Should we set dynamic usage
      * here? */
-    return d3d9_device_create_surface(device, width, height, format, TRUE,
-            FALSE, surface, 0, pool, D3DMULTISAMPLE_NONE, 0);
+    return d3d9_device_create_surface(device, width, height, format,
+            WINED3D_SURFACE_MAPPABLE, surface, 0, pool, D3DMULTISAMPLE_NONE, 0);
 }
 
 static HRESULT WINAPI d3d9_device_SetRenderTarget(IDirect3DDevice9Ex *iface, DWORD idx, IDirect3DSurface9 *surface)
@@ -1966,13 +2013,6 @@ static HRESULT WINAPI d3d9_device_DrawIndexedPrimitive(IDirect3DDevice9Ex *iface
     return hr;
 }
 
-static void STDMETHODCALLTYPE d3d9_null_wined3d_object_destroyed(void *parent) {}
-
-static const struct wined3d_parent_ops d3d9_null_wined3d_parent_ops =
-{
-    d3d9_null_wined3d_object_destroyed,
-};
-
 /* The caller is responsible for wined3d locking */
 static HRESULT d3d9_device_prepare_vertex_buffer(struct d3d9_device *device, UINT min_size)
 {
@@ -3259,28 +3299,33 @@ static void CDECL device_parent_mode_changed(struct wined3d_device_parent *devic
 }
 
 static HRESULT CDECL device_parent_create_texture_surface(struct wined3d_device_parent *device_parent,
-        void *container_parent, UINT width, UINT height, enum wined3d_format_id format, DWORD usage,
-        enum wined3d_pool pool, UINT sub_resource_idx, struct wined3d_surface **surface)
+        void *container_parent, const struct wined3d_resource_desc *desc, UINT sub_resource_idx,
+        DWORD flags, struct wined3d_surface **surface)
 {
     struct d3d9_device *device = device_from_device_parent(device_parent);
     struct d3d9_surface *d3d_surface;
-    BOOL lockable = TRUE;
     HRESULT hr;
 
-    TRACE("device_parent %p, container_parent %p, width %u, height %u, format %#x, usage %#x,\n"
-            "\tpool %#x, sub_resource_idx %u, surface %p.\n",
-            device_parent, container_parent, width, height, format, usage, pool, sub_resource_idx, surface);
+    TRACE("device_parent %p, container_parent %p, desc %p, sub_resource_idx %u, flags %#x, surface %p.\n",
+            device_parent, container_parent, desc, sub_resource_idx, flags, surface);
 
-    if (pool == WINED3D_POOL_DEFAULT && !(usage & D3DUSAGE_DYNAMIC))
-        lockable = FALSE;
+    if (!(d3d_surface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*d3d_surface))))
+    {
+        FIXME("Failed to allocate surface memory.\n");
+        return D3DERR_OUTOFVIDEOMEMORY;
+    }
 
-    if (FAILED(hr = d3d9_device_create_surface(device, width, height, d3dformat_from_wined3dformat(format),
-            lockable, FALSE, (IDirect3DSurface9 **)&d3d_surface, usage, pool, D3DMULTISAMPLE_NONE, 0)))
+    if (FAILED(hr = surface_init(d3d_surface, device, desc->width, desc->height,
+            d3dformat_from_wined3dformat(desc->format), flags, desc->usage, desc->pool,
+            desc->multisample_type, desc->multisample_quality)))
     {
-        WARN("Failed to create surface, hr %#x.\n", hr);
+        WARN("Failed to initialize surface, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, d3d_surface);
         return hr;
     }
 
+    TRACE("Created surface %p.\n", d3d_surface);
+
     *surface = d3d_surface->wined3d_surface;
     wined3d_surface_incref(*surface);
 
@@ -3295,42 +3340,43 @@ static HRESULT CDECL device_parent_create_texture_surface(struct wined3d_device_
 }
 
 static HRESULT CDECL device_parent_create_swapchain_surface(struct wined3d_device_parent *device_parent,
-        void *container_parent, UINT width, UINT height, enum wined3d_format_id format_id, DWORD usage,
-        enum wined3d_multisample_type multisample_type, DWORD multisample_quality, struct wined3d_surface **surface)
+        void *container_parent, const struct wined3d_resource_desc *desc, struct wined3d_surface **surface)
 {
     struct d3d9_device *device = device_from_device_parent(device_parent);
+    struct wined3d_resource_desc texture_desc;
     struct d3d9_surface *d3d_surface;
+    struct wined3d_texture *texture;
     HRESULT hr;
 
-    TRACE("device_parent %p, container_parent %p, width %u, height %u, format_id %#x, usage %#x,\n"
-            "\tmultisample_type %#x, multisample_quality %u, surface %p.\n",
-            device_parent, container_parent, width, height, format_id, usage,
-            multisample_type, multisample_quality, surface);
+    TRACE("device_parent %p, container_parent %p, desc %p, surface %p.\n",
+            device_parent, container_parent, desc, surface);
 
-    if (FAILED(hr = d3d9_device_create_surface(device, width, height, d3dformat_from_wined3dformat(format_id),
-            TRUE, FALSE, (IDirect3DSurface9 **)&d3d_surface, usage, D3DPOOL_DEFAULT, multisample_type,
-            multisample_quality)))
+    if (container_parent == device_parent)
+        container_parent = &device->IDirect3DDevice9Ex_iface;
+
+    texture_desc = *desc;
+    texture_desc.resource_type = WINED3D_RTYPE_TEXTURE;
+    if (FAILED(hr = wined3d_texture_create_2d(device->wined3d_device, &texture_desc, 1,
+            WINED3D_SURFACE_MAPPABLE, container_parent, &d3d9_null_wined3d_parent_ops, &texture)))
     {
-        WARN("Failed to create surface, hr %#x.\n", hr);
+        WARN("Failed to create texture, hr %#x.\n", hr);
         return hr;
     }
 
-    *surface = d3d_surface->wined3d_surface;
+    *surface = wined3d_surface_from_resource(wined3d_texture_get_sub_resource(texture, 0));
     wined3d_surface_incref(*surface);
+    wined3d_texture_decref(texture);
 
-    if (container_parent == device_parent)
-        d3d_surface->container = (IUnknown *)&device->IDirect3DDevice9Ex_iface;
-    else
-        d3d_surface->container = container_parent;
-    /* Implicit surfaces are created with an refcount of 0 */
-    IDirect3DSurface9_Release(&d3d_surface->IDirect3DSurface9_iface);
+    d3d_surface = wined3d_surface_get_parent(*surface);
+    d3d_surface->forwardReference = NULL;
+    d3d_surface->parent_device = &device->IDirect3DDevice9Ex_iface;
 
     return hr;
 }
 
 static HRESULT CDECL device_parent_create_volume(struct wined3d_device_parent *device_parent,
-        void *container_parent, UINT width, UINT height, UINT depth, enum wined3d_format_id format,
-        enum wined3d_pool pool, DWORD usage, struct wined3d_volume **volume)
+        void *container_parent, UINT width, UINT height, UINT depth, UINT level,
+        enum wined3d_format_id format, enum wined3d_pool pool, DWORD usage, struct wined3d_volume **volume)
 {
     struct d3d9_device *device = device_from_device_parent(device_parent);
     struct d3d9_volume *object;
@@ -3350,7 +3396,7 @@ static HRESULT CDECL device_parent_create_volume(struct wined3d_device_parent *d
         return D3DERR_OUTOFVIDEOMEMORY;
     }
 
-    hr = volume_init(object, device, width, height, depth, usage, format, pool);
+    hr = volume_init(object, device, width, height, depth, level, usage, format, pool);
     if (FAILED(hr))
     {
         WARN("Failed to initialize volume, hr %#x.\n", hr);
index 41b5e70..a21560f 100644 (file)
@@ -632,11 +632,12 @@ static const struct IDirect3D9ExVtbl d3d9_vtbl =
 
 BOOL d3d9_init(struct d3d9 *d3d9, BOOL extended)
 {
+    DWORD flags = extended ? 0 : WINED3D_VIDMEM_ACCOUNTING;
     d3d9->IDirect3D9Ex_iface.lpVtbl = &d3d9_vtbl;
     d3d9->refcount = 1;
 
     wined3d_mutex_lock();
-    d3d9->wined3d = wined3d_create(9, 0);
+    d3d9->wined3d = wined3d_create(9, flags);
     wined3d_mutex_unlock();
     if (!d3d9->wined3d)
         return FALSE;
index 3e1c34c..0f9688a 100644 (file)
@@ -391,10 +391,9 @@ static const struct wined3d_parent_ops d3d9_surface_wined3d_parent_ops =
 };
 
 HRESULT surface_init(struct d3d9_surface *surface, struct d3d9_device *device, UINT width, UINT height,
-        D3DFORMAT format, BOOL lockable, BOOL discard, DWORD usage, D3DPOOL pool,
-        D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality)
+        D3DFORMAT format, DWORD flags, DWORD usage, D3DPOOL pool, D3DMULTISAMPLE_TYPE multisample_type,
+        DWORD multisample_quality)
 {
-    DWORD flags = 0;
     HRESULT hr;
 
     surface->IDirect3DSurface9_iface.lpVtbl = &d3d9_surface_vtbl;
@@ -423,11 +422,6 @@ HRESULT surface_init(struct d3d9_surface *surface, struct d3d9_device *device, U
         multisample_quality = 0;
     }
 
-    if (lockable)
-        flags |= WINED3D_SURFACE_MAPPABLE;
-    if (discard)
-        flags |= WINED3D_SURFACE_DISCARD;
-
     wined3d_mutex_lock();
     hr = wined3d_surface_create(device->wined3d_device, width, height, wined3dformat_from_d3dformat(format),
             usage & WINED3DUSAGE_MASK, (enum wined3d_pool)pool, multisample_type, multisample_quality,
index de795b8..ec53cee 100644 (file)
@@ -1309,14 +1309,29 @@ static const struct wined3d_parent_ops d3d9_texture_wined3d_parent_ops =
 HRESULT texture_init(struct d3d9_texture *texture, struct d3d9_device *device,
         UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool)
 {
+    struct wined3d_resource_desc desc;
+    DWORD surface_flags = 0;
     HRESULT hr;
 
     texture->IDirect3DBaseTexture9_iface.lpVtbl = (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_2d_vtbl;
     texture->refcount = 1;
 
+    desc.resource_type = WINED3D_RTYPE_TEXTURE;
+    desc.format = wined3dformat_from_d3dformat(format);
+    desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
+    desc.multisample_quality = 0;
+    desc.usage = usage & WINED3DUSAGE_MASK;
+    desc.pool = pool;
+    desc.width = width;
+    desc.height = height;
+    desc.depth = 1;
+    desc.size = 0;
+
+    if (pool != D3DPOOL_DEFAULT || (usage & D3DUSAGE_DYNAMIC))
+        surface_flags |= WINED3D_SURFACE_MAPPABLE;
+
     wined3d_mutex_lock();
-    hr = wined3d_texture_create_2d(device->wined3d_device, width, height, levels,
-            usage & WINED3DUSAGE_MASK, wined3dformat_from_d3dformat(format), pool,
+    hr = wined3d_texture_create_2d(device->wined3d_device, &desc, levels, surface_flags,
             texture, &d3d9_texture_wined3d_parent_ops, &texture->wined3d_texture);
     wined3d_mutex_unlock();
     if (FAILED(hr))
@@ -1334,15 +1349,30 @@ HRESULT texture_init(struct d3d9_texture *texture, struct d3d9_device *device,
 HRESULT cubetexture_init(struct d3d9_texture *texture, struct d3d9_device *device,
         UINT edge_length, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool)
 {
+    struct wined3d_resource_desc desc;
+    DWORD surface_flags = 0;
     HRESULT hr;
 
     texture->IDirect3DBaseTexture9_iface.lpVtbl = (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_cube_vtbl;
     texture->refcount = 1;
 
+    desc.resource_type = WINED3D_RTYPE_CUBE_TEXTURE;
+    desc.format = wined3dformat_from_d3dformat(format);
+    desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
+    desc.multisample_quality = 0;
+    desc.usage = usage & WINED3DUSAGE_MASK;
+    desc.pool = pool;
+    desc.width = edge_length;
+    desc.height = edge_length;
+    desc.depth = 1;
+    desc.size = 0;
+
+    if (pool != D3DPOOL_DEFAULT || (usage & D3DUSAGE_DYNAMIC))
+        surface_flags |= WINED3D_SURFACE_MAPPABLE;
+
     wined3d_mutex_lock();
-    hr = wined3d_texture_create_cube(device->wined3d_device, edge_length,
-            levels, usage, wined3dformat_from_d3dformat(format), pool, texture,
-            &d3d9_texture_wined3d_parent_ops, &texture->wined3d_texture);
+    hr = wined3d_texture_create_cube(device->wined3d_device, &desc, levels, surface_flags,
+            texture, &d3d9_texture_wined3d_parent_ops, &texture->wined3d_texture);
     wined3d_mutex_unlock();
     if (FAILED(hr))
     {
@@ -1359,15 +1389,26 @@ HRESULT cubetexture_init(struct d3d9_texture *texture, struct d3d9_device *devic
 HRESULT volumetexture_init(struct d3d9_texture *texture, struct d3d9_device *device,
         UINT width, UINT height, UINT depth, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool)
 {
+    struct wined3d_resource_desc desc;
     HRESULT hr;
 
     texture->IDirect3DBaseTexture9_iface.lpVtbl = (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_3d_vtbl;
     texture->refcount = 1;
 
+    desc.resource_type = WINED3D_RTYPE_VOLUME_TEXTURE;
+    desc.format = wined3dformat_from_d3dformat(format);
+    desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
+    desc.multisample_quality = 0;
+    desc.usage = usage & WINED3DUSAGE_MASK;
+    desc.pool = pool;
+    desc.width = width;
+    desc.height = height;
+    desc.depth = depth;
+    desc.size = 0;
+
     wined3d_mutex_lock();
-    hr = wined3d_texture_create_3d(device->wined3d_device, width, height, depth, levels,
-            usage & WINED3DUSAGE_MASK, wined3dformat_from_d3dformat(format), pool, texture,
-            &d3d9_texture_wined3d_parent_ops, &texture->wined3d_texture);
+    hr = wined3d_texture_create_3d(device->wined3d_device, &desc, levels,
+            texture, &d3d9_texture_wined3d_parent_ops, &texture->wined3d_texture);
     wined3d_mutex_unlock();
     if (FAILED(hr))
     {
index 6511820..b3d7032 100644 (file)
@@ -275,15 +275,16 @@ static const struct wined3d_parent_ops d3d9_volume_wined3d_parent_ops =
 };
 
 HRESULT volume_init(struct d3d9_volume *volume, struct d3d9_device *device, UINT width, UINT height,
-        UINT depth, DWORD usage, enum wined3d_format_id format, enum wined3d_pool pool)
+        UINT depth, UINT level, DWORD usage, enum wined3d_format_id format, enum wined3d_pool pool)
 {
     HRESULT hr;
 
     volume->IDirect3DVolume9_iface.lpVtbl = &d3d9_volume_vtbl;
     volume->refcount = 1;
 
-    hr = wined3d_volume_create(device->wined3d_device, width, height, depth, usage & WINED3DUSAGE_MASK,
-            format, pool, volume, &d3d9_volume_wined3d_parent_ops, &volume->wined3d_volume);
+    hr = wined3d_volume_create(device->wined3d_device, width, height, depth, level,
+            usage & WINED3DUSAGE_MASK, format, pool, volume, &d3d9_volume_wined3d_parent_ops,
+            &volume->wined3d_volume);
     if (FAILED(hr))
     {
         WARN("Failed to create wined3d volume, hr %#x.\n", hr);
index 897a9c0..19f8756 100644 (file)
@@ -16,7 +16,6 @@ list(APPEND SOURCE
     main.c
     material.c
     palette.c
-    stubs.c
     surface.c
     utils.c
     vertexbuffer.c
@@ -24,34 +23,16 @@ list(APPEND SOURCE
     ${CMAKE_CURRENT_BINARY_DIR}/ddraw_stubs.c
     ${CMAKE_CURRENT_BINARY_DIR}/ddraw.def)
 
-add_library(ddraw SHARED
-    ${SOURCE}
-    ddraw.rc)
-
 if(MSVC)
     # FIXME: http://www.cmake.org/Bug/view.php?id=12998
     #add_target_compile_flags(ddraw "/FIwine/typeof.h")
     set_source_files_properties(${SOURCE} PROPERTIES COMPILE_FLAGS "/FIwine/typeof.h")
 endif()
 
+add_library(ddraw SHARED ${SOURCE} ddraw.rc)
 set_module_type(ddraw win32dll)
-
-target_link_libraries(ddraw
-    wine
-    uuid
-    dxguid
-    ${PSEH_LIB})
-
-add_importlibs(ddraw
-    advapi32
-    gdi32
-    ole32
-    user32
-    wined3d
-    msvcrt
-    kernel32
-    ntdll)
-
+target_link_libraries(ddraw wine uuid dxguid ${PSEH_LIB})
+add_importlibs(ddraw advapi32 gdi32 ole32 user32 wined3d msvcrt kernel32 ntdll)
 add_dependencies(ddraw wineheaders)
 add_pch(ddraw ddraw_private.h)
 add_cd_file(TARGET ddraw DESTINATION reactos/system32 FOR all)
index 337aab0..3f90377 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright 2000-2001 TransGaming Technologies Inc.
  * Copyright 2006 Stefan Dösinger
  * Copyright 2008 Denver Gingerich
+ * Copyright 2007-2008, 2011, 2013 Stefan Dösinger for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -366,7 +367,7 @@ void ddraw_destroy_swapchain(struct ddraw *ddraw)
     wined3d_swapchain_decref(ddraw->wined3d_swapchain);
     ddraw->wined3d_swapchain = NULL;
 
-    if (DefaultSurfaceType == DDRAW_SURFACE_TYPE_OPENGL)
+    if (!(ddraw->flags & DDRAW_NO3D))
     {
         UINT i;
 
@@ -392,7 +393,7 @@ void ddraw_destroy_swapchain(struct ddraw *ddraw)
             }
         }
 
-        ddraw->d3d_initialized = FALSE;
+        ddraw->flags &= ~DDRAW_D3D_INITIALIZED;
     }
     else
     {
@@ -586,11 +587,11 @@ static HRESULT ddraw_attach_d3d_device(struct ddraw *ddraw,
 
     /* Set this NOW, otherwise creating the depth stencil surface will cause a
      * recursive loop until ram or emulated video memory is full. */
-    ddraw->d3d_initialized = TRUE;
+    ddraw->flags |= DDRAW_D3D_INITIALIZED;
     hr = wined3d_device_init_3d(ddraw->wined3d_device, swapchain_desc);
     if (FAILED(hr))
     {
-        ddraw->d3d_initialized = FALSE;
+        ddraw->flags &= ~DDRAW_D3D_INITIALIZED;
         return hr;
     }
 
@@ -629,7 +630,7 @@ static HRESULT ddraw_create_swapchain(struct ddraw *ddraw, HWND window, BOOL win
     swapchain_desc.device_window = window;
     swapchain_desc.windowed = windowed;
 
-    if (DefaultSurfaceType == DDRAW_SURFACE_TYPE_OPENGL)
+    if (!(ddraw->flags & DDRAW_NO3D))
         hr = ddraw_attach_d3d_device(ddraw, &swapchain_desc);
     else
         hr = wined3d_device_init_gdi(ddraw->wined3d_device, &swapchain_desc);
@@ -652,6 +653,75 @@ static HRESULT ddraw_create_swapchain(struct ddraw *ddraw, HWND window, BOOL win
     return DD_OK;
 }
 
+/*****************************************************************************
+ * IDirectDraw7::RestoreDisplayMode
+ *
+ * Restores the display mode to what it was at creation time. Basically.
+ *
+ * Returns
+ *  DD_OK on success
+ *  DDERR_NOEXCLUSIVE mode if the device isn't in fullscreen mode
+ *
+ *****************************************************************************/
+static HRESULT WINAPI ddraw7_RestoreDisplayMode(IDirectDraw7 *iface)
+{
+    struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
+    HRESULT hr;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+
+    if (!(ddraw->flags & DDRAW_RESTORE_MODE))
+    {
+        wined3d_mutex_unlock();
+        return DD_OK;
+    }
+
+    if (exclusive_ddraw && exclusive_ddraw != ddraw)
+    {
+        wined3d_mutex_unlock();
+        return DDERR_NOEXCLUSIVEMODE;
+    }
+
+    if (SUCCEEDED(hr = wined3d_set_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &original_mode)))
+    {
+        ddraw->flags &= ~DDRAW_RESTORE_MODE;
+        restore_mode = FALSE;
+    }
+
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI ddraw4_RestoreDisplayMode(IDirectDraw4 *iface)
+{
+    struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    return ddraw7_RestoreDisplayMode(&ddraw->IDirectDraw7_iface);
+}
+
+static HRESULT WINAPI ddraw2_RestoreDisplayMode(IDirectDraw2 *iface)
+{
+    struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    return ddraw7_RestoreDisplayMode(&ddraw->IDirectDraw7_iface);
+}
+
+static HRESULT WINAPI ddraw1_RestoreDisplayMode(IDirectDraw *iface)
+{
+    struct ddraw *ddraw = impl_from_IDirectDraw(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    return ddraw7_RestoreDisplayMode(&ddraw->IDirectDraw7_iface);
+}
+
 /*****************************************************************************
  * IDirectDraw7::SetCooperativeLevel
  *
@@ -668,23 +738,21 @@ static HRESULT ddraw_create_swapchain(struct ddraw *ddraw, HWND window, BOOL win
  * fixme, be sure to run again with a +ddraw trace.
  *
  * What is known about cooperative levels (See the ddraw modes test):
- * DDSCL_EXCLUSIVE and DDSCL_FULLSCREEN must be used with each other
- * DDSCL_NORMAL is not compatible with DDSCL_EXCLUSIVE or DDSCL_FULLSCREEN
+ * DDSCL_EXCLUSIVE requires DDSCL_FULLSCREEN.
+ * DDSCL_NORMAL is not compatible with DDSCL_EXCLUSIVE.
+ * Unlike what msdn claims, DDSCL_NORMAL | DDSCL_FULLSCREEN is allowed.
  * DDSCL_SETFOCUSWINDOW can be passed only in DDSCL_NORMAL mode, but after that
- * DDSCL_FULLSCREEN can be activated
- * DDSCL_SETFOCUSWINDOW may only be used with DDSCL_NOWINDOWCHANGES
+ * DDSCL_EXCLUSIVE can be activated.
+ * DDSCL_SETFOCUSWINDOW may only be used with DDSCL_NOWINDOWCHANGES or
+ * DDSCL_CREATEDEVICEWINDOW.
  *
  * Handled flags: DDSCL_NORMAL, DDSCL_FULLSCREEN, DDSCL_EXCLUSIVE,
+ *                DDSCL_CREATEDEVICEWINDOW, DDSCL_SETDEVICEWINDOW
  *                DDSCL_SETFOCUSWINDOW (partially),
  *                DDSCL_MULTITHREADED (work in progress)
+ *                DDSCL_FPUPRESERVE (see device.c)
  *
- * Unhandled flags, which should be implemented
- *  DDSCL_SETDEVICEWINDOW: Sets a window specially used for rendering (I don't
- *  expect any difference to a normal window for wine)
- *  DDSCL_CREATEDEVICEWINDOW: Tells ddraw to create its own window for
- *  rendering (Possible test case: Half-Life)
- *
- * Unsure about these: DDSCL_FPUSETUP DDSCL_FPURESERVE
+ * Unsure about this: DDSCL_FPUSETUP
  *
  * These don't seem very important for wine:
  *  DDSCL_ALLOWREBOOT, DDSCL_NOWINDOWCHANGES, DDSCL_ALLOWMODEX
@@ -696,15 +764,16 @@ static HRESULT ddraw_create_swapchain(struct ddraw *ddraw, HWND window, BOOL win
  *   (Probably others too, have to investigate)
  *
  *****************************************************************************/
-static HRESULT WINAPI ddraw7_SetCooperativeLevel(IDirectDraw7 *iface, HWND window, DWORD cooplevel)
+static HRESULT ddraw_set_cooperative_level(struct ddraw *ddraw, HWND window,
+        DWORD cooplevel, BOOL restore_mode_on_normal)
 {
-    struct ddraw *This = impl_from_IDirectDraw7(iface);
     struct wined3d_surface *rt = NULL, *ds = NULL;
     struct wined3d_stateblock *stateblock;
     BOOL restore_state = FALSE;
     HRESULT hr;
 
-    TRACE("iface %p, window %p, flags %#x.\n", iface, window, cooplevel);
+    TRACE("ddraw %p, window %p, flags %#x, restore_mode_on_normal %x.\n", ddraw, window, cooplevel,
+            restore_mode_on_normal);
     DDRAW_dump_cooperativelevel(cooplevel);
 
     wined3d_mutex_lock();
@@ -745,7 +814,7 @@ static HRESULT WINAPI ddraw7_SetCooperativeLevel(IDirectDraw7 *iface, HWND windo
             return DDERR_INVALIDPARAMS;
         }
 
-        hr = ddraw_set_focus_window(This, window);
+        hr = ddraw_set_focus_window(ddraw, window);
         wined3d_mutex_unlock();
         return hr;
     }
@@ -763,7 +832,7 @@ static HRESULT WINAPI ddraw7_SetCooperativeLevel(IDirectDraw7 *iface, HWND windo
         {
             HWND device_window;
 
-            if (!This->focuswindow && !(cooplevel & DDSCL_SETFOCUSWINDOW))
+            if (!ddraw->focuswindow && !(cooplevel & DDSCL_SETFOCUSWINDOW))
             {
                 WARN("No focus window set.\n");
                 wined3d_mutex_unlock();
@@ -785,8 +854,8 @@ static HRESULT WINAPI ddraw7_SetCooperativeLevel(IDirectDraw7 *iface, HWND windo
 
             /* Native apparently leaks the created device window if setting the
              * focus window below fails. */
-            This->cooperative_level |= DDSCL_CREATEDEVICEWINDOW;
-            This->devicewindow = device_window;
+            ddraw->cooperative_level |= DDSCL_CREATEDEVICEWINDOW;
+            ddraw->devicewindow = device_window;
 
             if (cooplevel & DDSCL_SETFOCUSWINDOW)
             {
@@ -796,7 +865,7 @@ static HRESULT WINAPI ddraw7_SetCooperativeLevel(IDirectDraw7 *iface, HWND windo
                     return DDERR_NOHWND;
                 }
 
-                if (FAILED(hr = ddraw_set_focus_window(This, window)))
+                if (FAILED(hr = ddraw_set_focus_window(ddraw, window)))
                 {
                     wined3d_mutex_unlock();
                     return hr;
@@ -808,53 +877,37 @@ static HRESULT WINAPI ddraw7_SetCooperativeLevel(IDirectDraw7 *iface, HWND windo
     }
     else
     {
-        if (This->cooperative_level & DDSCL_CREATEDEVICEWINDOW)
-            DestroyWindow(This->devicewindow);
-        This->devicewindow = NULL;
-        This->focuswindow = NULL;
+        if (ddraw->cooperative_level & DDSCL_CREATEDEVICEWINDOW)
+            DestroyWindow(ddraw->devicewindow);
+        ddraw->devicewindow = NULL;
+        ddraw->focuswindow = NULL;
     }
 
-    if ((This->cooperative_level & DDSCL_EXCLUSIVE)
-            && (window != This->dest_window || !(cooplevel & DDSCL_EXCLUSIVE)))
-        wined3d_device_release_focus_window(This->wined3d_device);
-
-    if ((cooplevel & DDSCL_FULLSCREEN) != (This->cooperative_level & DDSCL_FULLSCREEN) || window != This->dest_window)
+    if ((cooplevel & DDSCL_FULLSCREEN) != (ddraw->cooperative_level & DDSCL_FULLSCREEN) || window != ddraw->dest_window)
     {
-        if (This->cooperative_level & DDSCL_FULLSCREEN)
-            wined3d_device_restore_fullscreen_window(This->wined3d_device, This->dest_window);
+        if (ddraw->cooperative_level & DDSCL_FULLSCREEN)
+            wined3d_device_restore_fullscreen_window(ddraw->wined3d_device, ddraw->dest_window);
 
         if (cooplevel & DDSCL_FULLSCREEN)
         {
             struct wined3d_display_mode display_mode;
 
-            wined3d_get_adapter_display_mode(This->wined3d, WINED3DADAPTER_DEFAULT, &display_mode, NULL);
-            wined3d_device_setup_fullscreen_window(This->wined3d_device, window,
+            wined3d_get_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &display_mode, NULL);
+            wined3d_device_setup_fullscreen_window(ddraw->wined3d_device, window,
                     display_mode.width, display_mode.height);
         }
     }
 
-    if ((cooplevel & DDSCL_EXCLUSIVE)
-            && (window != This->dest_window || !(This->cooperative_level & DDSCL_EXCLUSIVE)))
-    {
-        hr = wined3d_device_acquire_focus_window(This->wined3d_device, window);
-        if (FAILED(hr))
-        {
-            ERR("Failed to acquire focus window, hr %#x.\n", hr);
-            wined3d_mutex_unlock();
-            return hr;
-        }
-    }
-
-    if (cooplevel & DDSCL_MULTITHREADED && !(This->cooperative_level & DDSCL_MULTITHREADED))
-        wined3d_device_set_multithreaded(This->wined3d_device);
+    if (cooplevel & DDSCL_MULTITHREADED && !(ddraw->cooperative_level & DDSCL_MULTITHREADED))
+        wined3d_device_set_multithreaded(ddraw->wined3d_device);
 
-    if (This->wined3d_swapchain)
+    if (ddraw->wined3d_swapchain)
     {
-        if (DefaultSurfaceType != DDRAW_SURFACE_TYPE_GDI)
+        if (!(ddraw->flags & DDRAW_NO3D))
         {
             restore_state = TRUE;
 
-            if (FAILED(hr = wined3d_stateblock_create(This->wined3d_device, WINED3D_SBT_ALL, &stateblock)))
+            if (FAILED(hr = wined3d_stateblock_create(ddraw->wined3d_device, WINED3D_SBT_ALL, &stateblock)))
             {
                 ERR("Failed to create stateblock, hr %#x.\n", hr);
                 wined3d_mutex_unlock();
@@ -862,33 +915,33 @@ static HRESULT WINAPI ddraw7_SetCooperativeLevel(IDirectDraw7 *iface, HWND windo
             }
 
             wined3d_stateblock_capture(stateblock);
-            rt = wined3d_device_get_render_target(This->wined3d_device, 0);
-            if (rt == This->wined3d_frontbuffer)
+            rt = wined3d_device_get_render_target(ddraw->wined3d_device, 0);
+            if (rt == ddraw->wined3d_frontbuffer)
                 rt = NULL;
             else if (rt)
                 wined3d_surface_incref(rt);
 
-            if ((ds = wined3d_device_get_depth_stencil(This->wined3d_device)))
+            if ((ds = wined3d_device_get_depth_stencil(ddraw->wined3d_device)))
                 wined3d_surface_incref(ds);
         }
 
-        ddraw_destroy_swapchain(This);
+        ddraw_destroy_swapchain(ddraw);
     }
 
-    if (FAILED(hr = ddraw_create_swapchain(This, window, !(cooplevel & DDSCL_FULLSCREEN))))
+    if (FAILED(hr = ddraw_create_swapchain(ddraw, window, !(cooplevel & DDSCL_FULLSCREEN))))
         ERR("Failed to create swapchain, hr %#x.\n", hr);
 
     if (restore_state)
     {
         if (ds)
         {
-            wined3d_device_set_depth_stencil(This->wined3d_device, ds);
+            wined3d_device_set_depth_stencil(ddraw->wined3d_device, ds);
             wined3d_surface_decref(ds);
         }
 
         if (rt)
         {
-            wined3d_device_set_render_target(This->wined3d_device, 0, rt, FALSE);
+            wined3d_device_set_render_target(ddraw->wined3d_device, 0, rt, FALSE);
             wined3d_surface_decref(rt);
         }
 
@@ -896,35 +949,69 @@ static HRESULT WINAPI ddraw7_SetCooperativeLevel(IDirectDraw7 *iface, HWND windo
         wined3d_stateblock_decref(stateblock);
     }
 
+    if (!(cooplevel & DDSCL_EXCLUSIVE) && (ddraw->cooperative_level & DDSCL_EXCLUSIVE)
+            && restore_mode_on_normal)
+    {
+        hr = ddraw7_RestoreDisplayMode(&ddraw->IDirectDraw7_iface);
+        if (FAILED(hr))
+            ERR("RestoreDisplayMode failed\n");
+    }
+
+    if ((ddraw->cooperative_level & DDSCL_EXCLUSIVE)
+            && (window != ddraw->dest_window || !(cooplevel & DDSCL_EXCLUSIVE)))
+        wined3d_device_release_focus_window(ddraw->wined3d_device);
+
+    if ((cooplevel & DDSCL_EXCLUSIVE)
+            && (window != ddraw->dest_window || !(ddraw->cooperative_level & DDSCL_EXCLUSIVE)))
+    {
+        hr = wined3d_device_acquire_focus_window(ddraw->wined3d_device, window);
+        if (FAILED(hr))
+        {
+            ERR("Failed to acquire focus window, hr %#x.\n", hr);
+            wined3d_mutex_unlock();
+            return hr;
+        }
+    }
+
     /* Unhandled flags */
-    if(cooplevel & DDSCL_ALLOWREBOOT)
-        WARN("(%p) Unhandled flag DDSCL_ALLOWREBOOT, harmless\n", This);
-    if(cooplevel & DDSCL_ALLOWMODEX)
-        WARN("(%p) Unhandled flag DDSCL_ALLOWMODEX, harmless\n", This);
-    if(cooplevel & DDSCL_FPUSETUP)
-        WARN("(%p) Unhandled flag DDSCL_FPUSETUP, harmless\n", This);
+    if (cooplevel & DDSCL_ALLOWREBOOT)
+        WARN("Unhandled flag DDSCL_ALLOWREBOOT, harmless\n");
+    if (cooplevel & DDSCL_ALLOWMODEX)
+        WARN("Unhandled flag DDSCL_ALLOWMODEX, harmless\n");
+    if (cooplevel & DDSCL_FPUSETUP)
+        WARN("Unhandled flag DDSCL_FPUSETUP, harmless\n");
 
     if (cooplevel & DDSCL_EXCLUSIVE)
-        exclusive_ddraw = This;
-    else if (exclusive_ddraw == This)
+        exclusive_ddraw = ddraw;
+    else if (exclusive_ddraw == ddraw)
         exclusive_ddraw = NULL;
 
     /* Store the cooperative_level */
-    This->cooperative_level = cooplevel;
-    This->dest_window = window;
+    ddraw->cooperative_level = cooplevel;
+    ddraw->dest_window = window;
+
     TRACE("SetCooperativeLevel retuning DD_OK\n");
     wined3d_mutex_unlock();
 
     return DD_OK;
 }
 
+static HRESULT WINAPI ddraw7_SetCooperativeLevel(IDirectDraw7 *iface, HWND window, DWORD flags)
+{
+    struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
+
+    TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
+
+    return ddraw_set_cooperative_level(ddraw, window, flags, !(ddraw->flags & DDRAW_SCL_DDRAW1));
+}
+
 static HRESULT WINAPI ddraw4_SetCooperativeLevel(IDirectDraw4 *iface, HWND window, DWORD flags)
 {
     struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
 
     TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
 
-    return ddraw7_SetCooperativeLevel(&ddraw->IDirectDraw7_iface, window, flags);
+    return ddraw_set_cooperative_level(ddraw, window, flags, !(ddraw->flags & DDRAW_SCL_DDRAW1));
 }
 
 static HRESULT WINAPI ddraw2_SetCooperativeLevel(IDirectDraw2 *iface, HWND window, DWORD flags)
@@ -933,16 +1020,20 @@ static HRESULT WINAPI ddraw2_SetCooperativeLevel(IDirectDraw2 *iface, HWND windo
 
     TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
 
-    return ddraw7_SetCooperativeLevel(&ddraw->IDirectDraw7_iface, window, flags);
+    return ddraw_set_cooperative_level(ddraw, window, flags, !(ddraw->flags & DDRAW_SCL_DDRAW1));
 }
 
 static HRESULT WINAPI ddraw1_SetCooperativeLevel(IDirectDraw *iface, HWND window, DWORD flags)
 {
     struct ddraw *ddraw = impl_from_IDirectDraw(iface);
+    HRESULT hr;
 
     TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
 
-    return ddraw7_SetCooperativeLevel(&ddraw->IDirectDraw7_iface, window, flags);
+    hr = ddraw_set_cooperative_level(ddraw, window, flags, FALSE);
+    if (SUCCEEDED(hr))
+        ddraw->flags |= DDRAW_SCL_DDRAW1;
+    return hr;
 }
 
 /*****************************************************************************
@@ -1025,7 +1116,7 @@ static HRESULT WINAPI ddraw7_SetDisplayMode(IDirectDraw7 *iface, DWORD width, DW
     /* TODO: Lose the primary surface. */
     if (SUCCEEDED(hr = wined3d_set_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode)))
     {
-        ddraw->restore_mode = TRUE;
+        ddraw->flags |= DDRAW_RESTORE_MODE;
         restore_mode = TRUE;
     }
 
@@ -1069,75 +1160,6 @@ static HRESULT WINAPI ddraw1_SetDisplayMode(IDirectDraw *iface, DWORD width, DWO
     return ddraw7_SetDisplayMode(&ddraw->IDirectDraw7_iface, width, height, bpp, 0, 0);
 }
 
-/*****************************************************************************
- * IDirectDraw7::RestoreDisplayMode
- *
- * Restores the display mode to what it was at creation time. Basically.
- *
- * Returns
- *  DD_OK on success
- *  DDERR_NOEXCLUSIVE mode if the device isn't in fullscreen mode
- *
- *****************************************************************************/
-static HRESULT WINAPI ddraw7_RestoreDisplayMode(IDirectDraw7 *iface)
-{
-    struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
-    HRESULT hr;
-
-    TRACE("iface %p.\n", iface);
-
-    wined3d_mutex_lock();
-
-    if (!ddraw->restore_mode)
-    {
-        wined3d_mutex_unlock();
-        return DD_OK;
-    }
-
-    if (exclusive_ddraw && exclusive_ddraw != ddraw)
-    {
-        wined3d_mutex_unlock();
-        return DDERR_NOEXCLUSIVEMODE;
-    }
-
-    if (SUCCEEDED(hr = wined3d_set_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &original_mode)))
-    {
-        ddraw->restore_mode = FALSE;
-        restore_mode = FALSE;
-    }
-
-    wined3d_mutex_unlock();
-
-    return hr;
-}
-
-static HRESULT WINAPI ddraw4_RestoreDisplayMode(IDirectDraw4 *iface)
-{
-    struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
-
-    TRACE("iface %p.\n", iface);
-
-    return ddraw7_RestoreDisplayMode(&ddraw->IDirectDraw7_iface);
-}
-
-static HRESULT WINAPI ddraw2_RestoreDisplayMode(IDirectDraw2 *iface)
-{
-    struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
-
-    TRACE("iface %p.\n", iface);
-
-    return ddraw7_RestoreDisplayMode(&ddraw->IDirectDraw7_iface);
-}
-
-static HRESULT WINAPI ddraw1_RestoreDisplayMode(IDirectDraw *iface)
-{
-    struct ddraw *ddraw = impl_from_IDirectDraw(iface);
-
-    TRACE("iface %p.\n", iface);
-
-    return ddraw7_RestoreDisplayMode(&ddraw->IDirectDraw7_iface);
-}
-
 /*****************************************************************************
  * IDirectDraw7::GetCaps
  *
@@ -1206,18 +1228,8 @@ static HRESULT WINAPI ddraw7_GetCaps(IDirectDraw7 *iface, DDCAPS *DriverCaps, DD
     caps.dwSSBCKeyCaps = winecaps.ddraw_caps.ssb_color_key_caps;
     caps.dwSSBFXCaps = winecaps.ddraw_caps.ssb_fx_caps;
 
-    /* Even if wined3d supports 3D rendering, remove the cap if ddraw is
-     * configured not to use it. */
-    if (DefaultSurfaceType == DDRAW_SURFACE_TYPE_GDI)
-    {
-        caps.dwCaps &= ~DDCAPS_3D;
-        caps.ddsCaps.dwCaps &= ~(DDSCAPS_3DDEVICE | DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_ZBUFFER);
-    }
-    if (winecaps.ddraw_caps.stride_align)
-    {
-        caps.dwCaps |= DDCAPS_ALIGNSTRIDE;
-        caps.dwAlignStrideAlign = winecaps.ddraw_caps.stride_align;
-    }
+    caps.dwCaps |= DDCAPS_ALIGNSTRIDE;
+    caps.dwAlignStrideAlign = DDRAW_STRIDE_ALIGNMENT;
 
     if(DriverCaps)
     {
@@ -1360,7 +1372,7 @@ static HRESULT WINAPI ddraw7_GetDisplayMode(IDirectDraw7 *iface, DDSURFACEDESC2
     DDSD->u2.dwRefreshRate = 60;
     DDSD->ddsCaps.dwCaps = 0;
     DDSD->u4.ddpfPixelFormat.dwSize = sizeof(DDSD->u4.ddpfPixelFormat);
-    PixelFormat_WineD3DtoDD(&DDSD->u4.ddpfPixelFormat, mode.format_id);
+    ddrawformat_from_wined3dformat(&DDSD->u4.ddpfPixelFormat, mode.format_id);
     DDSD->u1.lPitch = mode.width * DDSD->u4.ddpfPixelFormat.u1.dwRGBBitCount / 8;
 
     if(TRACE_ON(ddraw))
@@ -1687,7 +1699,7 @@ static HRESULT WINAPI ddraw7_Initialize(IDirectDraw7 *iface, GUID *guid)
 
     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
 
-    if (ddraw->initialized)
+    if (ddraw->flags & DDRAW_INITIALIZED)
         return DDERR_ALREADYINITIALIZED;
 
     /* FIXME: To properly take the GUID into account we should call
@@ -1695,7 +1707,7 @@ static HRESULT WINAPI ddraw7_Initialize(IDirectDraw7 *iface, GUID *guid)
     if (guid)
         FIXME("Ignoring guid %s.\n", debugstr_guid(guid));
 
-    ddraw->initialized = TRUE;
+    ddraw->flags |= DDRAW_INITIALIZED;
     return DD_OK;
 }
 
@@ -2069,7 +2081,7 @@ static HRESULT WINAPI ddraw7_EnumDisplayModes(IDirectDraw7 *iface, DWORD Flags,
     struct wined3d_display_mode mode;
     unsigned int modenum, fmt;
     DDSURFACEDESC2 callback_sd;
-    unsigned enum_mode_count = 0, enum_mode_array_size = 0;
+    unsigned enum_mode_count = 0, enum_mode_array_size = 16;
     DDPIXELFORMAT pixelformat;
 
     static const enum wined3d_format_id checkFormatList[] =
@@ -2085,18 +2097,10 @@ static HRESULT WINAPI ddraw7_EnumDisplayModes(IDirectDraw7 *iface, DWORD Flags,
     if (!cb)
         return DDERR_INVALIDPARAMS;
 
+    enum_modes = HeapAlloc(GetProcessHeap(), 0, sizeof(*enum_modes) * enum_mode_array_size);
+    if (!enum_modes) return DDERR_OUTOFMEMORY;
+
     wined3d_mutex_lock();
-    if(!(Flags & DDEDM_REFRESHRATES))
-    {
-        enum_mode_array_size = 16;
-        enum_modes = HeapAlloc(GetProcessHeap(), 0, sizeof(*enum_modes) * enum_mode_array_size);
-        if (!enum_modes)
-        {
-            ERR("Out of memory\n");
-            wined3d_mutex_unlock();
-            return DDERR_OUTOFMEMORY;
-        }
-    }
 
     pixelformat.dwSize = sizeof(pixelformat);
     for(fmt = 0; fmt < (sizeof(checkFormatList) / sizeof(checkFormatList[0])); fmt++)
@@ -2105,7 +2109,10 @@ static HRESULT WINAPI ddraw7_EnumDisplayModes(IDirectDraw7 *iface, DWORD Flags,
         while (wined3d_enum_adapter_modes(ddraw->wined3d, WINED3DADAPTER_DEFAULT, checkFormatList[fmt],
                 WINED3D_SCANLINE_ORDERING_UNKNOWN, modenum++, &mode) == WINED3D_OK)
         {
-            PixelFormat_WineD3DtoDD(&pixelformat, mode.format_id);
+            BOOL found = FALSE;
+            unsigned i;
+
+            ddrawformat_from_wined3dformat(&pixelformat, mode.format_id);
             if (DDSD)
             {
                 if (DDSD->dwFlags & DDSD_WIDTH && mode.width != DDSD->dwWidth)
@@ -2119,27 +2126,18 @@ static HRESULT WINAPI ddraw7_EnumDisplayModes(IDirectDraw7 *iface, DWORD Flags,
                     continue;
             }
 
-            if(!(Flags & DDEDM_REFRESHRATES))
+            /* DX docs state EnumDisplayMode should return only unique modes */
+            for (i = 0; i < enum_mode_count; i++)
             {
-                /* DX docs state EnumDisplayMode should return only unique modes. If DDEDM_REFRESHRATES is not set, refresh
-                 * rate doesn't matter when determining if the mode is unique. So modes only differing in refresh rate have
-                 * to be reduced to a single unique result in such case.
-                 */
-                BOOL found = FALSE;
-                unsigned i;
-
-                for (i = 0; i < enum_mode_count; i++)
+                if (enum_modes[i].width == mode.width && enum_modes[i].height == mode.height
+                    && enum_modes[i].format_id == mode.format_id
+                    && (enum_modes[i].refresh_rate == mode.refresh_rate || !(Flags & DDEDM_REFRESHRATES)))
                 {
-                    if (enum_modes[i].width == mode.width && enum_modes[i].height == mode.height
-                            && enum_modes[i].format_id == mode.format_id)
-                    {
-                        found = TRUE;
-                        break;
-                    }
+                    found = TRUE;
+                    break;
                 }
-
-                if(found) continue;
             }
+            if(found) continue;
 
             memset(&callback_sd, 0, sizeof(callback_sd));
             callback_sd.dwSize = sizeof(callback_sd);
@@ -2169,28 +2167,23 @@ static HRESULT WINAPI ddraw7_EnumDisplayModes(IDirectDraw7 *iface, DWORD Flags,
                 return DD_OK;
             }
 
-            if(!(Flags & DDEDM_REFRESHRATES))
+            if (enum_mode_count == enum_mode_array_size)
             {
-                if (enum_mode_count == enum_mode_array_size)
+                struct wined3d_display_mode *new_enum_modes;
+
+                enum_mode_array_size *= 2;
+                new_enum_modes = HeapReAlloc(GetProcessHeap(), 0, enum_modes,
+                                             sizeof(*new_enum_modes) * enum_mode_array_size);
+                if (!new_enum_modes)
                 {
-                    struct wined3d_display_mode *new_enum_modes;
-
-                    enum_mode_array_size *= 2;
-                    new_enum_modes = HeapReAlloc(GetProcessHeap(), 0, enum_modes,
-                            sizeof(*new_enum_modes) * enum_mode_array_size);
-                    if (!new_enum_modes)
-                    {
-                        ERR("Out of memory\n");
-                        HeapFree(GetProcessHeap(), 0, enum_modes);
-                        wined3d_mutex_unlock();
-                        return DDERR_OUTOFMEMORY;
-                    }
-
-                    enum_modes = new_enum_modes;
+                    HeapFree(GetProcessHeap(), 0, enum_modes);
+                    wined3d_mutex_unlock();
+                    return DDERR_OUTOFMEMORY;
                 }
 
-                enum_modes[enum_mode_count++] = mode;
+                enum_modes = new_enum_modes;
             }
+            enum_modes[enum_mode_count++] = mode;
         }
     }
 
@@ -2475,22 +2468,22 @@ static HRESULT WINAPI ddraw7_StartModeTest(IDirectDraw7 *iface, SIZE *Modes, DWO
  *  DD_OK on success
  *
  *****************************************************************************/
-static HRESULT ddraw_create_surface(struct ddraw *ddraw, DDSURFACEDESC2 *pDDSD,
-        struct ddraw_surface **surface, UINT version)
+static HRESULT ddraw_create_surface(struct ddraw *ddraw, DDSURFACEDESC2 *desc,
+        DWORD flags, struct ddraw_surface **surface, UINT version)
 {
     HRESULT hr;
 
-    TRACE("ddraw %p, surface_desc %p, surface %p.\n", ddraw, pDDSD, surface);
+    TRACE("ddraw %p, desc %p, flags %#x, surface %p.\n", ddraw, desc, flags, surface);
 
     if (TRACE_ON(ddraw))
     {
         TRACE("Requesting surface desc:\n");
-        DDRAW_dump_surface_desc(pDDSD);
+        DDRAW_dump_surface_desc(desc);
     }
 
-    if ((pDDSD->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) && DefaultSurfaceType != DDRAW_SURFACE_TYPE_OPENGL)
+    if ((desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) && (ddraw->flags & DDRAW_NO3D))
     {
-        WARN("The application requests a 3D capable surface, but a non-OpenGL surface type was set in the registry.\n");
+        WARN("The application requests a 3D capable surface, but the ddraw object was created without 3D support.\n");
         /* Do not fail surface creation, only fail 3D device creation. */
     }
 
@@ -2502,7 +2495,7 @@ static HRESULT ddraw_create_surface(struct ddraw *ddraw, DDSURFACEDESC2 *pDDSD,
         return DDERR_OUTOFVIDEOMEMORY;
     }
 
-    if (FAILED(hr = ddraw_surface_init(*surface, ddraw, pDDSD, version)))
+    if (FAILED(hr = ddraw_surface_init(*surface, ddraw, desc, flags, version)))
     {
         WARN("Failed to initialize surface, hr %#x.\n", hr);
         HeapFree(GetProcessHeap(), 0, *surface);
@@ -2607,6 +2600,12 @@ static HRESULT CreateSurface(struct ddraw *ddraw, DDSURFACEDESC2 *DDSD,
     HRESULT hr;
     DDSURFACEDESC2 desc2;
     const DWORD sysvidmem = DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
+    /* Some applications assume surfaces will always be mapped at the same
+     * address. Some of those also assume that this address is valid even when
+     * the surface isn't mapped, and that updates done this way will be
+     * visible on the screen. The game Nox is such an application,
+     * Commandos: Behind Enemy Lines is another. */
+    const DWORD flags = WINED3D_SURFACE_MAPPABLE | WINED3D_SURFACE_PIN_SYSMEM;
 
     TRACE("ddraw %p, surface_desc %p, surface %p, outer_unknown %p.\n", ddraw, DDSD, surface, UnkOuter);
 
@@ -2715,7 +2714,7 @@ static HRESULT CreateSurface(struct ddraw *ddraw, DDSURFACEDESC2 *DDSD,
         desc2.dwFlags |= DDSD_PIXELFORMAT;
         desc2.u4.ddpfPixelFormat.dwSize=sizeof(DDPIXELFORMAT);
 
-        PixelFormat_WineD3DtoDD(&desc2.u4.ddpfPixelFormat, mode.format_id);
+        ddrawformat_from_wined3dformat(&desc2.u4.ddpfPixelFormat, mode.format_id);
     }
 
     /* No Width or no Height? Use the original screen size
@@ -2808,7 +2807,7 @@ static HRESULT CreateSurface(struct ddraw *ddraw, DDSURFACEDESC2 *DDSD,
     }
 
     /* Create the first surface */
-    if (FAILED(hr = ddraw_create_surface(ddraw, &desc2, &object, version)))
+    if (FAILED(hr = ddraw_create_surface(ddraw, &desc2, flags, &object, version)))
     {
         WARN("ddraw_create_surface failed, hr %#x.\n", hr);
         return hr;
@@ -2835,7 +2834,7 @@ static HRESULT CreateSurface(struct ddraw *ddraw, DDSURFACEDESC2 *DDSD,
         {
             struct ddraw_surface *object2 = NULL;
 
-            if (FAILED(hr = ddraw_create_surface(ddraw, &desc2, &object2, version)))
+            if (FAILED(hr = ddraw_create_surface(ddraw, &desc2, flags, &object2, version)))
             {
                 if (version == 7)
                     IDirectDrawSurface7_Release(&object->IDirectDrawSurface7_iface);
@@ -2864,7 +2863,7 @@ static HRESULT CreateSurface(struct ddraw *ddraw, DDSURFACEDESC2 *DDSD,
 
     /* Create a WineD3DTexture if a texture was requested */
     if (desc2.ddsCaps.dwCaps & DDSCAPS_TEXTURE)
-        ddraw_surface_create_texture(object);
+        ddraw_surface_create_texture(object, flags);
 
     return hr;
 }
@@ -4426,7 +4425,7 @@ static HRESULT WINAPI d3d7_EnumZBufferFormats(IDirect3D7 *iface, REFCLSID device
 
             memset(&pformat, 0, sizeof(pformat));
             pformat.dwSize = sizeof(pformat);
-            PixelFormat_WineD3DtoDD(&pformat, formats[i]);
+            ddrawformat_from_wined3dformat(&pformat, formats[i]);
 
             TRACE("Enumerating wined3d format %#x.\n", formats[i]);
             hr = callback(&pformat, context);
@@ -4492,7 +4491,7 @@ static HRESULT WINAPI d3d7_EvictManagedTextures(IDirect3D7 *iface)
     TRACE("iface %p!\n", iface);
 
     wined3d_mutex_lock();
-    if (ddraw->d3d_initialized)
+    if (ddraw->flags & DDRAW_D3D_INITIALIZED)
         wined3d_device_evict_managed_resources(ddraw->wined3d_device);
     wined3d_mutex_unlock();
 
@@ -5120,8 +5119,8 @@ static void CDECL device_parent_mode_changed(struct wined3d_device_parent *devic
 }
 
 static HRESULT CDECL device_parent_create_texture_surface(struct wined3d_device_parent *device_parent,
-        void *container_parent, UINT width, UINT height, enum wined3d_format_id format, DWORD usage,
-        enum wined3d_pool pool, UINT sub_resource_idx, struct wined3d_surface **surface)
+        void *container_parent, const struct wined3d_resource_desc *wined3d_desc, UINT sub_resource_idx,
+        DWORD flags, struct wined3d_surface **surface)
 {
     struct ddraw *ddraw = ddraw_from_device_parent(device_parent);
     struct ddraw_surface *tex_root = container_parent;
@@ -5129,9 +5128,8 @@ static HRESULT CDECL device_parent_create_texture_surface(struct wined3d_device_
     struct ddraw_surface *ddraw_surface;
     HRESULT hr;
 
-    TRACE("device_parent %p, container_parent %p, width %u, height %u, format %#x, usage %#x,\n"
-            "\tpool %#x, sub_resource_idx %u, surface %p.\n",
-            device_parent, container_parent, width, height, format, usage, pool, sub_resource_idx, surface);
+    TRACE("device_parent %p, container_parent %p, wined3d_desc %p, sub_resource_idx %u, flags %#x, surface %p.\n",
+            device_parent, container_parent, wined3d_desc, sub_resource_idx, flags, surface);
 
     /* The ddraw root surface is created before the wined3d texture. */
     if (!sub_resource_idx)
@@ -5140,11 +5138,11 @@ static HRESULT CDECL device_parent_create_texture_surface(struct wined3d_device_
         goto done;
     }
 
-    desc.dwWidth = width;
-    desc.dwHeight = height;
+    desc.dwWidth = wined3d_desc->width;
+    desc.dwHeight = wined3d_desc->height;
 
     /* FIXME: Validate that format, usage, pool, etc. really make sense. */
-    if (FAILED(hr = ddraw_create_surface(ddraw, &desc, &ddraw_surface, tex_root->version)))
+    if (FAILED(hr = ddraw_create_surface(ddraw, &desc, flags, &ddraw_surface, tex_root->version)))
         return hr;
 
 done:
@@ -5166,16 +5164,13 @@ static const struct wined3d_parent_ops ddraw_frontbuffer_parent_ops =
 };
 
 static HRESULT CDECL device_parent_create_swapchain_surface(struct wined3d_device_parent *device_parent,
-        void *container_parent, UINT width, UINT height, enum wined3d_format_id format_id, DWORD usage,
-        enum wined3d_multisample_type multisample_type, DWORD multisample_quality, struct wined3d_surface **surface)
+        void *container_parent, const struct wined3d_resource_desc *desc, struct wined3d_surface **surface)
 {
     struct ddraw *ddraw = ddraw_from_device_parent(device_parent);
     HRESULT hr;
 
-    TRACE("device_parent %p, container_parent %p, width %u, height %u, format_id %#x, usage %#x,\n"
-            "\tmultisample_type %#x, multisample_quality %u, surface %p.\n",
-            device_parent, container_parent, width, height, format_id, usage,
-            multisample_type, multisample_quality, surface);
+    TRACE("device_parent %p, container_parent %p, desc %p, surface %p.\n",
+            device_parent, container_parent, desc, surface);
 
     if (ddraw->wined3d_frontbuffer)
     {
@@ -5183,8 +5178,8 @@ static HRESULT CDECL device_parent_create_swapchain_surface(struct wined3d_devic
         return E_FAIL;
     }
 
-    if (SUCCEEDED(hr = wined3d_surface_create(ddraw->wined3d_device, width, height, format_id, usage,
-            WINED3D_POOL_DEFAULT, multisample_type, multisample_quality, WINED3D_SURFACE_MAPPABLE,
+    if (SUCCEEDED(hr = wined3d_surface_create(ddraw->wined3d_device, desc->width, desc->height, desc->format,
+            desc->usage, desc->pool, desc->multisample_type, desc->multisample_quality, WINED3D_SURFACE_MAPPABLE,
             ddraw, &ddraw_frontbuffer_parent_ops, surface)))
         ddraw->wined3d_frontbuffer = *surface;
 
@@ -5192,8 +5187,9 @@ static HRESULT CDECL device_parent_create_swapchain_surface(struct wined3d_devic
 }
 
 static HRESULT CDECL device_parent_create_volume(struct wined3d_device_parent *device_parent,
-        void *container_parent, UINT width, UINT height, UINT depth, enum wined3d_format_id format,
-        enum wined3d_pool pool, DWORD usage, struct wined3d_volume **volume)
+        void *container_parent, UINT width, UINT height, UINT depth, UINT level,
+        enum wined3d_format_id format, enum wined3d_pool pool, DWORD usage,
+        struct wined3d_volume **volume)
 {
     TRACE("device_parent %p, container_parent %p, width %u, height %u, depth %u, "
             "format %#x, pool %#x, usage %#x, volume %p.\n",
@@ -5238,6 +5234,7 @@ static const struct wined3d_device_parent_ops ddraw_wined3d_device_parent_ops =
 
 HRESULT ddraw_init(struct ddraw *ddraw, enum wined3d_device_type device_type)
 {
+    WINED3DCAPS caps;
     DWORD flags;
     HRESULT hr;
 
@@ -5253,25 +5250,31 @@ HRESULT ddraw_init(struct ddraw *ddraw, enum wined3d_device_type device_type)
     ddraw->numIfaces = 1;
     ddraw->ref7 = 1;
 
-    flags = WINED3D_LEGACY_DEPTH_BIAS;
-    if (DefaultSurfaceType != DDRAW_SURFACE_TYPE_OPENGL)
-        flags |= WINED3D_NO3D;
-
+    flags = WINED3D_LEGACY_DEPTH_BIAS | WINED3D_VIDMEM_ACCOUNTING;
     if (!(ddraw->wined3d = wined3d_create(7, flags)))
     {
-        if ((flags & WINED3D_NO3D) || !(ddraw->wined3d = wined3d_create(7, flags | WINED3D_NO3D)))
+        if (!(ddraw->wined3d = wined3d_create(7, flags | WINED3D_NO3D)))
         {
             WARN("Failed to create a wined3d object.\n");
             return E_FAIL;
         }
+    }
+
+    if (FAILED(hr = wined3d_get_device_caps(ddraw->wined3d, WINED3DADAPTER_DEFAULT, device_type, &caps)))
+    {
+        ERR("Failed to get device caps, hr %#x.\n", hr);
+        wined3d_decref(ddraw->wined3d);
+        return E_FAIL;
+    }
 
+    if (!(caps.ddraw_caps.caps & WINEDDCAPS_3D))
+    {
         WARN("Created a wined3d object without 3D support.\n");
-        DefaultSurfaceType = DDRAW_SURFACE_TYPE_GDI;
+        ddraw->flags |= DDRAW_NO3D;
     }
 
-    hr = wined3d_device_create(ddraw->wined3d, WINED3DADAPTER_DEFAULT, device_type,
-            NULL, 0, 8, &ddraw->device_parent, &ddraw->wined3d_device);
-    if (FAILED(hr))
+    if (FAILED(hr = wined3d_device_create(ddraw->wined3d, WINED3DADAPTER_DEFAULT, device_type,
+            NULL, 0, DDRAW_STRIDE_ALIGNMENT, &ddraw->device_parent, &ddraw->wined3d_device)))
     {
         WARN("Failed to create a wined3d device, hr %#x.\n", hr);
         wined3d_decref(ddraw->wined3d);
index b64e178..63b0532 100644 (file)
@@ -30,7 +30,6 @@
 
 #include <winbase.h>
 #include <wingdi.h>
-#include "winuser.h"
 #include <winuser.h>
 
 #include <d3d.h>
 #include <wine/list.h>
 #include <wine/wined3d.h>
 
-enum ddraw_surface_type
-{
-    DDRAW_SURFACE_TYPE_OPENGL,
-    DDRAW_SURFACE_TYPE_GDI,
-};
-
 extern const struct wined3d_parent_ops ddraw_null_wined3d_parent_ops DECLSPEC_HIDDEN;
-extern enum ddraw_surface_type DefaultSurfaceType DECLSPEC_HIDDEN;
 extern DWORD force_refresh_rate DECLSPEC_HIDDEN;
 
 /*****************************************************************************
@@ -60,6 +52,14 @@ struct FvfToDecl
     struct wined3d_vertex_declaration *decl;
 };
 
+#define DDRAW_INITIALIZED       0x00000001
+#define DDRAW_D3D_INITIALIZED   0x00000002
+#define DDRAW_RESTORE_MODE      0x00000004
+#define DDRAW_NO3D              0x00000008
+#define DDRAW_SCL_DDRAW1        0x00000010
+
+#define DDRAW_STRIDE_ALIGNMENT  8
+
 struct ddraw
 {
     /* Interfaces */
@@ -75,12 +75,10 @@ struct ddraw
 
     /* See comment in IDirectDraw::AddRef */
     LONG                    ref7, ref4, ref2, ref3, ref1, numIfaces;
-    BOOL initialized;
 
     struct wined3d *wined3d;
     struct wined3d_device *wined3d_device;
-    BOOL d3d_initialized;
-    BOOL restore_mode;
+    DWORD flags;
 
     struct ddraw_surface *primary;
     RECT primary_lock;
@@ -187,9 +185,9 @@ struct ddraw_surface
     DWORD                   Handle;
 };
 
-HRESULT ddraw_surface_create_texture(struct ddraw_surface *surface) DECLSPEC_HIDDEN;
+HRESULT ddraw_surface_create_texture(struct ddraw_surface *surface, DWORD surface_flags) DECLSPEC_HIDDEN;
 HRESULT ddraw_surface_init(struct ddraw_surface *surface, struct ddraw *ddraw,
-        DDSURFACEDESC2 *desc, UINT version) DECLSPEC_HIDDEN;
+        DDSURFACEDESC2 *desc, DWORD flags, UINT version) DECLSPEC_HIDDEN;
 ULONG ddraw_surface_release_iface(struct ddraw_surface *This) DECLSPEC_HIDDEN;
 
 static inline struct ddraw_surface *impl_from_IDirect3DTexture(IDirect3DTexture *iface)
@@ -558,8 +556,9 @@ struct d3d_vertex_buffer *unsafe_impl_from_IDirect3DVertexBuffer7(IDirect3DVerte
 #define GET_TEXCOORD_SIZE_FROM_FVF(d3dvtVertexType, tex_num) \
     (((((d3dvtVertexType) >> (16 + (2 * (tex_num)))) + 1) & 0x03) + 1)
 
-void PixelFormat_WineD3DtoDD(DDPIXELFORMAT *DDPixelFormat, enum wined3d_format_id WineD3DFormat) DECLSPEC_HIDDEN;
-enum wined3d_format_id PixelFormat_DD2WineD3D(const DDPIXELFORMAT *DDPixelFormat) DECLSPEC_HIDDEN;
+void ddrawformat_from_wined3dformat(DDPIXELFORMAT *ddraw_format,
+        enum wined3d_format_id wined3d_format) DECLSPEC_HIDDEN;
+enum wined3d_format_id wined3dformat_from_ddrawformat(const DDPIXELFORMAT *format) DECLSPEC_HIDDEN;
 void DDRAW_dump_surface_desc(const DDSURFACEDESC2 *lpddsd) DECLSPEC_HIDDEN;
 void dump_D3DMATRIX(const D3DMATRIX *mat) DECLSPEC_HIDDEN;
 void DDRAW_dump_DDCAPS(const DDCAPS *lpcaps) DECLSPEC_HIDDEN;
index 7724c8b..8b8006c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1998-2004 Lionel Ulmer
  * Copyright (c) 2002-2005 Christian Costa
- * Copyright (c) 2006-2009, 2011-2012 Stefan Dösinger
+ * Copyright (c) 2006-2009, 2011-2013 Stefan Dösinger
  * Copyright (c) 2008 Alexander Dorofeyev
  *
  * This library is free software; you can redistribute it and/or
@@ -1111,7 +1111,7 @@ static HRESULT d3d_device7_EnumTextureFormats(IDirect3DDevice7 *iface,
 
             memset(&pformat, 0, sizeof(pformat));
             pformat.dwSize = sizeof(pformat);
-            PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
+            ddrawformat_from_wined3dformat(&pformat, FormatList[i]);
 
             TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
             hr = callback(&pformat, context);
@@ -1134,7 +1134,7 @@ static HRESULT d3d_device7_EnumTextureFormats(IDirect3DDevice7 *iface,
 
             memset(&pformat, 0, sizeof(pformat));
             pformat.dwSize = sizeof(pformat);
-            PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
+            ddrawformat_from_wined3dformat(&pformat, BumpFormatList[i]);
 
             TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
             hr = callback(&pformat, context);
@@ -1242,7 +1242,7 @@ static HRESULT WINAPI d3d_device2_EnumTextureFormats(IDirect3DDevice2 *iface,
             sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
             sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
             sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
-            PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
+            ddrawformat_from_wined3dformat(&sdesc.ddpfPixelFormat, FormatList[i]);
 
             TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
             hr = callback(&sdesc, context);
@@ -2189,43 +2189,6 @@ static HRESULT WINAPI d3d_device2_Index(IDirect3DDevice2 *iface, WORD index)
     return d3d_device3_Index(&device->IDirect3DDevice3_iface, index);
 }
 
-/*****************************************************************************
- * IDirect3DDevice3::End
- *
- * Ends a draw begun with IDirect3DDevice3::Begin or
- * IDirect3DDevice::BeginIndexed. The vertices specified with
- * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
- * the IDirect3DDevice7::DrawPrimitive method. So far only
- * non-indexed mode is supported
- *
- * Version 2 and 3
- *
- * Params:
- *  Flags: Some flags, as usual. Don't know which are defined
- *
- * Returns:
- *  The return value of IDirect3DDevice7::DrawPrimitive
- *
- *****************************************************************************/
-static HRESULT WINAPI d3d_device3_End(IDirect3DDevice3 *iface, DWORD flags)
-{
-    struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
-
-    TRACE("iface %p, flags %#x.\n", iface, flags);
-
-    return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface, device->primitive_type,
-            device->vertex_type, device->sysmem_vertex_buffer, device->nb_vertices, device->render_flags);
-}
-
-static HRESULT WINAPI d3d_device2_End(IDirect3DDevice2 *iface, DWORD flags)
-{
-    struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
-
-    TRACE("iface %p, flags %#x.\n", iface, flags);
-
-    return d3d_device3_End(&device->IDirect3DDevice3_iface, flags);
-}
-
 /*****************************************************************************
  * IDirect3DDevice7::GetRenderState
  *
@@ -2463,7 +2426,7 @@ static HRESULT WINAPI d3d_device3_GetRenderState(IDirect3DDevice3 *iface,
 
                         wined3d_resource_get_desc(sub_resource, &desc);
                         ddfmt.dwSize = sizeof(ddfmt);
-                        PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
+                        ddrawformat_from_wined3dformat(&ddfmt, desc.format);
                         if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
                     }
                 }
@@ -2482,6 +2445,10 @@ static HRESULT WINAPI d3d_device3_GetRenderState(IDirect3DDevice3 *iface,
             return D3D_OK;
         }
 
+        case D3DRENDERSTATE_LIGHTING:
+            *value = 0xffffffff;
+            return D3D_OK;
+
         default:
             return IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, state, value);
     }
@@ -2752,7 +2719,7 @@ static HRESULT WINAPI d3d_device3_SetRenderState(IDirect3DDevice3 *iface,
 
                             wined3d_resource_get_desc(sub_resource, &desc);
                             ddfmt.dwSize = sizeof(ddfmt);
-                            PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
+                            ddrawformat_from_wined3dformat(&ddfmt, desc.format);
                             if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
                         }
                     }
@@ -2837,6 +2804,10 @@ static HRESULT WINAPI d3d_device3_SetRenderState(IDirect3DDevice3 *iface,
             break;
         }
 
+        case D3DRENDERSTATE_LIGHTING:
+            hr = D3D_OK;
+            break;
+
         default:
             hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, state, value);
             break;
@@ -3512,6 +3483,22 @@ static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *if
     return hr;
 }
 
+static void setup_lighting(const struct d3d_device *device, DWORD fvf, DWORD flags)
+{
+    BOOL enable;
+
+    /* Ignore the D3DFVF_XYZRHW case here, wined3d takes care of that */
+    if (flags & D3DDP_DONOTLIGHT)
+        enable = FALSE;
+    else if (!(fvf & D3DFVF_NORMAL))
+        enable = FALSE;
+    else
+        enable = TRUE;
+
+    wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_LIGHTING, enable);
+}
+
+
 static HRESULT WINAPI d3d_device3_DrawPrimitive(IDirect3DDevice3 *iface,
         D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
         DWORD flags)
@@ -3521,6 +3508,8 @@ static HRESULT WINAPI d3d_device3_DrawPrimitive(IDirect3DDevice3 *iface,
     TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
             iface, primitive_type, fvf, vertices, vertex_count, flags);
 
+    setup_lighting(device, fvf, flags);
+
     return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
             primitive_type, fvf, vertices, vertex_count, flags);
 }
@@ -3545,7 +3534,7 @@ static HRESULT WINAPI d3d_device2_DrawPrimitive(IDirect3DDevice2 *iface,
             return DDERR_INVALIDPARAMS;  /* Should never happen */
     }
 
-    return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
+    return d3d_device3_DrawPrimitive(&device->IDirect3DDevice3_iface,
             primitive_type, fvf, vertices, vertex_count, flags);
 }
 
@@ -3703,6 +3692,8 @@ static HRESULT WINAPI d3d_device3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
             "indices %p, index_count %u, flags %#x.\n",
             iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
 
+    setup_lighting(device, fvf, flags);
+
     return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
             primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
 }
@@ -3728,10 +3719,47 @@ static HRESULT WINAPI d3d_device2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
             return DDERR_INVALIDPARAMS;  /* Should never happen */
     }
 
-    return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
+    return d3d_device3_DrawIndexedPrimitive(&device->IDirect3DDevice3_iface,
             primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
 }
 
+/*****************************************************************************
+ * IDirect3DDevice3::End
+ *
+ * Ends a draw begun with IDirect3DDevice3::Begin or
+ * IDirect3DDevice::BeginIndexed. The vertices specified with
+ * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
+ * the IDirect3DDevice3::DrawPrimitive method. So far only
+ * non-indexed mode is supported
+ *
+ * Version 2 and 3
+ *
+ * Params:
+ *  Flags: Some flags, as usual. Don't know which are defined
+ *
+ * Returns:
+ *  The return value of IDirect3DDevice3::DrawPrimitive
+ *
+ *****************************************************************************/
+static HRESULT WINAPI d3d_device3_End(IDirect3DDevice3 *iface, DWORD flags)
+{
+    struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
+
+    TRACE("iface %p, flags %#x.\n", iface, flags);
+
+    return d3d_device3_DrawPrimitive(&device->IDirect3DDevice3_iface, device->primitive_type,
+            device->vertex_type, device->sysmem_vertex_buffer, device->nb_vertices, device->render_flags);
+}
+
+static HRESULT WINAPI d3d_device2_End(IDirect3DDevice2 *iface, DWORD flags)
+{
+    struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
+
+    TRACE("iface %p, flags %#x.\n", iface, flags);
+
+    return d3d_device3_End(&device->IDirect3DDevice3_iface, flags);
+}
+
 /*****************************************************************************
  * IDirect3DDevice7::SetClipStatus
  *
@@ -3972,6 +4000,8 @@ static HRESULT WINAPI d3d_device3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
     TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
             iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
 
+    setup_lighting(device, VertexType, Flags);
+
     return IDirect3DDevice7_DrawPrimitiveStrided(&device->IDirect3DDevice7_iface,
             PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
 }
@@ -4097,6 +4127,8 @@ static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *
     TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
             iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
 
+    setup_lighting(device, VertexType, Flags);
+
     return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&device->IDirect3DDevice7_iface,
             PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
 }
@@ -4189,6 +4221,8 @@ static HRESULT WINAPI d3d_device3_DrawPrimitiveVB(IDirect3DDevice3 *iface, D3DPR
     TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
             iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
 
+    setup_lighting(device, vb->fvf, Flags);
+
     return IDirect3DDevice7_DrawPrimitiveVB(&device->IDirect3DDevice7_iface,
             PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
 }
@@ -4320,6 +4354,8 @@ static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface
     TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
             iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
 
+    setup_lighting(device, vb->fvf, Flags);
+
     return IDirect3DDevice7_DrawIndexedPrimitiveVB(&device->IDirect3DDevice7_iface, PrimitiveType,
             &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount, Flags);
 }
@@ -4355,7 +4391,7 @@ static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVE
 {
     float distance, norm;
 
-    norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
+    norm = sqrtf(normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z);
     distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
 
     if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
@@ -4616,7 +4652,7 @@ static HRESULT WINAPI d3d_device3_SetTexture(IDirect3DDevice3 *iface,
 
                 wined3d_resource_get_desc(sub_resource, &desc);
                 ddfmt.dwSize = sizeof(ddfmt);
-                PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
+                ddrawformat_from_wined3dformat(&ddfmt, desc.format);
                 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
             }
         }
@@ -6728,6 +6764,8 @@ static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw,
             d3d_device_update_depth_stencil(device));
     if (version == 1) /* Color keying is initially enabled for version 1 devices. */
         wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_COLORKEYENABLE, TRUE);
+    else if (version == 2)
+        wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_SPECULARENABLE, TRUE);
 
     return D3D_OK;
 }
@@ -6741,7 +6779,7 @@ HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target,
     TRACE("ddraw %p, target %p, version %u, device %p, outer_unknown %p.\n",
             ddraw, target, version, device, outer_unknown);
 
-    if (DefaultSurfaceType != DDRAW_SURFACE_TYPE_OPENGL)
+    if (ddraw->flags & DDRAW_NO3D)
     {
         ERR_(winediag)("The application wants to create a Direct3D device, "
                 "but the current DirectDrawRenderer does not support this.\n");
index 7c7cd73..696db49 100644 (file)
@@ -381,11 +381,10 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
                            dst->u7.tu  = src->u7.tu;
                            dst->u8.tv  = src->u8.tv;
 
-                           /* Now, the matrix multiplication */
-                           dst->u1.sx = (src->u1.x * mat._11) + (src->u2.y * mat._21) + (src->u3.z * mat._31) + (1.0 * mat._41);
-                           dst->u2.sy = (src->u1.x * mat._12) + (src->u2.y * mat._22) + (src->u3.z * mat._32) + (1.0 * mat._42);
-                           dst->u3.sz = (src->u1.x * mat._13) + (src->u2.y * mat._23) + (src->u3.z * mat._33) + (1.0 * mat._43);
-                           dst->u4.rhw = (src->u1.x * mat._14) + (src->u2.y * mat._24) + (src->u3.z * mat._34) + (1.0 * mat._44);
+                            dst->u1.sx = (src->u1.x * mat._11) + (src->u2.y * mat._21) + (src->u3.z * mat._31) + mat._41;
+                            dst->u2.sy = (src->u1.x * mat._12) + (src->u2.y * mat._22) + (src->u3.z * mat._32) + mat._42;
+                            dst->u3.sz = (src->u1.x * mat._13) + (src->u2.y * mat._23) + (src->u3.z * mat._33) + mat._43;
+                            dst->u4.rhw = (src->u1.x * mat._14) + (src->u2.y * mat._24) + (src->u3.z * mat._34) + mat._44;
 
                            dst->u1.sx = dst->u1.sx / dst->u4.rhw * Viewport->dvScaleX
                                       + Viewport->dwX + Viewport->dwWidth / 2;
@@ -424,11 +423,10 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
                            dst->u7.tu = src->u6.tu;
                            dst->u8.tv = src->u7.tv;
 
-                           /* Now, the matrix multiplication */
-                           dst->u1.sx = (src->u1.x * mat._11) + (src->u2.y * mat._21) + (src->u3.z * mat._31) + (1.0 * mat._41);
-                           dst->u2.sy = (src->u1.x * mat._12) + (src->u2.y * mat._22) + (src->u3.z * mat._32) + (1.0 * mat._42);
-                           dst->u3.sz = (src->u1.x * mat._13) + (src->u2.y * mat._23) + (src->u3.z * mat._33) + (1.0 * mat._43);
-                           dst->u4.rhw = (src->u1.x * mat._14) + (src->u2.y * mat._24) + (src->u3.z * mat._34) + (1.0 * mat._44);
+                            dst->u1.sx = (src->u1.x * mat._11) + (src->u2.y * mat._21) + (src->u3.z * mat._31) + mat._41;
+                            dst->u2.sy = (src->u1.x * mat._12) + (src->u2.y * mat._22) + (src->u3.z * mat._32) + mat._42;
+                            dst->u3.sz = (src->u1.x * mat._13) + (src->u2.y * mat._23) + (src->u3.z * mat._33) + mat._43;
+                            dst->u4.rhw = (src->u1.x * mat._14) + (src->u2.y * mat._24) + (src->u3.z * mat._34) + mat._44;
 
                            dst->u1.sx = dst->u1.sx / dst->u4.rhw * Viewport->dvScaleX
                                       + Viewport->dwX + Viewport->dwWidth / 2;
index 1d8030a..6778b2f 100644 (file)
@@ -36,9 +36,6 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
 
-/* The configured default surface */
-enum ddraw_surface_type DefaultSurfaceType = DDRAW_SURFACE_TYPE_OPENGL;
-
 static struct list global_ddraw_list = LIST_INIT(global_ddraw_list);
 
 static HINSTANCE instance;
@@ -371,7 +368,6 @@ HRESULT WINAPI DirectDrawEnumerateA(LPDDENUMCALLBACKA callback, void *context)
 HRESULT WINAPI DirectDrawEnumerateExA(LPDDENUMCALLBACKEXA callback, void *context, DWORD flags)
 {
     struct wined3d *wined3d;
-    DWORD wined3d_flags;
 
     TRACE("callback %p, context %p, flags %#x.\n", callback, context, flags);
 
@@ -383,21 +379,16 @@ HRESULT WINAPI DirectDrawEnumerateExA(LPDDENUMCALLBACKEXA callback, void *contex
     if (flags)
         FIXME("flags 0x%08x not handled\n", flags);
 
-    wined3d_flags = WINED3D_LEGACY_DEPTH_BIAS;
-    if (DefaultSurfaceType != DDRAW_SURFACE_TYPE_OPENGL)
-        wined3d_flags |= WINED3D_NO3D;
-
     TRACE("Enumerating ddraw interfaces\n");
-    if (!(wined3d = wined3d_create(7, wined3d_flags)))
+    if (!(wined3d = wined3d_create(7, WINED3D_LEGACY_DEPTH_BIAS)))
     {
-        if ((wined3d_flags & WINED3D_NO3D) || !(wined3d = wined3d_create(7, wined3d_flags | WINED3D_NO3D)))
+        if (!(wined3d = wined3d_create(7, WINED3D_LEGACY_DEPTH_BIAS | WINED3D_NO3D)))
         {
             WARN("Failed to create a wined3d object.\n");
             return E_FAIL;
         }
 
         WARN("Created a wined3d object without 3D support.\n");
-        DefaultSurfaceType = DDRAW_SURFACE_TYPE_GDI;
     }
 
     __TRY
@@ -848,21 +839,16 @@ static inline DWORD get_config_key(HKEY defkey, HKEY appkey, const char* name, c
  * app didn't release them properly(Gothic 2, Diablo 2, Moto racer, ...)
  *
  ***********************************************************************/
-BOOL WINAPI
-DllMain(HINSTANCE hInstDLL,
-        DWORD Reason,
-        LPVOID lpv)
+BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD reason, LPVOID reserved)
 {
-    TRACE("(%p,%x,%p)\n", hInstDLL, Reason, lpv);
-    if (Reason == DLL_PROCESS_ATTACH)
+    TRACE("(%p,%x,%p)\n", hInstDLL, reason, reserved);
+    switch (reason)
+    {
+    case DLL_PROCESS_ATTACH:
     {
         static HMODULE ddraw_self;
-        char buffer[MAX_PATH+10];
-        DWORD size = sizeof(buffer);
         HKEY hkey = 0;
-        HKEY appkey = 0;
         WNDCLASSA wc;
-        DWORD len;
 
         /* Register the window class. This is used to create a hidden window
          * for D3D rendering, if the application didn't pass one. It can also
@@ -883,47 +869,6 @@ DllMain(HINSTANCE hInstDLL,
             return FALSE;
         }
 
-       /* @@ Wine registry key: HKCU\Software\Wine\Direct3D */
-       if ( RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Direct3D", &hkey ) ) hkey = 0;
-
-       len = GetModuleFileNameA( 0, buffer, MAX_PATH );
-       if (len && len < MAX_PATH)
-       {
-            HKEY tmpkey;
-            /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\Direct3D */
-            if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
-            {
-                char *p, *appname = buffer;
-                if ((p = strrchr( appname, '/' ))) appname = p + 1;
-                if ((p = strrchr( appname, '\\' ))) appname = p + 1;
-                strcat( appname, "\\Direct3D" );
-                TRACE("appname = [%s]\n", appname);
-                if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
-                RegCloseKey( tmpkey );
-            }
-       }
-
-       if ( 0 != hkey || 0 != appkey )
-       {
-            if ( !get_config_key( hkey, appkey, "DirectDrawRenderer", buffer, size) )
-            {
-                if (!strcmp(buffer,"gdi"))
-                {
-                    TRACE("Defaulting to GDI surfaces\n");
-                    DefaultSurfaceType = DDRAW_SURFACE_TYPE_GDI;
-                }
-                else if (!strcmp(buffer,"opengl"))
-                {
-                    TRACE("Defaulting to opengl surfaces\n");
-                    DefaultSurfaceType = DDRAW_SURFACE_TYPE_OPENGL;
-                }
-                else
-                {
-                    ERR("Unknown default surface type. Supported are:\n gdi, opengl\n");
-                }
-            }
-        }
-
         /* On Windows one can force the refresh rate that DirectDraw uses by
          * setting an override value in dxdiag.  This is documented in KB315614
          * (main article), KB230002, and KB217348.  By comparing registry dumps
@@ -946,7 +891,8 @@ DllMain(HINSTANCE hInstDLL,
          */
         if ( !RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Microsoft\\DirectDraw", &hkey ) )
         {
-            DWORD type, data;
+            DWORD type, data, size;
+
             size = sizeof(data);
             if (!RegQueryValueExA( hkey, "ForceRefreshRate", NULL, &type, (LPBYTE)&data, &size ) && type == REG_DWORD)
             {
@@ -968,9 +914,10 @@ DllMain(HINSTANCE hInstDLL,
 
         instance = hInstDLL;
         DisableThreadLibraryCalls(hInstDLL);
+        break;
     }
-    else if (Reason == DLL_PROCESS_DETACH)
-    {
+
+    case DLL_PROCESS_DETACH:
         if(!list_empty(&global_ddraw_list))
         {
             struct list *entry, *entry2;
@@ -1034,7 +981,7 @@ DllMain(HINSTANCE hInstDLL,
             }
         }
 
-        /* Unregister the window class. */
+        if (reserved) break;
         UnregisterClassA(DDRAW_WINDOW_CLASS_NAME, hInstDLL);
     }
 
index 2091bd2..fb8beb0 100644 (file)
@@ -4233,7 +4233,7 @@ static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface,
             | DDSD_HEIGHT | DDSD_PITCH | DDSD_CAPS;
     enum wined3d_format_id format_id;
     BOOL update_wined3d = FALSE;
-    UINT width, height;
+    UINT pitch, width, height;
 
     TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, DDSD, Flags);
 
@@ -4293,6 +4293,7 @@ static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface,
             TRACE("Surface pitch changed from %u to %u.\n", This->surface_desc.u1.lPitch, DDSD->u1.lPitch);
             update_wined3d = TRUE;
         }
+        pitch = DDSD->u1.lPitch;
         width = DDSD->dwWidth;
     }
     else if (DDSD->dwFlags & DDSD_PITCH)
@@ -4302,6 +4303,7 @@ static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface,
     }
     else
     {
+        pitch = This->surface_desc.u1.lPitch;
         width = This->surface_desc.dwWidth;
     }
 
@@ -4328,7 +4330,7 @@ static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface,
     if (DDSD->dwFlags & DDSD_PIXELFORMAT)
     {
         enum wined3d_format_id current_format_id;
-        format_id = PixelFormat_DD2WineD3D(&DDSD->u4.ddpfPixelFormat);
+        format_id = wined3dformat_from_ddrawformat(&DDSD->u4.ddpfPixelFormat);
 
         if (format_id == WINED3DFMT_UNKNOWN)
         {
@@ -4336,7 +4338,7 @@ static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface,
             wined3d_mutex_unlock();
             return DDERR_INVALIDPARAMS;
         }
-        current_format_id = PixelFormat_DD2WineD3D(&This->surface_desc.u4.ddpfPixelFormat);
+        current_format_id = wined3dformat_from_ddrawformat(&This->surface_desc.u4.ddpfPixelFormat);
         if (format_id != current_format_id)
         {
             TRACE("Surface format changed from %#x to %#x.\n", current_format_id, format_id);
@@ -4345,7 +4347,7 @@ static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface,
     }
     else
     {
-        format_id = PixelFormat_DD2WineD3D(&This->surface_desc.u4.ddpfPixelFormat);
+        format_id = wined3dformat_from_ddrawformat(&This->surface_desc.u4.ddpfPixelFormat);
     }
 
     if (update_wined3d)
@@ -4370,8 +4372,7 @@ static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface,
 
     if (DDSD->dwFlags & DDSD_LPSURFACE && DDSD->lpSurface)
     {
-        hr = wined3d_surface_set_mem(This->wined3d_surface, DDSD->lpSurface);
-        if (FAILED(hr))
+        if (FAILED(hr = wined3d_surface_set_mem(This->wined3d_surface, DDSD->lpSurface, pitch)))
         {
             /* No need for a trace here, wined3d does that for us */
             switch(hr)
@@ -5585,12 +5586,12 @@ static const struct wined3d_parent_ops ddraw_texture_wined3d_parent_ops =
     ddraw_texture_wined3d_object_destroyed,
 };
 
-HRESULT ddraw_surface_create_texture(struct ddraw_surface *surface)
+HRESULT ddraw_surface_create_texture(struct ddraw_surface *surface, DWORD surface_flags)
 {
     const DDSURFACEDESC2 *desc = &surface->surface_desc;
+    struct wined3d_resource_desc wined3d_desc;
     struct ddraw_surface *mip, **attach;
     struct wined3d_resource *resource;
-    enum wined3d_format_id format;
     UINT layers, levels, i, j;
     DDSURFACEDESC2 *mip_desc;
     enum wined3d_pool pool;
@@ -5613,13 +5614,28 @@ HRESULT ddraw_surface_create_texture(struct ddraw_surface *surface)
     else
         pool = WINED3D_POOL_DEFAULT;
 
-    format = PixelFormat_DD2WineD3D(&surface->surface_desc.u4.ddpfPixelFormat);
+    wined3d_desc.format = wined3dformat_from_ddrawformat(&surface->surface_desc.u4.ddpfPixelFormat);
+    wined3d_desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
+    wined3d_desc.multisample_quality = 0;
+    wined3d_desc.usage = 0;
+    wined3d_desc.pool = pool;
+    wined3d_desc.width = desc->dwWidth;
+    wined3d_desc.height = desc->dwHeight;
+    wined3d_desc.depth = 1;
+    wined3d_desc.size = 0;
+
     if (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
-        hr = wined3d_texture_create_cube(surface->ddraw->wined3d_device, desc->dwWidth,
-                levels, 0, format, pool, surface, &ddraw_texture_wined3d_parent_ops, &surface->wined3d_texture);
+    {
+        wined3d_desc.resource_type = WINED3D_RTYPE_CUBE_TEXTURE;
+        hr = wined3d_texture_create_cube(surface->ddraw->wined3d_device, &wined3d_desc, levels,
+                surface_flags, surface, &ddraw_texture_wined3d_parent_ops, &surface->wined3d_texture);
+    }
     else
-        hr = wined3d_texture_create_2d(surface->ddraw->wined3d_device, desc->dwWidth, desc->dwHeight,
-                levels, 0, format, pool, surface, &ddraw_texture_wined3d_parent_ops, &surface->wined3d_texture);
+    {
+        wined3d_desc.resource_type = WINED3D_RTYPE_TEXTURE;
+        hr = wined3d_texture_create_2d(surface->ddraw->wined3d_device, &wined3d_desc, levels,
+                surface_flags, surface, &ddraw_texture_wined3d_parent_ops, &surface->wined3d_texture);
+    }
 
     if (FAILED(hr))
     {
@@ -5682,10 +5698,10 @@ HRESULT ddraw_surface_create_texture(struct ddraw_surface *surface)
     return DD_OK;
 }
 
-HRESULT ddraw_surface_init(struct ddraw_surface *surface, struct ddraw *ddraw, DDSURFACEDESC2 *desc, UINT version)
+HRESULT ddraw_surface_init(struct ddraw_surface *surface, struct ddraw *ddraw,
+        DDSURFACEDESC2 *desc, DWORD flags, UINT version)
 {
     enum wined3d_pool pool = WINED3D_POOL_DEFAULT;
-    DWORD flags = WINED3D_SURFACE_MAPPABLE;
     enum wined3d_format_id format;
     DWORD usage = 0;
     HRESULT hr;
@@ -5699,13 +5715,6 @@ HRESULT ddraw_surface_init(struct ddraw_surface *surface, struct ddraw *ddraw, D
         desc->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY;
     }
 
-    /* Some applications assume surfaces will always be mapped at the same
-     * address. Some of those also assume that this address is valid even when
-     * the surface isn't mapped, and that updates done this way will be
-     * visible on the screen. The game Nox is such an application,
-     * Commandos: Behind Enemy Lines is another. */
-    flags |= WINED3D_SURFACE_PIN_SYSMEM;
-
     if (desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
     {
         usage |= WINED3DUSAGE_RENDERTARGET;
@@ -5745,7 +5754,7 @@ HRESULT ddraw_surface_init(struct ddraw_surface *surface, struct ddraw *ddraw, D
         desc->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM;
     }
 
-    format = PixelFormat_DD2WineD3D(&desc->u4.ddpfPixelFormat);
+    format = wined3dformat_from_ddrawformat(&desc->u4.ddpfPixelFormat);
     if (format == WINED3DFMT_UNKNOWN)
     {
         WARN("Unsupported / unknown pixelformat.\n");
@@ -5835,8 +5844,15 @@ HRESULT ddraw_surface_init(struct ddraw_surface *surface, struct ddraw *ddraw, D
     }
     if (desc->dwFlags & DDSD_LPSURFACE)
     {
-        hr = wined3d_surface_set_mem(surface->wined3d_surface, desc->lpSurface);
-        if (FAILED(hr))
+        UINT pitch = 0;
+
+        if (desc->dwFlags & DDSD_PITCH)
+        {
+            pitch = desc->u1.lPitch;
+            surface->surface_desc.u1.lPitch = pitch;
+        }
+
+        if (FAILED(hr = wined3d_surface_set_mem(surface->wined3d_surface, desc->lpSurface, pitch)))
         {
             ERR("Failed to set surface memory, hr %#x.\n", hr);
             wined3d_surface_decref(surface->wined3d_surface);
index 74e35dd..6308ee5 100644 (file)
@@ -30,26 +30,15 @@ WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
 
 static void DDRAW_dump_pixelformat(const DDPIXELFORMAT *pf);
 
-/*****************************************************************************
- * PixelFormat_WineD3DtoDD
- *
- * Converts an wined3d format ID into a DDPIXELFORMAT structure
- *
- * Params:
- *  DDPixelFormat: Address of the structure to write the pixel format to
- *  WineD3DFormat: Source format
- *
- *****************************************************************************/
-void PixelFormat_WineD3DtoDD(DDPIXELFORMAT *DDPixelFormat, enum wined3d_format_id WineD3DFormat)
+void ddrawformat_from_wined3dformat(DDPIXELFORMAT *DDPixelFormat, enum wined3d_format_id wined3d_format)
 {
     DWORD Size = DDPixelFormat->dwSize;
-    TRACE("Converting wined3d format %#x to DDRAW.\n", WineD3DFormat);
 
     if(Size==0) return;
 
     memset(DDPixelFormat, 0x00, Size);
     DDPixelFormat->dwSize = Size;
-    switch(WineD3DFormat)
+    switch (wined3d_format)
     {
         case WINED3DFMT_B8G8R8_UNORM:
             DDPixelFormat->dwFlags = DDPF_RGB;
@@ -247,13 +236,13 @@ void PixelFormat_WineD3DtoDD(DDPIXELFORMAT *DDPixelFormat, enum wined3d_format_i
         case WINED3DFMT_YUY2:
             DDPixelFormat->u1.dwYUVBitCount = 16;
             DDPixelFormat->dwFlags = DDPF_FOURCC;
-            DDPixelFormat->dwFourCC = WineD3DFormat;
+            DDPixelFormat->dwFourCC = wined3d_format;
             break;
 
         case WINED3DFMT_YV12:
             DDPixelFormat->u1.dwYUVBitCount = 12;
             DDPixelFormat->dwFlags = DDPF_FOURCC;
-            DDPixelFormat->dwFourCC = WineD3DFormat;
+            DDPixelFormat->dwFourCC = wined3d_format;
             break;
 
         case WINED3DFMT_DXT1:
@@ -265,7 +254,7 @@ void PixelFormat_WineD3DtoDD(DDPIXELFORMAT *DDPixelFormat, enum wined3d_format_i
         case WINED3DFMT_G8R8_G8B8:
         case WINED3DFMT_R8G8_B8G8:
             DDPixelFormat->dwFlags = DDPF_FOURCC;
-            DDPixelFormat->dwFourCC = WineD3DFormat;
+            DDPixelFormat->dwFourCC = wined3d_format;
             break;
 
         /* Luminance */
@@ -341,7 +330,8 @@ void PixelFormat_WineD3DtoDD(DDPIXELFORMAT *DDPixelFormat, enum wined3d_format_i
             break;
 
         default:
-            ERR("Can't translate this Pixelformat %d\n", WineD3DFormat);
+            FIXME("Unhandled wined3d format %#x.\n", wined3d_format);
+            break;
     }
 
     if(TRACE_ON(ddraw)) {
@@ -349,20 +339,8 @@ void PixelFormat_WineD3DtoDD(DDPIXELFORMAT *DDPixelFormat, enum wined3d_format_i
         DDRAW_dump_pixelformat(DDPixelFormat);
     }
 }
-/*****************************************************************************
- * PixelFormat_DD2WineD3D
- *
- * Reads a DDPIXELFORMAT structure and returns the equivalent wined3d
- * format ID.
- *
- * Params:
- *  DDPixelFormat: The source format
- *
- * Returns:
- *  The wined3d format ID equivalent to the DDraw format
- *  WINED3DFMT_UNKNOWN if a matching format wasn't found
- *****************************************************************************/
-enum wined3d_format_id PixelFormat_DD2WineD3D(const DDPIXELFORMAT *DDPixelFormat)
+
+enum wined3d_format_id wined3dformat_from_ddrawformat(const DDPIXELFORMAT *DDPixelFormat)
 {
     TRACE("Convert a DirectDraw Pixelformat to a WineD3D Pixelformat\n");
     if(TRACE_ON(ddraw))
index 22365c8..38bd21d 100644 (file)
@@ -428,10 +428,10 @@ static HRESULT WINAPI d3d_viewport_TransformVertices(IDirect3DViewport3 *iface,
     outH = lpData->lpHOut;
     for(i = 0; i < dwVertexCount; i++)
     {
-        x = (in[0] * mat._11) + (in[1] * mat._21) + (in[2] * mat._31) + (1.0 * mat._41);
-        y = (in[0] * mat._12) + (in[1] * mat._22) + (in[2] * mat._32) + (1.0 * mat._42);
-        z = (in[0] * mat._13) + (in[1] * mat._23) + (in[2] * mat._33) + (1.0 * mat._43);
-        w = (in[0] * mat._14) + (in[1] * mat._24) + (in[2] * mat._34) + (1.0 * mat._44);
+        x = (in[0] * mat._11) + (in[1] * mat._21) + (in[2] * mat._31) + mat._41;
+        y = (in[0] * mat._12) + (in[1] * mat._22) + (in[2] * mat._32) + mat._42;
+        z = (in[0] * mat._13) + (in[1] * mat._23) + (in[2] * mat._33) + mat._43;
+        w = (in[0] * mat._14) + (in[1] * mat._24) + (in[2] * mat._34) + mat._44;
 
         if(dwFlags & D3DTRANSFORM_CLIPPED)
         {
index b5ac102..ad4913c 100644 (file)
@@ -38,28 +38,9 @@ list(APPEND SOURCE
     wined3d_main.c
     ${CMAKE_CURRENT_BINARY_DIR}/wined3d.def)
 
-add_library(wined3d SHARED
-    ${SOURCE}
-    version.rc)
+add_library(wined3d SHARED ${SOURCE} version.rc)
 set_module_type(wined3d win32dll)
-
 target_link_libraries(wined3d wine)
-
-add_importlibs(wined3d
-    user32
-    opengl32
-    gdi32
-    advapi32
-    msvcrt
-    kernel32
-    ntdll)
-
-add_dependencies(wined3d wineheaders)
+add_importlibs(wined3d user32 opengl32 gdi32 advapi32 msvcrt kernel32 ntdll)
 add_pch(wined3d wined3d_private.h)
 add_cd_file(TARGET wined3d DESTINATION reactos/system32 FOR all)
-
-if(NOT MSVC)
-    # FIXME: http://www.cmake.org/Bug/view.php?id=12998
-    #allow_warnings(wined3d)
-    set_source_files_properties(${SOURCE} PROPERTIES COMPILE_FLAGS "-Wno-error")
-endif()
index 885d064..caa18dc 100644 (file)
@@ -9,7 +9,7 @@
  * Copyright 2006 Ivan Gyurdiev
  * Copyright 2006 Jason Green
  * Copyright 2006 Henri Verbeet
- * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
+ * Copyright 2007-2011, 2013 Stefan Dösinger for CodeWeavers
  * Copyright 2009 Henri Verbeet for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
@@ -39,6 +39,13 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
 WINE_DECLARE_DEBUG_CHANNEL(d3d_constants);
 WINE_DECLARE_DEBUG_CHANNEL(d3d);
 
+/* sRGB correction constants */
+static const float srgb_cmp = 0.0031308f;
+static const float srgb_mul_low = 12.92f;
+static const float srgb_pow = 0.41666f;
+static const float srgb_mul_high = 1.055f;
+static const float srgb_sub_high = 0.055f;
+
 static BOOL shader_is_pshader_version(enum wined3d_shader_type type)
 {
     return type == WINED3D_SHADER_TYPE_PIXEL;
@@ -271,6 +278,7 @@ struct shader_arb_ctx_priv
     BOOL                                muted;
     unsigned int                        num_loops, loop_depth, num_ifcs;
     int                                 aL;
+    BOOL                                ps_post_process;
 
     unsigned int                        vs_clipplanes;
     BOOL                                footer_written;
@@ -327,6 +335,7 @@ struct shader_arb_priv
     char *vshader_const_dirty, *pshader_const_dirty;
     const struct wined3d_context *last_context;
 
+    const struct wined3d_vertex_pipe_ops *vertex_pipe;
     const struct fragment_pipeline *fragment_pipe;
     BOOL ffp_proj_control;
 };
@@ -496,53 +505,50 @@ static unsigned int shader_arb_load_constantsF(const struct wined3d_shader *shad
     }
 }
 
-/**
- * Loads the texture dimensions for NP2 fixup into the currently set ARB_[vertex/fragment]_programs.
- */
-static void shader_arb_load_np2fixup_constants(void *shader_priv,
+/* Loads the texture dimensions for NP2 fixup into the currently set
+ * ARB_[vertex/fragment]_programs. */
+static void shader_arb_load_np2fixup_constants(const struct arb_ps_np2fixup_info *fixup,
         const struct wined3d_gl_info *gl_info, const struct wined3d_state *state)
 {
-    const struct shader_arb_priv * priv = shader_priv;
-
-    /* NP2 texcoord fixup is (currently) only done for pixelshaders. */
-    if (!use_ps(state)) return;
-
-    if (priv->compiled_fprog && priv->compiled_fprog->np2fixup_info.super.active) {
-        const struct arb_ps_np2fixup_info* const fixup = &priv->compiled_fprog->np2fixup_info;
-        UINT i;
-        WORD active = fixup->super.active;
-        GLfloat np2fixup_constants[4 * MAX_FRAGMENT_SAMPLERS];
+    GLfloat np2fixup_constants[4 * MAX_FRAGMENT_SAMPLERS];
+    WORD active = fixup->super.active;
+    UINT i;
 
-        for (i = 0; active; active >>= 1, ++i)
-        {
-            const struct wined3d_texture *tex = state->textures[i];
-            const unsigned char idx = fixup->super.idx[i];
-            GLfloat *tex_dim = &np2fixup_constants[(idx >> 1) * 4];
+    if (!active)
+        return;
 
-            if (!(active & 1)) continue;
+    for (i = 0; active; active >>= 1, ++i)
+    {
+        const struct wined3d_texture *tex = state->textures[i];
+        unsigned char idx = fixup->super.idx[i];
+        GLfloat *tex_dim = &np2fixup_constants[(idx >> 1) * 4];
 
-            if (!tex) {
-                FIXME("Nonexistent texture is flagged for NP2 texcoord fixup\n");
-                continue;
-            }
+        if (!(active & 1))
+            continue;
 
-            if (idx % 2)
-            {
-                tex_dim[2] = tex->pow2_matrix[0];
-                tex_dim[3] = tex->pow2_matrix[5];
-            }
-            else
-            {
-                tex_dim[0] = tex->pow2_matrix[0];
-                tex_dim[1] = tex->pow2_matrix[5];
-            }
+        if (!tex)
+        {
+            ERR("Nonexistent texture is flagged for NP2 texcoord fixup.\n");
+            continue;
         }
 
-        for (i = 0; i < fixup->super.num_consts; ++i) {
-            GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB,
-                                                   fixup->offset + i, &np2fixup_constants[i * 4]));
+        if (idx % 2)
+        {
+            tex_dim[2] = tex->pow2_matrix[0];
+            tex_dim[3] = tex->pow2_matrix[5];
+        }
+        else
+        {
+            tex_dim[0] = tex->pow2_matrix[0];
+            tex_dim[1] = tex->pow2_matrix[5];
         }
     }
+
+    for (i = 0; i < fixup->super.num_consts; ++i)
+    {
+        GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB,
+                fixup->offset + i, &np2fixup_constants[i * 4]));
+    }
 }
 
 /* Context activation is done by the caller. */
@@ -639,8 +645,8 @@ static void shader_arb_vs_local_constants(const struct arb_vs_compiled_shader *g
     checkGLcall("Load vs int consts");
 }
 
-static void shader_arb_select(const struct wined3d_context *context, enum wined3d_shader_mode vertex_mode,
-        enum wined3d_shader_mode fragment_mode);
+static void shader_arb_select(void *shader_priv, struct wined3d_context *context,
+        const struct wined3d_state *state);
 
 /**
  * Loads the app-supplied constants into the currently set ARB_[vertex/fragment]_programs.
@@ -649,51 +655,43 @@ static void shader_arb_select(const struct wined3d_context *context, enum wined3
  * worry about the Integers or Booleans
  */
 /* Context activation is done by the caller (state handler). */
-static void shader_arb_load_constants_internal(const struct wined3d_context *context,
+static void shader_arb_load_constants_internal(struct shader_arb_priv *priv,
+        struct wined3d_context *context, const struct wined3d_state *state,
         BOOL usePixelShader, BOOL useVertexShader, BOOL from_shader_select)
 {
-    struct wined3d_device *device = context->swapchain->device;
-    const struct wined3d_stateblock *stateblock = device->stateBlock;
-    const struct wined3d_state *state = &stateblock->state;
+    const struct wined3d_d3d_info *d3d_info = context->d3d_info;
     const struct wined3d_gl_info *gl_info = context->gl_info;
-    struct shader_arb_priv *priv = device->shader_priv;
 
     if (!from_shader_select)
     {
         const struct wined3d_shader *vshader = state->vertex_shader, *pshader = state->pixel_shader;
         if (vshader
-                && (stateblock->changed.vertexShaderConstantsB & vshader->reg_maps.boolean_constants
+                && (vshader->reg_maps.boolean_constants
                 || (!gl_info->supported[NV_VERTEX_PROGRAM2_OPTION]
-                && (stateblock->changed.vertexShaderConstantsI
-                & vshader->reg_maps.integer_constants & ~vshader->reg_maps.local_int_consts))))
+                && (vshader->reg_maps.integer_constants & ~vshader->reg_maps.local_int_consts))))
         {
             TRACE("bool/integer vertex shader constants potentially modified, forcing shader reselection.\n");
-            shader_arb_select(context,
-                    useVertexShader ? WINED3D_SHADER_MODE_SHADER : WINED3D_SHADER_MODE_FFP,
-                    usePixelShader ? WINED3D_SHADER_MODE_SHADER : WINED3D_SHADER_MODE_FFP);
+            shader_arb_select(priv, context, state);
         }
         else if (pshader
-                && (stateblock->changed.pixelShaderConstantsB & pshader->reg_maps.boolean_constants
+                && (pshader->reg_maps.boolean_constants
                 || (!gl_info->supported[NV_FRAGMENT_PROGRAM_OPTION]
-                && (stateblock->changed.pixelShaderConstantsI
-                & pshader->reg_maps.integer_constants & ~pshader->reg_maps.local_int_consts))))
+                && (pshader->reg_maps.integer_constants & ~pshader->reg_maps.local_int_consts))))
         {
             TRACE("bool/integer pixel shader constants potentially modified, forcing shader reselection.\n");
-            shader_arb_select(context,
-                    useVertexShader ? WINED3D_SHADER_MODE_SHADER : WINED3D_SHADER_MODE_FFP,
-                    usePixelShader ? WINED3D_SHADER_MODE_SHADER : WINED3D_SHADER_MODE_FFP);
+            shader_arb_select(priv, context, state);
         }
     }
 
     if (context != priv->last_context)
     {
         memset(priv->vshader_const_dirty, 1,
-                sizeof(*priv->vshader_const_dirty) * device->d3d_vshader_constantF);
-        priv->highest_dirty_vs_const = device->d3d_vshader_constantF;
+                sizeof(*priv->vshader_const_dirty) * d3d_info->limits.vs_uniform_count);
+        priv->highest_dirty_vs_const = d3d_info->limits.vs_uniform_count;
 
         memset(priv->pshader_const_dirty, 1,
-                sizeof(*priv->pshader_const_dirty) * device->d3d_pshader_constantF);
-        priv->highest_dirty_ps_const = device->d3d_pshader_constantF;
+                sizeof(*priv->pshader_const_dirty) * d3d_info->limits.ps_uniform_count);
+        priv->highest_dirty_ps_const = d3d_info->limits.ps_uniform_count;
 
         priv->last_context = context;
     }
@@ -719,18 +717,31 @@ static void shader_arb_load_constants_internal(const struct wined3d_context *con
         priv->highest_dirty_ps_const = shader_arb_load_constantsF(pshader, gl_info, GL_FRAGMENT_PROGRAM_ARB,
                 priv->highest_dirty_ps_const, state->ps_consts_f, priv->pshader_const_dirty);
         shader_arb_ps_local_constants(gl_shader, context, state, rt_height);
+
+        if (context->constant_update_mask & WINED3D_SHADER_CONST_PS_NP2_FIXUP)
+            shader_arb_load_np2fixup_constants(&gl_shader->np2fixup_info, gl_info, state);
     }
 }
 
-static void shader_arb_load_constants(const struct wined3d_context *context, BOOL ps, BOOL vs)
+static void shader_arb_load_constants(void *shader_priv, struct wined3d_context *context,
+        const struct wined3d_state *state)
 {
-    shader_arb_load_constants_internal(context, ps, vs, FALSE);
+    BOOL vs = use_vs(state);
+    BOOL ps = use_ps(state);
+
+    shader_arb_load_constants_internal(shader_priv, context, state, ps, vs, FALSE);
 }
 
 static void shader_arb_update_float_vertex_constants(struct wined3d_device *device, UINT start, UINT count)
 {
     struct wined3d_context *context = context_get_current();
     struct shader_arb_priv *priv = device->shader_priv;
+    unsigned int i;
+
+    for (i = 0; i < device->context_count; ++i)
+    {
+        device->contexts[i]->constant_update_mask |= WINED3D_SHADER_CONST_VS_F;
+    }
 
     /* We don't want shader constant dirtification to be an O(contexts), so just dirtify the active
      * context. On a context switch the old context will be fully dirtified */
@@ -744,6 +755,12 @@ static void shader_arb_update_float_pixel_constants(struct wined3d_device *devic
 {
     struct wined3d_context *context = context_get_current();
     struct shader_arb_priv *priv = device->shader_priv;
+    unsigned int i;
+
+    for (i = 0; i < device->context_count; ++i)
+    {
+        device->contexts[i]->constant_update_mask |= WINED3D_SHADER_CONST_PS_F;
+    }
 
     /* We don't want shader constant dirtification to be an O(contexts), so just dirtify the active
      * context. On a context switch the old context will be fully dirtified */
@@ -753,36 +770,13 @@ static void shader_arb_update_float_pixel_constants(struct wined3d_device *devic
     priv->highest_dirty_ps_const = max(priv->highest_dirty_ps_const, start + count);
 }
 
-static DWORD *local_const_mapping(const struct wined3d_shader *shader)
-{
-    const struct wined3d_shader_lconst *lconst;
-    DWORD *ret;
-    DWORD idx = 0;
-
-    if (shader->load_local_constsF || list_empty(&shader->constantsF))
-        return NULL;
-
-    ret = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD) * shader->limits.constant_float);
-    if (!ret)
-    {
-        ERR("Out of memory\n");
-        return NULL;
-    }
-
-    LIST_FOR_EACH_ENTRY(lconst, &shader->constantsF, struct wined3d_shader_lconst, entry)
-    {
-        ret[lconst->idx] = idx++;
-    }
-    return ret;
-}
-
 /* Generate the variable & register declarations for the ARB_vertex_program output target */
-static DWORD shader_generate_arb_declarations(const struct wined3d_shader *shader,
+static void shader_generate_arb_declarations(const struct wined3d_shader *shader,
         const struct wined3d_shader_reg_maps *reg_maps, struct wined3d_shader_buffer *buffer,
-        const struct wined3d_gl_info *gl_info, const DWORD *lconst_map,
-        DWORD *num_clipplanes, const struct shader_arb_ctx_priv *ctx)
+        const struct wined3d_gl_info *gl_info, DWORD *num_clipplanes,
+        const struct shader_arb_ctx_priv *ctx)
 {
-    DWORD i, next_local = 0;
+    DWORD i;
     char pshader = shader_is_pshader_version(reg_maps->shader_version.type);
     const struct wined3d_shader_lconst *lconst;
     unsigned max_constantsF;
@@ -874,16 +868,14 @@ static DWORD shader_generate_arb_declarations(const struct wined3d_shader *shade
         }
     }
 
-    /* Load local constants using the program-local space,
-     * this avoids reloading them each time the shader is used
-     */
-    if (lconst_map)
+    if (!shader->load_local_constsF)
     {
         LIST_FOR_EACH_ENTRY(lconst, &shader->constantsF, struct wined3d_shader_lconst, entry)
         {
-            shader_addline(buffer, "PARAM C%u = program.local[%u];\n", lconst->idx,
-                           lconst_map[lconst->idx]);
-            next_local = max(next_local, lconst_map[lconst->idx] + 1);
+            const float *value;
+            value = (const float *)lconst->value;
+            shader_addline(buffer, "PARAM C%u = {%.8e, %.8e, %.8e, %.8e};\n", lconst->idx,
+                           value[0], value[1], value[2], value[3]);
         }
     }
 
@@ -924,8 +916,6 @@ static DWORD shader_generate_arb_declarations(const struct wined3d_shader *shade
             }
         }
     }
-
-    return next_local;
 }
 
 static const char * const shift_tab[] = {
@@ -1183,7 +1173,7 @@ static void shader_arb_get_register_name(const struct wined3d_shader_instruction
             break;
 
         case WINED3DSPR_COLOROUT:
-            if (ctx->cur_ps_args->super.srgb_correction && !reg->idx[0].offset)
+            if (ctx->ps_post_process && !reg->idx[0].offset)
             {
                 strcpy(register_name, "TMP_COLOR");
             }
@@ -1395,14 +1385,14 @@ static void shader_hw_sample(const struct wined3d_shader_instruction *ins, DWORD
 {
     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
     DWORD sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx];
-    const struct wined3d_shader *shader = ins->ctx->shader;
-    const struct wined3d_texture *texture;
     const char *tex_type;
     BOOL np2_fixup = FALSE;
-    struct wined3d_device *device = shader->device;
     struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
     const char *mod;
     BOOL pshader = shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type);
+    const struct wined3d_shader *shader;
+    const struct wined3d_device *device;
+    const struct wined3d_gl_info *gl_info;
 
     /* D3D vertex shader sampler IDs are vertex samplers(0-3), not global d3d samplers */
     if(!pshader) sampler_idx += MAX_FRAGMENT_SAMPLERS;
@@ -1413,13 +1403,15 @@ static void shader_hw_sample(const struct wined3d_shader_instruction *ins, DWORD
             break;
 
         case WINED3DSTT_2D:
-            texture = device->stateBlock->state.textures[sampler_idx];
-            if (texture && texture->target == GL_TEXTURE_RECTANGLE_ARB)
-            {
+            shader = ins->ctx->shader;
+            device = shader->device;
+            gl_info = &device->adapter->gl_info;
+
+            if (pshader && priv->cur_ps_args->super.np2_fixup & (1 << sampler_idx)
+                    && gl_info->supported[ARB_TEXTURE_RECTANGLE])
                 tex_type = "RECT";
-            } else {
+            else
                 tex_type = "2D";
-            }
             if (shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type))
             {
                 if (priv->cur_np2fixup_info->super.active & (1 << sampler_idx))
@@ -1650,8 +1642,8 @@ static void pshader_hw_cnd(const struct wined3d_shader_instruction *ins)
     shader_arb_get_dst_param(ins, dst, dst_name);
     shader_arb_get_src_param(ins, &ins->src[1], 1, src_name[1]);
 
-    /* The coissue flag changes the semantic of the cnd instruction in <= 1.3 shaders */
-    if (shader_version <= WINED3D_SHADER_VERSION(1, 3) && ins->coissue)
+    if (shader_version <= WINED3D_SHADER_VERSION(1, 3) && ins->coissue
+            && ins->dst->write_mask != WINED3DSP_WRITEMASK_3)
     {
         shader_addline(buffer, "MOV%s %s, %s;\n", shader_arb_get_modifier(ins), dst_name, src_name[1]);
     }
@@ -1871,9 +1863,9 @@ static void shader_hw_mov(const struct wined3d_shader_instruction *ins)
     }
     else if (ins->dst[0].reg.type == WINED3DSPR_COLOROUT && !ins->dst[0].reg.idx[0].offset && pshader)
     {
-        if (ctx->cur_ps_args->super.srgb_correction && shader->u.ps.color0_mov)
+        if (ctx->ps_post_process && shader->u.ps.color0_mov)
         {
-            shader_addline(buffer, "#mov handled in srgb write code\n");
+            shader_addline(buffer, "#mov handled in srgb write or fog code\n");
             return;
         }
         shader_hw_map2gl(ins);
@@ -3580,23 +3572,31 @@ static void init_ps_input(const struct wined3d_shader *shader,
     }
 }
 
+static void arbfp_add_linear_fog(struct wined3d_shader_buffer *buffer,
+        const char *fragcolor, const char *tmp)
+{
+    shader_addline(buffer, "SUB %s.x, state.fog.params.z, fragment.fogcoord.x;\n", tmp);
+    shader_addline(buffer, "MUL_SAT %s.x, %s.x, state.fog.params.w;\n", tmp, tmp);
+    shader_addline(buffer, "LRP %s.rgb, %s.x, %s, state.fog.color;\n", fragcolor, tmp, fragcolor);
+}
+
 /* Context activation is done by the caller. */
 static GLuint shader_arb_generate_pshader(const struct wined3d_shader *shader,
         const struct wined3d_gl_info *gl_info, struct wined3d_shader_buffer *buffer,
         const struct arb_ps_compile_args *args, struct arb_ps_compiled_shader *compiled)
 {
     const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
-    const struct wined3d_shader_lconst *lconst;
     const DWORD *function = shader->function;
     GLuint retval;
     char fragcolor[16];
-    DWORD *lconst_map = local_const_mapping(shader), next_local;
+    DWORD next_local = 0;
     struct shader_arb_ctx_priv priv_ctx;
     BOOL dcl_td = FALSE;
     BOOL want_nv_prog = FALSE;
     struct arb_pshader_private *shader_priv = shader->backend_data;
     GLint errPos;
     DWORD map;
+    BOOL custom_linear_fog = FALSE;
 
     char srgbtmp[4][4];
     unsigned int i, found = 0;
@@ -3644,6 +3644,7 @@ static GLuint shader_arb_generate_pshader(const struct wined3d_shader *shader,
     priv_ctx.cur_np2fixup_info = &compiled->np2fixup_info;
     init_ps_input(shader, args, &priv_ctx);
     list_init(&priv_ctx.control_frames);
+    priv_ctx.ps_post_process = args->super.srgb_correction;
 
     /* Avoid enabling NV_fragment_program* if we do not need it.
      *
@@ -3691,16 +3692,23 @@ static GLuint shader_arb_generate_pshader(const struct wined3d_shader *shader,
 
     if (reg_maps->shader_version.major < 3)
     {
-        switch(args->super.fog) {
-            case FOG_OFF:
+        switch (args->super.fog)
+        {
+            case WINED3D_FFP_PS_FOG_OFF:
                 break;
-            case FOG_LINEAR:
+            case WINED3D_FFP_PS_FOG_LINEAR:
+                if (gl_info->quirks & WINED3D_QUIRK_BROKEN_ARB_FOG)
+                {
+                    custom_linear_fog = TRUE;
+                    priv_ctx.ps_post_process = TRUE;
+                    break;
+                }
                 shader_addline(buffer, "OPTION ARB_fog_linear;\n");
                 break;
-            case FOG_EXP:
+            case WINED3D_FFP_PS_FOG_EXP:
                 shader_addline(buffer, "OPTION ARB_fog_exp;\n");
                 break;
-            case FOG_EXP2:
+            case WINED3D_FFP_PS_FOG_EXP2:
                 shader_addline(buffer, "OPTION ARB_fog_exp2;\n");
                 break;
         }
@@ -3724,7 +3732,7 @@ static GLuint shader_arb_generate_pshader(const struct wined3d_shader *shader,
     }
     else
     {
-        if (args->super.srgb_correction)
+        if (priv_ctx.ps_post_process)
         {
             if (shader->u.ps.color0_mov)
             {
@@ -3748,8 +3756,7 @@ static GLuint shader_arb_generate_pshader(const struct wined3d_shader *shader,
     }
 
     /* Base Declarations */
-    next_local = shader_generate_arb_declarations(shader, reg_maps,
-            buffer, gl_info, lconst_map, NULL, &priv_ctx);
+    shader_generate_arb_declarations(shader, reg_maps, buffer, gl_info, NULL, &priv_ctx);
 
     for (i = 0, map = reg_maps->bumpmat; map; map >>= 1, ++i)
     {
@@ -3876,6 +3883,9 @@ static GLuint shader_arb_generate_pshader(const struct wined3d_shader *shader,
                                   priv_ctx.target_version >= NV2);
     }
 
+    if (custom_linear_fog)
+        arbfp_add_linear_fog(buffer, fragcolor, "TA");
+
     if(strcmp(fragcolor, "result.color")) {
         shader_addline(buffer, "MOV result.color, %s;\n", fragcolor);
     }
@@ -3890,7 +3900,7 @@ static GLuint shader_arb_generate_pshader(const struct wined3d_shader *shader,
     TRACE("Created hw pixel shader, prg=%d\n", retval);
     /* Create the program and check for errors */
     GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
-               buffer->bsize, buffer->buffer));
+               buffer->content_size, buffer->buffer));
     checkGLcall("glProgramStringARB()");
 
     gl_info->gl_ops.gl.p_glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
@@ -3910,18 +3920,6 @@ static GLuint shader_arb_generate_pshader(const struct wined3d_shader *shader,
         if (!native) WARN("Program exceeds native resource limits.\n");
     }
 
-    /* Load immediate constants */
-    if (lconst_map)
-    {
-        LIST_FOR_EACH_ENTRY(lconst, &shader->constantsF, struct wined3d_shader_lconst, entry)
-        {
-            const float *value = (const float *)lconst->value;
-            GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, lconst_map[lconst->idx], value));
-            checkGLcall("glProgramLocalParameter4fvARB");
-        }
-        HeapFree(GetProcessHeap(), 0, lconst_map);
-    }
-
     return retval;
 }
 
@@ -3991,7 +3989,8 @@ static DWORD find_input_signature(struct shader_arb_priv *priv, const struct win
     return found_sig->idx;
 }
 
-static void init_output_registers(const struct wined3d_shader *shader, DWORD sig_num,
+static void init_output_registers(const struct wined3d_shader *shader,
+        const struct wined3d_shader_signature_element *ps_input_sig,
         struct shader_arb_ctx_priv *priv_ctx, struct arb_vs_compiled_shader *compiled)
 {
     unsigned int i, j;
@@ -4000,8 +3999,6 @@ static void init_output_registers(const struct wined3d_shader *shader, DWORD sig
         "result.texcoord[0]", "result.texcoord[1]", "result.texcoord[2]", "result.texcoord[3]",
         "result.texcoord[4]", "result.texcoord[5]", "result.texcoord[6]", "result.texcoord[7]"
     };
-    struct wined3d_device *device = shader->device;
-    const struct wined3d_shader_signature_element *sig;
     const char *semantic_name;
     DWORD semantic_idx, reg_idx;
 
@@ -4015,7 +4012,7 @@ static void init_output_registers(const struct wined3d_shader *shader, DWORD sig
         "result.color.primary", "result.color.secondary"
     };
 
-    if(sig_num == ~0)
+    if (!ps_input_sig)
     {
         TRACE("Pixel shader uses builtin varyings\n");
         /* Map builtins to builtins */
@@ -4074,10 +4071,6 @@ static void init_output_registers(const struct wined3d_shader *shader, DWORD sig
         return;
     }
 
-    /* Instead of searching for the signature in the signature list, read the one from the current pixel shader.
-     * Its maybe not the shader where the signature came from, but it is the same signature and faster to find
-     */
-    sig = device->stateBlock->state.pixel_shader->input_signature;
     TRACE("Pixel shader uses declared varyings\n");
 
     /* Map builtin to declared. /dev/null the results by default to the TA temp reg */
@@ -4091,9 +4084,9 @@ static void init_output_registers(const struct wined3d_shader *shader, DWORD sig
 
     for(i = 0; i < MAX_REG_INPUT; i++)
     {
-        semantic_name = sig[i].semantic_name;
-        semantic_idx = sig[i].semantic_idx;
-        reg_idx = sig[i].register_idx;
+        semantic_name = ps_input_sig[i].semantic_name;
+        semantic_idx = ps_input_sig[i].semantic_idx;
+        reg_idx = ps_input_sig[i].register_idx;
         if (!semantic_name) continue;
 
         /* If a declared input register is not written by builtin arguments, don't write to it.
@@ -4152,12 +4145,12 @@ static void init_output_registers(const struct wined3d_shader *shader, DWORD sig
 
         for(j = 0; j < MAX_REG_INPUT; j++)
         {
-            if (!sig[j].semantic_name) continue;
+            if (!ps_input_sig[j].semantic_name) continue;
 
-            if (!strcmp(sig[j].semantic_name, semantic_name)
-                    && sig[j].semantic_idx == shader->output_signature[i].semantic_idx)
+            if (!strcmp(ps_input_sig[j].semantic_name, semantic_name)
+                    && ps_input_sig[j].semantic_idx == shader->output_signature[i].semantic_idx)
             {
-                priv_ctx->vs_output[i] = decl_idx_to_string[sig[j].register_idx];
+                priv_ctx->vs_output[i] = decl_idx_to_string[ps_input_sig[j].register_idx];
 
                 if (!strcmp(priv_ctx->vs_output[i], "result.color.primary")
                         || !strcmp(priv_ctx->vs_output[i], "result.color.secondary"))
@@ -4172,15 +4165,15 @@ static void init_output_registers(const struct wined3d_shader *shader, DWORD sig
 /* Context activation is done by the caller. */
 static GLuint shader_arb_generate_vshader(const struct wined3d_shader *shader,
         const struct wined3d_gl_info *gl_info, struct wined3d_shader_buffer *buffer,
-        const struct arb_vs_compile_args *args, struct arb_vs_compiled_shader *compiled)
+        const struct arb_vs_compile_args *args, struct arb_vs_compiled_shader *compiled,
+        const struct wined3d_shader_signature_element *ps_input_sig)
 {
     const struct arb_vshader_private *shader_data = shader->backend_data;
     const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
     struct shader_arb_priv *priv = shader->device->shader_priv;
-    const struct wined3d_shader_lconst *lconst;
     const DWORD *function = shader->function;
     GLuint ret;
-    DWORD next_local, *lconst_map = local_const_mapping(shader);
+    DWORD next_local = 0;
     struct shader_arb_ctx_priv priv_ctx;
     unsigned int i;
     GLint errPos;
@@ -4188,7 +4181,7 @@ static GLuint shader_arb_generate_vshader(const struct wined3d_shader *shader,
     memset(&priv_ctx, 0, sizeof(priv_ctx));
     priv_ctx.cur_vs_args = args;
     list_init(&priv_ctx.control_frames);
-    init_output_registers(shader, args->ps_signature, &priv_ctx, compiled);
+    init_output_registers(shader, ps_input_sig, &priv_ctx, compiled);
 
     /*  Create the hw ARB shader */
     shader_addline(buffer, "!!ARBvp1.0\n");
@@ -4228,8 +4221,8 @@ static GLuint shader_arb_generate_vshader(const struct wined3d_shader *shader,
     shader_addline(buffer, "TEMP TB;\n");
 
     /* Base Declarations */
-    next_local = shader_generate_arb_declarations(shader, reg_maps, buffer,
-            gl_info, lconst_map, &priv_ctx.vs_clipplanes, &priv_ctx);
+    shader_generate_arb_declarations(shader, reg_maps, buffer, gl_info,
+            &priv_ctx.vs_clipplanes, &priv_ctx);
 
     for(i = 0; i < MAX_CONST_I; i++)
     {
@@ -4303,7 +4296,7 @@ static GLuint shader_arb_generate_vshader(const struct wined3d_shader *shader,
     TRACE("Created hw vertex shader, prg=%d\n", ret);
     /* Create the program and check for errors */
     GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
-               buffer->bsize, buffer->buffer));
+               buffer->content_size, buffer->buffer));
     checkGLcall("glProgramStringARB()");
 
     gl_info->gl_ops.gl.p_glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
@@ -4321,18 +4314,7 @@ static GLuint shader_arb_generate_vshader(const struct wined3d_shader *shader,
         GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &native));
         checkGLcall("glGetProgramivARB()");
         if (!native) WARN("Program exceeds native resource limits.\n");
-
-        /* Load immediate constants */
-        if (lconst_map)
-        {
-            LIST_FOR_EACH_ENTRY(lconst, &shader->constantsF, struct wined3d_shader_lconst, entry)
-            {
-                const float *value = (const float *)lconst->value;
-                GL_EXTCALL(glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, lconst_map[lconst->idx], value));
-            }
-        }
     }
-    HeapFree(GetProcessHeap(), 0, lconst_map);
 
     return ret;
 }
@@ -4343,6 +4325,7 @@ static struct arb_ps_compiled_shader *find_arb_pshader(struct wined3d_shader *sh
 {
     struct wined3d_device *device = shader->device;
     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
     UINT i;
     DWORD new_size;
     struct arb_ps_compiled_shader *new_array;
@@ -4359,15 +4342,15 @@ static struct arb_ps_compiled_shader *find_arb_pshader(struct wined3d_shader *sh
         shader_data->clamp_consts = shader->reg_maps.shader_version.major == 1;
 
         if (shader->reg_maps.shader_version.major < 3)
-            shader_data->input_signature_idx = ~0;
+            shader_data->input_signature_idx = ~0U;
         else
             shader_data->input_signature_idx = find_input_signature(priv, shader->input_signature);
 
         TRACE("Shader got assigned input signature index %u\n", shader_data->input_signature_idx);
 
-        if (!device->vs_clipping)
+        if (!d3d_info->vs_clipping)
             shader_data->clipplane_emulation = shader_find_free_input_register(&shader->reg_maps,
-                    gl_info->limits.texture_stages - 1);
+                    d3d_info->limits.ffp_blend_stages - 1);
         else
             shader_data->clipplane_emulation = ~0U;
     }
@@ -4405,7 +4388,7 @@ static struct arb_ps_compiled_shader *find_arb_pshader(struct wined3d_shader *sh
 
     shader_data->gl_shaders[shader_data->num_gl_shaders].args = *args;
 
-    pixelshader_update_samplers(&shader->reg_maps, device->stateBlock->state.textures);
+    pixelshader_update_samplers(shader, args->super.tex_types);
 
     if (!shader_buffer_init(&buffer))
     {
@@ -4435,11 +4418,12 @@ static inline BOOL vs_args_equal(const struct arb_vs_compile_args *stored, const
 }
 
 static struct arb_vs_compiled_shader *find_arb_vshader(struct wined3d_shader *shader,
-        const struct arb_vs_compile_args *args)
+        const struct arb_vs_compile_args *args,
+        const struct wined3d_shader_signature_element *ps_input_sig)
 {
     struct wined3d_device *device = shader->device;
     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
-    DWORD use_map = device->strided_streams.use_map;
+    DWORD use_map = device->stream_info.use_map;
     UINT i;
     DWORD new_size;
     struct arb_vs_compiled_shader *new_array;
@@ -4513,7 +4497,8 @@ static struct arb_vs_compiled_shader *find_arb_vshader(struct wined3d_shader *sh
     }
 
     ret = shader_arb_generate_vshader(shader, gl_info, &buffer, args,
-            &shader_data->gl_shaders[shader_data->num_gl_shaders]);
+            &shader_data->gl_shaders[shader_data->num_gl_shaders],
+            ps_input_sig);
     shader_buffer_free(&buffer);
     shader_data->gl_shaders[shader_data->num_gl_shaders].prgId = ret;
 
@@ -4521,10 +4506,11 @@ static struct arb_vs_compiled_shader *find_arb_vshader(struct wined3d_shader *sh
 }
 
 static void find_arb_ps_compile_args(const struct wined3d_state *state,
-        const struct wined3d_shader *shader, struct arb_ps_compile_args *args)
+        const struct wined3d_context *context, const struct wined3d_shader *shader,
+        struct arb_ps_compile_args *args)
 {
-    struct wined3d_device *device = shader->device;
-    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    const struct wined3d_d3d_info *d3d_info = context->d3d_info;
     int i;
     WORD int_skip;
 
@@ -4543,7 +4529,7 @@ static void find_arb_ps_compile_args(const struct wined3d_state *state,
      * is quite expensive because it forces the driver to disable early Z discards. It is cheaper to
      * duplicate the shader than have a no-op KIL instruction in every shader
      */
-    if (!device->vs_clipping && use_vs(state)
+    if (!d3d_info->vs_clipping && use_vs(state)
             && state->render_states[WINED3D_RS_CLIPPING]
             && state->render_states[WINED3D_RS_CLIPPLANEENABLE])
         args->clip = 1;
@@ -4576,10 +4562,13 @@ static void find_arb_ps_compile_args(const struct wined3d_state *state,
 }
 
 static void find_arb_vs_compile_args(const struct wined3d_state *state,
-        const struct wined3d_shader *shader, struct arb_vs_compile_args *args)
+        const struct wined3d_context *context, const struct wined3d_shader *shader,
+        struct arb_vs_compile_args *args)
 {
     struct wined3d_device *device = shader->device;
-    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    const struct wined3d_adapter *adapter = device->adapter;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    const struct wined3d_d3d_info *d3d_info = context->d3d_info;
     int i;
     WORD int_skip;
 
@@ -4597,9 +4586,9 @@ static void find_arb_vs_compile_args(const struct wined3d_state *state,
     else
     {
         args->ps_signature = ~0;
-        if (!device->vs_clipping && device->adapter->fragment_pipe == &arbfp_fragment_pipeline)
+        if (!d3d_info->vs_clipping && adapter->fragment_pipe == &arbfp_fragment_pipeline)
         {
-            args->clip.boolclip.clip_texcoord = ffp_clip_emul(state) ? gl_info->limits.texture_stages : 0;
+            args->clip.boolclip.clip_texcoord = ffp_clip_emul(state) ? d3d_info->limits.ffp_blend_stages : 0;
         }
         /* Otherwise: Setting boolclip_compare set clip_texcoord to 0 */
     }
@@ -4652,24 +4641,22 @@ static void find_arb_vs_compile_args(const struct wined3d_state *state,
 }
 
 /* Context activation is done by the caller. */
-static void shader_arb_select(const struct wined3d_context *context, enum wined3d_shader_mode vertex_mode,
-        enum wined3d_shader_mode fragment_mode)
+static void shader_arb_select(void *shader_priv, struct wined3d_context *context,
+        const struct wined3d_state *state)
 {
-    struct wined3d_device *device = context->swapchain->device;
-    struct shader_arb_priv *priv = device->shader_priv;
+    struct shader_arb_priv *priv = shader_priv;
     const struct wined3d_gl_info *gl_info = context->gl_info;
-    const struct wined3d_state *state = &device->stateBlock->state;
     int i;
 
     /* Deal with pixel shaders first so the vertex shader arg function has the input signature ready */
-    if (fragment_mode == WINED3D_SHADER_MODE_SHADER)
+    if (use_ps(state))
     {
         struct wined3d_shader *ps = state->pixel_shader;
         struct arb_ps_compile_args compile_args;
         struct arb_ps_compiled_shader *compiled;
 
         TRACE("Using pixel shader %p.\n", ps);
-        find_arb_ps_compile_args(state, ps, &compile_args);
+        find_arb_ps_compile_args(state, context, ps, &compile_args);
         compiled = find_arb_pshader(ps, &compile_args);
         priv->current_fprogram_id = compiled->prgId;
         priv->compiled_fprog = compiled;
@@ -4685,8 +4672,7 @@ static void shader_arb_select(const struct wined3d_context *context, enum wined3
         gl_info->gl_ops.gl.p_glEnable(GL_FRAGMENT_PROGRAM_ARB);
         checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
 
-        TRACE("(%p) : Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n",
-                device, priv->current_fprogram_id);
+        TRACE("Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n", priv->current_fprogram_id);
 
         /* Pixel Shader 1.x constants are clamped to [-1;1], Pixel Shader 2.0 constants are not. If switching between
          * a 1.x and newer shader, reload the first 8 constants
@@ -4700,7 +4686,7 @@ static void shader_arb_select(const struct wined3d_context *context, enum wined3
                 priv->pshader_const_dirty[i] = 1;
             }
             /* Also takes care of loading local constants */
-            shader_arb_load_constants_internal(context, TRUE, FALSE, TRUE);
+            shader_arb_load_constants_internal(shader_priv, context, state, TRUE, FALSE, TRUE);
         }
         else
         {
@@ -4710,7 +4696,10 @@ static void shader_arb_select(const struct wined3d_context *context, enum wined3
 
         /* Force constant reloading for the NP2 fixup (see comment in shader_glsl_select for more info) */
         if (compiled->np2fixup_info.super.active)
-            shader_arb_load_np2fixup_constants(priv, gl_info, state);
+            context->constant_update_mask |= WINED3D_SHADER_CONST_PS_NP2_FIXUP;
+
+        if (ps->load_local_constsF)
+            context->constant_update_mask |= WINED3D_SHADER_CONST_PS_F;
     }
     else
     {
@@ -4724,18 +4713,28 @@ static void shader_arb_select(const struct wined3d_context *context, enum wined3
             checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)");
             priv->current_fprogram_id = 0;
         }
-        priv->fragment_pipe->enable_extension(gl_info, fragment_mode == WINED3D_SHADER_MODE_FFP);
+        priv->fragment_pipe->enable_extension(gl_info, TRUE);
     }
 
-    if (vertex_mode == WINED3D_SHADER_MODE_SHADER)
+    if (use_vs(state))
     {
         struct wined3d_shader *vs = state->vertex_shader;
         struct arb_vs_compile_args compile_args;
         struct arb_vs_compiled_shader *compiled;
+        const struct wined3d_shader_signature_element *ps_input_sig;
 
         TRACE("Using vertex shader %p\n", vs);
-        find_arb_vs_compile_args(state, vs, &compile_args);
-        compiled = find_arb_vshader(vs, &compile_args);
+        find_arb_vs_compile_args(state, context, vs, &compile_args);
+
+        /* Instead of searching for the signature in the signature list, read the one from the
+         * current pixel shader. It's maybe not the shader where the signature came from, but it
+         * is the same signature and faster to find. */
+        if (compile_args.ps_signature == ~0U)
+            ps_input_sig = NULL;
+        else
+            ps_input_sig = state->pixel_shader->input_signature;
+
+        compiled = find_arb_vshader(vs, &compile_args, ps_input_sig);
         priv->current_vprogram_id = compiled->prgId;
         priv->compiled_vprog = compiled;
 
@@ -4743,10 +4742,12 @@ static void shader_arb_select(const struct wined3d_context *context, enum wined3
         GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id));
         checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id);");
 
+        priv->vertex_pipe->vp_enable(gl_info, FALSE);
+
         /* Enable OpenGL vertex programs */
         gl_info->gl_ops.gl.p_glEnable(GL_VERTEX_PROGRAM_ARB);
         checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
-        TRACE("(%p) : Bound vertex program %u and enabled GL_VERTEX_PROGRAM_ARB\n", device, priv->current_vprogram_id);
+        TRACE("Bound vertex program %u and enabled GL_VERTEX_PROGRAM_ARB\n", priv->current_vprogram_id);
         shader_arb_vs_local_constants(compiled, context, state);
 
         if(priv->last_vs_color_unclamp != compiled->need_color_unclamp) {
@@ -4760,13 +4761,55 @@ static void shader_arb_select(const struct wined3d_context *context, enum wined3
                 FIXME("vertex color clamp needs to be changed, but extension not supported.\n");
             }
         }
+
+        if (vs->load_local_constsF)
+            context->constant_update_mask |= WINED3D_SHADER_CONST_VS_F;
     }
-    else if (gl_info->supported[ARB_VERTEX_PROGRAM])
+    else
+    {
+        if (gl_info->supported[ARB_VERTEX_PROGRAM])
+        {
+            priv->current_vprogram_id = 0;
+            gl_info->gl_ops.gl.p_glDisable(GL_VERTEX_PROGRAM_ARB);
+            checkGLcall("glDisable(GL_VERTEX_PROGRAM_ARB)");
+        }
+        priv->vertex_pipe->vp_enable(gl_info, TRUE);
+    }
+}
+
+
+/* Context activation is done by the caller. */
+static void shader_arb_disable(void *shader_priv, struct wined3d_context *context)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    struct shader_arb_priv *priv = shader_priv;
+
+    if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_FRAGMENT_PROGRAM_ARB);
+        checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)");
+        priv->current_fprogram_id = 0;
+    }
+    priv->fragment_pipe->enable_extension(gl_info, FALSE);
+
+    if (gl_info->supported[ARB_VERTEX_PROGRAM])
     {
         priv->current_vprogram_id = 0;
         gl_info->gl_ops.gl.p_glDisable(GL_VERTEX_PROGRAM_ARB);
         checkGLcall("glDisable(GL_VERTEX_PROGRAM_ARB)");
     }
+    priv->vertex_pipe->vp_enable(gl_info, FALSE);
+
+    if (gl_info->supported[ARB_COLOR_BUFFER_FLOAT] && priv->last_vs_color_unclamp)
+    {
+        GL_EXTCALL(glClampColorARB(GL_CLAMP_VERTEX_COLOR_ARB, GL_FIXED_ONLY_ARB));
+        checkGLcall("glClampColorARB");
+        priv->last_vs_color_unclamp = FALSE;
+    }
+
+    context->shader_update_mask = (1 << WINED3D_SHADER_TYPE_PIXEL)
+            | (1 << WINED3D_SHADER_TYPE_VERTEX)
+            | (1 << WINED3D_SHADER_TYPE_GEOMETRY);
 }
 
 /* Context activation is done by the caller. */
@@ -4888,32 +4931,42 @@ static const struct wine_rb_functions sig_tree_functions =
     sig_tree_compare
 };
 
-static HRESULT shader_arb_alloc(struct wined3d_device *device, const struct fragment_pipeline *fragment_pipe)
+static HRESULT shader_arb_alloc(struct wined3d_device *device, const struct wined3d_vertex_pipe_ops *vertex_pipe,
+        const struct fragment_pipeline *fragment_pipe)
 {
     struct shader_arb_priv *priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*priv));
     struct fragment_caps fragment_caps;
-    void *fragment_priv;
+    void *vertex_priv, *fragment_priv;
+    const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
+
+    if (!(vertex_priv = vertex_pipe->vp_alloc(&arb_program_shader_backend, priv)))
+    {
+        ERR("Failed to initialize vertex pipe.\n");
+        HeapFree(GetProcessHeap(), 0, priv);
+        return E_FAIL;
+    }
 
     if (!(fragment_priv = fragment_pipe->alloc_private(&arb_program_shader_backend, priv)))
     {
         ERR("Failed to initialize fragment pipe.\n");
+        vertex_pipe->vp_free(device);
         HeapFree(GetProcessHeap(), 0, priv);
         return E_FAIL;
     }
 
     priv->vshader_const_dirty = HeapAlloc(GetProcessHeap(), 0,
-            sizeof(*priv->vshader_const_dirty) * device->d3d_vshader_constantF);
+            sizeof(*priv->vshader_const_dirty) * d3d_info->limits.vs_uniform_count);
     if (!priv->vshader_const_dirty)
         goto fail;
     memset(priv->vshader_const_dirty, 1,
-           sizeof(*priv->vshader_const_dirty) * device->d3d_vshader_constantF);
+           sizeof(*priv->vshader_const_dirty) * d3d_info->limits.vs_uniform_count);
 
     priv->pshader_const_dirty = HeapAlloc(GetProcessHeap(), 0,
-            sizeof(*priv->pshader_const_dirty) * device->d3d_pshader_constantF);
+            sizeof(*priv->pshader_const_dirty) * d3d_info->limits.ps_uniform_count);
     if (!priv->pshader_const_dirty)
         goto fail;
     memset(priv->pshader_const_dirty, 1,
-            sizeof(*priv->pshader_const_dirty) * device->d3d_pshader_constantF);
+            sizeof(*priv->pshader_const_dirty) * d3d_info->limits.ps_uniform_count);
 
     if(wine_rb_init(&priv->signature_tree, &sig_tree_functions) == -1)
     {
@@ -4921,17 +4974,22 @@ static HRESULT shader_arb_alloc(struct wined3d_device *device, const struct frag
         goto fail;
     }
 
+    priv->vertex_pipe = vertex_pipe;
+    priv->fragment_pipe = fragment_pipe;
     fragment_pipe->get_caps(&device->adapter->gl_info, &fragment_caps);
     priv->ffp_proj_control = fragment_caps.wined3d_caps & WINED3D_FRAGMENT_CAP_PROJ_CONTROL;
+
+    device->vertex_priv = vertex_priv;
     device->fragment_priv = fragment_priv;
-    priv->fragment_pipe = fragment_pipe;
     device->shader_priv = priv;
+
     return WINED3D_OK;
 
 fail:
     HeapFree(GetProcessHeap(), 0, priv->pshader_const_dirty);
     HeapFree(GetProcessHeap(), 0, priv->vshader_const_dirty);
     fragment_pipe->free_private(device);
+    vertex_pipe->vp_free(device);
     HeapFree(GetProcessHeap(), 0, priv);
     return E_OUTOFMEMORY;
 }
@@ -4974,12 +5032,18 @@ static void shader_arb_free(struct wined3d_device *device)
     HeapFree(GetProcessHeap(), 0, priv->pshader_const_dirty);
     HeapFree(GetProcessHeap(), 0, priv->vshader_const_dirty);
     priv->fragment_pipe->free_private(device);
+    priv->vertex_pipe->vp_free(device);
     HeapFree(GetProcessHeap(), 0, device->shader_priv);
 }
 
-static void shader_arb_context_destroyed(void *shader_priv, const struct wined3d_context *context)
+static BOOL shader_arb_allocate_context_data(struct wined3d_context *context)
 {
-    struct shader_arb_priv *priv = shader_priv;
+    return TRUE;
+}
+
+static void shader_arb_free_context_data(struct wined3d_context *context)
+{
+    struct shader_arb_priv *priv = context->swapchain->device->shader_priv;
 
     if (priv->last_context == context)
         priv->last_context = NULL;
@@ -5648,16 +5712,17 @@ const struct wined3d_shader_backend_ops arb_program_shader_backend =
 {
     shader_arb_handle_instruction,
     shader_arb_select,
+    shader_arb_disable,
     shader_arb_select_depth_blt,
     shader_arb_deselect_depth_blt,
     shader_arb_update_float_vertex_constants,
     shader_arb_update_float_pixel_constants,
     shader_arb_load_constants,
-    shader_arb_load_np2fixup_constants,
     shader_arb_destroy,
     shader_arb_alloc,
     shader_arb_free,
-    shader_arb_context_destroyed,
+    shader_arb_allocate_context_data,
+    shader_arb_free_context_data,
     shader_arb_get_caps,
     shader_arb_color_fixup_supported,
     shader_arb_has_ffp_proj_control,
@@ -5844,21 +5909,16 @@ static void set_bumpmat_arbfp(struct wined3d_context *context, const struct wine
     const struct wined3d_gl_info *gl_info = context->gl_info;
     float mat[2][2];
 
-    if (use_ps(state))
-    {
-        /* The pixel shader has to know the bump env matrix. Do a constants
-         * update. */
-        if (stage && (state->pixel_shader->reg_maps.bumpmat & (1 << stage)))
-            context->load_constants = 1;
+    context->constant_update_mask |= WINED3D_SHADER_CONST_PS_BUMP_ENV;
 
-        if(device->shader_backend == &arb_program_shader_backend) {
-            /* Exit now, don't set the bumpmat below, otherwise we may overwrite pixel shader constants */
-            return;
-        }
-    }
-    else if (device->shader_backend == &arb_program_shader_backend)
+    if (device->shader_backend == &arb_program_shader_backend)
     {
         struct shader_arb_priv *priv = device->shader_priv;
+
+        /* Exit now, don't set the bumpmat below, otherwise we may overwrite pixel shader constants. */
+        if (use_ps(state))
+            return;
+
         priv->pshader_const_dirty[ARB_FFP_CONST_BUMPMAT(stage)] = 1;
         priv->highest_dirty_ps_const = max(priv->highest_dirty_ps_const, ARB_FFP_CONST_BUMPMAT(stage) + 1);
     }
@@ -5880,21 +5940,16 @@ static void tex_bumpenvlum_arbfp(struct wined3d_context *context,
     const struct wined3d_gl_info *gl_info = context->gl_info;
     float param[4];
 
-    if (use_ps(state))
-    {
-        /* The pixel shader has to know the luminance offset. Do a constants
-         * update. */
-        if (stage && (state->pixel_shader->reg_maps.luminanceparams & (1 << stage)))
-            context->load_constants = 1;
+    context->constant_update_mask |= WINED3D_SHADER_CONST_PS_BUMP_ENV;
 
-        if(device->shader_backend == &arb_program_shader_backend) {
-            /* Exit now, don't set the bumpmat below, otherwise we may overwrite pixel shader constants */
-            return;
-        }
-    }
-    else if (device->shader_backend == &arb_program_shader_backend)
+    if (device->shader_backend == &arb_program_shader_backend)
     {
         struct shader_arb_priv *priv = device->shader_priv;
+
+        /* Exit now, don't set the bumpmat below, otherwise we may overwrite pixel shader constants. */
+        if (use_ps(state))
+            return;
+
         priv->pshader_const_dirty[ARB_FFP_CONST_LUMINANCE(stage)] = 1;
         priv->highest_dirty_ps_const = max(priv->highest_dirty_ps_const, ARB_FFP_CONST_LUMINANCE(stage) + 1);
     }
@@ -6129,6 +6184,7 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, con
     BOOL op_equal;
     const char *final_combiner_src = "ret";
     GLint pos;
+    BOOL custom_linear_fog = FALSE;
 
     /* Find out which textures are read */
     for (stage = 0; stage < MAX_TEXTURES; ++stage)
@@ -6198,11 +6254,20 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, con
 
     shader_addline(&buffer, "!!ARBfp1.0\n");
 
-    switch(settings->fog) {
-        case FOG_OFF:                                                         break;
-        case FOG_LINEAR: shader_addline(&buffer, "OPTION ARB_fog_linear;\n"); break;
-        case FOG_EXP:    shader_addline(&buffer, "OPTION ARB_fog_exp;\n");    break;
-        case FOG_EXP2:   shader_addline(&buffer, "OPTION ARB_fog_exp2;\n");   break;
+    switch (settings->fog)
+    {
+        case WINED3D_FFP_PS_FOG_OFF:                                                         break;
+        case WINED3D_FFP_PS_FOG_LINEAR:
+            if (gl_info->quirks & WINED3D_QUIRK_BROKEN_ARB_FOG)
+            {
+                custom_linear_fog = TRUE;
+                break;
+            }
+            shader_addline(&buffer, "OPTION ARB_fog_linear;\n");
+            break;
+
+        case WINED3D_FFP_PS_FOG_EXP:    shader_addline(&buffer, "OPTION ARB_fog_exp;\n");    break;
+        case WINED3D_FFP_PS_FOG_EXP2:   shader_addline(&buffer, "OPTION ARB_fog_exp2;\n");   break;
         default: FIXME("Unexpected fog setting %d\n", settings->fog);
     }
 
@@ -6365,12 +6430,19 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, con
         }
     }
 
-    if(settings->sRGB_write) {
+    if (settings->sRGB_write || custom_linear_fog)
+    {
         shader_addline(&buffer, "MAD ret, fragment.color.secondary, specular_enable, %s;\n", final_combiner_src);
-        arbfp_add_sRGB_correction(&buffer, "ret", "arg0", "arg1", "arg2", "tempreg", FALSE);
+        if (settings->sRGB_write)
+            arbfp_add_sRGB_correction(&buffer, "ret", "arg0", "arg1", "arg2", "tempreg", FALSE);
+        if (custom_linear_fog)
+            arbfp_add_linear_fog(&buffer, "ret", "arg0");
         shader_addline(&buffer, "MOV result.color, ret;\n");
-    } else {
-        shader_addline(&buffer, "MAD result.color, fragment.color.secondary, specular_enable, %s;\n", final_combiner_src);
+    }
+    else
+    {
+        shader_addline(&buffer, "MAD result.color, fragment.color.secondary, specular_enable, %s;\n",
+                final_combiner_src);
     }
 
     /* Footer */
@@ -6430,7 +6502,7 @@ static void fragment_prog_arbfp(struct wined3d_context *context, const struct wi
         }
         else if (use_pshader)
         {
-            context->select_shader = 1;
+            context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_PIXEL;
         }
         return;
     }
@@ -6439,7 +6511,7 @@ static void fragment_prog_arbfp(struct wined3d_context *context, const struct wi
     {
         /* Find or create a shader implementing the fixed function pipeline
          * settings, then activate it. */
-        gen_ffp_frag_op(device, state, &settings, FALSE);
+        gen_ffp_frag_op(context, state, &settings, FALSE);
         desc = (const struct arbfp_ffp_desc *)find_ffp_frag_shader(&priv->fragment_shaders, &settings);
         if(!desc) {
             struct arbfp_ffp_desc *new_desc = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_desc));
@@ -6480,8 +6552,7 @@ static void fragment_prog_arbfp(struct wined3d_context *context, const struct wi
         context->last_was_pshader = TRUE;
     }
 
-    context->select_shader = 1;
-    context->load_constants = 1;
+    context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_PIXEL;
 }
 
 /* We can't link the fog states to the fragment state directly since the
@@ -6494,6 +6565,8 @@ static void fragment_prog_arbfp(struct wined3d_context *context, const struct wi
 static void state_arbfp_fog(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     enum fogsource new_source;
+    DWORD fogstart = state->render_states[WINED3D_RS_FOGSTART];
+    DWORD fogend = state->render_states[WINED3D_RS_FOGEND];
 
     TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);
 
@@ -6522,7 +6595,7 @@ static void state_arbfp_fog(struct wined3d_context *context, const struct wined3
         new_source = FOGSOURCE_FFP;
     }
 
-    if (new_source != context->fog_source)
+    if (new_source != context->fog_source || fogstart == fogend)
     {
         context->fog_source = new_source;
         state_fogstartend(context, state, STATE_RENDER(WINED3D_RS_FOGSTART));
@@ -7032,18 +7105,12 @@ static void upload_palette(const struct wined3d_surface *surface, struct wined3d
 {
     BYTE table[256][4];
     struct wined3d_device *device = surface->resource.device;
-    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
     struct arbfp_blit_priv *priv = device->blit_priv;
     BOOL colorkey = (surface->CKeyFlags & WINEDDSD_CKSRCBLT) != 0;
 
     d3dfmt_p8_init_palette(surface, table, colorkey);
 
-    if (gl_info->supported[APPLE_CLIENT_STORAGE])
-    {
-        gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
-        checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
-    }
-
     if (!priv->palette_texture)
         gl_info->gl_ops.gl.p_glGenTextures(1, &priv->palette_texture);
 
@@ -7060,12 +7127,6 @@ static void upload_palette(const struct wined3d_surface *surface, struct wined3d
     /* TODO: avoid unneeded uploads in the future by adding some SFLAG_PALETTE_DIRTY mechanism */
     gl_info->gl_ops.gl.p_glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, table);
 
-    if (gl_info->supported[APPLE_CLIENT_STORAGE])
-    {
-        gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
-        checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
-    }
-
     /* Switch back to unit 0 in which the 2D texture will be stored. */
     context_active_texture(context, gl_info, 0);
 }
@@ -7233,8 +7294,8 @@ static HRESULT arbfp_blit_set(void *blit_priv, struct wined3d_context *context,
     const struct wined3d_gl_info *gl_info = context->gl_info;
     GLenum textype;
 
-    if (surface->container.type == WINED3D_CONTAINER_TEXTURE)
-        textype = surface->container.u.texture->target;
+    if (surface->container)
+        textype = surface->container->target;
     else
         textype = surface->texture_target;
 
@@ -7417,8 +7478,7 @@ HRESULT arbfp_blit_surface(struct wined3d_device *device, DWORD filter,
     arbfp_blit_unset(context->gl_info);
 
     if (wined3d_settings.strict_draw_ordering
-            || (dst_surface->container.type == WINED3D_CONTAINER_SWAPCHAIN
-            && (dst_surface->container.u.swapchain->front_buffer == dst_surface)))
+            || (dst_surface->swapchain && (dst_surface->swapchain->front_buffer == dst_surface)))
         context->gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */
 
     context_release(context);
index a8e4dfb..be679dd 100644 (file)
@@ -838,13 +838,14 @@ static void set_tex_op_atifs(struct wined3d_context *context, const struct wined
 {
     const struct wined3d_device *device = context->swapchain->device;
     const struct wined3d_gl_info *gl_info = context->gl_info;
+    const struct wined3d_d3d_info *d3d_info = context->d3d_info;
     const struct atifs_ffp_desc *desc;
     struct ffp_frag_settings settings;
     struct atifs_private_data *priv = device->fragment_priv;
     DWORD mapped_stage;
     unsigned int i;
 
-    gen_ffp_frag_op(device, state, &settings, TRUE);
+    gen_ffp_frag_op(context, state, &settings, TRUE);
     desc = (const struct atifs_ffp_desc *)find_ffp_frag_shader(&priv->fragment_shaders, &settings);
     if(!desc) {
         struct atifs_ffp_desc *new_desc = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_desc));
@@ -854,7 +855,7 @@ static void set_tex_op_atifs(struct wined3d_context *context, const struct wined
             return;
         }
         new_desc->num_textures_used = 0;
-        for (i = 0; i < gl_info->limits.texture_stages; ++i)
+        for (i = 0; i < d3d_info->limits.ffp_blend_stages; ++i)
         {
             if (settings.op[i].cop == WINED3D_TOP_DISABLE)
                 break;
@@ -941,8 +942,7 @@ static void atifs_apply_pixelshader(struct wined3d_context *context, const struc
      * startup, and blitting disables all shaders and dirtifies all shader
      * states. If atifs can deal with this it keeps the rest of the code
      * simpler. */
-    context->select_shader = 1;
-    context->load_constants = 1;
+    context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_PIXEL;
 }
 
 static void atifs_srgbwriteenable(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
@@ -1166,10 +1166,9 @@ static void *atifs_alloc(const struct wined3d_shader_backend_ops *shader_backend
 }
 
 /* Context activation is done by the caller. */
-static void atifs_free_ffpshader(struct wine_rb_entry *entry, void *context)
+static void atifs_free_ffpshader(struct wine_rb_entry *entry, void *cb_ctx)
 {
-    struct wined3d_device *device = context;
-    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    const struct wined3d_gl_info *gl_info = cb_ctx;
     struct atifs_ffp_desc *entry_ati = WINE_RB_ENTRY_VALUE(entry, struct atifs_ffp_desc, parent.entry);
 
     GL_EXTCALL(glDeleteFragmentShaderATI(entry_ati->shader));
@@ -1182,7 +1181,7 @@ static void atifs_free(struct wined3d_device *device)
 {
     struct atifs_private_data *priv = device->fragment_priv;
 
-    wine_rb_destroy(&priv->fragment_shaders, atifs_free_ffpshader, device);
+    wine_rb_destroy(&priv->fragment_shaders, atifs_free_ffpshader, &device->adapter->gl_info);
 
     HeapFree(GetProcessHeap(), 0, priv);
     device->fragment_priv = NULL;
index 0fc122d..4e95fe2 100644 (file)
@@ -3,7 +3,7 @@
  * Copyright 2002-2005 Raphael Junqueira
  * Copyright 2004 Christian Costa
  * Copyright 2005 Oliver Stieber
- * Copyright 2007-2010 Stefan Dösinger for CodeWeavers
+ * Copyright 2007-2011, 2013 Stefan Dösinger for CodeWeavers
  * Copyright 2009-2010 Henri Verbeet for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
 
 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
 
+#define WINED3D_BUFFER_HASDESC      0x01    /* A vertex description has been found. */
+#define WINED3D_BUFFER_CREATEBO     0x02    /* Create a buffer object for this buffer. */
+#define WINED3D_BUFFER_DOUBLEBUFFER 0x04    /* Keep both a buffer object and a system memory copy for this buffer. */
+#define WINED3D_BUFFER_FLUSH        0x08    /* Manual unmap flushing. */
+#define WINED3D_BUFFER_DISCARD      0x10    /* A DISCARD lock has occurred since the last preload. */
+#define WINED3D_BUFFER_NOSYNC       0x20    /* All locks since the last preload had NOOVERWRITE set. */
+#define WINED3D_BUFFER_APPLESYNC    0x40    /* Using sync as in GL_APPLE_flush_buffer_range. */
+
 #define VB_MAXDECLCHANGES     100     /* After that number of decl changes we stop converting */
 #define VB_RESETDECLCHANGE    1000    /* Reset the decl changecount after that number of draws */
 #define VB_MAXFULLCONVERSIONS 5       /* Number of full conversions before we stop converting */
 #define VB_RESETFULLCONVS     20      /* Reset full conversion counts after that number of draws */
 
-static inline BOOL buffer_add_dirty_area(struct wined3d_buffer *This, UINT offset, UINT size)
+static void buffer_invalidate_bo_range(struct wined3d_buffer *buffer, UINT offset, UINT size)
 {
-    if (!This->buffer_object) return TRUE;
+    if (!offset && !size)
+        goto invalidate_all;
 
-    if (This->maps_size <= This->modified_areas)
+    if (offset > buffer->resource.size || offset + size > buffer->resource.size)
     {
-        void *new = HeapReAlloc(GetProcessHeap(), 0, This->maps,
-                                This->maps_size * 2 * sizeof(*This->maps));
-        if (!new)
-        {
-            ERR("Out of memory\n");
-            return FALSE;
-        }
-        else
-        {
-            This->maps = new;
-            This->maps_size *= 2;
-        }
+        WARN("Invalid range specified, invalidating entire buffer.\n");
+        goto invalidate_all;
     }
 
-    if(offset > This->resource.size || offset + size > This->resource.size)
-    {
-        WARN("Invalid range dirtified, marking entire buffer dirty\n");
-        offset = 0;
-        size = This->resource.size;
-    }
-    else if(!offset && !size)
+    if (buffer->modified_areas >= buffer->maps_size)
     {
-        size = This->resource.size;
+        struct wined3d_map_range *new;
+
+        if (!(new = HeapReAlloc(GetProcessHeap(), 0, buffer->maps, 2 * buffer->maps_size * sizeof(*buffer->maps))))
+        {
+            ERR("Failed to allocate maps array, invalidating entire buffer.\n");
+            goto invalidate_all;
+        }
+
+        buffer->maps = new;
+        buffer->maps_size *= 2;
     }
 
-    This->maps[This->modified_areas].offset = offset;
-    This->maps[This->modified_areas].size = size;
-    This->modified_areas++;
-    return TRUE;
+    buffer->maps[buffer->modified_areas].offset = offset;
+    buffer->maps[buffer->modified_areas].size = size;
+    ++buffer->modified_areas;
+    return;
+
+invalidate_all:
+    buffer->modified_areas = 1;
+    buffer->maps[0].offset = 0;
+    buffer->maps[0].size = buffer->resource.size;
 }
 
 static inline void buffer_clear_dirty_areas(struct wined3d_buffer *This)
@@ -113,7 +120,8 @@ static void delete_gl_buffer(struct wined3d_buffer *This, const struct wined3d_g
 /* Context activation is done by the caller. */
 static void buffer_create_buffer_object(struct wined3d_buffer *This, const struct wined3d_gl_info *gl_info)
 {
-    GLenum error, gl_usage;
+    GLenum gl_usage = GL_STATIC_DRAW_ARB;
+    GLenum error;
 
     TRACE("Creating an OpenGL vertex buffer object for wined3d_buffer %p with usage %s.\n",
             This, debug_d3dusage(This->resource.usage));
@@ -149,12 +157,9 @@ static void buffer_create_buffer_object(struct wined3d_buffer *This, const struc
         goto fail;
     }
 
-    /* Don't use static, because dx apps tend to update the buffer
-     * quite often even if they specify 0 usage.
-     */
-    if(This->resource.usage & WINED3DUSAGE_DYNAMIC)
+    if (This->resource.usage & WINED3DUSAGE_DYNAMIC)
     {
-        TRACE("Gl usage = GL_STREAM_DRAW_ARB\n");
+        TRACE("Buffer has WINED3DUSAGE_DYNAMIC set.\n");
         gl_usage = GL_STREAM_DRAW_ARB;
 
         if(gl_info->supported[APPLE_FLUSH_BUFFER_RANGE])
@@ -169,11 +174,6 @@ static void buffer_create_buffer_object(struct wined3d_buffer *This, const struc
         }
         /* No setup is needed here for GL_ARB_map_buffer_range */
     }
-    else
-    {
-        TRACE("Gl usage = GL_DYNAMIC_DRAW_ARB\n");
-        gl_usage = GL_DYNAMIC_DRAW_ARB;
-    }
 
     /* Reserve memory for the buffer. The amount of data won't change
      * so we are safe with calling glBufferData once and
@@ -191,19 +191,15 @@ static void buffer_create_buffer_object(struct wined3d_buffer *This, const struc
     This->buffer_object_size = This->resource.size;
     This->buffer_object_usage = gl_usage;
 
-    if(This->flags & WINED3D_BUFFER_DOUBLEBUFFER)
+    if (This->flags & WINED3D_BUFFER_DOUBLEBUFFER)
     {
-        if(!buffer_add_dirty_area(This, 0, 0))
-        {
-            ERR("buffer_add_dirty_area failed, this is not expected\n");
-            goto fail;
-        }
+        buffer_invalidate_bo_range(This, 0, 0);
     }
     else
     {
-        HeapFree(GetProcessHeap(), 0, This->resource.heapMemory);
+        wined3d_resource_free_sysmem(This->resource.heap_memory);
         This->resource.allocatedMemory = NULL;
-        This->resource.heapMemory = NULL;
+        This->resource.heap_memory = NULL;
     }
 
     return;
@@ -273,7 +269,7 @@ static BOOL buffer_process_converted_attribute(struct wined3d_buffer *This,
 }
 
 static BOOL buffer_check_attribute(struct wined3d_buffer *This, const struct wined3d_stream_info *si,
-        UINT attrib_idx, const BOOL check_d3dcolor, const BOOL is_ffp_position, const BOOL is_ffp_color,
+        UINT attrib_idx, const BOOL check_d3dcolor, const BOOL check_position, const BOOL is_ffp_color,
         DWORD *stride_this_run)
 {
     const struct wined3d_stream_info_element *attrib = &si->elements[attrib_idx];
@@ -295,7 +291,7 @@ static BOOL buffer_check_attribute(struct wined3d_buffer *This, const struct win
 
         if (!is_ffp_color) FIXME("Test for non-color fixed function WINED3DFMT_B8G8R8A8_UNORM format\n");
     }
-    else if (is_ffp_position && si->position_transformed)
+    else if (check_position && si->position_transformed)
     {
         if (format != WINED3DFMT_R32G32B32A32_FLOAT)
         {
@@ -316,12 +312,13 @@ static BOOL buffer_check_attribute(struct wined3d_buffer *This, const struct win
 static BOOL buffer_find_decl(struct wined3d_buffer *This)
 {
     struct wined3d_device *device = This->resource.device;
-    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
-    const struct wined3d_stream_info *si = &device->strided_streams;
-    const struct wined3d_state *state = &device->stateBlock->state;
+    const struct wined3d_adapter *adapter = device->adapter;
+    const struct wined3d_stream_info *si = &device->stream_info;
+    const struct wined3d_state *state = &device->state;
+    BOOL support_d3dcolor = adapter->gl_info.supported[ARB_VERTEX_ARRAY_BGRA];
+    BOOL support_xyzrhw = adapter->d3d_info.xyzrhw;
     UINT stride_this_run = 0;
     BOOL ret = FALSE;
-    BOOL support_d3dcolor = gl_info->supported[ARB_VERTEX_ARRAY_BGRA];
 
     /* In d3d7 the vertex buffer declaration NEVER changes because it is stored in the d3d7 vertex buffer.
      * Once we have our declaration there is no need to look it up again. Index buffers also never need
@@ -393,7 +390,7 @@ static BOOL buffer_find_decl(struct wined3d_buffer *This)
      */
 
     ret = buffer_check_attribute(This, si, WINED3D_FFP_POSITION,
-            TRUE, TRUE,  FALSE, &stride_this_run) || ret;
+            TRUE, !support_xyzrhw,  FALSE, &stride_this_run) || ret;
     ret = buffer_check_attribute(This, si, WINED3D_FFP_NORMAL,
             TRUE, FALSE, FALSE, &stride_this_run) || ret;
     ret = buffer_check_attribute(This, si, WINED3D_FFP_DIFFUSE,
@@ -503,8 +500,8 @@ BYTE *buffer_get_sysmem(struct wined3d_buffer *This, const struct wined3d_gl_inf
     /* 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));
+    This->resource.heap_memory = wined3d_resource_allocate_sysmem(This->resource.size);
+    This->resource.allocatedMemory = This->resource.heap_memory;
 
     if (This->buffer_type_hint == GL_ELEMENT_ARRAY_BUFFER_ARB)
         device_invalidate_state(This->resource.device, STATE_INDEXBUFFER);
@@ -557,12 +554,21 @@ static void buffer_unload(struct wined3d_resource *resource)
 ULONG CDECL wined3d_buffer_decref(struct wined3d_buffer *buffer)
 {
     ULONG refcount = InterlockedDecrement(&buffer->resource.ref);
+    struct wined3d_context *context;
 
     TRACE("%p decreasing refcount to %u.\n", buffer, refcount);
 
     if (!refcount)
     {
-        buffer_unload(&buffer->resource);
+        if (buffer->buffer_object)
+        {
+            context = context_acquire(buffer->resource.device, NULL);
+            delete_gl_buffer(buffer, context->gl_info);
+            context_release(context);
+
+            HeapFree(GetProcessHeap(), 0, buffer->conversion_map);
+        }
+
         resource_cleanup(&buffer->resource);
         buffer->resource.parent_ops->wined3d_object_destroyed(buffer->resource.parent);
         HeapFree(GetProcessHeap(), 0, buffer->maps);
@@ -805,14 +811,10 @@ void CDECL wined3d_buffer_preload(struct wined3d_buffer *buffer)
             return;
         }
 
-        /* The declaration changed, reload the whole buffer */
-        WARN("Reloading buffer because of decl change\n");
-        buffer_clear_dirty_areas(buffer);
-        if (!buffer_add_dirty_area(buffer, 0, 0))
-        {
-            ERR("buffer_add_dirty_area failed, this is not expected\n");
-            return;
-        }
+        /* The declaration changed, reload the whole buffer. */
+        WARN("Reloading buffer because of a vertex declaration change.\n");
+        buffer_invalidate_bo_range(buffer, 0, 0);
+
         /* Avoid unfenced updates, we might overwrite more areas of the buffer than the application
          * cleared for unsynchronized updates
          */
@@ -928,56 +930,6 @@ void CDECL wined3d_buffer_preload(struct wined3d_buffer *buffer)
     context_release(context);
 }
 
-static DWORD buffer_sanitize_flags(const struct wined3d_buffer *buffer, DWORD flags)
-{
-    /* Not all flags make sense together, but Windows never returns an error.
-     * Catch the cases that could cause issues. */
-    if (flags & WINED3D_MAP_READONLY)
-    {
-        if (flags & WINED3D_MAP_DISCARD)
-        {
-            WARN("WINED3D_MAP_READONLY combined with WINED3D_MAP_DISCARD, ignoring flags.\n");
-            return 0;
-        }
-        if (flags & WINED3D_MAP_NOOVERWRITE)
-        {
-            WARN("WINED3D_MAP_READONLY combined with WINED3D_MAP_NOOVERWRITE, ignoring flags.\n");
-            return 0;
-        }
-    }
-    else if ((flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE))
-            == (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE))
-    {
-        WARN("WINED3D_MAP_DISCARD and WINED3D_MAP_NOOVERWRITE used together, ignoring.\n");
-        return 0;
-    }
-    else if (flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE)
-            && !(buffer->resource.usage & WINED3DUSAGE_DYNAMIC))
-    {
-        WARN("DISCARD or NOOVERWRITE map on non-dynamic buffer, ignoring.\n");
-        return 0;
-    }
-
-    return flags;
-}
-
-static GLbitfield buffer_gl_map_flags(DWORD d3d_flags)
-{
-    GLbitfield ret = 0;
-
-    if (!(d3d_flags & WINED3D_MAP_READONLY))
-        ret |= GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT;
-    if (!(d3d_flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE)))
-        ret |= GL_MAP_READ_BIT;
-
-    if (d3d_flags & WINED3D_MAP_DISCARD)
-        ret |= GL_MAP_INVALIDATE_BUFFER_BIT;
-    if (d3d_flags & WINED3D_MAP_NOOVERWRITE)
-        ret |= GL_MAP_UNSYNCHRONIZED_BIT;
-
-    return ret;
-}
-
 struct wined3d_resource * CDECL wined3d_buffer_get_resource(struct wined3d_buffer *buffer)
 {
     TRACE("buffer %p.\n", buffer);
@@ -992,29 +944,20 @@ HRESULT CDECL wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UIN
 
     TRACE("buffer %p, offset %u, size %u, data %p, flags %#x\n", buffer, offset, size, data, flags);
 
-    flags = buffer_sanitize_flags(buffer, flags);
-    if (!(flags & WINED3D_MAP_READONLY))
-    {
-        if (flags & WINED3D_MAP_DISCARD)
-        {
-            /* DISCARD invalidates the entire buffer, regardless of the
-             * specified offset and size. Some applications also depend on the
-             * entire buffer being uploaded in that case. Two such
-             * applications are Port Royale and Darkstar One. */
-            if (!buffer_add_dirty_area(buffer, 0, 0))
-                return E_OUTOFMEMORY;
-        }
-        else
-        {
-            if (!buffer_add_dirty_area(buffer, offset, size))
-                return E_OUTOFMEMORY;
-        }
-    }
-
+    flags = wined3d_resource_sanitize_map_flags(&buffer->resource, flags);
     count = ++buffer->resource.map_count;
 
     if (buffer->buffer_object)
     {
+        /* DISCARD invalidates the entire buffer, regardless of the specified
+         * offset and size. Some applications also depend on the entire buffer
+         * being uploaded in that case. Two such applications are Port Royale
+         * and Darkstar One. */
+        if (flags & WINED3D_MAP_DISCARD)
+            buffer_invalidate_bo_range(buffer, 0, 0);
+        else if (!(flags & WINED3D_MAP_READONLY))
+            buffer_invalidate_bo_range(buffer, offset, size);
+
         if (!(buffer->flags & WINED3D_BUFFER_DOUBLEBUFFER))
         {
             if (count == 1)
@@ -1032,7 +975,7 @@ HRESULT CDECL wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UIN
 
                 if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
                 {
-                    GLbitfield mapflags = buffer_gl_map_flags(flags);
+                    GLbitfield mapflags = wined3d_resource_gl_map_flags(flags);
                     buffer->resource.allocatedMemory = GL_EXTCALL(glMapBufferRange(buffer->buffer_type_hint,
                             0, buffer->resource.size, mapflags));
                     checkGLcall("glMapBufferRange");
index 43b8718..84b5b58 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Context and render target management in wined3d
  *
- * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
+ * Copyright 2007-2011, 2013 Stefan Dösinger for CodeWeavers
  * Copyright 2009-2011 Henri Verbeet for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
 #include "wined3d_private.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
+WINE_DECLARE_DEBUG_CHANNEL(d3d_perf);
+WINE_DECLARE_DEBUG_CHANNEL(d3d_synchronous);
+
+#define WINED3D_MAX_FBO_ENTRIES 64
 
 static DWORD wined3d_context_tls_idx;
 
 /* FBO helper functions */
 
 /* Context activation is done by the caller. */
-static void context_bind_fbo(struct wined3d_context *context, GLenum target, GLuint *fbo)
+static void context_bind_fbo(struct wined3d_context *context, GLenum target, GLuint fbo)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
-    GLuint f;
-
-    if (!fbo)
-    {
-        f = 0;
-    }
-    else
-    {
-        if (!*fbo)
-        {
-            gl_info->fbo_ops.glGenFramebuffers(1, fbo);
-            checkGLcall("glGenFramebuffers()");
-            TRACE("Created FBO %u.\n", *fbo);
-        }
-        f = *fbo;
-    }
 
     switch (target)
     {
         case GL_READ_FRAMEBUFFER:
-            if (context->fbo_read_binding == f) return;
-            context->fbo_read_binding = f;
+            if (context->fbo_read_binding == fbo) return;
+            context->fbo_read_binding = fbo;
             break;
 
         case GL_DRAW_FRAMEBUFFER:
-            if (context->fbo_draw_binding == f) return;
-            context->fbo_draw_binding = f;
+            if (context->fbo_draw_binding == fbo) return;
+            context->fbo_draw_binding = fbo;
             break;
 
         case GL_FRAMEBUFFER:
-            if (context->fbo_read_binding == f
-                    && context->fbo_draw_binding == f) return;
-            context->fbo_read_binding = f;
-            context->fbo_draw_binding = f;
+            if (context->fbo_read_binding == fbo
+                    && context->fbo_draw_binding == fbo) return;
+            context->fbo_read_binding = fbo;
+            context->fbo_draw_binding = fbo;
             break;
 
         default:
@@ -80,7 +68,7 @@ static void context_bind_fbo(struct wined3d_context *context, GLenum target, GLu
             break;
     }
 
-    gl_info->fbo_ops.glBindFramebuffer(target, f);
+    gl_info->fbo_ops.glBindFramebuffer(target, fbo);
     checkGLcall("glBindFramebuffer()");
 }
 
@@ -102,15 +90,15 @@ static void context_clean_fbo_attachments(const struct wined3d_gl_info *gl_info,
 }
 
 /* Context activation is done by the caller. */
-static void context_destroy_fbo(struct wined3d_context *context, GLuint *fbo)
+static void context_destroy_fbo(struct wined3d_context *context, GLuint fbo)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
 
     context_bind_fbo(context, GL_FRAMEBUFFER, fbo);
     context_clean_fbo_attachments(gl_info, GL_FRAMEBUFFER);
-    context_bind_fbo(context, GL_FRAMEBUFFER, NULL);
+    context_bind_fbo(context, GL_FRAMEBUFFER, 0);
 
-    gl_info->fbo_ops.glDeleteFramebuffers(1, fbo);
+    gl_info->fbo_ops.glDeleteFramebuffers(1, &fbo);
     checkGLcall("glDeleteFramebuffers()");
 }
 
@@ -336,7 +324,9 @@ static struct fbo_entry *context_create_fbo_entry(const struct wined3d_context *
     entry->location = location;
     entry->rt_mask = context_generate_rt_mask(GL_COLOR_ATTACHMENT0);
     entry->attached = FALSE;
-    entry->id = 0;
+    gl_info->fbo_ops.glGenFramebuffers(1, &entry->id);
+    checkGLcall("glGenFramebuffers()");
+    TRACE("Created FBO %u.\n", entry->id);
 
     return entry;
 }
@@ -348,7 +338,7 @@ static void context_reuse_fbo_entry(struct wined3d_context *context, GLenum targ
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
 
-    context_bind_fbo(context, target, &entry->id);
+    context_bind_fbo(context, target, entry->id);
     context_clean_fbo_attachments(gl_info, target);
 
     memcpy(entry->render_targets, render_targets, gl_info->limits.buffers * sizeof(*entry->render_targets));
@@ -362,8 +352,8 @@ static void context_destroy_fbo_entry(struct wined3d_context *context, struct fb
 {
     if (entry->id)
     {
-        TRACE("Destroy FBO %d\n", entry->id);
-        context_destroy_fbo(context, &entry->id);
+        TRACE("Destroy FBO %u.\n", entry->id);
+        context_destroy_fbo(context, entry->id);
     }
     --context->fbo_entry_count;
     list_remove(&entry->entry);
@@ -422,10 +412,17 @@ static void context_apply_fbo_entry(struct wined3d_context *context, GLenum targ
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
     unsigned int i;
+    GLuint read_binding, draw_binding;
 
-    context_bind_fbo(context, target, &entry->id);
+    if (entry->attached)
+    {
+        context_bind_fbo(context, target, entry->id);
+        return;
+    }
 
-    if (entry->attached) return;
+    read_binding = context->fbo_read_binding;
+    draw_binding = context->fbo_draw_binding;
+    context_bind_fbo(context, GL_FRAMEBUFFER, entry->id);
 
     /* Apply render targets */
     for (i = 0; i < gl_info->limits.buffers; ++i)
@@ -438,6 +435,18 @@ static void context_apply_fbo_entry(struct wined3d_context *context, GLenum targ
         surface_set_compatible_renderbuffer(entry->depth_stencil, entry->render_targets[0]);
     context_attach_depth_stencil_fbo(context, target, entry->depth_stencil, entry->location);
 
+    /* Set valid read and draw buffer bindings to satisfy pedantic pre-ES2_compatibility
+     * GL contexts requirements. */
+    glReadBuffer(GL_NONE);
+    context_set_draw_buffer(context, GL_NONE);
+    if (target != GL_FRAMEBUFFER)
+    {
+        if (target == GL_READ_FRAMEBUFFER)
+            context_bind_fbo(context, GL_DRAW_FRAMEBUFFER, draw_binding);
+        else
+            context_bind_fbo(context, GL_READ_FRAMEBUFFER, read_binding);
+    }
+
     entry->attached = TRUE;
 }
 
@@ -454,14 +463,14 @@ static void context_apply_fbo_state(struct wined3d_context *context, GLenum targ
 
     if (context->rebind_fbo)
     {
-        context_bind_fbo(context, GL_FRAMEBUFFER, NULL);
+        context_bind_fbo(context, GL_FRAMEBUFFER, 0);
         context->rebind_fbo = FALSE;
     }
 
     if (location == SFLAG_INDRAWABLE)
     {
         context->current_fbo = NULL;
-        context_bind_fbo(context, target, NULL);
+        context_bind_fbo(context, target, 0);
     }
     else
     {
@@ -1257,6 +1266,37 @@ static void bind_dummy_textures(const struct wined3d_device *device, const struc
     }
 }
 
+BOOL context_debug_output_enabled(const struct wined3d_gl_info *gl_info)
+{
+    return gl_info->supported[ARB_DEBUG_OUTPUT]
+            && (ERR_ON(d3d) || FIXME_ON(d3d) || WARN_ON(d3d_perf));
+}
+
+static void WINE_GLAPI wined3d_debug_callback(GLenum source, GLenum type, GLuint id,
+        GLenum severity, GLsizei length, const char *message, void *ctx)
+{
+    switch (type)
+    {
+        case GL_DEBUG_TYPE_ERROR_ARB:
+            ERR("%p: %s.\n", ctx, debugstr_an(message, length));
+            break;
+
+        case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB:
+        case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB:
+        case GL_DEBUG_TYPE_PORTABILITY_ARB:
+            FIXME("%p: %s.\n", ctx, debugstr_an(message, length));
+            break;
+
+        case GL_DEBUG_TYPE_PERFORMANCE_ARB:
+            WARN_(d3d_perf)("%p: %s.\n", ctx, debugstr_an(message, length));
+            break;
+
+        default:
+            FIXME("ctx %p, type %#x: %s.\n", ctx, type, debugstr_an(message, length));
+            break;
+    }
+}
+
 /* Do not call while under the GL lock. */
 struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
         struct wined3d_surface *target, const struct wined3d_format *ds_format)
@@ -1266,11 +1306,11 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
     const struct wined3d_format *color_format;
     struct wined3d_context *ret;
     BOOL auxBuffers = FALSE;
+    HGLRC ctx, share_ctx;
     int pixel_format;
     unsigned int s;
     int swap_interval;
     DWORD state;
-    HGLRC ctx;
     HDC hdc;
 
     TRACE("swapchain %p, target %p, window %p.\n", swapchain, target, swapchain->win_handle);
@@ -1307,6 +1347,12 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
     list_init(&ret->fbo_list);
     list_init(&ret->fbo_destroy_list);
 
+    if (!device->shader_backend->shader_allocate_context_data(ret))
+    {
+        ERR("Failed to allocate shader backend context data.\n");
+        goto out;
+    }
+
     if (!(hdc = GetDC(swapchain->win_handle)))
     {
         WARN("Failed to retireve device context, trying swapchain backup.\n");
@@ -1367,19 +1413,38 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
         goto out;
     }
 
-    if (!(ctx = wglCreateContext(hdc)))
+    share_ctx = device->context_count ? device->contexts[0]->glCtx : NULL;
+    if (gl_info->p_wglCreateContextAttribsARB)
     {
-        ERR("Failed to create a WGL context.\n");
-        context_release(ret);
-        goto out;
-    }
+        unsigned int ctx_attrib_idx = 0;
+        GLint ctx_attribs[3];
 
-    if (device->context_count)
+        if (context_debug_output_enabled(gl_info))
+        {
+            ctx_attribs[ctx_attrib_idx++] = WGL_CONTEXT_FLAGS_ARB;
+            ctx_attribs[ctx_attrib_idx++] = WGL_CONTEXT_DEBUG_BIT_ARB;
+        }
+        ctx_attribs[ctx_attrib_idx] = 0;
+
+        if (!(ctx = gl_info->p_wglCreateContextAttribsARB(hdc, share_ctx, ctx_attribs)))
+        {
+            ERR("Failed to create a WGL context.\n");
+            context_release(ret);
+            goto out;
+        }
+    }
+    else
     {
-        if (!wglShareLists(device->contexts[0]->glCtx, ctx))
+        if (!(ctx = wglCreateContext(hdc)))
+        {
+            ERR("Failed to create a WGL context.\n");
+            context_release(ret);
+            goto out;
+        }
+
+        if (share_ctx && !wglShareLists(share_ctx, ctx))
         {
-            ERR("wglShareLists(%p, %p) failed, last error %#x.\n",
-                    device->contexts[0]->glCtx, ctx, GetLastError());
+            ERR("wglShareLists(%p, %p) failed, last error %#x.\n", share_ctx, ctx, GetLastError());
             context_release(ret);
             if (!wglDeleteContext(ctx))
                 ERR("wglDeleteContext(%p) failed, last error %#x.\n", ctx, GetLastError());
@@ -1397,6 +1462,7 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
     }
 
     ret->gl_info = gl_info;
+    ret->d3d_info = &device->adapter->d3d_info;
     ret->state_table = device->StateTable;
 
     /* Mark all states dirty to force a proper initialization of the states
@@ -1431,6 +1497,33 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
         goto out;
     }
 
+    if (context_debug_output_enabled(gl_info))
+    {
+        GL_EXTCALL(glDebugMessageCallbackARB(wined3d_debug_callback, ret));
+        if (TRACE_ON(d3d_synchronous))
+            gl_info->gl_ops.gl.p_glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
+        GL_EXTCALL(glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_FALSE));
+        if (ERR_ON(d3d))
+        {
+            GL_EXTCALL(glDebugMessageControlARB(GL_DONT_CARE, GL_DEBUG_TYPE_ERROR_ARB,
+                    GL_DONT_CARE, 0, NULL, GL_TRUE));
+        }
+        if (FIXME_ON(d3d))
+        {
+            GL_EXTCALL(glDebugMessageControlARB(GL_DONT_CARE, GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB,
+                    GL_DONT_CARE, 0, NULL, GL_TRUE));
+            GL_EXTCALL(glDebugMessageControlARB(GL_DONT_CARE, GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB,
+                    GL_DONT_CARE, 0, NULL, GL_TRUE));
+            GL_EXTCALL(glDebugMessageControlARB(GL_DONT_CARE, GL_DEBUG_TYPE_PORTABILITY_ARB,
+                    GL_DONT_CARE, 0, NULL, GL_TRUE));
+        }
+        if (WARN_ON(d3d_perf))
+        {
+            GL_EXTCALL(glDebugMessageControlARB(GL_DONT_CARE, GL_DEBUG_TYPE_PERFORMANCE_ARB,
+                    GL_DONT_CARE, 0, NULL, GL_TRUE));
+        }
+    }
+
     switch (swapchain->desc.swap_interval)
     {
         case WINED3DPRESENT_INTERVAL_IMMEDIATE:
@@ -1464,14 +1557,6 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
     gl_info->gl_ops.gl.p_glGetIntegerv(GL_AUX_BUFFERS, &ret->aux_buffers);
 
     TRACE("Setting up the screen\n");
-    /* Clear the screen */
-    gl_info->gl_ops.gl.p_glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
-    checkGLcall("glClearColor");
-    gl_info->gl_ops.gl.p_glClearIndex(0);
-    gl_info->gl_ops.gl.p_glClearDepth(1);
-    gl_info->gl_ops.gl.p_glClearStencil(0xffff);
-
-    checkGLcall("glClear");
 
     gl_info->gl_ops.gl.p_glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
     checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
@@ -1487,13 +1572,6 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
     gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_ALIGNMENT, device->surface_alignment);
     checkGLcall("glPixelStorei(GL_UNPACK_ALIGNMENT, device->surface_alignment);");
 
-    if (gl_info->supported[APPLE_CLIENT_STORAGE])
-    {
-        /* Most textures will use client storage if supported. Exceptions are
-         * non-native power of 2 textures and textures in DIB sections. */
-        gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
-        checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
-    }
     if (gl_info->supported[ARB_VERTEX_BLEND])
     {
         /* Direct3D always uses n-1 weights for n world matrices and uses
@@ -1554,7 +1632,9 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
     {
         GL_EXTCALL(glProvokingVertexEXT(GL_FIRST_VERTEX_CONVENTION_EXT));
     }
-    ret->select_shader = 1;
+    ret->shader_update_mask = (1 << WINED3D_SHADER_TYPE_PIXEL)
+            | (1 << WINED3D_SHADER_TYPE_VERTEX)
+            | (1 << WINED3D_SHADER_TYPE_GEOMETRY);
 
     /* If this happens to be the first context for the device, dummy textures
      * are not created yet. In that case, they will be created (and bound) by
@@ -1567,6 +1647,7 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
     return ret;
 
 out:
+    device->shader_backend->shader_free_context_data(ret);
     HeapFree(GetProcessHeap(), 0, ret->free_event_queries);
     HeapFree(GetProcessHeap(), 0, ret->free_occlusion_queries);
     HeapFree(GetProcessHeap(), 0, ret->draw_buffers);
@@ -1599,6 +1680,7 @@ void context_destroy(struct wined3d_device *device, struct wined3d_context *cont
         destroy = FALSE;
     }
 
+    device->shader_backend->shader_free_context_data(context);
     HeapFree(GetProcessHeap(), 0, context->draw_buffers);
     HeapFree(GetProcessHeap(), 0, context->blit_targets);
     device_context_remove(device, context);
@@ -1628,8 +1710,7 @@ static void context_get_rt_size(const struct wined3d_context *context, SIZE *siz
 {
     const struct wined3d_surface *rt = context->current_rt;
 
-    if (rt->container.type == WINED3D_CONTAINER_SWAPCHAIN
-            && rt->container.u.swapchain->front_buffer == rt)
+    if (rt->swapchain && rt->swapchain->front_buffer == rt)
     {
         RECT window_size;
 
@@ -1831,9 +1912,7 @@ static void SetupForBlit(const struct wined3d_device *device, struct wined3d_con
     set_blit_dimension(gl_info, rt_size.cx, rt_size.cy);
 
     /* Disable shaders */
-    device->shader_backend->shader_select(context, WINED3D_SHADER_MODE_NONE, WINED3D_SHADER_MODE_NONE);
-    context->select_shader = 1;
-    context->load_constants = 1;
+    device->shader_backend->shader_disable(device->shader_priv, context);
 
     context->blit_w = rt_size.cx;
     context->blit_h = rt_size.cy;
@@ -1905,13 +1984,16 @@ static void context_apply_draw_buffers(struct wined3d_context *context, DWORD rt
 void context_set_draw_buffer(struct wined3d_context *context, GLenum buffer)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
+    DWORD *current_mask = context->current_fbo ? &context->current_fbo->rt_mask : &context->draw_buffers_mask;
+    DWORD new_mask = context_generate_rt_mask(buffer);
+
+    if (new_mask == *current_mask)
+        return;
 
     gl_info->gl_ops.gl.p_glDrawBuffer(buffer);
     checkGLcall("glDrawBuffer()");
-    if (context->current_fbo)
-        context->current_fbo->rt_mask = context_generate_rt_mask(buffer);
-    else
-        context->draw_buffers_mask = context_generate_rt_mask(buffer);
+
+    *current_mask = new_mask;
 }
 
 /* Context activation is done by the caller. */
@@ -2006,7 +2088,7 @@ static void context_validate_onscreen_formats(struct wined3d_context *context,
         const struct wined3d_surface *depth_stencil)
 {
     /* Onscreen surfaces are always in a swapchain */
-    struct wined3d_swapchain *swapchain = context->current_rt->container.u.swapchain;
+    struct wined3d_swapchain *swapchain = context->current_rt->swapchain;
 
     if (context->render_offscreen || !depth_stencil) return;
     if (match_depth_stencil_format(swapchain->ds_format, depth_stencil->resource.format)) return;
@@ -2027,7 +2109,7 @@ static DWORD context_generate_rt_mask_no_fbo(const struct wined3d_device *device
 {
     if (!rt || rt->resource.format->id == WINED3DFMT_NULL)
         return 0;
-    else if (rt->container.type == WINED3D_CONTAINER_SWAPCHAIN)
+    else if (rt->swapchain)
         return context_generate_rt_mask_from_surface(rt);
     else
         return context_generate_rt_mask(device->offscreenBuffer);
@@ -2055,7 +2137,8 @@ void context_apply_blit_state(struct wined3d_context *context, const struct wine
         }
         else
         {
-            context_bind_fbo(context, GL_FRAMEBUFFER, NULL);
+            context->current_fbo = NULL;
+            context_bind_fbo(context, GL_FRAMEBUFFER, 0);
             rt_mask = context_generate_rt_mask_from_surface(rt);
         }
     }
@@ -2132,8 +2215,6 @@ BOOL context_apply_clear_state(struct wined3d_context *context, const struct win
                 }
                 context_apply_fbo_state(context, GL_FRAMEBUFFER, context->blit_targets, fb->depth_stencil,
                         rt_count ? rts[0]->draw_binding : SFLAG_INTEXTURE);
-                gl_info->gl_ops.gl.p_glReadBuffer(GL_NONE);
-                checkGLcall("glReadBuffer");
             }
             else
             {
@@ -2197,7 +2278,7 @@ BOOL context_apply_clear_state(struct wined3d_context *context, const struct win
 
 static DWORD find_draw_buffers_mask(const struct wined3d_context *context, const struct wined3d_device *device)
 {
-    const struct wined3d_state *state = &device->stateBlock->state;
+    const struct wined3d_state *state = &device->state;
     struct wined3d_surface **rts = state->fb->render_targets;
     struct wined3d_shader *ps = state->pixel_shader;
     DWORD rt_mask, rt_mask_bits;
@@ -2207,7 +2288,7 @@ static DWORD find_draw_buffers_mask(const struct wined3d_context *context, const
     else if (!context->render_offscreen) return context_generate_rt_mask_from_surface(rts[0]);
 
     rt_mask = ps ? ps->reg_maps.rt_mask : 1;
-    rt_mask &= device->valid_rt_mask;
+    rt_mask &= context->d3d_info->valid_rt_mask;
     rt_mask_bits = rt_mask;
     i = 0;
     while (rt_mask_bits)
@@ -2226,7 +2307,6 @@ static DWORD find_draw_buffers_mask(const struct wined3d_context *context, const
 void context_state_fb(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     const struct wined3d_device *device = context->swapchain->device;
-    const struct wined3d_gl_info *gl_info = context->gl_info;
     const struct wined3d_fb_state *fb = state->fb;
     DWORD rt_mask = find_draw_buffers_mask(context, device);
     DWORD *cur_mask;
@@ -2241,8 +2321,6 @@ void context_state_fb(struct wined3d_context *context, const struct wined3d_stat
         {
             context_apply_fbo_state(context, GL_FRAMEBUFFER, fb->render_targets, fb->depth_stencil,
                     fb->render_targets[0]->draw_binding);
-            gl_info->gl_ops.gl.p_glReadBuffer(GL_NONE);
-            checkGLcall("glReadBuffer");
         }
     }
 
@@ -2274,7 +2352,7 @@ void context_state_drawbuf(struct wined3d_context *context, const struct wined3d
 /* Context activation is done by the caller. */
 BOOL context_apply_draw_state(struct wined3d_context *context, struct wined3d_device *device)
 {
-    const struct wined3d_state *state = &device->stateBlock->state;
+    const struct wined3d_state *state = &device->state;
     const struct StateEntry *state_table = context->state_table;
     const struct wined3d_fb_state *fb = state->fb;
     unsigned int i;
@@ -2297,7 +2375,7 @@ BOOL context_apply_draw_state(struct wined3d_context *context, struct wined3d_de
         device_update_stream_info(device, context->gl_info);
     if (state->index_buffer)
     {
-        if (device->strided_streams.all_vbo)
+        if (device->stream_info.all_vbo)
             wined3d_buffer_preload(state->index_buffer);
         else
             buffer_get_sysmem(state->index_buffer, context->gl_info);
@@ -2312,18 +2390,16 @@ BOOL context_apply_draw_state(struct wined3d_context *context, struct wined3d_de
         state_table[rep].apply(context, state, rep);
     }
 
-    if (context->select_shader)
+    if (context->shader_update_mask)
     {
-        device->shader_backend->shader_select(context,
-                use_vs(state) ? WINED3D_SHADER_MODE_SHADER : WINED3D_SHADER_MODE_FFP,
-                use_ps(state) ? WINED3D_SHADER_MODE_SHADER : WINED3D_SHADER_MODE_FFP);
-        context->select_shader = 0;
+        device->shader_backend->shader_select(device->shader_priv, context, state);
+        context->shader_update_mask = 0;
     }
 
-    if (context->load_constants)
+    if (context->constant_update_mask)
     {
-        device->shader_backend->shader_load_constants(context, use_ps(state), use_vs(state));
-        context->load_constants = 0;
+        device->shader_backend->shader_load_constants(device->shader_priv, context, state);
+        context->constant_update_mask = 0;
     }
 
     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
@@ -2422,11 +2498,11 @@ struct wined3d_context *context_acquire(const struct wined3d_device *device, str
     {
         context = current_context;
     }
-    else if (target->container.type == WINED3D_CONTAINER_SWAPCHAIN)
+    else if (target->swapchain)
     {
         TRACE("Rendering onscreen.\n");
 
-        context = swapchain_get_context(target->container.u.swapchain);
+        context = swapchain_get_context(target->swapchain);
     }
     else
     {
index 119ed28..d3d358c 100644 (file)
@@ -35,6 +35,7 @@
 #include "wined3d_private.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
+WINE_DECLARE_DEBUG_CHANNEL(d3d_perf);
 
 /* Define the default light parameters as specified by MSDN. */
 const struct wined3d_light WINED3D_default_light =
@@ -52,17 +53,6 @@ const struct wined3d_light WINED3D_default_light =
     0.0f                        /* Phi */
 };
 
-/**********************************************************
- * Global variable / Constants follow
- **********************************************************/
-const struct wined3d_matrix identity =
-{{{
-    1.0f, 0.0f, 0.0f, 0.0f,
-    0.0f, 1.0f, 0.0f, 0.0f,
-    0.0f, 0.0f, 1.0f, 0.0f,
-    0.0f, 0.0f, 0.0f, 1.0f,
-}}};  /* When needed for comparisons */
-
 /* Note that except for WINED3DPT_POINTLIST and WINED3DPT_LINELIST these
  * actually have the same values in GL and D3D. */
 GLenum gl_primitive_type_from_d3d(enum wined3d_primitive_type primitive_type)
@@ -176,7 +166,7 @@ static BOOL fixed_get_input(BYTE usage, BYTE usage_idx, unsigned int *regnum)
 /* Context activation is done by the caller. */
 static void device_stream_info_from_declaration(struct wined3d_device *device, struct wined3d_stream_info *stream_info)
 {
-    const struct wined3d_state *state = &device->stateBlock->state;
+    const struct wined3d_state *state = &device->state;
     /* We need to deal with frequency data! */
     struct wined3d_vertex_declaration *declaration = state->vertex_declaration;
     BOOL use_vshader;
@@ -221,7 +211,7 @@ static void device_stream_info_from_declaration(struct wined3d_device *device, s
          * drawStridedSlow() is needed, including a vertex buffer path. */
         if (state->load_base_vertex_index < 0)
         {
-            WARN("load_base_vertex_index is < 0 (%d), not using VBOs.\n", state->load_base_vertex_index);
+            WARN_(d3d_perf)("load_base_vertex_index is < 0 (%d), not using VBOs.\n", state->load_base_vertex_index);
             data.buffer_object = 0;
             data.addr = buffer_get_sysmem(buffer, &device->adapter->gl_info);
             if ((UINT_PTR)data.addr < -state->load_base_vertex_index * stride)
@@ -317,8 +307,8 @@ static void device_stream_info_from_declaration(struct wined3d_device *device, s
 /* Context activation is done by the caller. */
 void device_update_stream_info(struct wined3d_device *device, const struct wined3d_gl_info *gl_info)
 {
-    struct wined3d_stream_info *stream_info = &device->strided_streams;
-    const struct wined3d_state *state = &device->stateBlock->state;
+    struct wined3d_stream_info *stream_info = &device->stream_info;
+    const struct wined3d_state *state = &device->state;
     DWORD prev_all_vbo = stream_info->all_vbo;
 
     TRACE("============================= Vertex Declaration =============================\n");
@@ -342,14 +332,11 @@ void device_update_stream_info(struct wined3d_device *device, const struct wined
         slow_mask |= -!gl_info->supported[ARB_VERTEX_ARRAY_BGRA]
                 & ((1 << WINED3D_FFP_DIFFUSE) | (1 << WINED3D_FFP_SPECULAR));
 
-        if ((stream_info->position_transformed || (stream_info->use_map & slow_mask)) && !stream_info->all_vbo)
-        {
+        if (((stream_info->position_transformed && !device->adapter->d3d_info.xyzrhw)
+                || (stream_info->use_map & slow_mask)) && !stream_info->all_vbo)
             device->useDrawStridedSlow = TRUE;
-        }
         else
-        {
             device->useDrawStridedSlow = FALSE;
-        }
     }
 
     if (prev_all_vbo != stream_info->all_vbo)
@@ -368,7 +355,7 @@ static void device_preload_texture(const struct wined3d_state *state, unsigned i
 
 void device_preload_textures(const struct wined3d_device *device)
 {
-    const struct wined3d_state *state = &device->stateBlock->state;
+    const struct wined3d_state *state = &device->state;
     unsigned int i;
 
     if (use_vs(state))
@@ -501,6 +488,14 @@ static void prepare_ds_clear(struct wined3d_surface *ds, struct wined3d_context
 {
     RECT current_rect, r;
 
+    if (ds->flags & SFLAG_DISCARDED)
+    {
+        /* Depth buffer was discarded, make it entirely current in its new location since
+         * there is no other place where we would get data anyway. */
+        SetRect(out_rect, 0, 0, ds->resource.width, ds->resource.height);
+        return;
+    }
+
     if (ds->flags & location)
         SetRect(&current_rect, 0, 0,
                 ds->ds_current_size.cx,
@@ -717,8 +712,7 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c
     }
 
     if (wined3d_settings.strict_draw_ordering || (flags & WINED3DCLEAR_TARGET
-            && target->container.type == WINED3D_CONTAINER_SWAPCHAIN
-            && target->container.u.swapchain->front_buffer == target))
+            && target->swapchain && target->swapchain->front_buffer == target))
         gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */
 
     context_release(context);
@@ -741,18 +735,13 @@ ULONG CDECL wined3d_device_decref(struct wined3d_device *device)
 
     if (!refcount)
     {
-        struct wined3d_stateblock *stateblock;
         UINT i;
 
-        if (wined3d_stateblock_decref(device->updateStateBlock)
-                && device->updateStateBlock != device->stateBlock)
-            FIXME("Something's still holding the update stateblock.\n");
-        device->updateStateBlock = NULL;
+        if (device->recording && wined3d_stateblock_decref(device->recording))
+            FIXME("Something's still holding the recording stateblock.\n");
+        device->recording = NULL;
 
-        stateblock = device->stateBlock;
-        device->stateBlock = NULL;
-        if (wined3d_stateblock_decref(stateblock))
-            FIXME("Something's still holding the stateblock.\n");
+        state_cleanup(&device->state);
 
         for (i = 0; i < sizeof(device->multistate_funcs) / sizeof(device->multistate_funcs[0]); ++i)
         {
@@ -877,13 +866,6 @@ static void create_dummy_textures(struct wined3d_device *device, struct wined3d_
      * We emulate this by creating dummy textures and binding them
      * to each texture stage when the currently set D3D texture is NULL. */
 
-    if (gl_info->supported[APPLE_CLIENT_STORAGE])
-    {
-        /* The dummy texture does not have client storage backing */
-        gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
-        checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
-    }
-
     count = min(MAX_COMBINED_SAMPLERS, gl_info->limits.combined_samplers);
     for (i = 0; i < count; ++i)
     {
@@ -947,13 +929,6 @@ static void create_dummy_textures(struct wined3d_device *device, struct wined3d_
             }
         }
     }
-
-    if (gl_info->supported[APPLE_CLIENT_STORAGE])
-    {
-        /* Re-enable because if supported it is enabled by default */
-        gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
-        checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
-    }
 }
 
 /* Context activation is done by the caller. */
@@ -982,10 +957,10 @@ static void destroy_dummy_textures(struct wined3d_device *device, const struct w
     gl_info->gl_ops.gl.p_glDeleteTextures(count, device->dummy_texture_2d);
     checkGLcall("glDeleteTextures(count, device->dummy_texture_2d)");
 
-    memset(device->dummy_texture_cube, 0, gl_info->limits.textures * sizeof(*device->dummy_texture_cube));
-    memset(device->dummy_texture_3d, 0, gl_info->limits.textures * sizeof(*device->dummy_texture_3d));
-    memset(device->dummy_texture_rect, 0, gl_info->limits.textures * sizeof(*device->dummy_texture_rect));
-    memset(device->dummy_texture_2d, 0, gl_info->limits.textures * sizeof(*device->dummy_texture_2d));
+    memset(device->dummy_texture_cube, 0, count * sizeof(*device->dummy_texture_cube));
+    memset(device->dummy_texture_3d, 0, count * sizeof(*device->dummy_texture_3d));
+    memset(device->dummy_texture_rect, 0, count * sizeof(*device->dummy_texture_rect));
+    memset(device->dummy_texture_2d, 0, count * sizeof(*device->dummy_texture_2d));
 }
 
 static LONG fullscreen_style(LONG style)
@@ -1032,7 +1007,7 @@ void CDECL wined3d_device_setup_fullscreen_window(struct wined3d_device *device,
 
     SetWindowLongW(window, GWL_STYLE, style);
     SetWindowLongW(window, GWL_EXSTYLE, exstyle);
-    SetWindowPos(window, HWND_TOP, 0, 0, w, h, SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOACTIVATE);
+    SetWindowPos(window, HWND_TOPMOST, 0, 0, w, h, SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOACTIVATE);
 
     device->filter_messages = filter_messages;
 }
@@ -1044,12 +1019,21 @@ void CDECL wined3d_device_restore_fullscreen_window(struct wined3d_device *devic
 
     if (!device->style && !device->exStyle) return;
 
-    TRACE("Restoring window style of window %p to %08x, %08x.\n",
-            window, device->style, device->exStyle);
-
     style = GetWindowLongW(window, GWL_STYLE);
     exstyle = GetWindowLongW(window, GWL_EXSTYLE);
 
+    /* These flags are set by wined3d_device_setup_fullscreen_window, not the
+     * application, and we want to ignore them in the test below, since it's
+     * not the application's fault that they changed. Additionally, we want to
+     * preserve the current status of these flags (i.e. don't restore them) to
+     * more closely emulate the behavior of Direct3D, which leaves these flags
+     * alone when returning to windowed mode. */
+    device->style ^= (device->style ^ style) & WS_VISIBLE;
+    device->exStyle ^= (device->exStyle ^ exstyle) & WS_EX_TOPMOST;
+
+    TRACE("Restoring window style of window %p to %08x, %08x.\n",
+            window, device->style, device->exStyle);
+
     filter_messages = device->filter_messages;
     device->filter_messages = TRUE;
 
@@ -1104,7 +1088,6 @@ HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device,
     struct wined3d_context *context;
     HRESULT hr;
     DWORD state;
-    unsigned int i;
 
     TRACE("device %p, swapchain_desc %p.\n", device, swapchain_desc);
 
@@ -1113,9 +1096,6 @@ HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device,
     if (device->wined3d->flags & WINED3D_NO3D)
         return WINED3DERR_INVALIDCALL;
 
-    device->valid_rt_mask = 0;
-    for (i = 0; i < gl_info->limits.buffers; ++i)
-        device->valid_rt_mask |= (1 << i);
     device->fb.render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
             sizeof(*device->fb.render_targets) * gl_info->limits.buffers);
 
@@ -1134,7 +1114,8 @@ HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device,
         }
     }
 
-    if (FAILED(hr = device->shader_backend->shader_alloc_private(device, device->adapter->fragment_pipe)))
+    if (FAILED(hr = device->shader_backend->shader_alloc_private(device,
+            device->adapter->vertex_pipe, device->adapter->fragment_pipe)))
     {
         TRACE("Shader private data couldn't be allocated\n");
         goto err_out;
@@ -1184,14 +1165,12 @@ HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device,
     /* Set up some starting GL setup */
 
     /* Setup all the devices defaults */
-    stateblock_init_default_state(device->stateBlock);
+    state_init_default(&device->state, device);
 
     context = context_acquire(device, swapchain->front_buffer);
 
     create_dummy_textures(device, context);
 
-    /* Initialize the current view state */
-    device->view_ident = 1;
     device->contexts[0]->last_was_rhw = 0;
 
     switch (wined3d_settings.offscreen_rendering_mode)
@@ -1302,7 +1281,7 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device)
     if (device->logo_surface)
         wined3d_surface_decref(device->logo_surface);
 
-    stateblock_unbind_resources(device->stateBlock);
+    state_unbind_resources(&device->state);
 
     /* Unload resources */
     LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &device->resources, struct wined3d_resource, resource_list_entry)
@@ -1331,6 +1310,7 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device)
     /* Destroy the shader backend. Note that this has to happen after all shaders are destroyed. */
     device->blitter->free_private(device);
     device->shader_backend->shader_free_private(device);
+    destroy_dummy_textures(device, gl_info);
 
     /* Release the buffers (with sanity checks)*/
     if (device->onscreen_depth_stencil)
@@ -1445,11 +1425,11 @@ void CDECL wined3d_device_set_stream_output(struct wined3d_device *device, UINT
         return;
     }
 
-    prev_buffer = device->updateStateBlock->state.stream_output[idx].buffer;
-    device->updateStateBlock->state.stream_output[idx].buffer = buffer;
-    device->updateStateBlock->state.stream_output[idx].offset = offset;
+    prev_buffer = device->update_state->stream_output[idx].buffer;
+    device->update_state->stream_output[idx].buffer = buffer;
+    device->update_state->stream_output[idx].offset = offset;
 
-    if (device->isRecordingState)
+    if (device->recording)
     {
         if (buffer)
             wined3d_buffer_incref(buffer);
@@ -1484,8 +1464,8 @@ struct wined3d_buffer * CDECL wined3d_device_get_stream_output(struct wined3d_de
         return NULL;
     }
 
-    *offset = device->stateBlock->state.stream_output[idx].offset;
-    return device->stateBlock->state.stream_output[idx].buffer;
+    *offset = device->state.stream_output[idx].offset;
+    return device->state.stream_output[idx].buffer;
 }
 
 HRESULT CDECL wined3d_device_set_stream_source(struct wined3d_device *device, UINT stream_idx,
@@ -1508,10 +1488,11 @@ HRESULT CDECL wined3d_device_set_stream_source(struct wined3d_device *device, UI
         return WINED3DERR_INVALIDCALL;
     }
 
-    stream = &device->updateStateBlock->state.streams[stream_idx];
+    stream = &device->update_state->streams[stream_idx];
     prev_buffer = stream->buffer;
 
-    device->updateStateBlock->changed.streamSource |= 1 << stream_idx;
+    if (device->recording)
+        device->recording->changed.streamSource |= 1 << stream_idx;
 
     if (prev_buffer == buffer
             && stream->stride == stride
@@ -1529,7 +1510,7 @@ HRESULT CDECL wined3d_device_set_stream_source(struct wined3d_device *device, UI
     }
 
     /* Handle recording of state blocks. */
-    if (device->isRecordingState)
+    if (device->recording)
     {
         TRACE("Recording... not performing anything.\n");
         if (buffer)
@@ -1558,7 +1539,7 @@ HRESULT CDECL wined3d_device_set_stream_source(struct wined3d_device *device, UI
 HRESULT CDECL wined3d_device_get_stream_source(const struct wined3d_device *device,
         UINT stream_idx, struct wined3d_buffer **buffer, UINT *offset, UINT *stride)
 {
-    struct wined3d_stream_state *stream;
+    const struct wined3d_stream_state *stream;
 
     TRACE("device %p, stream_idx %u, buffer %p, offset %p, stride %p.\n",
             device, stream_idx, buffer, offset, stride);
@@ -1569,7 +1550,7 @@ HRESULT CDECL wined3d_device_get_stream_source(const struct wined3d_device *devi
         return WINED3DERR_INVALIDCALL;
     }
 
-    stream = &device->stateBlock->state.streams[stream_idx];
+    stream = &device->state.streams[stream_idx];
     *buffer = stream->buffer;
     if (*buffer)
         wined3d_buffer_incref(*buffer);
@@ -1604,16 +1585,16 @@ HRESULT CDECL wined3d_device_set_stream_source_freq(struct wined3d_device *devic
         return WINED3DERR_INVALIDCALL;
     }
 
-    stream = &device->updateStateBlock->state.streams[stream_idx];
+    stream = &device->update_state->streams[stream_idx];
     old_flags = stream->flags;
     old_freq = stream->frequency;
 
     stream->flags = divider & (WINED3DSTREAMSOURCE_INSTANCEDATA | WINED3DSTREAMSOURCE_INDEXEDDATA);
     stream->frequency = divider & 0x7fffff;
 
-    device->updateStateBlock->changed.streamFreq |= 1 << stream_idx;
-
-    if (stream->frequency != old_freq || stream->flags != old_flags)
+    if (device->recording)
+        device->recording->changed.streamFreq |= 1 << stream_idx;
+    else if (stream->frequency != old_freq || stream->flags != old_flags)
         device_invalidate_state(device, STATE_STREAMSRC);
 
     return WINED3D_OK;
@@ -1622,11 +1603,11 @@ HRESULT CDECL wined3d_device_set_stream_source_freq(struct wined3d_device *devic
 HRESULT CDECL wined3d_device_get_stream_source_freq(const struct wined3d_device *device,
         UINT stream_idx, UINT *divider)
 {
-    struct wined3d_stream_state *stream;
+    const struct wined3d_stream_state *stream;
 
     TRACE("device %p, stream_idx %u, divider %p.\n", device, stream_idx, divider);
 
-    stream = &device->updateStateBlock->state.streams[stream_idx];
+    stream = &device->state.streams[stream_idx];
     *divider = stream->flags | stream->frequency;
 
     TRACE("Returning %#x.\n", *divider);
@@ -1645,11 +1626,11 @@ void CDECL wined3d_device_set_transform(struct wined3d_device *device,
     TRACE("%.8e %.8e %.8e %.8e\n", matrix->u.s._41, matrix->u.s._42, matrix->u.s._43, matrix->u.s._44);
 
     /* Handle recording of state blocks. */
-    if (device->isRecordingState)
+    if (device->recording)
     {
         TRACE("Recording... not performing anything.\n");
-        device->updateStateBlock->changed.transform[d3dts >> 5] |= 1 << (d3dts & 0x1f);
-        device->updateStateBlock->state.transforms[d3dts] = *matrix;
+        device->recording->changed.transform[d3dts >> 5] |= 1 << (d3dts & 0x1f);
+        device->update_state->transforms[d3dts] = *matrix;
         return;
     }
 
@@ -1659,15 +1640,13 @@ void CDECL wined3d_device_set_transform(struct wined3d_device *device,
      * tend towards setting the same matrix repeatedly for some reason.
      *
      * From here on we assume that the new matrix is different, wherever it matters. */
-    if (!memcmp(&device->stateBlock->state.transforms[d3dts].u.m[0][0], matrix, sizeof(*matrix)))
+    if (!memcmp(&device->state.transforms[d3dts].u.m[0][0], matrix, sizeof(*matrix)))
     {
         TRACE("The application is setting the same matrix over again.\n");
         return;
     }
 
-    device->stateBlock->state.transforms[d3dts] = *matrix;
-    if (d3dts == WINED3D_TS_VIEW)
-        device->view_ident = !memcmp(matrix, &identity, sizeof(identity));
+    device->state.transforms[d3dts] = *matrix;
 
     if (d3dts < WINED3D_TS_WORLD_MATRIX(device->adapter->gl_info.limits.blends))
         device_invalidate_state(device, STATE_TRANSFORM(d3dts));
@@ -1678,7 +1657,7 @@ void CDECL wined3d_device_get_transform(const struct wined3d_device *device,
 {
     TRACE("device %p, state %s, matrix %p.\n", device, debug_d3dtstype(state), matrix);
 
-    *matrix = device->stateBlock->state.transforms[state];
+    *matrix = device->state.transforms[state];
 }
 
 void CDECL wined3d_device_multiply_transform(struct wined3d_device *device,
@@ -1699,7 +1678,7 @@ void CDECL wined3d_device_multiply_transform(struct wined3d_device *device,
         return;
     }
 
-    mat = &device->updateStateBlock->state.transforms[state];
+    mat = &device->update_state->transforms[state];
     multiply_matrix(&temp, mat, matrix);
 
     /* Apply change via set transform - will reapply to eg. lights this way. */
@@ -1752,7 +1731,7 @@ HRESULT CDECL wined3d_device_set_light(struct wined3d_device *device,
         return WINED3DERR_INVALIDCALL;
     }
 
-    LIST_FOR_EACH(e, &device->updateStateBlock->state.light_map[hash_idx])
+    LIST_FOR_EACH(e, &device->update_state->light_map[hash_idx])
     {
         object = LIST_ENTRY(e, struct wined3d_light_info, entry);
         if (object->OriginalIndex == light_idx)
@@ -1767,7 +1746,7 @@ HRESULT CDECL wined3d_device_set_light(struct wined3d_device *device,
         if (!object)
             return E_OUTOFMEMORY;
 
-        list_add_head(&device->updateStateBlock->state.light_map[hash_idx], &object->entry);
+        list_add_head(&device->update_state->light_map[hash_idx], &object->entry);
         object->glIndex = -1;
         object->OriginalIndex = light_idx;
     }
@@ -1783,6 +1762,14 @@ HRESULT CDECL wined3d_device_set_light(struct wined3d_device *device,
     TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n",
             light->range, light->falloff, light->theta, light->phi);
 
+    /* Update the live definitions if the light is currently assigned a glIndex. */
+    if (object->glIndex != -1 && !device->recording)
+    {
+        if (object->OriginalParms.type != light->type)
+            device_invalidate_state(device, STATE_LIGHT_TYPE);
+        device_invalidate_state(device, STATE_ACTIVELIGHT(object->glIndex));
+    }
+
     /* Save away the information. */
     object->OriginalParms = *light;
 
@@ -1855,10 +1842,6 @@ HRESULT CDECL wined3d_device_set_light(struct wined3d_device *device,
             FIXME("Unrecognized light type %#x.\n", light->type);
     }
 
-    /* Update the live definitions if the light is currently assigned a glIndex. */
-    if (object->glIndex != -1 && !device->isRecordingState)
-        device_invalidate_state(device, STATE_ACTIVELIGHT(object->glIndex));
-
     return WINED3D_OK;
 }
 
@@ -1871,7 +1854,7 @@ HRESULT CDECL wined3d_device_get_light(const struct wined3d_device *device,
 
     TRACE("device %p, light_idx %u, light %p.\n", device, light_idx, light);
 
-    LIST_FOR_EACH(e, &device->stateBlock->state.light_map[hash_idx])
+    LIST_FOR_EACH(e, &device->state.light_map[hash_idx])
     {
         light_info = LIST_ENTRY(e, struct wined3d_light_info, entry);
         if (light_info->OriginalIndex == light_idx)
@@ -1897,7 +1880,7 @@ HRESULT CDECL wined3d_device_set_light_enable(struct wined3d_device *device, UIN
 
     TRACE("device %p, light_idx %u, enable %#x.\n", device, light_idx, enable);
 
-    LIST_FOR_EACH(e, &device->updateStateBlock->state.light_map[hash_idx])
+    LIST_FOR_EACH(e, &device->update_state->light_map[hash_idx])
     {
         light_info = LIST_ENTRY(e, struct wined3d_light_info, entry);
         if (light_info->OriginalIndex == light_idx)
@@ -1913,7 +1896,7 @@ HRESULT CDECL wined3d_device_set_light_enable(struct wined3d_device *device, UIN
         wined3d_device_set_light(device, light_idx, &WINED3D_default_light);
 
         /* Search for it again! Should be fairly quick as near head of list. */
-        LIST_FOR_EACH(e, &device->updateStateBlock->state.light_map[hash_idx])
+        LIST_FOR_EACH(e, &device->update_state->light_map[hash_idx])
         {
             light_info = LIST_ENTRY(e, struct wined3d_light_info, entry);
             if (light_info->OriginalIndex == light_idx)
@@ -1931,10 +1914,13 @@ HRESULT CDECL wined3d_device_set_light_enable(struct wined3d_device *device, UIN
     {
         if (light_info->glIndex != -1)
         {
-            if (!device->isRecordingState)
+            if (!device->recording)
+            {
+                device_invalidate_state(device, STATE_LIGHT_TYPE);
                 device_invalidate_state(device, STATE_ACTIVELIGHT(light_info->glIndex));
+            }
 
-            device->updateStateBlock->state.lights[light_info->glIndex] = NULL;
+            device->update_state->lights[light_info->glIndex] = NULL;
             light_info->glIndex = -1;
         }
         else
@@ -1957,9 +1943,9 @@ HRESULT CDECL wined3d_device_set_light_enable(struct wined3d_device *device, UIN
             /* Find a free GL light. */
             for (i = 0; i < gl_info->limits.lights; ++i)
             {
-                if (!device->updateStateBlock->state.lights[i])
+                if (!device->update_state->lights[i])
                 {
-                    device->updateStateBlock->state.lights[i] = light_info;
+                    device->update_state->lights[i] = light_info;
                     light_info->glIndex = i;
                     break;
                 }
@@ -1977,8 +1963,11 @@ HRESULT CDECL wined3d_device_set_light_enable(struct wined3d_device *device, UIN
             }
 
             /* i == light_info->glIndex */
-            if (!device->isRecordingState)
+            if (!device->recording)
+            {
+                device_invalidate_state(device, STATE_LIGHT_TYPE);
                 device_invalidate_state(device, STATE_ACTIVELIGHT(i));
+            }
         }
     }
 
@@ -1993,7 +1982,7 @@ HRESULT CDECL wined3d_device_get_light_enable(const struct wined3d_device *devic
 
     TRACE("device %p, light_idx %u, enable %p.\n", device, light_idx, enable);
 
-    LIST_FOR_EACH(e, &device->stateBlock->state.light_map[hash_idx])
+    LIST_FOR_EACH(e, &device->state.light_map[hash_idx])
     {
         light_info = LIST_ENTRY(e, struct wined3d_light_info, entry);
         if (light_info->OriginalIndex == light_idx)
@@ -2023,18 +2012,19 @@ HRESULT CDECL wined3d_device_set_clip_plane(struct wined3d_device *device,
         return WINED3DERR_INVALIDCALL;
     }
 
-    device->updateStateBlock->changed.clipplane |= 1 << plane_idx;
+    if (device->recording)
+        device->recording->changed.clipplane |= 1 << plane_idx;
 
-    if (!memcmp(&device->updateStateBlock->state.clip_planes[plane_idx], plane, sizeof(*plane)))
+    if (!memcmp(&device->update_state->clip_planes[plane_idx], plane, sizeof(*plane)))
     {
         TRACE("Application is setting old values over, nothing to do.\n");
         return WINED3D_OK;
     }
 
-    device->updateStateBlock->state.clip_planes[plane_idx] = *plane;
+    device->update_state->clip_planes[plane_idx] = *plane;
 
     /* Handle recording of state blocks. */
-    if (device->isRecordingState)
+    if (device->recording)
     {
         TRACE("Recording... not performing anything.\n");
         return WINED3D_OK;
@@ -2057,7 +2047,7 @@ HRESULT CDECL wined3d_device_get_clip_plane(const struct wined3d_device *device,
         return WINED3DERR_INVALIDCALL;
     }
 
-    *plane = device->stateBlock->state.clip_planes[plane_idx];
+    *plane = device->state.clip_planes[plane_idx];
 
     return WINED3D_OK;
 }
@@ -2088,12 +2078,12 @@ void CDECL wined3d_device_set_material(struct wined3d_device *device, const stru
 {
     TRACE("device %p, material %p.\n", device, material);
 
-    device->updateStateBlock->changed.material = TRUE;
-    device->updateStateBlock->state.material = *material;
+    device->update_state->material = *material;
 
     /* Handle recording of state blocks */
-    if (device->isRecordingState)
+    if (device->recording)
     {
+        device->recording->changed.material = TRUE;
         TRACE("Recording... not performing anything.\n");
         return;
     }
@@ -2105,7 +2095,7 @@ void CDECL wined3d_device_get_material(const struct wined3d_device *device, stru
 {
     TRACE("device %p, material %p.\n", device, material);
 
-    *material = device->updateStateBlock->state.material;
+    *material = device->state.material;
 
     TRACE("diffuse {%.8e, %.8e, %.8e, %.8e}\n",
             material->diffuse.r, material->diffuse.g,
@@ -2130,16 +2120,16 @@ void CDECL wined3d_device_set_index_buffer(struct wined3d_device *device,
     TRACE("device %p, buffer %p, format %s.\n",
             device, buffer, debug_d3dformat(format_id));
 
-    prev_buffer = device->updateStateBlock->state.index_buffer;
+    prev_buffer = device->update_state->index_buffer;
 
-    device->updateStateBlock->changed.indices = TRUE;
-    device->updateStateBlock->state.index_buffer = buffer;
-    device->updateStateBlock->state.index_format = format_id;
+    device->update_state->index_buffer = buffer;
+    device->update_state->index_format = format_id;
 
     /* Handle recording of state blocks. */
-    if (device->isRecordingState)
+    if (device->recording)
     {
         TRACE("Recording... not performing anything.\n");
+        device->recording->changed.indices = TRUE;
         if (buffer)
             wined3d_buffer_incref(buffer);
         if (prev_buffer)
@@ -2168,22 +2158,22 @@ struct wined3d_buffer * CDECL wined3d_device_get_index_buffer(const struct wined
 {
     TRACE("device %p, format %p.\n", device, format);
 
-    *format = device->stateBlock->state.index_format;
-    return device->stateBlock->state.index_buffer;
+    *format = device->state.index_format;
+    return device->state.index_buffer;
 }
 
 void CDECL wined3d_device_set_base_vertex_index(struct wined3d_device *device, INT base_index)
 {
     TRACE("device %p, base_index %d.\n", device, base_index);
 
-    device->updateStateBlock->state.base_vertex_index = base_index;
+    device->update_state->base_vertex_index = base_index;
 }
 
 INT CDECL wined3d_device_get_base_vertex_index(const struct wined3d_device *device)
 {
     TRACE("device %p.\n", device);
 
-    return device->stateBlock->state.base_vertex_index;
+    return device->state.base_vertex_index;
 }
 
 void CDECL wined3d_device_set_viewport(struct wined3d_device *device, const struct wined3d_viewport *viewport)
@@ -2192,13 +2182,13 @@ void CDECL wined3d_device_set_viewport(struct wined3d_device *device, const stru
     TRACE("x %u, y %u, w %u, h %u, min_z %.8e, max_z %.8e.\n",
           viewport->x, viewport->y, viewport->width, viewport->height, viewport->min_z, viewport->max_z);
 
-    device->updateStateBlock->changed.viewport = TRUE;
-    device->updateStateBlock->state.viewport = *viewport;
+    device->update_state->viewport = *viewport;
 
     /* Handle recording of state blocks */
-    if (device->isRecordingState)
+    if (device->recording)
     {
         TRACE("Recording... not performing anything\n");
+        device->recording->changed.viewport = TRUE;
         return;
     }
 
@@ -2209,23 +2199,39 @@ void CDECL wined3d_device_get_viewport(const struct wined3d_device *device, stru
 {
     TRACE("device %p, viewport %p.\n", device, viewport);
 
-    *viewport = device->stateBlock->state.viewport;
+    *viewport = device->state.viewport;
+}
+
+static void resolve_depth_buffer(struct wined3d_state *state)
+{
+    struct wined3d_texture *texture = state->textures[0];
+    struct wined3d_surface *depth_stencil, *surface;
+
+    if (!texture || texture->resource.type != WINED3D_RTYPE_TEXTURE
+            || !(texture->resource.format->flags & WINED3DFMT_FLAG_DEPTH))
+        return;
+    surface = surface_from_resource(texture->sub_resources[0]);
+    depth_stencil = state->fb->depth_stencil;
+    if (!depth_stencil)
+        return;
+
+    wined3d_surface_blt(surface, NULL, depth_stencil, NULL, 0, NULL, WINED3D_TEXF_POINT);
 }
 
 void CDECL wined3d_device_set_render_state(struct wined3d_device *device,
         enum wined3d_render_state state, DWORD value)
 {
-    DWORD old_value = device->stateBlock->state.render_states[state];
+    DWORD old_value = device->state.render_states[state];
 
     TRACE("device %p, state %s (%#x), value %#x.\n", device, debug_d3drenderstate(state), state, value);
 
-    device->updateStateBlock->changed.renderState[state >> 5] |= 1 << (state & 0x1f);
-    device->updateStateBlock->state.render_states[state] = value;
+    device->update_state->render_states[state] = value;
 
     /* Handle recording of state blocks. */
-    if (device->isRecordingState)
+    if (device->recording)
     {
         TRACE("Recording... not performing anything.\n");
+        device->recording->changed.renderState[state >> 5] |= 1 << (state & 0x1f);
         return;
     }
 
@@ -2234,13 +2240,19 @@ void CDECL wined3d_device_set_render_state(struct wined3d_device *device,
         TRACE("Application is setting the old value over, nothing to do.\n");
     else
         device_invalidate_state(device, STATE_RENDER(state));
+
+    if (state == WINED3D_RS_POINTSIZE && value == WINED3D_RESZ_CODE)
+    {
+        TRACE("RESZ multisampled depth buffer resolve triggered.\n");
+        resolve_depth_buffer(&device->state);
+    }
 }
 
 DWORD CDECL wined3d_device_get_render_state(const struct wined3d_device *device, enum wined3d_render_state state)
 {
     TRACE("device %p, state %s (%#x).\n", device, debug_d3drenderstate(state), state);
 
-    return device->stateBlock->state.render_states[state];
+    return device->state.render_states[state];
 }
 
 void CDECL wined3d_device_set_sampler_state(struct wined3d_device *device,
@@ -2254,21 +2266,20 @@ void CDECL wined3d_device_set_sampler_state(struct wined3d_device *device,
     if (sampler_idx >= WINED3DVERTEXTEXTURESAMPLER0 && sampler_idx <= WINED3DVERTEXTEXTURESAMPLER3)
         sampler_idx -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS);
 
-    if (sampler_idx >= sizeof(device->stateBlock->state.sampler_states)
-            / sizeof(*device->stateBlock->state.sampler_states))
+    if (sampler_idx >= sizeof(device->state.sampler_states) / sizeof(*device->state.sampler_states))
     {
         WARN("Invalid sampler %u.\n", sampler_idx);
         return; /* Windows accepts overflowing this array ... we do not. */
     }
 
-    old_value = device->stateBlock->state.sampler_states[sampler_idx][state];
-    device->updateStateBlock->state.sampler_states[sampler_idx][state] = value;
-    device->updateStateBlock->changed.samplerState[sampler_idx] |= 1 << state;
+    old_value = device->state.sampler_states[sampler_idx][state];
+    device->update_state->sampler_states[sampler_idx][state] = value;
 
     /* Handle recording of state blocks. */
-    if (device->isRecordingState)
+    if (device->recording)
     {
         TRACE("Recording... not performing anything.\n");
+        device->recording->changed.samplerState[sampler_idx] |= 1 << state;
         return;
     }
 
@@ -2290,29 +2301,30 @@ DWORD CDECL wined3d_device_get_sampler_state(const struct wined3d_device *device
     if (sampler_idx >= WINED3DVERTEXTEXTURESAMPLER0 && sampler_idx <= WINED3DVERTEXTEXTURESAMPLER3)
         sampler_idx -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS);
 
-    if (sampler_idx >= sizeof(device->stateBlock->state.sampler_states)
-            / sizeof(*device->stateBlock->state.sampler_states))
+    if (sampler_idx >= sizeof(device->state.sampler_states) / sizeof(*device->state.sampler_states))
     {
         WARN("Invalid sampler %u.\n", sampler_idx);
         return 0; /* Windows accepts overflowing this array ... we do not. */
     }
 
-    return device->stateBlock->state.sampler_states[sampler_idx][state];
+    return device->state.sampler_states[sampler_idx][state];
 }
 
 void CDECL wined3d_device_set_scissor_rect(struct wined3d_device *device, const RECT *rect)
 {
     TRACE("device %p, rect %s.\n", device, wine_dbgstr_rect(rect));
 
-    device->updateStateBlock->changed.scissorRect = TRUE;
-    if (EqualRect(&device->updateStateBlock->state.scissor_rect, rect))
+    if (device->recording)
+        device->recording->changed.scissorRect = TRUE;
+
+    if (EqualRect(&device->update_state->scissor_rect, rect))
     {
         TRACE("App is setting the old scissor rectangle over, nothing to do.\n");
         return;
     }
-    CopyRect(&device->updateStateBlock->state.scissor_rect, rect);
+    CopyRect(&device->update_state->scissor_rect, rect);
 
-    if (device->isRecordingState)
+    if (device->recording)
     {
         TRACE("Recording... not performing anything.\n");
         return;
@@ -2325,14 +2337,14 @@ void CDECL wined3d_device_get_scissor_rect(const struct wined3d_device *device,
 {
     TRACE("device %p, rect %p.\n", device, rect);
 
-    *rect = device->updateStateBlock->state.scissor_rect;
+    *rect = device->state.scissor_rect;
     TRACE("Returning rect %s.\n", wine_dbgstr_rect(rect));
 }
 
 void CDECL wined3d_device_set_vertex_declaration(struct wined3d_device *device,
         struct wined3d_vertex_declaration *declaration)
 {
-    struct wined3d_vertex_declaration *prev = device->updateStateBlock->state.vertex_declaration;
+    struct wined3d_vertex_declaration *prev = device->update_state->vertex_declaration;
 
     TRACE("device %p, declaration %p.\n", device, declaration);
 
@@ -2341,12 +2353,12 @@ void CDECL wined3d_device_set_vertex_declaration(struct wined3d_device *device,
     if (prev)
         wined3d_vertex_declaration_decref(prev);
 
-    device->updateStateBlock->state.vertex_declaration = declaration;
-    device->updateStateBlock->changed.vertexDecl = TRUE;
+    device->update_state->vertex_declaration = declaration;
 
-    if (device->isRecordingState)
+    if (device->recording)
     {
         TRACE("Recording... not performing anything.\n");
+        device->recording->changed.vertexDecl = TRUE;
         return;
     }
 
@@ -2364,12 +2376,12 @@ struct wined3d_vertex_declaration * CDECL wined3d_device_get_vertex_declaration(
 {
     TRACE("device %p.\n", device);
 
-    return device->stateBlock->state.vertex_declaration;
+    return device->state.vertex_declaration;
 }
 
 void CDECL wined3d_device_set_vertex_shader(struct wined3d_device *device, struct wined3d_shader *shader)
 {
-    struct wined3d_shader *prev = device->updateStateBlock->state.vertex_shader;
+    struct wined3d_shader *prev = device->update_state->vertex_shader;
 
     TRACE("device %p, shader %p.\n", device, shader);
 
@@ -2378,12 +2390,12 @@ void CDECL wined3d_device_set_vertex_shader(struct wined3d_device *device, struc
     if (prev)
         wined3d_shader_decref(prev);
 
-    device->updateStateBlock->state.vertex_shader = shader;
-    device->updateStateBlock->changed.vertexShader = TRUE;
+    device->update_state->vertex_shader = shader;
 
-    if (device->isRecordingState)
+    if (device->recording)
     {
         TRACE("Recording... not performing anything.\n");
+        device->recording->changed.vertexShader = TRUE;
         return;
     }
 
@@ -2400,7 +2412,7 @@ struct wined3d_shader * CDECL wined3d_device_get_vertex_shader(const struct wine
 {
     TRACE("device %p.\n", device);
 
-    return device->stateBlock->state.vertex_shader;
+    return device->state.vertex_shader;
 }
 
 void CDECL wined3d_device_set_vs_cb(struct wined3d_device *device, UINT idx, struct wined3d_buffer *buffer)
@@ -2415,10 +2427,10 @@ void CDECL wined3d_device_set_vs_cb(struct wined3d_device *device, UINT idx, str
         return;
     }
 
-    prev = device->updateStateBlock->state.vs_cb[idx];
-    device->updateStateBlock->state.vs_cb[idx] = buffer;
+    prev = device->update_state->vs_cb[idx];
+    device->update_state->vs_cb[idx] = buffer;
 
-    if (device->isRecordingState)
+    if (device->recording)
     {
         if (buffer)
             wined3d_buffer_incref(buffer);
@@ -2452,7 +2464,7 @@ struct wined3d_buffer * CDECL wined3d_device_get_vs_cb(const struct wined3d_devi
         return NULL;
     }
 
-    return device->stateBlock->state.vs_cb[idx];
+    return device->state.vs_cb[idx];
 }
 
 void CDECL wined3d_device_set_vs_sampler(struct wined3d_device *device, UINT idx, struct wined3d_sampler *sampler)
@@ -2467,8 +2479,8 @@ void CDECL wined3d_device_set_vs_sampler(struct wined3d_device *device, UINT idx
         return;
     }
 
-    prev = device->updateStateBlock->state.vs_sampler[idx];
-    device->updateStateBlock->state.vs_sampler[idx] = sampler;
+    prev = device->update_state->vs_sampler[idx];
+    device->update_state->vs_sampler[idx] = sampler;
 
     if (sampler)
         wined3d_sampler_incref(sampler);
@@ -2486,7 +2498,17 @@ struct wined3d_sampler * CDECL wined3d_device_get_vs_sampler(const struct wined3
         return NULL;
     }
 
-    return device->stateBlock->state.vs_sampler[idx];
+    return device->state.vs_sampler[idx];
+}
+
+void device_invalidate_shader_constants(const struct wined3d_device *device, DWORD mask)
+{
+    UINT i;
+
+    for (i = 0; i < device->context_count; ++i)
+    {
+        device->contexts[i]->constant_update_mask |= mask;
+    }
 }
 
 HRESULT CDECL wined3d_device_set_vs_consts_b(struct wined3d_device *device,
@@ -2501,15 +2523,19 @@ HRESULT CDECL wined3d_device_set_vs_consts_b(struct wined3d_device *device,
     if (!constants || start_register >= MAX_CONST_B)
         return WINED3DERR_INVALIDCALL;
 
-    memcpy(&device->updateStateBlock->state.vs_consts_b[start_register], constants, count * sizeof(BOOL));
+    memcpy(&device->update_state->vs_consts_b[start_register], constants, count * sizeof(BOOL));
     for (i = 0; i < count; ++i)
         TRACE("Set BOOL constant %u to %s.\n", start_register + i, constants[i] ? "true" : "false");
 
-    for (i = start_register; i < count + start_register; ++i)
-        device->updateStateBlock->changed.vertexShaderConstantsB |= (1 << i);
-
-    if (!device->isRecordingState)
-        device_invalidate_state(device, STATE_VERTEXSHADERCONSTANT);
+    if (device->recording)
+    {
+        for (i = start_register; i < count + start_register; ++i)
+            device->recording->changed.vertexShaderConstantsB |= (1 << i);
+    }
+    else
+    {
+        device_invalidate_shader_constants(device, WINED3D_SHADER_CONST_VS_B);
+    }
 
     return WINED3D_OK;
 }
@@ -2525,7 +2551,7 @@ HRESULT CDECL wined3d_device_get_vs_consts_b(const struct wined3d_device *device
     if (!constants || start_register >= MAX_CONST_B)
         return WINED3DERR_INVALIDCALL;
 
-    memcpy(constants, &device->stateBlock->state.vs_consts_b[start_register], count * sizeof(BOOL));
+    memcpy(constants, &device->state.vs_consts_b[start_register], count * sizeof(BOOL));
 
     return WINED3D_OK;
 }
@@ -2542,17 +2568,21 @@ HRESULT CDECL wined3d_device_set_vs_consts_i(struct wined3d_device *device,
     if (!constants || start_register >= MAX_CONST_I)
         return WINED3DERR_INVALIDCALL;
 
-    memcpy(&device->updateStateBlock->state.vs_consts_i[start_register * 4], constants, count * sizeof(int) * 4);
+    memcpy(&device->update_state->vs_consts_i[start_register * 4], constants, count * sizeof(int) * 4);
     for (i = 0; i < count; ++i)
         TRACE("Set INT constant %u to {%d, %d, %d, %d}.\n", start_register + i,
                 constants[i * 4], constants[i * 4 + 1],
                 constants[i * 4 + 2], constants[i * 4 + 3]);
 
-    for (i = start_register; i < count + start_register; ++i)
-        device->updateStateBlock->changed.vertexShaderConstantsI |= (1 << i);
-
-    if (!device->isRecordingState)
-        device_invalidate_state(device, STATE_VERTEXSHADERCONSTANT);
+    if (device->recording)
+    {
+        for (i = start_register; i < count + start_register; ++i)
+            device->recording->changed.vertexShaderConstantsI |= (1 << i);
+    }
+    else
+    {
+        device_invalidate_shader_constants(device, WINED3D_SHADER_CONST_VS_I);
+    }
 
     return WINED3D_OK;
 }
@@ -2568,7 +2598,7 @@ HRESULT CDECL wined3d_device_get_vs_consts_i(const struct wined3d_device *device
     if (!constants || start_register >= MAX_CONST_I)
         return WINED3DERR_INVALIDCALL;
 
-    memcpy(constants, &device->stateBlock->state.vs_consts_i[start_register * 4], count * sizeof(int) * 4);
+    memcpy(constants, &device->state.vs_consts_i[start_register * 4], count * sizeof(int) * 4);
     return WINED3D_OK;
 }
 
@@ -2576,6 +2606,7 @@ HRESULT CDECL wined3d_device_set_vs_consts_f(struct wined3d_device *device,
         UINT start_register, const float *constants, UINT vector4f_count)
 {
     UINT i;
+    const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
 
     TRACE("device %p, start_register %u, constants %p, vector4f_count %u.\n",
             device, start_register, constants, vector4f_count);
@@ -2583,11 +2614,11 @@ HRESULT CDECL wined3d_device_set_vs_consts_f(struct wined3d_device *device,
     /* Specifically test start_register > limit to catch MAX_UINT overflows
      * when adding start_register + vector4f_count. */
     if (!constants
-            || start_register + vector4f_count > device->d3d_vshader_constantF
-            || start_register > device->d3d_vshader_constantF)
+            || start_register + vector4f_count > d3d_info->limits.vs_uniform_count
+            || start_register > d3d_info->limits.vs_uniform_count)
         return WINED3DERR_INVALIDCALL;
 
-    memcpy(&device->updateStateBlock->state.vs_consts_f[start_register * 4],
+    memcpy(&device->update_state->vs_consts_f[start_register * 4],
             constants, vector4f_count * sizeof(float) * 4);
     if (TRACE_ON(d3d))
     {
@@ -2597,14 +2628,12 @@ HRESULT CDECL wined3d_device_set_vs_consts_f(struct wined3d_device *device,
                     constants[i * 4 + 2], constants[i * 4 + 3]);
     }
 
-    if (!device->isRecordingState)
-    {
+    if (device->recording)
+        memset(device->recording->changed.vertexShaderConstantsF + start_register, 1,
+                sizeof(*device->recording->changed.vertexShaderConstantsF) * vector4f_count);
+    else
         device->shader_backend->shader_update_float_vertex_constants(device, start_register, vector4f_count);
-        device_invalidate_state(device, STATE_VERTEXSHADERCONSTANT);
-    }
 
-    memset(device->updateStateBlock->changed.vertexShaderConstantsF + start_register, 1,
-            sizeof(*device->updateStateBlock->changed.vertexShaderConstantsF) * vector4f_count);
 
     return WINED3D_OK;
 }
@@ -2612,7 +2641,8 @@ HRESULT CDECL wined3d_device_set_vs_consts_f(struct wined3d_device *device,
 HRESULT CDECL wined3d_device_get_vs_consts_f(const struct wined3d_device *device,
         UINT start_register, float *constants, UINT vector4f_count)
 {
-    int count = min(vector4f_count, device->d3d_vshader_constantF - start_register);
+    const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
+    int count = min(vector4f_count, d3d_info->limits.vs_uniform_count - start_register);
 
     TRACE("device %p, start_register %u, constants %p, vector4f_count %u.\n",
             device, start_register, constants, vector4f_count);
@@ -2620,7 +2650,7 @@ HRESULT CDECL wined3d_device_get_vs_consts_f(const struct wined3d_device *device
     if (!constants || count < 0)
         return WINED3DERR_INVALIDCALL;
 
-    memcpy(constants, &device->stateBlock->state.vs_consts_f[start_register * 4], count * sizeof(float) * 4);
+    memcpy(constants, &device->state.vs_consts_f[start_register * 4], count * sizeof(float) * 4);
 
     return WINED3D_OK;
 }
@@ -2656,7 +2686,7 @@ static void device_update_fixed_function_usage_map(struct wined3d_device *device
     device->fixed_function_usage_map = 0;
     for (i = 0; i < MAX_TEXTURES; ++i)
     {
-        const struct wined3d_state *state = &device->stateBlock->state;
+        const struct wined3d_state *state = &device->state;
         enum wined3d_texture_op color_op = state->texture_states[i][WINED3D_TSS_COLOR_OP];
         enum wined3d_texture_op alpha_op = state->texture_states[i][WINED3D_TSS_ALPHA_OP];
         DWORD color_arg1 = state->texture_states[i][WINED3D_TSS_COLOR_ARG1] & WINED3DTA_SELECTMASK;
@@ -2686,7 +2716,7 @@ static void device_update_fixed_function_usage_map(struct wined3d_device *device
     }
 }
 
-static void device_map_fixed_function_samplers(struct wined3d_device *device, const struct wined3d_gl_info *gl_info)
+static void device_map_fixed_function_samplers(struct wined3d_device *device, const struct wined3d_d3d_info *d3d_info)
 {
     unsigned int i, tex;
     WORD ffu_map;
@@ -2694,8 +2724,8 @@ static void device_map_fixed_function_samplers(struct wined3d_device *device, co
     device_update_fixed_function_usage_map(device);
     ffu_map = device->fixed_function_usage_map;
 
-    if (device->max_ffp_textures == gl_info->limits.texture_stages
-            || device->stateBlock->state.lowest_disabled_stage <= device->max_ffp_textures)
+    if (d3d_info->limits.ffp_textures == d3d_info->limits.ffp_blend_stages
+            || device->state.lowest_disabled_stage <= d3d_info->limits.ffp_textures)
     {
         for (i = 0; ffu_map; ffu_map >>= 1, ++i)
         {
@@ -2728,10 +2758,10 @@ static void device_map_fixed_function_samplers(struct wined3d_device *device, co
     }
 }
 
-static void device_map_psamplers(struct wined3d_device *device, const struct wined3d_gl_info *gl_info)
+static void device_map_psamplers(struct wined3d_device *device, const struct wined3d_d3d_info *d3d_info)
 {
     const enum wined3d_sampler_texture_type *sampler_type =
-            device->stateBlock->state.pixel_shader->reg_maps.sampler_type;
+            device->state.pixel_shader->reg_maps.sampler_type;
     unsigned int i;
 
     for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i)
@@ -2740,7 +2770,7 @@ static void device_map_psamplers(struct wined3d_device *device, const struct win
         {
             device_map_stage(device, i, i);
             device_invalidate_state(device, STATE_SAMPLER(i));
-            if (i < gl_info->limits.texture_stages)
+            if (i < d3d_info->limits.ffp_blend_stages)
                 device_invalidate_texture_stage(device, i);
         }
     }
@@ -2774,7 +2804,7 @@ static BOOL device_unit_free_for_vs(const struct wined3d_device *device,
 static void device_map_vsamplers(struct wined3d_device *device, BOOL ps, const struct wined3d_gl_info *gl_info)
 {
     const enum wined3d_sampler_texture_type *vshader_sampler_type =
-            device->stateBlock->state.vertex_shader->reg_maps.sampler_type;
+            device->state.vertex_shader->reg_maps.sampler_type;
     const enum wined3d_sampler_texture_type *pshader_sampler_type = NULL;
     int start = min(MAX_COMBINED_SAMPLERS, gl_info->limits.combined_samplers) - 1;
     int i;
@@ -2783,7 +2813,7 @@ static void device_map_vsamplers(struct wined3d_device *device, BOOL ps, const s
     {
         /* Note that we only care if a sampler is sampled or not, not the sampler's specific type.
          * Otherwise we'd need to call shader_update_samplers() here for 1.x pixelshaders. */
-        pshader_sampler_type = device->stateBlock->state.pixel_shader->reg_maps.sampler_type;
+        pshader_sampler_type = device->state.pixel_shader->reg_maps.sampler_type;
     }
 
     for (i = 0; i < MAX_VERTEX_SAMPLERS; ++i) {
@@ -2816,7 +2846,8 @@ static void device_map_vsamplers(struct wined3d_device *device, BOOL ps, const s
 void device_update_tex_unit_map(struct wined3d_device *device)
 {
     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
-    const struct wined3d_state *state = &device->stateBlock->state;
+    const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
+    const struct wined3d_state *state = &device->state;
     BOOL vs = use_vs(state);
     BOOL ps = use_ps(state);
     /*
@@ -2827,9 +2858,9 @@ void device_update_tex_unit_map(struct wined3d_device *device)
      * to be reset. Because of that try to work with a 1:1 mapping as much as possible
      */
     if (ps)
-        device_map_psamplers(device, gl_info);
+        device_map_psamplers(device, d3d_info);
     else
-        device_map_fixed_function_samplers(device, gl_info);
+        device_map_fixed_function_samplers(device, d3d_info);
 
     if (vs)
         device_map_vsamplers(device, ps, gl_info);
@@ -2837,7 +2868,7 @@ void device_update_tex_unit_map(struct wined3d_device *device)
 
 void CDECL wined3d_device_set_pixel_shader(struct wined3d_device *device, struct wined3d_shader *shader)
 {
-    struct wined3d_shader *prev = device->updateStateBlock->state.pixel_shader;
+    struct wined3d_shader *prev = device->update_state->pixel_shader;
 
     TRACE("device %p, shader %p.\n", device, shader);
 
@@ -2846,12 +2877,12 @@ void CDECL wined3d_device_set_pixel_shader(struct wined3d_device *device, struct
     if (prev)
         wined3d_shader_decref(prev);
 
-    device->updateStateBlock->state.pixel_shader = shader;
-    device->updateStateBlock->changed.pixelShader = TRUE;
+    device->update_state->pixel_shader = shader;
 
-    if (device->isRecordingState)
+    if (device->recording)
     {
         TRACE("Recording... not performing anything.\n");
+        device->recording->changed.pixelShader = TRUE;
         return;
     }
 
@@ -2868,7 +2899,7 @@ struct wined3d_shader * CDECL wined3d_device_get_pixel_shader(const struct wined
 {
     TRACE("device %p.\n", device);
 
-    return device->stateBlock->state.pixel_shader;
+    return device->state.pixel_shader;
 }
 
 void CDECL wined3d_device_set_ps_cb(struct wined3d_device *device, UINT idx, struct wined3d_buffer *buffer)
@@ -2883,10 +2914,10 @@ void CDECL wined3d_device_set_ps_cb(struct wined3d_device *device, UINT idx, str
         return;
     }
 
-    prev = device->updateStateBlock->state.ps_cb[idx];
-    device->updateStateBlock->state.ps_cb[idx] = buffer;
+    prev = device->update_state->ps_cb[idx];
+    device->update_state->ps_cb[idx] = buffer;
 
-    if (device->isRecordingState)
+    if (device->recording)
     {
         if (buffer)
             wined3d_buffer_incref(buffer);
@@ -2920,7 +2951,7 @@ struct wined3d_buffer * CDECL wined3d_device_get_ps_cb(const struct wined3d_devi
         return NULL;
     }
 
-    return device->stateBlock->state.ps_cb[idx];
+    return device->state.ps_cb[idx];
 }
 
 void CDECL wined3d_device_set_ps_sampler(struct wined3d_device *device, UINT idx, struct wined3d_sampler *sampler)
@@ -2935,8 +2966,8 @@ void CDECL wined3d_device_set_ps_sampler(struct wined3d_device *device, UINT idx
         return;
     }
 
-    prev = device->updateStateBlock->state.ps_sampler[idx];
-    device->updateStateBlock->state.ps_sampler[idx] = sampler;
+    prev = device->update_state->ps_sampler[idx];
+    device->update_state->ps_sampler[idx] = sampler;
 
     if (sampler)
         wined3d_sampler_incref(sampler);
@@ -2954,7 +2985,7 @@ struct wined3d_sampler * CDECL wined3d_device_get_ps_sampler(const struct wined3
         return NULL;
     }
 
-    return device->stateBlock->state.ps_sampler[idx];
+    return device->state.ps_sampler[idx];
 }
 
 HRESULT CDECL wined3d_device_set_ps_consts_b(struct wined3d_device *device,
@@ -2969,15 +3000,19 @@ HRESULT CDECL wined3d_device_set_ps_consts_b(struct wined3d_device *device,
     if (!constants || start_register >= MAX_CONST_B)
         return WINED3DERR_INVALIDCALL;
 
-    memcpy(&device->updateStateBlock->state.ps_consts_b[start_register], constants, count * sizeof(BOOL));
+    memcpy(&device->update_state->ps_consts_b[start_register], constants, count * sizeof(BOOL));
     for (i = 0; i < count; ++i)
         TRACE("Set BOOL constant %u to %s.\n", start_register + i, constants[i] ? "true" : "false");
 
-    for (i = start_register; i < count + start_register; ++i)
-        device->updateStateBlock->changed.pixelShaderConstantsB |= (1 << i);
-
-    if (!device->isRecordingState)
-        device_invalidate_state(device, STATE_PIXELSHADERCONSTANT);
+    if (device->recording)
+    {
+        for (i = start_register; i < count + start_register; ++i)
+            device->recording->changed.pixelShaderConstantsB |= (1 << i);
+    }
+    else
+    {
+        device_invalidate_shader_constants(device, WINED3D_SHADER_CONST_PS_B);
+    }
 
     return WINED3D_OK;
 }
@@ -2993,7 +3028,7 @@ HRESULT CDECL wined3d_device_get_ps_consts_b(const struct wined3d_device *device
     if (!constants || start_register >= MAX_CONST_B)
         return WINED3DERR_INVALIDCALL;
 
-    memcpy(constants, &device->stateBlock->state.ps_consts_b[start_register], count * sizeof(BOOL));
+    memcpy(constants, &device->state.ps_consts_b[start_register], count * sizeof(BOOL));
 
     return WINED3D_OK;
 }
@@ -3010,17 +3045,21 @@ HRESULT CDECL wined3d_device_set_ps_consts_i(struct wined3d_device *device,
     if (!constants || start_register >= MAX_CONST_I)
         return WINED3DERR_INVALIDCALL;
 
-    memcpy(&device->updateStateBlock->state.ps_consts_i[start_register * 4], constants, count * sizeof(int) * 4);
+    memcpy(&device->update_state->ps_consts_i[start_register * 4], constants, count * sizeof(int) * 4);
     for (i = 0; i < count; ++i)
         TRACE("Set INT constant %u to {%d, %d, %d, %d}.\n", start_register + i,
                 constants[i * 4], constants[i * 4 + 1],
                 constants[i * 4 + 2], constants[i * 4 + 3]);
 
-    for (i = start_register; i < count + start_register; ++i)
-        device->updateStateBlock->changed.pixelShaderConstantsI |= (1 << i);
-
-    if (!device->isRecordingState)
-        device_invalidate_state(device, STATE_PIXELSHADERCONSTANT);
+    if (device->recording)
+    {
+        for (i = start_register; i < count + start_register; ++i)
+            device->recording->changed.pixelShaderConstantsI |= (1 << i);
+    }
+    else
+    {
+        device_invalidate_shader_constants(device, WINED3D_SHADER_CONST_PS_I);
+    }
 
     return WINED3D_OK;
 }
@@ -3036,7 +3075,7 @@ HRESULT CDECL wined3d_device_get_ps_consts_i(const struct wined3d_device *device
     if (!constants || start_register >= MAX_CONST_I)
         return WINED3DERR_INVALIDCALL;
 
-    memcpy(constants, &device->stateBlock->state.ps_consts_i[start_register * 4], count * sizeof(int) * 4);
+    memcpy(constants, &device->state.ps_consts_i[start_register * 4], count * sizeof(int) * 4);
 
     return WINED3D_OK;
 }
@@ -3045,6 +3084,7 @@ HRESULT CDECL wined3d_device_set_ps_consts_f(struct wined3d_device *device,
         UINT start_register, const float *constants, UINT vector4f_count)
 {
     UINT i;
+    const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
 
     TRACE("device %p, start_register %u, constants %p, vector4f_count %u.\n",
             device, start_register, constants, vector4f_count);
@@ -3052,11 +3092,11 @@ HRESULT CDECL wined3d_device_set_ps_consts_f(struct wined3d_device *device,
     /* Specifically test start_register > limit to catch MAX_UINT overflows
      * when adding start_register + vector4f_count. */
     if (!constants
-            || start_register + vector4f_count > device->d3d_pshader_constantF
-            || start_register > device->d3d_pshader_constantF)
+            || start_register + vector4f_count > d3d_info->limits.ps_uniform_count
+            || start_register > d3d_info->limits.ps_uniform_count)
         return WINED3DERR_INVALIDCALL;
 
-    memcpy(&device->updateStateBlock->state.ps_consts_f[start_register * 4],
+    memcpy(&device->update_state->ps_consts_f[start_register * 4],
             constants, vector4f_count * sizeof(float) * 4);
     if (TRACE_ON(d3d))
     {
@@ -3066,14 +3106,11 @@ HRESULT CDECL wined3d_device_set_ps_consts_f(struct wined3d_device *device,
                     constants[i * 4 + 2], constants[i * 4 + 3]);
     }
 
-    if (!device->isRecordingState)
-    {
+    if (device->recording)
+        memset(device->recording->changed.pixelShaderConstantsF + start_register, 1,
+                sizeof(*device->recording->changed.pixelShaderConstantsF) * vector4f_count);
+    else
         device->shader_backend->shader_update_float_pixel_constants(device, start_register, vector4f_count);
-        device_invalidate_state(device, STATE_PIXELSHADERCONSTANT);
-    }
-
-    memset(device->updateStateBlock->changed.pixelShaderConstantsF + start_register, 1,
-            sizeof(*device->updateStateBlock->changed.pixelShaderConstantsF) * vector4f_count);
 
     return WINED3D_OK;
 }
@@ -3081,7 +3118,8 @@ HRESULT CDECL wined3d_device_set_ps_consts_f(struct wined3d_device *device,
 HRESULT CDECL wined3d_device_get_ps_consts_f(const struct wined3d_device *device,
         UINT start_register, float *constants, UINT vector4f_count)
 {
-    int count = min(vector4f_count, device->d3d_pshader_constantF - start_register);
+    const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
+    int count = min(vector4f_count, d3d_info->limits.ps_uniform_count - start_register);
 
     TRACE("device %p, start_register %u, constants %p, vector4f_count %u.\n",
             device, start_register, constants, vector4f_count);
@@ -3089,14 +3127,14 @@ HRESULT CDECL wined3d_device_get_ps_consts_f(const struct wined3d_device *device
     if (!constants || count < 0)
         return WINED3DERR_INVALIDCALL;
 
-    memcpy(constants, &device->stateBlock->state.ps_consts_f[start_register * 4], count * sizeof(float) * 4);
+    memcpy(constants, &device->state.ps_consts_f[start_register * 4], count * sizeof(float) * 4);
 
     return WINED3D_OK;
 }
 
 void CDECL wined3d_device_set_geometry_shader(struct wined3d_device *device, struct wined3d_shader *shader)
 {
-    struct wined3d_shader *prev = device->updateStateBlock->state.geometry_shader;
+    struct wined3d_shader *prev = device->update_state->geometry_shader;
 
     TRACE("device %p, shader %p.\n", device, shader);
 
@@ -3105,9 +3143,9 @@ void CDECL wined3d_device_set_geometry_shader(struct wined3d_device *device, str
     if (prev)
         wined3d_shader_decref(prev);
 
-    device->updateStateBlock->state.geometry_shader = shader;
+    device->update_state->geometry_shader = shader;
 
-    if (device->isRecordingState || shader == prev)
+    if (device->recording || shader == prev)
         return;
 
     device_invalidate_state(device, STATE_GEOMETRY_SHADER);
@@ -3117,7 +3155,7 @@ struct wined3d_shader * CDECL wined3d_device_get_geometry_shader(const struct wi
 {
     TRACE("device %p.\n", device);
 
-    return device->stateBlock->state.geometry_shader;
+    return device->state.geometry_shader;
 }
 
 void CDECL wined3d_device_set_gs_cb(struct wined3d_device *device, UINT idx, struct wined3d_buffer *buffer)
@@ -3132,10 +3170,10 @@ void CDECL wined3d_device_set_gs_cb(struct wined3d_device *device, UINT idx, str
         return;
     }
 
-    prev = device->updateStateBlock->state.gs_cb[idx];
-    device->updateStateBlock->state.gs_cb[idx] = buffer;
+    prev = device->update_state->gs_cb[idx];
+    device->update_state->gs_cb[idx] = buffer;
 
-    if (device->isRecordingState)
+    if (device->recording)
     {
         if (buffer)
             wined3d_buffer_incref(buffer);
@@ -3169,7 +3207,7 @@ struct wined3d_buffer * CDECL wined3d_device_get_gs_cb(const struct wined3d_devi
         return NULL;
     }
 
-    return device->stateBlock->state.gs_cb[idx];
+    return device->state.gs_cb[idx];
 }
 
 void CDECL wined3d_device_set_gs_sampler(struct wined3d_device *device, UINT idx, struct wined3d_sampler *sampler)
@@ -3184,8 +3222,8 @@ void CDECL wined3d_device_set_gs_sampler(struct wined3d_device *device, UINT idx
         return;
     }
 
-    prev = device->updateStateBlock->state.gs_sampler[idx];
-    device->updateStateBlock->state.gs_sampler[idx] = sampler;
+    prev = device->update_state->gs_sampler[idx];
+    device->update_state->gs_sampler[idx] = sampler;
 
     if (sampler)
         wined3d_sampler_incref(sampler);
@@ -3203,7 +3241,7 @@ struct wined3d_sampler * CDECL wined3d_device_get_gs_sampler(const struct wined3
         return NULL;
     }
 
-    return device->stateBlock->state.gs_sampler[idx];
+    return device->state.gs_sampler[idx];
 }
 
 /* Context activation is done by the caller. */
@@ -3233,7 +3271,7 @@ static HRESULT process_vertices_strided(const struct wined3d_device *device, DWO
         return WINED3DERR_INVALIDCALL;
     }
 
-    if (device->stateBlock->state.render_states[WINED3D_RS_CLIPPING])
+    if (device->state.render_states[WINED3D_RS_CLIPPING])
     {
         static BOOL warned = FALSE;
         /*
@@ -3479,7 +3517,7 @@ HRESULT CDECL wined3d_device_process_vertices(struct wined3d_device *device,
         UINT src_start_idx, UINT dst_idx, UINT vertex_count, struct wined3d_buffer *dst_buffer,
         const struct wined3d_vertex_declaration *declaration, DWORD flags, DWORD dst_fvf)
 {
-    struct wined3d_state *state = &device->stateBlock->state;
+    struct wined3d_state *state = &device->state;
     struct wined3d_stream_info stream_info;
     const struct wined3d_gl_info *gl_info;
     struct wined3d_context *context;
@@ -3540,7 +3578,7 @@ HRESULT CDECL wined3d_device_process_vertices(struct wined3d_device *device,
 void CDECL wined3d_device_set_texture_stage_state(struct wined3d_device *device,
         UINT stage, enum wined3d_texture_stage_state state, DWORD value)
 {
-    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
     DWORD old_value;
 
     TRACE("device %p, stage %u, state %s, value %#x.\n",
@@ -3552,20 +3590,20 @@ void CDECL wined3d_device_set_texture_stage_state(struct wined3d_device *device,
         return;
     }
 
-    if (stage >= gl_info->limits.texture_stages)
+    if (stage >= d3d_info->limits.ffp_blend_stages)
     {
         WARN("Attempting to set stage %u which is higher than the max stage %u, ignoring.\n",
-                stage, gl_info->limits.texture_stages - 1);
+                stage, d3d_info->limits.ffp_blend_stages - 1);
         return;
     }
 
-    old_value = device->updateStateBlock->state.texture_states[stage][state];
-    device->updateStateBlock->changed.textureState[stage] |= 1 << state;
-    device->updateStateBlock->state.texture_states[stage][state] = value;
+    old_value = device->update_state->texture_states[stage][state];
+    device->update_state->texture_states[stage][state] = value;
 
-    if (device->isRecordingState)
+    if (device->recording)
     {
         TRACE("Recording... not performing anything.\n");
+        device->recording->changed.textureState[stage] |= 1 << state;
         return;
     }
 
@@ -3576,7 +3614,7 @@ void CDECL wined3d_device_set_texture_stage_state(struct wined3d_device *device,
         return;
     }
 
-    if (stage > device->stateBlock->state.lowest_disabled_stage
+    if (stage > device->state.lowest_disabled_stage
             && device->StateTable[STATE_TEXTURESTAGE(0, state)].representative
             == STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP))
     {
@@ -3596,12 +3634,12 @@ void CDECL wined3d_device_set_texture_stage_state(struct wined3d_device *device,
              * all enabled stages above stage, they have to be disabled.
              *
              * The current stage is dirtified below. */
-            for (i = stage + 1; i < device->stateBlock->state.lowest_disabled_stage; ++i)
+            for (i = stage + 1; i < device->state.lowest_disabled_stage; ++i)
             {
                 TRACE("Additionally dirtifying stage %u.\n", i);
                 device_invalidate_state(device, STATE_TEXTURESTAGE(i, WINED3D_TSS_COLOR_OP));
             }
-            device->stateBlock->state.lowest_disabled_stage = stage;
+            device->state.lowest_disabled_stage = stage;
             TRACE("New lowest disabled: %u.\n", stage);
         }
         else if (value != WINED3D_TOP_DISABLE && old_value == WINED3D_TOP_DISABLE)
@@ -3614,14 +3652,14 @@ void CDECL wined3d_device_set_texture_stage_state(struct wined3d_device *device,
              *
              * Again stage stage doesn't need to be dirtified here, it is
              * handled below. */
-            for (i = stage + 1; i < gl_info->limits.texture_stages; ++i)
+            for (i = stage + 1; i < d3d_info->limits.ffp_blend_stages; ++i)
             {
-                if (device->updateStateBlock->state.texture_states[i][WINED3D_TSS_COLOR_OP] == WINED3D_TOP_DISABLE)
+                if (device->update_state->texture_states[i][WINED3D_TSS_COLOR_OP] == WINED3D_TOP_DISABLE)
                     break;
                 TRACE("Additionally dirtifying stage %u due to enable.\n", i);
                 device_invalidate_state(device, STATE_TEXTURESTAGE(i, WINED3D_TSS_COLOR_OP));
             }
-            device->stateBlock->state.lowest_disabled_stage = i;
+            device->state.lowest_disabled_stage = i;
             TRACE("New lowest disabled: %u.\n", i);
         }
     }
@@ -3641,13 +3679,13 @@ DWORD CDECL wined3d_device_get_texture_stage_state(const struct wined3d_device *
         return 0;
     }
 
-    return device->updateStateBlock->state.texture_states[stage][state];
+    return device->state.texture_states[stage][state];
 }
 
 HRESULT CDECL wined3d_device_set_texture(struct wined3d_device *device,
         UINT stage, struct wined3d_texture *texture)
 {
-    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
     struct wined3d_texture *prev;
 
     TRACE("device %p, stage %u, texture %p.\n", device, stage, texture);
@@ -3656,7 +3694,7 @@ HRESULT CDECL wined3d_device_set_texture(struct wined3d_device *device,
         stage -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS);
 
     /* Windows accepts overflowing this array... we do not. */
-    if (stage >= sizeof(device->stateBlock->state.textures) / sizeof(*device->stateBlock->state.textures))
+    if (stage >= sizeof(device->state.textures) / sizeof(*device->state.textures))
     {
         WARN("Ignoring invalid stage %u.\n", stage);
         return WINED3D_OK;
@@ -3668,9 +3706,10 @@ HRESULT CDECL wined3d_device_set_texture(struct wined3d_device *device,
         return WINED3DERR_INVALIDCALL;
     }
 
-    device->updateStateBlock->changed.textures |= 1 << stage;
+    if (device->recording)
+        device->recording->changed.textures |= 1 << stage;
 
-    prev = device->updateStateBlock->state.textures[stage];
+    prev = device->update_state->textures[stage];
     TRACE("Previous texture %p.\n", prev);
 
     if (texture == prev)
@@ -3680,9 +3719,9 @@ HRESULT CDECL wined3d_device_set_texture(struct wined3d_device *device,
     }
 
     TRACE("Setting new texture to %p.\n", texture);
-    device->updateStateBlock->state.textures[stage] = texture;
+    device->update_state->textures[stage] = texture;
 
-    if (device->isRecordingState)
+    if (device->recording)
     {
         TRACE("Recording... not performing anything\n");
 
@@ -3701,7 +3740,7 @@ HRESULT CDECL wined3d_device_set_texture(struct wined3d_device *device,
         if (!prev || texture->target != prev->target)
             device_invalidate_state(device, STATE_PIXELSHADER);
 
-        if (!prev && stage < gl_info->limits.texture_stages)
+        if (!prev && stage < d3d_info->limits.ffp_blend_stages)
         {
             /* The source arguments for color and alpha ops have different
              * meanings when a NULL texture is bound, so the COLOR_OP and
@@ -3718,7 +3757,7 @@ HRESULT CDECL wined3d_device_set_texture(struct wined3d_device *device,
     {
         LONG bind_count = InterlockedDecrement(&prev->resource.bind_count);
 
-        if (!texture && stage < gl_info->limits.texture_stages)
+        if (!texture && stage < d3d_info->limits.ffp_blend_stages)
         {
             device_invalidate_state(device, STATE_TEXTURESTAGE(stage, WINED3D_TSS_COLOR_OP));
             device_invalidate_state(device, STATE_TEXTURESTAGE(stage, WINED3D_TSS_ALPHA_OP));
@@ -3733,7 +3772,7 @@ HRESULT CDECL wined3d_device_set_texture(struct wined3d_device *device,
             TRACE("Searching for other stages the texture is bound to.\n");
             for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
             {
-                if (device->updateStateBlock->state.textures[i] == prev)
+                if (device->update_state->textures[i] == prev)
                 {
                     TRACE("Texture is also bound to stage %u.\n", i);
                     prev->sampler = i;
@@ -3757,13 +3796,13 @@ struct wined3d_texture * CDECL wined3d_device_get_texture(const struct wined3d_d
     if (stage >= WINED3DVERTEXTEXTURESAMPLER0 && stage <= WINED3DVERTEXTEXTURESAMPLER3)
         stage -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS);
 
-    if (stage >= sizeof(device->stateBlock->state.textures) / sizeof(*device->stateBlock->state.textures))
+    if (stage >= sizeof(device->state.textures) / sizeof(*device->state.textures))
     {
         WARN("Ignoring invalid stage %u.\n", stage);
         return NULL; /* Windows accepts overflowing this array ... we do not. */
     }
 
-    return device->stateBlock->state.textures[stage];
+    return device->state.textures[stage];
 }
 
 HRESULT CDECL wined3d_device_get_back_buffer(const struct wined3d_device *device, UINT swapchain_idx,
@@ -3811,16 +3850,15 @@ HRESULT CDECL wined3d_device_begin_stateblock(struct wined3d_device *device)
 
     TRACE("device %p.\n", device);
 
-    if (device->isRecordingState)
+    if (device->recording)
         return WINED3DERR_INVALIDCALL;
 
     hr = wined3d_stateblock_create(device, WINED3D_SBT_RECORDED, &stateblock);
     if (FAILED(hr))
         return hr;
 
-    wined3d_stateblock_decref(device->updateStateBlock);
-    device->updateStateBlock = stateblock;
-    device->isRecordingState = TRUE;
+    device->recording = stateblock;
+    device->update_state = &stateblock->state;
 
     TRACE("Recording stateblock %p.\n", stateblock);
 
@@ -3830,11 +3868,11 @@ HRESULT CDECL wined3d_device_begin_stateblock(struct wined3d_device *device)
 HRESULT CDECL wined3d_device_end_stateblock(struct wined3d_device *device,
         struct wined3d_stateblock **stateblock)
 {
-    struct wined3d_stateblock *object = device->updateStateBlock;
+    struct wined3d_stateblock *object = device->recording;
 
     TRACE("device %p, stateblock %p.\n", device, stateblock);
 
-    if (!device->isRecordingState)
+    if (!device->recording)
     {
         WARN("Not recording.\n");
         *stateblock = NULL;
@@ -3844,9 +3882,8 @@ HRESULT CDECL wined3d_device_end_stateblock(struct wined3d_device *device,
     stateblock_init_contained_states(object);
 
     *stateblock = object;
-    device->isRecordingState = FALSE;
-    device->updateStateBlock = device->stateBlock;
-    wined3d_stateblock_incref(device->updateStateBlock);
+    device->recording = NULL;
+    device->update_state = &device->state;
 
     TRACE("Returning stateblock %p.\n", *stateblock);
 
@@ -3944,7 +3981,7 @@ HRESULT CDECL wined3d_device_clear(struct wined3d_device *device, DWORD rect_cou
         }
     }
 
-    wined3d_get_draw_rect(&device->stateBlock->state, &draw_rect);
+    wined3d_get_draw_rect(&device->state, &draw_rect);
     device_clear_render_targets(device, device->adapter->gl_info.limits.buffers,
             &device->fb, rect_count, rects, &draw_rect, flags, color, depth, stencil);
 
@@ -3954,10 +3991,17 @@ HRESULT CDECL wined3d_device_clear(struct wined3d_device *device, DWORD rect_cou
 void CDECL wined3d_device_set_primitive_type(struct wined3d_device *device,
         enum wined3d_primitive_type primitive_type)
 {
+    GLenum gl_primitive_type, prev;
+
     TRACE("device %p, primitive_type %s\n", device, debug_d3dprimitivetype(primitive_type));
 
-    device->updateStateBlock->changed.primitive_type = TRUE;
-    device->updateStateBlock->state.gl_primitive_type = gl_primitive_type_from_d3d(primitive_type);
+    gl_primitive_type = gl_primitive_type_from_d3d(primitive_type);
+    prev = device->update_state->gl_primitive_type;
+    device->update_state->gl_primitive_type = gl_primitive_type;
+    if (device->recording)
+        device->recording->changed.primitive_type = TRUE;
+    else if (gl_primitive_type != prev && (gl_primitive_type == GL_POINTS || prev == GL_POINTS))
+        device_invalidate_state(device, STATE_POINT_SIZE_ENABLE);
 }
 
 void CDECL wined3d_device_get_primitive_type(const struct wined3d_device *device,
@@ -3965,7 +4009,7 @@ void CDECL wined3d_device_get_primitive_type(const struct wined3d_device *device
 {
     TRACE("device %p, primitive_type %p\n", device, primitive_type);
 
-    *primitive_type = d3d_primitive_type_from_gl(device->stateBlock->state.gl_primitive_type);
+    *primitive_type = d3d_primitive_type_from_gl(device->state.gl_primitive_type);
 
     TRACE("Returning %s\n", debug_d3dprimitivetype(*primitive_type));
 }
@@ -3974,21 +4018,21 @@ HRESULT CDECL wined3d_device_draw_primitive(struct wined3d_device *device, UINT
 {
     TRACE("device %p, start_vertex %u, vertex_count %u.\n", device, start_vertex, vertex_count);
 
-    if (!device->stateBlock->state.vertex_declaration)
+    if (!device->state.vertex_declaration)
     {
         WARN("Called without a valid vertex declaration set.\n");
         return WINED3DERR_INVALIDCALL;
     }
 
-    if (device->stateBlock->state.load_base_vertex_index)
+    if (device->state.load_base_vertex_index)
     {
-        device->stateBlock->state.load_base_vertex_index = 0;
+        device->state.load_base_vertex_index = 0;
         device_invalidate_state(device, STATE_BASEVERTEXINDEX);
     }
 
     /* Account for the loading offset due to index buffers. Instead of
      * reloading all sources correct it with the startvertex parameter. */
-    draw_primitive(device, start_vertex, vertex_count, 0, 0, FALSE, NULL);
+    draw_primitive(device, start_vertex, vertex_count, 0, 0, FALSE);
     return WINED3D_OK;
 }
 
@@ -3998,7 +4042,7 @@ HRESULT CDECL wined3d_device_draw_indexed_primitive(struct wined3d_device *devic
 
     TRACE("device %p, start_idx %u, index_count %u.\n", device, start_idx, index_count);
 
-    if (!device->stateBlock->state.index_buffer)
+    if (!device->state.index_buffer)
     {
         /* D3D9 returns D3DERR_INVALIDCALL when DrawIndexedPrimitive is called
          * without an index buffer set. (The first time at least...)
@@ -4008,20 +4052,20 @@ HRESULT CDECL wined3d_device_draw_indexed_primitive(struct wined3d_device *devic
         return WINED3DERR_INVALIDCALL;
     }
 
-    if (!device->stateBlock->state.vertex_declaration)
+    if (!device->state.vertex_declaration)
     {
         WARN("Called without a valid vertex declaration set.\n");
         return WINED3DERR_INVALIDCALL;
     }
 
     if (!gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX] &&
-        device->stateBlock->state.load_base_vertex_index != device->stateBlock->state.base_vertex_index)
+        device->state.load_base_vertex_index != device->state.base_vertex_index)
     {
-        device->stateBlock->state.load_base_vertex_index = device->stateBlock->state.base_vertex_index;
+        device->state.load_base_vertex_index = device->state.base_vertex_index;
         device_invalidate_state(device, STATE_BASEVERTEXINDEX);
     }
 
-    draw_primitive(device, start_idx, index_count, 0, 0, TRUE, NULL);
+    draw_primitive(device, start_idx, index_count, 0, 0, TRUE);
 
     return WINED3D_OK;
 }
@@ -4031,7 +4075,7 @@ void CDECL wined3d_device_draw_indexed_primitive_instanced(struct wined3d_device
 {
     TRACE("device %p, start_idx %u, index_count %u.\n", device, start_idx, index_count);
 
-    draw_primitive(device, start_idx, index_count, start_instance, instance_count, TRUE, NULL);
+    draw_primitive(device, start_idx, index_count, start_instance, instance_count, TRUE);
 }
 
 /* This is a helper function for UpdateTexture, there is no UpdateVolume method in D3D. */
@@ -4039,29 +4083,41 @@ static HRESULT device_update_volume(struct wined3d_device *device,
         struct wined3d_volume *src_volume, struct wined3d_volume *dst_volume)
 {
     struct wined3d_map_desc src;
-    struct wined3d_map_desc dst;
     HRESULT hr;
+    struct wined3d_bo_address data;
+    struct wined3d_context *context;
 
     TRACE("device %p, src_volume %p, dst_volume %p.\n",
             device, src_volume, dst_volume);
 
-    /* TODO: Implement direct loading into the gl volume instead of using
-     * memcpy and dirtification to improve loading performance. */
-    if (FAILED(hr = wined3d_volume_map(src_volume, &src, NULL, WINED3D_MAP_READONLY)))
-        return hr;
-    if (FAILED(hr = wined3d_volume_map(dst_volume, &dst, NULL, WINED3D_MAP_DISCARD)))
+    if (src_volume->resource.format != dst_volume->resource.format)
     {
-        wined3d_volume_unmap(src_volume);
-        return hr;
+        FIXME("Source and destination formats do not match.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+    if (src_volume->resource.width != dst_volume->resource.width
+            || src_volume->resource.height != dst_volume->resource.height
+            || src_volume->resource.depth != dst_volume->resource.depth)
+    {
+        FIXME("Source and destination sizes do not match.\n");
+        return WINED3DERR_INVALIDCALL;
     }
 
-    memcpy(dst.data, src.data, dst_volume->resource.size);
+    if (FAILED(hr = wined3d_volume_map(src_volume, &src, NULL, WINED3D_MAP_READONLY)))
+        return hr;
 
-    hr = wined3d_volume_unmap(dst_volume);
-    if (FAILED(hr))
-        wined3d_volume_unmap(src_volume);
-    else
-        hr = wined3d_volume_unmap(src_volume);
+    context = context_acquire(device, NULL);
+
+    wined3d_volume_load(dst_volume, context, FALSE);
+
+    data.buffer_object = 0;
+    data.addr = src.data;
+    wined3d_volume_upload_data(dst_volume, context, &data);
+    wined3d_volume_invalidate_location(dst_volume, ~WINED3D_LOCATION_TEXTURE_RGB);
+
+    context_release(context);
+
+    hr = wined3d_volume_unmap(src_volume);
 
     return hr;
 }
@@ -4082,9 +4138,14 @@ HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device,
         return WINED3DERR_INVALIDCALL;
     }
 
-    if (src_texture == dst_texture)
+    if (src_texture->resource.pool != WINED3D_POOL_SYSTEM_MEM)
     {
-        WARN("Source and destination are the same object, returning WINED3DERR_INVALIDCALL.\n");
+        WARN("Source texture not in WINED3D_POOL_SYSTEM_MEM, returning WINED3DERR_INVALIDCALL.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+    if (dst_texture->resource.pool != WINED3D_POOL_DEFAULT)
+    {
+        WARN("Destination texture not in WINED3D_POOL_DEFAULT, returning WINED3DERR_INVALIDCALL.\n");
         return WINED3DERR_INVALIDCALL;
     }
 
@@ -4187,7 +4248,7 @@ HRESULT CDECL wined3d_device_get_front_buffer_data(const struct wined3d_device *
 
 HRESULT CDECL wined3d_device_validate_device(const struct wined3d_device *device, DWORD *num_passes)
 {
-    const struct wined3d_state *state = &device->stateBlock->state;
+    const struct wined3d_state *state = &device->state;
     struct wined3d_texture *texture;
     DWORD i;
 
@@ -4211,18 +4272,18 @@ HRESULT CDECL wined3d_device_validate_device(const struct wined3d_device *device
 
         if (state->sampler_states[i][WINED3D_SAMP_MAG_FILTER] != WINED3D_TEXF_POINT)
         {
-            WARN("Non-filterable texture and mag filter enabled on samper %u, returning E_FAIL\n", i);
+            WARN("Non-filterable texture and mag filter enabled on sampler %u, returning E_FAIL\n", i);
             return E_FAIL;
         }
         if (state->sampler_states[i][WINED3D_SAMP_MIN_FILTER] != WINED3D_TEXF_POINT)
         {
-            WARN("Non-filterable texture and min filter enabled on samper %u, returning E_FAIL\n", i);
+            WARN("Non-filterable texture and min filter enabled on sampler %u, returning E_FAIL\n", i);
             return E_FAIL;
         }
         if (state->sampler_states[i][WINED3D_SAMP_MIP_FILTER] != WINED3D_TEXF_NONE
                 && state->sampler_states[i][WINED3D_SAMP_MIP_FILTER] != WINED3D_TEXF_POINT)
         {
-            WARN("Non-filterable texture and mip filter enabled on samper %u, returning E_FAIL\n", i);
+            WARN("Non-filterable texture and mip filter enabled on sampler %u, returning E_FAIL\n", i);
             return E_FAIL;
         }
     }
@@ -4441,7 +4502,7 @@ HRESULT CDECL wined3d_device_set_render_target(struct wined3d_device *device,
      * primary stateblock. */
     if (!render_target_idx && set_viewport)
     {
-        struct wined3d_state *state = &device->stateBlock->state;
+        struct wined3d_state *state = &device->state;
 
         state->viewport.x = 0;
         state->viewport.y = 0;
@@ -4603,12 +4664,6 @@ HRESULT CDECL wined3d_device_set_cursor_properties(struct wined3d_device *device
 
             context = context_acquire(device, NULL);
 
-            if (gl_info->supported[APPLE_CLIENT_STORAGE])
-            {
-                gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
-                checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
-            }
-
             invalidate_active_texture(device, context);
             /* Create a new cursor texture */
             gl_info->gl_ops.gl.p_glGenTextures(1, &device->cursorTexture);
@@ -4619,12 +4674,6 @@ HRESULT CDECL wined3d_device_set_cursor_properties(struct wined3d_device *device
             checkGLcall("glTexImage2D");
             HeapFree(GetProcessHeap(), 0, mem);
 
-            if (gl_info->supported[APPLE_CLIENT_STORAGE])
-            {
-                gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
-                checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
-            }
-
             context_release(context);
         }
         else
@@ -4814,7 +4863,8 @@ static HRESULT create_primary_opengl_context(struct wined3d_device *device, stru
     struct wined3d_surface *target;
     HRESULT hr;
 
-    if (FAILED(hr = device->shader_backend->shader_alloc_private(device, device->adapter->fragment_pipe)))
+    if (FAILED(hr = device->shader_backend->shader_alloc_private(device,
+            device->adapter->vertex_pipe, device->adapter->fragment_pipe)))
     {
         ERR("Failed to allocate shader private data, hr %#x.\n", hr);
         return hr;
@@ -4865,6 +4915,8 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
     struct wined3d_display_mode m;
     BOOL DisplayModeChanged = FALSE;
     BOOL update_desc = FALSE;
+    UINT backbuffer_width = swapchain_desc->backbuffer_width;
+    UINT backbuffer_height = swapchain_desc->backbuffer_height;
     HRESULT hr = WINED3D_OK;
     unsigned int i;
 
@@ -4877,7 +4929,7 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
     }
 
     if (reset_state)
-        stateblock_unbind_resources(device->stateBlock);
+        state_unbind_resources(&device->state);
 
     if (device->fb.render_targets)
     {
@@ -4956,13 +5008,23 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
 
     if (swapchain_desc->enable_auto_depth_stencil && !device->auto_depth_stencil)
     {
+        struct wined3d_resource_desc surface_desc;
+
         TRACE("Creating the depth stencil buffer\n");
 
+        surface_desc.resource_type = WINED3D_RTYPE_SURFACE;
+        surface_desc.format = swapchain_desc->auto_depth_stencil_format;
+        surface_desc.multisample_type = swapchain_desc->multisample_type;
+        surface_desc.multisample_quality = swapchain_desc->multisample_quality;
+        surface_desc.usage = WINED3DUSAGE_DEPTHSTENCIL;
+        surface_desc.pool = WINED3D_POOL_DEFAULT;
+        surface_desc.width = swapchain_desc->backbuffer_width;
+        surface_desc.height = swapchain_desc->backbuffer_height;
+        surface_desc.depth = 1;
+        surface_desc.size = 0;
+
         if (FAILED(hr = device->device_parent->ops->create_swapchain_surface(device->device_parent,
-                device->device_parent, swapchain_desc->backbuffer_width, swapchain_desc->backbuffer_height,
-                swapchain_desc->auto_depth_stencil_format, WINED3DUSAGE_DEPTHSTENCIL,
-                swapchain_desc->multisample_type, swapchain_desc->multisample_quality,
-                &device->auto_depth_stencil)))
+                device->device_parent, &surface_desc, &device->auto_depth_stencil)))
         {
             ERR("Failed to create the depth stencil buffer, hr %#x.\n", hr);
             return WINED3DERR_INVALIDCALL;
@@ -4980,11 +5042,7 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
     }
     else if (swapchain_desc->windowed)
     {
-        m.width = swapchain->orig_width;
-        m.height = swapchain->orig_height;
-        m.refresh_rate = 0;
-        m.format_id = swapchain->desc.backbuffer_format;
-        m.scanline_ordering = WINED3D_SCANLINE_ORDERING_UNKNOWN;
+        m = swapchain->original_mode;
     }
     else
     {
@@ -4995,16 +5053,38 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
         m.scanline_ordering = WINED3D_SCANLINE_ORDERING_UNKNOWN;
     }
 
-    /* Should Width == 800 && Height == 0 set 800x600? */
-    if (swapchain_desc->backbuffer_width && swapchain_desc->backbuffer_height
-            && (swapchain_desc->backbuffer_width != swapchain->desc.backbuffer_width
-            || swapchain_desc->backbuffer_height != swapchain->desc.backbuffer_height))
+    if (!backbuffer_width || !backbuffer_height)
+    {
+        /* The application is requesting that either the swapchain width or
+         * height be set to the corresponding dimension in the window's
+         * client rect. */
+
+        RECT client_rect;
+
+        if (!swapchain_desc->windowed)
+            return WINED3DERR_INVALIDCALL;
+
+        if (!GetClientRect(swapchain->device_window, &client_rect))
+        {
+            ERR("Failed to get client rect, last error %#x.\n", GetLastError());
+            return WINED3DERR_INVALIDCALL;
+        }
+
+        if (!backbuffer_width)
+            backbuffer_width = client_rect.right;
+
+        if (!backbuffer_height)
+            backbuffer_height = client_rect.bottom;
+    }
+
+    if (backbuffer_width != swapchain->desc.backbuffer_width
+            || backbuffer_height != swapchain->desc.backbuffer_height)
     {
         if (!swapchain_desc->windowed)
             DisplayModeChanged = TRUE;
 
-        swapchain->desc.backbuffer_width = swapchain_desc->backbuffer_width;
-        swapchain->desc.backbuffer_height = swapchain_desc->backbuffer_height;
+        swapchain->desc.backbuffer_width = backbuffer_width;
+        swapchain->desc.backbuffer_height = backbuffer_height;
         update_desc = TRUE;
     }
 
@@ -5112,27 +5192,25 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
     if (reset_state)
     {
         TRACE("Resetting stateblock.\n");
-        wined3d_stateblock_decref(device->updateStateBlock);
-        wined3d_stateblock_decref(device->stateBlock);
+        if (device->recording)
+        {
+            wined3d_stateblock_decref(device->recording);
+            device->recording = NULL;
+        }
+        state_cleanup(&device->state);
 
         if (device->d3d_initialized)
             delete_opengl_contexts(device, swapchain);
 
-        /* Note: No parent needed for initial internal stateblock */
-        hr = wined3d_stateblock_create(device, WINED3D_SBT_INIT, &device->stateBlock);
-        if (FAILED(hr))
-            ERR("Resetting the stateblock failed with error %#x.\n", hr);
-        else
-            TRACE("Created stateblock %p.\n", device->stateBlock);
-        device->updateStateBlock = device->stateBlock;
-        wined3d_stateblock_incref(device->updateStateBlock);
-
-        stateblock_init_default_state(device->stateBlock);
+        if (FAILED(hr = state_init(&device->state, &device->adapter->d3d_info)))
+            ERR("Failed to initialize device state, hr %#x.\n", hr);
+        state_init_default(&device->state, device);
+        device->update_state = &device->state;
     }
     else
     {
         struct wined3d_surface *rt = device->fb.render_targets[0];
-        struct wined3d_state *state = &device->stateBlock->state;
+        struct wined3d_state *state = &device->state;
 
         /* Note the min_z / max_z is not reset. */
         state->viewport.x = 0;
@@ -5257,19 +5335,17 @@ void device_resource_released(struct wined3d_device *device, struct wined3d_reso
             {
                 struct wined3d_texture *texture = wined3d_texture_from_resource(resource);
 
-                if (device->stateBlock && device->stateBlock->state.textures[i] == texture)
+                if (device->state.textures[i] == texture)
                 {
-                    ERR("Texture %p is still in use by stateblock %p, stage %u.\n",
-                            texture, device->stateBlock, i);
-                    device->stateBlock->state.textures[i] = NULL;
+                    ERR("Texture %p is still in use, stage %u.\n", texture, i);
+                    device->state.textures[i] = NULL;
                 }
 
-                if (device->updateStateBlock != device->stateBlock
-                        && device->updateStateBlock->state.textures[i] == texture)
+                if (device->recording && device->update_state->textures[i] == texture)
                 {
-                    ERR("Texture %p is still in use by stateblock %p, stage %u.\n",
-                            texture, device->updateStateBlock, i);
-                    device->updateStateBlock->state.textures[i] = NULL;
+                    ERR("Texture %p is still in use by recording stateblock %p, stage %u.\n",
+                            texture, device->recording, i);
+                    device->update_state->textures[i] = NULL;
                 }
             }
             break;
@@ -5280,36 +5356,31 @@ void device_resource_released(struct wined3d_device *device, struct wined3d_reso
 
                 for (i = 0; i < MAX_STREAMS; ++i)
                 {
-                    if (device->stateBlock && device->stateBlock->state.streams[i].buffer == buffer)
+                    if (device->state.streams[i].buffer == buffer)
                     {
-                        ERR("Buffer %p is still in use by stateblock %p, stream %u.\n",
-                                buffer, device->stateBlock, i);
-                        device->stateBlock->state.streams[i].buffer = NULL;
+                        ERR("Buffer %p is still in use, stream %u.\n", buffer, i);
+                        device->state.streams[i].buffer = NULL;
                     }
 
-                    if (device->updateStateBlock != device->stateBlock
-                            && device->updateStateBlock->state.streams[i].buffer == buffer)
+                    if (device->recording && device->update_state->streams[i].buffer == buffer)
                     {
                         ERR("Buffer %p is still in use by stateblock %p, stream %u.\n",
-                                buffer, device->updateStateBlock, i);
-                        device->updateStateBlock->state.streams[i].buffer = NULL;
+                                buffer, device->recording, i);
+                        device->update_state->streams[i].buffer = NULL;
                     }
-
                 }
 
-                if (device->stateBlock && device->stateBlock->state.index_buffer == buffer)
+                if (device->state.index_buffer == buffer)
                 {
-                    ERR("Buffer %p is still in use by stateblock %p as index buffer.\n",
-                            buffer, device->stateBlock);
-                    device->stateBlock->state.index_buffer =  NULL;
+                    ERR("Buffer %p is still in use as index buffer.\n", buffer);
+                    device->state.index_buffer =  NULL;
                 }
 
-                if (device->updateStateBlock != device->stateBlock
-                        && device->updateStateBlock->state.index_buffer == buffer)
+                if (device->recording && device->update_state->index_buffer == buffer)
                 {
                     ERR("Buffer %p is still in use by stateblock %p as index buffer.\n",
-                            buffer, device->updateStateBlock);
-                    device->updateStateBlock->state.index_buffer =  NULL;
+                            buffer, device->recording);
+                    device->update_state->index_buffer =  NULL;
                 }
             }
             break;
@@ -5356,8 +5427,7 @@ HRESULT device_init(struct wined3d_device *device, struct wined3d *wined3d,
 {
     struct wined3d_adapter *adapter = &wined3d->adapters[adapter_idx];
     const struct fragment_pipeline *fragment_pipeline;
-    struct shader_caps shader_caps;
-    struct fragment_caps ffp_caps;
+    const struct wined3d_vertex_pipe_ops *vertex_pipeline;
     unsigned int i;
     HRESULT hr;
 
@@ -5377,21 +5447,15 @@ HRESULT device_init(struct wined3d_device *device, struct wined3d *wined3d,
     device->create_parms.flags = flags;
 
     device->shader_backend = adapter->shader_backend;
-    device->shader_backend->shader_get_caps(&adapter->gl_info, &shader_caps);
-    device->vs_version = shader_caps.vs_version;
-    device->gs_version = shader_caps.gs_version;
-    device->ps_version = shader_caps.ps_version;
-    device->d3d_vshader_constantF = shader_caps.vs_uniform_count;
-    device->d3d_pshader_constantF = shader_caps.ps_uniform_count;
-    device->vs_clipping = shader_caps.wined3d_caps & WINED3D_SHADER_CAP_VS_CLIPPING;
+
+    vertex_pipeline = adapter->vertex_pipe;
 
     fragment_pipeline = adapter->fragment_pipe;
-    fragment_pipeline->get_caps(&adapter->gl_info, &ffp_caps);
-    device->max_ffp_textures = ffp_caps.MaxSimultaneousTextures;
 
-    if (fragment_pipeline->states
+    if (vertex_pipeline->vp_states && fragment_pipeline->states
             && FAILED(hr = compile_state_table(device->StateTable, device->multistate_funcs,
-            &adapter->gl_info, ffp_vertexstate_template, fragment_pipeline, misc_state_template)))
+            &adapter->gl_info, &adapter->d3d_info, vertex_pipeline,
+            fragment_pipeline, misc_state_template)))
     {
         ERR("Failed to compile state table, hr %#x.\n", hr);
         wined3d_decref(device->wined3d);
@@ -5400,10 +5464,9 @@ HRESULT device_init(struct wined3d_device *device, struct wined3d *wined3d,
 
     device->blitter = adapter->blitter;
 
-    hr = wined3d_stateblock_create(device, WINED3D_SBT_INIT, &device->stateBlock);
-    if (FAILED(hr))
+    if (FAILED(hr = state_init(&device->state, &adapter->d3d_info)))
     {
-        WARN("Failed to create stateblock.\n");
+        ERR("Failed to initialize device state, hr %#x.\n", hr);
         for (i = 0; i < sizeof(device->multistate_funcs) / sizeof(device->multistate_funcs[0]); ++i)
         {
             HeapFree(GetProcessHeap(), 0, device->multistate_funcs[i]);
@@ -5411,10 +5474,7 @@ HRESULT device_init(struct wined3d_device *device, struct wined3d *wined3d,
         wined3d_decref(device->wined3d);
         return hr;
     }
-
-    TRACE("Created stateblock %p.\n", device->stateBlock);
-    device->updateStateBlock = device->stateBlock;
-    wined3d_stateblock_incref(device->updateStateBlock);
+    device->update_state = &device->state;
 
     return WINED3D_OK;
 }
index dd0ec43..ad9f549 100644 (file)
 //#include "winternl.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
+WINE_DECLARE_DEBUG_CHANNEL(d3d_perf);
 
 #define WINE_DEFAULT_VIDMEM (64 * 1024 * 1024)
+#define DEFAULT_REFRESH_RATE 0
 
 /* The driver names reflect the lowest GPU supported
  * by a certain driver, so DRIVER_AMD_R300 supports
@@ -92,6 +94,7 @@ static const struct wined3d_extension_map gl_extension_map[] =
 
     /* ARB */
     {"GL_ARB_color_buffer_float",           ARB_COLOR_BUFFER_FLOAT        },
+    {"GL_ARB_debug_output",                 ARB_DEBUG_OUTPUT              },
     {"GL_ARB_depth_buffer_float",           ARB_DEPTH_BUFFER_FLOAT        },
     {"GL_ARB_depth_clamp",                  ARB_DEPTH_CLAMP               },
     {"GL_ARB_depth_texture",                ARB_DEPTH_TEXTURE             },
@@ -106,6 +109,7 @@ static const struct wined3d_extension_map gl_extension_map[] =
     {"GL_ARB_half_float_pixel",             ARB_HALF_FLOAT_PIXEL          },
     {"GL_ARB_half_float_vertex",            ARB_HALF_FLOAT_VERTEX         },
     {"GL_ARB_instanced_arrays",             ARB_INSTANCED_ARRAYS,         },
+    {"GL_ARB_internalformat_query2",        ARB_INTERNALFORMAT_QUERY2,    },
     {"GL_ARB_map_buffer_alignment",         ARB_MAP_BUFFER_ALIGNMENT      },
     {"GL_ARB_map_buffer_range",             ARB_MAP_BUFFER_RANGE          },
     {"GL_ARB_multisample",                  ARB_MULTISAMPLE               }, /* needs GLX_ARB_MULTISAMPLE as well */
@@ -161,7 +165,6 @@ static const struct wined3d_extension_map gl_extension_map[] =
     {"GL_EXT_gpu_program_parameters",       EXT_GPU_PROGRAM_PARAMETERS    },
     {"GL_EXT_gpu_shader4",                  EXT_GPU_SHADER4               },
     {"GL_EXT_packed_depth_stencil",         EXT_PACKED_DEPTH_STENCIL      },
-    {"GL_EXT_paletted_texture",             EXT_PALETTED_TEXTURE          },
     {"GL_EXT_point_parameters",             EXT_POINT_PARAMETERS          },
     {"GL_EXT_provoking_vertex",             EXT_PROVOKING_VERTEX          },
     {"GL_EXT_secondary_color",              EXT_SECONDARY_COLOR           },
@@ -252,20 +255,6 @@ const GLenum magLookup_noFilter[] =
     GL_NEAREST, GL_NEAREST, GL_NEAREST,
 };
 
-/* drawStridedSlow attributes */
-glAttribFunc position_funcs[WINED3D_FFP_EMIT_COUNT];
-glAttribFunc diffuse_funcs[WINED3D_FFP_EMIT_COUNT];
-glAttribFunc specular_func_3ubv;
-glAttribFunc specular_funcs[WINED3D_FFP_EMIT_COUNT];
-glAttribFunc normal_funcs[WINED3D_FFP_EMIT_COUNT];
-glMultiTexCoordFunc multi_texcoord_funcs[WINED3D_FFP_EMIT_COUNT];
-
-/**
- * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created,
- * i.e., there is no GL Context - Get a default rendering context to enable the
- * function query some info from GL.
- */
-
 struct wined3d_fake_gl_ctx
 {
     HDC dc;
@@ -295,6 +284,35 @@ static void WineD3D_ReleaseFakeGLContext(const struct wined3d_fake_gl_ctx *ctx)
         ERR("Failed to restore previous GL context.\n");
 }
 
+static void wined3d_create_fake_gl_context_attribs(struct wined3d_fake_gl_ctx *fake_gl_ctx,
+        struct wined3d_gl_info *gl_info, const GLint *ctx_attribs)
+{
+    HGLRC new_ctx;
+
+    if (!(gl_info->p_wglCreateContextAttribsARB = (void *)wglGetProcAddress("wglCreateContextAttribsARB")))
+        return;
+
+    if (!(new_ctx = gl_info->p_wglCreateContextAttribsARB(fake_gl_ctx->dc, NULL, ctx_attribs)))
+    {
+        ERR("Failed to create a context using wglCreateContextAttribsARB(), last error %#x.\n", GetLastError());
+        gl_info->p_wglCreateContextAttribsARB = NULL;
+        return;
+    }
+
+    if (!wglMakeCurrent(fake_gl_ctx->dc, new_ctx))
+    {
+        ERR("Failed to make new context current, last error %#x.\n", GetLastError());
+        if (!wglDeleteContext(new_ctx))
+            ERR("Failed to delete new context, last error %#x.\n", GetLastError());
+        gl_info->p_wglCreateContextAttribsARB = NULL;
+        return;
+    }
+
+    if (!wglDeleteContext(fake_gl_ctx->gl_ctx))
+        ERR("Failed to delete old context, last error %#x.\n", GetLastError());
+    fake_gl_ctx->gl_ctx = new_ctx;
+}
+
 /* Do not call while under the GL lock. */
 static BOOL WineD3D_CreateFakeGLContext(struct wined3d_fake_gl_ctx *ctx)
 {
@@ -553,7 +571,7 @@ static void test_pbo_functionality(struct wined3d_gl_info *gl_info)
 
     if (memcmp(check, pattern, sizeof(check)))
     {
-        WARN("PBO test failed, read back data doesn't match original.\n"
+        WARN_(d3d_perf)("PBO test failed, read back data doesn't match original.\n"
                 "Disabling PBOs. This may result in slower performance.\n");
         gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = FALSE;
     }
@@ -759,6 +777,101 @@ static BOOL match_r200(const struct wined3d_gl_info *gl_info, const char *gl_ren
     return FALSE;
 }
 
+static BOOL match_broken_arb_fog(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
+        enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
+{
+    DWORD data[4];
+    GLuint tex, fbo;
+    GLenum status;
+    float color[4] = {0.0f, 1.0f, 0.0f, 0.0f};
+    GLuint prog;
+    GLint err_pos;
+    static const char *program_code =
+        "!!ARBfp1.0\n"
+        "OPTION ARB_fog_linear;\n"
+        "MOV result.color, {1.0, 0.0, 0.0, 0.0};\n"
+        "END\n";
+
+    if (wined3d_settings.offscreen_rendering_mode != ORM_FBO)
+        return FALSE;
+    if (!gl_info->supported[ARB_FRAGMENT_PROGRAM])
+        return FALSE;
+
+    gl_info->gl_ops.gl.p_glGenTextures(1, &tex);
+    gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, tex);
+    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 4, 1, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
+    checkGLcall("glTexImage2D");
+
+    gl_info->fbo_ops.glGenFramebuffers(1, &fbo);
+    gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+    gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
+    checkGLcall("glFramebufferTexture2D");
+
+    status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER);
+    if (status != GL_FRAMEBUFFER_COMPLETE) ERR("FBO status %#x\n", status);
+    checkGLcall("glCheckFramebufferStatus");
+
+    gl_info->gl_ops.gl.p_glClearColor(0.0f, 0.0f, 1.0f, 0.0f);
+    gl_info->gl_ops.gl.p_glClear(GL_COLOR_BUFFER_BIT);
+    checkGLcall("glClear");
+    gl_info->gl_ops.gl.p_glViewport(0, 0, 4, 1);
+    checkGLcall("glViewport");
+
+    gl_info->gl_ops.gl.p_glEnable(GL_FOG);
+    gl_info->gl_ops.gl.p_glFogf(GL_FOG_START, 0.5f);
+    gl_info->gl_ops.gl.p_glFogf(GL_FOG_END, 0.5f);
+    gl_info->gl_ops.gl.p_glFogi(GL_FOG_MODE, GL_LINEAR);
+    gl_info->gl_ops.gl.p_glHint(GL_FOG_HINT, GL_NICEST);
+    gl_info->gl_ops.gl.p_glFogfv(GL_FOG_COLOR, color);
+    checkGLcall("fog setup");
+
+    GL_EXTCALL(glGenProgramsARB(1, &prog));
+    GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, prog));
+    GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
+            strlen(program_code), program_code));
+    gl_info->gl_ops.gl.p_glEnable(GL_FRAGMENT_PROGRAM_ARB);
+    checkGLcall("Test fragment program setup");
+
+    gl_info->gl_ops.gl.p_glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &err_pos);
+    if (err_pos != -1)
+    {
+        const char *error_str;
+        error_str = (const char *)gl_info->gl_ops.gl.p_glGetString(GL_PROGRAM_ERROR_STRING_ARB);
+        FIXME("Fog test program error at position %d: %s\n\n", err_pos, debugstr_a(error_str));
+    }
+
+    gl_info->gl_ops.gl.p_glBegin(GL_TRIANGLE_STRIP);
+    gl_info->gl_ops.gl.p_glVertex3f(-1.0f, -1.0f,  0.0f);
+    gl_info->gl_ops.gl.p_glVertex3f( 1.0f, -1.0f,  1.0f);
+    gl_info->gl_ops.gl.p_glVertex3f(-1.0f,  1.0f,  0.0f);
+    gl_info->gl_ops.gl.p_glVertex3f( 1.0f,  1.0f,  1.0f);
+    gl_info->gl_ops.gl.p_glEnd();
+    checkGLcall("ARBfp fog test draw");
+
+    gl_info->gl_ops.gl.p_glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data);
+    checkGLcall("glGetTexImage");
+    data[0] &= 0x00ffffff;
+    data[1] &= 0x00ffffff;
+    data[2] &= 0x00ffffff;
+    data[3] &= 0x00ffffff;
+
+    gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, 0);
+    gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, 0);
+
+    gl_info->fbo_ops.glDeleteFramebuffers(1, &fbo);
+    gl_info->gl_ops.gl.p_glDeleteTextures(1, &tex);
+    gl_info->gl_ops.gl.p_glDisable(GL_FOG);
+    GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0));
+    gl_info->gl_ops.gl.p_glDisable(GL_FRAGMENT_PROGRAM_ARB);
+    GL_EXTCALL(glDeleteProgramsARB(1, &prog));
+    checkGLcall("ARBfp fog test teardown");
+
+    TRACE("Fog test data: %08x %08x %08x %08x\n", data[0], data[1], data[2], data[3]);
+    return data[0] != 0x00ff0000 || data[3] != 0x0000ff00;
+}
+
 static void quirk_apple_glsl_constants(struct wined3d_gl_info *gl_info)
 {
     /* MacOS needs uniforms for relative addressing offsets. This can accumulate to quite a few uniforms.
@@ -882,6 +995,11 @@ static void quirk_r200_constants(struct wined3d_gl_info *gl_info)
     gl_info->reserved_arb_constants = max(gl_info->reserved_arb_constants, 1);
 }
 
+static void quirk_broken_arb_fog(struct wined3d_gl_info *gl_info)
+{
+    gl_info->quirks |= WINED3D_QUIRK_BROKEN_ARB_FOG;
+}
+
 struct driver_quirk
 {
     BOOL (*match)(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
@@ -967,6 +1085,11 @@ static const struct driver_quirk quirk_table[] =
         quirk_r200_constants,
         "r200 vertex shader constants"
     },
+    {
+        match_broken_arb_fog,
+        quirk_broken_arb_fog,
+        "ARBfp fogstart == fogend workaround"
+    },
 };
 
 /* Certain applications (Steam) complain if we report an outdated driver version. In general,
@@ -1097,7 +1220,9 @@ static const struct gpu_description gpu_description_table[] =
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX260,     "NVIDIA GeForce GTX 260",           DRIVER_NVIDIA_GEFORCE6,  1024},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX275,     "NVIDIA GeForce GTX 275",           DRIVER_NVIDIA_GEFORCE6,  896 },
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX280,     "NVIDIA GeForce GTX 280",           DRIVER_NVIDIA_GEFORCE6,  1024},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_315M,       "NVIDIA GeForce 315M",              DRIVER_NVIDIA_GEFORCE6,  512 },
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_320M,       "NVIDIA GeForce 320M",              DRIVER_NVIDIA_GEFORCE6,  256},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_410M,       "NVIDIA GeForce 410M",              DRIVER_NVIDIA_GEFORCE6,  512},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT320M,     "NVIDIA GeForce GT 320M",           DRIVER_NVIDIA_GEFORCE6,  1024},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT325M,     "NVIDIA GeForce GT 325M",           DRIVER_NVIDIA_GEFORCE6,  1024},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT330,      "NVIDIA GeForce GT 330",            DRIVER_NVIDIA_GEFORCE6,  1024},
@@ -1120,6 +1245,7 @@ static const struct gpu_description gpu_description_table[] =
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX570,     "NVIDIA GeForce GTX 570",           DRIVER_NVIDIA_GEFORCE6,  1280},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX580,     "NVIDIA GeForce GTX 580",           DRIVER_NVIDIA_GEFORCE6,  1536},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT610,      "NVIDIA GeForce GT 610",            DRIVER_NVIDIA_GEFORCE6,  1024},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT630,      "NVIDIA GeForce GT 630",            DRIVER_NVIDIA_GEFORCE6,  1024},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT630M,     "NVIDIA GeForce GT 630M",           DRIVER_NVIDIA_GEFORCE6,  1024},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT640M,     "NVIDIA GeForce GT 640M",           DRIVER_NVIDIA_GEFORCE6,  1024},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT650M,     "NVIDIA GeForce GT 650M",           DRIVER_NVIDIA_GEFORCE6,  2048},
@@ -1128,7 +1254,10 @@ static const struct gpu_description gpu_description_table[] =
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX660,     "NVIDIA GeForce GTX 660",           DRIVER_NVIDIA_GEFORCE6,  2048},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX660TI,   "NVIDIA GeForce GTX 660 Ti",        DRIVER_NVIDIA_GEFORCE6,  2048},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX670,     "NVIDIA GeForce GTX 670",           DRIVER_NVIDIA_GEFORCE6,  2048},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX670MX,   "NVIDIA GeForce GTX 670MX",         DRIVER_NVIDIA_GEFORCE6,  3072},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX680,     "NVIDIA GeForce GTX 680",           DRIVER_NVIDIA_GEFORCE6,  2048},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX770M,    "NVIDIA GeForce GTX 770M",          DRIVER_NVIDIA_GEFORCE6,  3072},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX770,     "NVIDIA GeForce GTX 770",           DRIVER_NVIDIA_GEFORCE6,  2048},
 
     /* AMD cards */
     {HW_VENDOR_AMD,        CARD_AMD_RAGE_128PRO,           "ATI Rage Fury",                    DRIVER_AMD_RAGE_128PRO,  16  },
@@ -1142,6 +1271,7 @@ static const struct gpu_description gpu_description_table[] =
     {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD2600,         "ATI Mobility Radeon HD 2600",      DRIVER_AMD_R600,         256 },
     {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD2900,         "ATI Radeon HD 2900 XT",            DRIVER_AMD_R600,         512 },
     {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD3200,         "ATI Radeon HD 3200 Graphics",      DRIVER_AMD_R600,         128 },
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD4200M,        "ATI Mobility Radeon HD 4200",      DRIVER_AMD_R600,         256 },
     {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD4350,         "ATI Radeon HD 4350",               DRIVER_AMD_R600,         256 },
     {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD4600,         "ATI Radeon HD 4600 Series",        DRIVER_AMD_R600,         512 },
     {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD4700,         "ATI Radeon HD 4700 Series",        DRIVER_AMD_R600,         512 },
@@ -1280,14 +1410,19 @@ static void init_driver_info(struct wined3d_driver_info *driver_info,
                     driver_os_version = 7;
                     driver_model = DRIVER_MODEL_NT6X;
                 }
+                else if (os_version.dwMinorVersion == 1)
+                {
+                    driver_os_version = 8;
+                    driver_model = DRIVER_MODEL_NT6X;
+                }
                 else
                 {
-                    if (os_version.dwMinorVersion > 1)
+                    if (os_version.dwMinorVersion > 2)
                     {
-                        FIXME("Unhandled OS version %u.%u, reporting Win 7.\n",
+                        FIXME("Unhandled OS version %u.%u, reporting Win 8.\n",
                                 os_version.dwMajorVersion, os_version.dwMinorVersion);
                     }
-                    driver_os_version = 8;
+                    driver_os_version = 9;
                     driver_model = DRIVER_MODEL_NT6X;
                 }
                 break;
@@ -1525,7 +1660,10 @@ static enum wined3d_pci_device select_card_nvidia_binary(const struct wined3d_gl
         }
         cards[] =
         {
+            {"GTX 770M",    CARD_NVIDIA_GEFORCE_GTX770M},   /* Geforce 700 - midend high mobile */
+            {"GTX 770",     CARD_NVIDIA_GEFORCE_GTX770},    /* Geforce 700 - highend */
             {"GTX 680",     CARD_NVIDIA_GEFORCE_GTX680},    /* Geforce 600 - highend */
+            {"GTX 670MX",   CARD_NVIDIA_GEFORCE_GTX670MX},  /* Geforce 600 - highend */
             {"GTX 670",     CARD_NVIDIA_GEFORCE_GTX670},    /* Geforce 600 - midend high */
             {"GTX 660 Ti",  CARD_NVIDIA_GEFORCE_GTX660TI},  /* Geforce 600 - midend high */
             {"GTX 660",     CARD_NVIDIA_GEFORCE_GTX660},    /* Geforce 600 - midend high */
@@ -1534,6 +1672,7 @@ static enum wined3d_pci_device select_card_nvidia_binary(const struct wined3d_gl
             {"GT 650M",     CARD_NVIDIA_GEFORCE_GT650M},    /* Geforce 600 - midend mobile */
             {"GT 640M",     CARD_NVIDIA_GEFORCE_GT640M},    /* Geforce 600 - midend mobile */
             {"GT 630M",     CARD_NVIDIA_GEFORCE_GT630M},    /* Geforce 600 - midend mobile */
+            {"GT 630",      CARD_NVIDIA_GEFORCE_GT630},     /* Geforce 600 - lowend */
             {"GT 610",      CARD_NVIDIA_GEFORCE_GT610},     /* Geforce 600 - lowend */
             {"GTX 580",     CARD_NVIDIA_GEFORCE_GTX580},    /* Geforce 500 - highend */
             {"GTX 570",     CARD_NVIDIA_GEFORCE_GTX570},    /* Geforce 500 - midend high */
@@ -1552,6 +1691,7 @@ static enum wined3d_pci_device select_card_nvidia_binary(const struct wined3d_gl
             {"GT 440",      CARD_NVIDIA_GEFORCE_GT440},     /* Geforce 400 - lowend */
             {"GT 430",      CARD_NVIDIA_GEFORCE_GT430},     /* Geforce 400 - lowend */
             {"GT 420",      CARD_NVIDIA_GEFORCE_GT420},     /* Geforce 400 - lowend */
+            {"410M",        CARD_NVIDIA_GEFORCE_410M},      /* Geforce 400 - lowend mobile */
             {"GT 330",      CARD_NVIDIA_GEFORCE_GT330},     /* Geforce 300 - highend */
             {"GTS 360M",    CARD_NVIDIA_GEFORCE_GTS350M},   /* Geforce 300 - highend mobile */
             {"GTS 350M",    CARD_NVIDIA_GEFORCE_GTS350M},   /* Geforce 300 - highend mobile */
@@ -1559,6 +1699,7 @@ static enum wined3d_pci_device select_card_nvidia_binary(const struct wined3d_gl
             {"GT 325M",     CARD_NVIDIA_GEFORCE_GT325M},    /* Geforce 300 - midend mobile */
             {"GT 320M",     CARD_NVIDIA_GEFORCE_GT320M},    /* Geforce 300 - midend mobile */
             {"320M",        CARD_NVIDIA_GEFORCE_320M},      /* Geforce 300 - midend mobile */
+            {"315M",        CARD_NVIDIA_GEFORCE_315M},      /* Geforce 300 - midend mobile */
             {"GTX 295",     CARD_NVIDIA_GEFORCE_GTX280},    /* Geforce 200 - highend */
             {"GTX 285",     CARD_NVIDIA_GEFORCE_GTX280},    /* Geforce 200 - highend */
             {"GTX 280",     CARD_NVIDIA_GEFORCE_GTX280},    /* Geforce 200 - highend */
@@ -1769,6 +1910,7 @@ static enum wined3d_pci_device select_card_amd_binary(const struct wined3d_gl_in
             {"HD 4550", CARD_AMD_RADEON_HD4350},    /* Radeon RV710 */
             {"HD 4350", CARD_AMD_RADEON_HD4350},    /* Radeon RV710 */
             /* R600/R700 integrated */
+            {"HD 4200M", CARD_AMD_RADEON_HD4200M},
             {"HD 3300", CARD_AMD_RADEON_HD3200},
             {"HD 3200", CARD_AMD_RADEON_HD3200},
             {"HD 3100", CARD_AMD_RADEON_HD3200},
@@ -1944,7 +2086,7 @@ static enum wined3d_pci_device select_card_amd_mesa(const struct wined3d_gl_info
         {"RV730",       CARD_AMD_RADEON_HD4600},
         {"RV710",       CARD_AMD_RADEON_HD4350},
         /* R600/R700 integrated */
-        {"RS880",       CARD_AMD_RADEON_HD3200},
+        {"RS880",       CARD_AMD_RADEON_HD4200M},
         {"RS780",       CARD_AMD_RADEON_HD3200},
         /* R600 */
         {"R680",        CARD_AMD_RADEON_HD2900},
@@ -2011,6 +2153,7 @@ static enum wined3d_pci_device select_card_nvidia_mesa(const struct wined3d_gl_i
     cards[] =
     {
         /* Kepler */
+        {"NVE6",    CARD_NVIDIA_GEFORCE_GTX770M},
         {"NVE4",    CARD_NVIDIA_GEFORCE_GTX680},
         /* Fermi */
         {"NVD9",    CARD_NVIDIA_GEFORCE_GT520},
@@ -2247,7 +2390,7 @@ static enum wined3d_pci_device wined3d_guess_card(const struct wined3d_gl_info *
      * memory behind our backs if really needed. Note that the amount of video
      * memory can be overruled using a registry setting. */
 
-    int i;
+    unsigned int i;
     enum wined3d_pci_device device;
 
     for (i = 0; i < (sizeof(card_vendor_table) / sizeof(*card_vendor_table)); ++i)
@@ -2273,6 +2416,14 @@ static enum wined3d_pci_device wined3d_guess_card(const struct wined3d_gl_info *
     return select_card_fallback_nvidia(gl_info);
 }
 
+static const struct wined3d_vertex_pipe_ops *select_vertex_implementation(const struct wined3d_gl_info *gl_info,
+        const struct wined3d_shader_backend_ops *shader_backend_ops)
+{
+    if (shader_backend_ops == &glsl_shader_backend)
+        return &glsl_vertex_pipe;
+    return &ffp_vertex_pipe;
+}
+
 static const struct fragment_pipeline *select_fragment_implementation(const struct wined3d_gl_info *gl_info,
         const struct wined3d_shader_backend_ops *shader_backend_ops)
 {
@@ -2415,7 +2566,7 @@ static void wined3d_adapter_init_limits(struct wined3d_gl_info *gl_info)
     }
     else
     {
-        WARN("Driver doesn't guarantee a minimum buffer map alignment.\n");
+        WARN_(d3d_perf)("Driver doesn't guarantee a minimum buffer map alignment.\n");
     }
     if (gl_info->supported[NV_REGISTER_COMBINERS])
     {
@@ -2582,14 +2733,17 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter)
     struct wined3d_driver_info *driver_info = &adapter->driver_info;
     const char *gl_vendor_str, *gl_renderer_str, *gl_version_str;
     struct wined3d_gl_info *gl_info = &adapter->gl_info;
+    struct wined3d_vertex_caps vertex_caps;
     enum wined3d_pci_vendor card_vendor;
     struct fragment_caps fragment_caps;
+    struct shader_caps shader_caps;
     const char *WGL_Extensions = NULL;
     const char *GL_Extensions = NULL;
     enum wined3d_gl_vendor gl_vendor;
     enum wined3d_pci_device device;
     DWORD gl_version;
     HDC hdc;
+    unsigned int i;
 
     TRACE("adapter %p.\n", adapter);
 
@@ -2768,6 +2922,15 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter)
          * we never render to sRGB surfaces). */
         gl_info->supported[ARB_FRAMEBUFFER_SRGB] = FALSE;
     }
+    if (gl_info->supported[ARB_OCCLUSION_QUERY])
+    {
+        GLint counter_bits;
+
+        GL_EXTCALL(glGetQueryivARB(GL_SAMPLES_PASSED_ARB, GL_QUERY_COUNTER_BITS_ARB, &counter_bits));
+        TRACE("Occlusion query counter has %d bits.\n", counter_bits);
+        if (!counter_bits)
+            gl_info->supported[ARB_OCCLUSION_QUERY] = FALSE;
+    }
 
     wined3d_adapter_init_limits(gl_info);
 
@@ -2789,12 +2952,25 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter)
     checkGLcall("extension detection");
 
     adapter->shader_backend = select_shader_backend(gl_info);
+    adapter->vertex_pipe = select_vertex_implementation(gl_info, adapter->shader_backend);
     adapter->fragment_pipe = select_fragment_implementation(gl_info, adapter->shader_backend);
     adapter->blitter = select_blit_implementation(gl_info, adapter->shader_backend);
 
+    adapter->shader_backend->shader_get_caps(&adapter->gl_info, &shader_caps);
+    adapter->d3d_info.vs_clipping = shader_caps.wined3d_caps & WINED3D_SHADER_CAP_VS_CLIPPING;
+    adapter->d3d_info.limits.vs_version = shader_caps.vs_version;
+    adapter->d3d_info.limits.gs_version = shader_caps.gs_version;
+    adapter->d3d_info.limits.ps_version = shader_caps.ps_version;
+    adapter->d3d_info.limits.vs_uniform_count = shader_caps.vs_uniform_count;
+    adapter->d3d_info.limits.ps_uniform_count = shader_caps.ps_uniform_count;
+
+    adapter->vertex_pipe->vp_get_caps(gl_info, &vertex_caps);
+    adapter->d3d_info.xyzrhw = vertex_caps.xyzrhw;
+
     adapter->fragment_pipe->get_caps(gl_info, &fragment_caps);
-    gl_info->limits.texture_stages = fragment_caps.MaxTextureBlendStages;
-    TRACE("Max texture stages: %u.\n", gl_info->limits.texture_stages);
+    adapter->d3d_info.limits.ffp_blend_stages = fragment_caps.MaxTextureBlendStages;
+    adapter->d3d_info.limits.ffp_textures = fragment_caps.MaxSimultaneousTextures;
+    TRACE("Max texture stages: %u.\n", adapter->d3d_info.limits.ffp_blend_stages);
 
     if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT])
     {
@@ -2844,7 +3020,7 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter)
         }
         else if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
         {
-            WARN("Framebuffer objects not supported, falling back to backbuffer offscreen rendering mode.\n");
+            WARN_(d3d_perf)("Framebuffer objects not supported, falling back to backbuffer offscreen rendering mode.\n");
             wined3d_settings.offscreen_rendering_mode = ORM_BACKBUFFER;
         }
         if (gl_info->supported[EXT_FRAMEBUFFER_BLIT])
@@ -2874,6 +3050,10 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter)
     gl_info->wrap_lookup[WINED3D_TADDRESS_MIRROR_ONCE - WINED3D_TADDRESS_WRAP] =
             gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
 
+    adapter->d3d_info.valid_rt_mask = 0;
+    for (i = 0; i < gl_info->limits.buffers; ++i)
+        adapter->d3d_info.valid_rt_mask |= (1 << i);
+
     fixup_extensions(gl_info, gl_renderer_str, gl_vendor, card_vendor, device);
     init_driver_info(driver_info, card_vendor, device);
     add_gl_compat_wrappers(gl_info);
@@ -3599,6 +3779,14 @@ static BOOL CheckSurfaceCapability(const struct wined3d_adapter *adapter,
     return FALSE;
 }
 
+/* OpenGL supports mipmapping on all formats. Wrapping is unsupported, but we
+ * have to report mipmapping so we cannot reject WRAPANDMIP. Tests show that
+ * Windows reports WRAPANDMIP on unfilterable surfaces as well, apparently to
+ * show that wrapping is supported. The lack of filtering will sort out the
+ * mipmapping capability anyway.
+ *
+ * For now lets report this on all formats, but in the future we may want to
+ * restrict it to some should applications need that. */
 HRESULT CDECL wined3d_check_device_format(const struct wined3d *wined3d, UINT adapter_idx,
         enum wined3d_device_type device_type, enum wined3d_format_id adapter_format_id, DWORD usage,
         enum wined3d_resource_type resource_type, enum wined3d_format_id check_format_id)
@@ -3607,7 +3795,8 @@ HRESULT CDECL wined3d_check_device_format(const struct wined3d *wined3d, UINT ad
     const struct wined3d_gl_info *gl_info = &adapter->gl_info;
     const struct wined3d_format *adapter_format = wined3d_get_format(gl_info, adapter_format_id);
     const struct wined3d_format *format = wined3d_get_format(gl_info, check_format_id);
-    DWORD usage_caps = 0;
+    DWORD format_flags = 0;
+    DWORD allowed_usage;
 
     TRACE("wined3d %p, adapter_idx %u, device_type %s, adapter_format %s, usage %s, %s,\n"
             "resource_type %s, check_format %s.\n",
@@ -3621,375 +3810,94 @@ HRESULT CDECL wined3d_check_device_format(const struct wined3d *wined3d, UINT ad
     switch (resource_type)
     {
         case WINED3D_RTYPE_CUBE_TEXTURE:
-            /* Cubetexture allows:
-             *      - WINED3DUSAGE_AUTOGENMIPMAP
-             *      - WINED3DUSAGE_DEPTHSTENCIL
-             *      - WINED3DUSAGE_DYNAMIC
-             *      - WINED3DUSAGE_NONSECURE (d3d9ex)
-             *      - WINED3DUSAGE_RENDERTARGET
-             *      - WINED3DUSAGE_SOFTWAREPROCESSING
-             *      - WINED3DUSAGE_QUERY_WRAPANDMIP
-             */
-            if (wined3d->flags & WINED3D_NO3D)
-            {
-                TRACE("[FAILED]\n");
-                return WINED3DERR_NOTAVAILABLE;
-            }
-
             if (!gl_info->supported[ARB_TEXTURE_CUBE_MAP])
             {
                 TRACE("[FAILED] - No cube texture support.\n");
                 return WINED3DERR_NOTAVAILABLE;
             }
 
-            if (!(format->flags & WINED3DFMT_FLAG_TEXTURE))
-            {
-                TRACE("[FAILED] - Cube texture format not supported.\n");
-                return WINED3DERR_NOTAVAILABLE;
-            }
-
-            if (usage & WINED3DUSAGE_AUTOGENMIPMAP)
-            {
-                if (!gl_info->supported[SGIS_GENERATE_MIPMAP])
-                    /* When autogenmipmap isn't around continue and return
-                     * WINED3DOK_NOAUTOGEN instead of D3D_OK. */
-                    TRACE("[FAILED] - No autogenmipmap support, but continuing.\n");
-                else
-                    usage_caps |= WINED3DUSAGE_AUTOGENMIPMAP;
-            }
-
-            /* Always report dynamic locking. */
-            if (usage & WINED3DUSAGE_DYNAMIC)
-                usage_caps |= WINED3DUSAGE_DYNAMIC;
-
-            if (usage & WINED3DUSAGE_RENDERTARGET)
-            {
-                if (!CheckRenderTargetCapability(adapter, adapter_format, format))
-                {
-                    TRACE("[FAILED] - No render target support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_RENDERTARGET;
-            }
-
-            /* Always report software processing. */
-            if (usage & WINED3DUSAGE_SOFTWAREPROCESSING)
-                usage_caps |= WINED3DUSAGE_SOFTWAREPROCESSING;
-
-            if (usage & WINED3DUSAGE_QUERY_FILTER)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_FILTERING))
-                {
-                    TRACE("[FAILED] - No filter support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_FILTER;
-            }
-
-            if (usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING))
-                {
-                    TRACE("[FAILED] - No post pixelshader blending support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
-            }
-
-            if (usage & WINED3DUSAGE_QUERY_SRGBREAD)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_SRGB_READ))
-                {
-                    TRACE("[FAILED] - No sRGB read support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_SRGBREAD;
-            }
-
-            if (usage & WINED3DUSAGE_QUERY_SRGBWRITE)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_SRGB_WRITE))
-                {
-                    TRACE("[FAILED] - No sRGB write support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_SRGBWRITE;
-            }
-
-            if (usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_VTF))
-                {
-                    TRACE("[FAILED] - No vertex texture support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
-            }
-
-            /* OpenGL supports mipmapping on all formats. Wrapping is
-             * unsupported, but we have to report mipmapping so we cannot
-             * reject this flag. Tests show that Windows reports WRAPANDMIP on
-             * unfilterable surfaces as well, apparently to show that wrapping
-             * is supported. The lack of filtering will sort out the
-             * mipmapping capability anyway.
-             *
-             * For now lets report this on all formats, but in the future we
-             * may want to restrict it to some should applications need that. */
-            if (usage & WINED3DUSAGE_QUERY_WRAPANDMIP)
-                usage_caps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
-
+            format_flags |= WINED3DFMT_FLAG_TEXTURE;
+            allowed_usage = WINED3DUSAGE_AUTOGENMIPMAP
+                    | WINED3DUSAGE_DYNAMIC
+                    | WINED3DUSAGE_RENDERTARGET
+                    | WINED3DUSAGE_SOFTWAREPROCESSING
+                    | WINED3DUSAGE_QUERY_FILTER
+                    | WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING
+                    | WINED3DUSAGE_QUERY_SRGBREAD
+                    | WINED3DUSAGE_QUERY_SRGBWRITE
+                    | WINED3DUSAGE_QUERY_VERTEXTEXTURE
+                    | WINED3DUSAGE_QUERY_WRAPANDMIP;
             break;
 
         case WINED3D_RTYPE_SURFACE:
-            /* Surface allows:
-             *      - WINED3DUSAGE_DEPTHSTENCIL
-             *      - WINED3DUSAGE_NONSECURE (d3d9ex)
-             *      - WINED3DUSAGE_RENDERTARGET
-             */
             if (!CheckSurfaceCapability(adapter, adapter_format, format, wined3d->flags & WINED3D_NO3D))
             {
                 TRACE("[FAILED] - Not supported for plain surfaces.\n");
                 return WINED3DERR_NOTAVAILABLE;
             }
 
-            if (usage & WINED3DUSAGE_DEPTHSTENCIL)
-            {
-                if (!CheckDepthStencilCapability(adapter, adapter_format, format))
-                {
-                    TRACE("[FAILED] - No depth/stencil support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_DEPTHSTENCIL;
-            }
-
-            if (usage & WINED3DUSAGE_RENDERTARGET)
-            {
-                if (!CheckRenderTargetCapability(adapter, adapter_format, format))
-                {
-                    TRACE("[FAILED] - No render target support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_RENDERTARGET;
-            }
-
-            if (usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING))
-                {
-                    TRACE("[FAILED] - No post pixelshader blending support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
-            }
+            allowed_usage = WINED3DUSAGE_DEPTHSTENCIL
+                    | WINED3DUSAGE_RENDERTARGET
+                    | WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
             break;
 
         case WINED3D_RTYPE_TEXTURE:
-            /* Texture allows:
-             *      - WINED3DUSAGE_AUTOGENMIPMAP
-             *      - WINED3DUSAGE_DEPTHSTENCIL
-             *      - WINED3DUSAGE_DMAP
-             *      - WINED3DUSAGE_DYNAMIC
-             *      - WINED3DUSAGE_NONSECURE (d3d9ex)
-             *      - WINED3DUSAGE_RENDERTARGET
-             *      - WINED3DUSAGE_SOFTWAREPROCESSING
-             *      - WINED3DUSAGE_TEXTAPI (d3d9ex)
-             *      - WINED3DUSAGE_QUERY_WRAPANDMIP
-             */
-            if (wined3d->flags & WINED3D_NO3D)
-            {
-                TRACE("[FAILED]\n");
-                return WINED3DERR_NOTAVAILABLE;
-            }
-
-            if (!(format->flags & WINED3DFMT_FLAG_TEXTURE))
+            if ((usage & WINED3DUSAGE_DEPTHSTENCIL) && (format->flags & WINED3DFMT_FLAG_SHADOW)
+                    && !gl_info->supported[ARB_SHADOW])
             {
-                TRACE("[FAILED] - Texture format not supported.\n");
+                TRACE("[FAILED] - No shadow sampler support.\n");
                 return WINED3DERR_NOTAVAILABLE;
             }
 
-            if (usage & WINED3DUSAGE_AUTOGENMIPMAP)
-            {
-                if (!gl_info->supported[SGIS_GENERATE_MIPMAP])
-                    /* When autogenmipmap isn't around continue and return
-                     * WINED3DOK_NOAUTOGEN instead of D3D_OK. */
-                    TRACE("[FAILED] - No autogenmipmap support, but continuing.\n");
-                else
-                    usage_caps |= WINED3DUSAGE_AUTOGENMIPMAP;
-            }
-
-            /* Always report dynamic locking. */
-            if (usage & WINED3DUSAGE_DYNAMIC)
-                usage_caps |= WINED3DUSAGE_DYNAMIC;
-
-            if (usage & WINED3DUSAGE_RENDERTARGET)
-            {
-                if (!CheckRenderTargetCapability(adapter, adapter_format, format))
-                {
-                    TRACE("[FAILED] - No render target support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_RENDERTARGET;
-            }
-
-            /* Always report software processing. */
-            if (usage & WINED3DUSAGE_SOFTWAREPROCESSING)
-                usage_caps |= WINED3DUSAGE_SOFTWAREPROCESSING;
-
-            if (usage & WINED3DUSAGE_QUERY_FILTER)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_FILTERING))
-                {
-                    TRACE("[FAILED] - No filter support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_FILTER;
-            }
-
-            if (usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_BUMPMAP))
-                {
-                    TRACE("[FAILED] - No legacy bumpmap support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_LEGACYBUMPMAP;
-            }
-
-            if (usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING))
-                {
-                    TRACE("[FAILED] - No post pixelshader blending support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
-            }
-
-            if (usage & WINED3DUSAGE_QUERY_SRGBREAD)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_SRGB_READ))
-                {
-                    TRACE("[FAILED] - No sRGB read support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_SRGBREAD;
-            }
-
-            if (usage & WINED3DUSAGE_QUERY_SRGBWRITE)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_SRGB_WRITE))
-                {
-                    TRACE("[FAILED] - No sRGB write support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_SRGBWRITE;
-            }
-
-            if (usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_VTF))
-                {
-                    TRACE("[FAILED] - No vertex texture support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
-            }
-
-            if (usage & WINED3DUSAGE_QUERY_WRAPANDMIP)
-                usage_caps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
-
-            if (usage & WINED3DUSAGE_DEPTHSTENCIL)
-            {
-                if (!CheckDepthStencilCapability(adapter, adapter_format, format))
-                {
-                    TRACE("[FAILED] - No depth/stencil support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                if ((format->flags & WINED3DFMT_FLAG_SHADOW) && !gl_info->supported[ARB_SHADOW])
-                {
-                    TRACE("[FAILED] - No shadow sampler support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_DEPTHSTENCIL;
-            }
+            format_flags |= WINED3DFMT_FLAG_TEXTURE;
+            allowed_usage = WINED3DUSAGE_AUTOGENMIPMAP
+                    | WINED3DUSAGE_DEPTHSTENCIL
+                    | WINED3DUSAGE_DYNAMIC
+                    | WINED3DUSAGE_RENDERTARGET
+                    | WINED3DUSAGE_SOFTWAREPROCESSING
+                    | WINED3DUSAGE_QUERY_FILTER
+                    | WINED3DUSAGE_QUERY_LEGACYBUMPMAP
+                    | WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING
+                    | WINED3DUSAGE_QUERY_SRGBREAD
+                    | WINED3DUSAGE_QUERY_SRGBWRITE
+                    | WINED3DUSAGE_QUERY_VERTEXTEXTURE
+                    | WINED3DUSAGE_QUERY_WRAPANDMIP;
             break;
 
         case WINED3D_RTYPE_VOLUME_TEXTURE:
         case WINED3D_RTYPE_VOLUME:
             /* Volume is to VolumeTexture what Surface is to Texture, but its
              * usage caps are not documented. Most driver seem to offer
-             * (nearly) the same on Volume and VolumeTexture, so do that too.
-             *
-             * Volumetexture allows:
-             *      - D3DUSAGE_DYNAMIC
-             *      - D3DUSAGE_NONSECURE (d3d9ex)
-             *      - D3DUSAGE_SOFTWAREPROCESSING
-             *      - D3DUSAGE_QUERY_WRAPANDMIP
-             */
-            if (wined3d->flags & WINED3D_NO3D)
-            {
-                TRACE("[FAILED]\n");
-                return WINED3DERR_NOTAVAILABLE;
-            }
-
+             * (nearly) the same on Volume and VolumeTexture, so do that too. */
             if (!gl_info->supported[EXT_TEXTURE3D])
             {
                 TRACE("[FAILED] - No volume texture support.\n");
                 return WINED3DERR_NOTAVAILABLE;
             }
 
-            if (!(format->flags & WINED3DFMT_FLAG_TEXTURE))
-            {
-                TRACE("[FAILED] - Format not supported.\n");
-                return WINED3DERR_NOTAVAILABLE;
-            }
-
             /* Filter formats that need conversion; For one part, this
              * conversion is unimplemented, and volume textures are huge, so
              * it would be a big performance hit. Unless we hit an application
              * needing one of those formats, don't advertize them to avoid
              * leading applications into temptation. The windows drivers don't
-             * support most of those formats on volumes anyway, except for
-             * WINED3DFMT_R32_FLOAT. */
-            switch (check_format_id)
+             * support most of those formats on volumes anyway. */
+            if (format->convert)
             {
-                case WINED3DFMT_P8_UINT:
-                case WINED3DFMT_L4A4_UNORM:
-                case WINED3DFMT_R32_FLOAT:
-                case WINED3DFMT_R16_FLOAT:
-                case WINED3DFMT_R8G8_SNORM_L8X8_UNORM:
-                case WINED3DFMT_R5G5_SNORM_L6_UNORM:
-                case WINED3DFMT_R16G16_UNORM:
-                    TRACE("[FAILED] - No converted formats on volumes.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-
-                case WINED3DFMT_R8G8B8A8_SNORM:
-                case WINED3DFMT_R16G16_SNORM:
-                    if (!gl_info->supported[NV_TEXTURE_SHADER])
-                    {
-                        TRACE("[FAILED] - No converted formats on volumes.\n");
-                        return WINED3DERR_NOTAVAILABLE;
-                    }
-                    break;
-
-                case WINED3DFMT_R8G8_SNORM:
-                    if (!gl_info->supported[NV_TEXTURE_SHADER])
-                    {
-                        TRACE("[FAILED] - No converted formats on volumes.\n");
-                        return WINED3DERR_NOTAVAILABLE;
-                    }
-                    break;
+                TRACE("[FAILED] - No converted formats on volumes.\n");
+                return WINED3DERR_NOTAVAILABLE;
+            }
 
+            /* The GL_EXT_texture_compression_s3tc spec requires that loading
+             * an s3tc compressed texture results in an error. While the D3D
+             * refrast does support s3tc volumes, at least the nvidia Windows
+             * driver does not, so we're free not to support this format. */
+            switch (check_format_id)
+            {
                 case WINED3DFMT_DXT1:
                 case WINED3DFMT_DXT2:
                 case WINED3DFMT_DXT3:
                 case WINED3DFMT_DXT4:
                 case WINED3DFMT_DXT5:
-                    /* The GL_EXT_texture_compression_s3tc spec requires that
-                     * loading an s3tc compressed texture results in an error.
-                     * While the D3D refrast does support s3tc volumes, at
-                     * least the nvidia windows driver does not, so we're free
-                     * not to support this format. */
                     TRACE("[FAILED] - DXTn does not support 3D textures.\n");
                     return WINED3DERR_NOTAVAILABLE;
 
@@ -3998,86 +3906,78 @@ HRESULT CDECL wined3d_check_device_format(const struct wined3d *wined3d, UINT ad
                     break;
             }
 
-            /* Always report dynamic locking. */
-            if (usage & WINED3DUSAGE_DYNAMIC)
-                usage_caps |= WINED3DUSAGE_DYNAMIC;
-
-            /* Always report software processing. */
-            if (usage & WINED3DUSAGE_SOFTWAREPROCESSING)
-                usage_caps |= WINED3DUSAGE_SOFTWAREPROCESSING;
-
-            if (usage & WINED3DUSAGE_QUERY_FILTER)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_FILTERING))
-                {
-                    TRACE("[FAILED] - No filter support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_FILTER;
-            }
+            format_flags |= WINED3DFMT_FLAG_TEXTURE;
+            allowed_usage = WINED3DUSAGE_DYNAMIC
+                    | WINED3DUSAGE_SOFTWAREPROCESSING
+                    | WINED3DUSAGE_QUERY_FILTER
+                    | WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING
+                    | WINED3DUSAGE_QUERY_SRGBREAD
+                    | WINED3DUSAGE_QUERY_SRGBWRITE
+                    | WINED3DUSAGE_QUERY_VERTEXTEXTURE
+                    | WINED3DUSAGE_QUERY_WRAPANDMIP;
+            break;
 
-            if (usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING))
-                {
-                    TRACE("[FAILED] - No post pixelshader blending support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
-            }
+        default:
+            FIXME("Unhandled resource type %s.\n", debug_d3dresourcetype(resource_type));
+            return WINED3DERR_NOTAVAILABLE;
+    }
 
-            if (usage & WINED3DUSAGE_QUERY_SRGBREAD)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_SRGB_READ))
-                {
-                    TRACE("[FAILED] - No sRGB read support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_SRGBREAD;
-            }
+    if ((usage & allowed_usage) != usage)
+    {
+        TRACE("Requested usage %#x, but resource type %s only allows %#x.\n",
+                usage, debug_d3dresourcetype(resource_type), allowed_usage);
+        return WINED3DERR_NOTAVAILABLE;
+    }
 
-            if (usage & WINED3DUSAGE_QUERY_SRGBWRITE)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_SRGB_WRITE))
-                {
-                    TRACE("[FAILED] - No sRGB write support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_SRGBWRITE;
-            }
+    if (usage & WINED3DUSAGE_QUERY_FILTER)
+        format_flags |= WINED3DFMT_FLAG_FILTERING;
+    if (usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING)
+        format_flags |= WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING;
+    if (usage & WINED3DUSAGE_QUERY_SRGBREAD)
+        format_flags |= WINED3DFMT_FLAG_SRGB_READ;
+    if (usage & WINED3DUSAGE_QUERY_SRGBWRITE)
+        format_flags |= WINED3DFMT_FLAG_SRGB_WRITE;
+    if (usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE)
+        format_flags |= WINED3DFMT_FLAG_VTF;
+    if (usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP)
+        format_flags |= WINED3DFMT_FLAG_BUMPMAP;
 
-            if (usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_VTF))
-                {
-                    TRACE("[FAILED] - No vertex texture support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
-            }
+    if ((format->flags & format_flags) != format_flags)
+    {
+        TRACE("Requested format flags %#x, but format %s only has %#x.\n",
+                format_flags, debug_d3dformat(check_format_id), format->flags);
+        return WINED3DERR_NOTAVAILABLE;
+    }
 
-            if (usage & WINED3DUSAGE_QUERY_WRAPANDMIP)
-                usage_caps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
+    if ((format_flags & WINED3DFMT_FLAG_TEXTURE) && (wined3d->flags & WINED3D_NO3D))
+    {
+        TRACE("Requested texturing support, but wined3d was created with WINED3D_NO3D.\n");
+        return WINED3DERR_NOTAVAILABLE;
+    }
 
-            break;
+    if ((usage & WINED3DUSAGE_DEPTHSTENCIL)
+            && !CheckDepthStencilCapability(adapter, adapter_format, format))
+    {
+        TRACE("Requested WINED3DUSAGE_DEPTHSTENCIL, but format %s is not supported for depth / stencil buffers.\n",
+                debug_d3dformat(check_format_id));
+        return WINED3DERR_NOTAVAILABLE;
+    }
 
-        default:
-            FIXME("Unhandled resource type %s.\n", debug_d3dresourcetype(resource_type));
-            return WINED3DERR_NOTAVAILABLE;
+    if ((usage & WINED3DUSAGE_RENDERTARGET)
+            && !CheckRenderTargetCapability(adapter, adapter_format, format))
+    {
+        TRACE("Requested WINED3DUSAGE_RENDERTARGET, but format %s is not supported for render targets.\n",
+                debug_d3dformat(check_format_id));
+        return WINED3DERR_NOTAVAILABLE;
     }
 
-    /* When the usage_caps exactly matches usage return WINED3D_OK except for
-     * the situation in which WINED3DUSAGE_AUTOGENMIPMAP isn't around, then
-     * WINED3DOK_NOAUTOGEN is returned if all the other usage flags match. */
-    if (usage_caps == usage)
-        return WINED3D_OK;
-    if (usage_caps == (usage & ~WINED3DUSAGE_AUTOGENMIPMAP))
+    if ((usage & WINED3DUSAGE_AUTOGENMIPMAP) && !gl_info->supported[SGIS_GENERATE_MIPMAP])
+    {
+        TRACE("No WINED3DUSAGE_AUTOGENMIPMAP support, returning WINED3DOK_NOAUTOGEN.\n");
         return WINED3DOK_NOAUTOGEN;
+    }
 
-    TRACE("[FAILED] - Usage %#x requested for format %s and resource_type %s but only %#x is available.\n",
-            usage, debug_d3dformat(check_format_id), debug_d3dresourcetype(resource_type), usage_caps);
-
-    return WINED3DERR_NOTAVAILABLE;
+    return WINED3D_OK;
 }
 
 HRESULT CDECL wined3d_check_device_format_conversion(const struct wined3d *wined3d, UINT adapter_idx,
@@ -4198,6 +4098,7 @@ HRESULT CDECL wined3d_get_device_caps(const struct wined3d *wined3d, UINT adapte
     const struct wined3d_gl_info *gl_info = &adapter->gl_info;
     struct shader_caps shader_caps;
     struct fragment_caps fragment_caps;
+    struct wined3d_vertex_caps vertex_caps;
     DWORD ckey_caps, blit_caps, fx_caps, pal_caps;
 
     TRACE("wined3d %p, adapter_idx %u, device_type %s, caps %p.\n",
@@ -4282,16 +4183,6 @@ HRESULT CDECL wined3d_get_device_caps(const struct wined3d *wined3d, UINT adapte
                              WINED3DPRASTERCAPS_ZBIAS         |
                              WINED3DPRASTERCAPS_MIPMAPLODBIAS;
     }
-    if (gl_info->supported[NV_FOG_DISTANCE])
-    {
-        caps->RasterCaps          |= WINED3DPRASTERCAPS_FOGRANGE;
-    }
-                        /* FIXME Add:
-                           WINED3DPRASTERCAPS_COLORPERSPECTIVE
-                           WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
-                           WINED3DPRASTERCAPS_ANTIALIASEDGES
-                           WINED3DPRASTERCAPS_ZBUFFERLESSHSR
-                           WINED3DPRASTERCAPS_WBUFFER */
 
     caps->ZCmpCaps =  WINED3DPCMPCAPS_ALWAYS       |
                       WINED3DPCMPCAPS_EQUAL        |
@@ -4541,26 +4432,9 @@ HRESULT CDECL wined3d_get_device_caps(const struct wined3d *wined3d, UINT adapte
         caps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
     }
 
-    caps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
-
-    caps->MaxUserClipPlanes = gl_info->limits.clipplanes;
-    caps->MaxActiveLights = gl_info->limits.lights;
-
-    caps->MaxVertexBlendMatrices = gl_info->limits.blends;
-    caps->MaxVertexBlendMatrixIndex   = 0;
-
     caps->MaxAnisotropy = gl_info->limits.anisotropy;
     caps->MaxPointSize = gl_info->limits.pointsize_max;
 
-
-    /* FIXME: Add D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
-    caps->VertexProcessingCaps  = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
-                                  WINED3DVTXPCAPS_MATERIALSOURCE7   |
-                                  WINED3DVTXPCAPS_POSITIONALLIGHTS  |
-                                  WINED3DVTXPCAPS_LOCALVIEWER       |
-                                  WINED3DVTXPCAPS_VERTEXFOG         |
-                                  WINED3DVTXPCAPS_TEXGEN;
-
     caps->MaxPrimitiveCount   = 0xfffff; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
     caps->MaxVertexIndex      = 0xfffff;
     caps->MaxStreams          = MAX_STREAMS;
@@ -4584,6 +4458,7 @@ HRESULT CDECL wined3d_get_device_caps(const struct wined3d *wined3d, UINT adapte
 
     adapter->shader_backend->shader_get_caps(&adapter->gl_info, &shader_caps);
     adapter->fragment_pipe->get_caps(&adapter->gl_info, &fragment_caps);
+    adapter->vertex_pipe->vp_get_caps(&adapter->gl_info, &vertex_caps);
 
     /* Add shader misc caps. Only some of them belong to the shader parts of the pipeline */
     caps->PrimitiveMiscCaps |= fragment_caps.PrimitiveMiscCaps;
@@ -4598,6 +4473,14 @@ HRESULT CDECL wined3d_get_device_caps(const struct wined3d *wined3d, UINT adapte
     caps->MaxTextureBlendStages            = fragment_caps.MaxTextureBlendStages;
     caps->MaxSimultaneousTextures          = fragment_caps.MaxSimultaneousTextures;
 
+    caps->MaxUserClipPlanes                = vertex_caps.max_user_clip_planes;
+    caps->MaxActiveLights                  = vertex_caps.max_active_lights;
+    caps->MaxVertexBlendMatrices           = vertex_caps.max_vertex_blend_matrices;
+    caps->MaxVertexBlendMatrixIndex        = vertex_caps.max_vertex_blend_matrix_index;
+    caps->VertexProcessingCaps             = vertex_caps.vertex_processing_caps;
+    caps->FVFCaps                          = vertex_caps.fvf_caps;
+    caps->RasterCaps                      |= vertex_caps.raster_caps;
+
     /* The following caps are shader specific, but they are things we cannot detect, or which
      * are the same among all shader models. So to avoid code duplication set the shader version
      * specific, but otherwise constant caps here
@@ -4775,7 +4658,6 @@ HRESULT CDECL wined3d_get_device_caps(const struct wined3d *wined3d, UINT adapte
                                         WINEDDSCAPS_SYSTEMMEMORY            |
                                         WINEDDSCAPS_VIDEOMEMORY             |
                                         WINEDDSCAPS_VISIBLE;
-    caps->ddraw_caps.stride_align = DDRAW_PITCH_ALIGNMENT;
 
     if (!(wined3d->flags & WINED3D_NO3D))
     {
@@ -4880,11 +4762,14 @@ static void WINE_GLAPI diffuse_d3dcolor(const void *data)
 static void WINE_GLAPI specular_d3dcolor(const void *data)
 {
     DWORD specularColor = *((const DWORD *)data);
-    GLbyte d[] = {D3DCOLOR_B_R(specularColor),
-            D3DCOLOR_B_G(specularColor),
-            D3DCOLOR_B_B(specularColor)};
+    GLubyte d[] =
+    {
+        D3DCOLOR_B_R(specularColor),
+        D3DCOLOR_B_G(specularColor),
+        D3DCOLOR_B_B(specularColor)
+    };
 
-    specular_func_3ubv(d);
+    context_get_current()->gl_info->gl_ops.ext.p_glSecondaryColor3ubvEXT(d);
 }
 
 static void WINE_GLAPI warn_no_specular_func(const void *data)
@@ -4892,129 +4777,137 @@ static void WINE_GLAPI warn_no_specular_func(const void *data)
     WARN("GL_EXT_secondary_color not supported\n");
 }
 
-static void fillGLAttribFuncs(const struct wined3d_gl_info *gl_info)
+static void wined3d_adapter_init_ffp_attrib_ops(struct wined3d_adapter *adapter)
 {
-    position_funcs[WINED3D_FFP_EMIT_FLOAT1]      = invalid_func;
-    position_funcs[WINED3D_FFP_EMIT_FLOAT2]      = invalid_func;
-    position_funcs[WINED3D_FFP_EMIT_FLOAT3]      = (glAttribFunc)gl_info->gl_ops.gl.p_glVertex3fv;
-    position_funcs[WINED3D_FFP_EMIT_FLOAT4]      = position_float4;
-    position_funcs[WINED3D_FFP_EMIT_D3DCOLOR]    = position_d3dcolor;
-    position_funcs[WINED3D_FFP_EMIT_UBYTE4]      = invalid_func;
-    position_funcs[WINED3D_FFP_EMIT_SHORT2]      = invalid_func;
-    position_funcs[WINED3D_FFP_EMIT_SHORT4]      = (glAttribFunc)gl_info->gl_ops.gl.p_glVertex2sv;
-    position_funcs[WINED3D_FFP_EMIT_UBYTE4N]     = invalid_func;
-    position_funcs[WINED3D_FFP_EMIT_SHORT2N]     = invalid_func;
-    position_funcs[WINED3D_FFP_EMIT_SHORT4N]     = invalid_func;
-    position_funcs[WINED3D_FFP_EMIT_USHORT2N]    = invalid_func;
-    position_funcs[WINED3D_FFP_EMIT_USHORT4N]    = invalid_func;
-    position_funcs[WINED3D_FFP_EMIT_UDEC3]       = invalid_func;
-    position_funcs[WINED3D_FFP_EMIT_DEC3N]       = invalid_func;
-    position_funcs[WINED3D_FFP_EMIT_FLOAT16_2]   = invalid_func;
-    position_funcs[WINED3D_FFP_EMIT_FLOAT16_4]   = invalid_func;
-
-    diffuse_funcs[WINED3D_FFP_EMIT_FLOAT1]       = invalid_func;
-    diffuse_funcs[WINED3D_FFP_EMIT_FLOAT2]       = invalid_func;
-    diffuse_funcs[WINED3D_FFP_EMIT_FLOAT3]       = (glAttribFunc)gl_info->gl_ops.gl.p_glColor3fv;
-    diffuse_funcs[WINED3D_FFP_EMIT_FLOAT4]       = (glAttribFunc)gl_info->gl_ops.gl.p_glColor4fv;
-    diffuse_funcs[WINED3D_FFP_EMIT_D3DCOLOR]     = diffuse_d3dcolor;
-    diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4]       = invalid_func;
-    diffuse_funcs[WINED3D_FFP_EMIT_SHORT2]       = invalid_func;
-    diffuse_funcs[WINED3D_FFP_EMIT_SHORT4]       = invalid_func;
-    diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4N]      = (glAttribFunc)gl_info->gl_ops.gl.p_glColor4ubv;
-    diffuse_funcs[WINED3D_FFP_EMIT_SHORT2N]      = invalid_func;
-    diffuse_funcs[WINED3D_FFP_EMIT_SHORT4N]      = (glAttribFunc)gl_info->gl_ops.gl.p_glColor4sv;
-    diffuse_funcs[WINED3D_FFP_EMIT_USHORT2N]     = invalid_func;
-    diffuse_funcs[WINED3D_FFP_EMIT_USHORT4N]     = (glAttribFunc)gl_info->gl_ops.gl.p_glColor4usv;
-    diffuse_funcs[WINED3D_FFP_EMIT_UDEC3]        = invalid_func;
-    diffuse_funcs[WINED3D_FFP_EMIT_DEC3N]        = invalid_func;
-    diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_2]    = invalid_func;
-    diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_4]    = invalid_func;
-
-    /* No 4 component entry points here */
-    specular_funcs[WINED3D_FFP_EMIT_FLOAT1]      = invalid_func;
-    specular_funcs[WINED3D_FFP_EMIT_FLOAT2]      = invalid_func;
+    const struct wined3d_gl_info *gl_info = &adapter->gl_info;
+    struct wined3d_d3d_info *d3d_info = &adapter->d3d_info;
+    struct wined3d_ffp_attrib_ops *ops = &d3d_info->ffp_attrib_ops;
+
+    ops->position[WINED3D_FFP_EMIT_FLOAT1]    = invalid_func;
+    ops->position[WINED3D_FFP_EMIT_FLOAT2]    = invalid_func;
+    ops->position[WINED3D_FFP_EMIT_FLOAT3]    = (wined3d_ffp_attrib_func)gl_info->gl_ops.gl.p_glVertex3fv;
+    if (!d3d_info->xyzrhw)
+        ops->position[WINED3D_FFP_EMIT_FLOAT4]    = position_float4;
+    else
+        ops->position[WINED3D_FFP_EMIT_FLOAT4]    = (wined3d_ffp_attrib_func)gl_info->gl_ops.gl.p_glVertex4fv;
+    ops->position[WINED3D_FFP_EMIT_D3DCOLOR]  = position_d3dcolor;
+    ops->position[WINED3D_FFP_EMIT_UBYTE4]    = invalid_func;
+    ops->position[WINED3D_FFP_EMIT_SHORT2]    = invalid_func;
+    ops->position[WINED3D_FFP_EMIT_SHORT4]    = (wined3d_ffp_attrib_func)gl_info->gl_ops.gl.p_glVertex2sv;
+    ops->position[WINED3D_FFP_EMIT_UBYTE4N]   = invalid_func;
+    ops->position[WINED3D_FFP_EMIT_SHORT2N]   = invalid_func;
+    ops->position[WINED3D_FFP_EMIT_SHORT4N]   = invalid_func;
+    ops->position[WINED3D_FFP_EMIT_USHORT2N]  = invalid_func;
+    ops->position[WINED3D_FFP_EMIT_USHORT4N]  = invalid_func;
+    ops->position[WINED3D_FFP_EMIT_UDEC3]     = invalid_func;
+    ops->position[WINED3D_FFP_EMIT_DEC3N]     = invalid_func;
+    ops->position[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
+    ops->position[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
+    ops->position[WINED3D_FFP_EMIT_INVALID]   = invalid_func;
+
+    ops->diffuse[WINED3D_FFP_EMIT_FLOAT1]     = invalid_func;
+    ops->diffuse[WINED3D_FFP_EMIT_FLOAT2]     = invalid_func;
+    ops->diffuse[WINED3D_FFP_EMIT_FLOAT3]     = (wined3d_ffp_attrib_func)gl_info->gl_ops.gl.p_glColor3fv;
+    ops->diffuse[WINED3D_FFP_EMIT_FLOAT4]     = (wined3d_ffp_attrib_func)gl_info->gl_ops.gl.p_glColor4fv;
+    ops->diffuse[WINED3D_FFP_EMIT_D3DCOLOR]   = diffuse_d3dcolor;
+    ops->diffuse[WINED3D_FFP_EMIT_UBYTE4]     = invalid_func;
+    ops->diffuse[WINED3D_FFP_EMIT_SHORT2]     = invalid_func;
+    ops->diffuse[WINED3D_FFP_EMIT_SHORT4]     = invalid_func;
+    ops->diffuse[WINED3D_FFP_EMIT_UBYTE4N]    = (wined3d_ffp_attrib_func)gl_info->gl_ops.gl.p_glColor4ubv;
+    ops->diffuse[WINED3D_FFP_EMIT_SHORT2N]    = invalid_func;
+    ops->diffuse[WINED3D_FFP_EMIT_SHORT4N]    = (wined3d_ffp_attrib_func)gl_info->gl_ops.gl.p_glColor4sv;
+    ops->diffuse[WINED3D_FFP_EMIT_USHORT2N]   = invalid_func;
+    ops->diffuse[WINED3D_FFP_EMIT_USHORT4N]   = (wined3d_ffp_attrib_func)gl_info->gl_ops.gl.p_glColor4usv;
+    ops->diffuse[WINED3D_FFP_EMIT_UDEC3]      = invalid_func;
+    ops->diffuse[WINED3D_FFP_EMIT_DEC3N]      = invalid_func;
+    ops->diffuse[WINED3D_FFP_EMIT_FLOAT16_2]  = invalid_func;
+    ops->diffuse[WINED3D_FFP_EMIT_FLOAT16_4]  = invalid_func;
+    ops->diffuse[WINED3D_FFP_EMIT_INVALID]    = invalid_func;
+
+    /* No 4 component entry points here. */
+    ops->specular[WINED3D_FFP_EMIT_FLOAT1]    = invalid_func;
+    ops->specular[WINED3D_FFP_EMIT_FLOAT2]    = invalid_func;
     if (gl_info->supported[EXT_SECONDARY_COLOR])
-    {
-        specular_funcs[WINED3D_FFP_EMIT_FLOAT3]  = (glAttribFunc)GL_EXTCALL(glSecondaryColor3fvEXT);
-    }
+        ops->specular[WINED3D_FFP_EMIT_FLOAT3]    = (wined3d_ffp_attrib_func)GL_EXTCALL(glSecondaryColor3fvEXT);
     else
-    {
-        specular_funcs[WINED3D_FFP_EMIT_FLOAT3]  = warn_no_specular_func;
-    }
-    specular_funcs[WINED3D_FFP_EMIT_FLOAT4]      = invalid_func;
+        ops->specular[WINED3D_FFP_EMIT_FLOAT3]    = warn_no_specular_func;
+    ops->specular[WINED3D_FFP_EMIT_FLOAT4]    = invalid_func;
     if (gl_info->supported[EXT_SECONDARY_COLOR])
+        ops->specular[WINED3D_FFP_EMIT_D3DCOLOR]  = specular_d3dcolor;
+    else
+        ops->specular[WINED3D_FFP_EMIT_D3DCOLOR]  = warn_no_specular_func;
+    ops->specular[WINED3D_FFP_EMIT_UBYTE4]    = invalid_func;
+    ops->specular[WINED3D_FFP_EMIT_SHORT2]    = invalid_func;
+    ops->specular[WINED3D_FFP_EMIT_SHORT4]    = invalid_func;
+    ops->specular[WINED3D_FFP_EMIT_UBYTE4N]   = invalid_func;
+    ops->specular[WINED3D_FFP_EMIT_SHORT2N]   = invalid_func;
+    ops->specular[WINED3D_FFP_EMIT_SHORT4N]   = invalid_func;
+    ops->specular[WINED3D_FFP_EMIT_USHORT2N]  = invalid_func;
+    ops->specular[WINED3D_FFP_EMIT_USHORT4N]  = invalid_func;
+    ops->specular[WINED3D_FFP_EMIT_UDEC3]     = invalid_func;
+    ops->specular[WINED3D_FFP_EMIT_DEC3N]     = invalid_func;
+    ops->specular[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
+    ops->specular[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
+    ops->specular[WINED3D_FFP_EMIT_INVALID]   = invalid_func;
+
+    /* Only 3 component entry points here. Test how others behave. Float4
+     * normals are used by one of our tests, trying to pass it to the pixel
+     * shader, which fails on Windows. */
+    ops->normal[WINED3D_FFP_EMIT_FLOAT1]      = invalid_func;
+    ops->normal[WINED3D_FFP_EMIT_FLOAT2]      = invalid_func;
+    ops->normal[WINED3D_FFP_EMIT_FLOAT3]      = (wined3d_ffp_attrib_func)gl_info->gl_ops.gl.p_glNormal3fv;
+    /* Just ignore the 4th value. */
+    ops->normal[WINED3D_FFP_EMIT_FLOAT4]      = (wined3d_ffp_attrib_func)gl_info->gl_ops.gl.p_glNormal3fv;
+    ops->normal[WINED3D_FFP_EMIT_D3DCOLOR]    = invalid_func;
+    ops->normal[WINED3D_FFP_EMIT_UBYTE4]      = invalid_func;
+    ops->normal[WINED3D_FFP_EMIT_SHORT2]      = invalid_func;
+    ops->normal[WINED3D_FFP_EMIT_SHORT4]      = invalid_func;
+    ops->normal[WINED3D_FFP_EMIT_UBYTE4N]     = invalid_func;
+    ops->normal[WINED3D_FFP_EMIT_SHORT2N]     = invalid_func;
+    ops->normal[WINED3D_FFP_EMIT_SHORT4N]     = invalid_func;
+    ops->normal[WINED3D_FFP_EMIT_USHORT2N]    = invalid_func;
+    ops->normal[WINED3D_FFP_EMIT_USHORT4N]    = invalid_func;
+    ops->normal[WINED3D_FFP_EMIT_UDEC3]       = invalid_func;
+    ops->normal[WINED3D_FFP_EMIT_DEC3N]       = invalid_func;
+    ops->normal[WINED3D_FFP_EMIT_FLOAT16_2]   = invalid_func;
+    ops->normal[WINED3D_FFP_EMIT_FLOAT16_4]   = invalid_func;
+    ops->normal[WINED3D_FFP_EMIT_INVALID]     = invalid_func;
+
+    ops->texcoord[WINED3D_FFP_EMIT_FLOAT1]    = (wined3d_ffp_texcoord_func)gl_info->gl_ops.ext.p_glMultiTexCoord1fvARB;
+    ops->texcoord[WINED3D_FFP_EMIT_FLOAT2]    = (wined3d_ffp_texcoord_func)gl_info->gl_ops.ext.p_glMultiTexCoord2fvARB;
+    ops->texcoord[WINED3D_FFP_EMIT_FLOAT3]    = (wined3d_ffp_texcoord_func)gl_info->gl_ops.ext.p_glMultiTexCoord3fvARB;
+    ops->texcoord[WINED3D_FFP_EMIT_FLOAT4]    = (wined3d_ffp_texcoord_func)gl_info->gl_ops.ext.p_glMultiTexCoord4fvARB;
+    ops->texcoord[WINED3D_FFP_EMIT_D3DCOLOR]  = invalid_texcoord_func;
+    ops->texcoord[WINED3D_FFP_EMIT_UBYTE4]    = invalid_texcoord_func;
+    ops->texcoord[WINED3D_FFP_EMIT_SHORT2]    = (wined3d_ffp_texcoord_func)gl_info->gl_ops.ext.p_glMultiTexCoord2svARB;
+    ops->texcoord[WINED3D_FFP_EMIT_SHORT4]    = (wined3d_ffp_texcoord_func)gl_info->gl_ops.ext.p_glMultiTexCoord4svARB;
+    ops->texcoord[WINED3D_FFP_EMIT_UBYTE4N]   = invalid_texcoord_func;
+    ops->texcoord[WINED3D_FFP_EMIT_SHORT2N]   = invalid_texcoord_func;
+    ops->texcoord[WINED3D_FFP_EMIT_SHORT4N]   = invalid_texcoord_func;
+    ops->texcoord[WINED3D_FFP_EMIT_USHORT2N]  = invalid_texcoord_func;
+    ops->texcoord[WINED3D_FFP_EMIT_USHORT4N]  = invalid_texcoord_func;
+    ops->texcoord[WINED3D_FFP_EMIT_UDEC3]     = invalid_texcoord_func;
+    ops->texcoord[WINED3D_FFP_EMIT_DEC3N]     = invalid_texcoord_func;
+    if (gl_info->supported[NV_HALF_FLOAT])
     {
-        specular_func_3ubv = (glAttribFunc)GL_EXTCALL(glSecondaryColor3ubvEXT);
-        specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = specular_d3dcolor;
+        /* Not supported by ARB_HALF_FLOAT_VERTEX, so check for NV_HALF_FLOAT. */
+        ops->texcoord[WINED3D_FFP_EMIT_FLOAT16_2] =
+                (wined3d_ffp_texcoord_func)gl_info->gl_ops.ext.p_glMultiTexCoord2hvNV;
+        ops->texcoord[WINED3D_FFP_EMIT_FLOAT16_4] =
+                (wined3d_ffp_texcoord_func)gl_info->gl_ops.ext.p_glMultiTexCoord4hvNV;
     }
     else
     {
-        specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = warn_no_specular_func;
-    }
-    specular_funcs[WINED3D_FFP_EMIT_UBYTE4]      = invalid_func;
-    specular_funcs[WINED3D_FFP_EMIT_SHORT2]      = invalid_func;
-    specular_funcs[WINED3D_FFP_EMIT_SHORT4]      = invalid_func;
-    specular_funcs[WINED3D_FFP_EMIT_UBYTE4N]     = invalid_func;
-    specular_funcs[WINED3D_FFP_EMIT_SHORT2N]     = invalid_func;
-    specular_funcs[WINED3D_FFP_EMIT_SHORT4N]     = invalid_func;
-    specular_funcs[WINED3D_FFP_EMIT_USHORT2N]    = invalid_func;
-    specular_funcs[WINED3D_FFP_EMIT_USHORT4N]    = invalid_func;
-    specular_funcs[WINED3D_FFP_EMIT_UDEC3]       = invalid_func;
-    specular_funcs[WINED3D_FFP_EMIT_DEC3N]       = invalid_func;
-    specular_funcs[WINED3D_FFP_EMIT_FLOAT16_2]   = invalid_func;
-    specular_funcs[WINED3D_FFP_EMIT_FLOAT16_4]   = invalid_func;
-
-    /* Only 3 component entry points here. Test how others behave. Float4 normals are used
-     * by one of our tests, trying to pass it to the pixel shader, which fails on Windows.
-     */
-    normal_funcs[WINED3D_FFP_EMIT_FLOAT1]         = invalid_func;
-    normal_funcs[WINED3D_FFP_EMIT_FLOAT2]         = invalid_func;
-    normal_funcs[WINED3D_FFP_EMIT_FLOAT3]         = (glAttribFunc)gl_info->gl_ops.gl.p_glNormal3fv;
-    normal_funcs[WINED3D_FFP_EMIT_FLOAT4]         = (glAttribFunc)gl_info->gl_ops.gl.p_glNormal3fv; /* Just ignore the 4th value */
-    normal_funcs[WINED3D_FFP_EMIT_D3DCOLOR]       = invalid_func;
-    normal_funcs[WINED3D_FFP_EMIT_UBYTE4]         = invalid_func;
-    normal_funcs[WINED3D_FFP_EMIT_SHORT2]         = invalid_func;
-    normal_funcs[WINED3D_FFP_EMIT_SHORT4]         = invalid_func;
-    normal_funcs[WINED3D_FFP_EMIT_UBYTE4N]        = invalid_func;
-    normal_funcs[WINED3D_FFP_EMIT_SHORT2N]        = invalid_func;
-    normal_funcs[WINED3D_FFP_EMIT_SHORT4N]        = invalid_func;
-    normal_funcs[WINED3D_FFP_EMIT_USHORT2N]       = invalid_func;
-    normal_funcs[WINED3D_FFP_EMIT_USHORT4N]       = invalid_func;
-    normal_funcs[WINED3D_FFP_EMIT_UDEC3]          = invalid_func;
-    normal_funcs[WINED3D_FFP_EMIT_DEC3N]          = invalid_func;
-    normal_funcs[WINED3D_FFP_EMIT_FLOAT16_2]      = invalid_func;
-    normal_funcs[WINED3D_FFP_EMIT_FLOAT16_4]      = invalid_func;
-
-    multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT1]    = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord1fvARB);
-    multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT2]    = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2fvARB);
-    multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT3]    = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord3fvARB);
-    multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT4]    = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4fvARB);
-    multi_texcoord_funcs[WINED3D_FFP_EMIT_D3DCOLOR]  = invalid_texcoord_func;
-    multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4]    = invalid_texcoord_func;
-    multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2]    = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2svARB);
-    multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4]    = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4svARB);
-    multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4N]   = invalid_texcoord_func;
-    multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2N]   = invalid_texcoord_func;
-    multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4N]   = invalid_texcoord_func;
-    multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT2N]  = invalid_texcoord_func;
-    multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT4N]  = invalid_texcoord_func;
-    multi_texcoord_funcs[WINED3D_FFP_EMIT_UDEC3]     = invalid_texcoord_func;
-    multi_texcoord_funcs[WINED3D_FFP_EMIT_DEC3N]     = invalid_texcoord_func;
-    if (gl_info->supported[NV_HALF_FLOAT])
-    {
-        /* Not supported by ARB_HALF_FLOAT_VERTEX, so check for NV_HALF_FLOAT */
-        multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2hvNV);
-        multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4hvNV);
-    } else {
-        multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_texcoord_func;
-        multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_texcoord_func;
+        ops->texcoord[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_texcoord_func;
+        ops->texcoord[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_texcoord_func;
     }
+    ops->texcoord[WINED3D_FFP_EMIT_INVALID]   = invalid_texcoord_func;
 }
 
 static void wined3d_adapter_init_fb_cfgs(struct wined3d_adapter *adapter, HDC dc)
 {
     const struct wined3d_gl_info *gl_info = &adapter->gl_info;
-    unsigned int i;
+    int i;
 
     if (gl_info->supported[WGL_ARB_PIXEL_FORMAT])
     {
@@ -5143,7 +5036,9 @@ static BOOL wined3d_adapter_init(struct wined3d_adapter *adapter, UINT ordinal)
 {
     struct wined3d_gl_info *gl_info = &adapter->gl_info;
     struct wined3d_fake_gl_ctx fake_gl_ctx = {0};
+    unsigned int ctx_attrib_idx = 0;
     DISPLAY_DEVICEW display_device;
+    GLint ctx_attribs[3];
 
     TRACE("adapter %p, ordinal %u.\n", adapter, ordinal);
 
@@ -5189,6 +5084,14 @@ static BOOL wined3d_adapter_init(struct wined3d_adapter *adapter, UINT ordinal)
         return FALSE;
     }
 
+    if (context_debug_output_enabled(gl_info))
+    {
+        ctx_attribs[ctx_attrib_idx++] = WGL_CONTEXT_FLAGS_ARB;
+        ctx_attribs[ctx_attrib_idx++] = WGL_CONTEXT_DEBUG_BIT_ARB;
+    }
+    ctx_attribs[ctx_attrib_idx] = 0;
+    wined3d_create_fake_gl_context_attribs(&fake_gl_ctx, gl_info, ctx_attribs);
+
     if (!wined3d_adapter_init_gl_caps(adapter))
     {
         ERR("Failed to initialize GL caps for adapter %p.\n", adapter);
@@ -5226,7 +5129,7 @@ static BOOL wined3d_adapter_init(struct wined3d_adapter *adapter, UINT ordinal)
 
     WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
 
-    fillGLAttribFuncs(&adapter->gl_info);
+    wined3d_adapter_init_ffp_attrib_ops(adapter);
 
     return TRUE;
 }
@@ -5249,10 +5152,11 @@ static void wined3d_adapter_init_nogl(struct wined3d_adapter *adapter, UINT ordi
 
     initPixelFormatsNoGL(&adapter->gl_info);
 
+    adapter->vertex_pipe = &none_vertex_pipe;
     adapter->fragment_pipe = &none_fragment_pipe;
     adapter->shader_backend = &none_shader_backend;
     adapter->blitter = &cpu_blit;
-    
+
     display_device.cb = sizeof(display_device);
     EnumDisplayDevicesW(NULL, ordinal, &display_device, 0);
     TRACE("DeviceName: %s\n", debugstr_w(display_device.DeviceName));
index 1859b99..89f2d7a 100644 (file)
@@ -30,6 +30,7 @@
 #include "wined3d_private.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(d3d_draw);
+WINE_DECLARE_DEBUG_CHANNEL(d3d_perf);
 
 //#include <stdio.h>
 //#include <math.h>
@@ -90,19 +91,21 @@ static void drawStridedSlow(const struct wined3d_device *device, const struct wi
     const WORD                *pIdxBufS     = NULL;
     const DWORD               *pIdxBufL     = NULL;
     UINT vx_index;
-    const struct wined3d_state *state = &device->stateBlock->state;
+    const struct wined3d_state *state = &device->state;
     LONG SkipnStrides = startIdx;
     BOOL pixelShader = use_ps(state);
     BOOL specular_fog = FALSE;
     const BYTE *texCoords[WINED3DDP_MAXTEXCOORD];
     const BYTE *diffuse = NULL, *specular = NULL, *normal = NULL, *position = NULL;
     const struct wined3d_gl_info *gl_info = context->gl_info;
-    UINT texture_stages = gl_info->limits.texture_stages;
+    const struct wined3d_d3d_info *d3d_info = context->d3d_info;
+    const struct wined3d_ffp_attrib_ops *ops = &d3d_info->ffp_attrib_ops;
+    UINT texture_stages = d3d_info->limits.ffp_blend_stages;
     const struct wined3d_stream_info_element *element;
     UINT num_untracked_materials;
     DWORD tex_mask = 0;
 
-    TRACE("Using slow vertex array code\n");
+    TRACE_(d3d_perf)("Using slow vertex array code\n");
 
     /* Variable Initialization */
     if (idxSize)
@@ -264,15 +267,16 @@ static void drawStridedSlow(const struct wined3d_device *device, const struct wi
             ptr = texCoords[coord_idx] + (SkipnStrides * si->elements[WINED3D_FFP_TEXCOORD0 + coord_idx].stride);
 
             texture_idx = device->texUnitMap[texture];
-            multi_texcoord_funcs[si->elements[WINED3D_FFP_TEXCOORD0 + coord_idx].format->emit_idx](
+            ops->texcoord[si->elements[WINED3D_FFP_TEXCOORD0 + coord_idx].format->emit_idx](
                     GL_TEXTURE0_ARB + texture_idx, ptr);
         }
 
         /* Diffuse -------------------------------- */
-        if (diffuse) {
+        if (diffuse)
+        {
             const void *ptrToCoords = diffuse + SkipnStrides * si->elements[WINED3D_FFP_DIFFUSE].stride;
+            ops->diffuse[si->elements[WINED3D_FFP_DIFFUSE].format->emit_idx](ptrToCoords);
 
-            diffuse_funcs[si->elements[WINED3D_FFP_DIFFUSE].format->emit_idx](ptrToCoords);
             if (num_untracked_materials)
             {
                 DWORD diffuseColor = ((const DWORD *)ptrToCoords)[0];
@@ -292,10 +296,10 @@ static void drawStridedSlow(const struct wined3d_device *device, const struct wi
         }
 
         /* Specular ------------------------------- */
-        if (specular) {
+        if (specular)
+        {
             const void *ptrToCoords = specular + SkipnStrides * si->elements[WINED3D_FFP_SPECULAR].stride;
-
-            specular_funcs[si->elements[WINED3D_FFP_SPECULAR].format->emit_idx](ptrToCoords);
+            ops->specular[si->elements[WINED3D_FFP_SPECULAR].format->emit_idx](ptrToCoords);
 
             if (specular_fog)
             {
@@ -308,13 +312,14 @@ static void drawStridedSlow(const struct wined3d_device *device, const struct wi
         if (normal)
         {
             const void *ptrToCoords = normal + SkipnStrides * si->elements[WINED3D_FFP_NORMAL].stride;
-            normal_funcs[si->elements[WINED3D_FFP_NORMAL].format->emit_idx](ptrToCoords);
+            ops->normal[si->elements[WINED3D_FFP_NORMAL].format->emit_idx](ptrToCoords);
         }
 
         /* Position -------------------------------- */
-        if (position) {
+        if (position)
+        {
             const void *ptrToCoords = position + SkipnStrides * si->elements[WINED3D_FFP_POSITION].stride;
-            position_funcs[si->elements[WINED3D_FFP_POSITION].format->emit_idx](ptrToCoords);
+            ops->position[si->elements[WINED3D_FFP_POSITION].format->emit_idx](ptrToCoords);
         }
 
         /* For non indexed mode, step onto next parts */
@@ -577,15 +582,16 @@ static void remove_vbos(const struct wined3d_gl_info *gl_info,
 
 /* Routine common to the draw primitive and draw indexed primitive routines */
 void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_count,
-        UINT start_instance, UINT instance_count, BOOL indexed, const void *idx_data)
+        UINT start_instance, UINT instance_count, BOOL indexed)
 {
-    const struct wined3d_state *state = &device->stateBlock->state;
+    const struct wined3d_state *state = &device->state;
     const struct wined3d_stream_info *stream_info;
     struct wined3d_event_query *ib_query = NULL;
     struct wined3d_stream_info si_emulated;
     const struct wined3d_gl_info *gl_info;
     struct wined3d_context *context;
     BOOL emulation = FALSE;
+    const void *idx_data = NULL;
     UINT idx_size = 0;
     unsigned int i;
 
@@ -670,7 +676,7 @@ void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_co
         FIXME("Point sprite coordinate origin switching not supported.\n");
     }
 
-    stream_info = &device->strided_streams;
+    stream_info = &device->stream_info;
     if (device->instance_count)
         instance_count = device->instance_count;
 
@@ -701,7 +707,7 @@ void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_co
             if (!warned++)
                 FIXME("Using software emulation because not all material properties could be tracked.\n");
             else
-                WARN("Using software emulation because not all material properties could be tracked.\n");
+                WARN_(d3d_perf)("Using software emulation because not all material properties could be tracked.\n");
             emulation = TRUE;
         }
         else if (context->fog_coord && state->render_states[WINED3D_RS_FOGENABLE])
@@ -714,13 +720,13 @@ void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_co
             if (!warned++)
                 FIXME("Using software emulation because manual fog coordinates are provided.\n");
             else
-                WARN("Using software emulation because manual fog coordinates are provided.\n");
+                WARN_(d3d_perf)("Using software emulation because manual fog coordinates are provided.\n");
             emulation = TRUE;
         }
 
         if (emulation)
         {
-            si_emulated = device->strided_streams;
+            si_emulated = device->stream_info;
             remove_vbos(gl_info, state, &si_emulated);
             stream_info = &si_emulated;
         }
@@ -736,7 +742,7 @@ void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_co
             if (!warned++)
                 FIXME("Using immediate mode with vertex shaders for half float emulation.\n");
             else
-                WARN("Using immediate mode with vertex shaders for half float emulation.\n");
+                WARN_(d3d_perf)("Using immediate mode with vertex shaders for half float emulation.\n");
 
             drawStridedSlowVs(gl_info, state, stream_info, index_count,
                     state->gl_primitive_type, idx_data, idx_size, start_idx);
index b31b892..5757436 100644 (file)
@@ -29,6 +29,7 @@
 #include "wined3d_private.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(gl_compat);
+WINE_DECLARE_DEBUG_CHANNEL(d3d_perf);
 
 /* Start GL_ARB_multitexture emulation */
 static void WINE_GLAPI wine_glMultiTexCoord1fARB(GLenum target, GLfloat s) {
@@ -176,7 +177,7 @@ static void WINE_GLAPI wine_glFogi(GLenum pname, GLint param) {
         if(param == GL_FRAGMENT_DEPTH_EXT) {
             if(ctx->fog_enabled) old_fogcoord_glEnable(GL_FOG);
         } else {
-            WARN("Fog coords activated, but not supported. Using slow emulation\n");
+            WARN_(d3d_perf)("Fog coords activated, but not supported. Using slow emulation\n");
             old_fogcoord_glDisable(GL_FOG);
         }
     } else {
@@ -197,7 +198,7 @@ static void WINE_GLAPI wine_glFogiv(GLenum pname, const GLint *param) {
         if(*param == GL_FRAGMENT_DEPTH_EXT) {
             if(ctx->fog_enabled) old_fogcoord_glEnable(GL_FOG);
         } else {
-            WARN("Fog coords activated, but not supported. Using slow emulation\n");
+            WARN_(d3d_perf)("Fog coords activated, but not supported. Using slow emulation\n");
             old_fogcoord_glDisable(GL_FOG);
         }
     } else {
@@ -218,7 +219,7 @@ static void WINE_GLAPI wine_glFogf(GLenum pname, GLfloat param) {
         if(param == GL_FRAGMENT_DEPTH_EXT) {
             if(ctx->fog_enabled) old_fogcoord_glEnable(GL_FOG);
         } else {
-            WARN("Fog coords activated, but not supported. Using slow emulation\n");
+            WARN_(d3d_perf)("Fog coords activated, but not supported. Using slow emulation\n");
             old_fogcoord_glDisable(GL_FOG);
         }
     } else {
@@ -239,7 +240,7 @@ static void WINE_GLAPI wine_glFogfv(GLenum pname, const GLfloat *param) {
         if(*param == GL_FRAGMENT_DEPTH_EXT) {
             if(ctx->fog_enabled) old_fogcoord_glEnable(GL_FOG);
         } else {
-            WARN("Fog coords activated, but not supported. Using slow emulation\n");
+            WARN_(d3d_perf)("Fog coords activated, but not supported. Using slow emulation\n");
             old_fogcoord_glDisable(GL_FOG);
         }
     } else {
index 7b11567..5ff98dd 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright 2006 Jason Green
  * Copyright 2006-2007 Henri Verbeet
- * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
+ * Copyright 2007-2009, 2013 Stefan Dösinger for CodeWeavers
  * Copyright 2009-2011 Henri Verbeet for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
@@ -42,11 +42,18 @@ WINE_DECLARE_DEBUG_CHANNEL(d3d_constants);
 WINE_DECLARE_DEBUG_CHANNEL(d3d);
 WINE_DECLARE_DEBUG_CHANNEL(winediag);
 
+#ifdef _MSC_VER
+#define copysignf(x, y) ((x) < 0.0f ? -fabsf(y) : fabsf(y))
+#endif
+
 #define WINED3D_GLSL_SAMPLE_PROJECTED   0x1
-#define WINED3D_GLSL_SAMPLE_RECT        0x2
+#define WINED3D_GLSL_SAMPLE_NPOT        0x2
 #define WINED3D_GLSL_SAMPLE_LOD         0x4
 #define WINED3D_GLSL_SAMPLE_GRAD        0x8
 
+static const float srgb_const0[] = {0.41666f, 1.055f, 0.055f, 12.92f};  /* pow, mul_high, sub_high, mul_low */
+static const float srgb_const1[] = {0.0031308f, 0.0f, 0.0f, 0.0f};      /* cmp */
+
 struct glsl_dst_param
 {
     char reg_name[150];
@@ -81,6 +88,7 @@ struct constant_entry
 struct constant_heap
 {
     struct constant_entry *entries;
+    BOOL *contained;
     unsigned int *positions;
     unsigned int size;
 };
@@ -89,7 +97,6 @@ struct constant_heap
 struct shader_glsl_priv {
     struct wined3d_shader_buffer shader_buffer;
     struct wine_rb_tree program_lookup;
-    struct glsl_shader_prog_link *glsl_program;
     struct constant_heap vconst_heap;
     struct constant_heap pconst_heap;
     unsigned char *stack;
@@ -97,7 +104,9 @@ struct shader_glsl_priv {
     GLhandleARB depth_blt_program_masked[tex_type_count];
     UINT next_constant_version;
 
+    const struct wined3d_vertex_pipe_ops *vertex_pipe;
     const struct fragment_pipeline *fragment_pipe;
+    struct wine_rb_tree ffp_vertex_shaders;
     struct wine_rb_tree ffp_fragment_shaders;
     BOOL ffp_proj_control;
 };
@@ -142,6 +151,7 @@ struct glsl_shader_prog_link
     struct glsl_gs_program gs;
     struct glsl_ps_program ps;
     GLhandleARB programId;
+    DWORD constant_update_mask;
     UINT constant_version;
 };
 
@@ -158,6 +168,11 @@ struct shader_glsl_ctx_priv {
     struct ps_np2fixup_info         *cur_np2fixup_info;
 };
 
+struct glsl_context_data
+{
+    struct glsl_shader_prog_link *glsl_program;
+};
+
 struct glsl_ps_compiled_shader
 {
     struct ps_compile_args          args;
@@ -187,6 +202,13 @@ struct glsl_shader_private
     UINT num_gl_shaders, shader_array_size;
 };
 
+struct glsl_ffp_vertex_shader
+{
+    struct wined3d_ffp_vs_desc desc;
+    GLhandleARB id;
+    struct list linked_programs;
+};
+
 struct glsl_ffp_fragment_shader
 {
     struct ffp_frag_desc entry;
@@ -194,6 +216,12 @@ struct glsl_ffp_fragment_shader
     struct list linked_programs;
 };
 
+struct glsl_ffp_destroy_ctx
+{
+    struct shader_glsl_priv *priv;
+    const struct wined3d_gl_info *gl_info;
+};
+
 static const char *debug_gl_shader_type(GLenum type)
 {
     switch (type)
@@ -227,6 +255,64 @@ static const char *shader_glsl_get_prefix(enum wined3d_shader_type type)
     }
 }
 
+/* This should be equivalent to using the %.8e format specifier, but always
+ * using '.' as decimal separator. This doesn't handle +/-INF or NAN, since
+ * the GLSL parser wouldn't be able to handle those anyway. */
+static void shader_glsl_ftoa(float value, char *s)
+{
+    int x, frac, exponent;
+    const char *sign = "";
+    double d;
+
+    d = value;
+    if (copysignf(1.0f, value) < 0.0f)
+    {
+        d = -d;
+        sign = "-";
+    }
+
+    if (d == 0.0f)
+    {
+        x = 0;
+        frac = 0;
+        exponent = 0;
+    }
+    else
+    {
+        double t, diff;
+
+        exponent = floorf(log10f(d));
+        d /= pow(10.0, exponent);
+
+        x = d;
+        t = (d - x) * 100000000;
+        frac = t;
+        diff = t - frac;
+
+        if ((diff > 0.5) || (diff == 0.5 && (frac & 1)))
+        {
+            if (++frac >= 100000000)
+            {
+                frac = 0;
+                ++x;
+            }
+        }
+    }
+
+    sprintf(s, "%s%d.%08de%+03d", sign, x, frac, exponent);
+}
+
+static void shader_glsl_append_imm_vec4(struct wined3d_shader_buffer *buffer, const float *values)
+{
+    char str[4][16];
+
+    shader_glsl_ftoa(values[0], str[0]);
+    shader_glsl_ftoa(values[1], str[1]);
+    shader_glsl_ftoa(values[2], str[2]);
+    shader_glsl_ftoa(values[3], str[3]);
+    shader_addline(buffer, "vec4(%s, %s, %s, %s)", str[0], str[1], str[2], str[3]);
+}
+
 /* Extract a line from the info log.
  * Note that this modifies the source string. */
 static char *get_info_log_line(char **ptr)
@@ -430,6 +516,7 @@ static void shader_glsl_load_vsamplers(const struct wined3d_gl_info *gl_info,
 static inline void walk_constant_heap(const struct wined3d_gl_info *gl_info, const float *constants,
         const GLint *constant_locations, const struct constant_heap *heap, unsigned char *stack, DWORD version)
 {
+    unsigned int start = ~0U, end = 0;
     int stack_idx = 0;
     unsigned int heap_idx = 1;
     unsigned int idx;
@@ -437,7 +524,8 @@ static inline void walk_constant_heap(const struct wined3d_gl_info *gl_info, con
     if (heap->entries[heap_idx].version <= version) return;
 
     idx = heap->entries[heap_idx].idx;
-    if (constant_locations[idx] != -1) GL_EXTCALL(glUniform4fvARB(constant_locations[idx], 1, &constants[idx * 4]));
+    if (constant_locations[idx] != -1)
+        start = end = idx;
     stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
 
     while (stack_idx >= 0)
@@ -453,7 +541,12 @@ static inline void walk_constant_heap(const struct wined3d_gl_info *gl_info, con
                     heap_idx = left_idx;
                     idx = heap->entries[heap_idx].idx;
                     if (constant_locations[idx] != -1)
-                        GL_EXTCALL(glUniform4fvARB(constant_locations[idx], 1, &constants[idx * 4]));
+                    {
+                        if (start > idx)
+                            start = idx;
+                        if (end < idx)
+                            end = idx;
+                    }
 
                     stack[stack_idx++] = HEAP_NODE_TRAVERSE_RIGHT;
                     stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
@@ -469,7 +562,12 @@ static inline void walk_constant_heap(const struct wined3d_gl_info *gl_info, con
                     heap_idx = right_idx;
                     idx = heap->entries[heap_idx].idx;
                     if (constant_locations[idx] != -1)
-                        GL_EXTCALL(glUniform4fvARB(constant_locations[idx], 1, &constants[idx * 4]));
+                    {
+                        if (start > idx)
+                            start = idx;
+                        if (end < idx)
+                            end = idx;
+                    }
 
                     stack[stack_idx++] = HEAP_NODE_POP;
                     stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
@@ -483,6 +581,8 @@ static inline void walk_constant_heap(const struct wined3d_gl_info *gl_info, con
                 break;
         }
     }
+    if (start <= end)
+        GL_EXTCALL(glUniform4fvARB(constant_locations[start], end - start + 1, &constants[start * 4]));
     checkGLcall("walk_constant_heap()");
 }
 
@@ -582,9 +682,7 @@ static void shader_glsl_load_constantsF(const struct wined3d_shader *shader, con
     /* Immediate constants are clamped to [-1;1] at shader creation time if needed */
     LIST_FOR_EACH_ENTRY(lconst, &shader->constantsF, struct wined3d_shader_lconst, entry)
     {
-        GLint location = constant_locations[lconst->idx];
-        /* We found this uniform name in the program - go ahead and send the data */
-        if (location != -1) GL_EXTCALL(glUniform4fvARB(location, 1, (const GLfloat *)lconst->value));
+        GL_EXTCALL(glUniform4fvARB(constant_locations[lconst->idx], 1, (const GLfloat *)lconst->value));
     }
     checkGLcall("glUniform4fvARB()");
 }
@@ -650,12 +748,7 @@ static void shader_glsl_load_constantsB(const struct wined3d_shader *shader, con
          * locations of the constants to avoid looking up each time */
         snprintf(tmp_name, sizeof(tmp_name), "%s_b[%i]", prefix, i);
         tmp_loc = GL_EXTCALL(glGetUniformLocationARB(programId, tmp_name));
-        if (tmp_loc != -1)
-        {
-            /* We found this uniform name in the program - go ahead and send the data */
-            GL_EXTCALL(glUniform1ivARB(tmp_loc, 1, &constants[i]));
-            checkGLcall("glUniform1ivARB");
-        }
+        GL_EXTCALL(glUniform1ivARB(tmp_loc, 1, &constants[i]));
     }
 
     /* Load immediate constants */
@@ -670,13 +763,11 @@ static void shader_glsl_load_constantsB(const struct wined3d_shader *shader, con
 
         snprintf(tmp_name, sizeof(tmp_name), "%s_b[%i]", prefix, idx);
         tmp_loc = GL_EXTCALL(glGetUniformLocationARB(programId, tmp_name));
-        if (tmp_loc != -1) {
-            /* We found this uniform name in the program - go ahead and send the data */
-            GL_EXTCALL(glUniform1ivARB(tmp_loc, 1, values));
-            checkGLcall("glUniform1ivARB");
-        }
+        GL_EXTCALL(glUniform1ivARB(tmp_loc, 1, values));
         ptr = list_next(&shader->constantsB, ptr);
     }
+
+    checkGLcall("shader_glsl_load_constantsB()");
 }
 
 static void reset_program_constant_version(struct wine_rb_entry *entry, void *context)
@@ -685,66 +776,54 @@ static void reset_program_constant_version(struct wine_rb_entry *entry, void *co
 }
 
 /* Context activation is done by the caller (state handler). */
-static void shader_glsl_load_np2fixup_constants(void *shader_priv,
+static void shader_glsl_load_np2fixup_constants(const struct glsl_ps_program *ps,
         const struct wined3d_gl_info *gl_info, const struct wined3d_state *state)
 {
-    struct shader_glsl_priv *glsl_priv = shader_priv;
-    const struct glsl_shader_prog_link *prog = glsl_priv->glsl_program;
-
-    /* No GLSL program set - nothing to do. */
-    if (!prog) return;
-
-    /* NP2 texcoord fixup is (currently) only done for pixelshaders. */
-    if (!use_ps(state)) return;
+    GLfloat np2fixup_constants[4 * MAX_FRAGMENT_SAMPLERS];
+    UINT fixup = ps->np2_fixup_info->active;
+    UINT i;
 
-    if (prog->ps.np2_fixup_info && prog->ps.np2_fixup_location != -1)
+    for (i = 0; fixup; fixup >>= 1, ++i)
     {
-        UINT i;
-        UINT fixup = prog->ps.np2_fixup_info->active;
-        GLfloat np2fixup_constants[4 * MAX_FRAGMENT_SAMPLERS];
+        const struct wined3d_texture *tex = state->textures[i];
+        unsigned char idx = ps->np2_fixup_info->idx[i];
+        GLfloat *tex_dim = &np2fixup_constants[(idx >> 1) * 4];
 
-        for (i = 0; fixup; fixup >>= 1, ++i)
+        if (!tex)
         {
-            const struct wined3d_texture *tex = state->textures[i];
-            const unsigned char idx = prog->ps.np2_fixup_info->idx[i];
-            GLfloat *tex_dim = &np2fixup_constants[(idx >> 1) * 4];
-
-            if (!tex)
-            {
-                ERR("Nonexistent texture is flagged for NP2 texcoord fixup.\n");
-                continue;
-            }
-
-            if (idx % 2)
-            {
-                tex_dim[2] = tex->pow2_matrix[0];
-                tex_dim[3] = tex->pow2_matrix[5];
-            }
-            else
-            {
-                tex_dim[0] = tex->pow2_matrix[0];
-                tex_dim[1] = tex->pow2_matrix[5];
-            }
+            ERR("Nonexistent texture is flagged for NP2 texcoord fixup.\n");
+            continue;
         }
 
-        GL_EXTCALL(glUniform4fvARB(prog->ps.np2_fixup_location,
-                prog->ps.np2_fixup_info->num_consts, np2fixup_constants));
+        if (idx % 2)
+        {
+            tex_dim[2] = tex->pow2_matrix[0];
+            tex_dim[3] = tex->pow2_matrix[5];
+        }
+        else
+        {
+            tex_dim[0] = tex->pow2_matrix[0];
+            tex_dim[1] = tex->pow2_matrix[5];
+        }
     }
+
+    GL_EXTCALL(glUniform4fvARB(ps->np2_fixup_location, ps->np2_fixup_info->num_consts, np2fixup_constants));
 }
 
 /* Context activation is done by the caller (state handler). */
-static void shader_glsl_load_constants(const struct wined3d_context *context,
-        BOOL usePixelShader, BOOL useVertexShader)
+static void shader_glsl_load_constants(void *shader_priv, struct wined3d_context *context,
+        const struct wined3d_state *state)
 {
+    const struct glsl_context_data *ctx_data = context->shader_backend_data;
+    const struct wined3d_shader *vshader = state->vertex_shader;
+    const struct wined3d_shader *pshader = state->pixel_shader;
     const struct wined3d_gl_info *gl_info = context->gl_info;
-    struct wined3d_device *device = context->swapchain->device;
-    struct wined3d_stateblock *stateBlock = device->stateBlock;
-    const struct wined3d_state *state = &stateBlock->state;
-    struct shader_glsl_priv *priv = device->shader_priv;
+    struct shader_glsl_priv *priv = shader_priv;
     float position_fixup[4];
+    DWORD update_mask = 0;
 
     GLhandleARB programId;
-    struct glsl_shader_prog_link *prog = priv->glsl_program;
+    struct glsl_shader_prog_link *prog = ctx_data->glsl_program;
     UINT constant_version;
     int i;
 
@@ -754,107 +833,90 @@ static void shader_glsl_load_constants(const struct wined3d_context *context,
     }
     programId = prog->programId;
     constant_version = prog->constant_version;
+    update_mask = context->constant_update_mask & prog->constant_update_mask;
 
-    if (useVertexShader)
-    {
-        const struct wined3d_shader *vshader = state->vertex_shader;
-
-        /* Load DirectX 9 float constants/uniforms for vertex shader */
+    if (update_mask & WINED3D_SHADER_CONST_VS_F)
         shader_glsl_load_constantsF(vshader, gl_info, state->vs_consts_f,
                 prog->vs.uniform_f_locations, &priv->vconst_heap, priv->stack, constant_version);
 
-        /* Load DirectX 9 integer constants/uniforms for vertex shader */
+    if (update_mask & WINED3D_SHADER_CONST_VS_I)
         shader_glsl_load_constantsI(vshader, gl_info, prog->vs.uniform_i_locations, state->vs_consts_i,
-                stateBlock->changed.vertexShaderConstantsI & vshader->reg_maps.integer_constants);
+                vshader->reg_maps.integer_constants);
 
-        /* Load DirectX 9 boolean constants/uniforms for vertex shader */
+    if (update_mask & WINED3D_SHADER_CONST_VS_B)
         shader_glsl_load_constantsB(vshader, gl_info, programId, state->vs_consts_b,
-                stateBlock->changed.vertexShaderConstantsB & vshader->reg_maps.boolean_constants);
+                vshader->reg_maps.boolean_constants);
 
-        /* Upload the position fixup params */
+    if (update_mask & WINED3D_SHADER_CONST_VS_POS_FIXUP)
+    {
         shader_get_position_fixup(context, state, position_fixup);
         GL_EXTCALL(glUniform4fvARB(prog->vs.pos_fixup_location, 1, position_fixup));
         checkGLcall("glUniform4fvARB");
     }
 
-    if (usePixelShader)
-    {
-        const struct wined3d_shader *pshader = state->pixel_shader;
-
-        /* Load DirectX 9 float constants/uniforms for pixel shader */
+    if (update_mask & WINED3D_SHADER_CONST_PS_F)
         shader_glsl_load_constantsF(pshader, gl_info, state->ps_consts_f,
                 prog->ps.uniform_f_locations, &priv->pconst_heap, priv->stack, constant_version);
 
-        /* Load DirectX 9 integer constants/uniforms for pixel shader */
+    if (update_mask & WINED3D_SHADER_CONST_PS_I)
         shader_glsl_load_constantsI(pshader, gl_info, prog->ps.uniform_i_locations, state->ps_consts_i,
-                stateBlock->changed.pixelShaderConstantsI & pshader->reg_maps.integer_constants);
+                pshader->reg_maps.integer_constants);
 
-        /* Load DirectX 9 boolean constants/uniforms for pixel shader */
+    if (update_mask & WINED3D_SHADER_CONST_PS_B)
         shader_glsl_load_constantsB(pshader, gl_info, programId, state->ps_consts_b,
-                stateBlock->changed.pixelShaderConstantsB & pshader->reg_maps.boolean_constants);
+                pshader->reg_maps.boolean_constants);
 
-        /* Upload the environment bump map matrix if needed. The needsbumpmat
-         * member specifies the texture stage to load the matrix from. It
-         * can't be 0 for a valid texbem instruction. */
+    if (update_mask & WINED3D_SHADER_CONST_PS_BUMP_ENV)
+    {
         for (i = 0; i < MAX_TEXTURES; ++i)
         {
-            const float *data;
-
             if (prog->ps.bumpenv_mat_location[i] == -1)
                 continue;
 
-            data = (const float *)&state->texture_states[i][WINED3D_TSS_BUMPENV_MAT00];
-            GL_EXTCALL(glUniformMatrix2fvARB(prog->ps.bumpenv_mat_location[i], 1, 0, data));
-            checkGLcall("glUniformMatrix2fvARB");
+            GL_EXTCALL(glUniformMatrix2fvARB(prog->ps.bumpenv_mat_location[i], 1, 0,
+                    (const GLfloat *)&state->texture_states[i][WINED3D_TSS_BUMPENV_MAT00]));
 
-            /* texbeml needs the luminance scale and offset too. If texbeml
-             * is used, needsbumpmat is set too, so we can check that in the
-             * needsbumpmat check. */
             if (prog->ps.bumpenv_lum_scale_location[i] != -1)
             {
-                const GLfloat *scale = (const GLfloat *)&state->texture_states[i][WINED3D_TSS_BUMPENV_LSCALE];
-                const GLfloat *offset = (const GLfloat *)&state->texture_states[i][WINED3D_TSS_BUMPENV_LOFFSET];
-
-                GL_EXTCALL(glUniform1fvARB(prog->ps.bumpenv_lum_scale_location[i], 1, scale));
-                checkGLcall("glUniform1fvARB");
-                GL_EXTCALL(glUniform1fvARB(prog->ps.bumpenv_lum_offset_location[i], 1, offset));
-                checkGLcall("glUniform1fvARB");
+                GL_EXTCALL(glUniform1fvARB(prog->ps.bumpenv_lum_scale_location[i], 1,
+                        (const GLfloat *)&state->texture_states[i][WINED3D_TSS_BUMPENV_LSCALE]));
+                GL_EXTCALL(glUniform1fvARB(prog->ps.bumpenv_lum_offset_location[i], 1,
+                        (const GLfloat *)&state->texture_states[i][WINED3D_TSS_BUMPENV_LOFFSET]));
             }
         }
 
-        if (prog->ps.ycorrection_location != -1)
-        {
-            float correction_params[4];
+        checkGLcall("bump env uniforms");
+    }
 
-            if (context->render_offscreen)
-            {
-                correction_params[0] = 0.0f;
-                correction_params[1] = 1.0f;
-            } else {
-                /* position is window relative, not viewport relative */
-                correction_params[0] = (float) context->current_rt->resource.height;
-                correction_params[1] = -1.0f;
-            }
-            GL_EXTCALL(glUniform4fvARB(prog->ps.ycorrection_location, 1, correction_params));
+    if (update_mask & WINED3D_SHADER_CONST_PS_Y_CORR)
+    {
+        float correction_params[4];
+
+        if (context->render_offscreen)
+        {
+            correction_params[0] = 0.0f;
+            correction_params[1] = 1.0f;
+        } else {
+            /* position is window relative, not viewport relative */
+            correction_params[0] = (float) context->current_rt->resource.height;
+            correction_params[1] = -1.0f;
         }
+        GL_EXTCALL(glUniform4fvARB(prog->ps.ycorrection_location, 1, correction_params));
     }
-    else if (priv->fragment_pipe == &glsl_fragment_pipe)
+
+    if (update_mask & WINED3D_SHADER_CONST_PS_NP2_FIXUP)
+        shader_glsl_load_np2fixup_constants(&prog->ps, gl_info, state);
+
+    if (update_mask & WINED3D_SHADER_CONST_FFP_PS)
     {
         float col[4];
 
-        for (i = 0; i < MAX_TEXTURES; ++i)
+        if (prog->ps.tex_factor_location != -1)
         {
-            GL_EXTCALL(glUniformMatrix2fvARB(prog->ps.bumpenv_mat_location[i], 1, 0,
-                        (const float *)&state->texture_states[i][WINED3D_TSS_BUMPENV_MAT00]));
-            GL_EXTCALL(glUniform1fARB(prog->ps.bumpenv_lum_scale_location[i],
-                        *(const float *)&state->texture_states[i][WINED3D_TSS_BUMPENV_LSCALE]));
-            GL_EXTCALL(glUniform1fARB(prog->ps.bumpenv_lum_offset_location[i],
-                        *(const float *)&state->texture_states[i][WINED3D_TSS_BUMPENV_LOFFSET]));
+            D3DCOLORTOGLFLOAT4(state->render_states[WINED3D_RS_TEXTUREFACTOR], col);
+            GL_EXTCALL(glUniform4fvARB(prog->ps.tex_factor_location, 1, col));
         }
 
-        D3DCOLORTOGLFLOAT4(state->render_states[WINED3D_RS_TEXTUREFACTOR], col);
-        GL_EXTCALL(glUniform4fARB(prog->ps.tex_factor_location, col[0], col[1], col[2], col[3]));
-
         if (state->render_states[WINED3D_RS_SPECULARENABLE])
             GL_EXTCALL(glUniform4fARB(prog->ps.specular_enable_location, 1.0f, 1.0f, 1.0f, 0.0f));
         else
@@ -875,12 +937,21 @@ static void shader_glsl_load_constants(const struct wined3d_context *context,
     }
 }
 
-static void update_heap_entry(const struct constant_heap *heap, unsigned int idx,
-        unsigned int heap_idx, DWORD new_version)
+static void update_heap_entry(struct constant_heap *heap, unsigned int idx, DWORD new_version)
 {
     struct constant_entry *entries = heap->entries;
     unsigned int *positions = heap->positions;
-    unsigned int parent_idx;
+    unsigned int heap_idx, parent_idx;
+
+    if (!heap->contained[idx])
+    {
+        heap_idx = heap->size++;
+        heap->contained[idx] = TRUE;
+    }
+    else
+    {
+        heap_idx = positions[idx];
+    }
 
     while (heap_idx > 1)
     {
@@ -906,10 +977,12 @@ static void shader_glsl_update_float_vertex_constants(struct wined3d_device *dev
 
     for (i = start; i < count + start; ++i)
     {
-        if (!device->stateBlock->changed.vertexShaderConstantsF[i])
-            update_heap_entry(heap, i, heap->size++, priv->next_constant_version);
-        else
-            update_heap_entry(heap, i, heap->positions[i], priv->next_constant_version);
+        update_heap_entry(heap, i, priv->next_constant_version);
+    }
+
+    for (i = 0; i < device->context_count; ++i)
+    {
+        device->contexts[i]->constant_update_mask |= WINED3D_SHADER_CONST_VS_F;
     }
 }
 
@@ -921,10 +994,12 @@ static void shader_glsl_update_float_pixel_constants(struct wined3d_device *devi
 
     for (i = start; i < count + start; ++i)
     {
-        if (!device->stateBlock->changed.pixelShaderConstantsF[i])
-            update_heap_entry(heap, i, heap->size++, priv->next_constant_version);
-        else
-            update_heap_entry(heap, i, heap->positions[i], priv->next_constant_version);
+        update_heap_entry(heap, i, priv->next_constant_version);
+    }
+
+    for (i = 0; i < device->context_count; ++i)
+    {
+        device->contexts[i]->constant_update_mask |= WINED3D_SHADER_CONST_PS_F;
     }
 }
 
@@ -945,7 +1020,7 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
         const struct wined3d_shader_reg_maps *reg_maps, const struct shader_glsl_ctx_priv *ctx_priv)
 {
     const struct wined3d_shader_version *version = &reg_maps->shader_version;
-    const struct wined3d_state *state = &shader->device->stateBlock->state;
+    const struct wined3d_state *state = &shader->device->state;
     const struct ps_compile_args *ps_args = ctx_priv->cur_ps_args;
     const struct wined3d_gl_info *gl_info = context->gl_info;
     const struct wined3d_fb_state *fb = &shader->device->fb;
@@ -1058,7 +1133,7 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
         if (reg_maps->sampler_type[i])
         {
             BOOL shadow_sampler = version->type == WINED3D_SHADER_TYPE_PIXEL && (ps_args->shadow & (1 << i));
-            const struct wined3d_texture *texture;
+            BOOL tex_rect;
 
             switch (reg_maps->sampler_type[i])
             {
@@ -1069,17 +1144,18 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
                         shader_addline(buffer, "uniform sampler1D %s_sampler%u;\n", prefix, i);
                     break;
                 case WINED3DSTT_2D:
-                    texture = state->textures[i];
+                    tex_rect = version->type == WINED3D_SHADER_TYPE_PIXEL && (ps_args->np2_fixup & (1 << i));
+                    tex_rect = tex_rect && gl_info->supported[ARB_TEXTURE_RECTANGLE];
                     if (shadow_sampler)
                     {
-                        if (texture && texture->target == GL_TEXTURE_RECTANGLE_ARB)
+                        if (tex_rect)
                             shader_addline(buffer, "uniform sampler2DRectShadow %s_sampler%u;\n", prefix, i);
                         else
                             shader_addline(buffer, "uniform sampler2DShadow %s_sampler%u;\n", prefix, i);
                     }
                     else
                     {
-                        if (texture && texture->target == GL_TEXTURE_RECTANGLE_ARB)
+                        if (tex_rect)
                             shader_addline(buffer, "uniform sampler2DRect %s_sampler%u;\n", prefix, i);
                         else
                             shader_addline(buffer, "uniform sampler2D %s_sampler%u;\n", prefix, i);
@@ -1202,10 +1278,12 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
 
         if (ps_args->srgb_correction)
         {
-            shader_addline(buffer, "const vec4 srgb_const0 = vec4(%.8e, %.8e, %.8e, %.8e);\n",
-                    srgb_pow, srgb_mul_high, srgb_sub_high, srgb_mul_low);
-            shader_addline(buffer, "const vec4 srgb_const1 = vec4(%.8e, 0.0, 0.0, 0.0);\n",
-                    srgb_cmp);
+            shader_addline(buffer, "const vec4 srgb_const0 = ");
+            shader_glsl_append_imm_vec4(buffer, srgb_const0);
+            shader_addline(buffer, ";\n");
+            shader_addline(buffer, "const vec4 srgb_const1 = ");
+            shader_glsl_append_imm_vec4(buffer, srgb_const1);
+            shader_addline(buffer, ";\n");
         }
         if (reg_maps->vpos || reg_maps->usesdsy)
         {
@@ -1217,13 +1295,21 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
             }
             else
             {
-                /* This happens because we do not have proper tracking of the constant registers that are
-                 * actually used, only the max limit of the shader version
-                 */
+                float ycorrection[] =
+                {
+                    context->render_offscreen ? 0.0f : fb->render_targets[0]->resource.height,
+                    context->render_offscreen ? 1.0f : -1.0f,
+                    0.0f,
+                    0.0f,
+                };
+
+                /* This happens because we do not have proper tracking of the
+                 * constant registers that are actually used, only the max
+                 * limit of the shader version. */
                 FIXME("Cannot find a free uniform for vpos correction params\n");
-                shader_addline(buffer, "const vec4 ycorrection = vec4(%f, %f, 0.0, 0.0);\n",
-                        context->render_offscreen ? 0.0f : fb->render_targets[0]->resource.height,
-                        context->render_offscreen ? 1.0f : -1.0f);
+                shader_addline(buffer, "const vec4 ycorrection = ");
+                shader_glsl_append_imm_vec4(buffer, ycorrection);
+                shader_addline(buffer, ";\n");
             }
             shader_addline(buffer, "vec4 vpos;\n");
         }
@@ -1253,15 +1339,13 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
     shader_addline(buffer, "vec4 tmp0;\n");
     shader_addline(buffer, "vec4 tmp1;\n");
 
-    /* Local constants use a different name so they can be loaded once at shader link time
-     * They can't be hardcoded into the shader text via LC = {x, y, z, w}; because the
-     * float -> string conversion can cause precision loss.
-     */
     if (!shader->load_local_constsF)
     {
         LIST_FOR_EACH_ENTRY(lconst, &shader->constantsF, struct wined3d_shader_lconst, entry)
         {
-            shader_addline(buffer, "uniform vec4 %s_lc%u;\n", prefix, lconst->idx);
+            shader_addline(buffer, "const vec4 %s_lc%u = ", prefix, lconst->idx);
+            shader_glsl_append_imm_vec4(buffer, (const float *)lconst->value);
+            shader_addline(buffer, ";\n");
         }
     }
 
@@ -1385,6 +1469,7 @@ static void shader_glsl_get_register_name(const struct wined3d_shader_register *
     const struct wined3d_gl_info *gl_info = ins->ctx->gl_info;
     const char *prefix = shader_glsl_get_prefix(version->type);
     struct glsl_src_param rel_param0, rel_param1;
+    char imm_str[4][16];
 
     if (reg->idx[0].offset != ~0U && reg->idx[0].rel_addr)
         shader_glsl_add_src_param(ins, reg->idx[0].rel_addr, WINED3DSP_WRITEMASK_0, &rel_param0);
@@ -1580,7 +1665,7 @@ static void shader_glsl_get_register_name(const struct wined3d_shader_register *
                     switch (reg->data_type)
                     {
                         case WINED3D_DATA_FLOAT:
-                            sprintf(register_name, "%.8e", *(const float *)reg->immconst_data);
+                            shader_glsl_ftoa(*(const float *)reg->immconst_data, register_name);
                             break;
                         case WINED3D_DATA_INT:
                             sprintf(register_name, "%#x", reg->immconst_data[0]);
@@ -1600,9 +1685,12 @@ static void shader_glsl_get_register_name(const struct wined3d_shader_register *
                     switch (reg->data_type)
                     {
                         case WINED3D_DATA_FLOAT:
-                            sprintf(register_name, "vec4(%.8e, %.8e, %.8e, %.8e)",
-                                    *(const float *)&reg->immconst_data[0], *(const float *)&reg->immconst_data[1],
-                                    *(const float *)&reg->immconst_data[2], *(const float *)&reg->immconst_data[3]);
+                            shader_glsl_ftoa(*(const float *)&reg->immconst_data[0], imm_str[0]);
+                            shader_glsl_ftoa(*(const float *)&reg->immconst_data[1], imm_str[1]);
+                            shader_glsl_ftoa(*(const float *)&reg->immconst_data[2], imm_str[2]);
+                            shader_glsl_ftoa(*(const float *)&reg->immconst_data[3], imm_str[3]);
+                            sprintf(register_name, "vec4(%s, %s, %s, %s)",
+                                    imm_str[0], imm_str[1], imm_str[2], imm_str[3]);
                             break;
                         case WINED3D_DATA_INT:
                             sprintf(register_name, "ivec4(%#x, %#x, %#x, %#x)",
@@ -1870,7 +1958,7 @@ static void shader_glsl_get_sample_function(const struct wined3d_shader_context
     BOOL shadow = ctx->reg_maps->shader_version.type == WINED3D_SHADER_TYPE_PIXEL
             && (((const struct shader_glsl_ctx_priv *)ctx->backend_data)->cur_ps_args->shadow & (1 << sampler_idx));
     BOOL projected = flags & WINED3D_GLSL_SAMPLE_PROJECTED;
-    BOOL texrect = flags & WINED3D_GLSL_SAMPLE_RECT;
+    BOOL texrect = flags & WINED3D_GLSL_SAMPLE_NPOT && gl_info->supported[ARB_TEXTURE_RECTANGLE];
     BOOL lod = flags & WINED3D_GLSL_SAMPLE_LOD;
     BOOL grad = flags & WINED3D_GLSL_SAMPLE_GRAD;
 
@@ -2952,14 +3040,11 @@ static void shader_glsl_cnd(const struct wined3d_shader_instruction *ins)
         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)
-        {
+        if (ins->coissue && ins->dst->write_mask != WINED3DSP_WRITEMASK_3)
             shader_addline(ins->ctx->buffer, "%s /* COISSUE! */);\n", src1_param.param_str);
-        } else {
+        else
             shader_addline(ins->ctx->buffer, "%s > 0.5 ? %s : %s);\n",
                     src0_param.param_str, src1_param.param_str, src2_param.param_str);
-        }
         return;
     }
 
@@ -3458,15 +3543,13 @@ static void shader_glsl_ret(const struct wined3d_shader_instruction *ins)
  ********************************************/
 static void shader_glsl_tex(const struct wined3d_shader_instruction *ins)
 {
-    const struct wined3d_shader *shader = ins->ctx->shader;
-    struct wined3d_device *device = shader->device;
     DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major,
             ins->ctx->reg_maps->shader_version.minor);
     struct glsl_sample_function sample_function;
-    const struct wined3d_texture *texture;
     DWORD sample_flags = 0;
     DWORD sampler_idx;
     DWORD mask = 0, swizzle;
+    const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data;
 
     /* 1.0-1.4: Use destination register as sampler source.
      * 2.0+: Use provided sampler source. */
@@ -3474,11 +3557,9 @@ static void shader_glsl_tex(const struct wined3d_shader_instruction *ins)
         sampler_idx = ins->dst[0].reg.idx[0].offset;
     else
         sampler_idx = ins->src[1].reg.idx[0].offset;
-    texture = device->stateBlock->state.textures[sampler_idx];
 
     if (shader_version < WINED3D_SHADER_VERSION(1,4))
     {
-        const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data;
         DWORD flags = (priv->cur_ps_args->tex_transform >> sampler_idx * WINED3D_PSARGS_TEXTRANSFORM_SHIFT)
                 & WINED3D_PSARGS_TEXTRANSFORM_MASK;
         enum wined3d_sampler_texture_type sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx];
@@ -3516,8 +3597,11 @@ static void shader_glsl_tex(const struct wined3d_shader_instruction *ins)
             sample_flags |= WINED3D_GLSL_SAMPLE_PROJECTED;
             mask = WINED3DSP_WRITEMASK_3;
         }
-    } else {
-        if (ins->flags & WINED3DSI_TEXLD_PROJECT)
+    }
+    else
+    {
+        if ((ins->flags & WINED3DSI_TEXLD_PROJECT)
+                && ins->ctx->reg_maps->sampler_type[sampler_idx] != WINED3DSTT_CUBE)
         {
             /* ps 2.0 texldp instruction always divides by the fourth component. */
             sample_flags |= WINED3D_GLSL_SAMPLE_PROJECTED;
@@ -3525,8 +3609,8 @@ static void shader_glsl_tex(const struct wined3d_shader_instruction *ins)
         }
     }
 
-    if (texture && texture->target == GL_TEXTURE_RECTANGLE_ARB)
-        sample_flags |= WINED3D_GLSL_SAMPLE_RECT;
+    if (priv->cur_ps_args->np2_fixup & (1 << sampler_idx))
+        sample_flags |= WINED3D_GLSL_SAMPLE_NPOT;
 
     shader_glsl_get_sample_function(ins->ctx, sampler_idx, sample_flags, &sample_function);
     mask |= sample_function.coord_mask;
@@ -3562,15 +3646,13 @@ static void shader_glsl_tex(const struct wined3d_shader_instruction *ins)
 
 static void shader_glsl_texldd(const struct wined3d_shader_instruction *ins)
 {
-    const struct wined3d_shader *shader = ins->ctx->shader;
-    struct wined3d_device *device = shader->device;
     const struct wined3d_gl_info *gl_info = ins->ctx->gl_info;
     struct glsl_src_param coord_param, dx_param, dy_param;
     DWORD sample_flags = WINED3D_GLSL_SAMPLE_GRAD;
     struct glsl_sample_function sample_function;
     DWORD sampler_idx;
     DWORD swizzle = ins->src[1].swizzle;
-    const struct wined3d_texture *texture;
+    const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data;
 
     if (!gl_info->supported[ARB_SHADER_TEXTURE_LOD] && !gl_info->supported[EXT_GPU_SHADER4])
     {
@@ -3580,9 +3662,8 @@ static void shader_glsl_texldd(const struct wined3d_shader_instruction *ins)
     }
 
     sampler_idx = ins->src[1].reg.idx[0].offset;
-    texture = device->stateBlock->state.textures[sampler_idx];
-    if (texture && texture->target == GL_TEXTURE_RECTANGLE_ARB)
-        sample_flags |= WINED3D_GLSL_SAMPLE_RECT;
+    if (priv->cur_ps_args->np2_fixup & (1 << sampler_idx))
+        sample_flags |= WINED3D_GLSL_SAMPLE_NPOT;
 
     shader_glsl_get_sample_function(ins->ctx, sampler_idx, sample_flags, &sample_function);
     shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &coord_param);
@@ -3595,20 +3676,18 @@ static void shader_glsl_texldd(const struct wined3d_shader_instruction *ins)
 
 static void shader_glsl_texldl(const struct wined3d_shader_instruction *ins)
 {
-    const struct wined3d_shader *shader = ins->ctx->shader;
-    struct wined3d_device *device = shader->device;
     const struct wined3d_gl_info *gl_info = ins->ctx->gl_info;
     struct glsl_src_param coord_param, lod_param;
     DWORD sample_flags = WINED3D_GLSL_SAMPLE_LOD;
     struct glsl_sample_function sample_function;
     DWORD sampler_idx;
     DWORD swizzle = ins->src[1].swizzle;
-    const struct wined3d_texture *texture;
+    const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data;
 
     sampler_idx = ins->src[1].reg.idx[0].offset;
-    texture = device->stateBlock->state.textures[sampler_idx];
-    if (texture && texture->target == GL_TEXTURE_RECTANGLE_ARB)
-        sample_flags |= WINED3D_GLSL_SAMPLE_RECT;
+    if (ins->ctx->reg_maps->shader_version.type == WINED3D_SHADER_TYPE_PIXEL
+            && priv->cur_ps_args->np2_fixup & (1 << sampler_idx))
+        sample_flags |= WINED3D_GLSL_SAMPLE_NPOT;
 
     shader_glsl_get_sample_function(ins->ctx, sampler_idx, sample_flags, &sample_function);
     shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &coord_param);
@@ -4426,24 +4505,23 @@ static void shader_glsl_generate_srgb_write_correction(struct wined3d_shader_buf
     shader_addline(buffer, "gl_FragData[0] = clamp(gl_FragData[0], 0.0, 1.0);\n");
 }
 
-static void shader_glsl_generate_fog_code(struct wined3d_shader_buffer *buffer, enum fogmode mode)
+static void shader_glsl_generate_fog_code(struct wined3d_shader_buffer *buffer, enum wined3d_ffp_ps_fog_mode mode)
 {
     switch (mode)
     {
-        case FOG_OFF:
+        case WINED3D_FFP_PS_FOG_OFF:
             return;
 
-        case FOG_LINEAR:
-            /* Fog = (gl_Fog.end - gl_FogFragCoord) / (gl_Fog.end - gl_Fog.start) */
-            shader_addline(buffer, "float Fog = (gl_Fog.end - gl_FogFragCoord) / (gl_Fog.end - gl_Fog.start);\n");
+        case WINED3D_FFP_PS_FOG_LINEAR:
+            shader_addline(buffer, "float Fog = (gl_Fog.end - gl_FogFragCoord) * gl_Fog.scale;\n");
             break;
 
-        case FOG_EXP:
+        case WINED3D_FFP_PS_FOG_EXP:
             /* Fog = e^-(gl_Fog.density * gl_FogFragCoord) */
             shader_addline(buffer, "float Fog = exp(-gl_Fog.density * gl_FogFragCoord);\n");
             break;
 
-        case FOG_EXP2:
+        case WINED3D_FFP_PS_FOG_EXP2:
             /* Fog = e^-((gl_Fog.density * gl_FogFragCoord)^2) */
             shader_addline(buffer, "float Fog = exp(-gl_Fog.density * gl_Fog.density * gl_FogFragCoord * gl_FogFragCoord);\n");
             break;
@@ -4456,25 +4534,6 @@ static void shader_glsl_generate_fog_code(struct wined3d_shader_buffer *buffer,
     shader_addline(buffer, "gl_FragData[0].xyz = mix(gl_Fog.color.xyz, gl_FragData[0].xyz, clamp(Fog, 0.0, 1.0));\n");
 }
 
-/* Context activation is done by the caller. */
-static void hardcode_local_constants(const struct wined3d_shader *shader,
-        const struct wined3d_gl_info *gl_info, GLhandleARB programId, const char *prefix)
-{
-    const struct wined3d_shader_lconst *lconst;
-    GLint tmp_loc;
-    const float *value;
-    char glsl_name[10];
-
-    LIST_FOR_EACH_ENTRY(lconst, &shader->constantsF, struct wined3d_shader_lconst, entry)
-    {
-        value = (const float *)lconst->value;
-        snprintf(glsl_name, sizeof(glsl_name), "%s_lc%u", prefix, lconst->idx);
-        tmp_loc = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name));
-        GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, value));
-    }
-    checkGLcall("Hardcoding local constants");
-}
-
 /* Context activation is done by the caller. */
 static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context,
         struct wined3d_shader_buffer *buffer, const struct wined3d_shader *shader,
@@ -4646,7 +4705,6 @@ static GLhandleARB find_glsl_pshader(const struct wined3d_context *context,
         struct wined3d_shader_buffer *buffer, struct wined3d_shader *shader,
         const struct ps_compile_args *args, const struct ps_np2fixup_info **np2fixup_info)
 {
-    struct wined3d_state *state = &shader->device->stateBlock->state;
     struct glsl_ps_compiled_shader *gl_shaders, *new_array;
     struct glsl_shader_private *shader_data;
     struct ps_np2fixup_info *np2fixup;
@@ -4709,7 +4767,7 @@ static GLhandleARB find_glsl_pshader(const struct wined3d_context *context,
     memset(np2fixup, 0, sizeof(*np2fixup));
     *np2fixup_info = args->np2_fixup ? np2fixup : NULL;
 
-    pixelshader_update_samplers(&shader->reg_maps, state->textures);
+    pixelshader_update_samplers(shader, args->tex_types);
 
     shader_buffer_clear(buffer);
     ret = shader_glsl_generate_pshader(context, buffer, shader, args, np2fixup);
@@ -4731,7 +4789,7 @@ static GLhandleARB find_glsl_vshader(const struct wined3d_context *context,
 {
     UINT i;
     DWORD new_size;
-    DWORD use_map = shader->device->strided_streams.use_map;
+    DWORD use_map = shader->device->stream_info.use_map;
     struct glsl_vs_compiled_shader *gl_shaders, *new_array;
     struct glsl_shader_private *shader_data;
     GLhandleARB ret;
@@ -4829,6 +4887,239 @@ static GLhandleARB find_glsl_geometry_shader(const struct wined3d_context *conte
     return ret;
 }
 
+static const char *shader_glsl_ffp_mcs(enum wined3d_material_color_source mcs, const char *material)
+{
+    switch (mcs)
+    {
+        case WINED3D_MCS_MATERIAL:
+            return material;
+        case WINED3D_MCS_COLOR1:
+            return "gl_Color";
+        case WINED3D_MCS_COLOR2:
+            return "gl_SecondaryColor";
+        default:
+            ERR("Invalid material color source %#x.\n", mcs);
+            return "<invalid>";
+    }
+}
+
+static void shader_glsl_ffp_vertex_lighting(struct wined3d_shader_buffer *buffer,
+        const struct wined3d_ffp_vs_settings *settings, const struct wined3d_gl_info *gl_info)
+{
+    const char *diffuse, *specular, *emission, *ambient;
+    enum wined3d_light_type light_type;
+    unsigned int i;
+
+    if (!settings->lighting)
+    {
+        shader_addline(buffer, "gl_FrontColor = gl_Color;\n");
+        shader_addline(buffer, "gl_FrontSecondaryColor = gl_SecondaryColor;\n");
+        return;
+    }
+
+    shader_addline(buffer, "vec3 ambient = gl_LightModel.ambient.xyz;\n");
+    shader_addline(buffer, "vec3 diffuse = vec3(0.0);\n");
+    shader_addline(buffer, "vec4 specular = vec4(0.0);\n");
+    shader_addline(buffer, "vec3 dir, dst;\n");
+    shader_addline(buffer, "float att, t;\n");
+
+    ambient = shader_glsl_ffp_mcs(settings->ambient_source, "gl_FrontMaterial.ambient");
+    diffuse = shader_glsl_ffp_mcs(settings->diffuse_source, "gl_FrontMaterial.diffuse");
+    specular = shader_glsl_ffp_mcs(settings->specular_source, "gl_FrontMaterial.specular");
+    emission = shader_glsl_ffp_mcs(settings->emission_source, "gl_FrontMaterial.emission");
+
+    for (i = 0; i < MAX_ACTIVE_LIGHTS; ++i)
+    {
+        light_type = (settings->light_type >> WINED3D_FFP_LIGHT_TYPE_SHIFT(i)) & WINED3D_FFP_LIGHT_TYPE_MASK;
+        switch (light_type)
+        {
+            case WINED3D_LIGHT_POINT:
+                shader_addline(buffer, "dir = gl_LightSource[%u].position.xyz - ec_pos.xyz;\n", i);
+                shader_addline(buffer, "dst.z = dot(dir, dir);\n");
+                shader_addline(buffer, "dst.y = sqrt(dst.z);\n");
+                shader_addline(buffer, "dst.x = 1.0;\n");
+                shader_addline(buffer, "att = dot(dst.xyz, vec3(gl_LightSource[%u].constantAttenuation,"
+                        " gl_LightSource[%u].linearAttenuation, gl_LightSource[%u].quadraticAttenuation));\n", i, i, i);
+                shader_addline(buffer, "ambient += gl_LightSource[%u].ambient.xyz / att;\n", i);
+                if (!settings->normal)
+                    break;
+                shader_addline(buffer, "dir = normalize(dir);\n");
+                shader_addline(buffer, "diffuse += (max(0.0, dot(dir, normal))"
+                        " * gl_LightSource[%u].diffuse.xyz) / att;\n", i);
+                if (settings->localviewer)
+                    shader_addline(buffer, "t = dot(normal, normalize(dir - normalize(ec_pos.xyz)));\n");
+                else
+                    shader_addline(buffer, "t = dot(normal, normalize(dir + vec3(0.0, 0.0, 1.0)));\n");
+                shader_addline(buffer, "if (t > 0.0) specular += (pow(t, gl_FrontMaterial.shininess)"
+                        " * gl_LightSource[%u].specular) / att;\n", i);
+                break;
+
+            case WINED3D_LIGHT_SPOT:
+                shader_addline(buffer, "dir = gl_LightSource[%u].position.xyz - ec_pos.xyz;\n", i);
+                shader_addline(buffer, "dst.z = dot(dir, dir);\n");
+                shader_addline(buffer, "dst.y = sqrt(dst.z);\n");
+                shader_addline(buffer, "dst.x = 1.0;\n");
+                shader_addline(buffer, "dir = normalize(dir);\n");
+                shader_addline(buffer, "t = dot(-dir, normalize(gl_LightSource[%u].spotDirection));\n", i);
+                shader_addline(buffer, "if (t < gl_LightSource[%u].spotCosCutoff) att = 0.0;\n", i);
+                shader_addline(buffer, "else att = pow(t, gl_LightSource[%u].spotExponent)"
+                        " / dot(dst.xyz, vec3(gl_LightSource[%u].constantAttenuation,"
+                        " gl_LightSource[%u].linearAttenuation, gl_LightSource[%u].quadraticAttenuation));\n",
+                        i, i, i, i);
+                shader_addline(buffer, "ambient += gl_LightSource[%u].ambient.xyz * att;\n", i);
+                if (!settings->normal)
+                    break;
+                shader_addline(buffer, "diffuse += (max(0.0, dot(dir, normal))"
+                        " * gl_LightSource[%u].diffuse.xyz) * att;\n", i);
+                if (settings->localviewer)
+                    shader_addline(buffer, "t = dot(normal, normalize(dir - normalize(ec_pos.xyz)));\n");
+                else
+                    shader_addline(buffer, "t = dot(normal, normalize(dir + vec3(0.0, 0.0, 1.0)));\n");
+                shader_addline(buffer, "if (t > 0.0) specular += (pow(t, gl_FrontMaterial.shininess)"
+                        " * gl_LightSource[%u].specular) * att;\n", i);
+                break;
+
+            case WINED3D_LIGHT_DIRECTIONAL:
+                shader_addline(buffer, "ambient += gl_LightSource[%u].ambient.xyz;\n", i);
+                if (!settings->normal)
+                    break;
+                shader_addline(buffer, "dir = normalize(gl_LightSource[%u].position.xyz);\n", i);
+                shader_addline(buffer, "diffuse += max(0.0, dot(dir, normal)) * gl_LightSource[%u].diffuse.xyz;\n", i);
+                shader_addline(buffer, "t = dot(normal, gl_LightSource[%u].halfVector.xyz);\n", i);
+                shader_addline(buffer, "if (t > 0.0) specular += pow(t, gl_FrontMaterial.shininess)"
+                        " * gl_LightSource[%u].specular;\n", i);
+                break;
+
+            default:
+                if (light_type)
+                    FIXME("Unhandled light type %#x.\n", light_type);
+                continue;
+        }
+    }
+
+    shader_addline(buffer, "gl_FrontColor.xyz = %s.xyz * ambient + %s.xyz * diffuse + %s.xyz;\n",
+            ambient, diffuse, emission);
+    shader_addline(buffer, "gl_FrontColor.w = %s.w;\n", diffuse);
+    shader_addline(buffer, "gl_FrontSecondaryColor = %s * specular;\n", specular);
+}
+
+/* Context activation is done by the caller. */
+static GLhandleARB shader_glsl_generate_ffp_vertex_shader(struct wined3d_shader_buffer *buffer,
+        const struct wined3d_ffp_vs_settings *settings, const struct wined3d_gl_info *gl_info)
+{
+    GLhandleARB shader_obj;
+    unsigned int i;
+
+    shader_buffer_clear(buffer);
+
+    shader_addline(buffer, "#version 120\n");
+    shader_addline(buffer, "\n");
+    shader_addline(buffer, "void main()\n{\n");
+    shader_addline(buffer, "float m;\n");
+    shader_addline(buffer, "vec3 r;\n");
+
+    if (settings->transformed)
+    {
+        shader_addline(buffer, "vec4 ec_pos = vec4(gl_Vertex.xyz, 1.0);\n");
+        shader_addline(buffer, "gl_Position = gl_ProjectionMatrix * ec_pos;\n");
+        shader_addline(buffer, "if (gl_Vertex.w != 0.0) gl_Position /= gl_Vertex.w;\n");
+    }
+    else
+    {
+        shader_addline(buffer, "vec4 ec_pos = gl_ModelViewMatrix * gl_Vertex;\n");
+        shader_addline(buffer, "gl_Position = gl_ProjectionMatrix * ec_pos;\n");
+        if (settings->clipping)
+            shader_addline(buffer, "gl_ClipVertex = ec_pos;\n");
+        shader_addline(buffer, "ec_pos /= ec_pos.w;\n");
+    }
+
+    if (!settings->normal)
+        shader_addline(buffer, "vec3 normal = vec3(0.0);\n");
+    else if (settings->normalize)
+        shader_addline(buffer, "vec3 normal = normalize(gl_NormalMatrix * gl_Normal);\n");
+    else
+        shader_addline(buffer, "vec3 normal = gl_NormalMatrix * gl_Normal;\n");
+
+    shader_glsl_ffp_vertex_lighting(buffer, settings, gl_info);
+
+    for (i = 0; i < MAX_TEXTURES; ++i)
+    {
+        switch (settings->texgen[i] << WINED3D_FFP_TCI_SHIFT)
+        {
+            case WINED3DTSS_TCI_PASSTHRU:
+                if (settings->texcoords & (1 << i))
+                    shader_addline(buffer, "gl_TexCoord[%u] = gl_TextureMatrix[%u] * gl_MultiTexCoord%d;\n",
+                            i, i, i);
+                break;
+
+            case WINED3DTSS_TCI_CAMERASPACENORMAL:
+                shader_addline(buffer, "gl_TexCoord[%u] = gl_TextureMatrix[%u] * vec4(normal, 1.0);\n", i, i);
+                break;
+
+            case WINED3DTSS_TCI_CAMERASPACEPOSITION:
+                shader_addline(buffer, "gl_TexCoord[%u] = gl_TextureMatrix[%u] * ec_pos;\n", i, i);
+                break;
+
+            case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
+                shader_addline(buffer, "gl_TexCoord[%u] = gl_TextureMatrix[%u]"
+                        " * vec4(reflect(normalize(ec_pos.xyz), normal), 1.0);\n", i, i);
+                break;
+
+            case WINED3DTSS_TCI_SPHEREMAP:
+                shader_addline(buffer, "r = reflect(normalize(ec_pos.xyz), normal);\n");
+                shader_addline(buffer, "m = 2.0 * length(vec3(r.x, r.y, r.z + 1.0));\n");
+                shader_addline(buffer, "gl_TexCoord[%u] = gl_TextureMatrix[%u]"
+                        " * vec4(r.x / m + 0.5, r.y / m + 0.5, 0.0, 1.0);\n", i, i);
+                break;
+
+            default:
+                ERR("Unhandled texgen %#x.\n", settings->texgen[i]);
+                break;
+        }
+    }
+
+    switch (settings->fog_mode)
+    {
+        case WINED3D_FFP_VS_FOG_OFF:
+            break;
+
+        case WINED3D_FFP_VS_FOG_FOGCOORD:
+            shader_addline(buffer, "gl_FogFragCoord = gl_SecondaryColor.w * 255.0;\n");
+            break;
+
+        case WINED3D_FFP_VS_FOG_RANGE:
+            shader_addline(buffer, "gl_FogFragCoord = length(ec_pos.xyz);\n");
+            break;
+
+        case WINED3D_FFP_VS_FOG_DEPTH:
+            if (settings->ortho_fog)
+                /* Need to undo the [0.0 - 1.0] -> [-1.0 - 1.0] transformation from D3D to GL coordinates. */
+                shader_addline(buffer, "gl_FogFragCoord = gl_Position.z * 0.5 + 0.5;\n");
+            else
+                shader_addline(buffer, "gl_FogFragCoord = ec_pos.z;\n");
+            break;
+
+        default:
+            ERR("Unhandled fog mode %#x.\n", settings->fog_mode);
+            break;
+    }
+
+    if (settings->point_size)
+    {
+        shader_addline(buffer, "gl_PointSize = gl_Point.size / sqrt(gl_Point.distanceConstantAttenuation"
+                " + gl_Point.distanceLinearAttenuation * length(ec_pos.xyz)"
+                " + gl_Point.distanceQuadraticAttenuation * dot(ec_pos.xyz, ec_pos.xyz));\n");
+        shader_addline(buffer, "gl_PointSize = clamp(gl_PointSize, gl_Point.sizeMin, gl_Point.sizeMax);\n");
+    }
+
+    shader_addline(buffer, "}\n");
+
+    shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB));
+    shader_glsl_compile(gl_info, shader_obj, buffer->buffer);
+
+    return shader_obj;
+}
+
 static const char *shader_glsl_get_ffp_fragment_op_arg(struct wined3d_shader_buffer *buffer,
         DWORD argnum, unsigned int stage, DWORD arg)
 {
@@ -5149,6 +5440,9 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct wined3d_shader_buf
 
     shader_addline(buffer, "#version 120\n");
 
+    if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
+        shader_addline(buffer, "#extension GL_ARB_texture_rectangle : enable\n");
+
     shader_addline(buffer, "vec4 tmp0, tmp1;\n");
     shader_addline(buffer, "vec4 ret;\n");
     if (tempreg_used || settings->sRGB_write)
@@ -5199,16 +5493,18 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct wined3d_shader_buf
 
     if (settings->sRGB_write)
     {
-        shader_addline(buffer, "const vec4 srgb_const0 = vec4(%.8e, %.8e, %.8e, %.8e);\n",
-                srgb_pow, srgb_mul_high, srgb_sub_high, srgb_mul_low);
-        shader_addline(buffer, "const vec4 srgb_const1 = vec4(%.8e, 0.0, 0.0, 0.0);\n",
-                srgb_cmp);
+        shader_addline(buffer, "const vec4 srgb_const0 = ");
+        shader_glsl_append_imm_vec4(buffer, srgb_const0);
+        shader_addline(buffer, ";\n");
+        shader_addline(buffer, "const vec4 srgb_const1 = ");
+        shader_glsl_append_imm_vec4(buffer, srgb_const1);
+        shader_addline(buffer, ";\n");
     }
 
     shader_addline(buffer, "void main()\n{\n");
 
     if (lowest_disabled_stage < 7 && settings->emul_clipplanes)
-        shader_addline(buffer, "if (any(lessThan(gl_texCoord[7], vec4(0.0)))) discard;\n");
+        shader_addline(buffer, "if (any(lessThan(gl_TexCoord[7], vec4(0.0)))) discard;\n");
 
     /* Generate texture sampling instructions) */
     for (stage = 0; stage < MAX_TEXTURES && settings->op[stage].cop != WINED3D_TOP_DISABLE; ++stage)
@@ -5436,6 +5732,27 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct wined3d_shader_buf
     return shader_obj;
 }
 
+static struct glsl_ffp_vertex_shader *shader_glsl_find_ffp_vertex_shader(struct shader_glsl_priv *priv,
+        const struct wined3d_gl_info *gl_info, const struct wined3d_ffp_vs_settings *settings)
+{
+    struct glsl_ffp_vertex_shader *shader;
+    const struct wine_rb_entry *entry;
+
+    if ((entry = wine_rb_get(&priv->ffp_vertex_shaders, settings)))
+        return WINE_RB_ENTRY_VALUE(entry, struct glsl_ffp_vertex_shader, desc.entry);
+
+    if (!(shader = HeapAlloc(GetProcessHeap(), 0, sizeof(*shader))))
+        return NULL;
+
+    shader->desc.settings = *settings;
+    shader->id = shader_glsl_generate_ffp_vertex_shader(&priv->shader_buffer, settings, gl_info);
+    list_init(&shader->linked_programs);
+    if (wine_rb_put(&priv->ffp_vertex_shaders, &shader->desc.settings, &shader->desc.entry) == -1)
+        ERR("Failed to insert ffp vertex shader.\n");
+
+    return shader;
+}
+
 static struct glsl_ffp_fragment_shader *shader_glsl_find_ffp_fragment_shader(struct shader_glsl_priv *priv,
         const struct wined3d_gl_info *gl_info, const struct ffp_frag_settings *args)
 {
@@ -5517,13 +5834,11 @@ static void shader_glsl_init_ps_uniform_locations(const struct wined3d_gl_info *
 }
 
 /* Context activation is done by the caller. */
-static void set_glsl_shader_program(const struct wined3d_context *context, struct wined3d_device *device,
-        enum wined3d_shader_mode vertex_mode, enum wined3d_shader_mode fragment_mode)
+static void set_glsl_shader_program(const struct wined3d_context *context, const struct wined3d_state *state,
+        struct shader_glsl_priv *priv, struct glsl_context_data *ctx_data)
 {
-    const struct wined3d_state *state = &device->stateBlock->state;
     const struct wined3d_gl_info *gl_info = context->gl_info;
     const struct ps_np2fixup_info *np2fixup_info = NULL;
-    struct shader_glsl_priv *priv = device->shader_priv;
     struct glsl_shader_prog_link *entry = NULL;
     struct wined3d_shader *vshader = NULL;
     struct wined3d_shader *gshader = NULL;
@@ -5531,54 +5846,83 @@ static void set_glsl_shader_program(const struct wined3d_context *context, struc
     GLhandleARB programId                  = 0;
     GLhandleARB reorder_shader_id          = 0;
     unsigned int i;
-    struct ps_compile_args ps_compile_args;
-    struct vs_compile_args vs_compile_args;
-    GLhandleARB vs_id, gs_id, ps_id;
-    struct list *ps_list;
+    GLhandleARB vs_id = 0;
+    GLhandleARB gs_id = 0;
+    GLhandleARB ps_id = 0;
+    struct list *ps_list, *vs_list;
+    struct wined3d_device *device = context->swapchain->device;
 
-    if (vertex_mode == WINED3D_SHADER_MODE_SHADER)
+    if (!(context->shader_update_mask & (1 << WINED3D_SHADER_TYPE_VERTEX)))
     {
+        vs_id = ctx_data->glsl_program->vs.id;
+        vs_list = &ctx_data->glsl_program->vs.shader_entry;
+
+        if (use_vs(state))
+        {
+            vshader = state->vertex_shader;
+            gshader = state->geometry_shader;
+
+            if (!(context->shader_update_mask & (1 << WINED3D_SHADER_TYPE_GEOMETRY))
+                    && ctx_data->glsl_program->gs.id)
+                gs_id = ctx_data->glsl_program->gs.id;
+            else if (gshader)
+                gs_id = find_glsl_geometry_shader(context, &priv->shader_buffer, gshader);
+        }
+    }
+    else if (use_vs(state))
+    {
+        struct vs_compile_args vs_compile_args;
         vshader = state->vertex_shader;
+
         find_vs_compile_args(state, vshader, &vs_compile_args);
         vs_id = find_glsl_vshader(context, &priv->shader_buffer, vshader, &vs_compile_args);
+        vs_list = &vshader->linked_programs;
 
         if ((gshader = state->geometry_shader))
             gs_id = find_glsl_geometry_shader(context, &priv->shader_buffer, gshader);
-        else
-            gs_id = 0;
     }
-    else
+    else if (priv->vertex_pipe == &glsl_vertex_pipe)
     {
-        vs_id = 0;
-        gs_id = 0;
+        struct glsl_ffp_vertex_shader *ffp_shader;
+        struct wined3d_ffp_vs_settings settings;
+
+        wined3d_ffp_get_vs_settings(state, &device->stream_info, &settings);
+        ffp_shader = shader_glsl_find_ffp_vertex_shader(priv, gl_info, &settings);
+        vs_id = ffp_shader->id;
+        vs_list = &ffp_shader->linked_programs;
     }
 
-    if (fragment_mode == WINED3D_SHADER_MODE_SHADER)
+    if (!(context->shader_update_mask & (1 << WINED3D_SHADER_TYPE_PIXEL)))
+    {
+        ps_id = ctx_data->glsl_program->ps.id;
+        ps_list = &ctx_data->glsl_program->ps.shader_entry;
+
+        if (use_ps(state))
+            pshader = state->pixel_shader;
+    }
+    else if (use_ps(state))
     {
+        struct ps_compile_args ps_compile_args;
         pshader = state->pixel_shader;
         find_ps_compile_args(state, pshader, &ps_compile_args);
         ps_id = find_glsl_pshader(context, &priv->shader_buffer,
                 pshader, &ps_compile_args, &np2fixup_info);
         ps_list = &pshader->linked_programs;
     }
-    else if (fragment_mode == WINED3D_SHADER_MODE_FFP && priv->fragment_pipe == &glsl_fragment_pipe)
+    else if (priv->fragment_pipe == &glsl_fragment_pipe)
     {
         struct glsl_ffp_fragment_shader *ffp_shader;
         struct ffp_frag_settings settings;
 
-        gen_ffp_frag_op(device, state, &settings, FALSE);
+        gen_ffp_frag_op(context, state, &settings, FALSE);
         ffp_shader = shader_glsl_find_ffp_fragment_shader(priv, gl_info, &settings);
         ps_id = ffp_shader->id;
         ps_list = &ffp_shader->linked_programs;
     }
-    else
-    {
-        ps_id = 0;
-    }
 
     if ((!vs_id && !gs_id && !ps_id) || (entry = get_glsl_program_entry(priv, vs_id, gs_id, ps_id)))
     {
-        priv->glsl_program = entry;
+        ctx_data->glsl_program = entry;
         return;
     }
 
@@ -5598,9 +5942,18 @@ static void set_glsl_shader_program(const struct wined3d_context *context, struc
     add_glsl_program_entry(priv, entry);
 
     /* Set the current program */
-    priv->glsl_program = entry;
+    ctx_data->glsl_program = entry;
 
     /* Attach GLSL vshader */
+    if (vs_id)
+    {
+        TRACE("Attaching GLSL shader object %u to program %u.\n", vs_id, programId);
+        GL_EXTCALL(glAttachObjectARB(programId, vs_id));
+        checkGLcall("glAttachObjectARB");
+
+        list_add_head(vs_list, &entry->vs.shader_entry);
+    }
+
     if (vshader)
     {
         WORD map = vshader->reg_maps.input_registers;
@@ -5615,10 +5968,6 @@ static void set_glsl_shader_program(const struct wined3d_context *context, struc
          */
         GL_EXTCALL(glDeleteObjectARB(reorder_shader_id));
 
-        TRACE("Attaching GLSL shader object %u to program %u.\n", vs_id, programId);
-        GL_EXTCALL(glAttachObjectARB(programId, vs_id));
-        checkGLcall("glAttachObjectARB");
-
         /* Bind vertex attributes to a corresponding index number to match
          * the same index numbers as ARB_vertex_programs (makes loading
          * vertex attributes simpler).  With this method, we can use the
@@ -5636,8 +5985,6 @@ static void set_glsl_shader_program(const struct wined3d_context *context, struc
             GL_EXTCALL(glBindAttribLocationARB(programId, i, tmp_name));
         }
         checkGLcall("glBindAttribLocationARB");
-
-        list_add_head(&vshader->linked_programs, &entry->vs.shader_entry);
     }
 
     if (gshader)
@@ -5706,14 +6053,46 @@ static void set_glsl_shader_program(const struct wined3d_context *context, struc
     shader_glsl_load_vsamplers(gl_info, device->texUnitMap, programId);
     shader_glsl_load_psamplers(gl_info, device->texUnitMap, programId);
 
-    /* If the local constants do not have to be loaded with the environment constants,
-     * load them now to have them hardcoded in the GLSL program. This saves some CPU cycles
-     * later
-     */
-    if (pshader && !pshader->load_local_constsF)
-        hardcode_local_constants(pshader, gl_info, programId, "ps");
-    if (vshader && !vshader->load_local_constsF)
-        hardcode_local_constants(vshader, gl_info, programId, "vs");
+    entry->constant_update_mask = 0;
+    if (vshader)
+    {
+        entry->constant_update_mask |= WINED3D_SHADER_CONST_VS_F;
+        if (vshader->reg_maps.integer_constants)
+            entry->constant_update_mask |= WINED3D_SHADER_CONST_VS_I;
+        if (vshader->reg_maps.boolean_constants)
+            entry->constant_update_mask |= WINED3D_SHADER_CONST_VS_B;
+        entry->constant_update_mask |= WINED3D_SHADER_CONST_VS_POS_FIXUP;
+    }
+
+    if (ps_id)
+    {
+        if (pshader)
+        {
+            entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_F;
+            if (pshader->reg_maps.integer_constants)
+                entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_I;
+            if (pshader->reg_maps.boolean_constants)
+                entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_B;
+            if (entry->ps.ycorrection_location != -1)
+                entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_Y_CORR;
+        }
+        else
+        {
+            entry->constant_update_mask |= WINED3D_SHADER_CONST_FFP_PS;
+        }
+
+        for (i = 0; i < MAX_TEXTURES; ++i)
+        {
+            if (entry->ps.bumpenv_mat_location[i] != -1)
+            {
+                entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_BUMP_ENV;
+                break;
+            }
+        }
+
+        if (entry->ps.np2_fixup_location != -1)
+            entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_NP2_FIXUP;
+    }
 }
 
 /* Context activation is done by the caller. */
@@ -5827,18 +6206,42 @@ static GLhandleARB create_glsl_blt_shader(const struct wined3d_gl_info *gl_info,
 }
 
 /* Context activation is done by the caller. */
-static void shader_glsl_select(const struct wined3d_context *context, enum wined3d_shader_mode vertex_mode,
-        enum wined3d_shader_mode fragment_mode)
+static void shader_glsl_select(void *shader_priv, struct wined3d_context *context,
+        const struct wined3d_state *state)
 {
+    struct glsl_context_data *ctx_data = context->shader_backend_data;
     const struct wined3d_gl_info *gl_info = context->gl_info;
-    struct wined3d_device *device = context->swapchain->device;
-    struct shader_glsl_priv *priv = device->shader_priv;
-    GLhandleARB program_id = 0;
+    struct shader_glsl_priv *priv = shader_priv;
+    GLhandleARB program_id = 0, prev_id = 0;
     GLenum old_vertex_color_clamp, current_vertex_color_clamp;
 
-    old_vertex_color_clamp = priv->glsl_program ? priv->glsl_program->vs.vertex_color_clamp : GL_FIXED_ONLY_ARB;
-    set_glsl_shader_program(context, device, vertex_mode, fragment_mode);
-    current_vertex_color_clamp = priv->glsl_program ? priv->glsl_program->vs.vertex_color_clamp : GL_FIXED_ONLY_ARB;
+    priv->vertex_pipe->vp_enable(gl_info, !use_vs(state));
+    priv->fragment_pipe->enable_extension(gl_info, !use_ps(state));
+
+    if (ctx_data->glsl_program)
+    {
+        prev_id = ctx_data->glsl_program->programId;
+        old_vertex_color_clamp = ctx_data->glsl_program->vs.vertex_color_clamp;
+    }
+    else
+    {
+        prev_id = 0;
+        old_vertex_color_clamp = GL_FIXED_ONLY_ARB;
+    }
+
+    set_glsl_shader_program(context, state, priv, ctx_data);
+
+    if (ctx_data->glsl_program)
+    {
+        program_id = ctx_data->glsl_program->programId;
+        current_vertex_color_clamp = ctx_data->glsl_program->vs.vertex_color_clamp;
+    }
+    else
+    {
+        program_id = 0;
+        current_vertex_color_clamp = GL_FIXED_ONLY_ARB;
+    }
+
     if (old_vertex_color_clamp != current_vertex_color_clamp)
     {
         if (gl_info->supported[ARB_COLOR_BUFFER_FLOAT])
@@ -5852,17 +6255,46 @@ static void shader_glsl_select(const struct wined3d_context *context, enum wined
         }
     }
 
-    program_id = priv->glsl_program ? priv->glsl_program->programId : 0;
-    if (program_id) TRACE("Using GLSL program %u\n", program_id);
-    GL_EXTCALL(glUseProgramObjectARB(program_id));
+    TRACE("Using GLSL program %u.\n", program_id);
+
+    if (prev_id != program_id)
+    {
+        GL_EXTCALL(glUseProgramObjectARB(program_id));
+        checkGLcall("glUseProgramObjectARB");
+
+        if (program_id)
+            context->constant_update_mask |= ctx_data->glsl_program->constant_update_mask;
+    }
+}
+
+/* "context" is not necessarily the currently active context. */
+static void shader_glsl_invalidate_current_program(struct wined3d_context *context)
+{
+    struct glsl_context_data *ctx_data = context->shader_backend_data;
+
+    ctx_data->glsl_program = NULL;
+    context->shader_update_mask = (1 << WINED3D_SHADER_TYPE_PIXEL)
+            | (1 << WINED3D_SHADER_TYPE_VERTEX)
+            | (1 << WINED3D_SHADER_TYPE_GEOMETRY);
+}
+
+/* Context activation is done by the caller. */
+static void shader_glsl_disable(void *shader_priv, struct wined3d_context *context)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    struct shader_glsl_priv *priv = shader_priv;
+
+    shader_glsl_invalidate_current_program(context);
+    GL_EXTCALL(glUseProgramObjectARB(0));
     checkGLcall("glUseProgramObjectARB");
 
-    /* In case that NP2 texcoord fixup data is found for the selected program, trigger a reload of the
-     * constants. This has to be done because it can't be guaranteed that sampler() (from state.c) is
-     * called between selecting the shader and using it, which results in wrong fixup for some frames. */
-    if (priv->glsl_program && priv->glsl_program->ps.np2_fixup_info)
+    priv->vertex_pipe->vp_enable(gl_info, FALSE);
+    priv->fragment_pipe->enable_extension(gl_info, FALSE);
+
+    if (gl_info->supported[ARB_COLOR_BUFFER_FLOAT])
     {
-        shader_glsl_load_np2fixup_constants(priv, gl_info, &device->stateBlock->state);
+        GL_EXTCALL(glClampColorARB(GL_CLAMP_VERTEX_COLOR_ARB, GL_FIXED_ONLY_ARB));
+        checkGLcall("glClampColorARB");
     }
 }
 
@@ -5898,16 +6330,33 @@ static void shader_glsl_select_depth_blt(void *shader_priv, const struct wined3d
 /* Context activation is done by the caller. */
 static void shader_glsl_deselect_depth_blt(void *shader_priv, const struct wined3d_gl_info *gl_info)
 {
-    struct shader_glsl_priv *priv = shader_priv;
+    const struct glsl_context_data *ctx_data = context_get_current()->shader_backend_data;
     GLhandleARB program_id;
 
-    program_id = priv->glsl_program ? priv->glsl_program->programId : 0;
+    program_id = ctx_data->glsl_program ? ctx_data->glsl_program->programId : 0;
     if (program_id) TRACE("Using GLSL program %u\n", program_id);
 
     GL_EXTCALL(glUseProgramObjectARB(program_id));
     checkGLcall("glUseProgramObjectARB");
 }
 
+static void shader_glsl_invalidate_contexts_program(struct wined3d_device *device,
+        const struct glsl_shader_prog_link *program)
+{
+    const struct glsl_context_data *ctx_data;
+    struct wined3d_context *context;
+    unsigned int i;
+
+    for (i = 0; i < device->context_count; ++i)
+    {
+        context = device->contexts[i];
+        ctx_data = context->shader_backend_data;
+
+        if (ctx_data->glsl_program == program)
+            shader_glsl_invalidate_current_program(context);
+    }
+}
+
 static void shader_glsl_destroy(struct wined3d_shader *shader)
 {
     struct glsl_shader_private *shader_data = shader->backend_data;
@@ -5940,22 +6389,21 @@ static void shader_glsl_destroy(struct wined3d_shader *shader)
             {
                 struct glsl_ps_compiled_shader *gl_shaders = shader_data->gl_shaders.ps;
 
-                LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs,
-                        struct glsl_shader_prog_link, ps.shader_entry)
-                {
-                    delete_glsl_program_entry(priv, gl_info, entry);
-                }
-
                 for (i = 0; i < shader_data->num_gl_shaders; ++i)
                 {
                     TRACE("Deleting pixel shader %u.\n", gl_shaders[i].prgId);
-                    if (priv->glsl_program && priv->glsl_program->ps.id == gl_shaders[i].prgId)
-                        shader_glsl_select(context, WINED3D_SHADER_MODE_NONE, WINED3D_SHADER_MODE_NONE);
                     GL_EXTCALL(glDeleteObjectARB(gl_shaders[i].prgId));
                     checkGLcall("glDeleteObjectARB");
                 }
                 HeapFree(GetProcessHeap(), 0, shader_data->gl_shaders.ps);
 
+                LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs,
+                        struct glsl_shader_prog_link, ps.shader_entry)
+                {
+                    shader_glsl_invalidate_contexts_program(device, entry);
+                    delete_glsl_program_entry(priv, gl_info, entry);
+                }
+
                 break;
             }
 
@@ -5963,22 +6411,21 @@ static void shader_glsl_destroy(struct wined3d_shader *shader)
             {
                 struct glsl_vs_compiled_shader *gl_shaders = shader_data->gl_shaders.vs;
 
-                LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs,
-                        struct glsl_shader_prog_link, vs.shader_entry)
-                {
-                    delete_glsl_program_entry(priv, gl_info, entry);
-                }
-
                 for (i = 0; i < shader_data->num_gl_shaders; ++i)
                 {
                     TRACE("Deleting vertex shader %u.\n", gl_shaders[i].prgId);
-                    if (priv->glsl_program && priv->glsl_program->vs.id == gl_shaders[i].prgId)
-                        shader_glsl_select(context, WINED3D_SHADER_MODE_NONE, WINED3D_SHADER_MODE_NONE);
                     GL_EXTCALL(glDeleteObjectARB(gl_shaders[i].prgId));
                     checkGLcall("glDeleteObjectARB");
                 }
                 HeapFree(GetProcessHeap(), 0, shader_data->gl_shaders.vs);
 
+                LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs,
+                        struct glsl_shader_prog_link, vs.shader_entry)
+                {
+                    shader_glsl_invalidate_contexts_program(device, entry);
+                    delete_glsl_program_entry(priv, gl_info, entry);
+                }
+
                 break;
             }
 
@@ -5986,22 +6433,21 @@ static void shader_glsl_destroy(struct wined3d_shader *shader)
             {
                 struct glsl_gs_compiled_shader *gl_shaders = shader_data->gl_shaders.gs;
 
-                LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs,
-                        struct glsl_shader_prog_link, gs.shader_entry)
-                {
-                    delete_glsl_program_entry(priv, gl_info, entry);
-                }
-
                 for (i = 0; i < shader_data->num_gl_shaders; ++i)
                 {
                     TRACE("Deleting geometry shader %u.\n", gl_shaders[i].id);
-                    if (priv->glsl_program && priv->glsl_program->gs.id == gl_shaders[i].id)
-                        shader_glsl_select(context, WINED3D_SHADER_MODE_NONE, WINED3D_SHADER_MODE_NONE);
                     GL_EXTCALL(glDeleteObjectARB(gl_shaders[i].id));
                     checkGLcall("glDeleteObjectARB");
                 }
                 HeapFree(GetProcessHeap(), 0, shader_data->gl_shaders.gs);
 
+                LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs,
+                        struct glsl_shader_prog_link, gs.shader_entry)
+                {
+                    shader_glsl_invalidate_contexts_program(device, entry);
+                    delete_glsl_program_entry(priv, gl_info, entry);
+                }
+
                 break;
             }
 
@@ -6037,7 +6483,9 @@ static int glsl_program_key_compare(const void *key, const struct wine_rb_entry
 
 static BOOL constant_heap_init(struct constant_heap *heap, unsigned int constant_count)
 {
-    SIZE_T size = (constant_count + 1) * sizeof(*heap->entries) + constant_count * sizeof(*heap->positions);
+    SIZE_T size = (constant_count + 1) * sizeof(*heap->entries)
+            + constant_count * sizeof(*heap->contained)
+            + constant_count * sizeof(*heap->positions);
     void *mem = HeapAlloc(GetProcessHeap(), 0, size);
 
     if (!mem)
@@ -6048,7 +6496,9 @@ static BOOL constant_heap_init(struct constant_heap *heap, unsigned int constant
 
     heap->entries = mem;
     heap->entries[1].version = 0;
-    heap->positions = (unsigned int *)(heap->entries + constant_count + 1);
+    heap->contained = (BOOL *)(heap->entries + constant_count + 1);
+    memset(heap->contained, 0, constant_count * sizeof(*heap->contained));
+    heap->positions = (unsigned int *)(heap->contained + constant_count);
     heap->size = 1;
 
     return TRUE;
@@ -6067,18 +6517,27 @@ static const struct wine_rb_functions wined3d_glsl_program_rb_functions =
     glsl_program_key_compare,
 };
 
-static HRESULT shader_glsl_alloc(struct wined3d_device *device, const struct fragment_pipeline *fragment_pipe)
+static HRESULT shader_glsl_alloc(struct wined3d_device *device, const struct wined3d_vertex_pipe_ops *vertex_pipe,
+        const struct fragment_pipeline *fragment_pipe)
 {
     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
     struct shader_glsl_priv *priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct shader_glsl_priv));
     SIZE_T stack_size = wined3d_log2i(max(gl_info->limits.glsl_vs_float_constants,
             gl_info->limits.glsl_ps_float_constants)) + 1;
     struct fragment_caps fragment_caps;
-    void *fragment_priv;
+    void *vertex_priv, *fragment_priv;
+
+    if (!(vertex_priv = vertex_pipe->vp_alloc(&glsl_shader_backend, priv)))
+    {
+        ERR("Failed to initialize vertex pipe.\n");
+        HeapFree(GetProcessHeap(), 0, priv);
+        return E_FAIL;
+    }
 
     if (!(fragment_priv = fragment_pipe->alloc_private(&glsl_shader_backend, priv)))
     {
         ERR("Failed to initialize fragment pipe.\n");
+        vertex_pipe->vp_free(device);
         HeapFree(GetProcessHeap(), 0, priv);
         return E_FAIL;
     }
@@ -6115,12 +6574,15 @@ static HRESULT shader_glsl_alloc(struct wined3d_device *device, const struct fra
     }
 
     priv->next_constant_version = 1;
+    priv->vertex_pipe = vertex_pipe;
+    priv->fragment_pipe = fragment_pipe;
     fragment_pipe->get_caps(gl_info, &fragment_caps);
     priv->ffp_proj_control = fragment_caps.wined3d_caps & WINED3D_FRAGMENT_CAP_PROJ_CONTROL;
-    device->fragment_priv = fragment_priv;
-    priv->fragment_pipe = fragment_pipe;
 
+    device->vertex_priv = vertex_priv;
+    device->fragment_priv = fragment_priv;
     device->shader_priv = priv;
+
     return WINED3D_OK;
 
 fail:
@@ -6129,6 +6591,7 @@ fail:
     HeapFree(GetProcessHeap(), 0, priv->stack);
     shader_buffer_free(&priv->shader_buffer);
     fragment_pipe->free_private(device);
+    vertex_pipe->vp_free(device);
     HeapFree(GetProcessHeap(), 0, priv);
     return E_OUTOFMEMORY;
 }
@@ -6158,12 +6621,22 @@ static void shader_glsl_free(struct wined3d_device *device)
     HeapFree(GetProcessHeap(), 0, priv->stack);
     shader_buffer_free(&priv->shader_buffer);
     priv->fragment_pipe->free_private(device);
+    priv->vertex_pipe->vp_free(device);
 
     HeapFree(GetProcessHeap(), 0, device->shader_priv);
     device->shader_priv = NULL;
 }
 
-static void shader_glsl_context_destroyed(void *shader_priv, const struct wined3d_context *context) {}
+static BOOL shader_glsl_allocate_context_data(struct wined3d_context *context)
+{
+    return !!(context->shader_backend_data = HeapAlloc(GetProcessHeap(),
+            HEAP_ZERO_MEMORY, sizeof(struct glsl_context_data)));
+}
+
+static void shader_glsl_free_context_data(struct wined3d_context *context)
+{
+    HeapFree(GetProcessHeap(), 0, context->shader_backend_data);
+}
 
 static void shader_glsl_get_caps(const struct wined3d_gl_info *gl_info, struct shader_caps *caps)
 {
@@ -6371,21 +6844,281 @@ const struct wined3d_shader_backend_ops glsl_shader_backend =
 {
     shader_glsl_handle_instruction,
     shader_glsl_select,
+    shader_glsl_disable,
     shader_glsl_select_depth_blt,
     shader_glsl_deselect_depth_blt,
     shader_glsl_update_float_vertex_constants,
     shader_glsl_update_float_pixel_constants,
     shader_glsl_load_constants,
-    shader_glsl_load_np2fixup_constants,
     shader_glsl_destroy,
     shader_glsl_alloc,
     shader_glsl_free,
-    shader_glsl_context_destroyed,
+    shader_glsl_allocate_context_data,
+    shader_glsl_free_context_data,
     shader_glsl_get_caps,
     shader_glsl_color_fixup_supported,
     shader_glsl_has_ffp_proj_control,
 };
 
+static void glsl_vertex_pipe_vp_enable(const struct wined3d_gl_info *gl_info, BOOL enable)
+{
+    if (enable)
+        gl_info->gl_ops.gl.p_glEnable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB);
+    else
+        gl_info->gl_ops.gl.p_glDisable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB);
+    checkGLcall("GL_VERTEX_PROGRAM_POINT_SIZE_ARB");
+}
+
+static void glsl_vertex_pipe_vp_get_caps(const struct wined3d_gl_info *gl_info, struct wined3d_vertex_caps *caps)
+{
+    caps->xyzrhw = TRUE;
+    caps->max_active_lights = gl_info->limits.lights;
+    caps->max_vertex_blend_matrices = 0;
+    caps->max_vertex_blend_matrix_index = 0;
+    caps->vertex_processing_caps = WINED3DVTXPCAPS_TEXGEN
+            | WINED3DVTXPCAPS_MATERIALSOURCE7
+            | WINED3DVTXPCAPS_VERTEXFOG
+            | WINED3DVTXPCAPS_DIRECTIONALLIGHTS
+            | WINED3DVTXPCAPS_POSITIONALLIGHTS
+            | WINED3DVTXPCAPS_LOCALVIEWER
+            | WINED3DVTXPCAPS_TEXGEN_SPHEREMAP;
+    caps->fvf_caps = WINED3DFVFCAPS_PSIZE | 8; /* 8 texture coordinates. */
+    caps->max_user_clip_planes = gl_info->limits.clipplanes;
+    caps->raster_caps = WINED3DPRASTERCAPS_FOGRANGE;
+}
+
+static void *glsl_vertex_pipe_vp_alloc(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv)
+{
+    struct shader_glsl_priv *priv;
+
+    if (shader_backend == &glsl_shader_backend)
+    {
+        priv = shader_priv;
+
+        if (wine_rb_init(&priv->ffp_vertex_shaders, &wined3d_ffp_vertex_program_rb_functions) == -1)
+        {
+            ERR("Failed to initialize rbtree.\n");
+            return NULL;
+        }
+
+        return priv;
+    }
+
+    FIXME("GLSL vertex pipe without GLSL shader backend not implemented.\n");
+
+    return NULL;
+}
+
+static void shader_glsl_free_ffp_vertex_shader(struct wine_rb_entry *entry, void *context)
+{
+    struct glsl_ffp_vertex_shader *shader = WINE_RB_ENTRY_VALUE(entry,
+            struct glsl_ffp_vertex_shader, desc.entry);
+    struct glsl_shader_prog_link *program, *program2;
+    struct glsl_ffp_destroy_ctx *ctx = context;
+
+    LIST_FOR_EACH_ENTRY_SAFE(program, program2, &shader->linked_programs,
+            struct glsl_shader_prog_link, vs.shader_entry)
+    {
+        delete_glsl_program_entry(ctx->priv, ctx->gl_info, program);
+    }
+    ctx->gl_info->gl_ops.ext.p_glDeleteObjectARB(shader->id);
+    HeapFree(GetProcessHeap(), 0, shader);
+}
+
+/* Context activation is done by the caller. */
+static void glsl_vertex_pipe_vp_free(struct wined3d_device *device)
+{
+    struct shader_glsl_priv *priv = device->vertex_priv;
+    struct glsl_ffp_destroy_ctx ctx;
+
+    ctx.priv = priv;
+    ctx.gl_info = &device->adapter->gl_info;
+    wine_rb_destroy(&priv->ffp_vertex_shaders, shader_glsl_free_ffp_vertex_shader, &ctx);
+}
+
+static void glsl_vertex_pipe_shader(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id)
+{
+    context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_VERTEX;
+}
+
+static void glsl_vertex_pipe_projection(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id)
+{
+    /* Table fog behavior depends on the projection matrix. */
+    if (state->render_states[WINED3D_RS_FOGENABLE]
+            && state->render_states[WINED3D_RS_FOGTABLEMODE] != WINED3D_FOG_NONE)
+        context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_VERTEX;
+    transform_projection(context, state, state_id);
+}
+
+static const struct StateEntryTemplate glsl_vertex_pipe_vp_states[] =
+{
+    {STATE_VDECL,                                                {STATE_VDECL,                                                vertexdeclaration      }, WINED3D_GL_EXT_NONE          },
+    {STATE_VSHADER,                                              {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_MATERIAL,                                             {STATE_RENDER(WINED3D_RS_SPECULARENABLE),                    NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_SPECULARENABLE),                    {STATE_RENDER(WINED3D_RS_SPECULARENABLE),                    state_specularenable   }, WINED3D_GL_EXT_NONE          },
+    /* Clip planes */
+    {STATE_CLIPPLANE(0),                                         {STATE_CLIPPLANE(0),                                         clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(1),                                         {STATE_CLIPPLANE(1),                                         clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(2),                                         {STATE_CLIPPLANE(2),                                         clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(3),                                         {STATE_CLIPPLANE(3),                                         clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(4),                                         {STATE_CLIPPLANE(4),                                         clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(5),                                         {STATE_CLIPPLANE(5),                                         clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(6),                                         {STATE_CLIPPLANE(6),                                         clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(7),                                         {STATE_CLIPPLANE(7),                                         clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(8),                                         {STATE_CLIPPLANE(8),                                         clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(9),                                         {STATE_CLIPPLANE(9),                                         clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(10),                                        {STATE_CLIPPLANE(10),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(11),                                        {STATE_CLIPPLANE(11),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(12),                                        {STATE_CLIPPLANE(12),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(13),                                        {STATE_CLIPPLANE(13),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(14),                                        {STATE_CLIPPLANE(14),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(15),                                        {STATE_CLIPPLANE(15),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(16),                                        {STATE_CLIPPLANE(16),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(17),                                        {STATE_CLIPPLANE(17),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(18),                                        {STATE_CLIPPLANE(18),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(19),                                        {STATE_CLIPPLANE(19),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(20),                                        {STATE_CLIPPLANE(20),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(21),                                        {STATE_CLIPPLANE(21),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(22),                                        {STATE_CLIPPLANE(22),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(23),                                        {STATE_CLIPPLANE(23),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(24),                                        {STATE_CLIPPLANE(24),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(25),                                        {STATE_CLIPPLANE(25),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(26),                                        {STATE_CLIPPLANE(26),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(27),                                        {STATE_CLIPPLANE(27),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(28),                                        {STATE_CLIPPLANE(28),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(29),                                        {STATE_CLIPPLANE(29),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(30),                                        {STATE_CLIPPLANE(30),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    {STATE_CLIPPLANE(31),                                        {STATE_CLIPPLANE(31),                                        clipplane              }, WINED3D_GL_EXT_NONE          },
+    /* Lights */
+    {STATE_LIGHT_TYPE,                                           {STATE_RENDER(WINED3D_RS_FOGENABLE),                         NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_ACTIVELIGHT(0),                                       {STATE_ACTIVELIGHT(0),                                       light                  }, WINED3D_GL_EXT_NONE          },
+    {STATE_ACTIVELIGHT(1),                                       {STATE_ACTIVELIGHT(1),                                       light                  }, WINED3D_GL_EXT_NONE          },
+    {STATE_ACTIVELIGHT(2),                                       {STATE_ACTIVELIGHT(2),                                       light                  }, WINED3D_GL_EXT_NONE          },
+    {STATE_ACTIVELIGHT(3),                                       {STATE_ACTIVELIGHT(3),                                       light                  }, WINED3D_GL_EXT_NONE          },
+    {STATE_ACTIVELIGHT(4),                                       {STATE_ACTIVELIGHT(4),                                       light                  }, WINED3D_GL_EXT_NONE          },
+    {STATE_ACTIVELIGHT(5),                                       {STATE_ACTIVELIGHT(5),                                       light                  }, WINED3D_GL_EXT_NONE          },
+    {STATE_ACTIVELIGHT(6),                                       {STATE_ACTIVELIGHT(6),                                       light                  }, WINED3D_GL_EXT_NONE          },
+    {STATE_ACTIVELIGHT(7),                                       {STATE_ACTIVELIGHT(7),                                       light                  }, WINED3D_GL_EXT_NONE          },
+    /* Viewport */
+    {STATE_VIEWPORT,                                             {STATE_VIEWPORT,                                             viewport_vertexpart    }, WINED3D_GL_EXT_NONE          },
+    /* Transform states */
+    {STATE_TRANSFORM(WINED3D_TS_VIEW),                           {STATE_TRANSFORM(WINED3D_TS_VIEW),                           transform_view         }, WINED3D_GL_EXT_NONE          },
+    {STATE_TRANSFORM(WINED3D_TS_PROJECTION),                     {STATE_TRANSFORM(WINED3D_TS_PROJECTION),                     glsl_vertex_pipe_projection}, WINED3D_GL_EXT_NONE      },
+    {STATE_TRANSFORM(WINED3D_TS_TEXTURE0),                       {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_TRANSFORM(WINED3D_TS_TEXTURE1),                       {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_TRANSFORM(WINED3D_TS_TEXTURE2),                       {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_TRANSFORM(WINED3D_TS_TEXTURE3),                       {STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_TRANSFORM(WINED3D_TS_TEXTURE4),                       {STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_TRANSFORM(WINED3D_TS_TEXTURE5),                       {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_TRANSFORM(WINED3D_TS_TEXTURE6),                       {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_TRANSFORM(WINED3D_TS_TEXTURE7),                       {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)),                {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)),                transform_world        }, WINED3D_GL_EXT_NONE          },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture      }, WINED3D_GL_EXT_NONE          },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture      }, WINED3D_GL_EXT_NONE          },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture      }, WINED3D_GL_EXT_NONE          },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture      }, WINED3D_GL_EXT_NONE          },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture      }, WINED3D_GL_EXT_NONE          },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture      }, WINED3D_GL_EXT_NONE          },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture      }, WINED3D_GL_EXT_NONE          },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture      }, WINED3D_GL_EXT_NONE          },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXCOORD_INDEX),          {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXCOORD_INDEX),          {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXCOORD_INDEX),          {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXCOORD_INDEX),          {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXCOORD_INDEX),          {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXCOORD_INDEX),          {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXCOORD_INDEX),          {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXCOORD_INDEX),          {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    /* Fog */
+    {STATE_RENDER(WINED3D_RS_FOGENABLE),                         {STATE_RENDER(WINED3D_RS_FOGENABLE),                         glsl_vertex_pipe_shader}, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_FOGTABLEMODE),                      {STATE_RENDER(WINED3D_RS_FOGENABLE),                         NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_FOGVERTEXMODE),                     {STATE_RENDER(WINED3D_RS_FOGENABLE),                         NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_RANGEFOGENABLE),                    {STATE_RENDER(WINED3D_RS_FOGENABLE),                         NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_CLIPPING),                          {STATE_RENDER(WINED3D_RS_CLIPPING),                          state_clipping         }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_CLIPPLANEENABLE),                   {STATE_RENDER(WINED3D_RS_CLIPPING),                          NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_LIGHTING),                          {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_AMBIENT),                           {STATE_RENDER(WINED3D_RS_AMBIENT),                           state_ambient          }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_COLORVERTEX),                       {STATE_RENDER(WINED3D_RS_COLORVERTEX),                       glsl_vertex_pipe_shader}, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_LOCALVIEWER),                       {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_NORMALIZENORMALS),                  {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_DIFFUSEMATERIALSOURCE),             {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_SPECULARMATERIALSOURCE),            {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_AMBIENTMATERIALSOURCE),             {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_EMISSIVEMATERIALSOURCE),            {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_VERTEXBLEND),                       {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_POINTSIZE),                         {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE),                  NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),                     {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),                     state_psizemin_arb     }, ARB_POINT_PARAMETERS         },
+    {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),                     {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),                     state_psizemin_ext     }, EXT_POINT_PARAMETERS         },
+    {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),                     {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),                     state_psizemin_w       }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE),                 {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE),                 state_pointsprite      }, ARB_POINT_SPRITE             },
+    {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE),                 {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE),                 state_pointsprite_w    }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE),                  {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE),                  state_pscale           }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_POINTSCALE_A),                      {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE),                  NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_POINTSCALE_B),                      {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE),                  NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_POINTSCALE_C),                      {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE),                  NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_POINTSIZE_MAX),                     {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),                     NULL                   }, ARB_POINT_PARAMETERS         },
+    {STATE_RENDER(WINED3D_RS_POINTSIZE_MAX),                     {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),                     NULL                   }, EXT_POINT_PARAMETERS         },
+    {STATE_RENDER(WINED3D_RS_POINTSIZE_MAX),                     {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),                     NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_TWEENFACTOR),                       {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    {STATE_RENDER(WINED3D_RS_INDEXEDVERTEXBLENDENABLE),          {STATE_VDECL,                                                NULL                   }, WINED3D_GL_EXT_NONE          },
+    /* Samplers for NP2 texture matrix adjustions. They are not needed if
+     * GL_ARB_texture_non_power_of_two is supported, so register a NULL state
+     * handler in that case to get the vertex part of sampler() skipped (VTF
+     * is handled in the misc states). Otherwise, register
+     * sampler_texmatrix(), which takes care of updating the texture matrix. */
+    {STATE_SAMPLER(0),                                           {0,                                                          NULL                   }, ARB_TEXTURE_NON_POWER_OF_TWO },
+    {STATE_SAMPLER(0),                                           {0,                                                          NULL                   }, WINED3D_GL_NORMALIZED_TEXRECT},
+    {STATE_SAMPLER(0),                                           {STATE_SAMPLER(0),                                           sampler_texmatrix      }, WINED3D_GL_EXT_NONE          },
+    {STATE_SAMPLER(1),                                           {0,                                                          NULL                   }, ARB_TEXTURE_NON_POWER_OF_TWO },
+    {STATE_SAMPLER(1),                                           {0,                                                          NULL                   }, WINED3D_GL_NORMALIZED_TEXRECT},
+    {STATE_SAMPLER(1),                                           {STATE_SAMPLER(1),                                           sampler_texmatrix      }, WINED3D_GL_EXT_NONE          },
+    {STATE_SAMPLER(2),                                           {0,                                                          NULL                   }, ARB_TEXTURE_NON_POWER_OF_TWO },
+    {STATE_SAMPLER(2),                                           {0,                                                          NULL                   }, WINED3D_GL_NORMALIZED_TEXRECT},
+    {STATE_SAMPLER(2),                                           {STATE_SAMPLER(2),                                           sampler_texmatrix      }, WINED3D_GL_EXT_NONE          },
+    {STATE_SAMPLER(3),                                           {0,                                                          NULL                   }, ARB_TEXTURE_NON_POWER_OF_TWO },
+    {STATE_SAMPLER(3),                                           {0,                                                          NULL                   }, WINED3D_GL_NORMALIZED_TEXRECT},
+    {STATE_SAMPLER(3),                                           {STATE_SAMPLER(3),                                           sampler_texmatrix      }, WINED3D_GL_EXT_NONE          },
+    {STATE_SAMPLER(4),                                           {0,                                                          NULL                   }, ARB_TEXTURE_NON_POWER_OF_TWO },
+    {STATE_SAMPLER(4),                                           {0,                                                          NULL                   }, WINED3D_GL_NORMALIZED_TEXRECT},
+    {STATE_SAMPLER(4),                                           {STATE_SAMPLER(4),                                           sampler_texmatrix      }, WINED3D_GL_EXT_NONE          },
+    {STATE_SAMPLER(5),                                           {0,                                                          NULL                   }, ARB_TEXTURE_NON_POWER_OF_TWO },
+    {STATE_SAMPLER(5),                                           {0,                                                          NULL                   }, WINED3D_GL_NORMALIZED_TEXRECT},
+    {STATE_SAMPLER(5),                                           {STATE_SAMPLER(5),                                           sampler_texmatrix      }, WINED3D_GL_EXT_NONE          },
+    {STATE_SAMPLER(6),                                           {0,                                                          NULL                   }, ARB_TEXTURE_NON_POWER_OF_TWO },
+    {STATE_SAMPLER(6),                                           {0,                                                          NULL                   }, WINED3D_GL_NORMALIZED_TEXRECT},
+    {STATE_SAMPLER(6),                                           {STATE_SAMPLER(6),                                           sampler_texmatrix      }, WINED3D_GL_EXT_NONE          },
+    {STATE_SAMPLER(7),                                           {0,                                                          NULL                   }, ARB_TEXTURE_NON_POWER_OF_TWO },
+    {STATE_SAMPLER(7),                                           {0,                                                          NULL                   }, WINED3D_GL_NORMALIZED_TEXRECT},
+    {STATE_SAMPLER(7),                                           {STATE_SAMPLER(7),                                           sampler_texmatrix      }, WINED3D_GL_EXT_NONE          },
+    {STATE_POINT_SIZE_ENABLE,                                    {STATE_RENDER(WINED3D_RS_FOGENABLE),                         NULL                   }, WINED3D_GL_EXT_NONE          },
+    {0 /* Terminate */,                                          {0,                                                          NULL                   }, WINED3D_GL_EXT_NONE          },
+};
+
+/* TODO:
+ *   - This currently depends on GL fixed function functions to set things
+ *     like light parameters. Ideally we'd use regular uniforms for that.
+ *   - In part because of the previous point, much of this is modelled after
+ *     GL fixed function, and has much of the same limitations. For example,
+ *     D3D spot lights are slightly different from GL spot lights.
+ *   - We can now implement drawing transformed vertices using the GLSL pipe,
+ *     instead of using the immediate mode fallback.
+ *   - Similarly, we don't need the fallback for certain combinations of
+ *     material sources anymore.
+ *   - Implement vertex blending and vertex tweening.
+ *   - Handle WINED3D_TSS_TEXCOORD_INDEX in the shader, instead of duplicating
+ *     attribute arrays in load_tex_coords().
+ *   - Per-vertex point sizes. */
+const struct wined3d_vertex_pipe_ops glsl_vertex_pipe =
+{
+    glsl_vertex_pipe_vp_enable,
+    glsl_vertex_pipe_vp_get_caps,
+    glsl_vertex_pipe_vp_alloc,
+    glsl_vertex_pipe_vp_free,
+    glsl_vertex_pipe_vp_states,
+};
+
 static void glsl_fragment_pipe_enable(const struct wined3d_gl_info *gl_info, BOOL enable)
 {
     /* Nothing to do. */
@@ -6447,12 +7180,6 @@ static void *glsl_fragment_pipe_alloc(const struct wined3d_shader_backend_ops *s
     return NULL;
 }
 
-struct glsl_ffp_destroy_ctx
-{
-    struct shader_glsl_priv *priv;
-    const struct wined3d_gl_info *gl_info;
-};
-
 static void shader_glsl_free_ffp_fragment_shader(struct wine_rb_entry *entry, void *context)
 {
     struct glsl_ffp_fragment_shader *shader = WINE_RB_ENTRY_VALUE(entry,
@@ -6485,8 +7212,7 @@ static void glsl_fragment_pipe_shader(struct wined3d_context *context,
 {
     context->last_was_pshader = use_ps(state);
 
-    context->select_shader = 1;
-    context->load_constants = 1;
+    context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_PIXEL;
 }
 
 static void glsl_fragment_pipe_fog(struct wined3d_context *context,
@@ -6494,9 +7220,10 @@ static void glsl_fragment_pipe_fog(struct wined3d_context *context,
 {
     BOOL use_vshader = use_vs(state);
     enum fogsource new_source;
+    DWORD fogstart = state->render_states[WINED3D_RS_FOGSTART];
+    DWORD fogend = state->render_states[WINED3D_RS_FOGEND];
 
-    context->select_shader = 1;
-    context->load_constants = 1;
+    context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_PIXEL;
 
     if (!state->render_states[WINED3D_RS_FOGENABLE])
         return;
@@ -6515,7 +7242,7 @@ static void glsl_fragment_pipe_fog(struct wined3d_context *context,
         new_source = FOGSOURCE_FFP;
     }
 
-    if (new_source != context->fog_source)
+    if (new_source != context->fog_source || fogstart == fogend)
     {
         context->fog_source = new_source;
         state_fogstartend(context, state, STATE_RENDER(WINED3D_RS_FOGSTART));
@@ -6525,14 +7252,13 @@ static void glsl_fragment_pipe_fog(struct wined3d_context *context,
 static void glsl_fragment_pipe_tex_transform(struct wined3d_context *context,
         const struct wined3d_state *state, DWORD state_id)
 {
-    context->select_shader = 1;
-    context->load_constants = 1;
+    context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_PIXEL;
 }
 
 static void glsl_fragment_pipe_invalidate_constants(struct wined3d_context *context,
         const struct wined3d_state *state, DWORD state_id)
 {
-    context->load_constants = 1;
+    context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_PS;
 }
 
 static const struct StateEntryTemplate glsl_fragment_pipe_state_template[] =
@@ -6547,12 +7273,6 @@ static const struct StateEntryTemplate glsl_fragment_pipe_state_template[] =
     {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG2),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG0),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(0, WINED3D_TSS_RESULT_ARG),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),          {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),           glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT01),          {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT10),          {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT11),          {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE),         {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE),          glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LOFFSET),        {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE),          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_OP),               {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG1),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG2),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
@@ -6562,12 +7282,6 @@ static const struct StateEntryTemplate glsl_fragment_pipe_state_template[] =
     {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG2),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG0),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(1, WINED3D_TSS_RESULT_ARG),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),          {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),           glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT01),          {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT10),          {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT11),          {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE),         {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE),          glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LOFFSET),        {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE),          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_OP),               {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG1),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG2),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
@@ -6577,12 +7291,6 @@ static const struct StateEntryTemplate glsl_fragment_pipe_state_template[] =
     {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG2),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG0),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(2, WINED3D_TSS_RESULT_ARG),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),          {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),           glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT01),          {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT10),          {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT11),          {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE),         {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE),          glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LOFFSET),        {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE),          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_OP),               {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG1),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG2),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
@@ -6592,12 +7300,6 @@ static const struct StateEntryTemplate glsl_fragment_pipe_state_template[] =
     {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG2),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG0),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(3, WINED3D_TSS_RESULT_ARG),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),          {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),           glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT01),          {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT10),          {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT11),          {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE),         {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE),          glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LOFFSET),        {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE),          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_OP),               {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG1),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG2),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
@@ -6607,12 +7309,6 @@ static const struct StateEntryTemplate glsl_fragment_pipe_state_template[] =
     {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG2),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG0),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(4, WINED3D_TSS_RESULT_ARG),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),          {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),           glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT01),          {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT10),          {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT11),          {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE),         {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE),          glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LOFFSET),        {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE),          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_OP),               {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG1),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG2),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
@@ -6622,12 +7318,6 @@ static const struct StateEntryTemplate glsl_fragment_pipe_state_template[] =
     {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG2),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG0),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(5, WINED3D_TSS_RESULT_ARG),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),          {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),           glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT01),          {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT10),          {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT11),          {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE),         {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE),          glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LOFFSET),        {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE),          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_OP),               {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG1),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG2),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
@@ -6637,12 +7327,6 @@ static const struct StateEntryTemplate glsl_fragment_pipe_state_template[] =
     {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG2),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG0),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(6, WINED3D_TSS_RESULT_ARG),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),          {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),           glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT01),          {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT10),          {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT11),          {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE),         {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE),          glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LOFFSET),        {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE),          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_OP),               {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG1),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG2),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
@@ -6652,12 +7336,6 @@ static const struct StateEntryTemplate glsl_fragment_pipe_state_template[] =
     {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG2),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG0),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_TEXTURESTAGE(7, WINED3D_TSS_RESULT_ARG),             {STATE_PIXELSHADER,                                          NULL                                   }, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),          {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),           glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT01),          {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT10),          {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT11),          {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),           NULL                                   }, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE),         {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE),          glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
-    {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LOFFSET),        {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE),          NULL                                   }, WINED3D_GL_EXT_NONE },
     {STATE_PIXELSHADER,                                         {STATE_PIXELSHADER,                                          glsl_fragment_pipe_shader              }, WINED3D_GL_EXT_NONE },
     {STATE_RENDER(WINED3D_RS_FOGENABLE),                        {STATE_RENDER(WINED3D_RS_FOGENABLE),                         glsl_fragment_pipe_fog                 }, WINED3D_GL_EXT_NONE },
     {STATE_RENDER(WINED3D_RS_FOGTABLEMODE),                     {STATE_RENDER(WINED3D_RS_FOGENABLE),                         NULL                                   }, WINED3D_GL_EXT_NONE },
index 7059ca5..ff8e8b4 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright 2004 Christian Costa
  * Copyright 2005 Oliver Stieber
  * Copyright 2009-2010 Henri Verbeet for CodeWeavers
+ * Copyright 2006-2008, 2013 Stefan Dösinger for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -52,12 +53,10 @@ static DWORD resource_access_from_pool(enum wined3d_pool pool)
         case WINED3D_POOL_MANAGED:
             return WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_CPU;
 
+        case WINED3D_POOL_SCRATCH:
         case WINED3D_POOL_SYSTEM_MEM:
             return WINED3D_RESOURCE_ACCESS_CPU;
 
-        case WINED3D_POOL_SCRATCH:
-            return WINED3D_RESOURCE_ACCESS_SCRATCH;
-
         default:
             FIXME("Unhandled pool %#x.\n", pool);
             return 0;
@@ -84,6 +83,8 @@ HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device *
         void *parent, const struct wined3d_parent_ops *parent_ops,
         const struct wined3d_resource_ops *resource_ops)
 {
+    const struct wined3d *d3d = device->wined3d;
+
     resource->ref = 1;
     resource->device = device;
     resource->type = type;
@@ -109,8 +110,8 @@ HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device *
 
     if (size)
     {
-        resource->heapMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size + RESOURCE_ALIGNMENT);
-        if (!resource->heapMemory)
+        resource->heap_memory = wined3d_resource_allocate_sysmem(size);
+        if (!resource->heap_memory)
         {
             ERR("Out of memory!\n");
             return WINED3DERR_OUTOFVIDEOMEMORY;
@@ -118,18 +119,17 @@ HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device *
     }
     else
     {
-        resource->heapMemory = NULL;
+        resource->heap_memory = NULL;
     }
-    resource->allocatedMemory = (BYTE *)(((ULONG_PTR)resource->heapMemory
-            + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1));
+    resource->allocatedMemory = resource->heap_memory;
 
     /* Check that we have enough video ram left */
-    if (pool == WINED3D_POOL_DEFAULT)
+    if (pool == WINED3D_POOL_DEFAULT && d3d->flags & WINED3D_VIDMEM_ACCOUNTING)
     {
         if (size > wined3d_device_get_available_texture_mem(device))
         {
             ERR("Out of adapter memory\n");
-            HeapFree(GetProcessHeap(), 0, resource->heapMemory);
+            wined3d_resource_free_sysmem(resource->heap_memory);
             return WINED3DERR_OUTOFVIDEOMEMORY;
         }
         adapter_adjust_memory(device->adapter, size);
@@ -142,13 +142,14 @@ HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device *
 
 void resource_cleanup(struct wined3d_resource *resource)
 {
+    const struct wined3d *d3d = resource->device->wined3d;
     struct private_data *data;
     struct list *e1, *e2;
     HRESULT hr;
 
     TRACE("Cleaning up resource %p.\n", resource);
 
-    if (resource->pool == WINED3D_POOL_DEFAULT)
+    if (resource->pool == WINED3D_POOL_DEFAULT && d3d->flags & WINED3D_VIDMEM_ACCOUNTING)
     {
         TRACE("Decrementing device memory pool by %u.\n", resource->size);
         adapter_adjust_memory(resource->device->adapter, 0 - resource->size);
@@ -162,12 +163,11 @@ void resource_cleanup(struct wined3d_resource *resource)
             ERR("Failed to free private data when destroying resource %p, hr = %#x.\n", resource, hr);
     }
 
-    HeapFree(GetProcessHeap(), 0, resource->heapMemory);
-    resource->allocatedMemory = 0;
-    resource->heapMemory = 0;
+    wined3d_resource_free_sysmem(resource->heap_memory);
+    resource->allocatedMemory = NULL;
+    resource->heap_memory = NULL;
 
-    if (resource->device)
-        device_resource_released(resource->device, resource);
+    device_resource_released(resource->device, resource);
 }
 
 void resource_unload(struct wined3d_resource *resource)
@@ -333,3 +333,78 @@ void CDECL wined3d_resource_get_desc(const struct wined3d_resource *resource, st
     desc->depth = resource->depth;
     desc->size = resource->size;
 }
+
+void *wined3d_resource_allocate_sysmem(SIZE_T size)
+{
+    void **p;
+    SIZE_T align = RESOURCE_ALIGNMENT - 1 + sizeof(*p);
+    void *mem;
+
+    if (!(mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size + align)))
+        return NULL;
+
+    p = (void **)(((ULONG_PTR)mem + align) & ~(RESOURCE_ALIGNMENT - 1)) - 1;
+    *p = mem;
+
+    return ++p;
+}
+
+void wined3d_resource_free_sysmem(void *mem)
+{
+    void **p = mem;
+
+    if (!mem)
+        return;
+
+    HeapFree(GetProcessHeap(), 0, *(--p));
+}
+
+DWORD wined3d_resource_sanitize_map_flags(const struct wined3d_resource *resource, DWORD flags)
+{
+    /* Not all flags make sense together, but Windows never returns an error.
+     * Catch the cases that could cause issues. */
+    if (flags & WINED3D_MAP_READONLY)
+    {
+        if (flags & WINED3D_MAP_DISCARD)
+        {
+            WARN("WINED3D_MAP_READONLY combined with WINED3D_MAP_DISCARD, ignoring flags.\n");
+            return 0;
+        }
+        if (flags & WINED3D_MAP_NOOVERWRITE)
+        {
+            WARN("WINED3D_MAP_READONLY combined with WINED3D_MAP_NOOVERWRITE, ignoring flags.\n");
+            return 0;
+        }
+    }
+    else if ((flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE))
+            == (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE))
+    {
+        WARN("WINED3D_MAP_DISCARD and WINED3D_MAP_NOOVERWRITE used together, ignoring.\n");
+        return 0;
+    }
+    else if (flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE)
+            && !(resource->usage & WINED3DUSAGE_DYNAMIC))
+    {
+        WARN("DISCARD or NOOVERWRITE map on non-dynamic buffer, ignoring.\n");
+        return 0;
+    }
+
+    return flags;
+}
+
+GLbitfield wined3d_resource_gl_map_flags(DWORD d3d_flags)
+{
+    GLbitfield ret = 0;
+
+    if (!(d3d_flags & WINED3D_MAP_READONLY))
+        ret |= GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT;
+    if (!(d3d_flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE)))
+        ret |= GL_MAP_READ_BIT;
+
+    if (d3d_flags & WINED3D_MAP_DISCARD)
+        ret |= GL_MAP_INVALIDATE_BUFFER_BIT;
+    if (d3d_flags & WINED3D_MAP_NOOVERWRITE)
+        ret |= GL_MAP_UNSYNCHRONIZED_BIT;
+
+    return ret;
+}
index 38a74bb..43a9bbe 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright 2004 Christian Costa
  * Copyright 2005 Oliver Stieber
  * Copyright 2006 Ivan Gyurdiev
- * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
+ * Copyright 2007-2008, 2013 Stefan Dösinger for CodeWeavers
  * Copyright 2009-2011 Henri Verbeet for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
@@ -238,15 +238,15 @@ static const struct wined3d_shader_frontend *shader_select_frontend(DWORD versio
 void shader_buffer_clear(struct wined3d_shader_buffer *buffer)
 {
     buffer->buffer[0] = '\0';
-    buffer->bsize = 0;
+    buffer->content_size = 0;
     buffer->lineNo = 0;
     buffer->newline = TRUE;
 }
 
 BOOL shader_buffer_init(struct wined3d_shader_buffer *buffer)
 {
-    buffer->buffer = HeapAlloc(GetProcessHeap(), 0, SHADER_PGMSIZE);
-    if (!buffer->buffer)
+    buffer->buffer_size = 16384;
+    if (!(buffer->buffer = HeapAlloc(GetProcessHeap(), 0, buffer->buffer_size)))
     {
         ERR("Failed to allocate shader buffer memory.\n");
         return FALSE;
@@ -263,22 +263,35 @@ void shader_buffer_free(struct wined3d_shader_buffer *buffer)
 
 int shader_vaddline(struct wined3d_shader_buffer *buffer, const char *format, va_list args)
 {
-    char *base = buffer->buffer + buffer->bsize;
+    char *base = buffer->buffer + buffer->content_size;
     int rc;
+    char *new_buffer;
 
-    rc = vsnprintf(base, SHADER_PGMSIZE - 1 - buffer->bsize, format, args);
-
-    if (rc < 0 /* C89 */ || (unsigned int)rc > SHADER_PGMSIZE - 1 - buffer->bsize /* C99 */)
+    while(1)
     {
-        ERR("The buffer allocated for the shader program string "
-            "is too small at %d bytes.\n", SHADER_PGMSIZE);
-        buffer->bsize = SHADER_PGMSIZE - 1;
-        return -1;
+        rc = vsnprintf(base, buffer->buffer_size - buffer->content_size, format, args);
+        if (rc < 0 /* C89 */ || (unsigned int)rc >= buffer->buffer_size - buffer->content_size /* C99 */)
+        {
+            new_buffer = HeapReAlloc(GetProcessHeap(), 0, buffer->buffer, buffer->buffer_size * 2);
+            if (!new_buffer)
+            {
+                ERR("The buffer allocated for the shader program string is too small at %d bytes.\n", buffer->buffer_size);
+                buffer->content_size = buffer->buffer_size - 1;
+                return -1;
+            }
+            buffer->buffer = new_buffer;
+            buffer->buffer_size = buffer->buffer_size * 2;
+            base = buffer->buffer + buffer->content_size;
+        }
+        else
+        {
+            break;
+        }
     }
 
     if (buffer->newline)
     {
-        TRACE("GL HW (%u, %u) : %s", buffer->lineNo + 1, buffer->bsize, base);
+        TRACE("GL HW (%u, %u) : %s", buffer->lineNo + 1, buffer->content_size, base);
         buffer->newline = FALSE;
     }
     else
@@ -286,8 +299,8 @@ int shader_vaddline(struct wined3d_shader_buffer *buffer, const char *format, va
         TRACE("%s", base);
     }
 
-    buffer->bsize += rc;
-    if (buffer->buffer[buffer->bsize-1] == '\n')
+    buffer->content_size += rc;
+    if (buffer->buffer[buffer->content_size-1] == '\n')
     {
         ++buffer->lineNo;
         buffer->newline = TRUE;
@@ -570,15 +583,16 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
         else if (ins.handler_idx == WINED3DSIH_DEF)
         {
             struct wined3d_shader_lconst *lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(*lconst));
+            float *value;
             if (!lconst) return E_OUTOFMEMORY;
 
             lconst->idx = ins.dst[0].reg.idx[0].offset;
             memcpy(lconst->value, ins.src[0].reg.immconst_data, 4 * sizeof(DWORD));
+            value = (float *)lconst->value;
 
             /* In pixel shader 1.X shaders, the constants are clamped between [-1;1] */
             if (shader_version.major == 1 && shader_version.type == WINED3D_SHADER_TYPE_PIXEL)
             {
-                float *value = (float *)lconst->value;
                 if (value[0] < -1.0f) value[0] = -1.0f;
                 else if (value[0] > 1.0f) value[0] = 1.0f;
                 if (value[1] < -1.0f) value[1] = -1.0f;
@@ -590,6 +604,12 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
             }
 
             list_add_head(&shader->constantsF, &lconst->entry);
+
+            if (isinf(value[0]) || isnan(value[0]) || isinf(value[1]) || isnan(value[1])
+                    || isinf(value[2]) || isnan(value[2]) || isinf(value[3]) || isnan(value[3]))
+            {
+                shader->lconst_inf_or_nan = TRUE;
+            }
         }
         else if (ins.handler_idx == WINED3DSIH_DEFI)
         {
@@ -1477,6 +1497,7 @@ static void shader_cleanup(struct wined3d_shader *shader)
 
 struct shader_none_priv
 {
+    const struct wined3d_vertex_pipe_ops *vertex_pipe;
     const struct fragment_pipeline *fragment_pipe;
     BOOL ffp_proj_control;
 };
@@ -1487,42 +1508,68 @@ static void shader_none_select_depth_blt(void *shader_priv, const struct wined3d
 static void shader_none_deselect_depth_blt(void *shader_priv, const struct wined3d_gl_info *gl_info) {}
 static void shader_none_update_float_vertex_constants(struct wined3d_device *device, UINT start, UINT count) {}
 static void shader_none_update_float_pixel_constants(struct wined3d_device *device, UINT start, UINT count) {}
-static void shader_none_load_constants(const struct wined3d_context *context, BOOL usePS, BOOL useVS) {}
-static void shader_none_load_np2fixup_constants(void *shader_priv,
-        const struct wined3d_gl_info *gl_info, const struct wined3d_state *state) {}
+static void shader_none_load_constants(void *shader_priv, struct wined3d_context *context,
+        const struct wined3d_state *state) {}
 static void shader_none_destroy(struct wined3d_shader *shader) {}
-static void shader_none_context_destroyed(void *shader_priv, const struct wined3d_context *context) {}
+static void shader_none_free_context_data(struct wined3d_context *context) {}
 
-static void shader_none_select(const struct wined3d_context *context, enum wined3d_shader_mode vertex_mode,
-        enum wined3d_shader_mode fragment_mode)
+/* Context activation is done by the caller. */
+static void shader_none_select(void *shader_priv, struct wined3d_context *context,
+        const struct wined3d_state *state)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
-    struct wined3d_device *device = context->swapchain->device;
-    struct shader_none_priv *priv = device->shader_priv;
+    struct shader_none_priv *priv = shader_priv;
 
-    priv->fragment_pipe->enable_extension(gl_info, fragment_mode == WINED3D_SHADER_MODE_FFP);
+    priv->vertex_pipe->vp_enable(gl_info, !use_vs(state));
+    priv->fragment_pipe->enable_extension(gl_info, !use_ps(state));
 }
 
-static HRESULT shader_none_alloc(struct wined3d_device *device, const struct fragment_pipeline *fragment_pipe)
+/* Context activation is done by the caller. */
+static void shader_none_disable(void *shader_priv, struct wined3d_context *context)
+{
+    struct shader_none_priv *priv = shader_priv;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    priv->vertex_pipe->vp_enable(gl_info, FALSE);
+    priv->fragment_pipe->enable_extension(gl_info, FALSE);
+
+    context->shader_update_mask = (1 << WINED3D_SHADER_TYPE_PIXEL)
+            | (1 << WINED3D_SHADER_TYPE_VERTEX)
+            | (1 << WINED3D_SHADER_TYPE_GEOMETRY);
+}
+
+static HRESULT shader_none_alloc(struct wined3d_device *device, const struct wined3d_vertex_pipe_ops *vertex_pipe,
+        const struct fragment_pipeline *fragment_pipe)
 {
     struct fragment_caps fragment_caps;
+    void *vertex_priv, *fragment_priv;
     struct shader_none_priv *priv;
-    void *fragment_priv;
 
     if (!(priv = HeapAlloc(GetProcessHeap(), 0, sizeof(*priv))))
         return E_OUTOFMEMORY;
 
+    if (!(vertex_priv = vertex_pipe->vp_alloc(&none_shader_backend, priv)))
+    {
+        ERR("Failed to initialize vertex pipe.\n");
+        HeapFree(GetProcessHeap(), 0, priv);
+        return E_FAIL;
+    }
+
     if (!(fragment_priv = fragment_pipe->alloc_private(&none_shader_backend, priv)))
     {
         ERR("Failed to initialize fragment pipe.\n");
+        vertex_pipe->vp_free(device);
         HeapFree(GetProcessHeap(), 0, priv);
         return E_FAIL;
     }
 
+    priv->vertex_pipe = vertex_pipe;
+    priv->fragment_pipe = fragment_pipe;
     fragment_pipe->get_caps(&device->adapter->gl_info, &fragment_caps);
     priv->ffp_proj_control = fragment_caps.wined3d_caps & WINED3D_FRAGMENT_CAP_PROJ_CONTROL;
+
+    device->vertex_priv = vertex_priv;
     device->fragment_priv = fragment_priv;
-    priv->fragment_pipe = fragment_pipe;
     device->shader_priv = priv;
 
     return WINED3D_OK;
@@ -1533,9 +1580,15 @@ static void shader_none_free(struct wined3d_device *device)
     struct shader_none_priv *priv = device->shader_priv;
 
     priv->fragment_pipe->free_private(device);
+    priv->vertex_pipe->vp_free(device);
     HeapFree(GetProcessHeap(), 0, priv);
 }
 
+static BOOL shader_none_allocate_context_data(struct wined3d_context *context)
+{
+    return TRUE;
+}
+
 static void shader_none_get_caps(const struct wined3d_gl_info *gl_info, struct shader_caps *caps)
 {
     /* Set the shader caps to 0 for the none shader backend */
@@ -1566,16 +1619,17 @@ const struct wined3d_shader_backend_ops none_shader_backend =
 {
     shader_none_handle_instruction,
     shader_none_select,
+    shader_none_disable,
     shader_none_select_depth_blt,
     shader_none_deselect_depth_blt,
     shader_none_update_float_vertex_constants,
     shader_none_update_float_pixel_constants,
     shader_none_load_constants,
-    shader_none_load_np2fixup_constants,
     shader_none_destroy,
     shader_none_alloc,
     shader_none_free,
-    shader_none_context_destroyed,
+    shader_none_allocate_context_data,
+    shader_none_free_context_data,
     shader_none_get_caps,
     shader_none_color_fixup_supported,
     shader_none_has_ffp_proj_control,
@@ -1589,6 +1643,7 @@ static HRESULT shader_set_function(struct wined3d_shader *shader, const DWORD *b
     const struct wined3d_shader_frontend *fe;
     HRESULT hr;
     unsigned int backend_version;
+    const struct wined3d_d3d_info *d3d_info = &shader->device->adapter->d3d_info;
 
     TRACE("shader %p, byte_code %p, output_signature %p, float_const_count %u.\n",
             shader, byte_code, output_signature, float_const_count);
@@ -1615,6 +1670,7 @@ static HRESULT shader_set_function(struct wined3d_shader *shader, const DWORD *b
     list_init(&shader->constantsF);
     list_init(&shader->constantsB);
     list_init(&shader->constantsI);
+    shader->lconst_inf_or_nan = FALSE;
 
     /* Second pass: figure out which registers are used, what the semantics are, etc. */
     hr = shader_get_registers_used(shader, fe,
@@ -1635,13 +1691,13 @@ static HRESULT shader_set_function(struct wined3d_shader *shader, const DWORD *b
     switch (type)
     {
         case WINED3D_SHADER_TYPE_VERTEX:
-            backend_version = shader->device->vs_version;
+            backend_version = d3d_info->limits.vs_version;
             break;
         case WINED3D_SHADER_TYPE_GEOMETRY:
-            backend_version = shader->device->gs_version;
+            backend_version = d3d_info->limits.gs_version;
             break;
         case WINED3D_SHADER_TYPE_PIXEL:
-            backend_version = shader->device->ps_version;
+            backend_version = d3d_info->limits.ps_version;
             break;
         default:
             FIXME("No backend version-checking for this shader type\n");
@@ -1738,12 +1794,20 @@ HRESULT CDECL wined3d_shader_set_local_constants_float(struct wined3d_shader *sh
     for (i = start_idx; i < end_idx; ++i)
     {
         struct wined3d_shader_lconst *lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(*lconst));
+        float *value;
         if (!lconst)
             return E_OUTOFMEMORY;
 
         lconst->idx = i;
-        memcpy(lconst->value, src_data + (i - start_idx) * 4 /* 4 components */, 4 * sizeof(float));
+        value = (float *)lconst->value;
+        memcpy(value, src_data + (i - start_idx) * 4 /* 4 components */, 4 * sizeof(float));
         list_add_head(&shader->constantsF, &lconst->entry);
+
+        if (isinf(value[0]) || isnan(value[0]) || isinf(value[1]) || isnan(value[1])
+                || isinf(value[2]) || isnan(value[2]) || isinf(value[3]) || isnan(value[3]))
+        {
+            shader->lconst_inf_or_nan = TRUE;
+        }
     }
 
     return WINED3D_OK;
@@ -1756,7 +1820,7 @@ void find_vs_compile_args(const struct wined3d_state *state,
             == WINED3D_FOG_NONE ? VS_FOG_COORD : VS_FOG_Z;
     args->clip_enabled = state->render_states[WINED3D_RS_CLIPPING]
             && state->render_states[WINED3D_RS_CLIPPLANEENABLE];
-    args->swizzle_map = shader->device->strided_streams.swizzle_map;
+    args->swizzle_map = shader->device->stream_info.swizzle_map;
 }
 
 static BOOL match_usage(BYTE usage1, BYTE usage_idx1, BYTE usage2, BYTE usage_idx2)
@@ -1798,6 +1862,7 @@ static void vertexshader_set_limits(struct wined3d_shader *shader)
     DWORD shader_version = WINED3D_SHADER_VERSION(shader->reg_maps.shader_version.major,
             shader->reg_maps.shader_version.minor);
     struct wined3d_device *device = shader->device;
+    const DWORD vs_uniform_count = device->adapter->d3d_info.limits.vs_uniform_count;
 
     shader->limits.packed_input = 0;
 
@@ -1812,7 +1877,7 @@ static void vertexshader_set_limits(struct wined3d_shader *shader)
             /* TODO: vs_1_1 has a minimum of 96 constants. What happens when
              * a vs_1_1 shader is used on a vs_3_0 capable card that has 256
              * constants? */
-            shader->limits.constant_float = min(256, device->d3d_vshader_constantF);
+            shader->limits.constant_float = min(256, vs_uniform_count);
             break;
 
         case WINED3D_SHADER_VERSION(2, 0):
@@ -1821,7 +1886,7 @@ static void vertexshader_set_limits(struct wined3d_shader *shader)
             shader->limits.constant_int = 16;
             shader->limits.packed_output = 12;
             shader->limits.sampler = 0;
-            shader->limits.constant_float = min(256, device->d3d_vshader_constantF);
+            shader->limits.constant_float = min(256, vs_uniform_count);
             break;
 
         case WINED3D_SHADER_VERSION(3, 0):
@@ -1834,7 +1899,7 @@ static void vertexshader_set_limits(struct wined3d_shader *shader)
              * drivers advertise 1024). d3d9.dll and d3d8.dll clamp the
              * wined3d-advertised maximum. Clamp the constant limit for <= 3.0
              * shaders to 256. */
-            shader->limits.constant_float = min(256, device->d3d_vshader_constantF);
+            shader->limits.constant_float = min(256, vs_uniform_count);
             break;
 
         case WINED3D_SHADER_VERSION(4, 0):
@@ -1851,7 +1916,7 @@ static void vertexshader_set_limits(struct wined3d_shader *shader)
             shader->limits.constant_int = 16;
             shader->limits.packed_output = 12;
             shader->limits.sampler = 0;
-            shader->limits.constant_float = min(256, device->d3d_vshader_constantF);
+            shader->limits.constant_float = min(256, vs_uniform_count);
             FIXME("Unrecognized vertex shader version \"%u.%u\".\n",
                     shader->reg_maps.shader_version.major,
                     shader->reg_maps.shader_version.minor);
@@ -1866,11 +1931,12 @@ static HRESULT vertexshader_init(struct wined3d_shader *shader, struct wined3d_d
     unsigned int i;
     HRESULT hr;
     WORD map;
+    const DWORD vs_uniform_count = device->adapter->d3d_info.limits.vs_uniform_count;
 
     if (!byte_code) return WINED3DERR_INVALIDCALL;
 
     shader_init(shader, device, parent, parent_ops);
-    hr = shader_set_function(shader, byte_code, output_signature, device->d3d_vshader_constantF,
+    hr = shader_set_function(shader, byte_code, output_signature, vs_uniform_count,
             WINED3D_SHADER_TYPE_VERTEX, max_version);
     if (FAILED(hr))
     {
@@ -1902,8 +1968,8 @@ static HRESULT vertexshader_init(struct wined3d_shader *shader, struct wined3d_d
 
     vertexshader_set_limits(shader);
 
-    shader->load_local_constsF = reg_maps->usesrelconstF
-            && !list_empty(&shader->constantsF);
+    shader->load_local_constsF = (reg_maps->usesrelconstF && !list_empty(&shader->constantsF)) ||
+            shader->lconst_inf_or_nan;
 
     return WINED3D_OK;
 }
@@ -1950,7 +2016,7 @@ static HRESULT geometryshader_init(struct wined3d_shader *shader, struct wined3d
 
     geometryshader_set_limits(shader);
 
-    shader->load_local_constsF = FALSE;
+    shader->load_local_constsF = shader->lconst_inf_or_nan;
 
     return WINED3D_OK;
 }
@@ -1981,7 +2047,7 @@ void find_ps_compile_args(const struct wined3d_state *state,
     if (shader->reg_maps.shader_version.major == 1
             && shader->reg_maps.shader_version.minor <= 3)
     {
-        for (i = 0; i < 4; ++i)
+        for (i = 0; i < shader->limits.sampler; ++i)
         {
             DWORD flags = state->texture_states[i][WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS];
 
@@ -2032,6 +2098,39 @@ void find_ps_compile_args(const struct wined3d_state *state,
             }
         }
     }
+    if (shader->reg_maps.shader_version.major == 1
+            && shader->reg_maps.shader_version.minor <= 4)
+    {
+        for (i = 0; i < shader->limits.sampler; ++i)
+        {
+            const struct wined3d_texture *texture = state->textures[i];
+
+            if (!shader->reg_maps.sampler_type[i])
+                continue;
+
+            /* Treat unbound textures as 2D. The dummy texture will provide
+             * the proper sample value. The tex_types bitmap defaults to
+             * 2D because of the memset. */
+            if (!texture)
+                continue;
+
+            switch (texture->target)
+            {
+                /* RECT textures are distinguished from 2D textures via np2_fixup */
+                case GL_TEXTURE_RECTANGLE_ARB:
+                case GL_TEXTURE_2D:
+                    break;
+
+                case GL_TEXTURE_3D:
+                    args->tex_types |= WINED3D_SHADER_TEX_3D << i * WINED3D_PSARGS_TEXTYPE_SHIFT;
+                    break;
+
+                case GL_TEXTURE_CUBE_MAP_ARB:
+                    args->tex_types |= WINED3D_SHADER_TEX_CUBE << i * WINED3D_PSARGS_TEXTYPE_SHIFT;
+                    break;
+            }
+        }
+    }
 
     for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i)
     {
@@ -2055,19 +2154,13 @@ void find_ps_compile_args(const struct wined3d_state *state,
     }
     if (shader->reg_maps.shader_version.major >= 3)
     {
-        if (device->strided_streams.position_transformed)
-        {
+        if (device->stream_info.position_transformed)
             args->vp_mode = pretransformed;
-        }
         else if (use_vs(state))
-        {
             args->vp_mode = vertexshader;
-        }
         else
-        {
             args->vp_mode = fixedfunction;
-        }
-        args->fog = FOG_OFF;
+        args->fog = WINED3D_FFP_PS_FOG_OFF;
     }
     else
     {
@@ -2077,29 +2170,29 @@ void find_ps_compile_args(const struct wined3d_state *state,
             switch (state->render_states[WINED3D_RS_FOGTABLEMODE])
             {
                 case WINED3D_FOG_NONE:
-                    if (device->strided_streams.position_transformed || use_vs(state))
+                    if (device->stream_info.position_transformed || use_vs(state))
                     {
-                        args->fog = FOG_LINEAR;
+                        args->fog = WINED3D_FFP_PS_FOG_LINEAR;
                         break;
                     }
 
                     switch (state->render_states[WINED3D_RS_FOGVERTEXMODE])
                     {
                         case WINED3D_FOG_NONE: /* Fall through. */
-                        case WINED3D_FOG_LINEAR: args->fog = FOG_LINEAR; break;
-                        case WINED3D_FOG_EXP:    args->fog = FOG_EXP;    break;
-                        case WINED3D_FOG_EXP2:   args->fog = FOG_EXP2;   break;
+                        case WINED3D_FOG_LINEAR: args->fog = WINED3D_FFP_PS_FOG_LINEAR; break;
+                        case WINED3D_FOG_EXP:    args->fog = WINED3D_FFP_PS_FOG_EXP;    break;
+                        case WINED3D_FOG_EXP2:   args->fog = WINED3D_FFP_PS_FOG_EXP2;   break;
                     }
                     break;
 
-                case WINED3D_FOG_LINEAR: args->fog = FOG_LINEAR; break;
-                case WINED3D_FOG_EXP:    args->fog = FOG_EXP;    break;
-                case WINED3D_FOG_EXP2:   args->fog = FOG_EXP2;   break;
+                case WINED3D_FOG_LINEAR: args->fog = WINED3D_FFP_PS_FOG_LINEAR; break;
+                case WINED3D_FOG_EXP:    args->fog = WINED3D_FFP_PS_FOG_EXP;    break;
+                case WINED3D_FOG_EXP2:   args->fog = WINED3D_FFP_PS_FOG_EXP2;   break;
             }
         }
         else
         {
-            args->fog = FOG_OFF;
+            args->fog = WINED3D_FFP_PS_FOG_OFF;
         }
     }
 }
@@ -2184,11 +2277,12 @@ static HRESULT pixelshader_init(struct wined3d_shader *shader, struct wined3d_de
     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
     unsigned int i, highest_reg_used = 0, num_regs_used = 0;
     HRESULT hr;
+    const DWORD ps_uniform_count = device->adapter->d3d_info.limits.ps_uniform_count;
 
     if (!byte_code) return WINED3DERR_INVALIDCALL;
 
     shader_init(shader, device, parent, parent_ops);
-    hr = shader_set_function(shader, byte_code, output_signature, device->d3d_pshader_constantF,
+    hr = shader_set_function(shader, byte_code, output_signature, ps_uniform_count,
             WINED3D_SHADER_TYPE_PIXEL, max_version);
     if (FAILED(hr))
     {
@@ -2239,51 +2333,37 @@ static HRESULT pixelshader_init(struct wined3d_shader *shader, struct wined3d_de
         }
     }
 
-    shader->load_local_constsF = FALSE;
+    shader->load_local_constsF = shader->lconst_inf_or_nan;
 
     return WINED3D_OK;
 }
 
-void pixelshader_update_samplers(struct wined3d_shader_reg_maps *reg_maps, struct wined3d_texture * const *textures)
+void pixelshader_update_samplers(struct wined3d_shader *shader, WORD tex_types)
 {
+    struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
     enum wined3d_sampler_texture_type *sampler_type = reg_maps->sampler_type;
     unsigned int i;
 
     if (reg_maps->shader_version.major != 1) return;
 
-    for (i = 0; i < max(MAX_FRAGMENT_SAMPLERS, MAX_VERTEX_SAMPLERS); ++i)
+    for (i = 0; i < shader->limits.sampler; ++i)
     {
         /* We don't sample from this sampler. */
         if (!sampler_type[i]) continue;
 
-        if (!textures[i])
-        {
-            WARN("No texture bound to sampler %u, using 2D.\n", i);
-            sampler_type[i] = WINED3DSTT_2D;
-            continue;
-        }
-
-        switch (textures[i]->target)
+        switch ((tex_types >> i * WINED3D_PSARGS_TEXTYPE_SHIFT) & WINED3D_PSARGS_TEXTYPE_MASK)
         {
-            case GL_TEXTURE_RECTANGLE_ARB:
-            case GL_TEXTURE_2D:
-                /* We have to select between texture rectangles and 2D
-                 * textures later because 2.0 and 3.0 shaders only have
-                 * WINED3DSTT_2D as well. */
+            case WINED3D_SHADER_TEX_2D:
                 sampler_type[i] = WINED3DSTT_2D;
                 break;
 
-            case GL_TEXTURE_3D:
+            case WINED3D_SHADER_TEX_3D:
                 sampler_type[i] = WINED3DSTT_VOLUME;
                 break;
 
-            case GL_TEXTURE_CUBE_MAP_ARB:
+            case WINED3D_SHADER_TEX_CUBE:
                 sampler_type[i] = WINED3DSTT_CUBE;
                 break;
-
-            default:
-                FIXME("Unrecognized texture type %#x, using 2D.\n", textures[i]->target);
-                sampler_type[i] = WINED3DSTT_2D;
         }
     }
 }
index 7dff243..f1c5d8a 100644 (file)
@@ -87,7 +87,7 @@ static void state_lighting(struct wined3d_context *context, const struct wined3d
         return;
 
     if (state->render_states[WINED3D_RS_LIGHTING]
-            && !context->swapchain->device->strided_streams.position_transformed)
+            && !context->swapchain->device->stream_info.position_transformed)
     {
         gl_info->gl_ops.gl.p_glEnable(GL_LIGHTING);
         checkGLcall("glEnable GL_LIGHTING");
@@ -134,7 +134,7 @@ static void state_zenable(struct wined3d_context *context, const struct wined3d_
 
     if (context->gl_info->supported[ARB_DEPTH_CLAMP])
     {
-        if (!zenable && context->swapchain->device->strided_streams.position_transformed)
+        if (!zenable && context->swapchain->device->stream_info.position_transformed)
         {
             gl_info->gl_ops.gl.p_glEnable(GL_DEPTH_CLAMP);
             checkGLcall("glEnable(GL_DEPTH_CLAMP)");
@@ -267,26 +267,11 @@ static void state_zfunc(struct wined3d_context *context, const struct wined3d_st
 
     if (!depth_func) return;
 
-    if (depth_func == GL_EQUAL || depth_func == GL_NOTEQUAL)
-    {
-        static BOOL once;
-        /* There are a few issues with this: First, our inability to
-         * select a proper Z depth, most of the time we're stuck with
-         * D24S8, even if the app selects D32 or D16. There seem to be
-         * some other precision problems which have to be debugged to
-         * make NOTEQUAL and EQUAL work properly. */
-        if (!once)
-        {
-            once = TRUE;
-            FIXME("D3DCMP_NOTEQUAL and D3DCMP_EQUAL do not work correctly yet.\n");
-        }
-    }
-
     gl_info->gl_ops.gl.p_glDepthFunc(depth_func);
     checkGLcall("glDepthFunc");
 }
 
-static void state_ambient(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+void state_ambient(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
     float col[4];
@@ -597,45 +582,33 @@ static void state_alpha(struct wined3d_context *context, const struct wined3d_st
     }
 }
 
-static void shaderconstant(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
-{
-    context->load_constants = 1;
-}
-
-static void state_clipping(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+void state_clipping(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
     DWORD enable  = 0xffffffff;
     DWORD disable = 0x00000000;
 
-    if (use_vs(state))
+    if (use_vs(state) && !context->d3d_info->vs_clipping)
     {
-        const struct wined3d_device *device = context->swapchain->device;
-
-        if (!device->vs_clipping)
-        {
-            /* The spec says that opengl clipping planes are disabled when using shaders. Direct3D planes aren't,
-             * so that is an issue. The MacOS ATI driver keeps clipping planes activated with shaders in some
-             * conditions I got sick of tracking down. The shader state handler disables all clip planes because
-             * of that - don't do anything here and keep them disabled
-             */
-            if (state->render_states[WINED3D_RS_CLIPPLANEENABLE])
-            {
-                static BOOL warned = FALSE;
-                if(!warned) {
-                    FIXME("Clipping not supported with vertex shaders\n");
-                    warned = TRUE;
-                }
-            }
-            return;
-        }
+        static BOOL warned;
 
-        /* glEnable(GL_CLIP_PLANEx) doesn't apply to vertex shaders. The enabled / disabled planes are
-         * hardcoded into the shader. Update the shader to update the enabled clipplanes */
-        context->select_shader = 1;
-        context->load_constants = 1;
+        /* The OpenGL spec says that clipping planes are disabled when using
+         * shaders. Direct3D planes aren't, so that is an issue. The MacOS ATI
+         * driver keeps clipping planes activated with shaders in some
+         * conditions I got sick of tracking down. The shader state handler
+         * disables all clip planes because of that - don't do anything here
+         * and keep them disabled. */
+        if (state->render_states[WINED3D_RS_CLIPPLANEENABLE] && !warned++)
+            FIXME("Clipping not supported with vertex shaders\n");
+        return;
     }
 
+    /* glEnable(GL_CLIP_PLANEx) doesn't apply to (ARB backend) vertex shaders.
+     * The enabled / disabled planes are hardcoded into the shader. Update the
+     * shader to update the enabled clipplanes. In case of fixed function, we
+     * need to update the clipping field from ffp_vertex_settings. */
+    context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_VERTEX;
+
     /* TODO: Keep track of previously enabled clipplanes to avoid unnecessary resetting
      * of already set values
      */
@@ -671,7 +644,7 @@ static void state_clipping(struct wined3d_context *context, const struct wined3d
     checkGLcall("clip plane disable");
 }
 
-static void state_specularenable(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+void state_specularenable(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
     /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
@@ -791,7 +764,7 @@ static void state_texfactor(struct wined3d_context *context, const struct wined3
     D3DCOLORTOGLFLOAT4(state->render_states[WINED3D_RS_TEXTUREFACTOR], col);
 
     /* And now the default texture color as well */
-    for (i = 0; i < gl_info->limits.texture_stages; ++i)
+    for (i = 0; i < context->d3d_info->limits.ffp_blend_stages; ++i)
     {
         /* Note the WINED3D_RS value applies to all textures, but GL has one
          * per texture, so apply it now ready to be used! */
@@ -1064,8 +1037,13 @@ void state_fogstartend(struct wined3d_context *context, const struct wined3d_sta
             fogstart = tmpvalue.f;
             tmpvalue.d = state->render_states[WINED3D_RS_FOGEND];
             fogend = tmpvalue.f;
-            /* In GL, fogstart == fogend disables fog, in D3D everything's fogged.*/
-            if(fogstart == fogend) {
+            /* Special handling for fogstart == fogend. In d3d with vertex
+             * fog, everything is fogged. With table fog, everything with
+             * fog_coord < fog_start is unfogged, and fog_coord > fog_start
+             * is fogged. Windows drivers disagree when fog_coord == fog_start. */
+            if (state->render_states[WINED3D_RS_FOGTABLEMODE] == WINED3D_FOG_NONE
+                    && fogstart == fogend)
+            {
                 fogstart = -INFINITY;
                 fogend = 0.0f;
             }
@@ -1093,6 +1071,8 @@ void state_fog_fragpart(struct wined3d_context *context, const struct wined3d_st
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
     enum fogsource new_source;
+    DWORD fogstart = state->render_states[WINED3D_RS_FOGSTART];
+    DWORD fogend = state->render_states[WINED3D_RS_FOGEND];
 
     TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);
 
@@ -1238,7 +1218,7 @@ void state_fog_fragpart(struct wined3d_context *context, const struct wined3d_st
 
     glEnableWINE(GL_FOG);
     checkGLcall("glEnable GL_FOG");
-    if (new_source != context->fog_source)
+    if (new_source != context->fog_source || fogstart == fogend)
     {
         context->fog_source = new_source;
         state_fogstartend(context, state, STATE_RENDER(WINED3D_RS_FOGSTART));
@@ -1283,7 +1263,7 @@ static void state_colormat(struct wined3d_context *context, const struct wined3d
     }
 
     context->num_untracked_materials = 0;
-    if ((device->strided_streams.use_map & (1 << WINED3D_FFP_DIFFUSE))
+    if ((device->stream_info.use_map & (1 << WINED3D_FFP_DIFFUSE))
             && state->render_states[WINED3D_RS_COLORVERTEX])
     {
         TRACE("diff %d, amb %d, emis %d, spec %d\n",
@@ -1436,7 +1416,7 @@ static void state_normalize(struct wined3d_context *context, const struct wined3
      * by zero and is not properly defined in opengl, so avoid it
      */
     if (state->render_states[WINED3D_RS_NORMALIZENORMALS]
-            && (context->swapchain->device->strided_streams.use_map & (1 << WINED3D_FFP_NORMAL)))
+            && (context->swapchain->device->stream_info.use_map & (1 << WINED3D_FFP_NORMAL)))
     {
         gl_info->gl_ops.gl.p_glEnable(GL_NORMALIZE);
         checkGLcall("glEnable(GL_NORMALIZE);");
@@ -1448,7 +1428,7 @@ static void state_normalize(struct wined3d_context *context, const struct wined3
     }
 }
 
-static void state_psizemin_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+void state_psizemin_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     union {
         DWORD d;
@@ -1468,7 +1448,7 @@ static void state_psizemin_w(struct wined3d_context *context, const struct wined
 
 }
 
-static void state_psizemin_ext(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+void state_psizemin_ext(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
     union
@@ -1491,7 +1471,7 @@ static void state_psizemin_ext(struct wined3d_context *context, const struct win
     checkGLcall("glPointParameterfEXT(...)");
 }
 
-static void state_psizemin_arb(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+void state_psizemin_arb(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
     union
@@ -1514,7 +1494,7 @@ static void state_psizemin_arb(struct wined3d_context *context, const struct win
     checkGLcall("glPointParameterfARB(...)");
 }
 
-static void state_pscale(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+void state_pscale(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
     /* TODO: Group this with the viewport */
@@ -1689,7 +1669,7 @@ static void state_lastpixel(struct wined3d_context *context, const struct wined3
     }
 }
 
-static void state_pointsprite_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+void state_pointsprite_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     static BOOL warned;
 
@@ -1702,7 +1682,7 @@ static void state_pointsprite_w(struct wined3d_context *context, const struct wi
     }
 }
 
-static void state_pointsprite(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+void state_pointsprite(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
 
@@ -3312,7 +3292,7 @@ void tex_alphaop(struct wined3d_context *context, const struct wined3d_state *st
     }
 }
 
-static void transform_texture(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+void transform_texture(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     DWORD texUnit = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
     const struct wined3d_device *device = context->swapchain->device;
@@ -3338,8 +3318,8 @@ static void transform_texture(struct wined3d_context *context, const struct wine
     set_texture_matrix(gl_info, &state->transforms[WINED3D_TS_TEXTURE0 + texUnit].u.m[0][0],
             state->texture_states[texUnit][WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS],
             generated, context->last_was_rhw,
-            device->strided_streams.use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coordIdx))
-            ? device->strided_streams.elements[WINED3D_FFP_TEXCOORD0 + coordIdx].format->id
+            device->stream_info.use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coordIdx))
+            ? device->stream_info.elements[WINED3D_FFP_TEXCOORD0 + coordIdx].format->id
             : WINED3DFMT_UNKNOWN,
             device->shader_backend->shader_has_ffp_proj_control(device->shader_priv));
 
@@ -3378,7 +3358,7 @@ static void load_tex_coords(const struct wined3d_context *context, const struct
     unsigned int mapped_stage = 0;
     unsigned int textureNo = 0;
 
-    for (textureNo = 0; textureNo < gl_info->limits.texture_stages; ++textureNo)
+    for (textureNo = 0; textureNo < context->d3d_info->limits.ffp_blend_stages; ++textureNo)
     {
         int coordIdx = state->texture_states[textureNo][WINED3D_TSS_TEXCOORD_INDEX];
 
@@ -3602,21 +3582,11 @@ static void tex_coordindex(struct wined3d_context *context, const struct wined3d
         GLuint curVBO = gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] ? ~0U : 0;
 
         unload_tex_coords(gl_info);
-        load_tex_coords(context, &device->strided_streams, &curVBO, state);
+        load_tex_coords(context, &device->stream_info, &curVBO, state);
     }
 }
 
-static void tex_bumpenvlscale(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
-{
-    DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
-    const struct wined3d_shader *ps = state->pixel_shader;
-
-    /* The pixel shader has to know the luminance scale. Do a constants update. */
-    if (ps && stage && (ps->reg_maps.luminanceparams & (1 << stage)))
-        context->load_constants = 1;
-}
-
-static void sampler_texmatrix(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+void sampler_texmatrix(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     const DWORD sampler = state_id - STATE_SAMPLER(0);
     const struct wined3d_texture *texture = state->textures[sampler];
@@ -3706,7 +3676,7 @@ static void sampler(struct wined3d_context *context, const struct wined3d_state
 
         /* Trigger shader constant reloading (for NP2 texcoord fixup) */
         if (!(texture->flags & WINED3D_TEXTURE_POW2_MAT_IDENT))
-            device->shader_backend->shader_load_np2fixup_constants(device->shader_priv, gl_info, state);
+            context->constant_update_mask |= WINED3D_SHADER_CONST_PS_NP2_FIXUP;
     }
     else
     {
@@ -3753,7 +3723,7 @@ void apply_pixelshader(struct wined3d_context *context, const struct wined3d_sta
     {
         /* Disabled the pixel shader - color ops weren't applied while it was
          * enabled, so re-apply them. */
-        for (i = 0; i < context->gl_info->limits.texture_stages; ++i)
+        for (i = 0; i < context->d3d_info->limits.ffp_blend_stages; ++i)
         {
             if (!isStateDirty(context, STATE_TEXTURESTAGE(i, WINED3D_TSS_COLOR_OP)))
                 context_apply_state(context, state, STATE_TEXTURESTAGE(i, WINED3D_TSS_COLOR_OP));
@@ -3761,26 +3731,20 @@ void apply_pixelshader(struct wined3d_context *context, const struct wined3d_sta
         context->last_was_pshader = FALSE;
     }
 
-    context->select_shader = 1;
-    context->load_constants = 1;
+    context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_PIXEL;
 }
 
 static void state_geometry_shader(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
-    context->select_shader = 1;
+    context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_GEOMETRY;
 }
 
-static void shader_bumpenvmat(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+static void shader_bumpenv(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
-    DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
-    const struct wined3d_shader *ps = state->pixel_shader;
-
-    /* The pixel shader has to know the bump env matrix. Do a constants update. */
-    if (ps && stage && (ps->reg_maps.bumpmat & (1 << stage)))
-        context->load_constants = 1;
+    context->constant_update_mask |= WINED3D_SHADER_CONST_PS_BUMP_ENV;
 }
 
-static void transform_world(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+void transform_world(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
 
@@ -3801,23 +3765,14 @@ static void transform_world(struct wined3d_context *context, const struct wined3
     }
     else
     {
-        /* In the general case, the view matrix is the identity matrix */
-        if (context->swapchain->device->view_ident)
-        {
-            gl_info->gl_ops.gl.p_glLoadMatrixf(&state->transforms[WINED3D_TS_WORLD_MATRIX(0)].u.m[0][0]);
-            checkGLcall("glLoadMatrixf");
-        }
-        else
-        {
-            gl_info->gl_ops.gl.p_glLoadMatrixf(&state->transforms[WINED3D_TS_VIEW].u.m[0][0]);
-            checkGLcall("glLoadMatrixf");
-            gl_info->gl_ops.gl.p_glMultMatrixf(&state->transforms[WINED3D_TS_WORLD_MATRIX(0)].u.m[0][0]);
-            checkGLcall("glMultMatrixf");
-        }
+        gl_info->gl_ops.gl.p_glLoadMatrixf(&state->transforms[WINED3D_TS_VIEW].u.m[0][0]);
+        checkGLcall("glLoadMatrixf");
+        gl_info->gl_ops.gl.p_glMultMatrixf(&state->transforms[WINED3D_TS_WORLD_MATRIX(0)].u.m[0][0]);
+        checkGLcall("glMultMatrixf");
     }
 }
 
-static void clipplane(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+void clipplane(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
     UINT index = state_id - STATE_CLIPPLANE(0);
@@ -3883,18 +3838,10 @@ static void transform_worldex(struct wined3d_context *context, const struct wine
     /* World matrix 0 is multiplied with the view matrix because d3d uses 3
      * matrices while gl uses only 2. To avoid weighting the view matrix
      * incorrectly it has to be multiplied into every GL modelview matrix. */
-    if (context->swapchain->device->view_ident)
-    {
-        gl_info->gl_ops.gl.p_glLoadMatrixf(&state->transforms[WINED3D_TS_WORLD_MATRIX(matrix)].u.m[0][0]);
-        checkGLcall("glLoadMatrixf");
-    }
-    else
-    {
-        gl_info->gl_ops.gl.p_glLoadMatrixf(&state->transforms[WINED3D_TS_VIEW].u.m[0][0]);
-        checkGLcall("glLoadMatrixf");
-        gl_info->gl_ops.gl.p_glMultMatrixf(&state->transforms[WINED3D_TS_WORLD_MATRIX(matrix)].u.m[0][0]);
-        checkGLcall("glMultMatrixf");
-    }
+    gl_info->gl_ops.gl.p_glLoadMatrixf(&state->transforms[WINED3D_TS_VIEW].u.m[0][0]);
+    checkGLcall("glLoadMatrixf");
+    gl_info->gl_ops.gl.p_glMultMatrixf(&state->transforms[WINED3D_TS_WORLD_MATRIX(matrix)].u.m[0][0]);
+    checkGLcall("glMultMatrixf");
 }
 
 static void state_vertexblend_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
@@ -3953,7 +3900,7 @@ static void state_vertexblend(struct wined3d_context *context, const struct wine
     }
 }
 
-static void transform_view(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+void transform_view(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
     const struct wined3d_light_info *light = NULL;
@@ -4012,7 +3959,7 @@ static void transform_view(struct wined3d_context *context, const struct wined3d
     }
 }
 
-static void transform_projection(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+void transform_projection(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
 
@@ -4552,13 +4499,13 @@ static void streamsrc(struct wined3d_context *context, const struct wined3d_stat
     if (load_numbered)
     {
         TRACE("Loading numbered arrays\n");
-        load_numbered_arrays(context, &device->strided_streams, state);
+        load_numbered_arrays(context, &device->stream_info, state);
         context->numberedArraysLoaded = TRUE;
     }
     else if (load_named)
     {
         TRACE("Loading vertex data\n");
-        load_vertex_data(context, &device->strided_streams, state);
+        load_vertex_data(context, &device->stream_info, state);
         context->namedArraysLoaded = TRUE;
     }
 }
@@ -4570,7 +4517,7 @@ static void vdecl_miscpart(struct wined3d_context *context, const struct wined3d
     streamsrc(context, state, STATE_STREAMSRC);
 }
 
-static void vertexdeclaration(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+void vertexdeclaration(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     const struct wined3d_device *device = context->swapchain->device;
     const struct wined3d_gl_info *gl_info = context->gl_info;
@@ -4580,7 +4527,7 @@ static void vertexdeclaration(struct wined3d_context *context, const struct wine
     BOOL wasrhw = context->last_was_rhw;
     unsigned int i;
 
-    transformed = device->strided_streams.position_transformed;
+    transformed = device->stream_info.position_transformed;
     if (transformed != context->last_was_rhw && !useVertexShaderFunction)
         updateFog = TRUE;
 
@@ -4612,7 +4559,7 @@ static void vertexdeclaration(struct wined3d_context *context, const struct wine
                 && !isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_VIEW)))
             transform_world(context, state, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)));
         if (!isStateDirty(context, STATE_RENDER(WINED3D_RS_COLORVERTEX)))
-            state_colormat(context, state, STATE_RENDER(WINED3D_RS_COLORVERTEX));
+            context_apply_state(context, state, STATE_RENDER(WINED3D_RS_COLORVERTEX));
         if (!isStateDirty(context, STATE_RENDER(WINED3D_RS_LIGHTING)))
             state_lighting(context, state, STATE_RENDER(WINED3D_RS_LIGHTING));
 
@@ -4620,8 +4567,11 @@ static void vertexdeclaration(struct wined3d_context *context, const struct wine
         {
             updateFog = TRUE;
 
-            if (!device->vs_clipping && !isStateDirty(context, STATE_RENDER(WINED3D_RS_CLIPPLANEENABLE)))
+            if (!context->d3d_info->vs_clipping
+                    && !isStateDirty(context, STATE_RENDER(WINED3D_RS_CLIPPLANEENABLE)))
+            {
                 state_clipping(context, state, STATE_RENDER(WINED3D_RS_CLIPPLANEENABLE));
+            }
 
             for (i = 0; i < gl_info->limits.clipplanes; ++i)
             {
@@ -4635,7 +4585,8 @@ static void vertexdeclaration(struct wined3d_context *context, const struct wine
     {
         if(!context->last_was_vshader) {
             static BOOL warned = FALSE;
-            if(!device->vs_clipping) {
+            if (!context->d3d_info->vs_clipping)
+            {
                 /* Disable all clip planes to get defined results on all drivers. See comment in the
                  * state_clipping state handler
                  */
@@ -4679,8 +4630,7 @@ static void vertexdeclaration(struct wined3d_context *context, const struct wine
     }
 
     context->last_was_vshader = useVertexShaderFunction;
-    context->select_shader = 1;
-    context->load_constants = 1;
+    context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_VERTEX;
 
     if (updateFog)
         context_apply_state(context, state, STATE_RENDER(WINED3D_RS_FOGVERTEXMODE));
@@ -4694,6 +4644,10 @@ static void vertexdeclaration(struct wined3d_context *context, const struct wine
             if (!isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_TEXTURE0 + i)))
                 transform_texture(context, state, STATE_TEXTURESTAGE(i, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS));
         }
+
+        if (use_ps(state) && state->pixel_shader->reg_maps.shader_version.major == 1
+                && state->pixel_shader->reg_maps.shader_version.minor <= 3)
+            context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_PIXEL;
     }
 
     if (transformed != wasrhw && !isStateDirty(context, STATE_RENDER(WINED3D_RS_ZENABLE)))
@@ -4727,21 +4681,21 @@ static void viewport_miscpart(struct wined3d_context *context, const struct wine
         gl_info->gl_ops.gl.p_glViewport(vp.x, (height - (vp.y + vp.height)),
                 vp.width, vp.height);
     }
-
     checkGLcall("glViewport");
 }
 
-static void viewport_vertexpart(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+void viewport_vertexpart(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     if (!isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_PROJECTION)))
         transform_projection(context, state, STATE_TRANSFORM(WINED3D_TS_PROJECTION));
-    if (!isStateDirty(context, STATE_RENDER(WINED3D_RS_POINTSCALEENABLE)))
+    if (!isStateDirty(context, STATE_RENDER(WINED3D_RS_POINTSCALEENABLE))
+            && state->render_states[WINED3D_RS_POINTSCALEENABLE])
         state_pscale(context, state, STATE_RENDER(WINED3D_RS_POINTSCALEENABLE));
     /* Update the position fixup. */
-    context->load_constants = 1;
+    context->constant_update_mask |= WINED3D_SHADER_CONST_VS_POS_FIXUP;
 }
 
-static void light(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+void light(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
     UINT Index = state_id - STATE_ACTIVELIGHT(0);
@@ -4894,7 +4848,7 @@ static void scissorrect(struct wined3d_context *context, const struct wined3d_st
 
 static void indexbuffer(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
-    const struct wined3d_stream_info *stream_info = &context->swapchain->device->strided_streams;
+    const struct wined3d_stream_info *stream_info = &context->swapchain->device->stream_info;
     const struct wined3d_gl_info *gl_info = context->gl_info;
 
     if (!state->index_buffer || !stream_info->all_vbo)
@@ -4982,55 +4936,53 @@ const struct StateEntryTemplate misc_state_template[] = {
     /* TODO: Move shader constant loading to vertex and fragment pipeline respectively, as soon as the pshader and
      * vshader loadings are untied from each other
      */
-    { STATE_VERTEXSHADERCONSTANT,                         { STATE_VERTEXSHADERCONSTANT,                         shaderconstant      }, WINED3D_GL_EXT_NONE             },
-    { STATE_PIXELSHADERCONSTANT,                          { STATE_VERTEXSHADERCONSTANT,                         NULL                }, WINED3D_GL_EXT_NONE             },
-    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   shader_bumpenvmat   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   shader_bumpenv      }, WINED3D_GL_EXT_NONE             },
     { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
-    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   shader_bumpenvmat   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   shader_bumpenv      }, WINED3D_GL_EXT_NONE             },
     { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
-    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   shader_bumpenvmat   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   shader_bumpenv      }, WINED3D_GL_EXT_NONE             },
     { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
-    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   shader_bumpenvmat   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   shader_bumpenv      }, WINED3D_GL_EXT_NONE             },
     { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
-    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   shader_bumpenvmat   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   shader_bumpenv      }, WINED3D_GL_EXT_NONE             },
     { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
-    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   shader_bumpenvmat   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   shader_bumpenv      }, WINED3D_GL_EXT_NONE             },
     { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
-    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   shader_bumpenvmat   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   shader_bumpenv      }, WINED3D_GL_EXT_NONE             },
     { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
-    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   shader_bumpenvmat   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   shader_bumpenv      }, WINED3D_GL_EXT_NONE             },
     { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
-    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE),  { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE),  tex_bumpenvlscale   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE),  { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE),  shader_bumpenv      }, WINED3D_GL_EXT_NONE             },
     { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LOFFSET), { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE),  NULL                }, WINED3D_GL_EXT_NONE             },
-    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE),  { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE),  tex_bumpenvlscale   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE),  { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE),  shader_bumpenv      }, WINED3D_GL_EXT_NONE             },
     { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LOFFSET), { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE),  NULL                }, WINED3D_GL_EXT_NONE             },
-    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE),  { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE),  tex_bumpenvlscale   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE),  { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE),  shader_bumpenv      }, WINED3D_GL_EXT_NONE             },
     { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LOFFSET), { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE),  NULL                }, WINED3D_GL_EXT_NONE             },
-    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE),  { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE),  tex_bumpenvlscale   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE),  { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE),  shader_bumpenv      }, WINED3D_GL_EXT_NONE             },
     { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LOFFSET), { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE),  NULL                }, WINED3D_GL_EXT_NONE             },
-    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE),  { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE),  tex_bumpenvlscale   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE),  { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE),  shader_bumpenv      }, WINED3D_GL_EXT_NONE             },
     { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LOFFSET), { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE),  NULL                }, WINED3D_GL_EXT_NONE             },
-    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE),  { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE),  tex_bumpenvlscale   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE),  { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE),  shader_bumpenv      }, WINED3D_GL_EXT_NONE             },
     { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LOFFSET), { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE),  NULL                }, WINED3D_GL_EXT_NONE             },
-    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE),  { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE),  tex_bumpenvlscale   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE),  { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE),  shader_bumpenv      }, WINED3D_GL_EXT_NONE             },
     { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LOFFSET), { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE),  NULL                }, WINED3D_GL_EXT_NONE             },
-    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE),  { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE),  tex_bumpenvlscale   }, WINED3D_GL_EXT_NONE             },
+    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE),  { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE),  shader_bumpenv      }, WINED3D_GL_EXT_NONE             },
     { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LOFFSET), { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE),  NULL                }, WINED3D_GL_EXT_NONE             },
 
     { STATE_VIEWPORT,                                     { STATE_VIEWPORT,                                     viewport_miscpart   }, WINED3D_GL_EXT_NONE             },
@@ -5158,7 +5110,8 @@ const struct StateEntryTemplate misc_state_template[] = {
     {0 /* Terminate */,                                   { 0,                                                  0                   }, WINED3D_GL_EXT_NONE             },
 };
 
-const struct StateEntryTemplate ffp_vertexstate_template[] = {
+const struct StateEntryTemplate vp_ffp_states[] =
+{
     { STATE_VDECL,                                        { STATE_VDECL,                                        vertexdeclaration   }, WINED3D_GL_EXT_NONE             },
     { STATE_VSHADER,                                      { STATE_VDECL,                                        NULL                }, WINED3D_GL_EXT_NONE             },
     { STATE_MATERIAL,                                     { STATE_RENDER(WINED3D_RS_SPECULARENABLE),            NULL                }, WINED3D_GL_EXT_NONE             },
@@ -5197,6 +5150,7 @@ const struct StateEntryTemplate ffp_vertexstate_template[] = {
     { STATE_CLIPPLANE(30),                                { STATE_CLIPPLANE(30),                                clipplane           }, WINED3D_GL_EXT_NONE             },
     { STATE_CLIPPLANE(31),                                { STATE_CLIPPLANE(31),                                clipplane           }, WINED3D_GL_EXT_NONE             },
       /* Lights */
+    { STATE_LIGHT_TYPE,                                   { STATE_LIGHT_TYPE,                                   state_nop           }, WINED3D_GL_EXT_NONE             },
     { STATE_ACTIVELIGHT(0),                               { STATE_ACTIVELIGHT(0),                               light               }, WINED3D_GL_EXT_NONE             },
     { STATE_ACTIVELIGHT(1),                               { STATE_ACTIVELIGHT(1),                               light               }, WINED3D_GL_EXT_NONE             },
     { STATE_ACTIVELIGHT(2),                               { STATE_ACTIVELIGHT(2),                               light               }, WINED3D_GL_EXT_NONE             },
@@ -5552,6 +5506,7 @@ const struct StateEntryTemplate ffp_vertexstate_template[] = {
     { STATE_SAMPLER(7),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
     { STATE_SAMPLER(7),                                   { 0,                                                  NULL                }, WINED3D_GL_NORMALIZED_TEXRECT   },
     { STATE_SAMPLER(7),                                   { STATE_SAMPLER(7),                                   sampler_texmatrix   }, WINED3D_GL_EXT_NONE             },
+    { STATE_POINT_SIZE_ENABLE,                            { STATE_POINT_SIZE_ENABLE,                            state_nop           }, WINED3D_GL_EXT_NONE             },
     {0 /* Terminate */,                                   { 0,                                                  0                   }, WINED3D_GL_EXT_NONE             },
 };
 
@@ -5660,6 +5615,42 @@ static const struct StateEntryTemplate ffp_fragmentstate_template[] = {
 /* Context activation is done by the caller. */
 static void ffp_enable(const struct wined3d_gl_info *gl_info, BOOL enable) {}
 
+static void *ffp_alloc(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv)
+{
+    return shader_priv;
+}
+
+static void ffp_free(struct wined3d_device *device) {}
+
+static void vp_ffp_get_caps(const struct wined3d_gl_info *gl_info, struct wined3d_vertex_caps *caps)
+{
+    caps->xyzrhw = FALSE;
+    caps->max_active_lights = gl_info->limits.lights;
+    caps->max_vertex_blend_matrices = gl_info->limits.blends;
+    caps->max_vertex_blend_matrix_index = 0;
+    caps->vertex_processing_caps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS
+            | WINED3DVTXPCAPS_MATERIALSOURCE7
+            | WINED3DVTXPCAPS_POSITIONALLIGHTS
+            | WINED3DVTXPCAPS_LOCALVIEWER
+            | WINED3DVTXPCAPS_VERTEXFOG
+            | WINED3DVTXPCAPS_TEXGEN
+            | WINED3DVTXPCAPS_TEXGEN_SPHEREMAP;
+    caps->fvf_caps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
+    caps->max_user_clip_planes = gl_info->limits.clipplanes;
+    caps->raster_caps = 0;
+    if (gl_info->supported[NV_FOG_DISTANCE])
+        caps->raster_caps |= WINED3DPRASTERCAPS_FOGRANGE;
+}
+
+const struct wined3d_vertex_pipe_ops ffp_vertex_pipe =
+{
+    ffp_enable,
+    vp_ffp_get_caps,
+    ffp_alloc,
+    ffp_free,
+    vp_ffp_states,
+};
+
 static void ffp_fragment_get_caps(const struct wined3d_gl_info *gl_info, struct fragment_caps *caps)
 {
     caps->wined3d_caps = 0;
@@ -5701,12 +5692,6 @@ static void ffp_fragment_get_caps(const struct wined3d_gl_info *gl_info, struct
     caps->MaxSimultaneousTextures = gl_info->limits.textures;
 }
 
-static void *ffp_fragment_alloc(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv)
-{
-    return shader_priv;
-}
-
-static void ffp_fragment_free(struct wined3d_device *device) {}
 static BOOL ffp_color_fixup_supported(struct color_fixup_desc fixup)
 {
     if (TRACE_ON(d3d))
@@ -5729,25 +5714,39 @@ static BOOL ffp_color_fixup_supported(struct color_fixup_desc fixup)
 const struct fragment_pipeline ffp_fragment_pipeline = {
     ffp_enable,
     ffp_fragment_get_caps,
-    ffp_fragment_alloc,
-    ffp_fragment_free,
+    ffp_alloc,
+    ffp_free,
     ffp_color_fixup_supported,
     ffp_fragmentstate_template,
 };
 
-static void fp_none_enable(const struct wined3d_gl_info *gl_info, BOOL enable) {}
+static void none_enable(const struct wined3d_gl_info *gl_info, BOOL enable) {}
 
-static void fp_none_get_caps(const struct wined3d_gl_info *gl_info, struct fragment_caps *caps)
+static void *none_alloc(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv)
 {
-    memset(caps, 0, sizeof(*caps));
+    return shader_priv;
 }
 
-static void *fp_none_alloc(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv)
+static void none_free(struct wined3d_device *device) {}
+
+static void vp_none_get_caps(const struct wined3d_gl_info *gl_info, struct wined3d_vertex_caps *caps)
 {
-    return shader_priv;
+    memset(caps, 0, sizeof(*caps));
 }
 
-static void fp_none_free(struct wined3d_device *device) {}
+const struct wined3d_vertex_pipe_ops none_vertex_pipe =
+{
+    none_enable,
+    vp_none_get_caps,
+    none_alloc,
+    none_free,
+    NULL,
+};
+
+static void fp_none_get_caps(const struct wined3d_gl_info *gl_info, struct fragment_caps *caps)
+{
+    memset(caps, 0, sizeof(*caps));
+}
 
 static BOOL fp_none_color_fixup_supported(struct color_fixup_desc fixup)
 {
@@ -5756,10 +5755,10 @@ static BOOL fp_none_color_fixup_supported(struct color_fixup_desc fixup)
 
 const struct fragment_pipeline none_fragment_pipe =
 {
-    fp_none_enable,
+    none_enable,
     fp_none_get_caps,
-    fp_none_alloc,
-    fp_none_free,
+    none_alloc,
+    none_free,
     fp_none_color_fixup_supported,
     NULL,
 };
@@ -5784,11 +5783,12 @@ static void multistate_apply_3(struct wined3d_context *context, const struct win
     context->swapchain->device->multistate_funcs[state_id][2](context, state, state_id);
 }
 
-static void prune_invalid_states(struct StateEntry *state_table, const struct wined3d_gl_info *gl_info)
+static void prune_invalid_states(struct StateEntry *state_table, const struct wined3d_gl_info *gl_info,
+        const struct wined3d_d3d_info *d3d_info)
 {
     unsigned int start, last, i;
 
-    start = STATE_TEXTURESTAGE(gl_info->limits.texture_stages, 0);
+    start = STATE_TEXTURESTAGE(d3d_info->limits.ffp_blend_stages, 0);
     last = STATE_TEXTURESTAGE(MAX_TEXTURES - 1, WINED3D_HIGHEST_TEXTURE_STATE);
     for (i = start; i <= last; ++i)
     {
@@ -5796,7 +5796,7 @@ static void prune_invalid_states(struct StateEntry *state_table, const struct wi
         state_table[i].apply = state_undefined;
     }
 
-    start = STATE_TRANSFORM(WINED3D_TS_TEXTURE0 + gl_info->limits.texture_stages);
+    start = STATE_TRANSFORM(WINED3D_TS_TEXTURE0 + d3d_info->limits.ffp_blend_stages);
     last = STATE_TRANSFORM(WINED3D_TS_TEXTURE0 + MAX_TEXTURES - 1);
     for (i = start; i <= last; ++i)
     {
@@ -5841,17 +5841,17 @@ static void validate_state_table(struct StateEntry *state_table)
         STATE_VDECL,
         STATE_STREAMSRC,
         STATE_INDEXBUFFER,
-        STATE_VERTEXSHADERCONSTANT,
-        STATE_PIXELSHADERCONSTANT,
         STATE_VSHADER,
         STATE_GEOMETRY_SHADER,
         STATE_PIXELSHADER,
         STATE_VIEWPORT,
+        STATE_LIGHT_TYPE,
         STATE_SCISSORRECT,
         STATE_FRONTFACE,
         STATE_POINTSPRITECOORDORIGIN,
         STATE_BASEVERTEXINDEX,
-        STATE_FRAMEBUFFER
+        STATE_FRAMEBUFFER,
+        STATE_POINT_SIZE_ENABLE,
     };
     unsigned int i, current;
 
@@ -5901,8 +5901,9 @@ static void validate_state_table(struct StateEntry *state_table)
 }
 
 HRESULT compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_multistate_funcs,
-        const struct wined3d_gl_info *gl_info, const struct StateEntryTemplate *vertex,
-        const struct fragment_pipeline *fragment, const struct StateEntryTemplate *misc)
+        const struct wined3d_gl_info *gl_info, const struct wined3d_d3d_info *d3d_info,
+        const struct wined3d_vertex_pipe_ops *vertex, const struct fragment_pipeline *fragment,
+        const struct StateEntryTemplate *misc)
 {
     unsigned int i, type, handlers;
     APPLYSTATEFUNC multistate_funcs[STATE_HIGHEST + 1][3];
@@ -5921,7 +5922,7 @@ HRESULT compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_
         switch(type) {
             case 0: cur = misc; break;
             case 1: cur = fragment->states; break;
-            case 2: cur = vertex; break;
+            case 2: cur = vertex->vp_states; break;
             default: cur = NULL; /* Stupid compiler */
         }
         if(!cur) continue;
@@ -5990,16 +5991,17 @@ HRESULT compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_
                         cur[i].state, handlers + 1);
             }
 
-            if(StateTable[cur[i].state].representative &&
-            StateTable[cur[i].state].representative != cur[i].content.representative) {
-                FIXME("State %u has different representatives in different pipeline parts\n",
-                    cur[i].state);
+            if (StateTable[cur[i].state].representative
+                    && StateTable[cur[i].state].representative != cur[i].content.representative)
+            {
+                FIXME("State %s (%#x) has different representatives in different pipeline parts.\n",
+                        debug_d3dstate(cur[i].state), cur[i].state);
             }
             StateTable[cur[i].state].representative = cur[i].content.representative;
         }
     }
 
-    prune_invalid_states(StateTable, gl_info);
+    prune_invalid_states(StateTable, gl_info, d3d_info);
     validate_state_table(StateTable);
 
     return WINED3D_OK;
index fe028d3..1115544 100644 (file)
@@ -194,40 +194,29 @@ static const DWORD vertex_states_sampler[] =
  */
 static HRESULT stateblock_allocate_shader_constants(struct wined3d_stateblock *object)
 {
-    struct wined3d_device *device = object->device;
-
-    /* Allocate space for floating point constants */
-    object->state.ps_consts_f = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
-            sizeof(float) * device->d3d_pshader_constantF * 4);
-    if (!object->state.ps_consts_f) goto fail;
+    const struct wined3d_d3d_info *d3d_info = &object->device->adapter->d3d_info;
 
     object->changed.pixelShaderConstantsF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
-            sizeof(BOOL) * device->d3d_pshader_constantF);
+            sizeof(BOOL) * d3d_info->limits.ps_uniform_count);
     if (!object->changed.pixelShaderConstantsF) goto fail;
 
-    object->state.vs_consts_f = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
-            sizeof(float) * device->d3d_vshader_constantF * 4);
-    if (!object->state.vs_consts_f) goto fail;
-
     object->changed.vertexShaderConstantsF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
-            sizeof(BOOL) * device->d3d_vshader_constantF);
+            sizeof(BOOL) * d3d_info->limits.vs_uniform_count);
     if (!object->changed.vertexShaderConstantsF) goto fail;
 
     object->contained_vs_consts_f = HeapAlloc(GetProcessHeap(), 0,
-            sizeof(DWORD) * device->d3d_vshader_constantF);
+            sizeof(DWORD) * d3d_info->limits.vs_uniform_count);
     if (!object->contained_vs_consts_f) goto fail;
 
     object->contained_ps_consts_f = HeapAlloc(GetProcessHeap(), 0,
-            sizeof(DWORD) * device->d3d_pshader_constantF);
+            sizeof(DWORD) * d3d_info->limits.ps_uniform_count);
     if (!object->contained_ps_consts_f) goto fail;
 
     return WINED3D_OK;
 
 fail:
     ERR("Failed to allocate memory\n");
-    HeapFree(GetProcessHeap(), 0, object->state.ps_consts_f);
     HeapFree(GetProcessHeap(), 0, object->changed.pixelShaderConstantsF);
-    HeapFree(GetProcessHeap(), 0, object->state.vs_consts_f);
     HeapFree(GetProcessHeap(), 0, object->changed.vertexShaderConstantsF);
     HeapFree(GetProcessHeap(), 0, object->contained_vs_consts_f);
     HeapFree(GetProcessHeap(), 0, object->contained_ps_consts_f);
@@ -330,7 +319,7 @@ static void stateblock_savedstates_set_vertex(struct wined3d_saved_states *state
 
 void stateblock_init_contained_states(struct wined3d_stateblock *stateblock)
 {
-    struct wined3d_device *device = stateblock->device;
+    const struct wined3d_d3d_info *d3d_info = &stateblock->device->adapter->d3d_info;
     unsigned int i, j;
 
     for (i = 0; i <= WINEHIGHEST_RENDER_STATE >> 5; ++i)
@@ -357,7 +346,7 @@ void stateblock_init_contained_states(struct wined3d_stateblock *stateblock)
         }
     }
 
-    for (i = 0; i < device->d3d_vshader_constantF; ++i)
+    for (i = 0; i < d3d_info->limits.vs_uniform_count; ++i)
     {
         if (stateblock->changed.vertexShaderConstantsF[i])
         {
@@ -384,7 +373,7 @@ void stateblock_init_contained_states(struct wined3d_stateblock *stateblock)
         }
     }
 
-    for (i = 0; i < device->d3d_pshader_constantF; ++i)
+    for (i = 0; i < d3d_info->limits.ps_uniform_count; ++i)
     {
         if (stateblock->changed.pixelShaderConstantsF[i])
         {
@@ -467,9 +456,8 @@ ULONG CDECL wined3d_stateblock_incref(struct wined3d_stateblock *stateblock)
     return refcount;
 }
 
-void stateblock_unbind_resources(struct wined3d_stateblock *stateblock)
+void state_unbind_resources(struct wined3d_state *state)
 {
-    struct wined3d_state *state = &stateblock->state;
     struct wined3d_vertex_declaration *decl;
     struct wined3d_sampler *sampler;
     struct wined3d_texture *texture;
@@ -589,6 +577,50 @@ void stateblock_unbind_resources(struct wined3d_stateblock *stateblock)
     }
 }
 
+void state_cleanup(struct wined3d_state *state)
+{
+    unsigned int counter;
+
+    state_unbind_resources(state);
+
+    for (counter = 0; counter < LIGHTMAP_SIZE; ++counter)
+    {
+        struct list *e1, *e2;
+        LIST_FOR_EACH_SAFE(e1, e2, &state->light_map[counter])
+        {
+            struct wined3d_light_info *light = LIST_ENTRY(e1, struct wined3d_light_info, entry);
+            list_remove(&light->entry);
+            HeapFree(GetProcessHeap(), 0, light);
+        }
+    }
+
+    HeapFree(GetProcessHeap(), 0, state->vs_consts_f);
+    HeapFree(GetProcessHeap(), 0, state->ps_consts_f);
+}
+
+HRESULT state_init(struct wined3d_state *state, const struct wined3d_d3d_info *d3d_info)
+{
+    unsigned int i;
+
+    for (i = 0; i < LIGHTMAP_SIZE; i++)
+    {
+        list_init(&state->light_map[i]);
+    }
+
+    if (!(state->vs_consts_f = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+            4 * sizeof(float) * d3d_info->limits.vs_uniform_count)))
+        return E_OUTOFMEMORY;
+
+    if (!(state->ps_consts_f = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+            4 * sizeof(float) * d3d_info->limits.ps_uniform_count)))
+    {
+        HeapFree(GetProcessHeap(), 0, state->vs_consts_f);
+        return E_OUTOFMEMORY;
+    }
+
+    return WINED3D_OK;
+}
+
 ULONG CDECL wined3d_stateblock_decref(struct wined3d_stateblock *stateblock)
 {
     ULONG refcount = InterlockedDecrement(&stateblock->ref);
@@ -597,24 +629,9 @@ ULONG CDECL wined3d_stateblock_decref(struct wined3d_stateblock *stateblock)
 
     if (!refcount)
     {
-        int counter;
-
-        stateblock_unbind_resources(stateblock);
-
-        for (counter = 0; counter < LIGHTMAP_SIZE; ++counter)
-        {
-            struct list *e1, *e2;
-            LIST_FOR_EACH_SAFE(e1, e2, &stateblock->state.light_map[counter])
-            {
-                struct wined3d_light_info *light = LIST_ENTRY(e1, struct wined3d_light_info, entry);
-                list_remove(&light->entry);
-                HeapFree(GetProcessHeap(), 0, light);
-            }
-        }
+        state_cleanup(&stateblock->state);
 
-        HeapFree(GetProcessHeap(), 0, stateblock->state.vs_consts_f);
         HeapFree(GetProcessHeap(), 0, stateblock->changed.vertexShaderConstantsF);
-        HeapFree(GetProcessHeap(), 0, stateblock->state.ps_consts_f);
         HeapFree(GetProcessHeap(), 0, stateblock->changed.pixelShaderConstantsF);
         HeapFree(GetProcessHeap(), 0, stateblock->contained_vs_consts_f);
         HeapFree(GetProcessHeap(), 0, stateblock->contained_ps_consts_f);
@@ -683,7 +700,7 @@ static void wined3d_state_record_lights(struct wined3d_state *dst_state, const s
 
 void CDECL wined3d_stateblock_capture(struct wined3d_stateblock *stateblock)
 {
-    const struct wined3d_state *src_state = &stateblock->device->stateBlock->state;
+    const struct wined3d_state *src_state = &stateblock->device->state;
     unsigned int i;
     DWORD map;
 
@@ -1073,8 +1090,15 @@ void CDECL wined3d_stateblock_apply(const struct wined3d_stateblock *stateblock)
 
     if (stateblock->changed.primitive_type)
     {
-        stateblock->device->updateStateBlock->changed.primitive_type = TRUE;
-        stateblock->device->updateStateBlock->state.gl_primitive_type = stateblock->state.gl_primitive_type;
+        GLenum gl_primitive_type, prev;
+
+        if (device->recording)
+            device->recording->changed.primitive_type = TRUE;
+        gl_primitive_type = stateblock->state.gl_primitive_type;
+        prev = device->update_state->gl_primitive_type;
+        device->update_state->gl_primitive_type = gl_primitive_type;
+        if (gl_primitive_type != prev && (gl_primitive_type == GL_POINTS || prev == GL_POINTS))
+            device_invalidate_state(device, STATE_POINT_SIZE_ENABLE);
     }
 
     if (stateblock->changed.indices)
@@ -1131,12 +1155,12 @@ void CDECL wined3d_stateblock_apply(const struct wined3d_stateblock *stateblock)
         wined3d_device_set_clip_plane(device, i, &stateblock->state.clip_planes[i]);
     }
 
-    stateblock->device->stateBlock->state.lowest_disabled_stage = MAX_TEXTURES - 1;
+    stateblock->device->state.lowest_disabled_stage = MAX_TEXTURES - 1;
     for (i = 0; i < MAX_TEXTURES - 1; ++i)
     {
-        if (stateblock->device->stateBlock->state.texture_states[i][WINED3D_TSS_COLOR_OP] == WINED3D_TOP_DISABLE)
+        if (stateblock->device->state.texture_states[i][WINED3D_TSS_COLOR_OP] == WINED3D_TOP_DISABLE)
         {
-            stateblock->device->stateBlock->state.lowest_disabled_stage = i;
+            stateblock->device->state.lowest_disabled_stage = i;
             break;
         }
     }
@@ -1144,11 +1168,9 @@ void CDECL wined3d_stateblock_apply(const struct wined3d_stateblock *stateblock)
     TRACE("Applied stateblock %p.\n", stateblock);
 }
 
-void stateblock_init_default_state(struct wined3d_stateblock *stateblock)
+void state_init_default(struct wined3d_state *state, struct wined3d_device *device)
 {
-    struct wined3d_device *device = stateblock->device;
     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
-    struct wined3d_state *state = &stateblock->state;
     union
     {
         struct wined3d_line_pattern lp;
@@ -1161,11 +1183,15 @@ void stateblock_init_default_state(struct wined3d_stateblock *stateblock)
     unsigned int i;
     struct wined3d_swapchain *swapchain;
     struct wined3d_surface *backbuffer;
+    static const struct wined3d_matrix identity =
+    {{{
+        1.0f, 0.0f, 0.0f, 0.0f,
+        0.0f, 1.0f, 0.0f, 0.0f,
+        0.0f, 0.0f, 1.0f, 0.0f,
+        0.0f, 0.0f, 0.0f, 1.0f,
+    }}};
 
-    TRACE("stateblock %p.\n", stateblock);
-
-    memset(stateblock->changed.pixelShaderConstantsF, 0, device->d3d_pshader_constantF * sizeof(BOOL));
-    memset(stateblock->changed.vertexShaderConstantsF, 0, device->d3d_vshader_constantF * sizeof(BOOL));
+    TRACE("state %p, device %p.\n", state, device);
 
     /* Set some of the defaults for lights, transforms etc */
     state->transforms[WINED3D_TS_PROJECTION] = identity;
@@ -1391,42 +1417,43 @@ void stateblock_init_default_state(struct wined3d_stateblock *stateblock)
 static HRESULT stateblock_init(struct wined3d_stateblock *stateblock,
         struct wined3d_device *device, enum wined3d_stateblock_type type)
 {
-    unsigned int i;
     HRESULT hr;
+    const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
 
     stateblock->ref = 1;
     stateblock->device = device;
 
-    for (i = 0; i < LIGHTMAP_SIZE; i++)
+    if (FAILED(hr = state_init(&stateblock->state, d3d_info)))
+        return hr;
+
+    if (FAILED(hr = stateblock_allocate_shader_constants(stateblock)))
     {
-        list_init(&stateblock->state.light_map[i]);
+        state_cleanup(&stateblock->state);
+        return hr;
     }
 
-    hr = stateblock_allocate_shader_constants(stateblock);
-    if (FAILED(hr)) return hr;
-
-    /* The WINED3D_SBT_INIT stateblock type is used during initialization to
-     * produce a placeholder stateblock so other functions called can update a
-     * state block. */
-    if (type == WINED3D_SBT_INIT || type == WINED3D_SBT_RECORDED) return WINED3D_OK;
+    if (type == WINED3D_SBT_RECORDED)
+        return WINED3D_OK;
 
     TRACE("Updating changed flags appropriate for type %#x.\n", type);
 
     switch (type)
     {
         case WINED3D_SBT_ALL:
-            stateblock_init_lights(stateblock, device->stateBlock->state.light_map);
-            stateblock_savedstates_set_all(&stateblock->changed, device->d3d_vshader_constantF,
-                                           device->d3d_pshader_constantF);
+            stateblock_init_lights(stateblock, device->state.light_map);
+            stateblock_savedstates_set_all(&stateblock->changed,
+                    d3d_info->limits.vs_uniform_count, d3d_info->limits.ps_uniform_count);
             break;
 
         case WINED3D_SBT_PIXEL_STATE:
-            stateblock_savedstates_set_pixel(&stateblock->changed, device->d3d_pshader_constantF);
+            stateblock_savedstates_set_pixel(&stateblock->changed,
+                    d3d_info->limits.ps_uniform_count);
             break;
 
         case WINED3D_SBT_VERTEX_STATE:
-            stateblock_init_lights(stateblock, device->stateBlock->state.light_map);
-            stateblock_savedstates_set_vertex(&stateblock->changed, device->d3d_vshader_constantF);
+            stateblock_init_lights(stateblock, device->state.light_map);
+            stateblock_savedstates_set_vertex(&stateblock->changed,
+                    d3d_info->limits.vs_uniform_count);
             break;
 
         default:
index 12f29a4..97e5541 100644 (file)
@@ -6,7 +6,7 @@
  * Copyright 2002-2003 Raphael Junqueira
  * Copyright 2004 Christian Costa
  * Copyright 2005 Oliver Stieber
- * Copyright 2006-2011 Stefan Dösinger for CodeWeavers
+ * Copyright 2006-2011, 2013 Stefan Dösinger for CodeWeavers
  * Copyright 2007-2008 Henri Verbeet
  * Copyright 2006-2008 Roderick Colenbrander
  * Copyright 2009-2011 Henri Verbeet for CodeWeavers
@@ -31,6 +31,7 @@
 #include "wined3d_private.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface);
+WINE_DECLARE_DEBUG_CHANNEL(d3d_perf);
 WINE_DECLARE_DEBUG_CHANNEL(d3d);
 
 static HRESULT surface_cpu_blt(struct wined3d_surface *dst_surface, const RECT *dst_rect,
@@ -100,7 +101,7 @@ static void surface_cleanup(struct wined3d_surface *surface)
     }
 
     if (surface->flags & SFLAG_USERPTR)
-        wined3d_surface_set_mem(surface, NULL);
+        wined3d_surface_set_mem(surface, NULL, 0);
     if (surface->overlay_dest)
         list_remove(&surface->overlay_entry);
 
@@ -123,14 +124,11 @@ void surface_update_draw_binding(struct wined3d_surface *surface)
         surface->draw_binding = SFLAG_INTEXTURE;
 }
 
-void surface_set_container(struct wined3d_surface *surface, enum wined3d_container_type type, void *container)
+void surface_set_swapchain(struct wined3d_surface *surface, struct wined3d_swapchain *swapchain)
 {
-    TRACE("surface %p, container %p.\n", surface, container);
-
-    if (!container && type != WINED3D_CONTAINER_NONE)
-        ERR("Setting NULL container of type %#x.\n", type);
+    TRACE("surface %p, swapchain %p.\n", surface, swapchain);
 
-    if (type == WINED3D_CONTAINER_SWAPCHAIN)
+    if (swapchain)
     {
         surface->get_drawable_size = get_drawable_size_swapchain;
     }
@@ -152,8 +150,33 @@ void surface_set_container(struct wined3d_surface *surface, enum wined3d_contain
         }
     }
 
-    surface->container.type = type;
-    surface->container.u.base = container;
+    surface->swapchain = swapchain;
+    surface_update_draw_binding(surface);
+}
+
+void surface_set_container(struct wined3d_surface *surface, struct wined3d_texture *container)
+{
+    TRACE("surface %p, container %p.\n", surface, container);
+
+    if (!surface->swapchain)
+    {
+        switch (wined3d_settings.offscreen_rendering_mode)
+        {
+            case ORM_FBO:
+                surface->get_drawable_size = get_drawable_size_fbo;
+                break;
+
+            case ORM_BACKBUFFER:
+                surface->get_drawable_size = get_drawable_size_backbuffer;
+                break;
+
+            default:
+                ERR("Unhandled offscreen rendering mode %#x.\n", wined3d_settings.offscreen_rendering_mode);
+                return;
+        }
+    }
+
+    surface->container = container;
     surface_update_draw_binding(surface);
 }
 
@@ -357,9 +380,9 @@ void draw_textured_quad(const struct wined3d_surface *src_surface, struct wined3
 
     /* We changed the filtering settings on the texture. Inform the
      * container about this to get the filters reset properly next draw. */
-    if (src_surface->container.type == WINED3D_CONTAINER_TEXTURE)
+    if (src_surface->container)
     {
-        struct wined3d_texture *texture = src_surface->container.u.texture;
+        struct wined3d_texture *texture = src_surface->container;
         texture->texture_rgb.states[WINED3DTEXSTA_MAGFILTER] = WINED3D_TEXF_POINT;
         texture->texture_rgb.states[WINED3DTEXSTA_MINFILTER] = WINED3D_TEXF_POINT;
         texture->texture_rgb.states[WINED3DTEXSTA_MIPFILTER] = WINED3D_TEXF_NONE;
@@ -549,8 +572,8 @@ static void surface_load_pbo(struct wined3d_surface *surface, const struct wined
     /* We don't need the system memory anymore and we can't even use it for PBOs. */
     if (!(surface->flags & SFLAG_CLIENT))
     {
-        HeapFree(GetProcessHeap(), 0, surface->resource.heapMemory);
-        surface->resource.heapMemory = NULL;
+        wined3d_resource_free_sysmem(surface->resource.heap_memory);
+        surface->resource.heap_memory = NULL;
     }
     surface->resource.allocatedMemory = NULL;
     surface->flags |= SFLAG_PBO;
@@ -569,11 +592,10 @@ static void surface_prepare_system_memory(struct wined3d_surface *surface)
     {
         /* Whatever surface we have, make sure that there is memory allocated
          * for the downloaded copy, or a PBO to map. */
-        if (!surface->resource.heapMemory)
-            surface->resource.heapMemory = HeapAlloc(GetProcessHeap(), 0, surface->resource.size + RESOURCE_ALIGNMENT);
+        if (!surface->resource.heap_memory)
+            surface->resource.heap_memory = wined3d_resource_allocate_sysmem(surface->resource.size);
 
-        surface->resource.allocatedMemory = (BYTE *)(((ULONG_PTR)surface->resource.heapMemory
-                + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1));
+        surface->resource.allocatedMemory = surface->resource.heap_memory;
 
         if (surface->flags & SFLAG_INSYSMEM)
             ERR("Surface without memory or PBO has SFLAG_INSYSMEM set.\n");
@@ -585,9 +607,9 @@ static void surface_evict_sysmem(struct wined3d_surface *surface)
     if (surface->resource.map_count || (surface->flags & SFLAG_DONOTFREE))
         return;
 
-    HeapFree(GetProcessHeap(), 0, surface->resource.heapMemory);
+    wined3d_resource_free_sysmem(surface->resource.heap_memory);
     surface->resource.allocatedMemory = NULL;
-    surface->resource.heapMemory = NULL;
+    surface->resource.heap_memory = NULL;
     surface_modify_location(surface, SFLAG_INSYSMEM, FALSE);
 }
 
@@ -596,9 +618,9 @@ static void surface_bind(struct wined3d_surface *surface, struct wined3d_context
 {
     TRACE("surface %p, context %p, srgb %#x.\n", surface, context, srgb);
 
-    if (surface->container.type == WINED3D_CONTAINER_TEXTURE)
+    if (surface->container)
     {
-        struct wined3d_texture *texture = surface->container.u.texture;
+        struct wined3d_texture *texture = surface->container;
 
         TRACE("Passing to container (%p).\n", texture);
         texture->texture_ops->texture_bind(texture, context, srgb);
@@ -671,7 +693,6 @@ static void surface_release_client_storage(struct wined3d_surface *surface)
     struct wined3d_context *context = context_acquire(surface->resource.device, NULL);
     const struct wined3d_gl_info *gl_info = context->gl_info;
 
-    gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
     if (surface->texture_name)
     {
         surface_bind_and_dirtify(surface, context, FALSE);
@@ -684,7 +705,6 @@ static void surface_release_client_storage(struct wined3d_surface *surface)
         gl_info->gl_ops.gl.p_glTexImage2D(surface->texture_target, surface->texture_level,
                 GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
     }
-    gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
 
     context_release(context);
 
@@ -762,24 +782,6 @@ static HRESULT surface_private_setup(struct wined3d_surface *surface)
         TRACE("Creating an oversized surface: %ux%u.\n",
                 surface->pow2Width, surface->pow2Height);
     }
-    else
-    {
-        /* Don't use ARB_TEXTURE_RECTANGLE in case the surface format is P8
-         * and EXT_PALETTED_TEXTURE is used in combination with texture
-         * uploads (RTL_READTEX/RTL_TEXTEX). The reason is that
-         * EXT_PALETTED_TEXTURE doesn't work in combination with
-         * ARB_TEXTURE_RECTANGLE. */
-        if (surface->flags & SFLAG_NONPOW2 && gl_info->supported[ARB_TEXTURE_RECTANGLE]
-                && !(surface->resource.format->id == WINED3DFMT_P8_UINT
-                && gl_info->supported[EXT_PALETTED_TEXTURE]
-                && wined3d_settings.rendertargetlock_mode == RTL_READTEX))
-        {
-            surface->texture_target = GL_TEXTURE_RECTANGLE_ARB;
-            surface->pow2Width = surface->resource.width;
-            surface->pow2Height = surface->resource.height;
-            surface->flags &= ~(SFLAG_NONPOW2 | SFLAG_NORMCOORD);
-        }
-    }
 
     switch (wined3d_settings.offscreen_rendering_mode)
     {
@@ -893,6 +895,9 @@ static void surface_map(struct wined3d_surface *surface, const RECT *rect, DWORD
     }
     else
     {
+        if (surface->resource.usage & WINED3DUSAGE_DYNAMIC)
+            WARN_(d3d_perf)("Mapping a dynamic surface without WINED3D_MAP_DISCARD.\n");
+
         /* surface_load_location() does not check if the rectangle specifies
          * the full surface. Most callers don't need that, so do it here. */
         if (rect && !rect->top && !rect->left
@@ -984,8 +989,7 @@ static void surface_unmap(struct wined3d_surface *surface)
         goto done;
     }
 
-    if (surface->container.type == WINED3D_CONTAINER_SWAPCHAIN
-            && surface->container.u.swapchain->front_buffer == surface)
+    if (surface->swapchain && surface->swapchain->front_buffer == surface)
     {
         if (!surface->dirtyRect.left && !surface->dirtyRect.top
                 && surface->dirtyRect.right == surface->resource.width
@@ -1040,17 +1044,20 @@ static BOOL surface_is_full_rect(const struct wined3d_surface *surface, const RE
     return TRUE;
 }
 
-static void wined3d_surface_depth_blt_fbo(const struct wined3d_device *device, struct wined3d_surface *src_surface,
-        const RECT *src_rect, struct wined3d_surface *dst_surface, const RECT *dst_rect)
+static void surface_depth_blt_fbo(const struct wined3d_device *device,
+        struct wined3d_surface *src_surface, DWORD src_location, const RECT *src_rect,
+        struct wined3d_surface *dst_surface, DWORD dst_location, const RECT *dst_rect)
 {
     const struct wined3d_gl_info *gl_info;
     struct wined3d_context *context;
     DWORD src_mask, dst_mask;
     GLbitfield gl_mask;
 
-    TRACE("device %p, src_surface %p, src_rect %s, dst_surface %p, dst_rect %s.\n",
-            device, src_surface, wine_dbgstr_rect(src_rect),
-            dst_surface, wine_dbgstr_rect(dst_rect));
+    TRACE("device %p\n", device);
+    TRACE("src_surface %p, src_location %s, src_rect %s,\n",
+            src_surface, debug_surflocation(src_location), wine_dbgstr_rect(src_rect));
+    TRACE("dst_surface %p, dst_location %s, dst_rect %s.\n",
+            dst_surface, debug_surflocation(dst_location), wine_dbgstr_rect(dst_rect));
 
     src_mask = src_surface->resource.format->flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL);
     dst_mask = dst_surface->resource.format->flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL);
@@ -1078,9 +1085,9 @@ static void wined3d_surface_depth_blt_fbo(const struct wined3d_device *device, s
 
     /* Make sure the locations are up-to-date. Loading the destination
      * surface isn't required if the entire surface is overwritten. */
-    surface_load_location(src_surface, SFLAG_INTEXTURE, NULL);
+    surface_load_location(src_surface, src_location, NULL);
     if (!surface_is_full_rect(dst_surface, dst_rect))
-        surface_load_location(dst_surface, SFLAG_INTEXTURE, NULL);
+        surface_load_location(dst_surface, dst_location, NULL);
 
     context = context_acquire(device, NULL);
     if (!context->valid)
@@ -1092,12 +1099,10 @@ static void wined3d_surface_depth_blt_fbo(const struct wined3d_device *device, s
 
     gl_info = context->gl_info;
 
-    context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, NULL, src_surface, SFLAG_INTEXTURE);
-    gl_info->gl_ops.gl.p_glReadBuffer(GL_NONE);
-    checkGLcall("glReadBuffer()");
+    context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, NULL, src_surface, src_location);
     context_check_fbo_status(context, GL_READ_FRAMEBUFFER);
 
-    context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, NULL, dst_surface, SFLAG_INTEXTURE);
+    context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, NULL, dst_surface, dst_location);
     context_set_draw_buffer(context, GL_NONE);
     context_check_fbo_status(context, GL_DRAW_FRAMEBUFFER);
     context_invalidate_state(context, STATE_FRAMEBUFFER);
@@ -1243,7 +1248,7 @@ static void surface_blt_fbo(const struct wined3d_device *device, enum wined3d_te
 
     if (wined3d_settings.strict_draw_ordering
             || (dst_location == SFLAG_INDRAWABLE
-            && dst_surface->container.u.swapchain->front_buffer == dst_surface))
+            && dst_surface->swapchain->front_buffer == dst_surface))
         gl_info->gl_ops.gl.p_glFlush();
 
     context_release(context);
@@ -1404,8 +1409,8 @@ static HRESULT wined3d_surface_depth_fill(struct wined3d_surface *surface, const
     return blitter->depth_fill(device, surface, rect, depth);
 }
 
-static HRESULT wined3d_surface_depth_blt(struct wined3d_surface *src_surface, const RECT *src_rect,
-        struct wined3d_surface *dst_surface, const RECT *dst_rect)
+static HRESULT wined3d_surface_depth_blt(struct wined3d_surface *src_surface, DWORD src_location, const RECT *src_rect,
+        struct wined3d_surface *dst_surface, DWORD dst_location, const RECT *dst_rect)
 {
     struct wined3d_device *device = src_surface->resource.device;
 
@@ -1414,9 +1419,9 @@ static HRESULT wined3d_surface_depth_blt(struct wined3d_surface *src_surface, co
             dst_rect, dst_surface->resource.usage, dst_surface->resource.pool, dst_surface->resource.format))
         return WINED3DERR_INVALIDCALL;
 
-    wined3d_surface_depth_blt_fbo(device, src_surface, src_rect, dst_surface, dst_rect);
+    surface_depth_blt_fbo(device, src_surface, src_location, src_rect, dst_surface, dst_location, dst_rect);
 
-    surface_modify_ds_location(dst_surface, SFLAG_INTEXTURE,
+    surface_modify_ds_location(dst_surface, dst_location,
             dst_surface->ds_current_size.cx, dst_surface->ds_current_size.cy);
 
     return WINED3D_OK;
@@ -1548,25 +1553,22 @@ HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const REC
      * locking them. */
     if (dst_surface->flags & SFLAG_CONVERTED)
     {
-        WARN("Converted surface, using CPU blit.\n");
+        WARN_(d3d_perf)("Converted surface, using CPU blit.\n");
         return surface_cpu_blt(dst_surface, &dst_rect, src_surface, &src_rect, flags, fx, filter);
     }
 
     if (flags & ~simple_blit)
     {
-        WARN("Using fallback for complex blit (%#x).\n", flags);
+        WARN_(d3d_perf)("Using fallback for complex blit (%#x).\n", flags);
         goto fallback;
     }
 
-    if (src_surface && src_surface->container.type == WINED3D_CONTAINER_SWAPCHAIN)
-        src_swapchain = src_surface->container.u.swapchain;
+    if (src_surface)
+        src_swapchain = src_surface->swapchain;
     else
         src_swapchain = NULL;
 
-    if (dst_surface->container.type == WINED3D_CONTAINER_SWAPCHAIN)
-        dst_swapchain = dst_surface->container.u.swapchain;
-    else
-        dst_swapchain = NULL;
+    dst_swapchain = dst_surface->swapchain;
 
     /* This isn't strictly needed. FBO blits for example could deal with
      * cross-swapchain blits by first downloading the source to a texture
@@ -1612,7 +1614,8 @@ HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const REC
                 return WINED3DERR_INVALIDCALL;
             }
 
-            if (SUCCEEDED(wined3d_surface_depth_blt(src_surface, &src_rect, dst_surface, &dst_rect)))
+            if (SUCCEEDED(wined3d_surface_depth_blt(src_surface, src_surface->draw_binding, &src_rect,
+                    dst_surface, dst_surface->draw_binding, &dst_rect)))
                 return WINED3D_OK;
         }
     }
@@ -1756,14 +1759,13 @@ static void surface_remove_pbo(struct wined3d_surface *surface, const struct win
     }
     else
     {
-        if (!surface->resource.heapMemory)
-            surface->resource.heapMemory = HeapAlloc(GetProcessHeap(), 0, surface->resource.size + RESOURCE_ALIGNMENT);
+        if (!surface->resource.heap_memory)
+            surface->resource.heap_memory = wined3d_resource_allocate_sysmem(surface->resource.size);
         else if (!(surface->flags & SFLAG_CLIENT))
-            ERR("Surface %p has heapMemory %p and flags %#x.\n",
-                    surface, surface->resource.heapMemory, surface->flags);
+            ERR("Surface %p has heap_memory %p and flags %#x.\n",
+                    surface, surface->resource.heap_memory, surface->flags);
 
-        surface->resource.allocatedMemory = (BYTE *)(((ULONG_PTR)surface->resource.heapMemory
-                + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1));
+        surface->resource.allocatedMemory = surface->resource.heap_memory;
     }
 
     GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, surface->pbo));
@@ -1782,10 +1784,10 @@ static BOOL surface_init_sysmem(struct wined3d_surface *surface)
 {
     if (!surface->resource.allocatedMemory)
     {
-        if (!surface->resource.heapMemory)
+        if (!surface->resource.heap_memory)
         {
-            if (!(surface->resource.heapMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
-                    surface->resource.size + RESOURCE_ALIGNMENT)))
+            surface->resource.heap_memory = wined3d_resource_allocate_sysmem(surface->resource.size);
+            if (!surface->resource.heap_memory)
             {
                 ERR("Failed to allocate memory.\n");
                 return FALSE;
@@ -1793,12 +1795,11 @@ static BOOL surface_init_sysmem(struct wined3d_surface *surface)
         }
         else if (!(surface->flags & SFLAG_CLIENT))
         {
-            ERR("Surface %p has heapMemory %p and flags %#x.\n",
-                    surface, surface->resource.heapMemory, surface->flags);
+            ERR("Surface %p has heap_memory %p and flags %#x.\n",
+                    surface, surface->resource.heap_memory, surface->flags);
         }
 
-        surface->resource.allocatedMemory =
-            (BYTE *)(((ULONG_PTR)surface->resource.heapMemory + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1));
+        surface->resource.allocatedMemory = surface->resource.heap_memory;
     }
     else
     {
@@ -1873,7 +1874,7 @@ static void surface_unload(struct wined3d_resource *resource)
 
     /* If we're in a texture, the texture name belongs to the texture.
      * Otherwise, destroy it. */
-    if (surface->container.type != WINED3D_CONTAINER_TEXTURE)
+    if (!surface->container)
     {
         gl_info->gl_ops.gl.p_glDeleteTextures(1, &surface->texture_name);
         surface->texture_name = 0;
@@ -1941,8 +1942,8 @@ static HRESULT gdi_surface_private_setup(struct wined3d_surface *surface)
     hr = surface_create_dib_section(surface);
     if (SUCCEEDED(hr))
     {
-        HeapFree(GetProcessHeap(), 0, surface->resource.heapMemory);
-        surface->resource.heapMemory = NULL;
+        wined3d_resource_free_sysmem(surface->resource.heap_memory);
+        surface->resource.heap_memory = NULL;
         surface->resource.allocatedMemory = surface->dib.bitmap_data;
     }
 
@@ -1981,14 +1982,8 @@ static void gdi_surface_realize_palette(struct wined3d_surface *surface)
     /* Update the image because of the palette change. Some games like e.g.
      * Red Alert call SetEntries a lot to implement fading. */
     /* Tell the swapchain to update the screen. */
-    if (surface->container.type == WINED3D_CONTAINER_SWAPCHAIN)
-    {
-        struct wined3d_swapchain *swapchain = surface->container.u.swapchain;
-        if (surface == swapchain->front_buffer)
-        {
-            x11_copy_to_screen(swapchain, NULL);
-        }
-    }
+    if (surface->swapchain && surface == surface->swapchain->front_buffer)
+        x11_copy_to_screen(surface->swapchain, NULL);
 }
 
 static void gdi_surface_map(struct wined3d_surface *surface, const RECT *rect, DWORD flags)
@@ -2007,8 +2002,8 @@ static void gdi_surface_map(struct wined3d_surface *surface, const RECT *rect, D
             ERR("Failed to create dib section, hr %#x.\n", hr);
             return;
         }
-        HeapFree(GetProcessHeap(), 0, surface->resource.heapMemory);
-        surface->resource.heapMemory = NULL;
+        wined3d_resource_free_sysmem(surface->resource.heap_memory);
+        surface->resource.heap_memory = NULL;
         surface->resource.allocatedMemory = surface->dib.bitmap_data;
     }
 }
@@ -2018,14 +2013,8 @@ static void gdi_surface_unmap(struct wined3d_surface *surface)
     TRACE("surface %p.\n", surface);
 
     /* Tell the swapchain to update the screen. */
-    if (surface->container.type == WINED3D_CONTAINER_SWAPCHAIN)
-    {
-        struct wined3d_swapchain *swapchain = surface->container.u.swapchain;
-        if (surface == swapchain->front_buffer)
-        {
-            x11_copy_to_screen(swapchain, &surface->lockedRect);
-        }
-    }
+    if (surface->swapchain && surface == surface->swapchain->front_buffer)
+        x11_copy_to_screen(surface->swapchain, &surface->lockedRect);
 
     memset(&surface->lockedRect, 0, sizeof(RECT));
 }
@@ -2234,12 +2223,11 @@ static void surface_download_data(struct wined3d_surface *surface, const struct
             src_data = mem;
             dst_data = surface->resource.allocatedMemory;
             TRACE("(%p) : Repacking the surface data from pitch %d to pitch %d\n", surface, src_pitch, dst_pitch);
-            for (y = 1; y < surface->resource.height; ++y)
+            for (y = 0; y < surface->resource.height; ++y)
             {
-                /* skip the first row */
+                memcpy(dst_data, src_data, dst_pitch);
                 src_data += src_pitch;
                 dst_data += dst_pitch;
-                memcpy(dst_data, src_data, dst_pitch);
             }
 
             HeapFree(GetProcessHeap(), 0, mem);
@@ -2284,7 +2272,7 @@ static void surface_upload_data(struct wined3d_surface *surface, const struct wi
 
     if (format->flags & WINED3DFMT_FLAG_COMPRESSED)
     {
-        UINT row_length = wined3d_format_calculate_size(format, 1, update_w, 1);
+        UINT row_length = wined3d_format_calculate_size(format, 1, update_w, 1, 1);
         UINT row_count = (update_h + format->block_height - 1) / format->block_height;
         const BYTE *addr = data->addr;
         GLenum internal;
@@ -2393,7 +2381,7 @@ static HRESULT d3dfmt_get_conv(const struct wined3d_surface *surface, BOOL need_
                     &rect, surface->resource.usage, surface->resource.pool, surface->resource.format,
                     &rect, surface->resource.usage, surface->resource.pool, surface->resource.format);
 #endif
-            blit_supported = gl_info->supported[EXT_PALETTED_TEXTURE] || gl_info->supported[ARB_FRAGMENT_PROGRAM];
+            blit_supported = gl_info->supported[ARB_FRAGMENT_PROGRAM];
 
             /* Use conversion when the blit_shader backend supports it. It only supports this in case of
              * texturing. Further also use conversion in case of color keying.
@@ -2631,7 +2619,7 @@ HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const P
 static void surface_allocate_surface(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info,
         const struct wined3d_format *format, BOOL srgb)
 {
-    BOOL enable_client_storage = FALSE;
+    BOOL disable_client_storage = FALSE;
     GLsizei width = surface->pow2Width;
     GLsizei height = surface->pow2Height;
     const BYTE *mem = NULL;
@@ -2674,10 +2662,7 @@ static void surface_allocate_surface(struct wined3d_surface *surface, const stru
              * SFLAG_CONVERTED: The conversion destination memory is freed after loading the surface
              * allocatedMemory == NULL: Not defined in the extension. Seems to disable client storage effectively
              */
-            gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
-            checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
             surface->flags &= ~SFLAG_CLIENT;
-            enable_client_storage = TRUE;
         }
         else
         {
@@ -2685,9 +2670,12 @@ static void surface_allocate_surface(struct wined3d_surface *surface, const stru
 
             /* Point OpenGL to our allocated texture memory. Do not use
              * resource.allocatedMemory here because it might point into a
-             * PBO. Instead use heapMemory, but get the alignment right. */
-            mem = (BYTE *)(((ULONG_PTR)surface->resource.heapMemory
-                    + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1));
+             * PBO. Instead use heap_memory. */
+            mem = surface->resource.heap_memory;
+
+            gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
+            checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
+            disable_client_storage = TRUE;
         }
     }
 
@@ -2704,10 +2692,10 @@ static void surface_allocate_surface(struct wined3d_surface *surface, const stru
         checkGLcall("glTexImage2D");
     }
 
-    if (enable_client_storage)
+    if (disable_client_storage)
     {
-        gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
-        checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
+        gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
+        checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
     }
 }
 
@@ -2780,11 +2768,11 @@ void surface_set_compatible_renderbuffer(struct wined3d_surface *surface, const
 
 GLenum surface_get_gl_buffer(const struct wined3d_surface *surface)
 {
-    const struct wined3d_swapchain *swapchain = surface->container.u.swapchain;
+    const struct wined3d_swapchain *swapchain = surface->swapchain;
 
     TRACE("surface %p.\n", surface);
 
-    if (surface->container.type != WINED3D_CONTAINER_SWAPCHAIN)
+    if (!swapchain)
     {
         ERR("Surface %p is not on a swapchain.\n", surface);
         return GL_NONE;
@@ -2836,10 +2824,10 @@ void surface_add_dirty_rect(struct wined3d_surface *surface, const struct wined3
     }
 
     /* if the container is a texture then mark it dirty. */
-    if (surface->container.type == WINED3D_CONTAINER_TEXTURE)
+    if (surface->container)
     {
         TRACE("Passing to container.\n");
-        wined3d_texture_set_dirty(surface->container.u.texture, TRUE);
+        wined3d_texture_set_dirty(surface->container, TRUE);
     }
 }
 
@@ -2961,22 +2949,14 @@ ULONG CDECL wined3d_surface_incref(struct wined3d_surface *surface)
 {
     ULONG refcount;
 
-    TRACE("Surface %p, container %p of type %#x.\n",
-            surface, surface->container.u.base, surface->container.type);
+    TRACE("surface %p, swapchain %p, container %p.\n",
+            surface, surface->swapchain, surface->container);
 
-    switch (surface->container.type)
-    {
-        case WINED3D_CONTAINER_TEXTURE:
-            return wined3d_texture_incref(surface->container.u.texture);
+    if (surface->swapchain)
+        return wined3d_swapchain_incref(surface->swapchain);
 
-        case WINED3D_CONTAINER_SWAPCHAIN:
-            return wined3d_swapchain_incref(surface->container.u.swapchain);
-
-        default:
-            ERR("Unhandled container type %#x.\n", surface->container.type);
-        case WINED3D_CONTAINER_NONE:
-            break;
-    }
+    if (surface->container)
+        return wined3d_texture_incref(surface->container);
 
     refcount = InterlockedIncrement(&surface->resource.ref);
     TRACE("%p increasing refcount to %u.\n", surface, refcount);
@@ -2989,22 +2969,14 @@ ULONG CDECL wined3d_surface_decref(struct wined3d_surface *surface)
 {
     ULONG refcount;
 
-    TRACE("Surface %p, container %p of type %#x.\n",
-            surface, surface->container.u.base, surface->container.type);
+    TRACE("surface %p, swapchain %p, container %p.\n",
+            surface, surface->swapchain, surface->container);
 
-    switch (surface->container.type)
-    {
-        case WINED3D_CONTAINER_TEXTURE:
-            return wined3d_texture_decref(surface->container.u.texture);
+    if (surface->swapchain)
+        return wined3d_swapchain_decref(surface->swapchain);
 
-        case WINED3D_CONTAINER_SWAPCHAIN:
-            return wined3d_swapchain_decref(surface->container.u.swapchain);
-
-        default:
-            ERR("Unhandled container type %#x.\n", surface->container.type);
-        case WINED3D_CONTAINER_NONE:
-            break;
-    }
+    if (surface->container)
+        return wined3d_texture_decref(surface->container);
 
     refcount = InterlockedDecrement(&surface->resource.ref);
     TRACE("%p decreasing refcount to %u.\n", surface, refcount);
@@ -3206,6 +3178,9 @@ DWORD CDECL wined3d_surface_get_pitch(const struct wined3d_surface *surface)
 
     TRACE("surface %p.\n", surface);
 
+    if (surface->pitch)
+        return surface->pitch;
+
     if (format->flags & WINED3DFMT_FLAG_BLOCKS)
     {
         /* Since compressed formats are block based, pitch means the amount of
@@ -3225,7 +3200,7 @@ DWORD CDECL wined3d_surface_get_pitch(const struct wined3d_surface *surface)
     return pitch;
 }
 
-HRESULT CDECL wined3d_surface_set_mem(struct wined3d_surface *surface, void *mem)
+HRESULT CDECL wined3d_surface_set_mem(struct wined3d_surface *surface, void *mem, UINT pitch)
 {
     TRACE("surface %p, mem %p.\n", surface, mem);
 
@@ -3258,8 +3233,8 @@ HRESULT CDECL wined3d_surface_set_mem(struct wined3d_surface *surface, void *mem
         }
         else if (!(surface->flags & SFLAG_USERPTR))
         {
-            release = surface->resource.heapMemory;
-            surface->resource.heapMemory = NULL;
+            release = surface->resource.heap_memory;
+            surface->resource.heap_memory = NULL;
         }
         surface->resource.allocatedMemory = mem;
         surface->flags |= SFLAG_USERPTR;
@@ -3272,12 +3247,12 @@ HRESULT CDECL wined3d_surface_set_mem(struct wined3d_surface *surface, void *mem
             surface_release_client_storage(surface);
 
         /* Now free the old memory if any. */
-        HeapFree(GetProcessHeap(), 0, release);
+        wined3d_resource_free_sysmem(release);
     }
     else if (surface->flags & SFLAG_USERPTR)
     {
-        /* HeapMemory should be NULL already. */
-        if (surface->resource.heapMemory)
+        /* heap_memory should be NULL already. */
+        if (surface->resource.heap_memory)
             ERR("User pointer surface has heap memory allocated.\n");
 
         if (!mem)
@@ -3294,6 +3269,8 @@ HRESULT CDECL wined3d_surface_set_mem(struct wined3d_surface *surface, void *mem
         surface_modify_location(surface, SFLAG_INSYSMEM, TRUE);
     }
 
+    surface->pitch = pitch;
+
     return WINED3D_OK;
 }
 
@@ -3438,7 +3415,7 @@ HRESULT CDECL wined3d_surface_update_desc(struct wined3d_surface *surface,
     struct wined3d_device *device = surface->resource.device;
     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
     const struct wined3d_format *format = wined3d_get_format(gl_info, format_id);
-    UINT resource_size = wined3d_format_calculate_size(format, device->surface_alignment, width, height);
+    UINT resource_size = wined3d_format_calculate_size(format, device->surface_alignment, width, height, 1);
 
     TRACE("surface %p, width %u, height %u, format %s, multisample_type %#x, multisample_quality %u.\n",
             surface, width, height, debug_d3dformat(format_id), multisample_type, multisample_type);
@@ -3459,8 +3436,8 @@ HRESULT CDECL wined3d_surface_update_desc(struct wined3d_surface *surface,
 
     surface->flags &= ~(SFLAG_LOCATIONS | SFLAG_USERPTR);
     surface->resource.allocatedMemory = NULL;
-    HeapFree(GetProcessHeap(), 0, surface->resource.heapMemory);
-    surface->resource.heapMemory = NULL;
+    wined3d_resource_free_sysmem(surface->resource.heap_memory);
+    surface->resource.heap_memory = NULL;
 
     surface->resource.width = width;
     surface->resource.height = height;
@@ -3759,7 +3736,7 @@ static HRESULT _Blt_ColorFill(BYTE *buf, unsigned int width, unsigned int height
         unsigned int bpp, UINT pitch, DWORD color)
 {
     BYTE *first;
-    int x, y;
+    unsigned int x, y;
 
     /* Do first row */
 
@@ -3956,8 +3933,8 @@ HRESULT CDECL wined3d_surface_getdc(struct wined3d_surface *surface, HDC *dc)
         /* Use the DIB section from now on if we are not using a PBO. */
         if (!(surface->flags & (SFLAG_PBO | SFLAG_PIN_SYSMEM)))
         {
-            HeapFree(GetProcessHeap(), 0, surface->resource.heapMemory);
-            surface->resource.heapMemory = NULL;
+            wined3d_resource_free_sysmem(surface->resource.heap_memory);
+            surface->resource.heap_memory = NULL;
             surface->resource.allocatedMemory = surface->dib.bitmap_data;
         }
     }
@@ -4059,7 +4036,7 @@ HRESULT CDECL wined3d_surface_flip(struct wined3d_surface *surface, struct wined
             WARN("Ignoring flags %#x.\n", flags);
     }
 
-    if (surface->container.type == WINED3D_CONTAINER_SWAPCHAIN)
+    if (surface->swapchain)
     {
         ERR("Not supported on swapchain surfaces.\n");
         return WINEDDERR_NOTFLIPPABLE;
@@ -4088,9 +4065,9 @@ void surface_internal_preload(struct wined3d_surface *surface, enum WINED3DSRGB
 
     TRACE("iface %p, srgb %#x.\n", surface, srgb);
 
-    if (surface->container.type == WINED3D_CONTAINER_TEXTURE)
+    if (surface->container)
     {
-        struct wined3d_texture *texture = surface->container.u.texture;
+        struct wined3d_texture *texture = surface->container;
 
         TRACE("Passing to container (%p).\n", texture);
         texture->texture_ops->texture_preload(texture, srgb);
@@ -4416,9 +4393,9 @@ static void surface_prepare_texture_internal(struct wined3d_surface *surface,
 /* Context activation is done by the caller. */
 void surface_prepare_texture(struct wined3d_surface *surface, struct wined3d_context *context, BOOL srgb)
 {
-    if (surface->container.type == WINED3D_CONTAINER_TEXTURE)
+    if (surface->container)
     {
-        struct wined3d_texture *texture = surface->container.u.texture;
+        struct wined3d_texture *texture = surface->container;
         UINT sub_count = texture->level_count * texture->layer_count;
         UINT i;
 
@@ -4462,77 +4439,6 @@ void surface_prepare_rb(struct wined3d_surface *surface, const struct wined3d_gl
     }
 }
 
-static void flush_to_framebuffer_drawpixels(struct wined3d_surface *surface,
-        const RECT *rect, GLenum fmt, GLenum type, UINT bpp, const BYTE *mem)
-{
-    struct wined3d_device *device = surface->resource.device;
-    UINT pitch = wined3d_surface_get_pitch(surface);
-    const struct wined3d_gl_info *gl_info;
-    struct wined3d_context *context;
-    RECT local_rect;
-    UINT w, h;
-
-    surface_get_rect(surface, rect, &local_rect);
-
-    mem += local_rect.top * pitch + local_rect.left * bpp;
-    w = local_rect.right - local_rect.left;
-    h = local_rect.bottom - local_rect.top;
-
-    /* Activate the correct context for the render target */
-    context = context_acquire(device, surface);
-    context_apply_blit_state(context, device);
-    gl_info = context->gl_info;
-
-    if (!surface_is_offscreen(surface))
-    {
-        GLenum buffer = surface_get_gl_buffer(surface);
-        TRACE("Unlocking %#x buffer.\n", buffer);
-        context_set_draw_buffer(context, buffer);
-
-        surface_translate_drawable_coords(surface, context->win_handle, &local_rect);
-        gl_info->gl_ops.gl.p_glPixelZoom(1.0f, -1.0f);
-    }
-    else
-    {
-        /* Primary offscreen render target */
-        TRACE("Offscreen render target.\n");
-        context_set_draw_buffer(context, device->offscreenBuffer);
-
-        gl_info->gl_ops.gl.p_glPixelZoom(1.0f, 1.0f);
-    }
-
-    gl_info->gl_ops.gl.p_glRasterPos3i(local_rect.left, local_rect.top, 1);
-    checkGLcall("glRasterPos3i");
-
-    /* If not fullscreen, we need to skip a number of bytes to find the next row of data */
-    gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_ROW_LENGTH, surface->resource.width);
-
-    if (surface->flags & SFLAG_PBO)
-    {
-        GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, surface->pbo));
-        checkGLcall("glBindBufferARB");
-    }
-
-    gl_info->gl_ops.gl.p_glDrawPixels(w, h, fmt, type, mem);
-    checkGLcall("glDrawPixels");
-
-    if (surface->flags & SFLAG_PBO)
-    {
-        GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
-        checkGLcall("glBindBufferARB");
-    }
-
-    gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
-    checkGLcall("glPixelStorei(GL_UNPACK_ROW_LENGTH, 0)");
-
-    if (wined3d_settings.strict_draw_ordering
-            || (surface->container.type == WINED3D_CONTAINER_SWAPCHAIN
-            && surface->container.u.swapchain->front_buffer == surface))
-        gl_info->gl_ops.gl.p_glFlush();
-
-    context_release(context);
-}
-
 static BOOL color_in_range(const struct wined3d_color_key *color_key, DWORD color)
 {
     /* FIXME: Is this really how color keys are supposed to work? I think it
@@ -4557,7 +4463,7 @@ void d3dfmt_p8_init_palette(const struct wined3d_surface *surface, BYTE table[25
 
     if (!pal)
     {
-        ERR("This code should never get entered for DirectDraw!, expect problems\n");
+        FIXME("No palette set.\n");
         if (index_in_alpha)
         {
             /* Guarantees that memory representation remains correct after sysmem<->texture transfers even if
@@ -4787,9 +4693,9 @@ void flip_surface(struct wined3d_surface *front, struct wined3d_surface *back)
         front->resource.allocatedMemory = back->resource.allocatedMemory;
         back->resource.allocatedMemory = tmp;
 
-        tmp = front->resource.heapMemory;
-        front->resource.heapMemory = back->resource.heapMemory;
-        back->resource.heapMemory = tmp;
+        tmp = front->resource.heap_memory;
+        front->resource.heap_memory = back->resource.heap_memory;
+        back->resource.heap_memory = tmp;
     }
 
     /* Flip the PBO */
@@ -4838,14 +4744,13 @@ static void fb_copy_to_texture_direct(struct wined3d_surface *dst_surface, struc
     struct wined3d_device *device = dst_surface->resource.device;
     const struct wined3d_gl_info *gl_info;
     float xrel, yrel;
-    UINT row;
     struct wined3d_context *context;
     BOOL upsidedown = FALSE;
     RECT dst_rect = *dst_rect_in;
     GLenum dst_target;
 
-    if (dst_surface->container.type == WINED3D_CONTAINER_TEXTURE)
-        dst_target = dst_surface->container.u.texture->target;
+    if (dst_surface->container)
+        dst_target = dst_surface->container->target;
     else
         dst_target = dst_surface->texture_target;
 
@@ -4906,6 +4811,7 @@ static void fb_copy_to_texture_direct(struct wined3d_surface *dst_surface, struc
     }
     else
     {
+        LONG row;
         UINT yoffset = src_surface->resource.height - src_rect->top + dst_rect.top - 1;
         /* I have to process this row by row to swap the image,
          * otherwise it would be upside down, so stretching in y direction
@@ -4919,7 +4825,7 @@ static void fb_copy_to_texture_direct(struct wined3d_surface *dst_surface, struc
                 /* Well, that stuff works, but it's very slow.
                  * find a better way instead
                  */
-                UINT col;
+                LONG col;
 
                 for (col = dst_rect.left; col < dst_rect.right; ++col)
                 {
@@ -4951,7 +4857,6 @@ static void fb_copy_to_texture_hwstretch(struct wined3d_surface *dst_surface, st
         const RECT *src_rect, const RECT *dst_rect_in, enum wined3d_texture_filter_type filter)
 {
     struct wined3d_device *device = dst_surface->resource.device;
-    struct wined3d_swapchain *src_swapchain = NULL;
     GLuint src, backup = 0;
     float left, right, top, bottom; /* Texture coordinates */
     UINT fbwidth = src_surface->resource.width;
@@ -5049,9 +4954,7 @@ static void fb_copy_to_texture_hwstretch(struct wined3d_surface *dst_surface, st
             wined3d_gl_min_mip_filter(minMipLookup, filter, WINED3D_TEXF_NONE));
     checkGLcall("glTexParameteri");
 
-    if (src_surface->container.type == WINED3D_CONTAINER_SWAPCHAIN)
-        src_swapchain = src_surface->container.u.swapchain;
-    if (!src_swapchain || src_surface == src_swapchain->back_buffers[0])
+    if (!src_surface->swapchain || src_surface == src_surface->swapchain->back_buffers[0])
     {
         src = backup ? backup : src_surface->texture_name;
     }
@@ -5230,8 +5133,7 @@ void surface_translate_drawable_coords(const struct wined3d_surface *surface, HW
 {
     UINT drawable_height;
 
-    if (surface->container.type == WINED3D_CONTAINER_SWAPCHAIN
-            && surface == surface->container.u.swapchain->front_buffer)
+    if (surface->swapchain && surface == surface->swapchain->front_buffer)
     {
         POINT offset = {0, 0};
         RECT windowsize;
@@ -5312,8 +5214,7 @@ static void surface_blt_to_drawable(const struct wined3d_device *device,
     device->blitter->unset_shader(context->gl_info);
 
     if (wined3d_settings.strict_draw_ordering
-            || (dst_surface->container.type == WINED3D_CONTAINER_SWAPCHAIN
-            && (dst_surface->container.u.swapchain->front_buffer == dst_surface)))
+            || (dst_surface->swapchain && dst_surface->swapchain->front_buffer == dst_surface))
         gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */
 
     context_release(context);
@@ -5343,7 +5244,7 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(struct wined3d_surface *dst_surfa
 {
     struct wined3d_device *device = dst_surface->resource.device;
     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
-    struct wined3d_swapchain *srcSwapchain = NULL, *dstSwapchain = NULL;
+    struct wined3d_swapchain *src_swapchain, *dst_swapchain;
 
     TRACE("dst_surface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, blt_fx %p, filter %s.\n",
             dst_surface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect),
@@ -5356,8 +5257,7 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(struct wined3d_surface *dst_surfa
         return WINED3DERR_INVALIDCALL;
     }
 
-    if (dst_surface->container.type == WINED3D_CONTAINER_SWAPCHAIN)
-        dstSwapchain = dst_surface->container.u.swapchain;
+    dst_swapchain = dst_surface->swapchain;
 
     if (src_surface)
     {
@@ -5367,12 +5267,15 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(struct wined3d_surface *dst_surfa
             return WINED3DERR_INVALIDCALL;
         }
 
-        if (src_surface->container.type == WINED3D_CONTAINER_SWAPCHAIN)
-            srcSwapchain = src_surface->container.u.swapchain;
+        src_swapchain = src_surface->swapchain;
+    }
+    else
+    {
+        src_swapchain = NULL;
     }
 
     /* Early sort out of cases where no render target is used */
-    if (!dstSwapchain && !srcSwapchain
+    if (!dst_swapchain && !src_swapchain
             && src_surface != device->fb.render_targets[0]
             && dst_surface != device->fb.render_targets[0])
     {
@@ -5388,31 +5291,31 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(struct wined3d_surface *dst_surfa
         return WINED3DERR_INVALIDCALL;
     }
 
-    if (dstSwapchain && dstSwapchain == srcSwapchain)
+    if (dst_swapchain && dst_swapchain == src_swapchain)
     {
         FIXME("Implement hardware blit between two surfaces on the same swapchain\n");
         return WINED3DERR_INVALIDCALL;
     }
 
-    if (dstSwapchain && srcSwapchain)
+    if (dst_swapchain && src_swapchain)
     {
         FIXME("Implement hardware blit between two different swapchains\n");
         return WINED3DERR_INVALIDCALL;
     }
 
-    if (dstSwapchain)
+    if (dst_swapchain)
     {
         /* Handled with regular texture -> swapchain blit */
         if (src_surface == device->fb.render_targets[0])
             TRACE("Blit from active render target to a swapchain\n");
     }
-    else if (srcSwapchain && dst_surface == device->fb.render_targets[0])
+    else if (src_swapchain && dst_surface == device->fb.render_targets[0])
     {
         FIXME("Implement blit from a swapchain to the active render target\n");
         return WINED3DERR_INVALIDCALL;
     }
 
-    if ((srcSwapchain || src_surface == device->fb.render_targets[0]) && !dstSwapchain)
+    if ((src_swapchain || src_surface == device->fb.render_targets[0]) && !dst_swapchain)
     {
         /* Blit from render target to texture */
         BOOL stretchx;
@@ -5461,9 +5364,9 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(struct wined3d_surface *dst_surfa
 
         if (!dst_surface->resource.map_count && !(dst_surface->flags & SFLAG_DONOTFREE))
         {
-            HeapFree(GetProcessHeap(), 0, dst_surface->resource.heapMemory);
+            wined3d_resource_free_sysmem(dst_surface->resource.heap_memory);
             dst_surface->resource.allocatedMemory = NULL;
-            dst_surface->resource.heapMemory = NULL;
+            dst_surface->resource.heap_memory = NULL;
         }
         else
         {
@@ -5599,10 +5502,10 @@ void surface_modify_ds_location(struct wined3d_surface *surface,
     if (((surface->flags & SFLAG_INTEXTURE) && !(location & SFLAG_INTEXTURE))
             || (!(surface->flags & SFLAG_INTEXTURE) && (location & SFLAG_INTEXTURE)))
     {
-        if (surface->container.type == WINED3D_CONTAINER_TEXTURE)
+        if (surface->container)
         {
             TRACE("Passing to container.\n");
-            wined3d_texture_set_dirty(surface->container.u.texture, TRUE);
+            wined3d_texture_set_dirty(surface->container, TRUE);
         }
     }
 
@@ -5734,7 +5637,6 @@ void surface_load_ds_location(struct wined3d_surface *surface, struct wined3d_co
         context_apply_fbo_state_blit(context, GL_FRAMEBUFFER,
                 NULL, surface, SFLAG_INTEXTURE);
         context_set_draw_buffer(context, GL_NONE);
-        gl_info->gl_ops.gl.p_glReadBuffer(GL_NONE);
 
         /* Do the actual blit */
         surface_depth_blt(surface, context, device->depth_blt_texture, 0, 0, w, h, bind_target);
@@ -5792,10 +5694,10 @@ void surface_modify_location(struct wined3d_surface *surface, DWORD location, BO
         if (((surface->flags & SFLAG_INTEXTURE) && !(location & SFLAG_INTEXTURE))
                 || ((surface->flags & SFLAG_INSRGBTEX) && !(location & SFLAG_INSRGBTEX)))
         {
-            if (surface->container.type == WINED3D_CONTAINER_TEXTURE)
+            if (surface->container)
             {
                 TRACE("Passing to container.\n");
-                wined3d_texture_set_dirty(surface->container.u.texture, TRUE);
+                wined3d_texture_set_dirty(surface->container, TRUE);
             }
         }
         surface->flags &= ~SFLAG_LOCATIONS;
@@ -5814,10 +5716,10 @@ void surface_modify_location(struct wined3d_surface *surface, DWORD location, BO
     {
         if ((surface->flags & (SFLAG_INTEXTURE | SFLAG_INSRGBTEX)) && (location & (SFLAG_INTEXTURE | SFLAG_INSRGBTEX)))
         {
-            if (surface->container.type == WINED3D_CONTAINER_TEXTURE)
+            if (surface->container)
             {
                 TRACE("Passing to container\n");
-                wined3d_texture_set_dirty(surface->container.u.texture, TRUE);
+                wined3d_texture_set_dirty(surface->container, TRUE);
             }
         }
         surface->flags &= ~location;
@@ -5888,11 +5790,7 @@ static void surface_load_sysmem(struct wined3d_surface *surface,
 static HRESULT surface_load_drawable(struct wined3d_surface *surface,
         const struct wined3d_gl_info *gl_info, const RECT *rect)
 {
-    struct wined3d_device *device = surface->resource.device;
-    enum wined3d_conversion_type convert;
-    struct wined3d_format format;
-    UINT byte_count;
-    BYTE *mem;
+    RECT r;
 
     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && surface_is_offscreen(surface))
     {
@@ -5900,82 +5798,10 @@ static HRESULT surface_load_drawable(struct wined3d_surface *surface,
         return WINED3DERR_INVALIDCALL;
     }
 
-    if (wined3d_settings.rendertargetlock_mode == RTL_READTEX)
-        surface_load_location(surface, SFLAG_INTEXTURE, NULL);
-
-    if (surface->flags & SFLAG_INTEXTURE)
-    {
-        RECT r;
-
-        surface_get_rect(surface, rect, &r);
-        surface_blt_to_drawable(device, WINED3D_TEXF_POINT, FALSE, surface, &r, surface, &r);
-
-        return WINED3D_OK;
-    }
-
-    if ((surface->flags & SFLAG_LOCATIONS) == SFLAG_INSRGBTEX)
-    {
-        /* This needs colorspace conversion from sRGB to RGB. We take the slow
-         * path through sysmem. */
-        surface_load_location(surface, SFLAG_INSYSMEM, rect);
-    }
-
-    d3dfmt_get_conv(surface, FALSE, FALSE, &format, &convert);
-
-    /* Don't use PBOs for converted surfaces. During PBO conversion we look at
-     * SFLAG_CONVERTED but it isn't set (yet) in all cases where it is getting
-     * called. */
-    if ((convert != WINED3D_CT_NONE) && (surface->flags & SFLAG_PBO))
-    {
-        struct wined3d_context *context;
-
-        TRACE("Removing the pbo attached to surface %p.\n", surface);
-
-        /* TODO: Use already acquired context when possible. */
-        context = context_acquire(device, NULL);
-
-        surface_remove_pbo(surface, gl_info);
-
-        context_release(context);
-    }
-
-    if ((convert != WINED3D_CT_NONE) && surface->resource.allocatedMemory)
-    {
-        UINT height = surface->resource.height;
-        UINT width = surface->resource.width;
-        UINT src_pitch, dst_pitch;
-
-        byte_count = format.conv_byte_count;
-        src_pitch = wined3d_surface_get_pitch(surface);
-
-        /* Stick to the alignment for the converted surface too, makes it
-         * easier to load the surface. */
-        dst_pitch = width * byte_count;
-        dst_pitch = (dst_pitch + device->surface_alignment - 1) & ~(device->surface_alignment - 1);
-
-        if (!(mem = HeapAlloc(GetProcessHeap(), 0, dst_pitch * height)))
-        {
-            ERR("Out of memory (%u).\n", dst_pitch * height);
-            return E_OUTOFMEMORY;
-        }
-
-        d3dfmt_convert_surface(surface->resource.allocatedMemory, mem,
-                src_pitch, width, height, dst_pitch, convert, surface);
-
-        surface->flags |= SFLAG_CONVERTED;
-    }
-    else
-    {
-        surface->flags &= ~SFLAG_CONVERTED;
-        mem = surface->resource.allocatedMemory;
-        byte_count = format.byte_count;
-    }
-
-    flush_to_framebuffer_drawpixels(surface, rect, format.glFormat, format.glType, byte_count, mem);
-
-    /* Don't delete PBO memory. */
-    if ((mem != surface->resource.allocatedMemory) && !(surface->flags & SFLAG_PBO))
-        HeapFree(GetProcessHeap(), 0, mem);
+    surface_get_rect(surface, rect, &r);
+    surface_load_location(surface, SFLAG_INTEXTURE, NULL);
+    surface_blt_to_drawable(surface->resource.device,
+            WINED3D_TEXF_POINT, FALSE, surface, &r, surface, &r);
 
     return WINED3D_OK;
 }
@@ -6168,16 +5994,22 @@ HRESULT surface_load_location(struct wined3d_surface *surface, DWORD location, c
 
     if (surface->resource.usage & WINED3DUSAGE_DEPTHSTENCIL)
     {
-        if (location == SFLAG_INTEXTURE)
+        if (location == SFLAG_INTEXTURE && surface->flags & SFLAG_INDRAWABLE)
         {
             struct wined3d_context *context = context_acquire(device, NULL);
             surface_load_ds_location(surface, context, location);
             context_release(context);
             return WINED3D_OK;
         }
+        else if (location & surface->flags && surface->draw_binding != SFLAG_INDRAWABLE)
+        {
+            /* Already up to date, nothing to do. */
+            return WINED3D_OK;
+        }
         else
         {
-            FIXME("Unimplemented location %s for depth/stencil buffers.\n", debug_surflocation(location));
+            FIXME("Unimplemented copy from %s to %s for depth/stencil buffers.\n",
+                    debug_surflocation(surface->flags & SFLAG_LOCATIONS), debug_surflocation(location));
             return WINED3DERR_INVALIDCALL;
         }
     }
@@ -6256,10 +6088,11 @@ HRESULT surface_load_location(struct wined3d_surface *surface, DWORD location, c
 
 BOOL surface_is_offscreen(const struct wined3d_surface *surface)
 {
-    struct wined3d_swapchain *swapchain = surface->container.u.swapchain;
+    struct wined3d_swapchain *swapchain;
 
     /* Not on a swapchain - must be offscreen */
-    if (surface->container.type != WINED3D_CONTAINER_SWAPCHAIN) return TRUE;
+    if (!(swapchain = surface->swapchain))
+        return TRUE;
 
     /* The front buffer is always onscreen */
     if (surface == swapchain->front_buffer) return FALSE;
@@ -6273,44 +6106,17 @@ static HRESULT ffp_blit_alloc(struct wined3d_device *device) { return WINED3D_OK
 /* Context activation is done by the caller. */
 static void ffp_blit_free(struct wined3d_device *device) { }
 
-/* This function is used in case of 8bit paletted textures using GL_EXT_paletted_texture */
-/* Context activation is done by the caller. */
-static void ffp_blit_p8_upload_palette(const struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info)
-{
-    BYTE table[256][4];
-    BOOL colorkey_active = (surface->CKeyFlags & WINEDDSD_CKSRCBLT) != 0;
-    GLenum target;
-
-    if (surface->container.type == WINED3D_CONTAINER_TEXTURE)
-        target = surface->container.u.texture->target;
-    else
-        target = surface->texture_target;
-
-    d3dfmt_p8_init_palette(surface, table, colorkey_active);
-
-    TRACE("Using GL_EXT_PALETTED_TEXTURE for 8-bit paletted texture support\n");
-    GL_EXTCALL(glColorTableEXT(target, GL_RGBA, 256, GL_RGBA, GL_UNSIGNED_BYTE, table));
-}
-
 /* Context activation is done by the caller. */
 static HRESULT ffp_blit_set(void *blit_priv, struct wined3d_context *context, const struct wined3d_surface *surface)
 {
-    enum complex_fixup fixup = get_complex_fixup(surface->resource.format->color_fixup);
     const struct wined3d_gl_info *gl_info = context->gl_info;
     GLenum target;
 
-    if (surface->container.type == WINED3D_CONTAINER_TEXTURE)
-        target = surface->container.u.texture->target;
+    if (surface->container)
+        target = surface->container->target;
     else
         target = surface->texture_target;
 
-    /* When EXT_PALETTED_TEXTURE is around, palette conversion is done by the GPU
-     * else the surface is converted in software at upload time in LoadLocation.
-     */
-    if (!(surface->flags & SFLAG_CONVERTED) && fixup == COMPLEX_FIXUP_P8
-            && gl_info->supported[EXT_PALETTED_TEXTURE])
-        ffp_blit_p8_upload_palette(surface, gl_info);
-
     gl_info->gl_ops.gl.p_glEnable(target);
     checkGLcall("glEnable(target)");
 
@@ -6338,42 +6144,27 @@ static BOOL ffp_blit_supported(const struct wined3d_gl_info *gl_info, enum wined
         const RECT *src_rect, DWORD src_usage, enum wined3d_pool src_pool, const struct wined3d_format *src_format,
         const RECT *dst_rect, DWORD dst_usage, enum wined3d_pool dst_pool, const struct wined3d_format *dst_format)
 {
-    enum complex_fixup src_fixup;
-
     switch (blit_op)
     {
         case WINED3D_BLIT_OP_COLOR_BLIT:
             if (src_pool == WINED3D_POOL_SYSTEM_MEM || dst_pool == WINED3D_POOL_SYSTEM_MEM)
                 return FALSE;
 
-            src_fixup = get_complex_fixup(src_format->color_fixup);
             if (TRACE_ON(d3d_surface) && TRACE_ON(d3d))
             {
                 TRACE("Checking support for fixup:\n");
                 dump_color_fixup_desc(src_format->color_fixup);
             }
 
-            if (!is_identity_fixup(dst_format->color_fixup))
-            {
-                TRACE("Destination fixups are not supported\n");
-                return FALSE;
-            }
-
-            if (src_fixup == COMPLEX_FIXUP_P8 && gl_info->supported[EXT_PALETTED_TEXTURE])
-            {
-                TRACE("P8 fixup supported\n");
-                return TRUE;
-            }
-
             /* We only support identity conversions. */
-            if (is_identity_fixup(src_format->color_fixup))
+            if (!is_identity_fixup(src_format->color_fixup)
+                    || !is_identity_fixup(dst_format->color_fixup))
             {
-                TRACE("[OK]\n");
-                return TRUE;
+                TRACE("Fixups are not supported.\n");
+                return FALSE;
             }
 
-            TRACE("[FAILED]\n");
-            return FALSE;
+            return TRUE;
 
         case WINED3D_BLIT_OP_COLOR_FILL:
             if (dst_pool == WINED3D_POOL_SYSTEM_MEM)
@@ -7160,7 +6951,7 @@ static HRESULT surface_init(struct wined3d_surface *surface, UINT alignment, UIN
 
     /* FIXME: Check that the format is supported by the device. */
 
-    resource_size = wined3d_format_calculate_size(format, alignment, width, height);
+    resource_size = wined3d_format_calculate_size(format, alignment, width, height, 1);
     if (!resource_size)
         return WINED3DERR_INVALIDCALL;
 
@@ -7179,7 +6970,7 @@ static HRESULT surface_init(struct wined3d_surface *surface, UINT alignment, UIN
     }
 
     /* "Standalone" surface. */
-    surface_set_container(surface, WINED3D_CONTAINER_NONE, NULL);
+    surface_set_container(surface, NULL);
 
     list_init(&surface->overlays);
 
@@ -7223,8 +7014,8 @@ static HRESULT surface_init(struct wined3d_surface *surface, UINT alignment, UIN
     if ((usage & WINED3DUSAGE_OWNDC) && !surface->hDC
             && SUCCEEDED(surface_create_dib_section(surface)))
     {
-        HeapFree(GetProcessHeap(), 0, surface->resource.heapMemory);
-        surface->resource.heapMemory = NULL;
+        wined3d_resource_free_sysmem(surface->resource.heap_memory);
+        surface->resource.heap_memory = NULL;
         surface->resource.allocatedMemory = surface->dib.bitmap_data;
     }
 
index 7f8f339..4996cf5 100644 (file)
@@ -30,7 +30,6 @@ WINE_DECLARE_DEBUG_CHANNEL(fps);
 /* Do not call while under the GL lock. */
 static void swapchain_cleanup(struct wined3d_swapchain *swapchain)
 {
-    struct wined3d_display_mode mode;
     HRESULT hr;
     UINT i;
 
@@ -42,8 +41,7 @@ static void swapchain_cleanup(struct wined3d_swapchain *swapchain)
      * is the last buffer to be destroyed, FindContext() depends on that. */
     if (swapchain->front_buffer)
     {
-        if (swapchain->front_buffer->container.type == WINED3D_CONTAINER_SWAPCHAIN)
-            surface_set_container(swapchain->front_buffer, WINED3D_CONTAINER_NONE, NULL);
+        surface_set_swapchain(swapchain->front_buffer, NULL);
         if (wined3d_surface_decref(swapchain->front_buffer))
             WARN("Something's still holding the front buffer (%p).\n", swapchain->front_buffer);
         swapchain->front_buffer = NULL;
@@ -55,8 +53,7 @@ static void swapchain_cleanup(struct wined3d_swapchain *swapchain)
 
         while (i--)
         {
-            if (swapchain->back_buffers[i]->container.type == WINED3D_CONTAINER_SWAPCHAIN)
-                surface_set_container(swapchain->back_buffers[i], WINED3D_CONTAINER_NONE, NULL);
+            surface_set_swapchain(swapchain->back_buffers[i], NULL);
             if (wined3d_surface_decref(swapchain->back_buffers[i]))
                 WARN("Something's still holding back buffer %u (%p).\n", i, swapchain->back_buffers[i]);
         }
@@ -78,13 +75,8 @@ static void swapchain_cleanup(struct wined3d_swapchain *swapchain)
      * orig_height will be equal to the modes in the presentation params. */
     if (!swapchain->desc.windowed && swapchain->desc.auto_restore_display_mode)
     {
-        mode.width = swapchain->orig_width;
-        mode.height = swapchain->orig_height;
-        mode.refresh_rate = 0;
-        mode.format_id = swapchain->orig_fmt;
-        mode.scanline_ordering = WINED3D_SCANLINE_ORDERING_UNKNOWN;
         if (FAILED(hr = wined3d_set_adapter_display_mode(swapchain->device->wined3d,
-                swapchain->device->adapter->ordinal, &mode)))
+                swapchain->device->adapter->ordinal, &swapchain->original_mode)))
             ERR("Failed to restore display mode, hr %#x.\n", hr);
     }
 
@@ -745,10 +737,10 @@ static void swapchain_gdi_present(struct wined3d_swapchain *swapchain, const REC
         front->resource.allocatedMemory = back->resource.allocatedMemory;
         back->resource.allocatedMemory = tmp;
 
-        if (front->resource.heapMemory)
+        if (front->resource.heap_memory)
             ERR("GDI Surface %p has heap memory allocated.\n", front);
 
-        if (back->resource.heapMemory)
+        if (back->resource.heap_memory)
             ERR("GDI Surface %p has heap memory allocated.\n", back);
     }
 
@@ -819,8 +811,7 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3
         struct wined3d_swapchain_desc *desc, void *parent, const struct wined3d_parent_ops *parent_ops)
 {
     const struct wined3d_adapter *adapter = device->adapter;
-    const struct wined3d_format *format;
-    struct wined3d_display_mode mode;
+    struct wined3d_resource_desc surface_desc;
     BOOL displaymode_set = FALSE;
     RECT client_rect;
     HWND window;
@@ -854,11 +845,12 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3
     swapchain->win_handle = window;
     swapchain->device_window = window;
 
-    wined3d_get_adapter_display_mode(device->wined3d, adapter->ordinal, &mode, NULL);
-    swapchain->orig_width = mode.width;
-    swapchain->orig_height = mode.height;
-    swapchain->orig_fmt = mode.format_id;
-    format = wined3d_get_format(&adapter->gl_info, mode.format_id);
+    if (FAILED(hr = wined3d_get_adapter_display_mode(device->wined3d,
+            adapter->ordinal, &swapchain->original_mode, NULL)))
+    {
+        ERR("Failed to get current display mode, hr %#x.\n", hr);
+        goto err;
+    }
 
     GetClientRect(window, &client_rect);
     if (desc->windowed
@@ -880,26 +872,34 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3
 
         if (desc->backbuffer_format == WINED3DFMT_UNKNOWN)
         {
-            desc->backbuffer_format = swapchain->orig_fmt;
-            TRACE("Updating format to %s.\n", debug_d3dformat(swapchain->orig_fmt));
+            desc->backbuffer_format = swapchain->original_mode.format_id;
+            TRACE("Updating format to %s.\n", debug_d3dformat(swapchain->original_mode.format_id));
         }
     }
     swapchain->desc = *desc;
     swapchain_update_render_to_fbo(swapchain);
 
     TRACE("Creating front buffer.\n");
-    if (FAILED(hr = device->device_parent->ops->create_swapchain_surface(device->device_parent, parent,
-            swapchain->desc.backbuffer_width, swapchain->desc.backbuffer_height,
-            swapchain->desc.backbuffer_format, WINED3DUSAGE_RENDERTARGET,
-            swapchain->desc.multisample_type, swapchain->desc.multisample_quality,
-            &swapchain->front_buffer)))
+
+    surface_desc.resource_type = WINED3D_RTYPE_SURFACE;
+    surface_desc.format = swapchain->desc.backbuffer_format;
+    surface_desc.multisample_type = swapchain->desc.multisample_type;
+    surface_desc.multisample_quality = swapchain->desc.multisample_quality;
+    surface_desc.usage = WINED3DUSAGE_RENDERTARGET;
+    surface_desc.pool = WINED3D_POOL_DEFAULT;
+    surface_desc.width = swapchain->desc.backbuffer_width;
+    surface_desc.height = swapchain->desc.backbuffer_height;
+    surface_desc.depth = 1;
+    surface_desc.size = 0;
+
+    if (FAILED(hr = device->device_parent->ops->create_swapchain_surface(device->device_parent,
+            parent, &surface_desc, &swapchain->front_buffer)))
     {
         WARN("Failed to create front buffer, hr %#x.\n", hr);
         goto err;
     }
 
-    if (swapchain->front_buffer->container.type == WINED3D_CONTAINER_NONE)
-        surface_set_container(swapchain->front_buffer, WINED3D_CONTAINER_SWAPCHAIN, swapchain);
+    surface_set_swapchain(swapchain->front_buffer, swapchain);
     if (!(device->wined3d->flags & WINED3D_NO3D))
         surface_modify_location(swapchain->front_buffer, SFLAG_INDRAWABLE, TRUE);
 
@@ -918,7 +918,7 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3
         mode.refresh_rate = desc->refresh_rate;
         mode.scanline_ordering = WINED3D_SCANLINE_ORDERING_UNKNOWN;
 
-        if (FAILED(hr = wined3d_set_adapter_display_mode(device->wined3d, device->adapter->ordinal, &mode)))
+        if (FAILED(hr = wined3d_set_adapter_display_mode(device->wined3d, adapter->ordinal, &mode)))
         {
             WARN("Failed to set display mode, hr %#x.\n", hr);
             goto err;
@@ -937,7 +937,7 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3
             WINED3DFMT_S1_UINT_D15_UNORM
         };
 
-        const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+        const struct wined3d_gl_info *gl_info = &adapter->gl_info;
 
         swapchain->context = HeapAlloc(GetProcessHeap(), 0, sizeof(*swapchain->context));
         if (!swapchain->context)
@@ -998,17 +998,13 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3
         for (i = 0; i < swapchain->desc.backbuffer_count; ++i)
         {
             TRACE("Creating back buffer %u.\n", i);
-            if (FAILED(hr = device->device_parent->ops->create_swapchain_surface(device->device_parent, parent,
-                    swapchain->desc.backbuffer_width, swapchain->desc.backbuffer_height,
-                    swapchain->desc.backbuffer_format, WINED3DUSAGE_RENDERTARGET,
-                    swapchain->desc.multisample_type, swapchain->desc.multisample_quality,
-                    &swapchain->back_buffers[i])))
+            if (FAILED(hr = device->device_parent->ops->create_swapchain_surface(device->device_parent,
+                    parent, &surface_desc, &swapchain->back_buffers[i])))
             {
                 WARN("Failed to create back buffer %u, hr %#x.\n", i, hr);
                 goto err;
             }
-            if (swapchain->back_buffers[i]->container.type == WINED3D_CONTAINER_NONE)
-                surface_set_container(swapchain->back_buffers[i], WINED3D_CONTAINER_SWAPCHAIN, swapchain);
+            surface_set_swapchain(swapchain->back_buffers[i], swapchain);
         }
     }
 
@@ -1018,17 +1014,15 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3
         TRACE("Creating depth/stencil buffer.\n");
         if (!device->auto_depth_stencil)
         {
+            surface_desc.format = swapchain->desc.auto_depth_stencil_format;
+            surface_desc.usage = WINED3DUSAGE_DEPTHSTENCIL;
+
             if (FAILED(hr = device->device_parent->ops->create_swapchain_surface(device->device_parent,
-                    device->device_parent, swapchain->desc.backbuffer_width, swapchain->desc.backbuffer_height,
-                    swapchain->desc.auto_depth_stencil_format, WINED3DUSAGE_DEPTHSTENCIL,
-                    swapchain->desc.multisample_type, swapchain->desc.multisample_quality,
-                    &device->auto_depth_stencil)))
+                    device->device_parent, &surface_desc, &device->auto_depth_stencil)))
             {
                 WARN("Failed to create the auto depth stencil, hr %#x.\n", hr);
                 goto err;
             }
-
-            surface_set_container(device->auto_depth_stencil, WINED3D_CONTAINER_NONE, NULL);
         }
     }
 
@@ -1039,18 +1033,10 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3
 err:
     if (displaymode_set)
     {
-        DEVMODEW devmode;
-
+        if (FAILED(wined3d_set_adapter_display_mode(device->wined3d,
+                adapter->ordinal, &swapchain->original_mode)))
+            ERR("Failed to restore display mode.\n");
         ClipCursor(NULL);
-
-        /* Change the display settings */
-        memset(&devmode, 0, sizeof(devmode));
-        devmode.dmSize = sizeof(devmode);
-        devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
-        devmode.dmBitsPerPel = format->byte_count * CHAR_BIT;
-        devmode.dmPelsWidth = swapchain->orig_width;
-        devmode.dmPelsHeight = swapchain->orig_height;
-        ChangeDisplaySettingsExW(adapter->DeviceName, &devmode, NULL, CDS_FULLSCREEN, NULL);
     }
 
     if (swapchain->back_buffers)
@@ -1059,7 +1045,7 @@ err:
         {
             if (swapchain->back_buffers[i])
             {
-                surface_set_container(swapchain->back_buffers[i], WINED3D_CONTAINER_NONE, NULL);
+                surface_set_swapchain(swapchain->back_buffers[i], NULL);
                 wined3d_surface_decref(swapchain->back_buffers[i]);
             }
         }
@@ -1079,7 +1065,7 @@ err:
 
     if (swapchain->front_buffer)
     {
-        surface_set_container(swapchain->front_buffer, WINED3D_CONTAINER_NONE, NULL);
+        surface_set_swapchain(swapchain->front_buffer, NULL);
         wined3d_surface_decref(swapchain->front_buffer);
     }
 
index c025892..6137a77 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright 2002-2005 Jason Edmeades
  * Copyright 2002-2005 Raphael Junqueira
  * Copyright 2005 Oliver Stieber
- * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
+ * Copyright 2007-2009, 2013 Stefan Dösinger for CodeWeavers
  * Copyright 2009-2011 Henri Verbeet for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
 WINE_DEFAULT_DEBUG_CHANNEL(d3d_texture);
 
 static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struct wined3d_texture_ops *texture_ops,
-        UINT layer_count, UINT level_count, enum wined3d_resource_type resource_type, struct wined3d_device *device,
-        DWORD usage, const struct wined3d_format *format, enum wined3d_pool pool, void *parent,
-        const struct wined3d_parent_ops *parent_ops, const struct wined3d_resource_ops *resource_ops)
+        UINT layer_count, UINT level_count, const struct wined3d_resource_desc *desc, struct wined3d_device *device,
+        void *parent, const struct wined3d_parent_ops *parent_ops, const struct wined3d_resource_ops *resource_ops)
 {
+    const struct wined3d_format *format = wined3d_get_format(&device->adapter->gl_info, desc->format);
     HRESULT hr;
 
-    hr = resource_init(&texture->resource, device, resource_type, format,
-            WINED3D_MULTISAMPLE_NONE, 0, usage, pool, 0, 0, 0, 0,
-            parent, parent_ops, resource_ops);
-    if (FAILED(hr))
+    TRACE("texture %p, texture_ops %p, layer_count %u, level_count %u, resource_type %s, format %s, "
+            "multisample_type %#x, multisample_quality %#x, usage %s, pool %s, width %u, height %u, depth %u, "
+            "device %p, parent %p, parent_ops %p, resource_ops %p.\n",
+            texture, texture_ops, layer_count, level_count, debug_d3dresourcetype(desc->resource_type),
+            debug_d3dformat(desc->format), desc->multisample_type, desc->multisample_quality,
+            debug_d3dusage(desc->usage), debug_d3dpool(desc->pool), desc->width, desc->height, desc->depth,
+            device, parent, parent_ops, resource_ops);
+
+    if (FAILED(hr = resource_init(&texture->resource, device, desc->resource_type, format,
+            desc->multisample_type, desc->multisample_quality, desc->usage, desc->pool,
+            desc->width, desc->height, desc->depth, 0, parent, parent_ops, resource_ops)))
     {
         WARN("Failed to initialize resource, returning %#x\n", hr);
         return hr;
@@ -54,7 +61,7 @@ static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struc
 
     texture->layer_count = layer_count;
     texture->level_count = level_count;
-    texture->filter_type = (usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3D_TEXF_LINEAR : WINED3D_TEXF_NONE;
+    texture->filter_type = (desc->usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3D_TEXF_LINEAR : WINED3D_TEXF_NONE;
     texture->lod = 0;
     texture->texture_rgb.dirty = TRUE;
     texture->texture_srgb.dirty = TRUE;
@@ -715,7 +722,7 @@ static void texture2d_sub_resource_cleanup(struct wined3d_resource *sub_resource
     surface_set_texture_name(surface, 0, TRUE);
     surface_set_texture_name(surface, 0, FALSE);
     surface_set_texture_target(surface, 0, 0);
-    surface_set_container(surface, WINED3D_CONTAINER_NONE, NULL);
+    surface_set_container(surface, NULL);
     wined3d_surface_decref(surface);
 }
 
@@ -754,33 +761,31 @@ static const struct wined3d_resource_ops texture2d_resource_ops =
     texture2d_unload,
 };
 
-static HRESULT cubetexture_init(struct wined3d_texture *texture, UINT edge_length, UINT levels,
-        struct wined3d_device *device, DWORD usage, enum wined3d_format_id format_id, enum wined3d_pool pool,
-        void *parent, const struct wined3d_parent_ops *parent_ops)
+static HRESULT cubetexture_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc,
+        UINT levels, DWORD surface_flags, struct wined3d_device *device, void *parent,
+        const struct wined3d_parent_ops *parent_ops)
 {
     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
-    const struct wined3d_format *format = wined3d_get_format(gl_info, format_id);
-    UINT pow2_edge_length;
+    struct wined3d_resource_desc surface_desc;
     unsigned int i, j;
-    UINT tmp_w;
     HRESULT hr;
 
     /* TODO: It should only be possible to create textures for formats
      * that are reported as supported. */
-    if (WINED3DFMT_UNKNOWN >= format_id)
+    if (WINED3DFMT_UNKNOWN >= desc->format)
     {
         WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture);
         return WINED3DERR_INVALIDCALL;
     }
 
-    if (!gl_info->supported[ARB_TEXTURE_CUBE_MAP] && pool != WINED3D_POOL_SCRATCH)
+    if (!gl_info->supported[ARB_TEXTURE_CUBE_MAP] && desc->pool != WINED3D_POOL_SCRATCH)
     {
         WARN("(%p) : Tried to create not supported cube texture.\n", texture);
         return WINED3DERR_INVALIDCALL;
     }
 
     /* Calculate levels for mip mapping */
-    if (usage & WINED3DUSAGE_AUTOGENMIPMAP)
+    if (desc->usage & WINED3DUSAGE_AUTOGENMIPMAP)
     {
         if (!gl_info->supported[SGIS_GENERATE_MIPMAP])
         {
@@ -798,44 +803,47 @@ static HRESULT cubetexture_init(struct wined3d_texture *texture, UINT edge_lengt
     }
     else if (!levels)
     {
-        levels = wined3d_log2i(edge_length) + 1;
+        levels = wined3d_log2i(desc->width) + 1;
         TRACE("Calculated levels = %u.\n", levels);
     }
 
-    hr = wined3d_texture_init(texture, &texture2d_ops, 6, levels,
-            WINED3D_RTYPE_CUBE_TEXTURE, device, usage, format, pool,
-            parent, parent_ops, &texture2d_resource_ops);
-    if (FAILED(hr))
+    if (!gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
     {
-        WARN("Failed to initialize texture, returning %#x\n", hr);
-        return hr;
-    }
-
-    /* Find the nearest pow2 match. */
-    pow2_edge_length = 1;
-    while (pow2_edge_length < edge_length) pow2_edge_length <<= 1;
+        UINT pow2_edge_length = 1;
+        while (pow2_edge_length < desc->width)
+            pow2_edge_length <<= 1;
 
-    if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] || (edge_length == pow2_edge_length))
-    {
-        /* Precalculated scaling for 'faked' non power of two texture coords. */
-        texture->pow2_matrix[0] = 1.0f;
-        texture->pow2_matrix[5] = 1.0f;
-        texture->pow2_matrix[10] = 1.0f;
-        texture->pow2_matrix[15] = 1.0f;
+        if (desc->width != pow2_edge_length)
+        {
+            if (desc->pool == WINED3D_POOL_SCRATCH)
+            {
+                /* SCRATCH textures cannot be used for texturing */
+                WARN("Creating a scratch NPOT cube texture despite lack of HW support.\n");
+            }
+            else
+            {
+                WARN("Attempted to create a NPOT cube texture (edge length %u) without GL support.\n", desc->width);
+                return WINED3DERR_INVALIDCALL;
+            }
+        }
     }
-    else
+
+    if (FAILED(hr = wined3d_texture_init(texture, &texture2d_ops, 6, levels,
+            desc, device, parent, parent_ops, &texture2d_resource_ops)))
     {
-        /* Precalculated scaling for 'faked' non power of two texture coords. */
-        texture->pow2_matrix[0] = ((float)edge_length) / ((float)pow2_edge_length);
-        texture->pow2_matrix[5] = ((float)edge_length) / ((float)pow2_edge_length);
-        texture->pow2_matrix[10] = ((float)edge_length) / ((float)pow2_edge_length);
-        texture->pow2_matrix[15] = 1.0f;
-        texture->flags &= ~WINED3D_TEXTURE_POW2_MAT_IDENT;
+        WARN("Failed to initialize texture, returning %#x\n", hr);
+        return hr;
     }
+
+    texture->pow2_matrix[0] = 1.0f;
+    texture->pow2_matrix[5] = 1.0f;
+    texture->pow2_matrix[10] = 1.0f;
+    texture->pow2_matrix[15] = 1.0f;
     texture->target = GL_TEXTURE_CUBE_MAP_ARB;
 
     /* Generate all the surfaces. */
-    tmp_w = edge_length;
+    surface_desc = *desc;
+    surface_desc.resource_type = WINED3D_RTYPE_SURFACE;
     for (i = 0; i < texture->level_count; ++i)
     {
         /* Create the 6 faces. */
@@ -854,38 +862,38 @@ static HRESULT cubetexture_init(struct wined3d_texture *texture, UINT edge_lengt
             struct wined3d_surface *surface;
 
             if (FAILED(hr = device->device_parent->ops->create_texture_surface(device->device_parent,
-                    parent, tmp_w, tmp_w, format_id, usage, pool, idx, &surface)))
+                    parent, &surface_desc, idx, surface_flags, &surface)))
             {
                 FIXME("(%p) Failed to create surface, hr %#x.\n", texture, hr);
                 wined3d_texture_cleanup(texture);
                 return hr;
             }
 
-            surface_set_container(surface, WINED3D_CONTAINER_TEXTURE, texture);
+            surface_set_container(surface, texture);
             surface_set_texture_target(surface, cube_targets[j], i);
             texture->sub_resources[idx] = &surface->resource;
             TRACE("Created surface level %u @ %p.\n", i, surface);
         }
-        tmp_w = max(1, tmp_w >> 1);
+        surface_desc.width = max(1, surface_desc.width >> 1);
+        surface_desc.height = surface_desc.width;
     }
 
     return WINED3D_OK;
 }
 
-static HRESULT texture_init(struct wined3d_texture *texture, UINT width, UINT height, UINT levels,
-        struct wined3d_device *device, DWORD usage, enum wined3d_format_id format_id, enum wined3d_pool pool,
-        void *parent, const struct wined3d_parent_ops *parent_ops)
+static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc,
+        UINT levels, DWORD surface_flags, struct wined3d_device *device, void *parent,
+        const struct wined3d_parent_ops *parent_ops)
 {
     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
-    const struct wined3d_format *format = wined3d_get_format(gl_info, format_id);
+    struct wined3d_resource_desc surface_desc;
     UINT pow2_width, pow2_height;
-    UINT tmp_w, tmp_h;
     unsigned int i;
     HRESULT hr;
 
     /* TODO: It should only be possible to create textures for formats
      * that are reported as supported. */
-    if (WINED3DFMT_UNKNOWN >= format_id)
+    if (WINED3DFMT_UNKNOWN >= desc->format)
     {
         WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture);
         return WINED3DERR_INVALIDCALL;
@@ -894,29 +902,38 @@ static HRESULT texture_init(struct wined3d_texture *texture, UINT width, UINT he
     /* Non-power2 support. */
     if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
     {
-        pow2_width = width;
-        pow2_height = height;
+        pow2_width = desc->width;
+        pow2_height = desc->height;
     }
     else
     {
         /* Find the nearest pow2 match. */
         pow2_width = pow2_height = 1;
-        while (pow2_width < width) pow2_width <<= 1;
-        while (pow2_height < height) pow2_height <<= 1;
+        while (pow2_width < desc->width)
+            pow2_width <<= 1;
+        while (pow2_height < desc->height)
+            pow2_height <<= 1;
 
-        if (pow2_width != width || pow2_height != height)
+        if (pow2_width != desc->width || pow2_height != desc->height)
         {
-            if (levels > 1)
+            /* levels == 0 returns an error as well */
+            if (levels != 1)
             {
-                WARN("Attempted to create a mipmapped np2 texture without unconditional np2 support.\n");
-                return WINED3DERR_INVALIDCALL;
+                if (desc->pool == WINED3D_POOL_SCRATCH)
+                {
+                    WARN("Creating a scratch mipmapped NPOT texture despite lack of HW support.\n");
+                }
+                else
+                {
+                    WARN("Attempted to create a mipmapped NPOT texture without unconditional NPOT support.\n");
+                    return WINED3DERR_INVALIDCALL;
+                }
             }
-            levels = 1;
         }
     }
 
     /* Calculate levels for mip mapping. */
-    if (usage & WINED3DUSAGE_AUTOGENMIPMAP)
+    if (desc->usage & WINED3DUSAGE_AUTOGENMIPMAP)
     {
         if (!gl_info->supported[SGIS_GENERATE_MIPMAP])
         {
@@ -934,24 +951,20 @@ static HRESULT texture_init(struct wined3d_texture *texture, UINT width, UINT he
     }
     else if (!levels)
     {
-        levels = wined3d_log2i(max(width, height)) + 1;
+        levels = wined3d_log2i(max(desc->width, desc->height)) + 1;
         TRACE("Calculated levels = %u.\n", levels);
     }
 
-    hr = wined3d_texture_init(texture, &texture2d_ops, 1, levels,
-            WINED3D_RTYPE_TEXTURE, device, usage, format, pool,
-            parent, parent_ops, &texture2d_resource_ops);
-    if (FAILED(hr))
+    if (FAILED(hr = wined3d_texture_init(texture, &texture2d_ops, 1, levels,
+            desc, device, parent, parent_ops, &texture2d_resource_ops)))
     {
         WARN("Failed to initialize texture, returning %#x.\n", hr);
         return hr;
     }
 
-    /* Precalculated scaling for 'faked' non power of two texture coords.
-     * Second also don't use ARB_TEXTURE_RECTANGLE in case the surface format is P8 and EXT_PALETTED_TEXTURE
-     * is used in combination with texture uploads (RTL_READTEX). The reason is that EXT_PALETTED_TEXTURE
-     * doesn't work in combination with ARB_TEXTURE_RECTANGLE. */
-    if (gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT] && (width != pow2_width || height != pow2_height))
+    /* Precalculated scaling for 'faked' non power of two texture coords. */
+    if (gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT]
+            && (desc->width != pow2_width || desc->height != pow2_height))
     {
         texture->pow2_matrix[0] = 1.0f;
         texture->pow2_matrix[5] = 1.0f;
@@ -961,19 +974,16 @@ static HRESULT texture_init(struct wined3d_texture *texture, UINT width, UINT he
         texture->flags |= WINED3D_TEXTURE_COND_NP2;
         texture->min_mip_lookup = minMipLookup_noFilter;
     }
-    else if (gl_info->supported[ARB_TEXTURE_RECTANGLE] && (width != pow2_width || height != pow2_height)
-            && !(format->id == WINED3DFMT_P8_UINT && gl_info->supported[EXT_PALETTED_TEXTURE]
-            && wined3d_settings.rendertargetlock_mode == RTL_READTEX))
+    else if (gl_info->supported[ARB_TEXTURE_RECTANGLE]
+            && (desc->width != pow2_width || desc->height != pow2_height))
     {
-        if (width != 1 || height != 1)
-            texture->flags &= ~WINED3D_TEXTURE_POW2_MAT_IDENT;
-
-        texture->pow2_matrix[0] = (float)width;
-        texture->pow2_matrix[5] = (float)height;
+        texture->pow2_matrix[0] = (float)desc->width;
+        texture->pow2_matrix[5] = (float)desc->height;
         texture->pow2_matrix[10] = 1.0f;
         texture->pow2_matrix[15] = 1.0f;
         texture->target = GL_TEXTURE_RECTANGLE_ARB;
         texture->flags |= WINED3D_TEXTURE_COND_NP2;
+        texture->flags &= ~WINED3D_TEXTURE_POW2_MAT_IDENT;
 
         if (texture->resource.format->flags & WINED3DFMT_FLAG_FILTERING)
             texture->min_mip_lookup = minMipLookup_noMip;
@@ -982,10 +992,10 @@ static HRESULT texture_init(struct wined3d_texture *texture, UINT width, UINT he
     }
     else
     {
-        if ((width != pow2_width) || (height != pow2_height))
+        if ((desc->width != pow2_width) || (desc->height != pow2_height))
         {
-            texture->pow2_matrix[0] = (((float)width) / ((float)pow2_width));
-            texture->pow2_matrix[5] = (((float)height) / ((float)pow2_height));
+            texture->pow2_matrix[0] = (((float)desc->width) / ((float)pow2_width));
+            texture->pow2_matrix[5] = (((float)desc->height) / ((float)pow2_height));
             texture->flags &= ~WINED3D_TEXTURE_POW2_MAT_IDENT;
         }
         else
@@ -1001,28 +1011,28 @@ static HRESULT texture_init(struct wined3d_texture *texture, UINT width, UINT he
     TRACE("xf(%f) yf(%f)\n", texture->pow2_matrix[0], texture->pow2_matrix[5]);
 
     /* Generate all the surfaces. */
-    tmp_w = width;
-    tmp_h = height;
+    surface_desc = *desc;
+    surface_desc.resource_type = WINED3D_RTYPE_SURFACE;
     for (i = 0; i < texture->level_count; ++i)
     {
         struct wined3d_surface *surface;
 
         /* Use the callback to create the texture surface. */
         if (FAILED(hr = device->device_parent->ops->create_texture_surface(device->device_parent,
-                parent, tmp_w, tmp_h, format->id, usage, pool, i, &surface)))
+                parent, &surface_desc, i, surface_flags, &surface)))
         {
             FIXME("Failed to create surface %p, hr %#x\n", texture, hr);
             wined3d_texture_cleanup(texture);
             return hr;
         }
 
-        surface_set_container(surface, WINED3D_CONTAINER_TEXTURE, texture);
+        surface_set_container(surface, texture);
         surface_set_texture_target(surface, texture->target, i);
         texture->sub_resources[i] = &surface->resource;
         TRACE("Created surface level %u @ %p.\n", i, surface);
         /* Calculate the next mipmap level. */
-        tmp_w = max(1, tmp_w >> 1);
-        tmp_h = max(1, tmp_h >> 1);
+        surface_desc.width = max(1, surface_desc.width >> 1);
+        surface_desc.height = max(1, surface_desc.height >> 1);
     }
 
     return WINED3D_OK;
@@ -1042,64 +1052,44 @@ static HRESULT texture3d_bind(struct wined3d_texture *texture,
 /* Do not call while under the GL lock. */
 static void texture3d_preload(struct wined3d_texture *texture, enum WINED3DSRGB srgb)
 {
+    UINT sub_count = texture->level_count * texture->layer_count;
     struct wined3d_device *device = texture->resource.device;
-    struct wined3d_context *context;
-    BOOL srgb_was_toggled = FALSE;
-    unsigned int i;
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    struct wined3d_context *context = NULL;
+    struct gl_texture *gl_tex;
+    BOOL srgb_mode;
+    UINT i;
 
     TRACE("texture %p, srgb %#x.\n", texture, srgb);
 
-    /* TODO: Use already acquired context when possible. */
-    context = context_acquire(device, NULL);
-    if (texture->resource.bind_count > 0)
+    srgb_mode = texture_srgb_mode(texture, srgb);
+    gl_tex = wined3d_texture_get_gl_texture(texture, gl_info, srgb_mode);
+
+    if (gl_tex->dirty)
     {
-        BOOL texture_srgb = texture->flags & WINED3D_TEXTURE_IS_SRGB;
-        BOOL sampler_srgb = texture_srgb_mode(texture, srgb);
-        srgb_was_toggled = !texture_srgb != !sampler_srgb;
+        context = context_acquire(device, NULL);
 
-        if (srgb_was_toggled)
+        /* Reload the surfaces if the texture is marked dirty. */
+        for (i = 0; i < sub_count; ++i)
         {
-            if (sampler_srgb)
-                texture->flags |= WINED3D_TEXTURE_IS_SRGB;
-            else
-                texture->flags &= ~WINED3D_TEXTURE_IS_SRGB;
+            wined3d_volume_load(volume_from_resource(texture->sub_resources[i]), context,
+                    srgb_mode);
         }
-    }
 
-    /* If the texture is marked dirty or the sRGB sampler setting has changed
-     * since the last load then reload the volumes. */
-    if (texture->texture_rgb.dirty)
-    {
-        for (i = 0; i < texture->level_count; ++i)
-        {
-            volume_load(volume_from_resource(texture->sub_resources[i]), context, i,
-                    texture->flags & WINED3D_TEXTURE_IS_SRGB);
-        }
-    }
-    else if (srgb_was_toggled)
-    {
-        for (i = 0; i < texture->level_count; ++i)
-        {
-            struct wined3d_volume *volume = volume_from_resource(texture->sub_resources[i]);
-            volume_add_dirty_box(volume, NULL);
-            volume_load(volume, context, i, texture->flags & WINED3D_TEXTURE_IS_SRGB);
-        }
+        context_release(context);
     }
     else
     {
         TRACE("Texture %p not dirty, nothing to do.\n", texture);
     }
 
-    context_release(context);
-
-    /* No longer dirty */
-    texture->texture_rgb.dirty = FALSE;
+    /* No longer dirty. */
+    gl_tex->dirty = FALSE;
 }
 
 static void texture3d_sub_resource_add_dirty_region(struct wined3d_resource *sub_resource,
         const struct wined3d_box *dirty_region)
 {
-    volume_add_dirty_box(volume_from_resource(sub_resource), dirty_region);
 }
 
 static void texture3d_sub_resource_cleanup(struct wined3d_resource *sub_resource)
@@ -1141,19 +1131,17 @@ static const struct wined3d_resource_ops texture3d_resource_ops =
     texture3d_unload,
 };
 
-static HRESULT volumetexture_init(struct wined3d_texture *texture, UINT width, UINT height,
-        UINT depth, UINT levels, struct wined3d_device *device, DWORD usage, enum wined3d_format_id format_id,
-        enum wined3d_pool pool, void *parent, const struct wined3d_parent_ops *parent_ops)
+static HRESULT volumetexture_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc,
+        UINT levels, struct wined3d_device *device, void *parent, const struct wined3d_parent_ops *parent_ops)
 {
     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
-    const struct wined3d_format *format = wined3d_get_format(gl_info, format_id);
     UINT tmp_w, tmp_h, tmp_d;
     unsigned int i;
     HRESULT hr;
 
     /* TODO: It should only be possible to create textures for formats
      * that are reported as supported. */
-    if (WINED3DFMT_UNKNOWN >= format_id)
+    if (WINED3DFMT_UNKNOWN >= desc->format)
     {
         WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture);
         return WINED3DERR_INVALIDCALL;
@@ -1166,7 +1154,7 @@ static HRESULT volumetexture_init(struct wined3d_texture *texture, UINT width, U
     }
 
     /* Calculate levels for mip mapping. */
-    if (usage & WINED3DUSAGE_AUTOGENMIPMAP)
+    if (desc->usage & WINED3DUSAGE_AUTOGENMIPMAP)
     {
         if (!gl_info->supported[SGIS_GENERATE_MIPMAP])
         {
@@ -1184,20 +1172,45 @@ static HRESULT volumetexture_init(struct wined3d_texture *texture, UINT width, U
     }
     else if (!levels)
     {
-        levels = wined3d_log2i(max(max(width, height), depth)) + 1;
+        levels = wined3d_log2i(max(max(desc->width, desc->height), desc->depth)) + 1;
         TRACE("Calculated levels = %u.\n", levels);
     }
 
-    hr = wined3d_texture_init(texture, &texture3d_ops, 1, levels,
-            WINED3D_RTYPE_VOLUME_TEXTURE, device, usage, format, pool,
-            parent, parent_ops, &texture3d_resource_ops);
-    if (FAILED(hr))
+    if (!gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
+    {
+        UINT pow2_w, pow2_h, pow2_d;
+        pow2_w = 1;
+        while (pow2_w < desc->width)
+            pow2_w <<= 1;
+        pow2_h = 1;
+        while (pow2_h < desc->height)
+            pow2_h <<= 1;
+        pow2_d = 1;
+        while (pow2_d < desc->depth)
+            pow2_d <<= 1;
+
+        if (pow2_w != desc->width || pow2_h != desc->height || pow2_d != desc->depth)
+        {
+            if (desc->pool == WINED3D_POOL_SCRATCH)
+            {
+                WARN("Creating a scratch NPOT volume texture despite lack of HW support.\n");
+            }
+            else
+            {
+                WARN("Attempted to create a NPOT volume texture (%u, %u, %u) without GL support.\n",
+                        desc->width, desc->height, desc->depth);
+                return WINED3DERR_INVALIDCALL;
+            }
+        }
+    }
+
+    if (FAILED(hr = wined3d_texture_init(texture, &texture3d_ops, 1, levels,
+            desc, device, parent, parent_ops, &texture3d_resource_ops)))
     {
         WARN("Failed to initialize texture, returning %#x.\n", hr);
         return hr;
     }
 
-    /* Is NP2 support for volumes needed? */
     texture->pow2_matrix[0] = 1.0f;
     texture->pow2_matrix[5] = 1.0f;
     texture->pow2_matrix[10] = 1.0f;
@@ -1205,9 +1218,9 @@ static HRESULT volumetexture_init(struct wined3d_texture *texture, UINT width, U
     texture->target = GL_TEXTURE_3D;
 
     /* Generate all the surfaces. */
-    tmp_w = width;
-    tmp_h = height;
-    tmp_d = depth;
+    tmp_w = desc->width;
+    tmp_h = desc->height;
+    tmp_d = desc->depth;
 
     for (i = 0; i < texture->level_count; ++i)
     {
@@ -1215,7 +1228,7 @@ static HRESULT volumetexture_init(struct wined3d_texture *texture, UINT width, U
 
         /* Create the volume. */
         hr = device->device_parent->ops->create_volume(device->device_parent, parent,
-                tmp_w, tmp_h, tmp_d, format_id, pool, usage, &volume);
+                tmp_w, tmp_h, tmp_d, i, desc->format, desc->pool, desc->usage, &volume);
         if (FAILED(hr))
         {
             ERR("Creating a volume for the volume texture failed, hr %#x.\n", hr);
@@ -1236,17 +1249,15 @@ static HRESULT volumetexture_init(struct wined3d_texture *texture, UINT width, U
     return WINED3D_OK;
 }
 
-HRESULT CDECL wined3d_texture_create_2d(struct wined3d_device *device, UINT width, UINT height,
-        UINT level_count, DWORD usage, enum wined3d_format_id format_id, enum wined3d_pool pool, void *parent,
-        const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture)
+HRESULT CDECL wined3d_texture_create_2d(struct wined3d_device *device, const struct wined3d_resource_desc *desc,
+        UINT level_count, DWORD surface_flags, void *parent, const struct wined3d_parent_ops *parent_ops,
+        struct wined3d_texture **texture)
 {
     struct wined3d_texture *object;
     HRESULT hr;
 
-    TRACE("device %p, width %u, height %u, level_count %u, usage %#x\n",
-            device, width, height, level_count, usage);
-    TRACE("format %s, pool %#x, parent %p, parent_ops %p, texture %p.\n",
-            debug_d3dformat(format_id), pool, parent, parent_ops, texture);
+    TRACE("device %p, desc %p, level_count %u, surface_flags %#x, parent %p, parent_ops %p, texture %p.\n",
+            device, desc, level_count, surface_flags, parent, parent_ops, texture);
 
     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
     if (!object)
@@ -1255,9 +1266,7 @@ HRESULT CDECL wined3d_texture_create_2d(struct wined3d_device *device, UINT widt
         return WINED3DERR_OUTOFVIDEOMEMORY;
     }
 
-    hr = texture_init(object, width, height, level_count,
-            device, usage, format_id, pool, parent, parent_ops);
-    if (FAILED(hr))
+    if (FAILED(hr = texture_init(object, desc, level_count, surface_flags, device, parent, parent_ops)))
     {
         WARN("Failed to initialize texture, returning %#x.\n", hr);
         HeapFree(GetProcessHeap(), 0, object);
@@ -1271,17 +1280,14 @@ HRESULT CDECL wined3d_texture_create_2d(struct wined3d_device *device, UINT widt
     return WINED3D_OK;
 }
 
-HRESULT CDECL wined3d_texture_create_3d(struct wined3d_device *device, UINT width, UINT height, UINT depth,
-        UINT level_count, DWORD usage, enum wined3d_format_id format_id, enum wined3d_pool pool, void *parent,
-        const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture)
+HRESULT CDECL wined3d_texture_create_3d(struct wined3d_device *device, const struct wined3d_resource_desc *desc,
+        UINT level_count, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture)
 {
     struct wined3d_texture *object;
     HRESULT hr;
 
-    TRACE("device %p, width %u, height %u, depth %u, level_count %u, usage %#x\n",
-            device, width, height, depth, level_count, usage);
-    TRACE("format %s, pool %#x, parent %p, parent_ops %p, texture %p.\n",
-            debug_d3dformat(format_id), pool, parent, parent_ops, texture);
+    TRACE("device %p, desc %p, level_count %u, parent %p, parent_ops %p, texture %p.\n",
+            device, desc, level_count, parent, parent_ops, texture);
 
     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
     if (!object)
@@ -1290,9 +1296,7 @@ HRESULT CDECL wined3d_texture_create_3d(struct wined3d_device *device, UINT widt
         return WINED3DERR_OUTOFVIDEOMEMORY;
     }
 
-    hr = volumetexture_init(object, width, height, depth, level_count,
-            device, usage, format_id, pool, parent, parent_ops);
-    if (FAILED(hr))
+    if (FAILED(hr = volumetexture_init(object, desc, level_count, device, parent, parent_ops)))
     {
         WARN("Failed to initialize volumetexture, returning %#x\n", hr);
         HeapFree(GetProcessHeap(), 0, object);
@@ -1306,17 +1310,15 @@ HRESULT CDECL wined3d_texture_create_3d(struct wined3d_device *device, UINT widt
     return WINED3D_OK;
 }
 
-HRESULT CDECL wined3d_texture_create_cube(struct wined3d_device *device, UINT edge_length,
-        UINT level_count, DWORD usage, enum wined3d_format_id format_id, enum wined3d_pool pool, void *parent,
-        const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture)
+HRESULT CDECL wined3d_texture_create_cube(struct wined3d_device *device, const struct wined3d_resource_desc *desc,
+        UINT level_count, DWORD surface_flags, void *parent, const struct wined3d_parent_ops *parent_ops,
+        struct wined3d_texture **texture)
 {
     struct wined3d_texture *object;
     HRESULT hr;
 
-    TRACE("device %p, edge_length %u, level_count %u, usage %#x\n",
-            device, edge_length, level_count, usage);
-    TRACE("format %s, pool %#x, parent %p, parent_ops %p, texture %p.\n",
-            debug_d3dformat(format_id), pool, parent, parent_ops, texture);
+    TRACE("device %p, desc %p, level_count %u, surface_flags %#x, parent %p, parent_ops %p, texture %p.\n",
+            device, desc, level_count, surface_flags, parent, parent_ops, texture);
 
     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
     if (!object)
@@ -1325,9 +1327,7 @@ HRESULT CDECL wined3d_texture_create_cube(struct wined3d_device *device, UINT ed
         return WINED3DERR_OUTOFVIDEOMEMORY;
     }
 
-    hr = cubetexture_init(object, edge_length, level_count,
-            device, usage, format_id, pool, parent, parent_ops);
-    if (FAILED(hr))
+    if (FAILED(hr = cubetexture_init(object, desc, level_count, surface_flags, device, parent, parent_ops)))
     {
         WARN("Failed to initialize cubetexture, returning %#x\n", hr);
         HeapFree(GetProcessHeap(), 0, object);
index 807ff02..16358ac 100644 (file)
@@ -120,18 +120,33 @@ static const struct wined3d_format_channels formats[] =
     {WINED3DFMT_VERTEXDATA,                 0,  0,  0,  0,   0,  0,  0,  0,    0,   0,     0},
     {WINED3DFMT_R16_UINT,                  16,  0,  0,  0,   0,  0,  0,  0,    2,   0,     0},
     {WINED3DFMT_R32_UINT,                  32,  0,  0,  0,   0,  0,  0,  0,    4,   0,     0},
+    {WINED3DFMT_R32G32_UINT,               32, 32,  0,  0,   0, 32,  0,  0,    8,   0,     0},
+    {WINED3DFMT_R32G32B32_UINT,            32, 32, 32,  0,   0, 32, 64,  0,   12,   0,     0},
+    {WINED3DFMT_R32G32B32A32_UINT,         32, 32, 32, 32,   0, 32, 64, 96,   16,   0,     0},
     {WINED3DFMT_R16G16B16A16_SNORM,        16, 16, 16, 16,   0, 16, 32, 48,    8,   0,     0},
     /* Vendor-specific formats */
     {WINED3DFMT_ATI2N,                      0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
     {WINED3DFMT_NVDB,                       0,  0,  0,  0,   0,  0,  0,  0,    0,   0,     0},
     {WINED3DFMT_INST,                       0,  0,  0,  0,   0,  0,  0,  0,    0,   0,     0},
     {WINED3DFMT_INTZ,                       0,  0,  0,  0,   0,  0,  0,  0,    4,  24,     8},
+    {WINED3DFMT_RESZ,                       0,  0,  0,  0,   0,  0,  0,  0,    0,   0,     0},
     {WINED3DFMT_NVHU,                       0,  0,  0,  0,   0,  0,  0,  0,    2,   0,     0},
     {WINED3DFMT_NVHS,                       0,  0,  0,  0,   0,  0,  0,  0,    2,   0,     0},
     {WINED3DFMT_NULL,                       8,  8,  8,  8,   0,  8, 16, 24,    4,   0,     0},
     /* Unsure about them, could not find a Windows driver that supports them */
     {WINED3DFMT_R16,                       16,  0,  0,  0,   0,  0,  0,  0,    2,   0,     0},
     {WINED3DFMT_AL16,                       0,  0,  0, 16,   0,  0,  0, 16,    4,   0,     0},
+    /* Typeless */
+    {WINED3DFMT_R8_TYPELESS,                8,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
+    {WINED3DFMT_R8G8_TYPELESS,              8,  8,  0,  0,   0,  8,  0,  0,    2,   0,     0},
+    {WINED3DFMT_R8G8B8A8_TYPELESS,          8,  8,  8,  8,   0,  8, 16, 24,    4,   0,     0},
+    {WINED3DFMT_R16_TYPELESS,              16,  0,  0,  0,   0,  0,  0,  0,    2,   0,     0},
+    {WINED3DFMT_R16G16_TYPELESS,           16, 16,  0,  0,   0, 16,  0,  0,    4,   0,     0},
+    {WINED3DFMT_R16G16B16A16_TYPELESS,     16, 16, 16, 16,   0, 16, 32, 48,    8,   0,     0},
+    {WINED3DFMT_R32_TYPELESS,              32,  0,  0,  0,   0,  0,  0,  0,    4,   0,     0},
+    {WINED3DFMT_R32G32_TYPELESS,           32, 32,  0,  0,   0, 32,  0,  0,    8,   0,     0},
+    {WINED3DFMT_R32G32B32_TYPELESS,        32, 32, 32,  0,   0, 32, 64,  0,   12,   0,     0},
+    {WINED3DFMT_R32G32B32A32_TYPELESS,     32, 32, 32, 32,   0, 32, 64, 96,   16,   0,     0},
 };
 
 struct wined3d_format_base_flags
@@ -145,19 +160,6 @@ struct wined3d_format_base_flags
  * resource size. */
 static const struct wined3d_format_base_flags format_base_flags[] =
 {
-    {WINED3DFMT_UYVY,               WINED3DFMT_FLAG_FOURCC},
-    {WINED3DFMT_YUY2,               WINED3DFMT_FLAG_FOURCC},
-    {WINED3DFMT_YV12,               WINED3DFMT_FLAG_FOURCC},
-    {WINED3DFMT_DXT1,               WINED3DFMT_FLAG_FOURCC},
-    {WINED3DFMT_DXT2,               WINED3DFMT_FLAG_FOURCC},
-    {WINED3DFMT_DXT3,               WINED3DFMT_FLAG_FOURCC},
-    {WINED3DFMT_DXT4,               WINED3DFMT_FLAG_FOURCC},
-    {WINED3DFMT_DXT5,               WINED3DFMT_FLAG_FOURCC},
-    {WINED3DFMT_MULTI2_ARGB8,       WINED3DFMT_FLAG_FOURCC},
-    {WINED3DFMT_G8R8_G8B8,          WINED3DFMT_FLAG_FOURCC},
-    {WINED3DFMT_R8G8_B8G8,          WINED3DFMT_FLAG_FOURCC},
-    {WINED3DFMT_INTZ,               WINED3DFMT_FLAG_FOURCC},
-    {WINED3DFMT_NULL,               WINED3DFMT_FLAG_FOURCC},
     {WINED3DFMT_P8_UINT,            WINED3DFMT_FLAG_GETDC},
     {WINED3DFMT_B8G8R8_UNORM,       WINED3DFMT_FLAG_GETDC},
     {WINED3DFMT_B8G8R8A8_UNORM,     WINED3DFMT_FLAG_GETDC},
@@ -169,10 +171,7 @@ static const struct wined3d_format_base_flags format_base_flags[] =
     {WINED3DFMT_B4G4R4X4_UNORM,     WINED3DFMT_FLAG_GETDC},
     {WINED3DFMT_R8G8B8A8_UNORM,     WINED3DFMT_FLAG_GETDC},
     {WINED3DFMT_R8G8B8X8_UNORM,     WINED3DFMT_FLAG_GETDC},
-    {WINED3DFMT_ATI2N,              WINED3DFMT_FLAG_FOURCC | WINED3DFMT_FLAG_BROKEN_PITCH},
-    {WINED3DFMT_NVDB,               WINED3DFMT_FLAG_FOURCC},
-    {WINED3DFMT_NVHU,               WINED3DFMT_FLAG_FOURCC},
-    {WINED3DFMT_NVHS,               WINED3DFMT_FLAG_FOURCC},
+    {WINED3DFMT_ATI2N,              WINED3DFMT_FLAG_BROKEN_PITCH},
     {WINED3DFMT_R32_FLOAT,          WINED3DFMT_FLAG_FLOAT},
     {WINED3DFMT_R32G32_FLOAT,       WINED3DFMT_FLAG_FLOAT},
     {WINED3DFMT_R32G32B32_FLOAT,    WINED3DFMT_FLAG_FLOAT},
@@ -233,7 +232,11 @@ static const struct wined3d_format_vertex_info format_vertex_info[] =
     {WINED3DFMT_R10G10B10A2_UINT,   WINED3D_FFP_EMIT_UDEC3,     3, GL_UNSIGNED_SHORT, 3, GL_FALSE, sizeof(short int)},
     {WINED3DFMT_R10G10B10A2_SNORM,  WINED3D_FFP_EMIT_DEC3N,     3, GL_SHORT,          3, GL_TRUE,  sizeof(short int)},
     {WINED3DFMT_R16G16_FLOAT,       WINED3D_FFP_EMIT_FLOAT16_2, 2, GL_FLOAT,          2, GL_FALSE, sizeof(GLhalfNV)},
-    {WINED3DFMT_R16G16B16A16_FLOAT, WINED3D_FFP_EMIT_FLOAT16_4, 4, GL_FLOAT,          4, GL_FALSE, sizeof(GLhalfNV)}
+    {WINED3DFMT_R16G16B16A16_FLOAT, WINED3D_FFP_EMIT_FLOAT16_4, 4, GL_FLOAT,          4, GL_FALSE, sizeof(GLhalfNV)},
+    {WINED3DFMT_R32_UINT,           WINED3D_FFP_EMIT_INVALID,   1, GL_UNSIGNED_INT,   1, GL_FALSE, sizeof(UINT)},
+    {WINED3DFMT_R32G32_UINT,        WINED3D_FFP_EMIT_INVALID,   2, GL_UNSIGNED_INT,   2, GL_FALSE, sizeof(UINT)},
+    {WINED3DFMT_R32G32B32_UINT,     WINED3D_FFP_EMIT_INVALID,   3, GL_UNSIGNED_INT,   3, GL_FALSE, sizeof(UINT)},
+    {WINED3DFMT_R32G32B32A32_UINT,  WINED3D_FFP_EMIT_INVALID,   4, GL_UNSIGNED_INT,   4, GL_FALSE, sizeof(UINT)},
 };
 
 struct wined3d_format_texture_info
@@ -581,10 +584,10 @@ static void convert_s8_uint_d24_float(const BYTE *src, BYTE *dst, UINT pitch, UI
  *     WINED3DFMT_NVHS */
 static const struct wined3d_format_texture_info format_texture_info[] =
 {
-    /* format id                        internal                          srgbInternal                       rtInternal
-            format                      type
+    /* format id                        gl_internal                       gl_srgb_internal                      gl_rt_internal
+            gl_format                   gl_type                           conv_byte_count
             flags
-            extension */
+            extension                   convert */
     /* FourCC formats */
     /* GL_APPLE_ycbcr_422 claims that its '2YUV' format, which is supported via the UNSIGNED_SHORT_8_8_REV_APPLE type
      * is equivalent to 'UYVY' format on Windows, and the 'YUVS' via UNSIGNED_SHORT_8_8_APPLE equates to 'YUY2'. The
@@ -685,10 +688,6 @@ static const struct wined3d_format_texture_info format_texture_info[] =
             GL_ALPHA,                   GL_UNSIGNED_BYTE,                 0,
             0,
             ARB_FRAGMENT_PROGRAM,       NULL},
-    {WINED3DFMT_P8_UINT,                GL_COLOR_INDEX8_EXT,              GL_COLOR_INDEX8_EXT,                    0,
-            GL_COLOR_INDEX,             GL_UNSIGNED_BYTE,                 0,
-            0,
-            EXT_PALETTED_TEXTURE,       NULL},
     /* Standard ARGB formats */
     {WINED3DFMT_B8G8R8_UNORM,           GL_RGB8,                          GL_RGB8,                                0,
             GL_BGR,                     GL_UNSIGNED_BYTE,                 0,
@@ -924,7 +923,7 @@ static const struct wined3d_format_texture_info format_texture_info[] =
             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
             | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL,
             ARB_FRAMEBUFFER_OBJECT,     NULL},
-    {WINED3DFMT_NULL,                   GL_RGBA8,                         GL_RGBA8,                               0,
+    {WINED3DFMT_NULL,                   0,                                0,                                      0,
             GL_RGBA,                    GL_UNSIGNED_INT_8_8_8_8_REV,      0,
             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET,
             ARB_FRAMEBUFFER_OBJECT,     NULL},
@@ -1236,12 +1235,105 @@ static void check_fbo_compat(const struct wined3d_gl_info *gl_info, struct wined
     gl_info->gl_ops.gl.p_glDeleteTextures(1, &tex);
 }
 
+static void query_format_flag(struct wined3d_gl_info *gl_info, struct wined3d_format *format,
+        GLint internal, GLenum pname, DWORD flag, const char *string)
+{
+    GLint value;
+
+    gl_info->gl_ops.ext.p_glGetInternalformativ(GL_TEXTURE_2D, internal, pname, 1, &value);
+    if (value == GL_FULL_SUPPORT)
+    {
+        TRACE("Format %s supports %s.\n", debug_d3dformat(format->id), string);
+        format->flags |= flag;
+    }
+    else
+    {
+        TRACE("Format %s doesn't support %s.\n", debug_d3dformat(format->id), string);
+        format->flags &= ~flag;
+    }
+}
+
 /* Context activation is done by the caller. */
 static void init_format_fbo_compat_info(struct wined3d_gl_info *gl_info)
 {
     unsigned int i;
     GLuint fbo;
 
+    if (gl_info->supported[ARB_INTERNALFORMAT_QUERY2])
+    {
+        for (i = 0; i < sizeof(formats) / sizeof(*formats); ++i)
+        {
+            GLint value;
+            struct wined3d_format *format = &gl_info->formats[i];
+
+            if (!format->glInternal)
+                continue;
+            if (format->flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))
+                continue;
+
+            gl_info->gl_ops.ext.p_glGetInternalformativ(GL_TEXTURE_2D, format->glInternal,
+                    GL_FRAMEBUFFER_RENDERABLE, 1, &value);
+            if (value == GL_FULL_SUPPORT)
+            {
+                TRACE("Format %s is supported as FBO color attachment.\n", debug_d3dformat(format->id));
+                format->flags |= WINED3DFMT_FLAG_FBO_ATTACHABLE;
+                format->rtInternal = format->glInternal;
+
+                query_format_flag(gl_info, format, format->glInternal, GL_FRAMEBUFFER_BLEND,
+                        WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING, "post-pixelshader blending");
+            }
+            else
+            {
+                if (!format->rtInternal)
+                {
+                    if (format->flags & WINED3DFMT_FLAG_RENDERTARGET)
+                    {
+                        WARN("Format %s with rendertarget flag is not supported as FBO color attachment"
+                                " and no fallback specified.\n", debug_d3dformat(format->id));
+                        format->flags &= ~WINED3DFMT_FLAG_RENDERTARGET;
+                    }
+                    else
+                        TRACE("Format %s is not supported as FBO color attachment.\n", debug_d3dformat(format->id));
+                    format->rtInternal = format->glInternal;
+                }
+                else
+                {
+                    gl_info->gl_ops.ext.p_glGetInternalformativ(GL_TEXTURE_2D, format->rtInternal,
+                            GL_FRAMEBUFFER_RENDERABLE, 1, &value);
+                    if (value == GL_FULL_SUPPORT)
+                    {
+                        TRACE("Format %s rtInternal format is supported as FBO color attachment.\n",
+                                debug_d3dformat(format->id));
+                    }
+                    else
+                    {
+                        WARN("Format %s rtInternal format is not supported as FBO color attachment.\n",
+                                debug_d3dformat(format->id));
+                        format->flags &= ~WINED3DFMT_FLAG_RENDERTARGET;
+                    }
+                }
+            }
+
+            if (format->glInternal != format->glGammaInternal)
+            {
+                gl_info->gl_ops.ext.p_glGetInternalformativ(GL_TEXTURE_2D, format->glGammaInternal,
+                        GL_FRAMEBUFFER_RENDERABLE, 1, &value);
+                if (value == GL_FULL_SUPPORT)
+                {
+                    TRACE("Format %s's sRGB format is FBO attachable.\n", debug_d3dformat(format->id));
+                    format->flags |= WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB;
+                }
+                else
+                {
+                    WARN("Format %s's sRGB format is not FBO attachable.\n", debug_d3dformat(format->id));
+                }
+            }
+            else if (format->flags & WINED3DFMT_FLAG_FBO_ATTACHABLE)
+                format->flags |= WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB;
+        }
+        return;
+    }
+
     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
     {
         gl_info->fbo_ops.glGenFramebuffers(1, &fbo);
@@ -1329,30 +1421,57 @@ static BOOL init_format_texture_info(struct wined3d_adapter *adapter, struct win
         format->height_scale.numerator = 1;
         format->height_scale.denominator = 1;
 
-        if (!gl_info->limits.vertex_samplers)
-            format->flags &= ~WINED3DFMT_FLAG_VTF;
-
-        if (!(gl_info->quirks & WINED3D_QUIRK_LIMITED_TEX_FILTERING))
-            format->flags |= WINED3DFMT_FLAG_FILTERING;
-        else if (format->id != WINED3DFMT_R32G32B32A32_FLOAT && format->id != WINED3DFMT_R32_FLOAT)
-            format->flags &= ~WINED3DFMT_FLAG_VTF;
-
-        if (format->glGammaInternal != format->glInternal)
+        if (gl_info->supported[ARB_INTERNALFORMAT_QUERY2])
         {
-            /* Filter sRGB capabilities if EXT_texture_sRGB is not supported. */
-            if (!gl_info->supported[EXT_TEXTURE_SRGB])
+            query_format_flag(gl_info, format, format->glInternal, GL_VERTEX_TEXTURE,
+                    WINED3DFMT_FLAG_VTF, "vertex texture usage");
+            query_format_flag(gl_info, format, format->glInternal, GL_FILTER,
+                    WINED3DFMT_FLAG_FILTERING, "filtering");
+
+            if (format->glGammaInternal != format->glInternal)
             {
-                format->glGammaInternal = format->glInternal;
-                format->flags &= ~(WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_SRGB_WRITE);
+                query_format_flag(gl_info, format, format->glGammaInternal, GL_SRGB_READ,
+                        WINED3DFMT_FLAG_SRGB_READ, "sRGB read");
+
+                if (srgb_write)
+                    query_format_flag(gl_info, format, format->glGammaInternal, GL_SRGB_WRITE,
+                            WINED3DFMT_FLAG_SRGB_WRITE, "sRGB write");
+                else
+                    format->flags &= ~WINED3DFMT_FLAG_SRGB_WRITE;
+
+                if (!(format->flags & (WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_SRGB_WRITE)))
+                    format->glGammaInternal = format->glInternal;
+                else if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
+                    format->glInternal = format->glGammaInternal;
             }
-            else if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
+        }
+        else
+        {
+            if (!gl_info->limits.vertex_samplers)
+                format->flags &= ~WINED3DFMT_FLAG_VTF;
+
+            if (!(gl_info->quirks & WINED3D_QUIRK_LIMITED_TEX_FILTERING))
+                format->flags |= WINED3DFMT_FLAG_FILTERING;
+            else if (format->id != WINED3DFMT_R32G32B32A32_FLOAT && format->id != WINED3DFMT_R32_FLOAT)
+                format->flags &= ~WINED3DFMT_FLAG_VTF;
+
+            if (format->glGammaInternal != format->glInternal)
             {
-                format->glInternal = format->glGammaInternal;
+                /* Filter sRGB capabilities if EXT_texture_sRGB is not supported. */
+                if (!gl_info->supported[EXT_TEXTURE_SRGB])
+                {
+                    format->glGammaInternal = format->glInternal;
+                    format->flags &= ~(WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_SRGB_WRITE);
+                }
+                else if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
+                {
+                    format->glInternal = format->glGammaInternal;
+                }
             }
-        }
 
-        if ((format->flags & WINED3DFMT_FLAG_SRGB_WRITE) && !srgb_write)
-            format->flags &= ~WINED3DFMT_FLAG_SRGB_WRITE;
+            if ((format->flags & WINED3DFMT_FLAG_SRGB_WRITE) && !srgb_write)
+                format->flags &= ~WINED3DFMT_FLAG_SRGB_WRITE;
+        }
 
         /* Texture conversion stuff */
         format->convert = format_texture_info[i].convert;
@@ -1485,6 +1604,10 @@ static void init_format_filter_info(struct wined3d_gl_info *gl_info, enum wined3
     };
     BOOL filtered;
 
+    if (gl_info->supported[ARB_INTERNALFORMAT_QUERY2])
+        /* This was already handled by init_format_texture_info(). */
+        return;
+
     if(wined3d_settings.offscreen_rendering_mode != ORM_FBO)
     {
         WARN("No FBO support, or no FBO ORM, guessing filter info from GL caps\n");
@@ -1640,7 +1763,7 @@ static void apply_format_fixups(struct wined3d_adapter *adapter, struct wined3d_
     gl_info->formats[idx].height_scale.denominator = 2;
     gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_YV12);
 
-    if (gl_info->supported[EXT_PALETTED_TEXTURE] || gl_info->supported[ARB_FRAGMENT_PROGRAM])
+    if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
     {
         idx = getFmtIdx(WINED3DFMT_P8_UINT);
         gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_P8);
@@ -1712,9 +1835,18 @@ static void apply_format_fixups(struct wined3d_adapter *adapter, struct wined3d_
         gl_info->formats[idx].flags |= WINED3DFMT_FLAG_TEXTURE;
     }
 
+    /* RESZ aka AMD DX9-level hack for multisampled depth buffer resolve. You query for RESZ
+     * support by checking for availability of MAKEFOURCC('R','E','S','Z') surfaces with
+     * RENDERTARGET usage. */
+    if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT])
+    {
+        idx = getFmtIdx(WINED3DFMT_RESZ);
+        gl_info->formats[idx].flags |= WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET;
+    }
+
     for (i = 0; i < sizeof(formats) / sizeof(*formats); ++i)
     {
-        struct wined3d_format *format = &gl_info->formats[idx];
+        struct wined3d_format *format = &gl_info->formats[i];
 
         if (!(format->flags & WINED3DFMT_FLAG_TEXTURE))
             continue;
@@ -1806,7 +1938,8 @@ const struct wined3d_format *wined3d_get_format(const struct wined3d_gl_info *gl
     return &gl_info->formats[idx];
 }
 
-UINT wined3d_format_calculate_size(const struct wined3d_format *format, UINT alignment, UINT width, UINT height)
+UINT wined3d_format_calculate_size(const struct wined3d_format *format, UINT alignment,
+        UINT width, UINT height, UINT depth)
 {
     UINT size;
 
@@ -1832,6 +1965,8 @@ UINT wined3d_format_calculate_size(const struct wined3d_format *format, UINT ali
         size /= format->height_scale.denominator;
     }
 
+    size *= depth;
+
     return size;
 }
 
@@ -1975,6 +2110,7 @@ const char *debug_d3dformat(enum wined3d_format_id format_id)
         FMT_TO_STR(WINED3DFMT_B8G8R8A8_UNORM);
         FMT_TO_STR(WINED3DFMT_B8G8R8X8_UNORM);
         FMT_TO_STR(WINED3DFMT_INTZ);
+        FMT_TO_STR(WINED3DFMT_RESZ);
         FMT_TO_STR(WINED3DFMT_NULL);
         FMT_TO_STR(WINED3DFMT_R16);
         FMT_TO_STR(WINED3DFMT_AL16);
@@ -2449,10 +2585,8 @@ const char *debug_d3dstate(DWORD state)
         return "STATE_GEOMETRY_SHADER";
     if (STATE_IS_VIEWPORT(state))
         return "STATE_VIEWPORT";
-    if (STATE_IS_VERTEXSHADERCONSTANT(state))
-        return "STATE_VERTEXSHADERCONSTANT";
-    if (STATE_IS_PIXELSHADERCONSTANT(state))
-        return "STATE_PIXELSHADERCONSTANT";
+    if (STATE_IS_LIGHT_TYPE(state))
+        return "STATE_LIGHT_TYPE";
     if (STATE_IS_ACTIVELIGHT(state))
         return wine_dbg_sprintf("STATE_ACTIVELIGHT(%#x)", state - STATE_ACTIVELIGHT(0));
     if (STATE_IS_SCISSORRECT(state))
@@ -2469,6 +2603,8 @@ const char *debug_d3dstate(DWORD state)
         return "STATE_BASEVERTEXINDEX";
     if (STATE_IS_FRAMEBUFFER(state))
         return "STATE_FRAMEBUFFER";
+    if (STATE_IS_POINT_SIZE_ENABLE(state))
+        return "STATE_POINT_SIZE_ENABLE";
 
     return wine_dbg_sprintf("UNKNOWN_STATE(%#x)", state);
 }
@@ -2971,7 +3107,7 @@ DWORD get_flexible_vertex_size(DWORD d3dvtVertexType) {
     return size;
 }
 
-void gen_ffp_frag_op(const struct wined3d_device *device, const struct wined3d_state *state,
+void gen_ffp_frag_op(const struct wined3d_context *context, const struct wined3d_state *state,
         struct ffp_frag_settings *settings, BOOL ignore_textype)
 {
 #define ARG1 0x01
@@ -3011,9 +3147,10 @@ void gen_ffp_frag_op(const struct wined3d_device *device, const struct wined3d_s
     DWORD ttff;
     DWORD cop, aop, carg0, carg1, carg2, aarg0, aarg1, aarg2;
     const struct wined3d_surface *rt = state->fb->render_targets[0];
-    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    const struct wined3d_d3d_info *d3d_info = context->d3d_info;
 
-    for (i = 0; i < gl_info->limits.texture_stages; ++i)
+    for (i = 0; i < d3d_info->limits.ffp_blend_stages; ++i)
     {
         const struct wined3d_texture *texture;
 
@@ -3183,13 +3320,13 @@ void gen_ffp_frag_op(const struct wined3d_device *device, const struct wined3d_s
 
     if (!state->render_states[WINED3D_RS_FOGENABLE])
     {
-        settings->fog = FOG_OFF;
+        settings->fog = WINED3D_FFP_PS_FOG_OFF;
     }
     else if (state->render_states[WINED3D_RS_FOGTABLEMODE] == WINED3D_FOG_NONE)
     {
         if (use_vs(state) || state->vertex_declaration->position_transformed)
         {
-            settings->fog = FOG_LINEAR;
+            settings->fog = WINED3D_FFP_PS_FOG_LINEAR;
         }
         else
         {
@@ -3197,13 +3334,13 @@ void gen_ffp_frag_op(const struct wined3d_device *device, const struct wined3d_s
             {
                 case WINED3D_FOG_NONE:
                 case WINED3D_FOG_LINEAR:
-                    settings->fog = FOG_LINEAR;
+                    settings->fog = WINED3D_FFP_PS_FOG_LINEAR;
                     break;
                 case WINED3D_FOG_EXP:
-                    settings->fog = FOG_EXP;
+                    settings->fog = WINED3D_FFP_PS_FOG_EXP;
                     break;
                 case WINED3D_FOG_EXP2:
-                    settings->fog = FOG_EXP2;
+                    settings->fog = WINED3D_FFP_PS_FOG_EXP2;
                     break;
             }
         }
@@ -3213,13 +3350,13 @@ void gen_ffp_frag_op(const struct wined3d_device *device, const struct wined3d_s
         switch (state->render_states[WINED3D_RS_FOGTABLEMODE])
         {
             case WINED3D_FOG_LINEAR:
-                settings->fog = FOG_LINEAR;
+                settings->fog = WINED3D_FFP_PS_FOG_LINEAR;
                 break;
             case WINED3D_FOG_EXP:
-                settings->fog = FOG_EXP;
+                settings->fog = WINED3D_FFP_PS_FOG_EXP;
                 break;
             case WINED3D_FOG_EXP2:
-                settings->fog = FOG_EXP2;
+                settings->fog = WINED3D_FFP_PS_FOG_EXP2;
                 break;
         }
     }
@@ -3231,7 +3368,7 @@ void gen_ffp_frag_op(const struct wined3d_device *device, const struct wined3d_s
     } else {
         settings->sRGB_write = 0;
     }
-    if (device->vs_clipping || !use_vs(state) || !state->render_states[WINED3D_RS_CLIPPING]
+    if (d3d_info->vs_clipping || !use_vs(state) || !state->render_states[WINED3D_RS_CLIPPING]
             || !state->render_states[WINED3D_RS_CLIPPLANEENABLE])
     {
         /* No need to emulate clipplanes if GL supports native vertex shader clipping or if
@@ -3401,6 +3538,117 @@ const struct wine_rb_functions wined3d_ffp_frag_program_rb_functions =
     ffp_frag_program_key_compare,
 };
 
+void wined3d_ffp_get_vs_settings(const struct wined3d_state *state, const struct wined3d_stream_info *si,
+        struct wined3d_ffp_vs_settings *settings)
+{
+    unsigned int coord_idx, i;
+
+    if (si->position_transformed)
+    {
+        memset(settings, 0, sizeof(*settings));
+
+        settings->transformed = 1;
+        settings->point_size = state->gl_primitive_type == GL_POINTS;
+        if (!state->render_states[WINED3D_RS_FOGENABLE])
+            settings->fog_mode = WINED3D_FFP_VS_FOG_OFF;
+        else if (state->render_states[WINED3D_RS_FOGTABLEMODE] != WINED3D_FOG_NONE)
+            settings->fog_mode = WINED3D_FFP_VS_FOG_DEPTH;
+        else
+            settings->fog_mode = WINED3D_FFP_VS_FOG_FOGCOORD;
+
+        for (i = 0; i < MAX_TEXTURES; ++i)
+        {
+            coord_idx = state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX];
+            if (coord_idx < MAX_TEXTURES && (si->use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coord_idx))))
+                settings->texcoords |= 1 << i;
+            settings->texgen[i] = (state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX] >> WINED3D_FFP_TCI_SHIFT)
+                    & WINED3D_FFP_TCI_MASK;
+        }
+        return;
+    }
+
+    settings->transformed = 0;
+    settings->clipping = state->render_states[WINED3D_RS_CLIPPING]
+            && state->render_states[WINED3D_RS_CLIPPLANEENABLE];
+    settings->normal = !!(si->use_map & (1 << WINED3D_FFP_NORMAL));
+    settings->normalize = settings->normal && state->render_states[WINED3D_RS_NORMALIZENORMALS];
+    settings->lighting = !!state->render_states[WINED3D_RS_LIGHTING];
+    settings->localviewer = !!state->render_states[WINED3D_RS_LOCALVIEWER];
+    settings->point_size = state->gl_primitive_type == GL_POINTS;
+
+    if (state->render_states[WINED3D_RS_COLORVERTEX] && (si->use_map & (1 << WINED3D_FFP_DIFFUSE)))
+    {
+        settings->diffuse_source = state->render_states[WINED3D_RS_DIFFUSEMATERIALSOURCE];
+        settings->emission_source = state->render_states[WINED3D_RS_EMISSIVEMATERIALSOURCE];
+        settings->ambient_source = state->render_states[WINED3D_RS_AMBIENTMATERIALSOURCE];
+        settings->specular_source = state->render_states[WINED3D_RS_SPECULARMATERIALSOURCE];
+    }
+    else
+    {
+        settings->diffuse_source = WINED3D_MCS_MATERIAL;
+        settings->emission_source = WINED3D_MCS_MATERIAL;
+        settings->ambient_source = WINED3D_MCS_MATERIAL;
+        settings->specular_source = WINED3D_MCS_MATERIAL;
+    }
+
+    settings->texcoords = 0;
+    for (i = 0; i < MAX_TEXTURES; ++i)
+    {
+        coord_idx = state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX];
+        if (coord_idx < MAX_TEXTURES && (si->use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coord_idx))))
+            settings->texcoords |= 1 << i;
+        settings->texgen[i] = (state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX] >> WINED3D_FFP_TCI_SHIFT)
+                & WINED3D_FFP_TCI_MASK;
+    }
+
+    settings->light_type = 0;
+    for (i = 0; i < MAX_ACTIVE_LIGHTS; ++i)
+    {
+        if (state->lights[i])
+            settings->light_type |= (state->lights[i]->OriginalParms.type
+                    & WINED3D_FFP_LIGHT_TYPE_MASK) << WINED3D_FFP_LIGHT_TYPE_SHIFT(i);
+    }
+
+    settings->ortho_fog = 0;
+    if (!state->render_states[WINED3D_RS_FOGENABLE])
+        settings->fog_mode = WINED3D_FFP_VS_FOG_OFF;
+    else if (state->render_states[WINED3D_RS_FOGTABLEMODE] != WINED3D_FOG_NONE)
+    {
+        settings->fog_mode = WINED3D_FFP_VS_FOG_DEPTH;
+
+        if (state->transforms[WINED3D_TS_PROJECTION].u.m[0][3] == 0.0f
+                && state->transforms[WINED3D_TS_PROJECTION].u.m[1][3] == 0.0f
+                && state->transforms[WINED3D_TS_PROJECTION].u.m[2][3] == 0.0f
+                && state->transforms[WINED3D_TS_PROJECTION].u.m[3][3] == 1.0f)
+            settings->ortho_fog = 1;
+    }
+    else if (state->render_states[WINED3D_RS_FOGVERTEXMODE] == WINED3D_FOG_NONE)
+        settings->fog_mode = WINED3D_FFP_VS_FOG_FOGCOORD;
+    else if (state->render_states[WINED3D_RS_RANGEFOGENABLE])
+        settings->fog_mode = WINED3D_FFP_VS_FOG_RANGE;
+    else
+        settings->fog_mode = WINED3D_FFP_VS_FOG_DEPTH;
+
+    settings->padding = 0;
+}
+
+static int wined3d_ffp_vertex_program_key_compare(const void *key, const struct wine_rb_entry *entry)
+{
+    const struct wined3d_ffp_vs_settings *ka = key;
+    const struct wined3d_ffp_vs_settings *kb = &WINE_RB_ENTRY_VALUE(entry,
+            const struct wined3d_ffp_vs_desc, entry)->settings;
+
+    return memcmp(ka, kb, sizeof(*ka));
+}
+
+const struct wine_rb_functions wined3d_ffp_vertex_program_rb_functions =
+{
+    wined3d_rb_alloc,
+    wined3d_rb_realloc,
+    wined3d_rb_free,
+    wined3d_ffp_vertex_program_key_compare,
+};
+
 UINT wined3d_log2i(UINT32 x)
 {
     static const UINT l[] =
@@ -3459,3 +3707,20 @@ void wined3d_get_draw_rect(const struct wined3d_state *state, RECT *rect)
     if (state->render_states[WINED3D_RS_SCISSORTESTENABLE])
         IntersectRect(rect, rect, &state->scissor_rect);
 }
+
+const char *wined3d_debug_location(DWORD location)
+{
+    char buf[200];
+
+    buf[0] = '\0';
+#define LOCATION_TO_STR(u) if (location & u) { strcat(buf, " | "#u); location &= ~u; }
+    LOCATION_TO_STR(WINED3D_LOCATION_DISCARDED);
+    LOCATION_TO_STR(WINED3D_LOCATION_SYSMEM);
+    LOCATION_TO_STR(WINED3D_LOCATION_BUFFER);
+    LOCATION_TO_STR(WINED3D_LOCATION_TEXTURE_RGB);
+    LOCATION_TO_STR(WINED3D_LOCATION_TEXTURE_SRGB);
+#undef LOCATION_TO_STR
+    if (location) FIXME("Unrecognized location flag(s) %#x.\n", location);
+
+    return buf[0] ? wine_dbg_sprintf("%s", &buf[3]) : "0";
+}
index af1d78a..4a36325 100644 (file)
@@ -164,7 +164,6 @@ static HRESULT vertexdeclaration_init(struct wined3d_vertex_declaration *declara
         void *parent, const struct wined3d_parent_ops *parent_ops)
 {
     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
-    WORD preloaded = 0; /* MAX_STREAMS, 16 */
     unsigned int i;
 
     if (TRACE_ON(d3d_decl))
@@ -224,13 +223,6 @@ static HRESULT vertexdeclaration_init(struct wined3d_vertex_declaration *declara
             return E_FAIL;
         }
 
-        if (!(preloaded & (1 << e->input_slot)))
-        {
-            declaration->streams[declaration->num_streams] = e->input_slot;
-            ++declaration->num_streams;
-            preloaded |= 1 << e->input_slot;
-        }
-
         if (elements[i].format == WINED3DFMT_R16G16_FLOAT || elements[i].format == WINED3DFMT_R16G16B16A16_FLOAT)
         {
             if (!gl_info->supported[ARB_HALF_FLOAT_VERTEX]) declaration->half_float_conv_needed = TRUE;
index 7de40bc..88a1e22 100644 (file)
@@ -3,6 +3,7 @@
  * Copyright 2002-2005 Raphael Junqueira
  * Copyright 2005 Oliver Stieber
  * Copyright 2009-2011 Henri Verbeet for CodeWeavers
+ * Copyright 2013 Stefan Dösinger for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
 #include "wined3d_private.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface);
+WINE_DECLARE_DEBUG_CHANNEL(d3d_perf);
 
 /* Context activation is done by the caller. */
-static void volume_bind_and_dirtify(const struct wined3d_volume *volume, struct wined3d_context *context)
+static void volume_bind_and_dirtify(const struct wined3d_volume *volume,
+        struct wined3d_context *context, BOOL srgb)
 {
     struct wined3d_texture *container = volume->container;
     DWORD active_sampler;
@@ -44,69 +47,394 @@ static void volume_bind_and_dirtify(const struct wined3d_volume *volume, struct
     if (active_sampler != WINED3D_UNMAPPED_STAGE)
         device_invalidate_state(volume->resource.device, STATE_SAMPLER(active_sampler));
 
-    container->texture_ops->texture_bind(container, context, FALSE);
+    container->texture_ops->texture_bind(container, context, srgb);
 }
 
-void volume_add_dirty_box(struct wined3d_volume *volume, const struct wined3d_box *dirty_box)
+void volume_set_container(struct wined3d_volume *volume, struct wined3d_texture *container)
+{
+    TRACE("volume %p, container %p.\n", volume, container);
+
+    volume->container = container;
+}
+
+/* Context activation is done by the caller. */
+static void wined3d_volume_allocate_texture(const struct wined3d_volume *volume,
+        const struct wined3d_context *context, BOOL srgb)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    const struct wined3d_format *format = volume->resource.format;
+
+    GL_EXTCALL(glTexImage3DEXT(GL_TEXTURE_3D, volume->texture_level,
+            srgb ? format->glGammaInternal : format->glInternal,
+            volume->resource.width, volume->resource.height, volume->resource.depth,
+            0, format->glFormat, format->glType, NULL));
+    checkGLcall("glTexImage3D");
+}
+
+/* Context activation is done by the caller. */
+void wined3d_volume_upload_data(struct wined3d_volume *volume, const struct wined3d_context *context,
+        const struct wined3d_bo_address *data)
 {
-    volume->dirty = TRUE;
-    if (dirty_box)
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    const struct wined3d_format *format = volume->resource.format;
+
+    TRACE("volume %p, context %p, level %u, format %s (%#x).\n",
+            volume, context, volume->texture_level, debug_d3dformat(format->id),
+            format->id);
+
+
+    if (data->buffer_object)
     {
-        volume->lockedBox.left = min(volume->lockedBox.left, dirty_box->left);
-        volume->lockedBox.top = min(volume->lockedBox.top, dirty_box->top);
-        volume->lockedBox.front = min(volume->lockedBox.front, dirty_box->front);
-        volume->lockedBox.right = max(volume->lockedBox.right, dirty_box->right);
-        volume->lockedBox.bottom = max(volume->lockedBox.bottom, dirty_box->bottom);
-        volume->lockedBox.back = max(volume->lockedBox.back, dirty_box->back);
+        GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, data->buffer_object));
+        checkGLcall("glBindBufferARB");
     }
-    else
+
+    GL_EXTCALL(glTexSubImage3DEXT(GL_TEXTURE_3D, volume->texture_level, 0, 0, 0,
+            volume->resource.width, volume->resource.height, volume->resource.depth,
+            format->glFormat, format->glType, data->addr));
+    checkGLcall("glTexSubImage3D");
+
+    if (data->buffer_object)
     {
-        volume->lockedBox.left = 0;
-        volume->lockedBox.top = 0;
-        volume->lockedBox.front = 0;
-        volume->lockedBox.right = volume->resource.width;
-        volume->lockedBox.bottom = volume->resource.height;
-        volume->lockedBox.back = volume->resource.depth;
+        GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
+        checkGLcall("glBindBufferARB");
     }
 }
 
-void volume_set_container(struct wined3d_volume *volume, struct wined3d_texture *container)
+static void wined3d_volume_validate_location(struct wined3d_volume *volume, DWORD location)
 {
-    TRACE("volume %p, container %p.\n", volume, container);
+    TRACE("Volume %p, setting %s.\n", volume, wined3d_debug_location(location));
+    volume->locations |= location;
+    TRACE("new location flags are %s.\n", wined3d_debug_location(volume->locations));
+}
 
-    volume->container = container;
+void wined3d_volume_invalidate_location(struct wined3d_volume *volume, DWORD location)
+{
+    TRACE("Volume %p, clearing %s.\n", volume, wined3d_debug_location(location));
+    volume->locations &= ~location;
+    TRACE("new location flags are %s.\n", wined3d_debug_location(volume->locations));
 }
 
 /* Context activation is done by the caller. */
-void volume_load(const struct wined3d_volume *volume, struct wined3d_context *context, UINT level, BOOL srgb_mode)
+static void wined3d_volume_download_data(struct wined3d_volume *volume,
+        const struct wined3d_context *context, const struct wined3d_bo_address *data)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
     const struct wined3d_format *format = volume->resource.format;
 
-    TRACE("volume %p, context %p, level %u, srgb %#x, format %s (%#x).\n",
-            volume, context, level, srgb_mode, debug_d3dformat(format->id), format->id);
+    if (data->buffer_object)
+    {
+        GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, data->buffer_object));
+        checkGLcall("glBindBufferARB");
+    }
 
-    volume_bind_and_dirtify(volume, context);
+    gl_info->gl_ops.gl.p_glGetTexImage(GL_TEXTURE_3D, volume->texture_level,
+            format->glFormat, format->glType, data->addr);
+    checkGLcall("glGetTexImage");
 
-    GL_EXTCALL(glTexImage3DEXT(GL_TEXTURE_3D, level, format->glInternal,
-            volume->resource.width, volume->resource.height, volume->resource.depth,
-            0, format->glFormat, format->glType, volume->resource.allocatedMemory));
-    checkGLcall("glTexImage3D");
+    if (data->buffer_object)
+    {
+        GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0));
+        checkGLcall("glBindBufferARB");
+    }
 
-    /* When adding code releasing volume->resource.allocatedMemory to save
-     * data keep in mind that GL_UNPACK_CLIENT_STORAGE_APPLE is enabled by
-     * default if supported(GL_APPLE_client_storage). Thus do not release
-     * volume->resource.allocatedMemory if GL_APPLE_client_storage is
-     * supported. */
 }
 
-/* Do not call while under the GL lock. */
+static void wined3d_volume_evict_sysmem(struct wined3d_volume *volume)
+{
+    wined3d_resource_free_sysmem(volume->resource.heap_memory);
+    volume->resource.heap_memory = NULL;
+    volume->resource.allocatedMemory = NULL;
+    wined3d_volume_invalidate_location(volume, WINED3D_LOCATION_SYSMEM);
+}
+
+static DWORD volume_access_from_location(DWORD location)
+{
+    switch (location)
+    {
+        case WINED3D_LOCATION_DISCARDED:
+            return 0;
+
+        case WINED3D_LOCATION_SYSMEM:
+            return WINED3D_RESOURCE_ACCESS_CPU;
+
+        case WINED3D_LOCATION_BUFFER:
+        case WINED3D_LOCATION_TEXTURE_RGB:
+        case WINED3D_LOCATION_TEXTURE_SRGB:
+            return WINED3D_RESOURCE_ACCESS_GPU;
+
+        default:
+            FIXME("Unhandled location %#x.\n", location);
+            return 0;
+    }
+}
+
+/* Context activation is done by the caller. */
+static void wined3d_volume_srgb_transfer(struct wined3d_volume *volume,
+        struct wined3d_context *context, BOOL dest_is_srgb)
+{
+    struct wined3d_bo_address data;
+    /* Optimizations are possible, but the effort should be put into either
+     * implementing EXT_SRGB_DECODE in the driver or finding out why we
+     * picked the wrong copy for the original upload and fixing that.
+     *
+     * Also keep in mind that we want to avoid using resource.allocatedMemory
+     * for DEFAULT pool surfaces. */
+
+    WARN_(d3d_perf)("Performing slow rgb/srgb volume transfer.\n");
+    data.buffer_object = 0;
+    data.addr = HeapAlloc(GetProcessHeap(), 0, volume->resource.size);
+    if (!data.addr)
+        return;
+
+    volume_bind_and_dirtify(volume, context, !dest_is_srgb);
+    wined3d_volume_download_data(volume, context, &data);
+    volume_bind_and_dirtify(volume, context, dest_is_srgb);
+    wined3d_volume_upload_data(volume, context, &data);
+
+    HeapFree(GetProcessHeap(), 0, data.addr);
+}
+
+/* Context activation is done by the caller. */
+static void wined3d_volume_load_location(struct wined3d_volume *volume,
+        struct wined3d_context *context, DWORD location)
+{
+    DWORD required_access = volume_access_from_location(location);
+
+    TRACE("Volume %p, loading %s, have %s.\n", volume, wined3d_debug_location(location),
+        wined3d_debug_location(volume->locations));
+
+    if ((volume->locations & location) == location)
+    {
+        TRACE("Location(s) already up to date.\n");
+        return;
+    }
+
+    if ((volume->resource.access_flags & required_access) != required_access)
+    {
+        ERR("Operation requires %#x access, but volume only has %#x.\n",
+                required_access, volume->resource.access_flags);
+        return;
+    }
+
+    switch (location)
+    {
+        case WINED3D_LOCATION_TEXTURE_RGB:
+        case WINED3D_LOCATION_TEXTURE_SRGB:
+            if ((location == WINED3D_LOCATION_TEXTURE_RGB
+                    && !(volume->flags & WINED3D_VFLAG_ALLOCATED))
+                    || (location == WINED3D_LOCATION_TEXTURE_SRGB
+                    && !(volume->flags & WINED3D_VFLAG_SRGB_ALLOCATED)))
+                ERR("Trying to load (s)RGB texture without prior allocation.\n");
+
+            if (volume->locations & WINED3D_LOCATION_DISCARDED)
+            {
+                TRACE("Volume previously discarded, nothing to do.\n");
+                wined3d_volume_invalidate_location(volume, WINED3D_LOCATION_DISCARDED);
+            }
+            else if (volume->locations & WINED3D_LOCATION_SYSMEM)
+            {
+                struct wined3d_bo_address data = {0, volume->resource.allocatedMemory};
+                wined3d_volume_upload_data(volume, context, &data);
+            }
+            else if (volume->locations & WINED3D_LOCATION_BUFFER)
+            {
+                struct wined3d_bo_address data = {volume->pbo, NULL};
+                wined3d_volume_upload_data(volume, context, &data);
+            }
+            else if (volume->locations & WINED3D_LOCATION_TEXTURE_RGB)
+            {
+                wined3d_volume_srgb_transfer(volume, context, TRUE);
+            }
+            else if (volume->locations & WINED3D_LOCATION_TEXTURE_SRGB)
+            {
+                wined3d_volume_srgb_transfer(volume, context, FALSE);
+            }
+            else
+            {
+                FIXME("Implement texture loading from %s.\n", wined3d_debug_location(volume->locations));
+                return;
+            }
+            wined3d_volume_validate_location(volume, location);
+
+            if (volume->resource.pool == WINED3D_POOL_MANAGED && volume->download_count < 10)
+                wined3d_volume_evict_sysmem(volume);
+
+            break;
+
+        case WINED3D_LOCATION_SYSMEM:
+            if (!volume->resource.allocatedMemory || !volume->resource.heap_memory)
+            {
+                ERR("Trying to load WINED3D_LOCATION_SYSMEM without setting it up first.\n");
+                return;
+            }
+
+            if (volume->locations & WINED3D_LOCATION_DISCARDED)
+            {
+                TRACE("Volume previously discarded, nothing to do.\n");
+                wined3d_volume_invalidate_location(volume, WINED3D_LOCATION_DISCARDED);
+            }
+            else if (volume->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB))
+            {
+                struct wined3d_bo_address data = {0, volume->resource.allocatedMemory};
+
+                if (volume->locations & WINED3D_LOCATION_TEXTURE_RGB)
+                    volume_bind_and_dirtify(volume, context, FALSE);
+                else
+                    volume_bind_and_dirtify(volume, context, TRUE);
+
+                volume->download_count++;
+                wined3d_volume_download_data(volume, context, &data);
+            }
+            else
+            {
+                FIXME("Implement WINED3D_LOCATION_SYSMEM loading from %s.\n",
+                        wined3d_debug_location(volume->locations));
+                return;
+            }
+            wined3d_volume_validate_location(volume, WINED3D_LOCATION_SYSMEM);
+            break;
+
+        case WINED3D_LOCATION_BUFFER:
+            if (!volume->pbo || !(volume->flags & WINED3D_VFLAG_PBO))
+                ERR("Trying to load WINED3D_LOCATION_BUFFER without setting it up first.\n");
+
+            if (volume->locations & WINED3D_LOCATION_DISCARDED)
+            {
+                TRACE("Volume previously discarded, nothing to do.\n");
+                wined3d_volume_invalidate_location(volume, WINED3D_LOCATION_DISCARDED);
+            }
+            else if (volume->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB))
+            {
+                struct wined3d_bo_address data = {volume->pbo, NULL};
+
+                if (volume->locations & WINED3D_LOCATION_TEXTURE_RGB)
+                    volume_bind_and_dirtify(volume, context, FALSE);
+                else
+                    volume_bind_and_dirtify(volume, context, TRUE);
+
+                wined3d_volume_download_data(volume, context, &data);
+            }
+            else
+            {
+                FIXME("Implement WINED3D_LOCATION_BUFFER loading from %s.\n",
+                        wined3d_debug_location(volume->locations));
+                return;
+            }
+            wined3d_volume_validate_location(volume, WINED3D_LOCATION_BUFFER);
+            break;
+
+        default:
+            FIXME("Implement %s loading from %s.\n", wined3d_debug_location(location),
+                    wined3d_debug_location(volume->locations));
+    }
+}
+
+/* Context activation is done by the caller. */
+void wined3d_volume_load(struct wined3d_volume *volume, struct wined3d_context *context, BOOL srgb_mode)
+{
+    volume_bind_and_dirtify(volume, context, srgb_mode);
+
+    if (srgb_mode)
+    {
+        if (!(volume->flags & WINED3D_VFLAG_SRGB_ALLOCATED))
+        {
+            wined3d_volume_allocate_texture(volume, context, TRUE);
+            volume->flags |= WINED3D_VFLAG_SRGB_ALLOCATED;
+        }
+
+        wined3d_volume_load_location(volume, context, WINED3D_LOCATION_TEXTURE_SRGB);
+    }
+    else
+    {
+        if (!(volume->flags & WINED3D_VFLAG_ALLOCATED))
+        {
+            wined3d_volume_allocate_texture(volume, context, FALSE);
+            volume->flags |= WINED3D_VFLAG_ALLOCATED;
+        }
+
+        wined3d_volume_load_location(volume, context, WINED3D_LOCATION_TEXTURE_RGB);
+    }
+}
+
+/* Context activation is done by the caller. */
+static void wined3d_volume_prepare_pbo(struct wined3d_volume *volume, struct wined3d_context *context)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    if (volume->pbo)
+        return;
+
+    GL_EXTCALL(glGenBuffersARB(1, &volume->pbo));
+    GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, volume->pbo));
+    GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, volume->resource.size, NULL, GL_STREAM_DRAW_ARB));
+    GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
+    checkGLcall("Create PBO");
+
+    TRACE("Created PBO %u for volume %p.\n", volume->pbo, volume);
+}
+
+static void wined3d_volume_free_pbo(struct wined3d_volume *volume)
+{
+    struct wined3d_context *context = context_acquire(volume->resource.device, NULL);
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    TRACE("Deleting PBO %u belonging to volume %p.\n", volume->pbo, volume);
+    GL_EXTCALL(glDeleteBuffersARB(1, &volume->pbo));
+    checkGLcall("glDeleteBuffersARB");
+    volume->pbo = 0;
+    context_release(context);
+}
+
+static BOOL volume_prepare_system_memory(struct wined3d_volume *volume)
+{
+    if (volume->resource.allocatedMemory)
+        return TRUE;
+
+    volume->resource.heap_memory = wined3d_resource_allocate_sysmem(volume->resource.size);
+    if (!volume->resource.heap_memory)
+        return FALSE;
+    volume->resource.allocatedMemory = volume->resource.heap_memory;
+    return TRUE;
+}
+
+
 static void volume_unload(struct wined3d_resource *resource)
 {
+    struct wined3d_volume *volume = volume_from_resource(resource);
+    struct wined3d_device *device = volume->resource.device;
+    struct wined3d_context *context;
+
+    if (volume->resource.pool == WINED3D_POOL_DEFAULT)
+        ERR("Unloading DEFAULT pool volume.\n");
+
     TRACE("texture %p.\n", resource);
 
-    /* The whole content is shadowed on This->resource.allocatedMemory, and
-     * the texture name is managed by the VolumeTexture container. */
+    if (volume_prepare_system_memory(volume))
+    {
+        context = context_acquire(device, NULL);
+        wined3d_volume_load_location(volume, context, WINED3D_LOCATION_SYSMEM);
+        context_release(context);
+        wined3d_volume_invalidate_location(volume, ~WINED3D_LOCATION_SYSMEM);
+    }
+    else
+    {
+        ERR("Out of memory when unloading volume %p.\n", volume);
+        wined3d_volume_validate_location(volume, WINED3D_LOCATION_DISCARDED);
+        wined3d_volume_invalidate_location(volume, ~WINED3D_LOCATION_DISCARDED);
+    }
+
+    if (volume->pbo)
+    {
+        /* Should not happen because only dynamic default pool volumes
+         * have a buffer, and those are not evicted by device_evit_managed_resources
+         * and must be freed before a non-ex device reset. */
+        ERR("Unloading a volume with a buffer\n");
+        wined3d_volume_free_pbo(volume);
+    }
+
+    /* The texture name is managed by the container. */
+    volume->flags &= ~(WINED3D_VFLAG_ALLOCATED | WINED3D_VFLAG_SRGB_ALLOCATED);
 
     resource_unload(resource);
 }
@@ -145,6 +473,9 @@ ULONG CDECL wined3d_volume_decref(struct wined3d_volume *volume)
 
     if (!refcount)
     {
+        if (volume->pbo)
+            wined3d_volume_free_pbo(volume);
+
         resource_cleanup(&volume->resource);
         volume->resource.parent_ops->wined3d_object_destroyed(volume->resource.parent);
         HeapFree(GetProcessHeap(), 0, volume);
@@ -186,13 +517,75 @@ struct wined3d_resource * CDECL wined3d_volume_get_resource(struct wined3d_volum
 HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume,
         struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags)
 {
+    struct wined3d_device *device = volume->resource.device;
+    struct wined3d_context *context;
+    const struct wined3d_gl_info *gl_info;
+    BYTE *base_memory;
+
     TRACE("volume %p, map_desc %p, box %p, flags %#x.\n",
             volume, map_desc, box, flags);
 
-    if (!volume->resource.allocatedMemory)
-        volume->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, volume->resource.size);
+    if (!(volume->resource.access_flags & WINED3D_RESOURCE_ACCESS_CPU))
+    {
+        WARN("Volume %p is not CPU accessible.\n", volume);
+        map_desc->data = NULL;
+        return WINED3DERR_INVALIDCALL;
+    }
+    flags = wined3d_resource_sanitize_map_flags(&volume->resource, flags);
 
-    TRACE("allocatedMemory %p.\n", volume->resource.allocatedMemory);
+    if (volume->flags & WINED3D_VFLAG_PBO)
+    {
+        context = context_acquire(device, NULL);
+        gl_info = context->gl_info;
+
+        wined3d_volume_prepare_pbo(volume, context);
+        if (flags & WINED3D_MAP_DISCARD)
+            wined3d_volume_validate_location(volume, WINED3D_LOCATION_BUFFER);
+        else
+            wined3d_volume_load_location(volume, context, WINED3D_LOCATION_BUFFER);
+
+        GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, volume->pbo));
+
+        if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
+        {
+            GLbitfield mapflags = wined3d_resource_gl_map_flags(flags);
+            mapflags &= ~GL_MAP_FLUSH_EXPLICIT_BIT;
+            base_memory = GL_EXTCALL(glMapBufferRange(GL_PIXEL_UNPACK_BUFFER_ARB,
+                    0, volume->resource.size, mapflags));
+        }
+        else
+        {
+            base_memory = GL_EXTCALL(glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
+        }
+
+        GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
+        checkGLcall("Map PBO");
+
+        context_release(context);
+    }
+    else
+    {
+        if (!volume_prepare_system_memory(volume))
+        {
+            WARN("Out of memory.\n");
+            map_desc->data = NULL;
+            return E_OUTOFMEMORY;
+        }
+
+        if (flags & WINED3D_MAP_DISCARD)
+        {
+            wined3d_volume_validate_location(volume, WINED3D_LOCATION_SYSMEM);
+        }
+        else if (!(volume->locations & WINED3D_LOCATION_SYSMEM))
+        {
+            context = context_acquire(device, NULL);
+            wined3d_volume_load_location(volume, context, WINED3D_LOCATION_SYSMEM);
+            context_release(context);
+        }
+        base_memory = volume->resource.allocatedMemory;
+    }
+
+    TRACE("Base memory pointer %p.\n", base_memory);
 
     map_desc->row_pitch = volume->resource.format->byte_count * volume->resource.width; /* Bytes / row */
     map_desc->slice_pitch = volume->resource.format->byte_count
@@ -200,37 +593,29 @@ HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume,
     if (!box)
     {
         TRACE("No box supplied - all is ok\n");
-        map_desc->data = volume->resource.allocatedMemory;
-        volume->lockedBox.left   = 0;
-        volume->lockedBox.top    = 0;
-        volume->lockedBox.front  = 0;
-        volume->lockedBox.right  = volume->resource.width;
-        volume->lockedBox.bottom = volume->resource.height;
-        volume->lockedBox.back   = volume->resource.depth;
+        map_desc->data = base_memory;
     }
     else
     {
         TRACE("Lock Box (%p) = l %u, t %u, r %u, b %u, fr %u, ba %u\n",
                 box, box->left, box->top, box->right, box->bottom, box->front, box->back);
-        map_desc->data = volume->resource.allocatedMemory
+        map_desc->data = base_memory
                 + (map_desc->slice_pitch * box->front)     /* FIXME: is front < back or vica versa? */
                 + (map_desc->row_pitch * box->top)
                 + (box->left * volume->resource.format->byte_count);
-        volume->lockedBox.left   = box->left;
-        volume->lockedBox.top    = box->top;
-        volume->lockedBox.front  = box->front;
-        volume->lockedBox.right  = box->right;
-        volume->lockedBox.bottom = box->bottom;
-        volume->lockedBox.back   = box->back;
     }
 
     if (!(flags & (WINED3D_MAP_NO_DIRTY_UPDATE | WINED3D_MAP_READONLY)))
     {
-        volume_add_dirty_box(volume, &volume->lockedBox);
         wined3d_texture_set_dirty(volume->container, TRUE);
+
+        if (volume->flags & WINED3D_VFLAG_PBO)
+            wined3d_volume_invalidate_location(volume, ~WINED3D_LOCATION_BUFFER);
+        else
+            wined3d_volume_invalidate_location(volume, ~WINED3D_LOCATION_SYSMEM);
     }
 
-    volume->locked = TRUE;
+    volume->flags |= WINED3D_VFLAG_LOCKED;
 
     TRACE("Returning memory %p, row pitch %d, slice pitch %d.\n",
             map_desc->data, map_desc->row_pitch, map_desc->slice_pitch);
@@ -247,14 +632,27 @@ HRESULT CDECL wined3d_volume_unmap(struct wined3d_volume *volume)
 {
     TRACE("volume %p.\n", volume);
 
-    if (!volume->locked)
+    if (!(volume->flags & WINED3D_VFLAG_LOCKED))
     {
         WARN("Trying to unlock unlocked volume %p.\n", volume);
         return WINED3DERR_INVALIDCALL;
     }
 
-    volume->locked = FALSE;
-    memset(&volume->lockedBox, 0, sizeof(volume->lockedBox));
+    if (volume->flags & WINED3D_VFLAG_PBO)
+    {
+        struct wined3d_device *device = volume->resource.device;
+        struct wined3d_context *context = context_acquire(device, NULL);
+        const struct wined3d_gl_info *gl_info = context->gl_info;
+
+        GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, volume->pbo));
+        GL_EXTCALL(glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB));
+        GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
+        checkGLcall("Unmap PBO");
+
+        context_release(context);
+    }
+
+    volume->flags &= ~WINED3D_VFLAG_LOCKED;
 
     return WINED3D_OK;
 }
@@ -265,42 +663,57 @@ static const struct wined3d_resource_ops volume_resource_ops =
 };
 
 static HRESULT volume_init(struct wined3d_volume *volume, struct wined3d_device *device, UINT width,
-        UINT height, UINT depth, DWORD usage, enum wined3d_format_id format_id, enum wined3d_pool pool,
-        void *parent, const struct wined3d_parent_ops *parent_ops)
+        UINT height, UINT depth, UINT level, DWORD usage, enum wined3d_format_id format_id,
+        enum wined3d_pool pool, void *parent, const struct wined3d_parent_ops *parent_ops)
 {
     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
     const struct wined3d_format *format = wined3d_get_format(gl_info, format_id);
     HRESULT hr;
+    UINT size;
 
     if (!gl_info->supported[EXT_TEXTURE3D])
     {
         WARN("Volume cannot be created - no volume texture support.\n");
         return WINED3DERR_INVALIDCALL;
     }
+    /* TODO: Write tests for other resources and move this check
+     * to resource_init, if applicable. */
+    if (usage & WINED3DUSAGE_DYNAMIC
+            && (pool == WINED3D_POOL_MANAGED || pool == WINED3D_POOL_SCRATCH))
+    {
+        WARN("Attempted to create a DYNAMIC texture in pool %u.\n", pool);
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    size = wined3d_format_calculate_size(format, device->surface_alignment, width, height, depth);
 
     hr = resource_init(&volume->resource, device, WINED3D_RTYPE_VOLUME, format,
             WINED3D_MULTISAMPLE_NONE, 0, usage, pool, width, height, depth,
-            width * height * depth * format->byte_count, parent, parent_ops,
-            &volume_resource_ops);
+            size, parent, parent_ops, &volume_resource_ops);
     if (FAILED(hr))
     {
         WARN("Failed to initialize resource, returning %#x.\n", hr);
         return hr;
     }
 
-    volume->lockable = TRUE;
-    volume->locked = FALSE;
-    memset(&volume->lockedBox, 0, sizeof(volume->lockedBox));
-    volume->dirty = TRUE;
+    volume->texture_level = level;
+    volume->locations = WINED3D_LOCATION_DISCARDED;
 
-    volume_add_dirty_box(volume, NULL);
+    if (pool == WINED3D_POOL_DEFAULT && usage & WINED3DUSAGE_DYNAMIC
+            && gl_info->supported[ARB_PIXEL_BUFFER_OBJECT])
+    {
+        wined3d_resource_free_sysmem(volume->resource.heap_memory);
+        volume->resource.heap_memory = NULL;
+        volume->resource.allocatedMemory = NULL;
+        volume->flags |= WINED3D_VFLAG_PBO;
+    }
 
     return WINED3D_OK;
 }
 
 HRESULT CDECL wined3d_volume_create(struct wined3d_device *device, UINT width, UINT height,
-        UINT depth, DWORD usage, enum wined3d_format_id format_id, enum wined3d_pool pool, void *parent,
-        const struct wined3d_parent_ops *parent_ops, struct wined3d_volume **volume)
+        UINT depth, UINT level, DWORD usage, enum wined3d_format_id format_id, enum wined3d_pool pool,
+        void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_volume **volume)
 {
     struct wined3d_volume *object;
     HRESULT hr;
@@ -316,7 +729,8 @@ HRESULT CDECL wined3d_volume_create(struct wined3d_device *device, UINT width, U
         return WINED3DERR_OUTOFVIDEOMEMORY;
     }
 
-    hr = volume_init(object, device, width, height, depth, usage, format_id, pool, parent, parent_ops);
+    hr = volume_init(object, device, width, height, depth, level,
+            usage, format_id, pool, parent, parent_ops);
     if (FAILED(hr))
     {
         WARN("Failed to initialize volume, returning %#x.\n", hr);
index 0f7e703..f451b7a 100644 (file)
 @ cdecl wined3d_surface_releasedc(ptr ptr)
 @ cdecl wined3d_surface_restore(ptr)
 @ cdecl wined3d_surface_set_color_key(ptr long ptr)
-@ cdecl wined3d_surface_set_mem(ptr ptr)
+@ cdecl wined3d_surface_set_mem(ptr ptr long)
 @ cdecl wined3d_surface_set_overlay_position(ptr long long)
 @ cdecl wined3d_surface_set_palette(ptr ptr)
 @ cdecl wined3d_surface_set_priority(ptr long)
 @ cdecl wined3d_swapchain_set_window(ptr ptr)
 
 @ cdecl wined3d_texture_add_dirty_region(ptr long ptr)
-@ cdecl wined3d_texture_create_2d(ptr long long long long long long ptr ptr ptr)
-@ cdecl wined3d_texture_create_3d(ptr long long long long long long long ptr ptr ptr)
-@ cdecl wined3d_texture_create_cube(ptr long long long long long ptr ptr ptr)
+@ cdecl wined3d_texture_create_2d(ptr ptr long long ptr ptr ptr)
+@ cdecl wined3d_texture_create_3d(ptr ptr long ptr ptr ptr)
+@ cdecl wined3d_texture_create_cube(ptr ptr long long ptr ptr ptr)
 @ cdecl wined3d_texture_decref(ptr)
 @ cdecl wined3d_texture_generate_mipmaps(ptr)
 @ cdecl wined3d_texture_get_autogen_filter_type(ptr)
index 06b5274..8ad865e 100644 (file)
@@ -44,6 +44,7 @@ enum wined3d_gl_extension
     APPLE_YCBCR_422,
     /* ARB */
     ARB_COLOR_BUFFER_FLOAT,
+    ARB_DEBUG_OUTPUT,
     ARB_DEPTH_BUFFER_FLOAT,
     ARB_DEPTH_CLAMP,
     ARB_DEPTH_TEXTURE,
@@ -58,6 +59,7 @@ enum wined3d_gl_extension
     ARB_HALF_FLOAT_PIXEL,
     ARB_HALF_FLOAT_VERTEX,
     ARB_INSTANCED_ARRAYS,
+    ARB_INTERNALFORMAT_QUERY2,
     ARB_MAP_BUFFER_ALIGNMENT,
     ARB_MAP_BUFFER_RANGE,
     ARB_MULTISAMPLE,
@@ -111,7 +113,6 @@ enum wined3d_gl_extension
     EXT_GPU_PROGRAM_PARAMETERS,
     EXT_GPU_SHADER4,
     EXT_PACKED_DEPTH_STENCIL,
-    EXT_PALETTED_TEXTURE,
     EXT_POINT_PARAMETERS,
     EXT_PROVOKING_VERTEX,
     EXT_SECONDARY_COLOR,
@@ -179,6 +180,11 @@ enum wined3d_gl_extension
     USE_GL_FUNC(glFlushMappedBufferRangeAPPLE) \
     /* GL_ARB_color_buffer_float */ \
     USE_GL_FUNC(glClampColorARB) \
+    /* GL_ARB_debug_output */ \
+    USE_GL_FUNC(glDebugMessageCallbackARB) \
+    USE_GL_FUNC(glDebugMessageControlARB) \
+    USE_GL_FUNC(glDebugMessageInsertARB) \
+    USE_GL_FUNC(glGetDebugMessageLogARB) \
     /* GL_ARB_draw_buffers */ \
     USE_GL_FUNC(glDrawBuffersARB) \
     /* GL_ARB_draw_elements_base_vertex */ \
@@ -217,6 +223,10 @@ enum wined3d_gl_extension
     USE_GL_FUNC(glProgramParameteriARB) \
     /* GL_ARB_instanced_arrays */ \
     USE_GL_FUNC(glVertexAttribDivisorARB) \
+    /* GL_ARB_internalformat_query */ \
+    USE_GL_FUNC(glGetInternalformativ) \
+    /* GL_ARB_internalformat_query2 */ \
+    USE_GL_FUNC(glGetInternalformati64v) \
     /* GL_ARB_map_buffer_range */ \
     USE_GL_FUNC(glFlushMappedBufferRange) \
     USE_GL_FUNC(glMapBufferRange) \
@@ -240,8 +250,10 @@ enum wined3d_gl_extension
     USE_GL_FUNC(glDeleteQueriesARB) \
     USE_GL_FUNC(glEndQueryARB) \
     USE_GL_FUNC(glGenQueriesARB) \
+    USE_GL_FUNC(glGetQueryivARB) \
     USE_GL_FUNC(glGetQueryObjectivARB) \
     USE_GL_FUNC(glGetQueryObjectuivARB) \
+    USE_GL_FUNC(glIsQueryARB) \
     /* GL_ARB_point_parameters */ \
     USE_GL_FUNC(glPointParameterfARB) \
     USE_GL_FUNC(glPointParameterfvARB) \
@@ -474,8 +486,6 @@ enum wined3d_gl_extension
     USE_GL_FUNC(glVertexAttribI4uivEXT) \
     USE_GL_FUNC(glVertexAttribI4usvEXT) \
     USE_GL_FUNC(glVertexAttribIPointerEXT) \
-    /* GL_EXT_paletted_texture */ \
-    USE_GL_FUNC(glColorTableEXT) \
     /* GL_EXT_point_parameters */ \
     USE_GL_FUNC(glPointParameterfEXT) \
     USE_GL_FUNC(glPointParameterfvEXT) \
index cb2b0c4..56d45d2 100644 (file)
@@ -74,7 +74,6 @@ struct wined3d_settings wined3d_settings =
 {
     TRUE,           /* Use of GLSL enabled by default */
     ORM_FBO,        /* Use FBOs to do offscreen rendering */
-    RTL_READTEX,    /* Default render target locking method */
     PCI_VENDOR_NONE,/* PCI Vendor ID */
     PCI_DEVICE_NONE,/* PCI Device ID */
     0,              /* The default of memory is set in init_driver_info */
@@ -85,6 +84,7 @@ struct wined3d_settings wined3d_settings =
     ~0U,            /* No VS shader model limit by default. */
     ~0U,            /* No GS shader model limit by default. */
     ~0U,            /* No PS shader model limit by default. */
+    FALSE,          /* 3D support enabled by default. */
 };
 
 /* Do not call while under the GL lock. */
@@ -100,6 +100,9 @@ struct wined3d * CDECL wined3d_create(UINT version, DWORD flags)
         return NULL;
     }
 
+    if (version == 7 && wined3d_settings.no_3d)
+        flags |= WINED3D_NO3D;
+
     hr = wined3d_init(object, version, flags);
     if (FAILED(hr))
     {
@@ -219,19 +222,6 @@ static BOOL wined3d_dll_init(HINSTANCE hInstDLL)
                 wined3d_settings.offscreen_rendering_mode = ORM_FBO;
             }
         }
-        if ( !get_config_key( hkey, appkey, "RenderTargetLockMode", buffer, size) )
-        {
-            if (!strcmp(buffer,"readdraw"))
-            {
-                TRACE("Using glReadPixels for render target reading and glDrawPixels for writing\n");
-                wined3d_settings.rendertargetlock_mode = RTL_READDRAW;
-            }
-            else if (!strcmp(buffer,"readtex"))
-            {
-                TRACE("Using glReadPixels for render target reading and textures for writing\n");
-                wined3d_settings.rendertargetlock_mode = RTL_READTEX;
-            }
-        }
         if ( !get_config_key_dword( hkey, appkey, "VideoPciDeviceID", &tmpvalue) )
         {
             int pci_device_id = tmpvalue;
@@ -309,6 +299,12 @@ static BOOL wined3d_dll_init(HINSTANCE hInstDLL)
             TRACE("Limiting GS shader model to %u.\n", wined3d_settings.max_sm_gs);
         if (!get_config_key_dword(hkey, appkey, "MaxShaderModelPS", &wined3d_settings.max_sm_ps))
             TRACE("Limiting PS shader model to %u.\n", wined3d_settings.max_sm_ps);
+        if (!get_config_key(hkey, appkey, "DirectDrawRenderer", buffer, size)
+                && !strcmp(buffer, "gdi"))
+        {
+            TRACE("Disabling 3D support.\n");
+            wined3d_settings.no_3d = TRUE;
+        }
     }
 
     if (appkey) RegCloseKey( appkey );
@@ -521,18 +517,15 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
             return wined3d_dll_init(hInstDLL);
 
         case DLL_PROCESS_DETACH:
+            if (lpv) break;
             return wined3d_dll_destroy(hInstDLL);
 
         case DLL_THREAD_DETACH:
-        {
             if (!context_set_current(NULL))
             {
                 ERR("Failed to clear current context.\n");
             }
             return TRUE;
-        }
-
-        default:
-            return TRUE;
     }
+    return TRUE;
 }
index e57a1e7..db075cc 100644 (file)
@@ -5,6 +5,7 @@
  * Copyright 2002-2003 Raphael Junqueira
  * Copyright 2002-2003, 2004 Jason Edmeades
  * Copyright 2005 Oliver Stieber
+ * Copyright 2006-2011, 2013 Stefan Dösinger for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -65,6 +66,7 @@
 #define WINED3D_QUIRK_BROKEN_RGBA16             0x00000040
 #define WINED3D_QUIRK_INFO_LOG_SPAM             0x00000080
 #define WINED3D_QUIRK_LIMITED_TEX_FILTERING     0x00000100
+#define WINED3D_QUIRK_BROKEN_ARB_FOG            0x00000200
 
 /* Texture format fixups */
 
@@ -157,7 +159,6 @@ void *wined3d_rb_realloc(void *ptr, size_t size) DECLSPEC_HIDDEN;
 void wined3d_rb_free(void *ptr) DECLSPEC_HIDDEN;
 
 /* Device caps */
-#define MAX_PALETTES            65536
 #define MAX_STREAM_OUT          4
 #define MAX_STREAMS             16
 #define MAX_TEXTURES            8
@@ -244,9 +245,6 @@ static inline float float_24_to_32(DWORD in)
 #define ORM_BACKBUFFER  0
 #define ORM_FBO         1
 
-#define RTL_READDRAW   1
-#define RTL_READTEX    2
-
 #define PCI_VENDOR_NONE 0xffff /* e.g. 0x8086 for Intel and 0x10de for Nvidia */
 #define PCI_DEVICE_NONE 0xffff /* e.g. 0x14f for a Geforce6200 */
 
@@ -259,7 +257,6 @@ struct wined3d_settings
      * implemented, we'll leave it as a registry setting for developers. */
     BOOL glslRequested;
     int offscreen_rendering_mode;
-    int rendertargetlock_mode;
     unsigned short pci_vendor_id;
     unsigned short pci_device_id;
     /* Memory tracking and object counting. */
@@ -271,6 +268,7 @@ struct wined3d_settings
     unsigned int max_sm_vs;
     unsigned int max_sm_gs;
     unsigned int max_sm_ps;
+    BOOL no_3d;
 };
 
 extern struct wined3d_settings wined3d_settings DECLSPEC_HIDDEN;
@@ -284,6 +282,18 @@ enum wined3d_sampler_texture_type
     WINED3DSTT_VOLUME = 4,
 };
 
+#define WINED3D_SHADER_CONST_VS_F           0x00000001
+#define WINED3D_SHADER_CONST_VS_I           0x00000002
+#define WINED3D_SHADER_CONST_VS_B           0x00000004
+#define WINED3D_SHADER_CONST_VS_POS_FIXUP   0x00000008
+#define WINED3D_SHADER_CONST_PS_F           0x00000010
+#define WINED3D_SHADER_CONST_PS_I           0x00000020
+#define WINED3D_SHADER_CONST_PS_B           0x00000040
+#define WINED3D_SHADER_CONST_PS_BUMP_ENV    0x00000080
+#define WINED3D_SHADER_CONST_PS_Y_CORR      0x00000100
+#define WINED3D_SHADER_CONST_PS_NP2_FIXUP   0x00000200
+#define WINED3D_SHADER_CONST_FFP_PS         0x00000400
+
 enum wined3d_shader_register_type
 {
     WINED3DSPR_TEMP = 0,
@@ -406,12 +416,11 @@ enum wined3d_shader_rel_op
  * Shader model 3 according to msdn (and for software shaders) */
 #define MAX_LABELS 16
 
-#define SHADER_PGMSIZE 65535
-
 struct wined3d_shader_buffer
 {
     char *buffer;
-    unsigned int bsize;
+    unsigned int buffer_size;
+    unsigned int content_size;
     unsigned int lineNo;
     BOOL newline;
 };
@@ -735,11 +744,12 @@ enum vertexprocessing_mode {
 
 #define WINED3D_CONST_NUM_UNUSED ~0U
 
-enum fogmode {
-    FOG_OFF,
-    FOG_LINEAR,
-    FOG_EXP,
-    FOG_EXP2
+enum wined3d_ffp_ps_fog_mode
+{
+    WINED3D_FFP_PS_FOG_OFF,
+    WINED3D_FFP_PS_FOG_LINEAR,
+    WINED3D_FFP_PS_FOG_EXP,
+    WINED3D_FFP_PS_FOG_EXP2,
 };
 
 /* Stateblock dependent parameters which have to be hardcoded
@@ -749,13 +759,25 @@ enum fogmode {
 #define WINED3D_PSARGS_PROJECTED (1 << 3)
 #define WINED3D_PSARGS_TEXTRANSFORM_SHIFT 4
 #define WINED3D_PSARGS_TEXTRANSFORM_MASK 0xf
+#define WINED3D_PSARGS_TEXTYPE_SHIFT 2
+#define WINED3D_PSARGS_TEXTYPE_MASK 0x3
+
+/* Similar to tex_types, except that it doesn't have 1d textures
+ * (can't be bound), rect textures (handled via np2_fixup) and
+ * none / unknown (treated as 2d and handled via dummy textures). */
+enum wined3d_shader_tex_types
+{
+    WINED3D_SHADER_TEX_2D   = 0,
+    WINED3D_SHADER_TEX_3D   = 1,
+    WINED3D_SHADER_TEX_CUBE = 2,
+};
 
 struct ps_compile_args {
     struct color_fixup_desc     color_fixup[MAX_FRAGMENT_SAMPLERS];
     enum vertexprocessing_mode  vp_mode;
-    enum fogmode                fog;
+    enum wined3d_ffp_ps_fog_mode fog;
     WORD                        tex_transform; /* ps 1.0-1.3, 4 textures */
-    /* Texture types(2D, Cube, 3D) in ps 1.x */
+    WORD                        tex_types; /* ps 1.0 - 1.4, 6 textures */
     WORD                        srgb_correction;
     WORD                        np2_fixup;
     /* Bitmap for NP2 texcoord fixups (16 samplers max currently).
@@ -775,34 +797,30 @@ struct vs_compile_args {
     WORD                        swizzle_map;   /* MAX_ATTRIBS, 16 */
 };
 
-enum wined3d_shader_mode
-{
-    WINED3D_SHADER_MODE_NONE,
-    WINED3D_SHADER_MODE_FFP,
-    WINED3D_SHADER_MODE_SHADER,
-};
-
 struct wined3d_context;
 struct wined3d_state;
 struct fragment_pipeline;
+struct wined3d_vertex_pipe_ops;
 
 struct wined3d_shader_backend_ops
 {
     void (*shader_handle_instruction)(const struct wined3d_shader_instruction *);
-    void (*shader_select)(const struct wined3d_context *context, enum wined3d_shader_mode vertex_mode,
-            enum wined3d_shader_mode fragment_mode);
+    void (*shader_select)(void *shader_priv, struct wined3d_context *context,
+            const struct wined3d_state *state);
+    void (*shader_disable)(void *shader_priv, struct wined3d_context *context);
     void (*shader_select_depth_blt)(void *shader_priv, const struct wined3d_gl_info *gl_info,
             enum tex_types tex_type, const SIZE *ds_mask_size);
     void (*shader_deselect_depth_blt)(void *shader_priv, const struct wined3d_gl_info *gl_info);
     void (*shader_update_float_vertex_constants)(struct wined3d_device *device, UINT start, UINT count);
     void (*shader_update_float_pixel_constants)(struct wined3d_device *device, UINT start, UINT count);
-    void (*shader_load_constants)(const struct wined3d_context *context, BOOL usePS, BOOL useVS);
-    void (*shader_load_np2fixup_constants)(void *shader_priv, const struct wined3d_gl_info *gl_info,
+    void (*shader_load_constants)(void *shader_priv, struct wined3d_context *context,
             const struct wined3d_state *state);
     void (*shader_destroy)(struct wined3d_shader *shader);
-    HRESULT (*shader_alloc_private)(struct wined3d_device *device, const struct fragment_pipeline *fragment_pipe);
+    HRESULT (*shader_alloc_private)(struct wined3d_device *device, const struct wined3d_vertex_pipe_ops *vertex_pipe,
+            const struct fragment_pipeline *fragment_pipe);
     void (*shader_free_private)(struct wined3d_device *device);
-    void (*shader_context_destroyed)(void *shader_priv, const struct wined3d_context *context);
+    BOOL (*shader_allocate_context_data)(struct wined3d_context *context);
+    void (*shader_free_context_data)(struct wined3d_context *context);
     void (*shader_get_caps)(const struct wined3d_gl_info *gl_info, struct shader_caps *caps);
     BOOL (*shader_color_fixup_supported)(struct color_fixup_desc fixup);
     BOOL (*shader_has_ffp_proj_control)(void *shader_priv);
@@ -854,15 +872,6 @@ do {                                                                \
 #define checkGLcall(A) do {} while(0)
 #endif
 
-/* Trace vector and strided data information */
-#define TRACE_STRIDED(si, name) do { if (si->use_map & (1 << name)) \
-        TRACE( #name " = (data {%#x:%p}, stride %d, format %s, stream %u)\n", \
-        si->elements[name].data.buffer_object, si->elements[name].data.addr, si->elements[name].stride, \
-        debug_d3dformat(si->elements[name].format->id), si->elements[name].stream_idx); } while(0)
-
-/* Global variables */
-extern const struct wined3d_matrix identity DECLSPEC_HIDDEN;
-
 enum wined3d_ffp_idx
 {
     WINED3D_FFP_POSITION = 0,
@@ -901,13 +910,14 @@ enum wined3d_ffp_emit_idx
     WINED3D_FFP_EMIT_DEC3N = 14,
     WINED3D_FFP_EMIT_FLOAT16_2 = 15,
     WINED3D_FFP_EMIT_FLOAT16_4 = 16,
-    WINED3D_FFP_EMIT_COUNT = 17
+    WINED3D_FFP_EMIT_INVALID = 17,
+    WINED3D_FFP_EMIT_COUNT = 18
 };
 
 struct wined3d_bo_address
 {
     GLuint buffer_object;
-    const BYTE *addr;
+    BYTE *addr;
 };
 
 struct wined3d_stream_info_element
@@ -928,18 +938,9 @@ struct wined3d_stream_info
 };
 
 void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_count,
-        UINT start_instance, UINT instance_count, BOOL indexed, const void *idx_data) DECLSPEC_HIDDEN;
+        UINT start_instance, UINT instance_count, BOOL indexed) DECLSPEC_HIDDEN;
 DWORD get_flexible_vertex_size(DWORD d3dvtVertexType) DECLSPEC_HIDDEN;
 
-typedef void (WINE_GLAPI *glAttribFunc)(const void *data);
-typedef void (WINE_GLAPI *glMultiTexCoordFunc)(GLenum unit, const void *data);
-extern glAttribFunc position_funcs[WINED3D_FFP_EMIT_COUNT] DECLSPEC_HIDDEN;
-extern glAttribFunc diffuse_funcs[WINED3D_FFP_EMIT_COUNT] DECLSPEC_HIDDEN;
-extern glAttribFunc specular_func_3ubv DECLSPEC_HIDDEN;
-extern glAttribFunc specular_funcs[WINED3D_FFP_EMIT_COUNT] DECLSPEC_HIDDEN;
-extern glAttribFunc normal_funcs[WINED3D_FFP_EMIT_COUNT] DECLSPEC_HIDDEN;
-extern glMultiTexCoordFunc multi_texcoord_funcs[WINED3D_FFP_EMIT_COUNT] DECLSPEC_HIDDEN;
-
 #define eps 1e-8
 
 #define GET_TEXCOORD_SIZE_FROM_FVF(d3dvtVertexType, tex_num) \
@@ -980,12 +981,9 @@ extern glMultiTexCoordFunc multi_texcoord_funcs[WINED3D_FFP_EMIT_COUNT] DECLSPEC
 #define STATE_VIEWPORT (STATE_GEOMETRY_SHADER + 1)
 #define STATE_IS_VIEWPORT(a) ((a) == STATE_VIEWPORT)
 
-#define STATE_VERTEXSHADERCONSTANT (STATE_VIEWPORT + 1)
-#define STATE_PIXELSHADERCONSTANT (STATE_VERTEXSHADERCONSTANT + 1)
-#define STATE_IS_VERTEXSHADERCONSTANT(a) ((a) == STATE_VERTEXSHADERCONSTANT)
-#define STATE_IS_PIXELSHADERCONSTANT(a) ((a) == STATE_PIXELSHADERCONSTANT)
-
-#define STATE_ACTIVELIGHT(a) (STATE_PIXELSHADERCONSTANT + (a) + 1)
+#define STATE_LIGHT_TYPE (STATE_VIEWPORT + 1)
+#define STATE_IS_LIGHT_TYPE(a) ((a) == STATE_LIGHT_TYPE)
+#define STATE_ACTIVELIGHT(a) (STATE_LIGHT_TYPE + 1 + (a))
 #define STATE_IS_ACTIVELIGHT(a) ((a) >= STATE_ACTIVELIGHT(0) && (a) < STATE_ACTIVELIGHT(MAX_ACTIVE_LIGHTS))
 
 #define STATE_SCISSORRECT (STATE_ACTIVELIGHT(MAX_ACTIVE_LIGHTS - 1) + 1)
@@ -1009,7 +1007,10 @@ extern glMultiTexCoordFunc multi_texcoord_funcs[WINED3D_FFP_EMIT_COUNT] DECLSPEC
 #define STATE_FRAMEBUFFER (STATE_BASEVERTEXINDEX + 1)
 #define STATE_IS_FRAMEBUFFER(a) ((a) == STATE_FRAMEBUFFER)
 
-#define STATE_HIGHEST (STATE_FRAMEBUFFER)
+#define STATE_POINT_SIZE_ENABLE (STATE_FRAMEBUFFER + 1)
+#define STATE_IS_POINT_SIZE_ENABLE(a) ((a) == STATE_POINT_SIZE_ENABLE)
+
+#define STATE_HIGHEST (STATE_POINT_SIZE_ENABLE)
 
 enum fogsource {
     FOGSOURCE_FFP,
@@ -1017,8 +1018,6 @@ enum fogsource {
     FOGSOURCE_COORD,
 };
 
-#define WINED3D_MAX_FBO_ENTRIES 64
-
 struct wined3d_occlusion_query
 {
     struct list entry;
@@ -1057,6 +1056,7 @@ BOOL wined3d_event_query_supported(const struct wined3d_gl_info *gl_info) DECLSP
 struct wined3d_context
 {
     const struct wined3d_gl_info *gl_info;
+    const struct wined3d_d3d_info *d3d_info;
     const struct StateEntry *state_table;
     /* State dirtification
      * dirtyArray is an array that contains markers for dirty states. numDirtyEntries states are dirty, their numbers are in indices
@@ -1087,11 +1087,11 @@ struct wined3d_context
     DWORD current : 1;
     DWORD destroyed : 1;
     DWORD valid : 1;
-    DWORD select_shader : 1;
-    DWORD load_constants : 1;
-    DWORD padding : 15;
-    BYTE texShaderBumpMap;              /* MAX_TEXTURES, 8 */
-    BYTE lastWasPow2Texture;            /* MAX_TEXTURES, 8 */
+    DWORD padding : 1;
+    DWORD texShaderBumpMap : 8;         /* MAX_TEXTURES, 8 */
+    DWORD lastWasPow2Texture : 8;       /* MAX_TEXTURES, 8 */
+    DWORD shader_update_mask;
+    DWORD constant_update_mask;
     DWORD                   numbered_array_mask;
     GLenum                  tracking_parm;     /* Which source is tracking current colour         */
     GLenum                  untracked_materials[2];
@@ -1111,6 +1111,8 @@ struct wined3d_context
     int pixel_format;
     GLint                   aux_buffers;
 
+    void *shader_backend_data;
+
     /* FBOs */
     UINT                    fbo_entry_count;
     struct list             fbo_list;
@@ -1184,8 +1186,28 @@ struct fragment_pipeline
     const struct StateEntryTemplate *states;
 };
 
+struct wined3d_vertex_caps
+{
+    BOOL xyzrhw;
+    DWORD max_active_lights;
+    DWORD max_vertex_blend_matrices;
+    DWORD max_vertex_blend_matrix_index;
+    DWORD vertex_processing_caps;
+    DWORD fvf_caps;
+    DWORD max_user_clip_planes;
+    DWORD raster_caps;
+};
+
+struct wined3d_vertex_pipe_ops
+{
+    void (*vp_enable)(const struct wined3d_gl_info *gl_info, BOOL enable);
+    void (*vp_get_caps)(const struct wined3d_gl_info *gl_info, struct wined3d_vertex_caps *caps);
+    void *(*vp_alloc)(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv);
+    void (*vp_free)(struct wined3d_device *device);
+    const struct StateEntryTemplate *vp_states;
+};
+
 extern const struct StateEntryTemplate misc_state_template[] DECLSPEC_HIDDEN;
-extern const struct StateEntryTemplate ffp_vertexstate_template[] DECLSPEC_HIDDEN;
 extern const struct fragment_pipeline none_fragment_pipe DECLSPEC_HIDDEN;
 extern const struct fragment_pipeline ffp_fragment_pipeline DECLSPEC_HIDDEN;
 extern const struct fragment_pipeline atifs_fragment_pipeline DECLSPEC_HIDDEN;
@@ -1194,10 +1216,15 @@ extern const struct fragment_pipeline nvts_fragment_pipeline DECLSPEC_HIDDEN;
 extern const struct fragment_pipeline nvrc_fragment_pipeline DECLSPEC_HIDDEN;
 extern const struct fragment_pipeline glsl_fragment_pipe DECLSPEC_HIDDEN;
 
+extern const struct wined3d_vertex_pipe_ops none_vertex_pipe DECLSPEC_HIDDEN;
+extern const struct wined3d_vertex_pipe_ops ffp_vertex_pipe DECLSPEC_HIDDEN;
+extern const struct wined3d_vertex_pipe_ops glsl_vertex_pipe DECLSPEC_HIDDEN;
+
 /* "Base" state table */
 HRESULT compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_multistate_funcs,
-        const struct wined3d_gl_info *gl_info, const struct StateEntryTemplate *vertex,
-        const struct fragment_pipeline *fragment, const struct StateEntryTemplate *misc) DECLSPEC_HIDDEN;
+        const struct wined3d_gl_info *gl_info, const struct wined3d_d3d_info *d3d_info,
+        const struct wined3d_vertex_pipe_ops *vertex, const struct fragment_pipeline *fragment,
+        const struct StateEntryTemplate *misc) DECLSPEC_HIDDEN;
 
 enum wined3d_blit_op
 {
@@ -1256,6 +1283,7 @@ void context_bind_texture(struct wined3d_context *context, GLenum target, GLuint
 void context_check_fbo_status(const struct wined3d_context *context, GLenum target) DECLSPEC_HIDDEN;
 struct wined3d_context *context_create(struct wined3d_swapchain *swapchain, struct wined3d_surface *target,
         const struct wined3d_format *ds_format) DECLSPEC_HIDDEN;
+BOOL context_debug_output_enabled(const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN;
 void context_destroy(struct wined3d_device *device, struct wined3d_context *context) DECLSPEC_HIDDEN;
 void context_free_event_query(struct wined3d_event_query *query) DECLSPEC_HIDDEN;
 void context_free_occlusion_query(struct wined3d_occlusion_query *query) DECLSPEC_HIDDEN;
@@ -1333,6 +1361,7 @@ enum wined3d_pci_device
     CARD_AMD_RADEON_HD2600          = 0x9581,
     CARD_AMD_RADEON_HD2900          = 0x9400,
     CARD_AMD_RADEON_HD3200          = 0x9620,
+    CARD_AMD_RADEON_HD4200M         = 0x9712,
     CARD_AMD_RADEON_HD4350          = 0x954f,
     CARD_AMD_RADEON_HD4600          = 0x9495,
     CARD_AMD_RADEON_HD4700          = 0x944e,
@@ -1395,11 +1424,13 @@ enum wined3d_pci_device
     CARD_NVIDIA_GEFORCE_GTX260      = 0x05e2,
     CARD_NVIDIA_GEFORCE_GTX275      = 0x05e6,
     CARD_NVIDIA_GEFORCE_GTX280      = 0x05e1,
+    CARD_NVIDIA_GEFORCE_315M        = 0x0a7a,
     CARD_NVIDIA_GEFORCE_320M        = 0x08a3,
     CARD_NVIDIA_GEFORCE_GT320M      = 0x0a2d,
     CARD_NVIDIA_GEFORCE_GT325M      = 0x0a35,
     CARD_NVIDIA_GEFORCE_GT330       = 0x0ca0,
     CARD_NVIDIA_GEFORCE_GTS350M     = 0x0cb0,
+    CARD_NVIDIA_GEFORCE_410M        = 0x1055,
     CARD_NVIDIA_GEFORCE_GT420       = 0x0de2,
     CARD_NVIDIA_GEFORCE_GT430       = 0x0de1,
     CARD_NVIDIA_GEFORCE_GT440       = 0x0de0,
@@ -1418,6 +1449,7 @@ enum wined3d_pci_device
     CARD_NVIDIA_GEFORCE_GTX570      = 0x1081,
     CARD_NVIDIA_GEFORCE_GTX580      = 0x1080,
     CARD_NVIDIA_GEFORCE_GT610       = 0x104a,
+    CARD_NVIDIA_GEFORCE_GT630       = 0x0f00,
     CARD_NVIDIA_GEFORCE_GT630M      = 0x0de9,
     CARD_NVIDIA_GEFORCE_GT640M      = 0x0fd2,
     CARD_NVIDIA_GEFORCE_GT650M      = 0x0fd1,
@@ -1426,7 +1458,10 @@ enum wined3d_pci_device
     CARD_NVIDIA_GEFORCE_GTX660      = 0x11c0,
     CARD_NVIDIA_GEFORCE_GTX660TI    = 0x1183,
     CARD_NVIDIA_GEFORCE_GTX670      = 0x1189,
+    CARD_NVIDIA_GEFORCE_GTX670MX    = 0x11a1,
     CARD_NVIDIA_GEFORCE_GTX680      = 0x1180,
+    CARD_NVIDIA_GEFORCE_GTX770M     = 0x11e0,
+    CARD_NVIDIA_GEFORCE_GTX770      = 0x1184,
 
     CARD_INTEL_830M                 = 0x3577,
     CARD_INTEL_855GM                = 0x3582,
@@ -1500,7 +1535,6 @@ struct wined3d_gl_limits
     UINT buffers;
     UINT lights;
     UINT textures;
-    UINT texture_stages;
     UINT texture_coords;
     UINT fragment_samplers;
     UINT vertex_samplers;
@@ -1541,6 +1575,7 @@ struct wined3d_gl_info
     BOOL supported[WINED3D_GL_EXT_COUNT];
     GLint wrap_lookup[WINED3D_TADDRESS_MIRROR_ONCE - WINED3D_TADDRESS_WRAP + 1];
 
+    HGLRC (WINAPI *p_wglCreateContextAttribsARB)(HDC dc, HGLRC share, const GLint *attribs);
     struct opengl_funcs gl_ops;
     struct wined3d_fbo_ops fbo_ops;
 
@@ -1558,6 +1593,37 @@ struct wined3d_driver_info
     DWORD version_low;
 };
 
+struct wined3d_d3d_limits
+{
+    UINT vs_version, gs_version, ps_version;
+    DWORD vs_uniform_count;
+    DWORD ps_uniform_count;
+    UINT ffp_textures;
+    UINT ffp_blend_stages;
+};
+
+typedef void (WINE_GLAPI *wined3d_ffp_attrib_func)(const void *data);
+typedef void (WINE_GLAPI *wined3d_ffp_texcoord_func)(GLenum unit, const void *data);
+extern wined3d_ffp_attrib_func specular_func_3ubv DECLSPEC_HIDDEN;
+
+struct wined3d_ffp_attrib_ops
+{
+    wined3d_ffp_attrib_func position[WINED3D_FFP_EMIT_COUNT];
+    wined3d_ffp_attrib_func diffuse[WINED3D_FFP_EMIT_COUNT];
+    wined3d_ffp_attrib_func specular[WINED3D_FFP_EMIT_COUNT];
+    wined3d_ffp_attrib_func normal[WINED3D_FFP_EMIT_COUNT];
+    wined3d_ffp_texcoord_func texcoord[WINED3D_FFP_EMIT_COUNT];
+};
+
+struct wined3d_d3d_info
+{
+    struct wined3d_d3d_limits limits;
+    struct wined3d_ffp_attrib_ops ffp_attrib_ops;
+    BOOL xyzrhw;
+    BOOL vs_clipping;
+    DWORD valid_rt_mask;
+};
+
 /* The adapter structure */
 struct wined3d_adapter
 {
@@ -1566,6 +1632,7 @@ struct wined3d_adapter
     enum wined3d_format_id screen_format;
 
     struct wined3d_gl_info  gl_info;
+    struct wined3d_d3d_info d3d_info;
     struct wined3d_driver_info driver_info;
     WCHAR                   DeviceName[CCHDEVICENAME]; /* DeviceName for use with e.g. ChangeDisplaySettings */
     unsigned int cfg_count;
@@ -1574,6 +1641,7 @@ struct wined3d_adapter
     unsigned int            UsedTextureRam;
     LUID luid;
 
+    const struct wined3d_vertex_pipe_ops *vertex_pipe;
     const struct fragment_pipeline *fragment_pipe;
     const struct wined3d_shader_backend_ops *shader_backend;
     const struct blit_shader *blitter;
@@ -1621,9 +1689,10 @@ struct texture_stage_op
     unsigned                padding : 10;
 };
 
-struct ffp_frag_settings {
-    struct texture_stage_op     op[MAX_TEXTURES];
-    enum fogmode fog;
+struct ffp_frag_settings
+{
+    struct texture_stage_op op[MAX_TEXTURES];
+    enum wined3d_ffp_ps_fog_mode fog;
     /* Use shorts instead of chars to get dword alignment */
     unsigned short sRGB_write;
     unsigned short emul_clipplanes;
@@ -1636,15 +1705,62 @@ struct ffp_frag_desc
 };
 
 extern const struct wine_rb_functions wined3d_ffp_frag_program_rb_functions DECLSPEC_HIDDEN;
+extern const struct wine_rb_functions wined3d_ffp_vertex_program_rb_functions DECLSPEC_HIDDEN;
 extern const struct wined3d_parent_ops wined3d_null_parent_ops DECLSPEC_HIDDEN;
 
-void gen_ffp_frag_op(const struct wined3d_device *device, const struct wined3d_state *state,
+void gen_ffp_frag_op(const struct wined3d_context *context, const struct wined3d_state *state,
         struct ffp_frag_settings *settings, BOOL ignore_textype) DECLSPEC_HIDDEN;
 const struct ffp_frag_desc *find_ffp_frag_shader(const struct wine_rb_tree *fragment_shaders,
         const struct ffp_frag_settings *settings) DECLSPEC_HIDDEN;
 void add_ffp_frag_shader(struct wine_rb_tree *shaders, struct ffp_frag_desc *desc) DECLSPEC_HIDDEN;
 void wined3d_get_draw_rect(const struct wined3d_state *state, RECT *rect) DECLSPEC_HIDDEN;
 
+enum wined3d_ffp_vs_fog_mode
+{
+    WINED3D_FFP_VS_FOG_OFF      = 0,
+    WINED3D_FFP_VS_FOG_FOGCOORD = 1,
+    WINED3D_FFP_VS_FOG_DEPTH    = 2,
+    WINED3D_FFP_VS_FOG_RANGE    = 3,
+};
+
+#define WINED3D_FFP_TCI_SHIFT               16
+#define WINED3D_FFP_TCI_MASK                0xff
+
+#define WINED3D_FFP_LIGHT_TYPE_SHIFT(idx)   (3 * (idx))
+#define WINED3D_FFP_LIGHT_TYPE_MASK         0x7
+
+struct wined3d_ffp_vs_settings
+{
+    DWORD light_type      : 24; /* MAX_ACTIVE_LIGHTS, 8 * 3 */
+    DWORD diffuse_source  : 2;
+    DWORD emission_source : 2;
+    DWORD ambient_source  : 2;
+    DWORD specular_source : 2;
+
+    DWORD transformed     : 1;
+    DWORD clipping        : 1;
+    DWORD normal          : 1;
+    DWORD normalize       : 1;
+    DWORD lighting        : 1;
+    DWORD localviewer     : 1;
+    DWORD point_size      : 1;
+    DWORD fog_mode        : 2;
+    DWORD texcoords       : 8;  /* MAX_TEXTURES */
+    DWORD ortho_fog       : 1;
+    DWORD padding         : 14;
+
+    BYTE texgen[MAX_TEXTURES];
+};
+
+struct wined3d_ffp_vs_desc
+{
+    struct wine_rb_entry entry;
+    struct wined3d_ffp_vs_settings settings;
+};
+
+void wined3d_ffp_get_vs_settings(const struct wined3d_state *state, const struct wined3d_stream_info *si,
+        struct wined3d_ffp_vs_settings *settings) DECLSPEC_HIDDEN;
+
 struct wined3d
 {
     LONG ref;
@@ -1658,6 +1774,72 @@ HRESULT wined3d_init(struct wined3d *wined3d, UINT version, DWORD flags) DECLSPE
 BOOL wined3d_register_window(HWND window, struct wined3d_device *device) DECLSPEC_HIDDEN;
 void wined3d_unregister_window(HWND window) DECLSPEC_HIDDEN;
 
+struct wined3d_stream_output
+{
+    struct wined3d_buffer *buffer;
+    UINT offset;
+};
+
+struct wined3d_stream_state
+{
+    struct wined3d_buffer *buffer;
+    UINT offset;
+    UINT stride;
+    UINT frequency;
+    UINT flags;
+};
+
+struct wined3d_state
+{
+    const struct wined3d_fb_state *fb;
+
+    struct wined3d_vertex_declaration *vertex_declaration;
+    struct wined3d_stream_output stream_output[MAX_STREAM_OUT];
+    struct wined3d_stream_state streams[MAX_STREAMS + 1 /* tesselated pseudo-stream */];
+    struct wined3d_buffer *index_buffer;
+    enum wined3d_format_id index_format;
+    INT base_vertex_index;
+    INT load_base_vertex_index; /* Non-indexed drawing needs 0 here, indexed needs base_vertex_index. */
+    GLenum gl_primitive_type;
+
+    struct wined3d_shader *vertex_shader;
+    struct wined3d_buffer *vs_cb[MAX_CONSTANT_BUFFERS];
+    struct wined3d_sampler *vs_sampler[MAX_SAMPLER_OBJECTS];
+    BOOL vs_consts_b[MAX_CONST_B];
+    INT vs_consts_i[MAX_CONST_I * 4];
+    float *vs_consts_f;
+
+    struct wined3d_shader *geometry_shader;
+    struct wined3d_buffer *gs_cb[MAX_CONSTANT_BUFFERS];
+    struct wined3d_sampler *gs_sampler[MAX_SAMPLER_OBJECTS];
+
+    struct wined3d_shader *pixel_shader;
+    struct wined3d_buffer *ps_cb[MAX_CONSTANT_BUFFERS];
+    struct wined3d_sampler *ps_sampler[MAX_SAMPLER_OBJECTS];
+    BOOL ps_consts_b[MAX_CONST_B];
+    INT ps_consts_i[MAX_CONST_I * 4];
+    float *ps_consts_f;
+
+    struct wined3d_texture *textures[MAX_COMBINED_SAMPLERS];
+    DWORD sampler_states[MAX_COMBINED_SAMPLERS][WINED3D_HIGHEST_SAMPLER_STATE + 1];
+    DWORD texture_states[MAX_TEXTURES][WINED3D_HIGHEST_TEXTURE_STATE + 1];
+    DWORD lowest_disabled_stage;
+
+    struct wined3d_matrix transforms[HIGHEST_TRANSFORMSTATE + 1];
+    struct wined3d_vec4 clip_planes[MAX_CLIPPLANES];
+    struct wined3d_material material;
+    struct wined3d_viewport viewport;
+    RECT scissor_rect;
+
+    /* Light hashmap. Collisions are handled using linked lists. */
+#define LIGHTMAP_SIZE 43
+#define LIGHTMAP_HASHFUNC(x) ((x) % LIGHTMAP_SIZE)
+    struct list light_map[LIGHTMAP_SIZE];
+    const struct wined3d_light_info *lights[MAX_ACTIVE_LIGHTS];
+
+    DWORD render_states[WINEHIGHEST_RENDER_STATE + 1];
+};
+
 /*****************************************************************************
  * IWineD3DDevice implementation structure
  */
@@ -1685,21 +1867,16 @@ struct wined3d_device
     const struct wined3d_shader_backend_ops *shader_backend;
     void *shader_priv;
     void *fragment_priv;
+    void *vertex_priv;
     void *blit_priv;
     struct StateEntry StateTable[STATE_HIGHEST + 1];
     /* Array of functions for states which are handled by more than one pipeline part */
     APPLYSTATEFUNC *multistate_funcs[STATE_HIGHEST + 1];
     const struct blit_shader *blitter;
 
-    unsigned int max_ffp_textures;
-    UINT vs_version, gs_version, ps_version;
-    DWORD d3d_vshader_constantF, d3d_pshader_constantF; /* Advertised d3d caps, not GL ones */
-    DWORD vs_clipping;
     UINT instance_count;
 
-    WORD view_ident : 1;                /* true iff view matrix is identity */
     WORD vertexBlendUsed : 1;           /* To avoid needless setting of the blend matrices */
-    WORD isRecordingState : 1;
     WORD isInDraw : 1;
     WORD bCursorVisible : 1;
     WORD d3d_initialized : 1;
@@ -1707,17 +1884,15 @@ struct wined3d_device
     WORD softwareVertexProcessing : 1;  /* process vertex shaders using software or hardware */
     WORD useDrawStridedSlow : 1;
     WORD filter_messages : 1;
-    WORD padding : 6;
+    WORD padding : 8;
 
     BYTE fixed_function_usage_map;      /* MAX_TEXTURES, 8 */
 
-#define DDRAW_PITCH_ALIGNMENT 8
-#define D3D8_PITCH_ALIGNMENT 4
     unsigned char           surface_alignment; /* Line Alignment of surfaces                      */
 
-    /* State block related */
-    struct wined3d_stateblock *stateBlock;
-    struct wined3d_stateblock *updateStateBlock;
+    struct wined3d_state state;
+    struct wined3d_state *update_state;
+    struct wined3d_stateblock *recording;
 
     /* Internal use fields  */
     struct wined3d_device_creation_parameters create_parms;
@@ -1730,7 +1905,6 @@ struct wined3d_device
     struct list             shaders;   /* a linked list to track shaders (pixel and vertex)      */
 
     /* Render Target Support */
-    DWORD valid_rt_mask;
     struct wined3d_fb_state fb;
     struct wined3d_surface *onscreen_depth_stencil;
     struct wined3d_surface *auto_depth_stencil;
@@ -1761,7 +1935,7 @@ struct wined3d_device
     DWORD                     rev_tex_unit_map[MAX_COMBINED_SAMPLERS];
 
     /* Stream source management */
-    struct wined3d_stream_info strided_streams;
+    struct wined3d_stream_info stream_info;
     struct wined3d_event_query *buffer_queries[MAX_ATTRIBS];
     unsigned int num_buffer_queries;
 
@@ -1805,15 +1979,15 @@ static inline void invalidate_active_texture(const struct wined3d_device *device
 
 #define WINED3D_RESOURCE_ACCESS_GPU     0x1
 #define WINED3D_RESOURCE_ACCESS_CPU     0x2
-/* SCRATCH is mostly the same as CPU, but can't be used by the GPU at all,
- * not even for resource uploads. */
-#define WINED3D_RESOURCE_ACCESS_SCRATCH 0x4
 
 struct wined3d_resource_ops
 {
     void (*resource_unload)(struct wined3d_resource *resource);
 };
 
+void *wined3d_resource_allocate_sysmem(SIZE_T size) DECLSPEC_HIDDEN;
+void wined3d_resource_free_sysmem(void *mem) DECLSPEC_HIDDEN;
+
 struct wined3d_resource
 {
     LONG ref;
@@ -1823,19 +1997,19 @@ struct wined3d_resource
     enum wined3d_resource_type type;
     const struct wined3d_format *format;
     enum wined3d_multisample_type multisample_type;
-    UINT                    multisample_quality;
-    DWORD                   usage;
+    UINT multisample_quality;
+    DWORD usage;
     enum wined3d_pool pool;
     DWORD access_flags;
     UINT width;
     UINT height;
     UINT depth;
-    UINT                    size;
-    DWORD                   priority;
-    BYTE                   *allocatedMemory; /* Pointer to the real data location */
-    BYTE                   *heapMemory; /* Pointer to the HeapAlloced block of memory */
-    struct list             privateData;
-    struct list             resource_list_entry;
+    UINT size;
+    DWORD priority;
+    BYTE *allocatedMemory; /* Pointer to the real data location */
+    void *heap_memory;
+    struct list privateData;
+    struct list resource_list_entry;
 
     void *parent;
     const struct wined3d_parent_ops *parent_ops;
@@ -1852,6 +2026,9 @@ HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device *
         const struct wined3d_resource_ops *resource_ops) DECLSPEC_HIDDEN;
 DWORD resource_set_priority(struct wined3d_resource *resource, DWORD priority) DECLSPEC_HIDDEN;
 void resource_unload(struct wined3d_resource *resource) DECLSPEC_HIDDEN;
+DWORD wined3d_resource_sanitize_map_flags(const struct wined3d_resource *resource,
+        DWORD flags) DECLSPEC_HIDDEN;
+GLbitfield wined3d_resource_gl_map_flags(DWORD d3d_flags) DECLSPEC_HIDDEN;
 
 /* Tests show that the start address of resources is 32 byte aligned */
 #define RESOURCE_ALIGNMENT 16
@@ -1935,15 +2112,28 @@ void wined3d_texture_apply_state_changes(struct wined3d_texture *texture,
         const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN;
 void wined3d_texture_set_dirty(struct wined3d_texture *texture, BOOL dirty) DECLSPEC_HIDDEN;
 
+#define WINED3D_VFLAG_LOCKED            0x00000001
+#define WINED3D_VFLAG_ALLOCATED         0x00000002
+#define WINED3D_VFLAG_SRGB_ALLOCATED    0x00000004
+#define WINED3D_VFLAG_PBO               0x00000008
+
+#define WINED3D_LOCATION_DISCARDED      0x00000001
+#define WINED3D_LOCATION_SYSMEM         0x00000002
+#define WINED3D_LOCATION_BUFFER         0x00000004
+#define WINED3D_LOCATION_TEXTURE_RGB    0x00000008
+#define WINED3D_LOCATION_TEXTURE_SRGB   0x00000010
+
+const char *wined3d_debug_location(DWORD location) DECLSPEC_HIDDEN;
+
 struct wined3d_volume
 {
     struct wined3d_resource resource;
     struct wined3d_texture *container;
-    BOOL                    lockable;
-    BOOL                    locked;
-    struct wined3d_box lockedBox;
-    struct wined3d_box dirtyBox;
-    BOOL                    dirty;
+
+    DWORD flags, locations;
+    GLint texture_level;
+    DWORD download_count;
+    GLuint pbo;
 };
 
 static inline struct wined3d_volume *volume_from_resource(struct wined3d_resource *resource)
@@ -1951,9 +2141,11 @@ static inline struct wined3d_volume *volume_from_resource(struct wined3d_resourc
     return CONTAINING_RECORD(resource, struct wined3d_volume, resource);
 }
 
-void volume_add_dirty_box(struct wined3d_volume *volume, const struct wined3d_box *dirty_box) DECLSPEC_HIDDEN;
-void volume_load(const struct wined3d_volume *volume, struct wined3d_context *context, UINT level, BOOL srgb_mode) DECLSPEC_HIDDEN;
+void wined3d_volume_load(struct wined3d_volume *volume, struct wined3d_context *context, BOOL srgb_mode) DECLSPEC_HIDDEN;
 void volume_set_container(struct wined3d_volume *volume, struct wined3d_texture *container) DECLSPEC_HIDDEN;
+void wined3d_volume_invalidate_location(struct wined3d_volume *volume, DWORD location) DECLSPEC_HIDDEN;
+void wined3d_volume_upload_data(struct wined3d_volume *volume, const struct wined3d_context *context,
+        const struct wined3d_bo_address *data) DECLSPEC_HIDDEN;
 
 struct wined3d_surface_dib
 {
@@ -1981,24 +2173,6 @@ struct fbo_entry
     GLuint id;
 };
 
-enum wined3d_container_type
-{
-    WINED3D_CONTAINER_NONE = 0,
-    WINED3D_CONTAINER_SWAPCHAIN,
-    WINED3D_CONTAINER_TEXTURE,
-};
-
-struct wined3d_subresource_container
-{
-    enum wined3d_container_type type;
-    union
-    {
-        struct wined3d_swapchain *swapchain;
-        struct wined3d_texture *texture;
-        void *base;
-    } u;
-};
-
 struct wined3d_surface_ops
 {
     HRESULT (*surface_private_setup)(struct wined3d_surface *surface);
@@ -2011,14 +2185,16 @@ struct wined3d_surface
 {
     struct wined3d_resource resource;
     const struct wined3d_surface_ops *surface_ops;
-    struct wined3d_subresource_container container;
+    struct wined3d_texture *container;
+    struct wined3d_swapchain *swapchain;
     struct wined3d_palette *palette; /* D3D7 style palette handling */
     DWORD draw_binding;
 
     DWORD flags;
 
-    UINT                      pow2Width;
-    UINT                      pow2Height;
+    UINT pitch;
+    UINT pow2Width;
+    UINT pow2Height;
 
     /* A method to retrieve the drawable size. Not in the Vtable to make it changeable */
     void (*get_drawable_size)(const struct wined3d_context *context, UINT *width, UINT *height);
@@ -2093,8 +2269,8 @@ void surface_prepare_texture(struct wined3d_surface *surface,
         struct wined3d_context *context, BOOL srgb) DECLSPEC_HIDDEN;
 void surface_set_compatible_renderbuffer(struct wined3d_surface *surface,
         const struct wined3d_surface *rt) DECLSPEC_HIDDEN;
-void surface_set_container(struct wined3d_surface *surface,
-        enum wined3d_container_type type, void *container) DECLSPEC_HIDDEN;
+void surface_set_container(struct wined3d_surface *surface, struct wined3d_texture *container) DECLSPEC_HIDDEN;
+void surface_set_swapchain(struct wined3d_surface *surface, struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
 void surface_set_texture_name(struct wined3d_surface *surface, GLuint name, BOOL srgb_name) DECLSPEC_HIDDEN;
 void surface_set_texture_target(struct wined3d_surface *surface, GLenum target, GLint level) DECLSPEC_HIDDEN;
 void surface_translate_drawable_coords(const struct wined3d_surface *surface, HWND window, RECT *rect) DECLSPEC_HIDDEN;
@@ -2200,10 +2376,8 @@ struct wined3d_vertex_declaration
     struct wined3d_vertex_declaration_element *elements;
     UINT element_count;
 
-    DWORD                   streams[MAX_STREAMS];
-    UINT                    num_streams;
-    BOOL                    position_transformed;
-    BOOL                    half_float_conv_needed;
+    BOOL position_transformed;
+    BOOL half_float_conv_needed;
 };
 
 struct wined3d_saved_states
@@ -2238,72 +2412,6 @@ struct StageState {
     DWORD state;
 };
 
-struct wined3d_stream_output
-{
-    struct wined3d_buffer *buffer;
-    UINT offset;
-};
-
-struct wined3d_stream_state
-{
-    struct wined3d_buffer *buffer;
-    UINT offset;
-    UINT stride;
-    UINT frequency;
-    UINT flags;
-};
-
-struct wined3d_state
-{
-    const struct wined3d_fb_state *fb;
-
-    struct wined3d_vertex_declaration *vertex_declaration;
-    struct wined3d_stream_output stream_output[MAX_STREAM_OUT];
-    struct wined3d_stream_state streams[MAX_STREAMS + 1 /* tesselated pseudo-stream */];
-    struct wined3d_buffer *index_buffer;
-    enum wined3d_format_id index_format;
-    INT base_vertex_index;
-    INT load_base_vertex_index; /* Non-indexed drawing needs 0 here, indexed needs base_vertex_index. */
-    GLenum gl_primitive_type;
-
-    struct wined3d_shader *vertex_shader;
-    struct wined3d_buffer *vs_cb[MAX_CONSTANT_BUFFERS];
-    struct wined3d_sampler *vs_sampler[MAX_SAMPLER_OBJECTS];
-    BOOL vs_consts_b[MAX_CONST_B];
-    INT vs_consts_i[MAX_CONST_I * 4];
-    float *vs_consts_f;
-
-    struct wined3d_shader *geometry_shader;
-    struct wined3d_buffer *gs_cb[MAX_CONSTANT_BUFFERS];
-    struct wined3d_sampler *gs_sampler[MAX_SAMPLER_OBJECTS];
-
-    struct wined3d_shader *pixel_shader;
-    struct wined3d_buffer *ps_cb[MAX_CONSTANT_BUFFERS];
-    struct wined3d_sampler *ps_sampler[MAX_SAMPLER_OBJECTS];
-    BOOL ps_consts_b[MAX_CONST_B];
-    INT ps_consts_i[MAX_CONST_I * 4];
-    float *ps_consts_f;
-
-    struct wined3d_texture *textures[MAX_COMBINED_SAMPLERS];
-    DWORD sampler_states[MAX_COMBINED_SAMPLERS][WINED3D_HIGHEST_SAMPLER_STATE + 1];
-    DWORD texture_states[MAX_TEXTURES][WINED3D_HIGHEST_TEXTURE_STATE + 1];
-    DWORD lowest_disabled_stage;
-
-    struct wined3d_matrix transforms[HIGHEST_TRANSFORMSTATE + 1];
-    struct wined3d_vec4 clip_planes[MAX_CLIPPLANES];
-    struct wined3d_material material;
-    struct wined3d_viewport viewport;
-    RECT scissor_rect;
-
-    /* Light hashmap . Collisions are handled using standard wine double linked lists */
-#define LIGHTMAP_SIZE 43 /* Use of a prime number recommended. Set to 1 for a linked list! */
-#define LIGHTMAP_HASHFUNC(x) ((x) % LIGHTMAP_SIZE) /* Primitive and simple function */
-    struct list light_map[LIGHTMAP_SIZE]; /* Hash map containing the lights */
-    const struct wined3d_light_info *lights[MAX_ACTIVE_LIGHTS]; /* Map of opengl lights to d3d lights */
-
-    DWORD render_states[WINEHIGHEST_RENDER_STATE + 1];
-};
-
 struct wined3d_stateblock
 {
     LONG                      ref;     /* Note: Ref counting not required */
@@ -2337,8 +2445,11 @@ struct wined3d_stateblock
 };
 
 void stateblock_init_contained_states(struct wined3d_stateblock *stateblock) DECLSPEC_HIDDEN;
-void stateblock_init_default_state(struct wined3d_stateblock *stateblock) DECLSPEC_HIDDEN;
-void stateblock_unbind_resources(struct wined3d_stateblock *stateblock) DECLSPEC_HIDDEN;
+
+void state_cleanup(struct wined3d_state *state) DECLSPEC_HIDDEN;
+HRESULT state_init(struct wined3d_state *state, const struct wined3d_d3d_info *d3d_info) DECLSPEC_HIDDEN;
+void state_init_default(struct wined3d_state *state, struct wined3d_device *device) DECLSPEC_HIDDEN;
+void state_unbind_resources(struct wined3d_state *state) DECLSPEC_HIDDEN;
 
 /* Direct3D terminology with little modifications. We do not have an issued state
  * because only the driver knows about it, but we have a created state because d3d
@@ -2382,15 +2493,6 @@ struct wined3d_map_range
     UINT size;
 };
 
-#define WINED3D_BUFFER_OPTIMIZED    0x01    /* Optimize has been called for the buffer */
-#define WINED3D_BUFFER_HASDESC      0x02    /* A vertex description has been found */
-#define WINED3D_BUFFER_CREATEBO     0x04    /* Attempt to create a buffer object next PreLoad */
-#define WINED3D_BUFFER_DOUBLEBUFFER 0x08    /* Use a vbo and local allocated memory */
-#define WINED3D_BUFFER_FLUSH        0x10    /* Manual unmap flushing */
-#define WINED3D_BUFFER_DISCARD      0x20    /* A DISCARD lock has occurred since the last PreLoad */
-#define WINED3D_BUFFER_NOSYNC       0x40    /* All locks since the last PreLoad had NOOVERWRITE set */
-#define WINED3D_BUFFER_APPLESYNC    0x80    /* Using sync as in GL_APPLE_flush_buffer_range */
-
 struct wined3d_buffer
 {
     struct wined3d_resource resource;
@@ -2449,8 +2551,7 @@ struct wined3d_swapchain
     struct wined3d_surface **back_buffers;
     struct wined3d_surface *front_buffer;
     struct wined3d_swapchain_desc desc;
-    DWORD orig_width, orig_height;
-    enum wined3d_format_id orig_fmt;
+    struct wined3d_display_mode original_mode;
     struct wined3d_gamma_ramp orig_gamma;
     BOOL render_to_fbo;
     const struct wined3d_format *ds_format;
@@ -2475,8 +2576,6 @@ HDC swapchain_get_backup_dc(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN
 void swapchain_update_draw_bindings(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
 void swapchain_update_render_to_fbo(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
 
-#define DEFAULT_REFRESH_RATE 0
-
 /*****************************************************************************
  * Utility function prototypes
  */
@@ -2530,6 +2629,43 @@ void state_fog_fragpart(struct wined3d_context *context,
 void state_srgbwrite(struct wined3d_context *context,
         const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
 
+void sampler_texmatrix(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void state_specularenable(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void transform_world(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void transform_view(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void transform_projection(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void transform_texture(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void state_ambient(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void viewport_vertexpart(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void state_clipping(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void light(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void vertexdeclaration(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void clipplane(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void state_psizemin_w(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void state_psizemin_ext(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void state_psizemin_arb(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void state_pointsprite_w(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void state_pointsprite(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+void state_pscale(struct wined3d_context *context,
+        const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
+
 BOOL getColorBits(const struct wined3d_format *format,
         BYTE *redSize, BYTE *greenSize, BYTE *blueSize, BYTE *alphaSize, BYTE *totalSize) DECLSPEC_HIDDEN;
 BOOL getDepthStencilBits(const struct wined3d_format *format,
@@ -2619,6 +2755,7 @@ struct wined3d_shader
     struct list constantsF;
     struct list constantsI;
     struct wined3d_shader_reg_maps reg_maps;
+    BOOL lconst_inf_or_nan;
 
     struct wined3d_shader_signature_element input_signature[max(MAX_ATTRIBS, MAX_REG_INPUT)];
     struct wined3d_shader_signature_element output_signature[MAX_REG_OUTPUT];
@@ -2635,8 +2772,7 @@ struct wined3d_shader
     } u;
 };
 
-void pixelshader_update_samplers(struct wined3d_shader_reg_maps *reg_maps,
-        struct wined3d_texture * const *textures) DECLSPEC_HIDDEN;
+void pixelshader_update_samplers(struct wined3d_shader *shader, WORD tex_types) DECLSPEC_HIDDEN;
 void find_ps_compile_args(const struct wined3d_state *state,
         const struct wined3d_shader *shader, struct ps_compile_args *args) DECLSPEC_HIDDEN;
 
@@ -2741,13 +2877,6 @@ struct ps_np2fixup_info {
     WORD              num_consts;
 };
 
-/* sRGB correction constants */
-static const float srgb_cmp = 0.0031308f;
-static const float srgb_mul_low = 12.92f;
-static const float srgb_pow = 0.41666f;
-static const float srgb_mul_high = 1.055f;
-static const float srgb_sub_high = 0.055f;
-
 struct wined3d_palette
 {
     LONG ref;
@@ -2776,7 +2905,6 @@ extern enum wined3d_format_id pixelformat_for_depth(DWORD depth) DECLSPEC_HIDDEN
 #define WINED3DFMT_FLAG_DEPTH                       0x00000004
 #define WINED3DFMT_FLAG_STENCIL                     0x00000008
 #define WINED3DFMT_FLAG_RENDERTARGET                0x00000010
-#define WINED3DFMT_FLAG_FOURCC                      0x00000020
 #define WINED3DFMT_FLAG_FBO_ATTACHABLE              0x00000040
 #define WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB         0x00000080
 #define WINED3DFMT_FLAG_GETDC                       0x00000100
@@ -2840,7 +2968,7 @@ struct wined3d_format
 const struct wined3d_format *wined3d_get_format(const struct wined3d_gl_info *gl_info,
         enum wined3d_format_id format_id) DECLSPEC_HIDDEN;
 UINT wined3d_format_calculate_size(const struct wined3d_format *format,
-        UINT alignment, UINT width, UINT height) DECLSPEC_HIDDEN;
+        UINT alignment, UINT width, UINT height, UINT depth) DECLSPEC_HIDDEN;
 DWORD wined3d_format_convert_from_float(const struct wined3d_surface *surface,
         const struct wined3d_color *color) DECLSPEC_HIDDEN;
 
index a1ac0a7..bf4b392 100644 (file)
@@ -3,8 +3,8 @@
  * Copyright 2002-2003 Jason Edmeades
  * Copyright 2002-2003 Raphael Junqueira
  * Copyright 2005 Oliver Stieber
- * Copyright 2006 Stefan DÃ\83¶singer
- * Copyright 2006 Stefan DÃ\83¶singer for CodeWeavers
+ * Copyright 2006 Stefan Dösinger
+ * Copyright 2006 Stefan Dösinger for CodeWeavers
  * Copyright 2007 Henri Verbeet
  * Copyright 2008 Henri Verbeet for CodeWeavers
  *
@@ -245,6 +245,7 @@ enum wined3d_format_id
     WINED3DFMT_NVHU                         = WINEMAKEFOURCC('N','V','H','U'),
     WINED3DFMT_NVHS                         = WINEMAKEFOURCC('N','V','H','S'),
     WINED3DFMT_INTZ                         = WINEMAKEFOURCC('I','N','T','Z'),
+    WINED3DFMT_RESZ                         = WINEMAKEFOURCC('R','E','S','Z'),
     WINED3DFMT_NULL                         = WINEMAKEFOURCC('N','U','L','L'),
     WINED3DFMT_R16                          = WINEMAKEFOURCC(' ','R','1','6'),
     WINED3DFMT_AL16                         = WINEMAKEFOURCC('A','L','1','6'),
@@ -712,7 +713,6 @@ enum wined3d_query_type
 
 enum wined3d_stateblock_type
 {
-    WINED3D_SBT_INIT                        = 0,
     WINED3D_SBT_ALL                         = 1,
     WINED3D_SBT_PIXEL_STATE                 = 2,
     WINED3D_SBT_VERTEX_STATE                = 3,
@@ -1215,6 +1215,9 @@ enum wined3d_display_rotation
 
 #define WINED3D_LEGACY_DEPTH_BIAS                               0x00000001
 #define WINED3D_NO3D                                            0x00000002
+#define WINED3D_VIDMEM_ACCOUNTING                               0x00000004
+
+#define WINED3D_RESZ_CODE                                       0x7fa05000
 
 /* dwDDFX */
 /* arithmetic stretching along y axis */
@@ -1709,23 +1712,6 @@ struct wined3d_box
     UINT back;
 };
 
-struct wined3d_strided_element
-{
-    enum wined3d_format_id format;  /* Format of the data */
-    const BYTE *data;               /* Pointer to start of data */
-    UINT stride;                    /* Stride between occurrences of this data */
-};
-
-struct wined3d_strided_data
-{
-    struct wined3d_strided_element position;
-    struct wined3d_strided_element normal;
-    struct wined3d_strided_element diffuse;
-    struct wined3d_strided_element specular;
-    struct wined3d_strided_element tex_coords[WINED3DDP_MAXTEXCOORD];
-    BOOL position_transformed;
-};
-
 struct wined3d_vertex_shader_caps
 {
     DWORD caps;
@@ -1762,7 +1748,6 @@ struct wined3d_ddraw_caps
     DWORD ssb_color_key_caps;
     DWORD ssb_fx_caps;
     DWORD dds_caps;
-    DWORD stride_align;
 };
 
 typedef struct _WINED3DCAPS
@@ -1995,15 +1980,13 @@ struct wined3d_device_parent_ops
     void (__cdecl *wined3d_device_created)(struct wined3d_device_parent *device_parent, struct wined3d_device *device);
     void (__cdecl *mode_changed)(struct wined3d_device_parent *device_parent);
     HRESULT (__cdecl *create_swapchain_surface)(struct wined3d_device_parent *device_parent, void *container_parent,
-            UINT width, UINT height, enum wined3d_format_id format_id, DWORD usage,
-            enum wined3d_multisample_type multisample_type, DWORD multisample_quality,
-            struct wined3d_surface **surface);
+            const struct wined3d_resource_desc *desc, struct wined3d_surface **surface);
     HRESULT (__cdecl *create_texture_surface)(struct wined3d_device_parent *device_parent, void *container_parent,
-            UINT width, UINT height, enum wined3d_format_id format_id, DWORD usage, enum wined3d_pool pool,
-            UINT sub_resource_idx, struct wined3d_surface **surface);
+            const struct wined3d_resource_desc *desc, UINT sub_resource_idx, DWORD flags,
+            struct wined3d_surface **surface);
     HRESULT (__cdecl *create_volume)(struct wined3d_device_parent *device_parent, void *container_parent,
-            UINT width, UINT height, UINT depth, enum wined3d_format_id format_id, enum wined3d_pool pool, DWORD usage,
-            struct wined3d_volume **volume);
+            UINT width, UINT height, UINT depth, UINT level, enum wined3d_format_id format_id,
+            enum wined3d_pool pool, DWORD usage, struct wined3d_volume **volume);
     HRESULT (__cdecl *create_swapchain)(struct wined3d_device_parent *device_parent,
             struct wined3d_swapchain_desc *desc, struct wined3d_swapchain **swapchain);
 };
@@ -2347,7 +2330,7 @@ HRESULT __cdecl wined3d_surface_releasedc(struct wined3d_surface *surface, HDC d
 HRESULT __cdecl wined3d_surface_restore(struct wined3d_surface *surface);
 HRESULT __cdecl wined3d_surface_set_color_key(struct wined3d_surface *surface,
         DWORD flags, const struct wined3d_color_key *color_key);
-HRESULT __cdecl wined3d_surface_set_mem(struct wined3d_surface *surface, void *mem);
+HRESULT __cdecl wined3d_surface_set_mem(struct wined3d_surface *surface, void *mem, UINT pitch);
 HRESULT __cdecl wined3d_surface_set_overlay_position(struct wined3d_surface *surface, LONG x, LONG y);
 void __cdecl wined3d_surface_set_palette(struct wined3d_surface *surface, struct wined3d_palette *palette);
 DWORD __cdecl wined3d_surface_set_priority(struct wined3d_surface *surface, DWORD new_priority);
@@ -2387,15 +2370,14 @@ void __cdecl wined3d_swapchain_set_window(struct wined3d_swapchain *swapchain, H
 
 HRESULT __cdecl wined3d_texture_add_dirty_region(struct wined3d_texture *texture,
         UINT layer, const struct wined3d_box *dirty_region);
-HRESULT __cdecl wined3d_texture_create_2d(struct wined3d_device *device, UINT width, UINT height,
-        UINT level_count, DWORD usage, enum wined3d_format_id format_id, enum wined3d_pool pool, void *parent,
-        const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture);
-HRESULT __cdecl wined3d_texture_create_3d(struct wined3d_device *device, UINT width, UINT height, UINT depth,
-        UINT level_count, DWORD usage, enum wined3d_format_id format_id, enum wined3d_pool pool, void *parent,
-        const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture);
-HRESULT __cdecl wined3d_texture_create_cube(struct wined3d_device *device, UINT edge_length,
-        UINT level_count, DWORD usage, enum wined3d_format_id format_id, enum wined3d_pool pool, void *parent,
-        const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture);
+HRESULT __cdecl wined3d_texture_create_2d(struct wined3d_device *device, const struct wined3d_resource_desc *desc,
+        UINT level_count, DWORD surface_flags, void *parent, const struct wined3d_parent_ops *parent_ops,
+        struct wined3d_texture **texture);
+HRESULT __cdecl wined3d_texture_create_3d(struct wined3d_device *device, const struct wined3d_resource_desc *desc,
+        UINT level_count, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture);
+HRESULT __cdecl wined3d_texture_create_cube(struct wined3d_device *device, const struct wined3d_resource_desc *desc,
+        UINT level_count, DWORD surface_flags, void *parent, const struct wined3d_parent_ops *parent_ops,
+        struct wined3d_texture **texture);
 ULONG __cdecl wined3d_texture_decref(struct wined3d_texture *texture);
 void __cdecl wined3d_texture_generate_mipmaps(struct wined3d_texture *texture);
 enum wined3d_texture_filter_type __cdecl wined3d_texture_get_autogen_filter_type(const struct wined3d_texture *texture);
@@ -2424,7 +2406,7 @@ void * __cdecl wined3d_vertex_declaration_get_parent(const struct wined3d_vertex
 ULONG __cdecl wined3d_vertex_declaration_incref(struct wined3d_vertex_declaration *declaration);
 
 HRESULT __cdecl wined3d_volume_create(struct wined3d_device *device, UINT width, UINT height, UINT depth,
-        DWORD usage, enum wined3d_format_id format_id, enum wined3d_pool pool, void *parent,
+        UINT level, DWORD usage, enum wined3d_format_id format_id, enum wined3d_pool pool, void *parent,
         const struct wined3d_parent_ops *parent_ops, struct wined3d_volume **volume);
 ULONG __cdecl wined3d_volume_decref(struct wined3d_volume *volume);
 struct wined3d_volume * __cdecl wined3d_volume_from_resource(struct wined3d_resource *resource);
index 1419a18..bc8e590 100644 (file)
@@ -35,10 +35,14 @@ reactos/dll/directx/dplay         # Synced to Wine-1.5.26
 reactos/dll/directx/dplayx        # Synced to Wine-1.5.26
 reactos/dll/directx/dsound        # Synced to Wine-1.5.26
 reactos/dll/directx/dxdiagn       # Synced to Wine-0_9_5
-reactos/dll/directx/dxgi          # Synced to Wine-1.5.26
+reactos/dll/directx/dxgi          # Synced to Wine-1.7.1
 reactos/dll/directx/msdmo         # Autosync
 reactos/dll/directx/qedit         # Autosync
 reactos/dll/directx/quartz        # Synced to Wine-1.5.26
+reactos/dll/directx/wine/d3d8     # Synced to Wine-1.7.1
+reactos/dll/directx/wine/d3d9     # Synced to Wine-1.7.1
+reactos/dll/directx/wine/ddraw    # Synced to Wine-1.7.1
+reactos/dll/directx/wine/wined3d  # Synced to Wine-1.7.1
 reactos/dll/win32/activeds        # Synced to Wine-1.1.43?
 reactos/dll/win32/actxprxy        # Synced to Wine-1.5.26
 reactos/dll/win32/advpack         # Synced to Wine-1.7.1