[D3D8][D3D9][DDRAW][WINED3D]
authorAmine Khaldi <amine.khaldi@reactos.org>
Tue, 23 Sep 2014 17:50:22 +0000 (17:50 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Tue, 23 Sep 2014 17:50:22 +0000 (17:50 +0000)
* Sync with Wine 1.7.27.
CORE-8540

svn path=/trunk/; revision=64240

57 files changed:
reactos/dll/directx/wine/d3d8/buffer.c
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/surface.c
reactos/dll/directx/wine/d3d8/swapchain.c
reactos/dll/directx/wine/d3d8/texture.c
reactos/dll/directx/wine/d3d8/volume.c
reactos/dll/directx/wine/d3d9/buffer.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/query.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/ddraw.c
reactos/dll/directx/wine/ddraw/ddraw_private.h
reactos/dll/directx/wine/ddraw/device.c
reactos/dll/directx/wine/ddraw/executebuffer.c
reactos/dll/directx/wine/ddraw/palette.c
reactos/dll/directx/wine/ddraw/surface.c
reactos/dll/directx/wine/ddraw/utils.c
reactos/dll/directx/wine/ddraw/vertexbuffer.c
reactos/dll/directx/wine/ddraw/viewport.c
reactos/dll/directx/wine/wined3d/arb_program_shader.c
reactos/dll/directx/wine/wined3d/buffer.c
reactos/dll/directx/wine/wined3d/context.c
reactos/dll/directx/wine/wined3d/cs.c
reactos/dll/directx/wine/wined3d/device.c
reactos/dll/directx/wine/wined3d/directx.c
reactos/dll/directx/wine/wined3d/drawprim.c
reactos/dll/directx/wine/wined3d/glsl_shader.c
reactos/dll/directx/wine/wined3d/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/shader_sm4.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/view.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/d3d8.h
reactos/include/psdk/d3d8types.h
reactos/include/psdk/d3d9.h
reactos/include/psdk/d3d9types.h
reactos/include/reactos/wine/wined3d.h
reactos/media/doc/README.WINE

index e230519..a5786cc 100644 (file)
@@ -128,12 +128,14 @@ static HRESULT WINAPI d3d8_vertexbuffer_FreePrivateData(IDirect3DVertexBuffer8 *
 static DWORD WINAPI d3d8_vertexbuffer_SetPriority(IDirect3DVertexBuffer8 *iface, DWORD priority)
 {
     struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
+    struct wined3d_resource *resource;
     DWORD previous;
 
     TRACE("iface %p, priority %u.\n", iface, priority);
 
     wined3d_mutex_lock();
-    previous = wined3d_buffer_set_priority(buffer->wined3d_buffer, priority);
+    resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
+    previous = wined3d_resource_set_priority(resource, priority);
     wined3d_mutex_unlock();
 
     return previous;
@@ -142,12 +144,14 @@ static DWORD WINAPI d3d8_vertexbuffer_SetPriority(IDirect3DVertexBuffer8 *iface,
 static DWORD WINAPI d3d8_vertexbuffer_GetPriority(IDirect3DVertexBuffer8 *iface)
 {
     struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
+    const struct wined3d_resource *resource;
     DWORD priority;
 
     TRACE("iface %p.\n", iface);
 
     wined3d_mutex_lock();
-    priority = wined3d_buffer_get_priority(buffer->wined3d_buffer);
+    resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
+    priority = wined3d_resource_get_priority(resource);
     wined3d_mutex_unlock();
 
     return priority;
@@ -401,12 +405,14 @@ static HRESULT WINAPI d3d8_indexbuffer_FreePrivateData(IDirect3DIndexBuffer8 *if
 static DWORD WINAPI d3d8_indexbuffer_SetPriority(IDirect3DIndexBuffer8 *iface, DWORD priority)
 {
     struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
+    struct wined3d_resource *resource;
     DWORD previous;
 
     TRACE("iface %p, priority %u.\n", iface, priority);
 
     wined3d_mutex_lock();
-    previous = wined3d_buffer_set_priority(buffer->wined3d_buffer, priority);
+    resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
+    previous = wined3d_resource_set_priority(resource, priority);
     wined3d_mutex_unlock();
 
     return previous;
@@ -415,12 +421,14 @@ static DWORD WINAPI d3d8_indexbuffer_SetPriority(IDirect3DIndexBuffer8 *iface, D
 static DWORD WINAPI d3d8_indexbuffer_GetPriority(IDirect3DIndexBuffer8 *iface)
 {
     struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
+    const struct wined3d_resource *resource;
     DWORD priority;
 
     TRACE("iface %p.\n", iface);
 
     wined3d_mutex_lock();
-    priority = wined3d_buffer_get_priority(buffer->wined3d_buffer);
+    resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
+    priority = wined3d_resource_get_priority(resource);
     wined3d_mutex_unlock();
 
     return priority;
index a4dc5e6..144817a 100644 (file)
@@ -51,15 +51,6 @@ IDirect3D8 * WINAPI DECLSPEC_HOTPATCH Direct3DCreate8(UINT sdk_version)
     return &object->IDirect3D8_iface;
 }
 
-/* At process attach */
-BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, void *reserved)
-{
-    if (reason == DLL_PROCESS_ATTACH)
-        DisableThreadLibraryCalls(inst);
-
-    return TRUE;
-}
-
 /***********************************************************************
  *              ValidateVertexShader (D3D8.@)
  *
index a60652d..6d79917 100644 (file)
@@ -153,6 +153,13 @@ struct FvfToDecl
     struct d3d8_vertex_declaration *declaration;
 };
 
+enum d3d8_device_state
+{
+    D3D8_DEVICE_STATE_OK,
+    D3D8_DEVICE_STATE_LOST,
+    D3D8_DEVICE_STATE_NOT_RESET,
+};
+
 struct d3d8_device
 {
     /* IUnknown fields */
@@ -175,14 +182,19 @@ struct d3d8_device
     UINT                   index_buffer_size;
     UINT                   index_buffer_pos;
 
+    LONG device_state;
     /* Avoids recursion with nested ReleaseRef to 0 */
     BOOL                    inDestruction;
-    BOOL lost;
 };
 
 HRESULT device_init(struct d3d8_device *device, struct d3d8 *parent, struct wined3d *wined3d, UINT adapter,
         D3DDEVTYPE device_type, HWND focus_window, DWORD flags, D3DPRESENT_PARAMETERS *parameters) DECLSPEC_HIDDEN;
 
+static inline struct d3d8_device *impl_from_IDirect3DDevice8(IDirect3DDevice8 *iface)
+{
+    return CONTAINING_RECORD(iface, struct d3d8_device, IDirect3DDevice8_iface);
+}
+
 struct d3d8_resource
 {
     LONG refcount;
@@ -202,12 +214,11 @@ struct d3d8_volume
     IDirect3DVolume8 IDirect3DVolume8_iface;
     struct d3d8_resource resource;
     struct wined3d_volume *wined3d_volume;
-    IUnknown *container;
-    IUnknown *forwardReference;
+    struct d3d8_texture *texture;
 };
 
-void volume_init(struct d3d8_volume *volume, struct wined3d_volume *wined3d_volume,
-        const struct wined3d_parent_ops **parent_ops) DECLSPEC_HIDDEN;
+void volume_init(struct d3d8_volume *volume, struct d3d8_texture *texture,
+        struct wined3d_volume *wined3d_volume, const struct wined3d_parent_ops **parent_ops) DECLSPEC_HIDDEN;
 
 struct d3d8_swapchain
 {
@@ -225,17 +236,16 @@ struct d3d8_surface
     IDirect3DSurface8 IDirect3DSurface8_iface;
     struct d3d8_resource resource;
     struct wined3d_surface *wined3d_surface;
+    struct list rtv_entry;
+    struct wined3d_rendertarget_view *wined3d_rtv;
     IDirect3DDevice8 *parent_device;
-
-    /* The surface container */
-    IUnknown                    *container;
-
-    /* If set forward refcounting to this object */
-    IUnknown                    *forwardReference;
+    IUnknown *container;
+    struct d3d8_texture *texture;
 };
 
-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 wined3d_rendertarget_view *d3d8_surface_get_rendertarget_view(struct d3d8_surface *surface) DECLSPEC_HIDDEN;
+void surface_init(struct d3d8_surface *surface, IUnknown *container_parent,
+        struct wined3d_surface *wined3d_surface, const struct wined3d_parent_ops **parent_ops) DECLSPEC_HIDDEN;
 struct d3d8_surface *unsafe_impl_from_IDirect3DSurface8(IDirect3DSurface8 *iface) DECLSPEC_HIDDEN;
 
 struct d3d8_vertexbuffer
@@ -270,6 +280,7 @@ struct d3d8_texture
     struct d3d8_resource resource;
     struct wined3d_texture *wined3d_texture;
     IDirect3DDevice8 *parent_device;
+    struct list rtv_list;
 };
 
 HRESULT cubetexture_init(struct d3d8_texture *texture, struct d3d8_device *device,
index c519f80..7516764 100644 (file)
@@ -286,11 +286,6 @@ static void *d3d8_get_object(struct d3d8_handle_table *t, DWORD handle, enum d3d
     return entry->object;
 }
 
-static inline struct d3d8_device *impl_from_IDirect3DDevice8(IDirect3DDevice8 *iface)
-{
-    return CONTAINING_RECORD(iface, struct d3d8_device, IDirect3DDevice8_iface);
-}
-
 static HRESULT WINAPI d3d8_device_QueryInterface(IDirect3DDevice8 *iface, REFIID riid, void **out)
 {
     TRACE("iface %p, riid %s, out %p.\n",
@@ -373,27 +368,32 @@ static HRESULT WINAPI d3d8_device_TestCooperativeLevel(IDirect3DDevice8 *iface)
 
     TRACE("iface %p.\n", iface);
 
-    if (device->lost)
+    TRACE("device state: %#x.\n", device->device_state);
+
+    switch (device->device_state)
     {
-        TRACE("Device is lost.\n");
-        return D3DERR_DEVICENOTRESET;
+        default:
+        case D3D8_DEVICE_STATE_OK:
+            return D3D_OK;
+        case D3D8_DEVICE_STATE_LOST:
+            return D3DERR_DEVICELOST;
+        case D3D8_DEVICE_STATE_NOT_RESET:
+            return D3DERR_DEVICENOTRESET;
     }
-
-    return D3D_OK;
 }
 
 static UINT WINAPI d3d8_device_GetAvailableTextureMem(IDirect3DDevice8 *iface)
 {
     struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
-    HRESULT hr;
+    UINT ret;
 
     TRACE("iface %p.\n", iface);
 
     wined3d_mutex_lock();
-    hr = wined3d_device_get_available_texture_mem(device->wined3d_device);
+    ret = wined3d_device_get_available_texture_mem(device->wined3d_device);
     wined3d_mutex_unlock();
 
-    return hr;
+    return ret;
 }
 
 static HRESULT WINAPI d3d8_device_ResourceManagerDiscardBytes(IDirect3DDevice8 *iface, DWORD byte_count)
@@ -626,11 +626,11 @@ static HRESULT WINAPI d3d8_device_Reset(IDirect3DDevice8 *iface,
             NULL, reset_enum_callback, TRUE)))
     {
         wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_POINTSIZE_MIN, 0);
-        device->lost = FALSE;
+        device->device_state = D3D8_DEVICE_STATE_OK;
     }
     else
     {
-        device->lost = TRUE;
+        device->device_state = D3D8_DEVICE_STATE_NOT_RESET;
     }
     wined3d_mutex_unlock();
 
@@ -646,6 +646,9 @@ static HRESULT WINAPI d3d8_device_Present(IDirect3DDevice8 *iface, const RECT *s
     TRACE("iface %p, src_rect %s, dst_rect %s, dst_window_override %p, dirty_region %p.\n",
             iface, wine_dbgstr_rect(src_rect), wine_dbgstr_rect(dst_rect), dst_window_override, dirty_region);
 
+    if (device->device_state != D3D8_DEVICE_STATE_OK)
+        return D3DERR_DEVICELOST;
+
     wined3d_mutex_lock();
     hr = wined3d_device_present(device->wined3d_device, src_rect, dst_rect,
             dst_window_override, dirty_region, 0);
@@ -900,7 +903,6 @@ static HRESULT d3d8_device_create_surface(struct d3d8_device *device, UINT width
 
     sub_resource = wined3d_texture_get_sub_resource(texture, 0);
     surface_impl = wined3d_resource_get_parent(sub_resource);
-    surface_impl->forwardReference = NULL;
     surface_impl->parent_device = &device->IDirect3DDevice8_iface;
     *surface = &surface_impl->IDirect3DSurface8_iface;
     IDirect3DSurface8_AddRef(*surface);
@@ -1110,7 +1112,7 @@ static HRESULT WINAPI d3d8_device_SetRenderTarget(IDirect3DDevice8 *iface,
     struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
     struct d3d8_surface *rt_impl = unsafe_impl_from_IDirect3DSurface8(render_target);
     struct d3d8_surface *ds_impl = unsafe_impl_from_IDirect3DSurface8(depth_stencil);
-    struct wined3d_surface *original_ds = NULL;
+    struct wined3d_rendertarget_view *original_dsv;
     HRESULT hr = D3D_OK;
 
     TRACE("iface %p, render_target %p, depth_stencil %p.\n", iface, render_target, depth_stencil);
@@ -1119,19 +1121,22 @@ static HRESULT WINAPI d3d8_device_SetRenderTarget(IDirect3DDevice8 *iface,
 
     if (ds_impl)
     {
+        struct wined3d_rendertarget_view *original_rtv;
         struct wined3d_resource_desc ds_desc, rt_desc;
         struct wined3d_resource *wined3d_resource;
-        struct wined3d_surface *original_rt = NULL;
+        struct d3d8_surface *original_surface;
 
         /* If no render target is passed in check the size against the current RT */
         if (!render_target)
         {
-            if (!(original_rt = wined3d_device_get_render_target(device->wined3d_device, 0)))
+
+            if (!(original_rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0)))
             {
                 wined3d_mutex_unlock();
                 return D3DERR_NOTFOUND;
             }
-            wined3d_resource = wined3d_surface_get_resource(original_rt);
+            original_surface = wined3d_rendertarget_view_get_sub_resource_parent(original_rtv);
+            wined3d_resource = wined3d_surface_get_resource(original_surface->wined3d_surface);
         }
         else
             wined3d_resource = wined3d_surface_get_resource(rt_impl->wined3d_surface);
@@ -1148,14 +1153,12 @@ static HRESULT WINAPI d3d8_device_SetRenderTarget(IDirect3DDevice8 *iface,
         }
     }
 
-    original_ds = wined3d_device_get_depth_stencil(device->wined3d_device);
-    wined3d_device_set_depth_stencil(device->wined3d_device, ds_impl ? ds_impl->wined3d_surface : NULL);
-    if (render_target)
-    {
-        hr = wined3d_device_set_render_target(device->wined3d_device, 0, rt_impl->wined3d_surface, TRUE);
-        if (FAILED(hr))
-            wined3d_device_set_depth_stencil(device->wined3d_device, original_ds);
-    }
+    original_dsv = wined3d_device_get_depth_stencil_view(device->wined3d_device);
+    wined3d_device_set_depth_stencil_view(device->wined3d_device,
+            ds_impl ? d3d8_surface_get_rendertarget_view(ds_impl) : NULL);
+    if (render_target && FAILED(hr = wined3d_device_set_rendertarget_view(device->wined3d_device, 0,
+            d3d8_surface_get_rendertarget_view(rt_impl), TRUE)))
+        wined3d_device_set_depth_stencil_view(device->wined3d_device, original_dsv);
 
     wined3d_mutex_unlock();
 
@@ -1165,7 +1168,7 @@ static HRESULT WINAPI d3d8_device_SetRenderTarget(IDirect3DDevice8 *iface,
 static HRESULT WINAPI d3d8_device_GetRenderTarget(IDirect3DDevice8 *iface, IDirect3DSurface8 **render_target)
 {
     struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
-    struct wined3d_surface *wined3d_surface;
+    struct wined3d_rendertarget_view *wined3d_rtv;
     struct d3d8_surface *surface_impl;
     HRESULT hr;
 
@@ -1175,9 +1178,11 @@ static HRESULT WINAPI d3d8_device_GetRenderTarget(IDirect3DDevice8 *iface, IDire
         return D3DERR_INVALIDCALL;
 
     wined3d_mutex_lock();
-    if ((wined3d_surface = wined3d_device_get_render_target(device->wined3d_device, 0)))
+    if ((wined3d_rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0)))
     {
-        surface_impl = wined3d_surface_get_parent(wined3d_surface);
+        /* We want the sub resource parent here, since the view itself may be
+         * internal to wined3d and may not have a parent. */
+        surface_impl = wined3d_rendertarget_view_get_sub_resource_parent(wined3d_rtv);
         *render_target = &surface_impl->IDirect3DSurface8_iface;
         IDirect3DSurface8_AddRef(*render_target);
         hr = D3D_OK;
@@ -1196,7 +1201,7 @@ static HRESULT WINAPI d3d8_device_GetRenderTarget(IDirect3DDevice8 *iface, IDire
 static HRESULT WINAPI d3d8_device_GetDepthStencilSurface(IDirect3DDevice8 *iface, IDirect3DSurface8 **depth_stencil)
 {
     struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
-    struct wined3d_surface *wined3d_surface;
+    struct wined3d_rendertarget_view *wined3d_dsv;
     struct d3d8_surface *surface_impl;
     HRESULT hr = D3D_OK;
 
@@ -1206,9 +1211,11 @@ static HRESULT WINAPI d3d8_device_GetDepthStencilSurface(IDirect3DDevice8 *iface
         return D3DERR_INVALIDCALL;
 
     wined3d_mutex_lock();
-    if ((wined3d_surface = wined3d_device_get_depth_stencil(device->wined3d_device)))
+    if ((wined3d_dsv = wined3d_device_get_depth_stencil_view(device->wined3d_device)))
     {
-        surface_impl = wined3d_surface_get_parent(wined3d_surface);
+        /* We want the sub resource parent here, since the view itself may be
+         * internal to wined3d and may not have a parent. */
+        surface_impl = wined3d_rendertarget_view_get_sub_resource_parent(wined3d_dsv);
         *depth_stencil = &surface_impl->IDirect3DSurface8_iface;
         IDirect3DSurface8_AddRef(*depth_stencil);
     }
@@ -2776,7 +2783,6 @@ static HRESULT WINAPI d3d8_device_GetStreamSource(IDirect3DDevice8 *iface,
         buffer_impl = wined3d_buffer_get_parent(wined3d_buffer);
         *buffer = &buffer_impl->IDirect3DVertexBuffer8_iface;
         IDirect3DVertexBuffer8_AddRef(*buffer);
-        wined3d_buffer_decref(wined3d_buffer);
     }
     else
     {
@@ -2906,33 +2912,34 @@ static void CDECL device_parent_mode_changed(struct wined3d_device_parent *devic
     TRACE("device_parent %p.\n", device_parent);
 }
 
+static void CDECL device_parent_activate(struct wined3d_device_parent *device_parent, BOOL activate)
+{
+    struct d3d8_device *device = device_from_device_parent(device_parent);
+
+    TRACE("device_parent %p, activate %#x.\n", device_parent, activate);
+
+    if (!activate)
+        InterlockedCompareExchange(&device->device_state, D3D8_DEVICE_STATE_LOST, D3D8_DEVICE_STATE_OK);
+    else
+        InterlockedCompareExchange(&device->device_state, D3D8_DEVICE_STATE_NOT_RESET, D3D8_DEVICE_STATE_LOST);
+}
+
 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;
 
     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))))
-    {
-        FIXME("Failed to allocate surface memory.\n");
-        return D3DERR_OUTOFVIDEOMEMORY;
-    }
+        return E_OUTOFMEMORY;
 
-    surface_init(d3d_surface, surface, device, parent_ops);
+    surface_init(d3d_surface, container_parent, surface, parent_ops);
     *parent = d3d_surface;
     TRACE("Created surface %p.\n", d3d_surface);
 
-    d3d_surface->container = container_parent;
-    IDirect3DDevice8_Release(d3d_surface->parent_device);
-    d3d_surface->parent_device = NULL;
-
-    IDirect3DSurface8_Release(&d3d_surface->IDirect3DSurface8_iface);
-    d3d_surface->forwardReference = container_parent;
-
     return D3D_OK;
 }
 
@@ -2948,15 +2955,10 @@ static HRESULT CDECL device_parent_volume_created(struct wined3d_device_parent *
     if (!(d3d_volume = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*d3d_volume))))
         return E_OUTOFMEMORY;
 
-    volume_init(d3d_volume, volume, parent_ops);
+    volume_init(d3d_volume, container_parent, 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;
 }
 
@@ -2986,7 +2988,6 @@ static HRESULT CDECL device_parent_create_swapchain_surface(struct wined3d_devic
     wined3d_texture_decref(texture);
 
     d3d_surface = wined3d_surface_get_parent(*surface);
-    d3d_surface->forwardReference = NULL;
     d3d_surface->parent_device = &device->IDirect3DDevice8_iface;
 
     return hr;
@@ -3019,6 +3020,7 @@ static const struct wined3d_device_parent_ops d3d8_wined3d_device_parent_ops =
 {
     device_parent_wined3d_device_created,
     device_parent_mode_changed,
+    device_parent_activate,
     device_parent_surface_created,
     device_parent_volume_created,
     device_parent_create_swapchain_surface,
index 116b5b9..3310036 100644 (file)
@@ -47,69 +47,64 @@ static HRESULT WINAPI d3d8_surface_QueryInterface(IDirect3DSurface8 *iface, REFI
 static ULONG WINAPI d3d8_surface_AddRef(IDirect3DSurface8 *iface)
 {
     struct d3d8_surface *surface = impl_from_IDirect3DSurface8(iface);
+    ULONG refcount;
 
     TRACE("iface %p.\n", iface);
 
-    if (surface->forwardReference)
+    if (surface->texture)
     {
-        /* Forward refcounting */
-        TRACE("Forwarding to %p.\n", surface->forwardReference);
-        return IUnknown_AddRef(surface->forwardReference);
+        TRACE("Forwarding to %p.\n", surface->texture);
+        return IDirect3DBaseTexture8_AddRef(&surface->texture->IDirect3DBaseTexture8_iface);
     }
-    else
-    {
-        /* No container, handle our own refcounting */
-        ULONG ref = InterlockedIncrement(&surface->resource.refcount);
-
-        TRACE("%p increasing refcount to %u.\n", iface, ref);
 
-        if (ref == 1)
-        {
-            if (surface->parent_device)
-                IDirect3DDevice8_AddRef(surface->parent_device);
-            wined3d_mutex_lock();
-            wined3d_surface_incref(surface->wined3d_surface);
-            wined3d_mutex_unlock();
-        }
+    refcount = InterlockedIncrement(&surface->resource.refcount);
+    TRACE("%p increasing refcount to %u.\n", iface, refcount);
 
-        return ref;
+    if (refcount == 1)
+    {
+        if (surface->parent_device)
+            IDirect3DDevice8_AddRef(surface->parent_device);
+        wined3d_mutex_lock();
+        if (surface->wined3d_rtv)
+            wined3d_rendertarget_view_incref(surface->wined3d_rtv);
+        wined3d_surface_incref(surface->wined3d_surface);
+        wined3d_mutex_unlock();
     }
+
+    return refcount;
 }
 
 static ULONG WINAPI d3d8_surface_Release(IDirect3DSurface8 *iface)
 {
     struct d3d8_surface *surface = impl_from_IDirect3DSurface8(iface);
+    ULONG refcount;
 
     TRACE("iface %p.\n", iface);
 
-    if (surface->forwardReference)
+    if (surface->texture)
     {
-        /* Forward refcounting */
-        TRACE("Forwarding to %p.\n", surface->forwardReference);
-        return IUnknown_Release(surface->forwardReference);
+        TRACE("Forwarding to %p.\n", surface->texture);
+        return IDirect3DBaseTexture8_Release(&surface->texture->IDirect3DBaseTexture8_iface);
     }
-    else
-    {
-        /* No container, handle our own refcounting */
-        ULONG ref = InterlockedDecrement(&surface->resource.refcount);
-
-        TRACE("%p decreasing refcount to %u.\n", iface, ref);
 
-        if (!ref)
-        {
-            IDirect3DDevice8 *parent_device = surface->parent_device;
+    refcount = InterlockedDecrement(&surface->resource.refcount);
+    TRACE("%p decreasing refcount to %u.\n", iface, refcount);
 
-            /* Implicit surfaces are destroyed with the device, not if refcount reaches 0. */
-            wined3d_mutex_lock();
-            wined3d_surface_decref(surface->wined3d_surface);
-            wined3d_mutex_unlock();
+    if (!refcount)
+    {
+        IDirect3DDevice8 *parent_device = surface->parent_device;
 
-            if (parent_device)
-                IDirect3DDevice8_Release(parent_device);
-        }
+        wined3d_mutex_lock();
+        if (surface->wined3d_rtv)
+            wined3d_rendertarget_view_decref(surface->wined3d_rtv);
+        wined3d_surface_decref(surface->wined3d_surface);
+        wined3d_mutex_unlock();
 
-        return ref;
+        if (parent_device)
+            IDirect3DDevice8_Release(parent_device);
     }
+
+    return refcount;
 }
 
 static HRESULT WINAPI d3d8_surface_GetDevice(IDirect3DSurface8 *iface, IDirect3DDevice8 **device)
@@ -118,22 +113,8 @@ static HRESULT WINAPI d3d8_surface_GetDevice(IDirect3DSurface8 *iface, IDirect3D
 
     TRACE("iface %p, device %p.\n", iface, device);
 
-    if (surface->forwardReference)
-    {
-        IDirect3DResource8 *resource;
-        HRESULT hr;
-
-        hr = IUnknown_QueryInterface(surface->forwardReference, &IID_IDirect3DResource8, (void **)&resource);
-        if (SUCCEEDED(hr))
-        {
-            hr = IDirect3DResource8_GetDevice(resource, device);
-            IDirect3DResource8_Release(resource);
-
-            TRACE("Returning device %p.\n", *device);
-        }
-
-        return hr;
-    }
+    if (surface->texture)
+        return IDirect3DBaseTexture8_GetDevice(&surface->texture->IDirect3DBaseTexture8_iface, device);
 
     *device = surface->parent_device;
     IDirect3DDevice8_AddRef(*device);
@@ -308,19 +289,70 @@ static const struct wined3d_parent_ops d3d8_surface_wined3d_parent_ops =
     surface_wined3d_object_destroyed,
 };
 
-void surface_init(struct d3d8_surface *surface, struct wined3d_surface *wined3d_surface,
-        struct d3d8_device *device, const struct wined3d_parent_ops **parent_ops)
+void surface_init(struct d3d8_surface *surface, IUnknown *container_parent,
+        struct wined3d_surface *wined3d_surface, const struct wined3d_parent_ops **parent_ops)
 {
+    IDirect3DBaseTexture8 *texture;
+
     surface->IDirect3DSurface8_iface.lpVtbl = &d3d8_surface_vtbl;
     d3d8_resource_init(&surface->resource);
-    wined3d_surface_incref(wined3d_surface);
+    surface->resource.refcount = 0;
     surface->wined3d_surface = wined3d_surface;
-    surface->parent_device = &device->IDirect3DDevice8_iface;
-    IDirect3DDevice8_AddRef(surface->parent_device);
+    list_init(&surface->rtv_entry);
+    surface->container = container_parent;
+
+    if (container_parent && SUCCEEDED(IUnknown_QueryInterface(container_parent,
+            &IID_IDirect3DBaseTexture8, (void **)&texture)))
+    {
+        surface->texture = unsafe_impl_from_IDirect3DBaseTexture8(texture);
+        IDirect3DBaseTexture8_Release(texture);
+    }
 
     *parent_ops = &d3d8_surface_wined3d_parent_ops;
 }
 
+static void STDMETHODCALLTYPE view_wined3d_object_destroyed(void *parent)
+{
+    struct d3d8_surface *surface = parent;
+
+    /* If the surface reference count drops to zero, we release our reference
+     * to the view, but don't clear the pointer yet, in case e.g. a
+     * GetRenderTarget() call brings the surface back before the view is
+     * actually destroyed. When the view is destroyed, we need to clear the
+     * pointer, or a subsequent surface AddRef() would reference it again.
+     *
+     * This is safe because as long as the view still has a reference to the
+     * texture, the surface is also still alive, and we're called before the
+     * view releases that reference. */
+    surface->wined3d_rtv = NULL;
+    list_remove(&surface->rtv_entry);
+}
+
+static const struct wined3d_parent_ops d3d8_view_wined3d_parent_ops =
+{
+    view_wined3d_object_destroyed,
+};
+
+struct wined3d_rendertarget_view *d3d8_surface_get_rendertarget_view(struct d3d8_surface *surface)
+{
+    HRESULT hr;
+
+    if (surface->wined3d_rtv)
+        return surface->wined3d_rtv;
+
+    if (FAILED(hr = wined3d_rendertarget_view_create_from_surface(surface->wined3d_surface,
+            surface, &d3d8_view_wined3d_parent_ops, &surface->wined3d_rtv)))
+    {
+        ERR("Failed to create rendertarget view, hr %#x.\n", hr);
+        return NULL;
+    }
+
+    if (surface->texture)
+        list_add_head(&surface->texture->rtv_list, &surface->rtv_entry);
+
+    return surface->wined3d_rtv;
+}
+
 struct d3d8_surface *unsafe_impl_from_IDirect3DSurface8(IDirect3DSurface8 *iface)
 {
     if (!iface)
index 80c7e7d..9e69efb 100644 (file)
@@ -88,11 +88,15 @@ static HRESULT WINAPI d3d8_swapchain_Present(IDirect3DSwapChain8 *iface,
         const RGNDATA *dirty_region)
 {
     struct d3d8_swapchain *swapchain = impl_from_IDirect3DSwapChain8(iface);
+    struct d3d8_device *device = impl_from_IDirect3DDevice8(swapchain->parent_device);
     HRESULT hr;
 
     TRACE("iface %p, src_rect %s, dst_rect %s, dst_window_override %p, dirty_region %p.\n",
             iface, wine_dbgstr_rect(src_rect), wine_dbgstr_rect(dst_rect), dst_window_override, dirty_region);
 
+    if (device->device_state != D3D8_DEVICE_STATE_OK)
+        return D3DERR_DEVICELOST;
+
     wined3d_mutex_lock();
     hr = wined3d_swapchain_present(swapchain->wined3d_swapchain, src_rect,
             dst_rect, dst_window_override, dirty_region, 0);
index 7aadf5b..76c18cf 100644 (file)
@@ -62,8 +62,14 @@ static ULONG WINAPI d3d8_texture_2d_AddRef(IDirect3DTexture8 *iface)
 
     if (ref == 1)
     {
+        struct d3d8_surface *surface;
+
         IDirect3DDevice8_AddRef(texture->parent_device);
         wined3d_mutex_lock();
+        LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d8_surface, rtv_entry)
+        {
+            wined3d_rendertarget_view_incref(surface->wined3d_rtv);
+        }
         wined3d_texture_incref(texture->wined3d_texture);
         wined3d_mutex_unlock();
     }
@@ -81,8 +87,13 @@ static ULONG WINAPI d3d8_texture_2d_Release(IDirect3DTexture8 *iface)
     if (!ref)
     {
         IDirect3DDevice8 *parent_device = texture->parent_device;
+        struct d3d8_surface *surface;
 
         wined3d_mutex_lock();
+        LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d8_surface, rtv_entry)
+        {
+            wined3d_rendertarget_view_decref(surface->wined3d_rtv);
+        }
         wined3d_texture_decref(texture->wined3d_texture);
         wined3d_mutex_unlock();
 
@@ -137,12 +148,14 @@ static HRESULT WINAPI d3d8_texture_2d_FreePrivateData(IDirect3DTexture8 *iface,
 static DWORD WINAPI d3d8_texture_2d_SetPriority(IDirect3DTexture8 *iface, DWORD priority)
 {
     struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
+    struct wined3d_resource *resource;
     DWORD ret;
 
     TRACE("iface %p, priority %u.\n", iface, priority);
 
     wined3d_mutex_lock();
-    ret = wined3d_texture_set_priority(texture->wined3d_texture, priority);
+    resource = wined3d_texture_get_resource(texture->wined3d_texture);
+    ret = wined3d_resource_set_priority(resource, priority);
     wined3d_mutex_unlock();
 
     return ret;
@@ -151,12 +164,14 @@ static DWORD WINAPI d3d8_texture_2d_SetPriority(IDirect3DTexture8 *iface, DWORD
 static DWORD WINAPI d3d8_texture_2d_GetPriority(IDirect3DTexture8 *iface)
 {
     struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
+    const struct wined3d_resource *resource;
     DWORD ret;
 
     TRACE("iface %p.\n", iface);
 
     wined3d_mutex_lock();
-    ret = wined3d_texture_get_priority(texture->wined3d_texture);
+    resource = wined3d_texture_get_resource(texture->wined3d_texture);
+    ret = wined3d_resource_get_priority(resource);
     wined3d_mutex_unlock();
 
     return ret;
@@ -406,8 +421,14 @@ static ULONG WINAPI d3d8_texture_cube_AddRef(IDirect3DCubeTexture8 *iface)
 
     if (ref == 1)
     {
+        struct d3d8_surface *surface;
+
         IDirect3DDevice8_AddRef(texture->parent_device);
         wined3d_mutex_lock();
+        LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d8_surface, rtv_entry)
+        {
+            wined3d_rendertarget_view_incref(surface->wined3d_rtv);
+        }
         wined3d_texture_incref(texture->wined3d_texture);
         wined3d_mutex_unlock();
     }
@@ -425,10 +446,15 @@ static ULONG WINAPI d3d8_texture_cube_Release(IDirect3DCubeTexture8 *iface)
     if (!ref)
     {
         IDirect3DDevice8 *parent_device = texture->parent_device;
+        struct d3d8_surface *surface;
 
         TRACE("Releasing child %p.\n", texture->wined3d_texture);
 
         wined3d_mutex_lock();
+        LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d8_surface, rtv_entry)
+        {
+            wined3d_rendertarget_view_decref(surface->wined3d_rtv);
+        }
         wined3d_texture_decref(texture->wined3d_texture);
         wined3d_mutex_unlock();
 
@@ -483,12 +509,14 @@ static HRESULT WINAPI d3d8_texture_cube_FreePrivateData(IDirect3DCubeTexture8 *i
 static DWORD WINAPI d3d8_texture_cube_SetPriority(IDirect3DCubeTexture8 *iface, DWORD priority)
 {
     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
+    struct wined3d_resource *resource;
     DWORD ret;
 
     TRACE("iface %p, priority %u.\n", iface, priority);
 
     wined3d_mutex_lock();
-    ret = wined3d_texture_set_priority(texture->wined3d_texture, priority);
+    resource = wined3d_texture_get_resource(texture->wined3d_texture);
+    ret = wined3d_resource_set_priority(resource, priority);
     wined3d_mutex_unlock();
 
     return ret;
@@ -497,12 +525,14 @@ static DWORD WINAPI d3d8_texture_cube_SetPriority(IDirect3DCubeTexture8 *iface,
 static DWORD WINAPI d3d8_texture_cube_GetPriority(IDirect3DCubeTexture8 *iface)
 {
     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
+    const struct wined3d_resource *resource;
     DWORD ret;
 
     TRACE("iface %p.\n", iface);
 
     wined3d_mutex_lock();
-    ret =  wined3d_texture_get_priority(texture->wined3d_texture);
+    resource = wined3d_texture_get_resource(texture->wined3d_texture);
+    ret =  wined3d_resource_get_priority(resource);
     wined3d_mutex_unlock();
 
     return ret;
@@ -850,12 +880,14 @@ static HRESULT WINAPI d3d8_texture_3d_FreePrivateData(IDirect3DVolumeTexture8 *i
 static DWORD WINAPI d3d8_texture_3d_SetPriority(IDirect3DVolumeTexture8 *iface, DWORD priority)
 {
     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
+    struct wined3d_resource *resource;
     DWORD ret;
 
     TRACE("iface %p, priority %u.\n", iface, priority);
 
     wined3d_mutex_lock();
-    ret = wined3d_texture_set_priority(texture->wined3d_texture, priority);
+    resource = wined3d_texture_get_resource(texture->wined3d_texture);
+    ret = wined3d_resource_set_priority(resource, priority);
     wined3d_mutex_unlock();
 
     return ret;
@@ -864,12 +896,14 @@ static DWORD WINAPI d3d8_texture_3d_SetPriority(IDirect3DVolumeTexture8 *iface,
 static DWORD WINAPI d3d8_texture_3d_GetPriority(IDirect3DVolumeTexture8 *iface)
 {
     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
+    const struct wined3d_resource *resource;
     DWORD ret;
 
     TRACE("iface %p.\n", iface);
 
     wined3d_mutex_lock();
-    ret = wined3d_texture_get_priority(texture->wined3d_texture);
+    resource = wined3d_texture_get_resource(texture->wined3d_texture);
+    ret = wined3d_resource_get_priority(resource);
     wined3d_mutex_unlock();
 
     return ret;
@@ -1118,6 +1152,7 @@ HRESULT texture_init(struct d3d8_texture *texture, struct d3d8_device *device,
 
     texture->IDirect3DBaseTexture8_iface.lpVtbl = (const IDirect3DBaseTexture8Vtbl *)&Direct3DTexture8_Vtbl;
     d3d8_resource_init(&texture->resource);
+    list_init(&texture->rtv_list);
 
     desc.resource_type = WINED3D_RTYPE_TEXTURE;
     desc.format = wined3dformat_from_d3dformat(format);
@@ -1159,6 +1194,7 @@ HRESULT cubetexture_init(struct d3d8_texture *texture, struct d3d8_device *devic
 
     texture->IDirect3DBaseTexture8_iface.lpVtbl = (const IDirect3DBaseTexture8Vtbl *)&Direct3DCubeTexture8_Vtbl;
     d3d8_resource_init(&texture->resource);
+    list_init(&texture->rtv_list);
 
     desc.resource_type = WINED3D_RTYPE_CUBE_TEXTURE;
     desc.format = wined3dformat_from_d3dformat(format);
@@ -1199,6 +1235,7 @@ HRESULT volumetexture_init(struct d3d8_texture *texture, struct d3d8_device *dev
 
     texture->IDirect3DBaseTexture8_iface.lpVtbl = (const IDirect3DBaseTexture8Vtbl *)&Direct3DVolumeTexture8_Vtbl;
     d3d8_resource_init(&texture->resource);
+    list_init(&texture->rtv_list);
 
     desc.resource_type = WINED3D_RTYPE_VOLUME_TEXTURE;
     desc.format = wined3dformat_from_d3dformat(format);
index 6396887..8c94f53 100644 (file)
@@ -48,29 +48,9 @@ static ULONG WINAPI d3d8_volume_AddRef(IDirect3DVolume8 *iface)
     struct d3d8_volume *volume = impl_from_IDirect3DVolume8(iface);
 
     TRACE("iface %p.\n", iface);
+    TRACE("Forwarding to %p.\n", volume->texture);
 
-    if (volume->forwardReference)
-    {
-        /* Forward to the containerParent */
-        TRACE("Forwarding to %p,\n", volume->forwardReference);
-        return IUnknown_AddRef(volume->forwardReference);
-    }
-    else
-    {
-        /* No container, handle our own refcounting */
-        ULONG ref = InterlockedIncrement(&volume->resource.refcount);
-
-        TRACE("%p increasing refcount to %u.\n", iface, ref);
-
-        if (ref == 1)
-        {
-            wined3d_mutex_lock();
-            wined3d_volume_incref(volume->wined3d_volume);
-            wined3d_mutex_unlock();
-        }
-
-        return ref;
-    }
+    return IDirect3DBaseTexture8_AddRef(&volume->texture->IDirect3DBaseTexture8_iface);
 }
 
 static ULONG WINAPI d3d8_volume_Release(IDirect3DVolume8 *iface)
@@ -78,49 +58,18 @@ static ULONG WINAPI d3d8_volume_Release(IDirect3DVolume8 *iface)
     struct d3d8_volume *volume = impl_from_IDirect3DVolume8(iface);
 
     TRACE("iface %p.\n", iface);
+    TRACE("Forwarding to %p.\n", volume->texture);
 
-    if (volume->forwardReference)
-    {
-        /* Forward to the containerParent */
-        TRACE("Forwarding to %p.\n", volume->forwardReference);
-        return IUnknown_Release(volume->forwardReference);
-    }
-    else
-    {
-        /* No container, handle our own refcounting */
-        ULONG ref = InterlockedDecrement(&volume->resource.refcount);
-
-        TRACE("%p decreasing refcount to %u.\n", iface, ref);
-
-        if (!ref)
-        {
-            wined3d_mutex_lock();
-            wined3d_volume_decref(volume->wined3d_volume);
-            wined3d_mutex_unlock();
-        }
-
-        return ref;
-    }
+    return IDirect3DBaseTexture8_Release(&volume->texture->IDirect3DBaseTexture8_iface);
 }
 
 static HRESULT WINAPI d3d8_volume_GetDevice(IDirect3DVolume8 *iface, IDirect3DDevice8 **device)
 {
     struct d3d8_volume *volume = impl_from_IDirect3DVolume8(iface);
-    IDirect3DResource8 *resource;
-    HRESULT hr;
 
     TRACE("iface %p, device %p.\n", iface, device);
 
-    hr = IUnknown_QueryInterface(volume->forwardReference, &IID_IDirect3DResource8, (void **)&resource);
-    if (SUCCEEDED(hr))
-    {
-        hr = IDirect3DResource8_GetDevice(resource, device);
-        IDirect3DResource8_Release(resource);
-
-        TRACE("Returning device %p.\n", *device);
-    }
-
-    return hr;
+    return IDirect3DBaseTexture8_GetDevice(&volume->texture->IDirect3DBaseTexture8_iface, device);
 }
 
 static HRESULT WINAPI d3d8_volume_SetPrivateData(IDirect3DVolume8 *iface, REFGUID guid,
@@ -154,19 +103,10 @@ static HRESULT WINAPI d3d8_volume_FreePrivateData(IDirect3DVolume8 *iface, REFGU
 static HRESULT WINAPI d3d8_volume_GetContainer(IDirect3DVolume8 *iface, REFIID riid, void **container)
 {
     struct d3d8_volume *volume = impl_from_IDirect3DVolume8(iface);
-    HRESULT res;
-
-    TRACE("iface %p, riid %s, container %p.\n",
-            iface, debugstr_guid(riid), container);
-
-    if (!volume->container)
-        return E_NOINTERFACE;
-
-    res = IUnknown_QueryInterface(volume->container, riid, container);
 
-    TRACE("Returning %p.\n", *container);
+    TRACE("iface %p, riid %s, container %p.\n", iface, debugstr_guid(riid), container);
 
-    return res;
+    return IDirect3DBaseTexture8_QueryInterface(&volume->texture->IDirect3DBaseTexture8_iface, riid, container);
 }
 
 static HRESULT WINAPI d3d8_volume_GetDesc(IDirect3DVolume8 *iface, D3DVOLUME_DESC *desc)
@@ -258,13 +198,14 @@ static const struct wined3d_parent_ops d3d8_volume_wined3d_parent_ops =
     volume_wined3d_object_destroyed,
 };
 
-void volume_init(struct d3d8_volume *volume, struct wined3d_volume *wined3d_volume,
-        const struct wined3d_parent_ops **parent_ops)
+void volume_init(struct d3d8_volume *volume, struct d3d8_texture *texture,
+        struct wined3d_volume *wined3d_volume, const struct wined3d_parent_ops **parent_ops)
 {
     volume->IDirect3DVolume8_iface.lpVtbl = &d3d8_volume_vtbl;
     d3d8_resource_init(&volume->resource);
-    wined3d_volume_incref(wined3d_volume);
+    volume->resource.refcount = 0;
     volume->wined3d_volume = wined3d_volume;
+    volume->texture = texture;
 
     *parent_ops = &d3d8_volume_wined3d_parent_ops;
 }
index bb91b2a..9101fd1 100644 (file)
@@ -129,12 +129,14 @@ static HRESULT WINAPI d3d9_vertexbuffer_FreePrivateData(IDirect3DVertexBuffer9 *
 static DWORD WINAPI d3d9_vertexbuffer_SetPriority(IDirect3DVertexBuffer9 *iface, DWORD priority)
 {
     struct d3d9_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer9(iface);
+    struct wined3d_resource *resource;
     DWORD previous;
 
     TRACE("iface %p, priority %u.\n", iface, priority);
 
     wined3d_mutex_lock();
-    previous = wined3d_buffer_set_priority(buffer->wined3d_buffer, priority);
+    resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
+    previous = wined3d_resource_set_priority(resource, priority);
     wined3d_mutex_unlock();
 
     return previous;
@@ -143,12 +145,14 @@ static DWORD WINAPI d3d9_vertexbuffer_SetPriority(IDirect3DVertexBuffer9 *iface,
 static DWORD WINAPI d3d9_vertexbuffer_GetPriority(IDirect3DVertexBuffer9 *iface)
 {
     struct d3d9_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer9(iface);
+    const struct wined3d_resource *resource;
     DWORD priority;
 
     TRACE("iface %p.\n", iface);
 
     wined3d_mutex_lock();
-    priority = wined3d_buffer_get_priority(buffer->wined3d_buffer);
+    resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
+    priority = wined3d_resource_get_priority(resource);
     wined3d_mutex_unlock();
 
     return priority;
@@ -401,12 +405,14 @@ static HRESULT WINAPI d3d9_indexbuffer_FreePrivateData(IDirect3DIndexBuffer9 *if
 static DWORD WINAPI d3d9_indexbuffer_SetPriority(IDirect3DIndexBuffer9 *iface, DWORD priority)
 {
     struct d3d9_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer9(iface);
+    struct wined3d_resource *resource;
     DWORD previous;
 
     TRACE("iface %p, priority %u.\n", iface, priority);
 
     wined3d_mutex_lock();
-    previous = wined3d_buffer_set_priority(buffer->wined3d_buffer, priority);
+    resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
+    previous = wined3d_resource_set_priority(resource, priority);
     wined3d_mutex_unlock();
 
     return previous;
@@ -415,12 +421,14 @@ static DWORD WINAPI d3d9_indexbuffer_SetPriority(IDirect3DIndexBuffer9 *iface, D
 static DWORD WINAPI d3d9_indexbuffer_GetPriority(IDirect3DIndexBuffer9 *iface)
 {
     struct d3d9_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer9(iface);
+    const struct wined3d_resource *resource;
     DWORD priority;
 
     TRACE("iface %p.\n", iface);
 
     wined3d_mutex_lock();
-    priority = wined3d_buffer_get_priority(buffer->wined3d_buffer);
+    resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
+    priority = wined3d_resource_get_priority(resource);
     wined3d_mutex_unlock();
 
     return priority;
index c051856..4bd80e1 100644 (file)
@@ -86,17 +86,6 @@ void* WINAPI Direct3DShaderValidatorCreate9(void)
     return NULL;
 }
 
-/*******************************************************************
- *       DllMain
- */
-BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, void *reserved)
-{
-    if (reason == DLL_PROCESS_ATTACH)
-        DisableThreadLibraryCalls(inst);
-
-    return TRUE;
-}
-
 /***********************************************************************
  *              D3DPERF_BeginEvent (D3D9.@)
  */
index fb8d166..300a5f0 100644 (file)
@@ -145,6 +145,13 @@ struct fvf_declaration
     DWORD fvf;
 };
 
+enum d3d9_device_state
+{
+    D3D9_DEVICE_STATE_OK,
+    D3D9_DEVICE_STATE_LOST,
+    D3D9_DEVICE_STATE_NOT_RESET,
+};
+
 struct d3d9_device
 {
     IDirect3DDevice9Ex IDirect3DDevice9Ex_iface;
@@ -163,8 +170,8 @@ struct d3d9_device
     UINT index_buffer_size;
     UINT index_buffer_pos;
 
+    LONG device_state;
     BOOL in_destruction;
-    BOOL not_reset;
     BOOL in_scene;
 };
 
@@ -191,12 +198,11 @@ struct d3d9_volume
     IDirect3DVolume9 IDirect3DVolume9_iface;
     struct d3d9_resource resource;
     struct wined3d_volume *wined3d_volume;
-    IUnknown *container;
-    IUnknown *forwardReference;
+    struct d3d9_texture *texture;
 };
 
-void volume_init(struct d3d9_volume *volume, struct wined3d_volume *wined3d_volume,
-        const struct wined3d_parent_ops **parent_ops) DECLSPEC_HIDDEN;
+void volume_init(struct d3d9_volume *volume, struct d3d9_texture *texture,
+        struct wined3d_volume *wined3d_volume, const struct wined3d_parent_ops **parent_ops) DECLSPEC_HIDDEN;
 
 struct d3d9_swapchain
 {
@@ -214,14 +220,17 @@ struct d3d9_surface
     IDirect3DSurface9 IDirect3DSurface9_iface;
     struct d3d9_resource resource;
     struct wined3d_surface *wined3d_surface;
+    struct list rtv_entry;
+    struct wined3d_rendertarget_view *wined3d_rtv;
     IDirect3DDevice9Ex *parent_device;
     IUnknown *container;
-    IUnknown *forwardReference;
+    struct d3d9_texture *texture;
     BOOL getdc_supported;
 };
 
-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 wined3d_rendertarget_view *d3d9_surface_get_rendertarget_view(struct d3d9_surface *surface) DECLSPEC_HIDDEN;
+void surface_init(struct d3d9_surface *surface, IUnknown *container_parent,
+        struct wined3d_surface *wined3d_surface, const struct wined3d_parent_ops **parent_ops) DECLSPEC_HIDDEN;
 struct d3d9_surface *unsafe_impl_from_IDirect3DSurface9(IDirect3DSurface9 *iface) DECLSPEC_HIDDEN;
 
 struct d3d9_vertexbuffer
@@ -256,6 +265,7 @@ struct d3d9_texture
     struct d3d9_resource resource;
     struct wined3d_texture *wined3d_texture;
     IDirect3DDevice9Ex *parent_device;
+    struct list rtv_list;
 };
 
 HRESULT cubetexture_init(struct d3d9_texture *texture, struct d3d9_device *device,
index 7306d08..ff430d5 100644 (file)
@@ -320,27 +320,35 @@ static HRESULT WINAPI d3d9_device_TestCooperativeLevel(IDirect3DDevice9Ex *iface
 
     TRACE("iface %p.\n", iface);
 
-    if (device->not_reset)
+    TRACE("device state: %#x.\n", device->device_state);
+
+    if (device->d3d_parent->extended)
+        return D3D_OK;
+
+    switch (device->device_state)
     {
-        TRACE("D3D9 device is marked not reset.\n");
-        return D3DERR_DEVICENOTRESET;
+        default:
+        case D3D9_DEVICE_STATE_OK:
+            return D3D_OK;
+        case D3D9_DEVICE_STATE_LOST:
+            return D3DERR_DEVICELOST;
+        case D3D9_DEVICE_STATE_NOT_RESET:
+            return D3DERR_DEVICENOTRESET;
     }
-
-    return D3D_OK;
 }
 
 static UINT WINAPI d3d9_device_GetAvailableTextureMem(IDirect3DDevice9Ex *iface)
 {
     struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
-    HRESULT hr;
+    UINT ret;
 
     TRACE("iface %p.\n", iface);
 
     wined3d_mutex_lock();
-    hr = wined3d_device_get_available_texture_mem(device->wined3d_device);
+    ret = wined3d_device_get_available_texture_mem(device->wined3d_device);
     wined3d_mutex_unlock();
 
-    return hr;
+    return ret;
 }
 
 static HRESULT WINAPI d3d9_device_EvictManagedResources(IDirect3DDevice9Ex *iface)
@@ -618,9 +626,9 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_Reset(IDirect3DDevice9Ex *if
     hr = wined3d_device_reset(device->wined3d_device, &swapchain_desc,
             NULL, reset_enum_callback, !device->d3d_parent->extended);
     if (FAILED(hr) && !device->d3d_parent->extended)
-        device->not_reset = TRUE;
+        device->device_state = D3D9_DEVICE_STATE_NOT_RESET;
     else
-        device->not_reset = FALSE;
+        device->device_state = D3D9_DEVICE_STATE_OK;
     wined3d_mutex_unlock();
 
     return hr;
@@ -635,6 +643,9 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_Present(IDirect3DDevice9Ex *
     TRACE("iface %p, src_rect %p, dst_rect %p, dst_window_override %p, dirty_region %p.\n",
             iface, src_rect, dst_rect, dst_window_override, dirty_region);
 
+    if (device->device_state != D3D9_DEVICE_STATE_OK)
+        return device->d3d_parent->extended ? S_PRESENT_OCCLUDED : D3DERR_DEVICELOST;
+
     wined3d_mutex_lock();
     hr = wined3d_device_present(device->wined3d_device, src_rect, dst_rect,
             dst_window_override, dirty_region, 0);
@@ -1012,7 +1023,6 @@ static HRESULT d3d9_device_create_surface(struct d3d9_device *device, UINT width
 
     sub_resource = wined3d_texture_get_sub_resource(texture, 0);
     surface_impl = wined3d_resource_get_parent(sub_resource);
-    surface_impl->forwardReference = NULL;
     surface_impl->parent_device = &device->IDirect3DDevice9Ex_iface;
     *surface = &surface_impl->IDirect3DSurface9_iface;
     IDirect3DSurface9_AddRef(*surface);
@@ -1258,8 +1268,14 @@ static HRESULT WINAPI d3d9_device_ColorFill(IDirect3DDevice9Ex *iface,
         return D3DERR_INVALIDCALL;
     }
 
-    /* Colorfill can only be used on rendertarget surfaces, or offscreen plain surfaces in D3DPOOL_DEFAULT */
-    hr = wined3d_device_color_fill(device->wined3d_device, surface_impl->wined3d_surface, rect, &c);
+    if (desc.pool != WINED3D_POOL_DEFAULT && desc.pool != WINED3D_POOL_SYSTEM_MEM)
+    {
+        WARN("Color-fill not allowed on surfaces in pool %#x.\n", desc.pool);
+        return D3DERR_INVALIDCALL;
+    }
+
+    hr = wined3d_device_clear_rendertarget_view(device->wined3d_device,
+            d3d9_surface_get_rendertarget_view(surface_impl), rect, &c);
 
     wined3d_mutex_unlock();
 
@@ -1332,8 +1348,8 @@ static HRESULT WINAPI d3d9_device_SetRenderTarget(IDirect3DDevice9Ex *iface, DWO
     }
 
     wined3d_mutex_lock();
-    hr = wined3d_device_set_render_target(device->wined3d_device, idx,
-            surface_impl ? surface_impl->wined3d_surface : NULL, TRUE);
+    hr = wined3d_device_set_rendertarget_view(device->wined3d_device, idx,
+            surface_impl ? d3d9_surface_get_rendertarget_view(surface_impl) : NULL, TRUE);
     wined3d_mutex_unlock();
 
     return hr;
@@ -1342,7 +1358,7 @@ static HRESULT WINAPI d3d9_device_SetRenderTarget(IDirect3DDevice9Ex *iface, DWO
 static HRESULT WINAPI d3d9_device_GetRenderTarget(IDirect3DDevice9Ex *iface, DWORD idx, IDirect3DSurface9 **surface)
 {
     struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
-    struct wined3d_surface *wined3d_surface;
+    struct wined3d_rendertarget_view *wined3d_rtv;
     struct d3d9_surface *surface_impl;
     HRESULT hr = D3D_OK;
 
@@ -1358,9 +1374,11 @@ static HRESULT WINAPI d3d9_device_GetRenderTarget(IDirect3DDevice9Ex *iface, DWO
     }
 
     wined3d_mutex_lock();
-    if ((wined3d_surface = wined3d_device_get_render_target(device->wined3d_device, idx)))
+    if ((wined3d_rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, idx)))
     {
-        surface_impl = wined3d_surface_get_parent(wined3d_surface);
+        /* We want the sub resource parent here, since the view itself may be
+         * internal to wined3d and may not have a parent. */
+        surface_impl = wined3d_rendertarget_view_get_sub_resource_parent(wined3d_rtv);
         *surface = &surface_impl->IDirect3DSurface9_iface;
         IDirect3DSurface9_AddRef(*surface);
     }
@@ -1382,7 +1400,8 @@ static HRESULT WINAPI d3d9_device_SetDepthStencilSurface(IDirect3DDevice9Ex *ifa
     TRACE("iface %p, depth_stencil %p.\n", iface, depth_stencil);
 
     wined3d_mutex_lock();
-    wined3d_device_set_depth_stencil(device->wined3d_device, ds_impl ? ds_impl->wined3d_surface : NULL);
+    wined3d_device_set_depth_stencil_view(device->wined3d_device,
+            ds_impl ? d3d9_surface_get_rendertarget_view(ds_impl) : NULL);
     wined3d_mutex_unlock();
 
     return D3D_OK;
@@ -1391,7 +1410,7 @@ static HRESULT WINAPI d3d9_device_SetDepthStencilSurface(IDirect3DDevice9Ex *ifa
 static HRESULT WINAPI d3d9_device_GetDepthStencilSurface(IDirect3DDevice9Ex *iface, IDirect3DSurface9 **depth_stencil)
 {
     struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
-    struct wined3d_surface *wined3d_surface;
+    struct wined3d_rendertarget_view *wined3d_dsv;
     struct d3d9_surface *surface_impl;
     HRESULT hr = D3D_OK;
 
@@ -1401,9 +1420,11 @@ static HRESULT WINAPI d3d9_device_GetDepthStencilSurface(IDirect3DDevice9Ex *ifa
         return D3DERR_INVALIDCALL;
 
     wined3d_mutex_lock();
-    if ((wined3d_surface = wined3d_device_get_depth_stencil(device->wined3d_device)))
+    if ((wined3d_dsv = wined3d_device_get_depth_stencil_view(device->wined3d_device)))
     {
-        surface_impl = wined3d_surface_get_parent(wined3d_surface);
+        /* We want the sub resource parent here, since the view itself may be
+         * internal to wined3d and may not have a parent. */
+        surface_impl = wined3d_rendertarget_view_get_sub_resource_parent(wined3d_dsv);
         *depth_stencil = &surface_impl->IDirect3DSurface9_iface;
         IDirect3DSurface9_AddRef(*depth_stencil);
     }
@@ -2745,7 +2766,6 @@ static HRESULT WINAPI d3d9_device_GetStreamSource(IDirect3DDevice9Ex *iface,
         buffer_impl = wined3d_buffer_get_parent(wined3d_buffer);
         *buffer = &buffer_impl->IDirect3DVertexBuffer9_iface;
         IDirect3DVertexBuffer9_AddRef(*buffer);
-        wined3d_buffer_decref(wined3d_buffer);
     }
     else
     {
@@ -3074,6 +3094,9 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_PresentEx(IDirect3DDevice9Ex
             iface, wine_dbgstr_rect(src_rect), wine_dbgstr_rect(dst_rect),
             dst_window_override, dirty_region, flags);
 
+    if (device->device_state != D3D9_DEVICE_STATE_OK)
+        return S_PRESENT_OCCLUDED;
+
     wined3d_mutex_lock();
     hr = wined3d_device_present(device->wined3d_device, src_rect, dst_rect,
             dst_window_override, dirty_region, flags);
@@ -3130,14 +3153,26 @@ static HRESULT WINAPI d3d9_device_GetMaximumFrameLatency(IDirect3DDevice9Ex *ifa
 
 static HRESULT WINAPI d3d9_device_CheckDeviceState(IDirect3DDevice9Ex *iface, HWND dst_window)
 {
-    static int i;
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct wined3d_swapchain_desc swapchain_desc;
+    struct wined3d_swapchain *swapchain;
 
-    TRACE("iface %p, dst_window %p stub!\n", iface, dst_window);
+    TRACE("iface %p, dst_window %p.\n", iface, dst_window);
 
-    if (!i++)
-        FIXME("iface %p, dst_window %p stub!\n", iface, dst_window);
+    wined3d_mutex_lock();
+    swapchain = wined3d_device_get_swapchain(device->wined3d_device, 0);
+    wined3d_swapchain_get_desc(swapchain, &swapchain_desc);
+    wined3d_mutex_unlock();
 
-    return D3D_OK;
+    if (swapchain_desc.windowed)
+        return D3D_OK;
+
+    /* FIXME: This is actually supposed to check if any other device is in
+     * fullscreen mode. */
+    if (dst_window != swapchain_desc.device_window)
+        return device->device_state == D3D9_DEVICE_STATE_OK ? S_PRESENT_OCCLUDED : D3D_OK;
+
+    return device->device_state == D3D9_DEVICE_STATE_OK ? D3D_OK : S_PRESENT_OCCLUDED;
 }
 
 static HRESULT WINAPI d3d9_device_CreateRenderTargetEx(IDirect3DDevice9Ex *iface,
@@ -3411,33 +3446,39 @@ static void CDECL device_parent_mode_changed(struct wined3d_device_parent *devic
     TRACE("device_parent %p.\n", device_parent);
 }
 
+static void CDECL device_parent_activate(struct wined3d_device_parent *device_parent, BOOL activate)
+{
+    struct d3d9_device *device = device_from_device_parent(device_parent);
+
+    TRACE("device_parent %p, activate %#x.\n", device_parent, activate);
+
+    if (!device->d3d_parent)
+        return;
+
+    if (!activate)
+        InterlockedCompareExchange(&device->device_state, D3D9_DEVICE_STATE_LOST, D3D9_DEVICE_STATE_OK);
+    else if (device->d3d_parent->extended)
+        InterlockedCompareExchange(&device->device_state, D3D9_DEVICE_STATE_OK, D3D9_DEVICE_STATE_LOST);
+    else
+        InterlockedCompareExchange(&device->device_state, D3D9_DEVICE_STATE_NOT_RESET, D3D9_DEVICE_STATE_LOST);
+}
+
 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;
 
     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))))
-    {
-        FIXME("Failed to allocate surface memory.\n");
-        return D3DERR_OUTOFVIDEOMEMORY;
-    }
+        return E_OUTOFMEMORY;
 
-    surface_init(d3d_surface, surface, device, parent_ops);
+    surface_init(d3d_surface, container_parent, surface, parent_ops);
     *parent = d3d_surface;
     TRACE("Created surface %p.\n", d3d_surface);
 
-    d3d_surface->container = container_parent;
-    IDirect3DDevice9Ex_Release(d3d_surface->parent_device);
-    d3d_surface->parent_device = NULL;
-
-    IDirect3DSurface9_Release(&d3d_surface->IDirect3DSurface9_iface);
-    d3d_surface->forwardReference = container_parent;
-
     return D3D_OK;
 }
 
@@ -3453,15 +3494,10 @@ static HRESULT CDECL device_parent_volume_created(struct wined3d_device_parent *
     if (!(d3d_volume = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*d3d_volume))))
         return E_OUTOFMEMORY;
 
-    volume_init(d3d_volume, volume, parent_ops);
+    volume_init(d3d_volume, container_parent, 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;
 }
 
@@ -3494,7 +3530,6 @@ static HRESULT CDECL device_parent_create_swapchain_surface(struct wined3d_devic
     wined3d_texture_decref(texture);
 
     d3d_surface = wined3d_surface_get_parent(*surface);
-    d3d_surface->forwardReference = NULL;
     d3d_surface->parent_device = &device->IDirect3DDevice9Ex_iface;
 
     return hr;
@@ -3528,6 +3563,7 @@ static const struct wined3d_device_parent_ops d3d9_wined3d_device_parent_ops =
 {
     device_parent_wined3d_device_created,
     device_parent_mode_changed,
+    device_parent_activate,
     device_parent_surface_created,
     device_parent_volume_created,
     device_parent_create_swapchain_surface,
index 044a2ad..578476d 100644 (file)
@@ -150,8 +150,11 @@ static HRESULT WINAPI d3d9_query_GetData(IDirect3DQuery9 *iface, void *data, DWO
     {
         struct wined3d_query_data_timestamp_disjoint data_disjoint;
 
+        if (size > sizeof(data_disjoint.disjoint))
+            size = sizeof(data_disjoint.disjoint);
+
         hr = wined3d_query_get_data(query->wined3d_query, &data_disjoint, sizeof(data_disjoint), flags);
-        *(BOOL *)data = data_disjoint.disjoint;
+        memcpy(data, &data_disjoint.disjoint, size);
     }
     else
     {
@@ -183,7 +186,7 @@ HRESULT query_init(struct d3d9_query *query, struct d3d9_device *device, D3DQUER
     query->refcount = 1;
 
     wined3d_mutex_lock();
-    hr = wined3d_query_create(device->wined3d_device, type, &query->wined3d_query);
+    hr = wined3d_query_create(device->wined3d_device, type, query, &query->wined3d_query);
     wined3d_mutex_unlock();
     if (FAILED(hr))
     {
index 785e860..4a563d3 100644 (file)
@@ -52,10 +52,10 @@ static ULONG WINAPI d3d9_surface_AddRef(IDirect3DSurface9 *iface)
 
     TRACE("iface %p.\n", iface);
 
-    if (surface->forwardReference)
+    if (surface->texture)
     {
-        TRACE("Forwarding to %p.\n", surface->forwardReference);
-        return IUnknown_AddRef(surface->forwardReference);
+        TRACE("Forwarding to %p.\n", surface->texture);
+        return IDirect3DBaseTexture9_AddRef(&surface->texture->IDirect3DBaseTexture9_iface);
     }
 
     refcount = InterlockedIncrement(&surface->resource.refcount);
@@ -66,6 +66,8 @@ static ULONG WINAPI d3d9_surface_AddRef(IDirect3DSurface9 *iface)
         if (surface->parent_device)
             IDirect3DDevice9Ex_AddRef(surface->parent_device);
         wined3d_mutex_lock();
+        if (surface->wined3d_rtv)
+            wined3d_rendertarget_view_incref(surface->wined3d_rtv);
         wined3d_surface_incref(surface->wined3d_surface);
         wined3d_mutex_unlock();
     }
@@ -80,10 +82,10 @@ static ULONG WINAPI d3d9_surface_Release(IDirect3DSurface9 *iface)
 
     TRACE("iface %p.\n", iface);
 
-    if (surface->forwardReference)
+    if (surface->texture)
     {
-        TRACE("Forwarding to %p.\n", surface->forwardReference);
-        return IUnknown_Release(surface->forwardReference);
+        TRACE("Forwarding to %p.\n", surface->texture);
+        return IDirect3DBaseTexture9_Release(&surface->texture->IDirect3DBaseTexture9_iface);
     }
 
     refcount = InterlockedDecrement(&surface->resource.refcount);
@@ -94,6 +96,8 @@ static ULONG WINAPI d3d9_surface_Release(IDirect3DSurface9 *iface)
         IDirect3DDevice9Ex *parent_device = surface->parent_device;
 
         wined3d_mutex_lock();
+        if (surface->wined3d_rtv)
+            wined3d_rendertarget_view_decref(surface->wined3d_rtv);
         wined3d_surface_decref(surface->wined3d_surface);
         wined3d_mutex_unlock();
 
@@ -111,22 +115,8 @@ static HRESULT WINAPI d3d9_surface_GetDevice(IDirect3DSurface9 *iface, IDirect3D
 
     TRACE("iface %p, device %p.\n", iface, device);
 
-    if (surface->forwardReference)
-    {
-        IDirect3DResource9 *resource;
-        HRESULT hr;
-
-        hr = IUnknown_QueryInterface(surface->forwardReference, &IID_IDirect3DResource9, (void **)&resource);
-        if (SUCCEEDED(hr))
-        {
-            hr = IDirect3DResource9_GetDevice(resource, device);
-            IDirect3DResource9_Release(resource);
-
-            TRACE("Returning device %p.\n", *device);
-        }
-
-        return hr;
-    }
+    if (surface->texture)
+        return IDirect3DBaseTexture9_GetDevice(&surface->texture->IDirect3DBaseTexture9_iface, device);
 
     *device = (IDirect3DDevice9 *)surface->parent_device;
     IDirect3DDevice9_AddRef(*device);
@@ -166,30 +156,14 @@ static HRESULT WINAPI d3d9_surface_FreePrivateData(IDirect3DSurface9 *iface, REF
 
 static DWORD WINAPI d3d9_surface_SetPriority(IDirect3DSurface9 *iface, DWORD priority)
 {
-    struct d3d9_surface *surface = impl_from_IDirect3DSurface9(iface);
-    DWORD ret;
-
-    TRACE("iface %p, priority %u.\n", iface, priority);
-
-    wined3d_mutex_lock();
-    ret = wined3d_surface_set_priority(surface->wined3d_surface, priority);
-    wined3d_mutex_unlock();
-
-    return ret;
+    TRACE("iface %p, priority %u. Ignored on surfaces.\n", iface, priority);
+    return 0;
 }
 
 static DWORD WINAPI d3d9_surface_GetPriority(IDirect3DSurface9 *iface)
 {
-    struct d3d9_surface *surface = impl_from_IDirect3DSurface9(iface);
-    DWORD ret;
-
-    TRACE("iface %p.\n", iface);
-
-    wined3d_mutex_lock();
-    ret = wined3d_surface_get_priority(surface->wined3d_surface);
-    wined3d_mutex_unlock();
-
-    return ret;
+    TRACE("iface %p. Ignored on surfaces.\n", iface);
+    return 0;
 }
 
 static void WINAPI d3d9_surface_PreLoad(IDirect3DSurface9 *iface)
@@ -368,13 +342,25 @@ static const struct wined3d_parent_ops d3d9_surface_wined3d_parent_ops =
     surface_wined3d_object_destroyed,
 };
 
-void surface_init(struct d3d9_surface *surface, struct wined3d_surface *wined3d_surface,
-        struct d3d9_device *device, const struct wined3d_parent_ops **parent_ops)
+void surface_init(struct d3d9_surface *surface, IUnknown *container_parent,
+        struct wined3d_surface *wined3d_surface, const struct wined3d_parent_ops **parent_ops)
 {
     struct wined3d_resource_desc desc;
+    IDirect3DBaseTexture9 *texture;
 
     surface->IDirect3DSurface9_iface.lpVtbl = &d3d9_surface_vtbl;
     d3d9_resource_init(&surface->resource);
+    surface->resource.refcount = 0;
+    surface->wined3d_surface = wined3d_surface;
+    list_init(&surface->rtv_entry);
+    surface->container = container_parent;
+
+    if (container_parent && SUCCEEDED(IUnknown_QueryInterface(container_parent,
+            &IID_IDirect3DBaseTexture9, (void **)&texture)))
+    {
+        surface->texture = unsafe_impl_from_IDirect3DBaseTexture9(texture);
+        IDirect3DBaseTexture9_Release(texture);
+    }
 
     wined3d_resource_get_desc(wined3d_surface_get_resource(wined3d_surface), &desc);
     switch (d3dformat_from_wined3dformat(desc.format))
@@ -393,14 +379,51 @@ void surface_init(struct d3d9_surface *surface, struct wined3d_surface *wined3d_
             break;
     }
 
-    wined3d_surface_incref(wined3d_surface);
-    surface->wined3d_surface = wined3d_surface;
-    surface->parent_device = &device->IDirect3DDevice9Ex_iface;
-    IDirect3DDevice9Ex_AddRef(surface->parent_device);
-
     *parent_ops = &d3d9_surface_wined3d_parent_ops;
 }
 
+static void STDMETHODCALLTYPE view_wined3d_object_destroyed(void *parent)
+{
+    struct d3d9_surface *surface = parent;
+
+    /* If the surface reference count drops to zero, we release our reference
+     * to the view, but don't clear the pointer yet, in case e.g. a
+     * GetRenderTarget() call brings the surface back before the view is
+     * actually destroyed. When the view is destroyed, we need to clear the
+     * pointer, or a subsequent surface AddRef() would reference it again.
+     *
+     * This is safe because as long as the view still has a reference to the
+     * texture, the surface is also still alive, and we're called before the
+     * view releases that reference. */
+    surface->wined3d_rtv = NULL;
+    list_remove(&surface->rtv_entry);
+}
+
+static const struct wined3d_parent_ops d3d9_view_wined3d_parent_ops =
+{
+    view_wined3d_object_destroyed,
+};
+
+struct wined3d_rendertarget_view *d3d9_surface_get_rendertarget_view(struct d3d9_surface *surface)
+{
+    HRESULT hr;
+
+    if (surface->wined3d_rtv)
+        return surface->wined3d_rtv;
+
+    if (FAILED(hr = wined3d_rendertarget_view_create_from_surface(surface->wined3d_surface,
+            surface, &d3d9_view_wined3d_parent_ops, &surface->wined3d_rtv)))
+    {
+        ERR("Failed to create rendertarget view, hr %#x.\n", hr);
+        return NULL;
+    }
+
+    if (surface->texture)
+        list_add_head(&surface->texture->rtv_list, &surface->rtv_entry);
+
+    return surface->wined3d_rtv;
+}
+
 struct d3d9_surface *unsafe_impl_from_IDirect3DSurface9(IDirect3DSurface9 *iface)
 {
     if (!iface)
index f5ec383..6698a8b 100644 (file)
@@ -112,12 +112,16 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_swapchain_Present(IDirect3DSwapChai
         const RGNDATA *dirty_region, DWORD flags)
 {
     struct d3d9_swapchain *swapchain = impl_from_IDirect3DSwapChain9Ex(iface);
+    struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(swapchain->parent_device);
     HRESULT hr;
 
     TRACE("iface %p, src_rect %s, dst_rect %s, dst_window_override %p, dirty_region %p, flags %#x.\n",
             iface, wine_dbgstr_rect(src_rect), wine_dbgstr_rect(dst_rect),
             dst_window_override, dirty_region, flags);
 
+    if (device->device_state != D3D9_DEVICE_STATE_OK)
+        return device->d3d_parent->extended ? S_PRESENT_OCCLUDED : D3DERR_DEVICELOST;
+
     wined3d_mutex_lock();
     hr = wined3d_swapchain_present(swapchain->wined3d_swapchain, src_rect,
             dst_rect, dst_window_override, dirty_region, flags);
index 5f14bf2..182f53c 100644 (file)
@@ -64,8 +64,14 @@ static ULONG WINAPI d3d9_texture_2d_AddRef(IDirect3DTexture9 *iface)
 
     if (ref == 1)
     {
+        struct d3d9_surface *surface;
+
         IDirect3DDevice9Ex_AddRef(texture->parent_device);
         wined3d_mutex_lock();
+        LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d9_surface, rtv_entry)
+        {
+            wined3d_rendertarget_view_incref(surface->wined3d_rtv);
+        }
         wined3d_texture_incref(texture->wined3d_texture);
         wined3d_mutex_unlock();
     }
@@ -83,8 +89,13 @@ static ULONG WINAPI d3d9_texture_2d_Release(IDirect3DTexture9 *iface)
     if (!ref)
     {
         IDirect3DDevice9Ex *parent_device = texture->parent_device;
+        struct d3d9_surface *surface;
 
         wined3d_mutex_lock();
+        LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d9_surface, rtv_entry)
+        {
+            wined3d_rendertarget_view_decref(surface->wined3d_rtv);
+        }
         wined3d_texture_decref(texture->wined3d_texture);
         wined3d_mutex_unlock();
 
@@ -139,12 +150,14 @@ static HRESULT WINAPI d3d9_texture_2d_FreePrivateData(IDirect3DTexture9 *iface,
 static DWORD WINAPI d3d9_texture_2d_SetPriority(IDirect3DTexture9 *iface, DWORD priority)
 {
     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
+    struct wined3d_resource *resource;
     DWORD ret;
 
     TRACE("iface %p, priority %u.\n", iface, priority);
 
     wined3d_mutex_lock();
-    ret = wined3d_texture_set_priority(texture->wined3d_texture, priority);
+    resource = wined3d_texture_get_resource(texture->wined3d_texture);
+    ret = wined3d_resource_set_priority(resource, priority);
     wined3d_mutex_unlock();
 
     return ret;
@@ -153,12 +166,14 @@ static DWORD WINAPI d3d9_texture_2d_SetPriority(IDirect3DTexture9 *iface, DWORD
 static DWORD WINAPI d3d9_texture_2d_GetPriority(IDirect3DTexture9 *iface)
 {
     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
+    const struct wined3d_resource *resource;
     DWORD ret;
 
     TRACE("iface %p.\n", iface);
 
     wined3d_mutex_lock();
-    ret = wined3d_texture_get_priority(texture->wined3d_texture);
+    resource = wined3d_texture_get_resource(texture->wined3d_texture);
+    ret = wined3d_resource_get_priority(resource);
     wined3d_mutex_unlock();
 
     return ret;
@@ -451,8 +466,14 @@ static ULONG WINAPI d3d9_texture_cube_AddRef(IDirect3DCubeTexture9 *iface)
 
     if (ref == 1)
     {
+        struct d3d9_surface *surface;
+
         IDirect3DDevice9Ex_AddRef(texture->parent_device);
         wined3d_mutex_lock();
+        LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d9_surface, rtv_entry)
+        {
+            wined3d_rendertarget_view_decref(surface->wined3d_rtv);
+        }
         wined3d_texture_incref(texture->wined3d_texture);
         wined3d_mutex_unlock();
     }
@@ -470,10 +491,15 @@ static ULONG WINAPI d3d9_texture_cube_Release(IDirect3DCubeTexture9 *iface)
     if (!ref)
     {
         IDirect3DDevice9Ex *parent_device = texture->parent_device;
+        struct d3d9_surface *surface;
 
         TRACE("Releasing child %p.\n", texture->wined3d_texture);
 
         wined3d_mutex_lock();
+        LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d9_surface, rtv_entry)
+        {
+            wined3d_rendertarget_view_decref(surface->wined3d_rtv);
+        }
         wined3d_texture_decref(texture->wined3d_texture);
         wined3d_mutex_unlock();
 
@@ -528,12 +554,14 @@ static HRESULT WINAPI d3d9_texture_cube_FreePrivateData(IDirect3DCubeTexture9 *i
 static DWORD WINAPI d3d9_texture_cube_SetPriority(IDirect3DCubeTexture9 *iface, DWORD priority)
 {
     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
+    struct wined3d_resource *resource;
     DWORD ret;
 
     TRACE("iface %p, priority %u.\n", iface, priority);
 
     wined3d_mutex_lock();
-    ret = wined3d_texture_set_priority(texture->wined3d_texture, priority);
+    resource = wined3d_texture_get_resource(texture->wined3d_texture);
+    ret = wined3d_resource_set_priority(resource, priority);
     wined3d_mutex_unlock();
 
     return ret;
@@ -542,12 +570,14 @@ static DWORD WINAPI d3d9_texture_cube_SetPriority(IDirect3DCubeTexture9 *iface,
 static DWORD WINAPI d3d9_texture_cube_GetPriority(IDirect3DCubeTexture9 *iface)
 {
     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
+    const struct wined3d_resource *resource;
     DWORD ret;
 
     TRACE("iface %p.\n", iface);
 
     wined3d_mutex_lock();
-    ret = wined3d_texture_get_priority(texture->wined3d_texture);
+    resource = wined3d_texture_get_resource(texture->wined3d_texture);
+    ret = wined3d_resource_get_priority(resource);
     wined3d_mutex_unlock();
 
     return ret;
@@ -941,12 +971,14 @@ static HRESULT WINAPI d3d9_texture_3d_FreePrivateData(IDirect3DVolumeTexture9 *i
 static DWORD WINAPI d3d9_texture_3d_SetPriority(IDirect3DVolumeTexture9 *iface, DWORD priority)
 {
     struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
+    struct wined3d_resource *resource;
     DWORD ret;
 
     TRACE("iface %p, priority %u.\n", iface, priority);
 
     wined3d_mutex_lock();
-    ret = wined3d_texture_set_priority(texture->wined3d_texture, priority);
+    resource = wined3d_texture_get_resource(texture->wined3d_texture);
+    ret = wined3d_resource_set_priority(resource, priority);
     wined3d_mutex_unlock();
 
     return ret;
@@ -955,12 +987,14 @@ static DWORD WINAPI d3d9_texture_3d_SetPriority(IDirect3DVolumeTexture9 *iface,
 static DWORD WINAPI d3d9_texture_3d_GetPriority(IDirect3DVolumeTexture9 *iface)
 {
     struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
+    const struct wined3d_resource *resource;
     DWORD ret;
 
     TRACE("iface %p.\n", iface);
 
     wined3d_mutex_lock();
-    ret = wined3d_texture_get_priority(texture->wined3d_texture);
+    resource = wined3d_texture_get_resource(texture->wined3d_texture);
+    ret = wined3d_resource_get_priority(resource);
     wined3d_mutex_unlock();
 
     return ret;
@@ -1242,6 +1276,7 @@ HRESULT texture_init(struct d3d9_texture *texture, struct d3d9_device *device,
 
     texture->IDirect3DBaseTexture9_iface.lpVtbl = (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_2d_vtbl;
     d3d9_resource_init(&texture->resource);
+    list_init(&texture->rtv_list);
 
     desc.resource_type = WINED3D_RTYPE_TEXTURE;
     desc.format = wined3dformat_from_d3dformat(format);
@@ -1283,6 +1318,7 @@ HRESULT cubetexture_init(struct d3d9_texture *texture, struct d3d9_device *devic
 
     texture->IDirect3DBaseTexture9_iface.lpVtbl = (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_cube_vtbl;
     d3d9_resource_init(&texture->resource);
+    list_init(&texture->rtv_list);
 
     desc.resource_type = WINED3D_RTYPE_CUBE_TEXTURE;
     desc.format = wined3dformat_from_d3dformat(format);
@@ -1323,6 +1359,7 @@ HRESULT volumetexture_init(struct d3d9_texture *texture, struct d3d9_device *dev
 
     texture->IDirect3DBaseTexture9_iface.lpVtbl = (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_3d_vtbl;
     d3d9_resource_init(&texture->resource);
+    list_init(&texture->rtv_list);
 
     desc.resource_type = WINED3D_RTYPE_VOLUME_TEXTURE;
     desc.format = wined3dformat_from_d3dformat(format);
index 9a3419d..9a7aad6 100644 (file)
@@ -47,73 +47,30 @@ static HRESULT WINAPI d3d9_volume_QueryInterface(IDirect3DVolume9 *iface, REFIID
 static ULONG WINAPI d3d9_volume_AddRef(IDirect3DVolume9 *iface)
 {
     struct d3d9_volume *volume = impl_from_IDirect3DVolume9(iface);
-    ULONG refcount;
 
     TRACE("iface %p.\n", iface);
+    TRACE("Forwarding to %p.\n", volume->texture);
 
-    if (volume->forwardReference)
-    {
-        TRACE("Forwarding to %p.\n", volume->forwardReference);
-        return IUnknown_AddRef(volume->forwardReference);
-    }
-
-    refcount = InterlockedIncrement(&volume->resource.refcount);
-    TRACE("%p increasing refcount to %u.\n", iface, refcount);
-
-    if (refcount == 1)
-    {
-        wined3d_mutex_lock();
-        wined3d_volume_incref(volume->wined3d_volume);
-        wined3d_mutex_unlock();
-    }
-
-    return refcount;
+    return IDirect3DBaseTexture9_AddRef(&volume->texture->IDirect3DBaseTexture9_iface);
 }
 
 static ULONG WINAPI d3d9_volume_Release(IDirect3DVolume9 *iface)
 {
     struct d3d9_volume *volume = impl_from_IDirect3DVolume9(iface);
-    ULONG refcount;
 
     TRACE("iface %p.\n", iface);
+    TRACE("Forwarding to %p.\n", volume->texture);
 
-    if (volume->forwardReference)
-    {
-        TRACE("Forwarding to %p.\n", volume->forwardReference);
-        return IUnknown_Release(volume->forwardReference);
-    }
-
-    refcount = InterlockedDecrement(&volume->resource.refcount);
-    TRACE("%p decreasing refcount to %u.\n", iface, refcount);
-
-    if (!refcount)
-    {
-        wined3d_mutex_lock();
-        wined3d_volume_decref(volume->wined3d_volume);
-        wined3d_mutex_unlock();
-    }
-
-    return refcount;
+    return IDirect3DBaseTexture9_Release(&volume->texture->IDirect3DBaseTexture9_iface);
 }
 
 static HRESULT WINAPI d3d9_volume_GetDevice(IDirect3DVolume9 *iface, IDirect3DDevice9 **device)
 {
     struct d3d9_volume *volume = impl_from_IDirect3DVolume9(iface);
-    IDirect3DResource9 *resource;
-    HRESULT hr;
 
     TRACE("iface %p, device %p.\n", iface, device);
 
-    hr = IUnknown_QueryInterface(volume->forwardReference, &IID_IDirect3DResource9, (void **)&resource);
-    if (SUCCEEDED(hr))
-    {
-        hr = IDirect3DResource9_GetDevice(resource, device);
-        IDirect3DResource9_Release(resource);
-
-        TRACE("Returning device %p.\n", *device);
-    }
-
-    return hr;
+    return IDirect3DBaseTexture9_GetDevice(&volume->texture->IDirect3DBaseTexture9_iface, device);
 }
 
 static HRESULT WINAPI d3d9_volume_SetPrivateData(IDirect3DVolume9 *iface, REFGUID guid,
@@ -147,18 +104,10 @@ static HRESULT WINAPI d3d9_volume_FreePrivateData(IDirect3DVolume9 *iface, REFGU
 static HRESULT WINAPI d3d9_volume_GetContainer(IDirect3DVolume9 *iface, REFIID riid, void **container)
 {
     struct d3d9_volume *volume = impl_from_IDirect3DVolume9(iface);
-    HRESULT hr;
 
     TRACE("iface %p, riid %s, container %p.\n", iface, debugstr_guid(riid), container);
 
-    if (!volume->container)
-        return E_NOINTERFACE;
-
-    hr = IUnknown_QueryInterface(volume->container, riid, container);
-
-    TRACE("Returning %p,\n", *container);
-
-    return hr;
+    return IDirect3DBaseTexture9_QueryInterface(&volume->texture->IDirect3DBaseTexture9_iface, riid, container);
 }
 
 static HRESULT WINAPI d3d9_volume_GetDesc(IDirect3DVolume9 *iface, D3DVOLUME_DESC *desc)
@@ -249,13 +198,14 @@ static const struct wined3d_parent_ops d3d9_volume_wined3d_parent_ops =
     volume_wined3d_object_destroyed,
 };
 
-void volume_init(struct d3d9_volume *volume, struct wined3d_volume *wined3d_volume,
-        const struct wined3d_parent_ops **parent_ops)
+void volume_init(struct d3d9_volume *volume, struct d3d9_texture *texture,
+        struct wined3d_volume *wined3d_volume, const struct wined3d_parent_ops **parent_ops)
 {
     volume->IDirect3DVolume9_iface.lpVtbl = &d3d9_volume_vtbl;
     d3d9_resource_init(&volume->resource);
-    wined3d_volume_incref(wined3d_volume);
+    volume->resource.refcount = 0;
     volume->wined3d_volume = wined3d_volume;
+    volume->texture = texture;
 
     *parent_ops = &d3d9_volume_wined3d_parent_ops;
 }
index e16a23d..44e535d 100644 (file)
@@ -762,7 +762,7 @@ static HRESULT WINAPI ddraw1_RestoreDisplayMode(IDirectDraw *iface)
 static HRESULT ddraw_set_cooperative_level(struct ddraw *ddraw, HWND window,
         DWORD cooplevel, BOOL restore_mode_on_normal)
 {
-    struct wined3d_surface *rt = NULL, *ds = NULL;
+    struct wined3d_rendertarget_view *rtv = NULL, *dsv = NULL;
     struct wined3d_stateblock *stateblock;
     BOOL restore_state = FALSE;
     HRESULT hr;
@@ -913,14 +913,15 @@ static HRESULT ddraw_set_cooperative_level(struct ddraw *ddraw, HWND window,
             }
 
             wined3d_stateblock_capture(stateblock);
-            rt = wined3d_device_get_render_target(ddraw->wined3d_device, 0);
-            if (rt == ddraw->wined3d_frontbuffer)
-                rt = NULL;
-            else if (rt)
-                wined3d_surface_incref(rt);
-
-            if ((ds = wined3d_device_get_depth_stencil(ddraw->wined3d_device)))
-                wined3d_surface_incref(ds);
+            rtv = wined3d_device_get_rendertarget_view(ddraw->wined3d_device, 0);
+            /* Rendering to ddraw->wined3d_frontbuffer. */
+            if (rtv && !wined3d_rendertarget_view_get_sub_resource_parent(rtv))
+                rtv = NULL;
+            else if (rtv)
+                wined3d_rendertarget_view_incref(rtv);
+
+            if ((dsv = wined3d_device_get_depth_stencil_view(ddraw->wined3d_device)))
+                wined3d_rendertarget_view_incref(dsv);
         }
 
         ddraw_destroy_swapchain(ddraw);
@@ -931,16 +932,16 @@ static HRESULT ddraw_set_cooperative_level(struct ddraw *ddraw, HWND window,
 
     if (restore_state)
     {
-        if (ds)
+        if (dsv)
         {
-            wined3d_device_set_depth_stencil(ddraw->wined3d_device, ds);
-            wined3d_surface_decref(ds);
+            wined3d_device_set_depth_stencil_view(ddraw->wined3d_device, dsv);
+            wined3d_rendertarget_view_decref(dsv);
         }
 
-        if (rt)
+        if (rtv)
         {
-            wined3d_device_set_render_target(ddraw->wined3d_device, 0, rt, FALSE);
-            wined3d_surface_decref(rt);
+            wined3d_device_set_rendertarget_view(ddraw->wined3d_device, 0, rtv, FALSE);
+            wined3d_rendertarget_view_decref(rtv);
         }
 
         wined3d_stateblock_apply(stateblock);
@@ -1885,7 +1886,7 @@ static HRESULT WINAPI ddraw1_GetVerticalBlankStatus(IDirectDraw *iface, BOOL *st
  *
  * Returns
  *  DD_OK on success
- *  DDERR_INVALIDPARAMS of free and total are NULL
+ *  DDERR_INVALIDPARAMS if free and total are NULL
  *
  *****************************************************************************/
 static HRESULT WINAPI ddraw7_GetAvailableVidMem(IDirectDraw7 *iface, DDSCAPS2 *Caps, DWORD *total,
@@ -1921,7 +1922,7 @@ static HRESULT WINAPI ddraw7_GetAvailableVidMem(IDirectDraw7 *iface, DDSCAPS2 *C
         struct wined3d_adapter_identifier desc = {0};
 
         hr = wined3d_get_adapter_identifier(ddraw->wined3d, WINED3DADAPTER_DEFAULT, 0, &desc);
-        *total = desc.video_memory;
+        *total = min(UINT_MAX, desc.video_memory);
     }
 
     wined3d_mutex_unlock();
@@ -2180,23 +2181,13 @@ static HRESULT WINAPI ddraw1_GetScanLine(IDirectDraw *iface, DWORD *line)
     return ddraw7_GetScanLine(&ddraw->IDirectDraw7_iface, line);
 }
 
-/*****************************************************************************
- * IDirectDraw7::TestCooperativeLevel
- *
- * Informs the application about the state of the video adapter, depending
- * on the cooperative level
- *
- * Returns:
- *  DD_OK if the device is in a sane state
- *  DDERR_NOEXCLUSIVEMODE or DDERR_EXCLUSIVEMODEALREADYSET
- *  if the state is not correct(See below)
- *
- *****************************************************************************/
 static HRESULT WINAPI ddraw7_TestCooperativeLevel(IDirectDraw7 *iface)
 {
+    struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
+
     TRACE("iface %p.\n", iface);
 
-    return DD_OK;
+    return ddraw->device_state == DDRAW_DEVICE_STATE_OK ? DD_OK : DDERR_NOEXCLUSIVEMODE;
 }
 
 static HRESULT WINAPI ddraw4_TestCooperativeLevel(IDirectDraw4 *iface)
@@ -2680,27 +2671,20 @@ static HRESULT WINAPI ddraw4_GetSurfaceFromDC(IDirectDraw4 *iface, HDC dc,
     return hr;
 }
 
-/*****************************************************************************
- * IDirectDraw7::RestoreAllSurfaces
- *
- * Calls the restore method of all surfaces
- *
- * Params:
- *
- * Returns:
- *  Always returns DD_OK because it's a stub
- *
- *****************************************************************************/
+static HRESULT CALLBACK restore_callback(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context)
+{
+    IDirectDrawSurface_Restore(surface);
+    IDirectDrawSurface_Release(surface);
+
+    return DDENUMRET_OK;
+}
+
 static HRESULT WINAPI ddraw7_RestoreAllSurfaces(IDirectDraw7 *iface)
 {
-    FIXME("iface %p stub!\n", iface);
+    TRACE("iface %p.\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;
+    return IDirectDraw7_EnumSurfaces(iface, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
+            NULL, NULL, restore_callback);
 }
 
 static HRESULT WINAPI ddraw4_RestoreAllSurfaces(IDirectDraw4 *iface)
@@ -3695,6 +3679,8 @@ static HRESULT WINAPI d3d3_EnumDevices(IDirect3D3 *iface, LPD3DENUMDEVICESCALLBA
                 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
         /* RGB, RAMP and MMX devices have a HAL dcmColorModel of 0 */
         hal_desc.dcmColorModel = 0;
+        /* RGB, RAMP and MMX devices cannot report HAL hardware flags */
+        hal_desc.dwFlags = 0;
 
         hr = callback((GUID *)&IID_IDirect3DRGBDevice, reference_description,
                 device_name, &hal_desc, &hel_desc, context);
@@ -4169,7 +4155,7 @@ static HRESULT WINAPI d3d2_CreateDevice(IDirect3D2 *iface, REFCLSID riid,
  *  D3D_OK on success
  *  DDERR_OUTOFMEMORY if memory allocation failed
  *  The return value of IWineD3DDevice::CreateVertexBuffer if this call fails
- *  DDERR_INVALIDPARAMS if desc or vertex_buffer are NULL
+ *  DDERR_INVALIDPARAMS if desc or vertex_buffer is NULL
  *
  *****************************************************************************/
 static HRESULT WINAPI d3d7_CreateVertexBuffer(IDirect3D7 *iface, D3DVERTEXBUFFERDESC *desc,
@@ -4717,6 +4703,18 @@ static void CDECL device_parent_mode_changed(struct wined3d_device_parent *devic
         ERR("Failed to resize window.\n");
 }
 
+static void CDECL device_parent_activate(struct wined3d_device_parent *device_parent, BOOL activate)
+{
+    struct ddraw *ddraw = ddraw_from_device_parent(device_parent);
+
+    TRACE("device_parent %p, activate %#x.\n", device_parent, activate);
+
+    if (!activate)
+        InterlockedCompareExchange(&ddraw->device_state, DDRAW_DEVICE_STATE_LOST, DDRAW_DEVICE_STATE_OK);
+    else
+        InterlockedCompareExchange(&ddraw->device_state, DDRAW_DEVICE_STATE_OK, DDRAW_DEVICE_STATE_LOST);
+}
+
 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)
@@ -4728,8 +4726,8 @@ static HRESULT CDECL device_parent_surface_created(struct wined3d_device_parent
     TRACE("device_parent %p, container_parent %p, surface %p, parent %p, parent_ops %p.\n",
             device_parent, container_parent, surface, parent, parent_ops);
 
-    /* We have a swapchain texture. */
-    if (container_parent == ddraw)
+    /* We have a swapchain or wined3d internal texture. */
+    if (!container_parent || container_parent == ddraw)
     {
         *parent = NULL;
         *parent_ops = &ddraw_null_wined3d_parent_ops;
@@ -4841,6 +4839,7 @@ static const struct wined3d_device_parent_ops ddraw_wined3d_device_parent_ops =
 {
     device_parent_wined3d_device_created,
     device_parent_mode_changed,
+    device_parent_activate,
     device_parent_surface_created,
     device_parent_volume_created,
     device_parent_create_swapchain_surface,
index ae2adbd..1ad8c2c 100644 (file)
@@ -65,6 +65,12 @@ struct FvfToDecl
 
 #define DDRAW_STRIDE_ALIGNMENT  8
 
+enum ddraw_device_state
+{
+    DDRAW_DEVICE_STATE_OK,
+    DDRAW_DEVICE_STATE_LOST,
+};
+
 struct ddraw
 {
     /* Interfaces */
@@ -84,6 +90,7 @@ struct ddraw
     struct wined3d *wined3d;
     struct wined3d_device *wined3d_device;
     DWORD flags;
+    LONG device_state;
 
     struct ddraw_surface *primary;
     RECT primary_lock;
@@ -157,6 +164,7 @@ struct ddraw_surface
     struct ddraw *ddraw;
     struct wined3d_surface *wined3d_surface;
     struct wined3d_texture *wined3d_texture;
+    struct wined3d_rendertarget_view *wined3d_rtv;
     struct wined3d_private_store private_store;
     struct d3d_device *device1;
 
@@ -204,9 +212,12 @@ struct ddraw_texture
 
 HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_desc,
         struct ddraw_surface **surface, IUnknown *outer_unknown, unsigned int version) DECLSPEC_HIDDEN;
+struct wined3d_rendertarget_view *ddraw_surface_get_rendertarget_view(struct ddraw_surface *surface) 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;
+HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface,
+        const RECT *rect, BOOL read) DECLSPEC_HIDDEN;
 
 static inline struct ddraw_surface *impl_from_IDirect3DTexture(IDirect3DTexture *iface)
 {
@@ -582,6 +593,20 @@ void DDSD2_to_DDSD(const DDSURFACEDESC2 *in, DDSURFACEDESC *out) DECLSPEC_HIDDEN
 
 void multiply_matrix(D3DMATRIX *dst, const D3DMATRIX *src1, const D3DMATRIX *src2) DECLSPEC_HIDDEN;
 
+static inline BOOL format_is_compressed(const DDPIXELFORMAT *format)
+{
+    return (format->dwFlags & DDPF_FOURCC) && (format->dwFourCC == WINED3DFMT_DXT1
+            || format->dwFourCC == WINED3DFMT_DXT2 || format->dwFourCC == WINED3DFMT_DXT3
+            || format->dwFourCC == WINED3DFMT_DXT4 || format->dwFourCC == WINED3DFMT_DXT5);
+}
+
+static inline BOOL format_is_paletteindexed(const DDPIXELFORMAT *fmt)
+{
+    DWORD flags = DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 | DDPF_PALETTEINDEXED4
+            | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8;
+    return !!(fmt->dwFlags & flags);
+}
+
 /* Used for generic dumping */
 struct flag_info
 {
index c53f69b..ee0c258 100644 (file)
@@ -242,7 +242,7 @@ static ULONG WINAPI d3d_device_inner_Release(IUnknown *iface)
         if (This->vertex_buffer)
             wined3d_buffer_decref(This->vertex_buffer);
 
-        wined3d_device_set_render_target(This->wined3d_device, 0, NULL, FALSE);
+        wined3d_device_set_rendertarget_view(This->wined3d_device, 0, NULL, FALSE);
 
         /* Release the wined3d device. This won't destroy it. */
         if (!wined3d_device_decref(This->wined3d_device))
@@ -1794,11 +1794,8 @@ static HRESULT WINAPI d3d_device2_GetCurrentViewport(IDirect3DDevice2 *iface, ID
 
 static BOOL validate_surface_palette(struct ddraw_surface *surface)
 {
-    return !(surface->surface_desc.u4.ddpfPixelFormat.dwFlags
-            & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2
-            | DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8
-            | DDPF_PALETTEINDEXEDTO8))
-            || wined3d_surface_get_palette(surface->wined3d_surface);
+    return !format_is_paletteindexed(&surface->surface_desc.u4.ddpfPixelFormat)
+            || surface->palette;
 }
 
 static HRESULT d3d_device_set_render_target(struct d3d_device *device,
@@ -1817,8 +1814,8 @@ static HRESULT d3d_device_set_render_target(struct d3d_device *device,
         return DDERR_INVALIDPARAMS;
     }
 
-    if (FAILED(hr = wined3d_device_set_render_target(device->wined3d_device,
-            0, target->wined3d_surface, FALSE)))
+    if (FAILED(hr = wined3d_device_set_rendertarget_view(device->wined3d_device,
+            0, ddraw_surface_get_rendertarget_view(target), FALSE)))
         return hr;
 
     IUnknown_AddRef(rt_iface);
@@ -2941,16 +2938,19 @@ static HRESULT WINAPI d3d_device3_SetLightState(IDirect3DDevice3 *iface,
     wined3d_mutex_lock();
     if (state == D3DLIGHTSTATE_MATERIAL)
     {
-        struct d3d_material *m = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_MATERIAL);
-        if (!m)
+        if (value)
         {
-            WARN("Invalid material handle.\n");
-            wined3d_mutex_unlock();
-            return DDERR_INVALIDPARAMS;
-        }
+            struct d3d_material *m;
+
+            if (!(m = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_MATERIAL)))
+            {
+                WARN("Invalid material handle.\n");
+                wined3d_mutex_unlock();
+                return DDERR_INVALIDPARAMS;
+            }
 
-        TRACE(" activating material %p.\n", m);
-        material_activate(m);
+            material_activate(m);
+        }
 
         device->material = value;
     }
@@ -3564,15 +3564,11 @@ static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *if
 
 static void setup_lighting(const struct d3d_device *device, DWORD fvf, DWORD flags)
 {
-    BOOL enable;
+    BOOL enable = TRUE;
 
     /* Ignore the D3DFVF_XYZRHW case here, wined3d takes care of that */
-    if (flags & D3DDP_DONOTLIGHT)
+    if (!device->material || !(fvf & D3DFVF_NORMAL) || (flags & D3DDP_DONOTLIGHT))
         enable = FALSE;
-    else if (!(fvf & D3DFVF_NORMAL))
-        enable = FALSE;
-    else
-        enable = TRUE;
 
     wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_LIGHTING, enable);
 }
@@ -4440,8 +4436,8 @@ static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface
  * are passed in the Centers and Radii arrays, the results are passed back
  * in the ReturnValues array. Return values are either completely visible,
  * partially visible or completely invisible.
- * The return value consist of a combination of D3DCLIP_* flags, or it's
- * 0 if the sphere is completely visible(according to the SDK, not checked)
+ * The return value consists of a combination of D3DCLIP_* flags, or is
+ * 0 if the sphere is completely visible (according to the SDK, not checked)
  *
  * Version 3 and 7
  *
@@ -4732,7 +4728,7 @@ static HRESULT WINAPI d3d_device3_SetTexture(IDirect3DDevice3 *iface,
             }
         }
 
-        /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
+        /* Args 1 and 2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
         if (tex_alpha)
             wined3d_device_set_texture_stage_state(device->wined3d_device,
                     0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
@@ -6046,7 +6042,7 @@ static void copy_mipmap_chain(struct d3d_device *device, struct ddraw_surface *d
  *
  * Returns:
  *  D3D_OK on success
- *  DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
+ *  DDERR_INVALIDPARAMS if dst_texture or src_texture is NULL, broken coordinates or anything unexpected.
  *
  *
  *****************************************************************************/
@@ -6759,13 +6755,13 @@ enum wined3d_depth_buffer_type d3d_device_update_depth_stencil(struct d3d_device
     if (!depthStencil)
     {
         TRACE("Setting wined3d depth stencil to NULL\n");
-        wined3d_device_set_depth_stencil(device->wined3d_device, NULL);
+        wined3d_device_set_depth_stencil_view(device->wined3d_device, NULL);
         return WINED3D_ZB_FALSE;
     }
 
     dsi = impl_from_IDirectDrawSurface7(depthStencil);
-    TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
-    wined3d_device_set_depth_stencil(device->wined3d_device, dsi->wined3d_surface);
+    wined3d_device_set_depth_stencil_view(device->wined3d_device,
+            ddraw_surface_get_rendertarget_view(dsi));
 
     IDirectDrawSurface7_Release(depthStencil);
     return WINED3D_ZB_TRUE;
@@ -6818,8 +6814,8 @@ static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw,
     wined3d_device_incref(ddraw->wined3d_device);
 
     /* Render to the back buffer */
-    hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
-    if (FAILED(hr))
+    if (FAILED(hr = wined3d_device_set_rendertarget_view(ddraw->wined3d_device,
+            0, ddraw_surface_get_rendertarget_view(target), TRUE)))
     {
         ERR("Failed to set render target, hr %#x.\n", hr);
         ddraw_handle_table_destroy(&device->handle_table);
index 4109d7a..c645aed 100644 (file)
@@ -45,12 +45,27 @@ static void _dump_D3DEXECUTEBUFFERDESC(const D3DEXECUTEBUFFERDESC *lpDesc) {
     TRACE("lpData       : %p\n", lpDesc->lpData);
 }
 
+static void transform_vertex(D3DTLVERTEX *dst, const D3DMATRIX *mat,
+        const D3DVIEWPORT *vp, float x, float y, float z)
+{
+    dst->u1.sx = (x * mat->_11) + (y * mat->_21) + (z * mat->_31) + mat->_41;
+    dst->u2.sy = (x * mat->_12) + (y * mat->_22) + (z * mat->_32) + mat->_42;
+    dst->u3.sz = (x * mat->_13) + (y * mat->_23) + (z * mat->_33) + mat->_43;
+    dst->u4.rhw = (x * mat->_14) + (y * mat->_24) + (z * mat->_34) + mat->_44;
+
+    dst->u1.sx = dst->u1.sx / dst->u4.rhw * vp->dvScaleX + vp->dwX + vp->dwWidth / 2;
+    dst->u2.sy = -dst->u2.sy / dst->u4.rhw * vp->dvScaleY + vp->dwY + vp->dwHeight / 2;
+    dst->u3.sz /= dst->u4.rhw;
+    dst->u4.rhw = 1.0f / dst->u4.rhw;
+}
+
 HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
         struct d3d_device *device, struct d3d_viewport *viewport)
 {
     DWORD vs = buffer->data.dwVertexOffset;
     DWORD is = buffer->data.dwInstructionOffset;
     char *instr = (char *)buffer->desc.lpData + is;
+    unsigned int i;
 
     if (viewport->active_device != device)
     {
@@ -87,8 +102,8 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
                instr += count * size;
            } break;
 
-           case D3DOP_TRIANGLE: {
-                DWORD i;
+            case D3DOP_TRIANGLE:
+            {
                 D3DTLVERTEX *tl_vx = buffer->vertex_data;
                TRACE("TRIANGLE         (%d)\n", count);
 
@@ -139,10 +154,8 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
                instr += count * size;
                break;
 
-           case D3DOP_MATRIXMULTIPLY: {
-                DWORD  i;
-               TRACE("MATRIXMULTIPLY   (%d)\n", count);
-               
+            case D3DOP_MATRIXMULTIPLY:
+                TRACE("MATRIXMULTIPLY   (%d)\n", count);
                 for (i = 0; i < count; ++i)
                 {
                     D3DMATRIXMULTIPLY *ci = (D3DMATRIXMULTIPLY *)instr;
@@ -164,13 +177,11 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
                     }
 
                     instr += size;
-               }
-           } break;
+                }
+                break;
 
-           case D3DOP_STATETRANSFORM: {
-                DWORD i;
-               TRACE("STATETRANSFORM   (%d)\n", count);
-               
+            case D3DOP_STATETRANSFORM:
+                TRACE("STATETRANSFORM   (%d)\n", count);
                 for (i = 0; i < count; ++i)
                 {
                     D3DSTATE *ci = (D3DSTATE *)instr;
@@ -195,97 +206,42 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
 
                     instr += size;
                 }
-           } break;
-
-           case D3DOP_STATELIGHT: {
-                DWORD i;
-               TRACE("STATELIGHT       (%d)\n", count);
+                break;
 
+            case D3DOP_STATELIGHT:
+                TRACE("STATELIGHT       (%d)\n", count);
                 for (i = 0; i < count; ++i)
                 {
                     D3DSTATE *ci = (D3DSTATE *)instr;
 
-                   TRACE("(%08x,%08x)\n", ci->u1.dlstLightStateType, ci->u2.dwArg[0]);
-
-                   if (!ci->u1.dlstLightStateType || (ci->u1.dlstLightStateType > D3DLIGHTSTATE_COLORVERTEX))
-                       ERR("Unexpected Light State Type %d\n", ci->u1.dlstLightStateType);
-                    else if (ci->u1.dlstLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
-                    {
-                        struct d3d_material *m;
-
-                        m = ddraw_get_object(&device->handle_table, ci->u2.dwArg[0] - 1, DDRAW_HANDLE_MATERIAL);
-                        if (!m)
-                            ERR("Invalid material handle %#x.\n", ci->u2.dwArg[0]);
-                        else
-                            material_activate(m);
-                    }
-                    else if (ci->u1.dlstLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
-                    {
-                       switch (ci->u2.dwArg[0]) {
-                           case D3DCOLOR_MONO:
-                               ERR("DDCOLOR_MONO should not happen!\n");
-                               break;
-                           case D3DCOLOR_RGB:
-                               /* We are already in this mode */
-                               break;
-                           default:
-                               ERR("Unknown color model!\n");
-                       }
-                   } else {
-                       D3DRENDERSTATETYPE rs = 0;
-                       switch (ci->u1.dlstLightStateType) {
-
-                           case D3DLIGHTSTATE_AMBIENT:       /* 2 */
-                               rs = D3DRENDERSTATE_AMBIENT;
-                               break;
-                           case D3DLIGHTSTATE_FOGMODE:       /* 4 */
-                               rs = D3DRENDERSTATE_FOGVERTEXMODE;
-                               break;
-                           case D3DLIGHTSTATE_FOGSTART:      /* 5 */
-                               rs = D3DRENDERSTATE_FOGSTART;
-                               break;
-                           case D3DLIGHTSTATE_FOGEND:        /* 6 */
-                               rs = D3DRENDERSTATE_FOGEND;
-                               break;
-                           case D3DLIGHTSTATE_FOGDENSITY:    /* 7 */
-                               rs = D3DRENDERSTATE_FOGDENSITY;
-                               break;
-                           case D3DLIGHTSTATE_COLORVERTEX:   /* 8 */
-                               rs = D3DRENDERSTATE_COLORVERTEX;
-                               break;
-                           default:
-                               break;
-                       }
-
-                        IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, rs, ci->u2.dwArg[0]);
-                   }
-
-                   instr += size;
-               }
-           } break;
+                    if (FAILED(IDirect3DDevice3_SetLightState(&device->IDirect3DDevice3_iface,
+                            ci->u1.dlstLightStateType, ci->u2.dwArg[0])))
+                        WARN("Failed to set light state.\n");
 
-           case D3DOP_STATERENDER: {
-                DWORD i;
-                IDirect3DDevice2 *d3d_device2 = &device->IDirect3DDevice2_iface;
-               TRACE("STATERENDER      (%d)\n", count);
+                    instr += size;
+                }
+                break;
 
+            case D3DOP_STATERENDER:
+                TRACE("STATERENDER      (%d)\n", count);
                 for (i = 0; i < count; ++i)
                 {
                     D3DSTATE *ci = (D3DSTATE *)instr;
 
-                    IDirect3DDevice2_SetRenderState(d3d_device2, ci->u1.drstRenderStateType, ci->u2.dwArg[0]);
+                    if (FAILED(IDirect3DDevice3_SetRenderState(&device->IDirect3DDevice3_iface,
+                            ci->u1.drstRenderStateType, ci->u2.dwArg[0])))
+                        WARN("Failed to set render state.\n");
 
-                   instr += size;
-               }
-           } break;
+                    instr += size;
+                }
+                break;
 
             case D3DOP_PROCESSVERTICES:
             {
-                /* TODO: Share code with IDirect3DVertexBuffer::ProcessVertices and / or
-                 * IWineD3DDevice::ProcessVertices
-                 */
-                DWORD i;
-                D3DMATRIX view_mat, world_mat, proj_mat;
+                /* TODO: Share code with d3d_vertex_buffer7_ProcessVertices()
+                 * and / or wined3d_device_process_vertices(). */
+                D3DMATRIX view_mat, world_mat, proj_mat, mat;
+
                 TRACE("PROCESSVERTICES  (%d)\n", count);
 
                 /* Get the transform and world matrix */
@@ -297,157 +253,91 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
                 wined3d_device_get_transform(device->wined3d_device,
                         WINED3D_TS_WORLD_MATRIX(0), (struct wined3d_matrix *)&world_mat);
 
-                for (i = 0; i < count; ++i)
+                if (TRACE_ON(ddraw))
                 {
-                    D3DPROCESSVERTICES *ci = (D3DPROCESSVERTICES *)instr;
-
-                    TRACE("  Start : %d Dest : %d Count : %d\n",
-                         ci->wStart, ci->wDest, ci->dwCount);
-                   TRACE("  Flags : ");
-                    if (TRACE_ON(ddraw))
-                    {
-                       if (ci->dwFlags & D3DPROCESSVERTICES_COPY)
-                           TRACE("COPY ");
-                       if (ci->dwFlags & D3DPROCESSVERTICES_NOCOLOR)
-                           TRACE("NOCOLOR ");
-                       if (ci->dwFlags == D3DPROCESSVERTICES_OPMASK)
-                           TRACE("OPMASK ");
-                       if (ci->dwFlags & D3DPROCESSVERTICES_TRANSFORM)
-                           TRACE("TRANSFORM ");
-                       if (ci->dwFlags == D3DPROCESSVERTICES_TRANSFORMLIGHT)
-                           TRACE("TRANSFORMLIGHT ");
-                       if (ci->dwFlags & D3DPROCESSVERTICES_UPDATEEXTENTS)
-                           TRACE("UPDATEEXTENTS ");
-                       TRACE("\n");
-                   }
-
-                   /* This is where doing Direct3D on top on OpenGL is quite difficult.
-                      This method transforms a set of vertices using the CURRENT state
-                      (lighting, projection, ...) but does not rasterize them.
-                      They will only be put on screen later (with the POINT / LINE and
-                      TRIANGLE op-codes). The problem is that you can have a triangle
-                      with each point having been transformed using another state...
-
-                      In this implementation, I will emulate only ONE thing : each
-                      vertex can have its own "WORLD" transformation (this is used in the
-                      TWIST.EXE demo of the 5.2 SDK). I suppose that all vertices of the
-                      execute buffer use the same state.
-
-                      If I find applications that change other states, I will try to do a
-                      more 'fine-tuned' state emulation (but I may become quite tricky if
-                      it changes a light position in the middle of a triangle).
-
-                      In this case, a 'direct' approach (i.e. without using OpenGL, but
-                      writing our own 3D rasterizer) would be easier. */
-
-                   /* The current method (with the hypothesis that only the WORLD matrix
-                      will change between two points) is like this :
-                      - I transform 'manually' all the vertices with the current WORLD
-                        matrix and store them in the vertex buffer
-                      - during the rasterization phase, the WORLD matrix will be set to
-                        the Identity matrix */
-
-                   /* Enough for the moment */
-                   if (ci->dwFlags == D3DPROCESSVERTICES_TRANSFORMLIGHT) {
-                       unsigned int nb;
-                        D3DVERTEX *src = ((D3DVERTEX *)((char *)buffer->desc.lpData + vs)) + ci->wStart;
-                        D3DTLVERTEX *dst = ((D3DTLVERTEX *)buffer->vertex_data) + ci->wDest;
-                        D3DVIEWPORT *Viewport = &viewport->viewports.vp1;
-                       D3DMATRIX mat;
-                       
-                        if (TRACE_ON(ddraw))
-                        {
-                           TRACE("  Projection Matrix : (%p)\n", &proj_mat);
-                           dump_D3DMATRIX(&proj_mat);
-                           TRACE("  View       Matrix : (%p)\n", &view_mat);
-                           dump_D3DMATRIX(&view_mat);
-                           TRACE("  World Matrix : (%p)\n", &world_mat);
-                           dump_D3DMATRIX(&world_mat);
-                       }
-
-                        multiply_matrix(&mat,&view_mat,&world_mat);
-                        multiply_matrix(&mat,&proj_mat,&mat);
-
-                       for (nb = 0; nb < ci->dwCount; nb++) {
-                           /* No lighting yet */
-                           dst->u5.color = 0xFFFFFFFF; /* Opaque white */
-                           dst->u6.specular = 0xFF000000; /* No specular and no fog factor */
+                    TRACE("  Projection Matrix:\n");
+                    dump_D3DMATRIX(&proj_mat);
+                    TRACE("  View Matrix:\n");
+                    dump_D3DMATRIX(&view_mat);
+                    TRACE("  World Matrix:\n");
+                    dump_D3DMATRIX(&world_mat);
+                }
 
-                           dst->u7.tu  = src->u7.tu;
-                           dst->u8.tv  = src->u8.tv;
+                multiply_matrix(&mat, &view_mat, &world_mat);
+                multiply_matrix(&mat, &proj_mat, &mat);
 
-                            dst->u1.sx = (src->u1.x * mat._11) + (src->u2.y * mat._21) + (src->u3.z * mat._31) + mat._41;
-                            dst->u2.sy = (src->u1.x * mat._12) + (src->u2.y * mat._22) + (src->u3.z * mat._32) + mat._42;
-                            dst->u3.sz = (src->u1.x * mat._13) + (src->u2.y * mat._23) + (src->u3.z * mat._33) + mat._43;
-                            dst->u4.rhw = (src->u1.x * mat._14) + (src->u2.y * mat._24) + (src->u3.z * mat._34) + mat._44;
+                for (i = 0; i < count; ++i)
+                {
+                    D3DPROCESSVERTICES *ci = (D3DPROCESSVERTICES *)instr;
+                    D3DTLVERTEX *dst = (D3DTLVERTEX *)buffer->vertex_data + ci->wDest;
+                    DWORD op = ci->dwFlags & D3DPROCESSVERTICES_OPMASK;
 
-                           dst->u1.sx = dst->u1.sx / dst->u4.rhw * Viewport->dvScaleX
-                                      + Viewport->dwX + Viewport->dwWidth / 2;
-                           dst->u2.sy = (-dst->u2.sy) / dst->u4.rhw * Viewport->dvScaleY
-                                      + Viewport->dwY + Viewport->dwHeight / 2;
-                           dst->u3.sz /= dst->u4.rhw;
-                           dst->u4.rhw = 1 / dst->u4.rhw;
+                    TRACE("  start %u, dest %u, count %u, flags %#x.\n",
+                            ci->wStart, ci->wDest, ci->dwCount, ci->dwFlags);
 
-                           src++;
-                           dst++;
+                    if (ci->dwFlags & D3DPROCESSVERTICES_UPDATEEXTENTS)
+                        FIXME("D3DPROCESSVERTICES_UPDATEEXTENTS not implemented.\n");
+                    if (ci->dwFlags & D3DPROCESSVERTICES_NOCOLOR)
+                        FIXME("D3DPROCESSVERTICES_NOCOLOR not implemented.\n");
 
-                       }
-                   } else if (ci->dwFlags == D3DPROCESSVERTICES_TRANSFORM) {
-                       unsigned int nb;
-                        D3DLVERTEX *src = ((D3DLVERTEX *)((char *)buffer->desc.lpData + vs)) + ci->wStart;
-                        D3DTLVERTEX *dst = ((D3DTLVERTEX *)buffer->vertex_data) + ci->wDest;
-                        D3DVIEWPORT *Viewport = &viewport->viewports.vp1;
-                       D3DMATRIX mat;
-                       
-                        if (TRACE_ON(ddraw))
+                    switch (op)
+                    {
+                        case D3DPROCESSVERTICES_TRANSFORMLIGHT:
                         {
-                           TRACE("  Projection Matrix : (%p)\n", &proj_mat);
-                           dump_D3DMATRIX(&proj_mat);
-                           TRACE("  View       Matrix : (%p)\n",&view_mat);
-                           dump_D3DMATRIX(&view_mat);
-                           TRACE("  World Matrix : (%p)\n", &world_mat);
-                           dump_D3DMATRIX(&world_mat);
-                       }
-
-                       multiply_matrix(&mat,&view_mat,&world_mat);
-                       multiply_matrix(&mat,&proj_mat,&mat);
-
-                       for (nb = 0; nb < ci->dwCount; nb++) {
-                           dst->u5.color = src->u4.color;
-                           dst->u6.specular = src->u5.specular;
-                           dst->u7.tu = src->u6.tu;
-                           dst->u8.tv = src->u7.tv;
+                            const D3DVERTEX *src = (D3DVERTEX *)((char *)buffer->desc.lpData + vs) + ci->wStart;
+                            unsigned int vtx_idx;
+                            static unsigned int once;
+
+                            if (!once++)
+                                FIXME("Lighting not implemented.\n");
+
+                            for (vtx_idx = 0; vtx_idx < ci->dwCount; ++vtx_idx)
+                            {
+                                transform_vertex(&dst[vtx_idx], &mat, &viewport->viewports.vp1,
+                                        src[vtx_idx].u1.x, src[vtx_idx].u2.y, src[vtx_idx].u3.z);
+                                /* No lighting yet */
+                                dst[vtx_idx].u5.color = 0xffffffff; /* Opaque white */
+                                dst[vtx_idx].u6.specular = 0xff000000; /* No specular and no fog factor */
+                                dst[vtx_idx].u7.tu = src[vtx_idx].u7.tu;
+                                dst[vtx_idx].u8.tv = src[vtx_idx].u8.tv;
+                            }
+                            break;
+                        }
 
-                            dst->u1.sx = (src->u1.x * mat._11) + (src->u2.y * mat._21) + (src->u3.z * mat._31) + mat._41;
-                            dst->u2.sy = (src->u1.x * mat._12) + (src->u2.y * mat._22) + (src->u3.z * mat._32) + mat._42;
-                            dst->u3.sz = (src->u1.x * mat._13) + (src->u2.y * mat._23) + (src->u3.z * mat._33) + mat._43;
-                            dst->u4.rhw = (src->u1.x * mat._14) + (src->u2.y * mat._24) + (src->u3.z * mat._34) + mat._44;
+                        case D3DPROCESSVERTICES_TRANSFORM:
+                        {
+                            const D3DLVERTEX *src = (D3DLVERTEX *)((char *)buffer->desc.lpData + vs) + ci->wStart;
+                            unsigned int vtx_idx;
+
+                            for (vtx_idx = 0; vtx_idx < ci->dwCount; ++vtx_idx)
+                            {
+                                transform_vertex(&dst[vtx_idx], &mat, &viewport->viewports.vp1,
+                                        src[vtx_idx].u1.x, src[vtx_idx].u2.y, src[vtx_idx].u3.z);
+                                dst[vtx_idx].u5.color = src[vtx_idx].u4.color;
+                                dst[vtx_idx].u6.specular = src[vtx_idx].u5.specular;
+                                dst[vtx_idx].u7.tu = src[vtx_idx].u6.tu;
+                                dst[vtx_idx].u8.tv = src[vtx_idx].u7.tv;
+                            }
+                            break;
+                        }
 
-                           dst->u1.sx = dst->u1.sx / dst->u4.rhw * Viewport->dvScaleX
-                                      + Viewport->dwX + Viewport->dwWidth / 2;
-                           dst->u2.sy = (-dst->u2.sy) / dst->u4.rhw * Viewport->dvScaleY
-                                      + Viewport->dwY + Viewport->dwHeight / 2;
+                        case D3DPROCESSVERTICES_COPY:
+                        {
+                            const D3DTLVERTEX *src = (D3DTLVERTEX *)((char *)buffer->desc.lpData + vs) + ci->wStart;
 
-                           dst->u3.sz /= dst->u4.rhw;
-                           dst->u4.rhw = 1 / dst->u4.rhw;
+                            memcpy(dst, src, ci->dwCount * sizeof(*dst));
+                            break;
+                        }
 
-                           src++;
-                           dst++;
-                       }
+                        default:
+                            FIXME("Unhandled vertex processing op %#x.\n", op);
+                            break;
                     }
-                    else if (ci->dwFlags == D3DPROCESSVERTICES_COPY)
-                    {
-                        D3DTLVERTEX *src = ((D3DTLVERTEX *)((char *)buffer->desc.lpData + vs)) + ci->wStart;
-                        D3DTLVERTEX *dst = ((D3DTLVERTEX *)buffer->vertex_data) + ci->wDest;
-
-                       memcpy(dst, src, ci->dwCount * sizeof(D3DTLVERTEX));
-                   } else {
-                       ERR("Unhandled vertex processing flag %#x.\n", ci->dwFlags);
-                   }
 
-                   instr += size;
-               }
-           } break;
+                    instr += size;
+                }
+                break;
+            }
 
            case D3DOP_TEXTURELOAD: {
                WARN("TEXTURELOAD-s    (%d)\n", count);
@@ -463,10 +353,8 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
                goto end_of_buffer;
            } break;
 
-           case D3DOP_BRANCHFORWARD: {
-                DWORD i;
-               TRACE("BRANCHFORWARD    (%d)\n", count);
-
+            case D3DOP_BRANCHFORWARD:
+                TRACE("BRANCHFORWARD    (%d)\n", count);
                 for (i = 0; i < count; ++i)
                 {
                     D3DBRANCH *ci = (D3DBRANCH *)instr;
@@ -492,8 +380,8 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
                    }
 
                    instr += size;
-               }
-           } break;
+                }
+                break;
 
            case D3DOP_SPAN: {
                WARN("SPAN-s           (%d)\n", count);
@@ -501,16 +389,14 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
                instr += count * size;
            } break;
 
-           case D3DOP_SETSTATUS: {
-                DWORD i;
-               TRACE("SETSTATUS        (%d)\n", count);
-
+            case D3DOP_SETSTATUS:
+                TRACE("SETSTATUS        (%d)\n", count);
                 for (i = 0; i < count; ++i)
                 {
                     buffer->data.dsStatus = *(D3DSTATUS *)instr;
                     instr += size;
                 }
-           } break;
+                break;
 
            default:
                ERR("Unhandled OpCode %d !!!\n",current->bOpcode);
@@ -529,45 +415,24 @@ static inline struct d3d_execute_buffer *impl_from_IDirect3DExecuteBuffer(IDirec
     return CONTAINING_RECORD(iface, struct d3d_execute_buffer, IDirect3DExecuteBuffer_iface);
 }
 
-/*****************************************************************************
- * IDirect3DExecuteBuffer::QueryInterface
- *
- * Well, a usual QueryInterface function. Don't know fur sure which
- * interfaces it can Query.
- *
- * Params:
- *  riid: The interface ID queried for
- *  obj: Address to return the interface pointer at
- *
- * Returns:
- *  D3D_OK in case of a success (S_OK? Think it's the same)
- *  OLE_E_ENUM_NOMORE if the interface wasn't found.
- *   (E_NOINTERFACE?? Don't know what I really need)
- *
- *****************************************************************************/
-static HRESULT WINAPI d3d_execute_buffer_QueryInterface(IDirect3DExecuteBuffer *iface, REFIID riid, void **obj)
+static HRESULT WINAPI d3d_execute_buffer_QueryInterface(IDirect3DExecuteBuffer *iface, REFIID iid, void **out)
 {
-    TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
+    TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
 
-    *obj = NULL;
-
-    if ( IsEqualGUID( &IID_IUnknown,  riid ) ) {
-        IDirect3DExecuteBuffer_AddRef(iface);
-       *obj = iface;
-       TRACE("  Creating IUnknown interface at %p.\n", *obj);
-       return S_OK;
-    }
-    if ( IsEqualGUID( &IID_IDirect3DExecuteBuffer, riid ) ) {
+    if (IsEqualGUID(&IID_IDirect3DExecuteBuffer, iid)
+            || IsEqualGUID(&IID_IUnknown, iid))
+    {
         IDirect3DExecuteBuffer_AddRef(iface);
-        *obj = iface;
-       TRACE("  Creating IDirect3DExecuteBuffer interface %p\n", *obj);
-       return S_OK;
+        *out = iface;
+        return S_OK;
     }
-    FIXME("(%p): interface for IID %s NOT found!\n", iface, debugstr_guid(riid));
+
+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
+
+    *out = NULL;
     return E_NOINTERFACE;
 }
 
-
 /*****************************************************************************
  * IDirect3DExecuteBuffer::AddRef
  *
index fca2706..4f5570b 100644 (file)
@@ -170,6 +170,10 @@ static HRESULT WINAPI ddraw_palette_SetEntries(IDirectDrawPalette *iface,
 
     wined3d_mutex_lock();
     hr = wined3d_palette_set_entries(palette->wineD3DPalette, flags, start, count, entries);
+
+    if (SUCCEEDED(hr) && palette->flags & DDPCAPS_PRIMARYSURFACE)
+        ddraw_surface_update_frontbuffer(palette->ddraw->primary, NULL, FALSE);
+
     wined3d_mutex_unlock();
 
     return hr;
index 4e465d3..49db2aa 100644 (file)
@@ -35,7 +35,7 @@ static inline struct ddraw_surface *impl_from_IDirectDrawGammaControl(IDirectDra
  * applications from drawing to the screen while we've locked the frontbuffer.
  * We'd like to do this in wined3d instead, but for that to work wined3d needs
  * to support windowless rendering first. */
-static HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface, const RECT *rect, BOOL read)
+HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface, const RECT *rect, BOOL read)
 {
     HDC surface_dc, screen_dc;
     int x, y, w, h;
@@ -317,6 +317,8 @@ static void ddraw_surface_add_iface(struct ddraw_surface *surface)
         if (surface->ifaceToRelease)
             IUnknown_AddRef(surface->ifaceToRelease);
         wined3d_mutex_lock();
+        if (surface->wined3d_rtv)
+            wined3d_rendertarget_view_incref(surface->wined3d_rtv);
         if (surface->wined3d_surface)
             wined3d_surface_incref(surface->wined3d_surface);
         if (surface->wined3d_texture)
@@ -442,6 +444,47 @@ static ULONG WINAPI d3d_texture1_AddRef(IDirect3DTexture *iface)
     return IUnknown_AddRef(surface->texture_outer);
 }
 
+static HRESULT ddraw_surface_set_palette(struct ddraw_surface *surface, IDirectDrawPalette *palette)
+{
+    struct ddraw_palette *palette_impl = unsafe_impl_from_IDirectDrawPalette(palette);
+    struct ddraw_palette *prev;
+
+    TRACE("iface %p, palette %p.\n", surface, palette);
+
+    if (palette_impl && palette_impl->flags & DDPCAPS_ALPHA
+            && !(surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE))
+    {
+        WARN("Alpha palette set on non-texture surface, returning DDERR_INVALIDSURFACETYPE.\n");
+        return DDERR_INVALIDSURFACETYPE;
+    }
+
+    if (!format_is_paletteindexed(&surface->surface_desc.u4.ddpfPixelFormat))
+        return DDERR_INVALIDPIXELFORMAT;
+
+    wined3d_mutex_lock();
+
+    prev = surface->palette;
+    if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
+    {
+        if (prev)
+            prev->flags &= ~DDPCAPS_PRIMARYSURFACE;
+        if (palette_impl)
+            palette_impl->flags |= DDPCAPS_PRIMARYSURFACE;
+        wined3d_swapchain_set_palette(surface->ddraw->wined3d_swapchain,
+                palette_impl ? palette_impl->wineD3DPalette : NULL);
+        ddraw_surface_update_frontbuffer(surface, NULL, FALSE);
+    }
+    if (palette_impl)
+        IDirectDrawPalette_AddRef(&palette_impl->IDirectDrawPalette_iface);
+    if (prev)
+        IDirectDrawPalette_Release(&prev->IDirectDrawPalette_iface);
+    surface->palette = palette_impl;
+
+    wined3d_mutex_unlock();
+
+    return DD_OK;
+}
+
 static void ddraw_surface_cleanup(struct ddraw_surface *surface)
 {
     struct ddraw_surface *surf;
@@ -451,7 +494,7 @@ static void ddraw_surface_cleanup(struct ddraw_surface *surface)
 
     /* The refcount test shows that the palette is detached when the surface
      * is destroyed. */
-    IDirectDrawSurface7_SetPalette(&surface->IDirectDrawSurface7_iface, NULL);
+    ddraw_surface_set_palette(surface, NULL);
 
     /* Loop through all complex attached surfaces and destroy them.
      *
@@ -480,6 +523,8 @@ static void ddraw_surface_cleanup(struct ddraw_surface *surface)
                 surface, surface->ref7, surface->ref4, surface->ref3, surface->ref2, surface->ref1);
     }
 
+    if (surface->wined3d_rtv)
+        wined3d_rendertarget_view_decref(surface->wined3d_rtv);
     if (surface->wined3d_texture)
         wined3d_texture_decref(surface->wined3d_texture);
     if (surface->wined3d_surface)
@@ -965,12 +1010,9 @@ static HRESULT surface_lock(struct ddraw_surface *This,
             SetRect(&This->ddraw->primary_lock, 0, 0, This->surface_desc.dwWidth, This->surface_desc.dwHeight);
     }
 
-    /* Override the memory area. The pitch should be set already. Strangely windows
-     * does not set the LPSURFACE flag on locked surfaces !?!.
-     * DDSD->dwFlags |= DDSD_LPSURFACE;
-     */
-    This->surface_desc.lpSurface = map_desc.data;
+    /* Windows does not set DDSD_LPSURFACE on locked surfaces. */
     DD_STRUCT_COPY_BYSIZE(DDSD,&(This->surface_desc));
+    DDSD->lpSurface = map_desc.data;
 
     TRACE("locked surface returning description :\n");
     if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(DDSD);
@@ -1115,12 +1157,8 @@ static HRESULT WINAPI ddraw_surface7_Unlock(IDirectDrawSurface7 *iface, RECT *pR
 
     wined3d_mutex_lock();
     hr = wined3d_surface_unmap(surface->wined3d_surface);
-    if (SUCCEEDED(hr))
-    {
-        if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
-            hr = ddraw_surface_update_frontbuffer(surface, &surface->ddraw->primary_lock, FALSE);
-        surface->surface_desc.lpSurface = NULL;
-    }
+    if (SUCCEEDED(hr) && surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
+        hr = ddraw_surface_update_frontbuffer(surface, &surface->ddraw->primary_lock, FALSE);
     wined3d_mutex_unlock();
 
     return hr;
@@ -1169,11 +1207,12 @@ static HRESULT WINAPI ddraw_surface7_Flip(IDirectDrawSurface7 *iface, IDirectDra
 {
     struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface7(iface);
     struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface7(src);
+    struct wined3d_rendertarget_view *tmp_rtv, *src_rtv, *rtv;
     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;
+    struct wined3d_surface *tmp;
     HRESULT hr;
 
     TRACE("iface %p, src %p, flags %#x.\n", iface, src, flags);
@@ -1181,11 +1220,15 @@ static HRESULT WINAPI ddraw_surface7_Flip(IDirectDrawSurface7 *iface, IDirectDra
     if (src == iface || !(dst_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_OVERLAY)))
         return DDERR_NOTFLIPPABLE;
 
+    if (IDirectDrawSurface7_IsLost(iface) == DDERR_SURFACELOST)
+        return DDERR_SURFACELOST;
+
     wined3d_mutex_lock();
 
+    tmp_rtv = ddraw_surface_get_rendertarget_view(dst_impl);
     tmp = dst_impl->wined3d_surface;
     texture = dst_impl->wined3d_texture;
-    rt = wined3d_device_get_render_target(dst_impl->ddraw->wined3d_device, 0);
+    rtv = wined3d_device_get_rendertarget_view(dst_impl->ddraw->wined3d_device, 0);
     ddraw_texture = wined3d_texture_get_parent(dst_impl->wined3d_texture);
 
     if (src_impl)
@@ -1207,8 +1250,11 @@ static HRESULT WINAPI ddraw_surface7_Flip(IDirectDrawSurface7 *iface, IDirectDra
             }
         }
 
-        if (rt == dst_impl->wined3d_surface)
-            wined3d_device_set_render_target(dst_impl->ddraw->wined3d_device, 0, src_impl->wined3d_surface, FALSE);
+        src_rtv = ddraw_surface_get_rendertarget_view(src_impl);
+        if (rtv == dst_impl->wined3d_rtv)
+            wined3d_device_set_rendertarget_view(dst_impl->ddraw->wined3d_device, 0, src_rtv, FALSE);
+        wined3d_rendertarget_view_set_parent(src_rtv, dst_impl);
+        dst_impl->wined3d_rtv = src_rtv;
         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);
@@ -1234,8 +1280,11 @@ static HRESULT WINAPI ddraw_surface7_Flip(IDirectDrawSurface7 *iface, IDirectDra
             }
 
             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);
+            src_rtv = ddraw_surface_get_rendertarget_view(src_impl);
+            if (rtv == dst_impl->wined3d_rtv)
+                wined3d_device_set_rendertarget_view(dst_impl->ddraw->wined3d_device, 0, src_rtv, FALSE);
+            wined3d_rendertarget_view_set_parent(src_rtv, dst_impl);
+            dst_impl->wined3d_rtv = src_rtv;
             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);
@@ -1248,8 +1297,10 @@ static HRESULT WINAPI ddraw_surface7_Flip(IDirectDrawSurface7 *iface, IDirectDra
 
     /* 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);
+    if (rtv == src_impl->wined3d_rtv)
+        wined3d_device_set_rendertarget_view(dst_impl->ddraw->wined3d_device, 0, tmp_rtv, FALSE);
+    wined3d_rendertarget_view_set_parent(tmp_rtv, src_impl);
+    src_impl->wined3d_rtv = tmp_rtv;
     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);
@@ -1968,6 +2019,22 @@ static HRESULT WINAPI ddraw_surface7_GetDC(IDirectDrawSurface7 *iface, HDC *hdc)
         hr = ddraw_surface_update_frontbuffer(surface, NULL, TRUE);
     if (SUCCEEDED(hr))
         hr = wined3d_surface_getdc(surface->wined3d_surface, hdc);
+
+    if (SUCCEEDED(hr) && format_is_paletteindexed(&surface->surface_desc.u4.ddpfPixelFormat))
+    {
+        const struct ddraw_palette *palette;
+
+        if (surface->palette)
+            palette = surface->palette;
+        else if (surface->ddraw->primary)
+            palette = surface->ddraw->primary->palette;
+        else
+            palette = NULL;
+
+        if (palette)
+            wined3d_palette_apply_to_dc(palette->wineD3DPalette, *hdc);
+    }
+
     wined3d_mutex_unlock();
     switch(hr)
     {
@@ -2164,63 +2231,63 @@ static HRESULT WINAPI ddraw_surface1_GetCaps(IDirectDrawSurface *iface, DDSCAPS
     return hr;
 }
 
-/*****************************************************************************
- * IDirectDrawSurface7::SetPriority
- *
- * Sets a texture priority for managed textures.
- *
- * Params:
- *  Priority: The new priority
- *
- * Returns:
- *  DD_OK on success
- *  For more details, see IWineD3DSurface::SetPriority
- *
- *****************************************************************************/
-static HRESULT WINAPI ddraw_surface7_SetPriority(IDirectDrawSurface7 *iface, DWORD Priority)
+static HRESULT WINAPI ddraw_surface7_SetPriority(IDirectDrawSurface7 *iface, DWORD priority)
 {
     struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
+    DWORD managed = DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE;
     HRESULT hr;
+    struct wined3d_resource *resource;
 
-    TRACE("iface %p, priority %u.\n", iface, Priority);
+    TRACE("iface %p, priority %u.\n", iface, priority);
 
     wined3d_mutex_lock();
-    hr = wined3d_surface_set_priority(surface->wined3d_surface, Priority);
+    /* No need to check for offscreen plain surfaces or mipmap sublevels. SetPriority
+     * calls on such surfaces segfault on Windows. */
+    if (!(surface->surface_desc.ddsCaps.dwCaps2 & managed))
+    {
+        WARN("Called on non-managed texture returning DDERR_INVALIDPARAMS.\n");
+        hr = DDERR_INVALIDPARAMS;
+    }
+    else
+    {
+        resource = wined3d_texture_get_resource(surface->wined3d_texture);
+        wined3d_resource_set_priority(resource, priority);
+        hr = DD_OK;
+    }
     wined3d_mutex_unlock();
 
     return hr;
 }
 
-/*****************************************************************************
- * IDirectDrawSurface7::GetPriority
- *
- * Returns the surface's priority
- *
- * Params:
- *  Priority: Address of a variable to write the priority to
- *
- * Returns:
- *  D3D_OK on success
- *  DDERR_INVALIDPARAMS if Priority == NULL
- *  For more details, see IWineD3DSurface::GetPriority
- *
- *****************************************************************************/
-static HRESULT WINAPI ddraw_surface7_GetPriority(IDirectDrawSurface7 *iface, DWORD *Priority)
+static HRESULT WINAPI ddraw_surface7_GetPriority(IDirectDrawSurface7 *iface, DWORD *priority)
 {
     struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
+    const struct wined3d_resource *resource;
+    DWORD managed = DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE;
+    HRESULT hr;
 
-    TRACE("iface %p, priority %p.\n", iface, Priority);
+    TRACE("iface %p, priority %p.\n", iface, priority);
 
-    if(!Priority)
+    wined3d_mutex_lock();
+    if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN)
     {
-        return DDERR_INVALIDPARAMS;
+        WARN("Called on offscreenplain surface, returning DDERR_INVALIDOBJECT.\n");
+        hr = DDERR_INVALIDOBJECT;
+    }
+    else if (!(surface->surface_desc.ddsCaps.dwCaps2 & managed) || !surface->wined3d_texture)
+    {
+        WARN("Called on non-managed texture or mipmap sublevel, returning DDERR_INVALIDPARAMS.\n");
+        hr = DDERR_INVALIDPARAMS;
+    }
+    else
+    {
+        resource = wined3d_texture_get_resource(surface->wined3d_texture);
+        *priority = wined3d_resource_get_priority(resource);
+        hr = DD_OK;
     }
-
-    wined3d_mutex_lock();
-    *Priority = wined3d_surface_get_priority(surface->wined3d_surface);
     wined3d_mutex_unlock();
 
-    return DD_OK;
+    return hr;
 }
 
 /*****************************************************************************
@@ -4450,6 +4517,11 @@ static HRESULT WINAPI ddraw_surface7_GetPalette(IDirectDrawSurface7 *iface, IDir
 
     if (!palette)
         return DDERR_INVALIDPARAMS;
+    if (IDirectDrawSurface7_IsLost(iface) == DDERR_SURFACELOST)
+    {
+        WARN("Surface lost, returning DDERR_SURFACELOST.\n");
+        return DDERR_SURFACELOST;
+    }
 
     wined3d_mutex_lock();
     if ((palette_impl = surface->palette))
@@ -4635,42 +4707,18 @@ static HRESULT WINAPI ddraw_surface1_SetColorKey(IDirectDrawSurface *iface, DWOR
 static HRESULT WINAPI ddraw_surface7_SetPalette(IDirectDrawSurface7 *iface, IDirectDrawPalette *palette)
 {
     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, palette);
 
-    if (!(surface->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2
-            | DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8)))
-        return DDERR_INVALIDPIXELFORMAT;
-
     if (surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
         return DDERR_NOTONMIPMAPSUBLEVEL;
-
-    wined3d_mutex_lock();
-
-    prev = surface->palette;
-    if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
+    if (IDirectDrawSurface7_IsLost(iface) == DDERR_SURFACELOST)
     {
-        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);
+        WARN("Surface lost, returning DDERR_SURFACELOST.\n");
+        return DDERR_SURFACELOST;
     }
-    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();
-
-    return DD_OK;
+    return ddraw_surface_set_palette(surface, palette);
 }
 
 static HRESULT WINAPI ddraw_surface4_SetPalette(IDirectDrawSurface4 *iface, IDirectDrawPalette *palette)
@@ -4679,7 +4727,13 @@ static HRESULT WINAPI ddraw_surface4_SetPalette(IDirectDrawSurface4 *iface, IDir
 
     TRACE("iface %p, palette %p.\n", iface, palette);
 
-    return ddraw_surface7_SetPalette(&surface->IDirectDrawSurface7_iface, palette);
+    if (IDirectDrawSurface4_IsLost(iface) == DDERR_SURFACELOST)
+    {
+        WARN("Surface lost, returning DDERR_SURFACELOST.\n");
+        return DDERR_SURFACELOST;
+    }
+
+    return ddraw_surface_set_palette(surface, palette);
 }
 
 static HRESULT WINAPI ddraw_surface3_SetPalette(IDirectDrawSurface3 *iface, IDirectDrawPalette *palette)
@@ -4688,7 +4742,13 @@ static HRESULT WINAPI ddraw_surface3_SetPalette(IDirectDrawSurface3 *iface, IDir
 
     TRACE("iface %p, palette %p.\n", iface, palette);
 
-    return ddraw_surface7_SetPalette(&surface->IDirectDrawSurface7_iface, palette);
+    if (IDirectDrawSurface3_IsLost(iface) == DDERR_SURFACELOST)
+    {
+        WARN("Surface lost, returning DDERR_SURFACELOST.\n");
+        return DDERR_SURFACELOST;
+    }
+
+    return ddraw_surface_set_palette(surface, palette);
 }
 
 static HRESULT WINAPI ddraw_surface2_SetPalette(IDirectDrawSurface2 *iface, IDirectDrawPalette *palette)
@@ -4697,7 +4757,13 @@ static HRESULT WINAPI ddraw_surface2_SetPalette(IDirectDrawSurface2 *iface, IDir
 
     TRACE("iface %p, palette %p.\n", iface, palette);
 
-    return ddraw_surface7_SetPalette(&surface->IDirectDrawSurface7_iface, palette);
+    if (IDirectDrawSurface2_IsLost(iface) == DDERR_SURFACELOST)
+    {
+        WARN("Surface lost, returning DDERR_SURFACELOST.\n");
+        return DDERR_SURFACELOST;
+    }
+
+    return ddraw_surface_set_palette(surface, palette);
 }
 
 static HRESULT WINAPI ddraw_surface1_SetPalette(IDirectDrawSurface *iface, IDirectDrawPalette *palette)
@@ -4706,7 +4772,13 @@ static HRESULT WINAPI ddraw_surface1_SetPalette(IDirectDrawSurface *iface, IDire
 
     TRACE("iface %p, palette %p.\n", iface, palette);
 
-    return ddraw_surface7_SetPalette(&surface->IDirectDrawSurface7_iface, palette);
+    if (IDirectDrawSurface_IsLost(iface) == DDERR_SURFACELOST)
+    {
+        WARN("Surface lost, returning DDERR_SURFACELOST.\n");
+        return DDERR_SURFACELOST;
+    }
+
+    return ddraw_surface_set_palette(surface, palette);
 }
 
 /**********************************************************
@@ -4962,7 +5034,7 @@ static HRESULT WINAPI d3d_texture2_Load(IDirect3DTexture2 *iface, IDirect3DTextu
 
     for (;;)
     {
-        struct wined3d_palette *wined3d_dst_pal, *wined3d_src_pal;
+        struct ddraw_palette *dst_pal, *src_pal;
         DDSURFACEDESC *src_desc, *dst_desc;
 
         TRACE("Copying surface %p to surface %p (mipmap level %d).\n",
@@ -4972,20 +5044,20 @@ static HRESULT WINAPI d3d_texture2_Load(IDirect3DTexture2 *iface, IDirect3DTextu
         dst_surface->surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD;
 
         /* Get the palettes */
-        wined3d_dst_pal = wined3d_surface_get_palette(dst_surface->wined3d_surface);
-        wined3d_src_pal = wined3d_surface_get_palette(src_surface->wined3d_surface);
+        dst_pal = dst_surface->palette;
+        src_pal = src_surface->palette;
 
-        if (wined3d_src_pal)
+        if (src_pal)
         {
             PALETTEENTRY palent[256];
 
-            if (!wined3d_dst_pal)
+            if (!dst_pal)
             {
                 wined3d_mutex_unlock();
                 return DDERR_NOPALETTEATTACHED;
             }
-            wined3d_palette_get_entries(wined3d_src_pal, 0, 0, 256, palent);
-            wined3d_palette_set_entries(wined3d_dst_pal, 0, 0, 256, palent);
+            IDirectDrawPalette_GetEntries(&src_pal->IDirectDrawPalette_iface, 0, 0, 256, palent);
+            IDirectDrawPalette_SetEntries(&dst_pal->IDirectDrawPalette_iface, 0, 0, 256, palent);
         }
 
         /* Copy one surface on the other */
@@ -5851,11 +5923,30 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_
             return DDERR_INVALIDPARAMS;
         }
 
-        if (!(desc->dwFlags & DDSD_PITCH))
+        if (format_is_compressed(&desc->u4.ddpfPixelFormat))
         {
-            WARN("User memory surfaces should explicitly specify the pitch.\n");
-            HeapFree(GetProcessHeap(), 0, texture);
-            return DDERR_INVALIDPARAMS;
+            if (version != 4 && (desc->dwFlags & DDSD_PITCH))
+            {
+                WARN("Pitch specified on a compressed user memory surface.\n");
+                HeapFree(GetProcessHeap(), 0, texture);
+                return DDERR_INVALIDPARAMS;
+            }
+
+            if (!(desc->dwFlags & (DDSD_LINEARSIZE | DDSD_PITCH)))
+            {
+                WARN("Compressed user memory surfaces should explicitly specify the linear size.\n");
+                HeapFree(GetProcessHeap(), 0, texture);
+                return DDERR_INVALIDPARAMS;
+            }
+        }
+        else
+        {
+            if (!(desc->dwFlags & DDSD_PITCH))
+            {
+                WARN("User memory surfaces should explicitly specify the pitch.\n");
+                HeapFree(GetProcessHeap(), 0, texture);
+                return DDERR_INVALIDPARAMS;
+            }
         }
     }
 
@@ -6077,42 +6168,65 @@ HRESULT ddraw_surface_init(struct ddraw_surface *surface, struct ddraw *ddraw, s
     desc->dwHeight = wined3d_desc.height;
     surface->first_attached = surface;
 
-    /* Anno 1602 stores the pitch right after surface creation, so make sure
-     * it's there. TODO: Test other fourcc formats. */
-    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)
+    if (format_is_compressed(&desc->u4.ddpfPixelFormat))
     {
-        surface->surface_desc.dwFlags |= DDSD_LINEARSIZE;
-        if (wined3d_desc.format == WINED3DFMT_DXT1)
-            surface->surface_desc.u1.dwLinearSize = max(4, desc->dwWidth) * max(4, desc->dwHeight) / 2;
+        if (desc->dwFlags & DDSD_LPSURFACE)
+        {
+            if ((desc->dwFlags & DDSD_LINEARSIZE)
+                    && desc->u1.dwLinearSize < wined3d_surface_get_pitch(wined3d_surface) * ((desc->dwHeight + 3) / 4))
+            {
+                WARN("Invalid linear size %u specified.\n", desc->u1.dwLinearSize);
+                return DDERR_INVALIDPARAMS;
+            }
+
+            if (FAILED(hr = wined3d_surface_update_desc(wined3d_surface, wined3d_desc.width,
+                    wined3d_desc.height, wined3d_desc.format, WINED3D_MULTISAMPLE_NONE, 0,
+                    desc->lpSurface, 0)))
+            {
+                ERR("Failed to set surface memory, hr %#x.\n", hr);
+                return hr;
+            }
+
+            desc->dwFlags |= DDSD_LINEARSIZE;
+            desc->dwFlags &= ~(DDSD_LPSURFACE | DDSD_PITCH);
+            desc->u1.dwLinearSize = ~0u;
+        }
         else
-            surface->surface_desc.u1.dwLinearSize = max(4, desc->dwWidth) * max(4, desc->dwHeight);
-    }
-    else if (!(desc->dwFlags & DDSD_LPSURFACE))
-    {
-        desc->dwFlags |= DDSD_PITCH;
-        desc->u1.lPitch = wined3d_surface_get_pitch(wined3d_surface);
+        {
+            desc->dwFlags |= DDSD_LINEARSIZE;
+            desc->dwFlags &= ~DDSD_PITCH;
+            desc->u1.dwLinearSize = wined3d_surface_get_pitch(wined3d_surface) * ((desc->dwHeight + 3) / 4);
+        }
     }
-
-    if (desc->dwFlags & DDSD_LPSURFACE)
+    else
     {
-        if (desc->u1.lPitch < wined3d_surface_get_pitch(wined3d_surface) || desc->u1.lPitch & 3)
+        if (desc->dwFlags & DDSD_LPSURFACE)
         {
-            WARN("Invalid pitch %u specified.\n", desc->u1.lPitch);
-            return DDERR_INVALIDPARAMS;
-        }
+            if (desc->u1.lPitch < wined3d_calculate_format_pitch(ddraw->wined3d, WINED3DADAPTER_DEFAULT,
+                    wined3d_desc.format, wined3d_desc.width) || desc->u1.lPitch & 3)
+            {
+                WARN("Invalid pitch %u specified.\n", desc->u1.lPitch);
+                return DDERR_INVALIDPARAMS;
+            }
+
+            if (FAILED(hr = wined3d_surface_update_desc(wined3d_surface, wined3d_desc.width,
+                    wined3d_desc.height, wined3d_desc.format, WINED3D_MULTISAMPLE_NONE, 0,
+                    desc->lpSurface, desc->u1.lPitch)))
+            {
+                ERR("Failed to set surface memory, hr %#x.\n", hr);
+                return hr;
+            }
 
-        if (FAILED(hr = wined3d_surface_update_desc(wined3d_surface, wined3d_desc.width,
-                wined3d_desc.height, wined3d_desc.format, WINED3D_MULTISAMPLE_NONE, 0,
-                desc->lpSurface, desc->u1.lPitch)))
+            desc->dwFlags &= ~(DDSD_LPSURFACE | DDSD_LINEARSIZE);
+        }
+        else
         {
-            ERR("Failed to set surface memory, hr %#x.\n", hr);
-            return hr;
+            desc->dwFlags |= DDSD_PITCH;
+            desc->dwFlags &= ~DDSD_LINEARSIZE;
+            desc->u1.lPitch = wined3d_surface_get_pitch(wined3d_surface);
         }
-
-        desc->dwFlags &= ~DDSD_LPSURFACE;
     }
+    desc->lpSurface = NULL;
 
     wined3d_surface_incref(wined3d_surface);
     surface->wined3d_surface = wined3d_surface;
@@ -6122,3 +6236,41 @@ HRESULT ddraw_surface_init(struct ddraw_surface *surface, struct ddraw *ddraw, s
 
     return DD_OK;
 }
+
+static void STDMETHODCALLTYPE view_wined3d_object_destroyed(void *parent)
+{
+    struct ddraw_surface *surface = parent;
+
+    /* If the surface reference count drops to zero, we release our reference
+     * to the view, but don't clear the pointer yet, in case e.g. a
+     * GetRenderTarget() call brings the surface back before the view is
+     * actually destroyed. When the view is destroyed, we need to clear the
+     * pointer, or a subsequent surface AddRef() would reference it again.
+     *
+     * This is safe because as long as the view still has a reference to the
+     * texture, the surface is also still alive, and we're called before the
+     * view releases that reference. */
+    surface->wined3d_rtv = NULL;
+}
+
+static const struct wined3d_parent_ops ddraw_view_wined3d_parent_ops =
+{
+    view_wined3d_object_destroyed,
+};
+
+struct wined3d_rendertarget_view *ddraw_surface_get_rendertarget_view(struct ddraw_surface *surface)
+{
+    HRESULT hr;
+
+    if (surface->wined3d_rtv)
+        return surface->wined3d_rtv;
+
+    if (FAILED(hr = wined3d_rendertarget_view_create_from_surface(surface->wined3d_surface,
+            surface, &ddraw_view_wined3d_parent_ops, &surface->wined3d_rtv)))
+    {
+        ERR("Failed to create rendertarget view, hr %#x.\n", hr);
+        return NULL;
+    }
+
+    return surface->wined3d_rtv;
+}
index daf0f6c..ab2600a 100644 (file)
@@ -730,57 +730,35 @@ DDRAW_dump_pixelformat(const DDPIXELFORMAT *pf)
     TRACE("( ");
     DDRAW_dump_pixelformat_flag(pf->dwFlags);
     if (pf->dwFlags & DDPF_FOURCC)
-    {
-        TRACE(", dwFourCC code '%c%c%c%c' (0x%08x) - %d bits per pixel",
+        TRACE(", dwFourCC code '%c%c%c%c' (0x%08x) - %u bits per pixel",
                 (unsigned char)( pf->dwFourCC     &0xff),
                 (unsigned char)((pf->dwFourCC>> 8)&0xff),
                 (unsigned char)((pf->dwFourCC>>16)&0xff),
                 (unsigned char)((pf->dwFourCC>>24)&0xff),
                 pf->dwFourCC,
-                pf->u1.dwYUVBitCount
-        );
-    }
+                pf->u1.dwYUVBitCount);
     if (pf->dwFlags & DDPF_RGB)
     {
-        const char *cmd;
-        TRACE(", RGB bits: %d, ", pf->u1.dwRGBBitCount);
-        switch (pf->u1.dwRGBBitCount)
-        {
-        case 4: cmd = "%1lx"; break;
-        case 8: cmd = "%02lx"; break;
-        case 16: cmd = "%04lx"; break;
-        case 24: cmd = "%06lx"; break;
-        case 32: cmd = "%08lx"; break;
-        default: ERR("Unexpected bit depth!\n"); cmd = "%d"; break;
-        }
-        TRACE(" R "); TRACE(cmd, pf->u2.dwRBitMask);
-        TRACE(" G "); TRACE(cmd, pf->u3.dwGBitMask);
-        TRACE(" B "); TRACE(cmd, pf->u4.dwBBitMask);
+        TRACE(", RGB bits: %u, R 0x%08x G 0x%08x B 0x%08x",
+                pf->u1.dwRGBBitCount,
+                pf->u2.dwRBitMask,
+                pf->u3.dwGBitMask,
+                pf->u4.dwBBitMask);
         if (pf->dwFlags & DDPF_ALPHAPIXELS)
-        {
-            TRACE(" A "); TRACE(cmd, pf->u5.dwRGBAlphaBitMask);
-        }
+            TRACE(" A 0x%08x", pf->u5.dwRGBAlphaBitMask);
         if (pf->dwFlags & DDPF_ZPIXELS)
-        {
-            TRACE(" Z "); TRACE(cmd, pf->u5.dwRGBZBitMask);
-        }
+            TRACE(" Z 0x%08x", pf->u5.dwRGBZBitMask);
     }
     if (pf->dwFlags & DDPF_ZBUFFER)
-    {
-        TRACE(", Z bits : %d", pf->u1.dwZBufferBitDepth);
-    }
+        TRACE(", Z bits: %u", pf->u1.dwZBufferBitDepth);
     if (pf->dwFlags & DDPF_ALPHA)
-    {
-        TRACE(", Alpha bits : %d", pf->u1.dwAlphaBitDepth);
-    }
+        TRACE(", Alpha bits: %u", pf->u1.dwAlphaBitDepth);
     if (pf->dwFlags & DDPF_BUMPDUDV)
-    {
-        const char *cmd = "%08lx";
-        TRACE(", Bump bits: %d, ", pf->u1.dwBumpBitCount);
-        TRACE(" U "); TRACE(cmd, pf->u2.dwBumpDuBitMask);
-        TRACE(" V "); TRACE(cmd, pf->u3.dwBumpDvBitMask);
-        TRACE(" L "); TRACE(cmd, pf->u4.dwBumpLuminanceBitMask);
-    }
+        TRACE(", Bump bits: %u, U 0x%08x V 0x%08x L 0x%08x",
+                pf->u1.dwBumpBitCount,
+                pf->u2.dwBumpDuBitMask,
+                pf->u3.dwBumpDvBitMask,
+                pf->u4.dwBumpLuminanceBitMask);
     TRACE(")\n");
 }
 
index 842a3bd..47cebe8 100644 (file)
@@ -154,8 +154,6 @@ static ULONG WINAPI d3d_vertex_buffer7_Release(IDirect3DVertexBuffer7 *iface)
                 0, &curVB, &offset, &stride);
         if (curVB == buffer->wineD3DVertexBuffer)
             wined3d_device_set_stream_source(buffer->ddraw->wined3d_device, 0, NULL, 0, 0);
-        if (curVB)
-            wined3d_buffer_decref(curVB); /* For the GetStreamSource */
 
         wined3d_vertex_declaration_decref(buffer->wineD3DVertexDeclaration);
         wined3d_buffer_decref(buffer->wineD3DVertexBuffer);
index 4264005..f4114ad 100644 (file)
@@ -519,39 +519,18 @@ static HRESULT WINAPI d3d_viewport_LightElements(IDirect3DViewport3 *iface,
     return DDERR_UNSUPPORTED;
 }
 
-/*****************************************************************************
- * IDirect3DViewport3::SetBackground
- *
- * Sets the background material
- *
- * Params:
- *  hMat: Handle from a IDirect3DMaterial interface
- *
- * Returns:
- *  D3D_OK on success
- *
- *****************************************************************************/
-static HRESULT WINAPI d3d_viewport_SetBackground(IDirect3DViewport3 *iface, D3DMATERIALHANDLE hMat)
+static HRESULT WINAPI d3d_viewport_SetBackground(IDirect3DViewport3 *iface, D3DMATERIALHANDLE material)
 {
     struct d3d_viewport *viewport = impl_from_IDirect3DViewport3(iface);
     struct d3d_material *m;
 
-    TRACE("iface %p, material %#x.\n", iface, hMat);
+    TRACE("iface %p, material %#x.\n", iface, material);
 
     wined3d_mutex_lock();
 
-    if (!hMat)
+    if (!(m = ddraw_get_object(&viewport->ddraw->d3ddevice->handle_table, material - 1, DDRAW_HANDLE_MATERIAL)))
     {
-        viewport->background = NULL;
-        TRACE("Setting background to NULL\n");
-        wined3d_mutex_unlock();
-        return D3D_OK;
-    }
-
-    m = ddraw_get_object(&viewport->ddraw->d3ddevice->handle_table, hMat - 1, DDRAW_HANDLE_MATERIAL);
-    if (!m)
-    {
-        WARN("Invalid material handle.\n");
+        WARN("Invalid material handle %#x.\n", material);
         wined3d_mutex_unlock();
         return DDERR_INVALIDPARAMS;
     }
@@ -681,16 +660,13 @@ static HRESULT WINAPI d3d_viewport_Clear(IDirect3DViewport3 *iface,
 
     if (flags & D3DCLEAR_TARGET)
     {
-        if (This->background == NULL) {
-            ERR(" Trying to clear the color buffer without background material!\n");
-        }
+        if (!This->background)
+            WARN("No background material set.\n");
         else
-        {
-            color = ((int)((This->background->mat.u.diffuse.u1.r) * 255) << 16)
-                    | ((int) ((This->background->mat.u.diffuse.u2.g) * 255) <<  8)
-                    | ((int) ((This->background->mat.u.diffuse.u3.b) * 255) <<  0)
-                    | ((int) ((This->background->mat.u.diffuse.u4.a) * 255) << 24);
-        }
+            color = D3DRGBA(This->background->mat.u.diffuse.u1.r,
+                    This->background->mat.u.diffuse.u2.g,
+                    This->background->mat.u.diffuse.u3.b,
+                    This->background->mat.u.diffuse.u4.a);
     }
 
     /* Need to temporarily activate viewport to clear it. Previously active one will be restored
index 3519c78..d1e2a3c 100644 (file)
@@ -700,7 +700,7 @@ static void shader_arb_load_constants_internal(struct shader_arb_priv *priv,
     {
         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;
+        UINT rt_height = state->fb->render_targets[0]->height;
 
         /* Load DirectX 9 float constants for pixel shader */
         priv->highest_dirty_ps_const = shader_arb_load_constantsF(pshader, gl_info, GL_FRAGMENT_PROGRAM_ARB,
@@ -3278,7 +3278,7 @@ static GLuint create_arb_blt_vertex_program(const struct wined3d_gl_info *gl_inf
     GLuint program_id = 0;
     GLint pos;
 
-    const char *blt_vprogram =
+    static const char blt_vprogram[] =
         "!!ARBvp1.0\n"
         "PARAM c[1] = { { 1, 0.5 } };\n"
         "MOV result.position, vertex.position;\n"
@@ -4667,7 +4667,7 @@ static void shader_arb_select(void *shader_priv, struct wined3d_context *context
         }
         else
         {
-            UINT rt_height = state->fb->render_targets[0]->resource.height;
+            UINT rt_height = state->fb->render_targets[0]->height;
             shader_arb_ps_local_constants(compiled, context, state, rt_height);
         }
 
@@ -5185,6 +5185,7 @@ static const SHADER_HANDLER shader_arb_instruction_handler_table[WINED3DSIH_TABL
     /* WINED3DSIH_DEFB                  */ shader_hw_nop,
     /* WINED3DSIH_DEFI                  */ shader_hw_nop,
     /* WINED3DSIH_DIV                   */ NULL,
+    /* WINED3DSIH_DP2                   */ NULL,
     /* WINED3DSIH_DP2ADD                */ pshader_hw_dp2add,
     /* WINED3DSIH_DP3                   */ shader_hw_map2gl,
     /* WINED3DSIH_DP4                   */ shader_hw_map2gl,
@@ -5208,6 +5209,7 @@ static const SHADER_HANDLER shader_arb_instruction_handler_table[WINED3DSIH_TABL
     /* WINED3DSIH_IFC                   */ shader_hw_ifc,
     /* WINED3DSIH_IGE                   */ NULL,
     /* WINED3DSIH_IMUL                  */ NULL,
+    /* WINED3DSIH_ISHL                  */ NULL,
     /* WINED3DSIH_ITOF                  */ NULL,
     /* WINED3DSIH_LABEL                 */ shader_hw_label,
     /* WINED3DSIH_LD                    */ NULL,
@@ -6783,7 +6785,7 @@ static void arbfp_free_blit_shader(struct wine_rb_entry *entry, void *context)
     HeapFree(GetProcessHeap(), 0, entry_arb);
 }
 
-const struct wine_rb_functions wined3d_arbfp_blit_rb_functions =
+static const struct wine_rb_functions wined3d_arbfp_blit_rb_functions =
 {
     wined3d_rb_alloc,
     wined3d_rb_realloc,
@@ -7270,15 +7272,12 @@ static GLuint gen_p8_shader(struct arbfp_blit_priv *priv,
 }
 
 /* Context activation is done by the caller. */
-static void upload_palette(const struct wined3d_surface *surface, struct wined3d_context *context)
+static void upload_palette(const struct wined3d_texture *texture, struct wined3d_context *context)
 {
-    BYTE table[256][4];
-    struct wined3d_device *device = surface->resource.device;
+    const struct wined3d_palette *palette = texture->swapchain ? texture->swapchain->palette : NULL;
+    struct wined3d_device *device = texture->resource.device;
     const struct wined3d_gl_info *gl_info = context->gl_info;
     struct arbfp_blit_priv *priv = device->blit_priv;
-    BOOL colorkey = !!(surface->container->color_key_flags & WINEDDSD_CKSRCBLT);
-
-    d3dfmt_p8_init_palette(surface, table, colorkey);
 
     if (!priv->palette_texture)
         gl_info->gl_ops.gl.p_glGenTextures(1, &priv->palette_texture);
@@ -7292,9 +7291,19 @@ static void upload_palette(const struct wined3d_surface *surface, struct wined3d
     /* Make sure we have discrete color levels. */
     gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
     gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-    /* Upload the palette */
     /* TODO: avoid unneeded uploads in the future by adding some SFLAG_PALETTE_DIRTY mechanism */
-    gl_info->gl_ops.gl.p_glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, table);
+    if (palette)
+    {
+        gl_info->gl_ops.gl.p_glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 256, 0, GL_BGRA,
+                GL_UNSIGNED_INT_8_8_8_8_REV, palette->colors);
+    }
+    else
+    {
+        static const DWORD black;
+        FIXME("P8 surface loaded without a palette.\n");
+        gl_info->gl_ops.gl.p_glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 1, 0, GL_BGRA,
+                GL_UNSIGNED_INT_8_8_8_8_REV, &black);
+    }
 
     /* Switch back to unit 0 in which the 2D texture will be stored. */
     context_active_texture(context, gl_info, 0);
@@ -7523,7 +7532,7 @@ err_out:
     }
 
     if (fixup == COMPLEX_FIXUP_P8)
-        upload_palette(surface, context);
+        upload_palette(surface->container, context);
 
     gl_info->gl_ops.gl.p_glEnable(GL_FRAGMENT_PROGRAM_ARB);
     checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB)");
@@ -7630,7 +7639,7 @@ HRESULT arbfp_blit_surface(struct wined3d_device *device, DWORD filter,
     if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
             && (src_surface->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_DRAWABLE))
             == WINED3D_LOCATION_DRAWABLE
-            && !surface_is_offscreen(src_surface))
+            && !wined3d_resource_is_offscreen(&src_surface->container->resource))
     {
         /* Without FBO blits transferring from the drawable to the texture is
          * expensive, because we have to flip the data in sysmem. Since we can
@@ -7647,7 +7656,7 @@ HRESULT arbfp_blit_surface(struct wined3d_device *device, DWORD filter,
 
     context_apply_blit_state(context, device);
 
-    if (!surface_is_offscreen(dst_surface))
+    if (!wined3d_resource_is_offscreen(&dst_surface->container->resource))
         surface_translate_drawable_coords(dst_surface, context->win_handle, &dst_rect);
 
     arbfp_blit_set(device->blit_priv, context, src_surface);
@@ -7659,13 +7668,14 @@ HRESULT arbfp_blit_surface(struct wined3d_device *device, DWORD filter,
     arbfp_blit_unset(context->gl_info);
 
     if (wined3d_settings.strict_draw_ordering
-            || (dst_surface->swapchain && (dst_surface->swapchain->front_buffer == dst_surface)))
+            || (dst_surface->container->swapchain
+            && (dst_surface->container->swapchain->front_buffer == dst_surface->container)))
         context->gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */
 
     context_release(context);
 
-    surface_validate_location(dst_surface, dst_surface->draw_binding);
-    surface_invalidate_location(dst_surface, ~dst_surface->draw_binding);
+    surface_validate_location(dst_surface, dst_surface->container->resource.draw_binding);
+    surface_invalidate_location(dst_surface, ~dst_surface->container->resource.draw_binding);
 
     return WINED3D_OK;
 }
index 2bffe83..810771a 100644 (file)
@@ -31,7 +31,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d);
 #define WINED3D_BUFFER_DOUBLEBUFFER 0x04    /* Keep both a buffer object and a system memory copy for this buffer. */
 #define WINED3D_BUFFER_FLUSH        0x08    /* Manual unmap flushing. */
 #define WINED3D_BUFFER_DISCARD      0x10    /* A DISCARD lock has occurred since the last preload. */
-#define WINED3D_BUFFER_NOSYNC       0x20    /* All locks since the last preload had NOOVERWRITE set. */
+#define WINED3D_BUFFER_SYNC         0x20    /* There has been at least one synchronized map since the last preload. */
 #define WINED3D_BUFFER_APPLESYNC    0x40    /* Using sync as in GL_APPLE_flush_buffer_range. */
 
 #define VB_MAXDECLCHANGES     100     /* After that number of decl changes we stop converting */
@@ -574,16 +574,6 @@ void * CDECL wined3d_buffer_get_parent(const struct wined3d_buffer *buffer)
     return buffer->resource.parent;
 }
 
-DWORD CDECL wined3d_buffer_set_priority(struct wined3d_buffer *buffer, DWORD priority)
-{
-    return resource_set_priority(&buffer->resource, priority);
-}
-
-DWORD CDECL wined3d_buffer_get_priority(const struct wined3d_buffer *buffer)
-{
-    return resource_get_priority(&buffer->resource);
-}
-
 /* The caller provides a context and binds the buffer */
 static void buffer_sync_apple(struct wined3d_buffer *This, DWORD flags, const struct wined3d_gl_info *gl_info)
 {
@@ -669,7 +659,7 @@ static void buffer_direct_upload(struct wined3d_buffer *This, const struct wined
         mapflags = GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT;
         if (flags & WINED3D_BUFFER_DISCARD)
             mapflags |= GL_MAP_INVALIDATE_BUFFER_BIT;
-        if (flags & WINED3D_BUFFER_NOSYNC)
+        else if (!(flags & WINED3D_BUFFER_SYNC))
             mapflags |= GL_MAP_UNSYNCHRONIZED_BIT;
         map = GL_EXTCALL(glMapBufferRange(This->buffer_type_hint, 0,
                     This->resource.size, mapflags));
@@ -682,7 +672,7 @@ static void buffer_direct_upload(struct wined3d_buffer *This, const struct wined
             DWORD syncflags = 0;
             if (flags & WINED3D_BUFFER_DISCARD)
                 syncflags |= WINED3D_MAP_DISCARD;
-            if (flags & WINED3D_BUFFER_NOSYNC)
+            else if (!(flags & WINED3D_BUFFER_SYNC))
                 syncflags |= WINED3D_MAP_NOOVERWRITE;
             buffer_sync_apple(This, syncflags, gl_info);
         }
@@ -718,11 +708,16 @@ static void buffer_direct_upload(struct wined3d_buffer *This, const struct wined
     checkGLcall("glUnmapBufferARB");
 }
 
+void buffer_mark_used(struct wined3d_buffer *buffer)
+{
+    buffer->flags &= ~(WINED3D_BUFFER_SYNC | WINED3D_BUFFER_DISCARD);
+}
+
 /* 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);
+    DWORD flags = buffer->flags & (WINED3D_BUFFER_SYNC | 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;
@@ -738,7 +733,7 @@ void buffer_internal_preload(struct wined3d_buffer *buffer, struct wined3d_conte
         return;
     }
 
-    buffer->flags &= ~(WINED3D_BUFFER_NOSYNC | WINED3D_BUFFER_DISCARD);
+    buffer_mark_used(buffer);
 
     if (!buffer->buffer_object)
     {
@@ -1033,11 +1028,8 @@ HRESULT CDECL wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UIN
 
         if (flags & WINED3D_MAP_DISCARD)
             buffer->flags |= WINED3D_BUFFER_DISCARD;
-
-        if (!(flags & WINED3D_MAP_NOOVERWRITE))
-            buffer->flags &= ~WINED3D_BUFFER_NOSYNC;
-        else if (!buffer_is_dirty(buffer))
-            buffer->flags |= WINED3D_BUFFER_NOSYNC;
+        else if (!(flags & WINED3D_MAP_NOOVERWRITE))
+            buffer->flags |= WINED3D_BUFFER_SYNC;
     }
 
     base = buffer->map_ptr ? buffer->map_ptr : buffer->resource.heap_memory;
@@ -1118,8 +1110,20 @@ void CDECL wined3d_buffer_unmap(struct wined3d_buffer *buffer)
     }
 }
 
+static ULONG buffer_resource_incref(struct wined3d_resource *resource)
+{
+    return wined3d_buffer_incref(buffer_from_resource(resource));
+}
+
+static ULONG buffer_resource_decref(struct wined3d_resource *resource)
+{
+    return wined3d_buffer_decref(buffer_from_resource(resource));
+}
+
 static const struct wined3d_resource_ops buffer_resource_ops =
 {
+    buffer_resource_incref,
+    buffer_resource_decref,
     buffer_unload,
 };
 
@@ -1217,8 +1221,8 @@ static HRESULT buffer_init(struct wined3d_buffer *buffer, struct wined3d_device
     return WINED3D_OK;
 }
 
-HRESULT CDECL wined3d_buffer_create(struct wined3d_device *device, struct wined3d_buffer_desc *desc, const void *data,
-        void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_buffer **buffer)
+HRESULT CDECL wined3d_buffer_create(struct wined3d_device *device, const struct wined3d_buffer_desc *desc,
+        const void *data, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_buffer **buffer)
 {
     struct wined3d_buffer *object;
     HRESULT hr;
index a8d3033..cbb5815 100644 (file)
@@ -1582,7 +1582,7 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
     ret->current_rt = target;
     ret->tid = GetCurrentThreadId();
 
-    ret->render_offscreen = surface_is_offscreen(target);
+    ret->render_offscreen = wined3d_resource_is_offscreen(&target->container->resource);
     ret->draw_buffers_mask = context_generate_rt_mask(GL_BACK);
     ret->valid = 1;
 
@@ -1713,7 +1713,7 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
          * So make sure a program is assigned to each context. The first real ARBFP use will set a different
          * program and the dummy program is destroyed when the context is destroyed.
          */
-        const char *dummy_program =
+        static const char dummy_program[] =
                 "!!ARBfp1.0\n"
                 "MOV result.color, fragment.color.primary;\n"
                 "END\n";
@@ -1818,7 +1818,7 @@ static void context_get_rt_size(const struct wined3d_context *context, SIZE *siz
 {
     const struct wined3d_surface *rt = context->current_rt;
 
-    if (rt->swapchain && rt->swapchain->front_buffer == rt)
+    if (rt->container->swapchain && rt->container->swapchain->front_buffer == rt->container)
     {
         RECT window_size;
 
@@ -2193,13 +2193,13 @@ static BOOL match_depth_stencil_format(const struct wined3d_format *existing,
 
 /* The caller provides a context */
 static void context_validate_onscreen_formats(struct wined3d_context *context,
-        const struct wined3d_surface *depth_stencil)
+        const struct wined3d_rendertarget_view *depth_stencil)
 {
     /* Onscreen surfaces are always in a swapchain */
-    struct wined3d_swapchain *swapchain = context->current_rt->swapchain;
+    struct wined3d_swapchain *swapchain = context->current_rt->container->swapchain;
 
     if (context->render_offscreen || !depth_stencil) return;
-    if (match_depth_stencil_format(swapchain->ds_format, depth_stencil->resource.format)) return;
+    if (match_depth_stencil_format(swapchain->ds_format, depth_stencil->format)) return;
 
     /* TODO: If the requested format would satisfy the needs of the existing one(reverse match),
      * or no onscreen depth buffer was created, the OpenGL drawable could be changed to the new
@@ -2217,7 +2217,7 @@ static DWORD context_generate_rt_mask_no_fbo(const struct wined3d_device *device
 {
     if (!rt || rt->resource.format->id == WINED3DFMT_NULL)
         return 0;
-    else if (rt->swapchain)
+    else if (rt->container->swapchain)
         return context_generate_rt_mask_from_surface(rt);
     else
         return context_generate_rt_mask(device->offscreenBuffer);
@@ -2237,7 +2237,7 @@ void context_apply_blit_state(struct wined3d_context *context, const struct wine
         {
             wined3d_texture_load(rt->container, context, FALSE);
 
-            context_apply_fbo_state_blit(context, GL_FRAMEBUFFER, rt, NULL, rt->draw_binding);
+            context_apply_fbo_state_blit(context, GL_FRAMEBUFFER, rt, NULL, rt->container->resource.draw_binding);
             if (rt->resource.format->id != WINED3DFMT_NULL)
                 rt_mask = 1;
             else
@@ -2272,8 +2272,8 @@ void context_apply_blit_state(struct wined3d_context *context, const struct wine
     context_invalidate_state(context, STATE_FRAMEBUFFER);
 }
 
-static BOOL context_validate_rt_config(UINT rt_count,
-        struct wined3d_surface * const *rts, const struct wined3d_surface *ds)
+static BOOL context_validate_rt_config(UINT rt_count, struct wined3d_rendertarget_view * const *rts,
+        const struct wined3d_rendertarget_view *ds)
 {
     unsigned int i;
 
@@ -2281,7 +2281,7 @@ static BOOL context_validate_rt_config(UINT rt_count,
 
     for (i = 0; i < rt_count; ++i)
     {
-        if (rts[i] && rts[i]->resource.format->id != WINED3DFMT_NULL)
+        if (rts[i] && rts[i]->format->id != WINED3DFMT_NULL)
             return TRUE;
     }
 
@@ -2293,10 +2293,10 @@ static BOOL context_validate_rt_config(UINT rt_count,
 BOOL context_apply_clear_state(struct wined3d_context *context, const struct wined3d_device *device,
         UINT rt_count, const struct wined3d_fb_state *fb)
 {
+    struct wined3d_rendertarget_view **rts = fb->render_targets;
     const struct wined3d_gl_info *gl_info = context->gl_info;
     DWORD rt_mask = 0, *cur_mask;
     UINT i;
-    struct wined3d_surface **rts = fb->render_targets;
 
     if (isStateDirty(context, STATE_FRAMEBUFFER) || fb != &device->fb
             || rt_count != context->gl_info->limits.buffers)
@@ -2308,12 +2308,12 @@ BOOL context_apply_clear_state(struct wined3d_context *context, const struct win
         {
             context_validate_onscreen_formats(context, fb->depth_stencil);
 
-            if (!rt_count || surface_is_offscreen(rts[0]))
+            if (!rt_count || wined3d_resource_is_offscreen(rts[0]->resource))
             {
                 for (i = 0; i < rt_count; ++i)
                 {
-                    context->blit_targets[i] = rts[i];
-                    if (rts[i] && rts[i]->resource.format->id != WINED3DFMT_NULL)
+                    context->blit_targets[i] = wined3d_rendertarget_view_get_surface(rts[i]);
+                    if (rts[i] && rts[i]->format->id != WINED3DFMT_NULL)
                         rt_mask |= (1 << i);
                 }
                 while (i < context->gl_info->limits.buffers)
@@ -2321,13 +2321,14 @@ BOOL context_apply_clear_state(struct wined3d_context *context, const struct win
                     context->blit_targets[i] = NULL;
                     ++i;
                 }
-                context_apply_fbo_state(context, GL_FRAMEBUFFER, context->blit_targets, fb->depth_stencil,
-                        rt_count ? rts[0]->draw_binding : WINED3D_LOCATION_TEXTURE_RGB);
+                context_apply_fbo_state(context, GL_FRAMEBUFFER, context->blit_targets,
+                        wined3d_rendertarget_view_get_surface(fb->depth_stencil),
+                        rt_count ? rts[0]->resource->draw_binding : WINED3D_LOCATION_TEXTURE_RGB);
             }
             else
             {
                 context_apply_fbo_state(context, GL_FRAMEBUFFER, NULL, NULL, WINED3D_LOCATION_DRAWABLE);
-                rt_mask = context_generate_rt_mask_from_surface(rts[0]);
+                rt_mask = context_generate_rt_mask_from_surface(wined3d_rendertarget_view_get_surface(rts[0]));
             }
 
             /* If the framebuffer is not the device's fb the device's fb has to be reapplied
@@ -2337,20 +2338,23 @@ BOOL context_apply_clear_state(struct wined3d_context *context, const struct win
         }
         else
         {
-            rt_mask = context_generate_rt_mask_no_fbo(device, rt_count ? rts[0] : NULL);
+            rt_mask = context_generate_rt_mask_no_fbo(device,
+                    rt_count ? wined3d_rendertarget_view_get_surface(rts[0]) : NULL);
         }
     }
     else if (wined3d_settings.offscreen_rendering_mode == ORM_FBO
-            && (!rt_count || surface_is_offscreen(rts[0])))
+            && (!rt_count || wined3d_resource_is_offscreen(rts[0]->resource)))
     {
         for (i = 0; i < rt_count; ++i)
         {
-            if (rts[i] && rts[i]->resource.format->id != WINED3DFMT_NULL) rt_mask |= (1 << i);
+            if (rts[i] && rts[i]->format->id != WINED3DFMT_NULL)
+                rt_mask |= (1 << i);
         }
     }
     else
     {
-        rt_mask = context_generate_rt_mask_no_fbo(device, rt_count ? rts[0] : NULL);
+        rt_mask = context_generate_rt_mask_no_fbo(device,
+                rt_count ? wined3d_rendertarget_view_get_surface(rts[0]) : NULL);
     }
 
     cur_mask = context->current_fbo ? &context->current_fbo->rt_mask : &context->draw_buffers_mask;
@@ -2387,13 +2391,15 @@ BOOL context_apply_clear_state(struct wined3d_context *context, const struct win
 static DWORD find_draw_buffers_mask(const struct wined3d_context *context, const struct wined3d_device *device)
 {
     const struct wined3d_state *state = &device->state;
-    struct wined3d_surface **rts = state->fb->render_targets;
+    struct wined3d_rendertarget_view **rts = state->fb->render_targets;
     struct wined3d_shader *ps = state->shader[WINED3D_SHADER_TYPE_PIXEL];
     DWORD rt_mask, rt_mask_bits;
     unsigned int i;
 
-    if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) return context_generate_rt_mask_no_fbo(device, rts[0]);
-    else if (!context->render_offscreen) return context_generate_rt_mask_from_surface(rts[0]);
+    if (wined3d_settings.offscreen_rendering_mode != ORM_FBO)
+        return context_generate_rt_mask_no_fbo(device, wined3d_rendertarget_view_get_surface(rts[0]));
+    else if (!context->render_offscreen)
+        return context_generate_rt_mask_from_surface(wined3d_rendertarget_view_get_surface(rts[0]));
 
     rt_mask = ps ? ps->reg_maps.rt_mask : 1;
     rt_mask &= context->d3d_info->valid_rt_mask;
@@ -2402,7 +2408,7 @@ static DWORD find_draw_buffers_mask(const struct wined3d_context *context, const
     while (rt_mask_bits)
     {
         rt_mask_bits &= ~(1 << i);
-        if (!rts[i] || rts[i]->resource.format->id == WINED3DFMT_NULL)
+        if (!rts[i] || rts[i]->format->id == WINED3DFMT_NULL)
             rt_mask &= ~(1 << i);
 
         i++;
@@ -2427,8 +2433,15 @@ void context_state_fb(struct wined3d_context *context, const struct wined3d_stat
         }
         else
         {
-            context_apply_fbo_state(context, GL_FRAMEBUFFER, fb->render_targets, fb->depth_stencil,
-                    fb->render_targets[0]->draw_binding);
+            unsigned int i;
+
+            for (i = 0; i < context->gl_info->limits.buffers; ++i)
+            {
+                context->blit_targets[i] = wined3d_rendertarget_view_get_surface(fb->render_targets[i]);
+            }
+            context_apply_fbo_state(context, GL_FRAMEBUFFER, context->blit_targets,
+                    wined3d_rendertarget_view_get_surface(fb->depth_stencil),
+                    fb->render_targets[0]->resource->draw_binding);
         }
     }
 
@@ -2717,7 +2730,6 @@ static BOOL fixed_get_input(BYTE usage, BYTE usage_idx, unsigned int *regnum)
     return TRUE;
 }
 
-/* FIXME: Separate buffer loading from declaration decoding */
 /* Context activation is done by the caller. */
 void context_stream_info_from_declaration(struct wined3d_context *context,
         const struct wined3d_state *state, struct wined3d_stream_info *stream_info)
@@ -2726,11 +2738,9 @@ void context_stream_info_from_declaration(struct wined3d_context *context,
     struct wined3d_vertex_declaration *declaration = state->vertex_declaration;
     BOOL use_vshader = use_vs(state);
     unsigned int i;
-    WORD map;
 
     stream_info->use_map = 0;
     stream_info->swizzle_map = 0;
-    stream_info->all_vbo = 1;
     stream_info->position_transformed = declaration->position_transformed;
 
     /* Translate the declaration into strided data. */
@@ -2738,38 +2748,14 @@ void context_stream_info_from_declaration(struct wined3d_context *context,
     {
         const struct wined3d_vertex_declaration_element *element = &declaration->elements[i];
         const struct wined3d_stream_state *stream = &state->streams[element->input_slot];
-        struct wined3d_buffer *buffer = stream->buffer;
-        struct wined3d_bo_address data;
         BOOL stride_used;
         unsigned int idx;
-        DWORD stride;
 
         TRACE("%p Element %p (%u of %u).\n", declaration->elements,
                 element, i + 1, declaration->element_count);
 
-        if (!buffer) continue;
-
-        stride = stream->stride;
-        TRACE("Stream %u in buffer %p.\n", element->input_slot, buffer);
-        buffer_get_memory(buffer, context, &data);
-
-        /* Can't use vbo's if the base vertex index is negative. OpenGL doesn't accept negative offsets
-         * (or rather offsets bigger than the vbo, because the pointer is unsigned), so use system memory
-         * sources. In most sane cases the pointer - offset will still be > 0, otherwise it will wrap
-         * around to some big value. Hope that with the indices, the driver wraps it back internally. If
-         * not, drawStridedSlow is needed, including a vertex buffer path. */
-        if (state->load_base_vertex_index < 0)
-        {
-            WARN_(d3d_perf)("load_base_vertex_index is < 0 (%d), not using VBOs.\n",
-                    state->load_base_vertex_index);
-            data.buffer_object = 0;
-            data.addr = buffer_get_sysmem(buffer, context);
-            if ((UINT_PTR)data.addr < -state->load_base_vertex_index * stride)
-            {
-                FIXME("System memory vertex data load offset is negative!\n");
-            }
-        }
-        data.addr += element->offset;
+        if (!stream->buffer)
+            continue;
 
         TRACE("offset %u input_slot %u usage_idx %d.\n", element->offset, element->input_slot, element->usage_idx);
 
@@ -2806,16 +2792,15 @@ void context_stream_info_from_declaration(struct wined3d_context *context,
         if (stride_used)
         {
             TRACE("Load %s array %u [usage %s, usage_idx %u, "
-                    "input_slot %u, offset %u, stride %u, format %s, buffer_object %u].\n",
+                    "input_slot %u, offset %u, stride %u, format %s].\n",
                     use_vshader ? "shader": "fixed function", idx,
                     debug_d3ddeclusage(element->usage), element->usage_idx, element->input_slot,
-                    element->offset, stride, debug_d3dformat(element->format->id), data.buffer_object);
-
-            data.addr += stream->offset;
+                    element->offset, stream->stride, debug_d3dformat(element->format->id));
 
             stream_info->elements[idx].format = element->format;
-            stream_info->elements[idx].data = data;
-            stream_info->elements[idx].stride = stride;
+            stream_info->elements[idx].data.buffer_object = 0;
+            stream_info->elements[idx].data.addr = (BYTE *)NULL + stream->offset + element->offset;
+            stream_info->elements[idx].stride = stream->stride;
             stream_info->elements[idx].stream_idx = element->input_slot;
 
             if (!context->gl_info->supported[ARB_VERTEX_ARRAY_BGRA]
@@ -2826,12 +2811,26 @@ void context_stream_info_from_declaration(struct wined3d_context *context,
             stream_info->use_map |= 1 << idx;
         }
     }
+}
+
+/* Context activation is done by the caller. */
+static void context_update_stream_info(struct wined3d_context *context, const struct wined3d_state *state)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    const struct wined3d_d3d_info *d3d_info = context->d3d_info;
+    struct wined3d_stream_info *stream_info = &context->stream_info;
+    DWORD prev_all_vbo = stream_info->all_vbo;
+    unsigned int i;
+    WORD map;
 
-    /* Preload the vertex buffers. */
+    context_stream_info_from_declaration(context, state, stream_info);
+
+    stream_info->all_vbo = 1;
     context->num_buffer_queries = 0;
     for (i = 0, map = stream_info->use_map; map; map >>= 1, ++i)
     {
         struct wined3d_stream_info_element *element;
+        struct wined3d_bo_address data;
         struct wined3d_buffer *buffer;
 
         if (!(map & 1))
@@ -2839,34 +2838,39 @@ void context_stream_info_from_declaration(struct wined3d_context *context,
 
         element = &stream_info->elements[i];
         buffer = state->streams[element->stream_idx].buffer;
-        buffer_internal_preload(buffer, context, state);
 
-        /* If the preload dropped the buffer object, update the stream info. */
-        if (buffer->buffer_object != element->data.buffer_object)
+        /* We can't use VBOs if the base vertex index is negative. OpenGL
+         * doesn't accept negative offsets (or rather offsets bigger than the
+         * VBO, because the pointer is unsigned), so use system memory
+         * sources. In most sane cases the pointer - offset will still be > 0,
+         * otherwise it will wrap around to some big value. Hope that with the
+         * indices the driver wraps it back internally. If not,
+         * drawStridedSlow is needed, including a vertex buffer path. */
+        if (state->load_base_vertex_index < 0)
         {
+            WARN_(d3d_perf)("load_base_vertex_index is < 0 (%d), not using VBOs.\n",
+                    state->load_base_vertex_index);
             element->data.buffer_object = 0;
-            element->data.addr = buffer_get_sysmem(buffer, context)
-                    + (ptrdiff_t)element->data.addr;
+            element->data.addr += (ULONG_PTR)buffer_get_sysmem(buffer, context);
+            if ((UINT_PTR)element->data.addr < -state->load_base_vertex_index * element->stride)
+                FIXME("System memory vertex data load offset is negative!\n");
+        }
+        else
+        {
+            buffer_internal_preload(buffer, context, state);
+            buffer_get_memory(buffer, context, &data);
+            element->data.buffer_object = data.buffer_object;
+            element->data.addr += (ULONG_PTR)data.addr;
         }
 
-        if (!buffer->buffer_object)
+        if (!element->data.buffer_object)
             stream_info->all_vbo = 0;
 
         if (buffer->query)
             context->buffer_queries[context->num_buffer_queries++] = buffer->query;
-    }
-}
-
-/* Context activation is done by the caller. */
-static void context_update_stream_info(struct wined3d_context *context, const struct wined3d_state *state)
-{
-    const struct wined3d_gl_info *gl_info = context->gl_info;
-    const struct wined3d_d3d_info *d3d_info = context->d3d_info;
-    struct wined3d_stream_info *stream_info = &context->stream_info;
-    DWORD prev_all_vbo = stream_info->all_vbo;
 
-    TRACE("============================= Vertex Declaration =============================\n");
-    context_stream_info_from_declaration(context, state, stream_info);
+        TRACE("Load array %u {%#x:%p}.\n", i, element->data.buffer_object, element->data.addr);
+    }
 
     if (use_vs(state))
     {
@@ -2949,7 +2953,8 @@ BOOL context_apply_draw_state(struct wined3d_context *context, struct wined3d_de
     const struct wined3d_state *state = &device->state;
     const struct StateEntry *state_table = context->state_table;
     const struct wined3d_fb_state *fb = state->fb;
-    unsigned int i;
+    unsigned int i, j;
+    WORD map;
 
     if (!context_validate_rt_config(context->gl_info->limits.buffers,
             fb->render_targets, fb->depth_stencil))
@@ -2966,7 +2971,17 @@ BOOL context_apply_draw_state(struct wined3d_context *context, struct wined3d_de
     context_update_tex_unit_map(context, state);
     context_preload_textures(context, state);
     if (isStateDirty(context, STATE_VDECL) || isStateDirty(context, STATE_STREAMSRC))
+    {
         context_update_stream_info(context, state);
+    }
+    else
+    {
+        for (i = 0, map = context->stream_info.use_map; map; map >>= 1, ++i)
+        {
+            if (map & 1)
+                buffer_mark_used(state->streams[context->stream_info.elements[i].stream_idx].buffer);
+        }
+    }
     if (state->index_buffer)
     {
         if (context->stream_info.all_vbo)
@@ -2975,6 +2990,15 @@ BOOL context_apply_draw_state(struct wined3d_context *context, struct wined3d_de
             buffer_get_sysmem(state->index_buffer, context);
     }
 
+    for (i = 0; i < WINED3D_SHADER_TYPE_COUNT; ++i)
+    {
+        for (j = 0; j < WINED3D_MAX_CBS; ++j)
+        {
+            if (state->cb[i][j])
+                buffer_internal_preload(state->cb[i][j], context, state);
+        }
+    }
+
     for (i = 0; i < context->numDirtyEntries; ++i)
     {
         DWORD rep = context->dirtyArray[i];
@@ -3011,7 +3035,7 @@ static void context_setup_target(struct wined3d_context *context, struct wined3d
 {
     BOOL old_render_offscreen = context->render_offscreen, render_offscreen;
 
-    render_offscreen = surface_is_offscreen(target);
+    render_offscreen = wined3d_resource_is_offscreen(&target->container->resource);
     if (context->current_rt == target && render_offscreen == old_render_offscreen) return;
 
     /* To compensate the lack of format switching with some offscreen rendering methods and on onscreen buffers
@@ -3083,9 +3107,9 @@ struct wined3d_context *context_acquire(const struct wined3d_device *device, str
         {
             struct wined3d_swapchain *swapchain = device->swapchains[0];
             if (swapchain->back_buffers)
-                target = swapchain->back_buffers[0];
+                target = surface_from_resource(wined3d_texture_get_sub_resource(swapchain->back_buffers[0], 0));
             else
-                target = swapchain->front_buffer;
+                target = surface_from_resource(wined3d_texture_get_sub_resource(swapchain->front_buffer, 0));
         }
     }
 
@@ -3093,11 +3117,11 @@ struct wined3d_context *context_acquire(const struct wined3d_device *device, str
     {
         context = current_context;
     }
-    else if (target->swapchain)
+    else if (target->container->swapchain)
     {
         TRACE("Rendering onscreen.\n");
 
-        context = swapchain_get_context(target->swapchain);
+        context = swapchain_get_context(target->container->swapchain);
     }
     else
     {
index f85cf98..08dbbed 100644 (file)
@@ -27,10 +27,11 @@ enum wined3d_cs_op
     WINED3D_CS_OP_PRESENT,
     WINED3D_CS_OP_CLEAR,
     WINED3D_CS_OP_DRAW,
+    WINED3D_CS_OP_SET_PREDICATION,
     WINED3D_CS_OP_SET_VIEWPORT,
     WINED3D_CS_OP_SET_SCISSOR_RECT,
-    WINED3D_CS_OP_SET_RENDER_TARGET,
-    WINED3D_CS_OP_SET_DEPTH_STENCIL,
+    WINED3D_CS_OP_SET_RENDERTARGET_VIEW,
+    WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW,
     WINED3D_CS_OP_SET_VERTEX_DECLARATION,
     WINED3D_CS_OP_SET_STREAM_SOURCE,
     WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ,
@@ -38,6 +39,7 @@ enum wined3d_cs_op
     WINED3D_CS_OP_SET_INDEX_BUFFER,
     WINED3D_CS_OP_SET_CONSTANT_BUFFER,
     WINED3D_CS_OP_SET_TEXTURE,
+    WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW,
     WINED3D_CS_OP_SET_SAMPLER,
     WINED3D_CS_OP_SET_SHADER,
     WINED3D_CS_OP_SET_RENDER_STATE,
@@ -81,6 +83,13 @@ struct wined3d_cs_draw
     BOOL indexed;
 };
 
+struct wined3d_cs_set_predication
+{
+    enum wined3d_cs_op opcode;
+    struct wined3d_query *predicate;
+    BOOL value;
+};
+
 struct wined3d_cs_set_viewport
 {
     enum wined3d_cs_op opcode;
@@ -93,17 +102,17 @@ struct wined3d_cs_set_scissor_rect
     const RECT *rect;
 };
 
-struct wined3d_cs_set_render_target
+struct wined3d_cs_set_rendertarget_view
 {
     enum wined3d_cs_op opcode;
-    UINT render_target_idx;
-    struct wined3d_surface *render_target;
+    unsigned int view_idx;
+    struct wined3d_rendertarget_view *view;
 };
 
-struct wined3d_cs_set_depth_stencil
+struct wined3d_cs_set_depth_stencil_view
 {
     enum wined3d_cs_op opcode;
-    struct wined3d_surface *depth_stencil;
+    struct wined3d_rendertarget_view *view;
 };
 
 struct wined3d_cs_set_vertex_declaration
@@ -159,6 +168,14 @@ struct wined3d_cs_set_texture
     struct wined3d_texture *texture;
 };
 
+struct wined3d_cs_set_shader_resource_view
+{
+    enum wined3d_cs_op opcode;
+    enum wined3d_shader_type type;
+    UINT view_idx;
+    struct wined3d_shader_resource_view *view;
+};
+
 struct wined3d_cs_set_sampler
 {
     enum wined3d_cs_op opcode;
@@ -306,6 +323,26 @@ void wined3d_cs_emit_draw(struct wined3d_cs *cs, UINT start_idx, UINT index_coun
     cs->ops->submit(cs);
 }
 
+static void wined3d_cs_exec_set_predication(struct wined3d_cs *cs, const void *data)
+{
+    const struct wined3d_cs_set_predication *op = data;
+
+    cs->state.predicate = op->predicate;
+    cs->state.predicate_value = op->value;
+}
+
+void wined3d_cs_emit_set_predication(struct wined3d_cs *cs, struct wined3d_query *predicate, BOOL value)
+{
+    struct wined3d_cs_set_predication *op;
+
+    op = cs->ops->require_space(cs, sizeof(*op));
+    op->opcode = WINED3D_CS_OP_SET_PREDICATION;
+    op->predicate = predicate;
+    op->value = value;
+
+    cs->ops->submit(cs);
+}
+
 static void wined3d_cs_exec_set_viewport(struct wined3d_cs *cs, const void *data)
 {
     const struct wined3d_cs_set_viewport *op = data;
@@ -344,41 +381,42 @@ void wined3d_cs_emit_set_scissor_rect(struct wined3d_cs *cs, const RECT *rect)
     cs->ops->submit(cs);
 }
 
-static void wined3d_cs_exec_set_render_target(struct wined3d_cs *cs, const void *data)
+static void wined3d_cs_exec_set_rendertarget_view(struct wined3d_cs *cs, const void *data)
 {
-    const struct wined3d_cs_set_render_target *op = data;
+    const struct wined3d_cs_set_rendertarget_view *op = data;
 
-    cs->state.fb->render_targets[op->render_target_idx] = op->render_target;
+    cs->state.fb->render_targets[op->view_idx] = op->view;
     device_invalidate_state(cs->device, STATE_FRAMEBUFFER);
 }
 
-void wined3d_cs_emit_set_render_target(struct wined3d_cs *cs, UINT render_target_idx,
-        struct wined3d_surface *render_target)
+void wined3d_cs_emit_set_rendertarget_view(struct wined3d_cs *cs, unsigned int view_idx,
+        struct wined3d_rendertarget_view *view)
 {
-    struct wined3d_cs_set_render_target *op;
+    struct wined3d_cs_set_rendertarget_view *op;
 
     op = cs->ops->require_space(cs, sizeof(*op));
-    op->opcode = WINED3D_CS_OP_SET_RENDER_TARGET;
-    op->render_target_idx = render_target_idx;
-    op->render_target = render_target;
+    op->opcode = WINED3D_CS_OP_SET_RENDERTARGET_VIEW;
+    op->view_idx = view_idx;
+    op->view = view;
 
     cs->ops->submit(cs);
 }
 
-static void wined3d_cs_exec_set_depth_stencil(struct wined3d_cs *cs, const void *data)
+static void wined3d_cs_exec_set_depth_stencil_view(struct wined3d_cs *cs, const void *data)
 {
-    const struct wined3d_cs_set_depth_stencil *op = data;
+    const struct wined3d_cs_set_depth_stencil_view *op = data;
     struct wined3d_device *device = cs->device;
-    struct wined3d_surface *prev;
+    struct wined3d_rendertarget_view *prev;
 
     if ((prev = cs->state.fb->depth_stencil))
     {
-        if (device->swapchains[0]->desc.flags & WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL
-                || prev->flags & SFLAG_DISCARD)
+        struct wined3d_surface *prev_surface = wined3d_rendertarget_view_get_surface(prev);
+
+        if (prev_surface && (device->swapchains[0]->desc.flags & WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL
+                || prev_surface->flags & SFLAG_DISCARD))
         {
-            surface_modify_ds_location(prev, WINED3D_LOCATION_DISCARDED,
-                    prev->resource.width, prev->resource.height);
-            if (prev == device->onscreen_depth_stencil)
+            surface_modify_ds_location(prev_surface, WINED3D_LOCATION_DISCARDED, prev->width, prev->height);
+            if (prev_surface == device->onscreen_depth_stencil)
             {
                 wined3d_surface_decref(device->onscreen_depth_stencil);
                 device->onscreen_depth_stencil = NULL;
@@ -386,9 +424,9 @@ static void wined3d_cs_exec_set_depth_stencil(struct wined3d_cs *cs, const void
         }
     }
 
-    cs->fb.depth_stencil = op->depth_stencil;
+    cs->fb.depth_stencil = op->view;
 
-    if (!prev != !op->depth_stencil)
+    if (!prev != !op->view)
     {
         /* Swapping NULL / non NULL depth stencil affects the depth and tests */
         device_invalidate_state(device, STATE_RENDER(WINED3D_RS_ZENABLE));
@@ -396,7 +434,7 @@ static void wined3d_cs_exec_set_depth_stencil(struct wined3d_cs *cs, const void
         device_invalidate_state(device, STATE_RENDER(WINED3D_RS_STENCILWRITEMASK));
         device_invalidate_state(device, STATE_RENDER(WINED3D_RS_DEPTHBIAS));
     }
-    else if (prev && prev->resource.format->depth_size != op->depth_stencil->resource.format->depth_size)
+    else if (prev && prev->format->depth_size != op->view->format->depth_size)
     {
         device_invalidate_state(device, STATE_RENDER(WINED3D_RS_DEPTHBIAS));
     }
@@ -404,13 +442,13 @@ static void wined3d_cs_exec_set_depth_stencil(struct wined3d_cs *cs, const void
     device_invalidate_state(device, STATE_FRAMEBUFFER);
 }
 
-void wined3d_cs_emit_set_depth_stencil(struct wined3d_cs *cs, struct wined3d_surface *depth_stencil)
+void wined3d_cs_emit_set_depth_stencil_view(struct wined3d_cs *cs, struct wined3d_rendertarget_view *view)
 {
-    struct wined3d_cs_set_depth_stencil *op;
+    struct wined3d_cs_set_depth_stencil_view *op;
 
     op = cs->ops->require_space(cs, sizeof(*op));
-    op->opcode = WINED3D_CS_OP_SET_DEPTH_STENCIL;
-    op->depth_stencil = depth_stencil;
+    op->opcode = WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW;
+    op->view = view;
 
     cs->ops->submit(cs);
 }
@@ -567,6 +605,8 @@ static void wined3d_cs_exec_set_constant_buffer(struct wined3d_cs *cs, const voi
         InterlockedIncrement(&op->buffer->resource.bind_count);
     if (prev)
         InterlockedDecrement(&prev->resource.bind_count);
+
+    device_invalidate_state(cs->device, STATE_CONSTANT_BUFFER(op->type));
 }
 
 void wined3d_cs_emit_set_constant_buffer(struct wined3d_cs *cs, enum wined3d_shader_type type,
@@ -652,6 +692,27 @@ void wined3d_cs_emit_set_texture(struct wined3d_cs *cs, UINT stage, struct wined
     cs->ops->submit(cs);
 }
 
+static void wined3d_cs_exec_set_shader_resource_view(struct wined3d_cs *cs, const void *data)
+{
+    const struct wined3d_cs_set_shader_resource_view *op = data;
+
+    cs->state.shader_resource_view[op->type][op->view_idx] = op->view;
+}
+
+void wined3d_cs_emit_set_shader_resource_view(struct wined3d_cs *cs, enum wined3d_shader_type type,
+        UINT view_idx, struct wined3d_shader_resource_view *view)
+{
+    struct wined3d_cs_set_shader_resource_view *op;
+
+    op = cs->ops->require_space(cs, sizeof(*op));
+    op->opcode = WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW;
+    op->type = type;
+    op->view_idx = view_idx;
+    op->view = view;
+
+    cs->ops->submit(cs);
+}
+
 static void wined3d_cs_exec_set_sampler(struct wined3d_cs *cs, const void *data)
 {
     const struct wined3d_cs_set_sampler *op = data;
@@ -842,29 +903,31 @@ void wined3d_cs_emit_reset_state(struct wined3d_cs *cs)
 
 static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) =
 {
-    /* WINED3D_CS_OP_PRESENT                */ wined3d_cs_exec_present,
-    /* WINED3D_CS_OP_CLEAR                  */ wined3d_cs_exec_clear,
-    /* WINED3D_CS_OP_DRAW                   */ wined3d_cs_exec_draw,
-    /* WINED3D_CS_OP_SET_VIEWPORT           */ wined3d_cs_exec_set_viewport,
-    /* WINED3D_CS_OP_SET_SCISSOR_RECT       */ wined3d_cs_exec_set_scissor_rect,
-    /* WINED3D_CS_OP_SET_RENDER_TARGET      */ wined3d_cs_exec_set_render_target,
-    /* WINED3D_CS_OP_SET_DEPTH_STENCIL      */ wined3d_cs_exec_set_depth_stencil,
-    /* WINED3D_CS_OP_SET_VERTEX_DECLARATION */ wined3d_cs_exec_set_vertex_declaration,
-    /* WINED3D_CS_OP_SET_STREAM_SOURCE      */ wined3d_cs_exec_set_stream_source,
-    /* WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ */ wined3d_cs_exec_set_stream_source_freq,
-    /* WINED3D_CS_OP_SET_STREAM_OUTPUT      */ wined3d_cs_exec_set_stream_output,
-    /* WINED3D_CS_OP_SET_INDEX_BUFFER       */ wined3d_cs_exec_set_index_buffer,
-    /* WINED3D_CS_OP_SET_CONSTANT_BUFFER    */ wined3d_cs_exec_set_constant_buffer,
-    /* WINED3D_CS_OP_SET_TEXTURE            */ wined3d_cs_exec_set_texture,
-    /* WINED3D_CS_OP_SET_SAMPLER            */ wined3d_cs_exec_set_sampler,
-    /* WINED3D_CS_OP_SET_SHADER             */ wined3d_cs_exec_set_shader,
-    /* WINED3D_CS_OP_SET_RENDER_STATE       */ wined3d_cs_exec_set_render_state,
-    /* WINED3D_CS_OP_SET_TEXTURE_STATE      */ wined3d_cs_exec_set_texture_state,
-    /* WINED3D_CS_OP_SET_SAMPLER_STATE      */ wined3d_cs_exec_set_sampler_state,
-    /* WINED3D_CS_OP_SET_TRANSFORM          */ wined3d_cs_exec_set_transform,
-    /* WINED3D_CS_OP_SET_CLIP_PLANE         */ wined3d_cs_exec_set_clip_plane,
-    /* WINED3D_CS_OP_SET_MATERIAL           */ wined3d_cs_exec_set_material,
-    /* WINED3D_CS_OP_RESET_STATE            */ wined3d_cs_exec_reset_state,
+    /* WINED3D_CS_OP_PRESENT                    */ wined3d_cs_exec_present,
+    /* WINED3D_CS_OP_CLEAR                      */ wined3d_cs_exec_clear,
+    /* WINED3D_CS_OP_DRAW                       */ wined3d_cs_exec_draw,
+    /* WINED3D_CS_OP_SET_PREDICATION            */ wined3d_cs_exec_set_predication,
+    /* WINED3D_CS_OP_SET_VIEWPORT               */ wined3d_cs_exec_set_viewport,
+    /* WINED3D_CS_OP_SET_SCISSOR_RECT           */ wined3d_cs_exec_set_scissor_rect,
+    /* WINED3D_CS_OP_SET_RENDERTARGET_VIEW      */ wined3d_cs_exec_set_rendertarget_view,
+    /* WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW     */ wined3d_cs_exec_set_depth_stencil_view,
+    /* WINED3D_CS_OP_SET_VERTEX_DECLARATION     */ wined3d_cs_exec_set_vertex_declaration,
+    /* WINED3D_CS_OP_SET_STREAM_SOURCE          */ wined3d_cs_exec_set_stream_source,
+    /* WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ     */ wined3d_cs_exec_set_stream_source_freq,
+    /* WINED3D_CS_OP_SET_STREAM_OUTPUT          */ wined3d_cs_exec_set_stream_output,
+    /* WINED3D_CS_OP_SET_INDEX_BUFFER           */ wined3d_cs_exec_set_index_buffer,
+    /* WINED3D_CS_OP_SET_CONSTANT_BUFFER        */ wined3d_cs_exec_set_constant_buffer,
+    /* WINED3D_CS_OP_SET_TEXTURE                */ wined3d_cs_exec_set_texture,
+    /* WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW   */ wined3d_cs_exec_set_shader_resource_view,
+    /* WINED3D_CS_OP_SET_SAMPLER                */ wined3d_cs_exec_set_sampler,
+    /* WINED3D_CS_OP_SET_SHADER                 */ wined3d_cs_exec_set_shader,
+    /* WINED3D_CS_OP_SET_RENDER_STATE           */ wined3d_cs_exec_set_render_state,
+    /* WINED3D_CS_OP_SET_TEXTURE_STATE          */ wined3d_cs_exec_set_texture_state,
+    /* WINED3D_CS_OP_SET_SAMPLER_STATE          */ wined3d_cs_exec_set_sampler_state,
+    /* WINED3D_CS_OP_SET_TRANSFORM              */ wined3d_cs_exec_set_transform,
+    /* WINED3D_CS_OP_SET_CLIP_PLANE             */ wined3d_cs_exec_set_clip_plane,
+    /* WINED3D_CS_OP_SET_MATERIAL               */ wined3d_cs_exec_set_material,
+    /* WINED3D_CS_OP_RESET_STATE                */ wined3d_cs_exec_reset_state,
 };
 
 static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size)
index 37d9acb..5513a0d 100644 (file)
@@ -82,7 +82,8 @@ GLenum gl_primitive_type_from_d3d(enum wined3d_primitive_type primitive_type)
 
         default:
             FIXME("Unhandled primitive type %s\n", debug_d3dprimitivetype(primitive_type));
-            return GL_NONE;
+        case WINED3D_PT_UNDEFINED:
+            return ~0u;
     }
 }
 
@@ -122,6 +123,7 @@ static enum wined3d_primitive_type d3d_primitive_type_from_gl(GLenum primitive_t
 
         default:
             FIXME("Unhandled primitive type %s\n", debug_d3dprimitivetype(primitive_type));
+        case ~0u:
             return WINED3D_PT_UNDEFINED;
     }
 }
@@ -278,8 +280,10 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c
         UINT rect_count, const RECT *rects, const RECT *draw_rect, DWORD flags, const struct wined3d_color *color,
         float depth, DWORD stencil)
 {
+    struct wined3d_surface *target = rt_count ? wined3d_rendertarget_view_get_surface(fb->render_targets[0]) : NULL;
+    struct wined3d_surface *depth_stencil = fb->depth_stencil
+            ? wined3d_rendertarget_view_get_surface(fb->depth_stencil) : NULL;
     const RECT *clear_rect = (rect_count > 0 && rects) ? (const RECT *)rects : NULL;
-    struct wined3d_surface *target = rt_count ? fb->render_targets[0] : NULL;
     const struct wined3d_gl_info *gl_info;
     UINT drawable_width, drawable_height;
     struct wined3d_context *context;
@@ -300,9 +304,9 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c
     {
         for (i = 0; i < rt_count; ++i)
         {
-            struct wined3d_surface *rt = fb->render_targets[i];
+            struct wined3d_surface *rt = wined3d_rendertarget_view_get_surface(fb->render_targets[i]);
             if (rt)
-                surface_load_location(rt, rt->draw_binding);
+                surface_load_location(rt, rt->container->resource.draw_binding);
         }
     }
 
@@ -318,22 +322,22 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c
     if (target)
     {
         render_offscreen = context->render_offscreen;
-        target->get_drawable_size(context, &drawable_width, &drawable_height);
+        surface_get_drawable_size(target, context, &drawable_width, &drawable_height);
     }
     else
     {
         render_offscreen = TRUE;
-        drawable_width = fb->depth_stencil->pow2Width;
-        drawable_height = fb->depth_stencil->pow2Height;
+        drawable_width = depth_stencil->pow2Width;
+        drawable_height = depth_stencil->pow2Height;
     }
 
     if (flags & WINED3DCLEAR_ZBUFFER)
     {
-        DWORD location = render_offscreen ? fb->depth_stencil->draw_binding : WINED3D_LOCATION_DRAWABLE;
+        DWORD location = render_offscreen ? fb->depth_stencil->resource->draw_binding : WINED3D_LOCATION_DRAWABLE;
 
-        if (!render_offscreen && fb->depth_stencil != device->onscreen_depth_stencil)
-            device_switch_onscreen_ds(device, context, fb->depth_stencil);
-        prepare_ds_clear(fb->depth_stencil, context, location,
+        if (!render_offscreen && depth_stencil != device->onscreen_depth_stencil)
+            device_switch_onscreen_ds(device, context, depth_stencil);
+        prepare_ds_clear(depth_stencil, context, location,
                 draw_rect, rect_count, clear_rect, &ds_rect);
     }
 
@@ -361,9 +365,9 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c
 
     if (flags & WINED3DCLEAR_ZBUFFER)
     {
-        DWORD location = render_offscreen ? fb->depth_stencil->draw_binding : WINED3D_LOCATION_DRAWABLE;
+        DWORD location = render_offscreen ? fb->depth_stencil->resource->draw_binding : WINED3D_LOCATION_DRAWABLE;
 
-        surface_modify_ds_location(fb->depth_stencil, location, ds_rect.right, ds_rect.bottom);
+        surface_modify_ds_location(depth_stencil, location, ds_rect.right, ds_rect.bottom);
 
         gl_info->gl_ops.gl.p_glDepthMask(GL_TRUE);
         context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ZWRITEENABLE));
@@ -376,12 +380,12 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c
     {
         for (i = 0; i < rt_count; ++i)
         {
-            struct wined3d_surface *rt = fb->render_targets[i];
+            struct wined3d_surface *rt = wined3d_rendertarget_view_get_surface(fb->render_targets[i]);
 
             if (rt)
             {
-                surface_validate_location(rt, rt->draw_binding);
-                surface_invalidate_location(rt, ~rt->draw_binding);
+                surface_validate_location(rt, rt->container->resource.draw_binding);
+                surface_invalidate_location(rt, ~rt->container->resource.draw_binding);
             }
         }
 
@@ -452,7 +456,7 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c
     }
 
     if (wined3d_settings.strict_draw_ordering || (flags & WINED3DCLEAR_TARGET
-            && target->swapchain && target->swapchain->front_buffer == target))
+            && target->container->swapchain && target->container->swapchain->front_buffer == target->container))
         gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */
 
     context_release(context);
@@ -599,9 +603,11 @@ static void device_load_logo(struct wined3d_device *device, const char *filename
     }
     else
     {
+        const RECT rect = {0, 0, surface->resource.width, surface->resource.height};
         const struct wined3d_color c = {1.0f, 1.0f, 1.0f, 1.0f};
+
         /* Fill the surface with a white color to show that wined3d is there */
-        wined3d_device_color_fill(device, surface, NULL, &c);
+        surface_color_fill(surface, &rect, &c);
     }
 
 out:
@@ -841,13 +847,13 @@ static void device_init_swapchain_state(struct wined3d_device *device, struct wi
     {
         for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i)
         {
-            wined3d_device_set_render_target(device, i, NULL, FALSE);
+            wined3d_device_set_rendertarget_view(device, i, NULL, FALSE);
         }
-        if (swapchain->back_buffers && swapchain->back_buffers[0])
-            wined3d_device_set_render_target(device, 0, swapchain->back_buffers[0], TRUE);
+        if (device->back_buffer_view)
+            wined3d_device_set_rendertarget_view(device, 0, device->back_buffer_view, TRUE);
     }
 
-    wined3d_device_set_depth_stencil(device, ds_enable ? device->auto_depth_stencil : NULL);
+    wined3d_device_set_depth_stencil_view(device, ds_enable ? device->auto_depth_stencil_view : NULL);
     wined3d_device_set_render_state(device, WINED3D_RS_ZENABLE, ds_enable);
 }
 
@@ -893,6 +899,14 @@ HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device,
         goto err_out;
     }
 
+    if (swapchain_desc->backbuffer_count && FAILED(hr = wined3d_rendertarget_view_create_from_surface(
+            surface_from_resource(wined3d_texture_get_sub_resource(swapchain->back_buffers[0], 0)),
+            NULL, &wined3d_null_parent_ops, &device->back_buffer_view)))
+    {
+        ERR("Failed to create rendertarget view, hr %#x.\n", hr);
+        goto err_out;
+    }
+
     device->swapchain_count = 1;
     device->swapchains = HeapAlloc(GetProcessHeap(), 0, device->swapchain_count * sizeof(*device->swapchains));
     if (!device->swapchains)
@@ -903,7 +917,8 @@ HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device,
     device->swapchains[0] = swapchain;
     device_init_swapchain_state(device, swapchain);
 
-    context = context_acquire(device, swapchain->front_buffer);
+    context = context_acquire(device,
+            surface_from_resource(wined3d_texture_get_sub_resource(swapchain->front_buffer, 0)));
 
     create_dummy_textures(device, context);
 
@@ -952,6 +967,8 @@ err_out:
     HeapFree(GetProcessHeap(), 0, device->fb.render_targets);
     HeapFree(GetProcessHeap(), 0, device->swapchains);
     device->swapchain_count = 0;
+    if (device->back_buffer_view)
+        wined3d_rendertarget_view_decref(device->back_buffer_view);
     if (swapchain)
         wined3d_swapchain_decref(swapchain);
     if (device->blit_priv)
@@ -1053,25 +1070,31 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device)
 
     if (device->fb.depth_stencil)
     {
-        surface = device->fb.depth_stencil;
+        struct wined3d_rendertarget_view *view = device->fb.depth_stencil;
 
-        TRACE("Releasing depth/stencil buffer %p.\n", surface);
+        TRACE("Releasing depth/stencil view %p.\n", view);
 
         device->fb.depth_stencil = NULL;
-        wined3d_surface_decref(surface);
+        wined3d_rendertarget_view_decref(view);
     }
 
-    if (device->auto_depth_stencil)
+    if (device->auto_depth_stencil_view)
     {
-        surface = device->auto_depth_stencil;
-        device->auto_depth_stencil = NULL;
-        if (wined3d_surface_decref(surface))
-            FIXME("Something's still holding the auto depth stencil buffer (%p).\n", surface);
+        struct wined3d_rendertarget_view *view = device->auto_depth_stencil_view;
+
+        device->auto_depth_stencil_view = NULL;
+        if (wined3d_rendertarget_view_decref(view))
+            ERR("Something's still holding the auto depth/stencil view (%p).\n", view);
     }
 
     for (i = 0; i < gl_info->limits.buffers; ++i)
     {
-        wined3d_device_set_render_target(device, i, NULL, FALSE);
+        wined3d_device_set_rendertarget_view(device, i, NULL, FALSE);
+    }
+    if (device->back_buffer_view)
+    {
+        wined3d_rendertarget_view_decref(device->back_buffer_view);
+        device->back_buffer_view = NULL;
     }
 
     context_release(context);
@@ -1130,11 +1153,12 @@ UINT CDECL wined3d_device_get_available_texture_mem(const struct wined3d_device
 {
     TRACE("device %p.\n", device);
 
-    TRACE("Emulating %d MB, returning %d MB left.\n",
-            device->adapter->TextureRam / (1024 * 1024),
-            (device->adapter->TextureRam - device->adapter->UsedTextureRam) / (1024 * 1024));
+    TRACE("Emulating 0x%s bytes. 0x%s used, returning 0x%s left.\n",
+            wine_dbgstr_longlong(device->adapter->vram_bytes),
+            wine_dbgstr_longlong(device->adapter->vram_bytes_used),
+            wine_dbgstr_longlong(device->adapter->vram_bytes - device->adapter->vram_bytes_used));
 
-    return device->adapter->TextureRam - device->adapter->UsedTextureRam;
+    return min(UINT_MAX, device->adapter->vram_bytes - device->adapter->vram_bytes_used);
 }
 
 void CDECL wined3d_device_set_stream_output(struct wined3d_device *device, UINT idx,
@@ -1246,8 +1270,6 @@ HRESULT CDECL wined3d_device_get_stream_source(const struct wined3d_device *devi
 
     stream = &device->state.streams[stream_idx];
     *buffer = stream->buffer;
-    if (*buffer)
-        wined3d_buffer_incref(*buffer);
     if (offset)
         *offset = stream->offset;
     *stride = stream->stride;
@@ -1880,8 +1902,7 @@ static void resolve_depth_buffer(struct wined3d_state *state)
             || !(texture->resource.format->flags & WINED3DFMT_FLAG_DEPTH))
         return;
     surface = surface_from_resource(texture->sub_resources[0]);
-    depth_stencil = state->fb->depth_stencil;
-    if (!depth_stencil)
+    if (!(depth_stencil = wined3d_rendertarget_view_get_surface(state->fb->depth_stencil)))
         return;
 
     wined3d_surface_blt(surface, NULL, depth_stencil, NULL, 0, NULL, WINED3D_TEXF_POINT);
@@ -2111,6 +2132,52 @@ struct wined3d_buffer * CDECL wined3d_device_get_vs_cb(const struct wined3d_devi
     return device->state.cb[WINED3D_SHADER_TYPE_VERTEX][idx];
 }
 
+static void wined3d_device_set_shader_resource_view(struct wined3d_device *device,
+        enum wined3d_shader_type type, UINT idx, struct wined3d_shader_resource_view *view)
+{
+    struct wined3d_shader_resource_view *prev;
+
+    if (idx >= MAX_SHADER_RESOURCE_VIEWS)
+    {
+        WARN("Invalid view index %u.\n", idx);
+        return;
+    }
+
+    prev = device->update_state->shader_resource_view[type][idx];
+    if (view == prev)
+        return;
+
+    if (view)
+        wined3d_shader_resource_view_incref(view);
+    device->update_state->shader_resource_view[type][idx] = view;
+    if (!device->recording)
+        wined3d_cs_emit_set_shader_resource_view(device->cs, type, idx, view);
+    if (prev)
+        wined3d_shader_resource_view_decref(prev);
+}
+
+void CDECL wined3d_device_set_vs_resource_view(struct wined3d_device *device,
+        UINT idx, struct wined3d_shader_resource_view *view)
+{
+    TRACE("device %p, idx %u, view %p.\n", device, idx, view);
+
+    wined3d_device_set_shader_resource_view(device, WINED3D_SHADER_TYPE_VERTEX, idx, view);
+}
+
+struct wined3d_shader_resource_view * CDECL wined3d_device_get_vs_resource_view(const struct wined3d_device *device,
+        UINT idx)
+{
+    TRACE("device %p, idx %u.\n", device, idx);
+
+    if (idx >= MAX_SHADER_RESOURCE_VIEWS)
+    {
+        WARN("Invalid view index %u.\n", idx);
+        return NULL;
+    }
+
+    return device->state.shader_resource_view[WINED3D_SHADER_TYPE_VERTEX][idx];
+}
+
 static void wined3d_device_set_sampler(struct wined3d_device *device,
         enum wined3d_shader_type type, UINT idx, struct wined3d_sampler *sampler)
 {
@@ -2357,6 +2424,28 @@ struct wined3d_buffer * CDECL wined3d_device_get_ps_cb(const struct wined3d_devi
     return device->state.cb[WINED3D_SHADER_TYPE_PIXEL][idx];
 }
 
+void CDECL wined3d_device_set_ps_resource_view(struct wined3d_device *device,
+        UINT idx, struct wined3d_shader_resource_view *view)
+{
+    TRACE("device %p, idx %u, view %p.\n", device, idx, view);
+
+    wined3d_device_set_shader_resource_view(device, WINED3D_SHADER_TYPE_PIXEL, idx, view);
+}
+
+struct wined3d_shader_resource_view * CDECL wined3d_device_get_ps_resource_view(const struct wined3d_device *device,
+        UINT idx)
+{
+    TRACE("device %p, idx %u.\n", device, idx);
+
+    if (idx >= MAX_SHADER_RESOURCE_VIEWS)
+    {
+        WARN("Invalid view index %u.\n", idx);
+        return NULL;
+    }
+
+    return device->state.shader_resource_view[WINED3D_SHADER_TYPE_PIXEL][idx];
+}
+
 void CDECL wined3d_device_set_ps_sampler(struct wined3d_device *device, UINT idx, struct wined3d_sampler *sampler)
 {
     TRACE("device %p, idx %u, sampler %p.\n", device, idx, sampler);
@@ -2564,6 +2653,28 @@ struct wined3d_buffer * CDECL wined3d_device_get_gs_cb(const struct wined3d_devi
     return device->state.cb[WINED3D_SHADER_TYPE_GEOMETRY][idx];
 }
 
+void CDECL wined3d_device_set_gs_resource_view(struct wined3d_device *device,
+        UINT idx, struct wined3d_shader_resource_view *view)
+{
+    TRACE("device %p, idx %u, view %p.\n", device, idx, view);
+
+    wined3d_device_set_shader_resource_view(device, WINED3D_SHADER_TYPE_GEOMETRY, idx, view);
+}
+
+struct wined3d_shader_resource_view * CDECL wined3d_device_get_gs_resource_view(const struct wined3d_device *device,
+        UINT idx)
+{
+    TRACE("device %p, idx %u.\n", device, idx);
+
+    if (idx >= MAX_SHADER_RESOURCE_VIEWS)
+    {
+        WARN("Invalid view index %u.\n", idx);
+        return NULL;
+    }
+
+    return device->state.shader_resource_view[WINED3D_SHADER_TYPE_GEOMETRY][idx];
+}
+
 void CDECL wined3d_device_set_gs_sampler(struct wined3d_device *device, UINT idx, struct wined3d_sampler *sampler)
 {
     TRACE("device %p, idx %u, sampler %p.\n", device, idx, sampler);
@@ -2862,6 +2973,7 @@ HRESULT CDECL wined3d_device_process_vertices(struct wined3d_device *device,
     struct wined3d_shader *vs;
     unsigned int i;
     HRESULT hr;
+    WORD map;
 
     TRACE("device %p, src_start_idx %u, dst_idx %u, vertex_count %u, "
             "dst_buffer %p, declaration %p, flags %#x, dst_fvf %#x.\n",
@@ -2885,21 +2997,22 @@ HRESULT CDECL wined3d_device_process_vertices(struct wined3d_device *device,
      * VBOs in those buffers and fix up the stream_info structure.
      *
      * Also apply the start index. */
-    for (i = 0; i < (sizeof(stream_info.elements) / sizeof(*stream_info.elements)); ++i)
+    for (i = 0, map = stream_info.use_map; map; map >>= 1, ++i)
     {
         struct wined3d_stream_info_element *e;
+        struct wined3d_buffer *buffer;
 
-        if (!(stream_info.use_map & (1 << i)))
+        if (!(map & 1))
             continue;
 
         e = &stream_info.elements[i];
-        if (e->data.buffer_object)
+        buffer = state->streams[e->stream_idx].buffer;
+        e->data.buffer_object = 0;
+        e->data.addr += (ULONG_PTR)buffer_get_sysmem(buffer, context);
+        if (buffer->buffer_object)
         {
-            struct wined3d_buffer *vb = state->streams[e->stream_idx].buffer;
-            e->data.buffer_object = 0;
-            e->data.addr = (BYTE *)((ULONG_PTR)e->data.addr + (ULONG_PTR)buffer_get_sysmem(vb, context));
-            GL_EXTCALL(glDeleteBuffersARB(1, &vb->buffer_object));
-            vb->buffer_object = 0;
+            GL_EXTCALL(glDeleteBuffersARB(1, &buffer->buffer_object));
+            buffer->buffer_object = 0;
         }
         if (e->data.addr)
             e->data.addr += e->stride * src_start_idx;
@@ -3189,7 +3302,7 @@ HRESULT CDECL wined3d_device_clear(struct wined3d_device *device, DWORD rect_cou
 
     if (flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL))
     {
-        struct wined3d_surface *ds = device->fb.depth_stencil;
+        struct wined3d_rendertarget_view *ds = device->fb.depth_stencil;
         if (!ds)
         {
             WARN("Clearing depth and/or stencil without a depth stencil buffer attached, returning WINED3DERR_INVALIDCALL\n");
@@ -3198,8 +3311,8 @@ HRESULT CDECL wined3d_device_clear(struct wined3d_device *device, DWORD rect_cou
         }
         else if (flags & WINED3DCLEAR_TARGET)
         {
-            if (ds->resource.width < device->fb.render_targets[0]->resource.width
-                    || ds->resource.height < device->fb.render_targets[0]->resource.height)
+            if (ds->width < device->fb.render_targets[0]->width
+                    || ds->height < device->fb.render_targets[0]->height)
             {
                 WARN("Silently ignoring depth and target clear with mismatching sizes\n");
                 return WINED3D_OK;
@@ -3212,6 +3325,35 @@ HRESULT CDECL wined3d_device_clear(struct wined3d_device *device, DWORD rect_cou
     return WINED3D_OK;
 }
 
+void CDECL wined3d_device_set_predication(struct wined3d_device *device,
+        struct wined3d_query *predicate, BOOL value)
+{
+    struct wined3d_query *prev;
+
+    TRACE("device %p, predicate %p, value %#x.\n", device, predicate, value);
+
+    prev = device->update_state->predicate;
+    if (predicate)
+    {
+        FIXME("Predicated rendering not implemented.\n");
+        wined3d_query_incref(predicate);
+    }
+    device->update_state->predicate = predicate;
+    device->update_state->predicate_value = value;
+    if (!device->recording)
+        wined3d_cs_emit_set_predication(device->cs, predicate, value);
+    if (prev)
+        wined3d_query_decref(prev);
+}
+
+struct wined3d_query * CDECL wined3d_device_get_predication(struct wined3d_device *device, BOOL *value)
+{
+    TRACE("device %p, value %p.\n", device, value);
+
+    *value = device->state.predicate_value;
+    return device->state.predicate;
+}
+
 void CDECL wined3d_device_set_primitive_type(struct wined3d_device *device,
         enum wined3d_primitive_type primitive_type)
 {
@@ -3517,11 +3659,10 @@ HRESULT CDECL wined3d_device_validate_device(const struct wined3d_device *device
     if (state->render_states[WINED3D_RS_ZENABLE] || state->render_states[WINED3D_RS_ZWRITEENABLE]
             || state->render_states[WINED3D_RS_STENCILENABLE])
     {
-        struct wined3d_surface *ds = device->fb.depth_stencil;
-        struct wined3d_surface *target = device->fb.render_targets[0];
+        struct wined3d_rendertarget_view *rt = device->fb.render_targets[0];
+        struct wined3d_rendertarget_view *ds = device->fb.depth_stencil;
 
-        if(ds && target
-                && (ds->resource.width < target->resource.width || ds->resource.height < target->resource.height))
+        if (ds && rt && (ds->width < rt->width || ds->height < rt->height))
         {
             WARN("Depth stencil is smaller than the color buffer, returning D3DERR_CONFLICTINGRENDERSTATE\n");
             return WINED3DERR_CONFLICTINGRENDERSTATE;
@@ -3630,148 +3771,208 @@ HRESULT CDECL wined3d_device_update_surface(struct wined3d_device *device,
     return surface_upload_from_surface(dst_surface, dst_point, src_surface, src_rect);
 }
 
-HRESULT CDECL wined3d_device_color_fill(struct wined3d_device *device,
-        struct wined3d_surface *surface, const RECT *rect, const struct wined3d_color *color)
+void CDECL wined3d_device_copy_resource(struct wined3d_device *device,
+        struct wined3d_resource *dst_resource, struct wined3d_resource *src_resource)
 {
-    RECT r;
+    struct wined3d_surface *dst_surface, *src_surface;
+    struct wined3d_texture *dst_texture, *src_texture;
+    unsigned int i, count;
+    HRESULT hr;
 
-    TRACE("device %p, surface %p, rect %s, color {%.8e, %.8e, %.8e, %.8e}.\n",
-            device, surface, wine_dbgstr_rect(rect),
-            color->r, color->g, color->b, color->a);
+    TRACE("device %p, dst_resource %p, src_resource %p.\n", device, dst_resource, src_resource);
 
-    if (surface->resource.pool != WINED3D_POOL_DEFAULT && surface->resource.pool != WINED3D_POOL_SYSTEM_MEM)
+    if (src_resource == dst_resource)
     {
-        WARN("Color-fill not allowed on %s surfaces.\n", debug_d3dpool(surface->resource.pool));
-        return WINED3DERR_INVALIDCALL;
+        WARN("Source and destination are the same resource.\n");
+        return;
     }
 
-    if (!rect)
+    if (src_resource->type != dst_resource->type)
     {
-        SetRect(&r, 0, 0, surface->resource.width, surface->resource.height);
-        rect = &r;
+        WARN("Resource types (%s / %s) don't match.\n",
+                debug_d3dresourcetype(dst_resource->type),
+                debug_d3dresourcetype(src_resource->type));
+        return;
+    }
+
+    if (src_resource->width != dst_resource->width
+            || src_resource->height != dst_resource->height
+            || src_resource->depth != dst_resource->depth)
+    {
+        WARN("Resource dimensions (%ux%ux%u / %ux%ux%u) don't match.\n",
+                dst_resource->width, dst_resource->height, dst_resource->depth,
+                src_resource->width, src_resource->height, src_resource->depth);
+        return;
+    }
+
+    if (src_resource->format->id != dst_resource->format->id)
+    {
+        WARN("Resource formats (%s / %s) don't match.\n",
+                debug_d3dformat(dst_resource->format->id),
+                debug_d3dformat(src_resource->format->id));
+        return;
     }
 
-    return surface_color_fill(surface, rect, color);
+    if (dst_resource->type != WINED3D_RTYPE_TEXTURE)
+    {
+        FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(dst_resource->type));
+        return;
+    }
+
+    dst_texture = wined3d_texture_from_resource(dst_resource);
+    src_texture = wined3d_texture_from_resource(src_resource);
+
+    if (src_texture->layer_count != dst_texture->layer_count
+            || src_texture->level_count != dst_texture->level_count)
+    {
+        WARN("Subresource layouts (%ux%u / %ux%u) don't match.\n",
+                dst_texture->layer_count, dst_texture->level_count,
+                src_texture->layer_count, src_texture->level_count);
+        return;
+    }
+
+    count = dst_texture->layer_count * dst_texture->level_count;
+    for (i = 0; i < count; ++i)
+    {
+        dst_surface = surface_from_resource(wined3d_texture_get_sub_resource(dst_texture, i));
+        src_surface = surface_from_resource(wined3d_texture_get_sub_resource(src_texture, i));
+
+        if (FAILED(hr = wined3d_surface_blt(dst_surface, NULL, src_surface, NULL, 0, NULL, WINED3D_TEXF_POINT)))
+            ERR("Failed to blit, subresource %u, hr %#x.\n", i, hr);
+    }
 }
 
-void CDECL wined3d_device_clear_rendertarget_view(struct wined3d_device *device,
-        struct wined3d_rendertarget_view *rendertarget_view, const struct wined3d_color *color)
+HRESULT CDECL wined3d_device_clear_rendertarget_view(struct wined3d_device *device,
+        struct wined3d_rendertarget_view *view, const RECT *rect, const struct wined3d_color *color)
 {
     struct wined3d_resource *resource;
-    HRESULT hr;
-    RECT rect;
+    RECT r;
+
+    TRACE("device %p, view %p, rect %s, color {%.8e, %.8e, %.8e, %.8e}.\n",
+            device, view, wine_dbgstr_rect(rect), color->r, color->g, color->b, color->a);
 
-    resource = rendertarget_view->resource;
-    if (resource->type != WINED3D_RTYPE_SURFACE)
+    resource = view->resource;
+    if (resource->type != WINED3D_RTYPE_TEXTURE && resource->type != WINED3D_RTYPE_CUBE_TEXTURE)
     {
-        FIXME("Only supported on surface resources\n");
-        return;
+        FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(resource->type));
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    if (view->depth > 1)
+    {
+        FIXME("Layered clears not implemented.\n");
+        return WINED3DERR_INVALIDCALL;
     }
 
-    SetRect(&rect, 0, 0, resource->width, resource->height);
-    hr = surface_color_fill(surface_from_resource(resource), &rect, color);
-    if (FAILED(hr)) ERR("Color fill failed, hr %#x.\n", hr);
+    if (!rect)
+    {
+        SetRect(&r, 0, 0, view->width, view->height);
+        rect = &r;
+    }
+
+    resource = wined3d_texture_get_sub_resource(wined3d_texture_from_resource(resource), view->sub_resource_idx);
+
+    return surface_color_fill(surface_from_resource(resource), rect, color);
 }
 
-struct wined3d_surface * CDECL wined3d_device_get_render_target(const struct wined3d_device *device,
-        UINT render_target_idx)
+struct wined3d_rendertarget_view * CDECL wined3d_device_get_rendertarget_view(const struct wined3d_device *device,
+        unsigned int view_idx)
 {
-    TRACE("device %p, render_target_idx %u.\n", device, render_target_idx);
+    TRACE("device %p, view_idx %u.\n", device, view_idx);
 
-    if (render_target_idx >= device->adapter->gl_info.limits.buffers)
+    if (view_idx >= device->adapter->gl_info.limits.buffers)
     {
         WARN("Only %u render targets are supported.\n", device->adapter->gl_info.limits.buffers);
         return NULL;
     }
 
-    return device->fb.render_targets[render_target_idx];
+    return device->fb.render_targets[view_idx];
 }
 
-struct wined3d_surface * CDECL wined3d_device_get_depth_stencil(const struct wined3d_device *device)
+struct wined3d_rendertarget_view * CDECL wined3d_device_get_depth_stencil_view(const struct wined3d_device *device)
 {
     TRACE("device %p.\n", device);
 
     return device->fb.depth_stencil;
 }
 
-HRESULT CDECL wined3d_device_set_render_target(struct wined3d_device *device,
-        UINT render_target_idx, struct wined3d_surface *render_target, BOOL set_viewport)
+HRESULT CDECL wined3d_device_set_rendertarget_view(struct wined3d_device *device,
+        unsigned int view_idx, struct wined3d_rendertarget_view *view, BOOL set_viewport)
 {
-    struct wined3d_surface *prev;
+    struct wined3d_rendertarget_view *prev;
 
-    TRACE("device %p, render_target_idx %u, render_target %p, set_viewport %#x.\n",
-            device, render_target_idx, render_target, set_viewport);
+    TRACE("device %p, view_idx %u, view %p, set_viewport %#x.\n",
+            device, view_idx, view, set_viewport);
 
-    if (render_target_idx >= device->adapter->gl_info.limits.buffers)
+    if (view_idx >= device->adapter->gl_info.limits.buffers)
     {
         WARN("Only %u render targets are supported.\n", device->adapter->gl_info.limits.buffers);
         return WINED3DERR_INVALIDCALL;
     }
 
-    if (render_target && !(render_target->resource.usage & WINED3DUSAGE_RENDERTARGET))
+    if (view && !(view->resource->usage & WINED3DUSAGE_RENDERTARGET))
     {
-        WARN("Surface %p doesn't have render target usage.\n", render_target);
+        WARN("View resource %p doesn't have render target usage.\n", view->resource);
         return WINED3DERR_INVALIDCALL;
     }
 
     /* Set the viewport and scissor rectangles, if requested. Tests show that
      * stateblock recording is ignored, the change goes directly into the
      * primary stateblock. */
-    if (!render_target_idx && set_viewport)
+    if (!view_idx && set_viewport)
     {
         struct wined3d_state *state = &device->state;
 
         state->viewport.x = 0;
         state->viewport.y = 0;
-        state->viewport.width = render_target->resource.width;
-        state->viewport.height = render_target->resource.height;
+        state->viewport.width = view->width;
+        state->viewport.height = view->height;
         state->viewport.min_z = 0.0f;
         state->viewport.max_z = 1.0f;
         wined3d_cs_emit_set_viewport(device->cs, &state->viewport);
 
         state->scissor_rect.top = 0;
         state->scissor_rect.left = 0;
-        state->scissor_rect.right = render_target->resource.width;
-        state->scissor_rect.bottom = render_target->resource.height;
+        state->scissor_rect.right = view->width;
+        state->scissor_rect.bottom = view->height;
         wined3d_cs_emit_set_scissor_rect(device->cs, &state->scissor_rect);
     }
 
 
-    prev = device->fb.render_targets[render_target_idx];
-    if (render_target == prev)
+    prev = device->fb.render_targets[view_idx];
+    if (view == prev)
         return WINED3D_OK;
 
-    if (render_target)
-        wined3d_surface_incref(render_target);
-    device->fb.render_targets[render_target_idx] = render_target;
-    wined3d_cs_emit_set_render_target(device->cs, render_target_idx, render_target);
+    if (view)
+        wined3d_rendertarget_view_incref(view);
+    device->fb.render_targets[view_idx] = view;
+    wined3d_cs_emit_set_rendertarget_view(device->cs, view_idx, view);
     /* Release after the assignment, to prevent device_resource_released()
      * from seeing the surface as still in use. */
     if (prev)
-        wined3d_surface_decref(prev);
+        wined3d_rendertarget_view_decref(prev);
 
     return WINED3D_OK;
 }
 
-void CDECL wined3d_device_set_depth_stencil(struct wined3d_device *device, struct wined3d_surface *depth_stencil)
+void CDECL wined3d_device_set_depth_stencil_view(struct wined3d_device *device, struct wined3d_rendertarget_view *view)
 {
-    struct wined3d_surface *prev = device->fb.depth_stencil;
+    struct wined3d_rendertarget_view *prev;
 
-    TRACE("device %p, depth_stencil %p, old depth_stencil %p.\n",
-            device, depth_stencil, prev);
+    TRACE("device %p, view %p.\n", device, view);
 
-    if (prev == depth_stencil)
+    prev = device->fb.depth_stencil;
+    if (prev == view)
     {
         TRACE("Trying to do a NOP SetRenderTarget operation.\n");
         return;
     }
 
-    device->fb.depth_stencil = depth_stencil;
-    if (depth_stencil)
-        wined3d_surface_incref(depth_stencil);
-    wined3d_cs_emit_set_depth_stencil(device->cs, depth_stencil);
+    if ((device->fb.depth_stencil = view))
+        wined3d_rendertarget_view_incref(view);
+    wined3d_cs_emit_set_depth_stencil_view(device->cs, view);
     if (prev)
-        wined3d_surface_decref(prev);
+        wined3d_rendertarget_view_decref(prev);
 }
 
 static struct wined3d_texture *wined3d_device_create_cursor_texture(struct wined3d_device *device,
@@ -4085,7 +4286,9 @@ static HRESULT create_primary_opengl_context(struct wined3d_device *device, stru
         return E_OUTOFMEMORY;
     }
 
-    target = swapchain->back_buffers ? swapchain->back_buffers[0] : swapchain->front_buffer;
+    target = swapchain->back_buffers
+            ? surface_from_resource(wined3d_texture_get_sub_resource(swapchain->back_buffers[0], 0))
+            : surface_from_resource(wined3d_texture_get_sub_resource(swapchain->front_buffer, 0));
     if (!(context = context_create(swapchain, target, swapchain->ds_format)))
     {
         WARN("Failed to create context.\n");
@@ -4144,12 +4347,10 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
     {
         for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i)
         {
-            wined3d_device_set_render_target(device, i, NULL, FALSE);
+            wined3d_device_set_rendertarget_view(device, i, NULL, FALSE);
         }
-        if (swapchain->back_buffers && swapchain->back_buffers[0])
-            wined3d_device_set_render_target(device, 0, swapchain->back_buffers[0], FALSE);
     }
-    wined3d_device_set_depth_stencil(device, NULL);
+    wined3d_device_set_depth_stencil_view(device, NULL);
 
     if (device->onscreen_depth_stencil)
     {
@@ -4216,35 +4417,6 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
         wined3d_swapchain_set_window(swapchain, NULL);
     }
 
-    if (swapchain_desc->enable_auto_depth_stencil && !device->auto_depth_stencil)
-    {
-        struct wined3d_resource_desc surface_desc;
-
-        TRACE("Creating the depth stencil buffer\n");
-
-        surface_desc.resource_type = WINED3D_RTYPE_SURFACE;
-        surface_desc.format = swapchain_desc->auto_depth_stencil_format;
-        surface_desc.multisample_type = swapchain_desc->multisample_type;
-        surface_desc.multisample_quality = swapchain_desc->multisample_quality;
-        surface_desc.usage = WINED3DUSAGE_DEPTHSTENCIL;
-        surface_desc.pool = WINED3D_POOL_DEFAULT;
-        surface_desc.width = swapchain_desc->backbuffer_width;
-        surface_desc.height = swapchain_desc->backbuffer_height;
-        surface_desc.depth = 1;
-        surface_desc.size = 0;
-
-        if (FAILED(hr = device->device_parent->ops->create_swapchain_surface(device->device_parent,
-                device->device_parent, &surface_desc, &device->auto_depth_stencil)))
-        {
-            ERR("Failed to create the depth stencil buffer, hr %#x.\n", hr);
-            return WINED3DERR_INVALIDCALL;
-        }
-    }
-
-    /* Reset the depth stencil */
-    if (swapchain_desc->enable_auto_depth_stencil)
-        wined3d_device_set_depth_stencil(device, device->auto_depth_stencil);
-
     if (mode)
     {
         DisplayModeChanged = TRUE;
@@ -4317,25 +4489,75 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
     {
         UINT i;
 
-        if (FAILED(hr = wined3d_surface_update_desc(swapchain->front_buffer, swapchain->desc.backbuffer_width,
+        if (FAILED(hr = wined3d_surface_update_desc(surface_from_resource(
+                wined3d_texture_get_sub_resource(swapchain->front_buffer, 0)), swapchain->desc.backbuffer_width,
                 swapchain->desc.backbuffer_height, swapchain->desc.backbuffer_format,
                 swapchain->desc.multisample_type, swapchain->desc.multisample_quality, NULL, 0)))
             return hr;
 
         for (i = 0; i < swapchain->desc.backbuffer_count; ++i)
         {
-            if (FAILED(hr = wined3d_surface_update_desc(swapchain->back_buffers[i], swapchain->desc.backbuffer_width,
+            if (FAILED(hr = wined3d_surface_update_desc(surface_from_resource(
+                    wined3d_texture_get_sub_resource(swapchain->back_buffers[i], 0)), swapchain->desc.backbuffer_width,
                     swapchain->desc.backbuffer_height, swapchain->desc.backbuffer_format,
                     swapchain->desc.multisample_type, swapchain->desc.multisample_quality, NULL, 0)))
                 return hr;
         }
-        if (device->auto_depth_stencil)
+    }
+
+    if (device->auto_depth_stencil_view)
+    {
+        wined3d_rendertarget_view_decref(device->auto_depth_stencil_view);
+        device->auto_depth_stencil_view = NULL;
+    }
+    if (swapchain->desc.enable_auto_depth_stencil)
+    {
+        struct wined3d_resource_desc surface_desc;
+        struct wined3d_surface *surface;
+
+        TRACE("Creating the depth stencil buffer\n");
+
+        surface_desc.resource_type = WINED3D_RTYPE_SURFACE;
+        surface_desc.format = swapchain->desc.auto_depth_stencil_format;
+        surface_desc.multisample_type = swapchain->desc.multisample_type;
+        surface_desc.multisample_quality = swapchain->desc.multisample_quality;
+        surface_desc.usage = WINED3DUSAGE_DEPTHSTENCIL;
+        surface_desc.pool = WINED3D_POOL_DEFAULT;
+        surface_desc.width = swapchain->desc.backbuffer_width;
+        surface_desc.height = swapchain->desc.backbuffer_height;
+        surface_desc.depth = 1;
+        surface_desc.size = 0;
+
+        if (FAILED(hr = device->device_parent->ops->create_swapchain_surface(device->device_parent,
+                device->device_parent, &surface_desc, &surface)))
         {
-            if (FAILED(hr = wined3d_surface_update_desc(device->auto_depth_stencil, swapchain->desc.backbuffer_width,
-                    swapchain->desc.backbuffer_height, device->auto_depth_stencil->resource.format->id,
-                    swapchain->desc.multisample_type, swapchain->desc.multisample_quality, NULL, 0)))
-                return hr;
+            ERR("Failed to create the auto depth/stencil surface, hr %#x.\n", hr);
+            return WINED3DERR_INVALIDCALL;
         }
+
+        hr = wined3d_rendertarget_view_create_from_surface(surface,
+                NULL, &wined3d_null_parent_ops, &device->auto_depth_stencil_view);
+        wined3d_surface_decref(surface);
+        if (FAILED(hr))
+        {
+            ERR("Failed to create rendertarget view, hr %#x.\n", hr);
+            return hr;
+        }
+
+        wined3d_device_set_depth_stencil_view(device, device->auto_depth_stencil_view);
+    }
+
+    if (device->back_buffer_view)
+    {
+        wined3d_rendertarget_view_decref(device->back_buffer_view);
+        device->back_buffer_view = NULL;
+    }
+    if (swapchain->desc.backbuffer_count && FAILED(hr = wined3d_rendertarget_view_create_from_surface(
+            surface_from_resource(wined3d_texture_get_sub_resource(swapchain->back_buffers[0], 0)),
+            NULL, &wined3d_null_parent_ops, &device->back_buffer_view)))
+    {
+        ERR("Failed to create rendertarget view, hr %#x.\n", hr);
+        return hr;
     }
 
     if (!swapchain_desc->windowed != !swapchain->desc.windowed
@@ -4420,22 +4642,24 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
 
         device_init_swapchain_state(device, swapchain);
     }
-    else
+    else if (device->back_buffer_view)
     {
-        struct wined3d_surface *rt = device->fb.render_targets[0];
+        struct wined3d_rendertarget_view *view = device->back_buffer_view;
         struct wined3d_state *state = &device->state;
 
+        wined3d_device_set_rendertarget_view(device, 0, view, FALSE);
+
         /* Note the min_z / max_z is not reset. */
         state->viewport.x = 0;
         state->viewport.y = 0;
-        state->viewport.width = rt->resource.width;
-        state->viewport.height = rt->resource.height;
+        state->viewport.width = view->width;
+        state->viewport.height = view->height;
         wined3d_cs_emit_set_viewport(device->cs, &state->viewport);
 
         state->scissor_rect.top = 0;
         state->scissor_rect.left = 0;
-        state->scissor_rect.right = rt->resource.width;
-        state->scissor_rect.bottom = rt->resource.height;
+        state->scissor_rect.right = view->width;
+        state->scissor_rect.bottom = view->height;
         wined3d_cs_emit_set_scissor_rect(device->cs, &state->scissor_rect);
     }
 
@@ -4526,14 +4750,14 @@ void device_resource_released(struct wined3d_device *device, struct wined3d_reso
 
                 for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i)
                 {
-                    if (device->fb.render_targets[i] == surface)
+                    if (wined3d_rendertarget_view_get_surface(device->fb.render_targets[i]) == surface)
                     {
                         ERR("Surface %p is still in use as render target %u.\n", surface, i);
                         device->fb.render_targets[i] = NULL;
                     }
                 }
 
-                if (device->fb.depth_stencil == surface)
+                if (wined3d_rendertarget_view_get_surface(device->fb.depth_stencil) == surface)
                 {
                     ERR("Surface %p is still in use as depth/stencil buffer.\n", surface);
                     device->fb.depth_stencil = NULL;
@@ -4725,23 +4949,6 @@ void device_invalidate_state(const struct wined3d_device *device, DWORD state)
     }
 }
 
-void get_drawable_size_fbo(const struct wined3d_context *context, UINT *width, UINT *height)
-{
-    /* The drawable size of a fbo target is the opengl texture size, which is the power of two size. */
-    *width = context->current_rt->pow2Width;
-    *height = context->current_rt->pow2Height;
-}
-
-void get_drawable_size_backbuffer(const struct wined3d_context *context, UINT *width, UINT *height)
-{
-    const struct wined3d_swapchain *swapchain = context->swapchain;
-    /* The drawable size of a backbuffer / aux buffer offscreen target is the size of the
-     * current context's drawable, which is the size of the back buffer of the swapchain
-     * the active context belongs to. */
-    *width = swapchain->desc.backbuffer_width;
-    *height = swapchain->desc.backbuffer_height;
-}
-
 LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL unicode,
         UINT message, WPARAM wparam, LPARAM lparam, WNDPROC proc)
 {
@@ -4767,6 +4974,10 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL
     {
         device->device_parent->ops->mode_changed(device->device_parent);
     }
+    else if (message == WM_ACTIVATEAPP)
+    {
+        device->device_parent->ops->activate(device->device_parent, wparam);
+    }
 
     if (unicode)
         return CallWindowProcW(proc, window, message, wparam, lparam);
index 4ecbf6e..4927a0e 100644 (file)
 
 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
 WINE_DECLARE_DEBUG_CHANNEL(d3d_perf);
+WINE_DECLARE_DEBUG_CHANNEL(winediag);
 
 #define WINE_DEFAULT_VIDMEM (64 * 1024 * 1024)
 #define DEFAULT_REFRESH_RATE 0
 
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(array) (sizeof(array)/sizeof((array)[0]))
+#endif
+
 /* The driver names reflect the lowest GPU supported
  * by a certain driver, so DRIVER_AMD_R300 supports
  * R3xx, R4xx and R5xx GPUs. */
@@ -71,6 +76,19 @@ enum wined3d_gl_vendor
     GL_VENDOR_NVIDIA,
 };
 
+enum wined3d_d3d_level
+{
+    WINED3D_D3D_LEVEL_5,
+    WINED3D_D3D_LEVEL_6,
+    WINED3D_D3D_LEVEL_7,
+    WINED3D_D3D_LEVEL_8,
+    WINED3D_D3D_LEVEL_9_SM2,
+    WINED3D_D3D_LEVEL_9_SM3,
+    WINED3D_D3D_LEVEL_10,
+    WINED3D_D3D_LEVEL_11,
+    WINED3D_D3D_LEVEL_COUNT
+};
+
 /* The d3d device ID */
 static const GUID IID_D3DDEVICE_D3DUID = { 0xaeb2cdd4, 0x6e41, 0x43ea, { 0x94,0x1c,0x83,0x61,0xcc,0x76,0x07,0x81 } };
 
@@ -138,6 +156,7 @@ static const struct wined3d_extension_map gl_extension_map[] =
     {"GL_ARB_texture_rectangle",            ARB_TEXTURE_RECTANGLE         },
     {"GL_ARB_texture_rg",                   ARB_TEXTURE_RG                },
     {"GL_ARB_timer_query",                  ARB_TIMER_QUERY               },
+    {"GL_ARB_uniform_buffer_object",        ARB_UNIFORM_BUFFER_OBJECT     },
     {"GL_ARB_vertex_array_bgra",            ARB_VERTEX_ARRAY_BGRA         },
     {"GL_ARB_vertex_blend",                 ARB_VERTEX_BLEND              },
     {"GL_ARB_vertex_buffer_object",         ARB_VERTEX_BUFFER_OBJECT      },
@@ -389,11 +408,13 @@ fail:
 }
 
 /* Adjust the amount of used texture memory */
-unsigned int adapter_adjust_memory(struct wined3d_adapter *adapter, int amount)
+UINT64 adapter_adjust_memory(struct wined3d_adapter *adapter, INT64 amount)
 {
-    adapter->UsedTextureRam += amount;
-    TRACE("Adjusted adapter memory by %d to %d.\n", amount, adapter->UsedTextureRam);
-    return adapter->UsedTextureRam;
+    adapter->vram_bytes_used += amount;
+    TRACE("Adjusted used adapter memory by 0x%s to 0x%s.\n",
+            wine_dbgstr_longlong(amount),
+            wine_dbgstr_longlong(adapter->vram_bytes_used));
+    return adapter->vram_bytes_used;
 }
 
 static void wined3d_adapter_cleanup(struct wined3d_adapter *adapter)
@@ -436,7 +457,7 @@ static BOOL test_arb_vs_offset_limit(const struct wined3d_gl_info *gl_info)
 {
     GLuint prog;
     BOOL ret = FALSE;
-    const char *testcode =
+    static const char testcode[] =
         "!!ARBvp1.0\n"
         "PARAM C[66] = { program.env[0..65] };\n"
         "ADDRESS A0;"
@@ -650,7 +671,7 @@ static BOOL match_broken_nv_clip(const struct wined3d_gl_info *gl_info, const ch
     GLuint prog;
     BOOL ret = FALSE;
     GLint pos;
-    const char *testcode =
+    static const char testcode[] =
         "!!ARBvp1.0\n"
         "OPTION NV_vertex_program2;\n"
         "MOV result.clip[0], 0.0;\n"
@@ -787,7 +808,7 @@ static BOOL match_broken_arb_fog(const struct wined3d_gl_info *gl_info, const ch
     float color[4] = {0.0f, 1.0f, 0.0f, 0.0f};
     GLuint prog;
     GLint err_pos;
-    static const char *program_code =
+    static const char program_code[] =
         "!!ARBfp1.0\n"
         "OPTION ARB_fog_linear;\n"
         "MOV result.color, {1.0, 0.0, 0.0, 0.0};\n"
@@ -1267,6 +1288,8 @@ static const struct gpu_description gpu_description_table[] =
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX765M,    "NVIDIA GeForce GTX 765M",          DRIVER_NVIDIA_GEFORCE6,  2048},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX770M,    "NVIDIA GeForce GTX 770M",          DRIVER_NVIDIA_GEFORCE6,  3072},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX770,     "NVIDIA GeForce GTX 770",           DRIVER_NVIDIA_GEFORCE6,  2048},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX780,     "NVIDIA GeForce GTX 780",           DRIVER_NVIDIA_GEFORCE6,  3072},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX780TI,   "NVIDIA GeForce GTX 780 Ti",        DRIVER_NVIDIA_GEFORCE6,  3072},
 
     /* AMD cards */
     {HW_VENDOR_AMD,        CARD_AMD_RAGE_128PRO,           "ATI Rage Fury",                    DRIVER_AMD_RAGE_128PRO,  16  },
@@ -1299,9 +1322,16 @@ static const struct gpu_description gpu_description_table[] =
     {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD6700,         "AMD Radeon HD 6700 Series",        DRIVER_AMD_R600,         1024},
     {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD6800,         "AMD Radeon HD 6800 Series",        DRIVER_AMD_R600,         1024},
     {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD6900,         "AMD Radeon HD 6900 Series",        DRIVER_AMD_R600,         2048},
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD7660D,        "AMD Radeon HD 7660D",              DRIVER_AMD_R600,         2048},
     {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD7700,         "AMD Radeon HD 7700 Series",        DRIVER_AMD_R600,         1024},
     {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD7800,         "AMD Radeon HD 7800 Series",        DRIVER_AMD_R600,         2048},
     {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD7900,         "AMD Radeon HD 7900 Series",        DRIVER_AMD_R600,         2048},
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD8600M,        "AMD Radeon HD 8600M Series",       DRIVER_AMD_R600,         1024},
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD8670,         "AMD Radeon HD 8670",               DRIVER_AMD_R600,         2048},
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD8770,         "AMD Radeon HD 8770",               DRIVER_AMD_R600,         2048},
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_R3,             "AMD Radeon HD 8400 / R3 Series",   DRIVER_AMD_R600,         2048},
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_R7,             "AMD Radeon(TM) R7 Graphics",       DRIVER_AMD_R600,         2048},
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_R9,             "AMD Radeon R9 290",                DRIVER_AMD_R600,         4096},
 
     /* VMware */
     {HW_VENDOR_VMWARE,     CARD_VMWARE_SVGA3D,             "VMware SVGA 3D (Microsoft Corporation - WDDM)",             DRIVER_VMWARE,        1024},
@@ -1364,33 +1394,56 @@ static const struct driver_version_information *get_driver_version_info(enum win
     return NULL;
 }
 
+static const struct gpu_description *get_gpu_description(enum wined3d_pci_vendor vendor,
+        enum wined3d_pci_device device)
+{
+    unsigned int i;
+
+    for (i = 0; i < (sizeof(gpu_description_table) / sizeof(*gpu_description_table)); ++i)
+    {
+        if (vendor == gpu_description_table[i].vendor && device == gpu_description_table[i].card)
+            return &gpu_description_table[i];
+    }
+
+    return NULL;
+}
+
 static void init_driver_info(struct wined3d_driver_info *driver_info,
         enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
 {
     OSVERSIONINFOW os_version;
     WORD driver_os_version;
-    unsigned int i;
-    enum wined3d_display_driver driver = DRIVER_UNKNOWN;
+    enum wined3d_display_driver driver;
     enum wined3d_driver_model driver_model;
     const struct driver_version_information *version_info;
+    const struct gpu_description *gpu_desc;
 
-    if (wined3d_settings.pci_vendor_id != PCI_VENDOR_NONE)
+    if (driver_info->vendor != PCI_VENDOR_NONE || driver_info->device != PCI_DEVICE_NONE)
     {
-        TRACE("Overriding PCI vendor ID with 0x%04x.\n", wined3d_settings.pci_vendor_id);
-        vendor = wined3d_settings.pci_vendor_id;
-    }
-    driver_info->vendor = vendor;
+        static unsigned int once;
 
-    if (wined3d_settings.pci_device_id != PCI_DEVICE_NONE)
-    {
-        TRACE("Overriding PCI device ID with 0x%04x.\n", wined3d_settings.pci_device_id);
-        device = wined3d_settings.pci_device_id;
+        TRACE("GPU override %04x:%04x.\n", wined3d_settings.pci_vendor_id, wined3d_settings.pci_device_id);
+
+        driver_info->vendor = wined3d_settings.pci_vendor_id;
+        if (driver_info->vendor == PCI_VENDOR_NONE)
+            driver_info->vendor = vendor;
+
+        driver_info->device = wined3d_settings.pci_device_id;
+        if (driver_info->device == PCI_DEVICE_NONE)
+            driver_info->device = device;
+
+        if (get_gpu_description(driver_info->vendor, driver_info->device))
+        {
+            vendor = driver_info->vendor;
+            device = driver_info->device;
+        }
+        else if (!once++)
+            ERR_(winediag)("Invalid GPU override %04x:%04x specified, ignoring.\n",
+                    driver_info->vendor, driver_info->device);
     }
-    driver_info->device = device;
 
-    /* Set a default amount of video memory (64 MB). In general this code isn't used unless the user
-     * overrides the pci ids to a card which is not in our database. */
-    driver_info->vidmem = WINE_DEFAULT_VIDMEM;
+    driver_info->vendor = vendor;
+    driver_info->device = device;
 
     memset(&os_version, 0, sizeof(os_version));
     os_version.dwOSVersionInfoSize = sizeof(os_version);
@@ -1450,25 +1503,25 @@ static void init_driver_info(struct wined3d_driver_info *driver_info,
         }
     }
 
-    /* When we reach this stage we always have a vendor or device id (it can be a default one).
-     * This means that unless the ids are overridden, we will always find a GPU description. */
-    for (i = 0; i < (sizeof(gpu_description_table) / sizeof(gpu_description_table[0])); i++)
+    if ((gpu_desc = get_gpu_description(driver_info->vendor, driver_info->device)))
     {
-        if (vendor == gpu_description_table[i].vendor && device == gpu_description_table[i].card)
-        {
-            TRACE("Found card %04x:%04x in driver DB.\n", vendor, device);
-
-            driver_info->description = gpu_description_table[i].description;
-            driver_info->vidmem = gpu_description_table[i].vidmem * 1024*1024;
-            driver = gpu_description_table[i].driver;
-            break;
-        }
+        driver_info->description = gpu_desc->description;
+        driver_info->vram_bytes = (UINT64)gpu_desc->vidmem * 1024 * 1024;
+        driver = gpu_desc->driver;
+    }
+    else
+    {
+        ERR("Card %04x:%04x not found in driver DB.\n", vendor, device);
+        driver_info->description = "Direct3D HAL";
+        driver_info->vram_bytes = WINE_DEFAULT_VIDMEM;
+        driver = DRIVER_UNKNOWN;
     }
 
     if (wined3d_settings.emulated_textureram)
     {
-        TRACE("Overriding amount of video memory with %u bytes.\n", wined3d_settings.emulated_textureram);
-        driver_info->vidmem = wined3d_settings.emulated_textureram;
+        TRACE("Overriding amount of video memory with 0x%s bytes.\n",
+                wine_dbgstr_longlong(wined3d_settings.emulated_textureram));
+        driver_info->vram_bytes = wined3d_settings.emulated_textureram;
     }
 
     /* Try to obtain driver version information for the current Windows version. This fails in
@@ -1484,8 +1537,8 @@ static void init_driver_info(struct wined3d_driver_info *driver_info,
      * - the gpu is not in our database (can happen when the user overrides the vendor_id / device_id)
      *   This could be an indication that our database is not up to date, so this should be fixed.
      */
-    version_info = get_driver_version_info(driver, driver_model);
-    if (version_info)
+    if ((version_info = get_driver_version_info(driver, driver_model))
+            || (version_info = get_driver_version_info(driver, DRIVER_MODEL_NT5X)))
     {
         driver_info->name = version_info->driver_name;
         driver_info->version_high = MAKEDWORD_VERSION(driver_os_version, version_info->version);
@@ -1493,23 +1546,11 @@ static void init_driver_info(struct wined3d_driver_info *driver_info,
     }
     else
     {
-        version_info = get_driver_version_info(driver, DRIVER_MODEL_NT5X);
-        if (version_info)
-        {
-            driver_info->name = version_info->driver_name;
-            driver_info->version_high = MAKEDWORD_VERSION(driver_os_version, version_info->version);
-            driver_info->version_low = MAKEDWORD_VERSION(version_info->subversion, version_info->build);
-        }
-        else
-        {
-            driver_info->description = "Direct3D HAL";
-            driver_info->name = "Display";
-            driver_info->version_high = MAKEDWORD_VERSION(driver_os_version, 15);
-            driver_info->version_low = MAKEDWORD_VERSION(8, 6); /* Nvidia RIVA TNT, arbitrary */
-
-            FIXME("Unable to find a driver/device info for vendor_id=%#x device_id=%#x for driver_model=%d\n",
-                    vendor, device, driver_model);
-        }
+        ERR("No driver version info found for device %04x:%04x, driver model %#x.\n",
+                vendor, device, driver_model);
+        driver_info->name = "Display";
+        driver_info->version_high = MAKEDWORD_VERSION(driver_os_version, 15);
+        driver_info->version_low = MAKEDWORD_VERSION(8, 6); /* Nvidia RIVA TNT, arbitrary */
     }
 
     TRACE("Reporting (fake) driver version 0x%08x-0x%08x.\n",
@@ -1636,703 +1677,561 @@ static enum wined3d_pci_vendor wined3d_guess_card_vendor(const char *gl_vendor_s
     return HW_VENDOR_NVIDIA;
 }
 
-static UINT d3d_level_from_gl_info(const struct wined3d_gl_info *gl_info)
-{
-    UINT level = 0;
-
-    if (gl_info->supported[ARB_MULTITEXTURE])
-        level = 6;
-    if (gl_info->supported[ARB_TEXTURE_COMPRESSION]
-            && gl_info->supported[ARB_TEXTURE_CUBE_MAP]
-            && gl_info->supported[ARB_TEXTURE_ENV_DOT3])
-        level = 7;
-    if (level == 7 && gl_info->supported[ARB_MULTISAMPLE]
-            && gl_info->supported[ARB_TEXTURE_BORDER_CLAMP])
-        level = 8;
-    if (level == 8 && gl_info->supported[ARB_FRAGMENT_PROGRAM]
-            && gl_info->supported[ARB_VERTEX_SHADER])
-        level = 9;
-    if (level == 9 && gl_info->supported[EXT_GPU_SHADER4])
-        level = 10;
-
-    return level;
-}
+static const struct wined3d_shader_backend_ops *select_shader_backend(const struct wined3d_gl_info *gl_info);
+static const struct fragment_pipeline *select_fragment_implementation(const struct wined3d_gl_info *gl_info, const struct wined3d_shader_backend_ops *shader_backend_ops);
 
-static enum wined3d_pci_device select_card_nvidia_binary(const struct wined3d_gl_info *gl_info,
-        const char *gl_renderer)
+static enum wined3d_d3d_level d3d_level_from_gl_info(const struct wined3d_gl_info *gl_info)
 {
-    UINT d3d_level = d3d_level_from_gl_info(gl_info);
-    unsigned int i;
-
-    if (d3d_level >= 10)
-    {
-        static const struct
-        {
-            const char *renderer;
-            enum wined3d_pci_device id;
-        }
-        cards[] =
-        {
-            {"GTX 770M",    CARD_NVIDIA_GEFORCE_GTX770M},   /* Geforce 700 - midend high mobile */
-            {"GTX 770",     CARD_NVIDIA_GEFORCE_GTX770},    /* Geforce 700 - highend */
-            {"GTX 765M",    CARD_NVIDIA_GEFORCE_GTX765M},   /* Geforce 700 - midend high mobile */
-            {"GTX 760",     CARD_NVIDIA_GEFORCE_GTX760},    /* Geforce 700 - midend high  */
-            {"GTX 750 Ti",  CARD_NVIDIA_GEFORCE_GTX750TI},  /* Geforce 700 - midend */
-            {"GTX 750",     CARD_NVIDIA_GEFORCE_GTX750},    /* Geforce 700 - midend */
-            {"GTX 680",     CARD_NVIDIA_GEFORCE_GTX680},    /* Geforce 600 - highend */
-            {"GTX 670MX",   CARD_NVIDIA_GEFORCE_GTX670MX},  /* Geforce 600 - highend */
-            {"GTX 670",     CARD_NVIDIA_GEFORCE_GTX670},    /* Geforce 600 - midend high */
-            {"GTX 660 Ti",  CARD_NVIDIA_GEFORCE_GTX660TI},  /* Geforce 600 - midend high */
-            {"GTX 660M",    CARD_NVIDIA_GEFORCE_GTX660M},   /* Geforce 600 - midend high mobile */
-            {"GTX 660",     CARD_NVIDIA_GEFORCE_GTX660},    /* Geforce 600 - midend high */
-            {"GTX 650 Ti",  CARD_NVIDIA_GEFORCE_GTX650TI},  /* Geforce 600 - lowend */
-            {"GTX 650",     CARD_NVIDIA_GEFORCE_GTX650},    /* Geforce 600 - lowend */
-            {"GT 650M",     CARD_NVIDIA_GEFORCE_GT650M},    /* Geforce 600 - midend mobile */
-            {"GT 640M",     CARD_NVIDIA_GEFORCE_GT640M},    /* Geforce 600 - midend mobile */
-            {"GT 630M",     CARD_NVIDIA_GEFORCE_GT630M},    /* Geforce 600 - midend mobile */
-            {"GT 630",      CARD_NVIDIA_GEFORCE_GT630},     /* Geforce 600 - lowend */
-            {"GT 610",      CARD_NVIDIA_GEFORCE_GT610},     /* Geforce 600 - lowend */
-            {"GTX 580",     CARD_NVIDIA_GEFORCE_GTX580},    /* Geforce 500 - highend */
-            {"GTX 570",     CARD_NVIDIA_GEFORCE_GTX570},    /* Geforce 500 - midend high */
-            {"GTX 560 Ti",  CARD_NVIDIA_GEFORCE_GTX560TI},  /* Geforce 500 - midend */
-            {"GTX 560",     CARD_NVIDIA_GEFORCE_GTX560},    /* Geforce 500 - midend */
-            {"GT 555M",     CARD_NVIDIA_GEFORCE_GT555M},    /* Geforce 500 - midend mobile */
-            {"GTX 550 Ti",  CARD_NVIDIA_GEFORCE_GTX550},    /* Geforce 500 - midend */
-            {"GT 540M",     CARD_NVIDIA_GEFORCE_GT540M},    /* Geforce 500 - midend mobile */
-            {"GT 520",      CARD_NVIDIA_GEFORCE_GT520},     /* Geforce 500 - lowend */
-            {"GTX 480",     CARD_NVIDIA_GEFORCE_GTX480},    /* Geforce 400 - highend */
-            {"GTX 470",     CARD_NVIDIA_GEFORCE_GTX470},    /* Geforce 400 - midend high */
-            {"GTX 465",     CARD_NVIDIA_GEFORCE_GTX465},    /* Geforce 400 - midend */
-            {"GTX 460M",    CARD_NVIDIA_GEFORCE_GTX460M},   /* Geforce 400 - highend mobile */
-            {"GTX 460",     CARD_NVIDIA_GEFORCE_GTX460},    /* Geforce 400 - midend */
-            {"GTS 450",     CARD_NVIDIA_GEFORCE_GTS450},    /* Geforce 400 - midend low */
-            {"GT 440",      CARD_NVIDIA_GEFORCE_GT440},     /* Geforce 400 - lowend */
-            {"GT 430",      CARD_NVIDIA_GEFORCE_GT430},     /* Geforce 400 - lowend */
-            {"GT 420",      CARD_NVIDIA_GEFORCE_GT420},     /* Geforce 400 - lowend */
-            {"410M",        CARD_NVIDIA_GEFORCE_410M},      /* Geforce 400 - lowend mobile */
-            {"GT 330",      CARD_NVIDIA_GEFORCE_GT330},     /* Geforce 300 - highend */
-            {"GTS 360M",    CARD_NVIDIA_GEFORCE_GTS350M},   /* Geforce 300 - highend mobile */
-            {"GTS 350M",    CARD_NVIDIA_GEFORCE_GTS350M},   /* Geforce 300 - highend mobile */
-            {"GT 330M",     CARD_NVIDIA_GEFORCE_GT325M},    /* Geforce 300 - midend mobile */
-            {"GT 325M",     CARD_NVIDIA_GEFORCE_GT325M},    /* Geforce 300 - midend mobile */
-            {"GT 320M",     CARD_NVIDIA_GEFORCE_GT320M},    /* Geforce 300 - midend mobile */
-            {"320M",        CARD_NVIDIA_GEFORCE_320M},      /* Geforce 300 - midend mobile */
-            {"315M",        CARD_NVIDIA_GEFORCE_315M},      /* Geforce 300 - midend mobile */
-            {"GTX 295",     CARD_NVIDIA_GEFORCE_GTX280},    /* Geforce 200 - highend */
-            {"GTX 285",     CARD_NVIDIA_GEFORCE_GTX280},    /* Geforce 200 - highend */
-            {"GTX 280",     CARD_NVIDIA_GEFORCE_GTX280},    /* Geforce 200 - highend */
-            {"GTX 275",     CARD_NVIDIA_GEFORCE_GTX275},    /* Geforce 200 - midend high */
-            {"GTX 260",     CARD_NVIDIA_GEFORCE_GTX260},    /* Geforce 200 - midend */
-            {"GT 240",      CARD_NVIDIA_GEFORCE_GT240},     /* Geforce 200 - midend */
-            {"GT 220",      CARD_NVIDIA_GEFORCE_GT220},     /* Geforce 200 - lowend */
-            {"Geforce 310", CARD_NVIDIA_GEFORCE_210},       /* Geforce 200 - lowend */
-            {"Geforce 305", CARD_NVIDIA_GEFORCE_210},       /* Geforce 200 - lowend */
-            {"Geforce 210", CARD_NVIDIA_GEFORCE_210},       /* Geforce 200 - lowend */
-            {"G 210",       CARD_NVIDIA_GEFORCE_210},       /* Geforce 200 - lowend */
-            {"GTS 250",     CARD_NVIDIA_GEFORCE_9800GT},    /* Geforce 9 - highend / Geforce 200 - midend */
-            {"GTS 150",     CARD_NVIDIA_GEFORCE_9800GT},    /* Geforce 9 - highend / Geforce 200 - midend */
-            {"9800",        CARD_NVIDIA_GEFORCE_9800GT},    /* Geforce 9 - highend / Geforce 200 - midend */
-            {"GT 140",      CARD_NVIDIA_GEFORCE_9600GT},    /* Geforce 9 - midend */
-            {"9600",        CARD_NVIDIA_GEFORCE_9600GT},    /* Geforce 9 - midend */
-            {"GT 130",      CARD_NVIDIA_GEFORCE_9500GT},    /* Geforce 9 - midend low / Geforce 200 - low */
-            {"GT 120",      CARD_NVIDIA_GEFORCE_9500GT},    /* Geforce 9 - midend low / Geforce 200 - low */
-            {"9500",        CARD_NVIDIA_GEFORCE_9500GT},    /* Geforce 9 - midend low / Geforce 200 - low */
-            {"9400M",       CARD_NVIDIA_GEFORCE_9400M},     /* Geforce 9 - lowend */
-            {"9400",        CARD_NVIDIA_GEFORCE_9400GT},    /* Geforce 9 - lowend */
-            {"9300",        CARD_NVIDIA_GEFORCE_9300},      /* Geforce 9 - lowend low */
-            {"9200",        CARD_NVIDIA_GEFORCE_9200},      /* Geforce 9 - lowend low */
-            {"9100",        CARD_NVIDIA_GEFORCE_9200},      /* Geforce 9 - lowend low */
-            {"G 100",       CARD_NVIDIA_GEFORCE_9200},      /* Geforce 9 - lowend low */
-            {"8800 GTX",    CARD_NVIDIA_GEFORCE_8800GTX},   /* Geforce 8 - highend high */
-            {"8800",        CARD_NVIDIA_GEFORCE_8800GTS},   /* Geforce 8 - highend */
-            {"8600M",       CARD_NVIDIA_GEFORCE_8600MGT},   /* Geforce 8 - midend mobile */
-            {"8600 M",      CARD_NVIDIA_GEFORCE_8600MGT},   /* Geforce 8 - midend mobile */
-            {"8700",        CARD_NVIDIA_GEFORCE_8600GT},    /* Geforce 8 - midend */
-            {"8600",        CARD_NVIDIA_GEFORCE_8600GT},    /* Geforce 8 - midend */
-            {"8500",        CARD_NVIDIA_GEFORCE_8400GS},    /* Geforce 8 - mid-lowend */
-            {"8400",        CARD_NVIDIA_GEFORCE_8400GS},    /* Geforce 8 - mid-lowend */
-            {"8300",        CARD_NVIDIA_GEFORCE_8300GS},    /* Geforce 8 - lowend */
-            {"8200",        CARD_NVIDIA_GEFORCE_8300GS},    /* Geforce 8 - lowend */
-            {"8100",        CARD_NVIDIA_GEFORCE_8300GS},    /* Geforce 8 - lowend */
-        };
-
-        for (i = 0; i < sizeof(cards) / sizeof(*cards); ++i)
-        {
-            if (strstr(gl_renderer, cards[i].renderer))
-                return cards[i].id;
-        }
-        return PCI_DEVICE_NONE;
-    }
+    struct shader_caps shader_caps;
+    struct fragment_caps fragment_caps;
+    const struct wined3d_shader_backend_ops *shader_backend;
+    const struct fragment_pipeline *fragment_pipeline;
 
-    /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
-     * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
-     */
-    if (d3d_level >= 9 && gl_info->supported[NV_VERTEX_PROGRAM3])
-    {
-        static const struct
-        {
-            const char *renderer;
-            enum wined3d_pci_device id;
-        }
-        cards[] =
-        {
-            {"Quadro FX 5", CARD_NVIDIA_GEFORCE_7800GT},    /* Geforce 7 - highend */
-            {"Quadro FX 4", CARD_NVIDIA_GEFORCE_7800GT},    /* Geforce 7 - highend */
-            {"7950",        CARD_NVIDIA_GEFORCE_7800GT},    /* Geforce 7 - highend */
-            {"7900",        CARD_NVIDIA_GEFORCE_7800GT},    /* Geforce 7 - highend */
-            {"7800",        CARD_NVIDIA_GEFORCE_7800GT},    /* Geforce 7 - highend */
-            {"7700",        CARD_NVIDIA_GEFORCE_7600},      /* Geforce 7 - midend */
-            {"7600",        CARD_NVIDIA_GEFORCE_7600},      /* Geforce 7 - midend */
-            {"7400",        CARD_NVIDIA_GEFORCE_7400},      /* Geforce 7 - lower medium */
-            {"7300",        CARD_NVIDIA_GEFORCE_7300},      /* Geforce 7 - lowend */
-            {"6800",        CARD_NVIDIA_GEFORCE_6800},      /* Geforce 6 - highend */
-            {"6700",        CARD_NVIDIA_GEFORCE_6600GT},    /* Geforce 6 - midend */
-            {"6610",        CARD_NVIDIA_GEFORCE_6600GT},    /* Geforce 6 - midend */
-            {"6600",        CARD_NVIDIA_GEFORCE_6600GT},    /* Geforce 6 - midend */
-        };
-
-        for (i = 0; i < sizeof(cards) / sizeof(*cards); ++i)
-        {
-            if (strstr(gl_renderer, cards[i].renderer))
-                return cards[i].id;
-        }
-        return PCI_DEVICE_NONE;
-    }
+    shader_backend = select_shader_backend(gl_info);
+    shader_backend->shader_get_caps(gl_info, &shader_caps);
 
-    if (d3d_level >= 9)
+    if (shader_caps.vs_version >= 5)
+        return WINED3D_D3D_LEVEL_11;
+    if (shader_caps.vs_version == 4)
     {
-        /* GeforceFX - highend */
-        if (strstr(gl_renderer, "5800")
-                || strstr(gl_renderer, "5900")
-                || strstr(gl_renderer, "5950")
-                || strstr(gl_renderer, "Quadro FX"))
-        {
-            return CARD_NVIDIA_GEFORCEFX_5800;
-        }
-
-        /* GeforceFX - midend */
-        if (strstr(gl_renderer, "5600")
-                || strstr(gl_renderer, "5650")
-                || strstr(gl_renderer, "5700")
-                || strstr(gl_renderer, "5750"))
-        {
-            return CARD_NVIDIA_GEFORCEFX_5600;
-        }
-
-        /* GeforceFX - lowend */
-        return CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
+        /* No backed supports SM 5 at the moment */
+        if (gl_info->glsl_version >= MAKEDWORD_VERSION(4, 00))
+            return WINED3D_D3D_LEVEL_11;
+        return WINED3D_D3D_LEVEL_10;
     }
-
-    if (d3d_level >= 8)
+    if (shader_caps.vs_version == 3)
     {
-        if (strstr(gl_renderer, "GeForce4 Ti") || strstr(gl_renderer, "Quadro4"))
-        {
-            return CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
-        }
-
-        return CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
+        /* Wine can not use SM 4 on mesa drivers as the necessary functionality is not exposed
+         * on compatibility contexts */
+        if (gl_info->glsl_version >= MAKEDWORD_VERSION(1, 30))
+            return WINED3D_D3D_LEVEL_10;
+        return WINED3D_D3D_LEVEL_9_SM3;
     }
+    if (shader_caps.vs_version == 2)
+        return WINED3D_D3D_LEVEL_9_SM2;
+    if (shader_caps.vs_version == 1)
+        return WINED3D_D3D_LEVEL_8;
 
-    if (d3d_level >= 7)
-    {
-        if (strstr(gl_renderer, "GeForce4 MX"))
-        {
-            return CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
-        }
-
-        if (strstr(gl_renderer, "GeForce2 MX") || strstr(gl_renderer, "Quadro2 MXR"))
-        {
-            return CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
-        }
-
-        if (strstr(gl_renderer, "GeForce2") || strstr(gl_renderer, "Quadro2"))
-        {
-            return CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
-        }
-
-        return CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
-    }
+    fragment_pipeline = select_fragment_implementation(gl_info, shader_backend);
+    fragment_pipeline->get_caps(gl_info, &fragment_caps);
 
-    if (strstr(gl_renderer, "TNT2"))
-    {
-        return CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
-    }
+    if (fragment_caps.TextureOpCaps & WINED3DTEXOPCAPS_DOTPRODUCT3)
+        return WINED3D_D3D_LEVEL_7;
+    if (fragment_caps.MaxSimultaneousTextures > 1)
+        return WINED3D_D3D_LEVEL_6;
 
-    return CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
+    return WINED3D_D3D_LEVEL_5;
 }
 
-static enum wined3d_pci_device select_card_amd_binary(const struct wined3d_gl_info *gl_info,
-        const char *gl_renderer)
+static const struct wined3d_renderer_table
 {
-    UINT d3d_level = d3d_level_from_gl_info(gl_info);
-
-    /* See http://developer.amd.com/drivers/pc_vendor_id/Pages/default.aspx
-     *
-     * Beware: renderer string do not match exact card model,
-     * eg HD 4800 is returned for multiple cards, even for RV790 based ones. */
-    if (d3d_level >= 10)
-    {
-        unsigned int i;
-
-        static const struct
-        {
-            const char *renderer;
-            enum wined3d_pci_device id;
-        }
-        cards[] =
-        {
-            /* Southern Islands */
-            {"HD 7900", CARD_AMD_RADEON_HD7900},
-            {"HD 7800", CARD_AMD_RADEON_HD7800},
-            {"HD 7700", CARD_AMD_RADEON_HD7700},
-            /* Northern Islands */
-            {"HD 6970", CARD_AMD_RADEON_HD6900},
-            {"HD 6900", CARD_AMD_RADEON_HD6900},
-            {"HD 6800", CARD_AMD_RADEON_HD6800},
-            {"HD 6770M",CARD_AMD_RADEON_HD6600M},
-            {"HD 6750M",CARD_AMD_RADEON_HD6600M},
-            {"HD 6700", CARD_AMD_RADEON_HD6700},
-            {"HD 6670", CARD_AMD_RADEON_HD6600},
-            {"HD 6630M",CARD_AMD_RADEON_HD6600M},
-            {"HD 6600M",CARD_AMD_RADEON_HD6600M},
-            {"HD 6600", CARD_AMD_RADEON_HD6600},
-            {"HD 6570", CARD_AMD_RADEON_HD6600},
-            {"HD 6500M",CARD_AMD_RADEON_HD6600M},
-            {"HD 6500", CARD_AMD_RADEON_HD6600},
-            {"HD 6400", CARD_AMD_RADEON_HD6400},
-            {"HD 6300", CARD_AMD_RADEON_HD6300},
-            {"HD 6200", CARD_AMD_RADEON_HD6300},
-            /* Evergreen */
-            {"HD 5870", CARD_AMD_RADEON_HD5800},    /* Radeon EG CYPRESS PRO */
-            {"HD 5850", CARD_AMD_RADEON_HD5800},    /* Radeon EG CYPRESS XT */
-            {"HD 5800", CARD_AMD_RADEON_HD5800},    /* Radeon EG CYPRESS HD58xx generic renderer string */
-            {"HD 5770", CARD_AMD_RADEON_HD5700},    /* Radeon EG JUNIPER XT */
-            {"HD 5750", CARD_AMD_RADEON_HD5700},    /* Radeon EG JUNIPER LE */
-            {"HD 5700", CARD_AMD_RADEON_HD5700},    /* Radeon EG JUNIPER HD57xx generic renderer string */
-            {"HD 5670", CARD_AMD_RADEON_HD5600},    /* Radeon EG REDWOOD XT */
-            {"HD 5570", CARD_AMD_RADEON_HD5600},    /* Radeon EG REDWOOD PRO mapped to HD5600 series */
-            {"HD 5550", CARD_AMD_RADEON_HD5600},    /* Radeon EG REDWOOD LE mapped to HD5600 series */
-            {"HD 5450", CARD_AMD_RADEON_HD5400},    /* Radeon EG CEDAR PRO */
-            {"HD 5000", CARD_AMD_RADEON_HD5600},    /* Defaulting to HD 5600 */
-            /* R700 */
-            {"HD 4890", CARD_AMD_RADEON_HD4800},    /* Radeon RV790 */
-            {"HD 4870", CARD_AMD_RADEON_HD4800},    /* Radeon RV770 */
-            {"HD 4850", CARD_AMD_RADEON_HD4800},    /* Radeon RV770 */
-            {"HD 4830", CARD_AMD_RADEON_HD4800},    /* Radeon RV770 */
-            {"HD 4800", CARD_AMD_RADEON_HD4800},    /* Radeon RV7xx HD48xx generic renderer string */
-            {"HD 4770", CARD_AMD_RADEON_HD4700},    /* Radeon RV740 */
-            {"HD 4700", CARD_AMD_RADEON_HD4700},    /* Radeon RV7xx HD47xx generic renderer string */
-            {"HD 4670", CARD_AMD_RADEON_HD4600},    /* Radeon RV730 */
-            {"HD 4650", CARD_AMD_RADEON_HD4600},    /* Radeon RV730 */
-            {"HD 4600", CARD_AMD_RADEON_HD4600},    /* Radeon RV730 */
-            {"HD 4550", CARD_AMD_RADEON_HD4350},    /* Radeon RV710 */
-            {"HD 4350", CARD_AMD_RADEON_HD4350},    /* Radeon RV710 */
-            /* R600/R700 integrated */
-            {"HD 4200M", CARD_AMD_RADEON_HD4200M},
-            {"HD 3300", CARD_AMD_RADEON_HD3200},
-            {"HD 3200", CARD_AMD_RADEON_HD3200},
-            {"HD 3100", CARD_AMD_RADEON_HD3200},
-            /* R600 */
-            {"HD 3870", CARD_AMD_RADEON_HD2900},    /* HD2900/HD3800 - highend */
-            {"HD 3850", CARD_AMD_RADEON_HD2900},    /* HD2900/HD3800 - highend */
-            {"HD 2900", CARD_AMD_RADEON_HD2900},    /* HD2900/HD3800 - highend */
-            {"HD 3830", CARD_AMD_RADEON_HD2600},    /* China-only midend */
-            {"HD 3690", CARD_AMD_RADEON_HD2600},    /* HD2600/HD3600 - midend */
-            {"HD 3650", CARD_AMD_RADEON_HD2600},    /* HD2600/HD3600 - midend */
-            {"HD 2600", CARD_AMD_RADEON_HD2600},    /* HD2600/HD3600 - midend */
-            {"HD 3470", CARD_AMD_RADEON_HD2350},    /* HD2350/HD2400/HD3400 - lowend */
-            {"HD 3450", CARD_AMD_RADEON_HD2350},    /* HD2350/HD2400/HD3400 - lowend */
-            {"HD 3430", CARD_AMD_RADEON_HD2350},    /* HD2350/HD2400/HD3400 - lowend */
-            {"HD 3400", CARD_AMD_RADEON_HD2350},    /* HD2350/HD2400/HD3400 - lowend */
-            {"HD 2400", CARD_AMD_RADEON_HD2350},    /* HD2350/HD2400/HD3400 - lowend */
-            {"HD 2350", CARD_AMD_RADEON_HD2350},    /* HD2350/HD2400/HD3400 - lowend */
-        };
-
-        for (i = 0; i < sizeof(cards) / sizeof(*cards); ++i)
-        {
-            if (strstr(gl_renderer, cards[i].renderer))
-                return cards[i].id;
-        }
-        return PCI_DEVICE_NONE;
-    }
-
-    if (d3d_level >= 9)
-    {
-        /* Radeon R5xx */
-        if (strstr(gl_renderer, "X1600")
-                || strstr(gl_renderer, "X1650")
-                || strstr(gl_renderer, "X1800")
-                || strstr(gl_renderer, "X1900")
-                || strstr(gl_renderer, "X1950"))
-        {
-            return CARD_AMD_RADEON_X1600;
-        }
-
-        /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300/X2500/HD2300 (lowend R5xx)
-         * Note X2300/X2500/HD2300 are R5xx GPUs with a 2xxx naming but they are still DX9-only */
-        if (strstr(gl_renderer, "X700")
-                || strstr(gl_renderer, "X800")
-                || strstr(gl_renderer, "X850")
-                || strstr(gl_renderer, "X1300")
-                || strstr(gl_renderer, "X1400")
-                || strstr(gl_renderer, "X1450")
-                || strstr(gl_renderer, "X1550")
-                || strstr(gl_renderer, "X2300")
-                || strstr(gl_renderer, "X2500")
-                || strstr(gl_renderer, "HD 2300")
-                )
-        {
-            return CARD_AMD_RADEON_X700;
-        }
-
-        /* Radeon Xpress Series - onboard, DX9b, Shader 2.0, 300-400 MHz */
-        if (strstr(gl_renderer, "Radeon Xpress"))
-        {
-            return CARD_AMD_RADEON_XPRESS_200M;
-        }
-    }
-    return PCI_DEVICE_NONE;
+    const char *renderer;
+    enum wined3d_pci_device id;
 }
-
-static enum wined3d_pci_device select_card_intel(const struct wined3d_gl_info *gl_info,
-        const char *gl_renderer)
+cards_nvidia_binary[] =
 {
-    unsigned int i;
-
-    static const struct
-    {
-        const char *renderer;
-        enum wined3d_pci_device id;
-    }
-    cards[] =
-    {
-        /* Haswell */
-        {"Haswell Mobile",              CARD_INTEL_HWM},
-        /* Ivybridge */
-        {"Ivybridge Server",            CARD_INTEL_IVBS},
-        {"Ivybridge Mobile",            CARD_INTEL_IVBM},
-        {"Ivybridge Desktop",           CARD_INTEL_IVBD},
-        /* Sandybridge */
-        {"Sandybridge Server",          CARD_INTEL_SNBS},
-        {"Sandybridge Mobile",          CARD_INTEL_SNBM},
-        {"Sandybridge Desktop",         CARD_INTEL_SNBD},
-        /* Ironlake */
-        {"Ironlake Mobile",             CARD_INTEL_ILKM},
-        {"Ironlake Desktop",            CARD_INTEL_ILKD},
-        /* G4x */
-        {"B43",                         CARD_INTEL_B43},
-        {"G41",                         CARD_INTEL_G41},
-        {"G45",                         CARD_INTEL_G45},
-        {"Q45",                         CARD_INTEL_Q45},
-        {"Integrated Graphics Device",  CARD_INTEL_IGD},
-        {"GM45",                        CARD_INTEL_GM45},
-        /* i965 */
-        {"965GME",                      CARD_INTEL_965GME},
-        {"965GM",                       CARD_INTEL_965GM},
-        {"X3100",                       CARD_INTEL_965GM},  /* MacOS */
-        {"946GZ",                       CARD_INTEL_946GZ},
-        {"965G",                        CARD_INTEL_965G},
-        {"965Q",                        CARD_INTEL_965Q},
-        /* i945 */
-        {"Pineview M",                  CARD_INTEL_PNVM},
-        {"Pineview G",                  CARD_INTEL_PNVG},
-        {"IGD",                         CARD_INTEL_PNVG},
-        {"Q33",                         CARD_INTEL_Q33},
-        {"G33",                         CARD_INTEL_G33},
-        {"Q35",                         CARD_INTEL_Q35},
-        {"945GME",                      CARD_INTEL_945GME},
-        {"945GM",                       CARD_INTEL_945GM},
-        {"GMA 950",                     CARD_INTEL_945GM},  /* MacOS */
-        {"945G",                        CARD_INTEL_945G},
-        /* i915 */
-        {"915GM",                       CARD_INTEL_915GM},
-        {"E7221G",                      CARD_INTEL_E7221G},
-        {"915G",                        CARD_INTEL_915G},
-        /* i8xx */
-        {"865G",                        CARD_INTEL_865G},
-        {"845G",                        CARD_INTEL_845G},
-        {"855GM",                       CARD_INTEL_855GM},
-        {"830M",                        CARD_INTEL_830M},
-    };
-
-    for (i = 0; i < sizeof(cards) / sizeof(*cards); ++i)
-    {
-        if (strstr(gl_renderer, cards[i].renderer))
-            return cards[i].id;
-    }
-
-    return PCI_DEVICE_NONE;
-}
-
-static enum wined3d_pci_device select_card_amd_mesa(const struct wined3d_gl_info *gl_info,
-        const char *gl_renderer)
+    /* Direct 3D 11 */
+    {"GTX 780 Ti",                  CARD_NVIDIA_GEFORCE_GTX780TI},  /* Geforce 700 - highend */
+    {"GTX 780",                     CARD_NVIDIA_GEFORCE_GTX780},    /* Geforce 700 - highend */
+    {"GTX 770M",                    CARD_NVIDIA_GEFORCE_GTX770M},   /* Geforce 700 - midend high mobile */
+    {"GTX 770",                     CARD_NVIDIA_GEFORCE_GTX770},    /* Geforce 700 - highend */
+    {"GTX 765M",                    CARD_NVIDIA_GEFORCE_GTX765M},   /* Geforce 700 - midend high mobile */
+    {"GTX 760",                     CARD_NVIDIA_GEFORCE_GTX760},    /* Geforce 700 - midend high  */
+    {"GTX 750 Ti",                  CARD_NVIDIA_GEFORCE_GTX750TI},  /* Geforce 700 - midend */
+    {"GTX 750",                     CARD_NVIDIA_GEFORCE_GTX750},    /* Geforce 700 - midend */
+    {"GTX 680",                     CARD_NVIDIA_GEFORCE_GTX680},    /* Geforce 600 - highend */
+    {"GTX 670MX",                   CARD_NVIDIA_GEFORCE_GTX670MX},  /* Geforce 600 - highend */
+    {"GTX 670",                     CARD_NVIDIA_GEFORCE_GTX670},    /* Geforce 600 - midend high */
+    {"GTX 660 Ti",                  CARD_NVIDIA_GEFORCE_GTX660TI},  /* Geforce 600 - midend high */
+    {"GTX 660M",                    CARD_NVIDIA_GEFORCE_GTX660M},   /* Geforce 600 - midend high mobile */
+    {"GTX 660",                     CARD_NVIDIA_GEFORCE_GTX660},    /* Geforce 600 - midend high */
+    {"GTX 650 Ti",                  CARD_NVIDIA_GEFORCE_GTX650TI},  /* Geforce 600 - lowend */
+    {"GTX 650",                     CARD_NVIDIA_GEFORCE_GTX650},    /* Geforce 600 - lowend */
+    {"GT 650M",                     CARD_NVIDIA_GEFORCE_GT650M},    /* Geforce 600 - midend mobile */
+    {"GT 640M",                     CARD_NVIDIA_GEFORCE_GT640M},    /* Geforce 600 - midend mobile */
+    {"GT 630M",                     CARD_NVIDIA_GEFORCE_GT630M},    /* Geforce 600 - midend mobile */
+    {"GT 630",                      CARD_NVIDIA_GEFORCE_GT630},     /* Geforce 600 - lowend */
+    {"GT 610",                      CARD_NVIDIA_GEFORCE_GT610},     /* Geforce 600 - lowend */
+    {"GTX 580",                     CARD_NVIDIA_GEFORCE_GTX580},    /* Geforce 500 - highend */
+    {"GTX 570",                     CARD_NVIDIA_GEFORCE_GTX570},    /* Geforce 500 - midend high */
+    {"GTX 560 Ti",                  CARD_NVIDIA_GEFORCE_GTX560TI},  /* Geforce 500 - midend */
+    {"GTX 560",                     CARD_NVIDIA_GEFORCE_GTX560},    /* Geforce 500 - midend */
+    {"GT 555M",                     CARD_NVIDIA_GEFORCE_GT555M},    /* Geforce 500 - midend mobile */
+    {"GTX 550 Ti",                  CARD_NVIDIA_GEFORCE_GTX550},    /* Geforce 500 - midend */
+    {"GT 540M",                     CARD_NVIDIA_GEFORCE_GT540M},    /* Geforce 500 - midend mobile */
+    {"GT 520",                      CARD_NVIDIA_GEFORCE_GT520},     /* Geforce 500 - lowend */
+    {"GTX 480",                     CARD_NVIDIA_GEFORCE_GTX480},    /* Geforce 400 - highend */
+    {"GTX 470",                     CARD_NVIDIA_GEFORCE_GTX470},    /* Geforce 400 - midend high */
+    /* Direct 3D 10 */
+    {"GTX 465",                     CARD_NVIDIA_GEFORCE_GTX465},    /* Geforce 400 - midend */
+    {"GTX 460M",                    CARD_NVIDIA_GEFORCE_GTX460M},   /* Geforce 400 - highend mobile */
+    {"GTX 460",                     CARD_NVIDIA_GEFORCE_GTX460},    /* Geforce 400 - midend */
+    {"GTS 450",                     CARD_NVIDIA_GEFORCE_GTS450},    /* Geforce 400 - midend low */
+    {"GT 440",                      CARD_NVIDIA_GEFORCE_GT440},     /* Geforce 400 - lowend */
+    {"GT 430",                      CARD_NVIDIA_GEFORCE_GT430},     /* Geforce 400 - lowend */
+    {"GT 420",                      CARD_NVIDIA_GEFORCE_GT420},     /* Geforce 400 - lowend */
+    {"410M",                        CARD_NVIDIA_GEFORCE_410M},      /* Geforce 400 - lowend mobile */
+    {"GT 330",                      CARD_NVIDIA_GEFORCE_GT330},     /* Geforce 300 - highend */
+    {"GTS 360M",                    CARD_NVIDIA_GEFORCE_GTS350M},   /* Geforce 300 - highend mobile */
+    {"GTS 350M",                    CARD_NVIDIA_GEFORCE_GTS350M},   /* Geforce 300 - highend mobile */
+    {"GT 330M",                     CARD_NVIDIA_GEFORCE_GT325M},    /* Geforce 300 - midend mobile */
+    {"GT 325M",                     CARD_NVIDIA_GEFORCE_GT325M},    /* Geforce 300 - midend mobile */
+    {"GT 320M",                     CARD_NVIDIA_GEFORCE_GT320M},    /* Geforce 300 - midend mobile */
+    {"320M",                        CARD_NVIDIA_GEFORCE_320M},      /* Geforce 300 - midend mobile */
+    {"315M",                        CARD_NVIDIA_GEFORCE_315M},      /* Geforce 300 - midend mobile */
+    {"GTX 295",                     CARD_NVIDIA_GEFORCE_GTX280},    /* Geforce 200 - highend */
+    {"GTX 285",                     CARD_NVIDIA_GEFORCE_GTX280},    /* Geforce 200 - highend */
+    {"GTX 280",                     CARD_NVIDIA_GEFORCE_GTX280},    /* Geforce 200 - highend */
+    {"GTX 275",                     CARD_NVIDIA_GEFORCE_GTX275},    /* Geforce 200 - midend high */
+    {"GTX 260",                     CARD_NVIDIA_GEFORCE_GTX260},    /* Geforce 200 - midend */
+    {"GT 240",                      CARD_NVIDIA_GEFORCE_GT240},     /* Geforce 200 - midend */
+    {"GT 220",                      CARD_NVIDIA_GEFORCE_GT220},     /* Geforce 200 - lowend */
+    {"GeForce 310",                 CARD_NVIDIA_GEFORCE_210},       /* Geforce 200 - lowend */
+    {"GeForce 305",                 CARD_NVIDIA_GEFORCE_210},       /* Geforce 200 - lowend */
+    {"GeForce 210",                 CARD_NVIDIA_GEFORCE_210},       /* Geforce 200 - lowend */
+    {"G 210",                       CARD_NVIDIA_GEFORCE_210},       /* Geforce 200 - lowend */
+    {"GTS 250",                     CARD_NVIDIA_GEFORCE_9800GT},    /* Geforce 9 - highend / Geforce 200 - midend */
+    {"GTS 150",                     CARD_NVIDIA_GEFORCE_9800GT},    /* Geforce 9 - highend / Geforce 200 - midend */
+    {"9800",                        CARD_NVIDIA_GEFORCE_9800GT},    /* Geforce 9 - highend / Geforce 200 - midend */
+    {"GT 140",                      CARD_NVIDIA_GEFORCE_9600GT},    /* Geforce 9 - midend */
+    {"9600",                        CARD_NVIDIA_GEFORCE_9600GT},    /* Geforce 9 - midend */
+    {"GT 130",                      CARD_NVIDIA_GEFORCE_9500GT},    /* Geforce 9 - midend low / Geforce 200 - low */
+    {"GT 120",                      CARD_NVIDIA_GEFORCE_9500GT},    /* Geforce 9 - midend low / Geforce 200 - low */
+    {"9500",                        CARD_NVIDIA_GEFORCE_9500GT},    /* Geforce 9 - midend low / Geforce 200 - low */
+    {"9400M",                       CARD_NVIDIA_GEFORCE_9400M},     /* Geforce 9 - lowend */
+    {"9400",                        CARD_NVIDIA_GEFORCE_9400GT},    /* Geforce 9 - lowend */
+    {"9300",                        CARD_NVIDIA_GEFORCE_9300},      /* Geforce 9 - lowend low */
+    {"9200",                        CARD_NVIDIA_GEFORCE_9200},      /* Geforce 9 - lowend low */
+    {"9100",                        CARD_NVIDIA_GEFORCE_9200},      /* Geforce 9 - lowend low */
+    {"G 100",                       CARD_NVIDIA_GEFORCE_9200},      /* Geforce 9 - lowend low */
+    {"8800 GTX",                    CARD_NVIDIA_GEFORCE_8800GTX},   /* Geforce 8 - highend high */
+    {"8800",                        CARD_NVIDIA_GEFORCE_8800GTS},   /* Geforce 8 - highend */
+    {"8600M",                       CARD_NVIDIA_GEFORCE_8600MGT},   /* Geforce 8 - midend mobile */
+    {"8600 M",                      CARD_NVIDIA_GEFORCE_8600MGT},   /* Geforce 8 - midend mobile */
+    {"8700",                        CARD_NVIDIA_GEFORCE_8600GT},    /* Geforce 8 - midend */
+    {"8600",                        CARD_NVIDIA_GEFORCE_8600GT},    /* Geforce 8 - midend */
+    {"8500",                        CARD_NVIDIA_GEFORCE_8400GS},    /* Geforce 8 - mid-lowend */
+    {"8400",                        CARD_NVIDIA_GEFORCE_8400GS},    /* Geforce 8 - mid-lowend */
+    {"8300",                        CARD_NVIDIA_GEFORCE_8300GS},    /* Geforce 8 - lowend */
+    {"8200",                        CARD_NVIDIA_GEFORCE_8300GS},    /* Geforce 8 - lowend */
+    {"8100",                        CARD_NVIDIA_GEFORCE_8300GS},    /* Geforce 8 - lowend */
+    /* Direct 3D 9 SM3 */
+    {"Quadro FX 5",                 CARD_NVIDIA_GEFORCE_7800GT},    /* Geforce 7 - highend */
+    {"Quadro FX 4",                 CARD_NVIDIA_GEFORCE_7800GT},    /* Geforce 7 - highend */
+    {"7950",                        CARD_NVIDIA_GEFORCE_7800GT},    /* Geforce 7 - highend */
+    {"7900",                        CARD_NVIDIA_GEFORCE_7800GT},    /* Geforce 7 - highend */
+    {"7800",                        CARD_NVIDIA_GEFORCE_7800GT},    /* Geforce 7 - highend */
+    {"7700",                        CARD_NVIDIA_GEFORCE_7600},      /* Geforce 7 - midend */
+    {"7600",                        CARD_NVIDIA_GEFORCE_7600},      /* Geforce 7 - midend */
+    {"7400",                        CARD_NVIDIA_GEFORCE_7400},      /* Geforce 7 - lower medium */
+    {"7300",                        CARD_NVIDIA_GEFORCE_7300},      /* Geforce 7 - lowend */
+    {"6800",                        CARD_NVIDIA_GEFORCE_6800},      /* Geforce 6 - highend */
+    {"6700",                        CARD_NVIDIA_GEFORCE_6600GT},    /* Geforce 6 - midend */
+    {"6610",                        CARD_NVIDIA_GEFORCE_6600GT},    /* Geforce 6 - midend */
+    {"6600",                        CARD_NVIDIA_GEFORCE_6600GT},    /* Geforce 6 - midend */
+    /* Direct 3D 9 SM2 */
+    {"Quadro FX",                   CARD_NVIDIA_GEFORCEFX_5800},    /* GeforceFX - highend */
+    {"5950",                        CARD_NVIDIA_GEFORCEFX_5800},    /* GeforceFX - highend */
+    {"5900",                        CARD_NVIDIA_GEFORCEFX_5800},    /* GeforceFX - highend */
+    {"5800",                        CARD_NVIDIA_GEFORCEFX_5800},    /* GeforceFX - highend */
+    {"5750",                        CARD_NVIDIA_GEFORCEFX_5600},    /* GeforceFX - midend */
+    {"5700",                        CARD_NVIDIA_GEFORCEFX_5600},    /* GeforceFX - midend */
+    {"5650",                        CARD_NVIDIA_GEFORCEFX_5600},    /* GeforceFX - midend */
+    {"5600",                        CARD_NVIDIA_GEFORCEFX_5600},    /* GeforceFX - midend */
+    {"5500",                        CARD_NVIDIA_GEFORCEFX_5200},    /* GeforceFX - lowend */
+    {"5300",                        CARD_NVIDIA_GEFORCEFX_5200},    /* GeforceFX - lowend */
+    {"5250",                        CARD_NVIDIA_GEFORCEFX_5200},    /* GeforceFX - lowend */
+    {"5200",                        CARD_NVIDIA_GEFORCEFX_5200},    /* GeforceFX - lowend */
+    {"5100",                        CARD_NVIDIA_GEFORCEFX_5200},    /* GeforceFX - lowend */
+    /* Direct 3D 8 */
+    {"Quadro4",                     CARD_NVIDIA_GEFORCE4_TI4200},
+    {"GeForce4 Ti",                 CARD_NVIDIA_GEFORCE4_TI4200},   /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800 */
+    /* Direct 3D 7 */
+    {"GeForce4 MX",                 CARD_NVIDIA_GEFORCE4_MX},       /* MX420/MX440/MX460/MX4000 */
+    {"Quadro2 MXR",                 CARD_NVIDIA_GEFORCE2_MX},
+    {"GeForce2 MX",                 CARD_NVIDIA_GEFORCE2_MX},       /* Geforce2 standard/MX100/MX200/MX400 */
+    {"Quadro2",                     CARD_NVIDIA_GEFORCE2},
+    {"GeForce2",                    CARD_NVIDIA_GEFORCE2},          /* Geforce2 GTS/Pro/Ti/Ultra */
+    /* Direct 3D 6 */
+    {"TNT2",                        CARD_NVIDIA_RIVA_TNT2},         /* Riva TNT2 standard/M64/Pro/Ultra */
+},
+/* See http://developer.amd.com/resources/hardware-drivers/ati-catalyst-pc-vendor-id-1002-li/
+ *
+ * Beware: renderer string do not match exact card model,
+ * eg HD 4800 is returned for multiple cards, even for RV790 based ones. */
+cards_amd_binary[] =
 {
-    unsigned int i;
-
-    /* 20101109 - These are never returned by current Gallium radeon
-     * drivers: R700, RV790, R680, RV535, RV516, R410, RS485, RV360, RV351.
-     *
-     * These are returned but not handled: RC410, RV380. */
-    static const struct
-    {
-        const char *renderer;
-        enum wined3d_pci_device id;
-    }
-    cards[] =
-    {
-        /* Southern Islands */
-        {"TAHITI",      CARD_AMD_RADEON_HD7900},
-        {"PITCAIRN",    CARD_AMD_RADEON_HD7800},
-        {"CAPE VERDE",  CARD_AMD_RADEON_HD7700},
-        /* Northern Islands */
-        {"CAYMAN",      CARD_AMD_RADEON_HD6900},
-        {"BARTS",       CARD_AMD_RADEON_HD6800},
-        {"TURKS",       CARD_AMD_RADEON_HD6600},
-        {"SUMO2",       CARD_AMD_RADEON_HD6410D},   /* SUMO2 first, because we do a strstr(). */
-        {"SUMO",        CARD_AMD_RADEON_HD6550D},
-        {"CAICOS",      CARD_AMD_RADEON_HD6400},
-        {"PALM",        CARD_AMD_RADEON_HD6300},
-        /* Evergreen */
-        {"HEMLOCK",     CARD_AMD_RADEON_HD5900},
-        {"CYPRESS",     CARD_AMD_RADEON_HD5800},
-        {"JUNIPER",     CARD_AMD_RADEON_HD5700},
-        {"REDWOOD",     CARD_AMD_RADEON_HD5600},
-        {"CEDAR",       CARD_AMD_RADEON_HD5400},
-        /* R700 */
-        {"R700",        CARD_AMD_RADEON_HD4800},
-        {"RV790",       CARD_AMD_RADEON_HD4800},
-        {"RV770",       CARD_AMD_RADEON_HD4800},
-        {"RV740",       CARD_AMD_RADEON_HD4700},
-        {"RV730",       CARD_AMD_RADEON_HD4600},
-        {"RV710",       CARD_AMD_RADEON_HD4350},
-        /* R600/R700 integrated */
-        {"RS880",       CARD_AMD_RADEON_HD4200M},
-        {"RS780",       CARD_AMD_RADEON_HD3200},
-        /* R600 */
-        {"R680",        CARD_AMD_RADEON_HD2900},
-        {"R600",        CARD_AMD_RADEON_HD2900},
-        {"RV670",       CARD_AMD_RADEON_HD2900},
-        {"RV635",       CARD_AMD_RADEON_HD2600},
-        {"RV630",       CARD_AMD_RADEON_HD2600},
-        {"RV620",       CARD_AMD_RADEON_HD2350},
-        {"RV610",       CARD_AMD_RADEON_HD2350},
-        /* R500 */
-        {"R580",        CARD_AMD_RADEON_X1600},
-        {"R520",        CARD_AMD_RADEON_X1600},
-        {"RV570",       CARD_AMD_RADEON_X1600},
-        {"RV560",       CARD_AMD_RADEON_X1600},
-        {"RV535",       CARD_AMD_RADEON_X1600},
-        {"RV530",       CARD_AMD_RADEON_X1600},
-        {"RV516",       CARD_AMD_RADEON_X700},
-        {"RV515",       CARD_AMD_RADEON_X700},
-        /* R400 */
-        {"R481",        CARD_AMD_RADEON_X700},
-        {"R480",        CARD_AMD_RADEON_X700},
-        {"R430",        CARD_AMD_RADEON_X700},
-        {"R423",        CARD_AMD_RADEON_X700},
-        {"R420",        CARD_AMD_RADEON_X700},
-        {"R410",        CARD_AMD_RADEON_X700},
-        {"RV410",       CARD_AMD_RADEON_X700},
-        /* Radeon Xpress - onboard, DX9b, Shader 2.0, 300-400 MHz */
-        {"RS740",       CARD_AMD_RADEON_XPRESS_200M},
-        {"RS690",       CARD_AMD_RADEON_XPRESS_200M},
-        {"RS600",       CARD_AMD_RADEON_XPRESS_200M},
-        {"RS485",       CARD_AMD_RADEON_XPRESS_200M},
-        {"RS482",       CARD_AMD_RADEON_XPRESS_200M},
-        {"RS480",       CARD_AMD_RADEON_XPRESS_200M},
-        {"RS400",       CARD_AMD_RADEON_XPRESS_200M},
-        /* R300 */
-        {"R360",        CARD_AMD_RADEON_9500},
-        {"R350",        CARD_AMD_RADEON_9500},
-        {"R300",        CARD_AMD_RADEON_9500},
-        {"RV370",       CARD_AMD_RADEON_9500},
-        {"RV360",       CARD_AMD_RADEON_9500},
-        {"RV351",       CARD_AMD_RADEON_9500},
-        {"RV350",       CARD_AMD_RADEON_9500},
-    };
-
-    for (i = 0; i < sizeof(cards) / sizeof(*cards); ++i)
-    {
-        if (strstr(gl_renderer, cards[i].renderer))
-            return cards[i].id;
-    }
-
-    return PCI_DEVICE_NONE;
-}
-
-static enum wined3d_pci_device select_card_nvidia_mesa(const struct wined3d_gl_info *gl_info,
-        const char *gl_renderer)
+    /* Southern Islands */
+    {"HD 7900",                     CARD_AMD_RADEON_HD7900},
+    {"HD 7800",                     CARD_AMD_RADEON_HD7800},
+    {"HD 7700",                     CARD_AMD_RADEON_HD7700},
+    /* Northern Islands */
+    {"HD 6970",                     CARD_AMD_RADEON_HD6900},
+    {"HD 6900",                     CARD_AMD_RADEON_HD6900},
+    {"HD 6800",                     CARD_AMD_RADEON_HD6800},
+    {"HD 6770M",                    CARD_AMD_RADEON_HD6600M},
+    {"HD 6750M",                    CARD_AMD_RADEON_HD6600M},
+    {"HD 6700",                     CARD_AMD_RADEON_HD6700},
+    {"HD 6670",                     CARD_AMD_RADEON_HD6600},
+    {"HD 6630M",                    CARD_AMD_RADEON_HD6600M},
+    {"HD 6600M",                    CARD_AMD_RADEON_HD6600M},
+    {"HD 6600",                     CARD_AMD_RADEON_HD6600},
+    {"HD 6570",                     CARD_AMD_RADEON_HD6600},
+    {"HD 6500M",                    CARD_AMD_RADEON_HD6600M},
+    {"HD 6500",                     CARD_AMD_RADEON_HD6600},
+    {"HD 6400",                     CARD_AMD_RADEON_HD6400},
+    {"HD 6300",                     CARD_AMD_RADEON_HD6300},
+    {"HD 6200",                     CARD_AMD_RADEON_HD6300},
+    /* Evergreen */
+    {"HD 5870",                     CARD_AMD_RADEON_HD5800},    /* Radeon EG CYPRESS PRO */
+    {"HD 5850",                     CARD_AMD_RADEON_HD5800},    /* Radeon EG CYPRESS XT */
+    {"HD 5800",                     CARD_AMD_RADEON_HD5800},    /* Radeon EG CYPRESS HD58xx generic renderer string */
+    {"HD 5770",                     CARD_AMD_RADEON_HD5700},    /* Radeon EG JUNIPER XT */
+    {"HD 5750",                     CARD_AMD_RADEON_HD5700},    /* Radeon EG JUNIPER LE */
+    {"HD 5700",                     CARD_AMD_RADEON_HD5700},    /* Radeon EG JUNIPER HD57xx generic renderer string */
+    {"HD 5670",                     CARD_AMD_RADEON_HD5600},    /* Radeon EG REDWOOD XT */
+    {"HD 5570",                     CARD_AMD_RADEON_HD5600},    /* Radeon EG REDWOOD PRO mapped to HD5600 series */
+    {"HD 5550",                     CARD_AMD_RADEON_HD5600},    /* Radeon EG REDWOOD LE mapped to HD5600 series */
+    {"HD 5450",                     CARD_AMD_RADEON_HD5400},    /* Radeon EG CEDAR PRO */
+    {"HD 5000",                     CARD_AMD_RADEON_HD5600},    /* Defaulting to HD 5600 */
+    /* R700 */
+    {"HD 4890",                     CARD_AMD_RADEON_HD4800},    /* Radeon RV790 */
+    {"HD 4870",                     CARD_AMD_RADEON_HD4800},    /* Radeon RV770 */
+    {"HD 4850",                     CARD_AMD_RADEON_HD4800},    /* Radeon RV770 */
+    {"HD 4830",                     CARD_AMD_RADEON_HD4800},    /* Radeon RV770 */
+    {"HD 4800",                     CARD_AMD_RADEON_HD4800},    /* Radeon RV7xx HD48xx generic renderer string */
+    {"HD 4770",                     CARD_AMD_RADEON_HD4700},    /* Radeon RV740 */
+    {"HD 4700",                     CARD_AMD_RADEON_HD4700},    /* Radeon RV7xx HD47xx generic renderer string */
+    {"HD 4670",                     CARD_AMD_RADEON_HD4600},    /* Radeon RV730 */
+    {"HD 4650",                     CARD_AMD_RADEON_HD4600},    /* Radeon RV730 */
+    {"HD 4600",                     CARD_AMD_RADEON_HD4600},    /* Radeon RV730 */
+    {"HD 4550",                     CARD_AMD_RADEON_HD4350},    /* Radeon RV710 */
+    {"HD 4350",                     CARD_AMD_RADEON_HD4350},    /* Radeon RV710 */
+    /* R600/R700 integrated */
+    {"HD 4200M",                    CARD_AMD_RADEON_HD4200M},
+    {"HD 3300",                     CARD_AMD_RADEON_HD3200},
+    {"HD 3200",                     CARD_AMD_RADEON_HD3200},
+    {"HD 3100",                     CARD_AMD_RADEON_HD3200},
+    /* R600 */
+    {"HD 3870",                     CARD_AMD_RADEON_HD2900},    /* HD2900/HD3800 - highend */
+    {"HD 3850",                     CARD_AMD_RADEON_HD2900},    /* HD2900/HD3800 - highend */
+    {"HD 2900",                     CARD_AMD_RADEON_HD2900},    /* HD2900/HD3800 - highend */
+    {"HD 3830",                     CARD_AMD_RADEON_HD2600},    /* China-only midend */
+    {"HD 3690",                     CARD_AMD_RADEON_HD2600},    /* HD2600/HD3600 - midend */
+    {"HD 3650",                     CARD_AMD_RADEON_HD2600},    /* HD2600/HD3600 - midend */
+    {"HD 2600",                     CARD_AMD_RADEON_HD2600},    /* HD2600/HD3600 - midend */
+    {"HD 3470",                     CARD_AMD_RADEON_HD2350},    /* HD2350/HD2400/HD3400 - lowend */
+    {"HD 3450",                     CARD_AMD_RADEON_HD2350},    /* HD2350/HD2400/HD3400 - lowend */
+    {"HD 3430",                     CARD_AMD_RADEON_HD2350},    /* HD2350/HD2400/HD3400 - lowend */
+    {"HD 3400",                     CARD_AMD_RADEON_HD2350},    /* HD2350/HD2400/HD3400 - lowend */
+    {"HD 2400",                     CARD_AMD_RADEON_HD2350},    /* HD2350/HD2400/HD3400 - lowend */
+    {"HD 2350",                     CARD_AMD_RADEON_HD2350},    /* HD2350/HD2400/HD3400 - lowend */
+    /* Radeon R5xx */
+    {"X1950",                       CARD_AMD_RADEON_X1600},
+    {"X1900",                       CARD_AMD_RADEON_X1600},
+    {"X1800",                       CARD_AMD_RADEON_X1600},
+    {"X1650",                       CARD_AMD_RADEON_X1600},
+    {"X1600",                       CARD_AMD_RADEON_X1600},
+    /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300/X2500/HD2300 (lowend R5xx)
+     * Note X2300/X2500/HD2300 are R5xx GPUs with a 2xxx naming but they are still DX9-only */
+    {"HD 2300",                     CARD_AMD_RADEON_X700},
+    {"X2500",                       CARD_AMD_RADEON_X700},
+    {"X2300",                       CARD_AMD_RADEON_X700},
+    {"X1550",                       CARD_AMD_RADEON_X700},
+    {"X1450",                       CARD_AMD_RADEON_X700},
+    {"X1400",                       CARD_AMD_RADEON_X700},
+    {"X1300",                       CARD_AMD_RADEON_X700},
+    {"X850",                        CARD_AMD_RADEON_X700},
+    {"X800",                        CARD_AMD_RADEON_X700},
+    {"X700",                        CARD_AMD_RADEON_X700},
+    /* Radeon Xpress Series - onboard, DX9b, Shader 2.0, 300-400 MHz */
+    {"Radeon Xpress",               CARD_AMD_RADEON_XPRESS_200M},
+},
+cards_intel[] =
 {
-    unsigned int i;
-
-    static const struct
-    {
-        const char *renderer;
-        enum wined3d_pci_device id;
-    }
-    cards[] =
-    {
-        /* Maxwell */
-        {"NV117",   CARD_NVIDIA_GEFORCE_GTX750},
-        /* Kepler */
-        {"NVE6",    CARD_NVIDIA_GEFORCE_GTX770M},
-        {"NVE4",    CARD_NVIDIA_GEFORCE_GTX680},
-        /* Fermi */
-        {"NVD9",    CARD_NVIDIA_GEFORCE_GT520},
-        {"NVCF",    CARD_NVIDIA_GEFORCE_GTX550},
-        {"NVCE",    CARD_NVIDIA_GEFORCE_GTX560},
-        {"NVC8",    CARD_NVIDIA_GEFORCE_GTX570},
-        {"NVC4",    CARD_NVIDIA_GEFORCE_GTX460},
-        {"NVC3",    CARD_NVIDIA_GEFORCE_GT440},
-        {"NVC1",    CARD_NVIDIA_GEFORCE_GT420},
-        {"NVC0",    CARD_NVIDIA_GEFORCE_GTX480},
-        /* Tesla */
-        {"NVAF",    CARD_NVIDIA_GEFORCE_GT320M},
-        {"NVAC",    CARD_NVIDIA_GEFORCE_8200},
-        {"NVAA",    CARD_NVIDIA_GEFORCE_8200},
-        {"NVA8",    CARD_NVIDIA_GEFORCE_210},
-        {"NVA5",    CARD_NVIDIA_GEFORCE_GT220},
-        {"NVA3",    CARD_NVIDIA_GEFORCE_GT240},
-        {"NVA0",    CARD_NVIDIA_GEFORCE_GTX280},
-        {"NV98",    CARD_NVIDIA_GEFORCE_9200},
-        {"NV96",    CARD_NVIDIA_GEFORCE_9400GT},
- &nbs