[DIRECT3D]
authorJérôme Gardou <jerome.gardou@reactos.org>
Sun, 26 Jan 2014 20:53:31 +0000 (20:53 +0000)
committerJérôme Gardou <jerome.gardou@reactos.org>
Sun, 26 Jan 2014 20:53:31 +0000 (20:53 +0000)
 - Update d3d9, d3d8, ddraw and wined3d to wine 1.7.11
CORE-7796 CORE-7803 #resolve #comment Fixed with wine sync. Thanks.

svn path=/trunk/; revision=61843

52 files changed:
reactos/dll/directx/wine/d3d8/d3d8_main.c
reactos/dll/directx/wine/d3d8/d3d8_private.h
reactos/dll/directx/wine/d3d8/device.c
reactos/dll/directx/wine/d3d8/shader.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/d3d9_main.c
reactos/dll/directx/wine/d3d9/d3d9_private.h
reactos/dll/directx/wine/d3d9/device.c
reactos/dll/directx/wine/d3d9/surface.c
reactos/dll/directx/wine/d3d9/swapchain.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_classes.idl
reactos/dll/directx/wine/ddraw/ddraw_private.h
reactos/dll/directx/wine/ddraw/device.c
reactos/dll/directx/wine/ddraw/main.c
reactos/dll/directx/wine/ddraw/palette.c
reactos/dll/directx/wine/ddraw/surface.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/cs.c [new file with mode: 0644]
reactos/dll/directx/wine/wined3d/device.c
reactos/dll/directx/wine/wined3d/directx.c
reactos/dll/directx/wine/wined3d/drawprim.c
reactos/dll/directx/wine/wined3d/glsl_shader.c
reactos/dll/directx/wine/wined3d/nvidia_texture_shader.c
reactos/dll/directx/wine/wined3d/palette.c
reactos/dll/directx/wine/wined3d/query.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/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/psdk/d3d9.h
reactos/include/psdk/d3d9types.h
reactos/include/reactos/wine/wgl.h
reactos/include/reactos/wine/wined3d.h

index 13e3d35..51e5991 100644 (file)
@@ -52,11 +52,10 @@ IDirect3D8 * WINAPI DECLSPEC_HOTPATCH Direct3DCreate8(UINT sdk_version)
 }
 
 /* At process attach */
-BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
+BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, void *reserved)
 {
-    TRACE("fdwReason=%d\n", fdwReason);
-    if (fdwReason == DLL_PROCESS_ATTACH)
-        DisableThreadLibraryCalls(hInstDLL);
+    if (reason == DLL_PROCESS_ATTACH)
+        DisableThreadLibraryCalls(inst);
 
     return TRUE;
 }
index 6fb7296..9f4c224 100644 (file)
@@ -35,7 +35,6 @@
 #define NONAMELESSUNION
 #define NONAMELESSSTRUCT
 #define COBJMACROS
-
 #include <windef.h>
 #include <winbase.h>
 #include <wingdi.h>
@@ -193,9 +192,8 @@ struct d3d8_volume
     IUnknown *forwardReference;
 };
 
-HRESULT volume_init(struct d3d8_volume *volume, struct d3d8_device *device, UINT width, UINT height,
-        UINT depth, UINT level, DWORD usage, enum wined3d_format_id format,
-        enum wined3d_pool pool) DECLSPEC_HIDDEN;
+void volume_init(struct d3d8_volume *volume, struct wined3d_volume *wined3d_volume,
+        const struct wined3d_parent_ops **parent_ops) DECLSPEC_HIDDEN;
 
 struct d3d8_swapchain
 {
@@ -222,9 +220,8 @@ struct d3d8_surface
     IUnknown                    *forwardReference;
 };
 
-HRESULT surface_init(struct d3d8_surface *surface, struct d3d8_device *device, UINT width, UINT height,
-        D3DFORMAT format, DWORD flags, DWORD usage, D3DPOOL pool, D3DMULTISAMPLE_TYPE multisample_type,
-        DWORD multisample_quality) DECLSPEC_HIDDEN;
+void surface_init(struct d3d8_surface *surface, struct wined3d_surface *wined3d_surface,
+        struct d3d8_device *device, const struct wined3d_parent_ops **parent_ops) DECLSPEC_HIDDEN;
 struct d3d8_surface *unsafe_impl_from_IDirect3DSurface8(IDirect3DSurface8 *iface) DECLSPEC_HIDDEN;
 
 struct d3d8_vertexbuffer
index fd0661f..3737a74 100644 (file)
@@ -728,6 +728,7 @@ static HRESULT WINAPI d3d8_device_CreateTexture(IDirect3DDevice8 *iface,
     TRACE("iface %p, width %u, height %u, levels %u, usage %#x, format %#x, pool %#x, texture %p.\n",
             iface, width, height, levels, usage, format, pool, texture);
 
+    *texture = NULL;
     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
     if (!object)
         return D3DERR_OUTOFVIDEOMEMORY;
@@ -757,6 +758,7 @@ static HRESULT WINAPI d3d8_device_CreateVolumeTexture(IDirect3DDevice8 *iface,
     TRACE("iface %p, width %u, height %u, depth %u, levels %u, usage %#x, format %#x, pool %#x, texture %p.\n",
             iface, width, height, depth, levels, usage, format, pool, texture);
 
+    *texture = NULL;
     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
     if (!object)
         return D3DERR_OUTOFVIDEOMEMORY;
@@ -785,6 +787,7 @@ static HRESULT WINAPI d3d8_device_CreateCubeTexture(IDirect3DDevice8 *iface, UIN
     TRACE("iface %p, edge_length %u, levels %u, usage %#x, format %#x, pool %#x, texture %p.\n",
             iface, edge_length, levels, usage, format, pool, texture);
 
+    *texture = NULL;
     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
     if (!object)
         return D3DERR_OUTOFVIDEOMEMORY;
@@ -887,7 +890,7 @@ static HRESULT d3d8_device_create_surface(struct d3d8_device *device, UINT width
 
     wined3d_mutex_lock();
 
-    if (FAILED(hr = wined3d_texture_create_2d(device->wined3d_device, &desc,
+    if (FAILED(hr = wined3d_texture_create(device->wined3d_device, &desc,
             1, flags, NULL, &d3d8_null_wined3d_parent_ops, &texture)))
     {
         wined3d_mutex_unlock();
@@ -918,6 +921,7 @@ static HRESULT WINAPI d3d8_device_CreateRenderTarget(IDirect3DDevice8 *iface, UI
     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);
 
+    *surface = NULL;
     if (lockable)
         flags |= WINED3D_SURFACE_MAPPABLE;
 
@@ -934,6 +938,8 @@ static HRESULT WINAPI d3d8_device_CreateDepthStencilSurface(IDirect3DDevice8 *if
     TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, surface %p.\n",
             iface, width, height, format, multisample_type, surface);
 
+    *surface = NULL;
+
     /* TODO: Verify that Discard is false */
     return d3d8_device_create_surface(device, width, height, format, WINED3D_SURFACE_MAPPABLE,
             surface, D3DUSAGE_DEPTHSTENCIL, D3DPOOL_DEFAULT, multisample_type, 0);
@@ -948,6 +954,8 @@ 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);
 
+    *surface = NULL;
+
     return d3d8_device_create_surface(device, width, height, format, WINED3D_SURFACE_MAPPABLE,
             surface, 0, D3DPOOL_SYSTEMMEM, D3DMULTISAMPLE_NONE, 0);
 }
@@ -1005,7 +1013,7 @@ static HRESULT WINAPI d3d8_device_CopyRects(IDirect3DDevice8 *iface,
     {
         TRACE("Converting destination surface from WINED3DFMT_UNKNOWN to the source format.\n");
         if (FAILED(hr = wined3d_surface_update_desc(dst->wined3d_surface, wined3d_desc.width, wined3d_desc.height,
-                src_format, wined3d_desc.multisample_type, wined3d_desc.multisample_quality)))
+                src_format, wined3d_desc.multisample_type, wined3d_desc.multisample_quality, NULL, 0)))
         {
             WARN("Failed to update surface desc, hr %#x.\n", hr);
             wined3d_mutex_unlock();
@@ -2898,16 +2906,15 @@ static void CDECL device_parent_mode_changed(struct wined3d_device_parent *devic
     TRACE("device_parent %p.\n", device_parent);
 }
 
-static HRESULT CDECL device_parent_create_texture_surface(struct wined3d_device_parent *device_parent,
-        void *container_parent, const struct wined3d_resource_desc *desc, UINT sub_resource_idx,
-        DWORD flags, struct wined3d_surface **surface)
+static HRESULT CDECL device_parent_surface_created(struct wined3d_device_parent *device_parent,
+        void *container_parent, struct wined3d_surface *surface, void **parent,
+        const struct wined3d_parent_ops **parent_ops)
 {
     struct d3d8_device *device = device_from_device_parent(device_parent);
     struct d3d8_surface *d3d_surface;
-    HRESULT hr;
 
-    TRACE("device_parent %p, container_parent %p, desc %p, sub_resource_idx %u, flags %#x, surface %p.\n",
-            device_parent, container_parent, desc, sub_resource_idx, flags, surface);
+    TRACE("device_parent %p, container_parent %p, surface %p, parent %p, parent_ops %p.\n",
+            device_parent, container_parent, surface, parent, parent_ops);
 
     if (!(d3d_surface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*d3d_surface))))
     {
@@ -2915,20 +2922,10 @@ static HRESULT CDECL device_parent_create_texture_surface(struct wined3d_device_
         return D3DERR_OUTOFVIDEOMEMORY;
     }
 
-    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 initialize surface, hr %#x.\n", hr);
-        HeapFree(GetProcessHeap(), 0, d3d_surface);
-        return hr;
-    }
-
+    surface_init(d3d_surface, surface, device, parent_ops);
+    *parent = d3d_surface;
     TRACE("Created surface %p.\n", d3d_surface);
 
-    *surface = d3d_surface->wined3d_surface;
-    wined3d_surface_incref(*surface);
-
     d3d_surface->container = container_parent;
     IDirect3DDevice8_Release(d3d_surface->parent_device);
     d3d_surface->parent_device = NULL;
@@ -2936,7 +2933,31 @@ static HRESULT CDECL device_parent_create_texture_surface(struct wined3d_device_
     IDirect3DSurface8_Release(&d3d_surface->IDirect3DSurface8_iface);
     d3d_surface->forwardReference = container_parent;
 
-    return hr;
+    return D3D_OK;
+}
+
+static HRESULT CDECL device_parent_volume_created(struct wined3d_device_parent *device_parent,
+        void *container_parent, struct wined3d_volume *volume, void **parent,
+        const struct wined3d_parent_ops **parent_ops)
+{
+    struct d3d8_volume *d3d_volume;
+
+    TRACE("device_parent %p, container_parent %p, volume %p, parent %p, parent_ops %p.\n",
+            device_parent, container_parent, volume, parent, parent_ops);
+
+    if (!(d3d_volume = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*d3d_volume))))
+        return E_OUTOFMEMORY;
+
+    volume_init(d3d_volume, volume, parent_ops);
+    *parent = d3d_volume;
+    TRACE("Created volume %p.\n", d3d_volume);
+
+    d3d_volume->container = container_parent;
+
+    IDirect3DVolume8_Release(&d3d_volume->IDirect3DVolume8_iface);
+    d3d_volume->forwardReference = container_parent;
+
+    return D3D_OK;
 }
 
 static HRESULT CDECL device_parent_create_swapchain_surface(struct wined3d_device_parent *device_parent,
@@ -2953,7 +2974,7 @@ static HRESULT CDECL device_parent_create_swapchain_surface(struct wined3d_devic
 
     texture_desc = *desc;
     texture_desc.resource_type = WINED3D_RTYPE_TEXTURE;
-    if (FAILED(hr = wined3d_texture_create_2d(device->wined3d_device, &texture_desc, 1,
+    if (FAILED(hr = wined3d_texture_create(device->wined3d_device, &texture_desc, 1,
             WINED3D_SURFACE_MAPPABLE, &device->IDirect3DDevice8_iface, &d3d8_null_wined3d_parent_ops, &texture)))
     {
         WARN("Failed to create texture, hr %#x.\n", hr);
@@ -2971,48 +2992,6 @@ static HRESULT CDECL device_parent_create_swapchain_surface(struct wined3d_devic
     return hr;
 }
 
-static HRESULT CDECL device_parent_create_volume(struct wined3d_device_parent *device_parent,
-        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;
-    HRESULT hr;
-
-    TRACE("device_parent %p, container_parent %p, width %u, height %u, depth %u, "
-            "format %#x, pool %#x, usage %#x, volume %p.\n",
-            device_parent, container_parent, width, height, depth,
-            format, pool, usage, volume);
-
-    /* Allocate the storage for the device */
-    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
-    if (!object)
-    {
-        FIXME("Allocation of memory failed\n");
-        *volume = NULL;
-        return D3DERR_OUTOFVIDEOMEMORY;
-    }
-
-    hr = volume_init(object, device, width, height, depth, level, usage, format, pool);
-    if (FAILED(hr))
-    {
-        WARN("Failed to initialize volume, hr %#x.\n", hr);
-        HeapFree(GetProcessHeap(), 0, object);
-        return hr;
-    }
-
-    *volume = object->wined3d_volume;
-    wined3d_volume_incref(*volume);
-    IDirect3DVolume8_Release(&object->IDirect3DVolume8_iface);
-
-    object->container = container_parent;
-    object->forwardReference = container_parent;
-
-    TRACE("Created volume %p.\n", object);
-
-    return hr;
-}
-
 static HRESULT CDECL device_parent_create_swapchain(struct wined3d_device_parent *device_parent,
         struct wined3d_swapchain_desc *desc, struct wined3d_swapchain **swapchain)
 {
@@ -3040,9 +3019,9 @@ static const struct wined3d_device_parent_ops d3d8_wined3d_device_parent_ops =
 {
     device_parent_wined3d_device_created,
     device_parent_mode_changed,
+    device_parent_surface_created,
+    device_parent_volume_created,
     device_parent_create_swapchain_surface,
-    device_parent_create_texture_surface,
-    device_parent_create_volume,
     device_parent_create_swapchain,
 };
 
index 540a4c0..7453e01 100644 (file)
@@ -92,7 +92,7 @@ HRESULT d3d8_vertex_shader_init(struct d3d8_vertex_shader *shader, struct d3d8_d
 
             if (reg == D3DVSDE_NORMAL && type != D3DVSDT_FLOAT3 && !byte_code)
             {
-                WARN("Attempt to use a non-FLOAT3 normal with the fixed function function\n");
+                WARN("Attempt to use a non-FLOAT3 normal with the fixed-function function\n");
                 return D3DERR_INVALIDCALL;
             }
         }
index 8295a36..10abee8 100644 (file)
@@ -270,8 +270,16 @@ static HRESULT WINAPI d3d8_surface_LockRect(IDirect3DSurface8 *iface,
     hr = wined3d_surface_map(surface->wined3d_surface, &map_desc, rect, flags);
     wined3d_mutex_unlock();
 
-    locked_rect->Pitch = map_desc.row_pitch;
-    locked_rect->pBits = map_desc.data;
+    if (SUCCEEDED(hr))
+    {
+        locked_rect->Pitch = map_desc.row_pitch;
+        locked_rect->pBits = map_desc.data;
+    }
+    else
+    {
+        locked_rect->Pitch = 0;
+        locked_rect->pBits = NULL;
+    }
 
     return hr;
 }
@@ -322,37 +330,17 @@ static const struct wined3d_parent_ops d3d8_surface_wined3d_parent_ops =
     surface_wined3d_object_destroyed,
 };
 
-HRESULT surface_init(struct d3d8_surface *surface, struct d3d8_device *device, UINT width, UINT height,
-        D3DFORMAT format, DWORD flags, DWORD usage, D3DPOOL pool, D3DMULTISAMPLE_TYPE multisample_type,
-        DWORD multisample_quality)
+void surface_init(struct d3d8_surface *surface, struct wined3d_surface *wined3d_surface,
+        struct d3d8_device *device, const struct wined3d_parent_ops **parent_ops)
 {
-    HRESULT hr;
-
     surface->IDirect3DSurface8_iface.lpVtbl = &d3d8_surface_vtbl;
     surface->refcount = 1;
-
-    /* FIXME: Check MAX bounds of MultisampleQuality. */
-    if (multisample_quality > 0)
-    {
-        FIXME("Multisample quality set to %u, substituting 0.\n", multisample_quality);
-        multisample_quality = 0;
-    }
-
-    wined3d_mutex_lock();
-    hr = wined3d_surface_create(device->wined3d_device, width, height, wined3dformat_from_d3dformat(format),
-            usage & WINED3DUSAGE_MASK, (enum wined3d_pool)pool, multisample_type, multisample_quality,
-            flags, surface, &d3d8_surface_wined3d_parent_ops, &surface->wined3d_surface);
-    wined3d_mutex_unlock();
-    if (FAILED(hr))
-    {
-        WARN("Failed to create wined3d surface, hr %#x.\n", hr);
-        return hr;
-    }
-
+    wined3d_surface_incref(wined3d_surface);
+    surface->wined3d_surface = wined3d_surface;
     surface->parent_device = &device->IDirect3DDevice8_iface;
     IDirect3DDevice8_AddRef(surface->parent_device);
 
-    return D3D_OK;
+    *parent_ops = &d3d8_surface_wined3d_parent_ops;
 }
 
 struct d3d8_surface *unsafe_impl_from_IDirect3DSurface8(IDirect3DSurface8 *iface)
index e954ddc..9ea83e7 100644 (file)
@@ -1194,6 +1194,7 @@ HRESULT texture_init(struct d3d8_texture *texture, struct d3d8_device *device,
     desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
     desc.multisample_quality = 0;
     desc.usage = usage & WINED3DUSAGE_MASK;
+    desc.usage |= WINED3DUSAGE_TEXTURE;
     desc.pool = pool;
     desc.width = width;
     desc.height = height;
@@ -1204,7 +1205,7 @@ HRESULT texture_init(struct d3d8_texture *texture, struct d3d8_device *device,
         surface_flags |= WINED3D_SURFACE_MAPPABLE;
 
     wined3d_mutex_lock();
-    hr = wined3d_texture_create_2d(device->wined3d_device, &desc, levels, surface_flags,
+    hr = wined3d_texture_create(device->wined3d_device, &desc, levels, surface_flags,
             texture, &d3d8_texture_wined3d_parent_ops, &texture->wined3d_texture);
     wined3d_mutex_unlock();
     if (FAILED(hr))
@@ -1234,6 +1235,7 @@ HRESULT cubetexture_init(struct d3d8_texture *texture, struct d3d8_device *devic
     desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
     desc.multisample_quality = 0;
     desc.usage = usage & WINED3DUSAGE_MASK;
+    desc.usage |= WINED3DUSAGE_TEXTURE;
     desc.pool = pool;
     desc.width = edge_length;
     desc.height = edge_length;
@@ -1244,7 +1246,7 @@ HRESULT cubetexture_init(struct d3d8_texture *texture, struct d3d8_device *devic
         surface_flags |= WINED3D_SURFACE_MAPPABLE;
 
     wined3d_mutex_lock();
-    hr = wined3d_texture_create_cube(device->wined3d_device, &desc, levels, surface_flags,
+    hr = wined3d_texture_create(device->wined3d_device, &desc, levels, surface_flags,
             texture, &d3d8_texture_wined3d_parent_ops, &texture->wined3d_texture);
     wined3d_mutex_unlock();
     if (FAILED(hr))
@@ -1273,6 +1275,7 @@ HRESULT volumetexture_init(struct d3d8_texture *texture, struct d3d8_device *dev
     desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
     desc.multisample_quality = 0;
     desc.usage = usage & WINED3DUSAGE_MASK;
+    desc.usage |= WINED3DUSAGE_TEXTURE;
     desc.pool = pool;
     desc.width = width;
     desc.height = height;
@@ -1280,7 +1283,7 @@ HRESULT volumetexture_init(struct d3d8_texture *texture, struct d3d8_device *dev
     desc.size = 0;
 
     wined3d_mutex_lock();
-    hr = wined3d_texture_create_3d(device->wined3d_device, &desc, levels,
+    hr = wined3d_texture_create(device->wined3d_device, &desc, levels, 0,
             texture, &d3d8_texture_wined3d_parent_ops, &texture->wined3d_texture);
     wined3d_mutex_unlock();
     if (FAILED(hr))
index 5e3a8a4..d2399d5 100644 (file)
@@ -280,21 +280,13 @@ static const struct wined3d_parent_ops d3d8_volume_wined3d_parent_ops =
     volume_wined3d_object_destroyed,
 };
 
-HRESULT volume_init(struct d3d8_volume *volume, struct d3d8_device *device, UINT width, UINT height,
-        UINT depth, UINT level, DWORD usage, enum wined3d_format_id format, enum wined3d_pool pool)
+void volume_init(struct d3d8_volume *volume, struct wined3d_volume *wined3d_volume,
+        const struct wined3d_parent_ops **parent_ops)
 {
-    HRESULT hr;
-
     volume->IDirect3DVolume8_iface.lpVtbl = &d3d8_volume_vtbl;
     volume->refcount = 1;
+    wined3d_volume_incref(wined3d_volume);
+    volume->wined3d_volume = wined3d_volume;
 
-    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))
-    {
-        WARN("Failed to create wined3d volume, hr %#x.\n", hr);
-        return hr;
-    }
-
-    return D3D_OK;
+    *parent_ops = &d3d8_volume_wined3d_parent_ops;
 }
index 01d6b21..b2a1c68 100644 (file)
@@ -89,12 +89,10 @@ void* WINAPI Direct3DShaderValidatorCreate9(void)
 /*******************************************************************
  *       DllMain
  */
-BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
+BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, void *reserved)
 {
-    /* At process attach */
-    TRACE("fdwReason=%d\n", fdwReason);
-    if (fdwReason == DLL_PROCESS_ATTACH)
-        DisableThreadLibraryCalls(hInstDLL);
+    if (reason == DLL_PROCESS_ATTACH)
+        DisableThreadLibraryCalls(inst);
 
     return TRUE;
 }
@@ -102,8 +100,9 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
 /***********************************************************************
  *              D3DPERF_BeginEvent (D3D9.@)
  */
-int WINAPI D3DPERF_BeginEvent(D3DCOLOR color, LPCWSTR name) {
-    TRACE("(color %#x, name %s) : stub\n", color, debugstr_w(name));
+int WINAPI D3DPERF_BeginEvent(D3DCOLOR color, const WCHAR *name)
+{
+    TRACE("color 0x%08x, name %s.\n", color, debugstr_w(name));
 
     return D3DPERF_event_level++;
 }
@@ -147,13 +146,15 @@ BOOL WINAPI D3DPERF_QueryRepeatFrame(void) {
 /***********************************************************************
  *              D3DPERF_SetMarker (D3D9.@)
  */
-void WINAPI D3DPERF_SetMarker(D3DCOLOR color, LPCWSTR name) {
-    FIXME("(color %#x, name %s) : stub\n", color, debugstr_w(name));
+void WINAPI D3DPERF_SetMarker(D3DCOLOR color, const WCHAR *name)
+{
+    FIXME("color 0x%08x, name %s stub!\n", color, debugstr_w(name));
 }
 
 /***********************************************************************
  *              D3DPERF_SetRegion (D3D9.@)
  */
-void WINAPI D3DPERF_SetRegion(D3DCOLOR color, LPCWSTR name) {
-    FIXME("(color %#x, name %s) : stub\n", color, debugstr_w(name));
+void WINAPI D3DPERF_SetRegion(D3DCOLOR color, const WCHAR *name)
+{
+    FIXME("color 0x%08x, name %s stub!\n", color, debugstr_w(name));
 }
index 6ae0c4d..e896c28 100644 (file)
@@ -35,7 +35,6 @@
 #define NONAMELESSUNION
 #define NONAMELESSSTRUCT
 #define COBJMACROS
-
 #include <windef.h>
 #include <winbase.h>
 #include <wingdi.h>
@@ -182,13 +181,12 @@ struct d3d9_volume
     IUnknown *forwardReference;
 };
 
-HRESULT volume_init(struct d3d9_volume *volume, struct d3d9_device *device, UINT width, UINT height,
-        UINT depth, UINT level, DWORD usage, enum wined3d_format_id format,
-        enum wined3d_pool pool) DECLSPEC_HIDDEN;
+void volume_init(struct d3d9_volume *volume, struct wined3d_volume *wined3d_volume,
+        const struct wined3d_parent_ops **parent_ops) DECLSPEC_HIDDEN;
 
 struct d3d9_swapchain
 {
-    IDirect3DSwapChain9 IDirect3DSwapChain9_iface;
+    IDirect3DSwapChain9Ex IDirect3DSwapChain9Ex_iface;
     LONG refcount;
     struct wined3d_swapchain *wined3d_swapchain;
     IDirect3DDevice9Ex *parent_device;
@@ -208,9 +206,8 @@ struct d3d9_surface
     BOOL getdc_supported;
 };
 
-HRESULT surface_init(struct d3d9_surface *surface, struct d3d9_device *device, UINT width, UINT height,
-        D3DFORMAT format, DWORD flags, DWORD usage, D3DPOOL pool, D3DMULTISAMPLE_TYPE multisample_type,
-        DWORD multisample_quality) DECLSPEC_HIDDEN;
+void surface_init(struct d3d9_surface *surface, struct wined3d_surface *wined3d_surface,
+        struct d3d9_device *device, const struct wined3d_parent_ops **parent_ops) DECLSPEC_HIDDEN;
 struct d3d9_surface *unsafe_impl_from_IDirect3DSurface9(IDirect3DSurface9 *iface) DECLSPEC_HIDDEN;
 
 struct d3d9_vertexbuffer
@@ -319,4 +316,9 @@ struct d3d9_query
 
 HRESULT query_init(struct d3d9_query *query, struct d3d9_device *device, D3DQUERYTYPE type) DECLSPEC_HIDDEN;
 
+static inline struct d3d9_device *impl_from_IDirect3DDevice9Ex(IDirect3DDevice9Ex *iface)
+{
+    return CONTAINING_RECORD(iface, struct d3d9_device, IDirect3DDevice9Ex_iface);
+}
+
 #endif /* __WINE_D3D9_PRIVATE_H */
index 6bcc65b..efff993 100644 (file)
@@ -226,11 +226,6 @@ static void wined3d_swapchain_desc_from_present_parameters(struct wined3d_swapch
     swapchain_desc->auto_restore_display_mode = TRUE;
 }
 
-static inline struct d3d9_device *impl_from_IDirect3DDevice9Ex(IDirect3DDevice9Ex *iface)
-{
-    return CONTAINING_RECORD(iface, struct d3d9_device, IDirect3DDevice9Ex_iface);
-}
-
 static HRESULT WINAPI d3d9_device_QueryInterface(IDirect3DDevice9Ex *iface, REFIID riid, void **out)
 {
     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
@@ -504,7 +499,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_CreateAdditionalSwapChain(ID
 
     wined3d_swapchain_desc_from_present_parameters(&desc, present_parameters);
     if (SUCCEEDED(hr = d3d9_swapchain_create(device, &desc, &object)))
-        *swapchain = &object->IDirect3DSwapChain9_iface;
+        *swapchain = (IDirect3DSwapChain9 *)&object->IDirect3DSwapChain9Ex_iface;
     present_parameters_from_wined3d_swapchain_desc(present_parameters, &desc);
 
     return hr;
@@ -524,8 +519,8 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_GetSwapChain(IDirect3DDevice
     if ((wined3d_swapchain = wined3d_device_get_swapchain(device->wined3d_device, swapchain_idx)))
     {
        swapchain_impl = wined3d_swapchain_get_parent(wined3d_swapchain);
-       *swapchain = &swapchain_impl->IDirect3DSwapChain9_iface;
-       IDirect3DSwapChain9_AddRef(*swapchain);
+       *swapchain = (IDirect3DSwapChain9 *)&swapchain_impl->IDirect3DSwapChain9Ex_iface;
+       IDirect3DSwapChain9Ex_AddRef(*swapchain);
        hr = D3D_OK;
     }
     else
@@ -739,8 +734,15 @@ static HRESULT WINAPI d3d9_device_CreateTexture(IDirect3DDevice9Ex *iface,
     TRACE("iface %p, width %u, height %u, levels %u, usage %#x, format %#x, pool %#x, texture %p, shared_handle %p.\n",
             iface, width, height, levels, usage, format, pool, texture, shared_handle);
 
+    *texture = NULL;
     if (shared_handle)
     {
+        if (!device->d3d_parent->extended)
+        {
+            WARN("Trying to create a shared or user memory texture on a non-ex device.\n");
+            return E_NOTIMPL;
+        }
+
         if (pool == D3DPOOL_SYSTEMMEM)
         {
             if (levels != 1)
@@ -748,7 +750,14 @@ static HRESULT WINAPI d3d9_device_CreateTexture(IDirect3DDevice9Ex *iface,
             set_mem = TRUE;
         }
         else
+        {
+            if (pool != D3DPOOL_DEFAULT)
+            {
+                WARN("Trying to create a shared texture in pool %#x.\n", pool);
+                return D3DERR_INVALIDCALL;
+            }
             FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
+        }
     }
 
     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
@@ -770,7 +779,9 @@ 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, 0);
+        wined3d_surface_update_desc(surface->wined3d_surface, width, height,
+                wined3dformat_from_d3dformat(format), WINED3D_MULTISAMPLE_NONE, 0,
+                *shared_handle, 0);
     }
 
     TRACE("Created texture %p.\n", object);
@@ -792,8 +803,22 @@ static HRESULT WINAPI d3d9_device_CreateVolumeTexture(IDirect3DDevice9Ex *iface,
     TRACE("usage %#x, format %#x, pool %#x, texture %p, shared_handle %p.\n",
             usage, format, pool, texture, shared_handle);
 
+    *texture = NULL;
     if (shared_handle)
+    {
+        if (!device->d3d_parent->extended)
+        {
+            WARN("Trying to create a shared volume texture on a non-ex device.\n");
+            return E_NOTIMPL;
+        }
+
+        if (pool != D3DPOOL_DEFAULT)
+        {
+            WARN("Trying to create a shared volume texture in pool %#x.\n", pool);
+            return D3DERR_INVALIDCALL;
+        }
         FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
+    }
 
     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
     if (!object)
@@ -824,8 +849,22 @@ static HRESULT WINAPI d3d9_device_CreateCubeTexture(IDirect3DDevice9Ex *iface,
     TRACE("iface %p, edge_length %u, levels %u, usage %#x, format %#x, pool %#x, texture %p, shared_handle %p.\n",
             iface, edge_length, levels, usage, format, pool, texture, shared_handle);
 
+    *texture = NULL;
     if (shared_handle)
+    {
+        if (!device->d3d_parent->extended)
+        {
+            WARN("Trying to create a shared cube texture on a non-ex device.\n");
+            return E_NOTIMPL;
+        }
+
+        if (pool != D3DPOOL_DEFAULT)
+        {
+            WARN("Trying to create a shared cube texture in pool %#x.\n", pool);
+            return D3DERR_INVALIDCALL;
+        }
         FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
+    }
 
     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
     if (!object)
@@ -857,7 +896,20 @@ static HRESULT WINAPI d3d9_device_CreateVertexBuffer(IDirect3DDevice9Ex *iface,
             iface, size, usage, fvf, pool, buffer, shared_handle);
 
     if (shared_handle)
+    {
+        if (!device->d3d_parent->extended)
+        {
+            WARN("Trying to create a shared vertex buffer on a non-ex device.\n");
+            return E_NOTIMPL;
+        }
+
+        if (pool != D3DPOOL_DEFAULT)
+        {
+            WARN("Trying to create a shared vertex buffer in pool %#x.\n", pool);
+            return D3DERR_NOTAVAILABLE;
+        }
         FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
+    }
 
     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
     if (!object)
@@ -889,7 +941,20 @@ static HRESULT WINAPI d3d9_device_CreateIndexBuffer(IDirect3DDevice9Ex *iface, U
             iface, size, usage, format, pool, buffer, shared_handle);
 
     if (shared_handle)
+    {
+        if (!device->d3d_parent->extended)
+        {
+            WARN("Trying to create a shared index buffer on a non-ex device.\n");
+            return E_NOTIMPL;
+        }
+
+        if (pool != D3DPOOL_DEFAULT)
+        {
+            WARN("Trying to create a shared index buffer in pool %#x.\n", pool);
+            return D3DERR_NOTAVAILABLE;
+        }
         FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
+    }
 
     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
     if (!object)
@@ -911,7 +976,7 @@ 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, DWORD flags, IDirect3DSurface9 **surface, UINT usage, D3DPOOL pool,
-        D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality)
+        D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality, void *user_mem)
 {
     struct wined3d_resource *sub_resource;
     struct wined3d_resource_desc desc;
@@ -937,7 +1002,7 @@ static HRESULT d3d9_device_create_surface(struct d3d9_device *device, UINT width
 
     wined3d_mutex_lock();
 
-    if (FAILED(hr = wined3d_texture_create_2d(device->wined3d_device, &desc,
+    if (FAILED(hr = wined3d_texture_create(device->wined3d_device, &desc,
             1, flags, NULL, &d3d9_null_wined3d_parent_ops, &texture)))
     {
         wined3d_mutex_unlock();
@@ -953,6 +1018,10 @@ static HRESULT d3d9_device_create_surface(struct d3d9_device *device, UINT width
     IDirect3DSurface9_AddRef(*surface);
     wined3d_texture_decref(texture);
 
+    if (user_mem)
+        wined3d_surface_update_desc(surface_impl->wined3d_surface, width, height,
+                desc.format, multisample_type, multisample_quality, user_mem, 0);
+
     wined3d_mutex_unlock();
 
     return D3D_OK;
@@ -970,14 +1039,23 @@ static HRESULT WINAPI d3d9_device_CreateRenderTarget(IDirect3DDevice9Ex *iface,
             iface, width, height, format, multisample_type, multisample_quality,
             lockable, surface, shared_handle);
 
+    *surface = NULL;
     if (shared_handle)
+    {
+        if (!device->d3d_parent->extended)
+        {
+            WARN("Trying to create a shared render target on a non-ex device.\n");
+            return E_NOTIMPL;
+        }
+
         FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
+    }
 
     if (lockable)
         flags |= WINED3D_SURFACE_MAPPABLE;
 
     return d3d9_device_create_surface(device, width, height, format, flags, surface,
-            D3DUSAGE_RENDERTARGET, D3DPOOL_DEFAULT, multisample_type, multisample_quality);
+            D3DUSAGE_RENDERTARGET, D3DPOOL_DEFAULT, multisample_type, multisample_quality, NULL);
 }
 
 static HRESULT WINAPI d3d9_device_CreateDepthStencilSurface(IDirect3DDevice9Ex *iface, UINT width, UINT height,
@@ -992,14 +1070,23 @@ static HRESULT WINAPI d3d9_device_CreateDepthStencilSurface(IDirect3DDevice9Ex *
             iface, width, height, format, multisample_type, multisample_quality,
             discard, surface, shared_handle);
 
+    *surface = NULL;
     if (shared_handle)
+    {
+        if (!device->d3d_parent->extended)
+        {
+            WARN("Trying to create a shared depth stencil on a non-ex device.\n");
+            return E_NOTIMPL;
+        }
+
         FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
+    }
 
     if (discard)
         flags |= WINED3D_SURFACE_DISCARD;
 
     return d3d9_device_create_surface(device, width, height, format, flags, surface,
-            D3DUSAGE_DEPTHSTENCIL, D3DPOOL_DEFAULT, multisample_type, multisample_quality);
+            D3DUSAGE_DEPTHSTENCIL, D3DPOOL_DEFAULT, multisample_type, multisample_quality, NULL);
 }
 
 
@@ -1184,23 +1271,44 @@ static HRESULT WINAPI d3d9_device_CreateOffscreenPlainSurface(IDirect3DDevice9Ex
         HANDLE *shared_handle)
 {
     struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    void *user_mem = NULL;
 
     TRACE("iface %p, width %u, height %u, format %#x, pool %#x, surface %p, shared_handle %p.\n",
             iface, width, height, format, pool, surface, shared_handle);
 
-    if (shared_handle)
-        FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
-
+    *surface = NULL;
     if (pool == D3DPOOL_MANAGED)
     {
         WARN("Attempting to create a managed offscreen plain surface.\n");
         return D3DERR_INVALIDCALL;
     }
+
+    if (shared_handle)
+    {
+        if (!device->d3d_parent->extended)
+        {
+            WARN("Trying to create a shared or user memory surface on a non-ex device.\n");
+            return E_NOTIMPL;
+        }
+
+        if (pool == D3DPOOL_SYSTEMMEM)
+            user_mem = *shared_handle;
+        else
+        {
+            if (pool != D3DPOOL_DEFAULT)
+            {
+                WARN("Trying to create a shared surface in pool %#x.\n", pool);
+                return D3DERR_INVALIDCALL;
+            }
+            FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
+        }
+    }
+
     /* FIXME: Offscreen surfaces are supposed to be always lockable,
      * regardless of the pool they're created in. Should we set dynamic usage
      * here? */
     return d3d9_device_create_surface(device, width, height, format,
-            WINED3D_SURFACE_MAPPABLE, surface, 0, pool, D3DMULTISAMPLE_NONE, 0);
+            WINED3D_SURFACE_MAPPABLE, surface, 0, pool, D3DMULTISAMPLE_NONE, 0, user_mem);
 }
 
 static HRESULT WINAPI d3d9_device_SetRenderTarget(IDirect3DDevice9Ex *iface, DWORD idx, IDirect3DSurface9 *surface)
@@ -1217,6 +1325,12 @@ static HRESULT WINAPI d3d9_device_SetRenderTarget(IDirect3DDevice9Ex *iface, DWO
         return D3DERR_INVALIDCALL;
     }
 
+    if (!idx && !surface_impl)
+    {
+         WARN("Trying to set render target 0 to NULL.\n");
+         return D3DERR_INVALIDCALL;
+    }
+
     wined3d_mutex_lock();
     hr = wined3d_device_set_render_target(device->wined3d_device, idx,
             surface_impl ? surface_impl->wined3d_surface : NULL, TRUE);
@@ -2363,7 +2477,7 @@ static struct wined3d_vertex_declaration *device_get_fvf_declaration(struct d3d9
     fvf_decls[low].fvf = fvf;
     ++device->fvf_decl_count;
 
-    TRACE("Returning %p. %u declatations in array.\n", wined3d_declaration, device->fvf_decl_count);
+    TRACE("Returning %p. %u declarations in array.\n", wined3d_declaration, device->fvf_decl_count);
 
     return wined3d_declaration;
 }
@@ -3035,6 +3149,7 @@ static HRESULT WINAPI d3d9_device_CreateRenderTargetEx(IDirect3DDevice9Ex *iface
             iface, width, height, format, multisample_type, multisample_quality,
             lockable, surface, shared_handle, usage);
 
+    *surface = NULL;
     if (shared_handle)
         FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
 
@@ -3060,6 +3175,7 @@ static HRESULT WINAPI d3d9_device_CreateDepthStencilSurfaceEx(IDirect3DDevice9Ex
             iface, width, height, format, multisample_type, multisample_quality,
             discard, surface, shared_handle, usage);
 
+    *surface = NULL;
     if (shared_handle)
         FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
 
@@ -3295,16 +3411,15 @@ static void CDECL device_parent_mode_changed(struct wined3d_device_parent *devic
     TRACE("device_parent %p.\n", device_parent);
 }
 
-static HRESULT CDECL device_parent_create_texture_surface(struct wined3d_device_parent *device_parent,
-        void *container_parent, const struct wined3d_resource_desc *desc, UINT sub_resource_idx,
-        DWORD flags, struct wined3d_surface **surface)
+static HRESULT CDECL device_parent_surface_created(struct wined3d_device_parent *device_parent,
+        void *container_parent, struct wined3d_surface *surface, void **parent,
+        const struct wined3d_parent_ops **parent_ops)
 {
     struct d3d9_device *device = device_from_device_parent(device_parent);
     struct d3d9_surface *d3d_surface;
-    HRESULT hr;
 
-    TRACE("device_parent %p, container_parent %p, desc %p, sub_resource_idx %u, flags %#x, surface %p.\n",
-            device_parent, container_parent, desc, sub_resource_idx, flags, surface);
+    TRACE("device_parent %p, container_parent %p, surface %p, parent %p, parent_ops %p.\n",
+            device_parent, container_parent, surface, parent, parent_ops);
 
     if (!(d3d_surface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*d3d_surface))))
     {
@@ -3312,20 +3427,10 @@ static HRESULT CDECL device_parent_create_texture_surface(struct wined3d_device_
         return D3DERR_OUTOFVIDEOMEMORY;
     }
 
-    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 initialize surface, hr %#x.\n", hr);
-        HeapFree(GetProcessHeap(), 0, d3d_surface);
-        return hr;
-    }
-
+    surface_init(d3d_surface, surface, device, parent_ops);
+    *parent = d3d_surface;
     TRACE("Created surface %p.\n", d3d_surface);
 
-    *surface = d3d_surface->wined3d_surface;
-    wined3d_surface_incref(*surface);
-
     d3d_surface->container = container_parent;
     IDirect3DDevice9Ex_Release(d3d_surface->parent_device);
     d3d_surface->parent_device = NULL;
@@ -3333,7 +3438,31 @@ static HRESULT CDECL device_parent_create_texture_surface(struct wined3d_device_
     IDirect3DSurface9_Release(&d3d_surface->IDirect3DSurface9_iface);
     d3d_surface->forwardReference = container_parent;
 
-    return hr;
+    return D3D_OK;
+}
+
+static HRESULT CDECL device_parent_volume_created(struct wined3d_device_parent *device_parent,
+        void *container_parent, struct wined3d_volume *volume, void **parent,
+        const struct wined3d_parent_ops **parent_ops)
+{
+    struct d3d9_volume *d3d_volume;
+
+    TRACE("device_parent %p, container_parent %p, volume %p, parent %p, parent_ops %p.\n",
+            device_parent, container_parent, volume, parent, parent_ops);
+
+    if (!(d3d_volume = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*d3d_volume))))
+        return E_OUTOFMEMORY;
+
+    volume_init(d3d_volume, volume, parent_ops);
+    *parent = d3d_volume;
+    TRACE("Created volume %p.\n", d3d_volume);
+
+    d3d_volume->container = container_parent;
+
+    IDirect3DVolume9_Release(&d3d_volume->IDirect3DVolume9_iface);
+    d3d_volume->forwardReference = container_parent;
+
+    return D3D_OK;
 }
 
 static HRESULT CDECL device_parent_create_swapchain_surface(struct wined3d_device_parent *device_parent,
@@ -3353,7 +3482,7 @@ static HRESULT CDECL device_parent_create_swapchain_surface(struct wined3d_devic
 
     texture_desc = *desc;
     texture_desc.resource_type = WINED3D_RTYPE_TEXTURE;
-    if (FAILED(hr = wined3d_texture_create_2d(device->wined3d_device, &texture_desc, 1,
+    if (FAILED(hr = wined3d_texture_create(device->wined3d_device, &texture_desc, 1,
             WINED3D_SURFACE_MAPPABLE, container_parent, &d3d9_null_wined3d_parent_ops, &texture)))
     {
         WARN("Failed to create texture, hr %#x.\n", hr);
@@ -3371,48 +3500,6 @@ static HRESULT CDECL device_parent_create_swapchain_surface(struct wined3d_devic
     return hr;
 }
 
-static HRESULT CDECL device_parent_create_volume(struct wined3d_device_parent *device_parent,
-        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;
-    HRESULT hr;
-
-    TRACE("device_parent %p, container_parent %p, width %u, height %u, depth %u, "
-            "format %#x, pool %#x, usage %#x, volume %p\n",
-            device_parent, container_parent, width, height, depth,
-            format, pool, usage, volume);
-
-    /* Allocate the storage for the device */
-    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
-    if (!object)
-    {
-        FIXME("Allocation of memory failed\n");
-        *volume = NULL;
-        return D3DERR_OUTOFVIDEOMEMORY;
-    }
-
-    hr = volume_init(object, device, width, height, depth, level, usage, format, pool);
-    if (FAILED(hr))
-    {
-        WARN("Failed to initialize volume, hr %#x.\n", hr);
-        HeapFree(GetProcessHeap(), 0, object);
-        return hr;
-    }
-
-    *volume = object->wined3d_volume;
-    wined3d_volume_incref(*volume);
-    IDirect3DVolume9_Release(&object->IDirect3DVolume9_iface);
-
-    object->container = container_parent;
-    object->forwardReference = container_parent;
-
-    TRACE("Created volume %p.\n", object);
-
-    return hr;
-}
-
 static HRESULT CDECL device_parent_create_swapchain(struct wined3d_device_parent *device_parent,
         struct wined3d_swapchain_desc *desc, struct wined3d_swapchain **swapchain)
 {
@@ -3432,7 +3519,7 @@ static HRESULT CDECL device_parent_create_swapchain(struct wined3d_device_parent
 
     *swapchain = d3d_swapchain->wined3d_swapchain;
     wined3d_swapchain_incref(*swapchain);
-    IDirect3DSwapChain9_Release(&d3d_swapchain->IDirect3DSwapChain9_iface);
+    IDirect3DSwapChain9Ex_Release(&d3d_swapchain->IDirect3DSwapChain9Ex_iface);
 
     return hr;
 }
@@ -3441,9 +3528,9 @@ static const struct wined3d_device_parent_ops d3d9_wined3d_device_parent_ops =
 {
     device_parent_wined3d_device_created,
     device_parent_mode_changed,
+    device_parent_surface_created,
+    device_parent_volume_created,
     device_parent_create_swapchain_surface,
-    device_parent_create_texture_surface,
-    device_parent_create_volume,
     device_parent_create_swapchain,
 };
 
index c86d05d..27e6744 100644 (file)
@@ -290,8 +290,11 @@ static HRESULT WINAPI d3d9_surface_LockRect(IDirect3DSurface9 *iface,
     hr = wined3d_surface_map(surface->wined3d_surface, &map_desc, rect, flags);
     wined3d_mutex_unlock();
 
-    locked_rect->Pitch = map_desc.row_pitch;
-    locked_rect->pBits = map_desc.data;
+    if (SUCCEEDED(hr))
+    {
+        locked_rect->Pitch = map_desc.row_pitch;
+        locked_rect->pBits = map_desc.data;
+    }
 
     return hr;
 }
@@ -387,16 +390,16 @@ static const struct wined3d_parent_ops d3d9_surface_wined3d_parent_ops =
     surface_wined3d_object_destroyed,
 };
 
-HRESULT surface_init(struct d3d9_surface *surface, struct d3d9_device *device, UINT width, UINT height,
-        D3DFORMAT format, DWORD flags, DWORD usage, D3DPOOL pool, D3DMULTISAMPLE_TYPE multisample_type,
-        DWORD multisample_quality)
+void surface_init(struct d3d9_surface *surface, struct wined3d_surface *wined3d_surface,
+        struct d3d9_device *device, const struct wined3d_parent_ops **parent_ops)
 {
-    HRESULT hr;
+    struct wined3d_resource_desc desc;
 
     surface->IDirect3DSurface9_iface.lpVtbl = &d3d9_surface_vtbl;
     surface->refcount = 1;
 
-    switch (format)
+    wined3d_resource_get_desc(wined3d_surface_get_resource(wined3d_surface), &desc);
+    switch (d3dformat_from_wined3dformat(desc.format))
     {
         case D3DFMT_A8R8G8B8:
         case D3DFMT_X8R8G8B8:
@@ -412,28 +415,12 @@ HRESULT surface_init(struct d3d9_surface *surface, struct d3d9_device *device, U
             break;
     }
 
-    /* FIXME: Check MAX bounds of MultisampleQuality. */
-    if (multisample_quality > 0)
-    {
-        FIXME("Multisample quality set to %u, substituting 0.\n", multisample_quality);
-        multisample_quality = 0;
-    }
-
-    wined3d_mutex_lock();
-    hr = wined3d_surface_create(device->wined3d_device, width, height, wined3dformat_from_d3dformat(format),
-            usage & WINED3DUSAGE_MASK, (enum wined3d_pool)pool, multisample_type, multisample_quality,
-            flags, surface, &d3d9_surface_wined3d_parent_ops, &surface->wined3d_surface);
-    wined3d_mutex_unlock();
-    if (FAILED(hr))
-    {
-        WARN("Failed to create wined3d surface, hr %#x.\n", hr);
-        return hr;
-    }
-
+    wined3d_surface_incref(wined3d_surface);
+    surface->wined3d_surface = wined3d_surface;
     surface->parent_device = &device->IDirect3DDevice9Ex_iface;
     IDirect3DDevice9Ex_AddRef(surface->parent_device);
 
-    return D3D_OK;
+    *parent_ops = &d3d9_surface_wined3d_parent_ops;
 }
 
 struct d3d9_surface *unsafe_impl_from_IDirect3DSurface9(IDirect3DSurface9 *iface)
index c1be78f..f5ec383 100644 (file)
 
 #include "d3d9_private.h"
 
-static inline struct d3d9_swapchain *impl_from_IDirect3DSwapChain9(IDirect3DSwapChain9 *iface)
+static inline struct d3d9_swapchain *impl_from_IDirect3DSwapChain9Ex(IDirect3DSwapChain9Ex *iface)
 {
-    return CONTAINING_RECORD(iface, struct d3d9_swapchain, IDirect3DSwapChain9_iface);
+    return CONTAINING_RECORD(iface, struct d3d9_swapchain, IDirect3DSwapChain9Ex_iface);
 }
 
-static HRESULT WINAPI d3d9_swapchain_QueryInterface(IDirect3DSwapChain9 *iface, REFIID riid, void **out)
+static HRESULT WINAPI d3d9_swapchain_QueryInterface(IDirect3DSwapChain9Ex *iface, REFIID riid, void **out)
 {
     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
 
     if (IsEqualGUID(riid, &IID_IDirect3DSwapChain9)
             || IsEqualGUID(riid, &IID_IUnknown))
     {
-        IDirect3DSwapChain9_AddRef(iface);
+        IDirect3DSwapChain9Ex_AddRef(iface);
+        *out = iface;
+        return S_OK;
+    }
+
+    if (IsEqualGUID(riid, &IID_IDirect3DSwapChain9Ex))
+    {
+        struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9Ex(iface);
+        struct d3d9_device *device       = impl_from_IDirect3DDevice9Ex(swapchain->parent_device);
+
+        /* Find out if the creating d3d9 interface was created with Direct3DCreate9Ex.
+         * It doesn't matter with which function the device was created. */
+        if (!device->d3d_parent->extended)
+        {
+            WARN("IDirect3D9 instance wasn't created with CreateDirect3D9Ex, returning E_NOINTERFACE.\n");
+            *out = NULL;
+            return E_NOINTERFACE;
+        }
+
+        IDirect3DSwapChain9Ex_AddRef(iface);
         *out = iface;
         return S_OK;
     }
@@ -45,9 +64,9 @@ static HRESULT WINAPI d3d9_swapchain_QueryInterface(IDirect3DSwapChain9 *iface,
     return E_NOINTERFACE;
 }
 
-static ULONG WINAPI d3d9_swapchain_AddRef(IDirect3DSwapChain9 *iface)
+static ULONG WINAPI d3d9_swapchain_AddRef(IDirect3DSwapChain9Ex *iface)
 {
-    struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9(iface);
+    struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9Ex(iface);
     ULONG refcount = InterlockedIncrement(&swapchain->refcount);
 
     TRACE("%p increasing refcount to %u.\n", iface, refcount);
@@ -65,9 +84,9 @@ static ULONG WINAPI d3d9_swapchain_AddRef(IDirect3DSwapChain9 *iface)
     return refcount;
 }
 
-static ULONG WINAPI d3d9_swapchain_Release(IDirect3DSwapChain9 *iface)
+static ULONG WINAPI d3d9_swapchain_Release(IDirect3DSwapChain9Ex *iface)
 {
-    struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9(iface);
+    struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9Ex(iface);
     ULONG refcount = InterlockedDecrement(&swapchain->refcount);
 
     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
@@ -88,11 +107,11 @@ static ULONG WINAPI d3d9_swapchain_Release(IDirect3DSwapChain9 *iface)
     return refcount;
 }
 
-static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_swapchain_Present(IDirect3DSwapChain9 *iface,
+static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_swapchain_Present(IDirect3DSwapChain9Ex *iface,
         const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override,
         const RGNDATA *dirty_region, DWORD flags)
 {
-    struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9(iface);
+    struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9Ex(iface);
     HRESULT hr;
 
     TRACE("iface %p, src_rect %s, dst_rect %s, dst_window_override %p, dirty_region %p, flags %#x.\n",
@@ -107,9 +126,9 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_swapchain_Present(IDirect3DSwapChai
     return hr;
 }
 
-static HRESULT WINAPI d3d9_swapchain_GetFrontBufferData(IDirect3DSwapChain9 *iface, IDirect3DSurface9 *surface)
+static HRESULT WINAPI d3d9_swapchain_GetFrontBufferData(IDirect3DSwapChain9Ex *iface, IDirect3DSurface9 *surface)
 {
-    struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9(iface);
+    struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9Ex(iface);
     struct d3d9_surface *dst = unsafe_impl_from_IDirect3DSurface9(surface);
     HRESULT hr;
 
@@ -122,10 +141,10 @@ static HRESULT WINAPI d3d9_swapchain_GetFrontBufferData(IDirect3DSwapChain9 *ifa
     return hr;
 }
 
-static HRESULT WINAPI d3d9_swapchain_GetBackBuffer(IDirect3DSwapChain9 *iface,
+static HRESULT WINAPI d3d9_swapchain_GetBackBuffer(IDirect3DSwapChain9Ex *iface,
         UINT backbuffer_idx, D3DBACKBUFFER_TYPE backbuffer_type, IDirect3DSurface9 **backbuffer)
 {
-    struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9(iface);
+    struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9Ex(iface);
     struct wined3d_surface *wined3d_surface = NULL;
     struct d3d9_surface *surface_impl;
     HRESULT hr = D3D_OK;
@@ -150,9 +169,9 @@ static HRESULT WINAPI d3d9_swapchain_GetBackBuffer(IDirect3DSwapChain9 *iface,
     return hr;
 }
 
-static HRESULT WINAPI d3d9_swapchain_GetRasterStatus(IDirect3DSwapChain9 *iface, D3DRASTER_STATUS *raster_status)
+static HRESULT WINAPI d3d9_swapchain_GetRasterStatus(IDirect3DSwapChain9Ex *iface, D3DRASTER_STATUS *raster_status)
 {
-    struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9(iface);
+    struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9Ex(iface);
     HRESULT hr;
 
     TRACE("iface %p, raster_status %p.\n", iface, raster_status);
@@ -165,9 +184,9 @@ static HRESULT WINAPI d3d9_swapchain_GetRasterStatus(IDirect3DSwapChain9 *iface,
     return hr;
 }
 
-static HRESULT WINAPI d3d9_swapchain_GetDisplayMode(IDirect3DSwapChain9 *iface, D3DDISPLAYMODE *mode)
+static HRESULT WINAPI d3d9_swapchain_GetDisplayMode(IDirect3DSwapChain9Ex *iface, D3DDISPLAYMODE *mode)
 {
-    struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9(iface);
+    struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9Ex(iface);
     struct wined3d_display_mode wined3d_mode;
     HRESULT hr;
 
@@ -188,9 +207,9 @@ static HRESULT WINAPI d3d9_swapchain_GetDisplayMode(IDirect3DSwapChain9 *iface,
     return hr;
 }
 
-static HRESULT WINAPI d3d9_swapchain_GetDevice(IDirect3DSwapChain9 *iface, IDirect3DDevice9 **device)
+static HRESULT WINAPI d3d9_swapchain_GetDevice(IDirect3DSwapChain9Ex *iface, IDirect3DDevice9 **device)
 {
-    struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9(iface);
+    struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9Ex(iface);
 
     TRACE("iface %p, device %p.\n", iface, device);
 
@@ -202,10 +221,10 @@ static HRESULT WINAPI d3d9_swapchain_GetDevice(IDirect3DSwapChain9 *iface, IDire
     return D3D_OK;
 }
 
-static HRESULT WINAPI d3d9_swapchain_GetPresentParameters(IDirect3DSwapChain9 *iface,
+static HRESULT WINAPI d3d9_swapchain_GetPresentParameters(IDirect3DSwapChain9Ex *iface,
         D3DPRESENT_PARAMETERS *parameters)
 {
-    struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9(iface);
+    struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9Ex(iface);
     struct wined3d_swapchain_desc desc;
 
     TRACE("iface %p, parameters %p.\n", iface, parameters);
@@ -218,12 +237,64 @@ static HRESULT WINAPI d3d9_swapchain_GetPresentParameters(IDirect3DSwapChain9 *i
     return D3D_OK;
 }
 
+static HRESULT WINAPI d3d9_swapchain_GetLastPresentCount(IDirect3DSwapChain9Ex *iface,
+        UINT *last_present_count)
+{
+    FIXME("iface %p, last_present_count %p, stub!\n", iface, last_present_count);
+
+    if (last_present_count)
+        *last_present_count = 0;
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_swapchain_GetPresentStatistics(IDirect3DSwapChain9Ex *iface,
+        D3DPRESENTSTATS *present_stats)
+{
+    FIXME("iface %p, present_stats %p, stub!\n", iface, present_stats);
+
+    if (present_stats)
+        memset(present_stats, 0, sizeof(*present_stats));
+
+    return D3D_OK;
+}
+
+static HRESULT WINAPI d3d9_swapchain_GetDisplayModeEx(IDirect3DSwapChain9Ex *iface,
+        D3DDISPLAYMODEEX *mode, D3DDISPLAYROTATION *rotation)
+{
+    struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9Ex(iface);
+    struct wined3d_display_mode wined3d_mode;
+    HRESULT hr;
+
+    TRACE("iface %p, mode %p, rotation %p.\n", iface, mode, rotation);
+
+    if (mode->Size != sizeof(*mode))
+        return D3DERR_INVALIDCALL;
+
+    wined3d_mutex_lock();
+    hr = wined3d_swapchain_get_display_mode(swapchain->wined3d_swapchain, &wined3d_mode,
+            (enum wined3d_display_rotation *)rotation);
+    wined3d_mutex_unlock();
+
+    if (SUCCEEDED(hr))
+    {
+        mode->Width = wined3d_mode.width;
+        mode->Height = wined3d_mode.height;
+        mode->RefreshRate = wined3d_mode.refresh_rate;
+        mode->Format = d3dformat_from_wined3dformat(wined3d_mode.format_id);
+        mode->ScanLineOrdering = wined3d_mode.scanline_ordering;
+    }
+
+    return hr;
+}
 
-static const struct IDirect3DSwapChain9Vtbl d3d9_swapchain_vtbl =
+static const struct IDirect3DSwapChain9ExVtbl d3d9_swapchain_vtbl =
 {
+    /* IUnknown */
     d3d9_swapchain_QueryInterface,
     d3d9_swapchain_AddRef,
     d3d9_swapchain_Release,
+    /* IDirect3DSwapChain9 */
     d3d9_swapchain_Present,
     d3d9_swapchain_GetFrontBufferData,
     d3d9_swapchain_GetBackBuffer,
@@ -231,6 +302,10 @@ static const struct IDirect3DSwapChain9Vtbl d3d9_swapchain_vtbl =
     d3d9_swapchain_GetDisplayMode,
     d3d9_swapchain_GetDevice,
     d3d9_swapchain_GetPresentParameters,
+    /* IDirect3DSwapChain9Ex */
+    d3d9_swapchain_GetLastPresentCount,
+    d3d9_swapchain_GetPresentStatistics,
+    d3d9_swapchain_GetDisplayModeEx
 };
 
 static void STDMETHODCALLTYPE d3d9_swapchain_wined3d_object_released(void *parent)
@@ -249,7 +324,7 @@ static HRESULT swapchain_init(struct d3d9_swapchain *swapchain, struct d3d9_devi
     HRESULT hr;
 
     swapchain->refcount = 1;
-    swapchain->IDirect3DSwapChain9_iface.lpVtbl = &d3d9_swapchain_vtbl;
+    swapchain->IDirect3DSwapChain9Ex_iface.lpVtbl = &d3d9_swapchain_vtbl;
 
     wined3d_mutex_lock();
     hr = wined3d_swapchain_create(device->wined3d_device, desc, swapchain,
index 74ff5d9..2cddc57 100644 (file)
@@ -1318,6 +1318,7 @@ HRESULT texture_init(struct d3d9_texture *texture, struct d3d9_device *device,
     desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
     desc.multisample_quality = 0;
     desc.usage = usage & WINED3DUSAGE_MASK;
+    desc.usage |= WINED3DUSAGE_TEXTURE;
     desc.pool = pool;
     desc.width = width;
     desc.height = height;
@@ -1328,7 +1329,7 @@ HRESULT texture_init(struct d3d9_texture *texture, struct d3d9_device *device,
         surface_flags |= WINED3D_SURFACE_MAPPABLE;
 
     wined3d_mutex_lock();
-    hr = wined3d_texture_create_2d(device->wined3d_device, &desc, levels, surface_flags,
+    hr = wined3d_texture_create(device->wined3d_device, &desc, levels, surface_flags,
             texture, &d3d9_texture_wined3d_parent_ops, &texture->wined3d_texture);
     wined3d_mutex_unlock();
     if (FAILED(hr))
@@ -1358,6 +1359,7 @@ HRESULT cubetexture_init(struct d3d9_texture *texture, struct d3d9_device *devic
     desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
     desc.multisample_quality = 0;
     desc.usage = usage & WINED3DUSAGE_MASK;
+    desc.usage |= WINED3DUSAGE_TEXTURE;
     desc.pool = pool;
     desc.width = edge_length;
     desc.height = edge_length;
@@ -1368,7 +1370,7 @@ HRESULT cubetexture_init(struct d3d9_texture *texture, struct d3d9_device *devic
         surface_flags |= WINED3D_SURFACE_MAPPABLE;
 
     wined3d_mutex_lock();
-    hr = wined3d_texture_create_cube(device->wined3d_device, &desc, levels, surface_flags,
+    hr = wined3d_texture_create(device->wined3d_device, &desc, levels, surface_flags,
             texture, &d3d9_texture_wined3d_parent_ops, &texture->wined3d_texture);
     wined3d_mutex_unlock();
     if (FAILED(hr))
@@ -1397,6 +1399,7 @@ HRESULT volumetexture_init(struct d3d9_texture *texture, struct d3d9_device *dev
     desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
     desc.multisample_quality = 0;
     desc.usage = usage & WINED3DUSAGE_MASK;
+    desc.usage |= WINED3DUSAGE_TEXTURE;
     desc.pool = pool;
     desc.width = width;
     desc.height = height;
@@ -1404,7 +1407,7 @@ HRESULT volumetexture_init(struct d3d9_texture *texture, struct d3d9_device *dev
     desc.size = 0;
 
     wined3d_mutex_lock();
-    hr = wined3d_texture_create_3d(device->wined3d_device, &desc, levels,
+    hr = wined3d_texture_create(device->wined3d_device, &desc, levels, 0,
             texture, &d3d9_texture_wined3d_parent_ops, &texture->wined3d_texture);
     wined3d_mutex_unlock();
     if (FAILED(hr))
index ef54a56..b0a6290 100644 (file)
@@ -271,22 +271,13 @@ static const struct wined3d_parent_ops d3d9_volume_wined3d_parent_ops =
     volume_wined3d_object_destroyed,
 };
 
-HRESULT volume_init(struct d3d9_volume *volume, struct d3d9_device *device, UINT width, UINT height,
-        UINT depth, UINT level, DWORD usage, enum wined3d_format_id format, enum wined3d_pool pool)
+void volume_init(struct d3d9_volume *volume, struct wined3d_volume *wined3d_volume,
+        const struct wined3d_parent_ops **parent_ops)
 {
-    HRESULT hr;
-
     volume->IDirect3DVolume9_iface.lpVtbl = &d3d9_volume_vtbl;
     volume->refcount = 1;
+    wined3d_volume_incref(wined3d_volume);
+    volume->wined3d_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);
-        return hr;
-    }
-
-    return D3D_OK;
+    *parent_ops = &d3d9_volume_wined3d_parent_ops;
 }
index 19f8756..5872db0 100644 (file)
@@ -32,7 +32,7 @@ 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)
+add_importlibs(ddraw advapi32 gdi32 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 e1587a4..272e109 100644 (file)
@@ -773,21 +773,29 @@ static HRESULT ddraw_set_cooperative_level(struct ddraw *ddraw, HWND window,
 
     wined3d_mutex_lock();
 
+    if (ddraw->flags & DDRAW_SCL_RECURSIVE)
+    {
+        WARN("Recursive call, returning DD_OK.\n");
+        hr = DD_OK;
+        goto done;
+    }
+    ddraw->flags |= DDRAW_SCL_RECURSIVE;
+
     /* Tests suggest that we need one of them: */
     if(!(cooplevel & (DDSCL_SETFOCUSWINDOW |
                       DDSCL_NORMAL         |
                       DDSCL_EXCLUSIVE      )))
     {
         TRACE("Incorrect cooplevel flags, returning DDERR_INVALIDPARAMS\n");
-        wined3d_mutex_unlock();
-        return DDERR_INVALIDPARAMS;
+        hr = DDERR_INVALIDPARAMS;
+        goto done;
     }
 
     if ((cooplevel & DDSCL_CREATEDEVICEWINDOW) && !(cooplevel & DDSCL_EXCLUSIVE))
     {
         WARN("DDSCL_CREATEDEVICEWINDOW requires DDSCL_EXCLUSIVE.\n");
-        wined3d_mutex_unlock();
-        return DDERR_INVALIDPARAMS;
+        hr = DDERR_INVALIDPARAMS;
+        goto done;
     }
 
     /* Handle those levels first which set various hwnds */
@@ -805,13 +813,12 @@ static HRESULT ddraw_set_cooperative_level(struct ddraw *ddraw, HWND window,
                 | DDSCL_FULLSCREEN))
         {
             WARN("Called with incompatible flags, returning DDERR_INVALIDPARAMS.\n");
-            wined3d_mutex_unlock();
-            return DDERR_INVALIDPARAMS;
+            hr = DDERR_INVALIDPARAMS;
+            goto done;
         }
 
         hr = ddraw_set_focus_window(ddraw, window);
-        wined3d_mutex_unlock();
-        return hr;
+        goto done;
     }
 
     if (cooplevel & DDSCL_EXCLUSIVE)
@@ -819,8 +826,8 @@ static HRESULT ddraw_set_cooperative_level(struct ddraw *ddraw, HWND window,
         if (!(cooplevel & DDSCL_FULLSCREEN) || !(window || (cooplevel & DDSCL_CREATEDEVICEWINDOW)))
         {
             WARN("DDSCL_EXCLUSIVE requires DDSCL_FULLSCREEN and a window.\n");
-            wined3d_mutex_unlock();
-            return DDERR_INVALIDPARAMS;
+            hr = DDERR_INVALIDPARAMS;
+            goto done;
         }
 
         if (cooplevel & DDSCL_CREATEDEVICEWINDOW)
@@ -830,8 +837,8 @@ static HRESULT ddraw_set_cooperative_level(struct ddraw *ddraw, HWND window,
             if (!ddraw->focuswindow && !(cooplevel & DDSCL_SETFOCUSWINDOW))
             {
                 WARN("No focus window set.\n");
-                wined3d_mutex_unlock();
-                return DDERR_NOFOCUSWINDOW;
+                hr = DDERR_NOFOCUSWINDOW;
+                goto done;
             }
 
             device_window = CreateWindowExA(0, DDRAW_WINDOW_CLASS_NAME, "DirectDrawDeviceWnd",
@@ -840,8 +847,8 @@ static HRESULT ddraw_set_cooperative_level(struct ddraw *ddraw, HWND window,
             if (!device_window)
             {
                 ERR("Failed to create window, last error %#x.\n", GetLastError());
-                wined3d_mutex_unlock();
-                return E_FAIL;
+                hr = E_FAIL;
+                goto done;
             }
 
             ShowWindow(device_window, SW_SHOW);
@@ -856,15 +863,12 @@ static HRESULT ddraw_set_cooperative_level(struct ddraw *ddraw, HWND window,
             {
                 if (!window)
                 {
-                    wined3d_mutex_unlock();
-                    return DDERR_NOHWND;
+                    hr = DDERR_NOHWND;
+                    goto done;
                 }
 
                 if (FAILED(hr = ddraw_set_focus_window(ddraw, window)))
-                {
-                    wined3d_mutex_unlock();
-                    return hr;
-                }
+                    goto done;
             }
 
             window = device_window;
@@ -905,8 +909,7 @@ static HRESULT ddraw_set_cooperative_level(struct ddraw *ddraw, HWND window,
             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();
-                return hr;
+                goto done;
             }
 
             wined3d_stateblock_capture(stateblock);
@@ -963,8 +966,7 @@ static HRESULT ddraw_set_cooperative_level(struct ddraw *ddraw, HWND window,
         if (FAILED(hr))
         {
             ERR("Failed to acquire focus window, hr %#x.\n", hr);
-            wined3d_mutex_unlock();
-            return hr;
+            goto done;
         }
     }
 
@@ -986,9 +988,12 @@ static HRESULT ddraw_set_cooperative_level(struct ddraw *ddraw, HWND window,
     ddraw->dest_window = window;
 
     TRACE("SetCooperativeLevel retuning DD_OK\n");
+    hr = DD_OK;
+done:
+    ddraw->flags &= ~DDRAW_SCL_RECURSIVE;
     wined3d_mutex_unlock();
 
-    return DD_OK;
+    return hr;
 }
 
 static HRESULT WINAPI ddraw7_SetCooperativeLevel(IDirectDraw7 *iface, HWND window, DWORD flags)
@@ -1155,6 +1160,269 @@ static HRESULT WINAPI ddraw1_SetDisplayMode(IDirectDraw *iface, DWORD width, DWO
     return ddraw7_SetDisplayMode(&ddraw->IDirectDraw7_iface, width, height, bpp, 0, 0);
 }
 
+void ddraw_d3dcaps1_from_7(D3DDEVICEDESC *caps1, D3DDEVICEDESC7 *caps7)
+{
+    memset(caps1, 0, sizeof(*caps1));
+    caps1->dwSize = sizeof(*caps1);
+    caps1->dwFlags = D3DDD_COLORMODEL
+            | D3DDD_DEVCAPS
+            | D3DDD_TRANSFORMCAPS
+            | D3DDD_BCLIPPING
+            | D3DDD_LIGHTINGCAPS
+            | D3DDD_LINECAPS
+            | D3DDD_TRICAPS
+            | D3DDD_DEVICERENDERBITDEPTH
+            | D3DDD_DEVICEZBUFFERBITDEPTH
+            | D3DDD_MAXBUFFERSIZE
+            | D3DDD_MAXVERTEXCOUNT;
+    caps1->dcmColorModel = D3DCOLOR_RGB;
+    caps1->dwDevCaps = caps7->dwDevCaps;
+    caps1->dtcTransformCaps.dwSize = sizeof(caps1->dtcTransformCaps);
+    caps1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
+    caps1->bClipping = TRUE;
+    caps1->dlcLightingCaps.dwSize = sizeof(caps1->dlcLightingCaps);
+    caps1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL
+            | D3DLIGHTCAPS_PARALLELPOINT
+            | D3DLIGHTCAPS_POINT
+            | D3DLIGHTCAPS_SPOT;
+    caps1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
+    caps1->dlcLightingCaps.dwNumLights = caps7->dwMaxActiveLights;
+    caps1->dpcLineCaps = caps7->dpcLineCaps;
+    caps1->dpcTriCaps = caps7->dpcTriCaps;
+    caps1->dwDeviceRenderBitDepth = caps7->dwDeviceRenderBitDepth;
+    caps1->dwDeviceZBufferBitDepth = caps7->dwDeviceZBufferBitDepth;
+    caps1->dwMaxBufferSize = 0;
+    caps1->dwMaxVertexCount = 65536;
+    caps1->dwMinTextureWidth  = caps7->dwMinTextureWidth;
+    caps1->dwMinTextureHeight = caps7->dwMinTextureHeight;
+    caps1->dwMaxTextureWidth  = caps7->dwMaxTextureWidth;
+    caps1->dwMaxTextureHeight = caps7->dwMaxTextureHeight;
+    caps1->dwMinStippleWidth  = 1;
+    caps1->dwMinStippleHeight = 1;
+    caps1->dwMaxStippleWidth  = 32;
+    caps1->dwMaxStippleHeight = 32;
+    caps1->dwMaxTextureRepeat = caps7->dwMaxTextureRepeat;
+    caps1->dwMaxTextureAspectRatio = caps7->dwMaxTextureAspectRatio;
+    caps1->dwMaxAnisotropy = caps7->dwMaxAnisotropy;
+    caps1->dvGuardBandLeft = caps7->dvGuardBandLeft;
+    caps1->dvGuardBandTop = caps7->dvGuardBandTop;
+    caps1->dvGuardBandRight = caps7->dvGuardBandRight;
+    caps1->dvGuardBandBottom = caps7->dvGuardBandBottom;
+    caps1->dvExtentsAdjust = caps7->dvExtentsAdjust;
+    caps1->dwStencilCaps = caps7->dwStencilCaps;
+    caps1->dwFVFCaps = caps7->dwFVFCaps;
+    caps1->dwTextureOpCaps = caps7->dwTextureOpCaps;
+    caps1->wMaxTextureBlendStages = caps7->wMaxTextureBlendStages;
+    caps1->wMaxSimultaneousTextures = caps7->wMaxSimultaneousTextures;
+}
+
+HRESULT ddraw_get_d3dcaps(const struct ddraw *ddraw, D3DDEVICEDESC7 *caps)
+{
+    WINED3DCAPS wined3d_caps;
+    HRESULT hr;
+
+    TRACE("ddraw %p, caps %p.\n", ddraw, caps);
+
+    memset(&wined3d_caps, 0, sizeof(wined3d_caps));
+
+    wined3d_mutex_lock();
+    hr = wined3d_get_device_caps(ddraw->wined3d, 0, WINED3D_DEVICE_TYPE_HAL, &wined3d_caps);
+    wined3d_mutex_unlock();
+    if (FAILED(hr))
+    {
+        WARN("Failed to get device caps, hr %#x.\n", hr);
+        return hr;
+    }
+
+    caps->dwDevCaps = wined3d_caps.DevCaps;
+    caps->dpcLineCaps.dwMiscCaps = wined3d_caps.PrimitiveMiscCaps;
+    caps->dpcLineCaps.dwRasterCaps = wined3d_caps.RasterCaps;
+    caps->dpcLineCaps.dwZCmpCaps = wined3d_caps.ZCmpCaps;
+    caps->dpcLineCaps.dwSrcBlendCaps = wined3d_caps.SrcBlendCaps;
+    caps->dpcLineCaps.dwDestBlendCaps = wined3d_caps.DestBlendCaps;
+    caps->dpcLineCaps.dwAlphaCmpCaps = wined3d_caps.AlphaCmpCaps;
+    caps->dpcLineCaps.dwShadeCaps = wined3d_caps.ShadeCaps;
+    caps->dpcLineCaps.dwTextureCaps = wined3d_caps.TextureCaps;
+    caps->dpcLineCaps.dwTextureFilterCaps = wined3d_caps.TextureFilterCaps;
+    caps->dpcLineCaps.dwTextureAddressCaps = wined3d_caps.TextureAddressCaps;
+
+    caps->dwMaxTextureWidth = wined3d_caps.MaxTextureWidth;
+    caps->dwMaxTextureHeight = wined3d_caps.MaxTextureHeight;
+
+    caps->dwMaxTextureRepeat = wined3d_caps.MaxTextureRepeat;
+    caps->dwMaxTextureAspectRatio = wined3d_caps.MaxTextureAspectRatio;
+    caps->dwMaxAnisotropy = wined3d_caps.MaxAnisotropy;
+    caps->dvMaxVertexW = wined3d_caps.MaxVertexW;
+
+    caps->dvGuardBandLeft = wined3d_caps.GuardBandLeft;
+    caps->dvGuardBandTop = wined3d_caps.GuardBandTop;
+    caps->dvGuardBandRight = wined3d_caps.GuardBandRight;
+    caps->dvGuardBandBottom = wined3d_caps.GuardBandBottom;
+
+    caps->dvExtentsAdjust = wined3d_caps.ExtentsAdjust;
+    caps->dwStencilCaps = wined3d_caps.StencilCaps;
+
+    caps->dwFVFCaps = wined3d_caps.FVFCaps;
+    caps->dwTextureOpCaps = wined3d_caps.TextureOpCaps;
+
+    caps->dwVertexProcessingCaps = wined3d_caps.VertexProcessingCaps;
+    caps->dwMaxActiveLights = wined3d_caps.MaxActiveLights;
+
+    /* Remove all non-d3d7 caps */
+    caps->dwDevCaps &= (
+        D3DDEVCAPS_FLOATTLVERTEX         | D3DDEVCAPS_SORTINCREASINGZ          | D3DDEVCAPS_SORTDECREASINGZ          |
+        D3DDEVCAPS_SORTEXACT             | D3DDEVCAPS_EXECUTESYSTEMMEMORY      | D3DDEVCAPS_EXECUTEVIDEOMEMORY       |
+        D3DDEVCAPS_TLVERTEXSYSTEMMEMORY  | D3DDEVCAPS_TLVERTEXVIDEOMEMORY      | D3DDEVCAPS_TEXTURESYSTEMMEMORY      |
+        D3DDEVCAPS_TEXTUREVIDEOMEMORY    | D3DDEVCAPS_DRAWPRIMTLVERTEX         | D3DDEVCAPS_CANRENDERAFTERFLIP       |
+        D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_DRAWPRIMITIVES2          | D3DDEVCAPS_SEPARATETEXTUREMEMORIES  |
+        D3DDEVCAPS_DRAWPRIMITIVES2EX     | D3DDEVCAPS_HWTRANSFORMANDLIGHT      | D3DDEVCAPS_CANBLTSYSTONONLOCAL      |
+        D3DDEVCAPS_HWRASTERIZATION);
+
+    caps->dwStencilCaps &= (
+        D3DSTENCILCAPS_KEEP              | D3DSTENCILCAPS_ZERO                 | D3DSTENCILCAPS_REPLACE              |
+        D3DSTENCILCAPS_INCRSAT           | D3DSTENCILCAPS_DECRSAT              | D3DSTENCILCAPS_INVERT               |
+        D3DSTENCILCAPS_INCR              | D3DSTENCILCAPS_DECR);
+
+    /* FVF caps ?*/
+
+    caps->dwTextureOpCaps &= (
+        D3DTEXOPCAPS_DISABLE             | D3DTEXOPCAPS_SELECTARG1             | D3DTEXOPCAPS_SELECTARG2             |
+        D3DTEXOPCAPS_MODULATE            | D3DTEXOPCAPS_MODULATE2X             | D3DTEXOPCAPS_MODULATE4X             |
+        D3DTEXOPCAPS_ADD                 | D3DTEXOPCAPS_ADDSIGNED              | D3DTEXOPCAPS_ADDSIGNED2X            |
+        D3DTEXOPCAPS_SUBTRACT            | D3DTEXOPCAPS_ADDSMOOTH              | D3DTEXOPCAPS_BLENDTEXTUREALPHA      |
+        D3DTEXOPCAPS_BLENDFACTORALPHA    | D3DTEXOPCAPS_BLENDTEXTUREALPHAPM    | D3DTEXOPCAPS_BLENDCURRENTALPHA      |
+        D3DTEXOPCAPS_PREMODULATE         | D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR | D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
+        D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR | D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA | D3DTEXOPCAPS_BUMPENVMAP    |
+        D3DTEXOPCAPS_BUMPENVMAPLUMINANCE | D3DTEXOPCAPS_DOTPRODUCT3);
+
+    caps->dwVertexProcessingCaps &= (
+        D3DVTXPCAPS_TEXGEN               | D3DVTXPCAPS_MATERIALSOURCE7         | D3DVTXPCAPS_VERTEXFOG               |
+        D3DVTXPCAPS_DIRECTIONALLIGHTS    | D3DVTXPCAPS_POSITIONALLIGHTS        | D3DVTXPCAPS_LOCALVIEWER);
+
+    caps->dpcLineCaps.dwMiscCaps &= (
+        D3DPMISCCAPS_MASKPLANES          | D3DPMISCCAPS_MASKZ                  | D3DPMISCCAPS_LINEPATTERNREP         |
+        D3DPMISCCAPS_CONFORMANT          | D3DPMISCCAPS_CULLNONE               | D3DPMISCCAPS_CULLCW                 |
+        D3DPMISCCAPS_CULLCCW);
+
+    caps->dpcLineCaps.dwRasterCaps &= (
+        D3DPRASTERCAPS_DITHER            | D3DPRASTERCAPS_ROP2                 | D3DPRASTERCAPS_XOR                  |
+        D3DPRASTERCAPS_PAT               | D3DPRASTERCAPS_ZTEST                | D3DPRASTERCAPS_SUBPIXEL             |
+        D3DPRASTERCAPS_SUBPIXELX         | D3DPRASTERCAPS_FOGVERTEX            | D3DPRASTERCAPS_FOGTABLE             |
+        D3DPRASTERCAPS_STIPPLE           | D3DPRASTERCAPS_ANTIALIASSORTDEPENDENT | D3DPRASTERCAPS_ANTIALIASSORTINDEPENDENT |
+        D3DPRASTERCAPS_ANTIALIASEDGES    | D3DPRASTERCAPS_MIPMAPLODBIAS        | D3DPRASTERCAPS_ZBIAS                |
+        D3DPRASTERCAPS_ZBUFFERLESSHSR    | D3DPRASTERCAPS_FOGRANGE             | D3DPRASTERCAPS_ANISOTROPY           |
+        D3DPRASTERCAPS_WBUFFER           | D3DPRASTERCAPS_TRANSLUCENTSORTINDEPENDENT | D3DPRASTERCAPS_WFOG           |
+        D3DPRASTERCAPS_ZFOG);
+
+    caps->dpcLineCaps.dwZCmpCaps &= (
+        D3DPCMPCAPS_NEVER                | D3DPCMPCAPS_LESS                    | D3DPCMPCAPS_EQUAL                   |
+        D3DPCMPCAPS_LESSEQUAL            | D3DPCMPCAPS_GREATER                 | D3DPCMPCAPS_NOTEQUAL                |
+        D3DPCMPCAPS_GREATEREQUAL         | D3DPCMPCAPS_ALWAYS);
+
+    caps->dpcLineCaps.dwSrcBlendCaps &= (
+        D3DPBLENDCAPS_ZERO               | D3DPBLENDCAPS_ONE                   | D3DPBLENDCAPS_SRCCOLOR              |
+        D3DPBLENDCAPS_INVSRCCOLOR        | D3DPBLENDCAPS_SRCALPHA              | D3DPBLENDCAPS_INVSRCALPHA           |
+        D3DPBLENDCAPS_DESTALPHA          | D3DPBLENDCAPS_INVDESTALPHA          | D3DPBLENDCAPS_DESTCOLOR             |
+        D3DPBLENDCAPS_INVDESTCOLOR       | D3DPBLENDCAPS_SRCALPHASAT           | D3DPBLENDCAPS_BOTHSRCALPHA          |
+        D3DPBLENDCAPS_BOTHINVSRCALPHA);
+
+    caps->dpcLineCaps.dwDestBlendCaps &= (
+        D3DPBLENDCAPS_ZERO               | D3DPBLENDCAPS_ONE                   | D3DPBLENDCAPS_SRCCOLOR              |
+        D3DPBLENDCAPS_INVSRCCOLOR        | D3DPBLENDCAPS_SRCALPHA              | D3DPBLENDCAPS_INVSRCALPHA           |
+        D3DPBLENDCAPS_DESTALPHA          | D3DPBLENDCAPS_INVDESTALPHA          | D3DPBLENDCAPS_DESTCOLOR             |
+        D3DPBLENDCAPS_INVDESTCOLOR       | D3DPBLENDCAPS_SRCALPHASAT           | D3DPBLENDCAPS_BOTHSRCALPHA          |
+        D3DPBLENDCAPS_BOTHINVSRCALPHA);
+
+    caps->dpcLineCaps.dwAlphaCmpCaps &= (
+        D3DPCMPCAPS_NEVER                | D3DPCMPCAPS_LESS                    | D3DPCMPCAPS_EQUAL                   |
+        D3DPCMPCAPS_LESSEQUAL            | D3DPCMPCAPS_GREATER                 | D3DPCMPCAPS_NOTEQUAL                |
+        D3DPCMPCAPS_GREATEREQUAL         | D3DPCMPCAPS_ALWAYS);
+
+    caps->dpcLineCaps.dwShadeCaps &= (
+        D3DPSHADECAPS_COLORFLATMONO      | D3DPSHADECAPS_COLORFLATRGB          | D3DPSHADECAPS_COLORGOURAUDMONO      |
+        D3DPSHADECAPS_COLORGOURAUDRGB    | D3DPSHADECAPS_COLORPHONGMONO        | D3DPSHADECAPS_COLORPHONGRGB         |
+        D3DPSHADECAPS_SPECULARFLATMONO   | D3DPSHADECAPS_SPECULARFLATRGB       | D3DPSHADECAPS_SPECULARGOURAUDMONO   |
+        D3DPSHADECAPS_SPECULARGOURAUDRGB | D3DPSHADECAPS_SPECULARPHONGMONO     | D3DPSHADECAPS_SPECULARPHONGRGB      |
+        D3DPSHADECAPS_ALPHAFLATBLEND     | D3DPSHADECAPS_ALPHAFLATSTIPPLED     | D3DPSHADECAPS_ALPHAGOURAUDBLEND     |
+        D3DPSHADECAPS_ALPHAGOURAUDSTIPPLED | D3DPSHADECAPS_ALPHAPHONGBLEND     | D3DPSHADECAPS_ALPHAPHONGSTIPPLED    |
+        D3DPSHADECAPS_FOGFLAT            | D3DPSHADECAPS_FOGGOURAUD            | D3DPSHADECAPS_FOGPHONG);
+
+    caps->dpcLineCaps.dwTextureCaps &= (
+        D3DPTEXTURECAPS_PERSPECTIVE      | D3DPTEXTURECAPS_POW2                | D3DPTEXTURECAPS_ALPHA               |
+        D3DPTEXTURECAPS_TRANSPARENCY     | D3DPTEXTURECAPS_BORDER              | D3DPTEXTURECAPS_SQUAREONLY          |
+        D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE | D3DPTEXTURECAPS_ALPHAPALETTE| D3DPTEXTURECAPS_NONPOW2CONDITIONAL  |
+        D3DPTEXTURECAPS_PROJECTED        | D3DPTEXTURECAPS_CUBEMAP             | D3DPTEXTURECAPS_COLORKEYBLEND);
+
+    caps->dpcLineCaps.dwTextureFilterCaps &= (
+        D3DPTFILTERCAPS_NEAREST          | D3DPTFILTERCAPS_LINEAR              | D3DPTFILTERCAPS_MIPNEAREST          |
+        D3DPTFILTERCAPS_MIPLINEAR        | D3DPTFILTERCAPS_LINEARMIPNEAREST    | D3DPTFILTERCAPS_LINEARMIPLINEAR     |
+        D3DPTFILTERCAPS_MINFPOINT        | D3DPTFILTERCAPS_MINFLINEAR          | D3DPTFILTERCAPS_MINFANISOTROPIC     |
+        D3DPTFILTERCAPS_MIPFPOINT        | D3DPTFILTERCAPS_MIPFLINEAR          | D3DPTFILTERCAPS_MAGFPOINT           |
+        D3DPTFILTERCAPS_MAGFLINEAR       | D3DPTFILTERCAPS_MAGFANISOTROPIC     | D3DPTFILTERCAPS_MAGFAFLATCUBIC      |
+        D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC);
+
+    caps->dpcLineCaps.dwTextureAddressCaps &= (
+        D3DPTADDRESSCAPS_WRAP            | D3DPTADDRESSCAPS_MIRROR             | D3DPTADDRESSCAPS_CLAMP              |
+        D3DPTADDRESSCAPS_BORDER          | D3DPTADDRESSCAPS_INDEPENDENTUV);
+
+    if (!(caps->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2))
+    {
+        /* DirectX7 always has the np2 flag set, no matter what the card
+         * supports. Some old games (Rollcage) check the caps incorrectly.
+         * If wined3d supports nonpow2 textures it also has np2 conditional
+         * support. */
+        caps->dpcLineCaps.dwTextureCaps |= D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL;
+    }
+
+    /* Fill the missing members, and do some fixup */
+    caps->dpcLineCaps.dwSize = sizeof(caps->dpcLineCaps);
+    caps->dpcLineCaps.dwTextureBlendCaps = D3DPTBLENDCAPS_ADD
+            | D3DPTBLENDCAPS_MODULATEMASK
+            | D3DPTBLENDCAPS_COPY
+            | D3DPTBLENDCAPS_DECAL
+            | D3DPTBLENDCAPS_DECALALPHA
+            | D3DPTBLENDCAPS_DECALMASK
+            | D3DPTBLENDCAPS_MODULATE
+            | D3DPTBLENDCAPS_MODULATEALPHA;
+    caps->dpcLineCaps.dwStippleWidth = 32;
+    caps->dpcLineCaps.dwStippleHeight = 32;
+    /* Use the same for the TriCaps */
+    caps->dpcTriCaps = caps->dpcLineCaps;
+
+    caps->dwDeviceRenderBitDepth = DDBD_16 | DDBD_24 | DDBD_32;
+    caps->dwDeviceZBufferBitDepth = DDBD_16 | DDBD_24;
+    caps->dwMinTextureWidth = 1;
+    caps->dwMinTextureHeight = 1;
+
+    /* Convert DWORDs safely to WORDs */
+    if (wined3d_caps.MaxTextureBlendStages > 0xffff)
+        caps->wMaxTextureBlendStages = 0xffff;
+    else
+        caps->wMaxTextureBlendStages = (WORD)wined3d_caps.MaxTextureBlendStages;
+    if (wined3d_caps.MaxSimultaneousTextures > 0xffff)
+        caps->wMaxSimultaneousTextures = 0xffff;
+    else
+        caps->wMaxSimultaneousTextures = (WORD)wined3d_caps.MaxSimultaneousTextures;
+
+    if (wined3d_caps.MaxUserClipPlanes > 0xffff)
+        caps->wMaxUserClipPlanes = 0xffff;
+    else
+        caps->wMaxUserClipPlanes = (WORD)wined3d_caps.MaxUserClipPlanes;
+    if (wined3d_caps.MaxVertexBlendMatrices > 0xffff)
+        caps->wMaxVertexBlendMatrices = 0xffff;
+    else
+        caps->wMaxVertexBlendMatrices = (WORD)wined3d_caps.MaxVertexBlendMatrices;
+
+    caps->deviceGUID = IID_IDirect3DTnLHalDevice;
+
+    caps->dwReserved1 = 0;
+    caps->dwReserved2 = 0;
+    caps->dwReserved3 = 0;
+    caps->dwReserved4 = 0;
+
+    return DD_OK;
+}
+
 /*****************************************************************************
  * IDirectDraw7::GetCaps
  *
@@ -1201,9 +1469,18 @@ static HRESULT WINAPI ddraw7_GetCaps(IDirectDraw7 *iface, DDCAPS *DriverCaps, DD
     }
 
     hr = IDirectDraw7_GetAvailableVidMem(iface, &ddscaps, &caps.dwVidMemTotal, &caps.dwVidMemFree);
-    wined3d_mutex_unlock();
-    if(FAILED(hr)) {
+    if (FAILED(hr))
+    {
         WARN("IDirectDraw7::GetAvailableVidMem failed\n");
+        wined3d_mutex_unlock();
+        return hr;
+    }
+
+    hr = IDirectDraw7_GetFourCCCodes(iface, &caps.dwNumFourCCCodes, NULL);
+    wined3d_mutex_unlock();
+    if (FAILED(hr))
+    {
+        WARN("IDirectDraw7::GetFourCCCodes failed\n");
         return hr;
     }
 
@@ -1211,7 +1488,7 @@ static HRESULT WINAPI ddraw7_GetCaps(IDirectDraw7 *iface, DDCAPS *DriverCaps, DD
     caps.dwCaps2 = winecaps.ddraw_caps.caps2;
     caps.dwCKeyCaps = winecaps.ddraw_caps.color_key_caps;
     caps.dwFXCaps = winecaps.ddraw_caps.fx_caps;
-    caps.dwPalCaps = winecaps.ddraw_caps.pal_caps;
+    caps.dwPalCaps = DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE;
     caps.ddsCaps.dwCaps = winecaps.ddraw_caps.dds_caps;
     caps.dwSVBCaps = winecaps.ddraw_caps.svb_caps;
     caps.dwSVBCKeyCaps = winecaps.ddraw_caps.svb_color_key_caps;
@@ -2379,488 +2656,74 @@ static HRESULT WINAPI ddraw4_GetSurfaceFromDC(IDirectDraw4 *iface, HDC dc,
 /*****************************************************************************
  * IDirectDraw7::RestoreAllSurfaces
  *
- * Calls the restore method of all surfaces
- *
- * Params:
- *
- * Returns:
- *  Always returns DD_OK because it's a stub
- *
- *****************************************************************************/
-static HRESULT WINAPI ddraw7_RestoreAllSurfaces(IDirectDraw7 *iface)
-{
-    FIXME("iface %p stub!\n", iface);
-
-    /* This isn't hard to implement: Enumerate all WineD3D surfaces,
-     * get their parent and call their restore method. Do not implement
-     * it in WineD3D, as restoring a surface means re-creating the
-     * WineD3DDSurface
-     */
-    return DD_OK;
-}
-
-static HRESULT WINAPI ddraw4_RestoreAllSurfaces(IDirectDraw4 *iface)
-{
-    struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
-
-    TRACE("iface %p.\n", iface);
-
-    return ddraw7_RestoreAllSurfaces(&ddraw->IDirectDraw7_iface);
-}
-
-/*****************************************************************************
- * IDirectDraw7::StartModeTest
- *
- * Tests the specified video modes to update the system registry with
- * refresh rate information. StartModeTest starts the mode test,
- * EvaluateMode is used to fail or pass a mode. If EvaluateMode
- * isn't called within 15 seconds, the mode is failed automatically
- *
- * As refresh rates are handled by the X server, I don't think this
- * Method is important
- *
- * Params:
- *  Modes: An array of mode specifications
- *  NumModes: The number of modes in Modes
- *  Flags: Some flags...
- *
- * Returns:
- *  Returns DDERR_TESTFINISHED if flags contains DDSMT_ISTESTREQUIRED,
- *  if no modes are passed, DDERR_INVALIDPARAMS is returned,
- *  otherwise DD_OK
- *
- *****************************************************************************/
-static HRESULT WINAPI ddraw7_StartModeTest(IDirectDraw7 *iface, SIZE *Modes, DWORD NumModes, DWORD Flags)
-{
-    FIXME("iface %p, modes %p, mode_count %u, flags %#x partial stub!\n",
-            iface, Modes, NumModes, Flags);
-
-    /* This looks sane */
-    if( (!Modes) || (NumModes == 0) ) return DDERR_INVALIDPARAMS;
-
-    /* DDSMT_ISTESTREQUIRED asks if a mode test is necessary.
-     * As it is not, DDERR_TESTFINISHED is returned
-     * (hopefully that's correct
-     *
-    if(Flags & DDSMT_ISTESTREQUIRED) return DDERR_TESTFINISHED;
-     * well, that value doesn't (yet) exist in the wine headers, so ignore it
-     */
-
-    return DD_OK;
-}
-
-/*****************************************************************************
- * ddraw_create_surface
- *
- * A helper function for IDirectDraw7::CreateSurface. It creates a new surface
- * with the passed parameters.
- *
- * Params:
- *  DDSD: Description of the surface to create
- *  Surf: Address to store the interface pointer at
- *
- * Returns:
- *  DD_OK on success
- *
- *****************************************************************************/
-static HRESULT ddraw_create_surface(struct ddraw *ddraw, DDSURFACEDESC2 *desc,
-        DWORD flags, struct ddraw_surface **surface, UINT version)
-{
-    HRESULT hr;
-
-    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(desc);
-    }
-
-    if ((desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) && (ddraw->flags & DDRAW_NO3D))
-    {
-        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. */
-    }
-
-    /* Create the Surface object */
-    *surface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(**surface));
-    if (!*surface)
-    {
-        ERR("Failed to allocate surface memory.\n");
-        return DDERR_OUTOFVIDEOMEMORY;
-    }
-
-    if (FAILED(hr = ddraw_surface_init(*surface, ddraw, desc, flags, version)))
-    {
-        WARN("Failed to initialize surface, hr %#x.\n", hr);
-        HeapFree(GetProcessHeap(), 0, *surface);
-        return hr;
-    }
-
-    /* Increase the surface counter, and attach the surface */
-    list_add_head(&ddraw->surface_list, &(*surface)->surface_list_entry);
-
-    TRACE("Created surface %p.\n", *surface);
-
-    return DD_OK;
-}
-
-static HRESULT CDECL ddraw_reset_enum_callback(struct wined3d_resource *resource)
-{
-    return DD_OK;
-}
-
-/*****************************************************************************
- * IDirectDraw7::CreateSurface
- *
- * Creates a new IDirectDrawSurface object and returns its interface.
- *
- * The surface connections with wined3d are a bit tricky. Basically it works
- * like this:
- *
- * |------------------------|               |-----------------|
- * | DDraw surface          |               | WineD3DSurface  |
- * |                        |               |                 |
- * |        WineD3DSurface  |-------------->|                 |
- * |        Child           |<------------->| Parent          |
- * |------------------------|               |-----------------|
- *
- * The DDraw surface is the parent of the wined3d surface, and it releases
- * the WineD3DSurface when the ddraw surface is destroyed.
- *
- * However, for all surfaces which can be in a container in WineD3D,
- * we have to do this. These surfaces are usually complex surfaces,
- * so this concerns primary surfaces with a front and a back buffer,
- * and textures.
- *
- * |------------------------|               |-----------------|
- * | DDraw surface          |               | Container       |
- * |                        |               |                 |
- * |                  Child |<------------->| Parent          |
- * |                Texture |<------------->|                 |
- * |         WineD3DSurface |<----|         |          Levels |<--|
- * | Complex connection     |     |         |                 |   |
- * |------------------------|     |         |-----------------|   |
- *  ^                             |                               |
- *  |                             |                               |
- *  |                             |                               |
- *  |    |------------------|     |         |-----------------|   |
- *  |    | IParent          |     |-------->| WineD3DSurface  |   |
- *  |    |                  |               |                 |   |
- *  |    |            Child |<------------->| Parent          |   |
- *  |    |                  |               |       Container |<--|
- *  |    |------------------|               |-----------------|   |
- *  |                                                             |
- *  |   |----------------------|                                  |
- *  |   | DDraw surface 2      |                                  |
- *  |   |                      |                                  |
- *  |<->| Complex root   Child |                                  |
- *  |   |              Texture |                                  |
- *  |   |       WineD3DSurface |<----|                            |
- *  |   |----------------------|     |                            |
- *  |                                |                            |
- *  |    |---------------------|     |      |-----------------|   |
- *  |    | IParent             |     |----->| WineD3DSurface  |   |
- *  |    |                     |            |                 |   |
- *  |    |               Child |<---------->| Parent          |   |
- *  |    |---------------------|            |       Container |<--|
- *  |                                       |-----------------|   |
- *  |                                                             |
- *  |             ---More surfaces can follow---                  |
- *
- * The reason is that the IWineD3DSwapchain(render target container)
- * and the IWineD3DTexure(Texture container) release the parents
- * of their surface's children, but by releasing the complex root
- * the surfaces which are complexly attached to it are destroyed
- * too. See IDirectDrawSurface::Release for a more detailed
- * explanation.
- *
- * Params:
- *  DDSD: Description of the surface to create
- *  Surf: Address to store the interface pointer at
- *  UnkOuter: Basically for aggregation support, but ddraw doesn't support
- *            aggregation, so it has to be NULL
- *
- * Returns:
- *  DD_OK on success
- *  CLASS_E_NOAGGREGATION if UnkOuter != NULL
- *  DDERR_* if an error occurs
- *
- *****************************************************************************/
-static HRESULT CreateSurface(struct ddraw *ddraw, DDSURFACEDESC2 *DDSD,
-        struct ddraw_surface **surface, IUnknown *UnkOuter, UINT version)
-{
-    struct ddraw_surface *object = NULL;
-    struct wined3d_display_mode mode;
-    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);
-
-    /* Some checks before we start */
-    if (TRACE_ON(ddraw))
-    {
-        TRACE(" (%p) Requesting surface desc :\n", ddraw);
-        DDRAW_dump_surface_desc(DDSD);
-    }
-
-    if (UnkOuter != NULL)
-    {
-        FIXME("(%p) : outer != NULL?\n", ddraw);
-        return CLASS_E_NOAGGREGATION; /* unchecked */
-    }
-
-    if (!surface)
-    {
-        FIXME("(%p) You want to get back a surface? Don't give NULL ptrs!\n", ddraw);
-        return E_POINTER; /* unchecked */
-    }
-
-    if (!(DDSD->dwFlags & DDSD_CAPS))
-    {
-        /* DVIDEO.DLL does forget the DDSD_CAPS flag ... *sigh* */
-        DDSD->dwFlags |= DDSD_CAPS;
-    }
-
-    if (DDSD->ddsCaps.dwCaps & DDSCAPS_ALLOCONLOAD)
-    {
-        /* If the surface is of the 'alloconload' type, ignore the LPSURFACE field */
-        DDSD->dwFlags &= ~DDSD_LPSURFACE;
-    }
-
-    if ((DDSD->dwFlags & DDSD_LPSURFACE) && (DDSD->lpSurface == NULL))
-    {
-        /* Frank Herbert's Dune specifies a null pointer for the surface, ignore the LPSURFACE field */
-        WARN("(%p) Null surface pointer specified, ignore it!\n", ddraw);
-        DDSD->dwFlags &= ~DDSD_LPSURFACE;
-    }
-
-    if((DDSD->ddsCaps.dwCaps & (DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE)) == (DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE) &&
-       !(ddraw->cooperative_level & DDSCL_EXCLUSIVE))
-    {
-        TRACE("(%p): Attempt to create a flipable primary surface without DDSCL_EXCLUSIVE set\n",
-                ddraw);
-        *surface = NULL;
-        return DDERR_NOEXCLUSIVEMODE;
-    }
-
-    if((DDSD->ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER | DDSCAPS_PRIMARYSURFACE)) == (DDSCAPS_BACKBUFFER | DDSCAPS_PRIMARYSURFACE))
-    {
-        WARN("Application wanted to create back buffer primary surface\n");
-        return DDERR_INVALIDCAPS;
-    }
-
-    if((DDSD->ddsCaps.dwCaps & sysvidmem) == sysvidmem)
-    {
-        /* This is a special switch in ddrawex.dll, but not allowed in ddraw.dll */
-        WARN("Application tries to put the surface in both system and video memory\n");
-        *surface = NULL;
-        return DDERR_INVALIDCAPS;
-    }
-
-    /* Check cube maps but only if the size includes them */
-    if (DDSD->dwSize >= sizeof(DDSURFACEDESC2))
-    {
-        if(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES &&
-           !(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
-        {
-            WARN("Cube map faces requested without cube map flag\n");
-            return DDERR_INVALIDCAPS;
-        }
-        if(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP &&
-           (DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) == 0)
-        {
-            WARN("Cube map without faces requested\n");
-            return DDERR_INVALIDPARAMS;
-        }
-
-        /* Quick tests confirm those can be created, but we don't do that yet */
-        if(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP &&
-           (DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) != DDSCAPS2_CUBEMAP_ALLFACES)
-        {
-            FIXME("Partial cube maps not supported yet\n");
-        }
-    }
-
-    /* According to the msdn this flag is ignored by CreateSurface */
-    if (DDSD->dwSize >= sizeof(DDSURFACEDESC2))
-        DDSD->ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
-
-    /* Modify some flags */
-    copy_to_surfacedesc2(&desc2, DDSD);
-    desc2.u4.ddpfPixelFormat.dwSize=sizeof(DDPIXELFORMAT); /* Just to be sure */
-
-    if (FAILED(hr = wined3d_get_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
-    {
-        ERR("Failed to get display mode, hr %#x.\n", hr);
-        return hr;
-    }
-
-    /* No pixelformat given? Use the current screen format */
-    if(!(desc2.dwFlags & DDSD_PIXELFORMAT))
-    {
-        desc2.dwFlags |= DDSD_PIXELFORMAT;
-        desc2.u4.ddpfPixelFormat.dwSize=sizeof(DDPIXELFORMAT);
-
-        ddrawformat_from_wined3dformat(&desc2.u4.ddpfPixelFormat, mode.format_id);
-    }
-
-    /* No Width or no Height? Use the original screen size
-     */
-    if(!(desc2.dwFlags & DDSD_WIDTH) ||
-       !(desc2.dwFlags & DDSD_HEIGHT) )
-    {
-        /* Invalid for non-render targets */
-        if(!(desc2.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
-        {
-            WARN("Creating a non-Primary surface without Width or Height info, returning DDERR_INVALIDPARAMS\n");
-            *surface = NULL;
-            return DDERR_INVALIDPARAMS;
-        }
-
-        desc2.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
-        desc2.dwWidth = mode.width;
-        desc2.dwHeight = mode.height;
-    }
-
-    if (!desc2.dwWidth || !desc2.dwHeight)
-        return DDERR_INVALIDPARAMS;
-
-    /* Mipmap count fixes */
-    if(desc2.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
-    {
-        if(desc2.ddsCaps.dwCaps & DDSCAPS_COMPLEX)
-        {
-            if(desc2.dwFlags & DDSD_MIPMAPCOUNT)
-            {
-                /* Mipmap count is given, should not be 0 */
-                if( desc2.u2.dwMipMapCount == 0 )
-                    return DDERR_INVALIDPARAMS;
-            }
-            else
-            {
-                /* Undocumented feature: Create sublevels until
-                 * either the width or the height is 1
-                 */
-                DWORD min = desc2.dwWidth < desc2.dwHeight ?
-                            desc2.dwWidth : desc2.dwHeight;
-                desc2.u2.dwMipMapCount = 0;
-                while( min )
-                {
-                    desc2.u2.dwMipMapCount += 1;
-                    min >>= 1;
-                }
-            }
-        }
-        else
-        {
-            /* Not-complex mipmap -> Mipmapcount = 1 */
-            desc2.u2.dwMipMapCount = 1;
-        }
-
-        /* There's a mipmap count in the created surface in any case */
-        desc2.dwFlags |= DDSD_MIPMAPCOUNT;
-    }
-    /* If no mipmap is given, the texture has only one level */
-
-    /* The first surface is a front buffer, the back buffer is created afterwards */
-    if( (desc2.dwFlags & DDSD_CAPS) && (desc2.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) )
-    {
-        desc2.ddsCaps.dwCaps |= DDSCAPS_FRONTBUFFER;
-    }
-
-    /* The root surface in a cube map is positive x */
-    if(desc2.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
-    {
-        desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES;
-        desc2.ddsCaps.dwCaps2 |=  DDSCAPS2_CUBEMAP_POSITIVEX;
-    }
-
-    if ((desc2.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) && (ddraw->cooperative_level & DDSCL_EXCLUSIVE))
-    {
-        struct wined3d_swapchain_desc swapchain_desc;
-
-        wined3d_swapchain_get_desc(ddraw->wined3d_swapchain, &swapchain_desc);
-        swapchain_desc.backbuffer_width = mode.width;
-        swapchain_desc.backbuffer_height = mode.height;
-        swapchain_desc.backbuffer_format = mode.format_id;
-
-        hr = wined3d_device_reset(ddraw->wined3d_device,
-                &swapchain_desc, NULL, ddraw_reset_enum_callback, TRUE);
-        if (FAILED(hr))
-        {
-            ERR("Failed to reset device.\n");
-            return hr;
-        }
-    }
-
-    /* Create the first surface */
-    if (FAILED(hr = ddraw_create_surface(ddraw, &desc2, flags, &object, version)))
-    {
-        WARN("ddraw_create_surface failed, hr %#x.\n", hr);
-        return hr;
-    }
-    object->is_complex_root = TRUE;
-
-    *surface = object;
+ * Calls the restore method of all surfaces
+ *
+ * Params:
+ *
+ * Returns:
+ *  Always returns DD_OK because it's a stub
+ *
+ *****************************************************************************/
+static HRESULT WINAPI ddraw7_RestoreAllSurfaces(IDirectDraw7 *iface)
+{
+    FIXME("iface %p stub!\n", iface);
 
-    /* Create Additional surfaces if necessary
-     * This applies to Primary surfaces which have a back buffer count
-     * set, but not to mipmap textures. In case of Mipmap textures,
-     * wineD3D takes care of the creation of additional surfaces
+    /* This isn't hard to implement: Enumerate all WineD3D surfaces,
+     * get their parent and call their restore method. Do not implement
+     * it in WineD3D, as restoring a surface means re-creating the
+     * WineD3DDSurface
      */
-    if(DDSD->dwFlags & DDSD_BACKBUFFERCOUNT)
-    {
-        struct ddraw_surface *last = object;
-        UINT i;
-
-        desc2.ddsCaps.dwCaps &= ~DDSCAPS_FRONTBUFFER; /* It's not a front buffer */
-        desc2.ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER;
-        desc2.u5.dwBackBufferCount = 0;
+    return DD_OK;
+}
 
-        for (i = 0; i < DDSD->u5.dwBackBufferCount; ++i)
-        {
-            struct ddraw_surface *object2 = NULL;
+static HRESULT WINAPI ddraw4_RestoreAllSurfaces(IDirectDraw4 *iface)
+{
+    struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
 
-            if (FAILED(hr = ddraw_create_surface(ddraw, &desc2, flags, &object2, version)))
-            {
-                if (version == 7)
-                    IDirectDrawSurface7_Release(&object->IDirectDrawSurface7_iface);
-                else if (version == 4)
-                    IDirectDrawSurface4_Release(&object->IDirectDrawSurface4_iface);
-                else
-                    IDirectDrawSurface_Release(&object->IDirectDrawSurface_iface);
-
-                return hr;
-            }
+    TRACE("iface %p.\n", iface);
 
-            /* Add the new surface to the complex attachment array. */
-            last->complex_array[0] = object2;
-            last = object2;
+    return ddraw7_RestoreAllSurfaces(&ddraw->IDirectDraw7_iface);
+}
 
-            /* Remove the (possible) back buffer cap from the new surface
-             * description, because only one surface in the flipping chain is a
-             * back buffer, one is a front buffer, the others are just primary
-             * surfaces. */
-            desc2.ddsCaps.dwCaps &= ~DDSCAPS_BACKBUFFER;
-        }
-    }
+/*****************************************************************************
+ * IDirectDraw7::StartModeTest
+ *
+ * Tests the specified video modes to update the system registry with
+ * refresh rate information. StartModeTest starts the mode test,
+ * EvaluateMode is used to fail or pass a mode. If EvaluateMode
+ * isn't called within 15 seconds, the mode is failed automatically
+ *
+ * As refresh rates are handled by the X server, I don't think this
+ * Method is important
+ *
+ * Params:
+ *  Modes: An array of mode specifications
+ *  NumModes: The number of modes in Modes
+ *  Flags: Some flags...
+ *
+ * Returns:
+ *  Returns DDERR_TESTFINISHED if flags contains DDSMT_ISTESTREQUIRED,
+ *  if no modes are passed, DDERR_INVALIDPARAMS is returned,
+ *  otherwise DD_OK
+ *
+ *****************************************************************************/
+static HRESULT WINAPI ddraw7_StartModeTest(IDirectDraw7 *iface, SIZE *Modes, DWORD NumModes, DWORD Flags)
+{
+    FIXME("iface %p, modes %p, mode_count %u, flags %#x partial stub!\n",
+            iface, Modes, NumModes, Flags);
 
-    if (desc2.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
-        ddraw->primary = object;
+    /* This looks sane */
+    if( (!Modes) || (NumModes == 0) ) return DDERR_INVALIDPARAMS;
 
-    /* Create a WineD3DTexture if a texture was requested */
-    if (desc2.ddsCaps.dwCaps & DDSCAPS_TEXTURE)
-        ddraw_surface_create_texture(object, flags);
+    /* DDSMT_ISTESTREQUIRED asks if a mode test is necessary.
+     * As it is not, DDERR_TESTFINISHED is returned
+     * (hopefully that's correct
+     *
+    if(Flags & DDSMT_ISTESTREQUIRED) return DDERR_TESTFINISHED;
+     * well, that value doesn't (yet) exist in the wine headers, so ignore it
+     */
 
-    return hr;
+    return DD_OK;
 }
 
 static HRESULT WINAPI ddraw7_CreateSurface(IDirectDraw7 *iface, DDSURFACEDESC2 *surface_desc,
@@ -2902,7 +2765,7 @@ static HRESULT WINAPI ddraw7_CreateSurface(IDirectDraw7 *iface, DDSURFACEDESC2 *
         return DDERR_INVALIDCAPS;
     }
 
-    hr = CreateSurface(ddraw, surface_desc, &impl, outer_unknown, 7);
+    hr = ddraw_surface_create(ddraw, surface_desc, &impl, outer_unknown, 7);
     wined3d_mutex_unlock();
     if (FAILED(hr))
     {
@@ -2956,7 +2819,7 @@ static HRESULT WINAPI ddraw4_CreateSurface(IDirectDraw4 *iface,
         return DDERR_INVALIDCAPS;
     }
 
-    hr = CreateSurface(ddraw, surface_desc, &impl, outer_unknown, 4);
+    hr = ddraw_surface_create(ddraw, surface_desc, &impl, outer_unknown, 4);
     wined3d_mutex_unlock();
     if (FAILED(hr))
     {
@@ -3012,7 +2875,7 @@ static HRESULT WINAPI ddraw2_CreateSurface(IDirectDraw2 *iface,
         return DDERR_INVALIDCAPS;
     }
 
-    hr = CreateSurface(ddraw, &surface_desc2, &impl, outer_unknown, 2);
+    hr = ddraw_surface_create(ddraw, &surface_desc2, &impl, outer_unknown, 2);
     wined3d_mutex_unlock();
     if (FAILED(hr))
     {
@@ -3053,11 +2916,18 @@ static HRESULT WINAPI ddraw1_CreateSurface(IDirectDraw *iface,
         return DDERR_INVALIDPARAMS;
     }
 
-    /* Remove front buffer flag, this causes failure in v7, and its added to normal
-     * primaries anyway. */
-    surface_desc->ddsCaps.dwCaps &= ~DDSCAPS_FRONTBUFFER;
+    if ((surface_desc->ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER))
+            == (DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER)
+            || (surface_desc->ddsCaps.dwCaps & (DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER))
+            == ((DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER)))
+    {
+        WARN("Application tried to create an explicit front or back buffer.\n");
+        wined3d_mutex_unlock();
+        return DDERR_INVALIDCAPS;
+    }
+
     DDSD_to_DDSD2(surface_desc, &surface_desc2);
-    hr = CreateSurface(ddraw, &surface_desc2, &impl, outer_unknown, 1);
+    hr = ddraw_surface_create(ddraw, &surface_desc2, &impl, outer_unknown, 1);
     wined3d_mutex_unlock();
     if (FAILED(hr))
     {
@@ -3682,7 +3552,6 @@ static HRESULT WINAPI d3d7_EnumDevices(IDirect3D7 *iface, LPD3DENUMDEVICESCALLBA
 {
     struct ddraw *ddraw = impl_from_IDirect3D7(iface);
     D3DDEVICEDESC7 device_desc7;
-    D3DDEVICEDESC device_desc1;
     HRESULT hr;
     size_t i;
 
@@ -3693,8 +3562,7 @@ static HRESULT WINAPI d3d7_EnumDevices(IDirect3D7 *iface, LPD3DENUMDEVICESCALLBA
 
     wined3d_mutex_lock();
 
-    hr = IDirect3DImpl_GetCaps(ddraw->wined3d, &device_desc1, &device_desc7);
-    if (hr != D3D_OK)
+    if (FAILED(hr = ddraw_get_d3dcaps(ddraw, &device_desc7)))
     {
         wined3d_mutex_unlock();
         return hr;
@@ -3760,12 +3628,12 @@ static HRESULT WINAPI d3d3_EnumDevices(IDirect3D3 *iface, LPD3DENUMDEVICESCALLBA
 
     wined3d_mutex_lock();
 
-    hr = IDirect3DImpl_GetCaps(ddraw->wined3d, &device_desc1, &device_desc7);
-    if (hr != D3D_OK)
+    if (FAILED(hr = ddraw_get_d3dcaps(ddraw, &device_desc7)))
     {
         wined3d_mutex_unlock();
         return hr;
     }
+    ddraw_d3dcaps1_from_7(&device_desc1, &device_desc7);
 
     /* Do I have to enumerate the reference id? Note from old d3d7:
      * "It seems that enumerating the reference IID on Direct3D 1 games
@@ -4124,10 +3992,11 @@ static HRESULT WINAPI d3d3_FindDevice(IDirect3D3 *iface, D3DFINDDEVICESEARCH *fd
     }
 
     /* Get the caps */
-    hr = IDirect3DImpl_GetCaps(ddraw->wined3d, &desc1, &desc7);
-    if (hr != D3D_OK) return hr;
+    if (FAILED(hr = ddraw_get_d3dcaps(ddraw, &desc7)))
+        return hr;
 
     /* Now return our own GUID */
+    ddraw_d3dcaps1_from_7(&desc1, &desc7);
     fdr->guid = IID_D3DDEVICE_WineD3D;
     fdr->ddHwDesc = desc1;
     fdr->ddSwDesc = desc1;
@@ -4187,9 +4056,10 @@ static HRESULT WINAPI d3d7_CreateDevice(IDirect3D7 *iface, REFCLSID riid,
     TRACE("iface %p, riid %s, surface %p, device %p.\n", iface, debugstr_guid(riid), surface, device);
 
     wined3d_mutex_lock();
-    hr = d3d_device_create(ddraw, target, 7, &object, NULL);
-    if (SUCCEEDED(hr))
+    if (SUCCEEDED(hr = d3d_device_create(ddraw, target, (IUnknown *)surface, 7, &object, NULL)))
+    {
         *device = &object->IDirect3DDevice7_iface;
+    }
     else
     {
         WARN("Failed to create device, hr %#x.\n", hr);
@@ -4215,9 +4085,10 @@ static HRESULT WINAPI d3d3_CreateDevice(IDirect3D3 *iface, REFCLSID riid,
         return CLASS_E_NOAGGREGATION;
 
     wined3d_mutex_lock();
-    hr = d3d_device_create(ddraw, surface_impl, 3, &device_impl, NULL);
-    if (SUCCEEDED(hr))
+    if (SUCCEEDED(hr = d3d_device_create(ddraw, surface_impl, (IUnknown *)surface, 3, &device_impl, NULL)))
+    {
         *device = &device_impl->IDirect3DDevice3_iface;
+    }
     else
     {
         WARN("Failed to create device, hr %#x.\n", hr);
@@ -4240,9 +4111,10 @@ static HRESULT WINAPI d3d2_CreateDevice(IDirect3D2 *iface, REFCLSID riid,
             iface, debugstr_guid(riid), surface, device);
 
     wined3d_mutex_lock();
-    hr = d3d_device_create(ddraw, surface_impl, 2, &device_impl, NULL);
-    if (SUCCEEDED(hr))
+    if (SUCCEEDED(hr = d3d_device_create(ddraw, surface_impl, (IUnknown *)surface, 2, &device_impl, NULL)))
+    {
         *device = &device_impl->IDirect3DDevice2_iface;
+    }
     else
     {
         WARN("Failed to create device, hr %#x.\n", hr);
@@ -4502,301 +4374,6 @@ static HRESULT WINAPI d3d3_EvictManagedTextures(IDirect3D3 *iface)
     return d3d7_EvictManagedTextures(&ddraw->IDirect3D7_iface);
 }
 
-/*****************************************************************************
- * IDirect3DImpl_GetCaps
- *
- * This function retrieves the device caps from wined3d
- * and converts it into a D3D7 and D3D - D3D3 structure
- * This is a helper function called from various places in ddraw
- *
- * Params:
- *  wined3d: The interface to get the caps from
- *  desc1: Old D3D <3 structure to fill (needed)
- *  desc7: D3D7 device desc structure to fill (needed)
- *
- * Returns
- *  D3D_OK on success, or the return value of IWineD3D::GetCaps
- *
- *****************************************************************************/
-HRESULT IDirect3DImpl_GetCaps(const struct wined3d *wined3d, D3DDEVICEDESC *desc1, D3DDEVICEDESC7 *desc7)
-{
-    WINED3DCAPS wined3d_caps;
-    HRESULT hr;
-
-    TRACE("wined3d %p, desc1 %p, desc7 %p.\n", wined3d, desc1, desc7);
-
-    memset(&wined3d_caps, 0, sizeof(wined3d_caps));
-
-    wined3d_mutex_lock();
-    hr = wined3d_get_device_caps(wined3d, 0, WINED3D_DEVICE_TYPE_HAL, &wined3d_caps);
-    wined3d_mutex_unlock();
-    if (FAILED(hr))
-    {
-        WARN("Failed to get device caps, hr %#x.\n", hr);
-        return hr;
-    }
-
-    /* Copy the results into the d3d7 and d3d3 structures */
-    desc7->dwDevCaps = wined3d_caps.DevCaps;
-    desc7->dpcLineCaps.dwMiscCaps = wined3d_caps.PrimitiveMiscCaps;
-    desc7->dpcLineCaps.dwRasterCaps = wined3d_caps.RasterCaps;
-    desc7->dpcLineCaps.dwZCmpCaps = wined3d_caps.ZCmpCaps;
-    desc7->dpcLineCaps.dwSrcBlendCaps = wined3d_caps.SrcBlendCaps;
-    desc7->dpcLineCaps.dwDestBlendCaps = wined3d_caps.DestBlendCaps;
-    desc7->dpcLineCaps.dwAlphaCmpCaps = wined3d_caps.AlphaCmpCaps;
-    desc7->dpcLineCaps.dwShadeCaps = wined3d_caps.ShadeCaps;
-    desc7->dpcLineCaps.dwTextureCaps = wined3d_caps.TextureCaps;
-    desc7->dpcLineCaps.dwTextureFilterCaps = wined3d_caps.TextureFilterCaps;
-    desc7->dpcLineCaps.dwTextureAddressCaps = wined3d_caps.TextureAddressCaps;
-
-    desc7->dwMaxTextureWidth = wined3d_caps.MaxTextureWidth;
-    desc7->dwMaxTextureHeight = wined3d_caps.MaxTextureHeight;
-
-    desc7->dwMaxTextureRepeat = wined3d_caps.MaxTextureRepeat;
-    desc7->dwMaxTextureAspectRatio = wined3d_caps.MaxTextureAspectRatio;
-    desc7->dwMaxAnisotropy = wined3d_caps.MaxAnisotropy;
-    desc7->dvMaxVertexW = wined3d_caps.MaxVertexW;
-
-    desc7->dvGuardBandLeft = wined3d_caps.GuardBandLeft;
-    desc7->dvGuardBandTop = wined3d_caps.GuardBandTop;
-    desc7->dvGuardBandRight = wined3d_caps.GuardBandRight;
-    desc7->dvGuardBandBottom = wined3d_caps.GuardBandBottom;
-
-    desc7->dvExtentsAdjust = wined3d_caps.ExtentsAdjust;
-    desc7->dwStencilCaps = wined3d_caps.StencilCaps;
-
-    desc7->dwFVFCaps = wined3d_caps.FVFCaps;
-    desc7->dwTextureOpCaps = wined3d_caps.TextureOpCaps;
-
-    desc7->dwVertexProcessingCaps = wined3d_caps.VertexProcessingCaps;
-    desc7->dwMaxActiveLights = wined3d_caps.MaxActiveLights;
-
-    /* Remove all non-d3d7 caps */
-    desc7->dwDevCaps &= (
-        D3DDEVCAPS_FLOATTLVERTEX         | D3DDEVCAPS_SORTINCREASINGZ          | D3DDEVCAPS_SORTDECREASINGZ          |
-        D3DDEVCAPS_SORTEXACT             | D3DDEVCAPS_EXECUTESYSTEMMEMORY      | D3DDEVCAPS_EXECUTEVIDEOMEMORY       |
-        D3DDEVCAPS_TLVERTEXSYSTEMMEMORY  | D3DDEVCAPS_TLVERTEXVIDEOMEMORY      | D3DDEVCAPS_TEXTURESYSTEMMEMORY      |
-        D3DDEVCAPS_TEXTUREVIDEOMEMORY    | D3DDEVCAPS_DRAWPRIMTLVERTEX         | D3DDEVCAPS_CANRENDERAFTERFLIP       |
-        D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_DRAWPRIMITIVES2          | D3DDEVCAPS_SEPARATETEXTUREMEMORIES  |
-        D3DDEVCAPS_DRAWPRIMITIVES2EX     | D3DDEVCAPS_HWTRANSFORMANDLIGHT      | D3DDEVCAPS_CANBLTSYSTONONLOCAL      |
-        D3DDEVCAPS_HWRASTERIZATION);
-
-    desc7->dwStencilCaps &= (
-        D3DSTENCILCAPS_KEEP              | D3DSTENCILCAPS_ZERO                 | D3DSTENCILCAPS_REPLACE              |
-        D3DSTENCILCAPS_INCRSAT           | D3DSTENCILCAPS_DECRSAT              | D3DSTENCILCAPS_INVERT               |
-        D3DSTENCILCAPS_INCR              | D3DSTENCILCAPS_DECR);
-
-    /* FVF caps ?*/
-
-    desc7->dwTextureOpCaps &= (
-        D3DTEXOPCAPS_DISABLE             | D3DTEXOPCAPS_SELECTARG1             | D3DTEXOPCAPS_SELECTARG2             |
-        D3DTEXOPCAPS_MODULATE            | D3DTEXOPCAPS_MODULATE2X             | D3DTEXOPCAPS_MODULATE4X             |
-        D3DTEXOPCAPS_ADD                 | D3DTEXOPCAPS_ADDSIGNED              | D3DTEXOPCAPS_ADDSIGNED2X            |
-        D3DTEXOPCAPS_SUBTRACT            | D3DTEXOPCAPS_ADDSMOOTH              | D3DTEXOPCAPS_BLENDTEXTUREALPHA      |
-        D3DTEXOPCAPS_BLENDFACTORALPHA    | D3DTEXOPCAPS_BLENDTEXTUREALPHAPM    | D3DTEXOPCAPS_BLENDCURRENTALPHA      |
-        D3DTEXOPCAPS_PREMODULATE         | D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR | D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
-        D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR | D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA | D3DTEXOPCAPS_BUMPENVMAP    |
-        D3DTEXOPCAPS_BUMPENVMAPLUMINANCE | D3DTEXOPCAPS_DOTPRODUCT3);
-
-    desc7->dwVertexProcessingCaps &= (
-        D3DVTXPCAPS_TEXGEN               | D3DVTXPCAPS_MATERIALSOURCE7         | D3DVTXPCAPS_VERTEXFOG               |
-        D3DVTXPCAPS_DIRECTIONALLIGHTS    | D3DVTXPCAPS_POSITIONALLIGHTS        | D3DVTXPCAPS_LOCALVIEWER);
-
-    desc7->dpcLineCaps.dwMiscCaps &= (
-        D3DPMISCCAPS_MASKPLANES          | D3DPMISCCAPS_MASKZ                  | D3DPMISCCAPS_LINEPATTERNREP         |
-        D3DPMISCCAPS_CONFORMANT          | D3DPMISCCAPS_CULLNONE               | D3DPMISCCAPS_CULLCW                 |
-        D3DPMISCCAPS_CULLCCW);
-
-    desc7->dpcLineCaps.dwRasterCaps &= (
-        D3DPRASTERCAPS_DITHER            | D3DPRASTERCAPS_ROP2                 | D3DPRASTERCAPS_XOR                  |
-        D3DPRASTERCAPS_PAT               | D3DPRASTERCAPS_ZTEST                | D3DPRASTERCAPS_SUBPIXEL             |
-        D3DPRASTERCAPS_SUBPIXELX         | D3DPRASTERCAPS_FOGVERTEX            | D3DPRASTERCAPS_FOGTABLE             |
-        D3DPRASTERCAPS_STIPPLE           | D3DPRASTERCAPS_ANTIALIASSORTDEPENDENT | D3DPRASTERCAPS_ANTIALIASSORTINDEPENDENT |
-        D3DPRASTERCAPS_ANTIALIASEDGES    | D3DPRASTERCAPS_MIPMAPLODBIAS        | D3DPRASTERCAPS_ZBIAS                |
-        D3DPRASTERCAPS_ZBUFFERLESSHSR    | D3DPRASTERCAPS_FOGRANGE             | D3DPRASTERCAPS_ANISOTROPY           |
-        D3DPRASTERCAPS_WBUFFER           | D3DPRASTERCAPS_TRANSLUCENTSORTINDEPENDENT | D3DPRASTERCAPS_WFOG           |
-        D3DPRASTERCAPS_ZFOG);
-
-    desc7->dpcLineCaps.dwZCmpCaps &= (
-        D3DPCMPCAPS_NEVER                | D3DPCMPCAPS_LESS                    | D3DPCMPCAPS_EQUAL                   |
-        D3DPCMPCAPS_LESSEQUAL            | D3DPCMPCAPS_GREATER                 | D3DPCMPCAPS_NOTEQUAL                |
-        D3DPCMPCAPS_GREATEREQUAL         | D3DPCMPCAPS_ALWAYS);
-
-    desc7->dpcLineCaps.dwSrcBlendCaps &= (
-        D3DPBLENDCAPS_ZERO               | D3DPBLENDCAPS_ONE                   | D3DPBLENDCAPS_SRCCOLOR              |
-        D3DPBLENDCAPS_INVSRCCOLOR        | D3DPBLENDCAPS_SRCALPHA              | D3DPBLENDCAPS_INVSRCALPHA           |
-        D3DPBLENDCAPS_DESTALPHA          | D3DPBLENDCAPS_INVDESTALPHA          | D3DPBLENDCAPS_DESTCOLOR             |
-        D3DPBLENDCAPS_INVDESTCOLOR       | D3DPBLENDCAPS_SRCALPHASAT           | D3DPBLENDCAPS_BOTHSRCALPHA          |
-        D3DPBLENDCAPS_BOTHINVSRCALPHA);
-
-    desc7->dpcLineCaps.dwDestBlendCaps &= (
-        D3DPBLENDCAPS_ZERO               | D3DPBLENDCAPS_ONE                   | D3DPBLENDCAPS_SRCCOLOR              |
-        D3DPBLENDCAPS_INVSRCCOLOR        | D3DPBLENDCAPS_SRCALPHA              | D3DPBLENDCAPS_INVSRCALPHA           |
-        D3DPBLENDCAPS_DESTALPHA          | D3DPBLENDCAPS_INVDESTALPHA          | D3DPBLENDCAPS_DESTCOLOR             |
-        D3DPBLENDCAPS_INVDESTCOLOR       | D3DPBLENDCAPS_SRCALPHASAT           | D3DPBLENDCAPS_BOTHSRCALPHA          |
-        D3DPBLENDCAPS_BOTHINVSRCALPHA);
-
-    desc7->dpcLineCaps.dwAlphaCmpCaps &= (
-        D3DPCMPCAPS_NEVER                | D3DPCMPCAPS_LESS                    | D3DPCMPCAPS_EQUAL                   |
-        D3DPCMPCAPS_LESSEQUAL            | D3DPCMPCAPS_GREATER                 | D3DPCMPCAPS_NOTEQUAL                |
-        D3DPCMPCAPS_GREATEREQUAL         | D3DPCMPCAPS_ALWAYS);
-
-    desc7->dpcLineCaps.dwShadeCaps &= (
-        D3DPSHADECAPS_COLORFLATMONO      | D3DPSHADECAPS_COLORFLATRGB          | D3DPSHADECAPS_COLORGOURAUDMONO      |
-        D3DPSHADECAPS_COLORGOURAUDRGB    | D3DPSHADECAPS_COLORPHONGMONO        | D3DPSHADECAPS_COLORPHONGRGB         |
-        D3DPSHADECAPS_SPECULARFLATMONO   | D3DPSHADECAPS_SPECULARFLATRGB       | D3DPSHADECAPS_SPECULARGOURAUDMONO   |
-        D3DPSHADECAPS_SPECULARGOURAUDRGB | D3DPSHADECAPS_SPECULARPHONGMONO     | D3DPSHADECAPS_SPECULARPHONGRGB      |
-        D3DPSHADECAPS_ALPHAFLATBLEND     | D3DPSHADECAPS_ALPHAFLATSTIPPLED     | D3DPSHADECAPS_ALPHAGOURAUDBLEND     |
-        D3DPSHADECAPS_ALPHAGOURAUDSTIPPLED | D3DPSHADECAPS_ALPHAPHONGBLEND     | D3DPSHADECAPS_ALPHAPHONGSTIPPLED    |
-        D3DPSHADECAPS_FOGFLAT            | D3DPSHADECAPS_FOGGOURAUD            | D3DPSHADECAPS_FOGPHONG);
-
-    desc7->dpcLineCaps.dwTextureCaps &= (
-        D3DPTEXTURECAPS_PERSPECTIVE      | D3DPTEXTURECAPS_POW2                | D3DPTEXTURECAPS_ALPHA               |
-        D3DPTEXTURECAPS_TRANSPARENCY     | D3DPTEXTURECAPS_BORDER              | D3DPTEXTURECAPS_SQUAREONLY          |
-        D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE | D3DPTEXTURECAPS_ALPHAPALETTE| D3DPTEXTURECAPS_NONPOW2CONDITIONAL  |
-        D3DPTEXTURECAPS_PROJECTED        | D3DPTEXTURECAPS_CUBEMAP             | D3DPTEXTURECAPS_COLORKEYBLEND);
-
-    desc7->dpcLineCaps.dwTextureFilterCaps &= (
-        D3DPTFILTERCAPS_NEAREST          | D3DPTFILTERCAPS_LINEAR              | D3DPTFILTERCAPS_MIPNEAREST          |
-        D3DPTFILTERCAPS_MIPLINEAR        | D3DPTFILTERCAPS_LINEARMIPNEAREST    | D3DPTFILTERCAPS_LINEARMIPLINEAR     |
-        D3DPTFILTERCAPS_MINFPOINT        | D3DPTFILTERCAPS_MINFLINEAR          | D3DPTFILTERCAPS_MINFANISOTROPIC     |
-        D3DPTFILTERCAPS_MIPFPOINT        | D3DPTFILTERCAPS_MIPFLINEAR          | D3DPTFILTERCAPS_MAGFPOINT           |
-        D3DPTFILTERCAPS_MAGFLINEAR       | D3DPTFILTERCAPS_MAGFANISOTROPIC     | D3DPTFILTERCAPS_MAGFAFLATCUBIC      |
-        D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC);
-
-    desc7->dpcLineCaps.dwTextureAddressCaps &= (
-        D3DPTADDRESSCAPS_WRAP            | D3DPTADDRESSCAPS_MIRROR             | D3DPTADDRESSCAPS_CLAMP              |
-        D3DPTADDRESSCAPS_BORDER          | D3DPTADDRESSCAPS_INDEPENDENTUV);
-
-    if (!(desc7->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2))
-    {
-        /* DirectX7 always has the np2 flag set, no matter what the card
-         * supports. Some old games (Rollcage) check the caps incorrectly.
-         * If wined3d supports nonpow2 textures it also has np2 conditional
-         * support. */
-        desc7->dpcLineCaps.dwTextureCaps |= D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL;
-    }
-
-    /* Fill the missing members, and do some fixup */
-    desc7->dpcLineCaps.dwSize = sizeof(desc7->dpcLineCaps);
-    desc7->dpcLineCaps.dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_MODULATEMASK |
-                                            D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL |
-                                            D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
-                                            D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA;
-    desc7->dpcLineCaps.dwStippleWidth = 32;
-    desc7->dpcLineCaps.dwStippleHeight = 32;
-    /* Use the same for the TriCaps */
-    desc7->dpcTriCaps = desc7->dpcLineCaps;
-
-    desc7->dwDeviceRenderBitDepth = DDBD_16 | DDBD_24 | DDBD_32;
-    desc7->dwDeviceZBufferBitDepth = DDBD_16 | DDBD_24;
-    desc7->dwMinTextureWidth = 1;
-    desc7->dwMinTextureHeight = 1;
-
-    /* Convert DWORDs safely to WORDs */
-    if (wined3d_caps.MaxTextureBlendStages > 0xffff) desc7->wMaxTextureBlendStages = 0xffff;
-    else desc7->wMaxTextureBlendStages = (WORD)wined3d_caps.MaxTextureBlendStages;
-    if (wined3d_caps.MaxSimultaneousTextures > 0xffff) desc7->wMaxSimultaneousTextures = 0xffff;
-    else desc7->wMaxSimultaneousTextures = (WORD)wined3d_caps.MaxSimultaneousTextures;
-
-    if (wined3d_caps.MaxUserClipPlanes > 0xffff) desc7->wMaxUserClipPlanes = 0xffff;
-    else desc7->wMaxUserClipPlanes = (WORD)wined3d_caps.MaxUserClipPlanes;
-    if (wined3d_caps.MaxVertexBlendMatrices > 0xffff) desc7->wMaxVertexBlendMatrices = 0xffff;
-    else desc7->wMaxVertexBlendMatrices = (WORD)wined3d_caps.MaxVertexBlendMatrices;
-
-    desc7->deviceGUID = IID_IDirect3DTnLHalDevice;
-
-    desc7->dwReserved1 = 0;
-    desc7->dwReserved2 = 0;
-    desc7->dwReserved3 = 0;
-    desc7->dwReserved4 = 0;
-
-    /* Fill the old structure */
-    memset(desc1, 0, sizeof(*desc1));
-    desc1->dwSize = sizeof(D3DDEVICEDESC);
-    desc1->dwFlags = D3DDD_COLORMODEL
-            | D3DDD_DEVCAPS
-            | D3DDD_TRANSFORMCAPS
-            | D3DDD_BCLIPPING
-            | D3DDD_LIGHTINGCAPS
-            | D3DDD_LINECAPS
-            | D3DDD_TRICAPS
-            | D3DDD_DEVICERENDERBITDEPTH
-            | D3DDD_DEVICEZBUFFERBITDEPTH
-            | D3DDD_MAXBUFFERSIZE
-            | D3DDD_MAXVERTEXCOUNT;
-
-    desc1->dcmColorModel = D3DCOLOR_RGB;
-    desc1->dwDevCaps = desc7->dwDevCaps;
-    desc1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
-    desc1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
-    desc1->bClipping = TRUE;
-    desc1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
-    desc1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL
-            | D3DLIGHTCAPS_PARALLELPOINT
-            | D3DLIGHTCAPS_POINT
-            | D3DLIGHTCAPS_SPOT;
-
-    desc1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
-    desc1->dlcLightingCaps.dwNumLights = desc7->dwMaxActiveLights;
-
-    desc1->dpcLineCaps.dwSize = sizeof(D3DPRIMCAPS);
-    desc1->dpcLineCaps.dwMiscCaps = desc7->dpcLineCaps.dwMiscCaps;
-    desc1->dpcLineCaps.dwRasterCaps = desc7->dpcLineCaps.dwRasterCaps;
-    desc1->dpcLineCaps.dwZCmpCaps = desc7->dpcLineCaps.dwZCmpCaps;
-    desc1->dpcLineCaps.dwSrcBlendCaps = desc7->dpcLineCaps.dwSrcBlendCaps;
-    desc1->dpcLineCaps.dwDestBlendCaps = desc7->dpcLineCaps.dwDestBlendCaps;
-    desc1->dpcLineCaps.dwShadeCaps = desc7->dpcLineCaps.dwShadeCaps;
-    desc1->dpcLineCaps.dwTextureCaps = desc7->dpcLineCaps.dwTextureCaps;
-    desc1->dpcLineCaps.dwTextureFilterCaps = desc7->dpcLineCaps.dwTextureFilterCaps;
-    desc1->dpcLineCaps.dwTextureBlendCaps = desc7->dpcLineCaps.dwTextureBlendCaps;
-    desc1->dpcLineCaps.dwTextureAddressCaps = desc7->dpcLineCaps.dwTextureAddressCaps;
-    desc1->dpcLineCaps.dwStippleWidth = desc7->dpcLineCaps.dwStippleWidth;
-    desc1->dpcLineCaps.dwAlphaCmpCaps = desc7->dpcLineCaps.dwAlphaCmpCaps;
-
-    desc1->dpcTriCaps.dwSize = sizeof(D3DPRIMCAPS);
-    desc1->dpcTriCaps.dwMiscCaps = desc7->dpcTriCaps.dwMiscCaps;
-    desc1->dpcTriCaps.dwRasterCaps = desc7->dpcTriCaps.dwRasterCaps;
-    desc1->dpcTriCaps.dwZCmpCaps = desc7->dpcTriCaps.dwZCmpCaps;
-    desc1->dpcTriCaps.dwSrcBlendCaps = desc7->dpcTriCaps.dwSrcBlendCaps;
-    desc1->dpcTriCaps.dwDestBlendCaps = desc7->dpcTriCaps.dwDestBlendCaps;
-    desc1->dpcTriCaps.dwShadeCaps = desc7->dpcTriCaps.dwShadeCaps;
-    desc1->dpcTriCaps.dwTextureCaps = desc7->dpcTriCaps.dwTextureCaps;
-    desc1->dpcTriCaps.dwTextureFilterCaps = desc7->dpcTriCaps.dwTextureFilterCaps;
-    desc1->dpcTriCaps.dwTextureBlendCaps = desc7->dpcTriCaps.dwTextureBlendCaps;
-    desc1->dpcTriCaps.dwTextureAddressCaps = desc7->dpcTriCaps.dwTextureAddressCaps;
-    desc1->dpcTriCaps.dwStippleWidth = desc7->dpcTriCaps.dwStippleWidth;
-    desc1->dpcTriCaps.dwAlphaCmpCaps = desc7->dpcTriCaps.dwAlphaCmpCaps;
-
-    desc1->dwDeviceRenderBitDepth = desc7->dwDeviceRenderBitDepth;
-    desc1->dwDeviceZBufferBitDepth = desc7->dwDeviceZBufferBitDepth;
-    desc1->dwMaxBufferSize = 0;
-    desc1->dwMaxVertexCount = 65536;
-    desc1->dwMinTextureWidth  = desc7->dwMinTextureWidth;
-    desc1->dwMinTextureHeight = desc7->dwMinTextureHeight;
-    desc1->dwMaxTextureWidth  = desc7->dwMaxTextureWidth;
-    desc1->dwMaxTextureHeight = desc7->dwMaxTextureHeight;
-    desc1->dwMinStippleWidth  = 1;
-    desc1->dwMinStippleHeight = 1;
-    desc1->dwMaxStippleWidth  = 32;
-    desc1->dwMaxStippleHeight = 32;
-    desc1->dwMaxTextureRepeat = desc7->dwMaxTextureRepeat;
-    desc1->dwMaxTextureAspectRatio = desc7->dwMaxTextureAspectRatio;
-    desc1->dwMaxAnisotropy = desc7->dwMaxAnisotropy;
-    desc1->dvGuardBandLeft = desc7->dvGuardBandLeft;
-    desc1->dvGuardBandRight = desc7->dvGuardBandRight;
-    desc1->dvGuardBandTop = desc7->dvGuardBandTop;
-    desc1->dvGuardBandBottom = desc7->dvGuardBandBottom;
-    desc1->dvExtentsAdjust = desc7->dvExtentsAdjust;
-    desc1->dwStencilCaps = desc7->dwStencilCaps;
-    desc1->dwFVFCaps = desc7->dwFVFCaps;
-    desc1->dwTextureOpCaps = desc7->dwTextureOpCaps;
-    desc1->wMaxTextureBlendStages = desc7->wMaxTextureBlendStages;
-    desc1->wMaxSimultaneousTextures = desc7->wMaxSimultaneousTextures;
-
-    return DD_OK;
-}
-
 /*****************************************************************************
  * IDirectDraw7 VTable
  *****************************************************************************/
@@ -5113,36 +4690,56 @@ static void CDECL device_parent_mode_changed(struct wined3d_device_parent *devic
         ERR("Failed to resize window.\n");
 }
 
-static HRESULT CDECL device_parent_create_texture_surface(struct wined3d_device_parent *device_parent,
-        void *container_parent, const struct wined3d_resource_desc *wined3d_desc, UINT sub_resource_idx,
-        DWORD flags, struct wined3d_surface **surface)
+static HRESULT CDECL device_parent_surface_created(struct wined3d_device_parent *device_parent,
+        void *container_parent, struct wined3d_surface *surface,
+        void **parent, const struct wined3d_parent_ops **parent_ops)
 {
     struct ddraw *ddraw = ddraw_from_device_parent(device_parent);
-    struct ddraw_surface *tex_root = container_parent;
-    DDSURFACEDESC2 desc = tex_root->surface_desc;
     struct ddraw_surface *ddraw_surface;
     HRESULT hr;
 
-    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);
+    TRACE("device_parent %p, container_parent %p, surface %p, parent %p, parent_ops %p.\n",
+            device_parent, container_parent, surface, parent, parent_ops);
 
-    /* The ddraw root surface is created before the wined3d texture. */
-    if (!sub_resource_idx)
+    /* We have a swapchain texture. */
+    if (container_parent == ddraw)
     {
-        ddraw_surface = tex_root;
-        goto done;
+        *parent = NULL;
+        *parent_ops = &ddraw_null_wined3d_parent_ops;
+
+        return DD_OK;
     }
 
-    desc.dwWidth = wined3d_desc->width;
-    desc.dwHeight = wined3d_desc->height;
+    if (!(ddraw_surface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ddraw_surface))))
+    {
+        ERR("Failed to allocate surface memory.\n");
+        return DDERR_OUTOFVIDEOMEMORY;
+    }
 
-    /* FIXME: Validate that format, usage, pool, etc. really make sense. */
-    if (FAILED(hr = ddraw_create_surface(ddraw, &desc, flags, &ddraw_surface, tex_root->version)))
+    if (FAILED(hr = ddraw_surface_init(ddraw_surface, ddraw, container_parent, surface, parent_ops)))
+    {
+        WARN("Failed to initialize surface, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, ddraw_surface);
         return hr;
+    }
 
-done:
-    *surface = ddraw_surface->wined3d_surface;
-    wined3d_surface_incref(*surface);
+    *parent = ddraw_surface;
+    list_add_head(&ddraw->surface_list, &ddraw_surface->surface_list_entry);
+
+    TRACE("Created ddraw surface %p.\n", ddraw_surface);
+
+    return DD_OK;
+}
+
+static HRESULT CDECL device_parent_volume_created(struct wined3d_device_parent *device_parent,
+        void *container_parent, struct wined3d_volume *volume,
+        void **parent, const struct wined3d_parent_ops **parent_ops)
+{
+    TRACE("device_parent %p, container_parent %p, volume %p, parent %p, parent_ops %p.\n",
+            device_parent, container_parent, volume, parent, parent_ops);
+
+    *parent = NULL;
+    *parent_ops = &ddraw_null_wined3d_parent_ops;
 
     return DD_OK;
 }
@@ -5162,6 +4759,8 @@ static HRESULT CDECL device_parent_create_swapchain_surface(struct wined3d_devic
         void *container_parent, const struct wined3d_resource_desc *desc, struct wined3d_surface **surface)
 {
     struct ddraw *ddraw = ddraw_from_device_parent(device_parent);
+    struct wined3d_resource_desc texture_desc;
+    struct wined3d_texture *texture;
     HRESULT hr;
 
     TRACE("device_parent %p, container_parent %p, desc %p, surface %p.\n",
@@ -5173,27 +4772,21 @@ static HRESULT CDECL device_parent_create_swapchain_surface(struct wined3d_devic
         return E_FAIL;
     }
 
-    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;
-
-    return hr;
-}
-
-static HRESULT CDECL device_parent_create_volume(struct wined3d_device_parent *device_parent,
-        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",
-            device_parent, container_parent, width, height, depth,
-            format, pool, usage, volume);
+    texture_desc = *desc;
+    texture_desc.resource_type = WINED3D_RTYPE_TEXTURE;
+    if (FAILED(hr = wined3d_texture_create(ddraw->wined3d_device, &texture_desc, 1,
+            WINED3D_SURFACE_MAPPABLE, ddraw, &ddraw_frontbuffer_parent_ops, &texture)))
+    {
+        WARN("Failed to create texture, hr %#x.\n", hr);
+        return hr;
+    }
 
-    ERR("Not implemented!\n");
+    *surface = wined3d_surface_from_resource(wined3d_texture_get_sub_resource(texture, 0));
+    ddraw->wined3d_frontbuffer = *surface;
+    wined3d_surface_incref(*surface);
+    wined3d_texture_decref(texture);
 
-    return E_NOTIMPL;
+    return hr;
 }
 
 static HRESULT CDECL device_parent_create_swapchain(struct wined3d_device_parent *device_parent,
@@ -5221,9 +4814,9 @@ static const struct wined3d_device_parent_ops ddraw_wined3d_device_parent_ops =
 {
     device_parent_wined3d_device_created,
     device_parent_mode_changed,
+    device_parent_surface_created,
+    device_parent_volume_created,
     device_parent_create_swapchain_surface,
-    device_parent_create_texture_surface,
-    device_parent_create_volume,
     device_parent_create_swapchain,
 };
 
index d824700..6e33253 100644 (file)
@@ -18,6 +18,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#pragma makedep register
+
 [
     helpstring("DirectDraw Object"),
     threading(both),
index 6fb9608..a312ed7 100644 (file)
@@ -26,7 +26,7 @@
 #include <stdarg.h>
 
 #define _INC_WINDOWS
-#define COM_NO_WINDOWS_H
+#define COM_NO_WINDOW_H
 
 #define COBJMACROS
 #define NONAMELESSSTRUCT
@@ -61,6 +61,7 @@ struct FvfToDecl
 #define DDRAW_RESTORE_MODE      0x00000004
 #define DDRAW_NO3D              0x00000008
 #define DDRAW_SCL_DDRAW1        0x00000010
+#define DDRAW_SCL_RECURSIVE     0x00000020
 
 #define DDRAW_STRIDE_ALIGNMENT  8
 
@@ -118,7 +119,9 @@ struct ddraw
 #define DDRAW_WINDOW_CLASS_NAME "DirectDrawDeviceWnd"
 
 HRESULT ddraw_init(struct ddraw *ddraw, enum wined3d_device_type device_type) DECLSPEC_HIDDEN;
+void ddraw_d3dcaps1_from_7(D3DDEVICEDESC *caps1, D3DDEVICEDESC7 *caps7) DECLSPEC_HIDDEN;
 void ddraw_destroy_swapchain(struct ddraw *ddraw) DECLSPEC_HIDDEN;
+HRESULT ddraw_get_d3dcaps(const struct ddraw *ddraw, D3DDEVICEDESC7 *caps) DECLSPEC_HIDDEN;
 
 static inline void ddraw_set_swapchain_window(struct ddraw *ddraw, HWND window)
 {
@@ -182,6 +185,7 @@ struct ddraw_surface
 
     /* Clipper objects */
     struct ddraw_clipper *clipper;
+    struct ddraw_palette *palette;
 
     /* For the ddraw surface list */
     struct list             surface_list_entry;
@@ -189,9 +193,18 @@ struct ddraw_surface
     DWORD                   Handle;
 };
 
-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, DWORD flags, UINT version) DECLSPEC_HIDDEN;
+struct ddraw_texture
+{
+    unsigned int version;
+    DDSURFACEDESC2 surface_desc;
+
+    struct ddraw_surface *root;
+};
+
+HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_desc,
+        struct ddraw_surface **surface, IUnknown *outer_unknown, unsigned int version) DECLSPEC_HIDDEN;
+HRESULT ddraw_surface_init(struct ddraw_surface *surface, struct ddraw *ddraw, struct ddraw_texture *texture,
+        struct wined3d_surface *wined3d_surface, const struct wined3d_parent_ops **parent_ops) DECLSPEC_HIDDEN;
 ULONG ddraw_surface_release_iface(struct ddraw_surface *This) DECLSPEC_HIDDEN;
 
 static inline struct ddraw_surface *impl_from_IDirect3DTexture(IDirect3DTexture *iface)
@@ -281,7 +294,7 @@ struct d3d_device
     IUnknown *outer_unknown;
     struct wined3d_device *wined3d_device;
     struct ddraw *ddraw;
-    struct ddraw_surface *target;
+    IUnknown *rt_iface;
 
     struct wined3d_buffer *index_buffer;
     UINT index_buffer_size;
@@ -310,7 +323,7 @@ struct d3d_device
     DWORD vertex_type;
     DWORD render_flags;
     DWORD nb_vertices;
-    LPBYTE sysmem_vertex_buffer;
+    BYTE *sysmem_vertex_buffer;
     DWORD vertex_size;
     DWORD buffer_size;
 
@@ -319,17 +332,13 @@ struct d3d_device
     D3DMATRIXHANDLE          world, proj, view;
 };
 
-HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target,
+HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target, IUnknown *rt_iface,
         UINT version, struct d3d_device **device, IUnknown *outer_unknown) DECLSPEC_HIDDEN;
 enum wined3d_depth_buffer_type d3d_device_update_depth_stencil(struct d3d_device *device) DECLSPEC_HIDDEN;
 
 /* The IID */
 extern const GUID IID_D3DDEVICE_WineD3D DECLSPEC_HIDDEN;
 
-/* Helper functions */
-HRESULT IDirect3DImpl_GetCaps(const struct wined3d *wined3d,
-        D3DDEVICEDESC *Desc123, D3DDEVICEDESC7 *Desc7) DECLSPEC_HIDDEN;
-
 static inline struct d3d_device *impl_from_IDirect3DDevice(IDirect3DDevice *iface)
 {
     return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice_iface);
@@ -377,9 +386,9 @@ struct ddraw_palette
     LONG ref;
 
     struct wined3d_palette *wineD3DPalette;
-
-    /* IDirectDrawPalette fields */
-    IUnknown                  *ifaceToRelease;
+    struct ddraw *ddraw;
+    IUnknown *ifaceToRelease;
+    DWORD flags;
 };
 
 static inline struct ddraw_palette *impl_from_IDirectDrawPalette(IDirectDrawPalette *iface)
@@ -607,18 +616,6 @@ struct member_info
 
 #define DD_STRUCT_COPY_BYSIZE(to,from) DD_STRUCT_COPY_BYSIZE_(to,from,(from)->dwSize)
 
-#define SIZEOF_END_PADDING(type, last_field) \
-    (sizeof(type) - offsetof(type, last_field) - sizeof(((type *)0)->last_field))
-
-static inline void copy_to_surfacedesc2(DDSURFACEDESC2 *to, DDSURFACEDESC2 *from)
-{
-    DWORD from_size = from->dwSize;
-    if (from_size == sizeof(DDSURFACEDESC))
-        from_size -= SIZEOF_END_PADDING(DDSURFACEDESC, ddsCaps);
-    to->dwSize = sizeof(DDSURFACEDESC2); /* for struct copy */
-    DD_STRUCT_COPY_BYSIZE_(to, from, from_size);
-}
-
 HRESULT hr_ddraw_from_wined3d(HRESULT hr) DECLSPEC_HIDDEN;
 
-#endif /* __WINE_DLLS_DDRAW_DDRAW_PRIVATE_H */
+#endif
index baa0b77..cfad802 100644 (file)
@@ -220,6 +220,7 @@ static ULONG WINAPI d3d_device_inner_Release(IUnknown *iface)
 {
     struct d3d_device *This = impl_from_IUnknown(iface);
     ULONG ref = InterlockedDecrement(&This->ref);
+    IUnknown *rt_iface;
 
     TRACE("%p decreasing refcount to %u.\n", This, ref);
 
@@ -241,10 +242,7 @@ static ULONG WINAPI d3d_device_inner_Release(IUnknown *iface)
         if (This->vertex_buffer)
             wined3d_buffer_decref(This->vertex_buffer);
 
-        /* Set the device up to render to the front buffer since the back
-         * buffer will vanish soon. */
-        wined3d_device_set_render_target(This->wined3d_device, 0,
-                This->ddraw->wined3d_frontbuffer, TRUE);
+        wined3d_device_set_render_target(This->wined3d_device, 0, NULL, FALSE);
 
         /* Release the wined3d device. This won't destroy it. */
         if (!wined3d_device_decref(This->wined3d_device))
@@ -307,11 +305,12 @@ static ULONG WINAPI d3d_device_inner_Release(IUnknown *iface)
             IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
         }
 
-        TRACE("Releasing target %p.\n", This->target);
-        /* Release the render target. */
+        TRACE("Releasing render target %p.\n", This->rt_iface);
+        rt_iface = This->rt_iface;
+        This->rt_iface = NULL;
         if (This->version != 1)
-            IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
-        TRACE("Target release done\n");
+            IUnknown_Release(rt_iface);
+        TRACE("Render target release done.\n");
 
         This->ddraw->d3ddevice = NULL;
 
@@ -389,37 +388,20 @@ static HRESULT WINAPI d3d_device1_Initialize(IDirect3DDevice *iface,
     return D3D_OK;
 }
 
-/*****************************************************************************
- * IDirect3DDevice7::GetCaps
- *
- * Retrieves the device's capabilities
- *
- * This implementation is used for Version 7 only, the older versions have
- * their own implementation.
- *
- * Parameters:
- *  Desc: Pointer to a D3DDEVICEDESC7 structure to fill
- *
- * Returns:
- *  D3D_OK on success
- *  D3DERR_* if a problem occurs. See WineD3D
- *
- *****************************************************************************/
-static HRESULT d3d_device7_GetCaps(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *Desc)
+static HRESULT d3d_device7_GetCaps(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *device_desc)
 {
     struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
-    D3DDEVICEDESC OldDesc;
 
-    TRACE("iface %p, device_desc %p.\n", iface, Desc);
+    TRACE("iface %p, device_desc %p.\n", iface, device_desc);
 
-    if (!Desc)
+    if (!device_desc)
     {
-        WARN("Desc is NULL, returning DDERR_INVALIDPARAMS.\n");
+        WARN("device_desc is NULL, returning DDERR_INVALIDPARAMS.\n");
         return DDERR_INVALIDPARAMS;
     }
 
     /* Call the same function used by IDirect3D, this saves code */
-    return IDirect3DImpl_GetCaps(device->ddraw->wined3d, &OldDesc, Desc);
+    return ddraw_get_d3dcaps(device->ddraw, device_desc);
 }
 
 static HRESULT WINAPI d3d_device7_GetCaps_FPUSetup(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *desc)
@@ -481,8 +463,8 @@ static HRESULT WINAPI d3d_device3_GetCaps(IDirect3DDevice3 *iface,
         D3DDEVICEDESC *HWDesc, D3DDEVICEDESC *HelDesc)
 {
     struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
-    D3DDEVICEDESC oldDesc;
-    D3DDEVICEDESC7 newDesc;
+    D3DDEVICEDESC7 desc7;
+    D3DDEVICEDESC desc1;
     HRESULT hr;
 
     TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
@@ -508,12 +490,12 @@ static HRESULT WINAPI d3d_device3_GetCaps(IDirect3DDevice3 *iface,
         return DDERR_INVALIDPARAMS;
     }
 
-    hr = IDirect3DImpl_GetCaps(device->ddraw->wined3d, &oldDesc, &newDesc);
-    if (hr != D3D_OK)
+    if (FAILED(hr = ddraw_get_d3dcaps(device->ddraw, &desc7)))
         return hr;
 
-    DD_STRUCT_COPY_BYSIZE(HWDesc, &oldDesc);
-    DD_STRUCT_COPY_BYSIZE(HelDesc, &oldDesc);
+    ddraw_d3dcaps1_from_7(&desc1, &desc7);
+    DD_STRUCT_COPY_BYSIZE(HWDesc, &desc1);
+    DD_STRUCT_COPY_BYSIZE(HelDesc, &desc1);
     return D3D_OK;
 }
 
@@ -1069,7 +1051,9 @@ static HRESULT d3d_device7_EnumTextureFormats(IDirect3DDevice7 *iface,
         WINED3DFMT_P8_UINT,
         /* FOURCC codes */
         WINED3DFMT_DXT1,
+        WINED3DFMT_DXT2,
         WINED3DFMT_DXT3,
+        WINED3DFMT_DXT4,
         WINED3DFMT_DXT5,
     };
 
@@ -1808,62 +1792,88 @@ static HRESULT WINAPI d3d_device2_GetCurrentViewport(IDirect3DDevice2 *iface, ID
             (IDirect3DViewport3 **)viewport);
 }
 
-/*****************************************************************************
- * IDirect3DDevice7::SetRenderTarget
- *
- * Sets the render target for the Direct3DDevice.
- * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
- * IDirectDrawSurface3 == IDirectDrawSurface
- *
- * Version 2, 3 and 7
- *
- * Params:
- *  NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
- *             render target
- *  Flags: Some flags
- *
- * Returns:
- *  D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
- *
- *****************************************************************************/
-static HRESULT d3d_device_set_render_target(struct d3d_device *device, struct ddraw_surface *target)
+static BOOL validate_surface_palette(struct ddraw_surface *surface)
 {
-    HRESULT hr;
+    return !(surface->surface_desc.u4.ddpfPixelFormat.dwFlags
+            & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2
+            | DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8
+            | DDPF_PALETTEINDEXEDTO8))
+            || wined3d_surface_get_palette(surface->wined3d_surface);
+}
 
-    wined3d_mutex_lock();
+static HRESULT d3d_device_set_render_target(struct d3d_device *device,
+        struct ddraw_surface *target, IUnknown *rt_iface)
+{
+    HRESULT hr;
 
-    if (device->target == target)
+    if (device->rt_iface == rt_iface)
     {
         TRACE("No-op SetRenderTarget operation, not doing anything\n");
-        wined3d_mutex_unlock();
         return D3D_OK;
     }
-    device->target = target;
-    hr = wined3d_device_set_render_target(device->wined3d_device, 0,
-            target ? target->wined3d_surface : NULL, FALSE);
-    if(hr != D3D_OK)
+    if (!target)
     {
-        wined3d_mutex_unlock();
-        return hr;
+        WARN("Trying to set render target to NULL.\n");
+        return DDERR_INVALIDPARAMS;
     }
-    d3d_device_update_depth_stencil(device);
 
-    wined3d_mutex_unlock();
+    if (FAILED(hr = wined3d_device_set_render_target(device->wined3d_device,
+            0, target->wined3d_surface, FALSE)))
+        return hr;
+
+    IUnknown_AddRef(rt_iface);
+    IUnknown_Release(device->rt_iface);
+    device->rt_iface = rt_iface;
+    d3d_device_update_depth_stencil(device);
 
     return D3D_OK;
 }
 
 static HRESULT d3d_device7_SetRenderTarget(IDirect3DDevice7 *iface,
-        IDirectDrawSurface7 *NewTarget, DWORD flags)
+        IDirectDrawSurface7 *target, DWORD flags)
 {
+    struct ddraw_surface *target_impl = unsafe_impl_from_IDirectDrawSurface7(target);
     struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
-    struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface7(NewTarget);
+    HRESULT hr;
+
+    TRACE("iface %p, target %p, flags %#x.\n", iface, target, flags);
+
+    wined3d_mutex_lock();
+
+    if (!validate_surface_palette(target_impl))
+    {
+        WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl);
+        wined3d_mutex_unlock();
+        return DDERR_INVALIDCAPS;
+    }
 
-    TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, flags);
+    if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE))
+    {
+        WARN("Surface %p is not a render target.\n", target_impl);
+        wined3d_mutex_unlock();
+        return DDERR_INVALIDCAPS;
+    }
+
+    if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
+    {
+        WARN("Surface %p is not in video memory.\n", target_impl);
+        wined3d_mutex_unlock();
+        return DDERR_INVALIDPARAMS;
+    }
 
-    IDirectDrawSurface7_AddRef(NewTarget);
-    IDirectDrawSurface7_Release(&device->target->IDirectDrawSurface7_iface);
-    return d3d_device_set_render_target(device, target);
+    if (target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
+    {
+        WARN("Surface %p is a depth buffer.\n", target_impl);
+        IDirectDrawSurface7_AddRef(target);
+        IUnknown_Release(device->rt_iface);
+        device->rt_iface = (IUnknown *)target;
+        wined3d_mutex_unlock();
+        return DDERR_INVALIDPIXELFORMAT;
+    }
+
+    hr = d3d_device_set_render_target(device, target_impl, (IUnknown *)target);
+    wined3d_mutex_unlock();
+    return hr;
 }
 
 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
@@ -1886,29 +1896,102 @@ static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *
 }
 
 static HRESULT WINAPI d3d_device3_SetRenderTarget(IDirect3DDevice3 *iface,
-        IDirectDrawSurface4 *NewRenderTarget, DWORD flags)
+        IDirectDrawSurface4 *target, DWORD flags)
 {
+    struct ddraw_surface *target_impl = unsafe_impl_from_IDirectDrawSurface4(target);
     struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
-    struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface4(NewRenderTarget);
+    HRESULT hr;
 
-    TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, flags);
+    TRACE("iface %p, target %p, flags %#x.\n", iface, target, flags);
 
-    IDirectDrawSurface4_AddRef(NewRenderTarget);
-    IDirectDrawSurface4_Release(&device->target->IDirectDrawSurface4_iface);
-    return d3d_device_set_render_target(device, target);
+    wined3d_mutex_lock();
+
+    if (!validate_surface_palette(target_impl))
+    {
+        WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl);
+        wined3d_mutex_unlock();
+        return DDERR_INVALIDCAPS;
+    }
+
+    if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE))
+    {
+        WARN("Surface %p is not a render target.\n", target_impl);
+        wined3d_mutex_unlock();
+        return DDERR_INVALIDCAPS;
+    }
+
+    if (target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
+    {
+        WARN("Surface %p is a depth buffer.\n", target_impl);
+        IDirectDrawSurface4_AddRef(target);
+        IUnknown_Release(device->rt_iface);
+        device->rt_iface = (IUnknown *)target;
+        wined3d_mutex_unlock();
+        return DDERR_INVALIDPIXELFORMAT;
+    }
+
+    if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
+    {
+        WARN("Surface %p is not in video memory.\n", target_impl);
+        IDirectDrawSurface4_AddRef(target);
+        IUnknown_Release(device->rt_iface);
+        device->rt_iface = (IUnknown *)target;
+        wined3d_mutex_unlock();
+        return D3D_OK;
+    }
+
+    hr = d3d_device_set_render_target(device, target_impl, (IUnknown *)target);
+    wined3d_mutex_unlock();
+    return hr;
 }
 
 static HRESULT WINAPI d3d_device2_SetRenderTarget(IDirect3DDevice2 *iface,
-        IDirectDrawSurface *NewRenderTarget, DWORD flags)
+        IDirectDrawSurface *target, DWORD flags)
 {
+    struct ddraw_surface *target_impl = unsafe_impl_from_IDirectDrawSurface(target);
     struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
-    struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface(NewRenderTarget);
+    HRESULT hr;
 
-    TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, flags);
+    TRACE("iface %p, target %p, flags %#x.\n", iface, target, flags);
 
-    IDirectDrawSurface_AddRef(NewRenderTarget);
-    IDirectDrawSurface_Release(&device->target->IDirectDrawSurface_iface);
-    return d3d_device_set_render_target(device, target);
+    wined3d_mutex_lock();
+
+    if (!validate_surface_palette(target_impl))
+    {
+        WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl);
+        wined3d_mutex_unlock();
+        return DDERR_INVALIDCAPS;
+    }
+
+    if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE))
+    {
+        WARN("Surface %p is not a render target.\n", target_impl);
+        wined3d_mutex_unlock();
+        return DDERR_INVALIDCAPS;
+    }
+
+    if (target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
+    {
+        WARN("Surface %p is a depth buffer.\n", target_impl);
+        IUnknown_Release(device->rt_iface);
+        device->rt_iface = (IUnknown *)target;
+        wined3d_mutex_unlock();
+        return DDERR_INVALIDPIXELFORMAT;
+    }
+
+    if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
+    {
+        WARN("Surface %p is not in video memory.\n", target_impl);
+        IDirectDrawSurface_AddRef(target);
+        IUnknown_Release(device->rt_iface);
+        device->rt_iface = (IUnknown *)target;
+        wined3d_mutex_unlock();
+        return D3D_OK;
+    }
+
+    hr = d3d_device_set_render_target(device, target_impl, (IUnknown *)target);
+    wined3d_mutex_unlock();
+    return hr;
 }
 
 /*****************************************************************************
@@ -1931,6 +2014,7 @@ static HRESULT WINAPI d3d_device2_SetRenderTarget(IDirect3DDevice2 *iface,
 static HRESULT WINAPI d3d_device7_GetRenderTarget(IDirect3DDevice7 *iface, IDirectDrawSurface7 **RenderTarget)
 {
     struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
+    HRESULT hr;
 
     TRACE("iface %p, target %p.\n", iface, RenderTarget);
 
@@ -1938,11 +2022,10 @@ static HRESULT WINAPI d3d_device7_GetRenderTarget(IDirect3DDevice7 *iface, IDire
         return DDERR_INVALIDPARAMS;
 
     wined3d_mutex_lock();
-    *RenderTarget = &device->target->IDirectDrawSurface7_iface;
-    IDirectDrawSurface7_AddRef(*RenderTarget);
+    hr = IUnknown_QueryInterface(device->rt_iface, &IID_IDirectDrawSurface7, (void **)RenderTarget);
     wined3d_mutex_unlock();
 
-    return D3D_OK;
+    return hr;
 }
 
 static HRESULT WINAPI d3d_device3_GetRenderTarget(IDirect3DDevice3 *iface, IDirectDrawSurface4 **RenderTarget)
@@ -2367,9 +2450,9 @@ static HRESULT WINAPI d3d_device3_GetRenderState(IDirect3DDevice3 *iface,
             {
                 /* The parent of the texture is the IDirectDrawSurface7
                  * interface of the ddraw surface. */
-                struct ddraw_surface *parent = wined3d_texture_get_parent(tex);
+                struct ddraw_texture *parent = wined3d_texture_get_parent(tex);
                 if (parent)
-                    *value = parent->Handle;
+                    *value = parent->root->Handle;
             }
             wined3d_mutex_unlock();
 
@@ -4499,7 +4582,7 @@ static HRESULT d3d_device7_GetTexture(IDirect3DDevice7 *iface,
 {
     struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
     struct wined3d_texture *wined3d_texture;
-    struct ddraw_surface *surface;
+    struct ddraw_texture *ddraw_texture;
 
     TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
 
@@ -4514,8 +4597,8 @@ static HRESULT d3d_device7_GetTexture(IDirect3DDevice7 *iface,
         return D3D_OK;
     }
 
-    surface = wined3d_texture_get_parent(wined3d_texture);
-    *texture = &surface->IDirectDrawSurface7_iface;
+    ddraw_texture = wined3d_texture_get_parent(wined3d_texture);
+    *texture = &ddraw_texture->root->IDirectDrawSurface7_iface;
     IDirectDrawSurface7_AddRef(*texture);
     wined3d_mutex_unlock();
 
@@ -4581,14 +4664,16 @@ static HRESULT d3d_device7_SetTexture(IDirect3DDevice7 *iface,
 {
     struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
     struct ddraw_surface *surf = unsafe_impl_from_IDirectDrawSurface7(texture);
+    struct wined3d_texture *wined3d_texture = NULL;
     HRESULT hr;
 
     TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
 
-    /* Texture may be NULL here */
+    if (surf && (surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE))
+        wined3d_texture = surf->wined3d_texture;
+
     wined3d_mutex_lock();
-    hr = wined3d_device_set_texture(device->wined3d_device,
-            stage, surf ? surf->wined3d_texture : NULL);
+    hr = wined3d_device_set_texture(device->wined3d_device, stage, wined3d_texture);
     wined3d_mutex_unlock();
 
     return hr;
@@ -6667,10 +6752,16 @@ struct d3d_device *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
 enum wined3d_depth_buffer_type d3d_device_update_depth_stencil(struct d3d_device *device)
 {
     IDirectDrawSurface7 *depthStencil = NULL;
+    IDirectDrawSurface7 *render_target;
     static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, {0} };
     struct ddraw_surface *dsi;
 
-    IDirectDrawSurface7_GetAttachedSurface(&device->target->IDirectDrawSurface7_iface, &depthcaps, &depthStencil);
+    if (device->rt_iface && SUCCEEDED(IUnknown_QueryInterface(device->rt_iface,
+            &IID_IDirectDrawSurface7, (void **)&render_target)))
+    {
+        IDirectDrawSurface7_GetAttachedSurface(render_target, &depthcaps, &depthStencil);
+        IDirectDrawSurface7_Release(render_target);
+    }
     if (!depthStencil)
     {
         TRACE("Setting wined3d depth stencil to NULL\n");
@@ -6687,7 +6778,7 @@ enum wined3d_depth_buffer_type d3d_device_update_depth_stencil(struct d3d_device
 }
 
 static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw,
-        struct ddraw_surface *target, UINT version, IUnknown *outer_unknown)
+        struct ddraw_surface *target, IUnknown *rt_iface, UINT version, IUnknown *outer_unknown)
 {
     static const D3DMATRIX ident =
     {
@@ -6716,7 +6807,6 @@ static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw,
         device->outer_unknown = &device->IUnknown_inner;
 
     device->ddraw = ddraw;
-    device->target = target;
     list_init(&device->viewport_list);
 
     if (!ddraw_handle_table_init(&device->handle_table, 64))
@@ -6742,17 +6832,9 @@ static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw,
         return hr;
     }
 
-    /* FIXME: This is broken. The target AddRef() makes some sense, because
-     * we store a pointer during initialization, but then that's also where
-     * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
-    /* AddRef the render target. Also AddRef the render target from ddraw,
-     * because if it is released before the app releases the D3D device, the
-     * D3D capabilities of wined3d will be uninitialized, which has bad effects.
-     *
-     * In most cases, those surfaces are the same anyway, but this will simply
-     * add another ref which is released when the device is destroyed. */
+    device->rt_iface = rt_iface;
     if (version != 1)
-        IDirectDrawSurface7_AddRef(&target->IDirectDrawSurface7_iface);
+        IUnknown_AddRef(device->rt_iface);
 
     ddraw->d3ddevice = device;
 
@@ -6766,7 +6848,7 @@ static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw,
     return D3D_OK;
 }
 
-HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target,
+HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target, IUnknown *rt_iface,
         UINT version, struct d3d_device **device, IUnknown *outer_unknown)
 {
     struct d3d_device *object;
@@ -6775,6 +6857,25 @@ 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 (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
+            || (target->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
+    {
+        WARN("Surface %p is not a render target.\n", target);
+        return DDERR_INVALIDCAPS;
+    }
+
+    if (!validate_surface_palette(target))
+    {
+        WARN("Surface %p has an indexed pixel format, but no palette.\n", target);
+        return DDERR_NOPALETTEATTACHED;
+    }
+
+    if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
+    {
+        WARN("Surface %p is not in video memory.\n", target);
+        return D3DERR_SURFACENOTINVIDMEM;
+    }
+
     if (ddraw->flags & DDRAW_NO3D)
     {
         ERR_(winediag)("The application wants to create a Direct3D device, "
@@ -6796,8 +6897,7 @@ HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target,
         return DDERR_OUTOFMEMORY;
     }
 
-    hr = d3d_device_init(object, ddraw, target, version, outer_unknown);
-    if (FAILED(hr))
+    if (FAILED(hr = d3d_device_init(object, ddraw, target, rt_iface, version, outer_unknown)))
     {
         WARN("Failed to initialize device, hr %#x.\n", hr);
         HeapFree(GetProcessHeap(), 0, object);
index 8a98011..d9665d0 100644 (file)
  */
 
 #include "ddraw_private.h"
-
 #include <winreg.h>
 #include <rpcproxy.h>
 
-#include <wine/exception.h>
+#include "wine/exception.h"
 
 static struct list global_ddraw_list = LIST_INIT(global_ddraw_list);
 
@@ -54,6 +53,37 @@ static HRESULT CALLBACK enum_callback(GUID *guid, char *description, char *drive
     return info->callback(guid, description, driver_name, info->context);
 }
 
+static void ddraw_enumerate_secondary_devices(struct wined3d *wined3d, LPDDENUMCALLBACKEXA callback,
+                                              void *context)
+{
+    struct wined3d_adapter_identifier adapter_id;
+    BOOL cont_enum = TRUE;
+    HRESULT hr = S_OK;
+    UINT adapter = 0;
+
+    for (adapter = 0; SUCCEEDED(hr) && cont_enum; adapter++)
+    {
+        char DriverName[512] = "", DriverDescription[512] = "";
+
+        /* The Battle.net System Checker expects the GetAdapterIdentifier DeviceName to match the
+         * Driver Name, so obtain the DeviceName and GUID from D3D. */
+        memset(&adapter_id, 0x0, sizeof(adapter_id));
+        adapter_id.device_name = DriverName;
+        adapter_id.device_name_size = sizeof(DriverName);
+        adapter_id.description = DriverDescription;
+        adapter_id.description_size = sizeof(DriverDescription);
+        wined3d_mutex_lock();
+        hr = wined3d_get_adapter_identifier(wined3d, adapter, 0x0, &adapter_id);
+        wined3d_mutex_unlock();
+        if (SUCCEEDED(hr))
+        {
+            TRACE("Interface %d: %s\n", adapter, wine_dbgstr_guid(&adapter_id.device_identifier));
+            cont_enum = callback(&adapter_id.device_identifier, adapter_id.description,
+                    adapter_id.device_name, context, wined3d_get_adapter_monitor(wined3d, adapter));
+        }
+    }
+}
+
 /* Handle table functions */
 BOOL ddraw_handle_table_init(struct ddraw_handle_table *t, UINT initial_size)
 {
@@ -291,28 +321,25 @@ HRESULT WINAPI DECLSPEC_HOTPATCH DirectDrawCreate(GUID *driver_guid, IDirectDraw
  * Arguments, return values: See DDRAW_Create
  *
  ***********************************************************************/
-HRESULT WINAPI DECLSPEC_HOTPATCH
-DirectDrawCreateEx(GUID *guid,
-                   LPVOID *dd,
-                   REFIID iid,
-                   IUnknown *UnkOuter)
+HRESULT WINAPI DECLSPEC_HOTPATCH DirectDrawCreateEx(GUID *driver_guid,
+        void **ddraw, REFIID interface_iid, IUnknown *outer)
 {
     HRESULT hr;
 
-    TRACE("driver_guid %s, ddraw %p, interface_iid %s, outer_unknown %p.\n",
-            debugstr_guid(guid), dd, debugstr_guid(iid), UnkOuter);
+    TRACE("driver_guid %s, ddraw %p, interface_iid %s, outer %p.\n",
+            debugstr_guid(driver_guid), ddraw, debugstr_guid(interface_iid), outer);
 
-    if (!IsEqualGUID(iid, &IID_IDirectDraw7))
+    if (!IsEqualGUID(interface_iid, &IID_IDirectDraw7))
         return DDERR_INVALIDPARAMS;
 
     wined3d_mutex_lock();
-    hr = DDRAW_Create(guid, dd, UnkOuter, iid);
+    hr = DDRAW_Create(driver_guid, ddraw, outer, interface_iid);
     wined3d_mutex_unlock();
 
     if (SUCCEEDED(hr))
     {
-        IDirectDraw7 *ddraw7 = *(IDirectDraw7 **)dd;
-        hr = IDirectDraw7_Initialize(ddraw7, guid);
+        IDirectDraw7 *ddraw7 = *(IDirectDraw7 **)ddraw;
+        hr = IDirectDraw7_Initialize(ddraw7, driver_guid);
         if (FAILED(hr))
             IDirectDraw7_Release(ddraw7);
     }
@@ -371,8 +398,8 @@ HRESULT WINAPI DirectDrawEnumerateExA(LPDDENUMCALLBACKEXA callback, void *contex
                   DDENUM_NONDISPLAYDEVICES))
         return DDERR_INVALIDPARAMS;
 
-    if (flags)
-        FIXME("flags 0x%08x not handled\n", flags);
+    if (flags & ~DDENUM_ATTACHEDSECONDARYDEVICES)
+        FIXME("flags 0x%08x not handled\n", flags & ~DDENUM_ATTACHEDSECONDARYDEVICES);
 
     TRACE("Enumerating ddraw interfaces\n");
     if (!(wined3d = wined3d_create(7, WINED3D_LEGACY_DEPTH_BIAS)))
@@ -391,33 +418,14 @@ HRESULT WINAPI DirectDrawEnumerateExA(LPDDENUMCALLBACKEXA callback, void *contex
         /* QuickTime expects the description "DirectDraw HAL" */
         static CHAR driver_desc[] = "DirectDraw HAL",
         driver_name[] = "display";
-        struct wined3d_adapter_identifier adapter_id;
-        HRESULT hr = S_OK;
-        UINT adapter = 0;
         BOOL cont_enum;
 
-        /* The Battle.net System Checker expects both a NULL device and a GUID-based device */
         TRACE("Default interface: DirectDraw HAL\n");
         cont_enum = callback(NULL, driver_desc, driver_name, context, 0);
-        for (adapter = 0; SUCCEEDED(hr) && cont_enum; adapter++)
-        {
-            char DriverName[512] = "";
-
-            /* The Battle.net System Checker expects the GetAdapterIdentifier DeviceName to match the
-             * Driver Name, so obtain the DeviceName and GUID from D3D. */
-            memset(&adapter_id, 0x0, sizeof(adapter_id));
-            adapter_id.device_name = DriverName;
-            adapter_id.device_name_size = sizeof(DriverName);
-            wined3d_mutex_lock();
-            hr = wined3d_get_adapter_identifier(wined3d, adapter, 0x0, &adapter_id);
-            wined3d_mutex_unlock();
-            if (SUCCEEDED(hr))
-            {
-                TRACE("Interface %d: %s\n", adapter, wine_dbgstr_guid(&adapter_id.device_identifier));
-                cont_enum = callback(&adapter_id.device_identifier, driver_desc,
-                                     adapter_id.device_name, context, 0);
-            }
-        }
+
+        /* The Battle.net System Checker expects both a NULL device and a GUID-based device */
+        if (cont_enum && (flags & ~DDENUM_ATTACHEDSECONDARYDEVICES))
+            ddraw_enumerate_secondary_devices(wined3d, callback, context);
     }
     __EXCEPT_PAGE_FAULT
     {
@@ -546,7 +554,7 @@ struct ddraw_class_factory
     IClassFactory IClassFactory_iface;
 
     LONG ref;
-    HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, REFIID iid, LPVOID *ppObj);
+    HRESULT (*pfnCreateInstance)(IUnknown *outer, REFIID iid, void **out);
 };
 
 static inline struct ddraw_class_factory *impl_from_IClassFactory(IClassFactory *iface)
@@ -682,30 +690,13 @@ static const IClassFactoryVtbl IClassFactory_Vtbl =
     ddraw_class_factory_LockServer
 };
 
-/*******************************************************************************
- * DllGetClassObject [DDRAW.@]
- * Retrieves class object from a DLL object
- *
- * NOTES
- *    Docs say returns STDAPI
- *
- * PARAMS
- *    rclsid [I] CLSID for the class object
- *    riid   [I] Reference to identifier of interface for class object
- *    ppv    [O] Address of variable to receive interface pointer for riid
- *
- * RETURNS
- *    Success: S_OK
- *    Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
- *             E_UNEXPECTED
- */
-HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
+HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **out)
 {
     struct ddraw_class_factory *factory;
     unsigned int i;
 
-    TRACE("rclsid %s, riid %s, object %p.\n",
-            debugstr_guid(rclsid), debugstr_guid(riid), ppv);
+    TRACE("rclsid %s, riid %s, out %p.\n",
+            debugstr_guid(rclsid), debugstr_guid(riid), out);
 
     if (!IsEqualGUID(&IID_IClassFactory, riid)
             && !IsEqualGUID(&IID_IUnknown, riid))
@@ -731,7 +722,7 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
 
     factory->pfnCreateInstance = object_creation[i].pfnCreateInstance;
 
-    *ppv = factory;
+    *out = factory;
     return S_OK;
 }
 
@@ -813,19 +804,6 @@ DestroyCallback(IDirectDrawSurface7 *surf,
     return DDENUMRET_OK;
 }
 
-/***********************************************************************
- * get_config_key
- *
- * Reads a config key from the registry. Taken from WineD3D
- *
- ***********************************************************************/
-static inline DWORD get_config_key(HKEY defkey, HKEY appkey, const char* name, char* buffer, DWORD size)
-{
-    if (0 != appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE) buffer, &size )) return 0;
-    if (0 != defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE) buffer, &size )) return 0;
-    return ERROR_FILE_NOT_FOUND;
-}
-
 /***********************************************************************
  * DllMain (DDRAW.0)
  *
@@ -834,9 +812,8 @@ 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 reserved)
+BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, void *reserved)
 {
-    TRACE("(%p,%x,%p)\n", hInstDLL, reason, reserved);
     switch (reason)
     {
     case DLL_PROCESS_ATTACH:
@@ -852,7 +829,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD reason, LPVOID reserved)
         wc.lpfnWndProc = DefWindowProcA;
         wc.cbClsExtra = 0;
         wc.cbWndExtra = 0;
-        wc.hInstance = hInstDLL;
+        wc.hInstance = inst;
         wc.hIcon = 0;
         wc.hCursor = 0;
         wc.hbrBackground = GetStockObject(BLACK_BRUSH);
@@ -889,7 +866,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD reason, LPVOID reserved)
             DWORD type, data, size;
 
             size = sizeof(data);
-            if (!RegQueryValueExA( hkey, "ForceRefreshRate", NULL, &type, (LPBYTE)&data, &size ) && type == REG_DWORD)
+            if (!RegQueryValueExA(hkey, "ForceRefreshRate", NULL, &type, (BYTE *)&data, &size) && type == REG_DWORD)
             {
                 TRACE("ForceRefreshRate set; overriding refresh rate to %d Hz\n", data);
                 force_refresh_rate = data;
@@ -901,14 +878,13 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD reason, LPVOID reserved)
          * exclusive mode, we replace the window proc of the ddraw window. If
          * an application would unload ddraw from the WM_DESTROY handler for
          * that window, it would return to unmapped memory and die. Apparently
-         * this is supposed to work on Windows. We should probably use
-         * GET_MODULE_HANDLE_EX_FLAG_PIN for this, but that's not currently
-         * implemented. */
-        if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (const WCHAR *)&ddraw_self, &ddraw_self))
+         * this is supposed to work on Windows. */
+        if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_PIN,
+                (const WCHAR *)&ddraw_self, &ddraw_self))
             ERR("Failed to get own module handle.\n");
 
-        instance = hInstDLL;
-        DisableThreadLibraryCalls(hInstDLL);
+        instance = inst;
+        DisableThreadLibraryCalls(inst);
         break;
     }
 
@@ -977,7 +953,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD reason, LPVOID reserved)
         }
 
         if (reserved) break;
-        UnregisterClassA(DDRAW_WINDOW_CLASS_NAME, hInstDLL);
+        UnregisterClassA(DDRAW_WINDOW_CLASS_NAME, inst);
     }
 
     return TRUE;
index cd43e82..fca2706 100644 (file)
@@ -89,10 +89,10 @@ static ULONG WINAPI ddraw_palette_Release(IDirectDrawPalette *iface)
     {
         wined3d_mutex_lock();
         wined3d_palette_decref(This->wineD3DPalette);
-        if(This->ifaceToRelease)
-        {
+        if ((This->flags & DDPCAPS_PRIMARYSURFACE) && This->ddraw->primary)
+            This->ddraw->primary->palette = NULL;
+        if (This->ifaceToRelease)
             IUnknown_Release(This->ifaceToRelease);
-        }
         wined3d_mutex_unlock();
 
         HeapFree(GetProcessHeap(), 0, This);
@@ -125,20 +125,6 @@ static HRESULT WINAPI ddraw_palette_Initialize(IDirectDrawPalette *iface,
     return DDERR_ALREADYINITIALIZED;
 }
 
-/*****************************************************************************
- * IDirectDrawPalette::GetCaps
- *
- * Returns the palette description
- *
- * Params:
- *  Caps: Address to store the caps at
- *
- * Returns:
- *  D3D_OK on success
- *  DDERR_INVALIDPARAMS if Caps is NULL
- *  For more details, see IWineD3DPalette::GetCaps
- *
- *****************************************************************************/
 static HRESULT WINAPI ddraw_palette_GetCaps(IDirectDrawPalette *iface, DWORD *caps)
 {
     struct ddraw_palette *palette = impl_from_IDirectDrawPalette(iface);
@@ -146,7 +132,7 @@ static HRESULT WINAPI ddraw_palette_GetCaps(IDirectDrawPalette *iface, DWORD *ca
     TRACE("iface %p, caps %p.\n", iface, caps);
 
     wined3d_mutex_lock();
-    *caps = wined3d_palette_get_flags(palette->wineD3DPalette);
+    *caps = palette->flags;
     wined3d_mutex_unlock();
 
     return D3D_OK;
@@ -245,22 +231,55 @@ struct ddraw_palette *unsafe_impl_from_IDirectDrawPalette(IDirectDrawPalette *if
     return CONTAINING_RECORD(iface, struct ddraw_palette, IDirectDrawPalette_iface);
 }
 
+static unsigned int palette_size(DWORD flags)
+{
+    switch (flags & (DDPCAPS_1BIT | DDPCAPS_2BIT | DDPCAPS_4BIT | DDPCAPS_8BIT))
+    {
+        case DDPCAPS_1BIT:
+            return 2;
+        case DDPCAPS_2BIT:
+            return 4;
+        case DDPCAPS_4BIT:
+            return 16;
+        case DDPCAPS_8BIT:
+            return 256;
+        default:
+            return ~0u;
+    }
+}
+
 HRESULT ddraw_palette_init(struct ddraw_palette *palette,
         struct ddraw *ddraw, DWORD flags, PALETTEENTRY *entries)
 {
+    unsigned int entry_count;
+    DWORD wined3d_flags = 0;
     HRESULT hr;
 
+    if ((entry_count = palette_size(flags)) == ~0u)
+    {
+        WARN("Invalid flags %#x.\n", flags);
+        return DDERR_INVALIDPARAMS;
+    }
+
+    if (flags & DDPCAPS_8BITENTRIES)
+        wined3d_flags |= WINED3D_PALETTE_8BIT_ENTRIES;
+    if (flags & DDPCAPS_ALLOW256)
+        wined3d_flags |= WINED3D_PALETTE_ALLOW_256;
+    if (flags & DDPCAPS_ALPHA)
+        wined3d_flags |= WINED3D_PALETTE_ALPHA;
+
     palette->IDirectDrawPalette_iface.lpVtbl = &ddraw_palette_vtbl;
     palette->ref = 1;
+    palette->flags = flags;
 
-    hr = wined3d_palette_create(ddraw->wined3d_device, flags,
-            entries, palette, &palette->wineD3DPalette);
-    if (FAILED(hr))
+    if (FAILED(hr = wined3d_palette_create(ddraw->wined3d_device,
+            wined3d_flags, entry_count, entries, &palette->wineD3DPalette)))
     {
         WARN("Failed to create wined3d palette, hr %#x.\n", hr);
         return hr;
     }
 
+    palette->ddraw = ddraw;
     palette->ifaceToRelease = (IUnknown *)&ddraw->IDirectDraw7_iface;
     IUnknown_AddRef(palette->ifaceToRelease);
 
index b13708d..9a35b1a 100644 (file)
@@ -202,9 +202,10 @@ static HRESULT WINAPI ddraw_surface7_QueryInterface(IDirectDrawSurface7 *iface,
             wined3d_mutex_lock();
             if (!This->device1)
             {
-                HRESULT hr = d3d_device_create(This->ddraw, This, 1, &This->device1,
-                        (IUnknown *)&This->IDirectDrawSurface_iface);
-                if (FAILED(hr))
+                HRESULT hr;
+
+                if (FAILED(hr = d3d_device_create(This->ddraw, This, (IUnknown *)&This->IDirectDrawSurface_iface,
+                        1, &This->device1, (IUnknown *)&This->IDirectDrawSurface_iface)))
                 {
                     This->device1 = NULL;
                     wined3d_mutex_unlock();
@@ -463,7 +464,8 @@ static void ddraw_surface_cleanup(struct ddraw_surface *surface)
 
         surf = surface->complex_array[i];
         surface->complex_array[i] = NULL;
-        ddraw_surface_cleanup(surf);
+        if (!surf->is_complex_root)
+            ddraw_surface_cleanup(surf);
     }
 
     if (surface->device1)
@@ -478,6 +480,8 @@ static void ddraw_surface_cleanup(struct ddraw_surface *surface)
                 surface, surface->ref7, surface->ref4, surface->ref3, surface->ref2, surface->ref1);
     }
 
+    if (surface->wined3d_texture)
+        wined3d_texture_decref(surface->wined3d_texture);
     if (surface->wined3d_surface)
         wined3d_surface_decref(surface->wined3d_surface);
 }
@@ -499,10 +503,7 @@ ULONG ddraw_surface_release_iface(struct ddraw_surface *This)
             wined3d_mutex_unlock();
             return iface_count;
         }
-        if (This->wined3d_texture) /* If it's a texture, destroy the wined3d texture. */
-            wined3d_texture_decref(This->wined3d_texture);
-        else
-            ddraw_surface_cleanup(This);
+        ddraw_surface_cleanup(This);
         wined3d_mutex_unlock();
 
         if (release_iface)
@@ -934,7 +935,7 @@ static HRESULT surface_lock(struct ddraw_surface *This,
         }
     }
 
-    if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
+    if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
         hr = ddraw_surface_update_frontbuffer(This, Rect, TRUE);
     if (SUCCEEDED(hr))
         hr = wined3d_surface_map(This->wined3d_surface, &map_desc, Rect, Flags);
@@ -954,7 +955,7 @@ static HRESULT surface_lock(struct ddraw_surface *This,
         }
     }
 
-    if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
+    if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
     {
         if (Flags & DDLOCK_READONLY)
             memset(&This->ddraw->primary_lock, 0, sizeof(This->ddraw->primary_lock));
@@ -1116,7 +1117,7 @@ static HRESULT WINAPI ddraw_surface7_Unlock(IDirectDrawSurface7 *iface, RECT *pR
     hr = wined3d_surface_unmap(surface->wined3d_surface);
     if (SUCCEEDED(hr))
     {
-        if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
+        if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
             hr = ddraw_surface_update_frontbuffer(surface, &surface->ddraw->primary_lock, FALSE);
         surface->surface_desc.lpSurface = NULL;
     }
@@ -1164,64 +1165,109 @@ static HRESULT WINAPI ddraw_surface1_Unlock(IDirectDrawSurface *iface, void *dat
     return ddraw_surface7_Unlock(&surface->IDirectDrawSurface7_iface, NULL);
 }
 
-/*****************************************************************************
- * IDirectDrawSurface7::Flip
- *
- * Flips a surface with the DDSCAPS_FLIP flag. The flip is relayed to
- * IWineD3DSurface::Flip. Because WineD3D doesn't handle attached surfaces,
- * the flip target is passed to WineD3D, even if the app didn't specify one
- *
- * Params:
- *  DestOverride: Specifies the surface that will become the new front
- *                buffer. If NULL, the current back buffer is used
- *  Flags: some DirectDraw flags, see include/ddraw.h
- *
- * Returns:
- *  DD_OK on success
- *  DDERR_NOTFLIPPABLE if no flip target could be found
- *  DDERR_INVALIDOBJECT if the surface isn't a front buffer
- *  For more details, see IWineD3DSurface::Flip
- *
- *****************************************************************************/
-static HRESULT WINAPI ddraw_surface7_Flip(IDirectDrawSurface7 *iface, IDirectDrawSurface7 *DestOverride, DWORD Flags)
+static HRESULT WINAPI ddraw_surface7_Flip(IDirectDrawSurface7 *iface, IDirectDrawSurface7 *src, DWORD flags)
 {
-    struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
-    struct ddraw_surface *Override = unsafe_impl_from_IDirectDrawSurface7(DestOverride);
-    IDirectDrawSurface7 *Override7;
+    struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface7(iface);
+    struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface7(src);
+    struct ddraw_texture *ddraw_texture, *prev_ddraw_texture;
+    DDSCAPS2 caps = {DDSCAPS_FLIP, 0, 0, {0}};
+    struct wined3d_surface *tmp, *rt;
+    struct wined3d_texture *texture;
+    IDirectDrawSurface7 *current;
     HRESULT hr;
 
-    TRACE("iface %p, dst %p, flags %#x.\n", iface, DestOverride, Flags);
+    TRACE("iface %p, src %p, flags %#x.\n", iface, src, flags);
 
-    /* Flip has to be called from a front buffer
-     * What about overlay surfaces, AFAIK they can flip too? */
-    if (!(surface->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_OVERLAY)))
-        return DDERR_INVALIDOBJECT; /* Unchecked */
+    if (src == iface || !(dst_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_OVERLAY)))
+        return DDERR_NOTFLIPPABLE;
 
     wined3d_mutex_lock();
 
-    /* WineD3D doesn't keep track of attached surface, so find the target */
-    if(!Override)
+    tmp = dst_impl->wined3d_surface;
+    texture = dst_impl->wined3d_texture;
+    rt = wined3d_device_get_render_target(dst_impl->ddraw->wined3d_device, 0);
+    ddraw_texture = wined3d_texture_get_parent(dst_impl->wined3d_texture);
+
+    if (src_impl)
     {
-        DDSCAPS2 Caps;
+        for (current = iface; current != src;)
+        {
+            if (FAILED(hr = ddraw_surface7_GetAttachedSurface(current, &caps, &current)))
+            {
+                WARN("Surface %p is not on the same flip chain as surface %p.\n", src, iface);
+                wined3d_mutex_unlock();
+                return DDERR_NOTFLIPPABLE;
+            }
+            ddraw_surface7_Release(current);
+            if (current == iface)
+            {
+                WARN("Surface %p is not on the same flip chain as surface %p.\n", src, iface);
+                wined3d_mutex_unlock();
+                return DDERR_NOTFLIPPABLE;
+            }
+        }
 
-        memset(&Caps, 0, sizeof(Caps));
-        Caps.dwCaps |= DDSCAPS_BACKBUFFER;
-        hr = ddraw_surface7_GetAttachedSurface(iface, &Caps, &Override7);
-        if(hr != DD_OK)
+        if (rt == dst_impl->wined3d_surface)
+            wined3d_device_set_render_target(dst_impl->ddraw->wined3d_device, 0, src_impl->wined3d_surface, FALSE);
+        wined3d_resource_set_parent(wined3d_surface_get_resource(src_impl->wined3d_surface), dst_impl);
+        dst_impl->wined3d_surface = src_impl->wined3d_surface;
+        prev_ddraw_texture = wined3d_texture_get_parent(src_impl->wined3d_texture);
+        wined3d_resource_set_parent(wined3d_texture_get_resource(src_impl->wined3d_texture), ddraw_texture);
+        dst_impl->wined3d_texture = src_impl->wined3d_texture;
+        ddraw_texture = prev_ddraw_texture;
+    }
+    else
+    {
+        for (current = iface;;)
         {
-            ERR("Can't find a flip target\n");
-            wined3d_mutex_unlock();
-            return DDERR_NOTFLIPPABLE; /* Unchecked */
+            if (FAILED(hr = ddraw_surface7_GetAttachedSurface(current, &caps, &current)))
+            {
+                ERR("Can't find a flip target\n");
+                wined3d_mutex_unlock();
+                return DDERR_NOTFLIPPABLE; /* Unchecked */
+            }
+            ddraw_surface7_Release(current);
+            if (current == iface)
+            {
+                dst_impl = impl_from_IDirectDrawSurface7(iface);
+                break;
+            }
+
+            src_impl = impl_from_IDirectDrawSurface7(current);
+            if (rt == dst_impl->wined3d_surface)
+                wined3d_device_set_render_target(dst_impl->ddraw->wined3d_device, 0, src_impl->wined3d_surface, FALSE);
+            wined3d_resource_set_parent(wined3d_surface_get_resource(src_impl->wined3d_surface), dst_impl);
+            dst_impl->wined3d_surface = src_impl->wined3d_surface;
+            prev_ddraw_texture = wined3d_texture_get_parent(src_impl->wined3d_texture);
+            wined3d_resource_set_parent(wined3d_texture_get_resource(src_impl->wined3d_texture), ddraw_texture);
+            ddraw_texture = prev_ddraw_texture;
+            dst_impl->wined3d_texture = src_impl->wined3d_texture;
+            dst_impl = src_impl;
         }
-        Override = impl_from_IDirectDrawSurface7(Override7);
+    }
+
+    /* We don't have to worry about potential texture bindings, since
+     * flippable surfaces can never be textures. */
+    if (rt == src_impl->wined3d_surface)
+        wined3d_device_set_render_target(dst_impl->ddraw->wined3d_device, 0, tmp, FALSE);
+    wined3d_resource_set_parent(wined3d_surface_get_resource(tmp), src_impl);
+    src_impl->wined3d_surface = tmp;
+    wined3d_resource_set_parent(wined3d_texture_get_resource(texture), ddraw_texture);
+    src_impl->wined3d_texture = texture;
 
-        /* For the GetAttachedSurface */
-        ddraw_surface7_Release(Override7);
+    if (flags)
+    {
+        static UINT once;
+        if (!once++)
+            FIXME("Ignoring flags %#x.\n", flags);
+        else
+            WARN("Ignoring flags %#x.\n", flags);
     }
 
-    hr = wined3d_surface_flip(surface->wined3d_surface, Override->wined3d_surface, Flags);
-    if (SUCCEEDED(hr) && surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
-        hr = ddraw_surface_update_frontbuffer(surface, NULL, FALSE);
+    if (dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
+        hr = ddraw_surface_update_frontbuffer(dst_impl, NULL, FALSE);
+    else
+        hr = DD_OK;
 
     wined3d_mutex_unlock();
 
@@ -1287,12 +1333,12 @@ static HRESULT ddraw_surface_blt_clipped(struct ddraw_surface *dst_surface, cons
 
     if (!dst_surface->clipper)
     {
-        if (src_surface && src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
+        if (src_surface && src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
             hr = ddraw_surface_update_frontbuffer(src_surface, src_rect_in, TRUE);
         if (SUCCEEDED(hr))
             hr = wined3d_surface_blt(dst_surface->wined3d_surface, dst_rect_in,
                     wined3d_src_surface, src_rect_in, flags, fx, filter);
-        if (SUCCEEDED(hr) && (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER))
+        if (SUCCEEDED(hr) && (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
             hr = ddraw_surface_update_frontbuffer(dst_surface, dst_rect_in, FALSE);
 
         return hr;
@@ -1371,7 +1417,7 @@ static HRESULT ddraw_surface_blt_clipped(struct ddraw_surface *dst_surface, cons
             src_rect_clipped.right -= (LONG)((dst_rect.right - clip_rect[i].right) * scale_x);
             src_rect_clipped.bottom -= (LONG)((dst_rect.bottom - clip_rect[i].bottom) * scale_y);
 
-            if (src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
+            if (src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
             {
                 if (FAILED(hr = ddraw_surface_update_frontbuffer(src_surface, &src_rect_clipped, TRUE)))
                     break;
@@ -1382,7 +1428,7 @@ static HRESULT ddraw_surface_blt_clipped(struct ddraw_surface *dst_surface, cons
                 wined3d_src_surface, &src_rect_clipped, flags, fx, filter)))
             break;
 
-        if (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
+        if (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
         {
             if (FAILED(hr = ddraw_surface_update_frontbuffer(dst_surface, &clip_rect[i], FALSE)))
                 break;
@@ -1930,7 +1976,7 @@ static HRESULT WINAPI ddraw_surface7_GetDC(IDirectDrawSurface7 *iface, HDC *hdc)
         return DDERR_INVALIDPARAMS;
 
     wined3d_mutex_lock();
-    if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
+    if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
         hr = ddraw_surface_update_frontbuffer(surface, NULL, TRUE);
     if (SUCCEEDED(hr))
         hr = wined3d_surface_getdc(surface->wined3d_surface, hdc);
@@ -2006,7 +2052,7 @@ static HRESULT WINAPI ddraw_surface7_ReleaseDC(IDirectDrawSurface7 *iface, HDC h
 
     wined3d_mutex_lock();
     hr = wined3d_surface_releasedc(surface->wined3d_surface, hdc);
-    if (SUCCEEDED(hr) && (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER))
+    if (SUCCEEDED(hr) && (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
         hr = ddraw_surface_update_frontbuffer(surface, NULL, FALSE);
     wined3d_mutex_unlock();
 
@@ -3965,12 +4011,12 @@ static HRESULT WINAPI ddraw_surface7_BltFast(IDirectDrawSurface7 *iface, DWORD d
         return DDERR_BLTFASTCANTCLIP;
     }
 
-    if (src->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
+    if (src->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
         hr = ddraw_surface_update_frontbuffer(src, rsrc, TRUE);
     if (SUCCEEDED(hr))
         hr = wined3d_surface_blt(This->wined3d_surface, &dst_rect,
                 src->wined3d_surface, rsrc, flags, NULL, WINED3D_TEXF_POINT);
-    if (SUCCEEDED(hr) && (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER))
+    if (SUCCEEDED(hr) && (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
         hr = ddraw_surface_update_frontbuffer(This, &dst_rect, FALSE);
     wined3d_mutex_unlock();
 
@@ -4227,7 +4273,6 @@ static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface,
     const DWORD allowed_flags = DDSD_LPSURFACE | DDSD_PIXELFORMAT | DDSD_WIDTH
             | DDSD_HEIGHT | DDSD_PITCH | DDSD_CAPS;
     enum wined3d_format_id format_id;
-    BOOL update_wined3d = FALSE;
     UINT pitch, width, height;
 
     TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, DDSD, Flags);
@@ -4242,7 +4287,9 @@ static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface,
         WARN("Flags is %x, returning DDERR_INVALIDPARAMS\n", Flags);
         return DDERR_INVALIDPARAMS;
     }
-    if (!(This->surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY))
+    if (!(This->surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
+            || This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE
+            || This->surface_desc.ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE))
     {
         WARN("Surface is not in system memory, returning DDERR_INVALIDSURFACETYPE.\n");
         return DDERR_INVALIDSURFACETYPE;
@@ -4255,12 +4302,12 @@ static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface,
         WARN("Invalid flags (0x%08x) set, returning DDERR_INVALIDPARAMS\n", DDSD->dwFlags);
         return DDERR_INVALIDPARAMS;
     }
-    if (!(DDSD->dwFlags & DDSD_LPSURFACE))
+    if (!(DDSD->dwFlags & DDSD_LPSURFACE) || !DDSD->lpSurface)
     {
-        WARN("DDSD_LPSURFACE is not set, returning DDERR_INVALIDPARAMS\n");
+        WARN("DDSD_LPSURFACE is not set or lpSurface is NULL, returning DDERR_INVALIDPARAMS\n");
         return DDERR_INVALIDPARAMS;
     }
-    if (DDSD->dwFlags & DDSD_CAPS)
+    if ((DDSD->dwFlags & DDSD_CAPS) && DDSD->ddsCaps.dwCaps)
     {
         WARN("DDSD_CAPS is set, returning DDERR_INVALIDCAPS.\n");
         return DDERR_INVALIDCAPS;
@@ -4279,15 +4326,9 @@ static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface,
             return DDERR_INVALIDPARAMS;
         }
         if (DDSD->dwWidth != This->surface_desc.dwWidth)
-        {
             TRACE("Surface width changed from %u to %u.\n", This->surface_desc.dwWidth, DDSD->dwWidth);
-            update_wined3d = TRUE;
-        }
         if (DDSD->u1.lPitch != This->surface_desc.u1.lPitch)
-        {
             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;
     }
@@ -4310,10 +4351,7 @@ static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface,
             return DDERR_INVALIDPARAMS;
         }
         if (DDSD->dwHeight != This->surface_desc.dwHeight)
-        {
             TRACE("Surface height changed from %u to %u.\n", This->surface_desc.dwHeight, DDSD->dwHeight);
-            update_wined3d = TRUE;
-        }
         height = DDSD->dwHeight;
     }
     else
@@ -4335,52 +4373,29 @@ static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface,
         }
         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);
-            update_wined3d = TRUE;
-        }
     }
     else
     {
         format_id = wined3dformat_from_ddrawformat(&This->surface_desc.u4.ddpfPixelFormat);
     }
 
-    if (update_wined3d)
+    if (FAILED(hr = wined3d_surface_update_desc(This->wined3d_surface, width, height,
+            format_id, WINED3D_MULTISAMPLE_NONE, 0, DDSD->lpSurface, pitch)))
     {
-        if (FAILED(hr = wined3d_surface_update_desc(This->wined3d_surface, width, height,
-                format_id, WINED3D_MULTISAMPLE_NONE, 0)))
-        {
-            WARN("Failed to update surface desc, hr %#x.\n", hr);
-            wined3d_mutex_unlock();
-            return hr;
-        }
-
-        if (DDSD->dwFlags & DDSD_WIDTH)
-            This->surface_desc.dwWidth = width;
-        if (DDSD->dwFlags & DDSD_PITCH)
-            This->surface_desc.u1.lPitch = DDSD->u1.lPitch;
-        if (DDSD->dwFlags & DDSD_HEIGHT)
-            This->surface_desc.dwHeight = height;
-        if (DDSD->dwFlags & DDSD_PIXELFORMAT)
-            This->surface_desc.u4.ddpfPixelFormat = DDSD->u4.ddpfPixelFormat;
+        WARN("Failed to update surface desc, hr %#x.\n", hr);
+        wined3d_mutex_unlock();
+        return hr_ddraw_from_wined3d(hr);
     }
 
-    if (DDSD->dwFlags & DDSD_LPSURFACE && DDSD->lpSurface)
-    {
-        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)
-            {
-                case WINED3DERR_INVALIDCALL:
-                    wined3d_mutex_unlock();
-                    return DDERR_INVALIDPARAMS;
-                default:
-                    break; /* Go on */
-            }
-        }
-        /* DDSD->lpSurface is set by Lock() */
-    }
+    if (DDSD->dwFlags & DDSD_WIDTH)
+        This->surface_desc.dwWidth = width;
+    if (DDSD->dwFlags & DDSD_PITCH)
+        This->surface_desc.u1.lPitch = DDSD->u1.lPitch;
+    if (DDSD->dwFlags & DDSD_HEIGHT)
+        This->surface_desc.dwHeight = height;
+    if (DDSD->dwFlags & DDSD_PIXELFORMAT)
+        This->surface_desc.u4.ddpfPixelFormat = DDSD->u4.ddpfPixelFormat;
 
     wined3d_mutex_unlock();
 
@@ -4411,46 +4426,28 @@ static HRESULT WINAPI ddraw_surface3_SetSurfaceDesc(IDirectDrawSurface3 *iface,
             surface_desc ? &surface_desc2 : NULL, flags);
 }
 
-/*****************************************************************************
- * IDirectDrawSurface7::GetPalette
- *
- * Returns the IDirectDrawPalette interface of the palette currently assigned
- * to the surface
- *
- * Params:
- *  Pal: Address to write the interface pointer to
- *
- * Returns:
- *  DD_OK on success
- *  DDERR_INVALIDPARAMS if Pal is NULL
- *
- *****************************************************************************/
-static HRESULT WINAPI ddraw_surface7_GetPalette(IDirectDrawSurface7 *iface, IDirectDrawPalette **Pal)
+static HRESULT WINAPI ddraw_surface7_GetPalette(IDirectDrawSurface7 *iface, IDirectDrawPalette **palette)
 {
     struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
-    struct wined3d_palette *wined3d_palette;
     struct ddraw_palette *palette_impl;
     HRESULT hr = DD_OK;
 
-    TRACE("iface %p, palette %p.\n", iface, Pal);
+    TRACE("iface %p, palette %p.\n", iface, palette);
 
-    if(!Pal)
+    if (!palette)
         return DDERR_INVALIDPARAMS;
 
     wined3d_mutex_lock();
-    wined3d_palette = wined3d_surface_get_palette(surface->wined3d_surface);
-    if (wined3d_palette)
+    if ((palette_impl = surface->palette))
     {
-        palette_impl = wined3d_palette_get_parent(wined3d_palette);
-        *Pal = &palette_impl->IDirectDrawPalette_iface;
-        IDirectDrawPalette_AddRef(*Pal);
+        *palette = &palette_impl->IDirectDrawPalette_iface;
+        IDirectDrawPalette_AddRef(*palette);
     }
     else
     {
-        *Pal = NULL;
+        *palette = NULL;
         hr = DDERR_NOPALETTEATTACHED;
     }
-
     wined3d_mutex_unlock();
 
     return hr;
@@ -4492,132 +4489,97 @@ static HRESULT WINAPI ddraw_surface1_GetPalette(IDirectDrawSurface *iface, IDire
     return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette);
 }
 
-/*****************************************************************************
- * SetColorKeyEnum
- *
- * EnumAttachedSurface callback for SetColorKey. Used to set color keys
- * recursively in the surface tree
- *
- *****************************************************************************/
-struct SCKContext
+static HRESULT ddraw_surface_set_color_key(struct ddraw_surface *surface, DWORD flags, DDCOLORKEY *color_key)
 {
-    HRESULT ret;
-    struct wined3d_color_key *color_key;
-    DWORD Flags;
-};
-
-static HRESULT WINAPI SetColorKeyEnum(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context)
-{
-    struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface);
-    struct SCKContext *ctx = context;
-    HRESULT hr;
-
-    hr = wined3d_surface_set_color_key(surface_impl->wined3d_surface, ctx->Flags, ctx->color_key);
-    if (FAILED(hr))
-    {
-        WARN("IWineD3DSurface_SetColorKey failed, hr = %08x\n", hr);
-        ctx->ret = hr;
-    }
-
-    ddraw_surface7_EnumAttachedSurfaces(surface, context, SetColorKeyEnum);
-    ddraw_surface7_Release(surface);
-
-    return DDENUMRET_OK;
-}
-
-/*****************************************************************************
- * IDirectDrawSurface7::SetColorKey
- *
- * Sets the color keying options for the surface. Observations showed that
- * in case of complex surfaces the color key has to be assigned to all
- * sublevels.
- *
- * Params:
- *  Flags: DDCKEY_*
- *  CKey: The new color key
- *
- * Returns:
- *  DD_OK on success
- *  See IWineD3DSurface::SetColorKey for details
- *
- *****************************************************************************/
-static HRESULT WINAPI ddraw_surface7_SetColorKey(IDirectDrawSurface7 *iface, DWORD Flags, DDCOLORKEY *CKey)
-{
-    struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
-    DDCOLORKEY FixedCKey;
-    struct SCKContext ctx = { DD_OK, (struct wined3d_color_key *)(CKey ? &FixedCKey : NULL), Flags };
-
-    TRACE("iface %p, flags %#x, color_key %p.\n", iface, Flags, CKey);
+    DDCOLORKEY fixed_color_key;
+    HRESULT hr = WINED3D_OK;
 
     wined3d_mutex_lock();
-    if (CKey)
+
+    if (color_key)
     {
-        FixedCKey = *CKey;
+        fixed_color_key = *color_key;
         /* Handle case where dwColorSpaceHighValue < dwColorSpaceLowValue */
-        if (FixedCKey.dwColorSpaceHighValue < FixedCKey.dwColorSpaceLowValue)
-            FixedCKey.dwColorSpaceHighValue = FixedCKey.dwColorSpaceLowValue;
+        if (fixed_color_key.dwColorSpaceHighValue < fixed_color_key.dwColorSpaceLowValue)
+            fixed_color_key.dwColorSpaceHighValue = fixed_color_key.dwColorSpaceLowValue;
 
-        switch (Flags & ~DDCKEY_COLORSPACE)
+        switch (flags & ~DDCKEY_COLORSPACE)
         {
-        case DDCKEY_DESTBLT:
-            This->surface_desc.ddckCKDestBlt = FixedCKey;
-            This->surface_desc.dwFlags |= DDSD_CKDESTBLT;
-            break;
+            case DDCKEY_DESTBLT:
+                surface->surface_desc.ddckCKDestBlt = fixed_color_key;
+                surface->surface_desc.dwFlags |= DDSD_CKDESTBLT;
+                break;
 
-        case DDCKEY_DESTOVERLAY:
-            This->surface_desc.u3.ddckCKDestOverlay = FixedCKey;
-            This->surface_desc.dwFlags |= DDSD_CKDESTOVERLAY;
-            break;
+            case DDCKEY_DESTOVERLAY:
+                surface->surface_desc.u3.ddckCKDestOverlay = fixed_color_key;
+                surface->surface_desc.dwFlags |= DDSD_CKDESTOVERLAY;
+                break;
 
-        case DDCKEY_SRCOVERLAY:
-            This->surface_desc.ddckCKSrcOverlay = FixedCKey;
-            This->surface_desc.dwFlags |= DDSD_CKSRCOVERLAY;
-            break;
+            case DDCKEY_SRCOVERLAY:
+                surface->surface_desc.ddckCKSrcOverlay = fixed_color_key;
+                surface->surface_desc.dwFlags |= DDSD_CKSRCOVERLAY;
+                break;
 
-        case DDCKEY_SRCBLT:
-            This->surface_desc.ddckCKSrcBlt = FixedCKey;
-            This->surface_desc.dwFlags |= DDSD_CKSRCBLT;
-            break;
+            case DDCKEY_SRCBLT:
+                surface->surface_desc.ddckCKSrcBlt = fixed_color_key;
+                surface->surface_desc.dwFlags |= DDSD_CKSRCBLT;
+                break;
 
-        default:
-            wined3d_mutex_unlock();
-            return DDERR_INVALIDPARAMS;
+            default:
+                wined3d_mutex_unlock();
+                return DDERR_INVALIDPARAMS;
         }
     }
     else
     {
-        switch (Flags & ~DDCKEY_COLORSPACE)
+        switch (flags & ~DDCKEY_COLORSPACE)
         {
-        case DDCKEY_DESTBLT:
-            This->surface_desc.dwFlags &= ~DDSD_CKDESTBLT;
-            break;
+            case DDCKEY_DESTBLT:
+                surface->surface_desc.dwFlags &= ~DDSD_CKDESTBLT;
+                break;
 
-        case DDCKEY_DESTOVERLAY:
-            This->surface_desc.dwFlags &= ~DDSD_CKDESTOVERLAY;
-            break;
+            case DDCKEY_DESTOVERLAY:
+                surface->surface_desc.dwFlags &= ~DDSD_CKDESTOVERLAY;
+                break;
 
-        case DDCKEY_SRCOVERLAY:
-            This->surface_desc.dwFlags &= ~DDSD_CKSRCOVERLAY;
-            break;
+            case DDCKEY_SRCOVERLAY:
+                surface->surface_desc.dwFlags &= ~DDSD_CKSRCOVERLAY;
+                break;
 
-        case DDCKEY_SRCBLT:
-            This->surface_desc.dwFlags &= ~DDSD_CKSRCBLT;
-            break;
+            case DDCKEY_SRCBLT:
+                surface->surface_desc.dwFlags &= ~DDSD_CKSRCBLT;
+                break;
 
-        default:
-            wined3d_mutex_unlock();
-            return DDERR_INVALIDPARAMS;
+            default:
+                wined3d_mutex_unlock();
+                return DDERR_INVALIDPARAMS;
         }
     }
-    ctx.ret = wined3d_surface_set_color_key(This->wined3d_surface, Flags, ctx.color_key);
-    ddraw_surface7_EnumAttachedSurfaces(iface, &ctx, SetColorKeyEnum);
+
+    if (surface->wined3d_texture)
+        hr = wined3d_texture_set_color_key(surface->wined3d_texture, flags,
+                color_key ? (struct wined3d_color_key *)&fixed_color_key : NULL);
+
     wined3d_mutex_unlock();
 
-    switch(ctx.ret)
+    return hr_ddraw_from_wined3d(hr);
+}
+
+static HRESULT WINAPI ddraw_surface7_SetColorKey(IDirectDrawSurface7 *iface, DWORD flags, DDCOLORKEY *color_key)
+{
+    struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
+
+    TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
+
+    wined3d_mutex_lock();
+    if (!surface->wined3d_texture)
     {
-        case WINED3DERR_INVALIDCALL:        return DDERR_INVALIDPARAMS;
-        default:                            return ctx.ret;
+        wined3d_mutex_unlock();
+        return DDERR_NOTONMIPMAPSUBLEVEL;
     }
+    wined3d_mutex_unlock();
+
+    return ddraw_surface_set_color_key(surface, flags, color_key);
 }
 
 static HRESULT WINAPI ddraw_surface4_SetColorKey(IDirectDrawSurface4 *iface, DWORD flags, DDCOLORKEY *color_key)
@@ -4626,7 +4588,7 @@ static HRESULT WINAPI ddraw_surface4_SetColorKey(IDirectDrawSurface4 *iface, DWO
 
     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
 
-    return ddraw_surface7_SetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key);
+    return ddraw_surface_set_color_key(surface, flags, color_key);
 }
 
 static HRESULT WINAPI ddraw_surface3_SetColorKey(IDirectDrawSurface3 *iface, DWORD flags, DDCOLORKEY *color_key)
@@ -4635,7 +4597,7 @@ static HRESULT WINAPI ddraw_surface3_SetColorKey(IDirectDrawSurface3 *iface, DWO
 
     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
 
-    return ddraw_surface7_SetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key);
+    return ddraw_surface_set_color_key(surface, flags, color_key);
 }
 
 static HRESULT WINAPI ddraw_surface2_SetColorKey(IDirectDrawSurface2 *iface, DWORD flags, DDCOLORKEY *color_key)
@@ -4644,7 +4606,7 @@ static HRESULT WINAPI ddraw_surface2_SetColorKey(IDirectDrawSurface2 *iface, DWO
 
     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
 
-    return ddraw_surface7_SetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key);
+    return ddraw_surface_set_color_key(surface, flags, color_key);
 }
 
 static HRESULT WINAPI ddraw_surface1_SetColorKey(IDirectDrawSurface *iface, DWORD flags, DDCOLORKEY *color_key)
@@ -4653,89 +4615,44 @@ static HRESULT WINAPI ddraw_surface1_SetColorKey(IDirectDrawSurface *iface, DWOR
 
     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
 
-    return ddraw_surface7_SetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key);
+    return ddraw_surface_set_color_key(surface, flags, color_key);
 }
 
-/*****************************************************************************
- * IDirectDrawSurface7::SetPalette
- *
- * Assigns a DirectDrawPalette object to the surface
- *
- * Params:
- *  Pal: Interface to the palette to set
- *
- * Returns:
- *  DD_OK on success
- *
- *****************************************************************************/
-static HRESULT WINAPI ddraw_surface7_SetPalette(IDirectDrawSurface7 *iface, IDirectDrawPalette *Pal)
+static HRESULT WINAPI ddraw_surface7_SetPalette(IDirectDrawSurface7 *iface, IDirectDrawPalette *palette)
 {
-    struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
-    struct ddraw_palette *palette_impl = unsafe_impl_from_IDirectDrawPalette(Pal);
-    IDirectDrawPalette *oldPal;
-    struct ddraw_surface *surf;
-    HRESULT hr;
+    struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
+    struct ddraw_palette *palette_impl = unsafe_impl_from_IDirectDrawPalette(palette);
+    struct ddraw_palette *prev;
 
-    TRACE("iface %p, palette %p.\n", iface, Pal);
+    TRACE("iface %p, palette %p.\n", iface, palette);
 
-    if (!(This->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
-            DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8))) {
+    if (!(surface->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2
+            | DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8)))
         return DDERR_INVALIDPIXELFORMAT;
-    }
 
-    if (This->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
-    {
+    if (surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
         return DDERR_NOTONMIPMAPSUBLEVEL;
-    }
 
-    /* Find the old palette */
     wined3d_mutex_lock();
-    hr = IDirectDrawSurface_GetPalette(iface, &oldPal);
-    if(hr != DD_OK && hr != DDERR_NOPALETTEATTACHED)
-    {
-        wined3d_mutex_unlock();
-        return hr;
-    }
-    if(oldPal) IDirectDrawPalette_Release(oldPal);  /* For the GetPalette */
-
-    /* Set the new Palette */
-    wined3d_surface_set_palette(This->wined3d_surface, palette_impl ? palette_impl->wineD3DPalette : NULL);
-    /* AddRef the Palette */
-    if(Pal) IDirectDrawPalette_AddRef(Pal);
-
-    /* Release the old palette */
-    if(oldPal) IDirectDrawPalette_Release(oldPal);
-
-    /* Update the wined3d frontbuffer if this is the frontbuffer. */
-    if ((This->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER) && This->ddraw->wined3d_frontbuffer)
-        wined3d_surface_set_palette(This->ddraw->wined3d_frontbuffer,
-                palette_impl ? palette_impl->wineD3DPalette : NULL);
 
-    /* If this is a front buffer, also update the back buffers
-     * TODO: How do things work for palettized cube textures?
-     */
-    if(This->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
+    prev = surface->palette;
+    if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
     {
-        /* For primary surfaces the tree is just a list, so the simpler scheme fits too */
-        DDSCAPS2 caps2 = { DDSCAPS_PRIMARYSURFACE, 0, 0, {0} };
-
-        surf = This;
-        while(1)
-        {
-            IDirectDrawSurface7 *attach;
-            HRESULT hr;
-            hr = ddraw_surface7_GetAttachedSurface(&surf->IDirectDrawSurface7_iface, &caps2, &attach);
-            if(hr != DD_OK)
-            {
-                break;
-            }
-
-            TRACE("Setting palette on %p\n", attach);
-            ddraw_surface7_SetPalette(attach, Pal);
-            surf = impl_from_IDirectDrawSurface7(attach);
-            ddraw_surface7_Release(attach);
-        }
-    }
+        if (prev)
+            prev->flags &= ~DDPCAPS_PRIMARYSURFACE;
+        if (palette_impl)
+            palette_impl->flags |= DDPCAPS_PRIMARYSURFACE;
+        /* Update the wined3d frontbuffer if this is the primary. */
+        if (surface->ddraw->wined3d_frontbuffer)
+            wined3d_surface_set_palette(surface->ddraw->wined3d_frontbuffer,
+                    palette_impl ? palette_impl->wineD3DPalette : NULL);
+    }
+    if (palette_impl)
+        IDirectDrawPalette_AddRef(&palette_impl->IDirectDrawPalette_iface);
+    if (prev)
+        IDirectDrawPalette_Release(&prev->IDirectDrawPalette_iface);
+    surface->palette = palette_impl;
+    wined3d_surface_set_palette(surface->wined3d_surface, palette_impl ? palette_impl->wineD3DPalette : NULL);
 
     wined3d_mutex_unlock();
 
@@ -4995,7 +4912,7 @@ static struct ddraw_surface *get_sub_mimaplevel(struct ddraw_surface *surface)
  * Loads a texture created with the DDSCAPS_ALLOCONLOAD
  *
  * This function isn't relayed to WineD3D because the whole interface is
- * implemented in DDraw only. For speed improvements a implementation which
+ * implemented in DDraw only. For speed improvements an implementation which
  * takes OpenGL more into account could be placed into WineD3D.
  *
  * Params:
@@ -5569,11 +5486,9 @@ static const struct wined3d_parent_ops ddraw_surface_wined3d_parent_ops =
 
 static void STDMETHODCALLTYPE ddraw_texture_wined3d_object_destroyed(void *parent)
 {
-    struct ddraw_surface *surface = parent;
-
-    TRACE("surface %p.\n", surface);
+    TRACE("parent %p.\n", parent);
 
-    ddraw_surface_cleanup(surface);
+    HeapFree(GetProcessHeap(), 0, parent);
 }
 
 static const struct wined3d_parent_ops ddraw_texture_wined3d_parent_ops =
@@ -5581,75 +5496,388 @@ 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, DWORD surface_flags)
+static HRESULT CDECL ddraw_reset_enum_callback(struct wined3d_resource *resource)
 {
-    const DDSURFACEDESC2 *desc = &surface->surface_desc;
+    return DD_OK;
+}
+
+HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_desc,
+        struct ddraw_surface **surface, IUnknown *outer_unknown, unsigned int version)
+{
+    struct ddraw_surface *root, *mip, **attach;
     struct wined3d_resource_desc wined3d_desc;
-    struct ddraw_surface *mip, **attach;
+    struct wined3d_texture *wined3d_texture;
     struct wined3d_resource *resource;
+    struct wined3d_display_mode mode;
+    DDSURFACEDESC2 *desc, *mip_desc;
+    struct ddraw_texture *texture;
     UINT layers, levels, i, j;
-    DDSURFACEDESC2 *mip_desc;
-    enum wined3d_pool pool;
     HRESULT hr;
 
-    if (desc->ddsCaps.dwCaps & DDSCAPS_MIPMAP)
-        levels = desc->u2.dwMipMapCount;
-    else
-        levels = 1;
+    TRACE("ddraw %p, surface_desc %p, surface %p, outer_unknown %p, version %u.\n",
+            ddraw, surface_desc, surface, outer_unknown, version);
+    if (TRACE_ON(ddraw))
+    {
+        TRACE("Requesting surface desc:\n");
+        DDRAW_dump_surface_desc(surface_desc);
+    }
 
-    if (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
-        layers = 6;
-    else
-        layers = 1;
+    if (outer_unknown)
+        return CLASS_E_NOAGGREGATION;
 
-    /* DDSCAPS_SYSTEMMEMORY textures are in WINED3D_POOL_SYSTEM_MEM.
-     * Should I forward the MANAGED cap to the managed pool? */
-    if (desc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
-        pool = WINED3D_POOL_SYSTEM_MEM;
-    else
-        pool = WINED3D_POOL_DEFAULT;
+    if (!surface)
+        return E_POINTER;
+
+    if (!(texture = HeapAlloc(GetProcessHeap(), 0, sizeof(*texture))))
+        return E_OUTOFMEMORY;
+
+    texture->version = version;
+    texture->surface_desc = *surface_desc;
+    desc = &texture->surface_desc;
+
+    /* Ensure DDSD_CAPS is always set. */
+    desc->dwFlags |= DDSD_CAPS;
+
+    /* If the surface is of the 'ALLOCONLOAD' type, ignore the LPSURFACE
+     * field. Frank Herbert's Dune specifies a NULL pointer for lpSurface. */
+    if ((desc->ddsCaps.dwCaps & DDSCAPS_ALLOCONLOAD) || !desc->lpSurface)
+        desc->dwFlags &= ~DDSD_LPSURFACE;
+
+    if (desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
+    {
+        DWORD flippable = desc->ddsCaps.dwCaps & (DDSCAPS_FLIP | DDSCAPS_COMPLEX);
+
+        if (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
+        {
+            WARN("Tried to create a primary surface with DDSCAPS_TEXTURE.\n");
+            HeapFree(GetProcessHeap(), 0, texture);
+            return DDERR_INVALIDCAPS;
+        }
+
+        if (flippable)
+        {
+            if (flippable != (DDSCAPS_FLIP | DDSCAPS_COMPLEX))
+            {
+                WARN("Tried to create a flippable primary surface without both DDSCAPS_FLIP and DDSCAPS_COMPLEX.\n");
+                HeapFree(GetProcessHeap(), 0, texture);
+                return DDERR_INVALIDCAPS;
+            }
+
+            if (!(desc->dwFlags & DDSD_BACKBUFFERCOUNT) || !desc->u5.dwBackBufferCount)
+            {
+                WARN("Tried to create a flippable primary surface without any back buffers.\n");
+                HeapFree(GetProcessHeap(), 0, texture);
+                return DDERR_INVALIDCAPS;
+            }
+
+            if (!(ddraw->cooperative_level & DDSCL_EXCLUSIVE))
+            {
+                WARN("Tried to create a flippable primary surface without DDSCL_EXCLUSIVE.\n");
+                HeapFree(GetProcessHeap(), 0, texture);
+                return DDERR_NOEXCLUSIVEMODE;
+            }
+        }
+    }
+
+    /* This is a special case in ddrawex, but not allowed in ddraw. */
+    if ((desc->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY))
+            == (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY))
+    {
+        WARN("Tried to create a surface in both system and video memory.\n");
+        HeapFree(GetProcessHeap(), 0, texture);
+        return DDERR_INVALIDCAPS;
+    }
+
+    if ((desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES)
+            && !(desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
+    {
+        WARN("Cube map faces requested without cube map flag.\n");
+        HeapFree(GetProcessHeap(), 0, texture);
+        return DDERR_INVALIDCAPS;
+    }
+
+    if ((desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
+            && !(desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES))
+    {
+        WARN("Cube map without faces requested.\n");
+        HeapFree(GetProcessHeap(), 0, texture);
+        return DDERR_INVALIDPARAMS;
+    }
+
+    if ((desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
+            && (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) != DDSCAPS2_CUBEMAP_ALLFACES)
+        FIXME("Partial cube maps not implemented.\n");
+
+    if (desc->ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE))
+    {
+        if (!(desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE))
+        {
+            WARN("DDSCAPS2_TEXTUREMANAGE used without DDSCAPS_TEXTURE, returning DDERR_INVALIDCAPS.\n");
+            HeapFree(GetProcessHeap(), 0, texture);
+            return DDERR_INVALIDCAPS;
+        }
+        if (desc->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY))
+        {
+            WARN("DDSCAPS2_TEXTUREMANAGE used width DDSCAPS_VIDEOMEMORY "
+                    "or DDSCAPS_SYSTEMMEMORY, returning DDERR_INVALIDCAPS.\n");
+            HeapFree(GetProcessHeap(), 0, texture);
+            return DDERR_INVALIDCAPS;
+        }
+    }
+
+    if (FAILED(hr = wined3d_get_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
+    {
+        ERR("Failed to get display mode, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, texture);
+        return hr_ddraw_from_wined3d(hr);
+    }
+
+    /* No pixelformat given? Use the current screen format. */
+    if (!(desc->dwFlags & DDSD_PIXELFORMAT))
+    {
+        desc->dwFlags |= DDSD_PIXELFORMAT;
+        desc->u4.ddpfPixelFormat.dwSize = sizeof(desc->u4.ddpfPixelFormat);
+        ddrawformat_from_wined3dformat(&desc->u4.ddpfPixelFormat, mode.format_id);
+    }
+
+    wined3d_desc.format = wined3dformat_from_ddrawformat(&desc->u4.ddpfPixelFormat);
+    if (wined3d_desc.format == WINED3DFMT_UNKNOWN)
+    {
+        WARN("Unsupported / unknown pixelformat.\n");
+        HeapFree(GetProcessHeap(), 0, texture);
+        return DDERR_INVALIDPIXELFORMAT;
+    }
+
+    /* No width or no height? Use the screen size. */
+    if (!(desc->dwFlags & DDSD_WIDTH) || !(desc->dwFlags & DDSD_HEIGHT))
+    {
+        if (!(desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
+        {
+            WARN("No width / height specified.\n");
+            HeapFree(GetProcessHeap(), 0, texture);
+            return DDERR_INVALIDPARAMS;
+        }
+
+        desc->dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
+        desc->dwWidth = mode.width;
+        desc->dwHeight = mode.height;
+    }
+
+    if (!desc->dwWidth || !desc->dwHeight)
+    {
+        HeapFree(GetProcessHeap(), 0, texture);
+        return DDERR_INVALIDPARAMS;
+    }
+
+    if (desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
+    {
+        /* The first surface is a front buffer, the back buffers are created
+         * afterwards. */
+        if (desc->ddsCaps.dwCaps & DDSCAPS_FLIP)
+            desc->ddsCaps.dwCaps |= DDSCAPS_FRONTBUFFER;
+        desc->ddsCaps.dwCaps |= DDSCAPS_VISIBLE;
+        if (ddraw->cooperative_level & DDSCL_EXCLUSIVE)
+        {
+            struct wined3d_swapchain_desc swapchain_desc;
+
+            wined3d_swapchain_get_desc(ddraw->wined3d_swapchain, &swapchain_desc);
+            swapchain_desc.backbuffer_width = mode.width;
+            swapchain_desc.backbuffer_height = mode.height;
+            swapchain_desc.backbuffer_format = mode.format_id;
+
+            if (FAILED(hr = wined3d_device_reset(ddraw->wined3d_device,
+                    &swapchain_desc, NULL, ddraw_reset_enum_callback, TRUE)))
+            {
+                ERR("Failed to reset device.\n");
+                HeapFree(GetProcessHeap(), 0, texture);
+                return hr_ddraw_from_wined3d(hr);
+            }
+        }
+    }
 
-    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.pool = WINED3D_POOL_DEFAULT;
     wined3d_desc.width = desc->dwWidth;
     wined3d_desc.height = desc->dwHeight;
     wined3d_desc.depth = 1;
     wined3d_desc.size = 0;
 
+    if ((desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) && (ddraw->flags & DDRAW_NO3D))
+    {
+        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. */
+    }
+
+    /* Mipmap count fixes */
+    if (desc->ddsCaps.dwCaps & DDSCAPS_MIPMAP)
+    {
+        if (desc->ddsCaps.dwCaps & DDSCAPS_COMPLEX)
+        {
+            if (desc->dwFlags & DDSD_MIPMAPCOUNT)
+            {
+                /* Mipmap count is given, should not be 0. */
+                if (!desc->u2.dwMipMapCount)
+                {
+                    HeapFree(GetProcessHeap(), 0, texture);
+                    return DDERR_INVALIDPARAMS;
+                }
+            }
+            else
+            {
+                /* Undocumented feature: Create sublevels until either the
+                 * width or the height is 1. */
+                DWORD min = desc->dwWidth < desc->dwHeight ? desc->dwWidth : desc->dwHeight;
+
+                desc->u2.dwMipMapCount = 0;
+                while (min)
+                {
+                    ++desc->u2.dwMipMapCount;
+                    min >>= 1;
+                }
+            }
+        }
+        else
+        {
+            desc->u2.dwMipMapCount = 1;
+        }
+
+        desc->dwFlags |= DDSD_MIPMAPCOUNT;
+        levels = desc->u2.dwMipMapCount;
+    }
+    else
+    {
+        levels = 1;
+    }
+
+    if (!(desc->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY)))
+    {
+        if (!(desc->ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE)))
+        {
+            enum wined3d_resource_type rtype;
+            DWORD usage = 0;
+
+            if (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
+                rtype = WINED3D_RTYPE_CUBE_TEXTURE;
+            else if (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
+                rtype = WINED3D_RTYPE_TEXTURE;
+            else
+                rtype = WINED3D_RTYPE_SURFACE;
+
+            if (desc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
+                usage = WINED3DUSAGE_DEPTHSTENCIL;
+            else if (desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
+                usage = WINED3DUSAGE_RENDERTARGET;
+
+            if (SUCCEEDED(hr = wined3d_check_device_format(ddraw->wined3d, WINED3DADAPTER_DEFAULT,
+                    WINED3D_DEVICE_TYPE_HAL, mode.format_id, usage, rtype, wined3d_desc.format)))
+                desc->ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
+            else
+                desc->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
+        }
+        else if (!(desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE))
+        {
+            /* Tests show surfaces without memory flags get these flags added
+             * right after creation. */
+            desc->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY;
+        }
+    }
+
+    if ((desc->ddsCaps.dwCaps & (DDSCAPS_OVERLAY | DDSCAPS_SYSTEMMEMORY))
+            == (DDSCAPS_OVERLAY | DDSCAPS_SYSTEMMEMORY))
+    {
+        WARN("System memory overlays are not allowed.\n");
+        HeapFree(GetProcessHeap(), 0, texture);
+        return DDERR_NOOVERLAYHW;
+    }
+
+    if (desc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
+    {
+        wined3d_desc.pool = WINED3D_POOL_SYSTEM_MEM;
+    }
+    else
+    {
+        if (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
+            wined3d_desc.usage |= WINED3DUSAGE_TEXTURE;
+        if (desc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
+            wined3d_desc.usage |= WINED3DUSAGE_DEPTHSTENCIL;
+        else if (desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
+            wined3d_desc.usage |= WINED3DUSAGE_RENDERTARGET;
+
+        if (desc->ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE))
+        {
+            wined3d_desc.pool = WINED3D_POOL_MANAGED;
+            /* Managed textures have the system memory flag set. */
+            desc->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
+        }
+        else if (desc->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
+        {
+            /* Videomemory adds localvidmem. This is mutually exclusive with
+             * systemmemory and texturemanage. */
+            desc->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM;
+            wined3d_desc.usage |= WINED3DUSAGE_DYNAMIC;
+        }
+    }
+
+    if (desc->ddsCaps.dwCaps & (DDSCAPS_OVERLAY))
+        wined3d_desc.usage |= WINED3DUSAGE_OVERLAY;
+
+    if (desc->ddsCaps.dwCaps & DDSCAPS_OWNDC)
+        wined3d_desc.usage |= WINED3DUSAGE_OWNDC;
+
     if (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
     {
         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);
+        layers = 6;
     }
     else
     {
         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);
+        layers = 1;
     }
 
-    if (FAILED(hr))
+    /* 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. We set
+     * WINED3D_SURFACE_PIN_SYSMEM because of this. */
+    if (FAILED(hr = wined3d_texture_create(ddraw->wined3d_device, &wined3d_desc, levels,
+            WINED3D_SURFACE_PIN_SYSMEM, texture, &ddraw_texture_wined3d_parent_ops, &wined3d_texture)))
     {
         WARN("Failed to create wined3d texture, hr %#x.\n", hr);
-        return hr;
+        HeapFree(GetProcessHeap(), 0, texture);
+        return hr_ddraw_from_wined3d(hr);
     }
 
+    resource = wined3d_texture_get_sub_resource(wined3d_texture, 0);
+    root = wined3d_resource_get_parent(resource);
+    root->wined3d_texture = wined3d_texture;
+    root->is_complex_root = TRUE;
+    texture->root = root;
+
+    if (desc->dwFlags & DDSD_CKDESTOVERLAY)
+        wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTOVERLAY,
+                (struct wined3d_color_key *)&desc->u3.ddckCKDestOverlay);
+    if (desc->dwFlags & DDSD_CKDESTBLT)
+        wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTBLT,
+                (struct wined3d_color_key *)&desc->ddckCKDestBlt);
+    if (desc->dwFlags & DDSD_CKSRCOVERLAY)
+        wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCOVERLAY,
+                (struct wined3d_color_key *)&desc->ddckCKSrcOverlay);
+    if (desc->dwFlags & DDSD_CKSRCBLT)
+        wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCBLT,
+                (struct wined3d_color_key *)&desc->ddckCKSrcBlt);
+
     for (i = 0; i < layers; ++i)
     {
-        attach = &surface->complex_array[layers - 1 - i];
+        attach = &root->complex_array[layers - 1 - i];
 
         for (j = 0; j < levels; ++j)
         {
-            resource = wined3d_texture_get_sub_resource(surface->wined3d_texture, i * levels + j);
+            resource = wined3d_texture_get_sub_resource(wined3d_texture, i * levels + j);
             mip = wined3d_resource_get_parent(resource);
-
-            if (mip == surface)
-                continue;
-
             mip_desc = &mip->surface_desc;
 
             if (j)
@@ -5685,76 +5913,96 @@ HRESULT ddraw_surface_create_texture(struct ddraw_surface *surface, DWORD surfac
 
             }
 
+            if (mip == root)
+                continue;
+
             *attach = mip;
             attach = &mip->complex_array[0];
         }
     }
 
-    return DD_OK;
-}
+    if (desc->dwFlags & DDSD_BACKBUFFERCOUNT)
+    {
+        unsigned int count = desc->u5.dwBackBufferCount;
+        struct ddraw_surface *last = root;
 
-HRESULT ddraw_surface_init(struct ddraw_surface *surface, struct ddraw *ddraw,
-        DDSURFACEDESC2 *desc, DWORD flags, UINT version)
-{
-    enum wined3d_pool pool = WINED3D_POOL_DEFAULT;
-    enum wined3d_format_id format;
-    DWORD usage = 0;
-    HRESULT hr;
+        attach = &last->complex_array[0];
+        for (i = 0; i < count; ++i)
+        {
+            if (!(texture = HeapAlloc(GetProcessHeap(), 0, sizeof(*texture))))
+            {
+                hr = E_OUTOFMEMORY;
+                goto fail;
+            }
 
-    if (!(desc->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY))
-            && !((desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
-            && (desc->ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE)))
-    {
-        /* Tests show surfaces without memory flags get these flags added
-         * right after creation. */
-        desc->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY;
-    }
+            texture->version = version;
+            texture->surface_desc = root->surface_desc;
+            desc = &texture->surface_desc;
 
-    if (desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
-    {
-        usage |= WINED3DUSAGE_RENDERTARGET;
-        desc->ddsCaps.dwCaps |= DDSCAPS_VISIBLE;
-    }
+            /* Only one surface in the flipping chain is a back buffer, one is
+             * a front buffer, the others are just flippable surfaces. */
+            desc->ddsCaps.dwCaps &= ~(DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER
+                    | DDSCAPS_BACKBUFFER);
+            if (!i)
+                desc->ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER;
+            desc->u5.dwBackBufferCount = 0;
 
-    if ((desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) && !(desc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
-    {
-        usage |= WINED3DUSAGE_RENDERTARGET;
-    }
+            if (FAILED(hr = wined3d_texture_create(ddraw->wined3d_device, &wined3d_desc, 1,
+                    WINED3D_SURFACE_PIN_SYSMEM, texture, &ddraw_texture_wined3d_parent_ops, &wined3d_texture)))
+            {
+                HeapFree(GetProcessHeap(), 0, texture);
+                hr = hr_ddraw_from_wined3d(hr);
+                goto fail;
+            }
 
-    if (desc->ddsCaps.dwCaps & (DDSCAPS_OVERLAY))
-    {
-        usage |= WINED3DUSAGE_OVERLAY;
+            resource = wined3d_texture_get_sub_resource(wined3d_texture, 0);
+            last = wined3d_resource_get_parent(resource);
+            last->wined3d_texture = wined3d_texture;
+            texture->root = last;
+
+            if (desc->dwFlags & DDSD_CKDESTOVERLAY)
+                wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTOVERLAY,
+                        (struct wined3d_color_key *)&desc->u3.ddckCKDestOverlay);
+            if (desc->dwFlags & DDSD_CKDESTBLT)
+                wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTBLT,
+                        (struct wined3d_color_key *)&desc->ddckCKDestBlt);
+            if (desc->dwFlags & DDSD_CKSRCOVERLAY)
+                wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCOVERLAY,
+                        (struct wined3d_color_key *)&desc->ddckCKSrcOverlay);
+            if (desc->dwFlags & DDSD_CKSRCBLT)
+                wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCBLT,
+                        (struct wined3d_color_key *)&desc->ddckCKSrcBlt);
+
+            *attach = last;
+            attach = &last->complex_array[0];
+        }
+        *attach = root;
     }
 
-    if (desc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
-        usage |= WINED3DUSAGE_DEPTHSTENCIL;
+    if (surface_desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
+        ddraw->primary = root;
+    *surface = root;
 
-    if (desc->ddsCaps.dwCaps & DDSCAPS_OWNDC)
-        usage |= WINED3DUSAGE_OWNDC;
+    return DD_OK;
 
-    if (desc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
-    {
-        pool = WINED3D_POOL_SYSTEM_MEM;
-    }
-    else if (desc->ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE)
-    {
-        pool = WINED3D_POOL_MANAGED;
-        /* Managed textures have the system memory flag set. */
-        desc->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
-    }
-    else if (desc->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
-    {
-        /* Videomemory adds localvidmem. This is mutually exclusive with
-         * systemmemory and texturemanage. */
-        desc->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM;
-    }
+fail:
+    if (version == 7)
+        IDirectDrawSurface7_Release(&root->IDirectDrawSurface7_iface);
+    else if (version == 4)
+        IDirectDrawSurface4_Release(&root->IDirectDrawSurface4_iface);
+    else
+        IDirectDrawSurface_Release(&root->IDirectDrawSurface_iface);
 
-    format = wined3dformat_from_ddrawformat(&desc->u4.ddpfPixelFormat);
-    if (format == WINED3DFMT_UNKNOWN)
-    {
-        WARN("Unsupported / unknown pixelformat.\n");
-        return DDERR_INVALIDPIXELFORMAT;
-    }
+    return hr;
+}
+
+HRESULT ddraw_surface_init(struct ddraw_surface *surface, struct ddraw *ddraw, struct ddraw_texture *texture,
+        struct wined3d_surface *wined3d_surface, const struct wined3d_parent_ops **parent_ops)
+{
+    DDSURFACEDESC2 *desc = &surface->surface_desc;
+    struct wined3d_resource_desc wined3d_desc;
+    unsigned int version = texture->version;
+    HRESULT hr;
 
     surface->IDirectDrawSurface7_iface.lpVtbl = &ddraw_surface7_vtbl;
     surface->IDirectDrawSurface4_iface.lpVtbl = &ddraw_surface4_vtbl;
@@ -5784,59 +6032,30 @@ HRESULT ddraw_surface_init(struct ddraw_surface *surface, struct ddraw *ddraw,
         surface->texture_outer = (IUnknown *)&surface->IDirectDrawSurface_iface;
     }
 
-    copy_to_surfacedesc2(&surface->surface_desc, desc);
-
+    *desc = texture->surface_desc;
+    wined3d_resource_get_desc(wined3d_surface_get_resource(wined3d_surface), &wined3d_desc);
+    desc->dwWidth = wined3d_desc.width;
+    desc->dwHeight = wined3d_desc.height;
     surface->first_attached = surface;
 
-    if (FAILED(hr = wined3d_surface_create(ddraw->wined3d_device, desc->dwWidth, desc->dwHeight, format,
-            usage, pool, WINED3D_MULTISAMPLE_NONE, 0, flags, surface,
-            &ddraw_surface_wined3d_parent_ops, &surface->wined3d_surface)))
-    {
-        WARN("Failed to create wined3d surface, hr %#x.\n", hr);
-        return hr;
-    }
-
     /* Anno 1602 stores the pitch right after surface creation, so make sure
      * it's there. TODO: Test other fourcc formats. */
-    if (format == WINED3DFMT_DXT1 || format == WINED3DFMT_DXT2 || format == WINED3DFMT_DXT3
-            || format == WINED3DFMT_DXT4 || format == WINED3DFMT_DXT5)
+    if (wined3d_desc.format == WINED3DFMT_DXT1 || wined3d_desc.format == WINED3DFMT_DXT2
+            || wined3d_desc.format == WINED3DFMT_DXT3 || wined3d_desc.format == WINED3DFMT_DXT4
+            || wined3d_desc.format == WINED3DFMT_DXT5)
     {
         surface->surface_desc.dwFlags |= DDSD_LINEARSIZE;
-        if (format == WINED3DFMT_DXT1)
-        {
+        if (wined3d_desc.format == WINED3DFMT_DXT1)
             surface->surface_desc.u1.dwLinearSize = max(4, desc->dwWidth) * max(4, desc->dwHeight) / 2;
-        }
         else
-        {
             surface->surface_desc.u1.dwLinearSize = max(4, desc->dwWidth) * max(4, desc->dwHeight);
-        }
     }
     else
     {
         surface->surface_desc.dwFlags |= DDSD_PITCH;
-        surface->surface_desc.u1.lPitch = wined3d_surface_get_pitch(surface->wined3d_surface);
+        surface->surface_desc.u1.lPitch = wined3d_surface_get_pitch(wined3d_surface);
     }
 
-    if (desc->dwFlags & DDSD_CKDESTOVERLAY)
-    {
-        wined3d_surface_set_color_key(surface->wined3d_surface, DDCKEY_DESTOVERLAY,
-                (struct wined3d_color_key *)&desc->u3.ddckCKDestOverlay);
-    }
-    if (desc->dwFlags & DDSD_CKDESTBLT)
-    {
-        wined3d_surface_set_color_key(surface->wined3d_surface, DDCKEY_DESTBLT,
-                (struct wined3d_color_key *)&desc->ddckCKDestBlt);
-    }
-    if (desc->dwFlags & DDSD_CKSRCOVERLAY)
-    {
-        wined3d_surface_set_color_key(surface->wined3d_surface, DDCKEY_SRCOVERLAY,
-                (struct wined3d_color_key *)&desc->ddckCKSrcOverlay);
-    }
-    if (desc->dwFlags & DDSD_CKSRCBLT)
-    {
-        wined3d_surface_set_color_key(surface->wined3d_surface, DDCKEY_SRCBLT,
-                (struct wined3d_color_key *)&desc->ddckCKSrcBlt);
-    }
     if (desc->dwFlags & DDSD_LPSURFACE)
     {
         UINT pitch = 0;
@@ -5847,13 +6066,18 @@ HRESULT ddraw_surface_init(struct ddraw_surface *surface, struct ddraw *ddraw,
             surface->surface_desc.u1.lPitch = pitch;
         }
 
-        if (FAILED(hr = wined3d_surface_set_mem(surface->wined3d_surface, desc->lpSurface, pitch)))
+        if (FAILED(hr = wined3d_surface_update_desc(wined3d_surface, wined3d_desc.width,
+                wined3d_desc.height, wined3d_desc.format, WINED3D_MULTISAMPLE_NONE, 0,
+                desc->lpSurface, pitch)))
         {
             ERR("Failed to set surface memory, hr %#x.\n", hr);
-            wined3d_surface_decref(surface->wined3d_surface);
             return hr;
         }
     }
 
+    wined3d_surface_incref(wined3d_surface);
+    surface->wined3d_surface = wined3d_surface;
+    *parent_ops = &ddraw_surface_wined3d_parent_ops;
+
     return DD_OK;
 }
index ad4913c..a504e2b 100644 (file)
@@ -9,10 +9,11 @@ include_directories(BEFORE ${REACTOS_SOURCE_DIR}/include/reactos/wine)
 spec2def(wined3d.dll wined3d.spec ADD_IMPORTLIB)
 
 list(APPEND SOURCE
-    ati_fragment_shader.c
     arb_program_shader.c
+    ati_fragment_shader.c
     buffer.c
     context.c
+    cs.c
     device.c
     directx.c
     drawprim.c
index 66c4640..2d30dd2 100644 (file)
@@ -33,13 +33,6 @@ 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;
@@ -145,9 +138,9 @@ static const char *arb_get_helper_value(enum wined3d_shader_type shader, enum ar
     }
 }
 
-static inline BOOL ffp_clip_emul(const struct wined3d_state *state)
+static inline BOOL ffp_clip_emul(const struct wined3d_context *context)
 {
-    return state->lowest_disabled_stage < 7;
+    return context->lowest_disabled_stage < 7;
 }
 
 /* ARB_program_shader private data */
@@ -176,7 +169,7 @@ struct control_frame
 struct arb_ps_np2fixup_info
 {
     struct ps_np2fixup_info         super;
-    /* For ARB we need a offset value:
+    /* For ARB we need an offset value:
      * With both GLSL and ARB mode the NP2 fixup information (the texture dimensions) are stored in a
      * consecutive way (GLSL uses a uniform array). Since ARB doesn't know the notion of a "standalone"
      * array we need an offset to the index inside the program local parameter array. */
@@ -658,7 +651,9 @@ static void shader_arb_load_constants_internal(struct shader_arb_priv *priv,
 
     if (!from_shader_select)
     {
-        const struct wined3d_shader *vshader = state->vertex_shader, *pshader = state->pixel_shader;
+        const struct wined3d_shader *vshader = state->shader[WINED3D_SHADER_TYPE_VERTEX];
+        const struct wined3d_shader *pshader = state->shader[WINED3D_SHADER_TYPE_PIXEL];
+
         if (vshader
                 && (vshader->reg_maps.boolean_constants
                 || (!gl_info->supported[NV_VERTEX_PROGRAM2_OPTION]
@@ -692,7 +687,7 @@ static void shader_arb_load_constants_internal(struct shader_arb_priv *priv,
 
     if (useVertexShader)
     {
-        struct wined3d_shader *vshader = state->vertex_shader;
+        const struct wined3d_shader *vshader = state->shader[WINED3D_SHADER_TYPE_VERTEX];
         const struct arb_vs_compiled_shader *gl_shader = priv->compiled_vprog;
 
         /* Load DirectX 9 float constants for vertex shader */
@@ -703,7 +698,7 @@ static void shader_arb_load_constants_internal(struct shader_arb_priv *priv,
 
     if (usePixelShader)
     {
-        struct wined3d_shader *pshader = state->pixel_shader;
+        const struct wined3d_shader *pshader = state->shader[WINED3D_SHADER_TYPE_PIXEL];
         const struct arb_ps_compiled_shader *gl_shader = priv->compiled_fprog;
         UINT rt_height = state->fb->render_targets[0]->resource.height;
 
@@ -764,6 +759,17 @@ 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 void shader_arb_append_imm_vec4(struct wined3d_shader_buffer *buffer, const float *values)
+{
+    char str[4][17];
+
+    wined3d_ftoa(values[0], str[0]);
+    wined3d_ftoa(values[1], str[1]);
+    wined3d_ftoa(values[2], str[2]);
+    wined3d_ftoa(values[3], str[3]);
+    shader_addline(buffer, "{%s, %s, %s, %s}", str[0], str[1], str[2], str[3]);
+}
+
 /* Generate the variable & register declarations for the ARB_vertex_program output target */
 static void shader_generate_arb_declarations(const struct wined3d_shader *shader,
         const struct wined3d_shader_reg_maps *reg_maps, struct wined3d_shader_buffer *buffer,
@@ -868,8 +874,9 @@ static void shader_generate_arb_declarations(const struct wined3d_shader *shader
         {
             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]);
+            shader_addline(buffer, "PARAM C%u = ", lconst->idx);
+            shader_arb_append_imm_vec4(buffer, value);
+            shader_addline(buffer, ";\n");
         }
     }
 
@@ -1106,7 +1113,7 @@ static void shader_arb_get_register_name(const struct wined3d_shader_instruction
             if (!pshader && reg->idx[0].rel_addr)
             {
                 const struct arb_vshader_private *shader_data = shader->backend_data;
-                UINT rel_offset = shader_data->rel_offset;
+                UINT rel_offset = ctx->target_version == ARB ? shader_data->rel_offset : 0;
                 BOOL aL = FALSE;
                 char rel_reg[50];
                 if (reg_maps->shader_version.major < 2)
@@ -1493,17 +1500,16 @@ static void shader_arb_get_src_param(const struct wined3d_shader_instruction *in
         const struct wined3d_shader_src_param *src, unsigned int tmpreg, char *outregstr)
 {
     /* Generate a line that does the input modifier computation and return the input register to use */
-    BOOL is_color = FALSE;
+    BOOL is_color = FALSE, insert_line;
     char regstr[256];
     char swzstr[20];
-    int insert_line;
     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
     struct shader_arb_ctx_priv *ctx = ins->ctx->backend_data;
     const char *one = arb_get_helper_value(ins->ctx->reg_maps->shader_version.type, ARB_ONE);
     const char *two = arb_get_helper_value(ins->ctx->reg_maps->shader_version.type, ARB_TWO);
 
     /* Assume a new line will be added */
-    insert_line = 1;
+    insert_line = TRUE;
 
     /* Get register name */
     shader_arb_get_register_name(ins, &src->reg, regstr, &is_color);
@@ -1513,11 +1519,11 @@ static void shader_arb_get_src_param(const struct wined3d_shader_instruction *in
     {
     case WINED3DSPSM_NONE:
         sprintf(outregstr, "%s%s", regstr, swzstr);
-        insert_line = 0;
+        insert_line = FALSE;
         break;
     case WINED3DSPSM_NEG:
         sprintf(outregstr, "-%s%s", regstr, swzstr);
-        insert_line = 0;
+        insert_line = FALSE;
         break;
     case WINED3DSPSM_BIAS:
         shader_addline(buffer, "ADD T%c, %s, -coefdiv.x;\n", 'A' + tmpreg, regstr);
@@ -1551,7 +1557,7 @@ static void shader_arb_get_src_param(const struct wined3d_shader_instruction *in
     case WINED3DSPSM_ABS:
         if(ctx->target_version >= NV2) {
             sprintf(outregstr, "|%s%s|", regstr, swzstr);
-            insert_line = 0;
+            insert_line = FALSE;
         } else {
             shader_addline(buffer, "ABS T%c, %s;\n", 'A' + tmpreg, regstr);
         }
@@ -1563,11 +1569,11 @@ static void shader_arb_get_src_param(const struct wined3d_shader_instruction *in
             shader_addline(buffer, "ABS T%c, %s;\n", 'A' + tmpreg, regstr);
             sprintf(outregstr, "-T%c%s", 'A' + tmpreg, swzstr);
         }
-        insert_line = 0;
+        insert_line = FALSE;
         break;
     default:
         sprintf(outregstr, "%s%s", regstr, swzstr);
-        insert_line = 0;
+        insert_line = FALSE;
     }
 
     /* Return modified or original register, with swizzle */
@@ -1837,7 +1843,7 @@ static void shader_hw_mov(const struct wined3d_shader_instruction *ins)
         const struct arb_vshader_private *shader_data = shader->backend_data;
         src0_param[0] = '\0';
 
-        if (shader_data->rel_offset)
+        if (shader_data->rel_offset && ctx->target_version == ARB)
         {
             const char *offset = arb_get_helper_value(WINED3D_SHADER_TYPE_VERTEX, ARB_VS_REL_OFFSET);
             shader_arb_get_src_param(ins, &ins->src[0], 0, src0_param);
@@ -3442,29 +3448,29 @@ static void arbfp_add_sRGB_correction(struct wined3d_shader_buffer *buffer, cons
     if(condcode)
     {
         /* Sigh. MOVC CC doesn't work, so use one of the temps as dummy dest */
-        shader_addline(buffer, "SUBC %s, %s.x, srgb_consts1.y;\n", tmp1, fragcolor);
+        shader_addline(buffer, "SUBC %s, %s.x, srgb_consts1.x;\n", tmp1, fragcolor);
         /* Calculate the > 0.0031308 case */
-        shader_addline(buffer, "POW %s.x (GE), %s.x, srgb_consts1.z;\n", fragcolor, fragcolor);
-        shader_addline(buffer, "POW %s.y (GE), %s.y, srgb_consts1.z;\n", fragcolor, fragcolor);
-        shader_addline(buffer, "POW %s.z (GE), %s.z, srgb_consts1.z;\n", fragcolor, fragcolor);
-        shader_addline(buffer, "MUL %s.xyz (GE), %s, srgb_consts1.w;\n", fragcolor, fragcolor);
-        shader_addline(buffer, "SUB %s.xyz (GE), %s, srgb_consts2.x;\n", fragcolor, fragcolor);
+        shader_addline(buffer, "POW %s.x (GE), %s.x, srgb_consts0.x;\n", fragcolor, fragcolor);
+        shader_addline(buffer, "POW %s.y (GE), %s.y, srgb_consts0.x;\n", fragcolor, fragcolor);
+        shader_addline(buffer, "POW %s.z (GE), %s.z, srgb_consts0.x;\n", fragcolor, fragcolor);
+        shader_addline(buffer, "MUL %s.xyz (GE), %s, srgb_consts0.y;\n", fragcolor, fragcolor);
+        shader_addline(buffer, "SUB %s.xyz (GE), %s, srgb_consts0.z;\n", fragcolor, fragcolor);
         /* Calculate the < case */
-        shader_addline(buffer, "MUL %s.xyz (LT), srgb_consts1.x, %s;\n", fragcolor, fragcolor);
+        shader_addline(buffer, "MUL %s.xyz (LT), srgb_consts0.w, %s;\n", fragcolor, fragcolor);
     }
     else
     {
         /* Calculate the > 0.0031308 case */
-        shader_addline(buffer, "POW %s.x, %s.x, srgb_consts1.z;\n", tmp1, fragcolor);
-        shader_addline(buffer, "POW %s.y, %s.y, srgb_consts1.z;\n", tmp1, fragcolor);
-        shader_addline(buffer, "POW %s.z, %s.z, srgb_consts1.z;\n", tmp1, fragcolor);
-        shader_addline(buffer, "MUL %s, %s, srgb_consts1.w;\n", tmp1, tmp1);
-        shader_addline(buffer, "SUB %s, %s, srgb_consts2.x;\n", tmp1, tmp1);
+        shader_addline(buffer, "POW %s.x, %s.x, srgb_consts0.x;\n", tmp1, fragcolor);
+        shader_addline(buffer, "POW %s.y, %s.y, srgb_consts0.x;\n", tmp1, fragcolor);
+        shader_addline(buffer, "POW %s.z, %s.z, srgb_consts0.x;\n", tmp1, fragcolor);
+        shader_addline(buffer, "MUL %s, %s, srgb_consts0.y;\n", tmp1, tmp1);
+        shader_addline(buffer, "SUB %s, %s, srgb_consts0.z;\n", tmp1, tmp1);
         /* Calculate the < case */
-        shader_addline(buffer, "MUL %s, srgb_consts1.x, %s;\n", tmp2, fragcolor);
+        shader_addline(buffer, "MUL %s, srgb_consts0.w, %s;\n", tmp2, fragcolor);
         /* Get 1.0 / 0.0 masks for > 0.0031308 and < 0.0031308 */
-        shader_addline(buffer, "SLT %s, srgb_consts1.y, %s;\n", tmp3, fragcolor);
-        shader_addline(buffer, "SGE %s, srgb_consts1.y, %s;\n", tmp4, fragcolor);
+        shader_addline(buffer, "SLT %s, srgb_consts1.x, %s;\n", tmp3, fragcolor);
+        shader_addline(buffer, "SGE %s, srgb_consts1.x, %s;\n", tmp4, fragcolor);
         /* Store the components > 0.0031308 in the destination */
         shader_addline(buffer, "MUL %s.xyz, %s, %s;\n", fragcolor, tmp1, tmp3);
         /* Add the components that are < 0.0031308 */
@@ -3593,6 +3599,7 @@ static GLuint shader_arb_generate_pshader(const struct wined3d_shader *shader,
     BOOL custom_linear_fog = FALSE;
 
     char srgbtmp[4][4];
+    char ftoa_tmp[17];
     unsigned int i, found = 0;
 
     for (i = 0, map = reg_maps->temporary; map; map >>= 1, ++i)
@@ -3718,7 +3725,8 @@ static GLuint shader_arb_generate_pshader(const struct wined3d_shader *shader,
     if(dcl_td) shader_addline(buffer, "TEMP TD;\n"); /* Used for sRGB writing */
     shader_addline(buffer, "PARAM coefdiv = { 0.5, 0.25, 0.125, 0.0625 };\n");
     shader_addline(buffer, "PARAM coefmul = { 2, 4, 8, 16 };\n");
-    shader_addline(buffer, "PARAM ps_helper_const = { 0.0, 1.0, %1.10f, 0.0 };\n", eps);
+    wined3d_ftoa(eps, ftoa_tmp);
+    shader_addline(buffer, "PARAM ps_helper_const = { 0.0, 1.0, %s, 0.0 };\n", ftoa_tmp);
 
     if (reg_maps->shader_version.major < 2)
     {
@@ -3742,11 +3750,14 @@ static GLuint shader_arb_generate_pshader(const struct wined3d_shader *shader,
         }
     }
 
-    if(args->super.srgb_correction) {
-        shader_addline(buffer, "PARAM srgb_consts1 = {%f, %f, %f, %f};\n",
-                       srgb_mul_low, srgb_cmp, srgb_pow, srgb_mul_high);
-        shader_addline(buffer, "PARAM srgb_consts2 = {%f, %f, %f, %f};\n",
-                       srgb_sub_high, 0.0, 0.0, 0.0);
+    if (args->super.srgb_correction)
+    {
+        shader_addline(buffer, "PARAM srgb_consts0 = ");
+        shader_arb_append_imm_vec4(buffer, wined3d_srgb_const0);
+        shader_addline(buffer, ";\n");
+        shader_addline(buffer, "PARAM srgb_consts1 = ");
+        shader_arb_append_imm_vec4(buffer, wined3d_srgb_const1);
+        shader_addline(buffer, ";\n");
     }
 
     /* Base Declarations */
@@ -3972,7 +3983,7 @@ static DWORD find_input_signature(struct shader_arb_priv *priv, const struct win
         TRACE("Found existing signature %u\n", found_sig->idx);
         return found_sig->idx;
     }
-    found_sig = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*sig));
+    found_sig = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*found_sig));
     found_sig->sig = clone_sig(sig);
     found_sig->idx = priv->ps_sig_number++;
     TRACE("New signature stored and assigned number %u\n", found_sig->idx);
@@ -4203,7 +4214,9 @@ static GLuint shader_arb_generate_vshader(const struct wined3d_shader *shader,
         shader_addline(buffer, "TEMP TMP_FOGCOORD;\n");
     if (need_helper_const(shader_data, reg_maps, gl_info))
     {
-        shader_addline(buffer, "PARAM helper_const = { 0.0, 1.0, 2.0, %1.10f};\n", eps);
+        char ftoa_tmp[17];
+        wined3d_ftoa(eps, ftoa_tmp);
+        shader_addline(buffer, "PARAM helper_const = { 0.0, 1.0, 2.0, %s};\n", ftoa_tmp);
     }
     if (need_rel_addr_const(shader_data, reg_maps, gl_info))
     {
@@ -4412,12 +4425,9 @@ 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 wined3d_gl_info *gl_info, DWORD use_map, const struct arb_vs_compile_args *args,
         const struct wined3d_shader_signature_element *ps_input_sig)
 {
-    struct wined3d_device *device = shader->device;
-    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
-    DWORD use_map = device->stream_info.use_map;
     UINT i;
     DWORD new_size;
     struct arb_vs_compiled_shader *new_array;
@@ -4508,7 +4518,7 @@ static void find_arb_ps_compile_args(const struct wined3d_state *state,
     int i;
     WORD int_skip;
 
-    find_ps_compile_args(state, shader, &args->super);
+    find_ps_compile_args(state, shader, context->stream_info.position_transformed, &args->super, gl_info);
 
     /* This forces all local boolean constants to 1 to make them stateblock independent */
     args->bools = shader->reg_maps.local_bool_consts;
@@ -4559,19 +4569,19 @@ static void find_arb_vs_compile_args(const struct wined3d_state *state,
         const struct wined3d_context *context, const struct wined3d_shader *shader,
         struct arb_vs_compile_args *args)
 {
-    struct wined3d_device *device = shader->device;
+    const struct wined3d_device *device = shader->device;
     const struct wined3d_adapter *adapter = device->adapter;
     const struct wined3d_gl_info *gl_info = context->gl_info;
     const struct wined3d_d3d_info *d3d_info = context->d3d_info;
     int i;
     WORD int_skip;
 
-    find_vs_compile_args(state, shader, &args->super);
+    find_vs_compile_args(state, shader, context->stream_info.swizzle_map, &args->super);
 
     args->clip.boolclip_compare = 0;
     if (use_ps(state))
     {
-        const struct wined3d_shader *ps = state->pixel_shader;
+        const struct wined3d_shader *ps = state->shader[WINED3D_SHADER_TYPE_PIXEL];
         const struct arb_pshader_private *shader_priv = ps->backend_data;
         args->ps_signature = shader_priv->input_signature_idx;
 
@@ -4581,9 +4591,7 @@ static void find_arb_vs_compile_args(const struct wined3d_state *state,
     {
         args->ps_signature = ~0;
         if (!d3d_info->vs_clipping && adapter->fragment_pipe == &arbfp_fragment_pipeline)
-        {
-            args->clip.boolclip.clip_texcoord = ffp_clip_emul(state) ? d3d_info->limits.ffp_blend_stages : 0;
-        }
+            args->clip.boolclip.clip_texcoord = ffp_clip_emul(context) ? d3d_info->limits.ffp_blend_stages : 0;
         /* Otherwise: Setting boolclip_compare set clip_texcoord to 0 */
     }
 
@@ -4603,9 +4611,9 @@ static void find_arb_vs_compile_args(const struct wined3d_state *state,
             args->clip.boolclip.bools |= ( 1 << i);
     }
 
-    args->vertex.samplers[0] = device->texUnitMap[MAX_FRAGMENT_SAMPLERS + 0];
-    args->vertex.samplers[1] = device->texUnitMap[MAX_FRAGMENT_SAMPLERS + 1];
-    args->vertex.samplers[2] = device->texUnitMap[MAX_FRAGMENT_SAMPLERS + 2];
+    args->vertex.samplers[0] = context->tex_unit_map[MAX_FRAGMENT_SAMPLERS + 0];
+    args->vertex.samplers[1] = context->tex_unit_map[MAX_FRAGMENT_SAMPLERS + 1];
+    args->vertex.samplers[2] = context->tex_unit_map[MAX_FRAGMENT_SAMPLERS + 2];
     args->vertex.samplers[3] = 0;
 
     /* Skip if unused or local */
@@ -4645,7 +4653,7 @@ static void shader_arb_select(void *shader_priv, struct wined3d_context *context
     /* Deal with pixel shaders first so the vertex shader arg function has the input signature ready */
     if (use_ps(state))
     {
-        struct wined3d_shader *ps = state->pixel_shader;
+        struct wined3d_shader *ps = state->shader[WINED3D_SHADER_TYPE_PIXEL];
         struct arb_ps_compile_args compile_args;
         struct arb_ps_compiled_shader *compiled;
 
@@ -4712,7 +4720,7 @@ static void shader_arb_select(void *shader_priv, struct wined3d_context *context
 
     if (use_vs(state))
     {
-        struct wined3d_shader *vs = state->vertex_shader;
+        struct wined3d_shader *vs = state->shader[WINED3D_SHADER_TYPE_VERTEX];
         struct arb_vs_compile_args compile_args;
         struct arb_vs_compiled_shader *compiled;
         const struct wined3d_shader_signature_element *ps_input_sig;
@@ -4726,9 +4734,10 @@ static void shader_arb_select(void *shader_priv, struct wined3d_context *context
         if (compile_args.ps_signature == ~0U)
             ps_input_sig = NULL;
         else
-            ps_input_sig = state->pixel_shader->input_signature;
+            ps_input_sig = state->shader[WINED3D_SHADER_TYPE_PIXEL]->input_signature;
 
-        compiled = find_arb_vshader(vs, &compile_args, ps_input_sig);
+        compiled = find_arb_vshader(vs, context->gl_info, context->stream_info.use_map,
+                &compile_args, ps_input_sig);
         priv->current_vprogram_id = compiled->prgId;
         priv->compiled_vprog = compiled;
 
@@ -5300,7 +5309,7 @@ static BOOL get_bool_const(const struct wined3d_shader_instruction *ins,
 
     if (reg_maps->local_bool_consts & flag)
     {
-        /* What good is a if(bool) with a hardcoded local constant? I don't know, but handle it */
+        /* What good is an if(bool) with a hardcoded local constant? I don't know, but handle it */
         LIST_FOR_EACH_ENTRY(constant, &shader->constantsB, struct wined3d_shader_lconst, entry)
         {
             if (constant->idx == idx)
@@ -6170,7 +6179,7 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, con
     BOOL luminance_used[MAX_TEXTURES] = {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE};
     UINT lowest_disabled_stage;
     const char *textype;
-    const char *instr, *sat;
+    const char *instr;
     char colorcor_dst[8];
     GLuint ret;
     DWORD arg0, arg1, arg2;
@@ -6285,11 +6294,14 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, con
     }
     shader_addline(&buffer, "PARAM specular_enable = program.env[%u];\n", ARB_FFP_CONST_SPECULAR_ENABLE);
 
-    if(settings->sRGB_write) {
-        shader_addline(&buffer, "PARAM srgb_consts1 = {%f, %f, %f, %f};\n",
-                       srgb_mul_low, srgb_cmp, srgb_pow, srgb_mul_high);
-        shader_addline(&buffer, "PARAM srgb_consts2 = {%f, %f, %f, %f};\n",
-                       srgb_sub_high, 0.0, 0.0, 0.0);
+    if (settings->sRGB_write)
+    {
+        shader_addline(&buffer, "PARAM srgb_consts0 = ");
+        shader_arb_append_imm_vec4(&buffer, wined3d_srgb_const0);
+        shader_addline(&buffer, ";\n");
+        shader_addline(&buffer, "PARAM srgb_consts1 = ");
+        shader_arb_append_imm_vec4(&buffer, wined3d_srgb_const1);
+        shader_addline(&buffer, ";\n");
     }
 
     if (lowest_disabled_stage < 7 && settings->emul_clipplanes)
@@ -6310,12 +6322,6 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, con
             default: textype = "unexpected_textype";   break;
         }
 
-        if (settings->op[stage].cop == WINED3D_TOP_BUMPENVMAP
-                || settings->op[stage].cop == WINED3D_TOP_BUMPENVMAP_LUMINANCE)
-            sat = "";
-        else
-            sat = "_SAT";
-
         if(settings->op[stage].projected == proj_none) {
             instr = "TEX";
         } else if(settings->op[stage].projected == proj_count4 ||
@@ -6350,8 +6356,8 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, con
                 shader_addline(&buffer, "ADD ret, ret, fragment.texcoord[%u];\n", stage);
             }
 
-            shader_addline(&buffer, "%s%s tex%u, ret, texture[%u], %s;\n",
-                    instr, sat, stage, stage, textype);
+            shader_addline(&buffer, "%s tex%u, ret, texture[%u], %s;\n",
+                    instr, stage, stage, textype);
             if (settings->op[stage - 1].cop == WINED3D_TOP_BUMPENVMAP_LUMINANCE)
             {
                 shader_addline(&buffer, "MAD_SAT ret.x, tex%u.z, luminance%u.x, luminance%u.y;\n",
@@ -6361,11 +6367,11 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, con
         } else if(settings->op[stage].projected == proj_count3) {
             shader_addline(&buffer, "MOV ret, fragment.texcoord[%u];\n", stage);
             shader_addline(&buffer, "MOV ret.w, ret.z;\n");
-            shader_addline(&buffer, "%s%s tex%u, ret, texture[%u], %s;\n",
-                            instr, sat, stage, stage, textype);
+            shader_addline(&buffer, "%s tex%u, ret, texture[%u], %s;\n",
+                            instr, stage, stage, textype);
         } else {
-            shader_addline(&buffer, "%s%s tex%u, fragment.texcoord[%u], texture[%u], %s;\n",
-                            instr, sat, stage, stage, stage, textype);
+            shader_addline(&buffer, "%s tex%u, fragment.texcoord[%u], texture[%u], %s;\n",
+                            instr, stage, stage, stage, textype);
         }
 
         sprintf(colorcor_dst, "tex%u", stage);
@@ -6564,7 +6570,7 @@ static void state_arbfp_fog(struct wined3d_context *context, const struct wined3
 
     TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);
 
-    if (!isStateDirty(context, STATE_PIXELSHADER))
+    if (!isStateDirty(context, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL)))
         fragment_prog_arbfp(context, state, state_id);
 
     if (!state->render_states[WINED3D_RS_FOGENABLE])
@@ -6598,141 +6604,141 @@ static void state_arbfp_fog(struct wined3d_context *context, const struct wined3
 
 static void textransform(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
-    if (!isStateDirty(context, STATE_PIXELSHADER))
+    if (!isStateDirty(context, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL)))
         fragment_prog_arbfp(context, state, state_id);
 }
 
 static const struct StateEntryTemplate arbfp_fragmentstate_template[] =
 {
     {STATE_RENDER(WINED3D_RS_TEXTUREFACTOR),              { STATE_RENDER(WINED3D_RS_TEXTUREFACTOR),             state_texfactor_arbfp   }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG1),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG2),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG0),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_OP),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG1),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG2),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG0),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(0, WINED3D_TSS_RESULT_ARG),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),         { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG1),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG2),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG0),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_OP),         { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG1),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG2),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG0),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(0, WINED3D_TSS_RESULT_ARG),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   set_bumpmat_arbfp       }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT01),    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT10),    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT11),    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE),   { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE),  tex_bumpenvlum_arbfp    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LOFFSET),  { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE),  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_OP),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG1),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG2),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG0),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_OP),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG1),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG2),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG0),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(1, WINED3D_TSS_RESULT_ARG),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_OP),         { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG1),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG2),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG0),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_OP),         { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG1),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG2),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG0),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(1, WINED3D_TSS_RESULT_ARG),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   set_bumpmat_arbfp       }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT01),    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT10),    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT11),    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE),   { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE),  tex_bumpenvlum_arbfp    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LOFFSET),  { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE),  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_OP),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG1),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG2),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG0),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_OP),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG1),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG2),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG0),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(2, WINED3D_TSS_RESULT_ARG),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_OP),         { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG1),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG2),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG0),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_OP),         { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG1),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG2),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG0),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(2, WINED3D_TSS_RESULT_ARG),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   set_bumpmat_arbfp       }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT01),    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT10),    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT11),    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE),   { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE),  tex_bumpenvlum_arbfp    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LOFFSET),  { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE),  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_OP),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG1),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG2),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG0),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_OP),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG1),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG2),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG0),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(3, WINED3D_TSS_RESULT_ARG),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_OP),         { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG1),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG2),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG0),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_OP),         { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG1),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG2),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG0),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(3, WINED3D_TSS_RESULT_ARG),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   set_bumpmat_arbfp       }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT01),    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT10),    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT11),    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE),   { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE),  tex_bumpenvlum_arbfp    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LOFFSET),  { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE),  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_OP),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG1),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG2),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG0),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_OP),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG1),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG2),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG0),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(4, WINED3D_TSS_RESULT_ARG),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_OP),         { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG1),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG2),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG0),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_OP),         { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG1),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG2),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG0),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(4, WINED3D_TSS_RESULT_ARG),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   set_bumpmat_arbfp       }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT01),    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT10),    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT11),    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE),   { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE),  tex_bumpenvlum_arbfp    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LOFFSET),  { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE),  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_OP),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG1),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG2),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG0),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_OP),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG1),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG2),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG0),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(5, WINED3D_TSS_RESULT_ARG),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_OP),         { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG1),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG2),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG0),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_OP),         { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG1),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG2),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG0),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(5, WINED3D_TSS_RESULT_ARG),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   set_bumpmat_arbfp       }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT01),    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT10),    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT11),    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE),   { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE),  tex_bumpenvlum_arbfp    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LOFFSET),  { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE),  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_OP),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG1),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG2),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG0),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_OP),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG1),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG2),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG0),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(6, WINED3D_TSS_RESULT_ARG),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_OP),         { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG1),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG2),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG0),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_OP),         { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG1),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG2),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG0),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(6, WINED3D_TSS_RESULT_ARG),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   set_bumpmat_arbfp       }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT01),    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT10),    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT11),    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE),   { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE),  tex_bumpenvlum_arbfp    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LOFFSET),  { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE),  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_OP),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG1),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG2),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG0),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_OP),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG1),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG2),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG0),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_TEXTURESTAGE(7, WINED3D_TSS_RESULT_ARG),       { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_OP),         { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG1),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG2),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG0),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_OP),         { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG1),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG2),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG0),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_TEXTURESTAGE(7, WINED3D_TSS_RESULT_ARG),       { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   set_bumpmat_arbfp       }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT01),    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT10),    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT11),    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE),   { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE),  tex_bumpenvlum_arbfp    }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LOFFSET),  { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE),  NULL                    }, WINED3D_GL_EXT_NONE             },
-    {STATE_PIXELSHADER,                                   { STATE_PIXELSHADER,                                  fragment_prog_arbfp     }, WINED3D_GL_EXT_NONE             },
+    {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),             { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            fragment_prog_arbfp     }, WINED3D_GL_EXT_NONE             },
     {STATE_RENDER(WINED3D_RS_FOGENABLE),                  { STATE_RENDER(WINED3D_RS_FOGENABLE),                 state_arbfp_fog         }, WINED3D_GL_EXT_NONE             },
     {STATE_RENDER(WINED3D_RS_FOGTABLEMODE),               { STATE_RENDER(WINED3D_RS_FOGENABLE),                 NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_RENDER(WINED3D_RS_FOGVERTEXMODE),              { STATE_RENDER(WINED3D_RS_FOGENABLE),                 NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_RENDER(WINED3D_RS_FOGSTART),                   { STATE_RENDER(WINED3D_RS_FOGSTART),                  state_fogstartend       }, WINED3D_GL_EXT_NONE             },
     {STATE_RENDER(WINED3D_RS_FOGEND),                     { STATE_RENDER(WINED3D_RS_FOGSTART),                  NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE),            { STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE),           state_srgbwrite         }, ARB_FRAMEBUFFER_SRGB            },
-    {STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE),            { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
+    {STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE),            { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                    }, WINED3D_GL_EXT_NONE             },
     {STATE_RENDER(WINED3D_RS_FOGCOLOR),                   { STATE_RENDER(WINED3D_RS_FOGCOLOR),                  state_fogcolor          }, WINED3D_GL_EXT_NONE             },
     {STATE_RENDER(WINED3D_RS_FOGDENSITY),                 { STATE_RENDER(WINED3D_RS_FOGDENSITY),                state_fogdensity        }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(0,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
@@ -6888,6 +6894,8 @@ static BOOL gen_planar_yuv_read(struct wined3d_shader_buffer *buffer, enum compl
 static BOOL gen_yv12_read(struct wined3d_shader_buffer *buffer, GLenum textype, char *luminance)
 {
     const char *tex;
+    static const float yv12_coef[]
+            = {2.0f / 3.0f, 1.0f / 6.0f, (2.0f / 3.0f) + (1.0f / 6.0f), 1.0f / 3.0f};
 
     switch(textype) {
         case GL_TEXTURE_2D:             tex = "2D";     break;
@@ -6935,8 +6943,9 @@ static BOOL gen_yv12_read(struct wined3d_shader_buffer *buffer, GLenum textype,
      * When reading from rectangle textures, keep in mind that the input y coordinates
      * go from 0 to d3d_height, whereas the opengl texture height is 1.5 * d3d_height
      */
-    shader_addline(buffer, "PARAM yv12_coef = {%f, %f, %f, %f};\n",
-            2.0f / 3.0f, 1.0f / 6.0f, (2.0f / 3.0f) + (1.0f / 6.0f), 1.0f / 3.0f);
+    shader_addline(buffer, "PARAM yv12_coef = ");
+    shader_arb_append_imm_vec4(buffer, yv12_coef);
+    shader_addline(buffer, ";\n");
 
     shader_addline(buffer, "MOV texcrd, fragment.texcoord[0];\n");
     /* the chroma planes have only half the width */
@@ -7101,7 +7110,7 @@ static void upload_palette(const struct wined3d_surface *surface, struct wined3d
     struct wined3d_device *device = surface->resource.device;
     const struct wined3d_gl_info *gl_info = context->gl_info;
     struct arbfp_blit_priv *priv = device->blit_priv;
-    BOOL colorkey = (surface->CKeyFlags & WINEDDSD_CKSRCBLT) != 0;
+    BOOL colorkey = !!(surface->container->color_key_flags & WINEDDSD_CKSRCBLT);
 
     d3dfmt_p8_init_palette(surface, table, colorkey);
 
@@ -7286,12 +7295,7 @@ static HRESULT arbfp_blit_set(void *blit_priv, struct wined3d_context *context,
     struct arbfp_blit_priv *priv = blit_priv;
     enum complex_fixup fixup;
     const struct wined3d_gl_info *gl_info = context->gl_info;
-    GLenum textype;
-
-    if (surface->container)
-        textype = surface->container->target;
-    else
-        textype = surface->texture_target;
+    GLenum textype = surface->container->target;
 
     if (surface->flags & SFLAG_CONVERTED)
     {
@@ -7439,9 +7443,14 @@ HRESULT arbfp_blit_surface(struct wined3d_device *device, DWORD filter,
     RECT src_rect = *src_rect_in;
     RECT dst_rect = *dst_rect_in;
 
+    /* Activate the destination context, set it up for blitting */
+    context = context_acquire(device, dst_surface);
+
     /* Now load the surface */
     if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
-            && (src_surface->flags & (SFLAG_INTEXTURE | SFLAG_INDRAWABLE)) == SFLAG_INDRAWABLE)
+            && (src_surface->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_DRAWABLE))
+            == WINED3D_LOCATION_DRAWABLE
+            && !surface_is_offscreen(src_surface))
     {
         /* Without FBO blits transferring from the drawable to the texture is
          * expensive, because we have to flip the data in sysmem. Since we can
@@ -7454,10 +7463,8 @@ HRESULT arbfp_blit_surface(struct wined3d_device *device, DWORD filter,
         src_rect.bottom = src_surface->resource.height - src_rect.bottom;
     }
     else
-        surface_internal_preload(src_surface, SRGB_RGB);
+        wined3d_texture_load(src_surface->container, context, FALSE);
 
-    /* Activate the destination context, set it up for blitting */
-    context = context_acquire(device, dst_surface);
     context_apply_blit_state(context, device);
 
     if (!surface_is_offscreen(dst_surface))
@@ -7477,11 +7484,12 @@ HRESULT arbfp_blit_surface(struct wined3d_device *device, DWORD filter,
 
     context_release(context);
 
-    surface_modify_location(dst_surface, dst_surface->draw_binding, TRUE);
+    surface_validate_location(dst_surface, dst_surface->draw_binding);
+    surface_invalidate_location(dst_surface, ~dst_surface->draw_binding);
+
     return WINED3D_OK;
 }
 
-/* Do not call while under the GL lock. */
 static HRESULT arbfp_blit_color_fill(struct wined3d_device *device, struct wined3d_surface *dst_surface,
         const RECT *dst_rect, const struct wined3d_color *color)
 {
@@ -7489,7 +7497,6 @@ static HRESULT arbfp_blit_color_fill(struct wined3d_device *device, struct wined
     return WINED3DERR_INVALIDCALL;
 }
 
-/* Do not call while under the GL lock. */
 static HRESULT arbfp_blit_depth_fill(struct wined3d_device *device,
         struct wined3d_surface *surface, const RECT *rect, float depth)
 {
index 0dd5774..92c25db 100644 (file)
@@ -868,7 +868,7 @@ static void set_tex_op_atifs(struct wined3d_context *context, const struct wined
      */
     for (i = 0; i < desc->num_textures_used; ++i)
     {
-        mapped_stage = device->texUnitMap[i];
+        mapped_stage = context->tex_unit_map[i];
         if (mapped_stage != WINED3D_UNMAPPED_STAGE)
         {
             context_active_texture(context, gl_info, mapped_stage);
@@ -916,7 +916,7 @@ static void set_bumpmat(struct wined3d_context *context, const struct wined3d_st
 
 static void textransform(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
-    if (!isStateDirty(context, STATE_PIXELSHADER))
+    if (!isStateDirty(context, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL)))
         set_tex_op_atifs(context, state, state_id);
 }
 
@@ -1075,7 +1075,7 @@ static const struct StateEntryTemplate atifs_fragmentstate_template[] = {
     {STATE_TEXTURESTAGE(5,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(6,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
     {STATE_TEXTURESTAGE(7,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
-    {STATE_PIXELSHADER,                                   { STATE_PIXELSHADER,                                  atifs_apply_pixelshader }, WINED3D_GL_EXT_NONE             },
+    {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),             { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            atifs_apply_pixelshader }, WINED3D_GL_EXT_NONE             },
     {0 /* Terminate */,                                   { 0,                                                  0                       }, WINED3D_GL_EXT_NONE             },
 };
 
index 5a0f0ab..6a6fbcf 100644 (file)
@@ -3,7 +3,7 @@
  * Copyright 2002-2005 Raphael Junqueira
  * Copyright 2004 Christian Costa
  * Copyright 2005 Oliver Stieber
- * Copyright 2007-2011, 2013 Stefan Dösinger for CodeWeavers
+ * Copyright 2007-2011, 2013-2014 Stefan Dösinger for CodeWeavers
  * Copyright 2009-2010 Henri Verbeet for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
@@ -115,10 +115,11 @@ 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)
+static void buffer_create_buffer_object(struct wined3d_buffer *This, struct wined3d_context *context)
 {
     GLenum gl_usage = GL_STATIC_DRAW_ARB;
     GLenum error;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
 
     TRACE("Creating an OpenGL vertex buffer object for wined3d_buffer %p with usage %s.\n",
             This, debug_d3dusage(This->resource.usage));
@@ -145,7 +146,7 @@ static void buffer_create_buffer_object(struct wined3d_buffer *This, const struc
     }
 
     if (This->buffer_type_hint == GL_ELEMENT_ARRAY_BUFFER_ARB)
-        device_invalidate_state(This->resource.device, STATE_INDEXBUFFER);
+        context_invalidate_state(context, STATE_INDEXBUFFER);
     GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object));
     error = gl_info->gl_ops.gl.p_glGetError();
     if (error != GL_NO_ERROR)
@@ -177,7 +178,7 @@ static void buffer_create_buffer_object(struct wined3d_buffer *This, const struc
      * calling glBufferSubData on updates. Upload the actual data in case
      * we're not double buffering, so we can release the heap mem afterwards
      */
-    GL_EXTCALL(glBufferDataARB(This->buffer_type_hint, This->resource.size, This->resource.allocatedMemory, gl_usage));
+    GL_EXTCALL(glBufferDataARB(This->buffer_type_hint, This->resource.size, This->resource.heap_memory, gl_usage));
     error = gl_info->gl_ops.gl.p_glGetError();
     if (error != GL_NO_ERROR)
     {
@@ -185,19 +186,12 @@ static void buffer_create_buffer_object(struct wined3d_buffer *This, const struc
         goto fail;
     }
 
-    This->buffer_object_size = This->resource.size;
     This->buffer_object_usage = gl_usage;
 
     if (This->flags & WINED3D_BUFFER_DOUBLEBUFFER)
-    {
         buffer_invalidate_bo_range(This, 0, 0);
-    }
     else
-    {
-        wined3d_resource_free_sysmem(This->resource.heap_memory);
-        This->resource.allocatedMemory = NULL;
-        This->resource.heap_memory = NULL;
-    }
+        wined3d_resource_free_sysmem(&This->resource);
 
     return;
 
@@ -265,9 +259,11 @@ static BOOL buffer_process_converted_attribute(struct wined3d_buffer *This,
     return ret;
 }
 
+#define WINED3D_BUFFER_FIXUP_D3DCOLOR   0x01
+#define WINED3D_BUFFER_FIXUP_XYZRHW     0x02
+
 static BOOL buffer_check_attribute(struct wined3d_buffer *This, const struct wined3d_stream_info *si,
-        UINT attrib_idx, const BOOL check_d3dcolor, const BOOL check_position, const BOOL is_ffp_color,
-        DWORD *stride_this_run)
+        UINT attrib_idx, DWORD fixup_flags, DWORD *stride_this_run)
 {
     const struct wined3d_stream_info_element *attrib = &si->elements[attrib_idx];
     enum wined3d_format_id format;
@@ -282,13 +278,11 @@ static BOOL buffer_check_attribute(struct wined3d_buffer *This, const struct win
 
     format = attrib->format->id;
     /* Look for newly appeared conversion */
-    if (check_d3dcolor && format == WINED3DFMT_B8G8R8A8_UNORM)
+    if (fixup_flags & WINED3D_BUFFER_FIXUP_D3DCOLOR && format == WINED3DFMT_B8G8R8A8_UNORM)
     {
         ret = buffer_process_converted_attribute(This, CONV_D3DCOLOR, attrib, stride_this_run);
-
-        if (!is_ffp_color) FIXME("Test for non-color fixed function WINED3DFMT_B8G8R8A8_UNORM format\n");
     }
-    else if (check_position && si->position_transformed)
+    else if (fixup_flags & WINED3D_BUFFER_FIXUP_XYZRHW && si->position_transformed)
     {
         if (format != WINED3DFMT_R32G32B32A32_FLOAT)
         {
@@ -306,14 +300,9 @@ static BOOL buffer_check_attribute(struct wined3d_buffer *This, const struct win
     return ret;
 }
 
-static BOOL buffer_find_decl(struct wined3d_buffer *This)
+static BOOL buffer_find_decl(struct wined3d_buffer *This, const struct wined3d_stream_info *si,
+        DWORD fixup_flags)
 {
-    struct wined3d_device *device = This->resource.device;
-    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;
 
@@ -326,9 +315,9 @@ static BOOL buffer_find_decl(struct wined3d_buffer *This)
         if(This->resource.usage & WINED3DUSAGE_STATICDECL) return FALSE;
     }
 
-    if (use_vs(state))
+    if (!fixup_flags)
     {
-        TRACE("Vertex shaders used, no VBO conversion is needed\n");
+        TRACE("No fixup required.\n");
         if(This->conversion_map)
         {
             HeapFree(GetProcessHeap(), 0, This->conversion_map);
@@ -387,29 +376,31 @@ static BOOL buffer_find_decl(struct wined3d_buffer *This)
      */
 
     ret = buffer_check_attribute(This, si, WINED3D_FFP_POSITION,
-            TRUE, !support_xyzrhw,  FALSE, &stride_this_run) || ret;
+            fixup_flags, &stride_this_run) || ret;
+    fixup_flags &= ~WINED3D_BUFFER_FIXUP_XYZRHW;
+
     ret = buffer_check_attribute(This, si, WINED3D_FFP_NORMAL,
-            TRUE, FALSE, FALSE, &stride_this_run) || ret;
+            fixup_flags, &stride_this_run) || ret;
     ret = buffer_check_attribute(This, si, WINED3D_FFP_DIFFUSE,
-            !support_d3dcolor, FALSE, TRUE,  &stride_this_run) || ret;
+            fixup_flags, &stride_this_run) || ret;
     ret = buffer_check_attribute(This, si, WINED3D_FFP_SPECULAR,
-            !support_d3dcolor, FALSE, TRUE,  &stride_this_run) || ret;
+            fixup_flags, &stride_this_run) || ret;
     ret = buffer_check_attribute(This, si, WINED3D_FFP_TEXCOORD0,
-            TRUE, FALSE, FALSE, &stride_this_run) || ret;
+            fixup_flags, &stride_this_run) || ret;
     ret = buffer_check_attribute(This, si, WINED3D_FFP_TEXCOORD1,
-            TRUE, FALSE, FALSE, &stride_this_run) || ret;
+            fixup_flags, &stride_this_run) || ret;
     ret = buffer_check_attribute(This, si, WINED3D_FFP_TEXCOORD2,
-            TRUE, FALSE, FALSE, &stride_this_run) || ret;
+            fixup_flags, &stride_this_run) || ret;
     ret = buffer_check_attribute(This, si, WINED3D_FFP_TEXCOORD3,
-            TRUE, FALSE, FALSE, &stride_this_run) || ret;
+            fixup_flags, &stride_this_run) || ret;
     ret = buffer_check_attribute(This, si, WINED3D_FFP_TEXCOORD4,
-            TRUE, FALSE, FALSE, &stride_this_run) || ret;
+            fixup_flags, &stride_this_run) || ret;
     ret = buffer_check_attribute(This, si, WINED3D_FFP_TEXCOORD5,
-            TRUE, FALSE, FALSE, &stride_this_run) || ret;
+            fixup_flags, &stride_this_run) || ret;
     ret = buffer_check_attribute(This, si, WINED3D_FFP_TEXCOORD6,
-            TRUE, FALSE, FALSE, &stride_this_run) || ret;
+            fixup_flags, &stride_this_run) || ret;
     ret = buffer_check_attribute(This, si, WINED3D_FFP_TEXCOORD7,
-            TRUE, FALSE, FALSE, &stride_this_run) || ret;
+            fixup_flags, &stride_this_run) || ret;
 
     if (!stride_this_run && This->conversion_map)
     {
@@ -457,7 +448,7 @@ static inline void fixup_transformed_pos(float *p)
 }
 
 /* Context activation is done by the caller. */
-void buffer_get_memory(struct wined3d_buffer *buffer, const struct wined3d_gl_info *gl_info,
+void buffer_get_memory(struct wined3d_buffer *buffer, struct wined3d_context *context,
         struct wined3d_bo_address *data)
 {
     data->buffer_object = buffer->buffer_object;
@@ -465,7 +456,7 @@ void buffer_get_memory(struct wined3d_buffer *buffer, const struct wined3d_gl_in
     {
         if ((buffer->flags & WINED3D_BUFFER_CREATEBO) && !buffer->resource.map_count)
         {
-            buffer_create_buffer_object(buffer, gl_info);
+            buffer_create_buffer_object(buffer, context);
             buffer->flags &= ~WINED3D_BUFFER_CREATEBO;
             if (buffer->buffer_object)
             {
@@ -474,7 +465,7 @@ void buffer_get_memory(struct wined3d_buffer *buffer, const struct wined3d_gl_in
                 return;
             }
         }
-        data->addr = buffer->resource.allocatedMemory;
+        data->addr = buffer->resource.heap_memory;
     }
     else
     {
@@ -492,25 +483,27 @@ ULONG CDECL wined3d_buffer_incref(struct wined3d_buffer *buffer)
 }
 
 /* Context activation is done by the caller. */
-BYTE *buffer_get_sysmem(struct wined3d_buffer *This, const struct wined3d_gl_info *gl_info)
+BYTE *buffer_get_sysmem(struct wined3d_buffer *This, struct wined3d_context *context)
 {
-    /* AllocatedMemory exists if the buffer is double buffered or has no buffer object at all */
-    if(This->resource.allocatedMemory) return This->resource.allocatedMemory;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+
+    /* Heap_memory exists if the buffer is double buffered or has no buffer object at all. */
+    if (This->resource.heap_memory)
+        return This->resource.heap_memory;
 
-    This->resource.heap_memory = wined3d_resource_allocate_sysmem(This->resource.size);
-    This->resource.allocatedMemory = This->resource.heap_memory;
+    if (!wined3d_resource_allocate_sysmem(&This->resource))
+        ERR("Failed to allocate system memory.\n");
 
     if (This->buffer_type_hint == GL_ELEMENT_ARRAY_BUFFER_ARB)
-        device_invalidate_state(This->resource.device, STATE_INDEXBUFFER);
+        context_invalidate_state(context, STATE_INDEXBUFFER);
 
     GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object));
-    GL_EXTCALL(glGetBufferSubDataARB(This->buffer_type_hint, 0, This->resource.size, This->resource.allocatedMemory));
+    GL_EXTCALL(glGetBufferSubDataARB(This->buffer_type_hint, 0, This->resource.size, This->resource.heap_memory));
     This->flags |= WINED3D_BUFFER_DOUBLEBUFFER;
 
-    return This->resource.allocatedMemory;
+    return This->resource.heap_memory;
 }
 
-/* Do not call while under the GL lock. */
 static void buffer_unload(struct wined3d_resource *resource)
 {
     struct wined3d_buffer *buffer = buffer_from_resource(resource);
@@ -527,7 +520,7 @@ static void buffer_unload(struct wined3d_resource *resource)
         /* Download the buffer, but don't permanently enable double buffering */
         if (!(buffer->flags & WINED3D_BUFFER_DOUBLEBUFFER))
         {
-            buffer_get_sysmem(buffer, context->gl_info);
+            buffer_get_sysmem(buffer, context);
             buffer->flags &= ~WINED3D_BUFFER_DOUBLEBUFFER;
         }
 
@@ -547,7 +540,6 @@ static void buffer_unload(struct wined3d_resource *resource)
     resource_unload(resource);
 }
 
-/* Do not call while under the GL lock. */
 ULONG CDECL wined3d_buffer_decref(struct wined3d_buffer *buffer)
 {
     ULONG refcount = InterlockedDecrement(&buffer->resource.ref);
@@ -709,7 +701,7 @@ static void buffer_direct_upload(struct wined3d_buffer *This, const struct wined
         start = This->maps[This->modified_areas].offset;
         len = This->maps[This->modified_areas].size;
 
-        memcpy(map + start, This->resource.allocatedMemory + start, len);
+        memcpy(map + start, (BYTE *)This->resource.heap_memory + start, len);
 
         if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
         {
@@ -726,14 +718,14 @@ static void buffer_direct_upload(struct wined3d_buffer *This, const struct wined
     checkGLcall("glUnmapBufferARB");
 }
 
-/* Do not call while under the GL lock. */
-void CDECL wined3d_buffer_preload(struct wined3d_buffer *buffer)
+/* Context activation is done by the caller. */
+void buffer_internal_preload(struct wined3d_buffer *buffer, struct wined3d_context *context,
+        const struct wined3d_state *state)
 {
     DWORD flags = buffer->flags & (WINED3D_BUFFER_NOSYNC | WINED3D_BUFFER_DISCARD);
     struct wined3d_device *device = buffer->resource.device;
     UINT start = 0, end = 0, len = 0, vertices;
     const struct wined3d_gl_info *gl_info;
-    struct wined3d_context *context;
     BOOL decl_changed = FALSE;
     unsigned int i, j;
     BYTE *data;
@@ -753,9 +745,7 @@ void CDECL wined3d_buffer_preload(struct wined3d_buffer *buffer)
         /* TODO: Make converting independent from VBOs */
         if (buffer->flags & WINED3D_BUFFER_CREATEBO)
         {
-            context = context_acquire(device, NULL);
-            buffer_create_buffer_object(buffer, context->gl_info);
-            context_release(context);
+            buffer_create_buffer_object(buffer, context);
            &nb